1 /* 2 * Copyright 2010-2013, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <NetworkAddress.h> 8 9 #include <NetworkInterface.h> 10 #include <NetworkRoster.h> 11 12 #include <arpa/inet.h> 13 #include <ctype.h> 14 #include <errno.h> 15 #include <netinet/in.h> 16 #include <stdio.h> 17 #include <sys/sockio.h> 18 19 20 /* The GCC builtin below only exists in > GCC 3.4 21 * Benefits include faster execution time as the builtin 22 * uses a bitcounting cpu instruction if it exists 23 */ 24 #if __GNUC__ > 3 25 # define addr_bitcount(bitfield) __builtin_popcount(bitfield) 26 #else 27 static ssize_t 28 addr_bitcount(uint32 bitfield) 29 { 30 ssize_t result = 0; 31 for (uint8 i = 32; i > 0; i--) { 32 if ((bitfield & (1 << (i - 1))) == 0) 33 break; 34 result++; 35 } 36 return result; 37 } 38 #endif 39 40 41 static uint8 42 from_hex(char hex) 43 { 44 if (isdigit(hex)) 45 return hex - '0'; 46 47 return tolower(hex) - 'a' + 10; 48 } 49 50 51 // #pragma mark - 52 53 54 BNetworkAddress::BNetworkAddress() 55 { 56 Unset(); 57 } 58 59 60 BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags) 61 { 62 SetTo(host, port, flags); 63 } 64 65 66 BNetworkAddress::BNetworkAddress(const char* host, const char* service, 67 uint32 flags) 68 { 69 SetTo(host, service, flags); 70 } 71 72 73 BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port, 74 uint32 flags) 75 { 76 SetTo(family, host, port, flags); 77 } 78 79 80 BNetworkAddress::BNetworkAddress(int family, const char* host, 81 const char* service, uint32 flags) 82 { 83 SetTo(family, host, service, flags); 84 } 85 86 87 BNetworkAddress::BNetworkAddress(const sockaddr& address) 88 { 89 SetTo(address); 90 } 91 92 93 BNetworkAddress::BNetworkAddress(const sockaddr_storage& address) 94 { 95 SetTo(address); 96 } 97 98 99 BNetworkAddress::BNetworkAddress(const sockaddr_in& address) 100 { 101 SetTo(address); 102 } 103 104 105 BNetworkAddress::BNetworkAddress(const sockaddr_in6& address) 106 { 107 SetTo(address); 108 } 109 110 111 BNetworkAddress::BNetworkAddress(const sockaddr_dl& address) 112 { 113 SetTo(address); 114 } 115 116 117 BNetworkAddress::BNetworkAddress(in_addr_t address, uint16 port) 118 { 119 SetTo(address, port); 120 } 121 122 123 BNetworkAddress::BNetworkAddress(const in6_addr& address, uint16 port) 124 { 125 SetTo(address, port); 126 } 127 128 129 BNetworkAddress::BNetworkAddress(const BNetworkAddress& other) 130 : 131 fAddress(other.fAddress), 132 fStatus(other.fStatus) 133 { 134 } 135 136 137 BNetworkAddress::~BNetworkAddress() 138 { 139 } 140 141 142 status_t 143 BNetworkAddress::InitCheck() const 144 { 145 return fStatus; 146 } 147 148 149 void 150 BNetworkAddress::Unset() 151 { 152 fAddress.ss_family = AF_UNSPEC; 153 fAddress.ss_len = 2; 154 fStatus = B_OK; 155 } 156 157 158 status_t 159 BNetworkAddress::SetTo(const char* host, uint16 port, uint32 flags) 160 { 161 BNetworkAddressResolver resolver; 162 status_t status = resolver.SetTo(host, port, flags); 163 if (status != B_OK) 164 return status; 165 166 // Prefer IPv6 addresses 167 168 uint32 cookie = 0; 169 status = resolver.GetNextAddress(AF_INET6, &cookie, *this); 170 if (status == B_OK) 171 return B_OK; 172 173 cookie = 0; 174 return resolver.GetNextAddress(&cookie, *this); 175 } 176 177 178 status_t 179 BNetworkAddress::SetTo(const char* host, const char* service, uint32 flags) 180 { 181 BNetworkAddressResolver resolver; 182 status_t status = resolver.SetTo(host, service, flags); 183 if (status != B_OK) 184 return status; 185 186 // Prefer IPv6 addresses 187 188 uint32 cookie = 0; 189 status = resolver.GetNextAddress(AF_INET6, &cookie, *this); 190 if (status == B_OK) 191 return B_OK; 192 193 cookie = 0; 194 return resolver.GetNextAddress(&cookie, *this); 195 } 196 197 198 status_t 199 BNetworkAddress::SetTo(int family, const char* host, uint16 port, uint32 flags) 200 { 201 if (family == AF_LINK) { 202 if (port != 0) 203 return B_BAD_VALUE; 204 return _ParseLinkAddress(host); 205 } 206 207 BNetworkAddressResolver resolver; 208 status_t status = resolver.SetTo(family, host, port, flags); 209 if (status != B_OK) 210 return status; 211 212 uint32 cookie = 0; 213 return resolver.GetNextAddress(&cookie, *this); 214 } 215 216 217 status_t 218 BNetworkAddress::SetTo(int family, const char* host, const char* service, 219 uint32 flags) 220 { 221 if (family == AF_LINK) { 222 if (service != NULL) 223 return B_BAD_VALUE; 224 return _ParseLinkAddress(host); 225 } 226 227 BNetworkAddressResolver resolver; 228 status_t status = resolver.SetTo(family, host, service, flags); 229 if (status != B_OK) 230 return status; 231 232 uint32 cookie = 0; 233 return resolver.GetNextAddress(&cookie, *this); 234 } 235 236 237 void 238 BNetworkAddress::SetTo(const sockaddr& address) 239 { 240 if (address.sa_family == AF_UNSPEC) { 241 Unset(); 242 return; 243 } 244 245 size_t length = min_c(sizeof(sockaddr_storage), address.sa_len); 246 switch (address.sa_family) { 247 case AF_INET: 248 length = sizeof(sockaddr_in); 249 break; 250 case AF_INET6: 251 length = sizeof(sockaddr_in6); 252 break; 253 case AF_LINK: 254 { 255 sockaddr_dl& link = (sockaddr_dl&)address; 256 length = sizeof(sockaddr_dl) - sizeof(link.sdl_data) + link.sdl_alen 257 + link.sdl_nlen + link.sdl_slen; 258 break; 259 } 260 } 261 262 SetTo(address, length); 263 } 264 265 266 void 267 BNetworkAddress::SetTo(const sockaddr& address, size_t length) 268 { 269 if (address.sa_family == AF_UNSPEC || length == 0) { 270 Unset(); 271 return; 272 } 273 274 memcpy(&fAddress, &address, length); 275 fAddress.ss_len = length; 276 fStatus = B_OK; 277 } 278 279 280 void 281 BNetworkAddress::SetTo(const sockaddr_storage& address) 282 { 283 SetTo((sockaddr&)address); 284 } 285 286 287 void 288 BNetworkAddress::SetTo(const sockaddr_in& address) 289 { 290 SetTo((sockaddr&)address); 291 } 292 293 294 void 295 BNetworkAddress::SetTo(const sockaddr_in6& address) 296 { 297 SetTo((sockaddr&)address); 298 } 299 300 301 void 302 BNetworkAddress::SetTo(const sockaddr_dl& address) 303 { 304 SetTo((sockaddr&)address); 305 } 306 307 308 void 309 BNetworkAddress::SetTo(in_addr_t inetAddress, uint16 port) 310 { 311 memset(&fAddress, 0, sizeof(sockaddr_storage)); 312 313 fAddress.ss_family = AF_INET; 314 fAddress.ss_len = sizeof(sockaddr_in); 315 SetAddress(inetAddress); 316 SetPort(port); 317 318 fStatus = B_OK; 319 } 320 321 322 void 323 BNetworkAddress::SetTo(const in6_addr& inet6Address, uint16 port) 324 { 325 memset(&fAddress, 0, sizeof(sockaddr_storage)); 326 327 fAddress.ss_family = AF_INET6; 328 fAddress.ss_len = sizeof(sockaddr_in6); 329 SetAddress(inet6Address); 330 SetPort(port); 331 332 fStatus = B_OK; 333 } 334 335 336 void 337 BNetworkAddress::SetTo(const BNetworkAddress& other) 338 { 339 fAddress = other.fAddress; 340 fStatus = other.fStatus; 341 } 342 343 344 status_t 345 BNetworkAddress::SetToBroadcast(int family, uint16 port) 346 { 347 if (family != AF_INET) 348 return fStatus = B_NOT_SUPPORTED; 349 350 SetTo(INADDR_BROADCAST, port); 351 return B_OK; 352 } 353 354 355 status_t 356 BNetworkAddress::SetToLocal(int family, uint16 port) 357 { 358 // TODO: choose a local address from the network interfaces 359 return fStatus = B_NOT_SUPPORTED; 360 } 361 362 363 status_t 364 BNetworkAddress::SetToLoopback(int family, uint16 port) 365 { 366 switch (family) { 367 // TODO: choose family depending on availability of IPv6 368 case AF_UNSPEC: 369 case AF_INET: 370 SetTo(htonl(INADDR_LOOPBACK), port); 371 break; 372 373 case AF_INET6: 374 SetTo(in6addr_loopback, port); 375 break; 376 377 default: 378 return fStatus = B_NOT_SUPPORTED; 379 } 380 381 return B_OK; 382 } 383 384 385 status_t 386 BNetworkAddress::SetToMask(int family, uint32 prefixLength) 387 { 388 switch (family) { 389 case AF_INET: 390 { 391 if (prefixLength > 32) 392 return B_BAD_VALUE; 393 394 sockaddr_in& mask = (sockaddr_in&)fAddress; 395 memset(&fAddress, 0, sizeof(sockaddr_storage)); 396 mask.sin_family = AF_INET; 397 mask.sin_len = sizeof(sockaddr_in); 398 399 uint32 hostMask = 0; 400 for (uint8 i = 32; i > 32 - prefixLength; i--) 401 hostMask |= 1 << (i - 1); 402 403 mask.sin_addr.s_addr = htonl(hostMask); 404 break; 405 } 406 407 case AF_INET6: 408 { 409 if (prefixLength > 128) 410 return B_BAD_VALUE; 411 412 sockaddr_in6& mask = (sockaddr_in6&)fAddress; 413 memset(&fAddress, 0, sizeof(sockaddr_storage)); 414 mask.sin6_family = AF_INET6; 415 mask.sin6_len = sizeof(sockaddr_in6); 416 417 for (uint8 i = 0; i < sizeof(in6_addr); i++, prefixLength -= 8) { 418 if (prefixLength < 8) { 419 mask.sin6_addr.s6_addr[i] 420 = (uint8)(0xff << (8 - prefixLength)); 421 break; 422 } 423 424 mask.sin6_addr.s6_addr[i] = 0xff; 425 } 426 break; 427 } 428 429 default: 430 return fStatus = B_NOT_SUPPORTED; 431 } 432 433 return fStatus = B_OK; 434 } 435 436 437 status_t 438 BNetworkAddress::SetToWildcard(int family, uint16 port) 439 { 440 switch (family) { 441 case AF_INET: 442 SetTo(INADDR_ANY, port); 443 break; 444 445 case AF_INET6: 446 SetTo(in6addr_any, port); 447 break; 448 449 default: 450 return fStatus = B_NOT_SUPPORTED; 451 } 452 453 return B_OK; 454 } 455 456 457 status_t 458 BNetworkAddress::SetAddress(in_addr_t inetAddress) 459 { 460 if (Family() != AF_INET) 461 return B_BAD_VALUE; 462 463 sockaddr_in& address = (sockaddr_in&)fAddress; 464 address.sin_addr.s_addr = inetAddress; 465 return B_OK; 466 } 467 468 469 status_t 470 BNetworkAddress::SetAddress(const in6_addr& inet6Address) 471 { 472 if (Family() != AF_INET6) 473 return B_BAD_VALUE; 474 475 sockaddr_in6& address = (sockaddr_in6&)fAddress; 476 memcpy(address.sin6_addr.s6_addr, &inet6Address, 477 sizeof(address.sin6_addr.s6_addr)); 478 return B_OK; 479 } 480 481 482 void 483 BNetworkAddress::SetPort(uint16 port) 484 { 485 switch (fAddress.ss_family) { 486 case AF_INET: 487 ((sockaddr_in&)fAddress).sin_port = htons(port); 488 break; 489 490 case AF_INET6: 491 ((sockaddr_in6&)fAddress).sin6_port = htons(port); 492 break; 493 494 default: 495 break; 496 } 497 } 498 499 500 void 501 BNetworkAddress::SetToLinkLevel(uint8* address, size_t length) 502 { 503 sockaddr_dl& link = (sockaddr_dl&)fAddress; 504 memset(&link, 0, sizeof(sockaddr_dl)); 505 506 link.sdl_family = AF_LINK; 507 link.sdl_alen = length; 508 memcpy(LLADDR(&link), address, length); 509 510 link.sdl_len = sizeof(sockaddr_dl); 511 if (length > sizeof(link.sdl_data)) 512 link.sdl_len += length - sizeof(link.sdl_data); 513 } 514 515 516 void 517 BNetworkAddress::SetToLinkLevel(const char* name) 518 { 519 sockaddr_dl& link = (sockaddr_dl&)fAddress; 520 memset(&link, 0, sizeof(sockaddr_dl)); 521 522 size_t length = strlen(name); 523 if (length > sizeof(fAddress) - sizeof(sockaddr_dl) + sizeof(link.sdl_data)) 524 length = sizeof(fAddress) - sizeof(sockaddr_dl) + sizeof(link.sdl_data); 525 526 link.sdl_family = AF_LINK; 527 link.sdl_nlen = length; 528 529 memcpy(link.sdl_data, name, link.sdl_nlen); 530 531 link.sdl_len = sizeof(sockaddr_dl); 532 if (link.sdl_nlen > sizeof(link.sdl_data)) 533 link.sdl_len += link.sdl_nlen - sizeof(link.sdl_data); 534 } 535 536 537 void 538 BNetworkAddress::SetToLinkLevel(uint32 index) 539 { 540 sockaddr_dl& link = (sockaddr_dl&)fAddress; 541 memset(&link, 0, sizeof(sockaddr_dl)); 542 543 link.sdl_family = AF_LINK; 544 link.sdl_len = sizeof(sockaddr_dl); 545 link.sdl_index = index; 546 } 547 548 549 void 550 BNetworkAddress::SetLinkLevelIndex(uint32 index) 551 { 552 sockaddr_dl& link = (sockaddr_dl&)fAddress; 553 link.sdl_index = index; 554 } 555 556 557 void 558 BNetworkAddress::SetLinkLevelType(uint8 type) 559 { 560 sockaddr_dl& link = (sockaddr_dl&)fAddress; 561 link.sdl_type = type; 562 } 563 564 565 void 566 BNetworkAddress::SetLinkLevelFrameType(uint16 frameType) 567 { 568 sockaddr_dl& link = (sockaddr_dl&)fAddress; 569 link.sdl_e_type = htons(frameType); 570 } 571 572 573 int 574 BNetworkAddress::Family() const 575 { 576 return fAddress.ss_family; 577 } 578 579 580 uint16 581 BNetworkAddress::Port() const 582 { 583 switch (fAddress.ss_family) { 584 case AF_INET: 585 return ntohs(((sockaddr_in&)fAddress).sin_port); 586 587 case AF_INET6: 588 return ntohs(((sockaddr_in6&)fAddress).sin6_port); 589 590 default: 591 return 0; 592 } 593 } 594 595 596 size_t 597 BNetworkAddress::Length() const 598 { 599 return fAddress.ss_len; 600 } 601 602 603 const sockaddr& 604 BNetworkAddress::SockAddr() const 605 { 606 return (const sockaddr&)fAddress; 607 } 608 609 610 sockaddr& 611 BNetworkAddress::SockAddr() 612 { 613 return (sockaddr&)fAddress; 614 } 615 616 617 bool 618 BNetworkAddress::IsEmpty() const 619 { 620 return fAddress.ss_len == 0 || fAddress.ss_family == AF_UNSPEC; 621 } 622 623 624 bool 625 BNetworkAddress::IsWildcard() const 626 { 627 switch (fAddress.ss_family) { 628 case AF_INET: 629 return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_ANY; 630 631 case AF_INET6: 632 return !memcmp(&((sockaddr_in6&)fAddress).sin6_addr, &in6addr_any, 633 sizeof(in6_addr)); 634 635 default: 636 return false; 637 } 638 } 639 640 641 bool 642 BNetworkAddress::IsBroadcast() const 643 { 644 switch (fAddress.ss_family) { 645 case AF_INET: 646 return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_BROADCAST; 647 648 case AF_INET6: 649 // There is no broadcast in IPv6, only multicast/anycast 650 return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr); 651 652 default: 653 return false; 654 } 655 } 656 657 658 bool 659 BNetworkAddress::IsMulticast() const 660 { 661 switch (fAddress.ss_family) { 662 case AF_INET: 663 return IN_MULTICAST(((sockaddr_in&)fAddress).sin_addr.s_addr); 664 665 case AF_INET6: 666 return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr); 667 668 default: 669 return false; 670 } 671 } 672 673 674 bool 675 BNetworkAddress::IsMulticastGlobal() const 676 { 677 switch (fAddress.ss_family) { 678 case AF_INET6: 679 return IN6_IS_ADDR_MC_GLOBAL(&((sockaddr_in6&)fAddress).sin6_addr); 680 681 default: 682 return false; 683 } 684 } 685 686 687 bool 688 BNetworkAddress::IsMulticastNodeLocal() const 689 { 690 switch (fAddress.ss_family) { 691 case AF_INET6: 692 return IN6_IS_ADDR_MC_NODELOCAL( 693 &((sockaddr_in6&)fAddress).sin6_addr); 694 695 default: 696 return false; 697 } 698 } 699 700 701 bool 702 BNetworkAddress::IsMulticastLinkLocal() const 703 { 704 switch (fAddress.ss_family) { 705 case AF_INET6: 706 return IN6_IS_ADDR_MC_LINKLOCAL( 707 &((sockaddr_in6&)fAddress).sin6_addr); 708 709 default: 710 return false; 711 } 712 } 713 714 715 bool 716 BNetworkAddress::IsMulticastSiteLocal() const 717 { 718 switch (fAddress.ss_family) { 719 case AF_INET6: 720 return IN6_IS_ADDR_MC_SITELOCAL( 721 &((sockaddr_in6&)fAddress).sin6_addr); 722 723 default: 724 return false; 725 } 726 } 727 728 729 bool 730 BNetworkAddress::IsMulticastOrgLocal() const 731 { 732 switch (fAddress.ss_family) { 733 case AF_INET6: 734 return IN6_IS_ADDR_MC_ORGLOCAL( 735 &((sockaddr_in6&)fAddress).sin6_addr); 736 737 default: 738 return false; 739 } 740 } 741 742 743 bool 744 BNetworkAddress::IsLinkLocal() const 745 { 746 // TODO: ipv4 747 switch (fAddress.ss_family) { 748 case AF_INET6: 749 return IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6&)fAddress).sin6_addr); 750 751 default: 752 return false; 753 } 754 } 755 756 757 bool 758 BNetworkAddress::IsSiteLocal() const 759 { 760 switch (fAddress.ss_family) { 761 case AF_INET6: 762 return IN6_IS_ADDR_SITELOCAL(&((sockaddr_in6&)fAddress).sin6_addr); 763 764 default: 765 return false; 766 } 767 } 768 769 770 bool 771 BNetworkAddress::IsLocal() const 772 { 773 BNetworkRoster& roster = BNetworkRoster::Default(); 774 775 BNetworkInterface interface; 776 uint32 cookie = 0; 777 778 while (roster.GetNextInterface(&cookie, interface) == B_OK) { 779 int32 count = interface.CountAddresses(); 780 for (int32 j = 0; j < count; j++) { 781 BNetworkInterfaceAddress address; 782 if (interface.GetAddressAt(j, address) != B_OK) 783 break; 784 785 if (Equals(address.Address(), false)) 786 return true; 787 } 788 } 789 790 return false; 791 } 792 793 794 ssize_t 795 BNetworkAddress::PrefixLength() const 796 { 797 switch (fAddress.ss_family) { 798 case AF_INET: 799 { 800 sockaddr_in& mask = (sockaddr_in&)fAddress; 801 802 uint32 hostMask = ntohl(mask.sin_addr.s_addr); 803 return addr_bitcount(hostMask); 804 } 805 806 case AF_INET6: 807 { 808 sockaddr_in6& mask = (sockaddr_in6&)fAddress; 809 810 // TODO : see if we can use the optimized addr_bitcount for this 811 ssize_t result = 0; 812 for (uint8 i = 0; i < sizeof(in6_addr); i++) { 813 for (uint8 j = 0; j < 8; j++) { 814 if (!(mask.sin6_addr.s6_addr[i] & (1 << j))) 815 return result; 816 result++; 817 } 818 } 819 820 return 128; 821 } 822 823 default: 824 return B_NOT_SUPPORTED; 825 } 826 } 827 828 829 uint32 830 BNetworkAddress::LinkLevelIndex() const 831 { 832 return ((sockaddr_dl&)fAddress).sdl_index; 833 } 834 835 836 BString 837 BNetworkAddress::LinkLevelInterface() const 838 { 839 sockaddr_dl& address = (sockaddr_dl&)fAddress; 840 if (address.sdl_nlen == 0) 841 return ""; 842 843 BString name; 844 name.SetTo((const char*)address.sdl_data, address.sdl_nlen); 845 846 return name; 847 } 848 849 850 uint8 851 BNetworkAddress::LinkLevelType() const 852 { 853 return ((sockaddr_dl&)fAddress).sdl_type; 854 } 855 856 857 uint16 858 BNetworkAddress::LinkLevelFrameType() const 859 { 860 return ntohs(((sockaddr_dl&)fAddress).sdl_e_type); 861 } 862 863 864 uint8* 865 BNetworkAddress::LinkLevelAddress() const 866 { 867 return LLADDR(&(sockaddr_dl&)fAddress); 868 } 869 870 871 size_t 872 BNetworkAddress::LinkLevelAddressLength() const 873 { 874 return ((sockaddr_dl&)fAddress).sdl_alen; 875 } 876 877 878 status_t 879 BNetworkAddress::ResolveForDestination(const BNetworkAddress& destination) 880 { 881 if (!IsWildcard()) 882 return B_OK; 883 if (destination.fAddress.ss_family != fAddress.ss_family) 884 return B_BAD_VALUE; 885 886 char buffer[2048]; 887 memset(buffer, 0, sizeof(buffer)); 888 889 route_entry* route = (route_entry*)buffer; 890 route->destination = (sockaddr*)&destination.fAddress; 891 892 int socket = ::socket(fAddress.ss_family, SOCK_DGRAM, 0); 893 if (socket < 0) 894 return errno; 895 896 if (ioctl(socket, SIOCGETRT, route, sizeof(buffer)) != 0) { 897 close(socket); 898 return errno; 899 } 900 901 uint16 port = Port(); 902 memcpy(&fAddress, route->source, sizeof(sockaddr_storage)); 903 SetPort(port); 904 905 return B_OK; 906 } 907 908 909 status_t 910 BNetworkAddress::ResolveTo(const BNetworkAddress& address) 911 { 912 if (!IsWildcard()) 913 return B_OK; 914 if (address.fAddress.ss_family != fAddress.ss_family) 915 return B_BAD_VALUE; 916 917 uint16 port = Port(); 918 *this = address; 919 SetPort(port); 920 921 return B_OK; 922 } 923 924 925 BString 926 BNetworkAddress::ToString(bool includePort) const 927 { 928 char buffer[512]; 929 930 switch (fAddress.ss_family) { 931 case AF_INET: 932 inet_ntop(AF_INET, &((sockaddr_in&)fAddress).sin_addr, buffer, 933 sizeof(buffer)); 934 break; 935 936 case AF_INET6: 937 inet_ntop(AF_INET6, &((sockaddr_in6&)fAddress).sin6_addr, 938 buffer, sizeof(buffer)); 939 break; 940 941 case AF_LINK: 942 { 943 uint8 *byte = LinkLevelAddress(); 944 char* target = buffer; 945 int bytesLeft = sizeof(buffer); 946 target[0] = '\0'; 947 948 for (size_t i = 0; i < LinkLevelAddressLength(); i++) { 949 if (i != 0 && bytesLeft > 1) { 950 target[0] = ':'; 951 target[1] = '\0'; 952 target++; 953 bytesLeft--; 954 } 955 956 int bytesWritten = snprintf(target, bytesLeft, "%02x", byte[i]); 957 if (bytesWritten >= bytesLeft) 958 break; 959 960 target += bytesWritten; 961 bytesLeft -= bytesWritten; 962 } 963 break; 964 } 965 966 default: 967 return ""; 968 } 969 970 BString address = buffer; 971 if (includePort && Port() != 0) { 972 if (fAddress.ss_family == AF_INET6) { 973 address = "["; 974 address += buffer; 975 address += "]"; 976 } 977 978 snprintf(buffer, sizeof(buffer), ":%u", Port()); 979 address += buffer; 980 } 981 982 return address; 983 } 984 985 986 BString 987 BNetworkAddress::HostName() const 988 { 989 // TODO: implement host name lookup 990 return ToString(false); 991 } 992 993 994 BString 995 BNetworkAddress::ServiceName() const 996 { 997 // TODO: implement service lookup 998 BString portName; 999 portName << Port(); 1000 return portName; 1001 } 1002 1003 1004 bool 1005 BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const 1006 { 1007 if (IsEmpty() && other.IsEmpty()) 1008 return true; 1009 1010 if (Family() != other.Family() 1011 || (includePort && Port() != other.Port())) { 1012 return false; 1013 } 1014 1015 switch (fAddress.ss_family) { 1016 case AF_INET: 1017 { 1018 sockaddr_in& address = (sockaddr_in&)fAddress; 1019 sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress; 1020 return memcmp(&address.sin_addr, &otherAddress.sin_addr, 1021 sizeof(address.sin_addr)) == 0; 1022 } 1023 1024 case AF_INET6: 1025 { 1026 sockaddr_in6& address = (sockaddr_in6&)fAddress; 1027 sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress; 1028 return memcmp(&address.sin6_addr, &otherAddress.sin6_addr, 1029 sizeof(address.sin6_addr)) == 0; 1030 } 1031 1032 default: 1033 if (fAddress.ss_len != other.fAddress.ss_len) 1034 return false; 1035 1036 return memcmp(&fAddress, &other.fAddress, fAddress.ss_len); 1037 } 1038 } 1039 1040 1041 // #pragma mark - BFlattenable implementation 1042 1043 1044 bool 1045 BNetworkAddress::IsFixedSize() const 1046 { 1047 return false; 1048 } 1049 1050 1051 type_code 1052 BNetworkAddress::TypeCode() const 1053 { 1054 return B_NETWORK_ADDRESS_TYPE; 1055 } 1056 1057 1058 ssize_t 1059 BNetworkAddress::FlattenedSize() const 1060 { 1061 return Length(); 1062 } 1063 1064 1065 status_t 1066 BNetworkAddress::Flatten(void* buffer, ssize_t size) const 1067 { 1068 if (buffer == NULL || size < FlattenedSize()) 1069 return B_BAD_VALUE; 1070 1071 memcpy(buffer, &fAddress, Length()); 1072 return B_OK; 1073 } 1074 1075 1076 status_t 1077 BNetworkAddress::Unflatten(type_code code, const void* buffer, ssize_t size) 1078 { 1079 // 2 bytes minimum for family, and length 1080 if (buffer == NULL || size < 2) 1081 return fStatus = B_BAD_VALUE; 1082 if (!AllowsTypeCode(code)) 1083 return fStatus = B_BAD_TYPE; 1084 1085 memcpy(&fAddress, buffer, min_c(size, (ssize_t)sizeof(fAddress))); 1086 1087 // check if this can contain a valid address 1088 if (fAddress.ss_family != AF_UNSPEC && size < (ssize_t)sizeof(sockaddr)) 1089 return fStatus = B_BAD_VALUE; 1090 1091 return fStatus = B_OK; 1092 } 1093 1094 1095 // #pragma mark - operators 1096 1097 1098 BNetworkAddress& 1099 BNetworkAddress::operator=(const BNetworkAddress& other) 1100 { 1101 memcpy(&fAddress, &other.fAddress, other.fAddress.ss_len); 1102 fStatus = other.fStatus; 1103 1104 return *this; 1105 } 1106 1107 1108 bool 1109 BNetworkAddress::operator==(const BNetworkAddress& other) const 1110 { 1111 return Equals(other); 1112 } 1113 1114 1115 bool 1116 BNetworkAddress::operator!=(const BNetworkAddress& other) const 1117 { 1118 return !Equals(other); 1119 } 1120 1121 1122 bool 1123 BNetworkAddress::operator<(const BNetworkAddress& other) const 1124 { 1125 if (Family() < other.Family()) 1126 return true; 1127 if (Family() > other.Family()) 1128 return false; 1129 1130 int compare; 1131 1132 switch (fAddress.ss_family) { 1133 default: 1134 case AF_INET: 1135 { 1136 sockaddr_in& address = (sockaddr_in&)fAddress; 1137 sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress; 1138 compare = memcmp(&address.sin_addr, &otherAddress.sin_addr, 1139 sizeof(address.sin_addr)); 1140 break; 1141 } 1142 1143 case AF_INET6: 1144 { 1145 sockaddr_in6& address = (sockaddr_in6&)fAddress; 1146 sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress; 1147 compare = memcmp(&address.sin6_addr, &otherAddress.sin6_addr, 1148 sizeof(address.sin6_addr)); 1149 break; 1150 } 1151 1152 case AF_LINK: 1153 if (LinkLevelAddressLength() < other.LinkLevelAddressLength()) 1154 return true; 1155 if (LinkLevelAddressLength() > other.LinkLevelAddressLength()) 1156 return true; 1157 1158 // TODO: could compare index, and name, too 1159 compare = memcmp(LinkLevelAddress(), other.LinkLevelAddress(), 1160 LinkLevelAddressLength()); 1161 break; 1162 } 1163 1164 if (compare < 0) 1165 return true; 1166 if (compare > 0) 1167 return false; 1168 1169 return Port() < other.Port(); 1170 } 1171 1172 1173 BNetworkAddress::operator const sockaddr*() const 1174 { 1175 return (const sockaddr*)&fAddress; 1176 } 1177 1178 1179 BNetworkAddress::operator const sockaddr&() const 1180 { 1181 return (const sockaddr&)fAddress; 1182 } 1183 1184 1185 BNetworkAddress::operator sockaddr*() 1186 { 1187 return (sockaddr*)&fAddress; 1188 } 1189 1190 1191 BNetworkAddress::operator const sockaddr*() 1192 { 1193 return (sockaddr*)&fAddress; 1194 } 1195 1196 1197 BNetworkAddress::operator sockaddr&() 1198 { 1199 return (sockaddr&)fAddress; 1200 } 1201 1202 1203 BNetworkAddress::operator const sockaddr&() 1204 { 1205 return (sockaddr&)fAddress; 1206 } 1207 1208 1209 // #pragma mark - private 1210 1211 1212 status_t 1213 BNetworkAddress::_ParseLinkAddress(const char* address) 1214 { 1215 if (address == NULL) 1216 return B_BAD_VALUE; 1217 1218 uint8 linkAddress[128]; 1219 uint32 length = 0; 1220 while (length < sizeof(linkAddress)) { 1221 if (!isxdigit(address[0]) || !isxdigit(address[1])) 1222 return B_BAD_VALUE; 1223 1224 linkAddress[length++] = (from_hex(address[0]) << 4) 1225 | from_hex(address[1]); 1226 1227 if (address[2] == '\0') 1228 break; 1229 if (address[2] != ':') 1230 return B_BAD_VALUE; 1231 1232 address += 3; 1233 } 1234 1235 SetToLinkLevel(linkAddress, length); 1236 return B_OK; 1237 } 1238