blob: 3df71a1af09b53a22e4c3f3775945918b618d228 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +02004 * Copyright (c) Cyril Hrubis <chrubis@suse.cz> 2012
plars865695b2001-08-27 22:15:12 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 * the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiewbd455c42003-10-07 21:25:53 +000019 *
plars865695b2001-08-27 22:15:12 +000020 */
21
22/*
23 * Test Name: sendmsg01
24 *
25 * Test Description:
26 * Verify that sendmsg() returns the proper errno for various failure cases
27 *
plars865695b2001-08-27 22:15:12 +000028 * HISTORY
29 * 07/2001 Ported by Wayne Boyer
iyermanoj78562692003-05-01 20:50:38 +000030 * 05/2003 Modified by Manoj Iyer - Make setup function set up lo device.
plars865695b2001-08-27 22:15:12 +000031 */
32
33#include <stdio.h>
34#include <unistd.h>
35#include <errno.h>
vapier32cc0ac2006-06-22 04:28:32 +000036#include <string.h>
plars13cbed72002-03-26 20:43:10 +000037#include <fcntl.h>
robbiewc9c0b4e2003-04-16 20:47:48 +000038#include <time.h>
iyermanoj78562692003-05-01 20:50:38 +000039#include <stdlib.h>
plars865695b2001-08-27 22:15:12 +000040#include <sys/types.h>
41#include <sys/socket.h>
42#include <sys/signal.h>
43#include <sys/uio.h>
44#include <sys/un.h>
45#include <sys/file.h>
iyermanoj78562692003-05-01 20:50:38 +000046#include <sys/wait.h>
47
plars865695b2001-08-27 22:15:12 +000048#include <netinet/in.h>
49
50#include "test.h"
Stanislav Kholmanskikh9748d552014-05-13 10:20:22 +040051#include "msg_common.h"
plars865695b2001-08-27 22:15:12 +000052
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +020053char *TCID = "sendmsg01";
plars865695b2001-08-27 22:15:12 +000054int testno;
55
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +020056static char buf[1024], bigbuf[128 * 1024];
57static int s;
58static struct sockaddr_in sin1, sin2;
59static struct sockaddr_un sun1;
60static struct msghdr msgdat;
61static char cbuf[4096];
62static struct cmsghdr *control;
63static int controllen;
64static struct iovec iov[1];
subrata_modak56207ce2009-03-23 13:35:39 +000065static int sfd; /* shared between do_child and start_server */
66static int ufd; /* shared between do_child and start_server */
plars865695b2001-08-27 22:15:12 +000067
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +020068static void setup(void);
69static void setup0(void);
70static void setup1(void);
71static void setup2(void);
72static void setup3(void);
73static void setup4(void);
74static void setup5(void);
75static void setup6(void);
76static void setup8(void);
77
78static void cleanup(void);
79static void cleanup0(void);
80static void cleanup1(void);
81static void cleanup4(void);
82
83static void do_child(void);
plars865695b2001-08-27 22:15:12 +000084
85struct test_case_t { /* test case structure */
subrata_modak56207ce2009-03-23 13:35:39 +000086 int domain; /* PF_INET, PF_UNIX, ... */
87 int type; /* SOCK_STREAM, SOCK_DGRAM ... */
88 int proto; /* protocol number (usually 0 = default) */
89 struct iovec *iov;
90 int iovcnt; /* # elements in iovec */
91 void *buf; /* send data buffer */
92 int buflen; /* send buffer length */
plars865695b2001-08-27 22:15:12 +000093 struct msghdr *msg;
94 unsigned flags;
95 struct sockaddr *to; /* destination */
subrata_modak56207ce2009-03-23 13:35:39 +000096 int tolen; /* length of "to" buffer */
97 int retval; /* syscall return value */
98 int experrno; /* expected errno */
Wanlong Gao354ebb42012-12-07 10:10:04 +080099 void (*setup) (void);
100 void (*cleanup) (void);
plars865695b2001-08-27 22:15:12 +0000101 char *desc;
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200102};
plars865695b2001-08-27 22:15:12 +0000103
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200104struct test_case_t tdat[] = {
105 {.domain = PF_INET,
106 .type = SOCK_STREAM,
107 .proto = 0,
108 .iov = iov,
109 .iovcnt = 1,
110 .buf = buf,
111 .buflen = sizeof(buf),
112 .msg = &msgdat,
113 .flags = 0,
114 .to = (struct sockaddr *)&sin1,
115 .tolen = sizeof(sin1),
116 .retval = -1,
117 .experrno = EBADF,
118 .setup = setup0,
119 .cleanup = cleanup0,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800120 .desc = "bad file descriptor"}
121 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200122 {.domain = 0,
123 .type = 0,
124 .proto = 0,
125 .iov = iov,
126 .iovcnt = 1,
127 .buf = buf,
128 .buflen = sizeof(buf),
129 .msg = &msgdat,
130 .flags = 0,
131 .to = (struct sockaddr *)&sin1,
132 .tolen = sizeof(sin1),
133 .retval = -1,
134 .experrno = ENOTSOCK,
135 .setup = setup0,
136 .cleanup = cleanup0,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800137 .desc = "invalid socket"}
138 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200139 {.domain = PF_INET,
140 .type = SOCK_DGRAM,
141 .proto = 0,
142 .iov = iov,
143 .iovcnt = 1,
144 .buf = (void *)-1,
145 .buflen = sizeof(buf),
146 .msg = &msgdat,
147 .flags = 0,
148 .to = (struct sockaddr *)&sin1,
149 .tolen = sizeof(sin1),
150 .retval = -1,
151 .experrno = EFAULT,
152 .setup = setup1,
153 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800154 .desc = "invalid send buffer"}
155 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200156 {.domain = PF_INET,
157 .type = SOCK_STREAM,
158 .proto = 0,
159 .iov = iov,
160 .iovcnt = 1,
161 .buf = buf,
162 .buflen = sizeof(buf),
163 .msg = &msgdat,
164 .flags = 0,
165 .to = (struct sockaddr *)&sin2,
166 .tolen = sizeof(sin2),
167 .retval = 0,
168 .experrno = EFAULT,
169 .setup = setup5,
170 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800171 .desc = "connected TCP"}
172 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200173 {.domain = PF_INET,
174 .type = SOCK_STREAM,
175 .proto = 0,
176 .iov = iov,
177 .iovcnt = 1,
178 .buf = buf,
179 .buflen = sizeof(buf),
180 .msg = &msgdat,
181 .flags = 0,
182 .to = (struct sockaddr *)&sin1,
183 .tolen = sizeof(sin1),
184 .retval = -1,
185 .experrno = EPIPE,
186 .setup = setup3,
187 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800188 .desc = "not connected TCP"}
189 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200190 {.domain = PF_INET,
191 .type = SOCK_DGRAM,
192 .proto = 0,
193 .iov = iov,
194 .iovcnt = 1,
195 .buf = buf,
196 .buflen = sizeof(buf),
197 .msg = &msgdat,
198 .flags = 0,
199 .to = (struct sockaddr *)&sin1,
Jan Stancek9a3e8bc2013-12-05 12:23:49 +0100200 .tolen = 1,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200201 .retval = -1,
202 .experrno = EINVAL,
203 .setup = setup1,
204 .cleanup = cleanup1,
205 .desc = "invalid to buffer length"},
206 {.domain = PF_INET,
207 .type = SOCK_DGRAM,
208 .proto = 0,
209 .iov = iov,
210 .iovcnt = 1,
211 .buf = buf,
212 .buflen = sizeof(buf),
213 .msg = &msgdat,
214 .flags = 0,
215 .to = (struct sockaddr *)-1,
Wanlong Gaobad64052013-12-04 10:35:22 +0800216 .tolen = sizeof(struct sockaddr),
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200217 .retval = -1,
Wanlong Gaobad64052013-12-04 10:35:22 +0800218 .experrno = EFAULT,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200219 .setup = setup1,
220 .cleanup = cleanup1,
221 .desc = "invalid to buffer"},
222 {.domain = PF_INET,
223 .type = SOCK_DGRAM,
224 .proto = 0,
225 .iov = iov,
226 .iovcnt = 1,
227 .buf = bigbuf,
228 .buflen = sizeof(bigbuf),
229 .msg = &msgdat,
230 .flags = 0,
231 .to = (struct sockaddr *)&sin1,
232 .tolen = sizeof(sin1),
233 .retval = -1,
234 .experrno = EMSGSIZE,
235 .setup = setup1,
236 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800237 .desc = "UDP message too big"}
238 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200239 {.domain = PF_INET,
240 .type = SOCK_STREAM,
241 .proto = 0,
242 .iov = iov,
243 .iovcnt = 1,
244 .buf = buf,
245 .buflen = sizeof(buf),
246 .msg = &msgdat,
247 .flags = 0,
248 .to = (struct sockaddr *)&sin1,
249 .tolen = sizeof(sin1),
250 .retval = -1,
251 .experrno = EPIPE,
252 .setup = setup2,
253 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800254 .desc = "local endpoint shutdown"}
255 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200256 {.domain = PF_INET,
257 .type = SOCK_STREAM,
258 .proto = 0,
259 .iov = NULL,
260 .iovcnt = 1,
261 .buf = buf,
262 .buflen = sizeof(buf),
263 .msg = &msgdat,
264 .flags = 0,
265 .to = (struct sockaddr *)&sin1,
266 .tolen = sizeof(sin1),
267 .retval = -1,
268 .experrno = EFAULT,
269 .setup = setup1,
270 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800271 .desc = "invalid iovec pointer"}
272 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200273 {.domain = PF_INET,
274 .type = SOCK_STREAM,
275 .proto = 0,
276 .iov = iov,
277 .iovcnt = 1,
278 .buf = buf,
279 .buflen = sizeof(buf),
280 .msg = NULL,
281 .flags = 0,
282 .to = (struct sockaddr *)&sin1,
283 .tolen = sizeof(sin1),
284 .retval = -1,
285 .experrno = EFAULT,
286 .setup = setup1,
287 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800288 .desc = "invalid msghdr pointer"}
289 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200290 {.domain = PF_UNIX,
291 .type = SOCK_DGRAM,
292 .proto = 0,
293 .iov = iov,
294 .iovcnt = 1,
295 .buf = buf,
296 .buflen = sizeof(buf),
297 .msg = &msgdat,
298 .flags = 0,
299 .to = (struct sockaddr *)&sun1,
300 .tolen = sizeof(sun1),
301 .retval = 0,
302 .experrno = 0,
303 .setup = setup4,
304 .cleanup = cleanup4,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800305 .desc = "rights passing"}
306 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200307 {.domain = PF_UNIX,
308 .type = SOCK_DGRAM,
309 .proto = 0,
310 .iov = iov,
311 .iovcnt = 1,
312 .buf = buf,
313 .buflen = sizeof(buf),
314 .msg = &msgdat,
315 .flags = ~MSG_CMSG_COMPAT,
316 .to = (struct sockaddr *)&sun1,
317 .tolen = sizeof(sun1),
318 .retval = -1,
319 .experrno = EOPNOTSUPP,
320 .setup = setup4,
321 .cleanup = cleanup4,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800322 .desc = "invalid flags set w/ control"}
323 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200324 {.domain = PF_INET,
Jan Stancek1c6354e2013-11-29 11:39:34 +0100325 .type = SOCK_DGRAM,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200326 .proto = 0,
327 .iov = iov,
328 .iovcnt = 1,
329 .buf = buf,
330 .buflen = sizeof(buf),
331 .msg = &msgdat,
Jan Stancek1c6354e2013-11-29 11:39:34 +0100332 .flags = MSG_OOB,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200333 .to = (struct sockaddr *)&sin1,
334 .tolen = sizeof(sin1),
Jan Stancek1c6354e2013-11-29 11:39:34 +0100335 .retval = -1,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200336 .experrno = EOPNOTSUPP,
Jan Stancek1c6354e2013-11-29 11:39:34 +0100337 .setup = setup1,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200338 .cleanup = cleanup1,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800339 .desc = "invalid flags set"}
340 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200341 {.domain = PF_UNIX,
342 .type = SOCK_DGRAM,
343 .proto = 0,
344 .iov = iov,
345 .iovcnt = 1,
346 .buf = buf,
347 .buflen = sizeof(buf),
348 .msg = &msgdat,
349 .flags = 0,
350 .to = (struct sockaddr *)&sun1,
351 .tolen = sizeof(sun1),
352 .retval = 0,
353 .experrno = EOPNOTSUPP,
354 .setup = setup6,
355 .cleanup = cleanup4,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800356 .desc = "invalid cmsg length"}
357 ,
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200358 {.domain = PF_UNIX,
359 .type = SOCK_DGRAM,
360 .proto = 0,
361 .iov = iov,
362 .iovcnt = 1,
363 .buf = buf,
364 .buflen = sizeof(buf),
365 .msg = &msgdat,
366 .flags = 0,
367 .to = (struct sockaddr *)&sun1,
368 .tolen = sizeof(sun1),
369 .retval = -1,
370 .experrno = EFAULT,
371 .setup = setup8,
372 .cleanup = cleanup4,
373 .desc = "invalid cmsg pointer"}
374};
plars865695b2001-08-27 22:15:12 +0000375
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200376int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
plars865695b2001-08-27 22:15:12 +0000377
robbiewd34d5812005-07-11 22:28:09 +0000378#ifdef UCLINUX
379static char *argv0;
380#endif
381
subrata_modak56207ce2009-03-23 13:35:39 +0000382int main(int argc, char *argv[])
plars865695b2001-08-27 22:15:12 +0000383{
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200384 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200385 const char *msg;
plars865695b2001-08-27 22:15:12 +0000386
Garrett Cooper45e285d2010-11-22 12:19:25 -0800387 msg = parse_opts(argc, argv, NULL, NULL);
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200388 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +0000389 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200390
robbiewd34d5812005-07-11 22:28:09 +0000391#ifdef UCLINUX
392 argv0 = argv[0];
393 maybe_run_child(&do_child, "dd", &sfd, &ufd);
394#endif
395
plars865695b2001-08-27 22:15:12 +0000396 setup();
397
plars865695b2001-08-27 22:15:12 +0000398 for (lc = 0; TEST_LOOPING(lc); ++lc) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800399 tst_count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000400 for (testno = 0; testno < TST_TOTAL; ++testno) {
plars865695b2001-08-27 22:15:12 +0000401 tdat[testno].setup();
402
403 iov[0].iov_base = tdat[testno].buf;
404 iov[0].iov_len = tdat[testno].buflen;
405 if (tdat[testno].type != SOCK_STREAM) {
406 msgdat.msg_name = tdat[testno].to;
407 msgdat.msg_namelen = tdat[testno].tolen;
408 }
409 msgdat.msg_iov = tdat[testno].iov;
410 msgdat.msg_iovlen = tdat[testno].iovcnt;
411 msgdat.msg_control = control;
412 msgdat.msg_controllen = controllen;
413 msgdat.msg_flags = 0;
414
415 TEST(sendmsg(s, tdat[testno].msg, tdat[testno].flags));
416
417 if (TEST_RETURN > 0)
Cyril Hrubis605fa332015-02-04 13:11:20 +0100418 TEST_RETURN = 0;
robbiewbd455c42003-10-07 21:25:53 +0000419
plars865695b2001-08-27 22:15:12 +0000420 if (TEST_RETURN != tdat[testno].retval ||
421 (TEST_RETURN < 0 &&
robbiewbd455c42003-10-07 21:25:53 +0000422 TEST_ERRNO != tdat[testno].experrno)) {
plars865695b2001-08-27 22:15:12 +0000423 tst_resm(TFAIL, "%s ; returned"
subrata_modak923b23f2009-11-02 13:57:16 +0000424 " %ld (expected %d), errno %d (expected"
subrata_modak56207ce2009-03-23 13:35:39 +0000425 " %d)", tdat[testno].desc,
426 TEST_RETURN, tdat[testno].retval,
427 TEST_ERRNO, tdat[testno].experrno);
plars865695b2001-08-27 22:15:12 +0000428 } else {
429 tst_resm(TPASS, "%s successful",
subrata_modak56207ce2009-03-23 13:35:39 +0000430 tdat[testno].desc);
plars865695b2001-08-27 22:15:12 +0000431 }
432 tdat[testno].cleanup();
433 }
434 }
435 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800436 tst_exit();
437}
plars865695b2001-08-27 22:15:12 +0000438
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200439static pid_t start_server(struct sockaddr_in *sin0, struct sockaddr_un *sun0)
robbiewaa01abd2003-03-27 18:39:24 +0000440{
subrata_modak56207ce2009-03-23 13:35:39 +0000441 pid_t pid;
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100442 socklen_t slen = sizeof(*sin0);
443
444 sin0->sin_family = AF_INET;
445 sin0->sin_port = 0; /* pick random free port */
446 sin0->sin_addr.s_addr = INADDR_ANY;
robbiewaa01abd2003-03-27 18:39:24 +0000447
448 /* set up inet socket */
449 sfd = socket(PF_INET, SOCK_STREAM, 0);
450 if (sfd < 0) {
451 tst_brkm(TBROK, cleanup, "server socket failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000452 strerror(errno));
robbiewaa01abd2003-03-27 18:39:24 +0000453 return -1;
454 }
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100455 if (bind(sfd, (struct sockaddr *)sin0, sizeof(*sin0)) < 0) {
robbiewaa01abd2003-03-27 18:39:24 +0000456 tst_brkm(TBROK, cleanup, "server bind failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000457 strerror(errno));
robbiewaa01abd2003-03-27 18:39:24 +0000458 return -1;
459 }
460 if (listen(sfd, 10) < 0) {
461 tst_brkm(TBROK, cleanup, "server listen failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000462 strerror(errno));
robbiewaa01abd2003-03-27 18:39:24 +0000463 return -1;
464 }
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100465 if (getsockname(sfd, (struct sockaddr *)sin0, &slen) == -1)
466 tst_brkm(TBROK | TERRNO, cleanup, "getsockname failed");
467
robbiewaa01abd2003-03-27 18:39:24 +0000468 /* set up UNIX-domain socket */
469 ufd = socket(PF_UNIX, SOCK_DGRAM, 0);
470 if (ufd < 0) {
471 tst_brkm(TBROK, cleanup, "server UD socket failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000472 strerror(errno));
robbiewaa01abd2003-03-27 18:39:24 +0000473 return -1;
474 }
475 if (bind(ufd, (struct sockaddr *)sun0, sizeof(*sun0))) {
476 tst_brkm(TBROK, cleanup, "server UD bind failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000477 strerror(errno));
robbiewaa01abd2003-03-27 18:39:24 +0000478 return -1;
479 }
480
robbiewd34d5812005-07-11 22:28:09 +0000481 switch ((pid = FORK_OR_VFORK())) {
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200482 case 0:
robbiewd34d5812005-07-11 22:28:09 +0000483#ifdef UCLINUX
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200484 if (self_exec(argv0, "dd", sfd, ufd) < 0)
robbiewd34d5812005-07-11 22:28:09 +0000485 tst_brkm(TBROK, cleanup, "server self_exec failed");
robbiewd34d5812005-07-11 22:28:09 +0000486#else
487 do_child();
488#endif
robbiewaa01abd2003-03-27 18:39:24 +0000489 break;
490 case -1:
491 tst_brkm(TBROK, cleanup, "server fork failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000492 strerror(errno));
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200493 default:
494 close(sfd);
495 close(ufd);
robbiewaa01abd2003-03-27 18:39:24 +0000496 return pid;
497 }
498
Wanlong Gao354ebb42012-12-07 10:10:04 +0800499 exit(1);
robbiewd34d5812005-07-11 22:28:09 +0000500}
501
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200502static void do_child(void)
robbiewd34d5812005-07-11 22:28:09 +0000503{
504 struct sockaddr_in fsin;
505 struct sockaddr_un fsun;
subrata_modak56207ce2009-03-23 13:35:39 +0000506 fd_set afds, rfds;
507 int nfds, cc, fd;
robbiewd34d5812005-07-11 22:28:09 +0000508
robbiewaa01abd2003-03-27 18:39:24 +0000509 FD_ZERO(&afds);
510 FD_SET(sfd, &afds);
511 FD_SET(ufd, &afds);
512
Cyril Hrubis7855d092014-10-09 16:13:05 +0200513 nfds = MAX(sfd + 1, ufd + 1);
robbiewaa01abd2003-03-27 18:39:24 +0000514
515 /* accept connections until killed */
516 while (1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000517 socklen_t fromlen;
robbiewaa01abd2003-03-27 18:39:24 +0000518
519 memcpy(&rfds, &afds, sizeof(rfds));
520
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200521 if (select(nfds, &rfds, NULL, NULL, NULL) < 0)
robbiewaa01abd2003-03-27 18:39:24 +0000522 if (errno != EINTR)
523 exit(1);
524 if (FD_ISSET(sfd, &rfds)) {
525 int newfd;
526
527 fromlen = sizeof(fsin);
subrata_modak56207ce2009-03-23 13:35:39 +0000528 newfd = accept(sfd, (struct sockaddr *)&fsin, &fromlen);
Cyril Hrubis7855d092014-10-09 16:13:05 +0200529 if (newfd >= 0) {
robbiewaa01abd2003-03-27 18:39:24 +0000530 FD_SET(newfd, &afds);
Cyril Hrubis7855d092014-10-09 16:13:05 +0200531 nfds = MAX(nfds, newfd + 1);
532 }
robbiewaa01abd2003-03-27 18:39:24 +0000533 }
534 if (FD_ISSET(ufd, &rfds)) {
535 int newfd;
536
537 fromlen = sizeof(fsun);
subrata_modak56207ce2009-03-23 13:35:39 +0000538 newfd = accept(ufd, (struct sockaddr *)&fsun, &fromlen);
robbiewaa01abd2003-03-27 18:39:24 +0000539 if (newfd >= 0)
540 FD_SET(newfd, &afds);
541 }
subrata_modak56207ce2009-03-23 13:35:39 +0000542 for (fd = 0; fd < nfds; ++fd) {
robbiewaa01abd2003-03-27 18:39:24 +0000543 if (fd != sfd && fd != ufd && FD_ISSET(fd, &rfds)) {
544 cc = read(fd, buf, sizeof(buf));
545 if (cc == 0 || (cc < 0 && errno != EINTR)) {
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200546 close(fd);
robbiewaa01abd2003-03-27 18:39:24 +0000547 FD_CLR(fd, &afds);
548 }
549 }
550 }
551 }
552}
553
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200554static pid_t pid;
555static char tmpsunpath[1024];
plars865695b2001-08-27 22:15:12 +0000556
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200557static void setup(void)
plars865695b2001-08-27 22:15:12 +0000558{
plars865695b2001-08-27 22:15:12 +0000559
iyermanoj78562692003-05-01 20:50:38 +0000560 int ret = 0;
Zhouping Liued241672013-01-22 10:00:42 +0800561
562 tst_require_root(NULL);
563 tst_sig(FORK, DEF_HANDLER, cleanup);
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200564 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000565
plars865695b2001-08-27 22:15:12 +0000566
robbiewc9c0b4e2003-04-16 20:47:48 +0000567 tst_tmpdir();
subrata_modak56207ce2009-03-23 13:35:39 +0000568 snprintf(tmpsunpath, 1024, "udsock%ld", (long)time(NULL));
plars865695b2001-08-27 22:15:12 +0000569 sun1.sun_family = AF_UNIX;
robbiewc9c0b4e2003-04-16 20:47:48 +0000570 strcpy(sun1.sun_path, tmpsunpath);
plars865695b2001-08-27 22:15:12 +0000571
iyermanoj78562692003-05-01 20:50:38 +0000572 /* this test will fail or in some cases hang if no eth or lo is
Zhouping Liued241672013-01-22 10:00:42 +0800573 * configured, so making sure in setup that at least lo is up
iyermanoj78562692003-05-01 20:50:38 +0000574 */
Zhouping Liued241672013-01-22 10:00:42 +0800575 ret = system("ip link set lo up");
subrata_modak56207ce2009-03-23 13:35:39 +0000576 if (WEXITSTATUS(ret) != 0) {
Zhouping Liued241672013-01-22 10:00:42 +0800577 ret = system("ifconfig lo up 127.0.0.1");
578 if (WEXITSTATUS(ret) != 0) {
579 tst_brkm(TBROK, cleanup,
580 "ip/ifconfig failed to bring up loop back device");
Zhouping Liued241672013-01-22 10:00:42 +0800581 }
iyermanoj78562692003-05-01 20:50:38 +0000582 }
583
plars865695b2001-08-27 22:15:12 +0000584 pid = start_server(&sin1, &sun1);
585
robbiewc9c0b4e2003-04-16 20:47:48 +0000586 signal(SIGPIPE, SIG_IGN);
plars865695b2001-08-27 22:15:12 +0000587}
588
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200589static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000590{
subrata_modak56207ce2009-03-23 13:35:39 +0000591 if (pid > 0)
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200592 kill(pid, SIGKILL); /* kill server, if server exists */
plars865695b2001-08-27 22:15:12 +0000593 unlink(tmpsunpath);
subrata_modak56207ce2009-03-23 13:35:39 +0000594 tst_rmdir();
plars865695b2001-08-27 22:15:12 +0000595}
596
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200597static void setup0(void)
plars865695b2001-08-27 22:15:12 +0000598{
599 if (tdat[testno].experrno == EBADF)
600 s = 400; /* anything not an open file */
subrata_modak56207ce2009-03-23 13:35:39 +0000601 else if ((s = open("/dev/null", O_WRONLY)) == -1)
plars13cbed72002-03-26 20:43:10 +0000602 tst_brkm(TBROK, cleanup, "error opening /dev/null - "
subrata_modak56207ce2009-03-23 13:35:39 +0000603 "errno: %s", strerror(errno));
plars865695b2001-08-27 22:15:12 +0000604}
605
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200606static void cleanup0(void)
plars865695b2001-08-27 22:15:12 +0000607{
608 s = -1;
609}
610
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200611static void setup1(void)
plars865695b2001-08-27 22:15:12 +0000612{
613 s = socket(tdat[testno].domain, tdat[testno].type, tdat[testno].proto);
614 if (s < 0) {
615 tst_brkm(TBROK, cleanup, "socket setup failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000616 strerror(errno));
plars865695b2001-08-27 22:15:12 +0000617 }
618 if (tdat[testno].type == SOCK_STREAM &&
619 connect(s, (struct sockaddr *)tdat[testno].to,
subrata_modak56207ce2009-03-23 13:35:39 +0000620 tdat[testno].tolen) < 0) {
plars865695b2001-08-27 22:15:12 +0000621 tst_brkm(TBROK, cleanup, "connect failed: %s", strerror(errno));
622 }
623}
624
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200625static void cleanup1(void)
plars865695b2001-08-27 22:15:12 +0000626{
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200627 close(s);
plars865695b2001-08-27 22:15:12 +0000628 s = -1;
629}
630
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200631static void setup2(void)
plars865695b2001-08-27 22:15:12 +0000632{
subrata_modak56207ce2009-03-23 13:35:39 +0000633 setup1(); /* get a socket in s */
plars865695b2001-08-27 22:15:12 +0000634 if (shutdown(s, 1) < 0) {
635 tst_brkm(TBROK, cleanup, "socket setup failed connect "
subrata_modak56207ce2009-03-23 13:35:39 +0000636 "test %d: %s", testno, strerror(errno));
plars865695b2001-08-27 22:15:12 +0000637 }
638}
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200639
640static void setup3(void)
plars865695b2001-08-27 22:15:12 +0000641{
642 s = socket(tdat[testno].domain, tdat[testno].type, tdat[testno].proto);
643 if (s < 0) {
644 tst_brkm(TBROK, cleanup, "socket setup failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000645 strerror(errno));
plars865695b2001-08-27 22:15:12 +0000646 }
647}
648
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200649static char tmpfilename[1024];
650static int tfd;
plars865695b2001-08-27 22:15:12 +0000651
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200652static void setup4(void)
plars865695b2001-08-27 22:15:12 +0000653{
plars865695b2001-08-27 22:15:12 +0000654
subrata_modak56207ce2009-03-23 13:35:39 +0000655 setup1(); /* get a socket in s */
plars865695b2001-08-27 22:15:12 +0000656
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200657 strcpy(tmpfilename, "sockXXXXXX");
robbiewc9c0b4e2003-04-16 20:47:48 +0000658 tfd = mkstemp(tmpfilename);
plars865695b2001-08-27 22:15:12 +0000659 if (tfd < 0) {
660 tst_brkm(TBROK, cleanup4, "socket setup failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000661 strerror(errno));
plars865695b2001-08-27 22:15:12 +0000662 }
663 control = (struct cmsghdr *)cbuf;
vapier32cc0ac2006-06-22 04:28:32 +0000664 memset(cbuf, 0x00, sizeof(cbuf));
subrata_modak56207ce2009-03-23 13:35:39 +0000665 control->cmsg_len = sizeof(struct cmsghdr) + 4;
plars865695b2001-08-27 22:15:12 +0000666 control->cmsg_level = SOL_SOCKET;
667 control->cmsg_type = SCM_RIGHTS;
668 *(int *)CMSG_DATA(control) = tfd;
669 controllen = control->cmsg_len;
670}
671
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200672static void cleanup4(void)
plars865695b2001-08-27 22:15:12 +0000673{
674 cleanup1();
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200675 close(tfd);
plars865695b2001-08-27 22:15:12 +0000676 tfd = -1;
plars865695b2001-08-27 22:15:12 +0000677 control = 0;
678 controllen = 0;
679}
680
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200681static void setup5(void)
plars865695b2001-08-27 22:15:12 +0000682{
683 s = socket(tdat[testno].domain, tdat[testno].type, tdat[testno].proto);
684 if (s < 0) {
685 tst_brkm(TBROK, cleanup, "socket setup failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000686 strerror(errno));
plars865695b2001-08-27 22:15:12 +0000687 }
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200688
689 if (connect(s, (struct sockaddr *)&sin1, sizeof(sin1)) < 0)
plars865695b2001-08-27 22:15:12 +0000690 tst_brkm(TBROK, cleanup, "connect failed: %s", strerror(errno));
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200691
plars865695b2001-08-27 22:15:12 +0000692 /* slight change destination (port) so connect() is to different
693 * 5-tuple than already connected
694 */
695 sin2 = sin1;
Jan Stancek6e4e77a2014-03-07 11:39:56 +0100696 sin2.sin_port = tst_get_unused_port(cleanup, AF_INET, SOCK_STREAM);
plars865695b2001-08-27 22:15:12 +0000697}
698
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200699static void setup6(void)
plars865695b2001-08-27 22:15:12 +0000700{
701 setup4();
plars805e2852002-03-26 20:41:42 +0000702/*
plars865695b2001-08-27 22:15:12 +0000703 controllen = control->cmsg_len = sizeof(struct cmsghdr) - 4;
plars805e2852002-03-26 20:41:42 +0000704*/
705 controllen = control->cmsg_len = 0;
plars865695b2001-08-27 22:15:12 +0000706}
707
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200708static void setup8(void)
plars865695b2001-08-27 22:15:12 +0000709{
710 setup4();
711 control = (struct cmsghdr *)-1;
Cyril Hrubisa87dd2a2012-10-10 14:54:13 +0200712}