xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/bind/bind05.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  *   Copyright (c) 2019 Martin Doucha <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  */
5*49cdfc7eSAndroid Build Coastguard Worker 
6*49cdfc7eSAndroid Build Coastguard Worker /*
7*49cdfc7eSAndroid Build Coastguard Worker  * Create and bind socket for various standard datagram protocols.
8*49cdfc7eSAndroid Build Coastguard Worker  * Then connect to it and send some test data.
9*49cdfc7eSAndroid Build Coastguard Worker  */
10*49cdfc7eSAndroid Build Coastguard Worker 
11*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
14*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
15*49cdfc7eSAndroid Build Coastguard Worker 
16*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
17*49cdfc7eSAndroid Build Coastguard Worker #include "tst_net.h"
18*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_pthread.h"
19*49cdfc7eSAndroid Build Coastguard Worker #include "libbind.h"
20*49cdfc7eSAndroid Build Coastguard Worker 
21*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_un unix_addr = {
22*49cdfc7eSAndroid Build Coastguard Worker 	.sun_family = AF_UNIX,
23*49cdfc7eSAndroid Build Coastguard Worker 	.sun_path = MAIN_SOCKET_FILE
24*49cdfc7eSAndroid Build Coastguard Worker };
25*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_un abstract_addr = {
26*49cdfc7eSAndroid Build Coastguard Worker 	.sun_family = AF_UNIX,
27*49cdfc7eSAndroid Build Coastguard Worker 	.sun_path = ABSTRACT_SOCKET_PATH
28*49cdfc7eSAndroid Build Coastguard Worker };
29*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_un peer_addr = {
30*49cdfc7eSAndroid Build Coastguard Worker 	.sun_family = AF_UNIX,
31*49cdfc7eSAndroid Build Coastguard Worker 	.sun_path = PEER_SOCKET_FILE
32*49cdfc7eSAndroid Build Coastguard Worker };
33*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_in ipv4_addr;
34*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_in ipv4_any_addr;
35*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_in6 ipv6_addr;
36*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_in6 ipv6_any_addr;
37*49cdfc7eSAndroid Build Coastguard Worker 
38*49cdfc7eSAndroid Build Coastguard Worker static struct test_case testcase_list[] = {
39*49cdfc7eSAndroid Build Coastguard Worker 	/* UNIX sockets */
40*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, 0, (struct sockaddr *)&unix_addr, sizeof(unix_addr),
41*49cdfc7eSAndroid Build Coastguard Worker 		"AF_UNIX pathname datagram"},
42*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, 0, (struct sockaddr *)&abstract_addr,
43*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(abstract_addr), "AF_UNIX abstract datagram"},
44*49cdfc7eSAndroid Build Coastguard Worker 
45*49cdfc7eSAndroid Build Coastguard Worker 	/* IPv4 sockets */
46*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, 0, (struct sockaddr *)&ipv4_addr, sizeof(ipv4_addr),
47*49cdfc7eSAndroid Build Coastguard Worker 		"IPv4 loop UDP variant 1"},
48*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, IPPROTO_UDP, (struct sockaddr *)&ipv4_addr,
49*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv4_addr), "IPv4 loop UDP variant 2"},
50*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, IPPROTO_UDPLITE, (struct sockaddr *)&ipv4_addr,
51*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv4_addr), "IPv4 loop UDP-Lite"},
52*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, 0, (struct sockaddr *)&ipv4_any_addr,
53*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv4_any_addr), "IPv4 any UDP variant 1"},
54*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, IPPROTO_UDP, (struct sockaddr *)&ipv4_any_addr,
55*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv4_any_addr), "IPv4 any UDP variant 2"},
56*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, IPPROTO_UDPLITE, (struct sockaddr *)&ipv4_any_addr,
57*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv4_any_addr), "IPv4 any UDP-Lite"},
58*49cdfc7eSAndroid Build Coastguard Worker 
59*49cdfc7eSAndroid Build Coastguard Worker 	/* IPv6 sockets */
60*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, 0, (struct sockaddr *)&ipv6_addr, sizeof(ipv6_addr),
61*49cdfc7eSAndroid Build Coastguard Worker 		"IPv6 loop UDP variant 1"},
62*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, IPPROTO_UDP, (struct sockaddr *)&ipv6_addr,
63*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv6_addr), "IPv6 loop UDP variant 2"},
64*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, IPPROTO_UDPLITE, (struct sockaddr *)&ipv6_addr,
65*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv6_addr), "IPv6 loop UDP-Lite"},
66*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, 0, (struct sockaddr *)&ipv6_any_addr,
67*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv6_any_addr), "IPv6 any UDP variant 1"},
68*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, IPPROTO_UDP, (struct sockaddr *)&ipv6_any_addr,
69*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv6_any_addr), "IPv6 any UDP variant 2"},
70*49cdfc7eSAndroid Build Coastguard Worker 	{SOCK_DGRAM, IPPROTO_UDPLITE, (struct sockaddr *)&ipv6_any_addr,
71*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(ipv6_any_addr), "IPv6 any UDP-Lite"}
72*49cdfc7eSAndroid Build Coastguard Worker };
73*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)74*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
75*49cdfc7eSAndroid Build Coastguard Worker {
76*49cdfc7eSAndroid Build Coastguard Worker 	srand(time(0));
77*49cdfc7eSAndroid Build Coastguard Worker 
78*49cdfc7eSAndroid Build Coastguard Worker 	tst_init_sockaddr_inet(&ipv4_addr, IPV4_ADDRESS, 0);
79*49cdfc7eSAndroid Build Coastguard Worker 	tst_init_sockaddr_inet_bin(&ipv4_any_addr, INADDR_ANY, 0);
80*49cdfc7eSAndroid Build Coastguard Worker 	tst_init_sockaddr_inet6_bin(&ipv6_addr, &in6addr_loopback, 0);
81*49cdfc7eSAndroid Build Coastguard Worker 	tst_init_sockaddr_inet6_bin(&ipv6_any_addr, &in6addr_any, 0);
82*49cdfc7eSAndroid Build Coastguard Worker }
83*49cdfc7eSAndroid Build Coastguard Worker 
peer_thread(void * tc_ptr)84*49cdfc7eSAndroid Build Coastguard Worker static void *peer_thread(void *tc_ptr)
85*49cdfc7eSAndroid Build Coastguard Worker {
86*49cdfc7eSAndroid Build Coastguard Worker 	const struct test_case *tc = tc_ptr;
87*49cdfc7eSAndroid Build Coastguard Worker 	int sock;
88*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int request = 0;
89*49cdfc7eSAndroid Build Coastguard Worker 	const char *response;
90*49cdfc7eSAndroid Build Coastguard Worker 
91*49cdfc7eSAndroid Build Coastguard Worker 	sock = SAFE_SOCKET(tc->address->sa_family, tc->type, tc->protocol);
92*49cdfc7eSAndroid Build Coastguard Worker 
93*49cdfc7eSAndroid Build Coastguard Worker 	/*
94*49cdfc7eSAndroid Build Coastguard Worker 	 * Both sides of AF_UNIX/SOCK_DGRAM socket must be bound for
95*49cdfc7eSAndroid Build Coastguard Worker 	 * bidirectional communication
96*49cdfc7eSAndroid Build Coastguard Worker 	 */
97*49cdfc7eSAndroid Build Coastguard Worker 	if (tc->address->sa_family == AF_UNIX)
98*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_BIND(sock, (struct sockaddr *)&peer_addr,
99*49cdfc7eSAndroid Build Coastguard Worker 			sizeof(struct sockaddr_un));
100*49cdfc7eSAndroid Build Coastguard Worker 
101*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CONNECT(sock, tc->address, tc->addrlen);
102*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_WRITE(SAFE_WRITE_ALL, sock, &request, sizeof(request));
103*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_READ(1, sock, &request, sizeof(request));
104*49cdfc7eSAndroid Build Coastguard Worker 
105*49cdfc7eSAndroid Build Coastguard Worker 	if (request < ARRAY_SIZE(testcase_list))
106*49cdfc7eSAndroid Build Coastguard Worker 		response = testcase_list[request].description;
107*49cdfc7eSAndroid Build Coastguard Worker 	else
108*49cdfc7eSAndroid Build Coastguard Worker 		response = "Invalid request value";
109*49cdfc7eSAndroid Build Coastguard Worker 
110*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_WRITE(SAFE_WRITE_ALL, sock, response, strlen(response) + 1);
111*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(sock);
112*49cdfc7eSAndroid Build Coastguard Worker 
113*49cdfc7eSAndroid Build Coastguard Worker 	if (tc->address->sa_family == AF_UNIX)
114*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_UNLINK(PEER_SOCKET_FILE);
115*49cdfc7eSAndroid Build Coastguard Worker 
116*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
117*49cdfc7eSAndroid Build Coastguard Worker }
118*49cdfc7eSAndroid Build Coastguard Worker 
test_bind(unsigned int n)119*49cdfc7eSAndroid Build Coastguard Worker static void test_bind(unsigned int n)
120*49cdfc7eSAndroid Build Coastguard Worker {
121*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case tc_copy, *tc = testcase_list + n;
122*49cdfc7eSAndroid Build Coastguard Worker 	struct sockaddr_storage listen_addr, remote_addr;
123*49cdfc7eSAndroid Build Coastguard Worker 	struct sockaddr_un *tmp_addr;
124*49cdfc7eSAndroid Build Coastguard Worker 	socklen_t remote_len = sizeof(struct sockaddr_storage);
125*49cdfc7eSAndroid Build Coastguard Worker 	int sock, size;
126*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int rand_index;
127*49cdfc7eSAndroid Build Coastguard Worker 	pthread_t thread_id;
128*49cdfc7eSAndroid Build Coastguard Worker 	char buffer[BUFFER_SIZE];
129*49cdfc7eSAndroid Build Coastguard Worker 	const char *exp_data;
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Testing %s", tc->description);
132*49cdfc7eSAndroid Build Coastguard Worker 	sock = SAFE_SOCKET(tc->address->sa_family, tc->type, tc->protocol);
133*49cdfc7eSAndroid Build Coastguard Worker 
134*49cdfc7eSAndroid Build Coastguard Worker 	TST_EXP_PASS_SILENT(bind(sock, tc->address, tc->addrlen), "bind()");
135*49cdfc7eSAndroid Build Coastguard Worker 
136*49cdfc7eSAndroid Build Coastguard Worker 	if (!TST_PASS) {
137*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(sock);
138*49cdfc7eSAndroid Build Coastguard Worker 		return;
139*49cdfc7eSAndroid Build Coastguard Worker 	}
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker 	/*
142*49cdfc7eSAndroid Build Coastguard Worker 	 * IPv4/IPv6 tests use wildcard addresses, resolve a valid connection
143*49cdfc7eSAndroid Build Coastguard Worker 	 * address for peer thread
144*49cdfc7eSAndroid Build Coastguard Worker 	 */
145*49cdfc7eSAndroid Build Coastguard Worker 	memcpy(&tc_copy, tc, sizeof(struct test_case));
146*49cdfc7eSAndroid Build Coastguard Worker 	tc_copy.addrlen = tst_get_connect_address(sock, &listen_addr);
147*49cdfc7eSAndroid Build Coastguard Worker 	tc_copy.address = (struct sockaddr *)&listen_addr;
148*49cdfc7eSAndroid Build Coastguard Worker 
149*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_PTHREAD_CREATE(&thread_id, NULL, peer_thread, &tc_copy);
150*49cdfc7eSAndroid Build Coastguard Worker 	size = recvfrom(sock, &rand_index, sizeof(rand_index), 0,
151*49cdfc7eSAndroid Build Coastguard Worker 		(struct sockaddr *)&remote_addr, &remote_len);
152*49cdfc7eSAndroid Build Coastguard Worker 
153*49cdfc7eSAndroid Build Coastguard Worker 	if (size != sizeof(rand_index)) {
154*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(sock);
155*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "Error while waiting for connection");
156*49cdfc7eSAndroid Build Coastguard Worker 	}
157*49cdfc7eSAndroid Build Coastguard Worker 
158*49cdfc7eSAndroid Build Coastguard Worker 	rand_index = rand() % ARRAY_SIZE(testcase_list);
159*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_SENDTO(1, sock, &rand_index, sizeof(rand_index), 0,
160*49cdfc7eSAndroid Build Coastguard Worker 		(struct sockaddr *)&remote_addr, remote_len);
161*49cdfc7eSAndroid Build Coastguard Worker 
162*49cdfc7eSAndroid Build Coastguard Worker 	size = SAFE_READ(0, sock, buffer, BUFFER_SIZE - 1);
163*49cdfc7eSAndroid Build Coastguard Worker 	buffer[size] = '\0';
164*49cdfc7eSAndroid Build Coastguard Worker 	exp_data = testcase_list[rand_index].description;
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker 	if (!strcmp(buffer, exp_data))
167*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "Communication successful");
168*49cdfc7eSAndroid Build Coastguard Worker 	else
169*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "Received invalid data. Expected: \"%s\". "
170*49cdfc7eSAndroid Build Coastguard Worker 			"Received: \"%s\"", exp_data, buffer);
171*49cdfc7eSAndroid Build Coastguard Worker 
172*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(sock);
173*49cdfc7eSAndroid Build Coastguard Worker 	pthread_join(thread_id, NULL);
174*49cdfc7eSAndroid Build Coastguard Worker 	tmp_addr = (struct sockaddr_un *)tc->address;
175*49cdfc7eSAndroid Build Coastguard Worker 
176*49cdfc7eSAndroid Build Coastguard Worker 	if (tc->address->sa_family == AF_UNIX && tmp_addr->sun_path[0])
177*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_UNLINK(tmp_addr->sun_path);
178*49cdfc7eSAndroid Build Coastguard Worker }
179*49cdfc7eSAndroid Build Coastguard Worker 
180*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
181*49cdfc7eSAndroid Build Coastguard Worker 	.test = test_bind,
182*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = ARRAY_SIZE(testcase_list),
183*49cdfc7eSAndroid Build Coastguard Worker 	.needs_tmpdir = 1,
184*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
185*49cdfc7eSAndroid Build Coastguard Worker };
186