1/* SCTP kernel Implementation 2 * (C) Copyright IBM Corp. 2002, 2003 3 * Copyright (c) 1999-2000 Cisco, Inc. 4 * Copyright (c) 1999-2001 Motorola, Inc. 5 * Copyright (c) 2001 Intel Corp. 6 * Copyright (c) 2001 Nokia, Inc. 7 * Copyright (c) 2001 La Monte H.P. Yarroll 8 * 9 * The SCTP implementation is free software; 10 * you can redistribute it and/or modify it under the terms of 11 * the GNU General Public License as published by 12 * the Free Software Foundation; either version 2, or (at your option) 13 * any later version. 14 * 15 * The SCTP implementation is distributed in the hope that it 16 * will be useful, but WITHOUT ANY WARRANTY; without even the implied 17 * ************************ 18 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 * See the GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with GNU CC; see the file COPYING. If not, write to 23 * the Free Software Foundation, 59 Temple Place - Suite 330, 24 * Boston, MA 02111-1307, USA. 25 * 26 * Please send any bug reports or fixes you make to the 27 * email address(es): 28 * lksctp developers <lksctp-developers@lists.sourceforge.net> 29 * 30 * Or submit a bug report through the following website: 31 * http://www.sf.net/projects/lksctp 32 * 33 * Any bugs reported to us we will try to fix... any fixes shared will 34 * be incorporated into the next SCTP release. 35 * 36 * Written or modified by: 37 * La Monte H.P. Yarroll <piggy@acm.org> 38 * Karl Knutson <karl@athena.chicago.il.us> 39 * Jon Grimm <jgrimm@us.ibm.com> 40 * Sridhar Samudrala <sri@us.ibm.com> 41 * Daisy Chang <daisyc@us.ibm.com> 42 */ 43 44/* This is a functional test to verify binding a socket with INADDRY_ANY 45 * address and send messages. 46 */ 47 48#include <stdio.h> 49#include <unistd.h> 50#include <string.h> 51#include <stdlib.h> 52#include <sys/types.h> 53#include <sys/socket.h> 54#include <sys/uio.h> 55#include <netinet/in.h> 56#include <errno.h> 57#include <netinet/sctp.h> 58#include <sctputil.h> 59 60char *TCID = __FILE__; 61int TST_TOTAL = 2; 62int TST_CNT = 0; 63 64int 65main(void) 66{ 67 int sk1, sk2; 68 sockaddr_storage_t loop; 69 sockaddr_storage_t anyaddr; 70 struct msghdr outmessage; 71 char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))]; 72 char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; 73 struct cmsghdr *cmsg; 74 struct sctp_sndrcvinfo *sinfo; 75 struct iovec out_iov; 76 struct iovec iov; 77 struct msghdr inmessage; 78 char *message = "hello, world!\n"; 79 char *telephone = "Watson, come here! I need you!\n"; 80 char *telephone_resp = "I already brought your coffee...\n"; 81 int error; 82 int pf_class; 83 uint32_t ppid; 84 uint32_t stream; 85 socklen_t namelen; 86 87 /* Rather than fflush() throughout the code, set stdout to 88 * be unbuffered. 89 */ 90 setvbuf(stdout, NULL, _IONBF, 0); 91 92 /* Set some basic values which depend on the address family. */ 93#if TEST_V6 94 pf_class = PF_INET6; 95 96 loop.v6.sin6_family = AF_INET6; 97 loop.v6.sin6_addr = (struct in6_addr)SCTP_IN6ADDR_LOOPBACK_INIT; 98 loop.v6.sin6_port = 0; 99 100 anyaddr.v6.sin6_family = AF_INET6; 101 anyaddr.v6.sin6_addr = (struct in6_addr)SCTP_IN6ADDR_ANY_INIT; 102 anyaddr.v6.sin6_port = 0; 103#else 104 pf_class = PF_INET; 105 106 loop.v4.sin_family = AF_INET; 107 loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 108 loop.v4.sin_port = 0; 109 110 anyaddr.v4.sin_family = AF_INET; 111 anyaddr.v4.sin_addr.s_addr = INADDR_ANY; 112 anyaddr.v4.sin_port = 0; 113#endif /* TEST_V6 */ 114 115 /* Create the two endpoints which will talk to each other. */ 116 sk1 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); 117 sk2 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); 118 119 /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ 120 test_enable_assoc_change(sk1); 121 test_enable_assoc_change(sk2); 122 123 /* Bind these sockets to the test ports. */ 124 test_bind(sk1, &loop.sa, sizeof(loop)); 125 test_bind(sk2, &anyaddr.sa, sizeof(anyaddr)); 126 127 tst_resm(TPASS, "bind INADDR_ANY address"); 128 129 /* Mark sk2 as being able to accept new associations */ 130 test_listen(sk2, 1); 131 132 /* Now use getsockaname() to retrieve the ephmeral ports. */ 133 namelen = sizeof(loop); 134 error = getsockname(sk1, &loop.sa, &namelen); 135 if (error != 0) 136 tst_brkm(TBROK, tst_exit, "getsockname: %s", strerror(errno)); 137 138 namelen = sizeof(anyaddr); 139 error = getsockname(sk2, &anyaddr.sa, &namelen); 140 if (error != 0) 141 tst_brkm(TBROK, tst_exit, "getsockname: %s", strerror(errno)); 142 143#if TEST_V6 144 loop.v6.sin6_port = anyaddr.v6.sin6_port; 145#else 146 loop.v4.sin_port = anyaddr.v4.sin_port; 147#endif 148 149 /* Send the first message. This will create the association. */ 150 outmessage.msg_name = &loop; 151 outmessage.msg_namelen = sizeof(loop); 152 outmessage.msg_iov = &out_iov; 153 outmessage.msg_iovlen = 1; 154 outmessage.msg_control = outcmsg; 155 outmessage.msg_controllen = sizeof(outcmsg); 156 outmessage.msg_flags = 0; 157 cmsg = CMSG_FIRSTHDR(&outmessage); 158 cmsg->cmsg_level = IPPROTO_SCTP; 159 cmsg->cmsg_type = SCTP_SNDRCV; 160 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 161 outmessage.msg_controllen = cmsg->cmsg_len; 162 sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); 163 memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); 164 ppid = rand(); /* Choose an arbitrary value. */ 165 stream = 1; 166 sinfo->sinfo_ppid = ppid; 167 sinfo->sinfo_stream = stream; 168 outmessage.msg_iov->iov_base = message; 169 outmessage.msg_iov->iov_len = strlen(message) + 1; 170 test_sendmsg(sk1, &outmessage, 0, strlen(message)+1); 171 172 /* Initialize inmessage for all receives. */ 173 memset(&inmessage, 0, sizeof(inmessage)); 174 iov.iov_base = test_malloc(REALLY_BIG); 175 iov.iov_len = REALLY_BIG; 176 inmessage.msg_iov = &iov; 177 inmessage.msg_iovlen = 1; 178 inmessage.msg_control = incmsg; 179 180 /* Get the communication up message on sk2. */ 181 inmessage.msg_controllen = sizeof(incmsg); 182 error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 183 test_check_msg_notification(&inmessage, error, 184 sizeof(struct sctp_assoc_change), 185 SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 186 187 /* Get the communication up message on sk1. */ 188 inmessage.msg_controllen = sizeof(incmsg); 189 error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); 190 test_check_msg_notification(&inmessage, error, 191 sizeof(struct sctp_assoc_change), 192 SCTP_ASSOC_CHANGE, SCTP_COMM_UP); 193 194 /* Get the first message which was sent. */ 195 inmessage.msg_controllen = sizeof(incmsg); 196 error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 197 test_check_msg_data(&inmessage, error, strlen(message) + 1, 198 MSG_EOR, stream, ppid); 199 200 /* Send 2 messages. */ 201 outmessage.msg_name = &loop; 202 outmessage.msg_namelen = sizeof(loop); 203 outmessage.msg_controllen = sizeof(outcmsg); 204 outmessage.msg_flags = 0; 205 cmsg = CMSG_FIRSTHDR(&outmessage); 206 cmsg->cmsg_level = IPPROTO_SCTP; 207 cmsg->cmsg_type = SCTP_SNDRCV; 208 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 209 outmessage.msg_controllen = cmsg->cmsg_len; 210 sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); 211 memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); 212 ppid++; 213 stream++; 214 sinfo->sinfo_ppid = ppid; 215 sinfo->sinfo_stream = stream; 216 outmessage.msg_iov->iov_base = telephone; 217 outmessage.msg_iov->iov_len = strlen(telephone) + 1; 218 test_sendmsg(sk1, &outmessage, 0, strlen(telephone)+1); 219 220 outmessage.msg_iov->iov_base = telephone_resp; 221 outmessage.msg_iov->iov_len = strlen(telephone_resp) + 1; 222 test_sendmsg(sk1, &outmessage, 0, strlen(telephone_resp)+1); 223 224 /* Get those two messages. */ 225 inmessage.msg_controllen = sizeof(incmsg); 226 error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 227 test_check_msg_data(&inmessage, error, strlen(telephone) + 1, 228 MSG_EOR, stream, ppid); 229 230 inmessage.msg_controllen = sizeof(incmsg); 231 error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 232 test_check_msg_data(&inmessage, error, strlen(telephone_resp) + 1, 233 MSG_EOR, stream, ppid); 234 235 /* Shut down the link. */ 236 close(sk1); 237 238 /* Get the shutdown complete notification. */ 239 inmessage.msg_controllen = sizeof(incmsg); 240 error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); 241 test_check_msg_notification(&inmessage, error, 242 sizeof(struct sctp_assoc_change), 243 SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP); 244 245 close(sk2); 246 247 tst_resm(TPASS, "send msgs from a socket with INADDR_ANY bind address"); 248 249 /* Indicate successful completion. */ 250 return 0; 251} 252