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