BPicture: Fix archive constructor.
[haiku.git] / src / kits / network / libnetapi / NetworkAddress.cpp
blob57de4bc77408c1849fdd053d5ddf792cebc257fe
1 /*
2 * Copyright 2010-2015, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <NetworkAddress.h>
9 #include <NetworkInterface.h>
10 #include <NetworkRoster.h>
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>
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
24 #if __GNUC__ > 3
25 # define addr_bitcount(bitfield) __builtin_popcount(bitfield)
26 #else
27 static ssize_t
28 addr_bitcount(uint32 bitfield)
30 ssize_t result = 0;
31 for (uint8 i = 32; i > 0; i--) {
32 if ((bitfield & (1 << (i - 1))) == 0)
33 break;
34 result++;
36 return result;
38 #endif
41 static uint8
42 from_hex(char hex)
44 if (isdigit(hex))
45 return hex - '0';
47 return tolower(hex) - 'a' + 10;
51 // #pragma mark -
54 BNetworkAddress::BNetworkAddress()
56 Unset();
60 BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags)
62 fStatus = SetTo(host, port, flags);
66 BNetworkAddress::BNetworkAddress(const char* host, const char* service,
67 uint32 flags)
69 fStatus = SetTo(host, service, flags);
73 BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port,
74 uint32 flags)
76 fStatus = SetTo(family, host, port, flags);
80 BNetworkAddress::BNetworkAddress(int family, const char* host,
81 const char* service, uint32 flags)
83 fStatus = SetTo(family, host, service, flags);
87 BNetworkAddress::BNetworkAddress(const sockaddr& address)
89 SetTo(address);
93 BNetworkAddress::BNetworkAddress(const sockaddr_storage& address)
95 SetTo(address);
99 BNetworkAddress::BNetworkAddress(const sockaddr_in& address)
101 SetTo(address);
105 BNetworkAddress::BNetworkAddress(const sockaddr_in6& address)
107 SetTo(address);
111 BNetworkAddress::BNetworkAddress(const sockaddr_dl& address)
113 SetTo(address);
117 BNetworkAddress::BNetworkAddress(in_addr_t address, uint16 port)
119 SetTo(address, port);
123 BNetworkAddress::BNetworkAddress(const in6_addr& address, uint16 port)
125 SetTo(address, port);
129 BNetworkAddress::BNetworkAddress(const BNetworkAddress& other)
131 fAddress(other.fAddress),
132 fStatus(other.fStatus)
137 BNetworkAddress::~BNetworkAddress()
142 status_t
143 BNetworkAddress::InitCheck() const
145 return fStatus;
149 void
150 BNetworkAddress::Unset()
152 fAddress.ss_family = AF_UNSPEC;
153 fAddress.ss_len = 2;
154 fStatus = B_OK;
158 status_t
159 BNetworkAddress::SetTo(const char* host, uint16 port, uint32 flags)
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;
169 // Prefer IPv6 addresses
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;
178 cookie = 0;
179 status = resolver->GetNextAddress(&cookie, *this);
180 if (status != B_OK)
181 Unset();
182 fStatus = status;
183 return status;
187 status_t
188 BNetworkAddress::SetTo(const char* host, const char* service, uint32 flags)
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;
198 // Prefer IPv6 addresses
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;
207 cookie = 0;
208 status = resolver->GetNextAddress(&cookie, *this);
209 if (status != B_OK)
210 Unset();
211 fStatus = status;
212 return status;
216 status_t
217 BNetworkAddress::SetTo(int family, const char* host, uint16 port, uint32 flags)
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
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;
234 uint32 cookie = 0;
235 status = resolver->GetNextAddress(&cookie, *this);
236 if (status != B_OK)
237 Unset();
238 fStatus = status;
239 return status;
243 status_t
244 BNetworkAddress::SetTo(int family, const char* host, const char* service,
245 uint32 flags)
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
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;
262 uint32 cookie = 0;
263 status = resolver->GetNextAddress(&cookie, *this);
264 if (status != B_OK)
265 Unset();
266 fStatus = status;
267 return status;
271 void
272 BNetworkAddress::SetTo(const sockaddr& address)
274 if (address.sa_family == AF_UNSPEC) {
275 Unset();
276 return;
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:
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;
296 SetTo(address, length);
300 void
301 BNetworkAddress::SetTo(const sockaddr& address, size_t length)
303 if (address.sa_family == AF_UNSPEC || length == 0) {
304 Unset();
305 return;
308 memcpy(&fAddress, &address, length);
309 fAddress.ss_len = length;
310 fStatus = B_OK;
314 void
315 BNetworkAddress::SetTo(const sockaddr_storage& address)
317 SetTo((sockaddr&)address);
321 void
322 BNetworkAddress::SetTo(const sockaddr_in& address)
324 SetTo((sockaddr&)address);
328 void
329 BNetworkAddress::SetTo(const sockaddr_in6& address)
331 SetTo((sockaddr&)address);
335 void
336 BNetworkAddress::SetTo(const sockaddr_dl& address)
338 SetTo((sockaddr&)address);
342 void
343 BNetworkAddress::SetTo(in_addr_t inetAddress, uint16 port)
345 memset(&fAddress, 0, sizeof(sockaddr_storage));
347 fAddress.ss_family = AF_INET;
348 fAddress.ss_len = sizeof(sockaddr_in);
349 SetAddress(inetAddress);
350 SetPort(port);
352 fStatus = B_OK;
356 void
357 BNetworkAddress::SetTo(const in6_addr& inet6Address, uint16 port)
359 memset(&fAddress, 0, sizeof(sockaddr_storage));
361 fAddress.ss_family = AF_INET6;
362 fAddress.ss_len = sizeof(sockaddr_in6);
363 SetAddress(inet6Address);
364 SetPort(port);
366 fStatus = B_OK;
370 void
371 BNetworkAddress::SetTo(const BNetworkAddress& other)
373 fAddress = other.fAddress;
374 fStatus = other.fStatus;
378 status_t
379 BNetworkAddress::SetToBroadcast(int family, uint16 port)
381 if (family != AF_INET)
382 return fStatus = B_NOT_SUPPORTED;
384 SetTo(INADDR_BROADCAST, port);
385 return fStatus;
389 status_t
390 BNetworkAddress::SetToLocal(int family, uint16 port)
392 // TODO: choose a local address from the network interfaces
393 return fStatus = B_NOT_SUPPORTED;
397 status_t
398 BNetworkAddress::SetToLoopback(int family, uint16 port)
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;
407 case AF_INET6:
408 SetTo(in6addr_loopback, port);
409 break;
411 default:
412 return fStatus = B_NOT_SUPPORTED;
415 return fStatus;
419 status_t
420 BNetworkAddress::SetToMask(int family, uint32 prefixLength)
422 switch (family) {
423 case AF_INET:
425 if (prefixLength > 32)
426 return B_BAD_VALUE;
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);
433 uint32 hostMask = 0;
434 for (uint8 i = 32; i > 32 - prefixLength; i--)
435 hostMask |= 1 << (i - 1);
437 mask.sin_addr.s_addr = htonl(hostMask);
438 break;
441 case AF_INET6:
443 if (prefixLength > 128)
444 return B_BAD_VALUE;
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);
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;
458 mask.sin6_addr.s6_addr[i] = 0xff;
460 break;
463 default:
464 return B_NOT_SUPPORTED;
467 return fStatus = B_OK;
471 status_t
472 BNetworkAddress::SetToWildcard(int family, uint16 port)
474 switch (family) {
475 case AF_INET:
476 SetTo(INADDR_ANY, port);
477 break;
479 case AF_INET6:
480 SetTo(in6addr_any, port);
481 break;
483 default:
484 return B_NOT_SUPPORTED;
487 return fStatus;
491 status_t
492 BNetworkAddress::SetAddress(in_addr_t inetAddress)
494 if (Family() != AF_INET)
495 return B_BAD_VALUE;
497 sockaddr_in& address = (sockaddr_in&)fAddress;
498 address.sin_addr.s_addr = inetAddress;
499 return B_OK;
503 status_t
504 BNetworkAddress::SetAddress(const in6_addr& inet6Address)
506 if (Family() != AF_INET6)
507 return B_BAD_VALUE;
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;
516 void
517 BNetworkAddress::SetPort(uint16 port)
519 switch (fAddress.ss_family) {
520 case AF_INET:
521 ((sockaddr_in&)fAddress).sin_port = htons(port);
522 break;
524 case AF_INET6:
525 ((sockaddr_in6&)fAddress).sin6_port = htons(port);
526 break;
528 default:
529 break;
534 void
535 BNetworkAddress::SetToLinkLevel(uint8* address, size_t length)
537 sockaddr_dl& link = (sockaddr_dl&)fAddress;
538 memset(&link, 0, sizeof(sockaddr_dl));
540 link.sdl_family = AF_LINK;
541 link.sdl_alen = length;
542 memcpy(LLADDR(&link), address, length);
544 link.sdl_len = sizeof(sockaddr_dl);
545 if (length > sizeof(link.sdl_data))
546 link.sdl_len += length - sizeof(link.sdl_data);
548 fStatus = B_OK;
552 void
553 BNetworkAddress::SetToLinkLevel(const char* name)
555 sockaddr_dl& link = (sockaddr_dl&)fAddress;
556 memset(&link, 0, sizeof(sockaddr_dl));
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);
562 link.sdl_family = AF_LINK;
563 link.sdl_nlen = length;
565 memcpy(link.sdl_data, name, link.sdl_nlen);
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);
571 fStatus = B_OK;
575 void
576 BNetworkAddress::SetToLinkLevel(uint32 index)
578 sockaddr_dl& link = (sockaddr_dl&)fAddress;
579 memset(&link, 0, sizeof(sockaddr_dl));
581 link.sdl_family = AF_LINK;
582 link.sdl_len = sizeof(sockaddr_dl);
583 link.sdl_index = index;
585 fStatus = B_OK;
589 void
590 BNetworkAddress::SetLinkLevelIndex(uint32 index)
592 sockaddr_dl& link = (sockaddr_dl&)fAddress;
593 link.sdl_index = index;
597 void
598 BNetworkAddress::SetLinkLevelType(uint8 type)
600 sockaddr_dl& link = (sockaddr_dl&)fAddress;
601 link.sdl_type = type;
605 void
606 BNetworkAddress::SetLinkLevelFrameType(uint16 frameType)
608 sockaddr_dl& link = (sockaddr_dl&)fAddress;
609 link.sdl_e_type = htons(frameType);
614 BNetworkAddress::Family() const
616 return fAddress.ss_family;
620 uint16
621 BNetworkAddress::Port() const
623 switch (fAddress.ss_family) {
624 case AF_INET:
625 return ntohs(((sockaddr_in&)fAddress).sin_port);
627 case AF_INET6:
628 return ntohs(((sockaddr_in6&)fAddress).sin6_port);
630 default:
631 return 0;
636 size_t
637 BNetworkAddress::Length() const
639 return fAddress.ss_len;
643 const sockaddr&
644 BNetworkAddress::SockAddr() const
646 return (const sockaddr&)fAddress;
650 sockaddr&
651 BNetworkAddress::SockAddr()
653 return (sockaddr&)fAddress;
657 bool
658 BNetworkAddress::IsEmpty() const
660 if (fAddress.ss_len == 0)
661 return true;
663 switch (fAddress.ss_family) {
664 case AF_UNSPEC:
665 return true;
666 case AF_INET:
668 sockaddr_in& sin = (sockaddr_in&)fAddress;
669 return sin.sin_addr.s_addr == INADDR_ANY && sin.sin_port == 0;
671 case AF_INET6:
673 sockaddr_in6& sin6 = (sockaddr_in6&)fAddress;
674 return IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)
675 && sin6.sin6_port == 0;
678 default:
679 return false;
684 bool
685 BNetworkAddress::IsWildcard() const
687 switch (fAddress.ss_family) {
688 case AF_INET:
689 return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_ANY;
691 case AF_INET6:
692 return !memcmp(&((sockaddr_in6&)fAddress).sin6_addr, &in6addr_any,
693 sizeof(in6_addr));
695 default:
696 return false;
701 bool
702 BNetworkAddress::IsBroadcast() const
704 switch (fAddress.ss_family) {
705 case AF_INET:
706 return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_BROADCAST;
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);
712 default:
713 return false;
718 bool
719 BNetworkAddress::IsMulticast() const
721 switch (fAddress.ss_family) {
722 case AF_INET:
723 return IN_MULTICAST(((sockaddr_in&)fAddress).sin_addr.s_addr);
725 case AF_INET6:
726 return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
728 default:
729 return false;
734 bool
735 BNetworkAddress::IsMulticastGlobal() const
737 switch (fAddress.ss_family) {
738 case AF_INET6:
739 return IN6_IS_ADDR_MC_GLOBAL(&((sockaddr_in6&)fAddress).sin6_addr);
741 default:
742 return false;
747 bool
748 BNetworkAddress::IsMulticastNodeLocal() const
750 switch (fAddress.ss_family) {
751 case AF_INET6:
752 return IN6_IS_ADDR_MC_NODELOCAL(
753 &((sockaddr_in6&)fAddress).sin6_addr);
755 default:
756 return false;
761 bool
762 BNetworkAddress::IsMulticastLinkLocal() const
764 switch (fAddress.ss_family) {
765 case AF_INET6:
766 return IN6_IS_ADDR_MC_LINKLOCAL(
767 &((sockaddr_in6&)fAddress).sin6_addr);
769 default:
770 return false;
775 bool
776 BNetworkAddress::IsMulticastSiteLocal() const
778 switch (fAddress.ss_family) {
779 case AF_INET6:
780 return IN6_IS_ADDR_MC_SITELOCAL(
781 &((sockaddr_in6&)fAddress).sin6_addr);
783 default:
784 return false;
789 bool
790 BNetworkAddress::IsMulticastOrgLocal() const
792 switch (fAddress.ss_family) {
793 case AF_INET6:
794 return IN6_IS_ADDR_MC_ORGLOCAL(
795 &((sockaddr_in6&)fAddress).sin6_addr);
797 default:
798 return false;
803 bool
804 BNetworkAddress::IsLinkLocal() const
806 // TODO: ipv4
807 switch (fAddress.ss_family) {
808 case AF_INET6:
809 return IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
811 default:
812 return false;
817 bool
818 BNetworkAddress::IsSiteLocal() const
820 switch (fAddress.ss_family) {
821 case AF_INET6:
822 return IN6_IS_ADDR_SITELOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
824 default:
825 return false;
830 bool
831 BNetworkAddress::IsLocal() const
833 BNetworkRoster& roster = BNetworkRoster::Default();
835 BNetworkInterface interface;
836 uint32 cookie = 0;
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;
845 if (Equals(address.Address(), false))
846 return true;
850 return false;
854 ssize_t
855 BNetworkAddress::PrefixLength() const
857 switch (fAddress.ss_family) {
858 case AF_INET:
860 sockaddr_in& mask = (sockaddr_in&)fAddress;
862 uint32 hostMask = ntohl(mask.sin_addr.s_addr);
863 return addr_bitcount(hostMask);
866 case AF_INET6:
868 sockaddr_in6& mask = (sockaddr_in6&)fAddress;
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++;
880 return 128;
883 default:
884 return B_NOT_SUPPORTED;
889 uint32
890 BNetworkAddress::LinkLevelIndex() const
892 return ((sockaddr_dl&)fAddress).sdl_index;
896 BString
897 BNetworkAddress::LinkLevelInterface() const
899 sockaddr_dl& address = (sockaddr_dl&)fAddress;
900 if (address.sdl_nlen == 0)
901 return "";
903 BString name;
904 name.SetTo((const char*)address.sdl_data, address.sdl_nlen);
906 return name;
910 uint8
911 BNetworkAddress::LinkLevelType() const
913 return ((sockaddr_dl&)fAddress).sdl_type;
917 uint16
918 BNetworkAddress::LinkLevelFrameType() const
920 return ntohs(((sockaddr_dl&)fAddress).sdl_e_type);
924 uint8*
925 BNetworkAddress::LinkLevelAddress() const
927 return LLADDR(&(sockaddr_dl&)fAddress);
931 size_t
932 BNetworkAddress::LinkLevelAddressLength() const
934 return ((sockaddr_dl&)fAddress).sdl_alen;
938 status_t
939 BNetworkAddress::ResolveForDestination(const BNetworkAddress& destination)
941 if (!IsWildcard())
942 return B_OK;
943 if (destination.fAddress.ss_family != fAddress.ss_family)
944 return B_BAD_VALUE;
946 char buffer[2048];
947 memset(buffer, 0, sizeof(buffer));
949 route_entry* route = (route_entry*)buffer;
950 route->destination = (sockaddr*)&destination.fAddress;
952 int socket = ::socket(fAddress.ss_family, SOCK_DGRAM, 0);
953 if (socket < 0)
954 return errno;
956 if (ioctl(socket, SIOCGETRT, route, sizeof(buffer)) != 0) {
957 close(socket);
958 return errno;
961 uint16 port = Port();
962 memcpy(&fAddress, route->source, sizeof(sockaddr_storage));
963 SetPort(port);
965 return B_OK;
969 status_t
970 BNetworkAddress::ResolveTo(const BNetworkAddress& address)
972 if (!IsWildcard())
973 return B_OK;
974 if (address.fAddress.ss_family != fAddress.ss_family)
975 return B_BAD_VALUE;
977 uint16 port = Port();
978 *this = address;
979 SetPort(port);
981 return B_OK;
985 BString
986 BNetworkAddress::ToString(bool includePort) const
988 char buffer[512];
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;
996 case AF_INET6:
997 inet_ntop(AF_INET6, &((sockaddr_in6&)fAddress).sin6_addr,
998 buffer, sizeof(buffer));
999 break;
1001 case AF_LINK:
1003 uint8 *byte = LinkLevelAddress();
1004 char* target = buffer;
1005 int bytesLeft = sizeof(buffer);
1006 target[0] = '\0';
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--;
1016 int bytesWritten = snprintf(target, bytesLeft, "%02x", byte[i]);
1017 if (bytesWritten >= bytesLeft)
1018 break;
1020 target += bytesWritten;
1021 bytesLeft -= bytesWritten;
1023 break;
1026 default:
1027 return "";
1030 BString address = buffer;
1031 if (includePort && Port() != 0) {
1032 if (fAddress.ss_family == AF_INET6) {
1033 address = "[";
1034 address += buffer;
1035 address += "]";
1038 snprintf(buffer, sizeof(buffer), ":%u", Port());
1039 address += buffer;
1042 return address;
1046 BString
1047 BNetworkAddress::HostName() const
1049 // TODO: implement host name lookup
1050 return ToString(false);
1054 BString
1055 BNetworkAddress::ServiceName() const
1057 // TODO: implement service lookup
1058 BString portName;
1059 portName << Port();
1060 return portName;
1064 bool
1065 BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const
1067 if (IsEmpty() && other.IsEmpty())
1068 return true;
1070 if (Family() != other.Family()
1071 || (includePort && Port() != other.Port())) {
1072 return false;
1075 switch (fAddress.ss_family) {
1076 case AF_INET:
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;
1084 case AF_INET6:
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;
1092 default:
1093 if (fAddress.ss_len != other.fAddress.ss_len)
1094 return false;
1096 return memcmp(&fAddress, &other.fAddress, fAddress.ss_len);
1101 // #pragma mark - BFlattenable implementation
1104 bool
1105 BNetworkAddress::IsFixedSize() const
1107 return false;
1111 type_code
1112 BNetworkAddress::TypeCode() const
1114 return B_NETWORK_ADDRESS_TYPE;
1118 ssize_t
1119 BNetworkAddress::FlattenedSize() const
1121 return Length();
1125 status_t
1126 BNetworkAddress::Flatten(void* buffer, ssize_t size) const
1128 if (buffer == NULL || size < FlattenedSize())
1129 return B_BAD_VALUE;
1131 memcpy(buffer, &fAddress, Length());
1132 return B_OK;
1136 status_t
1137 BNetworkAddress::Unflatten(type_code code, const void* buffer, ssize_t size)
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;
1145 memcpy(&fAddress, buffer, min_c(size, (ssize_t)sizeof(fAddress)));
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;
1151 return fStatus = B_OK;
1155 // #pragma mark - operators
1158 BNetworkAddress&
1159 BNetworkAddress::operator=(const BNetworkAddress& other)
1161 memcpy(&fAddress, &other.fAddress, other.fAddress.ss_len);
1162 fStatus = other.fStatus;
1164 return *this;
1168 bool
1169 BNetworkAddress::operator==(const BNetworkAddress& other) const
1171 return Equals(other);
1175 bool
1176 BNetworkAddress::operator!=(const BNetworkAddress& other) const
1178 return !Equals(other);
1182 bool
1183 BNetworkAddress::operator<(const BNetworkAddress& other) const
1185 if (Family() < other.Family())
1186 return true;
1187 if (Family() > other.Family())
1188 return false;
1190 int compare;
1192 switch (fAddress.ss_family) {
1193 default:
1194 case AF_INET:
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;
1203 case AF_INET6:
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;
1212 case AF_LINK:
1213 if (LinkLevelAddressLength() < other.LinkLevelAddressLength())
1214 return true;
1215 if (LinkLevelAddressLength() > other.LinkLevelAddressLength())
1216 return true;
1218 // TODO: could compare index, and name, too
1219 compare = memcmp(LinkLevelAddress(), other.LinkLevelAddress(),
1220 LinkLevelAddressLength());
1221 break;
1224 if (compare < 0)
1225 return true;
1226 if (compare > 0)
1227 return false;
1229 return Port() < other.Port();
1233 BNetworkAddress::operator const sockaddr*() const
1235 return (const sockaddr*)&fAddress;
1239 BNetworkAddress::operator const sockaddr&() const
1241 return (const sockaddr&)fAddress;
1245 BNetworkAddress::operator sockaddr*()
1247 return (sockaddr*)&fAddress;
1251 BNetworkAddress::operator const sockaddr*()
1253 return (sockaddr*)&fAddress;
1257 BNetworkAddress::operator sockaddr&()
1259 return (sockaddr&)fAddress;
1263 BNetworkAddress::operator const sockaddr&()
1265 return (sockaddr&)fAddress;
1269 // #pragma mark - private
1272 status_t
1273 BNetworkAddress::_ParseLinkAddress(const char* address)
1275 if (address == NULL)
1276 return B_BAD_VALUE;
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;
1284 linkAddress[length++] = (from_hex(address[0]) << 4)
1285 | from_hex(address[1]);
1287 if (address[2] == '\0')
1288 break;
1289 if (address[2] != ':')
1290 return B_BAD_VALUE;
1292 address += 3;
1295 SetToLinkLevel(linkAddress, length);
1296 return B_OK;