1 /* $OpenBSD: unixsock_test.c,v 1.2 2021/12/15 20:41:28 bluhm 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
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
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
80 main()
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