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