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.Get() == NULL) 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.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 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.Get() == NULL) 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.Get() == NULL) 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 return B_OK; 967 } 968 969 970 status_t 971 BNetworkAddress::ResolveTo(const BNetworkAddress& address) 972 { 973 if (!IsWildcard()) 974 return B_OK; 975 if (address.fAddress.ss_family != fAddress.ss_family) 976 return B_BAD_VALUE; 977 978 uint16 port = Port(); 979 *this = address; 980 SetPort(port); 981 982 return B_OK; 983 } 984 985 986 BString 987 BNetworkAddress::ToString(bool includePort) const 988 { 989 char buffer[512]; 990 991 switch (fAddress.ss_family) { 992 case AF_INET: 993 inet_ntop(AF_INET, &((sockaddr_in&)fAddress).sin_addr, buffer, 994 sizeof(buffer)); 995 break; 996 997 case AF_INET6: 998 inet_ntop(AF_INET6, &((sockaddr_in6&)fAddress).sin6_addr, 999 buffer, sizeof(buffer)); 1000 break; 1001 1002 case AF_LINK: 1003 { 1004 uint8 *byte = LinkLevelAddress(); 1005 char* target = buffer; 1006 int bytesLeft = sizeof(buffer); 1007 target[0] = '\0'; 1008 1009 for (size_t i = 0; i < LinkLevelAddressLength(); i++) { 1010 if (i != 0 && bytesLeft > 1) { 1011 target[0] = ':'; 1012 target[1] = '\0'; 1013 target++; 1014 bytesLeft--; 1015 } 1016 1017 int bytesWritten = snprintf(target, bytesLeft, "%02x", byte[i]); 1018 if (bytesWritten >= bytesLeft) 1019 break; 1020 1021 target += bytesWritten; 1022 bytesLeft -= bytesWritten; 1023 } 1024 break; 1025 } 1026 1027 default: 1028 return ""; 1029 } 1030 1031 BString address = buffer; 1032 if (includePort && Port() != 0) { 1033 if (fAddress.ss_family == AF_INET6) { 1034 address = "["; 1035 address += buffer; 1036 address += "]"; 1037 } 1038 1039 snprintf(buffer, sizeof(buffer), ":%u", Port()); 1040 address += buffer; 1041 } 1042 1043 return address; 1044 } 1045 1046 1047 BString 1048 BNetworkAddress::HostName() const 1049 { 1050 // TODO: implement host name lookup 1051 return fHostName; 1052 } 1053 1054 1055 BString 1056 BNetworkAddress::ServiceName() const 1057 { 1058 // TODO: implement service lookup 1059 BString portName; 1060 portName << Port(); 1061 return portName; 1062 } 1063 1064 1065 bool 1066 BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const 1067 { 1068 if (IsEmpty() && other.IsEmpty()) 1069 return true; 1070 1071 if (Family() != other.Family() 1072 || (includePort && Port() != other.Port())) { 1073 return false; 1074 } 1075 1076 switch (fAddress.ss_family) { 1077 case AF_INET: 1078 { 1079 sockaddr_in& address = (sockaddr_in&)fAddress; 1080 sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress; 1081 return memcmp(&address.sin_addr, &otherAddress.sin_addr, 1082 sizeof(address.sin_addr)) == 0; 1083 } 1084 1085 case AF_INET6: 1086 { 1087 sockaddr_in6& address = (sockaddr_in6&)fAddress; 1088 sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress; 1089 return memcmp(&address.sin6_addr, &otherAddress.sin6_addr, 1090 sizeof(address.sin6_addr)) == 0; 1091 } 1092 1093 default: 1094 if (fAddress.ss_len != other.fAddress.ss_len) 1095 return false; 1096 1097 return memcmp(&fAddress, &other.fAddress, fAddress.ss_len); 1098 } 1099 } 1100 1101 1102 // #pragma mark - BFlattenable implementation 1103 1104 1105 bool 1106 BNetworkAddress::IsFixedSize() const 1107 { 1108 return false; 1109 } 1110 1111 1112 type_code 1113 BNetworkAddress::TypeCode() const 1114 { 1115 return B_NETWORK_ADDRESS_TYPE; 1116 } 1117 1118 1119 ssize_t 1120 BNetworkAddress::FlattenedSize() const 1121 { 1122 return Length(); 1123 } 1124 1125 1126 status_t 1127 BNetworkAddress::Flatten(void* buffer, ssize_t size) const 1128 { 1129 if (buffer == NULL || size < FlattenedSize()) 1130 return B_BAD_VALUE; 1131 1132 memcpy(buffer, &fAddress, Length()); 1133 return B_OK; 1134 } 1135 1136 1137 status_t 1138 BNetworkAddress::Unflatten(type_code code, const void* buffer, ssize_t size) 1139 { 1140 // 2 bytes minimum for family, and length 1141 if (buffer == NULL || size < 2) 1142 return fStatus = B_BAD_VALUE; 1143 if (!AllowsTypeCode(code)) 1144 return fStatus = B_BAD_TYPE; 1145 1146 memcpy(&fAddress, buffer, min_c(size, (ssize_t)sizeof(fAddress))); 1147 1148 // check if this can contain a valid address 1149 if (fAddress.ss_family != AF_UNSPEC && size < (ssize_t)sizeof(sockaddr)) 1150 return fStatus = B_BAD_VALUE; 1151 1152 return fStatus = B_OK; 1153 } 1154 1155 1156 // #pragma mark - operators 1157 1158 1159 BNetworkAddress& 1160 BNetworkAddress::operator=(const BNetworkAddress& other) 1161 { 1162 memcpy(&fAddress, &other.fAddress, other.fAddress.ss_len); 1163 fHostName = other.fHostName; 1164 fStatus = other.fStatus; 1165 1166 return *this; 1167 } 1168 1169 1170 bool 1171 BNetworkAddress::operator==(const BNetworkAddress& other) const 1172 { 1173 return Equals(other); 1174 } 1175 1176 1177 bool 1178 BNetworkAddress::operator!=(const BNetworkAddress& other) const 1179 { 1180 return !Equals(other); 1181 } 1182 1183 1184 bool 1185 BNetworkAddress::operator<(const BNetworkAddress& other) const 1186 { 1187 if (Family() < other.Family()) 1188 return true; 1189 if (Family() > other.Family()) 1190 return false; 1191 1192 int compare; 1193 1194 switch (fAddress.ss_family) { 1195 default: 1196 case AF_INET: 1197 { 1198 sockaddr_in& address = (sockaddr_in&)fAddress; 1199 sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress; 1200 compare = memcmp(&address.sin_addr, &otherAddress.sin_addr, 1201 sizeof(address.sin_addr)); 1202 break; 1203 } 1204 1205 case AF_INET6: 1206 { 1207 sockaddr_in6& address = (sockaddr_in6&)fAddress; 1208 sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress; 1209 compare = memcmp(&address.sin6_addr, &otherAddress.sin6_addr, 1210 sizeof(address.sin6_addr)); 1211 break; 1212 } 1213 1214 case AF_LINK: 1215 if (LinkLevelAddressLength() < other.LinkLevelAddressLength()) 1216 return true; 1217 if (LinkLevelAddressLength() > other.LinkLevelAddressLength()) 1218 return true; 1219 1220 // TODO: could compare index, and name, too 1221 compare = memcmp(LinkLevelAddress(), other.LinkLevelAddress(), 1222 LinkLevelAddressLength()); 1223 break; 1224 } 1225 1226 if (compare < 0) 1227 return true; 1228 if (compare > 0) 1229 return false; 1230 1231 return Port() < other.Port(); 1232 } 1233 1234 1235 BNetworkAddress::operator const sockaddr*() const 1236 { 1237 return (const sockaddr*)&fAddress; 1238 } 1239 1240 1241 BNetworkAddress::operator const sockaddr&() const 1242 { 1243 return (const sockaddr&)fAddress; 1244 } 1245 1246 1247 BNetworkAddress::operator sockaddr*() 1248 { 1249 return (sockaddr*)&fAddress; 1250 } 1251 1252 1253 BNetworkAddress::operator const sockaddr*() 1254 { 1255 return (sockaddr*)&fAddress; 1256 } 1257 1258 1259 BNetworkAddress::operator sockaddr&() 1260 { 1261 return (sockaddr&)fAddress; 1262 } 1263 1264 1265 BNetworkAddress::operator const sockaddr&() 1266 { 1267 return (sockaddr&)fAddress; 1268 } 1269 1270 1271 // #pragma mark - private 1272 1273 1274 status_t 1275 BNetworkAddress::_ParseLinkAddress(const char* address) 1276 { 1277 if (address == NULL) 1278 return B_BAD_VALUE; 1279 1280 uint8 linkAddress[128]; 1281 uint32 length = 0; 1282 while (length < sizeof(linkAddress)) { 1283 if (!isxdigit(address[0]) || !isxdigit(address[1])) 1284 return B_BAD_VALUE; 1285 1286 linkAddress[length++] = (from_hex(address[0]) << 4) 1287 | from_hex(address[1]); 1288 1289 if (address[2] == '\0') 1290 break; 1291 if (address[2] != ':') 1292 return B_BAD_VALUE; 1293 1294 address += 3; 1295 } 1296 1297 fHostName = address; 1298 1299 SetToLinkLevel(linkAddress, length); 1300 return B_OK; 1301 } 1302