Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 1 | /* SCTP kernel Implementation |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 2 | * (C) Copyright IBM Corp. 2002, 2003 |
| 3 | * Copyright (c) 1999-2001 Motorola, Inc. |
| 4 | * |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 5 | * The SCTP implementation is free software; |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 6 | * you can redistribute it and/or modify it under the terms of |
| 7 | * the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 2, or (at your option) |
| 9 | * any later version. |
| 10 | * |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 11 | * The SCTP implementation is distributed in the hope that it |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 12 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
| 13 | * ************************ |
| 14 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 15 | * See the GNU General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License |
| 18 | * along with GNU CC; see the file COPYING. If not, write to |
| 19 | * the Free Software Foundation, 59 Temple Place - Suite 330, |
| 20 | * Boston, MA 02111-1307, USA. |
| 21 | * |
| 22 | * Please send any bug reports or fixes you make to the |
| 23 | * email address(es): |
| 24 | * lksctp developers <lksctp-developers@lists.sourceforge.net> |
| 25 | * |
| 26 | * Or submit a bug report through the following website: |
| 27 | * http://www.sf.net/projects/lksctp |
| 28 | * |
| 29 | * Any bugs reported given to us we will try to fix... any fixes shared will |
| 30 | * be incorporated into the next SCTP release. |
| 31 | * |
| 32 | * Written or modified by: |
| 33 | * Sridhar Samudrala <sri@us.ibm.com> |
| 34 | */ |
| 35 | |
| 36 | /* This is a kernel test to verify the one-to-many style connect() in blocking |
| 37 | * and non-blocking modes. |
| 38 | */ |
| 39 | |
| 40 | #include <stdio.h> |
| 41 | #include <unistd.h> |
| 42 | #include <stdlib.h> |
| 43 | #include <string.h> |
| 44 | #include <fcntl.h> |
| 45 | #include <sys/types.h> |
| 46 | #include <sys/socket.h> |
| 47 | #include <sys/uio.h> |
| 48 | #include <netinet/in.h> |
| 49 | #include <errno.h> |
| 50 | #include <netinet/sctp.h> |
| 51 | #include <sctputil.h> |
| 52 | |
| 53 | char *TCID = __FILE__; |
| 54 | int TST_TOTAL = 5; |
| 55 | int TST_CNT = 0; |
| 56 | |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 57 | int |
| 58 | main(int argc, char *argv[]) |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 59 | { |
| 60 | int svr_sk, clt_sk1, clt_sk2, peeloff_sk; |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 61 | sctp_assoc_t svr_associd1; |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 62 | sockaddr_storage_t svr_loop, clt_loop1, clt_loop2, clt_loop3; |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 63 | struct sctp_assoc_change *sac; |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 64 | struct iovec iov; |
| 65 | struct msghdr inmessage; |
| 66 | int error; |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 67 | char *big_buffer; |
| 68 | int flags; |
| 69 | |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 70 | /* Rather than fflush() throughout the code, set stdout to |
| 71 | * be unbuffered. |
| 72 | */ |
| 73 | setvbuf(stdout, NULL, _IONBF, 0); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 74 | |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 75 | /* Initialize the server and client addresses. */ |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 76 | svr_loop.v4.sin_family = AF_INET; |
| 77 | svr_loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; |
| 78 | svr_loop.v4.sin_port = htons(SCTP_TESTPORT_1); |
| 79 | clt_loop1.v4.sin_family = AF_INET; |
| 80 | clt_loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; |
| 81 | clt_loop1.v4.sin_port = htons(SCTP_TESTPORT_2); |
| 82 | clt_loop2.v4.sin_family = AF_INET; |
| 83 | clt_loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 84 | clt_loop2.v4.sin_port = htons(SCTP_TESTPORT_2+1); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 85 | clt_loop3.v4.sin_family = AF_INET; |
| 86 | clt_loop3.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 87 | clt_loop3.v4.sin_port = htons(SCTP_TESTPORT_2+2); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 88 | |
| 89 | /* Create and bind the server socket. */ |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 90 | svr_sk = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 91 | test_bind(svr_sk, &svr_loop.sa, sizeof(svr_loop)); |
| 92 | |
| 93 | /* Mark server socket as being able to accept new associations. */ |
| 94 | test_listen(svr_sk, 1); |
| 95 | |
| 96 | /* Create and bind the client sockets. */ |
| 97 | clt_sk1 = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); |
| 98 | test_bind(clt_sk1, &clt_loop1.sa, sizeof(clt_loop1)); |
| 99 | clt_sk2 = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); |
| 100 | test_bind(clt_sk2, &clt_loop2.sa, sizeof(clt_loop2)); |
| 101 | |
| 102 | /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ |
| 103 | test_enable_assoc_change(svr_sk); |
| 104 | test_enable_assoc_change(clt_sk1); |
| 105 | test_enable_assoc_change(clt_sk2); |
| 106 | |
| 107 | /* Set clt_sk1 as non-blocking. */ |
| 108 | flags = fcntl(clt_sk1, F_GETFL, 0); |
| 109 | if (flags < 0) |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 110 | tst_brkm(TBROK, tst_exit, "fcntl F_GETFL: %s", strerror(errno)); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 111 | if (fcntl(clt_sk1, F_SETFL, flags | O_NONBLOCK) < 0) |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 112 | tst_brkm(TBROK, tst_exit, "fcntl F_SETFL: %s", strerror(errno)); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 113 | |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 114 | /* Do a non-blocking connect from clt_sk1 to svr_sk */ |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 115 | error = connect(clt_sk1, &svr_loop.sa, sizeof(svr_loop)); |
| 116 | /* Non-blocking connect should return immediately with EINPROGRESS. */ |
| 117 | if ((error != -1) || (EINPROGRESS != errno)) |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 118 | tst_brkm(TBROK, tst_exit, "non-blocking connect error: %d" |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 119 | "errno:%d", error, errno); |
| 120 | |
| 121 | tst_resm(TPASS, "non-blocking connect"); |
| 122 | |
| 123 | /* Doing a connect on a socket to create an association that is |
| 124 | * is already established should return EISCONN. |
| 125 | */ |
| 126 | error = connect(clt_sk1, &svr_loop.sa, sizeof(svr_loop)); |
| 127 | if ((error != -1) || (EISCONN != errno)) |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 128 | tst_brkm(TBROK, tst_exit, "connect on a socket to create an " |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 129 | "assoc that is already established error:%d errno:%d", |
| 130 | error, errno); |
| 131 | |
| 132 | tst_resm(TPASS, "connect on a socket to create an assoc that is " |
| 133 | "already established"); |
| 134 | |
| 135 | /* Initialize inmessage for all receives. */ |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 136 | memset(&inmessage, 0, sizeof(inmessage)); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 137 | big_buffer = test_malloc(REALLY_BIG); |
| 138 | iov.iov_base = big_buffer; |
| 139 | iov.iov_len = REALLY_BIG; |
| 140 | inmessage.msg_iov = &iov; |
| 141 | inmessage.msg_iovlen = 1; |
| 142 | inmessage.msg_control = NULL; |
| 143 | |
| 144 | /* Get COMM_UP on clt_sk1 */ |
| 145 | error = test_recvmsg(clt_sk1, &inmessage, MSG_WAITALL); |
| 146 | test_check_msg_notification(&inmessage, error, |
| 147 | sizeof(struct sctp_assoc_change), |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 148 | SCTP_ASSOC_CHANGE, SCTP_COMM_UP); |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 149 | #if 0 |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 150 | sac = (struct sctp_assoc_change *)iov.iov_base; |
| 151 | clt_associd1 = sac->sac_assoc_id; |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 152 | #endif |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 153 | |
| 154 | /* Get COMM_UP on svr_sk */ |
| 155 | error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); |
| 156 | test_check_msg_notification(&inmessage, error, |
| 157 | sizeof(struct sctp_assoc_change), |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 158 | SCTP_ASSOC_CHANGE, SCTP_COMM_UP); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 159 | sac = (struct sctp_assoc_change *)iov.iov_base; |
| 160 | svr_associd1 = sac->sac_assoc_id; |
| 161 | |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 162 | /* Do a blocking connect from clt_sk2 to svr_sk. |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 163 | * Blocking connect should block until the association is established |
| 164 | * and return success. |
| 165 | */ |
| 166 | test_connect(clt_sk2, &svr_loop.sa, sizeof(svr_loop)); |
| 167 | |
| 168 | /* Get COMM_UP on clt_sk2 */ |
| 169 | error = test_recvmsg(clt_sk2, &inmessage, MSG_WAITALL); |
| 170 | test_check_msg_notification(&inmessage, error, |
| 171 | sizeof(struct sctp_assoc_change), |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 172 | SCTP_ASSOC_CHANGE, SCTP_COMM_UP); |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 173 | #if 0 |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 174 | sac = (struct sctp_assoc_change *)iov.iov_base; |
| 175 | clt_associd2 = sac->sac_assoc_id; |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 176 | #endif |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 177 | |
| 178 | /* Get COMM_UP on svr_sk */ |
| 179 | error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); |
| 180 | test_check_msg_notification(&inmessage, error, |
| 181 | sizeof(struct sctp_assoc_change), |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 182 | SCTP_ASSOC_CHANGE, SCTP_COMM_UP); |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 183 | #if 0 |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 184 | sac = (struct sctp_assoc_change *)iov.iov_base; |
| 185 | svr_associd2 = sac->sac_assoc_id; |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 186 | #endif |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 187 | |
| 188 | tst_resm(TPASS, "blocking connect"); |
| 189 | |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 190 | peeloff_sk = test_sctp_peeloff(svr_sk, svr_associd1); |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 191 | |
| 192 | /* Doing a connect on a peeled off socket should fail. */ |
| 193 | error = connect(peeloff_sk, &clt_loop3.sa, sizeof(clt_loop3)); |
| 194 | if ((error != -1) || (EISCONN != errno)) |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 195 | tst_brkm(TBROK, tst_exit, "connect on a peeled off socket " |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 196 | "error:%d, errno:%d", error, errno); |
| 197 | |
| 198 | tst_resm(TPASS, "connect on a peeled off socket"); |
| 199 | |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 200 | /* Trying to create an association on a socket that matches an |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 201 | * existing peeled-off association should fail. |
| 202 | */ |
| 203 | error = connect(svr_sk, &clt_loop1.sa, sizeof(clt_loop1)); |
| 204 | if ((error != -1) || (EADDRNOTAVAIL != errno)) |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 205 | tst_brkm(TBROK, tst_exit, "connect to create an assoc that " |
uid52817 | 89de9aa | 2003-10-23 18:42:24 +0000 | [diff] [blame] | 206 | "matches a peeled off assoc error:%d errno:%d", |
| 207 | error, errno); |
| 208 | |
| 209 | tst_resm(TPASS, "connect to create an assoc that matches a peeled off " |
| 210 | "assoc"); |
| 211 | |
| 212 | close(svr_sk); |
| 213 | close(clt_sk1); |
| 214 | close(clt_sk2); |
| 215 | close(peeloff_sk); |
| 216 | |
Simon Xu | 6f22494 | 2013-12-06 11:51:16 +0800 | [diff] [blame] | 217 | /* Indicate successful completion. */ |
| 218 | return 0; |
Chris Dearman | ec6edca | 2012-10-17 19:54:01 -0700 | [diff] [blame] | 219 | } |