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