blob: 07abf1584cd5e478c0d70ffb5aa4b66df583f4fa [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
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
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
robbiewdaafaa02003-04-28 14:45:42 +000043/* The #ifndef code below is for 2.5 64-bit kernels, where */
44/* the MSG_CMSG_COMPAT flag must be 0 in order for the syscall */
45/* and this test to function correctly. */
46#ifndef MSG_CMSG_COMPAT
robbiewa26ed812003-06-17 21:26:54 +000047
subrata_modakbea91c22008-10-29 06:16:59 +000048#if defined (__powerpc64__) || defined (__mips64) || defined (__x86_64__) || defined (__sparc64__)
robbiewa26ed812003-06-17 21:26:54 +000049#define MSG_CMSG_COMPAT 0x80000000
50#else
robbiewdaafaa02003-04-28 14:45:42 +000051#define MSG_CMSG_COMPAT 0
robbiew869fdf72003-06-18 17:00:05 +000052#endif
robbiewa26ed812003-06-17 21:26:54 +000053
robbiewdaafaa02003-04-28 14:45:42 +000054#endif
55/***************************************************/
56
plars865695b2001-08-27 22:15:12 +000057#include <stdio.h>
58#include <unistd.h>
vapier32cc0ac2006-06-22 04:28:32 +000059#include <string.h>
plars865695b2001-08-27 22:15:12 +000060#include <errno.h>
plarsd8afa782002-05-06 21:55:58 +000061#include <fcntl.h>
plars865695b2001-08-27 22:15:12 +000062
63#include <sys/types.h>
64#include <sys/socket.h>
65#include <sys/signal.h>
66#include <sys/uio.h>
67#include <sys/un.h>
68#include <sys/file.h>
69
70#include <netinet/in.h>
71
72#include "test.h"
73#include "usctest.h"
74
subrata_modak56207ce2009-03-23 13:35:39 +000075char *TCID = "recvmsg01"; /* Test program identifier. */
plars865695b2001-08-27 22:15:12 +000076int testno;
77
subrata_modak56207ce2009-03-23 13:35:39 +000078char buf[1024], cbuf[1024];
79int s; /* socket descriptor */
80int passed_fd = -1; /* rights-passing test descriptor */
plars865695b2001-08-27 22:15:12 +000081struct sockaddr_in sin1, from;
82struct sockaddr_un sun1;
83struct msghdr msgdat;
84struct cmsghdr *control = 0;
subrata_modak56207ce2009-03-23 13:35:39 +000085int controllen = 0;
plars865695b2001-08-27 22:15:12 +000086struct iovec iov[1];
subrata_modak56207ce2009-03-23 13:35:39 +000087static int sfd; /* shared between do_child and start_server */
88static int ufd; /* shared between do_child and start_server */
plars865695b2001-08-27 22:15:12 +000089
plars8525f2f2003-01-28 17:32:52 +000090void setup(void);
91void setup0(void);
92void setup1(void);
93void setup2(void);
94void setup3(void);
95void setup4(void);
96void cleanup(void);
97void cleanup0(void);
98void cleanup1(void);
99void cleanup2(void);
robbiewd34d5812005-07-11 22:28:09 +0000100void do_child(void);
plars865695b2001-08-27 22:15:12 +0000101
102void sender(int);
plars8525f2f2003-01-28 17:32:52 +0000103pid_t start_server(struct sockaddr_in *, struct sockaddr_un *);
plars865695b2001-08-27 22:15:12 +0000104
105struct test_case_t { /* test case structure */
subrata_modak56207ce2009-03-23 13:35:39 +0000106 int domain; /* PF_INET, PF_UNIX, ... */
107 int type; /* SOCK_STREAM, SOCK_DGRAM ... */
108 int proto; /* protocol number (usually 0 = default) */
109 struct iovec *iov;
110 int iovcnt;
111 void *buf; /* recv data buffer */
112 int buflen; /* recv buffer length */
plars865695b2001-08-27 22:15:12 +0000113 struct msghdr *msg;
subrata_modakbdbaec52009-02-26 12:14:51 +0000114 unsigned flags;
plars865695b2001-08-27 22:15:12 +0000115 struct sockaddr *from; /* from address */
subrata_modak56207ce2009-03-23 13:35:39 +0000116 int fromlen; /* from address value/result buffer length */
117 int retval; /* syscall return value */
118 int experrno; /* expected errno */
119 void (*setup) (void);
120 void (*cleanup) (void);
plars865695b2001-08-27 22:15:12 +0000121 char *desc;
122} tdat[] = {
plars8525f2f2003-01-28 17:32:52 +0000123/* 1 */
subrata_modak56207ce2009-03-23 13:35:39 +0000124 {
125 PF_INET, SOCK_STREAM, 0, iov, 1, buf, sizeof(buf), &msgdat, 0,
126 (struct sockaddr *)&from, sizeof(from),
127 -1, EBADF, setup0, cleanup0, "bad file descriptor"}
128 ,
plars8525f2f2003-01-28 17:32:52 +0000129/* 2 */
subrata_modak56207ce2009-03-23 13:35:39 +0000130 {
131 0, 0, 0, iov, 1, (void *)buf, sizeof(buf), &msgdat, 0,
132 (struct sockaddr *)&from, sizeof(from),
133 -1, ENOTSOCK, setup0, cleanup0, "invalid socket"}
134 ,
plars8525f2f2003-01-28 17:32:52 +0000135/* 3 */
subrata_modak56207ce2009-03-23 13:35:39 +0000136 {
137 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
138 &msgdat, 0, (struct sockaddr *)-1, sizeof(from), 0,
139 ENOTSOCK, setup1, cleanup1, "invalid socket buffer"}
140 ,
plars8525f2f2003-01-28 17:32:52 +0000141/* 4 */
subrata_modak56207ce2009-03-23 13:35:39 +0000142 {
143 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
144 &msgdat, -1, (struct sockaddr *)&from, -1, -1,
145 EINVAL, setup1, cleanup1, "invalid socket length"},
plars8525f2f2003-01-28 17:32:52 +0000146/* 5 */
subrata_modak56207ce2009-03-23 13:35:39 +0000147 {
148 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)-1, sizeof(buf),
149 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
150 -1, EFAULT, setup1, cleanup1, "invalid recv buffer"}
151 ,
plars8525f2f2003-01-28 17:32:52 +0000152/* 6 */
subrata_modak56207ce2009-03-23 13:35:39 +0000153 {
154 PF_INET, SOCK_STREAM, 0, 0, 1, (void *)buf, sizeof(buf),
155 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
156 -1, EFAULT, setup1, cleanup1, "invalid iovec buffer"}
157 ,
plars8525f2f2003-01-28 17:32:52 +0000158/* 7 */
subrata_modak56207ce2009-03-23 13:35:39 +0000159 {
160 PF_INET, SOCK_STREAM, 0, iov, -1, (void *)buf, sizeof(buf),
161 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
162 -1, EMSGSIZE, setup1, cleanup1, "invalid iovec count"}
163 ,
plars8525f2f2003-01-28 17:32:52 +0000164/* 8 */
subrata_modak56207ce2009-03-23 13:35:39 +0000165 {
166 PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
167 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
168 0, 0, setup2, cleanup2, "rights reception"}
169 ,
plars8525f2f2003-01-28 17:32:52 +0000170/* 9 */
subrata_modak56207ce2009-03-23 13:35:39 +0000171 {
172 PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
173 &msgdat, ~MSG_CMSG_COMPAT, (struct sockaddr *)&from,
174 sizeof(from), -1, EINVAL, setup1, cleanup1,
175 "invalid flags set"}
176 ,
plars8525f2f2003-01-28 17:32:52 +0000177/* 10 */
subrata_modak56207ce2009-03-23 13:35:39 +0000178 {
179 PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
180 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
181 0, EINVAL, setup3, cleanup2, "invalid cmsg length"}
182 ,
plars8525f2f2003-01-28 17:32:52 +0000183/* 11 */
subrata_modak56207ce2009-03-23 13:35:39 +0000184 {
185 PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
186 &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
187 0, 0, setup4, cleanup2, "large cmesg length"}
188,};
plars865695b2001-08-27 22:15:12 +0000189
subrata_modak56207ce2009-03-23 13:35:39 +0000190int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); /* Total number of test cases. */
plars865695b2001-08-27 22:15:12 +0000191
subrata_modak56207ce2009-03-23 13:35:39 +0000192int exp_enos[] = { EBADF, ENOTSOCK, EFAULT, EINVAL, 0 };
plars865695b2001-08-27 22:15:12 +0000193
194extern int Tst_count;
195
robbiewd34d5812005-07-11 22:28:09 +0000196#ifdef UCLINUX
197static char *argv0;
198#endif
199
subrata_modak56207ce2009-03-23 13:35:39 +0000200int main(int argc, char *argv[])
plars865695b2001-08-27 22:15:12 +0000201{
202 int lc; /* loop counter */
203 char *msg; /* message returned from parse_opts */
204
205 /* Parse standard options given to run the test. */
Garrett Cooper45e285d2010-11-22 12:19:25 -0800206 msg = parse_opts(argc, argv, NULL, NULL);
207 if (msg != NULL) {
Garrett Cooper60fa8012010-11-22 13:50:58 -0800208 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
plars865695b2001-08-27 22:15:12 +0000209 }
robbiewd34d5812005-07-11 22:28:09 +0000210#ifdef UCLINUX
211 argv0 = argv[0];
212 maybe_run_child(&do_child, "dd", &sfd, &ufd);
213#endif
214
plars865695b2001-08-27 22:15:12 +0000215 setup();
216
217 TEST_EXP_ENOS(exp_enos);
218
219 /* Check looping state if -i option given */
220 for (lc = 0; TEST_LOOPING(lc); ++lc) {
221 Tst_count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000222 for (testno = 0; testno < TST_TOTAL; ++testno) {
plars865695b2001-08-27 22:15:12 +0000223 tdat[testno].setup();
224
225 /* setup common to all tests */
226
227 iov[0].iov_base = tdat[testno].buf;
228 iov[0].iov_len = tdat[testno].buflen;
229 msgdat.msg_name = tdat[testno].from;
230 msgdat.msg_namelen = tdat[testno].fromlen;
231 msgdat.msg_iov = tdat[testno].iov;
232 msgdat.msg_iovlen = tdat[testno].iovcnt;
233 msgdat.msg_control = control;
234 msgdat.msg_controllen = controllen;
235 msgdat.msg_flags = 0;
236
237 TEST(recvmsg(s, tdat[testno].msg, tdat[testno].flags));
238 if (TEST_RETURN >= 0)
subrata_modak56207ce2009-03-23 13:35:39 +0000239 TEST_RETURN = 0; /* all nonzero equal here */
plars865695b2001-08-27 22:15:12 +0000240 if (TEST_RETURN != tdat[testno].retval ||
241 (TEST_RETURN < 0 &&
242 TEST_ERRNO != tdat[testno].experrno)) {
243 tst_resm(TFAIL, "%s ; returned"
vapierc450e062009-08-28 14:28:52 +0000244 " %ld (expected %d), errno %d (expected"
subrata_modak56207ce2009-03-23 13:35:39 +0000245 " %d)", tdat[testno].desc,
246 TEST_RETURN, tdat[testno].retval,
247 TEST_ERRNO, tdat[testno].experrno);
plars865695b2001-08-27 22:15:12 +0000248 } else {
249 TEST_ERROR_LOG(TEST_ERRNO);
250 tst_resm(TPASS, "%s successful",
subrata_modak56207ce2009-03-23 13:35:39 +0000251 tdat[testno].desc);
plars865695b2001-08-27 22:15:12 +0000252 }
253 tdat[testno].cleanup();
254 }
255 }
256 cleanup();
subrata_modak56207ce2009-03-23 13:35:39 +0000257 /*NOT REACHED */
plars8525f2f2003-01-28 17:32:52 +0000258 return 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000259} /* End main */
plars865695b2001-08-27 22:15:12 +0000260
261pid_t pid;
262char tmpsunpath[1024];
263
subrata_modak56207ce2009-03-23 13:35:39 +0000264void setup(void)
plars865695b2001-08-27 22:15:12 +0000265{
plars4c78d162002-09-04 18:56:14 +0000266 int tfd;
subrata_modak56207ce2009-03-23 13:35:39 +0000267 TEST_PAUSE; /* if -P option specified */
plars865695b2001-08-27 22:15:12 +0000268
269 /* initialize sockaddr's */
270 sin1.sin_family = AF_INET;
subrata_modak56207ce2009-03-23 13:35:39 +0000271 sin1.sin_port = htons((getpid() % 32768) + 11000);
plars865695b2001-08-27 22:15:12 +0000272 sin1.sin_addr.s_addr = INADDR_ANY;
robbiewde02ee42003-04-16 21:15:20 +0000273 tst_tmpdir();
subrata_modak56207ce2009-03-23 13:35:39 +0000274 (void)strcpy(tmpsunpath, "udsockXXXXXX");
plars4c78d162002-09-04 18:56:14 +0000275 tfd = mkstemp(tmpsunpath);
276 close(tfd);
277 unlink(tmpsunpath);
plars865695b2001-08-27 22:15:12 +0000278 sun1.sun_family = AF_UNIX;
subrata_modak56207ce2009-03-23 13:35:39 +0000279 (void)strcpy(sun1.sun_path, tmpsunpath);
plars865695b2001-08-27 22:15:12 +0000280
281 signal(SIGPIPE, SIG_IGN);
282
283 pid = start_server(&sin1, &sun1);
284}
285
subrata_modak56207ce2009-03-23 13:35:39 +0000286void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000287{
subrata_modak56207ce2009-03-23 13:35:39 +0000288 (void)kill(pid, SIGKILL); /* kill server */
plars865695b2001-08-27 22:15:12 +0000289 if (tmpsunpath[0] != '\0')
subrata_modak56207ce2009-03-23 13:35:39 +0000290 (void)unlink(tmpsunpath);
plars865695b2001-08-27 22:15:12 +0000291 TEST_CLEANUP;
robbiewde02ee42003-04-16 21:15:20 +0000292 tst_rmdir();
plars865695b2001-08-27 22:15:12 +0000293 tst_exit();
294}
295
subrata_modak56207ce2009-03-23 13:35:39 +0000296void setup0(void)
plars865695b2001-08-27 22:15:12 +0000297{
298 if (tdat[testno].experrno == EBADF)
299 s = 400; /* anything not an open file */
subrata_modak56207ce2009-03-23 13:35:39 +0000300 else if ((s = open("/dev/null", O_WRONLY)) == -1)
vapierc450e062009-08-28 14:28:52 +0000301 tst_brkm(TBROK|TERRNO, cleanup, "open(/dev/null) failed");
plars865695b2001-08-27 22:15:12 +0000302}
303
subrata_modak56207ce2009-03-23 13:35:39 +0000304void cleanup0(void)
plars865695b2001-08-27 22:15:12 +0000305{
306 s = -1;
307}
308
subrata_modak56207ce2009-03-23 13:35:39 +0000309void setup1(void)
plars865695b2001-08-27 22:15:12 +0000310{
subrata_modak56207ce2009-03-23 13:35:39 +0000311 fd_set rdfds;
312 struct timeval timeout;
313 int n;
robbiewef952662003-03-27 15:10:06 +0000314
plars865695b2001-08-27 22:15:12 +0000315 s = socket(tdat[testno].domain, tdat[testno].type, tdat[testno].proto);
vapierc450e062009-08-28 14:28:52 +0000316 if (s < 0)
317 tst_brkm(TBROK|TERRNO, cleanup, "socket setup failed");
plars865695b2001-08-27 22:15:12 +0000318 if (tdat[testno].type == SOCK_STREAM) {
319 if (tdat[testno].domain == PF_INET) {
subrata_modak56207ce2009-03-23 13:35:39 +0000320 if (connect(s, (struct sockaddr *)&sin1, sizeof(sin1)) <
321 0)
vapierc450e062009-08-28 14:28:52 +0000322 tst_brkm(TBROK|TERRNO, cleanup, "connect failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000323 /* Wait for something to be readable, else we won't detect EFAULT on recv */
324 FD_ZERO(&rdfds);
325 FD_SET(s, &rdfds);
326 timeout.tv_sec = 2;
327 timeout.tv_usec = 0;
328 n = select(s + 1, &rdfds, 0, 0, &timeout);
329 if (n != 1 || !FD_ISSET(s, &rdfds))
330 tst_brkm(TBROK, cleanup,
331 "client setup1 failed - no message ready in 2 sec");
plars865695b2001-08-27 22:15:12 +0000332 } else if (tdat[testno].domain == PF_UNIX) {
subrata_modak56207ce2009-03-23 13:35:39 +0000333 if (connect(s, (struct sockaddr *)&sun1, sizeof(sun1)) <
334 0)
vapierc450e062009-08-28 14:28:52 +0000335 tst_brkm(TBROK|TERRNO, cleanup, "UD connect failed");
plars865695b2001-08-27 22:15:12 +0000336 }
337 }
338}
339
subrata_modak56207ce2009-03-23 13:35:39 +0000340void setup2(void)
plars865695b2001-08-27 22:15:12 +0000341{
342 setup1();
vapierc450e062009-08-28 14:28:52 +0000343 if (write(s, "R", 1) < 0)
344 tst_brkm(TBROK|TERRNO, cleanup, "test setup failed: write:");
plars865695b2001-08-27 22:15:12 +0000345 control = (struct cmsghdr *)cbuf;
346 controllen = control->cmsg_len = sizeof(cbuf);
347}
348
subrata_modak56207ce2009-03-23 13:35:39 +0000349void setup3(void)
plars865695b2001-08-27 22:15:12 +0000350{
351 setup2();
subrata_modak56207ce2009-03-23 13:35:39 +0000352 controllen = sizeof(struct cmsghdr) - 1;
plars865695b2001-08-27 22:15:12 +0000353}
354
subrata_modak56207ce2009-03-23 13:35:39 +0000355void setup4(void)
plars865695b2001-08-27 22:15:12 +0000356{
357 setup2();
358 controllen = 128 * 1024;
359}
360
subrata_modak56207ce2009-03-23 13:35:39 +0000361void cleanup1(void)
plars865695b2001-08-27 22:15:12 +0000362{
subrata_modak56207ce2009-03-23 13:35:39 +0000363 (void)close(s);
subrata_modakdad6e1a2007-10-30 10:46:58 +0000364 close(ufd);
365 close(sfd);
plars865695b2001-08-27 22:15:12 +0000366 s = -1;
367}
368
subrata_modak56207ce2009-03-23 13:35:39 +0000369void cleanup2(void)
plars865695b2001-08-27 22:15:12 +0000370{
subrata_modakdad6e1a2007-10-30 10:46:58 +0000371 close(ufd);
372 close(sfd);
subrata_modak56207ce2009-03-23 13:35:39 +0000373 (void)close(s);
plars865695b2001-08-27 22:15:12 +0000374 s = -1;
375
376 if (passed_fd >= 0)
subrata_modak56207ce2009-03-23 13:35:39 +0000377 (void)close(passed_fd);
plars865695b2001-08-27 22:15:12 +0000378 passed_fd = -1;
379 control = 0;
380 controllen = 0;
381}
382
subrata_modak56207ce2009-03-23 13:35:39 +0000383pid_t start_server(struct sockaddr_in *ssin, struct sockaddr_un *ssun)
plars865695b2001-08-27 22:15:12 +0000384{
subrata_modak56207ce2009-03-23 13:35:39 +0000385 pid_t pid;
plars865695b2001-08-27 22:15:12 +0000386
387 /* set up inet socket */
388 sfd = socket(PF_INET, SOCK_STREAM, 0);
389 if (sfd < 0) {
vapierc450e062009-08-28 14:28:52 +0000390 tst_brkm(TBROK|TERRNO, cleanup, "server socket failed");
plars865695b2001-08-27 22:15:12 +0000391 return -1;
392 }
393 if (bind(sfd, (struct sockaddr *)ssin, sizeof(*ssin)) < 0) {
vapierc450e062009-08-28 14:28:52 +0000394 tst_brkm(TBROK|TERRNO, cleanup, "server bind failed");
plars865695b2001-08-27 22:15:12 +0000395 return -1;
396 }
397 if (listen(sfd, 10) < 0) {
vapierc450e062009-08-28 14:28:52 +0000398 tst_brkm(TBROK|TERRNO, cleanup, "server listen failed");
plars865695b2001-08-27 22:15:12 +0000399 return -1;
400 }
401 /* set up UNIX-domain socket */
402 ufd = socket(PF_UNIX, SOCK_STREAM, 0);
403 if (ufd < 0) {
vapierc450e062009-08-28 14:28:52 +0000404 tst_brkm(TBROK|TERRNO, cleanup, "server UD socket failed");
plars865695b2001-08-27 22:15:12 +0000405 return -1;
406 }
407 if (bind(ufd, (struct sockaddr *)ssun, sizeof(*ssun))) {
vapierc450e062009-08-28 14:28:52 +0000408 tst_brkm(TBROK|TERRNO, cleanup, "server UD bind failed");
plars865695b2001-08-27 22:15:12 +0000409 return -1;
410 }
411 if (listen(ufd, 10) < 0) {
vapierc450e062009-08-28 14:28:52 +0000412 tst_brkm(TBROK|TERRNO, cleanup, "server UD listen failed");
plars865695b2001-08-27 22:15:12 +0000413 return -1;
414 }
415
vapierfed9da32006-02-19 09:25:08 +0000416 switch ((pid = FORK_OR_VFORK())) {
subrata_modak56207ce2009-03-23 13:35:39 +0000417 case 0: /* child */
robbiewd34d5812005-07-11 22:28:09 +0000418#ifdef UCLINUX
vapierc450e062009-08-28 14:28:52 +0000419 if (self_exec(argv0, "dd", sfd, ufd) < 0)
420 tst_brkm(TBROK|TERRNO, cleanup, "server self_exec failed");
robbiewd34d5812005-07-11 22:28:09 +0000421#else
422 do_child();
423#endif
plars865695b2001-08-27 22:15:12 +0000424 break;
425 case -1:
vapierc450e062009-08-28 14:28:52 +0000426 tst_brkm(TBROK|TERRNO, cleanup, "server fork failed");
plars865695b2001-08-27 22:15:12 +0000427 /* fall through */
subrata_modak56207ce2009-03-23 13:35:39 +0000428 default: /* parent */
429 (void)close(sfd);
430 (void)close(ufd);
plars865695b2001-08-27 22:15:12 +0000431 return pid;
432 }
subrata_modak56207ce2009-03-23 13:35:39 +0000433 /*NOTREACHED*/ exit(1);
robbiewd34d5812005-07-11 22:28:09 +0000434}
435
subrata_modak56207ce2009-03-23 13:35:39 +0000436void do_child()
robbiewd34d5812005-07-11 22:28:09 +0000437{
438 struct sockaddr_in fsin;
439 struct sockaddr_un fsun;
subrata_modak56207ce2009-03-23 13:35:39 +0000440 fd_set afds, rfds;
robbiewd34d5812005-07-11 22:28:09 +0000441 int nfds, cc, fd;
442
plars865695b2001-08-27 22:15:12 +0000443 FD_ZERO(&afds);
444 FD_SET(sfd, &afds);
445 FD_SET(ufd, &afds);
446
447 nfds = getdtablesize();
448
449 /* accept connections until killed */
450 while (1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000451 socklen_t fromlen;
plars865695b2001-08-27 22:15:12 +0000452
453 memcpy(&rfds, &afds, sizeof(rfds));
454
subrata_modak56207ce2009-03-23 13:35:39 +0000455 if (select(nfds, &rfds, (fd_set *) 0, (fd_set *) 0,
456 (struct timeval *)0) < 0) {
plars865695b2001-08-27 22:15:12 +0000457 if (errno != EINTR) {
458 perror("server select");
459 exit(1);
460 }
461 continue;
462 }
463 if (FD_ISSET(sfd, &rfds)) {
464 int newfd;
465
466 fromlen = sizeof(fsin);
plars8525f2f2003-01-28 17:32:52 +0000467 newfd = accept(sfd, (struct sockaddr *)&fsin, &fromlen);
plars865695b2001-08-27 22:15:12 +0000468 if (newfd >= 0) {
469 FD_SET(newfd, &afds);
470 /* send something back */
subrata_modak56207ce2009-03-23 13:35:39 +0000471 (void)write(newfd, "hoser\n", 6);
plars865695b2001-08-27 22:15:12 +0000472 }
473 }
474 if (FD_ISSET(ufd, &rfds)) {
475 int newfd;
476
477 fromlen = sizeof(fsun);
plars8525f2f2003-01-28 17:32:52 +0000478 newfd = accept(ufd, (struct sockaddr *)&fsun, &fromlen);
plars865695b2001-08-27 22:15:12 +0000479 if (newfd >= 0)
480 FD_SET(newfd, &afds);
481 }
subrata_modak56207ce2009-03-23 13:35:39 +0000482 for (fd = 0; fd < nfds; ++fd)
plars865695b2001-08-27 22:15:12 +0000483 if (fd != sfd && fd != ufd && FD_ISSET(fd, &rfds)) {
subrata_modak56207ce2009-03-23 13:35:39 +0000484 char rbuf[1024];
plars865695b2001-08-27 22:15:12 +0000485
486 cc = read(fd, rbuf, sizeof(rbuf));
487 if (cc && rbuf[0] == 'R')
488 sender(fd);
489 if (cc == 0 || (cc < 0 && errno != EINTR)) {
subrata_modak56207ce2009-03-23 13:35:39 +0000490 (void)close(fd);
plars865695b2001-08-27 22:15:12 +0000491 FD_CLR(fd, &afds);
492 }
493 }
494 }
495}
496
497#define TM "from recvmsg01 server"
498
499/* special for rights-passing test */
subrata_modak56207ce2009-03-23 13:35:39 +0000500void sender(int fd)
plars865695b2001-08-27 22:15:12 +0000501{
502 struct msghdr mh;
503 struct cmsghdr *control;
subrata_modak56207ce2009-03-23 13:35:39 +0000504 char tmpfn[1024], snd_cbuf[1024];
505 int tfd;
plars865695b2001-08-27 22:15:12 +0000506
subrata_modak56207ce2009-03-23 13:35:39 +0000507 (void)strcpy(tmpfn, "smtXXXXXX");
plars4c78d162002-09-04 18:56:14 +0000508 tfd = mkstemp(tmpfn);
plars865695b2001-08-27 22:15:12 +0000509 if (tfd < 0)
510 return;
plars865695b2001-08-27 22:15:12 +0000511
vapier32cc0ac2006-06-22 04:28:32 +0000512 memset(&mh, 0x00, sizeof(mh));
plars865695b2001-08-27 22:15:12 +0000513
514 /* set up cmsghdr */
515 control = (struct cmsghdr *)snd_cbuf;
vapier32cc0ac2006-06-22 04:28:32 +0000516 memset(control, 0x00, sizeof(struct cmsghdr));
subrata_modak56207ce2009-03-23 13:35:39 +0000517 control->cmsg_len = sizeof(struct cmsghdr) + 4;
plars865695b2001-08-27 22:15:12 +0000518 control->cmsg_level = SOL_SOCKET;
519 control->cmsg_type = SCM_RIGHTS;
520 *(int *)CMSG_DATA(control) = tfd;
521
522 /* set up msghdr */
523 iov[0].iov_base = TM;
524 iov[0].iov_len = sizeof(TM);
525 mh.msg_iov = iov;
526 mh.msg_iovlen = 1;
527 mh.msg_flags = 0;
528 mh.msg_control = control;
529 mh.msg_controllen = control->cmsg_len;
530
531 /* do it */
subrata_modak56207ce2009-03-23 13:35:39 +0000532 (void)sendmsg(fd, &mh, 0);
533 (void)close(tfd);
534 (void)unlink(tmpfn);
plars865695b2001-08-27 22:15:12 +0000535}