test: Add test for unix socket cross/self reference
[dragonfly.git] / test / unix / loopdesc / loopdesc.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/un.h>
4
5 #include <err.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 static void
12 test_sendto_self(int to_s, int s)
13 {
14         struct msghdr msg;
15         struct iovec iov;
16         union {
17                 struct cmsghdr cm;
18                 uint8_t data[CMSG_SPACE(sizeof(int))];
19         } ctrl;
20         struct cmsghdr *cm;
21         int n, buf;
22
23         iov.iov_base = &buf;
24         iov.iov_len = sizeof(buf);
25
26         memset(&msg, 0, sizeof(msg));
27         msg.msg_iov = &iov;
28         msg.msg_iovlen = 1;
29         msg.msg_control = ctrl.data;
30         msg.msg_controllen = sizeof(ctrl.data);
31
32         memset(&ctrl, 0, sizeof(ctrl));
33         cm = CMSG_FIRSTHDR(&msg);
34         cm->cmsg_len = CMSG_LEN(sizeof(int));
35         cm->cmsg_level = SOL_SOCKET;
36         cm->cmsg_type = SCM_RIGHTS;
37         *((int *)CMSG_DATA(cm)) = s;
38
39         n = sendmsg(to_s, &msg, 0);
40         if (n < 0)
41                 err(1, "sendmsg failed");
42         else if (n != sizeof(buf))
43                 errx(1, "sendmsg sent %d", n);
44 }
45
46 static void
47 usage(const char *cmd)
48 {
49         fprintf(stderr, "%s [-x]\n", cmd);
50         exit(1);
51 }
52
53 int
54 main(int argc, char *argv[])
55 {
56         int s[2], opt, xref;
57
58         xref = 0;
59         while ((opt = getopt(argc, argv, "x")) != -1) {
60                 switch (opt) {
61                 case 'x':
62                         xref = 1;
63                         break;
64
65                 default:
66                         usage(argv[0]);
67                 }
68         }
69
70         if (socketpair(AF_LOCAL, SOCK_STREAM, 0, s) < 0)
71                 err(1, "socketpair(LOCAL, STREAM) failed");
72
73         if (xref) {
74                 fprintf(stderr, "cross reference\n");
75                 /* Send s[0] to s[1].rcvbuf */
76                 test_sendto_self(s[0], s[0]);
77                 /* Send s[1] to s[0].rcvbuf */
78                 test_sendto_self(s[1], s[1]);
79         } else {
80                 fprintf(stderr, "self reference\n");
81                 /* Send s[0] to s[0].rcvbuf */
82                 test_sendto_self(s[1], s[0]);
83                 /* Send s[1] to s[1].rcvbuf */
84                 test_sendto_self(s[0], s[1]);
85         }
86         exit(0);
87 }