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 * La Monte H.P. Yarroll <piggy@acm.org> 37f08c3bdfSopenharmony_ci * Karl Knutson <karl@athena.chicago.il.us> 38f08c3bdfSopenharmony_ci * Hui Huang <hui.huang@nokia.com> 39f08c3bdfSopenharmony_ci * Jon Grimm <jgrimm@us.ibm.com> 40f08c3bdfSopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 41f08c3bdfSopenharmony_ci */ 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci/* This is a functional test to verify the data fragmentation, reassembly 44f08c3bdfSopenharmony_ci * support and SCTP_DISABLE_FRAGMENTS socket option. 45f08c3bdfSopenharmony_ci * The following tests are done in sequence. 46f08c3bdfSopenharmony_ci * - Verify SCTP_DISABLE_FRAGMENTS socket option by doing a setsockopt() 47f08c3bdfSopenharmony_ci * followed by a getsockopt(). 48f08c3bdfSopenharmony_ci * - Verify that a message size exceeding the association fragmentation 49f08c3bdfSopenharmony_ci * point cannot be sent when fragmentation is disabled. 50f08c3bdfSopenharmony_ci * - Send and receive a set of messages that are bigger than the path mtu. 51f08c3bdfSopenharmony_ci * The different message sizes to be tested are specified in the array 52f08c3bdfSopenharmony_ci * msg_sizes[]. 53f08c3bdfSopenharmony_ci */ 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci#include <stdio.h> 56f08c3bdfSopenharmony_ci#include <unistd.h> 57f08c3bdfSopenharmony_ci#include <stdlib.h> 58f08c3bdfSopenharmony_ci#include <string.h> 59f08c3bdfSopenharmony_ci#include <sys/types.h> 60f08c3bdfSopenharmony_ci#include <sys/socket.h> 61f08c3bdfSopenharmony_ci#include <sys/uio.h> 62f08c3bdfSopenharmony_ci#include <netinet/in.h> 63f08c3bdfSopenharmony_ci#include <sys/errno.h> 64f08c3bdfSopenharmony_ci#include <errno.h> 65f08c3bdfSopenharmony_ci#include <netinet/sctp.h> 66f08c3bdfSopenharmony_ci#include <sctputil.h> 67f08c3bdfSopenharmony_ci#include "tst_kernel.h" 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_cichar *TCID = __FILE__; 70f08c3bdfSopenharmony_ciint TST_TOTAL = 4; 71f08c3bdfSopenharmony_ciint TST_CNT = 0; 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ciint msg_sizes[] = {1353, 2000, 5000, 10000, 20000, 32768}; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ciint 76f08c3bdfSopenharmony_cimain(void) 77f08c3bdfSopenharmony_ci{ 78f08c3bdfSopenharmony_ci int sk1, sk2; 79f08c3bdfSopenharmony_ci sockaddr_storage_t loop1; 80f08c3bdfSopenharmony_ci sockaddr_storage_t loop2; 81f08c3bdfSopenharmony_ci struct iovec iov; 82f08c3bdfSopenharmony_ci struct msghdr inmessage; 83f08c3bdfSopenharmony_ci struct msghdr outmessage; 84f08c3bdfSopenharmony_ci char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))]; 85f08c3bdfSopenharmony_ci char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; 86f08c3bdfSopenharmony_ci struct cmsghdr *cmsg; 87f08c3bdfSopenharmony_ci struct sctp_sndrcvinfo *sinfo; 88f08c3bdfSopenharmony_ci struct iovec out_iov; 89f08c3bdfSopenharmony_ci int error, bytes_sent; 90f08c3bdfSopenharmony_ci int pf_class; 91f08c3bdfSopenharmony_ci uint32_t ppid; 92f08c3bdfSopenharmony_ci uint32_t stream; 93f08c3bdfSopenharmony_ci char *big_buffer; 94f08c3bdfSopenharmony_ci int msg_len, msg_cnt, i; 95f08c3bdfSopenharmony_ci void *msg_buf; 96f08c3bdfSopenharmony_ci int disable_frag; 97f08c3bdfSopenharmony_ci socklen_t optlen; 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci if (tst_check_driver("sctp")) 100f08c3bdfSopenharmony_ci tst_brkm(TCONF, tst_exit, "sctp driver not available"); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci /* Rather than fflush() throughout the code, set stdout to 103f08c3bdfSopenharmony_ci * be unbuffered. 104f08c3bdfSopenharmony_ci */ 105f08c3bdfSopenharmony_ci setvbuf(stdout, NULL, _IONBF, 0); 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci /* Set some basic values which depend on the address family. */ 108f08c3bdfSopenharmony_ci#if TEST_V6 109f08c3bdfSopenharmony_ci pf_class = PF_INET6; 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci loop1.v6.sin6_family = AF_INET6; 112f08c3bdfSopenharmony_ci loop1.v6.sin6_addr = in6addr_loopback; 113f08c3bdfSopenharmony_ci loop1.v6.sin6_port = htons(SCTP_TESTPORT_1); 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci loop2.v6.sin6_family = AF_INET6; 116f08c3bdfSopenharmony_ci loop2.v6.sin6_addr = in6addr_loopback; 117f08c3bdfSopenharmony_ci loop2.v6.sin6_port = htons(SCTP_TESTPORT_2); 118f08c3bdfSopenharmony_ci#else 119f08c3bdfSopenharmony_ci pf_class = PF_INET; 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci loop1.v4.sin_family = AF_INET; 122f08c3bdfSopenharmony_ci loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 123f08c3bdfSopenharmony_ci loop1.v4.sin_port = htons(SCTP_TESTPORT_1); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci loop2.v4.sin_family = AF_INET; 126f08c3bdfSopenharmony_ci loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 127f08c3bdfSopenharmony_ci loop2.v4.sin_port = htons(SCTP_TESTPORT_2); 128f08c3bdfSopenharmony_ci#endif /* TEST_V6 */ 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci /* Create the two endpoints which will talk to each other. */ 131f08c3bdfSopenharmony_ci sk1 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); 132f08c3bdfSopenharmony_ci sk2 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ 135f08c3bdfSopenharmony_ci test_enable_assoc_change(sk1); 136f08c3bdfSopenharmony_ci test_enable_assoc_change(sk2); 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci /* Bind these sockets to the test ports. */ 139f08c3bdfSopenharmony_ci test_bind(sk1, &loop1.sa, sizeof(loop1)); 140f08c3bdfSopenharmony_ci test_bind(sk2, &loop2.sa, sizeof(loop2)); 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci /* Mark sk2 as being able to accept new associations. */ 143f08c3bdfSopenharmony_ci test_listen(sk2, 1); 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_ci /* Send the first message. This will create the association. */ 146f08c3bdfSopenharmony_ci outmessage.msg_name = &loop2; 147f08c3bdfSopenharmony_ci outmessage.msg_namelen = sizeof(loop2); 148f08c3bdfSopenharmony_ci outmessage.msg_iov = &out_iov; 149f08c3bdfSopenharmony_ci outmessage.msg_iovlen = 1; 150f08c3bdfSopenharmony_ci outmessage.msg_control = outcmsg; 151f08c3bdfSopenharmony_ci outmessage.msg_controllen = sizeof(outcmsg); 152f08c3bdfSopenharmony_ci outmessage.msg_flags = 0; 153f08c3bdfSopenharmony_ci cmsg = CMSG_FIRSTHDR(&outmessage); 154f08c3bdfSopenharmony_ci cmsg->cmsg_level = IPPROTO_SCTP; 155f08c3bdfSopenharmony_ci cmsg->cmsg_type = SCTP_SNDRCV; 156f08c3bdfSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 157f08c3bdfSopenharmony_ci outmessage.msg_controllen = cmsg->cmsg_len; 158f08c3bdfSopenharmony_ci sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); 159f08c3bdfSopenharmony_ci memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); 160f08c3bdfSopenharmony_ci ppid = rand(); /* Choose an arbitrary value. */ 161f08c3bdfSopenharmony_ci stream = 1; 162f08c3bdfSopenharmony_ci sinfo->sinfo_ppid = ppid; 163f08c3bdfSopenharmony_ci sinfo->sinfo_stream = stream; 164f08c3bdfSopenharmony_ci msg_len = 10; 165f08c3bdfSopenharmony_ci msg_buf = test_build_msg(10); 166f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = msg_buf; 167f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = msg_len; 168f08c3bdfSopenharmony_ci test_sendmsg(sk1, &outmessage, 0, msg_len); 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci /* Initialize inmessage for all receives. */ 172f08c3bdfSopenharmony_ci big_buffer = test_malloc(REALLY_BIG); 173f08c3bdfSopenharmony_ci memset(&inmessage, 0, sizeof(inmessage)); 174f08c3bdfSopenharmony_ci iov.iov_base = big_buffer; 175f08c3bdfSopenharmony_ci iov.iov_len = REALLY_BIG; 176f08c3bdfSopenharmony_ci inmessage.msg_iov = &iov; 177f08c3bdfSopenharmony_ci inmessage.msg_iovlen = 1; 178f08c3bdfSopenharmony_ci inmessage.msg_control = incmsg; 179f08c3bdfSopenharmony_ci 180f08c3bdfSopenharmony_ci /* Get the communication up message on sk2. */ 181f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 182f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 183f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 184f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 185f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 186f08c3bdfSopenharmony_ci#if 0 187f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 188f08c3bdfSopenharmony_ci associd2 = sac->sac_assoc_id; 189f08c3bdfSopenharmony_ci#endif 190f08c3bdfSopenharmony_ci /* Get the communication up message on sk1. */ 191f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 192f08c3bdfSopenharmony_ci error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); 193f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 194f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 195f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 196f08c3bdfSopenharmony_ci#if 0 197f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 198f08c3bdfSopenharmony_ci associd1 = sac->sac_assoc_id; 199f08c3bdfSopenharmony_ci#endif 200f08c3bdfSopenharmony_ci /* Get the first message which was sent. */ 201f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 202f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 203f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, msg_len, MSG_EOR, stream, ppid); 204f08c3bdfSopenharmony_ci 205f08c3bdfSopenharmony_ci free(msg_buf); 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ci /* Disable fragmentation. */ 208f08c3bdfSopenharmony_ci disable_frag = 1; 209f08c3bdfSopenharmony_ci test_setsockopt(sk1, SCTP_DISABLE_FRAGMENTS, &disable_frag, 210f08c3bdfSopenharmony_ci sizeof(disable_frag)); 211f08c3bdfSopenharmony_ci 212f08c3bdfSopenharmony_ci tst_resm(TPASS, "setsockopt(SCTP_DISABLE_FRAGMENTS)"); 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_ci /* Do a getsockopt() and verify that fragmentation is disabled. */ 215f08c3bdfSopenharmony_ci disable_frag = 0; 216f08c3bdfSopenharmony_ci optlen = sizeof(disable_frag); 217f08c3bdfSopenharmony_ci error = test_getsockopt(sk1, SCTP_DISABLE_FRAGMENTS, &disable_frag, 218f08c3bdfSopenharmony_ci &optlen); 219f08c3bdfSopenharmony_ci if ((error != 0) && (disable_frag != 1)) 220f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "getsockopt(SCTP_DISABLE_FRAGMENTS) " 221f08c3bdfSopenharmony_ci "error:%d errno:%d disable_frag:%d", 222f08c3bdfSopenharmony_ci error, errno, disable_frag); 223f08c3bdfSopenharmony_ci 224f08c3bdfSopenharmony_ci tst_resm(TPASS, "getsockopt(SCTP_DISABLE_FRAGMENTS)"); 225f08c3bdfSopenharmony_ci 226f08c3bdfSopenharmony_ci /* Try to send a messsage that exceeds association fragmentation point 227f08c3bdfSopenharmony_ci * and verify that it fails. 228f08c3bdfSopenharmony_ci */ 229f08c3bdfSopenharmony_ci msg_len = 100000; 230f08c3bdfSopenharmony_ci msg_buf = test_build_msg(msg_len); 231f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = msg_buf; 232f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = msg_len; 233f08c3bdfSopenharmony_ci error = sendmsg(sk1, &outmessage, 0); 234f08c3bdfSopenharmony_ci if ((error != -1) || (errno != EMSGSIZE)) 235f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "Send a message that exceeds " 236f08c3bdfSopenharmony_ci "assoc frag point error:%d errno:%d", error, errno); 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_ci tst_resm(TPASS, "Send a message that exceeds assoc frag point"); 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_ci /* Enable Fragmentation. */ 241f08c3bdfSopenharmony_ci disable_frag = 0; 242f08c3bdfSopenharmony_ci test_setsockopt(sk1, SCTP_DISABLE_FRAGMENTS, &disable_frag, 243f08c3bdfSopenharmony_ci sizeof(disable_frag)); 244f08c3bdfSopenharmony_ci 245f08c3bdfSopenharmony_ci msg_cnt = sizeof(msg_sizes) / sizeof(int); 246f08c3bdfSopenharmony_ci 247f08c3bdfSopenharmony_ci /* Send and receive the messages of different sizes specified in the 248f08c3bdfSopenharmony_ci * msg_sizes array in a loop. 249f08c3bdfSopenharmony_ci */ 250f08c3bdfSopenharmony_ci for (i = 0; i < msg_cnt; i++) { 251f08c3bdfSopenharmony_ci 252f08c3bdfSopenharmony_ci msg_len = msg_sizes[i]; 253f08c3bdfSopenharmony_ci msg_buf = test_build_msg(msg_len); 254f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = msg_buf; 255f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = msg_len; 256f08c3bdfSopenharmony_ci bytes_sent = test_sendmsg(sk1, &outmessage, 0, msg_len); 257f08c3bdfSopenharmony_ci 258f08c3bdfSopenharmony_ci tst_resm(TINFO, "Sent %d byte message", bytes_sent); 259f08c3bdfSopenharmony_ci 260f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 261f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 262f08c3bdfSopenharmony_ci /* Handle Partial Reads. */ 263f08c3bdfSopenharmony_ci if (inmessage.msg_flags & MSG_EOR) { 264f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, bytes_sent, 265f08c3bdfSopenharmony_ci MSG_EOR, stream, ppid); 266f08c3bdfSopenharmony_ci tst_resm(TINFO, "Received %d byte message", error); 267f08c3bdfSopenharmony_ci } else { 268f08c3bdfSopenharmony_ci int remain; 269f08c3bdfSopenharmony_ci 270f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, error, 0, 271f08c3bdfSopenharmony_ci stream, ppid); 272f08c3bdfSopenharmony_ci tst_resm(TINFO, "Received %d byte message", error); 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci /* Read the remaining message. */ 275f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 276f08c3bdfSopenharmony_ci remain = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 277f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, remain, 278f08c3bdfSopenharmony_ci bytes_sent - error, 279f08c3bdfSopenharmony_ci MSG_EOR, stream, ppid); 280f08c3bdfSopenharmony_ci tst_resm(TINFO, "Received %d byte message", error); 281f08c3bdfSopenharmony_ci } 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_ci free(msg_buf); 284f08c3bdfSopenharmony_ci } 285f08c3bdfSopenharmony_ci 286f08c3bdfSopenharmony_ci tst_resm(TPASS, "Send/Receive fragmented messages"); 287f08c3bdfSopenharmony_ci 288f08c3bdfSopenharmony_ci /* Shut down the link. */ 289f08c3bdfSopenharmony_ci close(sk1); 290f08c3bdfSopenharmony_ci 291f08c3bdfSopenharmony_ci /* Get the shutdown complete notification. */ 292f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 293f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 294f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 295f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 296f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP); 297f08c3bdfSopenharmony_ci 298f08c3bdfSopenharmony_ci close(sk2); 299f08c3bdfSopenharmony_ci 300f08c3bdfSopenharmony_ci /* Indicate successful completion. */ 301f08c3bdfSopenharmony_ci return 0; 302f08c3bdfSopenharmony_ci} 303