xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/send/send02.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) 2020 SUSE LLC <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  */
5*49cdfc7eSAndroid Build Coastguard Worker 
6*49cdfc7eSAndroid Build Coastguard Worker /*\
7*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
8*49cdfc7eSAndroid Build Coastguard Worker  *
9*49cdfc7eSAndroid Build Coastguard Worker  * Check that the kernel correctly handles send()/sendto()/sendmsg() calls
10*49cdfc7eSAndroid Build Coastguard Worker  * with MSG_MORE flag.
11*49cdfc7eSAndroid Build Coastguard Worker  */
12*49cdfc7eSAndroid Build Coastguard Worker 
13*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
14*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <sys/socket.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <netinet/in.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include <sys/ioctl.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <net/if.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <sched.h>
20*49cdfc7eSAndroid Build Coastguard Worker 
21*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
22*49cdfc7eSAndroid Build Coastguard Worker #include "tst_net.h"
23*49cdfc7eSAndroid Build Coastguard Worker 
24*49cdfc7eSAndroid Build Coastguard Worker #define SENDSIZE 16
25*49cdfc7eSAndroid Build Coastguard Worker #define RECVSIZE 32
26*49cdfc7eSAndroid Build Coastguard Worker 
27*49cdfc7eSAndroid Build Coastguard Worker static int sock = -1, dst_sock = -1, listen_sock = -1;
28*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_in addr;
29*49cdfc7eSAndroid Build Coastguard Worker static char sendbuf[SENDSIZE];
30*49cdfc7eSAndroid Build Coastguard Worker 
do_send(int sock,void * buf,size_t size,int flags)31*49cdfc7eSAndroid Build Coastguard Worker static void do_send(int sock, void *buf, size_t size, int flags)
32*49cdfc7eSAndroid Build Coastguard Worker {
33*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_SEND(1, sock, buf, size, flags);
34*49cdfc7eSAndroid Build Coastguard Worker }
35*49cdfc7eSAndroid Build Coastguard Worker 
do_sendto(int sock,void * buf,size_t size,int flags)36*49cdfc7eSAndroid Build Coastguard Worker static void do_sendto(int sock, void *buf, size_t size, int flags)
37*49cdfc7eSAndroid Build Coastguard Worker {
38*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_SENDTO(1, sock, buf, size, flags, (struct sockaddr *)&addr,
39*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(addr));
40*49cdfc7eSAndroid Build Coastguard Worker }
41*49cdfc7eSAndroid Build Coastguard Worker 
do_sendmsg(int sock,void * buf,size_t size,int flags)42*49cdfc7eSAndroid Build Coastguard Worker static void do_sendmsg(int sock, void *buf, size_t size, int flags)
43*49cdfc7eSAndroid Build Coastguard Worker {
44*49cdfc7eSAndroid Build Coastguard Worker 	struct msghdr msg;
45*49cdfc7eSAndroid Build Coastguard Worker 	struct iovec iov;
46*49cdfc7eSAndroid Build Coastguard Worker 
47*49cdfc7eSAndroid Build Coastguard Worker 	iov.iov_base = buf;
48*49cdfc7eSAndroid Build Coastguard Worker 	iov.iov_len = size;
49*49cdfc7eSAndroid Build Coastguard Worker 	msg.msg_name = &addr;
50*49cdfc7eSAndroid Build Coastguard Worker 	msg.msg_namelen = sizeof(addr);
51*49cdfc7eSAndroid Build Coastguard Worker 	msg.msg_iov = &iov;
52*49cdfc7eSAndroid Build Coastguard Worker 	msg.msg_iovlen = 1;
53*49cdfc7eSAndroid Build Coastguard Worker 	msg.msg_control = NULL;
54*49cdfc7eSAndroid Build Coastguard Worker 	msg.msg_controllen = 0;
55*49cdfc7eSAndroid Build Coastguard Worker 	msg.msg_flags = 0;
56*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_SENDMSG(size, sock, &msg, flags);
57*49cdfc7eSAndroid Build Coastguard Worker }
58*49cdfc7eSAndroid Build Coastguard Worker 
59*49cdfc7eSAndroid Build Coastguard Worker static struct test_case {
60*49cdfc7eSAndroid Build Coastguard Worker 	int domain, type, protocol;
61*49cdfc7eSAndroid Build Coastguard Worker 	void (*send)(int sock, void *buf, size_t size, int flags);
62*49cdfc7eSAndroid Build Coastguard Worker 	int needs_connect, needs_accept;
63*49cdfc7eSAndroid Build Coastguard Worker 	const char *name;
64*49cdfc7eSAndroid Build Coastguard Worker } testcase_list[] = {
65*49cdfc7eSAndroid Build Coastguard Worker 	{AF_INET, SOCK_STREAM, 0, do_send, 1, 1, "TCP send"},
66*49cdfc7eSAndroid Build Coastguard Worker 	{AF_INET, SOCK_DGRAM, 0, do_send, 1, 0, "UDP send"},
67*49cdfc7eSAndroid Build Coastguard Worker 	{AF_INET, SOCK_DGRAM, 0, do_sendto, 0, 0, "UDP sendto"},
68*49cdfc7eSAndroid Build Coastguard Worker 	{AF_INET, SOCK_DGRAM, 0, do_sendmsg, 0, 0, "UDP sendmsg"}
69*49cdfc7eSAndroid Build Coastguard Worker };
70*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)71*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
72*49cdfc7eSAndroid Build Coastguard Worker {
73*49cdfc7eSAndroid Build Coastguard Worker 	memset(sendbuf, 0x42, SENDSIZE);
74*49cdfc7eSAndroid Build Coastguard Worker }
75*49cdfc7eSAndroid Build Coastguard Worker 
check_recv(int sock,long expsize,int loop)76*49cdfc7eSAndroid Build Coastguard Worker static int check_recv(int sock, long expsize, int loop)
77*49cdfc7eSAndroid Build Coastguard Worker {
78*49cdfc7eSAndroid Build Coastguard Worker 	char recvbuf[RECVSIZE] = {0};
79*49cdfc7eSAndroid Build Coastguard Worker 
80*49cdfc7eSAndroid Build Coastguard Worker 	while (1) {
81*49cdfc7eSAndroid Build Coastguard Worker 		TEST(recv(sock, recvbuf, RECVSIZE, MSG_DONTWAIT));
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker 		if (TST_RET == -1) {
84*49cdfc7eSAndroid Build Coastguard Worker 			/* expected error immediately after send(MSG_MORE) */
85*49cdfc7eSAndroid Build Coastguard Worker 			if (TST_ERR == EAGAIN || TST_ERR == EWOULDBLOCK) {
86*49cdfc7eSAndroid Build Coastguard Worker 				if (expsize)
87*49cdfc7eSAndroid Build Coastguard Worker 					continue;
88*49cdfc7eSAndroid Build Coastguard Worker 				else
89*49cdfc7eSAndroid Build Coastguard Worker 					break;
90*49cdfc7eSAndroid Build Coastguard Worker 			}
91*49cdfc7eSAndroid Build Coastguard Worker 
92*49cdfc7eSAndroid Build Coastguard Worker 			/* unexpected error */
93*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL | TTERRNO, "recv() error at step %d, expsize %ld",
94*49cdfc7eSAndroid Build Coastguard Worker 				loop, expsize);
95*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
96*49cdfc7eSAndroid Build Coastguard Worker 		}
97*49cdfc7eSAndroid Build Coastguard Worker 
98*49cdfc7eSAndroid Build Coastguard Worker 		if (TST_RET < 0) {
99*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL | TTERRNO, "recv() returns %ld at step %d, expsize %ld",
100*49cdfc7eSAndroid Build Coastguard Worker 				TST_RET, loop, expsize);
101*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
102*49cdfc7eSAndroid Build Coastguard Worker 		}
103*49cdfc7eSAndroid Build Coastguard Worker 
104*49cdfc7eSAndroid Build Coastguard Worker 		if (TST_RET != expsize) {
105*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "recv() read %ld bytes, expected %ld, step %d",
106*49cdfc7eSAndroid Build Coastguard Worker 				TST_RET, expsize, loop);
107*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
108*49cdfc7eSAndroid Build Coastguard Worker 		}
109*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
110*49cdfc7eSAndroid Build Coastguard Worker 	}
111*49cdfc7eSAndroid Build Coastguard Worker 
112*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
113*49cdfc7eSAndroid Build Coastguard Worker }
114*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)115*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
116*49cdfc7eSAndroid Build Coastguard Worker {
117*49cdfc7eSAndroid Build Coastguard Worker 	if (sock >= 0)
118*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(sock);
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker 	if (dst_sock >= 0 && dst_sock != listen_sock)
121*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(dst_sock);
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker 	if (listen_sock >= 0)
124*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(listen_sock);
125*49cdfc7eSAndroid Build Coastguard Worker }
126*49cdfc7eSAndroid Build Coastguard Worker 
run(unsigned int n)127*49cdfc7eSAndroid Build Coastguard Worker static void run(unsigned int n)
128*49cdfc7eSAndroid Build Coastguard Worker {
129*49cdfc7eSAndroid Build Coastguard Worker 	int i, ret;
130*49cdfc7eSAndroid Build Coastguard Worker 	struct test_case *tc = testcase_list + n;
131*49cdfc7eSAndroid Build Coastguard Worker 	socklen_t len = sizeof(addr);
132*49cdfc7eSAndroid Build Coastguard Worker 
133*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Testing %s", tc->name);
134*49cdfc7eSAndroid Build Coastguard Worker 
135*49cdfc7eSAndroid Build Coastguard Worker 	tst_init_sockaddr_inet_bin(&addr, INADDR_LOOPBACK, 0);
136*49cdfc7eSAndroid Build Coastguard Worker 	listen_sock = SAFE_SOCKET(tc->domain, tc->type, tc->protocol);
137*49cdfc7eSAndroid Build Coastguard Worker 	dst_sock = listen_sock;
138*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_BIND(listen_sock, (struct sockaddr *)&addr, sizeof(addr));
139*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_GETSOCKNAME(listen_sock, (struct sockaddr *)&addr, &len);
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker 	if (tc->needs_accept)
142*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_LISTEN(listen_sock, 1);
143*49cdfc7eSAndroid Build Coastguard Worker 
144*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < 1000; i++) {
145*49cdfc7eSAndroid Build Coastguard Worker 		sock = SAFE_SOCKET(tc->domain, tc->type, tc->protocol);
146*49cdfc7eSAndroid Build Coastguard Worker 
147*49cdfc7eSAndroid Build Coastguard Worker 		if (tc->needs_connect)
148*49cdfc7eSAndroid Build Coastguard Worker 			SAFE_CONNECT(sock, (struct sockaddr *)&addr, len);
149*49cdfc7eSAndroid Build Coastguard Worker 
150*49cdfc7eSAndroid Build Coastguard Worker 		if (tc->needs_accept)
151*49cdfc7eSAndroid Build Coastguard Worker 			dst_sock = SAFE_ACCEPT(listen_sock, NULL, NULL);
152*49cdfc7eSAndroid Build Coastguard Worker 
153*49cdfc7eSAndroid Build Coastguard Worker 		tc->send(sock, sendbuf, SENDSIZE, 0);
154*49cdfc7eSAndroid Build Coastguard Worker 		ret = check_recv(dst_sock, SENDSIZE, i + 1);
155*49cdfc7eSAndroid Build Coastguard Worker 
156*49cdfc7eSAndroid Build Coastguard Worker 		if (!ret)
157*49cdfc7eSAndroid Build Coastguard Worker 			break;
158*49cdfc7eSAndroid Build Coastguard Worker 
159*49cdfc7eSAndroid Build Coastguard Worker 		tc->send(sock, sendbuf, SENDSIZE, MSG_MORE);
160*49cdfc7eSAndroid Build Coastguard Worker 		ret = check_recv(dst_sock, 0, i + 1);
161*49cdfc7eSAndroid Build Coastguard Worker 
162*49cdfc7eSAndroid Build Coastguard Worker 		if (!ret)
163*49cdfc7eSAndroid Build Coastguard Worker 			break;
164*49cdfc7eSAndroid Build Coastguard Worker 
165*49cdfc7eSAndroid Build Coastguard Worker 		tc->send(sock, sendbuf, 1, 0);
166*49cdfc7eSAndroid Build Coastguard Worker 		ret = check_recv(dst_sock, SENDSIZE + 1, i + 1);
167*49cdfc7eSAndroid Build Coastguard Worker 
168*49cdfc7eSAndroid Build Coastguard Worker 		if (!ret)
169*49cdfc7eSAndroid Build Coastguard Worker 			break;
170*49cdfc7eSAndroid Build Coastguard Worker 
171*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(sock);
172*49cdfc7eSAndroid Build Coastguard Worker 
173*49cdfc7eSAndroid Build Coastguard Worker 		if (dst_sock != listen_sock)
174*49cdfc7eSAndroid Build Coastguard Worker 			SAFE_CLOSE(dst_sock);
175*49cdfc7eSAndroid Build Coastguard Worker 	}
176*49cdfc7eSAndroid Build Coastguard Worker 
177*49cdfc7eSAndroid Build Coastguard Worker 	if (ret)
178*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "MSG_MORE works correctly");
179*49cdfc7eSAndroid Build Coastguard Worker 
180*49cdfc7eSAndroid Build Coastguard Worker 	cleanup();
181*49cdfc7eSAndroid Build Coastguard Worker 	dst_sock = -1;
182*49cdfc7eSAndroid Build Coastguard Worker }
183*49cdfc7eSAndroid Build Coastguard Worker 
184*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
185*49cdfc7eSAndroid Build Coastguard Worker 	.test = run,
186*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = ARRAY_SIZE(testcase_list),
187*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
188*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup
189*49cdfc7eSAndroid Build Coastguard Worker };
190