Imported Upstream version 1.0.10
[platform/upstream/lksctp-tools.git] / src / func_tests / test_inaddr_any.c
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
60 char *TCID = __FILE__;
61 int TST_TOTAL = 2;
62 int TST_CNT = 0;
63
64 int
65 main(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, af_family;
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         af_family = AF_INET6;
96
97         loop.v6.sin6_family = AF_INET6;
98         loop.v6.sin6_addr = (struct in6_addr)SCTP_IN6ADDR_LOOPBACK_INIT;
99         loop.v6.sin6_port = 0;
100
101         anyaddr.v6.sin6_family = AF_INET6;
102         anyaddr.v6.sin6_addr = (struct in6_addr)SCTP_IN6ADDR_ANY_INIT;
103         anyaddr.v6.sin6_port = 0;
104 #else
105         pf_class = PF_INET;
106         af_family = AF_INET;
107
108         loop.v4.sin_family = AF_INET;
109         loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK;
110         loop.v4.sin_port = 0;
111
112         anyaddr.v4.sin_family = AF_INET;
113         anyaddr.v4.sin_addr.s_addr = INADDR_ANY;
114         anyaddr.v4.sin_port = 0;
115 #endif /* TEST_V6 */
116
117         /* Create the two endpoints which will talk to each other.  */
118         sk1 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP);
119         sk2 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP);
120
121         /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */
122         test_enable_assoc_change(sk1);
123         test_enable_assoc_change(sk2);
124
125         /* Bind these sockets to the test ports.  */
126         test_bind(sk1, &loop.sa, sizeof(loop));
127         test_bind(sk2, &anyaddr.sa, sizeof(anyaddr));
128
129         tst_resm(TPASS, "bind INADDR_ANY address");
130
131         /* Mark sk2 as being able to accept new associations */
132         test_listen(sk2, 1);
133
134         /* Now use getsockaname() to retrieve the ephmeral ports. */
135         namelen = sizeof(loop);
136         error = getsockname(sk1, &loop.sa, &namelen);
137         if (error != 0)
138                 tst_brkm(TBROK, tst_exit, "getsockname: %s", strerror(errno));
139
140         namelen = sizeof(anyaddr);
141         error = getsockname(sk2, &anyaddr.sa, &namelen);
142         if (error != 0)
143                 tst_brkm(TBROK, tst_exit, "getsockname: %s", strerror(errno));
144         
145 #if TEST_V6
146         loop.v6.sin6_port = anyaddr.v6.sin6_port;
147 #else
148         loop.v4.sin_port = anyaddr.v4.sin_port;
149 #endif
150
151         /* Send the first message.  This will create the association.  */
152         outmessage.msg_name = &loop;
153         outmessage.msg_namelen = sizeof(loop);
154         outmessage.msg_iov = &out_iov;
155         outmessage.msg_iovlen = 1;
156         outmessage.msg_control = outcmsg;
157         outmessage.msg_controllen = sizeof(outcmsg);
158         outmessage.msg_flags = 0;
159         cmsg = CMSG_FIRSTHDR(&outmessage);
160         cmsg->cmsg_level = IPPROTO_SCTP;
161         cmsg->cmsg_type = SCTP_SNDRCV;
162         cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
163         outmessage.msg_controllen = cmsg->cmsg_len;
164         sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
165         memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
166         ppid = rand(); /* Choose an arbitrary value. */
167         stream = 1; 
168         sinfo->sinfo_ppid = ppid;
169         sinfo->sinfo_stream = stream;
170         outmessage.msg_iov->iov_base = message;
171         outmessage.msg_iov->iov_len = strlen(message) + 1;
172         test_sendmsg(sk1, &outmessage, 0, strlen(message)+1);
173
174         /* Initialize inmessage for all receives. */
175         memset(&inmessage, 0, sizeof(inmessage));
176         iov.iov_base = test_malloc(REALLY_BIG);
177         iov.iov_len = REALLY_BIG;
178         inmessage.msg_iov = &iov;
179         inmessage.msg_iovlen = 1;
180         inmessage.msg_control = incmsg;
181
182         /* Get the communication up message on sk2.  */
183         inmessage.msg_controllen = sizeof(incmsg);
184         error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
185         test_check_msg_notification(&inmessage, error,
186                                     sizeof(struct sctp_assoc_change),
187                                     SCTP_ASSOC_CHANGE, SCTP_COMM_UP);   
188
189         /* Get the communication up message on sk1.  */
190         inmessage.msg_controllen = sizeof(incmsg);
191         error = test_recvmsg(sk1, &inmessage, MSG_WAITALL);
192         test_check_msg_notification(&inmessage, error,
193                                     sizeof(struct sctp_assoc_change),
194                                     SCTP_ASSOC_CHANGE, SCTP_COMM_UP);   
195
196         /* Get the first message which was sent.  */
197         inmessage.msg_controllen = sizeof(incmsg);
198         error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
199         test_check_msg_data(&inmessage, error, strlen(message) + 1, 
200                             MSG_EOR, stream, ppid);
201
202        /* Send 2 messages.  */
203         outmessage.msg_name = &loop;
204         outmessage.msg_namelen = sizeof(loop);
205         outmessage.msg_controllen = sizeof(outcmsg);
206         outmessage.msg_flags = 0;
207         cmsg = CMSG_FIRSTHDR(&outmessage);
208         cmsg->cmsg_level = IPPROTO_SCTP;
209         cmsg->cmsg_type = SCTP_SNDRCV;
210         cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
211         outmessage.msg_controllen = cmsg->cmsg_len;
212         sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
213         memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
214         ppid++;
215         stream++;
216         sinfo->sinfo_ppid = ppid;
217         sinfo->sinfo_stream = stream;
218         outmessage.msg_iov->iov_base = telephone;
219         outmessage.msg_iov->iov_len = strlen(telephone) + 1;
220         test_sendmsg(sk1, &outmessage, 0, strlen(telephone)+1);
221
222         outmessage.msg_iov->iov_base = telephone_resp;
223         outmessage.msg_iov->iov_len = strlen(telephone_resp) + 1;
224         test_sendmsg(sk1, &outmessage, 0, strlen(telephone_resp)+1);
225         
226         /* Get those two messages.  */
227         inmessage.msg_controllen = sizeof(incmsg);
228         error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
229         test_check_msg_data(&inmessage, error, strlen(telephone) + 1, 
230                             MSG_EOR, stream, ppid);
231
232         inmessage.msg_controllen = sizeof(incmsg);
233         error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
234         test_check_msg_data(&inmessage, error, strlen(telephone_resp) + 1, 
235                             MSG_EOR, stream, ppid);
236         
237         /* Shut down the link.  */
238         close(sk1);
239
240         /* Get the shutdown complete notification. */
241         inmessage.msg_controllen = sizeof(incmsg);
242         error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
243         test_check_msg_notification(&inmessage, error,
244                                     sizeof(struct sctp_assoc_change),
245                                     SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP);
246
247         close(sk2);
248
249         tst_resm(TPASS, "send msgs from a socket with INADDR_ANY bind address");
250
251         /* Indicate successful completion.  */
252         return 0;
253 }