1f08c3bdfSopenharmony_ci/* SCTP kernel Implementation 2f08c3bdfSopenharmony_ci * (C) Copyright IBM Corp. 2001, 2003 3f08c3bdfSopenharmony_ci * Copyright (c) 1999-2000 Cisco, Inc. 4f08c3bdfSopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc. 5f08c3bdfSopenharmony_ci * Copyright (c) 2001 Intel Corp. 6f08c3bdfSopenharmony_ci * Copyright (c) 2001 Nokia, Inc. 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * The SCTP implementation is free software; 9f08c3bdfSopenharmony_ci * you can redistribute it and/or modify it under the terms of 10f08c3bdfSopenharmony_ci * the GNU General Public License as published by 11f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2, or (at your option) 12f08c3bdfSopenharmony_ci * any later version. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * The SCTP implementation is distributed in the hope that it 15f08c3bdfSopenharmony_ci * will be useful, but WITHOUT ANY WARRANTY; without even the implied 16f08c3bdfSopenharmony_ci * ************************ 17f08c3bdfSopenharmony_ci * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 18f08c3bdfSopenharmony_ci * See the GNU General Public License for more details. 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 21f08c3bdfSopenharmony_ci * along with GNU CC; see the file COPYING. If not, write to 22f08c3bdfSopenharmony_ci * the Free Software Foundation, 59 Temple Place - Suite 330, 23f08c3bdfSopenharmony_ci * Boston, MA 02111-1307, USA. 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * Please send any bug reports or fixes you make to the 26f08c3bdfSopenharmony_ci * email address(es): 27f08c3bdfSopenharmony_ci * lksctp developers <lksctp-developers@lists.sourceforge.net> 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * Or submit a bug report through the following website: 30f08c3bdfSopenharmony_ci * http://www.sf.net/projects/lksctp 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci * Any bugs reported to us we will try to fix... any fixes shared will 33f08c3bdfSopenharmony_ci * be incorporated into the next SCTP release. 34f08c3bdfSopenharmony_ci * 35f08c3bdfSopenharmony_ci * Written or modified by: 36f08c3bdfSopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 37f08c3bdfSopenharmony_ci */ 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci/* This is a Functional test to verify the new SCTP interface sctp_peeloff() 40f08c3bdfSopenharmony_ci * that can be used to branch off an association into a separate socket. 41f08c3bdfSopenharmony_ci */ 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci#include <stdio.h> 44f08c3bdfSopenharmony_ci#include <unistd.h> 45f08c3bdfSopenharmony_ci#include <stdlib.h> 46f08c3bdfSopenharmony_ci#include <string.h> 47f08c3bdfSopenharmony_ci#include <sys/types.h> 48f08c3bdfSopenharmony_ci#include <sys/socket.h> 49f08c3bdfSopenharmony_ci#include <sys/uio.h> 50f08c3bdfSopenharmony_ci#include <netinet/in.h> 51f08c3bdfSopenharmony_ci#include <errno.h> 52f08c3bdfSopenharmony_ci#include <netinet/sctp.h> 53f08c3bdfSopenharmony_ci#include <sctputil.h> 54f08c3bdfSopenharmony_ci#include "tst_kernel.h" 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cichar *TCID = __FILE__; 57f08c3bdfSopenharmony_ciint TST_TOTAL = 6; 58f08c3bdfSopenharmony_ciint TST_CNT = 0; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci#define MAX_CLIENTS 10 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ciint 63f08c3bdfSopenharmony_cimain(void) 64f08c3bdfSopenharmony_ci{ 65f08c3bdfSopenharmony_ci int svr_sk, clt_sk[MAX_CLIENTS], peeloff_sk[MAX_CLIENTS]; 66f08c3bdfSopenharmony_ci sctp_assoc_t svr_associd[MAX_CLIENTS]; 67f08c3bdfSopenharmony_ci sockaddr_storage_t svr_loop, clt_loop[MAX_CLIENTS]; 68f08c3bdfSopenharmony_ci struct iovec iov; 69f08c3bdfSopenharmony_ci struct msghdr inmessage; 70f08c3bdfSopenharmony_ci struct msghdr outmessage; 71f08c3bdfSopenharmony_ci char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))]; 72f08c3bdfSopenharmony_ci char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; 73f08c3bdfSopenharmony_ci struct cmsghdr *cmsg; 74f08c3bdfSopenharmony_ci struct sctp_sndrcvinfo *sinfo; 75f08c3bdfSopenharmony_ci struct iovec out_iov; 76f08c3bdfSopenharmony_ci int error; 77f08c3bdfSopenharmony_ci uint32_t ppid; 78f08c3bdfSopenharmony_ci uint32_t stream; 79f08c3bdfSopenharmony_ci struct sctp_assoc_change *sac; 80f08c3bdfSopenharmony_ci char *big_buffer; 81f08c3bdfSopenharmony_ci int i; 82f08c3bdfSopenharmony_ci char *message = "hello, world!\n"; 83f08c3bdfSopenharmony_ci int pf_class; 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#if TEST_V6 94f08c3bdfSopenharmony_ci pf_class = PF_INET6; 95f08c3bdfSopenharmony_ci svr_loop.v6.sin6_family = AF_INET6; 96f08c3bdfSopenharmony_ci svr_loop.v6.sin6_addr = in6addr_loopback; 97f08c3bdfSopenharmony_ci svr_loop.v6.sin6_port = htons(SCTP_TESTPORT_1); 98f08c3bdfSopenharmony_ci#else 99f08c3bdfSopenharmony_ci pf_class = PF_INET; 100f08c3bdfSopenharmony_ci svr_loop.v4.sin_family = AF_INET; 101f08c3bdfSopenharmony_ci svr_loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 102f08c3bdfSopenharmony_ci svr_loop.v4.sin_port = htons(SCTP_TESTPORT_1); 103f08c3bdfSopenharmony_ci#endif 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci /* Create and bind the server socket. */ 106f08c3bdfSopenharmony_ci svr_sk = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); 107f08c3bdfSopenharmony_ci test_bind(svr_sk, &svr_loop.sa, sizeof(svr_loop)); 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ 110f08c3bdfSopenharmony_ci test_enable_assoc_change(svr_sk); 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci /* Mark server socket as being able to accept new associations. */ 113f08c3bdfSopenharmony_ci test_listen(svr_sk, 1); 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci /* Create and bind all the client sockets. */ 116f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 117f08c3bdfSopenharmony_ci clt_sk[i] = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); 118f08c3bdfSopenharmony_ci#if TEST_V6 119f08c3bdfSopenharmony_ci clt_loop[i].v6.sin6_family = AF_INET6; 120f08c3bdfSopenharmony_ci clt_loop[i].v6.sin6_addr = in6addr_loopback; 121f08c3bdfSopenharmony_ci clt_loop[i].v6.sin6_port = htons(SCTP_TESTPORT_2 + i); 122f08c3bdfSopenharmony_ci#else 123f08c3bdfSopenharmony_ci clt_loop[i].v4.sin_family = AF_INET; 124f08c3bdfSopenharmony_ci clt_loop[i].v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 125f08c3bdfSopenharmony_ci clt_loop[i].v4.sin_port = htons(SCTP_TESTPORT_2 + i); 126f08c3bdfSopenharmony_ci#endif 127f08c3bdfSopenharmony_ci test_bind(clt_sk[i], &clt_loop[i].sa, sizeof(clt_loop[i])); 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci test_enable_assoc_change(clt_sk[i]); 130f08c3bdfSopenharmony_ci } 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci /* Send the first message from all the clients to the server. This 133f08c3bdfSopenharmony_ci * will create the associations. 134f08c3bdfSopenharmony_ci */ 135f08c3bdfSopenharmony_ci outmessage.msg_name = &svr_loop; 136f08c3bdfSopenharmony_ci outmessage.msg_namelen = sizeof(svr_loop); 137f08c3bdfSopenharmony_ci outmessage.msg_iov = &out_iov; 138f08c3bdfSopenharmony_ci outmessage.msg_iovlen = 1; 139f08c3bdfSopenharmony_ci outmessage.msg_control = outcmsg; 140f08c3bdfSopenharmony_ci outmessage.msg_controllen = sizeof(outcmsg); 141f08c3bdfSopenharmony_ci outmessage.msg_flags = 0; 142f08c3bdfSopenharmony_ci cmsg = CMSG_FIRSTHDR(&outmessage); 143f08c3bdfSopenharmony_ci cmsg->cmsg_level = IPPROTO_SCTP; 144f08c3bdfSopenharmony_ci cmsg->cmsg_type = SCTP_SNDRCV; 145f08c3bdfSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 146f08c3bdfSopenharmony_ci outmessage.msg_controllen = cmsg->cmsg_len; 147f08c3bdfSopenharmony_ci sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); 148f08c3bdfSopenharmony_ci memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); 149f08c3bdfSopenharmony_ci ppid = rand(); /* Choose an arbitrary value. */ 150f08c3bdfSopenharmony_ci stream = 1; 151f08c3bdfSopenharmony_ci sinfo->sinfo_ppid = ppid; 152f08c3bdfSopenharmony_ci sinfo->sinfo_stream = stream; 153f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = message; 154f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = strlen(message) + 1; 155f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) 156f08c3bdfSopenharmony_ci test_sendmsg(clt_sk[i], &outmessage, 0, 157f08c3bdfSopenharmony_ci strlen(message)+1); 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci /* Initialize inmessage for all receives. */ 160f08c3bdfSopenharmony_ci big_buffer = test_malloc(REALLY_BIG); 161f08c3bdfSopenharmony_ci memset(&inmessage, 0, sizeof(inmessage)); 162f08c3bdfSopenharmony_ci iov.iov_base = big_buffer; 163f08c3bdfSopenharmony_ci iov.iov_len = REALLY_BIG; 164f08c3bdfSopenharmony_ci inmessage.msg_iov = &iov; 165f08c3bdfSopenharmony_ci inmessage.msg_iovlen = 1; 166f08c3bdfSopenharmony_ci inmessage.msg_control = incmsg; 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_ci /* Get the communication up message on all client sockets. */ 169f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 170f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 171f08c3bdfSopenharmony_ci error = test_recvmsg(clt_sk[i], &inmessage, MSG_WAITALL); 172f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 173f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 174f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 175f08c3bdfSopenharmony_ci#if 0 176f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 177f08c3bdfSopenharmony_ci clt_associd[i] = sac->sac_assoc_id; 178f08c3bdfSopenharmony_ci#endif 179f08c3bdfSopenharmony_ci } 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_ci /* Get the communication up message and the data message on the 182f08c3bdfSopenharmony_ci * server sockets for all the clients. 183f08c3bdfSopenharmony_ci */ 184f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 185f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 186f08c3bdfSopenharmony_ci error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); 187f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 188f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 189f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 190f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 191f08c3bdfSopenharmony_ci svr_associd[i] = sac->sac_assoc_id; 192f08c3bdfSopenharmony_ci 193f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 194f08c3bdfSopenharmony_ci error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); 195f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, strlen(message) + 1, 196f08c3bdfSopenharmony_ci MSG_EOR, stream, ppid); 197f08c3bdfSopenharmony_ci } 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ci /* Branch off all the associations on the server socket to separate 200f08c3bdfSopenharmony_ci * individual sockets. 201f08c3bdfSopenharmony_ci */ 202f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) 203f08c3bdfSopenharmony_ci peeloff_sk[i] = test_sctp_peeloff(svr_sk, svr_associd[i]); 204f08c3bdfSopenharmony_ci 205f08c3bdfSopenharmony_ci tst_resm(TPASS, "sctp_peeloff"); 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ci errno = 0; 208f08c3bdfSopenharmony_ci /* Verify that a peeled off socket is not allowed to do a listen(). */ 209f08c3bdfSopenharmony_ci error = listen(peeloff_sk[0], 1); 210f08c3bdfSopenharmony_ci if (error != -1) 211f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "listen on a peeled off socket " 212f08c3bdfSopenharmony_ci "error: %d, errno: %d", error, errno); 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_ci tst_resm(TPASS, "listen on a peeled off socket"); 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci errno = 0; 217f08c3bdfSopenharmony_ci /* Verify that an association cannot be branched off an already 218f08c3bdfSopenharmony_ci * peeled-off socket. 219f08c3bdfSopenharmony_ci */ 220f08c3bdfSopenharmony_ci if ((-1 != sctp_peeloff(peeloff_sk[0], svr_associd[0])) || 221f08c3bdfSopenharmony_ci (EINVAL != errno)) 222f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "sctp_peeloff on a peeled off " 223f08c3bdfSopenharmony_ci "socket error:%d, errno:%d", 224f08c3bdfSopenharmony_ci error, errno); 225f08c3bdfSopenharmony_ci 226f08c3bdfSopenharmony_ci tst_resm(TPASS, "sctp_peeloff on a peeled off socket"); 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci /* Send a message from all the client sockets to the server socket. */ 229f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) 230f08c3bdfSopenharmony_ci test_sendmsg(clt_sk[i], &outmessage, 0, strlen(message)+1); 231f08c3bdfSopenharmony_ci 232f08c3bdfSopenharmony_ci /* Receive the sent messages on the peeled off server sockets. */ 233f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 234f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 235f08c3bdfSopenharmony_ci error = test_recvmsg(peeloff_sk[i], &inmessage, MSG_WAITALL); 236f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, strlen(message) + 1, 237f08c3bdfSopenharmony_ci MSG_EOR, stream, ppid); 238f08c3bdfSopenharmony_ci } 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_ci tst_resm(TPASS, "Receive msgs on peeled off sockets"); 241f08c3bdfSopenharmony_ci 242f08c3bdfSopenharmony_ci /* Send a message from all the peeled off server sockets to the client 243f08c3bdfSopenharmony_ci * sockets. 244f08c3bdfSopenharmony_ci */ 245f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 246f08c3bdfSopenharmony_ci outmessage.msg_name = &clt_loop[i]; 247f08c3bdfSopenharmony_ci outmessage.msg_namelen = sizeof(clt_loop[i]); 248f08c3bdfSopenharmony_ci test_sendmsg(peeloff_sk[i], &outmessage, 0, strlen(message)+1); 249f08c3bdfSopenharmony_ci } 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci /* Receive the messages sent from the peeled of server sockets on 252f08c3bdfSopenharmony_ci * the client sockets. 253f08c3bdfSopenharmony_ci */ 254f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 255f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 256f08c3bdfSopenharmony_ci error = test_recvmsg(clt_sk[i], &inmessage, MSG_WAITALL); 257f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, strlen(message) + 1, 258f08c3bdfSopenharmony_ci MSG_EOR, stream, ppid); 259f08c3bdfSopenharmony_ci } 260f08c3bdfSopenharmony_ci 261f08c3bdfSopenharmony_ci tst_resm(TPASS, "Send msgs on peeled off sockets"); 262f08c3bdfSopenharmony_ci 263f08c3bdfSopenharmony_ci errno = 0; 264f08c3bdfSopenharmony_ci /* Verify that a peeled-off socket cannot initialize a new 265f08c3bdfSopenharmony_ci * association by trying to send a message to a client that is not 266f08c3bdfSopenharmony_ci * associated with the peeled-off socket. 267f08c3bdfSopenharmony_ci * The message is sent to the client that is associated with the 268f08c3bdfSopenharmony_ci * socket. 269f08c3bdfSopenharmony_ci */ 270f08c3bdfSopenharmony_ci outmessage.msg_name = &clt_loop[1]; 271f08c3bdfSopenharmony_ci outmessage.msg_namelen = sizeof(clt_loop[1]); 272f08c3bdfSopenharmony_ci test_sendmsg(peeloff_sk[0], &outmessage, 0, strlen(message)+1); 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 275f08c3bdfSopenharmony_ci error = test_recvmsg(clt_sk[0], &inmessage, MSG_WAITALL); 276f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, strlen(message) + 1, 277f08c3bdfSopenharmony_ci MSG_EOR, stream, ppid); 278f08c3bdfSopenharmony_ci 279f08c3bdfSopenharmony_ci tst_resm(TPASS, "peeled off socket cannot initialize a new assoc"); 280f08c3bdfSopenharmony_ci 281f08c3bdfSopenharmony_ci close(svr_sk); 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_ci /* Close all the peeled off server sockets. */ 284f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) 285f08c3bdfSopenharmony_ci close(peeloff_sk[i]); 286f08c3bdfSopenharmony_ci 287f08c3bdfSopenharmony_ci /* Get the shutdown complete notification from all the client 288f08c3bdfSopenharmony_ci * sockets. 289f08c3bdfSopenharmony_ci */ 290f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 291f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 292f08c3bdfSopenharmony_ci error = test_recvmsg(clt_sk[i], &inmessage, MSG_WAITALL); 293f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 294f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 295f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, 296f08c3bdfSopenharmony_ci SCTP_SHUTDOWN_COMP); 297f08c3bdfSopenharmony_ci 298f08c3bdfSopenharmony_ci close(clt_sk[i]); 299f08c3bdfSopenharmony_ci } 300f08c3bdfSopenharmony_ci 301f08c3bdfSopenharmony_ci /* Indicate successful completion. */ 302f08c3bdfSopenharmony_ci return 0; 303f08c3bdfSopenharmony_ci} 304