1*e8249070SRobert Mustacchi /*
2*e8249070SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*e8249070SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*e8249070SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*e8249070SRobert Mustacchi * 1.0 of the CDDL.
6*e8249070SRobert Mustacchi *
7*e8249070SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*e8249070SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*e8249070SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*e8249070SRobert Mustacchi */
11*e8249070SRobert Mustacchi
12*e8249070SRobert Mustacchi /*
13*e8249070SRobert Mustacchi * Copyright 2024 Oxide Computer Company
14*e8249070SRobert Mustacchi */
15*e8249070SRobert Mustacchi
16*e8249070SRobert Mustacchi /*
17*e8249070SRobert Mustacchi * Basic set of tests for IP_MINTTL and IPV6_MINHOPCOUNT. The main design of
18*e8249070SRobert Mustacchi * this is to spin up connections on localhost that walk through different
19*e8249070SRobert Mustacchi * socket types and confirm that we can use the corresponding socket option and
20*e8249070SRobert Mustacchi * that we receive traffic when the TTL is set and not otherwise.
21*e8249070SRobert Mustacchi */
22*e8249070SRobert Mustacchi
23*e8249070SRobert Mustacchi #include <err.h>
24*e8249070SRobert Mustacchi #include <port.h>
25*e8249070SRobert Mustacchi #include <stdlib.h>
26*e8249070SRobert Mustacchi #include <sys/types.h>
27*e8249070SRobert Mustacchi #include <sys/socket.h>
28*e8249070SRobert Mustacchi #include <netinet/in.h>
29*e8249070SRobert Mustacchi #include <netinet/sctp.h>
30*e8249070SRobert Mustacchi #include <arpa/inet.h>
31*e8249070SRobert Mustacchi #include <sys/sysmacros.h>
32*e8249070SRobert Mustacchi #include <stdbool.h>
33*e8249070SRobert Mustacchi #include <unistd.h>
34*e8249070SRobert Mustacchi #include <string.h>
35*e8249070SRobert Mustacchi #include <errno.h>
36*e8249070SRobert Mustacchi #include <sys/debug.h>
37*e8249070SRobert Mustacchi
38*e8249070SRobert Mustacchi /*
39*e8249070SRobert Mustacchi * The IP protocols 0xfd-0xfe are reserved for experiments. This is the safest
40*e8249070SRobert Mustacchi * IP protocol for us to use then in our testing for raw sockets.
41*e8249070SRobert Mustacchi */
42*e8249070SRobert Mustacchi #define TTL_IPPROTO_EXP 0xfd
43*e8249070SRobert Mustacchi
44*e8249070SRobert Mustacchi static hrtime_t tt_sock_to = MSEC2NSEC(100); /* ms in ns */
45*e8249070SRobert Mustacchi static const uint32_t tt_msg = 0x7777;
46*e8249070SRobert Mustacchi
47*e8249070SRobert Mustacchi typedef enum {
48*e8249070SRobert Mustacchi TTL_SENDRECV,
49*e8249070SRobert Mustacchi TTL_NOCONNECT,
50*e8249070SRobert Mustacchi TTL_NODATA
51*e8249070SRobert Mustacchi } ttl_pass_t;
52*e8249070SRobert Mustacchi
53*e8249070SRobert Mustacchi typedef struct {
54*e8249070SRobert Mustacchi const char *tt_desc;
55*e8249070SRobert Mustacchi int tt_domain;
56*e8249070SRobert Mustacchi int tt_type;
57*e8249070SRobert Mustacchi int tt_ttl;
58*e8249070SRobert Mustacchi int tt_proto;
59*e8249070SRobert Mustacchi int tt_minttl;
60*e8249070SRobert Mustacchi ttl_pass_t tt_pass;
61*e8249070SRobert Mustacchi } ttl_test_t;
62*e8249070SRobert Mustacchi
63*e8249070SRobert Mustacchi static const ttl_test_t ttl_tests[] = {
64*e8249070SRobert Mustacchi {
65*e8249070SRobert Mustacchi .tt_desc = "IPv4 TCP TTL/MIN: unset/0",
66*e8249070SRobert Mustacchi .tt_domain = PF_INET,
67*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
68*e8249070SRobert Mustacchi .tt_ttl = 0,
69*e8249070SRobert Mustacchi .tt_minttl = 0,
70*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
71*e8249070SRobert Mustacchi }, {
72*e8249070SRobert Mustacchi .tt_desc = "IPv4 TCP TTL/MIN: 200/100",
73*e8249070SRobert Mustacchi .tt_domain = PF_INET,
74*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
75*e8249070SRobert Mustacchi .tt_ttl = 200,
76*e8249070SRobert Mustacchi .tt_minttl = 100,
77*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
78*e8249070SRobert Mustacchi }, {
79*e8249070SRobert Mustacchi .tt_desc = "IPv4 TCP TTL/MIN: 255/255",
80*e8249070SRobert Mustacchi .tt_domain = PF_INET,
81*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
82*e8249070SRobert Mustacchi .tt_ttl = 255,
83*e8249070SRobert Mustacchi .tt_minttl = 255,
84*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
85*e8249070SRobert Mustacchi }, {
86*e8249070SRobert Mustacchi .tt_desc = "IPv4 TCP TTL/MIN: 23/169",
87*e8249070SRobert Mustacchi .tt_domain = PF_INET,
88*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
89*e8249070SRobert Mustacchi .tt_ttl = 23,
90*e8249070SRobert Mustacchi .tt_minttl = 169,
91*e8249070SRobert Mustacchi .tt_pass = TTL_NOCONNECT
92*e8249070SRobert Mustacchi }, {
93*e8249070SRobert Mustacchi .tt_desc = "IPv4 TCP TTL/MIN: 254/255",
94*e8249070SRobert Mustacchi .tt_domain = PF_INET,
95*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
96*e8249070SRobert Mustacchi .tt_ttl = 254,
97*e8249070SRobert Mustacchi .tt_minttl = 255,
98*e8249070SRobert Mustacchi .tt_pass = TTL_NOCONNECT
99*e8249070SRobert Mustacchi }, {
100*e8249070SRobert Mustacchi .tt_desc = "IPv4 UDP TTL/MIN: unset/0",
101*e8249070SRobert Mustacchi .tt_domain = PF_INET,
102*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
103*e8249070SRobert Mustacchi .tt_ttl = 0,
104*e8249070SRobert Mustacchi .tt_minttl = 0,
105*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
106*e8249070SRobert Mustacchi }, {
107*e8249070SRobert Mustacchi .tt_desc = "IPv4 UDP TTL/MIN: 200/100",
108*e8249070SRobert Mustacchi .tt_domain = PF_INET,
109*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
110*e8249070SRobert Mustacchi .tt_ttl = 200,
111*e8249070SRobert Mustacchi .tt_minttl = 100,
112*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
113*e8249070SRobert Mustacchi }, {
114*e8249070SRobert Mustacchi .tt_desc = "IPv4 UDP TTL/MIN: 255/255",
115*e8249070SRobert Mustacchi .tt_domain = PF_INET,
116*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
117*e8249070SRobert Mustacchi .tt_ttl = 255,
118*e8249070SRobert Mustacchi .tt_minttl = 255,
119*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
120*e8249070SRobert Mustacchi }, {
121*e8249070SRobert Mustacchi .tt_desc = "IPv4 UDP TTL/MIN: 23/169",
122*e8249070SRobert Mustacchi .tt_domain = PF_INET,
123*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
124*e8249070SRobert Mustacchi .tt_ttl = 23,
125*e8249070SRobert Mustacchi .tt_minttl = 169,
126*e8249070SRobert Mustacchi .tt_pass = TTL_NODATA
127*e8249070SRobert Mustacchi }, {
128*e8249070SRobert Mustacchi .tt_desc = "IPv4 UDP TTL/MIN: 254/255",
129*e8249070SRobert Mustacchi .tt_domain = PF_INET,
130*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
131*e8249070SRobert Mustacchi .tt_ttl = 254,
132*e8249070SRobert Mustacchi .tt_minttl = 255,
133*e8249070SRobert Mustacchi .tt_pass = TTL_NODATA
134*e8249070SRobert Mustacchi }, {
135*e8249070SRobert Mustacchi .tt_desc = "IPv4 SCTP TTL/MIN: unset/0",
136*e8249070SRobert Mustacchi .tt_domain = PF_INET,
137*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
138*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
139*e8249070SRobert Mustacchi .tt_ttl = 0,
140*e8249070SRobert Mustacchi .tt_minttl = 0,
141*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
142*e8249070SRobert Mustacchi }, {
143*e8249070SRobert Mustacchi .tt_desc = "IPv4 SCTP TTL/MIN: 200/100",
144*e8249070SRobert Mustacchi .tt_domain = PF_INET,
145*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
146*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
147*e8249070SRobert Mustacchi .tt_ttl = 200,
148*e8249070SRobert Mustacchi .tt_minttl = 100,
149*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
150*e8249070SRobert Mustacchi }, {
151*e8249070SRobert Mustacchi .tt_desc = "IPv4 SCTP TTL/MIN: 255/255",
152*e8249070SRobert Mustacchi .tt_domain = PF_INET,
153*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
154*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
155*e8249070SRobert Mustacchi .tt_ttl = 255,
156*e8249070SRobert Mustacchi .tt_minttl = 255,
157*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
158*e8249070SRobert Mustacchi }, {
159*e8249070SRobert Mustacchi .tt_desc = "IPv4 SCTP TTL/MIN: 23/169",
160*e8249070SRobert Mustacchi .tt_domain = PF_INET,
161*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
162*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
163*e8249070SRobert Mustacchi .tt_ttl = 23,
164*e8249070SRobert Mustacchi .tt_minttl = 169,
165*e8249070SRobert Mustacchi .tt_pass = TTL_NOCONNECT
166*e8249070SRobert Mustacchi }, {
167*e8249070SRobert Mustacchi .tt_desc = "IPv4 SCTP TTL/MIN: 254/255",
168*e8249070SRobert Mustacchi .tt_domain = PF_INET,
169*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
170*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
171*e8249070SRobert Mustacchi .tt_ttl = 254,
172*e8249070SRobert Mustacchi .tt_minttl = 255,
173*e8249070SRobert Mustacchi .tt_pass = TTL_NOCONNECT
174*e8249070SRobert Mustacchi }, {
175*e8249070SRobert Mustacchi .tt_desc = "IPv4 RAW (0xfd) TTL/MIN: unset/0",
176*e8249070SRobert Mustacchi .tt_domain = PF_INET,
177*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
178*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
179*e8249070SRobert Mustacchi .tt_ttl = 0,
180*e8249070SRobert Mustacchi .tt_minttl = 0,
181*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
182*e8249070SRobert Mustacchi }, {
183*e8249070SRobert Mustacchi .tt_desc = "IPv4 RAW (0xfd) TTL/MIN: 200/100",
184*e8249070SRobert Mustacchi .tt_domain = PF_INET,
185*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
186*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
187*e8249070SRobert Mustacchi .tt_ttl = 200,
188*e8249070SRobert Mustacchi .tt_minttl = 100,
189*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
190*e8249070SRobert Mustacchi }, {
191*e8249070SRobert Mustacchi .tt_desc = "IPv4 RAW (0xfd) TTL/MIN: 255/255",
192*e8249070SRobert Mustacchi .tt_domain = PF_INET,
193*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
194*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
195*e8249070SRobert Mustacchi .tt_ttl = 255,
196*e8249070SRobert Mustacchi .tt_minttl = 255,
197*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
198*e8249070SRobert Mustacchi }, {
199*e8249070SRobert Mustacchi .tt_desc = "IPv4 RAW (0xfd) TTL/MIN: 23/169",
200*e8249070SRobert Mustacchi .tt_domain = PF_INET,
201*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
202*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
203*e8249070SRobert Mustacchi .tt_ttl = 23,
204*e8249070SRobert Mustacchi .tt_minttl = 169,
205*e8249070SRobert Mustacchi .tt_pass = TTL_NODATA
206*e8249070SRobert Mustacchi }, {
207*e8249070SRobert Mustacchi .tt_desc = "IPv4 RAW (0xfd) TTL/MIN: 254/255",
208*e8249070SRobert Mustacchi .tt_domain = PF_INET,
209*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
210*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
211*e8249070SRobert Mustacchi .tt_ttl = 254,
212*e8249070SRobert Mustacchi .tt_minttl = 255,
213*e8249070SRobert Mustacchi .tt_pass = TTL_NODATA
214*e8249070SRobert Mustacchi }, {
215*e8249070SRobert Mustacchi .tt_desc = "IPv6 TCP TTL/MIN: unset/0",
216*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
217*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
218*e8249070SRobert Mustacchi .tt_ttl = 0,
219*e8249070SRobert Mustacchi .tt_minttl = 0,
220*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
221*e8249070SRobert Mustacchi }, {
222*e8249070SRobert Mustacchi .tt_desc = "IPv6 TCP TTL/MIN: 200/100",
223*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
224*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
225*e8249070SRobert Mustacchi .tt_ttl = 200,
226*e8249070SRobert Mustacchi .tt_minttl = 100,
227*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
228*e8249070SRobert Mustacchi }, {
229*e8249070SRobert Mustacchi .tt_desc = "IPv6 TCP TTL/MIN: 255/255",
230*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
231*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
232*e8249070SRobert Mustacchi .tt_ttl = 255,
233*e8249070SRobert Mustacchi .tt_minttl = 255,
234*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
235*e8249070SRobert Mustacchi }, {
236*e8249070SRobert Mustacchi .tt_desc = "IPv6 CTP TTL/MIN: 23/169",
237*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
238*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
239*e8249070SRobert Mustacchi .tt_ttl = 23,
240*e8249070SRobert Mustacchi .tt_minttl = 169,
241*e8249070SRobert Mustacchi .tt_pass = TTL_NOCONNECT
242*e8249070SRobert Mustacchi }, {
243*e8249070SRobert Mustacchi .tt_desc = "IPv6 CTP TTL/MIN: 254/255",
244*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
245*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
246*e8249070SRobert Mustacchi .tt_ttl = 254,
247*e8249070SRobert Mustacchi .tt_minttl = 255,
248*e8249070SRobert Mustacchi .tt_pass = TTL_NOCONNECT
249*e8249070SRobert Mustacchi }, {
250*e8249070SRobert Mustacchi .tt_desc = "IPv6 UDP TTL/MIN: unset/0",
251*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
252*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
253*e8249070SRobert Mustacchi .tt_ttl = 0,
254*e8249070SRobert Mustacchi .tt_minttl = 0,
255*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
256*e8249070SRobert Mustacchi }, {
257*e8249070SRobert Mustacchi .tt_desc = "IPv6 UDP TTL/MIN: 200/100",
258*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
259*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
260*e8249070SRobert Mustacchi .tt_ttl = 200,
261*e8249070SRobert Mustacchi .tt_minttl = 100,
262*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
263*e8249070SRobert Mustacchi }, {
264*e8249070SRobert Mustacchi .tt_desc = "IPv6 UDP TTL/MIN: 255/255",
265*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
266*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
267*e8249070SRobert Mustacchi .tt_ttl = 255,
268*e8249070SRobert Mustacchi .tt_minttl = 255,
269*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
270*e8249070SRobert Mustacchi }, {
271*e8249070SRobert Mustacchi .tt_desc = "IPv6 UDP TTL/MIN: 23/169",
272*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
273*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
274*e8249070SRobert Mustacchi .tt_ttl = 23,
275*e8249070SRobert Mustacchi .tt_minttl = 169,
276*e8249070SRobert Mustacchi .tt_pass = TTL_NODATA
277*e8249070SRobert Mustacchi }, {
278*e8249070SRobert Mustacchi .tt_desc = "IPv6 UDP TTL/MIN: 254/255",
279*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
280*e8249070SRobert Mustacchi .tt_type = SOCK_DGRAM,
281*e8249070SRobert Mustacchi .tt_ttl = 254,
282*e8249070SRobert Mustacchi .tt_minttl = 255,
283*e8249070SRobert Mustacchi .tt_pass = TTL_NODATA
284*e8249070SRobert Mustacchi }, {
285*e8249070SRobert Mustacchi .tt_desc = "IPv6 SCTP TTL/MIN: unset/0",
286*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
287*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
288*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
289*e8249070SRobert Mustacchi .tt_ttl = 0,
290*e8249070SRobert Mustacchi .tt_minttl = 0,
291*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
292*e8249070SRobert Mustacchi }, {
293*e8249070SRobert Mustacchi .tt_desc = "IPv6 SCTP TTL/MIN: 200/100",
294*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
295*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
296*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
297*e8249070SRobert Mustacchi .tt_ttl = 200,
298*e8249070SRobert Mustacchi .tt_minttl = 100,
299*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
300*e8249070SRobert Mustacchi }, {
301*e8249070SRobert Mustacchi .tt_desc = "IPv6 SCTP TTL/MIN: 255/255",
302*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
303*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
304*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
305*e8249070SRobert Mustacchi .tt_ttl = 255,
306*e8249070SRobert Mustacchi .tt_minttl = 255,
307*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
308*e8249070SRobert Mustacchi }, {
309*e8249070SRobert Mustacchi .tt_desc = "IPv6 SCTP TTL/MIN: 23/169",
310*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
311*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
312*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
313*e8249070SRobert Mustacchi .tt_ttl = 23,
314*e8249070SRobert Mustacchi .tt_minttl = 169,
315*e8249070SRobert Mustacchi .tt_pass = TTL_NOCONNECT
316*e8249070SRobert Mustacchi }, {
317*e8249070SRobert Mustacchi .tt_desc = "IPv6 SCTP TTL/MIN: 254/255",
318*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
319*e8249070SRobert Mustacchi .tt_type = SOCK_STREAM,
320*e8249070SRobert Mustacchi .tt_proto = IPPROTO_SCTP,
321*e8249070SRobert Mustacchi .tt_ttl = 254,
322*e8249070SRobert Mustacchi .tt_minttl = 255,
323*e8249070SRobert Mustacchi .tt_pass = TTL_NOCONNECT
324*e8249070SRobert Mustacchi }, {
325*e8249070SRobert Mustacchi .tt_desc = "IPv6 RAW (0xfd) TTL/MIN: unset/0",
326*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
327*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
328*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
329*e8249070SRobert Mustacchi .tt_ttl = 0,
330*e8249070SRobert Mustacchi .tt_minttl = 0,
331*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
332*e8249070SRobert Mustacchi }, {
333*e8249070SRobert Mustacchi .tt_desc = "IPv6 RAW (0xfd) TTL/MIN: 200/100",
334*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
335*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
336*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
337*e8249070SRobert Mustacchi .tt_ttl = 200,
338*e8249070SRobert Mustacchi .tt_minttl = 100,
339*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
340*e8249070SRobert Mustacchi }, {
341*e8249070SRobert Mustacchi .tt_desc = "IPv6 RAW (0xfd) TTL/MIN: 255/255",
342*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
343*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
344*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
345*e8249070SRobert Mustacchi .tt_ttl = 255,
346*e8249070SRobert Mustacchi .tt_minttl = 255,
347*e8249070SRobert Mustacchi .tt_pass = TTL_SENDRECV
348*e8249070SRobert Mustacchi }, {
349*e8249070SRobert Mustacchi .tt_desc = "IPv6 RAW (0xfd) TTL/MIN: 23/169",
350*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
351*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
352*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
353*e8249070SRobert Mustacchi .tt_ttl = 23,
354*e8249070SRobert Mustacchi .tt_minttl = 169,
355*e8249070SRobert Mustacchi .tt_pass = TTL_NODATA
356*e8249070SRobert Mustacchi }, {
357*e8249070SRobert Mustacchi .tt_desc = "IPv6 RAW (0xfd) TTL/MIN: 254/255",
358*e8249070SRobert Mustacchi .tt_domain = PF_INET6,
359*e8249070SRobert Mustacchi .tt_type = SOCK_RAW,
360*e8249070SRobert Mustacchi .tt_proto = TTL_IPPROTO_EXP,
361*e8249070SRobert Mustacchi .tt_ttl = 254,
362*e8249070SRobert Mustacchi .tt_minttl = 255,
363*e8249070SRobert Mustacchi .tt_pass = TTL_NODATA
364*e8249070SRobert Mustacchi }
365*e8249070SRobert Mustacchi };
366*e8249070SRobert Mustacchi
367*e8249070SRobert Mustacchi static bool
ttl_bind_dest(const ttl_test_t * test,int sock,struct sockaddr_storage * dst)368*e8249070SRobert Mustacchi ttl_bind_dest(const ttl_test_t *test, int sock, struct sockaddr_storage *dst)
369*e8249070SRobert Mustacchi {
370*e8249070SRobert Mustacchi socklen_t len;
371*e8249070SRobert Mustacchi struct sockaddr_storage addr;
372*e8249070SRobert Mustacchi
373*e8249070SRobert Mustacchi (void) memset(&addr, 0, sizeof (struct sockaddr_storage));
374*e8249070SRobert Mustacchi
375*e8249070SRobert Mustacchi if (test->tt_domain == PF_INET) {
376*e8249070SRobert Mustacchi struct sockaddr_in *in = (struct sockaddr_in *)&addr;
377*e8249070SRobert Mustacchi in->sin_family = AF_INET;
378*e8249070SRobert Mustacchi in->sin_port = htons(0);
379*e8249070SRobert Mustacchi if (inet_pton(AF_INET, "127.0.0.1", &in->sin_addr) != 1) {
380*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: failed to convert 127.0.0.1 "
381*e8249070SRobert Mustacchi "to an IPv4 address", test->tt_desc);
382*e8249070SRobert Mustacchi return (false);
383*e8249070SRobert Mustacchi }
384*e8249070SRobert Mustacchi len = sizeof (struct sockaddr_in);
385*e8249070SRobert Mustacchi } else {
386*e8249070SRobert Mustacchi struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
387*e8249070SRobert Mustacchi in6->sin6_family = AF_INET6;
388*e8249070SRobert Mustacchi in6->sin6_port = htons(0);
389*e8249070SRobert Mustacchi if (inet_pton(AF_INET6, "::1", &in6->sin6_addr) != 1) {
390*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: failed to convert ::1 "
391*e8249070SRobert Mustacchi "to an IPv6 address", test->tt_desc);
392*e8249070SRobert Mustacchi return (false);
393*e8249070SRobert Mustacchi }
394*e8249070SRobert Mustacchi len = sizeof (struct sockaddr_in6);
395*e8249070SRobert Mustacchi }
396*e8249070SRobert Mustacchi
397*e8249070SRobert Mustacchi if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
398*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to bind listen socket",
399*e8249070SRobert Mustacchi test->tt_desc);
400*e8249070SRobert Mustacchi return (false);
401*e8249070SRobert Mustacchi }
402*e8249070SRobert Mustacchi
403*e8249070SRobert Mustacchi len = sizeof (struct sockaddr_storage);
404*e8249070SRobert Mustacchi if (getsockname(sock, (struct sockaddr *)dst, &len) != 0) {
405*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to retrieve socket address ",
406*e8249070SRobert Mustacchi test->tt_desc);
407*e8249070SRobert Mustacchi return (false);
408*e8249070SRobert Mustacchi }
409*e8249070SRobert Mustacchi
410*e8249070SRobert Mustacchi return (true);
411*e8249070SRobert Mustacchi }
412*e8249070SRobert Mustacchi
413*e8249070SRobert Mustacchi /*
414*e8249070SRobert Mustacchi * Our job is to attempt to connect to the other end with our current settings.
415*e8249070SRobert Mustacchi * This may not work, so we use our port to get things ready just in case.
416*e8249070SRobert Mustacchi */
417*e8249070SRobert Mustacchi static bool
ttl_connect(const ttl_test_t * test,int port,int src,int dst,int * cfd,const struct sockaddr * addr)418*e8249070SRobert Mustacchi ttl_connect(const ttl_test_t *test, int port, int src, int dst, int *cfd,
419*e8249070SRobert Mustacchi const struct sockaddr *addr)
420*e8249070SRobert Mustacchi {
421*e8249070SRobert Mustacchi struct timespec to = { .tv_nsec = tt_sock_to };
422*e8249070SRobert Mustacchi int namelen = test->tt_domain == PF_INET ? sizeof (struct sockaddr_in) :
423*e8249070SRobert Mustacchi sizeof (struct sockaddr_in6);
424*e8249070SRobert Mustacchi int conn;
425*e8249070SRobert Mustacchi port_event_t pe;
426*e8249070SRobert Mustacchi
427*e8249070SRobert Mustacchi if (listen(dst, 5) != 0) {
428*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to listen", test->tt_desc);
429*e8249070SRobert Mustacchi return (false);
430*e8249070SRobert Mustacchi }
431*e8249070SRobert Mustacchi
432*e8249070SRobert Mustacchi if (connect(src, addr, namelen) != 0 && errno != EINPROGRESS) {
433*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to connect", test->tt_desc);
434*e8249070SRobert Mustacchi return (false);
435*e8249070SRobert Mustacchi }
436*e8249070SRobert Mustacchi
437*e8249070SRobert Mustacchi if (port_associate(port, PORT_SOURCE_FD, src, POLLOUT, NULL) != 0) {
438*e8249070SRobert Mustacchi err(EXIT_FAILURE, "INTERNAL TEST FAILURE: %s: could not port "
439*e8249070SRobert Mustacchi "associate to watch connect", test->tt_desc);
440*e8249070SRobert Mustacchi }
441*e8249070SRobert Mustacchi
442*e8249070SRobert Mustacchi if (port_get(port, &pe, &to) != 0) {
443*e8249070SRobert Mustacchi if (test->tt_pass == TTL_NOCONNECT) {
444*e8249070SRobert Mustacchi (void) printf("TEST PASSED: %s: correctly failed to "
445*e8249070SRobert Mustacchi "connect\n", test->tt_desc);
446*e8249070SRobert Mustacchi return (true);
447*e8249070SRobert Mustacchi } else {
448*e8249070SRobert Mustacchi warn("TEST FAILED: %s: timed out waiting to connect",
449*e8249070SRobert Mustacchi test->tt_desc);
450*e8249070SRobert Mustacchi return (false);
451*e8249070SRobert Mustacchi }
452*e8249070SRobert Mustacchi }
453*e8249070SRobert Mustacchi
454*e8249070SRobert Mustacchi if ((pe.portev_events & POLLOUT) == 0) {
455*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: connect port event doesn't contain "
456*e8249070SRobert Mustacchi "POLLOUT, found 0x%x", test->tt_desc, pe.portev_events);
457*e8249070SRobert Mustacchi return (false);
458*e8249070SRobert Mustacchi }
459*e8249070SRobert Mustacchi
460*e8249070SRobert Mustacchi /*
461*e8249070SRobert Mustacchi * Now make sure the listen socket is ready.
462*e8249070SRobert Mustacchi */
463*e8249070SRobert Mustacchi if (port_associate(port, PORT_SOURCE_FD, dst, POLLIN, NULL) != 0) {
464*e8249070SRobert Mustacchi err(EXIT_FAILURE, "INTERNAL TEST FAILURE: %s: could not port "
465*e8249070SRobert Mustacchi "associate to watch accept", test->tt_desc);
466*e8249070SRobert Mustacchi }
467*e8249070SRobert Mustacchi
468*e8249070SRobert Mustacchi if (port_get(port, &pe, &to) != 0) {
469*e8249070SRobert Mustacchi warn("TEST FAILED: %s: timed out waiting to accept",
470*e8249070SRobert Mustacchi test->tt_desc);
471*e8249070SRobert Mustacchi return (false);
472*e8249070SRobert Mustacchi }
473*e8249070SRobert Mustacchi
474*e8249070SRobert Mustacchi if ((pe.portev_events & POLLIN) == 0) {
475*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: accept port event doesn't contain "
476*e8249070SRobert Mustacchi "POLLIN, found 0x%x", test->tt_desc, pe.portev_events);
477*e8249070SRobert Mustacchi return (false);
478*e8249070SRobert Mustacchi }
479*e8249070SRobert Mustacchi
480*e8249070SRobert Mustacchi conn = accept4(dst, NULL, NULL, SOCK_NONBLOCK);
481*e8249070SRobert Mustacchi if (conn < 0) {
482*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to get client connection",
483*e8249070SRobert Mustacchi test->tt_desc);
484*e8249070SRobert Mustacchi return (false);
485*e8249070SRobert Mustacchi }
486*e8249070SRobert Mustacchi
487*e8249070SRobert Mustacchi if (test->tt_pass != TTL_SENDRECV) {
488*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: expected connect to fail, but passed",
489*e8249070SRobert Mustacchi test->tt_desc);
490*e8249070SRobert Mustacchi return (false);
491*e8249070SRobert Mustacchi }
492*e8249070SRobert Mustacchi
493*e8249070SRobert Mustacchi *cfd = conn;
494*e8249070SRobert Mustacchi return (true);
495*e8249070SRobert Mustacchi }
496*e8249070SRobert Mustacchi
497*e8249070SRobert Mustacchi static bool
ttl_check_ancil(const ttl_test_t * test,const struct msghdr * msg)498*e8249070SRobert Mustacchi ttl_check_ancil(const ttl_test_t *test, const struct msghdr *msg)
499*e8249070SRobert Mustacchi {
500*e8249070SRobert Mustacchi int level, ttlopt;
501*e8249070SRobert Mustacchi
502*e8249070SRobert Mustacchi if (test->tt_domain == PF_INET) {
503*e8249070SRobert Mustacchi level = IPPROTO_IP;
504*e8249070SRobert Mustacchi ttlopt = IP_RECVTTL;
505*e8249070SRobert Mustacchi } else {
506*e8249070SRobert Mustacchi level = IPPROTO_IPV6;
507*e8249070SRobert Mustacchi ttlopt = IPV6_HOPLIMIT;
508*e8249070SRobert Mustacchi }
509*e8249070SRobert Mustacchi
510*e8249070SRobert Mustacchi if (msg->msg_controllen != CMSG_SPACE(sizeof (int))) {
511*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: expected %u bytes of ancillary "
512*e8249070SRobert Mustacchi "data, found %u", test->tt_desc, CMSG_SPACE(sizeof (int)),
513*e8249070SRobert Mustacchi msg->msg_controllen);
514*e8249070SRobert Mustacchi return (false);
515*e8249070SRobert Mustacchi }
516*e8249070SRobert Mustacchi
517*e8249070SRobert Mustacchi for (const struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
518*e8249070SRobert Mustacchi cmsg = CMSG_NXTHDR(msg, cmsg)) {
519*e8249070SRobert Mustacchi int val;
520*e8249070SRobert Mustacchi
521*e8249070SRobert Mustacchi if (cmsg->cmsg_level != level || cmsg->cmsg_type != ttlopt)
522*e8249070SRobert Mustacchi continue;
523*e8249070SRobert Mustacchi (void) memcpy(&val, CMSG_DATA(cmsg), sizeof (int));
524*e8249070SRobert Mustacchi if (test->tt_ttl != 0 && val != test->tt_ttl) {
525*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: TTL/HLIM mismatch: expected "
526*e8249070SRobert Mustacchi "0x%x, found 0x%x", test->tt_desc, test->tt_ttl,
527*e8249070SRobert Mustacchi val);
528*e8249070SRobert Mustacchi return (false);
529*e8249070SRobert Mustacchi }
530*e8249070SRobert Mustacchi
531*e8249070SRobert Mustacchi (void) printf("TEST PASSED: %s: TTL/HLIM is correct\n",
532*e8249070SRobert Mustacchi test->tt_desc);
533*e8249070SRobert Mustacchi return (true);
534*e8249070SRobert Mustacchi }
535*e8249070SRobert Mustacchi
536*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: failed to find TTL/HLIM in ancillary options",
537*e8249070SRobert Mustacchi test->tt_desc);
538*e8249070SRobert Mustacchi return (false);
539*e8249070SRobert Mustacchi }
540*e8249070SRobert Mustacchi
541*e8249070SRobert Mustacchi /*
542*e8249070SRobert Mustacchi * Attempt to send data with the TTLs set up appropriately. This might fail,
543*e8249070SRobert Mustacchi * hence our port_associate dance and unfortunately regrettable timeout.
544*e8249070SRobert Mustacchi */
545*e8249070SRobert Mustacchi static bool
ttl_sendrecv(const ttl_test_t * test,int port,int src,int dst,struct sockaddr * addr)546*e8249070SRobert Mustacchi ttl_sendrecv(const ttl_test_t *test, int port, int src, int dst,
547*e8249070SRobert Mustacchi struct sockaddr *addr)
548*e8249070SRobert Mustacchi {
549*e8249070SRobert Mustacchi struct timespec to = { .tv_nsec = tt_sock_to };
550*e8249070SRobert Mustacchi int namelen = test->tt_domain == PF_INET ? sizeof (struct sockaddr_in) :
551*e8249070SRobert Mustacchi sizeof (struct sockaddr_in6);
552*e8249070SRobert Mustacchi uint8_t ancil[CMSG_SPACE(sizeof (int)) * 2];
553*e8249070SRobert Mustacchi port_event_t pe;
554*e8249070SRobert Mustacchi struct msghdr msg;
555*e8249070SRobert Mustacchi uint32_t data;
556*e8249070SRobert Mustacchi struct iovec iov;
557*e8249070SRobert Mustacchi ssize_t sret;
558*e8249070SRobert Mustacchi
559*e8249070SRobert Mustacchi if (sendto(src, &tt_msg, sizeof (tt_msg), MSG_NOSIGNAL, addr,
560*e8249070SRobert Mustacchi namelen) != sizeof (tt_msg)) {
561*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to write message to socket",
562*e8249070SRobert Mustacchi test->tt_desc);
563*e8249070SRobert Mustacchi }
564*e8249070SRobert Mustacchi
565*e8249070SRobert Mustacchi if (port_associate(port, PORT_SOURCE_FD, dst, POLLIN, NULL) != 0) {
566*e8249070SRobert Mustacchi err(EXIT_FAILURE, "INTERNAL TEST FAILURE: %s: could not port "
567*e8249070SRobert Mustacchi "associate to watch recv", test->tt_desc);
568*e8249070SRobert Mustacchi }
569*e8249070SRobert Mustacchi
570*e8249070SRobert Mustacchi if (port_get(port, &pe, &to) != 0) {
571*e8249070SRobert Mustacchi if (test->tt_pass == TTL_NODATA) {
572*e8249070SRobert Mustacchi (void) printf("TEST PASSED: %s: timed out waiting "
573*e8249070SRobert Mustacchi "for data\n", test->tt_desc);
574*e8249070SRobert Mustacchi return (true);
575*e8249070SRobert Mustacchi } else {
576*e8249070SRobert Mustacchi warn("TEST FAILED: %s: timed out waiting to recv",
577*e8249070SRobert Mustacchi test->tt_desc);
578*e8249070SRobert Mustacchi return (false);
579*e8249070SRobert Mustacchi }
580*e8249070SRobert Mustacchi }
581*e8249070SRobert Mustacchi
582*e8249070SRobert Mustacchi if ((pe.portev_events & POLLIN) == 0) {
583*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: receive port event doesn't contain "
584*e8249070SRobert Mustacchi "POLLIN, found 0x%x", test->tt_desc, pe.portev_events);
585*e8249070SRobert Mustacchi return (false);
586*e8249070SRobert Mustacchi }
587*e8249070SRobert Mustacchi
588*e8249070SRobert Mustacchi (void) memset(&msg, 0, sizeof (msg));
589*e8249070SRobert Mustacchi iov.iov_base = (void *)&data;
590*e8249070SRobert Mustacchi iov.iov_len = sizeof (data);
591*e8249070SRobert Mustacchi msg.msg_iov = &iov;
592*e8249070SRobert Mustacchi msg.msg_iovlen = 1;
593*e8249070SRobert Mustacchi msg.msg_control = ancil;
594*e8249070SRobert Mustacchi msg.msg_controllen = sizeof (ancil);
595*e8249070SRobert Mustacchi
596*e8249070SRobert Mustacchi sret = recvmsg(dst, &msg, MSG_DONTWAIT);
597*e8249070SRobert Mustacchi if (sret != (ssize_t)sizeof (data)) {
598*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: failed to receive data: %zx",
599*e8249070SRobert Mustacchi test->tt_desc, sret);
600*e8249070SRobert Mustacchi return (false);
601*e8249070SRobert Mustacchi }
602*e8249070SRobert Mustacchi
603*e8249070SRobert Mustacchi if (test->tt_pass != TTL_SENDRECV) {
604*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: found data, despite expecting not to",
605*e8249070SRobert Mustacchi test->tt_desc);
606*e8249070SRobert Mustacchi return (false);
607*e8249070SRobert Mustacchi }
608*e8249070SRobert Mustacchi
609*e8249070SRobert Mustacchi /*
610*e8249070SRobert Mustacchi * We skip testing the data on raw sockets so we can ignore having to
611*e8249070SRobert Mustacchi * parse the IPv4 or IPv6 headers.
612*e8249070SRobert Mustacchi */
613*e8249070SRobert Mustacchi if (data != tt_msg && test->tt_type != SOCK_RAW) {
614*e8249070SRobert Mustacchi warnx("TEST FAILED: %s: data mismatch: expected 0x%x, found "
615*e8249070SRobert Mustacchi "0x%x", test->tt_desc, tt_msg, data);
616*e8249070SRobert Mustacchi return (false);
617*e8249070SRobert Mustacchi }
618*e8249070SRobert Mustacchi
619*e8249070SRobert Mustacchi if (test->tt_type == SOCK_DGRAM && !ttl_check_ancil(test, &msg)) {
620*e8249070SRobert Mustacchi return (false);
621*e8249070SRobert Mustacchi }
622*e8249070SRobert Mustacchi
623*e8249070SRobert Mustacchi (void) printf("TEST PASSED: %s: Successfully received data\n",
624*e8249070SRobert Mustacchi test->tt_desc);
625*e8249070SRobert Mustacchi return (true);
626*e8249070SRobert Mustacchi }
627*e8249070SRobert Mustacchi
628*e8249070SRobert Mustacchi static bool
ttl_test_one(const ttl_test_t * test)629*e8249070SRobert Mustacchi ttl_test_one(const ttl_test_t *test)
630*e8249070SRobert Mustacchi {
631*e8249070SRobert Mustacchi int src = -1, dst = -1, cfd = -1, port = -1, tdst;
632*e8249070SRobert Mustacchi int level, ttlopt, minttlopt, recvopt, en = 1;
633*e8249070SRobert Mustacchi bool ret = true;
634*e8249070SRobert Mustacchi struct sockaddr_storage dst_addr;
635*e8249070SRobert Mustacchi
636*e8249070SRobert Mustacchi if ((port = port_create()) < 0) {
637*e8249070SRobert Mustacchi err(EXIT_FAILURE, "TEST FAILED: failed to create event port");
638*e8249070SRobert Mustacchi }
639*e8249070SRobert Mustacchi
640*e8249070SRobert Mustacchi src = socket(test->tt_domain, test->tt_type | SOCK_NONBLOCK,
641*e8249070SRobert Mustacchi test->tt_proto);
642*e8249070SRobert Mustacchi if (src < 0) {
643*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to create source socket",
644*e8249070SRobert Mustacchi test->tt_desc);
645*e8249070SRobert Mustacchi ret = false;
646*e8249070SRobert Mustacchi goto cleanup;
647*e8249070SRobert Mustacchi }
648*e8249070SRobert Mustacchi
649*e8249070SRobert Mustacchi dst = socket(test->tt_domain, test->tt_type | SOCK_NONBLOCK,
650*e8249070SRobert Mustacchi test->tt_proto);
651*e8249070SRobert Mustacchi if (dst < 0) {
652*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to create destination socket",
653*e8249070SRobert Mustacchi test->tt_desc);
654*e8249070SRobert Mustacchi ret = false;
655*e8249070SRobert Mustacchi goto cleanup;
656*e8249070SRobert Mustacchi }
657*e8249070SRobert Mustacchi
658*e8249070SRobert Mustacchi if (!ttl_bind_dest(test, dst, &dst_addr)) {
659*e8249070SRobert Mustacchi ret = false;
660*e8249070SRobert Mustacchi goto cleanup;
661*e8249070SRobert Mustacchi }
662*e8249070SRobert Mustacchi
663*e8249070SRobert Mustacchi if (test->tt_domain == PF_INET) {
664*e8249070SRobert Mustacchi level = IPPROTO_IP;
665*e8249070SRobert Mustacchi ttlopt = IP_TTL;
666*e8249070SRobert Mustacchi minttlopt = IP_MINTTL;
667*e8249070SRobert Mustacchi recvopt = IP_RECVTTL;
668*e8249070SRobert Mustacchi } else {
669*e8249070SRobert Mustacchi level = IPPROTO_IPV6;
670*e8249070SRobert Mustacchi ttlopt = IPV6_UNICAST_HOPS;
671*e8249070SRobert Mustacchi minttlopt = IPV6_MINHOPCOUNT;
672*e8249070SRobert Mustacchi recvopt = IPV6_RECVHOPLIMIT;
673*e8249070SRobert Mustacchi }
674*e8249070SRobert Mustacchi
675*e8249070SRobert Mustacchi if (test->tt_ttl > 0 && setsockopt(src, level, ttlopt, &test->tt_ttl,
676*e8249070SRobert Mustacchi sizeof (int)) != 0) {
677*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to set TTL/HLIM to %d",
678*e8249070SRobert Mustacchi test->tt_desc, test->tt_ttl);
679*e8249070SRobert Mustacchi ret = false;
680*e8249070SRobert Mustacchi goto cleanup;
681*e8249070SRobert Mustacchi }
682*e8249070SRobert Mustacchi
683*e8249070SRobert Mustacchi if (setsockopt(dst, level, minttlopt, &test->tt_minttl,
684*e8249070SRobert Mustacchi sizeof (int)) != 0) {
685*e8249070SRobert Mustacchi warn("TEST FAILED: %s: failed to set min TTL/HLIM to %d",
686*e8249070SRobert Mustacchi test->tt_desc, test->tt_minttl);
687*e8249070SRobert Mustacchi ret = false;
688*e8249070SRobert Mustacchi goto cleanup;
689*e8249070SRobert Mustacchi }
690*e8249070SRobert Mustacchi
691*e8249070SRobert Mustacchi if (test->tt_type == SOCK_DGRAM && setsockopt(dst, level, recvopt, &en,
692*e8249070SRobert Mustacchi sizeof (int)) != 0) {
693*e8249070SRobert Mustacchi warn("TEST FAILED: %s failed to enable receiving the TTL",
694*e8249070SRobert Mustacchi test->tt_desc);
695*e8249070SRobert Mustacchi ret = false;
696*e8249070SRobert Mustacchi goto cleanup;
697*e8249070SRobert Mustacchi }
698*e8249070SRobert Mustacchi
699*e8249070SRobert Mustacchi if (test->tt_type != SOCK_DGRAM && test->tt_type != SOCK_RAW) {
700*e8249070SRobert Mustacchi if (!ttl_connect(test, port, src, dst, &cfd,
701*e8249070SRobert Mustacchi (struct sockaddr *)&dst_addr)) {
702*e8249070SRobert Mustacchi ret = false;
703*e8249070SRobert Mustacchi goto cleanup;
704*e8249070SRobert Mustacchi }
705*e8249070SRobert Mustacchi if (test->tt_pass != TTL_SENDRECV) {
706*e8249070SRobert Mustacchi goto cleanup;
707*e8249070SRobert Mustacchi }
708*e8249070SRobert Mustacchi tdst = cfd;
709*e8249070SRobert Mustacchi } else {
710*e8249070SRobert Mustacchi tdst = dst;
711*e8249070SRobert Mustacchi }
712*e8249070SRobert Mustacchi
713*e8249070SRobert Mustacchi if (!ttl_sendrecv(test, port, src, tdst,
714*e8249070SRobert Mustacchi (struct sockaddr *)&dst_addr)) {
715*e8249070SRobert Mustacchi ret = false;
716*e8249070SRobert Mustacchi goto cleanup;
717*e8249070SRobert Mustacchi }
718*e8249070SRobert Mustacchi
719*e8249070SRobert Mustacchi cleanup:
720*e8249070SRobert Mustacchi if (port > -1)
721*e8249070SRobert Mustacchi (void) close(port);
722*e8249070SRobert Mustacchi if (src > -1)
723*e8249070SRobert Mustacchi (void) close(src);
724*e8249070SRobert Mustacchi if (dst > -1)
725*e8249070SRobert Mustacchi (void) close(dst);
726*e8249070SRobert Mustacchi if (cfd > -1)
727*e8249070SRobert Mustacchi (void) close(cfd);
728*e8249070SRobert Mustacchi return (ret);
729*e8249070SRobert Mustacchi }
730*e8249070SRobert Mustacchi
731*e8249070SRobert Mustacchi int
main(void)732*e8249070SRobert Mustacchi main(void)
733*e8249070SRobert Mustacchi {
734*e8249070SRobert Mustacchi int ret = EXIT_SUCCESS;
735*e8249070SRobert Mustacchi
736*e8249070SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(ttl_tests); i++) {
737*e8249070SRobert Mustacchi if (!ttl_test_one(&ttl_tests[i])) {
738*e8249070SRobert Mustacchi ret = EXIT_FAILURE;
739*e8249070SRobert Mustacchi }
740*e8249070SRobert Mustacchi }
741*e8249070SRobert Mustacchi
742*e8249070SRobert Mustacchi if (ret == EXIT_SUCCESS) {
743*e8249070SRobert Mustacchi (void) printf("All tests passed successfully\n");
744*e8249070SRobert Mustacchi }
745*e8249070SRobert Mustacchi
746*e8249070SRobert Mustacchi return (ret);
747*e8249070SRobert Mustacchi }
748