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