xref: /linux/tools/testing/selftests/net/af_unix/unix_connect.c (revision e95ab1d852897a0b697cd0fb609d496ce97fff3a)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #define _GNU_SOURCE
4 #include <sched.h>
5 
6 #include <stdio.h>
7 #include <unistd.h>
8 
9 #include <sys/socket.h>
10 #include <sys/un.h>
11 
12 #include "../../kselftest_harness.h"
13 
14 FIXTURE(unix_connect)
15 {
16 	int server, client;
17 	int family;
18 };
19 
20 FIXTURE_VARIANT(unix_connect)
21 {
22 	int type;
23 	char sun_path[8];
24 	int len;
25 	int flags;
26 	int err;
27 };
28 
29 FIXTURE_VARIANT_ADD(unix_connect, stream_pathname)
30 {
31 	.type = SOCK_STREAM,
32 	.sun_path = "test",
33 	.len = 4 + 1,
34 	.flags = 0,
35 	.err = 0,
36 };
37 
38 FIXTURE_VARIANT_ADD(unix_connect, stream_abstract)
39 {
40 	.type = SOCK_STREAM,
41 	.sun_path = "\0test",
42 	.len = 5,
43 	.flags = 0,
44 	.err = 0,
45 };
46 
47 FIXTURE_VARIANT_ADD(unix_connect, stream_pathname_netns)
48 {
49 	.type = SOCK_STREAM,
50 	.sun_path = "test",
51 	.len = 4 + 1,
52 	.flags = CLONE_NEWNET,
53 	.err = 0,
54 };
55 
56 FIXTURE_VARIANT_ADD(unix_connect, stream_abstract_netns)
57 {
58 	.type = SOCK_STREAM,
59 	.sun_path = "\0test",
60 	.len = 5,
61 	.flags = CLONE_NEWNET,
62 	.err = ECONNREFUSED,
63 };
64 
65 FIXTURE_VARIANT_ADD(unix_connect, dgram_pathname)
66 {
67 	.type = SOCK_DGRAM,
68 	.sun_path = "test",
69 	.len = 4 + 1,
70 	.flags = 0,
71 	.err = 0,
72 };
73 
74 FIXTURE_VARIANT_ADD(unix_connect, dgram_abstract)
75 {
76 	.type = SOCK_DGRAM,
77 	.sun_path = "\0test",
78 	.len = 5,
79 	.flags = 0,
80 	.err = 0,
81 };
82 
83 FIXTURE_VARIANT_ADD(unix_connect, dgram_pathname_netns)
84 {
85 	.type = SOCK_DGRAM,
86 	.sun_path = "test",
87 	.len = 4 + 1,
88 	.flags = CLONE_NEWNET,
89 	.err = 0,
90 };
91 
92 FIXTURE_VARIANT_ADD(unix_connect, dgram_abstract_netns)
93 {
94 	.type = SOCK_DGRAM,
95 	.sun_path = "\0test",
96 	.len = 5,
97 	.flags = CLONE_NEWNET,
98 	.err = ECONNREFUSED,
99 };
100 
101 FIXTURE_SETUP(unix_connect)
102 {
103 	self->family = AF_UNIX;
104 }
105 
106 FIXTURE_TEARDOWN(unix_connect)
107 {
108 	close(self->server);
109 	close(self->client);
110 
111 	if (variant->sun_path[0])
112 		remove("test");
113 }
114 
115 #define offsetof(type, member) ((size_t)&((type *)0)->(member))
116 
117 TEST_F(unix_connect, test)
118 {
119 	socklen_t addrlen;
120 	struct sockaddr_un addr = {
121 		.sun_family = self->family,
122 	};
123 	int err;
124 
125 	self->server = socket(self->family, variant->type, 0);
126 	ASSERT_NE(-1, self->server);
127 
128 	addrlen = offsetof(struct sockaddr_un, sun_path) + variant->len;
129 	memcpy(&addr.sun_path, variant->sun_path, variant->len);
130 
131 	err = bind(self->server, (struct sockaddr *)&addr, addrlen);
132 	ASSERT_EQ(0, err);
133 
134 	if (variant->type == SOCK_STREAM) {
135 		err = listen(self->server, 32);
136 		ASSERT_EQ(0, err);
137 	}
138 
139 	err = unshare(variant->flags);
140 	ASSERT_EQ(0, err);
141 
142 	self->client = socket(self->family, variant->type, 0);
143 	ASSERT_LT(0, self->client);
144 
145 	err = connect(self->client, (struct sockaddr *)&addr, addrlen);
146 	ASSERT_EQ(variant->err, err == -1 ? errno : 0);
147 }
148 
149 TEST_HARNESS_MAIN
150