1/* SCTP kernel Implementation 2 * (C) Copyright IBM Corp. 2002, 2003 3 * Copyright (c) 1999-2001 Motorola, Inc. 4 * 5 * The SCTP implementation is free software; 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 * 11 * The SCTP implementation is distributed in the hope that it 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#include "tst_kernel.h" 53 54char *TCID = __FILE__; 55int TST_TOTAL = 5; 56int TST_CNT = 0; 57 58int 59main(void) 60{ 61 int svr_sk, clt_sk1, clt_sk2, peeloff_sk; 62 sctp_assoc_t svr_associd1; 63 sockaddr_storage_t svr_loop, clt_loop1, clt_loop2, clt_loop3; 64 struct sctp_assoc_change *sac; 65 struct iovec iov; 66 struct msghdr inmessage; 67 int error; 68 char *big_buffer; 69 int flags; 70 71 if (tst_check_driver("sctp")) 72 tst_brkm(TCONF, tst_exit, "sctp driver not available"); 73 74 /* Rather than fflush() throughout the code, set stdout to 75 * be unbuffered. 76 */ 77 setvbuf(stdout, NULL, _IONBF, 0); 78 79 /* Initialize the server and client addresses. */ 80 svr_loop.v4.sin_family = AF_INET; 81 svr_loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 82 svr_loop.v4.sin_port = htons(SCTP_TESTPORT_1); 83 clt_loop1.v4.sin_family = AF_INET; 84 clt_loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 85 clt_loop1.v4.sin_port = htons(SCTP_TESTPORT_2); 86 clt_loop2.v4.sin_family = AF_INET; 87 clt_loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 88 clt_loop2.v4.sin_port = htons(SCTP_TESTPORT_2+1); 89 clt_loop3.v4.sin_family = AF_INET; 90 clt_loop3.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 91 clt_loop3.v4.sin_port = htons(SCTP_TESTPORT_2+2); 92 93 /* Create and bind the server socket. */ 94 svr_sk = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); 95 test_bind(svr_sk, &svr_loop.sa, sizeof(svr_loop)); 96 97 /* Mark server socket as being able to accept new associations. */ 98 test_listen(svr_sk, 1); 99 100 /* Create and bind the client sockets. */ 101 clt_sk1 = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); 102 test_bind(clt_sk1, &clt_loop1.sa, sizeof(clt_loop1)); 103 clt_sk2 = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); 104 test_bind(clt_sk2, &clt_loop2.sa, sizeof(clt_loop2)); 105 106 /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ 107 test_enable_assoc_change(svr_sk); 108 test_enable_assoc_change(clt_sk1); 109 test_enable_assoc_change(clt_sk2); 110 111 /* Set clt_sk1 as non-blocking. */ 112 flags = fcntl(clt_sk1, F_GETFL, 0); 113 if (flags < 0) 114 tst_brkm(TBROK, tst_exit, "fcntl F_GETFL: %s", strerror(errno)); 115 if (fcntl(clt_sk1, F_SETFL, flags | O_NONBLOCK) < 0) 116 tst_brkm(TBROK, tst_exit, "fcntl F_SETFL: %s", strerror(errno)); 117 118 /* Do a non-blocking connect from clt_sk1 to svr_sk */ 119 error = connect(clt_sk1, &svr_loop.sa, sizeof(svr_loop)); 120 /* Non-blocking connect should return immediately with EINPROGRESS. */ 121 if ((error != -1) || (EINPROGRESS != errno)) 122 tst_brkm(TBROK, tst_exit, "non-blocking connect error: %d " 123 "errno:%d", error, errno); 124 125 tst_resm(TPASS, "non-blocking connect"); 126 127 /* Doing a connect on a socket to create an association that is 128 * is already established should return EISCONN. 129 */ 130 error = connect(clt_sk1, &svr_loop.sa, sizeof(svr_loop)); 131 if ((error != -1) || (EISCONN != errno)) 132 tst_brkm(TBROK, tst_exit, "connect on a socket to create an " 133 "assoc that is already established error:%d errno:%d", 134 error, errno); 135 136 tst_resm(TPASS, "connect on a socket to create an assoc that is " 137 "already established"); 138 139 /* Initialize inmessage for all receives. */ 140 memset(&inmessage, 0, sizeof(inmessage)); 141 big_buffer = test_malloc(REALLY_BIG); 142 iov.iov_base = big_buffer; 143 iov.iov_len = REALLY_BIG; 144 inmessage.msg_iov = &iov; 145 inmessage.msg_iovlen = 1; 146 inmessage.msg_control = NULL; 147 148 /* Get COMM_UP on clt_sk1 */ 149 error = test_recvmsg(clt_sk1, &inmessage, MSG_WAITALL); 150 test_check_msg_notification(&inmessage, error, 151 sizeof(struct sctp_assoc_change), 152 SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 153#if 0 154 sac = (struct sctp_assoc_change *)iov.iov_base; 155 clt_associd1 = sac->sac_assoc_id; 156#endif 157 158 /* Get COMM_UP on svr_sk */ 159 error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); 160 test_check_msg_notification(&inmessage, error, 161 sizeof(struct sctp_assoc_change), 162 SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 163 sac = (struct sctp_assoc_change *)iov.iov_base; 164 svr_associd1 = sac->sac_assoc_id; 165 166 /* Do a blocking connect from clt_sk2 to svr_sk. 167 * Blocking connect should block until the association is established 168 * and return success. 169 */ 170 test_connect(clt_sk2, &svr_loop.sa, sizeof(svr_loop)); 171 172 /* Get COMM_UP on clt_sk2 */ 173 error = test_recvmsg(clt_sk2, &inmessage, MSG_WAITALL); 174 test_check_msg_notification(&inmessage, error, 175 sizeof(struct sctp_assoc_change), 176 SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 177#if 0 178 sac = (struct sctp_assoc_change *)iov.iov_base; 179 clt_associd2 = sac->sac_assoc_id; 180#endif 181 182 /* Get COMM_UP on svr_sk */ 183 error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); 184 test_check_msg_notification(&inmessage, error, 185 sizeof(struct sctp_assoc_change), 186 SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 187#if 0 188 sac = (struct sctp_assoc_change *)iov.iov_base; 189 svr_associd2 = sac->sac_assoc_id; 190#endif 191 192 tst_resm(TPASS, "blocking connect"); 193 194 peeloff_sk = test_sctp_peeloff(svr_sk, svr_associd1); 195 196 /* Doing a connect on a peeled off socket should fail. */ 197 error = connect(peeloff_sk, &clt_loop3.sa, sizeof(clt_loop3)); 198 if ((error != -1) || (EISCONN != errno)) 199 tst_brkm(TBROK, tst_exit, "connect on a peeled off socket " 200 "error:%d, errno:%d", error, errno); 201 202 tst_resm(TPASS, "connect on a peeled off socket"); 203 204 /* Trying to create an association on a socket that matches an 205 * existing peeled-off association should fail. 206 */ 207 error = connect(svr_sk, &clt_loop1.sa, sizeof(clt_loop1)); 208 if ((error != -1) || (EADDRNOTAVAIL != errno)) 209 tst_brkm(TBROK, tst_exit, "connect to create an assoc that " 210 "matches a peeled off assoc error:%d errno:%d", 211 error, errno); 212 213 tst_resm(TPASS, "connect to create an assoc that matches a peeled off " 214 "assoc"); 215 216 close(svr_sk); 217 close(clt_sk1); 218 close(clt_sk2); 219 close(peeloff_sk); 220 221 /* Indicate successful completion. */ 222 return 0; 223} 224