if_clone: Check cloner name to avoid duplicate in if_clone_attach()
[dragonfly.git] / test / unix / passdesc / passdesc.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/stat.h>
4 #include <sys/un.h>
5 #include <sys/wait.h>
6
7 #include <err.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13
14 #define TEST_FILENAME   "/tmp/passdesc"
15
16 static int      test_buflen;
17 static void     *test_buf;
18
19 static void
20 test_send_desc(int s, int fd)
21 {
22         struct msghdr msg;
23         struct iovec iov;
24         union {
25                 struct cmsghdr cm;
26                 uint8_t data[CMSG_SPACE(sizeof(int))];
27         } ctrl;
28         struct cmsghdr *cm;
29         int n;
30
31         iov.iov_base = test_buf;
32         iov.iov_len = test_buflen;
33
34         memset(&msg, 0, sizeof(msg));
35         msg.msg_iov = &iov;
36         msg.msg_iovlen = 1;
37         msg.msg_control = ctrl.data;
38         msg.msg_controllen = sizeof(ctrl.data);
39
40         memset(&ctrl, 0, sizeof(ctrl));
41         cm = CMSG_FIRSTHDR(&msg);
42         cm->cmsg_len = CMSG_LEN(sizeof(int));
43         cm->cmsg_level = SOL_SOCKET;
44         cm->cmsg_type = SCM_RIGHTS;
45         *((int *)CMSG_DATA(cm)) = fd;
46
47         n = sendmsg(s, &msg, 0);
48         if (n < 0)
49                 err(1, "sendmsg failed");
50         else if (n != test_buflen)
51                 errx(1, "sendmsg sent %d", n);
52         close(fd);
53 }
54
55 static void
56 test_recv_desc(int s)
57 {
58         struct msghdr msg;
59         struct iovec iov;
60         union {
61                 struct cmsghdr cm;
62                 uint8_t data[CMSG_SPACE(sizeof(int))];
63         } ctrl;
64         struct cmsghdr *cm;
65         int n, fd;
66         char data[16];
67
68         iov.iov_base = test_buf;
69         iov.iov_len = test_buflen;
70
71         memset(&msg, 0, sizeof(msg));
72         msg.msg_iov = &iov;
73         msg.msg_iovlen = 1;
74         msg.msg_control = ctrl.data;
75         msg.msg_controllen = sizeof(ctrl.data);
76
77         n = recvmsg(s, &msg, MSG_WAITALL);
78         if (n < 0)
79                 err(1, "recvmsg failed");
80         else if (n != test_buflen)
81                 errx(1, "recvmsg received %d", n);
82
83         cm = CMSG_FIRSTHDR(&msg);
84         if (cm == NULL)
85                 errx(1, "no cmsg");
86         if (cm->cmsg_len != CMSG_LEN(sizeof(int)))
87                 errx(1, "cmsg len mismatch");
88         if (cm->cmsg_level != SOL_SOCKET)
89                 errx(1, "cmsg level mismatch");
90         if (cm->cmsg_type != SCM_RIGHTS)
91                 errx(1, "cmsg type mismatch");
92
93         fd = *((int *)CMSG_DATA(cm));
94
95         n = read(fd, data, sizeof(data) - 1);
96         if (n < 0)
97                 err(1, "read failed");
98         data[n] = '\0';
99
100         fprintf(stderr, "fd content: %s\n", data);
101 }
102
103 static void
104 usage(const char *cmd)
105 {
106         fprintf(stderr, "%s [-d] [-s] [-p payload_len]\n", cmd);
107         exit(1);
108 }
109
110 int
111 main(int argc, char *argv[])
112 {
113         int s[2], fd, status, n, discard, skipfd;
114         int opt;
115         off_t ofs;
116
117         discard = 0;
118         skipfd = 0;
119         while ((opt = getopt(argc, argv, "dp:s")) != -1) {
120                 switch (opt) {
121                 case 'd':
122                         discard = 1;
123                         break;
124
125                 case 'p':
126                         test_buflen = strtoul(optarg, NULL, 10);
127                         break;
128
129                 case 's':
130                         skipfd = 1;
131                         break;
132
133                 default:
134                         usage(argv[0]);
135                 }
136         }
137
138         if (test_buflen <= 0)
139                 test_buflen = sizeof(int);
140         test_buf = malloc(test_buflen);
141         if (test_buf == NULL)
142                 err(1, "malloc %d failed", test_buflen);
143
144         if (socketpair(AF_LOCAL, SOCK_STREAM, 0, s) < 0)
145                 err(1, "socketpair(LOCAL, STREAM) failed");
146
147         if (fork() == 0) {
148                 close(s[0]);
149                 if (!discard && !skipfd) {
150                         test_recv_desc(s[1]);
151                 } else if (skipfd) {
152                         int buf;
153
154                         fprintf(stderr, "skipfd\n");
155                         n = read(s[1], &buf, sizeof(buf));
156                         if (n < 0)
157                                 err(1, "read failed");
158                 } else {
159                         fprintf(stderr, "discard msg\n");
160                         sleep(5);
161                 }
162                 exit(0);
163         }
164         close(s[1]);
165
166         fd = open(TEST_FILENAME, O_RDWR | O_TRUNC | O_CREAT,
167             S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
168         if (fd < 0)
169                 err(1, "open " TEST_FILENAME " failed");
170
171         n = write(fd, TEST_FILENAME, strlen(TEST_FILENAME));
172         if (n < 0)
173                 err(1, "write failed");
174         else if (n != strlen(TEST_FILENAME))
175                 errx(1, "write %d", n);
176
177         ofs = lseek(fd, 0, SEEK_SET);
178         if (ofs < 0)
179                 err(1, "lseek failed");
180         else if (ofs != 0)
181                 errx(1, "lseek offset %jd", (intmax_t)ofs);
182
183         test_send_desc(s[0], fd);
184
185         wait(&status);
186         exit(0);
187 }