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