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