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 * Jon Grimm <jgrimm@us.ibm.com> 37f08c3bdfSopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 38f08c3bdfSopenharmony_ci */ 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci/* 41f08c3bdfSopenharmony_ci * This is a basic functional test for the SCTP kernel 42f08c3bdfSopenharmony_ci * implementation of sndrcvinfo.sinfo_timetolive. 43f08c3bdfSopenharmony_ci * 44f08c3bdfSopenharmony_ci * 1) Create two sockets, the listening socket sets its RECVBUF small 45f08c3bdfSopenharmony_ci * 2) Create a connection. Send enough data to the non-reading listener 46f08c3bdfSopenharmony_ci * to fill the RCVBUF. 47f08c3bdfSopenharmony_ci * 5) Set sinfo_timetolive on a message and send. 48f08c3bdfSopenharmony_ci * 6) Disable sinfo_timetolive on a message and send. 49f08c3bdfSopenharmony_ci * 7) Wait sinfo_timetolive. 50f08c3bdfSopenharmony_ci * 8) Read out all the data at the receiver. 51f08c3bdfSopenharmony_ci * 9) Make sure timed out message did not make it. 52f08c3bdfSopenharmony_ci * 10) Make sure that the message with no timeout makes it to the receiver. 53f08c3bdfSopenharmony_ci * 54f08c3bdfSopenharmony_ci * Also test with SEND_FAILED notifications. Also, use a fragmented 55f08c3bdfSopenharmony_ci * message so as to also exercise the SEND_FAILED of fragmentation 56f08c3bdfSopenharmony_ci * code. 57f08c3bdfSopenharmony_ci */ 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci#include <stdio.h> 60f08c3bdfSopenharmony_ci#include <unistd.h> 61f08c3bdfSopenharmony_ci#include <stdlib.h> 62f08c3bdfSopenharmony_ci#include <string.h> 63f08c3bdfSopenharmony_ci#include <sys/types.h> 64f08c3bdfSopenharmony_ci#include <sys/socket.h> 65f08c3bdfSopenharmony_ci#include <sys/uio.h> 66f08c3bdfSopenharmony_ci#include <netinet/in.h> 67f08c3bdfSopenharmony_ci#include <sys/errno.h> 68f08c3bdfSopenharmony_ci#include <errno.h> 69f08c3bdfSopenharmony_ci#include <netinet/sctp.h> 70f08c3bdfSopenharmony_ci#include <sctputil.h> 71f08c3bdfSopenharmony_ci#include "tst_kernel.h" 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_cichar *TCID = __FILE__; 74f08c3bdfSopenharmony_ciint TST_TOTAL = 6; 75f08c3bdfSopenharmony_ciint TST_CNT = 0; 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci/* This is the size of our RCVBUF */ 78f08c3bdfSopenharmony_ci#define SMALL_RCVBUF 3000 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci/* MAX segment size */ 81f08c3bdfSopenharmony_ci#define SMALL_MAXSEG 500 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci/* RWND_SLOP is the extra data that fills up the rwnd */ 84f08c3bdfSopenharmony_ci#define RWND_SLOP 100 85f08c3bdfSopenharmony_cistatic char *fillmsg = NULL; 86f08c3bdfSopenharmony_cistatic char *ttlmsg = "This should time out!\n"; 87f08c3bdfSopenharmony_cistatic char *nottlmsg = "This should NOT time out!\n"; 88f08c3bdfSopenharmony_cistatic char ttlfrag[SMALL_MAXSEG*3] = {0}; 89f08c3bdfSopenharmony_cistatic char *message = "Hello world\n"; 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ciint main(void) 92f08c3bdfSopenharmony_ci{ 93f08c3bdfSopenharmony_ci int sk1, sk2; 94f08c3bdfSopenharmony_ci sockaddr_storage_t loop1; 95f08c3bdfSopenharmony_ci sockaddr_storage_t loop2; 96f08c3bdfSopenharmony_ci struct iovec iov; 97f08c3bdfSopenharmony_ci struct msghdr inmessage; 98f08c3bdfSopenharmony_ci struct msghdr outmessage; 99f08c3bdfSopenharmony_ci char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))]; 100f08c3bdfSopenharmony_ci char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; 101f08c3bdfSopenharmony_ci struct cmsghdr *cmsg; 102f08c3bdfSopenharmony_ci struct sctp_sndrcvinfo *sinfo; 103f08c3bdfSopenharmony_ci struct iovec out_iov; 104f08c3bdfSopenharmony_ci int error; 105f08c3bdfSopenharmony_ci int pf_class; 106f08c3bdfSopenharmony_ci uint32_t ppid; 107f08c3bdfSopenharmony_ci uint32_t stream; 108f08c3bdfSopenharmony_ci sctp_assoc_t associd1; 109f08c3bdfSopenharmony_ci struct sctp_assoc_change *sac; 110f08c3bdfSopenharmony_ci struct sctp_event_subscribe subscribe; 111f08c3bdfSopenharmony_ci char *big_buffer; 112f08c3bdfSopenharmony_ci int offset; 113f08c3bdfSopenharmony_ci struct sctp_send_failed *ssf; 114f08c3bdfSopenharmony_ci socklen_t len; /* Really becomes 2xlen when set. */ 115f08c3bdfSopenharmony_ci int orig_len; 116f08c3bdfSopenharmony_ci struct sctp_status gstatus; 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci if (tst_check_driver("sctp")) 119f08c3bdfSopenharmony_ci tst_brkm(TCONF, tst_exit, "sctp driver not available"); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci /* Rather than fflush() throughout the code, set stdout to 122f08c3bdfSopenharmony_ci * be unbuffered. 123f08c3bdfSopenharmony_ci */ 124f08c3bdfSopenharmony_ci setvbuf(stdout, NULL, _IONBF, 0); 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci /* Set some basic values which depend on the address family. */ 127f08c3bdfSopenharmony_ci#if TEST_V6 128f08c3bdfSopenharmony_ci pf_class = PF_INET6; 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci loop1.v6.sin6_family = AF_INET6; 131f08c3bdfSopenharmony_ci loop1.v6.sin6_addr = in6addr_loopback; 132f08c3bdfSopenharmony_ci loop1.v6.sin6_port = htons(SCTP_TESTPORT_1); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci loop2.v6.sin6_family = AF_INET6; 135f08c3bdfSopenharmony_ci loop2.v6.sin6_addr = in6addr_loopback; 136f08c3bdfSopenharmony_ci loop2.v6.sin6_port = htons(SCTP_TESTPORT_2); 137f08c3bdfSopenharmony_ci#else 138f08c3bdfSopenharmony_ci pf_class = PF_INET; 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci loop1.v4.sin_family = AF_INET; 141f08c3bdfSopenharmony_ci loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 142f08c3bdfSopenharmony_ci loop1.v4.sin_port = htons(SCTP_TESTPORT_1); 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci loop2.v4.sin_family = AF_INET; 145f08c3bdfSopenharmony_ci loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 146f08c3bdfSopenharmony_ci loop2.v4.sin_port = htons(SCTP_TESTPORT_2); 147f08c3bdfSopenharmony_ci#endif /* TEST_V6 */ 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci /* Create the two endpoints which will talk to each other. */ 150f08c3bdfSopenharmony_ci sk1 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); 151f08c3bdfSopenharmony_ci sk2 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci len = sizeof(int); 154f08c3bdfSopenharmony_ci error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &orig_len, 155f08c3bdfSopenharmony_ci &len); 156f08c3bdfSopenharmony_ci if (error) 157f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "can't get rcvbuf size: %s", 158f08c3bdfSopenharmony_ci strerror(errno)); 159f08c3bdfSopenharmony_ci /* Set the MAXSEG to something smallish. */ 160f08c3bdfSopenharmony_ci { 161f08c3bdfSopenharmony_ci int val = SMALL_MAXSEG; 162f08c3bdfSopenharmony_ci test_setsockopt(sk1, SCTP_MAXSEG, &val, sizeof(val)); 163f08c3bdfSopenharmony_ci } 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci memset(&subscribe, 0, sizeof(subscribe)); 166f08c3bdfSopenharmony_ci subscribe.sctp_data_io_event = 1; 167f08c3bdfSopenharmony_ci subscribe.sctp_association_event = 1; 168f08c3bdfSopenharmony_ci subscribe.sctp_send_failure_event = 1; 169f08c3bdfSopenharmony_ci test_setsockopt(sk1, SCTP_EVENTS, &subscribe, sizeof(subscribe)); 170f08c3bdfSopenharmony_ci test_setsockopt(sk2, SCTP_EVENTS, &subscribe, sizeof(subscribe)); 171f08c3bdfSopenharmony_ci 172f08c3bdfSopenharmony_ci /* Bind these sockets to the test ports. */ 173f08c3bdfSopenharmony_ci test_bind(sk1, &loop1.sa, sizeof(loop1)); 174f08c3bdfSopenharmony_ci test_bind(sk2, &loop2.sa, sizeof(loop2)); 175f08c3bdfSopenharmony_ci 176f08c3bdfSopenharmony_ci /* 177f08c3bdfSopenharmony_ci * This code sets the associations RWND very small so we can 178f08c3bdfSopenharmony_ci * fill it. It does this by manipulating the rcvbuf as follows: 179f08c3bdfSopenharmony_ci * 1) Reduce the rcvbuf size on the socket 180f08c3bdfSopenharmony_ci * 2) create an association so that we advertize rcvbuf/2 as 181f08c3bdfSopenharmony_ci * our initial rwnd 182f08c3bdfSopenharmony_ci * 3) raise the rcvbuf value so that we don't drop data wile 183f08c3bdfSopenharmony_ci * receiving later data 184f08c3bdfSopenharmony_ci */ 185f08c3bdfSopenharmony_ci len = SMALL_RCVBUF; 186f08c3bdfSopenharmony_ci error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &len, 187f08c3bdfSopenharmony_ci sizeof(len)); 188f08c3bdfSopenharmony_ci if (error) 189f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "setsockopt(SO_RCVBUF): %s", 190f08c3bdfSopenharmony_ci strerror(errno)); 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci /* Mark sk2 as being able to accept new associations. */ 193f08c3bdfSopenharmony_ci test_listen(sk2, 1); 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_ci /* Send the first message. This will create the association. */ 196f08c3bdfSopenharmony_ci outmessage.msg_name = &loop2; 197f08c3bdfSopenharmony_ci outmessage.msg_namelen = sizeof(loop2); 198f08c3bdfSopenharmony_ci outmessage.msg_iov = &out_iov; 199f08c3bdfSopenharmony_ci outmessage.msg_iovlen = 1; 200f08c3bdfSopenharmony_ci outmessage.msg_control = outcmsg; 201f08c3bdfSopenharmony_ci outmessage.msg_controllen = sizeof(outcmsg); 202f08c3bdfSopenharmony_ci outmessage.msg_flags = 0; 203f08c3bdfSopenharmony_ci cmsg = CMSG_FIRSTHDR(&outmessage); 204f08c3bdfSopenharmony_ci cmsg->cmsg_level = IPPROTO_SCTP; 205f08c3bdfSopenharmony_ci cmsg->cmsg_type = SCTP_SNDRCV; 206f08c3bdfSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 207f08c3bdfSopenharmony_ci outmessage.msg_controllen = cmsg->cmsg_len; 208f08c3bdfSopenharmony_ci sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); 209f08c3bdfSopenharmony_ci memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); 210f08c3bdfSopenharmony_ci ppid = rand(); /* Choose an arbitrary value. */ 211f08c3bdfSopenharmony_ci stream = 1; 212f08c3bdfSopenharmony_ci sinfo->sinfo_ppid = ppid; 213f08c3bdfSopenharmony_ci sinfo->sinfo_stream = stream; 214f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = message; 215f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = strlen(message) + 1; 216f08c3bdfSopenharmony_ci test_sendmsg(sk1, &outmessage, 0, strlen(message)+1); 217f08c3bdfSopenharmony_ci 218f08c3bdfSopenharmony_ci /* Initialize inmessage for all receives. */ 219f08c3bdfSopenharmony_ci big_buffer = test_malloc(REALLY_BIG); 220f08c3bdfSopenharmony_ci memset(&inmessage, 0, sizeof(inmessage)); 221f08c3bdfSopenharmony_ci iov.iov_base = big_buffer; 222f08c3bdfSopenharmony_ci iov.iov_len = REALLY_BIG; 223f08c3bdfSopenharmony_ci inmessage.msg_iov = &iov; 224f08c3bdfSopenharmony_ci inmessage.msg_iovlen = 1; 225f08c3bdfSopenharmony_ci inmessage.msg_control = incmsg; 226f08c3bdfSopenharmony_ci 227f08c3bdfSopenharmony_ci /* Get the communication up message on sk2. */ 228f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 229f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 230f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 231f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 232f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 233f08c3bdfSopenharmony_ci#if 0 234f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 235f08c3bdfSopenharmony_ci associd2 = sac->sac_assoc_id; 236f08c3bdfSopenharmony_ci#endif 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_ci /* Get the communication up message on sk1. */ 239f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 240f08c3bdfSopenharmony_ci error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); 241f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 242f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 243f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 244f08c3bdfSopenharmony_ci sac = (struct sctp_assoc_change *)iov.iov_base; 245f08c3bdfSopenharmony_ci associd1 = sac->sac_assoc_id; 246f08c3bdfSopenharmony_ci 247f08c3bdfSopenharmony_ci /* restore the rcvbuffer size for the receiving socket */ 248f08c3bdfSopenharmony_ci error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &orig_len, 249f08c3bdfSopenharmony_ci sizeof(orig_len)); 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci if (error) 252f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "setsockopt(SO_RCVBUF): %s", 253f08c3bdfSopenharmony_ci strerror(errno)); 254f08c3bdfSopenharmony_ci 255f08c3bdfSopenharmony_ci /* Get the first data message which was sent. */ 256f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 257f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 258f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, strlen(message) + 1, 259f08c3bdfSopenharmony_ci MSG_EOR, stream, ppid); 260f08c3bdfSopenharmony_ci 261f08c3bdfSopenharmony_ci /* Figure out how big to make our fillmsg */ 262f08c3bdfSopenharmony_ci len = sizeof(struct sctp_status); 263f08c3bdfSopenharmony_ci memset(&gstatus,0,sizeof(struct sctp_status)); 264f08c3bdfSopenharmony_ci gstatus.sstat_assoc_id = associd1; 265f08c3bdfSopenharmony_ci error = getsockopt(sk1, IPPROTO_SCTP, SCTP_STATUS, &gstatus, &len); 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_ci if (error) 268f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "can't get rwnd size: %s", 269f08c3bdfSopenharmony_ci strerror(errno)); 270f08c3bdfSopenharmony_ci tst_resm(TINFO, "Creating fillmsg of size %d", 271f08c3bdfSopenharmony_ci gstatus.sstat_rwnd+RWND_SLOP); 272f08c3bdfSopenharmony_ci fillmsg = malloc(gstatus.sstat_rwnd+RWND_SLOP); 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci /* Send a fillmsg */ 275f08c3bdfSopenharmony_ci outmessage.msg_controllen = sizeof(outcmsg); 276f08c3bdfSopenharmony_ci outmessage.msg_flags = 0; 277f08c3bdfSopenharmony_ci cmsg = CMSG_FIRSTHDR(&outmessage); 278f08c3bdfSopenharmony_ci cmsg->cmsg_level = IPPROTO_SCTP; 279f08c3bdfSopenharmony_ci cmsg->cmsg_type = SCTP_SNDRCV; 280f08c3bdfSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 281f08c3bdfSopenharmony_ci outmessage.msg_controllen = cmsg->cmsg_len; 282f08c3bdfSopenharmony_ci sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); 283f08c3bdfSopenharmony_ci memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); 284f08c3bdfSopenharmony_ci ppid++; 285f08c3bdfSopenharmony_ci stream++; 286f08c3bdfSopenharmony_ci sinfo->sinfo_ppid = ppid; 287f08c3bdfSopenharmony_ci sinfo->sinfo_stream = stream; 288f08c3bdfSopenharmony_ci memset(fillmsg, 'X', gstatus.sstat_rwnd+RWND_SLOP); 289f08c3bdfSopenharmony_ci fillmsg[gstatus.sstat_rwnd+RWND_SLOP-1] = '\0'; 290f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = fillmsg; 291f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = gstatus.sstat_rwnd+RWND_SLOP; 292f08c3bdfSopenharmony_ci outmessage.msg_name = NULL; 293f08c3bdfSopenharmony_ci outmessage.msg_namelen = 0; 294f08c3bdfSopenharmony_ci sinfo->sinfo_assoc_id = associd1; 295f08c3bdfSopenharmony_ci sinfo->sinfo_timetolive = 0; 296f08c3bdfSopenharmony_ci test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, 297f08c3bdfSopenharmony_ci gstatus.sstat_rwnd+RWND_SLOP); 298f08c3bdfSopenharmony_ci 299f08c3bdfSopenharmony_ci /* Now send the message with timeout. */ 300f08c3bdfSopenharmony_ci sinfo->sinfo_ppid = ppid; 301f08c3bdfSopenharmony_ci sinfo->sinfo_stream = stream; 302f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = ttlmsg; 303f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = strlen(ttlmsg) + 1; 304f08c3bdfSopenharmony_ci outmessage.msg_name = NULL; 305f08c3bdfSopenharmony_ci outmessage.msg_namelen = 0; 306f08c3bdfSopenharmony_ci sinfo->sinfo_assoc_id = associd1; 307f08c3bdfSopenharmony_ci sinfo->sinfo_timetolive = 2000; 308f08c3bdfSopenharmony_ci test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(ttlmsg) + 1); 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci tst_resm(TPASS, "Send a message with timeout"); 311f08c3bdfSopenharmony_ci 312f08c3bdfSopenharmony_ci /* Next send a message with no timeout. */ 313f08c3bdfSopenharmony_ci sinfo->sinfo_ppid = ppid; 314f08c3bdfSopenharmony_ci sinfo->sinfo_stream = stream; 315f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = nottlmsg; 316f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = strlen(nottlmsg) + 1; 317f08c3bdfSopenharmony_ci outmessage.msg_name = NULL; 318f08c3bdfSopenharmony_ci outmessage.msg_namelen = 0; 319f08c3bdfSopenharmony_ci sinfo->sinfo_assoc_id = associd1; 320f08c3bdfSopenharmony_ci sinfo->sinfo_timetolive = 0; 321f08c3bdfSopenharmony_ci test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(nottlmsg)+1); 322f08c3bdfSopenharmony_ci 323f08c3bdfSopenharmony_ci tst_resm(TPASS, "Send a message with no timeout"); 324f08c3bdfSopenharmony_ci 325f08c3bdfSopenharmony_ci /* And finally a fragmented message that will time out. */ 326f08c3bdfSopenharmony_ci sinfo->sinfo_ppid = ppid; 327f08c3bdfSopenharmony_ci sinfo->sinfo_stream = stream; 328f08c3bdfSopenharmony_ci memset(ttlfrag, '0', sizeof(ttlfrag)); 329f08c3bdfSopenharmony_ci ttlfrag[sizeof(ttlfrag)-1] = '\0'; 330f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_base = ttlfrag; 331f08c3bdfSopenharmony_ci outmessage.msg_iov->iov_len = sizeof(ttlfrag); 332f08c3bdfSopenharmony_ci outmessage.msg_name = NULL; 333f08c3bdfSopenharmony_ci outmessage.msg_namelen = 0; 334f08c3bdfSopenharmony_ci sinfo->sinfo_assoc_id = associd1; 335f08c3bdfSopenharmony_ci sinfo->sinfo_timetolive = 2000; 336f08c3bdfSopenharmony_ci test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, sizeof(ttlfrag)); 337f08c3bdfSopenharmony_ci 338f08c3bdfSopenharmony_ci tst_resm(TPASS, "Send a fragmented message with timeout"); 339f08c3bdfSopenharmony_ci 340f08c3bdfSopenharmony_ci /* Sleep waiting for the message to time out. */ 341f08c3bdfSopenharmony_ci tst_resm(TINFO, " ** SLEEPING for 3 seconds **"); 342f08c3bdfSopenharmony_ci sleep(3); 343f08c3bdfSopenharmony_ci 344f08c3bdfSopenharmony_ci /* Read the fillmsg snuck in between the ttl'd messages. */ 345f08c3bdfSopenharmony_ci do { 346f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 347f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 348f08c3bdfSopenharmony_ci } while (!(inmessage.msg_flags & MSG_EOR)); 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ci /* Now get the message that did NOT time out. */ 351f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 352f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 353f08c3bdfSopenharmony_ci test_check_msg_data(&inmessage, error, strlen(nottlmsg) + 1, 354f08c3bdfSopenharmony_ci MSG_EOR, stream, ppid); 355f08c3bdfSopenharmony_ci if (0 != strncmp(iov.iov_base, nottlmsg, strlen(nottlmsg)+1)) 356f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "Received Wrong Message !!!"); 357f08c3bdfSopenharmony_ci 358f08c3bdfSopenharmony_ci tst_resm(TPASS, "Receive message with no timeout"); 359f08c3bdfSopenharmony_ci 360f08c3bdfSopenharmony_ci /* Get the SEND_FAILED notification for the message that DID 361f08c3bdfSopenharmony_ci * time out. 362f08c3bdfSopenharmony_ci */ 363f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 364f08c3bdfSopenharmony_ci error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); 365f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 366f08c3bdfSopenharmony_ci sizeof(struct sctp_send_failed) + 367f08c3bdfSopenharmony_ci strlen(ttlmsg) + 1, 368f08c3bdfSopenharmony_ci SCTP_SEND_FAILED, 0); 369f08c3bdfSopenharmony_ci ssf = (struct sctp_send_failed *)iov.iov_base; 370f08c3bdfSopenharmony_ci if (0 != strncmp(ttlmsg, (char *)ssf->ssf_data, strlen(ttlmsg) + 1)) 371f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "SEND_FAILED data mismatch"); 372f08c3bdfSopenharmony_ci 373f08c3bdfSopenharmony_ci tst_resm(TPASS, "Receive SEND_FAILED for message with timeout"); 374f08c3bdfSopenharmony_ci 375f08c3bdfSopenharmony_ci /* Get the SEND_FAILED notification for the fragmented message that 376f08c3bdfSopenharmony_ci * DID time out. 377f08c3bdfSopenharmony_ci */ 378f08c3bdfSopenharmony_ci offset = 0; 379f08c3bdfSopenharmony_ci do { 380f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 381f08c3bdfSopenharmony_ci error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); 382f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 383f08c3bdfSopenharmony_ci sizeof(struct sctp_send_failed) + 384f08c3bdfSopenharmony_ci SMALL_MAXSEG, 385f08c3bdfSopenharmony_ci SCTP_SEND_FAILED, 0); 386f08c3bdfSopenharmony_ci ssf = (struct sctp_send_failed *)iov.iov_base; 387f08c3bdfSopenharmony_ci if (0 != strncmp(&ttlfrag[offset], (char *)ssf->ssf_data, 388f08c3bdfSopenharmony_ci SMALL_MAXSEG)) 389f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "SEND_FAILED data mismatch"); 390f08c3bdfSopenharmony_ci offset += SMALL_MAXSEG; 391f08c3bdfSopenharmony_ci } while (!(ssf->ssf_info.sinfo_flags & 0x01)); /* LAST_FRAG */ 392f08c3bdfSopenharmony_ci 393f08c3bdfSopenharmony_ci tst_resm(TPASS, "Receive SEND_FAILED for fragmented message with " 394f08c3bdfSopenharmony_ci "timeout"); 395f08c3bdfSopenharmony_ci 396f08c3bdfSopenharmony_ci /* Shut down the link. */ 397f08c3bdfSopenharmony_ci close(sk1); 398f08c3bdfSopenharmony_ci 399f08c3bdfSopenharmony_ci /* Get the shutdown complete notification. */ 400f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 401f08c3bdfSopenharmony_ci error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 402f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 403f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 404f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP); 405f08c3bdfSopenharmony_ci 406f08c3bdfSopenharmony_ci close(sk2); 407f08c3bdfSopenharmony_ci 408f08c3bdfSopenharmony_ci /* Indicate successful completion. */ 409f08c3bdfSopenharmony_ci return 0; 410f08c3bdfSopenharmony_ci} 411