1 /*
2 * test_mkfds - make various file descriptors
3 *
4 * Written by Masatake YAMATO <yamato@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <arpa/inet.h>
21 #include <ctype.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <getopt.h>
26 #include <linux/if_ether.h>
27 #include <linux/if_packet.h>
28 #include <linux/netlink.h>
29 #include <linux/sockios.h> /* SIOCGSKNS */
30 #include <net/if.h>
31 #include <netinet/in.h>
32 #include <netinet/tcp.h>
33 #include <sched.h>
34 #include <signal.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/inotify.h>
40 #include <sys/ioctl.h>
41 #include <sys/mman.h>
42 #include <sys/prctl.h>
43 #include <sys/select.h>
44 #include <sys/socket.h>
45 #include <sys/syscall.h>
46 #include <sys/types.h>
47 #include <sys/un.h>
48 #include <sys/user.h>
49 #include <unistd.h>
50
51 #include "c.h"
52 #include "xalloc.h"
53
54 #define EXIT_ENOSYS 17
55 #define EXIT_EPERM 18
56 #define EXIT_ENOPROTOOPT 19
57 #define EXIT_EPROTONOSUPPORT 20
58 #define EXIT_EACCESS 21
59
60 #define _U_ __attribute__((__unused__))
61
62 static int pidfd_open(pid_t pid, unsigned int flags);
63
64 static void __attribute__((__noreturn__)) usage(FILE *out, int status)
65 {
66 fputs("\nUsage:\n", out);
67 fprintf(out, " %s [options] FACTORY FD... [PARAM=VAL...]\n", program_invocation_short_name);
68
69 fputs("\nOptions:\n", out);
70 fputs(" -l, --list list available file descriptor factories and exit\n", out);
71 fputs(" -I, --parameters <factory> list parameters the factory takes\n", out);
72 fputs(" -r, --comm <name> rename self\n", out);
73 fputs(" -q, --quiet don't print pid(s)\n", out);
74 fputs(" -c, --dont-pause don't pause after making fd(s)\n", out);
75
76 fputs("\n", out);
77 fputs("Examples:\n", out);
78 fprintf(out, "Using 3, open /etc/group:\n\n $ %s ro-regular-file 3 file=/etc/group\n\n",
79 program_invocation_short_name);
80 fprintf(out, "Using 3 and 4, make a pipe:\n\n $ %s pipe-no-fork 3 4\n\n",
81 program_invocation_short_name);
82
83 exit(status);
84 }
85
86 union value {
87 const char *string;
88 long integer;
89 unsigned long uinteger;
90 bool boolean;
91 };
92
93 enum ptype {
94 PTYPE_STRING,
95 PTYPE_INTEGER,
96 PTYPE_UINTEGER,
97 PTYPE_BOOLEAN,
98 };
99
100 struct ptype_class {
101 const char *name;
102
103 /* Covert to a string representation.
104 * A caller must free the returned value with free(3) after using. */
105 char *(*sprint)(const union value *value);
106
107 /* Convert from a string. If ARG is NULL, use DEFV instead.
108 * A caller must free the returned value with the free method
109 * after using. */
110 union value (*read)(const char *arg, const union value *defv);
111
112 /* Free the value returned from the read method. */
113 void (*free)(union value value);
114 };
115
116 #define ARG_STRING(A) (A.v.string)
117 #define ARG_INTEGER(A) (A.v.integer)
118 #define ARG_UINTEGER(A) (A.v.uinteger)
119 #define ARG_BOOLEAN(A) (A.v.boolean)
120 struct arg {
121 union value v;
122 void (*free)(union value value);
123 };
124
125 struct parameter {
126 const char *name;
127 const enum ptype type;
128 const char *desc;
129 union value defv; /* Default value */
130 };
131
132 static char *string_sprint(const union value *value)
133 {
134 return xstrdup(value->string);
135 }
136
137 static union value string_read(const char *arg, const union value *defv)
138 {
139 return (union value){ .string = xstrdup(arg?: defv->string) };
140 }
141
142 static void string_free(union value value)
143 {
144 free((void *)value.string);
145 }
146
147 static char *integer_sprint(const union value *value)
148 {
149 char *str = NULL;
150 xasprintf(&str, "%ld", value->integer);
151 return str;
152 }
153
154 static union value integer_read(const char *arg, const union value *defv)
155 {
156 char *ep;
157 union value r;
158
159 if (!arg)
160 return *defv;
161
162 errno = 0;
163 r.integer = strtol(arg, &ep, 10);
164 if (errno)
165 err(EXIT_FAILURE, "fail to make a number from %s", arg);
166 else if (*ep != '\0')
167 errx(EXIT_FAILURE, "garbage at the end of number: %s", arg);
168 return r;
169 }
170
171 static void integer_free(union value value _U_)
172 {
173 /* Do nothing */
174 }
175
176 static char *uinteger_sprint(const union value *value)
177 {
178 char *str = NULL;
179 xasprintf(&str, "%lu", value->uinteger);
180 return str;
181 }
182
183 static union value uinteger_read(const char *arg, const union value *defv)
184 {
185 char *ep;
186 union value r;
187
188 if (!arg)
189 return *defv;
190
191 errno = 0;
192 r.uinteger = strtoul(arg, &ep, 10);
193 if (errno)
194 err(EXIT_FAILURE, "fail to make a number from %s", arg);
195 else if (*ep != '\0')
196 errx(EXIT_FAILURE, "garbage at the end of number: %s", arg);
197 return r;
198 }
199
200 static void uinteger_free(union value value _U_)
201 {
202 /* Do nothing */
203 }
204
205 static char *boolean_sprint(const union value *value)
206 {
207 return xstrdup(value->boolean? "true": "false");
208 }
209
210 static union value boolean_read(const char *arg, const union value *defv)
211 {
212 union value r;
213
214 if (!arg)
215 return *defv;
216
217 if (strcasecmp(arg, "true") == 0
218 || strcmp(arg, "1") == 0
219 || strcasecmp(arg, "yes") == 0
220 || strcasecmp(arg, "y") == 0)
221 r.boolean = true;
222 else
223 r.boolean = false;
224 return r;
225 }
226
227 static void boolean_free(union value value _U_)
228 {
229 /* Do nothing */
230 }
231
232 struct ptype_class ptype_classes [] = {
233 [PTYPE_STRING] = {
234 .name = "string",
235 .sprint = string_sprint,
236 .read = string_read,
237 .free = string_free,
238 },
239 [PTYPE_INTEGER] = {
240 .name = "integer",
241 .sprint = integer_sprint,
242 .read = integer_read,
243 .free = integer_free,
244 },
245 [PTYPE_UINTEGER] = {
246 .name = "uinteger",
247 .sprint = uinteger_sprint,
248 .read = uinteger_read,
249 .free = uinteger_free,
250 },
251 [PTYPE_BOOLEAN] = {
252 .name = "boolean",
253 .sprint = boolean_sprint,
254 .read = boolean_read,
255 .free = boolean_free,
256 },
257 };
258
259 static struct arg decode_arg(const char *pname,
260 const struct parameter *parameters,
261 int argc, char **argv)
262 {
263 char *v = NULL;
264 size_t len = strlen(pname);
265 const struct parameter *p = NULL;
266 struct arg arg;
267
268 while (parameters->name) {
269 if (strcmp(pname, parameters->name) == 0) {
270 p = parameters;
271 break;
272 }
273 parameters++;
274 }
275 if (p == NULL)
276 errx(EXIT_FAILURE, "no such parameter: %s", pname);
277
278 for (int i = 0; i < argc; i++) {
279 if (strncmp(pname, argv[i], len) == 0) {
280 v = argv[i] + len;
281 if (*v == '=') {
282 v++;
283 break;
284 } else if (*v == '\0')
285 errx(EXIT_FAILURE,
286 "no value given for \"%s\" parameter",
287 pname);
288 else
289 v = NULL;
290 }
291 }
292 arg.v = ptype_classes [p->type].read (v, &p->defv);
293 arg.free = ptype_classes [p->type].free;
294 return arg;
295 }
296
297 static void free_arg(struct arg *arg)
298 {
299 arg->free(arg->v);
300 }
301
302 struct fdesc {
303 int fd;
304 void (*close)(int, void *);
305 void *data;
306 };
307
308 struct factory {
309 const char *name; /* [-a-zA-Z0-9_]+ */
310 const char *desc;
311 bool priv; /* the root privilege is needed to make fd(s) */
312 #define MAX_N 5
313 int N; /* the number of fds this factory makes */
314 int EX_N; /* fds made optionally */
315 void *(*make)(const struct factory *, struct fdesc[], int, char **);
316 void (*free)(const struct factory *, void *);
317 void (*report)(const struct factory *, void *, FILE *);
318 const struct parameter * params;
319 };
320
321 static void close_fdesc(int fd, void *data _U_)
322 {
323 close(fd);
324 }
325
326 static void *open_ro_regular_file(const struct factory *factory, struct fdesc fdescs[],
327 int argc, char ** argv)
328 {
329 struct arg file = decode_arg("file", factory->params, argc, argv);
330 struct arg offset = decode_arg("offset", factory->params, argc, argv);
331
332 int fd = open(ARG_STRING(file), O_RDONLY);
333 if (fd < 0)
334 err(EXIT_FAILURE, "failed to open: %s", ARG_STRING(file));
335 free_arg(&file);
336
337 if (ARG_INTEGER(offset) != 0) {
338 if (lseek(fd, (off_t)ARG_INTEGER(offset), SEEK_CUR) < 0) {
339 int e = errno;
340 close(fd);
341 errno = e;
342 err(EXIT_FAILURE, "failed to seek 0 -> %ld", ARG_INTEGER(offset));
343 }
344 }
345 free_arg(&offset);
346
347 if (fd != fdescs[0].fd) {
348 if (dup2(fd, fdescs[0].fd) < 0) {
349 int e = errno;
350 close(fd);
351 errno = e;
352 err(EXIT_FAILURE, "failed to dup %d -> %d", fd, fdescs[0].fd);
353 }
354 close(fd);
355 }
356
357 fdescs[0] = (struct fdesc){
358 .fd = fdescs[0].fd,
359 .close = close_fdesc,
360 .data = NULL
361 };
362
363 return NULL;
364 }
365
366 static void *make_pipe(const struct factory *factory, struct fdesc fdescs[],
367 int argc, char ** argv)
368 {
369 int pd[2];
370 int nonblock_flags[2] = {0, 0};
371 struct arg nonblock = decode_arg("nonblock", factory->params, argc, argv);
372 if (strlen(ARG_STRING(nonblock)) != 2) {
373 errx(EXIT_FAILURE, "string value for %s has unexpected length: %s",
374 "nonblock", ARG_STRING(nonblock));
375 }
376
377 /* Make extra pipe descriptors for making pipe objects connected
378 * with fds more than 2.
379 * See https://github.com/util-linux/util-linux/pull/1622
380 * about the background of the requirement. */
381 struct arg rdup = decode_arg("rdup", factory->params, argc, argv);
382 struct arg wdup = decode_arg("wdup", factory->params, argc, argv);
383 int xpd[2];
384 xpd [0] = ARG_INTEGER(rdup);
385 xpd [1] = ARG_INTEGER(wdup);
386
387 for (int i = 0; i < 2; i++) {
388 if (ARG_STRING(nonblock)[i] == '-')
389 continue;
390 if ((i == 0 && ARG_STRING(nonblock)[i] == 'r')
391 || (i == 1 && ARG_STRING(nonblock)[i] == 'w'))
392 nonblock_flags[i] = 1;
393 else
394 errx(EXIT_FAILURE, "unexpected value %c for the %s fd of %s",
395 ARG_STRING(nonblock)[i],
396 (i == 0)? "read": "write",
397 "nonblock");
398 }
399 free_arg(&nonblock);
400
401 if (pipe(pd) < 0)
402 err(EXIT_FAILURE, "failed to make pipe");
403
404 for (int i = 0; i < 2; i++) {
405 if (nonblock_flags[i]) {
406 int flags = fcntl(pd[i], F_GETFL);
407 if (fcntl(pd[i], F_SETFL, flags|O_NONBLOCK) < 0) {
408 int e = errno;
409 close(pd[0]);
410 close(pd[1]);
411 errno = e;
412 errx(EXIT_FAILURE, "failed to set NONBLOCK flag to the %s fd",
413 (i == 0)? "read": "write");
414 }
415 }
416 }
417
418 for (int i = 0; i < 2; i++) {
419 if (pd[i] != fdescs[i].fd) {
420 if (dup2(pd[i], fdescs[i].fd) < 0) {
421 int e = errno;
422 close(pd[0]);
423 close(pd[1]);
424 errno = e;
425 err(EXIT_FAILURE, "failed to dup %d -> %d",
426 pd[i], fdescs[i].fd);
427 }
428 close(pd[i]);
429 }
430 fdescs[i] = (struct fdesc){
431 .fd = fdescs[i].fd,
432 .close = close_fdesc,
433 .data = NULL
434 };
435 }
436
437 /* Make extra pipe descriptors. */
438 for (int i = 0; i < 2; i++) {
439 if (xpd[i] >= 0) {
440 if (dup2(fdescs[i].fd, xpd[i]) < 0) {
441 int e = errno;
442 close(fdescs[0].fd);
443 close(fdescs[1].fd);
444 if (i > 0 && xpd[0] >= 0)
445 close(xpd[0]);
446 errno = e;
447 err(EXIT_FAILURE, "failed to dup %d -> %d",
448 fdescs[i].fd, xpd[i]);
449 }
450 fdescs[i + 2] = (struct fdesc){
451 .fd = xpd[i],
452 .close = close_fdesc,
453 .data = NULL
454 };
455 }
456 }
457
458 return NULL;
459 }
460
461 static void close_dir(int fd, void *data)
462 {
463 DIR *dp = data;
464 if (dp)
465 closedir(dp);
466 else
467 close_fdesc(fd, NULL);
468 }
469
470 static void *open_directory(const struct factory *factory, struct fdesc fdescs[],
471 int argc, char ** argv)
472 {
473 struct arg dir = decode_arg("dir", factory->params, argc, argv);
474 struct arg dentries = decode_arg("dentries", factory->params, argc, argv);
475 DIR *dp = NULL;
476
477 int fd = open(ARG_STRING(dir), O_RDONLY|O_DIRECTORY);
478 if (fd < 0)
479 err(EXIT_FAILURE, "failed to open: %s", ARG_STRING(dir));
480 free_arg(&dir);
481
482 if (fd != fdescs[0].fd) {
483 if (dup2(fd, fdescs[0].fd) < 0) {
484 int e = errno;
485 close(fd);
486 errno = e;
487 err(EXIT_FAILURE, "failed to dup %d -> %d", fd, fdescs[0].fd);
488 }
489 close(fd);
490 }
491
492 if (ARG_INTEGER(dentries) > 0) {
493 dp = fdopendir(fdescs[0].fd);
494 if (dp == NULL) {
495 int e = errno;
496 close(fdescs[0].fd);
497 errno = e;
498 err(EXIT_FAILURE, "failed to make DIR* from fd: %s", ARG_STRING(dir));
499 }
500 for (int i = 0; i < ARG_INTEGER(dentries); i++) {
501 struct dirent *d = readdir(dp);
502 if (!d) {
503 int e = errno;
504 closedir(dp);
505 errno = e;
506 err(EXIT_FAILURE, "failed in readdir(3)");
507 }
508 }
509 }
510 free_arg(&dentries);
511
512 fdescs[0] = (struct fdesc){
513 .fd = fdescs[0].fd,
514 .close = close_dir,
515 .data = dp
516 };
517
518 return NULL;
519 }
520
521 static void *open_rw_chrdev(const struct factory *factory, struct fdesc fdescs[],
522 int argc, char ** argv)
523 {
524 struct arg chrdev = decode_arg("chrdev", factory->params, argc, argv);
525 int fd = open(ARG_STRING(chrdev), O_RDWR);
526 if (fd < 0)
527 err(EXIT_FAILURE, "failed to open: %s", ARG_STRING(chrdev));
528 free_arg(&chrdev);
529
530 if (fd != fdescs[0].fd) {
531 if (dup2(fd, fdescs[0].fd) < 0) {
532 int e = errno;
533 close(fd);
534 errno = e;
535 err(EXIT_FAILURE, "failed to dup %d -> %d", fd, fdescs[0].fd);
536 }
537 close(fd);
538 }
539
540 fdescs[0] = (struct fdesc){
541 .fd = fdescs[0].fd,
542 .close = close_fdesc,
543 .data = NULL
544 };
545
546 return NULL;
547 }
548
549 static void *make_socketpair(const struct factory *factory, struct fdesc fdescs[],
550 int argc, char ** argv)
551 {
552 int sd[2];
553 struct arg socktype = decode_arg("socktype", factory->params, argc, argv);
554 int isocktype;
555 if (strcmp(ARG_STRING(socktype), "STREAM") == 0)
556 isocktype = SOCK_STREAM;
557 else if (strcmp(ARG_STRING(socktype), "DGRAM") == 0)
558 isocktype = SOCK_DGRAM;
559 else if (strcmp(ARG_STRING(socktype), "SEQPACKET") == 0)
560 isocktype = SOCK_SEQPACKET;
561 else
562 errx(EXIT_FAILURE,
563 "unknown socket type for socketpair(AF_UNIX,...): %s",
564 ARG_STRING(socktype));
565 free_arg(&socktype);
566
567 if (socketpair(AF_UNIX, isocktype, 0, sd) < 0)
568 err(EXIT_FAILURE, "failed to make socket pair");
569
570 for (int i = 0; i < 2; i++) {
571 if (sd[i] != fdescs[i].fd) {
572 if (dup2(sd[i], fdescs[i].fd) < 0) {
573 int e = errno;
574 close(sd[0]);
575 close(sd[1]);
576 errno = e;
577 err(EXIT_FAILURE, "failed to dup %d -> %d",
578 sd[i], fdescs[i].fd);
579 }
580 close(sd[i]);
581 }
582 fdescs[i] = (struct fdesc){
583 .fd = fdescs[i].fd,
584 .close = close_fdesc,
585 .data = NULL
586 };
587 }
588
589 return NULL;
590 }
591
592 static void *open_with_opath(const struct factory *factory, struct fdesc fdescs[],
593 int argc, char ** argv)
594 {
595 struct arg path = decode_arg("path", factory->params, argc, argv);
596 int fd = open(ARG_STRING(path), O_PATH|O_NOFOLLOW);
597 if (fd < 0)
598 err(EXIT_FAILURE, "failed to open with O_PATH: %s", ARG_STRING(path));
599 free_arg(&path);
600
601 if (fd != fdescs[0].fd) {
602 if (dup2(fd, fdescs[0].fd) < 0) {
603 int e = errno;
604 close(fd);
605 errno = e;
606 err(EXIT_FAILURE, "failed to dup %d -> %d", fd, fdescs[0].fd);
607 }
608 close(fd);
609 }
610
611 fdescs[0] = (struct fdesc){
612 .fd = fdescs[0].fd,
613 .close = close_fdesc,
614 .data = NULL
615 };
616
617 return NULL;
618 }
619
620 static void *open_ro_blkdev(const struct factory *factory, struct fdesc fdescs[],
621 int argc, char ** argv)
622 {
623 struct arg blkdev = decode_arg("blkdev", factory->params, argc, argv);
624 int fd = open(ARG_STRING(blkdev), O_RDONLY);
625 if (fd < 0)
626 err(EXIT_FAILURE, "failed to open: %s", ARG_STRING(blkdev));
627 free_arg(&blkdev);
628
629 if (fd != fdescs[0].fd) {
630 if (dup2(fd, fdescs[0].fd) < 0) {
631 int e = errno;
632 close(fd);
633 errno = e;
634 err(EXIT_FAILURE, "failed to dup %d -> %d", fd, fdescs[0].fd);
635 }
636 close(fd);
637 }
638
639 fdescs[0] = (struct fdesc){
640 .fd = fdescs[0].fd,
641 .close = close_fdesc,
642 .data = NULL,
643 };
644
645 return NULL;
646 }
647
648 static int make_packet_socket(int socktype, const char *interface)
649 {
650 int sd;
651 struct sockaddr_ll addr;
652
653 sd = socket(AF_PACKET, socktype, htons(ETH_P_ALL));
654 if (sd < 0)
655 err(EXIT_FAILURE, "failed to make a socket with AF_PACKET");
656
657 if (interface == NULL)
658 return sd; /* Just making a socket */
659
660 memset(&addr, 0, sizeof(struct sockaddr_ll));
661 addr.sll_family = AF_PACKET;
662 addr.sll_ifindex = if_nametoindex(interface);
663 if (addr.sll_ifindex == 0) {
664 int e = errno;
665 close(sd);
666 errno = e;
667 err(EXIT_FAILURE,
668 "failed to get the interface index for %s", interface);
669 }
670 if (bind(sd, (struct sockaddr *)&addr, sizeof(struct sockaddr_ll)) < 0) {
671 int e = errno;
672 close(sd);
673 errno = e;
674 err(EXIT_FAILURE,
675 "failed to get the interface index for %s", interface);
676 }
677
678 return sd;
679 }
680
681 struct munmap_data {
682 void *ptr;
683 size_t len;
684 };
685
686 static void close_fdesc_after_munmap(int fd, void *data)
687 {
688 struct munmap_data *munmap_data = data;
689 munmap(munmap_data->ptr, munmap_data->len);
690 free(data);
691 close(fd);
692 }
693
694 static void *make_mmapped_packet_socket(const struct factory *factory, struct fdesc fdescs[],
695 int argc, char ** argv)
696 {
697 int sd;
698 struct arg socktype = decode_arg("socktype", factory->params, argc, argv);
699 struct arg interface = decode_arg("interface", factory->params, argc, argv);
700
701 int isocktype;
702 const char *sinterface;
703 struct tpacket_req req;
704 struct munmap_data *munmap_data;
705
706 if (strcmp(ARG_STRING(socktype), "DGRAM") == 0)
707 isocktype = SOCK_DGRAM;
708 else if (strcmp(ARG_STRING(socktype), "RAW") == 0)
709 isocktype = SOCK_RAW;
710 else
711 errx(EXIT_FAILURE,
712 "unknown socket type for socket(AF_PACKET,...): %s",
713 ARG_STRING(socktype));
714 free_arg(&socktype);
715
716 sinterface = ARG_STRING(interface);
717 sd = make_packet_socket(isocktype, sinterface);
718 free_arg(&interface);
719
720 /* Specify the spec of ring buffers.
721 *
722 * ref.
723 * - linux/Documentation/networking/packet_mmap.rst
724 * - https://sites.google.com/site/packetmmap/home
725 */
726 req.tp_block_size = getpagesize();
727 req.tp_frame_size = getpagesize();
728 req.tp_block_nr = 1;
729 req.tp_frame_nr = 1;
730 if (setsockopt(sd, SOL_PACKET, PACKET_TX_RING, (char *)&req, sizeof(req)) < 0) {
731 int e = errno;
732 close(sd);
733 errno = e;
734 err((errno == ENOPROTOOPT? EXIT_ENOPROTOOPT: EXIT_FAILURE),
735 "failed to specify a buffer spec to a packet socket");
736 }
737
738 munmap_data = xmalloc(sizeof (*munmap_data));
739 munmap_data->len = (size_t) req.tp_block_size * req.tp_block_nr;
740 munmap_data->ptr = mmap(NULL, munmap_data->len, PROT_WRITE, MAP_SHARED, sd, 0);
741 if (munmap_data->ptr == MAP_FAILED) {
742 int e = errno;
743 close(sd);
744 free(munmap_data);
745 errno = e;
746 err(EXIT_FAILURE, "failed to do mmap a packet socket");
747 }
748
749 if (sd != fdescs[0].fd) {
750 if (dup2(sd, fdescs[0].fd) < 0) {
751 int e = errno;
752 close(sd);
753 munmap(munmap_data->ptr, munmap_data->len);
754 free(munmap_data);
755 errno = e;
756 err(EXIT_FAILURE, "failed to dup %d -> %d", sd, fdescs[0].fd);
757 }
758 close(sd);
759 }
760
761 fdescs[0] = (struct fdesc){
762 .fd = fdescs[0].fd,
763 .close = close_fdesc_after_munmap,
764 .data = munmap_data,
765 };
766
767 return NULL;
768 }
769
770 static void *make_pidfd(const struct factory *factory, struct fdesc fdescs[],
771 int argc, char ** argv)
772 {
773 struct arg target_pid = decode_arg("target-pid", factory->params, argc, argv);
774 pid_t pid = ARG_INTEGER(target_pid);
775
776 int fd = pidfd_open(pid, 0);
777 if (fd < 0)
778 err((errno == ENOSYS? EXIT_ENOSYS: EXIT_FAILURE),
779 "failed in pidfd_open(%d)", (int)pid);
780 free_arg(&target_pid);
781
782 if (fd != fdescs[0].fd) {
783 if (dup2(fd, fdescs[0].fd) < 0) {
784 int e = errno;
785 close(fd);
786 errno = e;
787 err(EXIT_FAILURE, "failed to dup %d -> %d", fd, fdescs[0].fd);
788 }
789 close(fd);
790 }
791
792 fdescs[0] = (struct fdesc){
793 .fd = fdescs[0].fd,
794 .close = close_fdesc,
795 .data = NULL
796 };
797
798 return NULL;
799 }
800
801 static void *make_inotify_fd(const struct factory *factory _U_, struct fdesc fdescs[],
802 int argc _U_, char ** argv _U_)
803 {
804 int fd = inotify_init();
805 if (fd < 0)
806 err(EXIT_FAILURE, "failed in inotify_init()");
807
808 if (fd != fdescs[0].fd) {
809 if (dup2(fd, fdescs[0].fd) < 0) {
810 int e = errno;
811 close(fd);
812 errno = e;
813 err(EXIT_FAILURE, "failed to dup %d -> %d", fd, fdescs[0].fd);
814 }
815 close(fd);
816 }
817
818 fdescs[0] = (struct fdesc){
819 .fd = fdescs[0].fd,
820 .close = close_fdesc,
821 .data = NULL
822 };
823
824 return NULL;
825 }
826
827 static void close_unix_socket(int fd, void *data)
828 {
829 char *path = data;
830 close(fd);
831 if (path) {
832 unlink(path);
833 free(path);
834 }
835 }
836
837 static void *make_unix_stream_core(const struct factory *factory, struct fdesc fdescs[],
838 int argc, char ** argv, int type, const char *typestr)
839 {
840 struct arg path = decode_arg("path", factory->params, argc, argv);
841 const char *spath = ARG_STRING(path);
842
843 struct arg backlog = decode_arg("backlog", factory->params, argc, argv);
844 int ibacklog = ARG_INTEGER(path);
845
846 struct arg abstract = decode_arg("abstract", factory->params, argc, argv);
847 bool babstract = ARG_BOOLEAN(abstract);
848
849 struct arg server_shutdown = decode_arg("server-shutdown", factory->params, argc, argv);
850 int iserver_shutdown = ARG_INTEGER(server_shutdown);
851 struct arg client_shutdown = decode_arg("client-shutdown", factory->params, argc, argv);
852 int iclient_shutdown = ARG_INTEGER(client_shutdown);
853
854 int ssd, csd, asd; /* server, client, and accepted socket descriptors */
855 struct sockaddr_un un;
856 size_t un_len = sizeof(un);
857
858 memset(&un, 0, sizeof(un));
859 un.sun_family = AF_UNIX;
860 if (babstract) {
861 strncpy(un.sun_path + 1, spath, sizeof(un.sun_path) - 1 - 1);
862 size_t pathlen = strlen(spath);
863 if (sizeof(un.sun_path) - 1 > pathlen)
864 un_len = sizeof(un) - sizeof(un.sun_path) + 1 + pathlen;
865 } else
866 strncpy(un.sun_path, spath, sizeof(un.sun_path) - 1 );
867
868 free_arg(&client_shutdown);
869 free_arg(&server_shutdown);
870 free_arg(&abstract);
871 free_arg(&backlog);
872 free_arg(&path);
873
874 if (iserver_shutdown < 0 || iserver_shutdown > 3)
875 errx(EXIT_FAILURE, "the server shudown specification in unexpected range");
876 if (iclient_shutdown < 0 || iclient_shutdown > 3)
877 errx(EXIT_FAILURE, "the client shudown specification in unexpected range");
878
879 ssd = socket(AF_UNIX, type, 0);
880 if (ssd < 0)
881 err(EXIT_FAILURE,
882 "failed to make a socket with AF_UNIX + SOCK_%s (server side)", typestr);
883 if (ssd != fdescs[0].fd) {
884 if (dup2(ssd, fdescs[0].fd) < 0) {
885 int e = errno;
886 close(ssd);
887 errno = e;
888 err(EXIT_FAILURE, "failed to dup %d -> %d", ssd, fdescs[0].fd);
889 }
890 close(ssd);
891 ssd = fdescs[0].fd;
892 }
893
894 fdescs[0] = (struct fdesc){
895 .fd = fdescs[0].fd,
896 .close = close_unix_socket,
897 .data = NULL,
898 };
899
900 if (!babstract)
901 unlink(un.sun_path);
902 if (bind(ssd, (const struct sockaddr *)&un, un_len) < 0) {
903 int e = errno;
904 close(ssd);
905 errno = e;
906 err(EXIT_FAILURE, "failed to bind a socket for listening");
907 }
908
909 if (!babstract)
910 fdescs[0].data = xstrdup(un.sun_path);
911 if (listen(ssd, ibacklog) < 0) {
912 int e = errno;
913 close_unix_socket(ssd, fdescs[0].data);
914 errno = e;
915 err(EXIT_FAILURE, "failed to listen a socket");
916 }
917
918 csd = socket(AF_UNIX, type, 0);
919 if (csd < 0)
920 err(EXIT_FAILURE,
921 "failed to make a socket with AF_UNIX + SOCK_%s (client side)", typestr);
922 if (csd != fdescs[1].fd) {
923 if (dup2(csd, fdescs[1].fd) < 0) {
924 int e = errno;
925 close(csd);
926 close_unix_socket(ssd, fdescs[0].data);
927 errno = e;
928 err(EXIT_FAILURE, "failed to dup %d -> %d", csd, fdescs[1].fd);
929 }
930 close(csd);
931 csd = fdescs[1].fd;
932 }
933
934 fdescs[1] = (struct fdesc){
935 .fd = fdescs[1].fd,
936 .close = close_fdesc,
937 .data = NULL,
938 };
939
940 if (connect(csd, (const struct sockaddr *)&un, un_len) < 0) {
941 int e = errno;
942 close_fdesc(csd, NULL);
943 close_unix_socket(ssd, fdescs[0].data);
944 errno = e;
945 err(EXIT_FAILURE, "failed to connect a socket to the listening socket");
946 }
947
948 if (!babstract)
949 unlink(un.sun_path);
950
951 asd = accept(ssd, NULL, NULL);
952 if (asd < 0) {
953 int e = errno;
954 close_fdesc(csd, NULL);
955 close_unix_socket(ssd, fdescs[0].data);
956 errno = e;
957 err(EXIT_FAILURE, "failed to accept a socket from the listening socket");
958 }
959 if (asd != fdescs[2].fd) {
960 if (dup2(asd, fdescs[2].fd) < 0) {
961 int e = errno;
962 close(asd);
963 close_fdesc(csd, NULL);
964 close_unix_socket(ssd, fdescs[0].data);
965 errno = e;
966 err(EXIT_FAILURE, "failed to dup %d -> %d", asd, fdescs[2].fd);
967 }
968 close(asd);
969 asd = fdescs[2].fd;
970 }
971
972 if (iserver_shutdown & (1 << 0))
973 shutdown(asd, SHUT_RD);
974 if (iserver_shutdown & (1 << 1))
975 shutdown(asd, SHUT_WR);
976 if (iclient_shutdown & (1 << 0))
977 shutdown(csd, SHUT_RD);
978 if (iclient_shutdown & (1 << 1))
979 shutdown(csd, SHUT_WR);
980
981 return NULL;
982 }
983
984 static void *make_unix_stream(const struct factory *factory, struct fdesc fdescs[],
985 int argc, char ** argv)
986 {
987 struct arg type = decode_arg("type", factory->params, argc, argv);
988 const char *stype = ARG_STRING(type);
989
990 int typesym;
991 const char *typestr;
992
993 if (strcmp(stype, "stream") == 0) {
994 typesym = SOCK_STREAM;
995 typestr = "STREAM";
996 } else if (strcmp(stype, "seqpacket") == 0) {
997 typesym = SOCK_SEQPACKET;
998 typestr = "SEQPACKET";
999 } else
1000 errx(EXIT_FAILURE, "unknown unix socket type: %s", stype);
1001
1002 free_arg(&type);
1003
1004 return make_unix_stream_core(factory, fdescs, argc, argv, typesym, typestr);
1005 }
1006
1007 static void *make_unix_dgram(const struct factory *factory, struct fdesc fdescs[],
1008 int argc, char ** argv)
1009 {
1010 struct arg path = decode_arg("path", factory->params, argc, argv);
1011 const char *spath = ARG_STRING(path);
1012
1013 struct arg abstract = decode_arg("abstract", factory->params, argc, argv);
1014 bool babstract = ARG_BOOLEAN(abstract);
1015
1016 int ssd, csd; /* server and client socket descriptors */
1017
1018 struct sockaddr_un un;
1019 size_t un_len = sizeof(un);
1020
1021 memset(&un, 0, sizeof(un));
1022 un.sun_family = AF_UNIX;
1023 if (babstract) {
1024 strncpy(un.sun_path + 1, spath, sizeof(un.sun_path) - 1 - 1);
1025 size_t pathlen = strlen(spath);
1026 if (sizeof(un.sun_path) - 1 > pathlen)
1027 un_len = sizeof(un) - sizeof(un.sun_path) + 1 + pathlen;
1028 } else
1029 strncpy(un.sun_path, spath, sizeof(un.sun_path) - 1 );
1030
1031 free_arg(&abstract);
1032 free_arg(&path);
1033
1034 ssd = socket(AF_UNIX, SOCK_DGRAM, 0);
1035 if (ssd < 0)
1036 err(EXIT_FAILURE,
1037 "failed to make a socket with AF_UNIX + SOCK_DGRAM (server side)");
1038 if (ssd != fdescs[0].fd) {
1039 if (dup2(ssd, fdescs[0].fd) < 0) {
1040 int e = errno;
1041 close(ssd);
1042 errno = e;
1043 err(EXIT_FAILURE, "failed to dup %d -> %d", ssd, fdescs[0].fd);
1044 }
1045 close(ssd);
1046 ssd = fdescs[0].fd;
1047 }
1048
1049 fdescs[0] = (struct fdesc){
1050 .fd = fdescs[0].fd,
1051 .close = close_unix_socket,
1052 .data = NULL,
1053 };
1054
1055 if (!babstract)
1056 unlink(un.sun_path);
1057 if (bind(ssd, (const struct sockaddr *)&un, un_len) < 0) {
1058 int e = errno;
1059 close(ssd);
1060 errno = e;
1061 err(EXIT_FAILURE, "failed to bind a socket for server");
1062 }
1063
1064 if (!babstract)
1065 fdescs[0].data = xstrdup(un.sun_path);
1066 csd = socket(AF_UNIX, SOCK_DGRAM, 0);
1067 if (csd < 0)
1068 err(EXIT_FAILURE,
1069 "failed to make a socket with AF_UNIX + SOCK_DGRAM (client side)");
1070 if (csd != fdescs[1].fd) {
1071 if (dup2(csd, fdescs[1].fd) < 0) {
1072 int e = errno;
1073 close(csd);
1074 close_unix_socket(ssd, fdescs[0].data);
1075 errno = e;
1076 err(EXIT_FAILURE, "failed to dup %d -> %d", csd, fdescs[1].fd);
1077 }
1078 close(csd);
1079 csd = fdescs[1].fd;
1080 }
1081
1082 fdescs[1] = (struct fdesc){
1083 .fd = fdescs[1].fd,
1084 .close = close_fdesc,
1085 .data = NULL,
1086 };
1087
1088 if (connect(csd, (const struct sockaddr *)&un, un_len) < 0) {
1089 int e = errno;
1090 close_fdesc(csd, NULL);
1091 close_unix_socket(ssd, fdescs[0].data);
1092 errno = e;
1093 err(EXIT_FAILURE, "failed to connect a socket to the server socket");
1094 }
1095
1096 if (!babstract)
1097 unlink(un.sun_path);
1098
1099 return NULL;
1100 }
1101
1102 static void *make_unix_in_new_netns(const struct factory *factory, struct fdesc fdescs[],
1103 int argc, char ** argv)
1104 {
1105 struct arg type = decode_arg("type", factory->params, argc, argv);
1106 const char *stype = ARG_STRING(type);
1107
1108 struct arg path = decode_arg("path", factory->params, argc, argv);
1109 const char *spath = ARG_STRING(path);
1110
1111 struct arg abstract = decode_arg("abstract", factory->params, argc, argv);
1112 bool babstract = ARG_BOOLEAN(abstract);
1113
1114 int typesym;
1115 const char *typestr;
1116
1117 struct sockaddr_un un;
1118 size_t un_len = sizeof(un);
1119
1120 int self_netns, tmp_netns, sd;
1121
1122 if (strcmp(stype, "stream") == 0) {
1123 typesym = SOCK_STREAM;
1124 typestr = "STREAM";
1125 } else if (strcmp(stype, "seqpacket") == 0) {
1126 typesym = SOCK_SEQPACKET;
1127 typestr = "SEQPACKET";
1128 } else if (strcmp(stype, "dgram") == 0) {
1129 typesym = SOCK_DGRAM;
1130 typestr = "DGRAM";
1131 } else {
1132 free_arg(&abstract);
1133 free_arg(&path);
1134 free_arg(&type);
1135 errx(EXIT_FAILURE, "unknown unix socket type: %s", stype);
1136 }
1137
1138 memset(&un, 0, sizeof(un));
1139 un.sun_family = AF_UNIX;
1140 if (babstract) {
1141 strncpy(un.sun_path + 1, spath, sizeof(un.sun_path) - 1 - 1);
1142 size_t pathlen = strlen(spath);
1143 if (sizeof(un.sun_path) - 1 > pathlen)
1144 un_len = sizeof(un) - sizeof(un.sun_path) + 1 + pathlen;
1145 } else
1146 strncpy(un.sun_path, spath, sizeof(un.sun_path) - 1 );
1147
1148 free_arg(&abstract);
1149 free_arg(&path);
1150 free_arg(&type);
1151
1152 self_netns = open("/proc/self/ns/net", O_RDONLY);
1153 if (self_netns < 0)
1154 err(EXIT_FAILURE, "failed to open /proc/self/ns/net");
1155 if (self_netns != fdescs[0].fd) {
1156 if (dup2(self_netns, fdescs[0].fd) < 0) {
1157 int e = errno;
1158 close(self_netns);
1159 errno = e;
1160 err(EXIT_FAILURE, "failed to dup %d -> %d", self_netns, fdescs[0].fd);
1161 }
1162 close(self_netns);
1163 self_netns = fdescs[0].fd;
1164 }
1165
1166 fdescs[0] = (struct fdesc){
1167 .fd = fdescs[0].fd,
1168 .close = close_fdesc,
1169 .data = NULL,
1170 };
1171
1172 if (unshare(CLONE_NEWNET) < 0) {
1173 int e = errno;
1174 close_fdesc(self_netns, NULL);
1175 errno = e;
1176 err((errno == EPERM? EXIT_EPERM: EXIT_FAILURE),
1177 "failed in unshare");
1178 }
1179
1180 tmp_netns = open("/proc/self/ns/net", O_RDONLY);
1181 if (tmp_netns < 0) {
1182 int e = errno;
1183 close_fdesc(self_netns, NULL);
1184 errno = e;
1185 err(EXIT_FAILURE, "failed to open /proc/self/ns/net for the new netns");
1186 }
1187 if (tmp_netns != fdescs[1].fd) {
1188 if (dup2(tmp_netns, fdescs[1].fd) < 0) {
1189 int e = errno;
1190 close_fdesc(self_netns, NULL);
1191 close(tmp_netns);
1192 errno = e;
1193 err(EXIT_FAILURE, "failed to dup %d -> %d", tmp_netns, fdescs[1].fd);
1194 }
1195 close(tmp_netns);
1196 tmp_netns = fdescs[1].fd;
1197 }
1198
1199 fdescs[1] = (struct fdesc){
1200 .fd = fdescs[1].fd,
1201 .close = close_fdesc,
1202 .data = NULL,
1203 };
1204
1205 sd = socket(AF_UNIX, typesym, 0);
1206 if (sd < 0) {
1207 int e = errno;
1208 close_fdesc(self_netns, NULL);
1209 close_fdesc(tmp_netns, NULL);
1210 errno = e;
1211 err(EXIT_FAILURE,
1212 "failed to make a socket with AF_UNIX + SOCK_%s",
1213 typestr);
1214 }
1215
1216 if (sd != fdescs[2].fd) {
1217 if (dup2(sd, fdescs[2].fd) < 0) {
1218 int e = errno;
1219 close_fdesc(self_netns, NULL);
1220 close_fdesc(tmp_netns, NULL);
1221 close(sd);
1222 errno = e;
1223 err(EXIT_FAILURE, "failed to dup %d -> %d", sd, fdescs[2].fd);
1224 }
1225 close(sd);
1226 sd = fdescs[2].fd;
1227 }
1228
1229 fdescs[2] = (struct fdesc){
1230 .fd = fdescs[2].fd,
1231 .close = close_unix_socket,
1232 .data = NULL,
1233 };
1234
1235 if (!babstract)
1236 unlink(un.sun_path);
1237 if (bind(sd, (const struct sockaddr *)&un, un_len) < 0) {
1238 int e = errno;
1239 close_fdesc(self_netns, NULL);
1240 close_fdesc(tmp_netns, NULL);
1241 close_unix_socket(sd, NULL);
1242 errno = e;
1243 err(EXIT_FAILURE, "failed to bind a socket");
1244 }
1245
1246 if (!babstract)
1247 fdescs[2].data = xstrdup(un.sun_path);
1248
1249 if (typesym != SOCK_DGRAM) {
1250 if (listen(sd, 1) < 0) {
1251 int e = errno;
1252 close_fdesc(self_netns, NULL);
1253 close_fdesc(tmp_netns, NULL);
1254 close_unix_socket(sd, fdescs[2].data);
1255 errno = e;
1256 err(EXIT_FAILURE, "failed to listen a socket");
1257 }
1258 }
1259
1260 if (setns(self_netns, CLONE_NEWNET) < 0) {
1261 int e = errno;
1262 close_fdesc(self_netns, NULL);
1263 close_fdesc(tmp_netns, NULL);
1264 close_unix_socket(sd, fdescs[2].data);
1265 errno = e;
1266 err(EXIT_FAILURE, "failed to swich back to the original net namespace");
1267 }
1268
1269 return NULL;
1270 }
1271
1272 static void *make_tcp_common(const struct factory *factory, struct fdesc fdescs[],
1273 int argc, char ** argv,
1274 int family,
1275 void (*init_addr)(struct sockaddr *, unsigned short),
1276 size_t addr_size,
1277 struct sockaddr * sin, struct sockaddr * cin)
1278 {
1279 struct arg server_port = decode_arg("server-port", factory->params, argc, argv);
1280 unsigned short iserver_port = (unsigned short)ARG_INTEGER(server_port);
1281 struct arg client_port = decode_arg("client-port", factory->params, argc, argv);
1282 unsigned short iclient_port = (unsigned short)ARG_INTEGER(client_port);
1283
1284 int ssd, csd, asd;
1285
1286 const int y = 1;
1287
1288 free_arg(&server_port);
1289 free_arg(&client_port);
1290
1291 ssd = socket(family, SOCK_STREAM, 0);
1292 if (ssd < 0)
1293 err(EXIT_FAILURE,
1294 "failed to make a tcp socket for listening");
1295
1296 if (setsockopt(ssd, SOL_SOCKET,
1297 SO_REUSEADDR, (const char *)&y, sizeof(y)) < 0) {
1298 int e = errno;
1299 close(ssd);
1300 errno = e;
1301 err(EXIT_FAILURE, "failed to setsockopt(SO_REUSEADDR)");
1302 }
1303
1304 if (ssd != fdescs[0].fd) {
1305 if (dup2(ssd, fdescs[0].fd) < 0) {
1306 int e = errno;
1307 close(ssd);
1308 errno = e;
1309 err(EXIT_FAILURE, "failed to dup %d -> %d", ssd, fdescs[0].fd);
1310 }
1311 close(ssd);
1312 ssd = fdescs[0].fd;
1313 }
1314
1315 init_addr(sin, iserver_port);
1316 if (bind(ssd, sin, addr_size) < 0) {
1317 int e = errno;
1318 close(ssd);
1319 errno = e;
1320 err(EXIT_FAILURE, "failed to bind a listening socket");
1321 }
1322
1323 if (listen(ssd, 1) < 0) {
1324 int e = errno;
1325 close(ssd);
1326 errno = e;
1327 err(EXIT_FAILURE, "failed to listen a socket");
1328 }
1329
1330 csd = socket(family, SOCK_STREAM, 0);
1331 if (csd < 0) {
1332 int e = errno;
1333 close(ssd);
1334 errno = e;
1335 err(EXIT_FAILURE,
1336 "failed to make a tcp client socket");
1337 }
1338
1339 if (setsockopt(csd, SOL_SOCKET,
1340 SO_REUSEADDR, (const char *)&y, sizeof(y)) < 0) {
1341 int e = errno;
1342 close(ssd);
1343 close(csd);
1344 errno = e;
1345 err(EXIT_FAILURE, "failed to setsockopt(SO_REUSEADDR)");
1346 }
1347
1348 if (csd != fdescs[1].fd) {
1349 if (dup2(csd, fdescs[1].fd) < 0) {
1350 int e = errno;
1351 close(ssd);
1352 close(csd);
1353 errno = e;
1354 err(EXIT_FAILURE, "failed to dup %d -> %d", csd, fdescs[1].fd);
1355 }
1356 close(csd);
1357 csd = fdescs[1].fd;
1358 }
1359
1360 init_addr(cin, iclient_port);
1361 if (bind(csd, cin, addr_size) < 0) {
1362 int e = errno;
1363 close(ssd);
1364 close(csd);
1365 errno = e;
1366 err(EXIT_FAILURE, "failed to bind a client socket");
1367 }
1368
1369 if (connect(csd, sin, addr_size) < 0) {
1370 int e = errno;
1371 close(ssd);
1372 close(csd);
1373 errno = e;
1374 err(EXIT_FAILURE, "failed to connect a client socket to the server socket");
1375 }
1376
1377 asd = accept(ssd, NULL, NULL);
1378 if (asd < 0) {
1379 int e = errno;
1380 close(ssd);
1381 close(csd);
1382 errno = e;
1383 err(EXIT_FAILURE, "failed to accept a socket from the listening socket");
1384 }
1385 if (asd != fdescs[2].fd) {
1386 if (dup2(asd, fdescs[2].fd) < 0) {
1387 int e = errno;
1388 close(ssd);
1389 close(csd);
1390 errno = e;
1391 err(EXIT_FAILURE, "failed to dup %d -> %d", asd, fdescs[2].fd);
1392 }
1393 close(asd);
1394 asd = fdescs[2].fd;
1395 }
1396
1397 fdescs[0] = (struct fdesc) {
1398 .fd = fdescs[0].fd,
1399 .close = close_fdesc,
1400 .data = NULL,
1401 };
1402 fdescs[1] = (struct fdesc) {
1403 .fd = fdescs[1].fd,
1404 .close = close_fdesc,
1405 .data = NULL,
1406 };
1407 fdescs[2] = (struct fdesc) {
1408 .fd = fdescs[2].fd,
1409 .close = close_fdesc,
1410 .data = NULL,
1411 };
1412
1413 return NULL;
1414 }
1415
1416 static void tcp_init_addr(struct sockaddr *addr, unsigned short port)
1417 {
1418 struct sockaddr_in *in = (struct sockaddr_in *)addr;
1419 memset(in, 0, sizeof(*in));
1420 in->sin_family = AF_INET;
1421 in->sin_port = htons(port);
1422 in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1423 }
1424
1425 static void *make_tcp(const struct factory *factory, struct fdesc fdescs[],
1426 int argc, char ** argv)
1427 {
1428 struct sockaddr_in sin, cin;
1429 return make_tcp_common(factory, fdescs, argc, argv,
1430 AF_INET,
1431 tcp_init_addr, sizeof(sin),
1432 (struct sockaddr *)&sin, (struct sockaddr *)&cin);
1433 }
1434
1435 static void *make_udp_common(const struct factory *factory, struct fdesc fdescs[],
1436 int argc, char ** argv,
1437 int family,
1438 void (*init_addr)(struct sockaddr *, unsigned short),
1439 size_t addr_size,
1440 struct sockaddr * sin, struct sockaddr * cin)
1441 {
1442 struct arg lite = decode_arg("lite", factory->params, argc, argv);
1443 bool blite = ARG_BOOLEAN(lite);
1444
1445 struct arg server_port = decode_arg("server-port", factory->params, argc, argv);
1446 unsigned short iserver_port = (unsigned short)ARG_INTEGER(server_port);
1447 struct arg client_port = decode_arg("client-port", factory->params, argc, argv);
1448 unsigned short iclient_port = (unsigned short)ARG_INTEGER(client_port);
1449
1450 struct arg server_do_bind = decode_arg("server-do-bind", factory->params, argc, argv);
1451 bool bserver_do_bind = ARG_BOOLEAN(server_do_bind);
1452 struct arg client_do_bind = decode_arg("client-do-bind", factory->params, argc, argv);
1453 bool bclient_do_bind = ARG_BOOLEAN(client_do_bind);
1454 struct arg client_do_connect = decode_arg("client-do-connect", factory->params, argc, argv);
1455 bool bclient_do_connect = ARG_BOOLEAN(client_do_connect);
1456
1457 int ssd, csd;
1458
1459 const int y = 1;
1460
1461 free_arg(&client_do_connect);
1462 free_arg(&client_do_bind);
1463 free_arg(&server_do_bind);
1464 free_arg(&server_port);
1465 free_arg(&client_port);
1466 free_arg(&lite);
1467
1468 ssd = socket(family, SOCK_DGRAM, blite? IPPROTO_UDPLITE: 0);
1469 if (ssd < 0)
1470 err(EXIT_FAILURE,
1471 "failed to make a udp socket for server");
1472
1473 if (setsockopt(ssd, SOL_SOCKET,
1474 SO_REUSEADDR, (const char *)&y, sizeof(y)) < 0) {
1475 int e = errno;
1476 close(ssd);
1477 errno = e;
1478 err(EXIT_FAILURE, "failed to setsockopt(SO_REUSEADDR)");
1479 }
1480
1481 if (ssd != fdescs[0].fd) {
1482 if (dup2(ssd, fdescs[0].fd) < 0) {
1483 int e = errno;
1484 close(ssd);
1485 errno = e;
1486 err(EXIT_FAILURE, "failed to dup %d -> %d", ssd, fdescs[0].fd);
1487 }
1488 close(ssd);
1489 ssd = fdescs[0].fd;
1490 }
1491
1492 init_addr(sin, iserver_port);
1493 if (bserver_do_bind) {
1494 if (bind(ssd, sin, addr_size) < 0) {
1495 int e = errno;
1496 close(ssd);
1497 errno = e;
1498 err(EXIT_FAILURE, "failed to bind a server socket");
1499 }
1500 }
1501
1502 csd = socket(family, SOCK_DGRAM, blite? IPPROTO_UDPLITE: 0);
1503 if (csd < 0) {
1504 int e = errno;
1505 close(ssd);
1506 errno = e;
1507 err(EXIT_FAILURE,
1508 "failed to make a udp client socket");
1509 }
1510
1511 if (setsockopt(csd, SOL_SOCKET,
1512 SO_REUSEADDR, (const char *)&y, sizeof(y)) < 0) {
1513 int e = errno;
1514 close(ssd);
1515 close(csd);
1516 errno = e;
1517 err(EXIT_FAILURE, "failed to setsockopt(SO_REUSEADDR)");
1518 }
1519
1520 if (csd != fdescs[1].fd) {
1521 if (dup2(csd, fdescs[1].fd) < 0) {
1522 int e = errno;
1523 close(ssd);
1524 close(csd);
1525 errno = e;
1526 err(EXIT_FAILURE, "failed to dup %d -> %d", csd, fdescs[1].fd);
1527 }
1528 close(csd);
1529 csd = fdescs[1].fd;
1530 }
1531
1532 if (bclient_do_bind) {
1533 init_addr(cin, iclient_port);
1534 if (bind(csd, cin, addr_size) < 0) {
1535 int e = errno;
1536 close(ssd);
1537 close(csd);
1538 errno = e;
1539 err(EXIT_FAILURE, "failed to bind a client socket");
1540 }
1541 }
1542
1543 if (bclient_do_connect) {
1544 if (connect(csd, sin, addr_size) < 0) {
1545 int e = errno;
1546 close(ssd);
1547 close(csd);
1548 errno = e;
1549 err(EXIT_FAILURE, "failed to connect a client socket to the server socket");
1550 }
1551 }
1552
1553 fdescs[0] = (struct fdesc) {
1554 .fd = fdescs[0].fd,
1555 .close = close_fdesc,
1556 .data = NULL,
1557 };
1558 fdescs[1] = (struct fdesc) {
1559 .fd = fdescs[1].fd,
1560 .close = close_fdesc,
1561 .data = NULL,
1562 };
1563
1564 return NULL;
1565 }
1566
1567 static void *make_udp(const struct factory *factory, struct fdesc fdescs[],
1568 int argc, char ** argv)
1569 {
1570 struct sockaddr_in sin, cin;
1571 return make_udp_common(factory, fdescs, argc, argv,
1572 AF_INET,
1573 tcp_init_addr, sizeof(sin),
1574 (struct sockaddr *)&sin, (struct sockaddr *)&cin);
1575 }
1576
1577 static void *make_raw_common(const struct factory *factory, struct fdesc fdescs[],
1578 int argc, char ** argv,
1579 int family,
1580 void (*init_addr)(struct sockaddr *, bool),
1581 size_t addr_size,
1582 struct sockaddr * sin)
1583 {
1584 struct arg protocol = decode_arg("protocol", factory->params, argc, argv);
1585 int iprotocol = ARG_INTEGER(protocol);
1586 int ssd;
1587
1588 free_arg(&protocol);
1589
1590 ssd = socket(family, SOCK_RAW, iprotocol);
1591 if (ssd < 0)
1592 err(EXIT_FAILURE,
1593 "failed to make a udp socket for server");
1594
1595 if (ssd != fdescs[0].fd) {
1596 if (dup2(ssd, fdescs[0].fd) < 0) {
1597 int e = errno;
1598 close(ssd);
1599 errno = e;
1600 err(EXIT_FAILURE, "failed to dup %d -> %d", ssd, fdescs[0].fd);
1601 }
1602 close(ssd);
1603 ssd = fdescs[0].fd;
1604 }
1605
1606 init_addr(sin, false);
1607 if (bind(ssd, sin, addr_size) < 0) {
1608 int e = errno;
1609 close(ssd);
1610 errno = e;
1611 err(EXIT_FAILURE, "failed in bind(2)");
1612 }
1613
1614 init_addr(sin, true);
1615 if (connect(ssd, sin, addr_size) < 0) {
1616 int e = errno;
1617 close(ssd);
1618 errno = e;
1619 err(EXIT_FAILURE, "failed in connect(2)");
1620 }
1621
1622 fdescs[0] = (struct fdesc) {
1623 .fd = fdescs[0].fd,
1624 .close = close_fdesc,
1625 .data = NULL,
1626 };
1627
1628 return NULL;
1629 }
1630
1631 static void raw_init_addr(struct sockaddr * addr, bool remote_addr)
1632 {
1633 struct sockaddr_in *in = (struct sockaddr_in *)addr;
1634 memset(in, 0, sizeof(*in));
1635 in->sin_family = AF_INET;
1636 in->sin_addr.s_addr = htonl(INADDR_LOOPBACK + (remote_addr? 1: 0));
1637 }
1638
1639 static void *make_raw(const struct factory *factory, struct fdesc fdescs[],
1640 int argc, char ** argv)
1641 {
1642 struct sockaddr_in sin;
1643 return make_raw_common(factory, fdescs, argc, argv,
1644 AF_INET,
1645 raw_init_addr, sizeof(sin),
1646 (struct sockaddr *)&sin);
1647 }
1648
1649 static void *make_ping_common(const struct factory *factory, struct fdesc fdescs[],
1650 int argc, char ** argv,
1651 int family, int protocol,
1652 void (*init_addr)(struct sockaddr *, unsigned short),
1653 size_t addr_size,
1654 struct sockaddr *sin)
1655 {
1656 struct arg connect_ = decode_arg("connect", factory->params, argc, argv);
1657 bool bconnect = ARG_BOOLEAN(connect_);
1658
1659 struct arg bind_ = decode_arg("bind", factory->params, argc, argv);
1660 bool bbind = ARG_BOOLEAN(bind_);
1661
1662 struct arg id = decode_arg("id", factory->params, argc, argv);
1663 unsigned short iid = (unsigned short)ARG_INTEGER(id);
1664
1665 int sd;
1666
1667 free_arg(&id);
1668 free_arg(&bind_);
1669 free_arg(&connect_);
1670
1671 sd = socket(family, SOCK_DGRAM, protocol);
1672 if (sd < 0)
1673 err((errno == EACCES? EXIT_EACCESS: EXIT_FAILURE),
1674 "failed to make an icmp socket");
1675
1676 if (sd != fdescs[0].fd) {
1677 if (dup2(sd, fdescs[0].fd) < 0) {
1678 int e = errno;
1679 close(sd);
1680 errno = e;
1681 err(EXIT_FAILURE, "failed to dup %d -> %d", sd, fdescs[0].fd);
1682 }
1683 close(sd);
1684 sd = fdescs[0].fd;
1685 }
1686
1687 if (bbind) {
1688 init_addr(sin, iid);
1689 if (bind(sd, sin, addr_size) < 0) {
1690 int e = errno;
1691 close(sd);
1692 errno = e;
1693 err((errno == EACCES? EXIT_EACCESS: EXIT_FAILURE),
1694 "failed in bind(2)");
1695 }
1696 }
1697
1698 if (bconnect) {
1699 init_addr(sin, 0);
1700 if (connect(sd, sin, addr_size) < 0) {
1701 int e = errno;
1702 close(sd);
1703 errno = e;
1704 err(EXIT_FAILURE, "failed in connect(2)");
1705 }
1706 }
1707
1708 fdescs[0] = (struct fdesc) {
1709 .fd = fdescs[0].fd,
1710 .close = close_fdesc,
1711 .data = NULL,
1712 };
1713
1714 return NULL;
1715 }
1716
1717 static void ping_init_addr(struct sockaddr *addr, unsigned short id)
1718 {
1719 struct sockaddr_in *in = (struct sockaddr_in *)addr;
1720 memset(in, 0, sizeof(*in));
1721 in->sin_family = AF_INET;
1722 in->sin_port = htons(id);
1723 in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1724 }
1725
1726 static void *make_ping(const struct factory *factory, struct fdesc fdescs[],
1727 int argc, char ** argv)
1728 {
1729 struct sockaddr_in in;
1730 return make_ping_common(factory, fdescs, argc, argv,
1731 AF_INET, IPPROTO_ICMP,
1732 ping_init_addr,
1733 sizeof(in),
1734 (struct sockaddr *)&in);
1735 }
1736
1737 static void tcp6_init_addr(struct sockaddr *addr, unsigned short port)
1738 {
1739 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
1740 memset(in6, 0, sizeof(*in6));
1741 in6->sin6_family = AF_INET6;
1742 in6->sin6_flowinfo = 0;
1743 in6->sin6_port = htons(port);
1744 in6->sin6_addr = in6addr_loopback;
1745 }
1746
1747 static void *make_tcp6(const struct factory *factory, struct fdesc fdescs[],
1748 int argc, char ** argv)
1749 {
1750 struct sockaddr_in6 sin, cin;
1751 return make_tcp_common(factory, fdescs, argc, argv,
1752 AF_INET6,
1753 tcp6_init_addr, sizeof(sin),
1754 (struct sockaddr *)&sin, (struct sockaddr *)&cin);
1755 }
1756
1757 static void *make_udp6(const struct factory *factory, struct fdesc fdescs[],
1758 int argc, char ** argv)
1759 {
1760 struct sockaddr_in6 sin, cin;
1761 return make_udp_common(factory, fdescs, argc, argv,
1762 AF_INET6,
1763 tcp6_init_addr, sizeof(sin),
1764 (struct sockaddr *)&sin, (struct sockaddr *)&cin);
1765 }
1766
1767 static void raw6_init_addr(struct sockaddr *addr, bool remote_addr)
1768 {
1769 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
1770 memset(in6, 0, sizeof(*in6));
1771 in6->sin6_family = AF_INET6;
1772 in6->sin6_flowinfo = 0;
1773
1774 if (remote_addr) {
1775 /* ::ffff:127.0.0.1 */
1776 in6->sin6_addr.s6_addr16[5] = 0xffff;
1777 in6->sin6_addr.s6_addr32[3] = htonl(INADDR_LOOPBACK);
1778 } else
1779 in6->sin6_addr = in6addr_loopback;
1780 }
1781
1782 static void *make_raw6(const struct factory *factory, struct fdesc fdescs[],
1783 int argc, char ** argv)
1784 {
1785 struct sockaddr_in6 sin;
1786 return make_raw_common(factory, fdescs, argc, argv,
1787 AF_INET6,
1788 raw6_init_addr, sizeof(sin),
1789 (struct sockaddr *)&sin);
1790 }
1791
1792 static void ping6_init_addr(struct sockaddr *addr, unsigned short id)
1793 {
1794 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
1795 memset(in6, 0, sizeof(*in6));
1796 in6->sin6_family = AF_INET6;
1797 in6->sin6_port = htons(id);
1798 in6->sin6_addr = in6addr_loopback;
1799 }
1800
1801 static void *make_ping6(const struct factory *factory, struct fdesc fdescs[],
1802 int argc, char ** argv)
1803 {
1804 struct sockaddr_in6 in6;
1805 return make_ping_common(factory, fdescs, argc, argv,
1806 AF_INET6, IPPROTO_ICMPV6,
1807 ping6_init_addr,
1808 sizeof(in6),
1809 (struct sockaddr *)&in6);
1810 }
1811
1812 static void *make_netns(const struct factory *factory _U_, struct fdesc fdescs[],
1813 int argc _U_, char ** argv _U_)
1814 {
1815 int sd = socket(AF_UNIX, SOCK_STREAM, 0);
1816 if (sd < 0)
1817 err(EXIT_FAILURE, "failed in socket()");
1818
1819 int ns = ioctl(sd, SIOCGSKNS);
1820 if (ns < 0)
1821 err((errno == ENOSYS? EXIT_ENOSYS: EXIT_FAILURE),
1822 "failed in ioctl(SIOCGSKNS)");
1823 close(sd);
1824
1825 if (ns != fdescs[0].fd) {
1826 if (dup2(ns, fdescs[0].fd) < 0) {
1827 int e = errno;
1828 close(ns);
1829 errno = e;
1830 err(EXIT_FAILURE, "failed to dup %d -> %d", ns, fdescs[0].fd);
1831 }
1832 close(ns);
1833 }
1834
1835 fdescs[0] = (struct fdesc){
1836 .fd = fdescs[0].fd,
1837 .close = close_fdesc,
1838 .data = NULL
1839 };
1840
1841 return NULL;
1842 }
1843
1844 static void *make_netlink(const struct factory *factory, struct fdesc fdescs[],
1845 int argc, char ** argv)
1846 {
1847 struct arg protocol = decode_arg("protocol", factory->params, argc, argv);
1848 int iprotocol = ARG_INTEGER(protocol);
1849 struct arg groups = decode_arg("groups", factory->params, argc, argv);
1850 unsigned int ugroups = ARG_UINTEGER(groups);
1851 int sd;
1852
1853 free_arg(&protocol);
1854
1855 sd = socket(AF_NETLINK, SOCK_RAW, iprotocol);
1856 if (sd < 0)
1857 err((errno == EPROTONOSUPPORT)? EXIT_EPROTONOSUPPORT: EXIT_FAILURE,
1858 "failed in socket()");
1859
1860 if (sd != fdescs[0].fd) {
1861 if (dup2(sd, fdescs[0].fd) < 0) {
1862 int e = errno;
1863 close(sd);
1864 errno = e;
1865 err(EXIT_FAILURE, "failed to dup %d -> %d", sd, fdescs[0].fd);
1866 }
1867 close(sd);
1868 }
1869
1870 struct sockaddr_nl nl;
1871 memset(&nl, 0, sizeof(nl));
1872 nl.nl_family = AF_NETLINK;
1873 nl.nl_groups = ugroups;
1874 if (bind(sd, (struct sockaddr*)&nl, sizeof(nl)) < 0) {
1875 int e = errno;
1876 close(sd);
1877 errno = e;
1878 err(EXIT_FAILURE, "failed in bind(2)");
1879 }
1880
1881 fdescs[0] = (struct fdesc){
1882 .fd = fdescs[0].fd,
1883 .close = close_fdesc,
1884 .data = NULL
1885 };
1886
1887 return NULL;
1888 }
1889
1890 #define PARAM_END { .name = NULL, }
1891 static const struct factory factories[] = {
1892 {
1893 .name = "ro-regular-file",
1894 .desc = "read-only regular file",
1895 .priv = false,
1896 .N = 1,
1897 .EX_N = 0,
1898 .make = open_ro_regular_file,
1899 .params = (struct parameter []) {
1900 {
1901 .name = "file",
1902 .type = PTYPE_STRING,
1903 .desc = "file to be opened",
1904 .defv.string = "/etc/passwd",
1905 },
1906 {
1907 .name = "offset",
1908 .type = PTYPE_INTEGER,
1909 .desc = "seek bytes after open with SEEK_CUR",
1910 .defv.integer = 0,
1911 },
1912 PARAM_END
1913 },
1914 },
1915 {
1916 .name = "pipe-no-fork",
1917 .desc = "making pair of fds with pipe(2)",
1918 .priv = false,
1919 .N = 2,
1920 .EX_N = 2,
1921 .make = make_pipe,
1922 .params = (struct parameter []) {
1923 {
1924 .name = "nonblock",
1925 .type = PTYPE_STRING,
1926 .desc = "set nonblock flag (\"--\", \"r-\", \"-w\", or \"rw\")",
1927 .defv.string = "--",
1928 },
1929 {
1930 .name = "rdup",
1931 .type = PTYPE_INTEGER,
1932 .desc = "file descriptor for duplicating the pipe input",
1933 .defv.integer = -1,
1934 },
1935 {
1936 .name = "wdup",
1937 .type = PTYPE_INTEGER,
1938 .desc = "file descriptor for duplicating the pipe output",
1939 .defv.integer = -1,
1940 },
1941 PARAM_END
1942 },
1943 },
1944 {
1945 .name = "directory",
1946 .desc = "directory",
1947 .priv = false,
1948 .N = 1,
1949 .EX_N = 0,
1950 .make = open_directory,
1951 .params = (struct parameter []) {
1952 {
1953 .name = "dir",
1954 .type = PTYPE_STRING,
1955 .desc = "directory to be opened",
1956 .defv.string = "/",
1957 },
1958 {
1959 .name = "dentries",
1960 .type = PTYPE_INTEGER,
1961 .desc = "read the number of dentries after open with readdir(3)",
1962 .defv.integer = 0,
1963 },
1964 PARAM_END
1965 },
1966 },
1967 {
1968 .name = "rw-character-device",
1969 .desc = "character device with O_RDWR flag",
1970 .priv = false,
1971 .N = 1,
1972 .EX_N = 0,
1973 .make = open_rw_chrdev,
1974 .params = (struct parameter []) {
1975 {
1976 .name = "chrdev",
1977 .type = PTYPE_STRING,
1978 .desc = "character device node to be opened",
1979 .defv.string = "/dev/zero",
1980 },
1981 PARAM_END
1982 },
1983 },
1984 {
1985 .name = "socketpair",
1986 .desc = "AF_UNIX socket pair created with socketpair(2)",
1987 .priv = false,
1988 .N = 2,
1989 .EX_N = 0,
1990 .make = make_socketpair,
1991 .params = (struct parameter []) {
1992 {
1993 .name = "socktype",
1994 .type = PTYPE_STRING,
1995 .desc = "STREAM, DGRAM, or SEQPACKET",
1996 .defv.string = "STREAM",
1997 },
1998 PARAM_END
1999 },
2000 },
2001 {
2002 .name = "symlink",
2003 .desc = "symbolic link itself opened with O_PATH",
2004 .priv = false,
2005 .N = 1,
2006 .EX_N = 0,
2007 .make = open_with_opath,
2008 .params = (struct parameter []) {
2009 {
2010 .name = "path",
2011 .type = PTYPE_STRING,
2012 .desc = "path to a symbolic link",
2013 .defv.string = "/dev/stdin",
2014 },
2015 PARAM_END
2016 },
2017 },
2018 {
2019 .name = "ro-block-device",
2020 .desc = "block device with O_RDONLY flag",
2021 .priv = true,
2022 .N = 1,
2023 .EX_N = 0,
2024 .make = open_ro_blkdev,
2025 .params = (struct parameter []) {
2026 {
2027 .name = "blkdev",
2028 .type = PTYPE_STRING,
2029 .desc = "block device node to be opened",
2030 .defv.string = "/dev/nullb0",
2031 },
2032 PARAM_END
2033 },
2034 },
2035 {
2036 .name = "mapped-packet-socket",
2037 .desc = "mmap'ed AF_PACKET socket",
2038 .priv = true,
2039 .N = 1,
2040 .EX_N = 0,
2041 .make = make_mmapped_packet_socket,
2042 .params = (struct parameter []) {
2043 {
2044 .name = "socktype",
2045 .type = PTYPE_STRING,
2046 .desc = "DGRAM or RAW",
2047 .defv.string = "RAW",
2048 },
2049 {
2050 .name = "interface",
2051 .type = PTYPE_STRING,
2052 .desc = "a name of network interface like eth0 or lo",
2053 .defv.string = "lo",
2054 },
2055 PARAM_END
2056 },
2057 },
2058 {
2059 .name = "pidfd",
2060 .desc = "pidfd returned from pidfd_open(2)",
2061 .priv = false,
2062 .N = 1,
2063 .EX_N = 0,
2064 .make = make_pidfd,
2065 .params = (struct parameter []) {
2066 {
2067 .name = "target-pid",
2068 .type = PTYPE_INTEGER,
2069 .desc = "the pid of the target process",
2070 .defv.integer = 1,
2071 },
2072 PARAM_END
2073 },
2074 },
2075 {
2076 .name = "inotify",
2077 .desc = "inotify fd returned from inotify_init(2)",
2078 .priv = false,
2079 .N = 1,
2080 .EX_N = 0,
2081 .make = make_inotify_fd,
2082 .params = (struct parameter []) {
2083 PARAM_END
2084 },
2085 },
2086 {
2087 .name = "unix-stream",
2088 .desc = "AF_UNIX+SOCK_STREAM sockets",
2089 .priv = false,
2090 .N = 3,
2091 .EX_N = 0,
2092 .make = make_unix_stream,
2093 .params = (struct parameter []) {
2094 {
2095 .name = "path",
2096 .type = PTYPE_STRING,
2097 .desc = "path for listening-socket bound to",
2098 .defv.string = "/tmp/test_mkfds-unix-stream",
2099 },
2100 {
2101 .name = "backlog",
2102 .type = PTYPE_INTEGER,
2103 .desc = "backlog passed to listen(2)",
2104 .defv.integer = 5,
2105 },
2106 {
2107 .name = "abstract",
2108 .type = PTYPE_BOOLEAN,
2109 .desc = "use PATH as an abstract socket address",
2110 .defv.boolean = false,
2111 },
2112 {
2113 .name = "server-shutdown",
2114 .type = PTYPE_INTEGER,
2115 .desc = "shutdown the accepted socket; 1: R, 2: W, 3: RW",
2116 .defv.integer = 0,
2117 },
2118 {
2119 .name = "client-shutdown",
2120 .type = PTYPE_INTEGER,
2121 .desc = "shutdown the client socket; 1: R, 2: W, 3: RW",
2122 .defv.integer = 0,
2123 },
2124 {
2125 .name = "type",
2126 .type = PTYPE_STRING,
2127 .desc = "stream or seqpacket",
2128 .defv.string = "stream",
2129 },
2130 PARAM_END
2131 },
2132 },
2133 {
2134 .name = "unix-dgram",
2135 .desc = "AF_UNIX+SOCK_DGRAM sockets",
2136 .priv = false,
2137 .N = 2,
2138 .EX_N = 0,
2139 .make = make_unix_dgram,
2140 .params = (struct parameter []) {
2141 {
2142 .name = "path",
2143 .type = PTYPE_STRING,
2144 .desc = "path for unix non-stream bound to",
2145 .defv.string = "/tmp/test_mkfds-unix-dgram",
2146 },
2147 {
2148 .name = "abstract",
2149 .type = PTYPE_BOOLEAN,
2150 .desc = "use PATH as an abstract socket address",
2151 .defv.boolean = false,
2152 },
2153 PARAM_END
2154 },
2155 },
2156 {
2157 .name = "unix-in-netns",
2158 .desc = "make a unix socket in a new network namespace",
2159 .priv = true,
2160 .N = 3,
2161 .EX_N = 0,
2162 .make = make_unix_in_new_netns,
2163 .params = (struct parameter []) {
2164 {
2165 .name = "type",
2166 .type = PTYPE_STRING,
2167 .desc = "dgram, stream, or seqpacket",
2168 .defv.string = "stream",
2169 },
2170 {
2171 .name = "path",
2172 .type = PTYPE_STRING,
2173 .desc = "path for unix non-stream bound to",
2174 .defv.string = "/tmp/test_mkfds-unix-in-netns",
2175 },
2176 {
2177 .name = "abstract",
2178 .type = PTYPE_BOOLEAN,
2179 .desc = "use PATH as an abstract socket address",
2180 .defv.boolean = false,
2181 },
2182 PARAM_END
2183 },
2184 },
2185 {
2186 .name = "tcp",
2187 .desc = "AF_INET+SOCK_STREAM sockets",
2188 .priv = false,
2189 .N = 3,
2190 .EX_N = 0,
2191 .make = make_tcp,
2192 .params = (struct parameter []) {
2193 {
2194 .name = "server-port",
2195 .type = PTYPE_INTEGER,
2196 .desc = "TCP port the server may listen",
2197 .defv.integer = 12345,
2198 },
2199 {
2200 .name = "client-port",
2201 .type = PTYPE_INTEGER,
2202 .desc = "TCP port the client may bind",
2203 .defv.integer = 23456,
2204 },
2205 PARAM_END
2206 }
2207 },
2208 {
2209 .name = "udp",
2210 .desc = "AF_INET+SOCK_DGRAM sockets",
2211 .priv = false,
2212 .N = 2,
2213 .EX_N = 0,
2214 .make = make_udp,
2215 .params = (struct parameter []) {
2216 {
2217 .name = "lite",
2218 .type = PTYPE_BOOLEAN,
2219 .desc = "Use UDPLITE instead of UDP",
2220 .defv.boolean = false,
2221 },
2222 {
2223 .name = "server-port",
2224 .type = PTYPE_INTEGER,
2225 .desc = "UDP port the server may listen",
2226 .defv.integer = 12345,
2227 },
2228 {
2229 .name = "client-port",
2230 .type = PTYPE_INTEGER,
2231 .desc = "UDP port the client may bind",
2232 .defv.integer = 23456,
2233 },
2234 {
2235 .name = "server-do-bind",
2236 .type = PTYPE_BOOLEAN,
2237 .desc = "call bind with the server socket",
2238 .defv.boolean = true,
2239 },
2240 {
2241 .name = "client-do-bind",
2242 .type = PTYPE_BOOLEAN,
2243 .desc = "call bind with the client socket",
2244 .defv.boolean = true,
2245 },
2246 {
2247 .name = "client-do-connect",
2248 .type = PTYPE_BOOLEAN,
2249 .desc = "call connect with the client socket",
2250 .defv.boolean = true,
2251 },
2252 PARAM_END
2253 }
2254 },
2255 {
2256 .name = "raw",
2257 .desc = "AF_INET+SOCK_RAW sockets",
2258 .priv = true,
2259 .N = 1,
2260 .EX_N = 0,
2261 .make = make_raw,
2262 .params = (struct parameter []) {
2263 {
2264 .name = "protocol",
2265 .type = PTYPE_INTEGER,
2266 .desc = "protocol passed to socket(AF_INET, SOCK_RAW, protocol)",
2267 .defv.integer = IPPROTO_IPIP,
2268 },
2269 PARAM_END
2270 }
2271
2272 },
2273 {
2274 .name = "ping",
2275 .desc = "AF_INET+SOCK_DGRAM+IPPROTO_ICMP sockets",
2276 .priv = false,
2277 .N = 1,
2278 .EX_N = 0,
2279 .make = make_ping,
2280 .params = (struct parameter []) {
2281 {
2282 .name = "connect",
2283 .type = PTYPE_BOOLEAN,
2284 .desc = "call connect(2) with the socket",
2285 .defv.boolean = true,
2286 },
2287 {
2288 .name = "bind",
2289 .type = PTYPE_BOOLEAN,
2290 .desc = "call bind(2) with the socket",
2291 .defv.boolean = true,
2292 },
2293 {
2294 .name = "id",
2295 .type = PTYPE_INTEGER,
2296 .desc = "ICMP echo request id",
2297 .defv.integer = 0,
2298 },
2299 PARAM_END
2300 }
2301 },
2302 {
2303 .name = "tcp6",
2304 .desc = "AF_INET6+SOCK_STREAM sockets",
2305 .priv = false,
2306 .N = 3,
2307 .EX_N = 0,
2308 .make = make_tcp6,
2309 .params = (struct parameter []) {
2310 {
2311 .name = "server-port",
2312 .type = PTYPE_INTEGER,
2313 .desc = "TCP port the server may listen",
2314 .defv.integer = 12345,
2315 },
2316 {
2317 .name = "client-port",
2318 .type = PTYPE_INTEGER,
2319 .desc = "TCP port the client may bind",
2320 .defv.integer = 23456,
2321 },
2322 PARAM_END
2323 }
2324 },
2325 {
2326 .name = "udp6",
2327 .desc = "AF_INET6+SOCK_DGRAM sockets",
2328 .priv = false,
2329 .N = 2,
2330 .EX_N = 0,
2331 .make = make_udp6,
2332 .params = (struct parameter []) {
2333 {
2334 .name = "lite",
2335 .type = PTYPE_BOOLEAN,
2336 .desc = "Use UDPLITE instead of UDP",
2337 .defv.boolean = false,
2338 },
2339 {
2340 .name = "server-port",
2341 .type = PTYPE_INTEGER,
2342 .desc = "UDP port the server may listen",
2343 .defv.integer = 12345,
2344 },
2345 {
2346 .name = "client-port",
2347 .type = PTYPE_INTEGER,
2348 .desc = "UDP port the client may bind",
2349 .defv.integer = 23456,
2350 },
2351 {
2352 .name = "server-do-bind",
2353 .type = PTYPE_BOOLEAN,
2354 .desc = "call bind with the server socket",
2355 .defv.boolean = true,
2356 },
2357 {
2358 .name = "client-do-bind",
2359 .type = PTYPE_BOOLEAN,
2360 .desc = "call bind with the client socket",
2361 .defv.boolean = true,
2362 },
2363 {
2364 .name = "client-do-connect",
2365 .type = PTYPE_BOOLEAN,
2366 .desc = "call connect with the client socket",
2367 .defv.boolean = true,
2368 },
2369 PARAM_END
2370 }
2371 },
2372 {
2373 .name = "raw6",
2374 .desc = "AF_INET6+SOCK_RAW sockets",
2375 .priv = true,
2376 .N = 1,
2377 .EX_N = 0,
2378 .make = make_raw6,
2379 .params = (struct parameter []) {
2380 {
2381 .name = "protocol",
2382 .type = PTYPE_INTEGER,
2383 .desc = "protocol passed to socket(AF_INET6, SOCK_RAW, protocol)",
2384 .defv.integer = IPPROTO_IPIP,
2385 },
2386 PARAM_END
2387 }
2388
2389 },
2390 {
2391 .name = "ping6",
2392 .desc = "AF_INET6+SOCK_DGRAM+IPPROTO_ICMPV6 sockets",
2393 .priv = false,
2394 .N = 1,
2395 .EX_N = 0,
2396 .make = make_ping6,
2397 .params = (struct parameter []) {
2398 {
2399 .name = "connect",
2400 .type = PTYPE_BOOLEAN,
2401 .desc = "call connect(2) with the socket",
2402 .defv.boolean = true,
2403 },
2404 {
2405 .name = "bind",
2406 .type = PTYPE_BOOLEAN,
2407 .desc = "call bind(2) with the socket",
2408 .defv.boolean = true,
2409 },
2410 {
2411 .name = "id",
2412 .type = PTYPE_INTEGER,
2413 .desc = "ICMP echo request id",
2414 .defv.integer = 0,
2415 },
2416 PARAM_END
2417 }
2418 },
2419 {
2420 .name = "netns",
2421 .desc = "open a file specifying a netns",
2422 .priv = true,
2423 .N = 1,
2424 .EX_N = 0,
2425 .make = make_netns,
2426 .params = (struct parameter []) {
2427 PARAM_END
2428 }
2429 },
2430 {
2431 .name = "netlink",
2432 .desc = "AF_NETLINK sockets",
2433 .priv = false,
2434 .N = 1,
2435 .EX_N = 0,
2436 .make = make_netlink,
2437 .params = (struct parameter []) {
2438 {
2439 .name = "protocol",
2440 .type = PTYPE_INTEGER,
2441 .desc = "protocol passed to socket(AF_NETLINK, SOCK_RAW, protocol)",
2442 .defv.integer = NETLINK_USERSOCK,
2443 },
2444 {
2445 .name = "groups",
2446 .type = PTYPE_UINTEGER,
2447 .desc = "multicast groups of netlink communication (requires CAP_NET_ADMIN)",
2448 .defv.uinteger = 0,
2449 },
2450 PARAM_END
2451 }
2452 },
2453 };
2454
2455 static int count_parameters(const struct factory *factory)
2456 {
2457
2458 const struct parameter *p = factory->params;
2459 if (!p)
2460 return 0;
2461 while (p->name)
2462 p++;
2463 return p - factory->params;
2464 }
2465
2466 static void print_factory(const struct factory *factory)
2467 {
2468 printf("%-20s %4s %5d %6d %s\n",
2469 factory->name,
2470 factory->priv? "yes": "no",
2471 factory->N,
2472 count_parameters(factory),
2473 factory->desc);
2474 }
2475
2476 static void list_factories(void)
2477 {
2478 printf("%-20s PRIV COUNT NPARAM DESCRIPTION\n", "FACTORY");
2479 for (size_t i = 0; i < ARRAY_SIZE(factories); i++)
2480 print_factory(factories + i);
2481 }
2482
2483 static const struct factory *find_factory(const char *name)
2484 {
2485 for (size_t i = 0; i < ARRAY_SIZE(factories); i++)
2486 if (strcmp(factories[i].name, name) == 0)
2487 return factories + i;
2488 return NULL;
2489 }
2490
2491 static void list_parameters(const char *factory_name)
2492 {
2493 const struct factory *factory = find_factory(factory_name);
2494 const char *fmt = "%-15s %-8s %15s %s\n";
2495
2496 if (!factory)
2497 errx(EXIT_FAILURE, "no such factory: %s", factory_name);
2498
2499 if (!factory->params)
2500 return;
2501
2502 printf(fmt, "PARAMETER", "TYPE", "DEFAULT_VALUE", "DESCRIPTION");
2503 for (const struct parameter *p = factory->params; p->name != NULL; p++) {
2504 char *defv = ptype_classes[p->type].sprint(&p->defv);
2505 printf(fmt, p->name, ptype_classes[p->type].name, defv, p->desc);
2506 free(defv);
2507 }
2508 }
2509
2510 static void rename_self(const char *comm)
2511 {
2512 if (prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0) < 0)
2513 err(EXIT_FAILURE, "failed to rename self via prctl: %s", comm);
2514 }
2515
2516 static void do_nothing(int signum _U_)
2517 {
2518 }
2519
2520 #ifdef __NR_pidfd_open
2521
2522 static int
2523 pidfd_open(pid_t pid, unsigned int flags)
2524 {
2525 return syscall(__NR_pidfd_open, pid, flags);
2526 }
2527 #else
2528 static int
2529 pidfd_open(pid_t pid _U_, unsigned int flags _U_)
2530 {
2531 errno = ENOSYS;
2532 return -1;
2533 }
2534 #endif
2535
2536 static void wait_event(void)
2537 {
2538 fd_set readfds;
2539 sigset_t sigset;
2540 int n = 0;
2541
2542 FD_ZERO(&readfds);
2543 /* Monitor the standard input only when the process
2544 * is in foreground. */
2545 if (tcgetpgrp(STDIN_FILENO) == getpgrp()) {
2546 n = 1;
2547 FD_SET(0, &readfds);
2548 }
2549
2550 sigemptyset(&sigset);
2551
2552 if (pselect(n, &readfds, NULL, NULL, NULL, &sigset) < 0
2553 && errno != EINTR)
2554 errx(EXIT_FAILURE, "failed in pselect");
2555 }
2556
2557 int main(int argc, char **argv)
2558 {
2559 int c;
2560 const struct factory *factory;
2561 struct fdesc fdescs[MAX_N];
2562 bool quiet = false;
2563 bool cont = false;
2564 void *data;
2565
2566 static const struct option longopts[] = {
2567 { "list", no_argument, NULL, 'l' },
2568 { "parameters", required_argument, NULL, 'I' },
2569 { "comm", required_argument, NULL, 'r' },
2570 { "quiet", no_argument, NULL, 'q' },
2571 { "dont-puase", no_argument, NULL, 'c' },
2572 { "help", no_argument, NULL, 'h' },
2573 { NULL, 0, NULL, 0 },
2574 };
2575
2576 while ((c = getopt_long(argc, argv, "lhqcI:r:", longopts, NULL)) != -1) {
2577 switch (c) {
2578 case 'h':
2579 usage(stdout, EXIT_SUCCESS);
2580 case 'l':
2581 list_factories();
2582 exit(EXIT_SUCCESS);
2583 case 'I':
2584 list_parameters(optarg);
2585 exit(EXIT_SUCCESS);
2586 case 'q':
2587 quiet = true;
2588 break;
2589 case 'c':
2590 cont = true;
2591 break;
2592 case 'r':
2593 rename_self(optarg);
2594 break;
2595 default:
2596 usage(stderr, EXIT_FAILURE);
2597 }
2598 }
2599
2600 if (optind == argc)
2601 errx(EXIT_FAILURE, "no file descriptor specification given");
2602
2603 factory = find_factory(argv[optind]);
2604 if (!factory)
2605 errx(EXIT_FAILURE, "no such factory: %s", argv[optind]);
2606 assert(factory->N + factory->EX_N < MAX_N);
2607 optind++;
2608
2609 if ((optind + factory->N) > argc)
2610 errx(EXIT_FAILURE, "not enough file descriptors given for %s",
2611 factory->name);
2612
2613 if (factory->priv && getuid() != 0)
2614 errx(EXIT_FAILURE, "%s factory requires root privilege", factory->name);
2615
2616 for (int i = 0; i < MAX_N; i++) {
2617 fdescs[i].fd = -1;
2618 fdescs[i].close = NULL;
2619 }
2620
2621 for (int i = 0; i < factory->N; i++) {
2622 char *str = argv[optind + i];
2623 long fd;
2624 char *ep;
2625
2626 errno = 0;
2627 fd = strtol(str, &ep, 10);
2628 if (errno)
2629 err(EXIT_FAILURE, "failed to convert fd number: %s", str);
2630 if (ep == str)
2631 errx(EXIT_FAILURE, "failed to convert fd number: %s", str);
2632 if (*ep != '\0')
2633 errx(EXIT_FAILURE, "garbage at the end of number: %s", str);
2634 if (fd < 0)
2635 errx(EXIT_FAILURE, "fd number should not be negative: %s", str);
2636 if (fd < 3)
2637 errx(EXIT_FAILURE, "fd 0, 1, 2 are reserved: %s", str);
2638 fdescs[i].fd = fd;
2639 }
2640 optind += factory->N;
2641
2642 data = factory->make(factory, fdescs, argc - optind, argv + optind);
2643
2644 signal(SIGCONT, do_nothing);
2645
2646 if (!quiet) {
2647 printf("%d", getpid());
2648 putchar('\n');
2649 if (factory->report)
2650 factory->report(factory, data, stdout);
2651 fflush(stdout);
2652 }
2653
2654 if (!cont)
2655 wait_event();
2656
2657 for (int i = 0; i < factory->N + factory->EX_N; i++)
2658 if (fdescs[i].fd >= 0 && fdescs[i].close)
2659 fdescs[i].close(fdescs[i].fd, fdescs[i].data);
2660
2661 if (factory->free)
2662 factory->free (factory, data);
2663
2664 exit(EXIT_SUCCESS);
2665 }