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) 2001 Wayne Boyer International Business Machines
4*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) Linux Test Project, 2002-2022
5*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2023 Wei Gao <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker */
7*49cdfc7eSAndroid Build Coastguard Worker
8*49cdfc7eSAndroid Build Coastguard Worker /*\
9*49cdfc7eSAndroid Build Coastguard Worker * [Description]
10*49cdfc7eSAndroid Build Coastguard Worker *
11*49cdfc7eSAndroid Build Coastguard Worker * Verify that recvmsg() returns the proper errno for various failure cases.
12*49cdfc7eSAndroid Build Coastguard Worker */
13*49cdfc7eSAndroid Build Coastguard Worker
14*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
18*49cdfc7eSAndroid Build Coastguard Worker
19*49cdfc7eSAndroid Build Coastguard Worker #define MSG "from recvmsg01 server"
20*49cdfc7eSAndroid Build Coastguard Worker #define BUF_SIZE 1024
21*49cdfc7eSAndroid Build Coastguard Worker #define CONTROL_LEN (128 * 1024)
22*49cdfc7eSAndroid Build Coastguard Worker
23*49cdfc7eSAndroid Build Coastguard Worker static char recv_buf[BUF_SIZE], cbuf[BUF_SIZE];
24*49cdfc7eSAndroid Build Coastguard Worker static int sock;
25*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_in sin1, from;
26*49cdfc7eSAndroid Build Coastguard Worker static struct sockaddr_un sun1;
27*49cdfc7eSAndroid Build Coastguard Worker static struct msghdr msgdat;
28*49cdfc7eSAndroid Build Coastguard Worker static struct cmsghdr *control;
29*49cdfc7eSAndroid Build Coastguard Worker static int controllen;
30*49cdfc7eSAndroid Build Coastguard Worker static struct iovec iov[1];
31*49cdfc7eSAndroid Build Coastguard Worker static int sfd; /* shared between do_child and start_server */
32*49cdfc7eSAndroid Build Coastguard Worker static int ufd; /* shared between do_child and start_server */
33*49cdfc7eSAndroid Build Coastguard Worker static pid_t pid;
34*49cdfc7eSAndroid Build Coastguard Worker static char tmpsunpath[BUF_SIZE];
35*49cdfc7eSAndroid Build Coastguard Worker
36*49cdfc7eSAndroid Build Coastguard Worker static void setup_all(void);
37*49cdfc7eSAndroid Build Coastguard Worker static void setup_invalid_sock(int);
38*49cdfc7eSAndroid Build Coastguard Worker static void setup_valid_sock(int);
39*49cdfc7eSAndroid Build Coastguard Worker static void setup_valid_msg_control(int);
40*49cdfc7eSAndroid Build Coastguard Worker static void setup_large_msg_control(int);
41*49cdfc7eSAndroid Build Coastguard Worker static void cleanup_all(void);
42*49cdfc7eSAndroid Build Coastguard Worker static void cleanup_invalid_sock(int);
43*49cdfc7eSAndroid Build Coastguard Worker static void cleanup_close_sock(int);
44*49cdfc7eSAndroid Build Coastguard Worker static void cleanup_reset_all(int);
45*49cdfc7eSAndroid Build Coastguard Worker static void do_child(void);
46*49cdfc7eSAndroid Build Coastguard Worker static pid_t start_server(struct sockaddr_in *, struct sockaddr_un *);
47*49cdfc7eSAndroid Build Coastguard Worker
48*49cdfc7eSAndroid Build Coastguard Worker static struct tcase {
49*49cdfc7eSAndroid Build Coastguard Worker int domain;
50*49cdfc7eSAndroid Build Coastguard Worker int type;
51*49cdfc7eSAndroid Build Coastguard Worker int protocol;
52*49cdfc7eSAndroid Build Coastguard Worker struct iovec *iov;
53*49cdfc7eSAndroid Build Coastguard Worker int iovcnt;
54*49cdfc7eSAndroid Build Coastguard Worker void *recv_buf;
55*49cdfc7eSAndroid Build Coastguard Worker int buflen;
56*49cdfc7eSAndroid Build Coastguard Worker struct msghdr *msg;
57*49cdfc7eSAndroid Build Coastguard Worker unsigned int flags;
58*49cdfc7eSAndroid Build Coastguard Worker struct sockaddr *from;
59*49cdfc7eSAndroid Build Coastguard Worker int fromlen;
60*49cdfc7eSAndroid Build Coastguard Worker int exp_errno;
61*49cdfc7eSAndroid Build Coastguard Worker void (*setup)(int n);
62*49cdfc7eSAndroid Build Coastguard Worker void (*cleanup)(int n);
63*49cdfc7eSAndroid Build Coastguard Worker char *desc;
64*49cdfc7eSAndroid Build Coastguard Worker } tcases[] = {
65*49cdfc7eSAndroid Build Coastguard Worker {
66*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
67*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
68*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
69*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
70*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = recv_buf,
71*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
72*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
73*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
74*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
75*49cdfc7eSAndroid Build Coastguard Worker .exp_errno = EBADF,
76*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_invalid_sock,
77*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_invalid_sock,
78*49cdfc7eSAndroid Build Coastguard Worker .desc = "bad file descriptor",
79*49cdfc7eSAndroid Build Coastguard Worker },
80*49cdfc7eSAndroid Build Coastguard Worker {
81*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
82*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
83*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
84*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
85*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = (void *)recv_buf,
86*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
87*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
88*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
89*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
90*49cdfc7eSAndroid Build Coastguard Worker .exp_errno = ENOTSOCK,
91*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_invalid_sock,
92*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_invalid_sock,
93*49cdfc7eSAndroid Build Coastguard Worker .desc = "invalid socket",
94*49cdfc7eSAndroid Build Coastguard Worker },
95*49cdfc7eSAndroid Build Coastguard Worker {
96*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
97*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
98*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
99*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
100*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = (void *)recv_buf,
101*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
102*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
103*49cdfc7eSAndroid Build Coastguard Worker .flags = -1,
104*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
105*49cdfc7eSAndroid Build Coastguard Worker .fromlen = -1,
106*49cdfc7eSAndroid Build Coastguard Worker .exp_errno = EINVAL,
107*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_valid_sock,
108*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_close_sock,
109*49cdfc7eSAndroid Build Coastguard Worker .desc = "invalid socket length",
110*49cdfc7eSAndroid Build Coastguard Worker },
111*49cdfc7eSAndroid Build Coastguard Worker {
112*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
113*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
114*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
115*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
116*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = (void *)-1,
117*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
118*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
119*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
120*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
121*49cdfc7eSAndroid Build Coastguard Worker .exp_errno = EFAULT,
122*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_valid_sock,
123*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_close_sock,
124*49cdfc7eSAndroid Build Coastguard Worker .desc = "invalid recv buffer",
125*49cdfc7eSAndroid Build Coastguard Worker },
126*49cdfc7eSAndroid Build Coastguard Worker {
127*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
128*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
129*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
130*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = recv_buf,
131*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
132*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
133*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
134*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
135*49cdfc7eSAndroid Build Coastguard Worker .exp_errno = EFAULT,
136*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_valid_sock,
137*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_close_sock,
138*49cdfc7eSAndroid Build Coastguard Worker .desc = "invalid iovec buffer",
139*49cdfc7eSAndroid Build Coastguard Worker },
140*49cdfc7eSAndroid Build Coastguard Worker {
141*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
142*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
143*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
144*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = -1,
145*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = recv_buf,
146*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
147*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
148*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
149*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
150*49cdfc7eSAndroid Build Coastguard Worker .exp_errno = EMSGSIZE,
151*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_valid_sock,
152*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_close_sock,
153*49cdfc7eSAndroid Build Coastguard Worker .desc = "invalid iovec count",
154*49cdfc7eSAndroid Build Coastguard Worker },
155*49cdfc7eSAndroid Build Coastguard Worker {
156*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
157*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
158*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
159*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
160*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = recv_buf,
161*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
162*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
163*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
164*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
165*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_valid_msg_control,
166*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_reset_all,
167*49cdfc7eSAndroid Build Coastguard Worker .desc = "permission reception",
168*49cdfc7eSAndroid Build Coastguard Worker },
169*49cdfc7eSAndroid Build Coastguard Worker {
170*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
171*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
172*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
173*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
174*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = recv_buf,
175*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
176*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
177*49cdfc7eSAndroid Build Coastguard Worker .flags = MSG_OOB,
178*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
179*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
180*49cdfc7eSAndroid Build Coastguard Worker .exp_errno = EINVAL,
181*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_valid_sock,
182*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_close_sock,
183*49cdfc7eSAndroid Build Coastguard Worker .desc = "invalid MSG_OOB flag set",
184*49cdfc7eSAndroid Build Coastguard Worker },
185*49cdfc7eSAndroid Build Coastguard Worker {
186*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
187*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
188*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
189*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
190*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = recv_buf,
191*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
192*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
193*49cdfc7eSAndroid Build Coastguard Worker .flags = MSG_ERRQUEUE,
194*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
195*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
196*49cdfc7eSAndroid Build Coastguard Worker .exp_errno = EAGAIN,
197*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_valid_sock,
198*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_close_sock,
199*49cdfc7eSAndroid Build Coastguard Worker .desc = "invalid MSG_ERRQUEUE flag set",
200*49cdfc7eSAndroid Build Coastguard Worker },
201*49cdfc7eSAndroid Build Coastguard Worker {
202*49cdfc7eSAndroid Build Coastguard Worker .domain = PF_INET,
203*49cdfc7eSAndroid Build Coastguard Worker .type = SOCK_STREAM,
204*49cdfc7eSAndroid Build Coastguard Worker .iov = iov,
205*49cdfc7eSAndroid Build Coastguard Worker .iovcnt = 1,
206*49cdfc7eSAndroid Build Coastguard Worker .recv_buf = recv_buf,
207*49cdfc7eSAndroid Build Coastguard Worker .buflen = sizeof(recv_buf),
208*49cdfc7eSAndroid Build Coastguard Worker .msg = &msgdat,
209*49cdfc7eSAndroid Build Coastguard Worker .from = (struct sockaddr *)&from,
210*49cdfc7eSAndroid Build Coastguard Worker .fromlen = sizeof(from),
211*49cdfc7eSAndroid Build Coastguard Worker .setup = setup_large_msg_control,
212*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup_reset_all,
213*49cdfc7eSAndroid Build Coastguard Worker .desc = "large cmesg length",
214*49cdfc7eSAndroid Build Coastguard Worker },
215*49cdfc7eSAndroid Build Coastguard Worker
216*49cdfc7eSAndroid Build Coastguard Worker };
217*49cdfc7eSAndroid Build Coastguard Worker
run(unsigned int n)218*49cdfc7eSAndroid Build Coastguard Worker static void run(unsigned int n)
219*49cdfc7eSAndroid Build Coastguard Worker {
220*49cdfc7eSAndroid Build Coastguard Worker struct tcase *tc = &tcases[n];
221*49cdfc7eSAndroid Build Coastguard Worker int ret = tc->exp_errno ? -1 : 0;
222*49cdfc7eSAndroid Build Coastguard Worker
223*49cdfc7eSAndroid Build Coastguard Worker if ((tst_kvercmp(3, 17, 0) < 0)
224*49cdfc7eSAndroid Build Coastguard Worker && (tc->flags & MSG_ERRQUEUE)
225*49cdfc7eSAndroid Build Coastguard Worker && (tc->type & SOCK_STREAM)) {
226*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "MSG_ERRQUEUE requires kernel >= 3.17");
227*49cdfc7eSAndroid Build Coastguard Worker return;
228*49cdfc7eSAndroid Build Coastguard Worker }
229*49cdfc7eSAndroid Build Coastguard Worker
230*49cdfc7eSAndroid Build Coastguard Worker setup_all();
231*49cdfc7eSAndroid Build Coastguard Worker tc->setup(n);
232*49cdfc7eSAndroid Build Coastguard Worker
233*49cdfc7eSAndroid Build Coastguard Worker iov[0].iov_base = tc->recv_buf;
234*49cdfc7eSAndroid Build Coastguard Worker iov[0].iov_len = tc->buflen;
235*49cdfc7eSAndroid Build Coastguard Worker msgdat.msg_name = tc->from;
236*49cdfc7eSAndroid Build Coastguard Worker msgdat.msg_namelen = tc->fromlen;
237*49cdfc7eSAndroid Build Coastguard Worker msgdat.msg_iov = tc->iov;
238*49cdfc7eSAndroid Build Coastguard Worker msgdat.msg_iovlen = tc->iovcnt;
239*49cdfc7eSAndroid Build Coastguard Worker msgdat.msg_control = control;
240*49cdfc7eSAndroid Build Coastguard Worker msgdat.msg_controllen = controllen;
241*49cdfc7eSAndroid Build Coastguard Worker msgdat.msg_flags = 0;
242*49cdfc7eSAndroid Build Coastguard Worker
243*49cdfc7eSAndroid Build Coastguard Worker TEST(recvmsg(sock, tc->msg, tc->flags));
244*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET >= 0)
245*49cdfc7eSAndroid Build Coastguard Worker TST_RET = 0;
246*49cdfc7eSAndroid Build Coastguard Worker
247*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET != ret) {
248*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TTERRNO, "%s: expected %d, returned %ld",
249*49cdfc7eSAndroid Build Coastguard Worker tc->desc, ret, TST_RET);
250*49cdfc7eSAndroid Build Coastguard Worker } else if (TST_ERR != tc->exp_errno) {
251*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TTERRNO,
252*49cdfc7eSAndroid Build Coastguard Worker "%s: expected %s",
253*49cdfc7eSAndroid Build Coastguard Worker tc->desc, tst_strerrno(tc->exp_errno));
254*49cdfc7eSAndroid Build Coastguard Worker } else {
255*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "%s passed", tc->desc);
256*49cdfc7eSAndroid Build Coastguard Worker }
257*49cdfc7eSAndroid Build Coastguard Worker
258*49cdfc7eSAndroid Build Coastguard Worker tc->cleanup(n);
259*49cdfc7eSAndroid Build Coastguard Worker cleanup_all();
260*49cdfc7eSAndroid Build Coastguard Worker }
261*49cdfc7eSAndroid Build Coastguard Worker
262*49cdfc7eSAndroid Build Coastguard Worker
setup_all(void)263*49cdfc7eSAndroid Build Coastguard Worker static void setup_all(void)
264*49cdfc7eSAndroid Build Coastguard Worker {
265*49cdfc7eSAndroid Build Coastguard Worker int tfd;
266*49cdfc7eSAndroid Build Coastguard Worker
267*49cdfc7eSAndroid Build Coastguard Worker sun1.sun_family = AF_UNIX;
268*49cdfc7eSAndroid Build Coastguard Worker
269*49cdfc7eSAndroid Build Coastguard Worker (void)strcpy(tmpsunpath, "udsockXXXXXX");
270*49cdfc7eSAndroid Build Coastguard Worker tfd = mkstemp(tmpsunpath);
271*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(tfd);
272*49cdfc7eSAndroid Build Coastguard Worker SAFE_UNLINK(tmpsunpath);
273*49cdfc7eSAndroid Build Coastguard Worker (void)strcpy(sun1.sun_path, tmpsunpath);
274*49cdfc7eSAndroid Build Coastguard Worker SAFE_SIGNAL(SIGPIPE, SIG_IGN);
275*49cdfc7eSAndroid Build Coastguard Worker pid = start_server(&sin1, &sun1);
276*49cdfc7eSAndroid Build Coastguard Worker }
277*49cdfc7eSAndroid Build Coastguard Worker
cleanup_all(void)278*49cdfc7eSAndroid Build Coastguard Worker static void cleanup_all(void)
279*49cdfc7eSAndroid Build Coastguard Worker {
280*49cdfc7eSAndroid Build Coastguard Worker if (pid > 0) {
281*49cdfc7eSAndroid Build Coastguard Worker (void)kill(pid, SIGKILL); /* kill server */
282*49cdfc7eSAndroid Build Coastguard Worker wait(NULL);
283*49cdfc7eSAndroid Build Coastguard Worker }
284*49cdfc7eSAndroid Build Coastguard Worker
285*49cdfc7eSAndroid Build Coastguard Worker if (tmpsunpath[0] != '\0')
286*49cdfc7eSAndroid Build Coastguard Worker (void)SAFE_UNLINK(tmpsunpath);
287*49cdfc7eSAndroid Build Coastguard Worker }
288*49cdfc7eSAndroid Build Coastguard Worker
setup_invalid_sock(int n)289*49cdfc7eSAndroid Build Coastguard Worker static void setup_invalid_sock(int n)
290*49cdfc7eSAndroid Build Coastguard Worker {
291*49cdfc7eSAndroid Build Coastguard Worker if (tcases[n].exp_errno == EBADF)
292*49cdfc7eSAndroid Build Coastguard Worker sock = 400; /* anything not an open file */
293*49cdfc7eSAndroid Build Coastguard Worker else
294*49cdfc7eSAndroid Build Coastguard Worker sock = SAFE_OPEN("/dev/null", O_WRONLY);
295*49cdfc7eSAndroid Build Coastguard Worker }
296*49cdfc7eSAndroid Build Coastguard Worker
cleanup_invalid_sock(int n)297*49cdfc7eSAndroid Build Coastguard Worker static void cleanup_invalid_sock(int n)
298*49cdfc7eSAndroid Build Coastguard Worker {
299*49cdfc7eSAndroid Build Coastguard Worker if (tcases[n].exp_errno == EBADF)
300*49cdfc7eSAndroid Build Coastguard Worker sock = -1;
301*49cdfc7eSAndroid Build Coastguard Worker else
302*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(sock);
303*49cdfc7eSAndroid Build Coastguard Worker }
304*49cdfc7eSAndroid Build Coastguard Worker
setup_valid_sock(int n)305*49cdfc7eSAndroid Build Coastguard Worker static void setup_valid_sock(int n)
306*49cdfc7eSAndroid Build Coastguard Worker {
307*49cdfc7eSAndroid Build Coastguard Worker fd_set rdfds;
308*49cdfc7eSAndroid Build Coastguard Worker struct timeval timeout;
309*49cdfc7eSAndroid Build Coastguard Worker
310*49cdfc7eSAndroid Build Coastguard Worker sock = SAFE_SOCKET(tcases[n].domain, tcases[n].type, tcases[n].protocol);
311*49cdfc7eSAndroid Build Coastguard Worker
312*49cdfc7eSAndroid Build Coastguard Worker if (tcases[n].type == SOCK_STREAM) {
313*49cdfc7eSAndroid Build Coastguard Worker if (tcases[n].domain == PF_INET) {
314*49cdfc7eSAndroid Build Coastguard Worker SAFE_CONNECT(sock, (struct sockaddr *)&sin1, sizeof(sin1));
315*49cdfc7eSAndroid Build Coastguard Worker /* Wait for something to be readable, else we won't detect EFAULT on recv */
316*49cdfc7eSAndroid Build Coastguard Worker FD_ZERO(&rdfds);
317*49cdfc7eSAndroid Build Coastguard Worker FD_SET(sock, &rdfds);
318*49cdfc7eSAndroid Build Coastguard Worker timeout.tv_sec = 2;
319*49cdfc7eSAndroid Build Coastguard Worker timeout.tv_usec = 0;
320*49cdfc7eSAndroid Build Coastguard Worker n = select(sock + 1, &rdfds, 0, 0, &timeout);
321*49cdfc7eSAndroid Build Coastguard Worker
322*49cdfc7eSAndroid Build Coastguard Worker if (n != 1 || !FD_ISSET(sock, &rdfds))
323*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "no message ready in %d sec", (int)timeout.tv_sec);
324*49cdfc7eSAndroid Build Coastguard Worker
325*49cdfc7eSAndroid Build Coastguard Worker } else if (tcases[n].domain == PF_UNIX) {
326*49cdfc7eSAndroid Build Coastguard Worker SAFE_CONNECT(sock, (struct sockaddr *)&sun1, sizeof(sun1));
327*49cdfc7eSAndroid Build Coastguard Worker }
328*49cdfc7eSAndroid Build Coastguard Worker }
329*49cdfc7eSAndroid Build Coastguard Worker }
330*49cdfc7eSAndroid Build Coastguard Worker
setup_valid_msg_control(int n)331*49cdfc7eSAndroid Build Coastguard Worker static void setup_valid_msg_control(int n)
332*49cdfc7eSAndroid Build Coastguard Worker {
333*49cdfc7eSAndroid Build Coastguard Worker setup_valid_sock(n);
334*49cdfc7eSAndroid Build Coastguard Worker SAFE_SEND(1, sock, "R", 1, 0);
335*49cdfc7eSAndroid Build Coastguard Worker control = (struct cmsghdr *)cbuf;
336*49cdfc7eSAndroid Build Coastguard Worker controllen = control->cmsg_len = sizeof(cbuf);
337*49cdfc7eSAndroid Build Coastguard Worker }
338*49cdfc7eSAndroid Build Coastguard Worker
setup_large_msg_control(int n)339*49cdfc7eSAndroid Build Coastguard Worker static void setup_large_msg_control(int n)
340*49cdfc7eSAndroid Build Coastguard Worker {
341*49cdfc7eSAndroid Build Coastguard Worker setup_valid_msg_control(n);
342*49cdfc7eSAndroid Build Coastguard Worker controllen = CONTROL_LEN;
343*49cdfc7eSAndroid Build Coastguard Worker }
344*49cdfc7eSAndroid Build Coastguard Worker
cleanup_close_sock(int n LTP_ATTRIBUTE_UNUSED)345*49cdfc7eSAndroid Build Coastguard Worker static void cleanup_close_sock(int n LTP_ATTRIBUTE_UNUSED)
346*49cdfc7eSAndroid Build Coastguard Worker {
347*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(sock);
348*49cdfc7eSAndroid Build Coastguard Worker }
349*49cdfc7eSAndroid Build Coastguard Worker
cleanup_reset_all(int n LTP_ATTRIBUTE_UNUSED)350*49cdfc7eSAndroid Build Coastguard Worker static void cleanup_reset_all(int n LTP_ATTRIBUTE_UNUSED)
351*49cdfc7eSAndroid Build Coastguard Worker {
352*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(sock);
353*49cdfc7eSAndroid Build Coastguard Worker
354*49cdfc7eSAndroid Build Coastguard Worker control = 0;
355*49cdfc7eSAndroid Build Coastguard Worker controllen = 0;
356*49cdfc7eSAndroid Build Coastguard Worker }
357*49cdfc7eSAndroid Build Coastguard Worker
start_server(struct sockaddr_in * ssin,struct sockaddr_un * ssun)358*49cdfc7eSAndroid Build Coastguard Worker pid_t start_server(struct sockaddr_in *ssin, struct sockaddr_un *ssun)
359*49cdfc7eSAndroid Build Coastguard Worker {
360*49cdfc7eSAndroid Build Coastguard Worker pid_t pid;
361*49cdfc7eSAndroid Build Coastguard Worker socklen_t slen = sizeof(*ssin);
362*49cdfc7eSAndroid Build Coastguard Worker
363*49cdfc7eSAndroid Build Coastguard Worker ssin->sin_family = AF_INET;
364*49cdfc7eSAndroid Build Coastguard Worker ssin->sin_port = 0; /* pick random free port */
365*49cdfc7eSAndroid Build Coastguard Worker ssin->sin_addr.s_addr = INADDR_ANY;
366*49cdfc7eSAndroid Build Coastguard Worker
367*49cdfc7eSAndroid Build Coastguard Worker /* set up inet socket */
368*49cdfc7eSAndroid Build Coastguard Worker sfd = SAFE_SOCKET(PF_INET, SOCK_STREAM, 0);
369*49cdfc7eSAndroid Build Coastguard Worker SAFE_BIND(sfd, (struct sockaddr *)ssin, sizeof(*ssin));
370*49cdfc7eSAndroid Build Coastguard Worker SAFE_LISTEN(sfd, 10);
371*49cdfc7eSAndroid Build Coastguard Worker SAFE_GETSOCKNAME(sfd, (struct sockaddr *)ssin, &slen);
372*49cdfc7eSAndroid Build Coastguard Worker
373*49cdfc7eSAndroid Build Coastguard Worker /* set up UNIX-domain socket */
374*49cdfc7eSAndroid Build Coastguard Worker ufd = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
375*49cdfc7eSAndroid Build Coastguard Worker SAFE_BIND(ufd, (struct sockaddr *)ssun, sizeof(*ssun));
376*49cdfc7eSAndroid Build Coastguard Worker SAFE_LISTEN(ufd, 10);
377*49cdfc7eSAndroid Build Coastguard Worker
378*49cdfc7eSAndroid Build Coastguard Worker pid = SAFE_FORK();
379*49cdfc7eSAndroid Build Coastguard Worker if (!pid) {
380*49cdfc7eSAndroid Build Coastguard Worker do_child();
381*49cdfc7eSAndroid Build Coastguard Worker exit(1);
382*49cdfc7eSAndroid Build Coastguard Worker }
383*49cdfc7eSAndroid Build Coastguard Worker
384*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(sfd);
385*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(ufd);
386*49cdfc7eSAndroid Build Coastguard Worker
387*49cdfc7eSAndroid Build Coastguard Worker return pid;
388*49cdfc7eSAndroid Build Coastguard Worker }
389*49cdfc7eSAndroid Build Coastguard Worker
390*49cdfc7eSAndroid Build Coastguard Worker /* for permission test */
sender(int fd)391*49cdfc7eSAndroid Build Coastguard Worker static void sender(int fd)
392*49cdfc7eSAndroid Build Coastguard Worker {
393*49cdfc7eSAndroid Build Coastguard Worker struct msghdr mh = {};
394*49cdfc7eSAndroid Build Coastguard Worker struct cmsghdr *control;
395*49cdfc7eSAndroid Build Coastguard Worker char tmpfn[BUF_SIZE] = "";
396*49cdfc7eSAndroid Build Coastguard Worker char snd_cbuf[BUF_SIZE] = "";
397*49cdfc7eSAndroid Build Coastguard Worker int tfd;
398*49cdfc7eSAndroid Build Coastguard Worker
399*49cdfc7eSAndroid Build Coastguard Worker (void)strcpy(tmpfn, "smtXXXXXX");
400*49cdfc7eSAndroid Build Coastguard Worker tfd = mkstemp(tmpfn);
401*49cdfc7eSAndroid Build Coastguard Worker if (tfd < 0)
402*49cdfc7eSAndroid Build Coastguard Worker return;
403*49cdfc7eSAndroid Build Coastguard Worker
404*49cdfc7eSAndroid Build Coastguard Worker /* set up cmsghdr */
405*49cdfc7eSAndroid Build Coastguard Worker control = (struct cmsghdr *)snd_cbuf;
406*49cdfc7eSAndroid Build Coastguard Worker control->cmsg_len = sizeof(struct cmsghdr) + 4;
407*49cdfc7eSAndroid Build Coastguard Worker control->cmsg_level = SOL_SOCKET;
408*49cdfc7eSAndroid Build Coastguard Worker control->cmsg_type = SCM_RIGHTS;
409*49cdfc7eSAndroid Build Coastguard Worker *(int *)CMSG_DATA(control) = tfd;
410*49cdfc7eSAndroid Build Coastguard Worker
411*49cdfc7eSAndroid Build Coastguard Worker /* set up msghdr */
412*49cdfc7eSAndroid Build Coastguard Worker iov[0].iov_base = MSG;
413*49cdfc7eSAndroid Build Coastguard Worker iov[0].iov_len = sizeof(MSG);
414*49cdfc7eSAndroid Build Coastguard Worker mh.msg_iov = iov;
415*49cdfc7eSAndroid Build Coastguard Worker mh.msg_iovlen = 1;
416*49cdfc7eSAndroid Build Coastguard Worker mh.msg_flags = 0;
417*49cdfc7eSAndroid Build Coastguard Worker mh.msg_control = control;
418*49cdfc7eSAndroid Build Coastguard Worker mh.msg_controllen = control->cmsg_len;
419*49cdfc7eSAndroid Build Coastguard Worker
420*49cdfc7eSAndroid Build Coastguard Worker /* do it */
421*49cdfc7eSAndroid Build Coastguard Worker SAFE_SENDMSG(sizeof(MSG), fd, &mh, 0);
422*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(tfd);
423*49cdfc7eSAndroid Build Coastguard Worker (void)SAFE_UNLINK(tmpfn);
424*49cdfc7eSAndroid Build Coastguard Worker }
425*49cdfc7eSAndroid Build Coastguard Worker
do_child(void)426*49cdfc7eSAndroid Build Coastguard Worker static void do_child(void)
427*49cdfc7eSAndroid Build Coastguard Worker {
428*49cdfc7eSAndroid Build Coastguard Worker struct sockaddr_in fsin;
429*49cdfc7eSAndroid Build Coastguard Worker struct sockaddr_un fsun;
430*49cdfc7eSAndroid Build Coastguard Worker fd_set afds, rfds;
431*49cdfc7eSAndroid Build Coastguard Worker int nfds, fd;
432*49cdfc7eSAndroid Build Coastguard Worker
433*49cdfc7eSAndroid Build Coastguard Worker FD_ZERO(&afds);
434*49cdfc7eSAndroid Build Coastguard Worker FD_SET(sfd, &afds);
435*49cdfc7eSAndroid Build Coastguard Worker FD_SET(ufd, &afds);
436*49cdfc7eSAndroid Build Coastguard Worker
437*49cdfc7eSAndroid Build Coastguard Worker nfds = MAX(sfd + 1, ufd + 1);
438*49cdfc7eSAndroid Build Coastguard Worker
439*49cdfc7eSAndroid Build Coastguard Worker /* accept connections until killed */
440*49cdfc7eSAndroid Build Coastguard Worker while (1) {
441*49cdfc7eSAndroid Build Coastguard Worker socklen_t fromlen;
442*49cdfc7eSAndroid Build Coastguard Worker
443*49cdfc7eSAndroid Build Coastguard Worker memcpy(&rfds, &afds, sizeof(rfds));
444*49cdfc7eSAndroid Build Coastguard Worker
445*49cdfc7eSAndroid Build Coastguard Worker if (select(nfds, &rfds, NULL, NULL,
446*49cdfc7eSAndroid Build Coastguard Worker NULL) < 0) {
447*49cdfc7eSAndroid Build Coastguard Worker if (errno != EINTR) {
448*49cdfc7eSAndroid Build Coastguard Worker perror("server select");
449*49cdfc7eSAndroid Build Coastguard Worker exit(1);
450*49cdfc7eSAndroid Build Coastguard Worker }
451*49cdfc7eSAndroid Build Coastguard Worker continue;
452*49cdfc7eSAndroid Build Coastguard Worker }
453*49cdfc7eSAndroid Build Coastguard Worker if (FD_ISSET(sfd, &rfds)) {
454*49cdfc7eSAndroid Build Coastguard Worker int newfd;
455*49cdfc7eSAndroid Build Coastguard Worker
456*49cdfc7eSAndroid Build Coastguard Worker fromlen = sizeof(fsin);
457*49cdfc7eSAndroid Build Coastguard Worker newfd = SAFE_ACCEPT(sfd, (struct sockaddr *)&fsin, &fromlen);
458*49cdfc7eSAndroid Build Coastguard Worker if (newfd >= 0) {
459*49cdfc7eSAndroid Build Coastguard Worker FD_SET(newfd, &afds);
460*49cdfc7eSAndroid Build Coastguard Worker nfds = MAX(nfds, newfd + 1);
461*49cdfc7eSAndroid Build Coastguard Worker /* send something back */
462*49cdfc7eSAndroid Build Coastguard Worker SAFE_SEND(1, newfd, "hi", 2, 0);
463*49cdfc7eSAndroid Build Coastguard Worker }
464*49cdfc7eSAndroid Build Coastguard Worker }
465*49cdfc7eSAndroid Build Coastguard Worker if (FD_ISSET(ufd, &rfds)) {
466*49cdfc7eSAndroid Build Coastguard Worker int newfd;
467*49cdfc7eSAndroid Build Coastguard Worker
468*49cdfc7eSAndroid Build Coastguard Worker fromlen = sizeof(fsun);
469*49cdfc7eSAndroid Build Coastguard Worker newfd = SAFE_ACCEPT(ufd, (struct sockaddr *)&fsun, &fromlen);
470*49cdfc7eSAndroid Build Coastguard Worker if (newfd >= 0) {
471*49cdfc7eSAndroid Build Coastguard Worker FD_SET(newfd, &afds);
472*49cdfc7eSAndroid Build Coastguard Worker nfds = MAX(nfds, newfd + 1);
473*49cdfc7eSAndroid Build Coastguard Worker }
474*49cdfc7eSAndroid Build Coastguard Worker }
475*49cdfc7eSAndroid Build Coastguard Worker for (fd = 0; fd < nfds; ++fd)
476*49cdfc7eSAndroid Build Coastguard Worker if (fd != sfd && fd != ufd && FD_ISSET(fd, &rfds)) {
477*49cdfc7eSAndroid Build Coastguard Worker char rbuf[BUF_SIZE];
478*49cdfc7eSAndroid Build Coastguard Worker
479*49cdfc7eSAndroid Build Coastguard Worker TEST(read(fd, rbuf, sizeof(rbuf)));
480*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET > 0 && rbuf[0] == 'R')
481*49cdfc7eSAndroid Build Coastguard Worker sender(fd);
482*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET == 0 || (TST_RET < 0 && TST_ERR != EINTR)) {
483*49cdfc7eSAndroid Build Coastguard Worker close(fd);
484*49cdfc7eSAndroid Build Coastguard Worker FD_CLR(fd, &afds);
485*49cdfc7eSAndroid Build Coastguard Worker }
486*49cdfc7eSAndroid Build Coastguard Worker }
487*49cdfc7eSAndroid Build Coastguard Worker }
488*49cdfc7eSAndroid Build Coastguard Worker }
489*49cdfc7eSAndroid Build Coastguard Worker
490*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
491*49cdfc7eSAndroid Build Coastguard Worker .test = run,
492*49cdfc7eSAndroid Build Coastguard Worker .tcnt = ARRAY_SIZE(tcases),
493*49cdfc7eSAndroid Build Coastguard Worker .forks_child = 1,
494*49cdfc7eSAndroid Build Coastguard Worker .needs_tmpdir = 1,
495*49cdfc7eSAndroid Build Coastguard Worker };
496