accel/qaic: Add AIC200 support
[drm/drm-misc.git] / tools / testing / selftests / net / af_unix / scm_rights.c
blobd663362565803c5115dea179c8c959d6cbf05b68
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright Amazon.com Inc. or its affiliates. */
3 #define _GNU_SOURCE
4 #include <sched.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <sys/un.h>
13 #include "../../kselftest_harness.h"
15 FIXTURE(scm_rights)
17 int fd[32];
20 FIXTURE_VARIANT(scm_rights)
22 char name[32];
23 int type;
24 int flags;
25 bool test_listener;
28 FIXTURE_VARIANT_ADD(scm_rights, dgram)
30 .name = "UNIX ",
31 .type = SOCK_DGRAM,
32 .flags = 0,
33 .test_listener = false,
36 FIXTURE_VARIANT_ADD(scm_rights, stream)
38 .name = "UNIX-STREAM ",
39 .type = SOCK_STREAM,
40 .flags = 0,
41 .test_listener = false,
44 FIXTURE_VARIANT_ADD(scm_rights, stream_oob)
46 .name = "UNIX-STREAM ",
47 .type = SOCK_STREAM,
48 .flags = MSG_OOB,
49 .test_listener = false,
52 FIXTURE_VARIANT_ADD(scm_rights, stream_listener)
54 .name = "UNIX-STREAM ",
55 .type = SOCK_STREAM,
56 .flags = 0,
57 .test_listener = true,
60 FIXTURE_VARIANT_ADD(scm_rights, stream_listener_oob)
62 .name = "UNIX-STREAM ",
63 .type = SOCK_STREAM,
64 .flags = MSG_OOB,
65 .test_listener = true,
68 static int count_sockets(struct __test_metadata *_metadata,
69 const FIXTURE_VARIANT(scm_rights) *variant)
71 int sockets = -1, len, ret;
72 char *line = NULL;
73 size_t unused;
74 FILE *f;
76 f = fopen("/proc/net/protocols", "r");
77 ASSERT_NE(NULL, f);
79 len = strlen(variant->name);
81 while (getline(&line, &unused, f) != -1) {
82 int unused2;
84 if (strncmp(line, variant->name, len))
85 continue;
87 ret = sscanf(line + len, "%d %d", &unused2, &sockets);
88 ASSERT_EQ(2, ret);
90 break;
93 free(line);
95 ret = fclose(f);
96 ASSERT_EQ(0, ret);
98 return sockets;
101 FIXTURE_SETUP(scm_rights)
103 int ret;
105 ret = unshare(CLONE_NEWNET);
106 ASSERT_EQ(0, ret);
108 ret = count_sockets(_metadata, variant);
109 ASSERT_EQ(0, ret);
112 FIXTURE_TEARDOWN(scm_rights)
114 int ret;
116 sleep(1);
118 ret = count_sockets(_metadata, variant);
119 ASSERT_EQ(0, ret);
122 static void create_listeners(struct __test_metadata *_metadata,
123 FIXTURE_DATA(scm_rights) *self,
124 int n)
126 struct sockaddr_un addr = {
127 .sun_family = AF_UNIX,
129 socklen_t addrlen;
130 int i, ret;
132 for (i = 0; i < n * 2; i += 2) {
133 self->fd[i] = socket(AF_UNIX, SOCK_STREAM, 0);
134 ASSERT_LE(0, self->fd[i]);
136 addrlen = sizeof(addr.sun_family);
137 ret = bind(self->fd[i], (struct sockaddr *)&addr, addrlen);
138 ASSERT_EQ(0, ret);
140 ret = listen(self->fd[i], -1);
141 ASSERT_EQ(0, ret);
143 addrlen = sizeof(addr);
144 ret = getsockname(self->fd[i], (struct sockaddr *)&addr, &addrlen);
145 ASSERT_EQ(0, ret);
147 self->fd[i + 1] = socket(AF_UNIX, SOCK_STREAM, 0);
148 ASSERT_LE(0, self->fd[i + 1]);
150 ret = connect(self->fd[i + 1], (struct sockaddr *)&addr, addrlen);
151 ASSERT_EQ(0, ret);
155 static void create_socketpairs(struct __test_metadata *_metadata,
156 FIXTURE_DATA(scm_rights) *self,
157 const FIXTURE_VARIANT(scm_rights) *variant,
158 int n)
160 int i, ret;
162 ASSERT_GE(sizeof(self->fd) / sizeof(int), n);
164 for (i = 0; i < n * 2; i += 2) {
165 ret = socketpair(AF_UNIX, variant->type, 0, self->fd + i);
166 ASSERT_EQ(0, ret);
170 static void __create_sockets(struct __test_metadata *_metadata,
171 FIXTURE_DATA(scm_rights) *self,
172 const FIXTURE_VARIANT(scm_rights) *variant,
173 int n)
175 ASSERT_LE(n * 2, sizeof(self->fd) / sizeof(self->fd[0]));
177 if (variant->test_listener)
178 create_listeners(_metadata, self, n);
179 else
180 create_socketpairs(_metadata, self, variant, n);
183 static void __close_sockets(struct __test_metadata *_metadata,
184 FIXTURE_DATA(scm_rights) *self,
185 int n)
187 int i, ret;
189 ASSERT_GE(sizeof(self->fd) / sizeof(int), n);
191 for (i = 0; i < n * 2; i++) {
192 ret = close(self->fd[i]);
193 ASSERT_EQ(0, ret);
197 void __send_fd(struct __test_metadata *_metadata,
198 const FIXTURE_DATA(scm_rights) *self,
199 const FIXTURE_VARIANT(scm_rights) *variant,
200 int inflight, int receiver)
202 #define MSG "x"
203 #define MSGLEN 1
204 struct {
205 struct cmsghdr cmsghdr;
206 int fd[2];
207 } cmsg = {
208 .cmsghdr = {
209 .cmsg_len = CMSG_LEN(sizeof(cmsg.fd)),
210 .cmsg_level = SOL_SOCKET,
211 .cmsg_type = SCM_RIGHTS,
213 .fd = {
214 self->fd[inflight * 2],
215 self->fd[inflight * 2],
218 struct iovec iov = {
219 .iov_base = MSG,
220 .iov_len = MSGLEN,
222 struct msghdr msg = {
223 .msg_name = NULL,
224 .msg_namelen = 0,
225 .msg_iov = &iov,
226 .msg_iovlen = 1,
227 .msg_control = &cmsg,
228 .msg_controllen = CMSG_SPACE(sizeof(cmsg.fd)),
230 int ret;
232 ret = sendmsg(self->fd[receiver * 2 + 1], &msg, variant->flags);
233 ASSERT_EQ(MSGLEN, ret);
236 #define create_sockets(n) \
237 __create_sockets(_metadata, self, variant, n)
238 #define close_sockets(n) \
239 __close_sockets(_metadata, self, n)
240 #define send_fd(inflight, receiver) \
241 __send_fd(_metadata, self, variant, inflight, receiver)
243 TEST_F(scm_rights, self_ref)
245 create_sockets(2);
247 send_fd(0, 0);
249 send_fd(1, 1);
251 close_sockets(2);
254 TEST_F(scm_rights, triangle)
256 create_sockets(6);
258 send_fd(0, 1);
259 send_fd(1, 2);
260 send_fd(2, 0);
262 send_fd(3, 4);
263 send_fd(4, 5);
264 send_fd(5, 3);
266 close_sockets(6);
269 TEST_F(scm_rights, cross_edge)
271 create_sockets(8);
273 send_fd(0, 1);
274 send_fd(1, 2);
275 send_fd(2, 0);
276 send_fd(1, 3);
277 send_fd(3, 2);
279 send_fd(4, 5);
280 send_fd(5, 6);
281 send_fd(6, 4);
282 send_fd(5, 7);
283 send_fd(7, 6);
285 close_sockets(8);
288 TEST_F(scm_rights, backtrack_from_scc)
290 create_sockets(10);
292 send_fd(0, 1);
293 send_fd(0, 4);
294 send_fd(1, 2);
295 send_fd(2, 3);
296 send_fd(3, 1);
298 send_fd(5, 6);
299 send_fd(5, 9);
300 send_fd(6, 7);
301 send_fd(7, 8);
302 send_fd(8, 6);
304 close_sockets(10);
307 TEST_HARNESS_MAIN