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