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 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 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