xref: /illumos-gate/usr/src/test/os-tests/tests/minttl/minttl_err.c (revision cdd3e9a818787b4def17c9f707f435885ce0ed31)
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
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
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