1f08c3bdfSopenharmony_ci/* SCTP kernel Implementation
2f08c3bdfSopenharmony_ci * (C) Copyright IBM Corp. 2004
3f08c3bdfSopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc.
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci * The SCTP implementation is free software;
6f08c3bdfSopenharmony_ci * you can redistribute it and/or modify it under the terms of
7f08c3bdfSopenharmony_ci * the GNU General Public License as published by
8f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2, or (at your option)
9f08c3bdfSopenharmony_ci * any later version.
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * The SCTP implementation is distributed in the hope that it
12f08c3bdfSopenharmony_ci * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13f08c3bdfSopenharmony_ci *                 ************************
14f08c3bdfSopenharmony_ci * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15f08c3bdfSopenharmony_ci * See the GNU General Public License for more details.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License
18f08c3bdfSopenharmony_ci * along with GNU CC; see the file COPYING.  If not, write to
19f08c3bdfSopenharmony_ci * the Free Software Foundation, 59 Temple Place - Suite 330,
20f08c3bdfSopenharmony_ci * Boston, MA 02111-1307, USA.
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci * Please send any bug reports or fixes you make to the
23f08c3bdfSopenharmony_ci * email address(es):
24f08c3bdfSopenharmony_ci *    lksctp developers <lksctp-developers@lists.sourceforge.net>
25f08c3bdfSopenharmony_ci *
26f08c3bdfSopenharmony_ci * Or submit a bug report through the following website:
27f08c3bdfSopenharmony_ci *    http://www.sf.net/projects/lksctp
28f08c3bdfSopenharmony_ci *
29f08c3bdfSopenharmony_ci * Any bugs reported given to us we will try to fix... any fixes shared will
30f08c3bdfSopenharmony_ci * be incorporated into the next SCTP release.
31f08c3bdfSopenharmony_ci *
32f08c3bdfSopenharmony_ci * Written or modified by:
33f08c3bdfSopenharmony_ci *    Sridhar Samudrala		<sri@us.ibm.com>
34f08c3bdfSopenharmony_ci */
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci/* This is a kernel test to verify getsockname() and getpeername() interfaces
37f08c3bdfSopenharmony_ci * for single-homed one-to-one style sockets.
38f08c3bdfSopenharmony_ci */
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci#include <stdio.h>
41f08c3bdfSopenharmony_ci#include <unistd.h>
42f08c3bdfSopenharmony_ci#include <stdlib.h>
43f08c3bdfSopenharmony_ci#include <string.h>
44f08c3bdfSopenharmony_ci#include <fcntl.h>
45f08c3bdfSopenharmony_ci#include <sys/types.h>
46f08c3bdfSopenharmony_ci#include <sys/socket.h>
47f08c3bdfSopenharmony_ci#include <sys/uio.h>
48f08c3bdfSopenharmony_ci#include <netinet/in.h>
49f08c3bdfSopenharmony_ci#include <errno.h>
50f08c3bdfSopenharmony_ci#include <netinet/sctp.h>
51f08c3bdfSopenharmony_ci#include <sctputil.h>
52f08c3bdfSopenharmony_ci#include "tst_kernel.h"
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_cichar *TCID = __FILE__;
55f08c3bdfSopenharmony_ciint TST_TOTAL = 13;
56f08c3bdfSopenharmony_ciint TST_CNT = 0;
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci#define MAX_CLIENTS 10
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ciint
61f08c3bdfSopenharmony_cimain(void)
62f08c3bdfSopenharmony_ci{
63f08c3bdfSopenharmony_ci	int clt_sk, svr_sk, accept_sk;
64f08c3bdfSopenharmony_ci	sockaddr_storage_t svr_loop, accept_loop;
65f08c3bdfSopenharmony_ci	sockaddr_storage_t svr_local_addr, svr_peer_addr;
66f08c3bdfSopenharmony_ci	sockaddr_storage_t clt_local_addr, clt_peer_addr;
67f08c3bdfSopenharmony_ci	socklen_t len;
68f08c3bdfSopenharmony_ci	int error;
69f08c3bdfSopenharmony_ci	int pf_class;
70f08c3bdfSopenharmony_ci	int fd, err_no = 0;
71f08c3bdfSopenharmony_ci	char filename[21];
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci	if (tst_check_driver("sctp"))
74f08c3bdfSopenharmony_ci		tst_brkm(TCONF, tst_exit, "sctp driver not available");
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci        /* Rather than fflush() throughout the code, set stdout to
77f08c3bdfSopenharmony_ci	 * be unbuffered.
78f08c3bdfSopenharmony_ci	 */
79f08c3bdfSopenharmony_ci	setvbuf(stdout, NULL, _IONBF, 0);
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ci	/* Initialize the server and client addresses. */
82f08c3bdfSopenharmony_ci#if TEST_V6
83f08c3bdfSopenharmony_ci	pf_class = PF_INET6;
84f08c3bdfSopenharmony_ci        svr_loop.v6.sin6_family = AF_INET6;
85f08c3bdfSopenharmony_ci        svr_loop.v6.sin6_addr = (struct in6_addr)SCTP_IN6ADDR_ANY_INIT;
86f08c3bdfSopenharmony_ci        svr_loop.v6.sin6_port = htons(SCTP_TESTPORT_1);
87f08c3bdfSopenharmony_ci#else
88f08c3bdfSopenharmony_ci	pf_class = PF_INET;
89f08c3bdfSopenharmony_ci	svr_loop.v4.sin_family = AF_INET;
90f08c3bdfSopenharmony_ci	svr_loop.v4.sin_addr.s_addr = INADDR_ANY;
91f08c3bdfSopenharmony_ci	svr_loop.v4.sin_port = htons(SCTP_TESTPORT_1);
92f08c3bdfSopenharmony_ci#endif
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_ci	/* Create and bind the listening server socket.  */
95f08c3bdfSopenharmony_ci        svr_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);
96f08c3bdfSopenharmony_ci	test_bind(svr_sk, &svr_loop.sa, sizeof(svr_loop));
97f08c3bdfSopenharmony_ci
98f08c3bdfSopenharmony_ci	memset(&svr_local_addr, 0, sizeof(svr_local_addr));
99f08c3bdfSopenharmony_ci	len = sizeof(svr_local_addr);
100f08c3bdfSopenharmony_ci	/* Verify that getsockname() on an unconnected socket works fine. */
101f08c3bdfSopenharmony_ci	error = getsockname(svr_sk, (struct sockaddr *)&svr_local_addr, &len);
102f08c3bdfSopenharmony_ci	if (0 != error)
103f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getsockname: %s", strerror(errno));
104f08c3bdfSopenharmony_ci
105f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getsockname on an unconnected socket");
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	memset(&svr_peer_addr, 0, sizeof(svr_peer_addr));
108f08c3bdfSopenharmony_ci	len = sizeof(svr_peer_addr);
109f08c3bdfSopenharmony_ci	/* Verify that getpeername() on an unconnected socket fails. */
110f08c3bdfSopenharmony_ci	error = getpeername(svr_sk, (struct sockaddr *)&svr_peer_addr, &len);
111f08c3bdfSopenharmony_ci	if ((-1 != error) || (ENOTCONN != errno))
112f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getpeername on an unconnected "
113f08c3bdfSopenharmony_ci			 "socket error:%d, errno:%d", error, errno);
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getpeername on an unconnected socket");
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ci	/* Mark svr_sk as being able to accept new associations.  */
118f08c3bdfSopenharmony_ci	test_listen(svr_sk, 5);
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_ci	/* Create the client socket.  */
121f08c3bdfSopenharmony_ci	clt_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_ci	/* Do a blocking connect from clt_sk to svr_sk */
124f08c3bdfSopenharmony_ci#if TEST_V6
125f08c3bdfSopenharmony_ci	svr_loop.v6.sin6_addr = in6addr_loopback;
126f08c3bdfSopenharmony_ci#else
127f08c3bdfSopenharmony_ci	svr_loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK;
128f08c3bdfSopenharmony_ci#endif
129f08c3bdfSopenharmony_ci	test_connect(clt_sk, &svr_loop.sa, sizeof(svr_loop));
130f08c3bdfSopenharmony_ci
131f08c3bdfSopenharmony_ci	memset(&clt_local_addr, 0, sizeof(clt_local_addr));
132f08c3bdfSopenharmony_ci	len = sizeof(clt_local_addr);
133f08c3bdfSopenharmony_ci	/* Get the client's local address. */
134f08c3bdfSopenharmony_ci	error = getsockname(clt_sk, (struct sockaddr *)&clt_local_addr, &len);
135f08c3bdfSopenharmony_ci	if (0 != error)
136f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getsockname on a connected client "
137f08c3bdfSopenharmony_ci			 "socket: %s", strerror(errno));
138f08c3bdfSopenharmony_ci
139f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getsockname on a connected client socket");
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci	memset(&clt_peer_addr, 0, sizeof(clt_peer_addr));
142f08c3bdfSopenharmony_ci	len = sizeof(clt_peer_addr);
143f08c3bdfSopenharmony_ci	/* Get the client's peer address. */
144f08c3bdfSopenharmony_ci	error = getpeername(clt_sk, (struct sockaddr *)&clt_peer_addr, &len);
145f08c3bdfSopenharmony_ci	if (0 != error)
146f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getpeername on a connected client "
147f08c3bdfSopenharmony_ci			 "socket: %s", strerror(errno));
148f08c3bdfSopenharmony_ci
149f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getpeername on a connected client socket");
150f08c3bdfSopenharmony_ci
151f08c3bdfSopenharmony_ci	/* Extract the association on the listening socket as a new socket. */
152f08c3bdfSopenharmony_ci	len = sizeof(accept_loop);
153f08c3bdfSopenharmony_ci	accept_sk = test_accept(svr_sk, &accept_loop.sa, &len);
154f08c3bdfSopenharmony_ci
155f08c3bdfSopenharmony_ci	memset(&svr_local_addr, 0, sizeof(svr_local_addr));
156f08c3bdfSopenharmony_ci	len = sizeof(svr_local_addr);
157f08c3bdfSopenharmony_ci	/* Get the server's local address. */
158f08c3bdfSopenharmony_ci	error = getsockname(accept_sk, (struct sockaddr *)&svr_local_addr,
159f08c3bdfSopenharmony_ci				&len);
160f08c3bdfSopenharmony_ci	if (0 != error)
161f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getsockname on a connected server "
162f08c3bdfSopenharmony_ci			 "socket: %s", strerror(errno));
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getsockname on a connected server socket");
165f08c3bdfSopenharmony_ci
166f08c3bdfSopenharmony_ci	memset(&svr_peer_addr, 0, sizeof(svr_peer_addr));
167f08c3bdfSopenharmony_ci	len = sizeof(svr_peer_addr);
168f08c3bdfSopenharmony_ci	/* Get the server's peer address. */
169f08c3bdfSopenharmony_ci	error = getpeername(accept_sk, (struct sockaddr *)&svr_peer_addr,
170f08c3bdfSopenharmony_ci				&len);
171f08c3bdfSopenharmony_ci	if (0 != error)
172f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getpeername on a connected server "
173f08c3bdfSopenharmony_ci			 "socket: %s", strerror(errno));
174f08c3bdfSopenharmony_ci
175f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getpeername on a connected server socket");
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ci	if (svr_local_addr.v4.sin_port != clt_peer_addr.v4.sin_port)
178f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "Server's local port(%d) doesn't "
179f08c3bdfSopenharmony_ci			 "match Client's peer port(%d)\n",
180f08c3bdfSopenharmony_ci			 svr_local_addr.v4.sin_port, clt_peer_addr.v4.sin_port);
181f08c3bdfSopenharmony_ci
182f08c3bdfSopenharmony_ci	if (svr_peer_addr.v4.sin_port != clt_local_addr.v4.sin_port)
183f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "Server's peer port(%d) doesn't "
184f08c3bdfSopenharmony_ci			 "match Client's local port(%d)\n",
185f08c3bdfSopenharmony_ci			 svr_peer_addr.v4.sin_port, clt_local_addr.v4.sin_port);
186f08c3bdfSopenharmony_ci#if TEST_V6
187f08c3bdfSopenharmony_ci	if (memcmp(&svr_local_addr, &clt_peer_addr, len) != 0)
188f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "Server's local address and client's "
189f08c3bdfSopenharmony_ci			 "peer addresses do not match\n");
190f08c3bdfSopenharmony_ci
191f08c3bdfSopenharmony_ci	if (memcmp(&svr_peer_addr, &clt_local_addr, len) != 0)
192f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "Server's peer address and client's "
193f08c3bdfSopenharmony_ci			 "local addresses do not match\n");
194f08c3bdfSopenharmony_ci#else
195f08c3bdfSopenharmony_ci	if (svr_local_addr.v4.sin_addr.s_addr !=
196f08c3bdfSopenharmony_ci		 		clt_peer_addr.v4.sin_addr.s_addr)
197f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "Server's local address and client's "
198f08c3bdfSopenharmony_ci			 "peer addresses do not match\n");
199f08c3bdfSopenharmony_ci	if (svr_peer_addr.v4.sin_addr.s_addr !=
200f08c3bdfSopenharmony_ci		 		clt_local_addr.v4.sin_addr.s_addr)
201f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "Server's peer address and client's "
202f08c3bdfSopenharmony_ci			 "local addresses do not match\n");
203f08c3bdfSopenharmony_ci#endif
204f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getsockname/getpeername server/client match");
205f08c3bdfSopenharmony_ci
206f08c3bdfSopenharmony_ci	memset(&clt_local_addr, 0, sizeof(clt_local_addr));
207f08c3bdfSopenharmony_ci	len = sizeof(clt_local_addr);
208f08c3bdfSopenharmony_ci	/*getsockname():  Bad socket descriptor, EBADF expected error*/
209f08c3bdfSopenharmony_ci	error = getsockname(-1, (struct sockaddr *)&clt_local_addr, &len);
210f08c3bdfSopenharmony_ci	if (error != -1 || errno != EBADF)
211f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getsockname on a bad socket "
212f08c3bdfSopenharmony_ci			 "descriptor. error:%d errno:%d", error, errno);
213f08c3bdfSopenharmony_ci
214f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getsockname on a bad socket descriptor - EBADF");
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci	/*getsockname(): Invalid socket, ENOTSOCK expected error*/
217f08c3bdfSopenharmony_ci	strcpy(filename, "/tmp/sctptest.XXXXXX");
218f08c3bdfSopenharmony_ci	fd = mkstemp(filename);
219f08c3bdfSopenharmony_ci	if (fd == -1)
220f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "Failed to mkstemp %s: %s",
221f08c3bdfSopenharmony_ci				filename, strerror(errno));
222f08c3bdfSopenharmony_ci	error = getsockname(fd, (struct sockaddr *)&clt_local_addr, &len);
223f08c3bdfSopenharmony_ci	if (error == -1)
224f08c3bdfSopenharmony_ci		err_no = errno;
225f08c3bdfSopenharmony_ci	close(fd);
226f08c3bdfSopenharmony_ci	unlink(filename);
227f08c3bdfSopenharmony_ci	if (error != -1 || err_no != ENOTSOCK)
228f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getsockname on an invalid socket "
229f08c3bdfSopenharmony_ci			 "error:%d errno:%d", error, err_no);
230f08c3bdfSopenharmony_ci
231f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getsockname on an invalid socket - ENOTSOCK");
232f08c3bdfSopenharmony_ci
233f08c3bdfSopenharmony_ci	/*getsockname(): Invalid structure, EFAULT expected error*/
234f08c3bdfSopenharmony_ci	error = getsockname(clt_sk, (struct sockaddr *)-1, &len);
235f08c3bdfSopenharmony_ci	if (error != -1 || errno != EFAULT)
236f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getsockname with invalid buffer "
237f08c3bdfSopenharmony_ci			 "error:%d errno:%d", error, errno);
238f08c3bdfSopenharmony_ci
239f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getsockname with invalid buffer - EFAULT");
240f08c3bdfSopenharmony_ci
241f08c3bdfSopenharmony_ci	memset(&clt_peer_addr, 0, sizeof(clt_peer_addr));
242f08c3bdfSopenharmony_ci	len = sizeof(clt_peer_addr);
243f08c3bdfSopenharmony_ci	/*getpeername():  Bad socket descriptor, EBADF expected error*/
244f08c3bdfSopenharmony_ci	error = getpeername(-1, (struct sockaddr *)&clt_local_addr, &len);
245f08c3bdfSopenharmony_ci	if (error != -1 || errno != EBADF)
246f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getpeername on a bad socket "
247f08c3bdfSopenharmony_ci			 "descriptor. error:%d errno:%d", error, errno);
248f08c3bdfSopenharmony_ci
249f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getpeername on a bad socket descriptor - EBADF");
250f08c3bdfSopenharmony_ci
251f08c3bdfSopenharmony_ci	/*getpeername(): Invalid socket, ENOTSOCK expected error*/
252f08c3bdfSopenharmony_ci	strcpy(filename, "/tmp/sctptest.XXXXXX");
253f08c3bdfSopenharmony_ci	fd = mkstemp(filename);
254f08c3bdfSopenharmony_ci	if (fd == -1)
255f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "Failed to mkstemp %s: %s",
256f08c3bdfSopenharmony_ci				filename, strerror(errno));
257f08c3bdfSopenharmony_ci	error = getpeername(fd, (struct sockaddr *)&clt_local_addr, &len);
258f08c3bdfSopenharmony_ci	if (error == -1)
259f08c3bdfSopenharmony_ci		err_no = errno;
260f08c3bdfSopenharmony_ci	close(fd);
261f08c3bdfSopenharmony_ci	unlink(filename);
262f08c3bdfSopenharmony_ci	if (error != -1 || err_no != ENOTSOCK)
263f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getpeername on an invalid socket "
264f08c3bdfSopenharmony_ci			 "error:%d errno:%d", error, err_no);
265f08c3bdfSopenharmony_ci
266f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getpeername on an invalid socket - ENOTSOCK");
267f08c3bdfSopenharmony_ci
268f08c3bdfSopenharmony_ci	/*getpeername(): Invalid structure, EFAULT expected error*/
269f08c3bdfSopenharmony_ci	error = getpeername(clt_sk, (struct sockaddr *)-1, &len);
270f08c3bdfSopenharmony_ci	if (error != -1 || errno != EFAULT)
271f08c3bdfSopenharmony_ci		tst_brkm(TBROK, tst_exit, "getpeername with invalid buffer "
272f08c3bdfSopenharmony_ci			 "error:%d errno:%d", error, errno);
273f08c3bdfSopenharmony_ci
274f08c3bdfSopenharmony_ci	tst_resm(TPASS, "getpeername with invalid buffer - EFAULT");
275f08c3bdfSopenharmony_ci
276f08c3bdfSopenharmony_ci	close(clt_sk);
277f08c3bdfSopenharmony_ci	close(svr_sk);
278f08c3bdfSopenharmony_ci	close(accept_sk);
279f08c3bdfSopenharmony_ci
280f08c3bdfSopenharmony_ci        /* Indicate successful completion.  */
281f08c3bdfSopenharmony_ci	return 0;
282f08c3bdfSopenharmony_ci}
283