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 * Go through and test various cases that should fail with setting both
18 * IP_MINTTL and IPV6_MINHOPCOUNT. In particular we want to verify that the
19 * following fail:
20 *
21 * o Testing it on non-IP related sockets (UDS, PF_KEY, etc.)
22 * o Setting IP_MINTTL on an IPv6 socket and IPV6_MINHOPCOUNT on IPv4
23 * o Using negative values on supported sockets
24 * o Using values greater than 255 on supported sockets
25 *
26 * This does not test using the wrong socket level for a given option because
27 * they can end up as valid settings.
28 */
29
30 #include <stdlib.h>
31 #include <err.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/sysmacros.h>
35 #include <errno.h>
36 #include <stdbool.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <netinet/in.h>
40 #include <net/pfkeyv2.h>
41 #include <net/pfpolicy.h>
42
43 typedef struct {
44 const char *me_desc;
45 int me_domain;
46 int me_type;
47 int me_proto;
48 int me_value;
49 int me_level;
50 int me_sockopt;
51 int me_errno;
52 } minttl_err_test_t;
53
54 static const minttl_err_test_t minttl_err_tests[] = {
55 {
56 .me_desc = "IP_MINTTL: UDS SOCK_STREAM not supported",
57 .me_domain = PF_UNIX,
58 .me_type = SOCK_STREAM,
59 .me_level = IPPROTO_IP,
60 .me_sockopt = IP_MINTTL,
61 .me_errno = ENOPROTOOPT
62 }, {
63 .me_desc = "IP_MINTTL: UDS SOCK_DGRAM not supported",
64 .me_domain = PF_UNIX,
65 .me_type = SOCK_DGRAM,
66 .me_level = IPPROTO_IP,
67 .me_sockopt = IP_MINTTL,
68 .me_errno = ENOPROTOOPT
69 }, {
70 .me_desc = "IP_MINTTL: UDS SOCK_SEQPACKET not supported",
71 .me_domain = PF_UNIX,
72 .me_type = SOCK_SEQPACKET,
73 .me_level = IPPROTO_IP,
74 .me_sockopt = IP_MINTTL,
75 .me_errno = ENOPROTOOPT
76 }, {
77 .me_desc = "IP_MINTTL: PF_ROUTE IPv4 not supported",
78 .me_domain = PF_ROUTE,
79 .me_type = SOCK_RAW,
80 .me_proto = AF_INET,
81 .me_level = IPPROTO_IP,
82 .me_sockopt = IP_MINTTL,
83 .me_errno = ENOPROTOOPT
84 }, {
85 .me_desc = "IP_MINTTL: PF_ROUTE IPv6 not supported",
86 .me_domain = PF_ROUTE,
87 .me_type = SOCK_RAW,
88 .me_proto = AF_INET6,
89 .me_level = IPPROTO_IP,
90 .me_sockopt = IP_MINTTL,
91 .me_errno = ENOPROTOOPT
92 }, {
93 .me_desc = "IP_MINTTL: PF_POLICY not supported",
94 .me_domain = PF_POLICY,
95 .me_type = SOCK_RAW,
96 .me_proto = PF_POLICY_V1,
97 .me_level = IPPROTO_IP,
98 .me_sockopt = IP_MINTTL,
99 .me_errno = ENOPROTOOPT
100 }, {
101 .me_desc = "IP_MINTTL: PF_KEY not supported",
102 .me_domain = PF_KEY,
103 .me_type = SOCK_RAW,
104 .me_proto = PF_KEY_V2,
105 .me_level = IPPROTO_IP,
106 .me_sockopt = IP_MINTTL,
107 .me_errno = ENOPROTOOPT
108 }, {
109 .me_desc = "IPV6_MINHOPCOUNT: UDS SOCK_STREAM not supported",
110 .me_domain = PF_UNIX,
111 .me_type = SOCK_STREAM,
112 .me_level = IPPROTO_IPV6,
113 .me_sockopt = IPV6_MINHOPCOUNT,
114 .me_errno = ENOPROTOOPT
115 }, {
116 .me_desc = "IPV6_MINHOPCOUNT: UDS SOCK_DGRAM not supported",
117 .me_domain = PF_UNIX,
118 .me_type = SOCK_DGRAM,
119 .me_level = IPPROTO_IPV6,
120 .me_sockopt = IPV6_MINHOPCOUNT,
121 .me_errno = ENOPROTOOPT
122 }, {
123 .me_desc = "IPV6_MINHOPCOUNT: UDS SOCK_SEQPACKET not supported",
124 .me_domain = PF_UNIX,
125 .me_type = SOCK_SEQPACKET,
126 .me_level = IPPROTO_IPV6,
127 .me_sockopt = IPV6_MINHOPCOUNT,
128 .me_errno = ENOPROTOOPT
129 }, {
130 .me_desc = "IPV6_MINHOPCOUNT: PF_ROUTE IPv4 not supported",
131 .me_domain = PF_ROUTE,
132 .me_type = SOCK_RAW,
133 .me_proto = AF_INET,
134 .me_level = IPPROTO_IPV6,
135 .me_sockopt = IPV6_MINHOPCOUNT,
136 .me_errno = ENOPROTOOPT
137 }, {
138 .me_desc = "IPV6_MINHOPCOUNT: PF_ROUTE IPv6 not supported",
139 .me_domain = PF_ROUTE,
140 .me_type = SOCK_RAW,
141 .me_proto = AF_INET6,
142 .me_level = IPPROTO_IPV6,
143 .me_sockopt = IPV6_MINHOPCOUNT,
144 .me_errno = ENOPROTOOPT
145 }, {
146 .me_desc = "IPV6_MINHOPCOUNT: PF_POLICY not supported",
147 .me_domain = PF_POLICY,
148 .me_type = SOCK_RAW,
149 .me_proto = PF_POLICY_V1,
150 .me_level = IPPROTO_IPV6,
151 .me_sockopt = IPV6_MINHOPCOUNT,
152 .me_errno = ENOPROTOOPT
153 }, {
154 .me_desc = "IPV6_MINHOPCOUNT: PF_KEY not supported",
155 .me_domain = PF_KEY,
156 .me_type = SOCK_RAW,
157 .me_proto = PF_KEY_V2,
158 .me_level = IPPROTO_IPV6,
159 .me_sockopt = IPV6_MINHOPCOUNT,
160 .me_errno = ENOPROTOOPT
161 }, {
162 .me_desc = "IP_MINTTL can't be set on IPv6 TCP socket",
163 .me_domain = PF_INET6,
164 .me_type = SOCK_STREAM,
165 .me_level = IPPROTO_IP,
166 .me_sockopt = IP_MINTTL,
167 .me_errno = EINVAL
168 }, {
169 .me_desc = "IP_MINTTL can't be set on IPv6 UDP socket",
170 .me_domain = PF_INET6,
171 .me_type = SOCK_DGRAM,
172 .me_level = IPPROTO_IP,
173 .me_sockopt = IP_MINTTL,
174 .me_errno = EINVAL
175 }, {
176 .me_desc = "IP_MINTTL can't be set on IPv6 SCTP socket",
177 .me_domain = PF_INET6,
178 .me_type = SOCK_STREAM,
179 .me_proto = IPPROTO_SCTP,
180 .me_level = IPPROTO_IP,
181 .me_sockopt = IP_MINTTL,
182 .me_errno = EINVAL
183 }, {
184 .me_desc = "IPV6_MINHOPCOUNT can't be set on IPv4 TCP socket",
185 .me_domain = PF_INET,
186 .me_type = SOCK_STREAM,
187 .me_level = IPPROTO_IPV6,
188 .me_sockopt = IPV6_MINHOPCOUNT,
189 .me_errno = EINVAL
190 }, {
191 .me_desc = "IPV6_MINHOPCOUNT can't be set on IPv4 UDP socket",
192 .me_domain = PF_INET,
193 .me_type = SOCK_DGRAM,
194 .me_level = IPPROTO_IPV6,
195 .me_sockopt = IPV6_MINHOPCOUNT,
196 .me_errno = EINVAL
197 }, {
198 .me_desc = "IPV6_MINHOPCOUNT can't be set on IPv4 SCTP socket",
199 .me_domain = PF_INET,
200 .me_type = SOCK_STREAM,
201 .me_proto = IPPROTO_SCTP,
202 .me_level = IPPROTO_IPV6,
203 .me_sockopt = IPV6_MINHOPCOUNT,
204 .me_errno = EINVAL
205 }, {
206 .me_desc = "IP_MINTTL: negative value rejected",
207 .me_domain = PF_INET,
208 .me_type = SOCK_STREAM,
209 .me_value = -1,
210 .me_level = IPPROTO_IP,
211 .me_sockopt = IP_MINTTL,
212 .me_errno = EINVAL
213 }, {
214 .me_desc = "IP_MINTTL: larger value rejected",
215 .me_domain = PF_INET,
216 .me_type = SOCK_STREAM,
217 .me_value = 256,
218 .me_level = IPPROTO_IP,
219 .me_sockopt = IP_MINTTL,
220 .me_errno = EINVAL
221 }, {
222 .me_desc = "IPV6_MINHOPCOUNT: negative value rejected",
223 .me_domain = PF_INET6,
224 .me_type = SOCK_STREAM,
225 .me_value = -1,
226 .me_level = IPPROTO_IPV6,
227 .me_sockopt = IPV6_MINHOPCOUNT,
228 .me_errno = EINVAL
229 }, {
230 .me_desc = "IPV6_MINHOPCOUNT: larger value rejected",
231 .me_domain = PF_INET6,
232 .me_type = SOCK_STREAM,
233 .me_value = 256,
234 .me_level = IPPROTO_IPV6,
235 .me_sockopt = IPV6_MINHOPCOUNT,
236 .me_errno = EINVAL
237 }
238 };
239
240 static bool
minttl_err_one(const minttl_err_test_t * test)241 minttl_err_one(const minttl_err_test_t *test)
242 {
243 int sock = -1, val;
244 bool ret = false;
245
246 sock = socket(test->me_domain, test->me_type, test->me_proto);
247 if (sock < 0) {
248 warn("TEST FAILED: %s: failed to create socket", test->me_desc);
249 goto out;
250 }
251
252 val = test->me_value;
253 if (setsockopt(sock, test->me_level, test->me_sockopt, &val,
254 sizeof (val)) != -1) {
255 warnx("TEST FAILED: %s: setsockopt incorrectly passed",
256 test->me_desc);
257 } else if (errno != test->me_errno) {
258 int e = errno;
259 warnx("TEST FAILED: %s: expected errno %s, found %s",
260 test->me_desc, strerrorname_np(test->me_errno),
261 strerrorname_np(e));
262 } else {
263 (void) printf("TEST PASSED: %s\n", test->me_desc);
264 ret = true;
265 }
266 out:
267 if (sock > -1)
268 (void) close(sock);
269 return (ret);
270 }
271
272 int
main(void)273 main(void)
274 {
275 int ret = EXIT_SUCCESS;
276
277 for (size_t i = 0; i < ARRAY_SIZE(minttl_err_tests); i++) {
278 if (!minttl_err_one(&minttl_err_tests[i])) {
279 ret = EXIT_FAILURE;
280 }
281 }
282
283 if (ret == EXIT_SUCCESS) {
284 (void) printf("All tests completed successfully\n");
285 }
286
287 return (ret);
288 }
289