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