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 27static ssize_t 28addr_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 41static uint8 42from_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 54BNetworkAddress::BNetworkAddress() 55{ 56 Unset(); 57} 58 59 60BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags) 61{ 62 fStatus = SetTo(host, port, flags); 63} 64 65 66BNetworkAddress::BNetworkAddress(const char* host, const char* service, 67 uint32 flags) 68{ 69 fStatus = SetTo(host, service, flags); 70} 71 72 73BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port, 74 uint32 flags) 75{ 76 fStatus = SetTo(family, host, port, flags); 77} 78 79 80BNetworkAddress::BNetworkAddress(int family, const char* host, 81 const char* service, uint32 flags) 82{ 83 fStatus = SetTo(family, host, service, flags); 84} 85 86 87BNetworkAddress::BNetworkAddress(const sockaddr& address) 88{ 89 SetTo(address); 90} 91 92 93BNetworkAddress::BNetworkAddress(const sockaddr_storage& address) 94{ 95 SetTo(address); 96} 97 98 99BNetworkAddress::BNetworkAddress(const sockaddr_in& address) 100{ 101 SetTo(address); 102} 103 104 105BNetworkAddress::BNetworkAddress(const sockaddr_in6& address) 106{ 107 SetTo(address); 108} 109 110 111BNetworkAddress::BNetworkAddress(const sockaddr_dl& address) 112{ 113 SetTo(address); 114} 115 116 117BNetworkAddress::BNetworkAddress(in_addr_t address, uint16 port) 118{ 119 SetTo(address, port); 120} 121 122 123BNetworkAddress::BNetworkAddress(const in6_addr& address, uint16 port) 124{ 125 SetTo(address, port); 126} 127 128 129BNetworkAddress::BNetworkAddress(const BNetworkAddress& other) 130 : 131 fAddress(other.fAddress), 132 fStatus(other.fStatus), 133 fHostName(other.fHostName) 134{ 135} 136 137 138BNetworkAddress::~BNetworkAddress() 139{ 140} 141 142 143status_t 144BNetworkAddress::InitCheck() const 145{ 146 return fStatus; 147} 148 149 150void 151BNetworkAddress::Unset() 152{ 153 fAddress.ss_family = AF_UNSPEC; 154 fAddress.ss_len = 2; 155 fHostName = ""; 156 fStatus = B_OK; 157} 158 159 160status_t 161BNetworkAddress::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 187status_t 188BNetworkAddress::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 214status_t 215BNetworkAddress::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 242status_t 243BNetworkAddress::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 271void 272BNetworkAddress::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 300void 301BNetworkAddress::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 314void 315BNetworkAddress::SetTo(const sockaddr_storage& address) 316{ 317 SetTo((sockaddr&)address); 318} 319 320 321void 322BNetworkAddress::SetTo(const sockaddr_in& address) 323{ 324 SetTo((sockaddr&)address); 325} 326 327 328void 329BNetworkAddress::SetTo(const sockaddr_in6& address) 330{ 331 SetTo((sockaddr&)address); 332} 333 334 335void 336BNetworkAddress::SetTo(const sockaddr_dl& address) 337{ 338 SetTo((sockaddr&)address); 339} 340 341 342void 343BNetworkAddress::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 356void 357BNetworkAddress::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 370void 371BNetworkAddress::SetTo(const BNetworkAddress& other) 372{ 373 fAddress = other.fAddress; 374 fStatus = other.fStatus; 375 fHostName = other.fHostName; 376} 377 378 379status_t 380BNetworkAddress::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 390status_t 391BNetworkAddress::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 398status_t 399BNetworkAddress::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 420status_t 421BNetworkAddress::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 472status_t 473BNetworkAddress::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 492status_t 493BNetworkAddress::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 504status_t 505BNetworkAddress::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 517void 518BNetworkAddress::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 535void 536BNetworkAddress::SetToLinkLevel(const 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 553void 554BNetworkAddress::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 576void 577BNetworkAddress::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 590void 591BNetworkAddress::SetLinkLevelIndex(uint32 index) 592{ 593 sockaddr_dl& link = (sockaddr_dl&)fAddress; 594 link.sdl_index = index; 595} 596 597 598void 599BNetworkAddress::SetLinkLevelType(uint8 type) 600{ 601 sockaddr_dl& link = (sockaddr_dl&)fAddress; 602 link.sdl_type = type; 603} 604 605 606void 607BNetworkAddress::SetLinkLevelFrameType(uint16 frameType) 608{ 609 sockaddr_dl& link = (sockaddr_dl&)fAddress; 610 link.sdl_e_type = htons(frameType); 611} 612 613 614int 615BNetworkAddress::Family() const 616{ 617 return fAddress.ss_family; 618} 619 620 621uint16 622BNetworkAddress::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 637size_t 638BNetworkAddress::Length() const 639{ 640 return fAddress.ss_len; 641} 642 643 644const sockaddr& 645BNetworkAddress::SockAddr() const 646{ 647 return (const sockaddr&)fAddress; 648} 649 650 651sockaddr& 652BNetworkAddress::SockAddr() 653{ 654 return (sockaddr&)fAddress; 655} 656 657 658bool 659BNetworkAddress::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 685bool 686BNetworkAddress::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 702bool 703BNetworkAddress::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 719bool 720BNetworkAddress::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 735bool 736BNetworkAddress::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 748bool 749BNetworkAddress::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 762bool 763BNetworkAddress::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 776bool 777BNetworkAddress::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 790bool 791BNetworkAddress::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 804bool 805BNetworkAddress::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 818bool 819BNetworkAddress::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 831bool 832BNetworkAddress::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 855ssize_t 856BNetworkAddress::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 890uint32 891BNetworkAddress::LinkLevelIndex() const 892{ 893 return ((sockaddr_dl&)fAddress).sdl_index; 894} 895 896 897BString 898BNetworkAddress::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 911uint8 912BNetworkAddress::LinkLevelType() const 913{ 914 return ((sockaddr_dl&)fAddress).sdl_type; 915} 916 917 918uint16 919BNetworkAddress::LinkLevelFrameType() const 920{ 921 return ntohs(((sockaddr_dl&)fAddress).sdl_e_type); 922} 923 924 925uint8* 926BNetworkAddress::LinkLevelAddress() const 927{ 928 return LLADDR(&(sockaddr_dl&)fAddress); 929} 930 931 932size_t 933BNetworkAddress::LinkLevelAddressLength() const 934{ 935 return ((sockaddr_dl&)fAddress).sdl_alen; 936} 937 938 939status_t 940BNetworkAddress::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 971status_t 972BNetworkAddress::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 987BString 988BNetworkAddress::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 1048BString 1049BNetworkAddress::HostName() const 1050{ 1051 // TODO: implement host name lookup 1052 return fHostName; 1053} 1054 1055 1056BString 1057BNetworkAddress::ServiceName() const 1058{ 1059 // TODO: implement service lookup 1060 BString portName; 1061 portName << Port(); 1062 return portName; 1063} 1064 1065 1066bool 1067BNetworkAddress::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 1106bool 1107BNetworkAddress::IsFixedSize() const 1108{ 1109 return false; 1110} 1111 1112 1113type_code 1114BNetworkAddress::TypeCode() const 1115{ 1116 return B_NETWORK_ADDRESS_TYPE; 1117} 1118 1119 1120ssize_t 1121BNetworkAddress::FlattenedSize() const 1122{ 1123 return Length(); 1124} 1125 1126 1127status_t 1128BNetworkAddress::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 1138status_t 1139BNetworkAddress::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 1160BNetworkAddress& 1161BNetworkAddress::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 1171bool 1172BNetworkAddress::operator==(const BNetworkAddress& other) const 1173{ 1174 return Equals(other); 1175} 1176 1177 1178bool 1179BNetworkAddress::operator!=(const BNetworkAddress& other) const 1180{ 1181 return !Equals(other); 1182} 1183 1184 1185bool 1186BNetworkAddress::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 1236BNetworkAddress::operator const sockaddr*() const 1237{ 1238 return (const sockaddr*)&fAddress; 1239} 1240 1241 1242BNetworkAddress::operator const sockaddr&() const 1243{ 1244 return (const sockaddr&)fAddress; 1245} 1246 1247 1248BNetworkAddress::operator sockaddr*() 1249{ 1250 return (sockaddr*)&fAddress; 1251} 1252 1253 1254BNetworkAddress::operator const sockaddr*() 1255{ 1256 return (sockaddr*)&fAddress; 1257} 1258 1259 1260BNetworkAddress::operator sockaddr&() 1261{ 1262 return (sockaddr&)fAddress; 1263} 1264 1265 1266BNetworkAddress::operator const sockaddr&() 1267{ 1268 return (sockaddr&)fAddress; 1269} 1270 1271 1272// #pragma mark - private 1273 1274 1275status_t 1276BNetworkAddress::_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