xref: /illumos-gate/usr/src/test/os-tests/tests/sockfs/so_protocol.c (revision b1529121add3ff25fc7b58196363a5439c0f6b67)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2024 Oxide Computer Company
14  */
15 
16 /*
17  * Basic tests to verify that SO_PROTOCOL, SO_DOMAIN, and SO_TYPE perform as we
18  * expect.
19  */
20 
21 #include <stdlib.h>
22 #include <stdbool.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <stdio.h>
26 #include <err.h>
27 #include <unistd.h>
28 #include <sys/sysmacros.h>
29 #include <sys/debug.h>
30 #include <net/pfkeyv2.h>
31 #include <net/pfpolicy.h>
32 
33 typedef struct {
34 	const char *sp_desc;
35 	int sp_dom;
36 	int sp_type;
37 	int sp_prot;
38 	int sp_expprot;
39 	bool sp_noproto;
40 } so_prot_test_t;
41 
42 static const so_prot_test_t so_prot_tests[] = { {
43 	.sp_desc = "IPv4 TCP (prot=0)",
44 	.sp_dom = PF_INET,
45 	.sp_type = SOCK_STREAM,
46 	.sp_prot = 0,
47 	.sp_expprot = IPPROTO_TCP
48 }, {
49 	.sp_desc = "IPv4 TCP (prot=TCP)",
50 	.sp_dom = PF_INET,
51 	.sp_type = SOCK_STREAM,
52 	.sp_prot = IPPROTO_TCP,
53 	.sp_expprot = IPPROTO_TCP
54 }, {
55 	.sp_desc = "IPv4 UDP (prot=0)",
56 	.sp_dom = PF_INET,
57 	.sp_type = SOCK_DGRAM,
58 	.sp_prot = 0,
59 	.sp_expprot = IPPROTO_UDP
60 }, {
61 	.sp_desc = "IPv4 UDP (prot=UDP)",
62 	.sp_dom = PF_INET,
63 	.sp_type = SOCK_DGRAM,
64 	.sp_prot = IPPROTO_UDP,
65 	.sp_expprot = IPPROTO_UDP
66 }, {
67 	.sp_desc = "IPv4 SCTP (type=STREAM)",
68 	.sp_dom = PF_INET,
69 	.sp_type = SOCK_STREAM,
70 	.sp_prot = IPPROTO_SCTP,
71 	.sp_expprot = IPPROTO_SCTP
72 }, {
73 	.sp_desc = "IPv4 SCTP (type=SEQPACKET)",
74 	.sp_dom = PF_INET,
75 	.sp_type = SOCK_SEQPACKET,
76 	.sp_prot = IPPROTO_SCTP,
77 	.sp_expprot = IPPROTO_SCTP
78 }, {
79 	.sp_desc = "IPv6 TCP (prot=0)",
80 	.sp_dom = PF_INET6,
81 	.sp_type = SOCK_STREAM,
82 	.sp_prot = 0,
83 	.sp_expprot = IPPROTO_TCP
84 }, {
85 	.sp_desc = "IPv6 TCP (prot=TCP)",
86 	.sp_dom = PF_INET6,
87 	.sp_type = SOCK_STREAM,
88 	.sp_prot = IPPROTO_TCP,
89 	.sp_expprot = IPPROTO_TCP
90 }, {
91 	.sp_desc = "IPv6 UDP (prot=0)",
92 	.sp_dom = PF_INET6,
93 	.sp_type = SOCK_DGRAM,
94 	.sp_prot = 0,
95 	.sp_expprot = IPPROTO_UDP
96 }, {
97 	.sp_desc = "IPv6 UDP (prot=UDP)",
98 	.sp_dom = PF_INET6,
99 	.sp_type = SOCK_DGRAM,
100 	.sp_prot = IPPROTO_UDP,
101 	.sp_expprot = IPPROTO_UDP
102 }, {
103 	.sp_desc = "IPv6 SCTP (type=STREAM)",
104 	.sp_dom = PF_INET6,
105 	.sp_type = SOCK_STREAM,
106 	.sp_prot = IPPROTO_SCTP,
107 	.sp_expprot = IPPROTO_SCTP
108 }, {
109 	.sp_desc = "IPv6 SCTP (type=SEQPACKET)",
110 	.sp_dom = PF_INET6,
111 	.sp_type = SOCK_SEQPACKET,
112 	.sp_prot = IPPROTO_SCTP,
113 	.sp_expprot = IPPROTO_SCTP
114 }, {
115 	.sp_desc = "UDS (type=STREAM)",
116 	.sp_dom = PF_UNIX,
117 	.sp_type = SOCK_STREAM,
118 	.sp_prot = 0,
119 	.sp_expprot = 0
120 }, {
121 	.sp_desc = "UDS (type=DGRAM)",
122 	.sp_dom = PF_UNIX,
123 	.sp_type = SOCK_DGRAM,
124 	.sp_prot = 0,
125 	.sp_expprot = 0
126 }, {
127 	.sp_desc = "UDS (type=SEQPACKET)",
128 	.sp_dom = PF_UNIX,
129 	.sp_type = SOCK_SEQPACKET,
130 	.sp_prot = 0,
131 	.sp_expprot = 0
132 }, {
133 	.sp_desc = "PF_KEY",
134 	.sp_dom = PF_KEY,
135 	.sp_type = SOCK_RAW,
136 	.sp_prot = PF_KEY_V2,
137 	.sp_expprot = PF_KEY_V2
138 }, {
139 	.sp_desc = "PF_POLICY",
140 	.sp_dom = PF_POLICY,
141 	.sp_type = SOCK_RAW,
142 	.sp_prot = PF_POLICY_V1,
143 	.sp_expprot = PF_POLICY_V1
144 }, {
145 	.sp_desc = "ICMP",
146 	.sp_dom = PF_INET,
147 	.sp_type = SOCK_RAW,
148 	.sp_prot = IPPROTO_ICMP,
149 	.sp_expprot = IPPROTO_ICMP
150 }, {
151 	.sp_desc = "ICMPv6",
152 	.sp_dom = PF_INET6,
153 	.sp_type = SOCK_RAW,
154 	.sp_prot = IPPROTO_ICMPV6,
155 	.sp_expprot = IPPROTO_ICMPV6
156 }, {
157 	.sp_desc = "PF_ROUTE (IPv4)",
158 	.sp_dom = PF_ROUTE,
159 	.sp_type = SOCK_RAW,
160 	.sp_prot = AF_INET,
161 	.sp_expprot = AF_INET
162 }, {
163 	.sp_desc = "PF_ROUTE (IPv6)",
164 	.sp_dom = PF_ROUTE,
165 	.sp_type = SOCK_RAW,
166 	.sp_prot = AF_INET6,
167 	.sp_expprot = AF_INET6
168 }, {
169 	.sp_desc = "PF_ROUTE (IPv4+IPv6)",
170 	.sp_dom = PF_ROUTE,
171 	.sp_type = SOCK_RAW,
172 	.sp_prot = 0,
173 	.sp_expprot = 0
174 }, {
175 	.sp_desc = "Trill",
176 	.sp_dom = PF_TRILL,
177 	.sp_type = SOCK_DGRAM,
178 	.sp_prot = 0,
179 	.sp_expprot = 0
180 }  };
181 
182 static bool
183 so_test_one(const so_prot_test_t *test)
184 {
185 	int s, opt;
186 	socklen_t len;
187 	bool ret = true;
188 
189 	s = socket(test->sp_dom, test->sp_type, test->sp_prot);
190 	if (s < 0) {
191 		warn("TEST FAILED: %s: failed to create socket with "
192 		    "domain/type/protocol 0x%x/0x%x/0x%x", test->sp_desc,
193 		    test->sp_dom, test->sp_type, test->sp_prot);
194 		return (false);
195 	}
196 
197 	len = sizeof (opt);
198 	if (getsockopt(s, SOL_SOCKET, SO_DOMAIN, &opt, &len) != 0) {
199 		warn("TEST FAILED: %s: failed to get SO_DOMAIN", test->sp_desc);
200 		ret = false;
201 	} else if (opt != test->sp_dom) {
202 		warnx("TEST FAILED: %s: expected domain 0x%x, but found 0x%x",
203 		    test->sp_desc, test->sp_dom, opt);
204 		ret = false;
205 	} else {
206 		(void) printf("TEST PASSED: %s: received correct domain\n",
207 		    test->sp_desc);
208 	}
209 
210 	len = sizeof (opt);
211 	if (getsockopt(s, SOL_SOCKET, SO_TYPE, &opt, &len) != 0) {
212 		warn("TEST FAILED: %s: failed to get SO_TYPE", test->sp_desc);
213 		ret = false;
214 	} else if (opt != test->sp_type) {
215 		warnx("TEST FAILED: %s: expected type 0x%x, but found 0x%x",
216 		    test->sp_desc, test->sp_type, opt);
217 		ret = false;
218 	} else {
219 		(void) printf("TEST PASSED: %s: received correct type\n",
220 		    test->sp_desc);
221 	}
222 
223 	len = sizeof (opt);
224 	if (getsockopt(s, SOL_SOCKET, SO_PROTOCOL, &opt, &len) != 0) {
225 		warn("TEST FAILED: %s: failed to get SO_PROTOCOL",
226 		    test->sp_desc);
227 		ret = false;
228 	} else if (opt != test->sp_expprot) {
229 		warnx("TEST FAILED: %s: expected protocol 0x%x, but found 0x%x",
230 		    test->sp_desc, test->sp_expprot, opt);
231 		ret = false;
232 	} else {
233 		(void) printf("TEST PASSED: %s: received correct protocol\n",
234 		    test->sp_desc);
235 	}
236 
237 	VERIFY0(close(s));
238 	return (ret);
239 }
240 
241 int
242 main(void)
243 {
244 	int ret = EXIT_SUCCESS;
245 
246 	for (size_t i = 0; i < ARRAY_SIZE(so_prot_tests); i++) {
247 		if (!so_test_one(&so_prot_tests[i]))
248 			ret = EXIT_FAILURE;
249 	}
250 
251 	if (ret == EXIT_SUCCESS)
252 		(void) printf("All tests passed successfully\n");
253 	return (ret);
254 }
255