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 sctp_connectx() 37f08c3bdfSopenharmony_ci * in blocking 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 = 9; 56f08c3bdfSopenharmony_ciint TST_CNT = 0; 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci#define NUMADDR 6 59f08c3bdfSopenharmony_ci#define SCTP_IP_LOOPBACK_I(I) htonl(0x7f000001 + I) 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci#define NIPQUAD(addr) \ 62f08c3bdfSopenharmony_ci ((unsigned char *)&addr)[0], \ 63f08c3bdfSopenharmony_ci ((unsigned char *)&addr)[1], \ 64f08c3bdfSopenharmony_ci ((unsigned char *)&addr)[2], \ 65f08c3bdfSopenharmony_ci ((unsigned char *)&addr)[3] 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ciint 68f08c3bdfSopenharmony_cimain(void) 69f08c3bdfSopenharmony_ci{ 70f08c3bdfSopenharmony_ci int svr_sk, clt_sk1, clt_sk2, peeloff_sk; 71f08c3bdfSopenharmony_ci sctp_assoc_t associd, svr_associd1, svr_associd2, clt_associd1, clt_associd2; 72f08c3bdfSopenharmony_ci struct iovec iov; 73f08c3bdfSopenharmony_ci struct msghdr inmessage; 74f08c3bdfSopenharmony_ci int error, i; 75f08c3bdfSopenharmony_ci struct sctp_assoc_change *sac; 76f08c3bdfSopenharmony_ci char *big_buffer; 77f08c3bdfSopenharmony_ci int flags; 78f08c3bdfSopenharmony_ci struct sockaddr_in svr_loop[NUMADDR]; 79f08c3bdfSopenharmony_ci struct sockaddr_in svr_try[NUMADDR]; 80f08c3bdfSopenharmony_ci struct sockaddr_in clt_loop1[NUMADDR]; 81f08c3bdfSopenharmony_ci struct sockaddr_in clt_loop2[NUMADDR]; 82f08c3bdfSopenharmony_ci struct sockaddr_in clt_loop3[NUMADDR]; 83f08c3bdfSopenharmony_ci sockaddr_storage_t svr_test[NUMADDR], clt_test1[NUMADDR], clt_test2[NUMADDR]; 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci if (tst_check_driver("sctp")) 86f08c3bdfSopenharmony_ci tst_brkm(TCONF, tst_exit, "sctp driver not available"); 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci /* Rather than fflush() throughout the code, set stdout to 89f08c3bdfSopenharmony_ci * be unbuffered. 90f08c3bdfSopenharmony_ci */ 91f08c3bdfSopenharmony_ci setvbuf(stdout, NULL, _IONBF, 0); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci for (i = 0; i < NUMADDR; i++) { 94f08c3bdfSopenharmony_ci /* Initialize the server and client addresses. */ 95f08c3bdfSopenharmony_ci svr_loop[i].sin_family = AF_INET; 96f08c3bdfSopenharmony_ci svr_loop[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i); 97f08c3bdfSopenharmony_ci svr_loop[i].sin_port = htons(SCTP_TESTPORT_1); 98f08c3bdfSopenharmony_ci svr_test[i].v4.sin_family = AF_INET; 99f08c3bdfSopenharmony_ci svr_test[i].v4.sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i); 100f08c3bdfSopenharmony_ci svr_test[i].v4.sin_port = htons(SCTP_TESTPORT_1); 101f08c3bdfSopenharmony_ci svr_try[i].sin_family = AF_INET; 102f08c3bdfSopenharmony_ci if (i < (NUMADDR-1)) { 103f08c3bdfSopenharmony_ci svr_try[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i); 104f08c3bdfSopenharmony_ci } else { 105f08c3bdfSopenharmony_ci /* Make last address invalid. */ 106f08c3bdfSopenharmony_ci svr_try[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x400); 107f08c3bdfSopenharmony_ci } 108f08c3bdfSopenharmony_ci svr_try[i].sin_port = htons(SCTP_TESTPORT_1); 109f08c3bdfSopenharmony_ci clt_loop1[i].sin_family = AF_INET; 110f08c3bdfSopenharmony_ci clt_loop1[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x100); 111f08c3bdfSopenharmony_ci clt_loop1[i].sin_port = htons(SCTP_TESTPORT_2); 112f08c3bdfSopenharmony_ci clt_test1[i].v4.sin_family = AF_INET; 113f08c3bdfSopenharmony_ci clt_test1[i].v4.sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x100); 114f08c3bdfSopenharmony_ci clt_test1[i].v4.sin_port = htons(SCTP_TESTPORT_2); 115f08c3bdfSopenharmony_ci clt_loop2[i].sin_family = AF_INET; 116f08c3bdfSopenharmony_ci clt_loop2[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x200); 117f08c3bdfSopenharmony_ci clt_loop2[i].sin_port = htons(SCTP_TESTPORT_2+1); 118f08c3bdfSopenharmony_ci clt_test2[i].v4.sin_family = AF_INET; 119f08c3bdfSopenharmony_ci clt_test2[i].v4.sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x200); 120f08c3bdfSopenharmony_ci clt_test2[i].v4.sin_port = htons(SCTP_TESTPORT_2+1); 121f08c3bdfSopenharmony_ci clt_loop3[i].sin_family = AF_INET; 122f08c3bdfSopenharmony_ci clt_loop3[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x300); 123f08c3bdfSopenharmony_ci clt_loop3[i].sin_port = htons(SCTP_TESTPORT_2+2); 124f08c3bdfSopenharmony_ci } 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci /* Create and bind the server socket. */ 127f08c3bdfSopenharmony_ci svr_sk = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); 128f08c3bdfSopenharmony_ci test_bind(svr_sk, (struct sockaddr *)&svr_loop[0], sizeof(svr_loop[0])); 129f08c3bdfSopenharmony_ci test_bindx_add(svr_sk, (struct sockaddr *)&svr_loop[1], NUMADDR-1); 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci /* Mark server socket as being able to accept new associations. */ 132f08c3bdfSopenharmony_ci test_listen(svr_sk, 1); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci /* Create and bind the client sockets. */ 135f08c3bdfSopenharmony_ci clt_sk1 = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); 136f08c3bdfSopenharmony_ci test_bind(clt_sk1, (struct sockaddr *)&clt_loop1[0], sizeof(clt_loop1)); 137f08c3bdfSopenharmony_ci test_bindx_add(clt_sk1, (struct sockaddr *)&clt_loop1[1], NUMADDR-1); 138f08c3bdfSopenharmony_ci clt_sk2 = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); 139f08c3bdfSopenharmony_ci test_bind(clt_sk2, (struct sockaddr *)&clt_loop2[0], sizeof(clt_loop2)); 140f08c3bdfSopenharmony_ci test_bindx_add(clt_sk2, (struct sockaddr *)&clt_loop2[1], NUMADDR-1); 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ 143f08c3bdfSopenharmony_ci test_enable_assoc_change(svr_sk); 144f08c3bdfSopenharmony_ci test_enable_assoc_change(clt_sk1); 145f08c3bdfSopenharmony_ci test_enable_assoc_change(clt_sk2); 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci /* Set clt_sk1 as non-blocking. */ 148f08c3bdfSopenharmony_ci flags = fcntl(clt_sk1, F_GETFL, 0); 149f08c3bdfSopenharmony_ci if (flags < 0) 150f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "fcntl F_GETFL: %s", strerror(errno)); 151f08c3bdfSopenharmony_ci if (fcntl(clt_sk1, F_SETFL, flags | O_NONBLOCK) < 0) 152f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "fcntl F_SETFL: %s", strerror(errno)); 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci /* Do a non-blocking connectx from clt_sk1 to svr_sk */ 155f08c3bdfSopenharmony_ci error = sctp_connectx(clt_sk1, (struct sockaddr *)svr_try, NUMADDR, 156f08c3bdfSopenharmony_ci &associd); 157f08c3bdfSopenharmony_ci /* Non-blocking connectx should return immediately with EINPROGRESS. */ 158f08c3bdfSopenharmony_ci if ((error != -1) || (EINPROGRESS != errno)) 159f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "non-blocking connectx error: %d " 160f08c3bdfSopenharmony_ci "errno:%d", error, errno); 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_ci tst_resm(TPASS, "non-blocking connectx"); 163f08c3bdfSopenharmony_ci 164f08c3bdfSopenharmony_ci /* Doing a connectx on a socket to create an association that is 165f08c3bdfSopenharmony_ci * is already established should return EISCONN. 166f08c3bdfSopenharmony_ci */ 167f08c3bdfSopenharmony_ci error = sctp_connectx(clt_sk1, (struct sockaddr *)svr_try, NUMADDR, 168f08c3bdfSopenharmony_ci NULL); 169f08c3bdfSopenharmony_ci if ((error != -1) || (EISCONN != errno)) 170f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "connectx on a socket to create an " 171f08c3bdfSopenharmony_ci "assoc that is already established error:%d errno:%d", 172f08c3bdfSopenharmony_ci error, errno); 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci tst_resm(TPASS, "connectx on a socket to create an assoc that is " 175f08c3bdfSopenharmony_ci "already established"); 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_ci /* Initialize inmessage for all receives. */ 178f08c3bdfSopenharmony_ci memset(&inmessage, 0, sizeof(inmessage)); 179f08c3bdfSopenharmony_ci big_buffer = test_malloc(REALLY_BIG); 180f08c3bdfSopenharmony_ci iov.iov_base = big_buffer; 181f08c3bdfSopenharmony_ci iov.iov_len = REALLY_BIG; 182f08c3bdfSopenharmony_ci inmessage.msg_iov = &iov; 183f08c3bdfSopenharmony_ci inmessage.msg_iovlen = 1; 184f08c3bdfSopenharmony_ci inmessage.msg_control = NULL; 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci /* Get COMM_UP on clt_sk1 */ 187f08c3bdfSopenharmony_ci error = test_recvmsg(clt_sk1, &inmessage, MSG_WAITALL); 188f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 189f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 190f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 191f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 192f08c3bdfSopenharmony_ci clt_associd1 = sac->sac_assoc_id; 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci if (associd) { 195f08c3bdfSopenharmony_ci if (associd != clt_associd1) 196f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "Association id mismatch: " 197f08c3bdfSopenharmony_ci "connectx returned %d, notification returned:%d", 198f08c3bdfSopenharmony_ci associd, clt_associd1); 199f08c3bdfSopenharmony_ci tst_resm(TPASS, "Association id match between sctp_connectx()" 200f08c3bdfSopenharmony_ci " and notification."); 201f08c3bdfSopenharmony_ci } 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci /* Get COMM_UP on svr_sk */ 204f08c3bdfSopenharmony_ci error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); 205f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 206f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 207f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 208f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 209f08c3bdfSopenharmony_ci svr_associd1 = sac->sac_assoc_id; 210f08c3bdfSopenharmony_ci 211f08c3bdfSopenharmony_ci /* Do a blocking connectx from clt_sk2 to svr_sk. 212f08c3bdfSopenharmony_ci * Blocking connectx should block until the association is established 213f08c3bdfSopenharmony_ci * and return success. 214f08c3bdfSopenharmony_ci */ 215f08c3bdfSopenharmony_ci test_connectx(clt_sk2, (struct sockaddr *)svr_try, NUMADDR); 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci /* Get COMM_UP on clt_sk2 */ 218f08c3bdfSopenharmony_ci error = test_recvmsg(clt_sk2, &inmessage, MSG_WAITALL); 219f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 220f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 221f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 222f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 223f08c3bdfSopenharmony_ci clt_associd2 = sac->sac_assoc_id; 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci /* Get COMM_UP on svr_sk */ 226f08c3bdfSopenharmony_ci error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); 227f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 228f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 229f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 230f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 231f08c3bdfSopenharmony_ci svr_associd2 = sac->sac_assoc_id; 232f08c3bdfSopenharmony_ci 233f08c3bdfSopenharmony_ci tst_resm(TPASS, "blocking connectx"); 234f08c3bdfSopenharmony_ci 235f08c3bdfSopenharmony_ci peeloff_sk = test_sctp_peeloff(svr_sk, svr_associd1); 236f08c3bdfSopenharmony_ci 237f08c3bdfSopenharmony_ci /* Doing a connectx on a peeled off socket should fail. */ 238f08c3bdfSopenharmony_ci error = sctp_connectx(peeloff_sk, (struct sockaddr *)clt_loop3, NUMADDR, 239f08c3bdfSopenharmony_ci NULL); 240f08c3bdfSopenharmony_ci if ((error != -1) || (EISCONN != errno)) 241f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "connectx on a peeled off socket " 242f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 243f08c3bdfSopenharmony_ci 244f08c3bdfSopenharmony_ci tst_resm(TPASS, "connectx on a peeled off socket"); 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci /* Trying to create an association on a socket that matches an 247f08c3bdfSopenharmony_ci * existing peeled-off association should fail. 248f08c3bdfSopenharmony_ci */ 249f08c3bdfSopenharmony_ci error = sctp_connectx(svr_sk, (struct sockaddr *)clt_loop1, NUMADDR, 250f08c3bdfSopenharmony_ci NULL); 251f08c3bdfSopenharmony_ci if ((error != -1) || (EADDRNOTAVAIL != errno)) 252f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "connectx to create an assoc that " 253f08c3bdfSopenharmony_ci "matches a peeled off assoc error:%d errno:%d", 254f08c3bdfSopenharmony_ci error, errno); 255f08c3bdfSopenharmony_ci 256f08c3bdfSopenharmony_ci tst_resm(TPASS, "connectx to create an assoc that matches a peeled off " 257f08c3bdfSopenharmony_ci "assoc"); 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_ci test_peer_addr(peeloff_sk, svr_associd1, clt_test1, NUMADDR); 260f08c3bdfSopenharmony_ci tst_resm(TPASS, "server association 1 peers ok"); 261f08c3bdfSopenharmony_ci test_peer_addr(svr_sk, svr_associd2, clt_test2, NUMADDR); 262f08c3bdfSopenharmony_ci tst_resm(TPASS, "server association 2 peers ok"); 263f08c3bdfSopenharmony_ci test_peer_addr(clt_sk1, clt_associd1, svr_test, NUMADDR); 264f08c3bdfSopenharmony_ci tst_resm(TPASS, "client association 1 peers ok"); 265f08c3bdfSopenharmony_ci test_peer_addr(clt_sk2, clt_associd2, svr_test, NUMADDR); 266f08c3bdfSopenharmony_ci tst_resm(TPASS, "client association 2 peers ok"); 267f08c3bdfSopenharmony_ci close(svr_sk); 268f08c3bdfSopenharmony_ci close(clt_sk1); 269f08c3bdfSopenharmony_ci close(clt_sk2); 270f08c3bdfSopenharmony_ci close(peeloff_sk); 271f08c3bdfSopenharmony_ci 272f08c3bdfSopenharmony_ci /* Indicate successful completion. */ 273f08c3bdfSopenharmony_ci return 0; 274f08c3bdfSopenharmony_ci} 275