Changes in uspace/lib/c/generic/inet/addr.c [3495654:26de91a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/inet/addr.c
r3495654 r26de91a 33 33 */ 34 34 35 #include <assert.h> 35 36 #include <errno.h> 37 #include <unistd.h> 38 #include <net/socket_codes.h> 36 39 #include <inet/addr.h> 40 #include <net/inet.h> 37 41 #include <stdio.h> 42 #include <malloc.h> 43 #include <bitops.h> 44 45 #define INET_PREFIXSTRSIZE 5 46 47 #if !(defined(__BE__) ^ defined(__LE__)) 48 #error The architecture must be either big-endian or little-endian. 49 #endif 50 51 const addr32_t addr32_broadcast_all_hosts = 0xffffffff; 52 53 const addr48_t addr48_broadcast = { 54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 55 }; 56 57 static const addr48_t inet_addr48_solicited_node = { 58 0x33, 0x33, 0xff, 0, 0, 0 59 }; 60 61 static const inet_addr_t inet_addr_any_addr = { 62 .version = ip_v4, 63 .addr = 0 64 }; 65 66 static const inet_addr_t inet_addr_any_addr6 = { 67 .version = ip_v6, 68 .addr6 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 69 }; 70 71 void addr48(const addr48_t src, addr48_t dst) 72 { 73 memcpy(dst, src, 6); 74 } 75 76 void addr128(const addr128_t src, addr128_t dst) 77 { 78 memcpy(dst, src, 16); 79 } 80 81 /** Compare addr48. 82 * 83 * @return Non-zero if equal, zero if not equal. 84 */ 85 int addr48_compare(const addr48_t a, const addr48_t b) 86 { 87 return memcmp(a, b, 6) == 0; 88 } 89 90 /** Compare addr128. 91 * 92 * @return Non-zero if equal, zero if not equal. 93 */ 94 int addr128_compare(const addr128_t a, const addr128_t b) 95 { 96 return memcmp(a, b, 16) == 0; 97 } 98 99 /** Compute solicited node MAC multicast address from target IPv6 address 100 * 101 * @param ip Target IPv6 address 102 * @param mac Solicited MAC address to be assigned 103 * 104 */ 105 void addr48_solicited_node(const addr128_t ip, addr48_t mac) 106 { 107 memcpy(mac, inet_addr48_solicited_node, 3); 108 memcpy(mac + 3, ip + 13, 3); 109 } 110 111 void host2addr128_t_be(const addr128_t host, addr128_t be) 112 { 113 memcpy(be, host, 16); 114 } 115 116 void addr128_t_be2host(const addr128_t be, addr128_t host) 117 { 118 memcpy(host, be, 16); 119 } 120 121 void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d) 122 { 123 addr->version = ip_v4; 124 addr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) | 125 ((addr32_t) c << 8) | ((addr32_t) d); 126 } 127 128 void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d, 129 uint8_t prefix) 130 { 131 naddr->version = ip_v4; 132 naddr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) | 133 ((addr32_t) c << 8) | ((addr32_t) d); 134 naddr->prefix = prefix; 135 } 136 137 void inet_addr6(inet_addr_t *addr, uint16_t a, uint16_t b, uint16_t c, 138 uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h) 139 { 140 addr->version = ip_v6; 141 addr->addr6[0] = (a >> 8) & 0xff; 142 addr->addr6[1] = a & 0xff; 143 addr->addr6[2] = (b >> 8) & 0xff; 144 addr->addr6[3] = b & 0xff; 145 addr->addr6[4] = (c >> 8) & 0xff; 146 addr->addr6[5] = c & 0xff; 147 addr->addr6[6] = (d >> 8) & 0xff; 148 addr->addr6[7] = d & 0xff; 149 addr->addr6[8] = (e >> 8) & 0xff; 150 addr->addr6[9] = e & 0xff; 151 addr->addr6[10] = (f >> 8) & 0xff; 152 addr->addr6[11] = f & 0xff; 153 addr->addr6[12] = (g >> 8) & 0xff; 154 addr->addr6[13] = g & 0xff; 155 addr->addr6[14] = (h >> 8) & 0xff; 156 addr->addr6[15] = h & 0xff; 157 } 158 159 void inet_naddr6(inet_naddr_t *naddr, uint16_t a, uint16_t b, uint16_t c, 160 uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h, uint8_t prefix) 161 { 162 naddr->version = ip_v6; 163 naddr->addr6[0] = (a >> 8) & 0xff; 164 naddr->addr6[1] = a & 0xff; 165 naddr->addr6[2] = (b >> 8) & 0xff; 166 naddr->addr6[3] = b & 0xff; 167 naddr->addr6[4] = (c >> 8) & 0xff; 168 naddr->addr6[5] = c & 0xff; 169 naddr->addr6[6] = (d >> 8) & 0xff; 170 naddr->addr6[7] = d & 0xff; 171 naddr->addr6[8] = (e >> 8) & 0xff; 172 naddr->addr6[9] = e & 0xff; 173 naddr->addr6[10] = (f >> 8) & 0xff; 174 naddr->addr6[11] = f & 0xff; 175 naddr->addr6[12] = (g >> 8) & 0xff; 176 naddr->addr6[13] = g & 0xff; 177 naddr->addr6[14] = (h >> 8) & 0xff; 178 naddr->addr6[15] = h & 0xff; 179 naddr->prefix = prefix; 180 } 181 182 /** Determine address version. 183 * 184 * @param text Address in common notation. 185 * @param af Place to store address version. 186 * 187 * @return EOK on success, EINVAL if input is not in valid format. 188 * 189 */ 190 static int inet_addr_version(const char *text, ip_ver_t *ver) 191 { 192 char *dot = str_chr(text, '.'); 193 if (dot != NULL) { 194 *ver = ip_v4; 195 return EOK; 196 } 197 198 char *collon = str_chr(text, ':'); 199 if (collon != NULL) { 200 *ver = ip_v6; 201 return EOK; 202 } 203 204 return EINVAL; 205 } 206 207 static int ipver_af(ip_ver_t ver) 208 { 209 switch (ver) { 210 case ip_any: 211 return AF_NONE; 212 case ip_v4: 213 return AF_INET; 214 case ip_v6: 215 return AF_INET6; 216 default: 217 assert(false); 218 return EINVAL; 219 } 220 } 221 222 ip_ver_t ipver_from_af(int af) 223 { 224 switch (af) { 225 case AF_NONE: 226 return ip_any; 227 case AF_INET: 228 return ip_v4; 229 case AF_INET6: 230 return ip_v6; 231 default: 232 assert(false); 233 return EINVAL; 234 } 235 } 236 237 void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr) 238 { 239 addr->version = naddr->version; 240 memcpy(addr->addr6, naddr->addr6, 16); 241 } 242 243 void inet_addr_naddr(const inet_addr_t *addr, uint8_t prefix, 244 inet_naddr_t *naddr) 245 { 246 naddr->version = addr->version; 247 memcpy(naddr->addr6, addr->addr6, 16); 248 naddr->prefix = prefix; 249 } 250 251 void inet_addr_any(inet_addr_t *addr) 252 { 253 addr->version = ip_any; 254 memset(addr->addr6, 0, 16); 255 } 256 257 void inet_naddr_any(inet_naddr_t *naddr) 258 { 259 naddr->version = ip_any; 260 memset(naddr->addr6, 0, 16); 261 naddr->prefix = 0; 262 } 263 264 int inet_addr_compare(const inet_addr_t *a, const inet_addr_t *b) 265 { 266 if (a->version != b->version) 267 return 0; 268 269 switch (a->version) { 270 case ip_v4: 271 return (a->addr == b->addr); 272 case ip_v6: 273 return addr128_compare(a->addr6, b->addr6); 274 default: 275 return 0; 276 } 277 } 278 279 int inet_addr_is_any(const inet_addr_t *addr) 280 { 281 return ((addr->version == ip_any) || 282 (inet_addr_compare(addr, &inet_addr_any_addr)) || 283 (inet_addr_compare(addr, &inet_addr_any_addr6))); 284 } 285 286 int inet_naddr_compare(const inet_naddr_t *naddr, const inet_addr_t *addr) 287 { 288 if (naddr->version != addr->version) 289 return 0; 290 291 switch (naddr->version) { 292 case ip_v4: 293 return (naddr->addr == addr->addr); 294 case ip_v6: 295 return addr128_compare(naddr->addr6, addr->addr6); 296 default: 297 return 0; 298 } 299 } 300 301 int inet_naddr_compare_mask(const inet_naddr_t *naddr, const inet_addr_t *addr) 302 { 303 if (naddr->version != addr->version) 304 return 0; 305 306 switch (naddr->version) { 307 case ip_v4: 308 if (naddr->prefix > 32) 309 return 0; 310 311 addr32_t mask = 312 BIT_RANGE(addr32_t, 31, 31 - (naddr->prefix - 1)); 313 return ((naddr->addr & mask) == (addr->addr & mask)); 314 case ip_v6: 315 if (naddr->prefix > 128) 316 return 0; 317 318 size_t pos = 0; 319 for (size_t i = 0; i < 16; i++) { 320 /* Further bits do not matter */ 321 if (naddr->prefix < pos) 322 break; 323 324 if (naddr->prefix - pos > 8) { 325 /* Comparison without masking */ 326 if (naddr->addr6[i] != addr->addr6[i]) 327 return 0; 328 } else { 329 /* Comparison with masking */ 330 uint8_t mask = 331 BIT_RANGE(uint8_t, 8, 8 - (naddr->prefix - pos - 1)); 332 if ((naddr->addr6[i] & mask) != (addr->addr6[i] & mask)) 333 return 0; 334 } 335 336 pos += 8; 337 } 338 339 return 1; 340 default: 341 return 0; 342 } 343 } 344 345 /** Parse node address. 346 * 347 * @param text Network address in common notation. 348 * @param addr Place to store node address. 349 * 350 * @return EOK on success, EINVAL if input is not in valid format. 351 * 352 */ 353 int inet_addr_parse(const char *text, inet_addr_t *addr) 354 { 355 int rc = inet_addr_version(text, &addr->version); 356 if (rc != EOK) 357 return rc; 358 359 uint8_t buf[16]; 360 rc = inet_pton(ipver_af(addr->version), text, buf); 361 if (rc != EOK) 362 return rc; 363 364 switch (addr->version) { 365 case ip_v4: 366 addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | 367 buf[3]; 368 break; 369 case ip_v6: 370 memcpy(addr->addr6, buf, 16); 371 break; 372 default: 373 return EINVAL; 374 } 375 376 return EOK; 377 } 38 378 39 379 /** Parse network address. 40 380 * 41 * @param text Network address in CIDR notation (a.b.c.d/w) 42 * @param naddr Place to store network address 43 * 44 * @return EOK on success, EINVAL if input is not in valid format 381 * @param text Network address in common notation. 382 * @param naddr Place to store network address. 383 * 384 * @return EOK on success, EINVAL if input is not in valid format. 385 * 45 386 */ 46 387 int inet_naddr_parse(const char *text, inet_naddr_t *naddr) 47 388 { 48 unsigned long a[4], bits; 49 char *cp = (char *)text; 50 int i; 51 52 for (i = 0; i < 3; i++) { 53 a[i] = strtoul(cp, &cp, 10); 54 if (*cp != '.') 389 char *slash = str_chr(text, '/'); 390 if (slash == NULL) 391 return EINVAL; 392 393 *slash = 0; 394 395 int rc = inet_addr_version(text, &naddr->version); 396 if (rc != EOK) 397 return rc; 398 399 uint8_t buf[16]; 400 rc = inet_pton(ipver_af(naddr->version), text, buf); 401 *slash = '/'; 402 403 if (rc != EOK) 404 return rc; 405 406 slash++; 407 uint8_t prefix; 408 409 switch (naddr->version) { 410 case ip_v4: 411 prefix = strtoul(slash, &slash, 10); 412 if (prefix > 32) 55 413 return EINVAL; 56 ++cp; 57 } 58 59 a[3] = strtoul(cp, &cp, 10); 60 if (*cp != '/') 61 return EINVAL; 62 ++cp; 63 64 bits = strtoul(cp, &cp, 10); 65 if (*cp != '\0') 66 return EINVAL; 67 68 naddr->ipv4 = 0; 69 for (i = 0; i < 4; i++) { 70 if (a[i] > 255) 414 415 naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | 416 buf[3]; 417 naddr->prefix = prefix; 418 419 break; 420 case ip_v6: 421 prefix = strtoul(slash, &slash, 10); 422 if (prefix > 128) 71 423 return EINVAL; 72 naddr->ipv4 = (naddr->ipv4 << 8) | a[i]; 73 } 74 75 if (bits > 31) 76 return EINVAL; 77 78 naddr->bits = bits; 424 425 memcpy(naddr->addr6, buf, 16); 426 naddr->prefix = prefix; 427 428 break; 429 default: 430 return ENOTSUP; 431 } 432 79 433 return EOK; 80 434 } 81 435 82 /** Parse node address. 83 * 84 * @param text Network address in dot notation (a.b.c.d) 85 * @param addr Place to store node address 86 * 87 * @return EOK on success, EINVAL if input is not in valid format 88 */ 89 int inet_addr_parse(const char *text, inet_addr_t *addr) 90 { 91 unsigned long a[4]; 92 char *cp = (char *)text; 93 int i; 94 95 for (i = 0; i < 3; i++) { 96 a[i] = strtoul(cp, &cp, 10); 97 if (*cp != '.') 98 return EINVAL; 99 ++cp; 100 } 101 102 a[3] = strtoul(cp, &cp, 10); 103 if (*cp != '\0') 104 return EINVAL; 105 106 addr->ipv4 = 0; 107 for (i = 0; i < 4; i++) { 108 if (a[i] > 255) 109 return EINVAL; 110 addr->ipv4 = (addr->ipv4 << 8) | a[i]; 111 } 112 113 return EOK; 114 } 115 116 /** Format network address. 117 * 118 * @param naddr Network address 119 * @param bufp Place to store pointer to formatted string (CIDR notation) 120 * 121 * @return EOK on success, ENOMEM if out of memory. 122 */ 123 int inet_naddr_format(inet_naddr_t *naddr, char **bufp) 124 { 125 int rc; 126 127 rc = asprintf(bufp, "%d.%d.%d.%d/%d", naddr->ipv4 >> 24, 128 (naddr->ipv4 >> 16) & 0xff, (naddr->ipv4 >> 8) & 0xff, 129 naddr->ipv4 & 0xff, naddr->bits); 130 436 /** Format node address. 437 * 438 * @param addr Node address. 439 * @param bufp Place to store pointer to formatted string. 440 * 441 * @return EOK on success. 442 * @return ENOMEM if out of memory. 443 * @return ENOTSUP on unsupported address family. 444 * 445 */ 446 int inet_addr_format(const inet_addr_t *addr, char **bufp) 447 { 448 int rc = 0; 449 450 switch (addr->version) { 451 case ip_any: 452 rc = asprintf(bufp, "none"); 453 break; 454 case ip_v4: 455 rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff, 456 (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff, 457 addr->addr & 0xff); 458 break; 459 case ip_v6: 460 *bufp = (char *) malloc(INET6_ADDRSTRLEN); 461 if (*bufp == NULL) 462 return ENOMEM; 463 464 return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN); 465 default: 466 return ENOTSUP; 467 } 468 131 469 if (rc < 0) 132 470 return ENOMEM; 133 471 134 472 return EOK; 135 473 } 136 474 137 /** Format node address. 138 * 139 * @param addr Node address 140 * @param bufp Place to store pointer to formatted string (dot notation) 141 * 142 * @return EOK on success, ENOMEM if out of memory. 143 */ 144 int inet_addr_format(inet_addr_t *addr, char **bufp) 145 { 146 int rc; 147 148 rc = asprintf(bufp, "%d.%d.%d.%d", addr->ipv4 >> 24, 149 (addr->ipv4 >> 16) & 0xff, (addr->ipv4 >> 8) & 0xff, 150 addr->ipv4 & 0xff); 151 475 /** Format network address. 476 * 477 * @param naddr Network address. 478 * @param bufp Place to store pointer to formatted string. 479 * 480 * @return EOK on success. 481 * @return ENOMEM if out of memory. 482 * @return ENOTSUP on unsupported address family. 483 * 484 */ 485 int inet_naddr_format(const inet_naddr_t *naddr, char **bufp) 486 { 487 int rc = 0; 488 char prefix[INET_PREFIXSTRSIZE]; 489 490 switch (naddr->version) { 491 case ip_any: 492 rc = asprintf(bufp, "none"); 493 break; 494 case ip_v4: 495 rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 496 "/%" PRIu8, (naddr->addr >> 24) & 0xff, 497 (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff, 498 naddr->addr & 0xff, naddr->prefix); 499 break; 500 case ip_v6: 501 *bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE); 502 if (*bufp == NULL) 503 return ENOMEM; 504 505 rc = inet_ntop(AF_INET6, naddr->addr6, *bufp, 506 INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE); 507 if (rc != EOK) { 508 free(*bufp); 509 return rc; 510 } 511 512 rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8, 513 naddr->prefix); 514 if (rc < 0) { 515 free(*bufp); 516 return ENOMEM; 517 } 518 519 str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix); 520 521 break; 522 default: 523 return ENOTSUP; 524 } 525 152 526 if (rc < 0) 153 527 return ENOMEM; 154 528 155 529 return EOK; 156 530 } 157 531 532 ip_ver_t inet_addr_get(const inet_addr_t *addr, addr32_t *v4, addr128_t *v6) 533 { 534 switch (addr->version) { 535 case ip_v4: 536 if (v4 != NULL) 537 *v4 = addr->addr; 538 break; 539 case ip_v6: 540 if (v6 != NULL) 541 memcpy(*v6, addr->addr6, 16); 542 break; 543 default: 544 assert(false); 545 break; 546 } 547 548 return addr->version; 549 } 550 551 ip_ver_t inet_naddr_get(const inet_naddr_t *naddr, addr32_t *v4, addr128_t *v6, 552 uint8_t *prefix) 553 { 554 switch (naddr->version) { 555 case ip_v4: 556 if (v4 != NULL) 557 *v4 = naddr->addr; 558 if (prefix != NULL) 559 *prefix = naddr->prefix; 560 break; 561 case ip_v6: 562 if (v6 != NULL) 563 memcpy(*v6, naddr->addr6, 16); 564 if (prefix != NULL) 565 *prefix = naddr->prefix; 566 break; 567 default: 568 assert(false); 569 break; 570 } 571 572 return naddr->version; 573 } 574 575 void inet_addr_set(addr32_t v4, inet_addr_t *addr) 576 { 577 addr->version = ip_v4; 578 addr->addr = v4; 579 } 580 581 void inet_naddr_set(addr32_t v4, uint8_t prefix, inet_naddr_t *naddr) 582 { 583 naddr->version = ip_v4; 584 naddr->addr = v4; 585 naddr->prefix = prefix; 586 } 587 588 void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr) 589 { 590 addr->version = ip_v4; 591 addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr); 592 } 593 594 void inet_addr_set6(addr128_t v6, inet_addr_t *addr) 595 { 596 addr->version = ip_v6; 597 memcpy(addr->addr6, v6, 16); 598 } 599 600 void inet_naddr_set6(addr128_t v6, uint8_t prefix, inet_naddr_t *naddr) 601 { 602 naddr->version = ip_v6; 603 memcpy(naddr->addr6, v6, 16); 604 naddr->prefix = prefix; 605 } 606 607 void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6, 608 inet_addr_t *addr) 609 { 610 addr->version = ip_v6; 611 addr128_t_be2host(sockaddr_in6->sin6_addr.s6_addr, addr->addr6); 612 } 613 614 uint16_t inet_addr_sockaddr_in(const inet_addr_t *addr, 615 sockaddr_in_t *sockaddr_in, sockaddr_in6_t *sockaddr_in6) 616 { 617 switch (addr->version) { 618 case ip_v4: 619 if (sockaddr_in != NULL) { 620 sockaddr_in->sin_family = AF_INET; 621 sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr); 622 } 623 break; 624 case ip_v6: 625 if (sockaddr_in6 != NULL) { 626 sockaddr_in6->sin6_family = AF_INET6; 627 host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr); 628 } 629 break; 630 default: 631 assert(false); 632 break; 633 } 634 635 return ipver_af(addr->version); 636 } 637 638 int inet_addr_sockaddr(const inet_addr_t *addr, uint16_t port, 639 sockaddr_t **nsockaddr, socklen_t *naddrlen) 640 { 641 sockaddr_in_t *sa4; 642 sockaddr_in6_t *sa6; 643 644 switch (addr->version) { 645 case ip_v4: 646 sa4 = calloc(1, sizeof(sockaddr_in_t)); 647 if (sa4 == NULL) 648 return ENOMEM; 649 650 sa4->sin_family = AF_INET; 651 sa4->sin_port = host2uint16_t_be(port); 652 sa4->sin_addr.s_addr = host2uint32_t_be(addr->addr); 653 if (nsockaddr != NULL) 654 *nsockaddr = (sockaddr_t *)sa4; 655 if (naddrlen != NULL) 656 *naddrlen = sizeof(*sa4); 657 break; 658 case ip_v6: 659 sa6 = calloc(1, sizeof(sockaddr_in6_t)); 660 if (sa6 == NULL) 661 return ENOMEM; 662 663 sa6->sin6_family = AF_INET6; 664 sa6->sin6_port = host2uint16_t_be(port); 665 host2addr128_t_be(addr->addr6, sa6->sin6_addr.s6_addr); 666 if (nsockaddr != NULL) 667 *nsockaddr = (sockaddr_t *)sa6; 668 if (naddrlen != NULL) 669 *naddrlen = sizeof(*sa6); 670 break; 671 default: 672 assert(false); 673 break; 674 } 675 676 return EOK; 677 } 678 158 679 /** @} 159 680 */
Note:
See TracChangeset
for help on using the changeset viewer.