1 /* $OpenBSD: unixsock_test.c,v 1.3 2024/03/23 01:35:57 mvs Exp $ */
2 /* Written by Claudio Jeker in 2011 */
3 /* Public domain */
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #include <sys/stat.h>
7 #include <sys/un.h>
8 #include <sys/wait.h>
9 #include <err.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15
16 char path[1024];
17 char *dir;
18
19 static int
test_bind(struct sockaddr_un * sun,socklen_t slen)20 test_bind(struct sockaddr_un *sun, socklen_t slen)
21 {
22 int s, e, r;
23
24 s = socket(AF_UNIX, SOCK_STREAM, 0);
25 if (s == -1)
26 err(1, "socket");
27
28 r = bind(s, (struct sockaddr *)sun, slen);
29 e = errno;
30 close(s);
31 sun->sun_path[slen - 2] = '\0';
32 unlink(sun->sun_path);
33 errno = e;
34 return r;
35 }
36
37 static int
test_connect(struct sockaddr_un * sun,socklen_t slen,struct sockaddr_un * b)38 test_connect(struct sockaddr_un *sun, socklen_t slen, struct sockaddr_un *b)
39 {
40 int s, s2, e, r;
41
42 s = socket(AF_UNIX, SOCK_STREAM, 0);
43 if (s == -1)
44 err(1, "socket");
45
46 s2 = socket(AF_UNIX, SOCK_STREAM, 0);
47 if (s2 == -1)
48 err(1, "socket");
49 if (bind(s2, (struct sockaddr *)b, sizeof(*b)) == -1)
50 err(1, "bind");
51 if (listen(s2, 5) == -1)
52 err(1, "listen");
53
54 r = connect(s, (struct sockaddr *)sun, slen);
55 e = errno;
56 close(s);
57 close(s2);
58 unlink(b->sun_path);
59 errno = e;
60 return r;
61 }
62
63 struct test {
64 socklen_t len;
65 int r;
66 } t[] = {
67 {30, 0},
68 {50, 0},
69 {100, 0},
70 {102, 0},
71 {103, 0},
72 {104, -1},
73 {105, -1},
74 {110, -1},
75 {200, -1},
76 {0, 0}
77 };
78
79 int
main(void)80 main(void)
81 {
82 struct sockaddr_storage ss;
83 struct sockaddr_un *sun, sun2;
84 char dir_template[] = "/tmp/peer.XXXXXXXXXX";
85 char aaa[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
86 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
87 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
88 int i, fail = 0;
89
90 dir = mkdtemp(dir_template);
91 if (!dir)
92 err(1, "mkdtemp");
93 if (chdir(dir) == -1)
94 err(1, "chdir");
95 snprintf(path, sizeof path, "%s/%s", dir, "socket");
96
97 for (i = 0; t[i].len != 0; i++) {
98 socklen_t slen = t[i].len;
99 memset(&ss, 0xfe, sizeof(ss));
100 sun = (struct sockaddr_un *)&ss;
101 sun->sun_family = AF_UNIX;
102
103 memset(&sun2, 0, sizeof(sun2));
104 sun2.sun_family = AF_UNIX;
105
106 snprintf(sun->sun_path, sizeof(ss) - 2, "%s.%.*s", path,
107 (int)(slen - strlen(path) - 1), aaa);
108 snprintf(sun2.sun_path, sizeof(sun2) - 2, "%s.%.*s", "socket",
109 (int)(slen - strlen(path) - 1), aaa);
110
111 if (test_bind(sun, slen + 2) != t[i].r) {
112 warn("FAIL: bind(\"%s\") len %d", sun->sun_path,
113 slen + 2);
114 fail = 1;
115 }
116 if (test_bind(sun, slen + 3) != t[i].r) {
117 warn("FAIL2: bind(\"%s\") len %d", sun->sun_path,
118 slen + 3);
119 fail = 1;
120 }
121 if (sizeof(*sun) >= slen + 2 &&
122 test_bind(sun, sizeof(*sun)) != t[i].r) {
123 warn("FAIL3: bind(\"%s\") len %zd", sun->sun_path,
124 sizeof(*sun));
125 fail = 1;
126 }
127 sun->sun_path[slen] = 'a';
128 if (test_bind(sun, slen + 2) != t[i].r) {
129 warn("FAIL4: bind(\"%.*s\") len %d no-NUL",
130 (int)(slen + 2), sun->sun_path, slen + 2);
131 fail = 1;
132 }
133 sun->sun_path[slen] = '\0';
134
135 if (test_connect(sun, slen + 2, &sun2) != t[i].r) {
136 warn("FAIL: connect(\"%s\") len %d", sun->sun_path,
137 slen + 2);
138 fail = 1;
139 }
140 if (test_connect(sun, slen + 3, &sun2) != t[i].r) {
141 warn("FAIL2: connect(\"%s\") len %d", sun->sun_path,
142 slen + 3);
143 fail = 1;
144 }
145 if (sizeof(*sun) >= slen + 2 &&
146 test_connect(sun, sizeof(*sun), &sun2) != t[i].r) {
147 warn("FAIL3: connect(\"%s\") len %zd", sun->sun_path,
148 sizeof(*sun));
149 fail = 1;
150 }
151 sun->sun_path[slen] = 'a';
152 if (test_connect(sun, slen + 2, &sun2) != t[i].r) {
153 warn("FAIL4: connect(\"%.*s\") len %d no-NUL",
154 slen + 2, sun->sun_path, slen + 2);
155 fail = 1;
156 }
157 }
158 return fail;
159 }
160