blob: a6dbe6e7dd70f67800835fbc8bfccdeb71a32c45 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * Test Name: recvmsg01
22 *
23 * Test Description:
24 * Verify that recvmsg() returns the proper errno for various failure cases
25 *
26 * Usage: <for command-line>
27 * recvmsg01 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
28 * where, -c n : Run n copies concurrently.
29 * -e : Turn on errno logging.
30 * -i n : Execute test n times.
31 * -I x : Execute test for x seconds.
32 * -P x : Pause for x seconds between iterations.
33 * -t : Turn on syscall timing.
34 *
35 * HISTORY
36 * 07/2001 Ported by Wayne Boyer
37 *
38 * RESTRICTIONS:
39 * None.
40 *
41 */
42
43#include <stdio.h>
44#include <unistd.h>
vapier32cc0ac2006-06-22 04:28:32 +000045#include <string.h>
plars865695b2001-08-27 22:15:12 +000046#include <errno.h>
plarsd8afa782002-05-06 21:55:58 +000047#include <fcntl.h>
plars865695b2001-08-27 22:15:12 +000048
49#include <sys/types.h>
50#include <sys/socket.h>
51#include <sys/signal.h>
52#include <sys/uio.h>
53#include <sys/un.h>
54#include <sys/file.h>
55
56#include <netinet/in.h>
57
58#include "test.h"
Stanislav Kholmanskikh9748d552014-05-13 10:20:22 +040059#include "msg_common.h"
plars865695b2001-08-27 22:15:12 +000060
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020061char *TCID = "recvmsg01";
plars865695b2001-08-27 22:15:12 +000062int testno;
63
subrata_modak56207ce2009-03-23 13:35:39 +000064char buf[1024], cbuf[1024];
65int s; /* socket descriptor */
66int passed_fd = -1; /* rights-passing test descriptor */
plars865695b2001-08-27 22:15:12 +000067struct sockaddr_in sin1, from;
68struct sockaddr_un sun1;
69struct msghdr msgdat;
70struct cmsghdr *control = 0;
subrata_modak56207ce2009-03-23 13:35:39 +000071int controllen = 0;
plars865695b2001-08-27 22:15:12 +000072struct iovec iov[1];
subrata_modak56207ce2009-03-23 13:35:39 +000073static int sfd; /* shared between do_child and start_server */
74static int ufd; /* shared between do_child and start_server */
plars865695b2001-08-27 22:15:12 +000075
plars8525f2f2003-01-28 17:32:52 +000076void setup(void);
77void setup0(void);
78void setup1(void);
79void setup2(void);
80void setup3(void);
81void setup4(void);
82void cleanup(void);
83void cleanup0(void);
84void cleanup1(void);
85void cleanup2(void);
robbiewd34d5812005-07-11 22:28:09 +000086void do_child(void);
plars865695b2001-08-27 22:15:12 +000087
88void sender(int);
plars8525f2f2003-01-28 17:32:52 +000089pid_t start_server(struct sockaddr_in *, struct sockaddr_un *);
plars865695b2001-08-27 22:15:12 +000090
91struct test_case_t { /* test case structure */
subrata_modak56207ce2009-03-23 13:35:39 +000092 int domain; /* PF_INET, PF_UNIX, ... */
93 int type; /* SOCK_STREAM, SOCK_DGRAM ... */
94 int proto; /* protocol number (usually 0 = default) */
95 struct iovec *iov;
96 int iovcnt;
97 void *buf; /* recv data buffer */
98 int buflen; /* recv buffer length */
plars865695b2001-08-27 22:15:12 +000099 struct msghdr *msg;
subrata_modakbdbaec52009-02-26 12:14:51 +0000100 unsigned flags;
plars865695b2001-08-27 22:15:12 +0000101 struct sockaddr *from; /* from address */
subrata_modak56207ce2009-03-23 13:35:39 +0000102 int fromlen; /* from address value/result buffer length */
103 int retval; /* syscall return value */
104 int experrno; /* expected errno */
105 void (*setup) (void);
106 void (*cleanup) (void);
plars865695b2001-08-27 22:15:12 +0000107 char *desc;
108} tdat[] = {
plars8525f2f2003-01-28 17:32:52 +0000109/* 1 */
subrata_modak56207ce2009-03-23 13:35:39 +0000110 {
111 PF_INET, SOCK_STREAM, 0, iov, 1, buf, sizeof(buf), &msgdat, 0,
112 (struct sockaddr *)&from, sizeof(from),
113 -1, EBADF, setup0, cleanup0, "bad file descriptor"}
114 ,
plars8525f2f2003-01-28 17:32:52 +0000115/* 2 */
subrata_modak56207ce2009-03-23 13:35:39 +0000116 {
117 0, 0, 0, iov, 1, (void *)buf, sizeof(buf), &msgdat, 0,
118 (struct sockaddr *)&from, sizeof(from),
119 -1, ENOTSOCK, setup0, cleanup0, "invalid socket"}
120 ,
plars8525f2f2003-01-28 17:32:52 +0000121/* 3 */
subrata_modak56207ce2009-03-23 13:35:39 +0000122 {
123 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
124 &msgdat, 0, (struct sockaddr *)-1, sizeof(from), 0,
125 ENOTSOCK, setup1, cleanup1, "invalid socket buffer"}
126 ,
plars8525f2f2003-01-28 17:32:52 +0000127/* 4 */
subrata_modak56207ce2009-03-23 13:35:39 +0000128 {
129 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
130 &msgdat, -1, (struct sockaddr *)&from, -1, -1,
131 EINVAL, setup1, cleanup1, "invalid socket length"},
plars8525f2f2003-01-28 17:32:52 +0000132/* 5 */
subrata_modak56207ce2009-03-23 13:35:39 +0000133 {
134 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)-1, sizeof(buf),
135 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
136 -1, EFAULT, setup1, cleanup1, "invalid recv buffer"}
137 ,
plars8525f2f2003-01-28 17:32:52 +0000138/* 6 */
subrata_modak56207ce2009-03-23 13:35:39 +0000139 {
140 PF_INET, SOCK_STREAM, 0, 0, 1, (void *)buf, sizeof(buf),
141 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
142 -1, EFAULT, setup1, cleanup1, "invalid iovec buffer"}
143 ,
plars8525f2f2003-01-28 17:32:52 +0000144/* 7 */
subrata_modak56207ce2009-03-23 13:35:39 +0000145 {
146 PF_INET, SOCK_STREAM, 0, iov, -1, (void *)buf, sizeof(buf),
147 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
148 -1, EMSGSIZE, setup1, cleanup1, "invalid iovec count"}
149 ,
plars8525f2f2003-01-28 17:32:52 +0000150/* 8 */
subrata_modak56207ce2009-03-23 13:35:39 +0000151 {
152 PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
153 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
154 0, 0, setup2, cleanup2, "rights reception"}
155 ,
plars8525f2f2003-01-28 17:32:52 +0000156/* 9 */
subrata_modak56207ce2009-03-23 13:35:39 +0000157 {
158 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
Cyril Hrubisd7aa1762014-11-26 12:34:14 +0100159 &msgdat, MSG_OOB, (struct sockaddr *)&from,
subrata_modak56207ce2009-03-23 13:35:39 +0000160 sizeof(from), -1, EINVAL, setup1, cleanup1,
Cyril Hrubisd7aa1762014-11-26 12:34:14 +0100161 "invalid MSG_OOB flag set"}
subrata_modak56207ce2009-03-23 13:35:39 +0000162 ,
plars8525f2f2003-01-28 17:32:52 +0000163/* 10 */
subrata_modak56207ce2009-03-23 13:35:39 +0000164 {
Cyril Hrubisd7aa1762014-11-26 12:34:14 +0100165 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
166 &msgdat, MSG_ERRQUEUE, (struct sockaddr *)&from,
167 sizeof(from), -1, EAGAIN, setup1, cleanup1,
168 "invalid MSG_ERRQUEUE flag set"}
169 ,
170/* 11 */
171 {
subrata_modak56207ce2009-03-23 13:35:39 +0000172 PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
173 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
174 0, EINVAL, setup3, cleanup2, "invalid cmsg length"}
175 ,
Cyril Hrubisd7aa1762014-11-26 12:34:14 +0100176/* 12 */
subrata_modak56207ce2009-03-23 13:35:39 +0000177 {
178 PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
179 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
180 0, 0, setup4, cleanup2, "large cmesg length"}
181,};
plars865695b2001-08-27 22:15:12 +0000182
Cyril Hrubisfdce7d52013-04-04 18:35:48 +0200183int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
plars865695b2001-08-27 22:15:12 +0000184
robbiewd34d5812005-07-11 22:28:09 +0000185#ifdef UCLINUX
186static char *argv0;
187#endif
188
subrata_modak56207ce2009-03-23 13:35:39 +0000189int main(int argc, char *argv[])
plars865695b2001-08-27 22:15:12 +0000190{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200191 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200192 const char *msg;
plars865695b2001-08-27 22:15:12 +0000193
Garrett Cooper53740502010-12-16 00:04:01 -0800194 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800195 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
robbiewd34d5812005-07-11 22:28:09 +0000196#ifdef UCLINUX
197 argv0 = argv[0];
198 maybe_run_child(&do_child, "dd", &sfd, &ufd);
199#endif
200
plars865695b2001-08-27 22:15:12 +0000201 setup();
202
plars865695b2001-08-27 22:15:12 +0000203 for (lc = 0; TEST_LOOPING(lc); ++lc) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800204 tst_count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000205 for (testno = 0; testno < TST_TOTAL; ++testno) {
Jan Stanceke5fd5122015-01-10 11:08:03 +0100206 if ((tst_kvercmp(3, 17, 0) < 0)
207 && (tdat[testno].flags & MSG_ERRQUEUE)
208 && (tdat[testno].type & SOCK_STREAM)) {
209 tst_resm(TCONF, "skip MSG_ERRQUEUE test, "
210 "it's supported from 3.17");
211 continue;
212 }
213
plars865695b2001-08-27 22:15:12 +0000214 tdat[testno].setup();
215
216 /* setup common to all tests */
plars865695b2001-08-27 22:15:12 +0000217 iov[0].iov_base = tdat[testno].buf;
218 iov[0].iov_len = tdat[testno].buflen;
219 msgdat.msg_name = tdat[testno].from;
220 msgdat.msg_namelen = tdat[testno].fromlen;
221 msgdat.msg_iov = tdat[testno].iov;
222 msgdat.msg_iovlen = tdat[testno].iovcnt;
223 msgdat.msg_control = control;
224 msgdat.msg_controllen = controllen;
225 msgdat.msg_flags = 0;
226
227 TEST(recvmsg(s, tdat[testno].msg, tdat[testno].flags));
228 if (TEST_RETURN >= 0)
subrata_modak56207ce2009-03-23 13:35:39 +0000229 TEST_RETURN = 0; /* all nonzero equal here */
plars865695b2001-08-27 22:15:12 +0000230 if (TEST_RETURN != tdat[testno].retval ||
231 (TEST_RETURN < 0 &&
232 TEST_ERRNO != tdat[testno].experrno)) {
233 tst_resm(TFAIL, "%s ; returned"
vapierc450e062009-08-28 14:28:52 +0000234 " %ld (expected %d), errno %d (expected"
subrata_modak56207ce2009-03-23 13:35:39 +0000235 " %d)", tdat[testno].desc,
236 TEST_RETURN, tdat[testno].retval,
237 TEST_ERRNO, tdat[testno].experrno);
plars865695b2001-08-27 22:15:12 +0000238 } else {
plars865695b2001-08-27 22:15:12 +0000239 tst_resm(TPASS, "%s successful",
subrata_modak56207ce2009-03-23 13:35:39 +0000240 tdat[testno].desc);
plars865695b2001-08-27 22:15:12 +0000241 }
242 tdat[testno].cleanup();
243 }
244 }
245 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800246
247 tst_exit();
248}
plars865695b2001-08-27 22:15:12 +0000249
250pid_t pid;
251char tmpsunpath[1024];
252
subrata_modak56207ce2009-03-23 13:35:39 +0000253void setup(void)
plars865695b2001-08-27 22:15:12 +0000254{
plars4c78d162002-09-04 18:56:14 +0000255 int tfd;
Cyril Hrubisfdce7d52013-04-04 18:35:48 +0200256 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000257
robbiewde02ee42003-04-16 21:15:20 +0000258 tst_tmpdir();
subrata_modak56207ce2009-03-23 13:35:39 +0000259 (void)strcpy(tmpsunpath, "udsockXXXXXX");
plars4c78d162002-09-04 18:56:14 +0000260 tfd = mkstemp(tmpsunpath);
261 close(tfd);
262 unlink(tmpsunpath);
plars865695b2001-08-27 22:15:12 +0000263 sun1.sun_family = AF_UNIX;
subrata_modak56207ce2009-03-23 13:35:39 +0000264 (void)strcpy(sun1.sun_path, tmpsunpath);
plars865695b2001-08-27 22:15:12 +0000265
266 signal(SIGPIPE, SIG_IGN);
267
268 pid = start_server(&sin1, &sun1);
269}
270
subrata_modak56207ce2009-03-23 13:35:39 +0000271void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000272{
Jan Stancek809ea9b2011-11-07 13:53:42 +0100273 if (pid > 0)
274 (void)kill(pid, SIGKILL); /* kill server */
plars865695b2001-08-27 22:15:12 +0000275 if (tmpsunpath[0] != '\0')
subrata_modak56207ce2009-03-23 13:35:39 +0000276 (void)unlink(tmpsunpath);
robbiewde02ee42003-04-16 21:15:20 +0000277 tst_rmdir();
Garrett Cooper2c282152010-12-16 00:55:50 -0800278
plars865695b2001-08-27 22:15:12 +0000279}
280
subrata_modak56207ce2009-03-23 13:35:39 +0000281void setup0(void)
plars865695b2001-08-27 22:15:12 +0000282{
283 if (tdat[testno].experrno == EBADF)
284 s = 400; /* anything not an open file */
subrata_modak56207ce2009-03-23 13:35:39 +0000285 else if ((s = open("/dev/null", O_WRONLY)) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800286 tst_brkm(TBROK | TERRNO, cleanup, "open(/dev/null) failed");
plars865695b2001-08-27 22:15:12 +0000287}
288
subrata_modak56207ce2009-03-23 13:35:39 +0000289void cleanup0(void)
plars865695b2001-08-27 22:15:12 +0000290{
291 s = -1;
292}
293
subrata_modak56207ce2009-03-23 13:35:39 +0000294void setup1(void)
plars865695b2001-08-27 22:15:12 +0000295{
subrata_modak56207ce2009-03-23 13:35:39 +0000296 fd_set rdfds;
297 struct timeval timeout;
298 int n;
robbiewef952662003-03-27 15:10:06 +0000299
plars865695b2001-08-27 22:15:12 +0000300 s = socket(tdat[testno].domain, tdat[testno].type, tdat[testno].proto);
vapierc450e062009-08-28 14:28:52 +0000301 if (s < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800302 tst_brkm(TBROK | TERRNO, cleanup, "socket setup failed");
plars865695b2001-08-27 22:15:12 +0000303 if (tdat[testno].type == SOCK_STREAM) {
304 if (tdat[testno].domain == PF_INET) {
subrata_modak56207ce2009-03-23 13:35:39 +0000305 if (connect(s, (struct sockaddr *)&sin1, sizeof(sin1)) <
306 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800307 tst_brkm(TBROK | TERRNO, cleanup,
308 "connect failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000309 /* Wait for something to be readable, else we won't detect EFAULT on recv */
310 FD_ZERO(&rdfds);
311 FD_SET(s, &rdfds);
312 timeout.tv_sec = 2;
313 timeout.tv_usec = 0;
314 n = select(s + 1, &rdfds, 0, 0, &timeout);
315 if (n != 1 || !FD_ISSET(s, &rdfds))
316 tst_brkm(TBROK, cleanup,
317 "client setup1 failed - no message ready in 2 sec");
plars865695b2001-08-27 22:15:12 +0000318 } else if (tdat[testno].domain == PF_UNIX) {
subrata_modak56207ce2009-03-23 13:35:39 +0000319 if (connect(s, (struct sockaddr *)&sun1, sizeof(sun1)) <
320 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800321 tst_brkm(TBROK | TERRNO, cleanup,
322 "UD connect failed");
plars865695b2001-08-27 22:15:12 +0000323 }
324 }
325}
326
subrata_modak56207ce2009-03-23 13:35:39 +0000327void setup2(void)
plars865695b2001-08-27 22:15:12 +0000328{
329 setup1();
vapierc450e062009-08-28 14:28:52 +0000330 if (write(s, "R", 1) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800331 tst_brkm(TBROK | TERRNO, cleanup, "test setup failed: write:");
plars865695b2001-08-27 22:15:12 +0000332 control = (struct cmsghdr *)cbuf;
333 controllen = control->cmsg_len = sizeof(cbuf);
334}
335
subrata_modak56207ce2009-03-23 13:35:39 +0000336void setup3(void)
plars865695b2001-08-27 22:15:12 +0000337{
338 setup2();
subrata_modak56207ce2009-03-23 13:35:39 +0000339 controllen = sizeof(struct cmsghdr) - 1;
plars865695b2001-08-27 22:15:12 +0000340}
341
subrata_modak56207ce2009-03-23 13:35:39 +0000342void setup4(void)
plars865695b2001-08-27 22:15:12 +0000343{
344 setup2();
345 controllen = 128 * 1024;
346}
347
subrata_modak56207ce2009-03-23 13:35:39 +0000348void cleanup1(void)
plars865695b2001-08-27 22:15:12 +0000349{
subrata_modak56207ce2009-03-23 13:35:39 +0000350 (void)close(s);
subrata_modakdad6e1a2007-10-30 10:46:58 +0000351 close(ufd);
352 close(sfd);
plars865695b2001-08-27 22:15:12 +0000353 s = -1;
354}
355
subrata_modak56207ce2009-03-23 13:35:39 +0000356void cleanup2(void)
plars865695b2001-08-27 22:15:12 +0000357{
subrata_modakdad6e1a2007-10-30 10:46:58 +0000358 close(ufd);
359 close(sfd);
subrata_modak56207ce2009-03-23 13:35:39 +0000360 (void)close(s);
plars865695b2001-08-27 22:15:12 +0000361 s = -1;
362
363 if (passed_fd >= 0)
subrata_modak56207ce2009-03-23 13:35:39 +0000364 (void)close(passed_fd);
plars865695b2001-08-27 22:15:12 +0000365 passed_fd = -1;
366 control = 0;
367 controllen = 0;
368}
369
subrata_modak56207ce2009-03-23 13:35:39 +0000370pid_t start_server(struct sockaddr_in *ssin, struct sockaddr_un *ssun)
plars865695b2001-08-27 22:15:12 +0000371{
subrata_modak56207ce2009-03-23 13:35:39 +0000372 pid_t pid;
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100373 socklen_t slen = sizeof(*ssin);
374
375 ssin->sin_family = AF_INET;
376 ssin->sin_port = 0; /* pick random free port */
377 ssin->sin_addr.s_addr = INADDR_ANY;
plars865695b2001-08-27 22:15:12 +0000378
379 /* set up inet socket */
380 sfd = socket(PF_INET, SOCK_STREAM, 0);
381 if (sfd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800382 tst_brkm(TBROK | TERRNO, cleanup, "server socket failed");
plars865695b2001-08-27 22:15:12 +0000383 return -1;
384 }
385 if (bind(sfd, (struct sockaddr *)ssin, sizeof(*ssin)) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800386 tst_brkm(TBROK | TERRNO, cleanup, "server bind failed");
plars865695b2001-08-27 22:15:12 +0000387 return -1;
388 }
389 if (listen(sfd, 10) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800390 tst_brkm(TBROK | TERRNO, cleanup, "server listen failed");
plars865695b2001-08-27 22:15:12 +0000391 return -1;
392 }
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100393 if (getsockname(sfd, (struct sockaddr *)ssin, &slen) == -1)
394 tst_brkm(TBROK | TERRNO, cleanup, "getsockname failed");
395
plars865695b2001-08-27 22:15:12 +0000396 /* set up UNIX-domain socket */
397 ufd = socket(PF_UNIX, SOCK_STREAM, 0);
398 if (ufd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800399 tst_brkm(TBROK | TERRNO, cleanup, "server UD socket failed");
plars865695b2001-08-27 22:15:12 +0000400 return -1;
401 }
402 if (bind(ufd, (struct sockaddr *)ssun, sizeof(*ssun))) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800403 tst_brkm(TBROK | TERRNO, cleanup, "server UD bind failed");
plars865695b2001-08-27 22:15:12 +0000404 return -1;
405 }
406 if (listen(ufd, 10) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800407 tst_brkm(TBROK | TERRNO, cleanup, "server UD listen failed");
plars865695b2001-08-27 22:15:12 +0000408 return -1;
409 }
410
vapierfed9da32006-02-19 09:25:08 +0000411 switch ((pid = FORK_OR_VFORK())) {
subrata_modak56207ce2009-03-23 13:35:39 +0000412 case 0: /* child */
robbiewd34d5812005-07-11 22:28:09 +0000413#ifdef UCLINUX
vapierc450e062009-08-28 14:28:52 +0000414 if (self_exec(argv0, "dd", sfd, ufd) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800415 tst_brkm(TBROK | TERRNO, cleanup,
416 "server self_exec failed");
robbiewd34d5812005-07-11 22:28:09 +0000417#else
418 do_child();
419#endif
plars865695b2001-08-27 22:15:12 +0000420 break;
421 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800422 tst_brkm(TBROK | TERRNO, cleanup, "server fork failed");
plars865695b2001-08-27 22:15:12 +0000423 /* fall through */
subrata_modak56207ce2009-03-23 13:35:39 +0000424 default: /* parent */
425 (void)close(sfd);
426 (void)close(ufd);
plars865695b2001-08-27 22:15:12 +0000427 return pid;
428 }
Garrett Cooper53740502010-12-16 00:04:01 -0800429 exit(1);
robbiewd34d5812005-07-11 22:28:09 +0000430}
431
Mike Frysingerc57fba52014-04-09 18:56:30 -0400432void do_child(void)
robbiewd34d5812005-07-11 22:28:09 +0000433{
434 struct sockaddr_in fsin;
435 struct sockaddr_un fsun;
subrata_modak56207ce2009-03-23 13:35:39 +0000436 fd_set afds, rfds;
robbiewd34d5812005-07-11 22:28:09 +0000437 int nfds, cc, fd;
438
plars865695b2001-08-27 22:15:12 +0000439 FD_ZERO(&afds);
440 FD_SET(sfd, &afds);
441 FD_SET(ufd, &afds);
442
Cyril Hrubis7855d092014-10-09 16:13:05 +0200443 nfds = MAX(sfd + 1, ufd + 1);
plars865695b2001-08-27 22:15:12 +0000444
445 /* accept connections until killed */
446 while (1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000447 socklen_t fromlen;
plars865695b2001-08-27 22:15:12 +0000448
449 memcpy(&rfds, &afds, sizeof(rfds));
450
Cyril Hrubis4e2bab82014-09-24 16:34:35 +0200451 if (select(nfds, &rfds, NULL, NULL,
452 NULL) < 0) {
plars865695b2001-08-27 22:15:12 +0000453 if (errno != EINTR) {
454 perror("server select");
455 exit(1);
456 }
457 continue;
458 }
459 if (FD_ISSET(sfd, &rfds)) {
460 int newfd;
461
462 fromlen = sizeof(fsin);
plars8525f2f2003-01-28 17:32:52 +0000463 newfd = accept(sfd, (struct sockaddr *)&fsin, &fromlen);
plars865695b2001-08-27 22:15:12 +0000464 if (newfd >= 0) {
465 FD_SET(newfd, &afds);
Cyril Hrubis7855d092014-10-09 16:13:05 +0200466 nfds = MAX(nfds, newfd + 1);
plars865695b2001-08-27 22:15:12 +0000467 /* send something back */
subrata_modak56207ce2009-03-23 13:35:39 +0000468 (void)write(newfd, "hoser\n", 6);
plars865695b2001-08-27 22:15:12 +0000469 }
470 }
471 if (FD_ISSET(ufd, &rfds)) {
472 int newfd;
473
474 fromlen = sizeof(fsun);
plars8525f2f2003-01-28 17:32:52 +0000475 newfd = accept(ufd, (struct sockaddr *)&fsun, &fromlen);
Jan Stancekb9f01962015-01-10 11:13:17 +0100476 if (newfd >= 0) {
plars865695b2001-08-27 22:15:12 +0000477 FD_SET(newfd, &afds);
Jan Stancekb9f01962015-01-10 11:13:17 +0100478 nfds = MAX(nfds, newfd + 1);
479 }
plars865695b2001-08-27 22:15:12 +0000480 }
subrata_modak56207ce2009-03-23 13:35:39 +0000481 for (fd = 0; fd < nfds; ++fd)
plars865695b2001-08-27 22:15:12 +0000482 if (fd != sfd && fd != ufd && FD_ISSET(fd, &rfds)) {
subrata_modak56207ce2009-03-23 13:35:39 +0000483 char rbuf[1024];
plars865695b2001-08-27 22:15:12 +0000484
485 cc = read(fd, rbuf, sizeof(rbuf));
486 if (cc && rbuf[0] == 'R')
487 sender(fd);
488 if (cc == 0 || (cc < 0 && errno != EINTR)) {
subrata_modak56207ce2009-03-23 13:35:39 +0000489 (void)close(fd);
plars865695b2001-08-27 22:15:12 +0000490 FD_CLR(fd, &afds);
491 }
492 }
493 }
494}
495
496#define TM "from recvmsg01 server"
497
498/* special for rights-passing test */
subrata_modak56207ce2009-03-23 13:35:39 +0000499void sender(int fd)
plars865695b2001-08-27 22:15:12 +0000500{
501 struct msghdr mh;
502 struct cmsghdr *control;
subrata_modak56207ce2009-03-23 13:35:39 +0000503 char tmpfn[1024], snd_cbuf[1024];
504 int tfd;
plars865695b2001-08-27 22:15:12 +0000505
subrata_modak56207ce2009-03-23 13:35:39 +0000506 (void)strcpy(tmpfn, "smtXXXXXX");
plars4c78d162002-09-04 18:56:14 +0000507 tfd = mkstemp(tmpfn);
plars865695b2001-08-27 22:15:12 +0000508 if (tfd < 0)
509 return;
plars865695b2001-08-27 22:15:12 +0000510
vapier32cc0ac2006-06-22 04:28:32 +0000511 memset(&mh, 0x00, sizeof(mh));
plars865695b2001-08-27 22:15:12 +0000512
513 /* set up cmsghdr */
514 control = (struct cmsghdr *)snd_cbuf;
vapier32cc0ac2006-06-22 04:28:32 +0000515 memset(control, 0x00, sizeof(struct cmsghdr));
subrata_modak56207ce2009-03-23 13:35:39 +0000516 control->cmsg_len = sizeof(struct cmsghdr) + 4;
plars865695b2001-08-27 22:15:12 +0000517 control->cmsg_level = SOL_SOCKET;
518 control->cmsg_type = SCM_RIGHTS;
519 *(int *)CMSG_DATA(control) = tfd;
520
521 /* set up msghdr */
522 iov[0].iov_base = TM;
523 iov[0].iov_len = sizeof(TM);
524 mh.msg_iov = iov;
525 mh.msg_iovlen = 1;
526 mh.msg_flags = 0;
527 mh.msg_control = control;
528 mh.msg_controllen = control->cmsg_len;
529
530 /* do it */
subrata_modak56207ce2009-03-23 13:35:39 +0000531 (void)sendmsg(fd, &mh, 0);
532 (void)close(tfd);
533 (void)unlink(tmpfn);
Jan Stancek809ea9b2011-11-07 13:53:42 +0100534}