1 /* $OpenBSD: addr.c,v 1.7 2023/03/27 03:31:05 djm Exp $ */ 2 3 /* 4 * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "includes.h" 20 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <netinet/in.h> 24 #include <arpa/inet.h> 25 26 #include <netdb.h> 27 #include <string.h> 28 #include <stdlib.h> 29 #include <stdio.h> 30 31 #include "addr.h" 32 33 #define _SA(x) ((struct sockaddr *)(x)) 34 35 int 36 addr_unicast_masklen(int af) 37 { 38 switch (af) { 39 case AF_INET: 40 return 32; 41 case AF_INET6: 42 return 128; 43 default: 44 return -1; 45 } 46 } 47 48 static inline int 49 masklen_valid(int af, u_int masklen) 50 { 51 switch (af) { 52 case AF_INET: 53 return masklen <= 32 ? 0 : -1; 54 case AF_INET6: 55 return masklen <= 128 ? 0 : -1; 56 default: 57 return -1; 58 } 59 } 60 61 int 62 addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, socklen_t *len, 63 u_int16_t port) 64 { 65 struct sockaddr_in *in4 = (struct sockaddr_in *)sa; 66 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; 67 68 if (xa == NULL || sa == NULL || len == NULL) 69 return -1; 70 71 switch (xa->af) { 72 case AF_INET: 73 if (*len < sizeof(*in4)) 74 return -1; 75 memset(sa, '\0', sizeof(*in4)); 76 *len = sizeof(*in4); 77 #ifdef SOCK_HAS_LEN 78 in4->sin_len = sizeof(*in4); 79 #endif 80 in4->sin_family = AF_INET; 81 in4->sin_port = htons(port); 82 memcpy(&in4->sin_addr, &xa->v4, sizeof(in4->sin_addr)); 83 break; 84 case AF_INET6: 85 if (*len < sizeof(*in6)) 86 return -1; 87 memset(sa, '\0', sizeof(*in6)); 88 *len = sizeof(*in6); 89 #ifdef SOCK_HAS_LEN 90 in6->sin6_len = sizeof(*in6); 91 #endif 92 in6->sin6_family = AF_INET6; 93 in6->sin6_port = htons(port); 94 memcpy(&in6->sin6_addr, &xa->v6, sizeof(in6->sin6_addr)); 95 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 96 in6->sin6_scope_id = xa->scope_id; 97 #endif 98 break; 99 default: 100 return -1; 101 } 102 return 0; 103 } 104 105 /* 106 * Convert struct sockaddr to struct xaddr 107 * Returns 0 on success, -1 on failure. 108 */ 109 int 110 addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa) 111 { 112 struct sockaddr_in *in4 = (struct sockaddr_in *)sa; 113 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; 114 115 memset(xa, '\0', sizeof(*xa)); 116 117 switch (sa->sa_family) { 118 case AF_INET: 119 if (slen < (socklen_t)sizeof(*in4)) 120 return -1; 121 xa->af = AF_INET; 122 memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4)); 123 break; 124 case AF_INET6: 125 if (slen < (socklen_t)sizeof(*in6)) 126 return -1; 127 xa->af = AF_INET6; 128 memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6)); 129 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 130 xa->scope_id = in6->sin6_scope_id; 131 #endif 132 break; 133 default: 134 return -1; 135 } 136 137 return 0; 138 } 139 140 int 141 addr_invert(struct xaddr *n) 142 { 143 int i; 144 145 if (n == NULL) 146 return -1; 147 148 switch (n->af) { 149 case AF_INET: 150 n->v4.s_addr = ~n->v4.s_addr; 151 return 0; 152 case AF_INET6: 153 for (i = 0; i < 4; i++) 154 n->addr32[i] = ~n->addr32[i]; 155 return 0; 156 default: 157 return -1; 158 } 159 } 160 161 /* 162 * Calculate a netmask of length 'l' for address family 'af' and 163 * store it in 'n'. 164 * Returns 0 on success, -1 on failure. 165 */ 166 int 167 addr_netmask(int af, u_int l, struct xaddr *n) 168 { 169 int i; 170 171 if (masklen_valid(af, l) != 0 || n == NULL) 172 return -1; 173 174 memset(n, '\0', sizeof(*n)); 175 switch (af) { 176 case AF_INET: 177 n->af = AF_INET; 178 if (l == 0) 179 return 0; 180 n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); 181 return 0; 182 case AF_INET6: 183 n->af = AF_INET6; 184 for (i = 0; i < 4 && l >= 32; i++, l -= 32) 185 n->addr32[i] = 0xffffffffU; 186 if (i < 4 && l != 0) 187 n->addr32[i] = htonl((0xffffffff << (32 - l)) & 188 0xffffffff); 189 return 0; 190 default: 191 return -1; 192 } 193 } 194 195 int 196 addr_hostmask(int af, u_int l, struct xaddr *n) 197 { 198 if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1) 199 return -1; 200 return 0; 201 } 202 203 /* 204 * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'. 205 * Returns 0 on success, -1 on failure. 206 */ 207 int 208 addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) 209 { 210 int i; 211 212 if (dst == NULL || a == NULL || b == NULL || a->af != b->af) 213 return -1; 214 215 memcpy(dst, a, sizeof(*dst)); 216 switch (a->af) { 217 case AF_INET: 218 dst->v4.s_addr &= b->v4.s_addr; 219 return 0; 220 case AF_INET6: 221 dst->scope_id = a->scope_id; 222 for (i = 0; i < 4; i++) 223 dst->addr32[i] &= b->addr32[i]; 224 return 0; 225 default: 226 return -1; 227 } 228 } 229 230 int 231 addr_or(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) 232 { 233 int i; 234 235 if (dst == NULL || a == NULL || b == NULL || a->af != b->af) 236 return (-1); 237 238 memcpy(dst, a, sizeof(*dst)); 239 switch (a->af) { 240 case AF_INET: 241 dst->v4.s_addr |= b->v4.s_addr; 242 return (0); 243 case AF_INET6: 244 for (i = 0; i < 4; i++) 245 dst->addr32[i] |= b->addr32[i]; 246 return (0); 247 default: 248 return (-1); 249 } 250 } 251 252 int 253 addr_cmp(const struct xaddr *a, const struct xaddr *b) 254 { 255 int i; 256 257 if (a->af != b->af) 258 return (a->af == AF_INET6 ? 1 : -1); 259 260 switch (a->af) { 261 case AF_INET: 262 /* 263 * Can't just subtract here as 255.255.255.255 - 0.0.0.0 is 264 * too big to fit into a signed int 265 */ 266 if (a->v4.s_addr == b->v4.s_addr) 267 return 0; 268 return (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1); 269 case AF_INET6: 270 /* 271 * Do this a byte at a time to avoid the above issue and 272 * any endian problems 273 */ 274 for (i = 0; i < 16; i++) 275 if (a->addr8[i] - b->addr8[i] != 0) 276 return (a->addr8[i] - b->addr8[i]); 277 if (a->scope_id == b->scope_id) 278 return (0); 279 return (a->scope_id > b->scope_id ? 1 : -1); 280 default: 281 return (-1); 282 } 283 } 284 285 int 286 addr_is_all0s(const struct xaddr *a) 287 { 288 int i; 289 290 switch (a->af) { 291 case AF_INET: 292 return (a->v4.s_addr == 0 ? 0 : -1); 293 case AF_INET6: 294 for (i = 0; i < 4; i++) 295 if (a->addr32[i] != 0) 296 return -1; 297 return 0; 298 default: 299 return -1; 300 } 301 } 302 303 /* Increment the specified address. Note, does not do overflow checking */ 304 void 305 addr_increment(struct xaddr *a) 306 { 307 int i; 308 uint32_t n; 309 310 switch (a->af) { 311 case AF_INET: 312 a->v4.s_addr = htonl(ntohl(a->v4.s_addr) + 1); 313 break; 314 case AF_INET6: 315 for (i = 0; i < 4; i++) { 316 /* Increment with carry */ 317 n = ntohl(a->addr32[3 - i]) + 1; 318 a->addr32[3 - i] = htonl(n); 319 if (n != 0) 320 break; 321 } 322 break; 323 } 324 } 325 326 /* 327 * Test whether host portion of address 'a', as determined by 'masklen' 328 * is all zeros. 329 * Returns 0 if host portion of address is all-zeros, 330 * -1 if not all zeros or on failure. 331 */ 332 int 333 addr_host_is_all0s(const struct xaddr *a, u_int masklen) 334 { 335 struct xaddr tmp_addr, tmp_mask, tmp_result; 336 337 memcpy(&tmp_addr, a, sizeof(tmp_addr)); 338 if (addr_hostmask(a->af, masklen, &tmp_mask) == -1) 339 return -1; 340 if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1) 341 return -1; 342 return addr_is_all0s(&tmp_result); 343 } 344 345 #if 0 346 int 347 addr_host_to_all0s(struct xaddr *a, u_int masklen) 348 { 349 struct xaddr tmp_mask; 350 351 if (addr_netmask(a->af, masklen, &tmp_mask) == -1) 352 return (-1); 353 if (addr_and(a, a, &tmp_mask) == -1) 354 return (-1); 355 return (0); 356 } 357 #endif 358 359 int 360 addr_host_to_all1s(struct xaddr *a, u_int masklen) 361 { 362 struct xaddr tmp_mask; 363 364 if (addr_hostmask(a->af, masklen, &tmp_mask) == -1) 365 return (-1); 366 if (addr_or(a, a, &tmp_mask) == -1) 367 return (-1); 368 return (0); 369 } 370 371 /* 372 * Parse string address 'p' into 'n'. 373 * Returns 0 on success, -1 on failure. 374 */ 375 int 376 addr_pton(const char *p, struct xaddr *n) 377 { 378 struct addrinfo hints, *ai; 379 380 memset(&hints, '\0', sizeof(hints)); 381 hints.ai_flags = AI_NUMERICHOST; 382 383 if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0) 384 return -1; 385 386 if (ai == NULL) 387 return -1; 388 389 if (ai->ai_addr == NULL) { 390 freeaddrinfo(ai); 391 return -1; 392 } 393 394 if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, 395 n) == -1) { 396 freeaddrinfo(ai); 397 return -1; 398 } 399 400 freeaddrinfo(ai); 401 return 0; 402 } 403 404 int 405 addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, socklen_t slen) 406 { 407 struct addrinfo hints, *ai; 408 409 memset(&hints, '\0', sizeof(hints)); 410 hints.ai_flags = AI_NUMERICHOST; 411 412 if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0) 413 return -1; 414 415 if (ai == NULL) 416 return -1; 417 418 if (ai->ai_addr == NULL) { 419 freeaddrinfo(ai); 420 return -1; 421 } 422 423 if (sa != NULL) { 424 if (slen < ai->ai_addrlen) { 425 freeaddrinfo(ai); 426 return -1; 427 } 428 memcpy(sa, &ai->ai_addr, ai->ai_addrlen); 429 } 430 431 freeaddrinfo(ai); 432 return 0; 433 } 434 435 int 436 addr_ntop(const struct xaddr *n, char *p, size_t len) 437 { 438 struct sockaddr_storage ss; 439 socklen_t slen = sizeof(ss); 440 441 if (addr_xaddr_to_sa(n, _SA(&ss), &slen, 0) == -1) 442 return -1; 443 if (p == NULL || len == 0) 444 return -1; 445 if (getnameinfo(_SA(&ss), slen, p, len, NULL, 0, 446 NI_NUMERICHOST) != 0) 447 return -1; 448 449 return 0; 450 } 451 452 /* 453 * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z). 454 * Return -1 on parse error, -2 on inconsistency or 0 on success. 455 */ 456 int 457 addr_pton_cidr(const char *p, struct xaddr *n, u_int *l) 458 { 459 struct xaddr tmp; 460 long unsigned int masklen = 999; 461 char addrbuf[64], *mp, *cp; 462 463 /* Don't modify argument */ 464 if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf)) 465 return -1; 466 467 if ((mp = strchr(addrbuf, '/')) != NULL) { 468 *mp = '\0'; 469 mp++; 470 masklen = strtoul(mp, &cp, 10); 471 if (*mp < '0' || *mp > '9' || *cp != '\0' || masklen > 128) 472 return -1; 473 } 474 475 if (addr_pton(addrbuf, &tmp) == -1) 476 return -1; 477 478 if (mp == NULL) 479 masklen = addr_unicast_masklen(tmp.af); 480 if (masklen_valid(tmp.af, masklen) == -1) 481 return -2; 482 if (addr_host_is_all0s(&tmp, masklen) != 0) 483 return -2; 484 485 if (n != NULL) 486 memcpy(n, &tmp, sizeof(*n)); 487 if (l != NULL) 488 *l = masklen; 489 490 return 0; 491 } 492 493 int 494 addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen) 495 { 496 struct xaddr tmp_mask, tmp_result; 497 498 if (host->af != net->af) 499 return -1; 500 501 if (addr_netmask(host->af, masklen, &tmp_mask) == -1) 502 return -1; 503 if (addr_and(&tmp_result, host, &tmp_mask) == -1) 504 return -1; 505 return addr_cmp(&tmp_result, net); 506 } 507