1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2024 Oxide Computer Company
14 */
15
16 /*
17 * This is a utility program for the various cp/mv/ln tests to create file
18 * system objects which are not as simple with basic utilities. In particular we
19 * support creating bound unix domain sockets, doors, and throw in a fifo for
20 * good measure (though that's a bit easier).
21 */
22
23 #include <err.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <door.h>
30 #include <stropts.h>
31 #include <string.h>
32 #include <sys/socket.h>
33
34 static void
mkobj_server(void * cookie,char * argp,size_t size,door_desc_t * dp,uint_t ndesc)35 mkobj_server(void *cookie, char *argp, size_t size, door_desc_t *dp,
36 uint_t ndesc)
37 {
38 (void) door_return(NULL, 0, NULL, 0);
39 }
40
41 int
main(int argc,char * argv[])42 main(int argc, char *argv[])
43 {
44 int c;
45 const char *door = NULL;
46 const char *fifo = NULL;
47 const char *uds = NULL;
48
49 while ((c = getopt(argc, argv, ":d:f:s:")) != -1) {
50 switch (c) {
51 case 'd':
52 door = optarg;
53 break;
54 case 'f':
55 fifo = optarg;
56 break;
57 case 's':
58 uds = optarg;
59 break;
60 case ':':
61 errx(EXIT_FAILURE, "option -%c requires an operand", c);
62 case '?':
63 (void) fprintf(stderr, "unknown option: -%c\n", c);
64 (void) fprintf(stderr, "mkobj [-d door] [-f fifo] "
65 "[-s socket]\n");
66 exit(EXIT_FAILURE);
67 }
68 }
69
70 argv += optind;
71 argc -= optind;
72
73 if (argc != 0) {
74 errx(EXIT_FAILURE, "extraneous arguments starting with %s",
75 argv[0]);
76 }
77
78 if (door == NULL && fifo == NULL && uds == NULL) {
79 errx(EXIT_FAILURE, "at least one of -d, -f and -s must be "
80 "specified");
81 }
82
83 if (door != NULL) {
84 int fd;
85
86 if ((fd = open(door, O_CREAT | O_EXCL | O_RDWR, 0666)) < 0) {
87 err(EXIT_FAILURE, "failed to create file %s for door "
88 "server attachment", door);
89 }
90
91 (void) close(fd);
92
93 if ((fd = door_create(mkobj_server, NULL, DOOR_REFUSE_DESC |
94 DOOR_NO_CANCEL)) < 0) {
95 err(EXIT_FAILURE, "failed to create door server");
96 }
97
98 if (fattach(fd, door) != 0) {
99 err(EXIT_FAILURE, "failed to attach door to %s", door);
100 }
101 }
102
103 if (fifo != NULL) {
104 if (mkfifo(fifo, 0666) != 0) {
105 err(EXIT_FAILURE, "failed to make fifo %s", fifo);
106 }
107 }
108
109 if (uds != NULL) {
110 int fd;
111 struct sockaddr_un un;
112
113 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
114 err(EXIT_FAILURE, "failed to create a unix domain "
115 "socket");
116 }
117
118 (void) memset(&un, 0, sizeof (un));
119 un.sun_family = AF_UNIX;
120 if (strlcpy(un.sun_path, uds, sizeof (un.sun_path)) >=
121 sizeof (un.sun_path)) {
122 errx(EXIT_FAILURE, "UDS path %s doesn't fit in "
123 "sockaddr sun_path", uds);
124 }
125
126 if (bind(fd, (struct sockaddr *)&un, sizeof (un)) != 0) {
127 errx(EXIT_FAILURE, "failed to bind uds to %s", uds);
128 }
129 }
130
131 /*
132 * Explicitly exit to ensure that we don't end up letting door threads
133 * stick around.
134 */
135 exit(EXIT_SUCCESS);
136 }
137