vfs: check userland buffers before reading them.
[haiku.git] / src / kits / network / libnetapi / NetworkAddress.cpp
blob7eaf5a166cf8823b18f6682ffeaf7e146643bd7e
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),
133 fHostName(other.fHostName)
138 BNetworkAddress::~BNetworkAddress()
143 status_t
144 BNetworkAddress::InitCheck() const
146 return fStatus;
150 void
151 BNetworkAddress::Unset()
153 fAddress.ss_family = AF_UNSPEC;
154 fAddress.ss_len = 2;
155 fHostName = "";
156 fStatus = B_OK;
160 status_t
161 BNetworkAddress::SetTo(const char* host, uint16 port, uint32 flags)
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;
171 // Prefer IPv6 addresses
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();
181 fHostName = host;
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 cookie = 0;
204 status = resolver->GetNextAddress(&cookie, *this);
205 if (status != B_OK)
206 Unset();
208 fHostName = host;
209 fStatus = status;
210 return status;
214 status_t
215 BNetworkAddress::SetTo(int family, const char* host, uint16 port, uint32 flags)
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
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;
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;
242 status_t
243 BNetworkAddress::SetTo(int family, const char* host, const char* service,
244 uint32 flags)
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
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;
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;
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;
375 fHostName = other.fHostName;
379 status_t
380 BNetworkAddress::SetToBroadcast(int family, uint16 port)
382 if (family != AF_INET)
383 return fStatus = B_NOT_SUPPORTED;
385 SetTo(INADDR_BROADCAST, port);
386 return fStatus;
390 status_t
391 BNetworkAddress::SetToLocal(int family, uint16 port)
393 // TODO: choose a local address from the network interfaces
394 return fStatus = B_NOT_SUPPORTED;
398 status_t
399 BNetworkAddress::SetToLoopback(int family, uint16 port)
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;
408 case AF_INET6:
409 SetTo(in6addr_loopback, port);
410 break;
412 default:
413 return fStatus = B_NOT_SUPPORTED;
416 return fStatus;
420 status_t
421 BNetworkAddress::SetToMask(int family, uint32 prefixLength)
423 switch (family) {
424 case AF_INET:
426 if (prefixLength > 32)
427 return B_BAD_VALUE;
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);
434 uint32 hostMask = 0;
435 for (uint8 i = 32; i > 32 - prefixLength; i--)
436 hostMask |= 1 << (i - 1);
438 mask.sin_addr.s_addr = htonl(hostMask);
439 break;
442 case AF_INET6:
444 if (prefixLength > 128)
445 return B_BAD_VALUE;
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);
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;
459 mask.sin6_addr.s6_addr[i] = 0xff;
461 break;
464 default:
465 return B_NOT_SUPPORTED;
468 return fStatus = B_OK;
472 status_t
473 BNetworkAddress::SetToWildcard(int family, uint16 port)
475 switch (family) {
476 case AF_INET:
477 SetTo(INADDR_ANY, port);
478 break;
480 case AF_INET6:
481 SetTo(in6addr_any, port);
482 break;
484 default:
485 return B_NOT_SUPPORTED;
488 return fStatus;
492 status_t
493 BNetworkAddress::SetAddress(in_addr_t inetAddress)
495 if (Family() != AF_INET)
496 return B_BAD_VALUE;
498 sockaddr_in& address = (sockaddr_in&)fAddress;
499 address.sin_addr.s_addr = inetAddress;
500 return B_OK;
504 status_t
505 BNetworkAddress::SetAddress(const in6_addr& inet6Address)
507 if (Family() != AF_INET6)
508 return B_BAD_VALUE;
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;
517 void
518 BNetworkAddress::SetPort(uint16 port)
520 switch (fAddress.ss_family) {
521 case AF_INET:
522 ((sockaddr_in&)fAddress).sin_port = htons(port);
523 break;
525 case AF_INET6:
526 ((sockaddr_in6&)fAddress).sin6_port = htons(port);
527 break;
529 default:
530 break;
535 void
536 BNetworkAddress::SetToLinkLevel(uint8* address, size_t length)
538 sockaddr_dl& link = (sockaddr_dl&)fAddress;
539 memset(&link, 0, sizeof(sockaddr_dl));
541 link.sdl_family = AF_LINK;
542 link.sdl_alen = length;
543 memcpy(LLADDR(&link), address, length);
545 link.sdl_len = sizeof(sockaddr_dl);
546 if (length > sizeof(link.sdl_data))
547 link.sdl_len += length - sizeof(link.sdl_data);
549 fStatus = B_OK;
553 void
554 BNetworkAddress::SetToLinkLevel(const char* name)
556 sockaddr_dl& link = (sockaddr_dl&)fAddress;
557 memset(&link, 0, sizeof(sockaddr_dl));
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);
563 link.sdl_family = AF_LINK;
564 link.sdl_nlen = length;
566 memcpy(link.sdl_data, name, link.sdl_nlen);
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);
572 fStatus = B_OK;
576 void
577 BNetworkAddress::SetToLinkLevel(uint32 index)
579 sockaddr_dl& link = (sockaddr_dl&)fAddress;
580 memset(&link, 0, sizeof(sockaddr_dl));
582 link.sdl_family = AF_LINK;
583 link.sdl_len = sizeof(sockaddr_dl);
584 link.sdl_index = index;
586 fStatus = B_OK;
590 void
591 BNetworkAddress::SetLinkLevelIndex(uint32 index)
593 sockaddr_dl& link = (sockaddr_dl&)fAddress;
594 link.sdl_index = index;
598 void
599 BNetworkAddress::SetLinkLevelType(uint8 type)
601 sockaddr_dl& link = (sockaddr_dl&)fAddress;
602 link.sdl_type = type;
606 void
607 BNetworkAddress::SetLinkLevelFrameType(uint16 frameType)
609 sockaddr_dl& link = (sockaddr_dl&)fAddress;
610 link.sdl_e_type = htons(frameType);
615 BNetworkAddress::Family() const
617 return fAddress.ss_family;
621 uint16
622 BNetworkAddress::Port() const
624 switch (fAddress.ss_family) {
625 case AF_INET:
626 return ntohs(((sockaddr_in&)fAddress).sin_port);
628 case AF_INET6:
629 return ntohs(((sockaddr_in6&)fAddress).sin6_port);
631 default:
632 return 0;
637 size_t
638 BNetworkAddress::Length() const
640 return fAddress.ss_len;
644 const sockaddr&
645 BNetworkAddress::SockAddr() const
647 return (const sockaddr&)fAddress;
651 sockaddr&
652 BNetworkAddress::SockAddr()
654 return (sockaddr&)fAddress;
658 bool
659 BNetworkAddress::IsEmpty() const
661 if (fAddress.ss_len == 0)
662 return true;
664 switch (fAddress.ss_family) {
665 case AF_UNSPEC:
666 return true;
667 case AF_INET:
669 sockaddr_in& sin = (sockaddr_in&)fAddress;
670 return sin.sin_addr.s_addr == INADDR_ANY && sin.sin_port == 0;
672 case AF_INET6:
674 sockaddr_in6& sin6 = (sockaddr_in6&)fAddress;
675 return IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)
676 && sin6.sin6_port == 0;
679 default:
680 return false;
685 bool
686 BNetworkAddress::IsWildcard() const
688 switch (fAddress.ss_family) {
689 case AF_INET:
690 return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_ANY;
692 case AF_INET6:
693 return !memcmp(&((sockaddr_in6&)fAddress).sin6_addr, &in6addr_any,
694 sizeof(in6_addr));
696 default:
697 return false;
702 bool
703 BNetworkAddress::IsBroadcast() const
705 switch (fAddress.ss_family) {
706 case AF_INET:
707 return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_BROADCAST;
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);
713 default:
714 return false;
719 bool
720 BNetworkAddress::IsMulticast() const
722 switch (fAddress.ss_family) {
723 case AF_INET:
724 return IN_MULTICAST(((sockaddr_in&)fAddress).sin_addr.s_addr);
726 case AF_INET6:
727 return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
729 default:
730 return false;
735 bool
736 BNetworkAddress::IsMulticastGlobal() const
738 switch (fAddress.ss_family) {
739 case AF_INET6:
740 return IN6_IS_ADDR_MC_GLOBAL(&((sockaddr_in6&)fAddress).sin6_addr);
742 default:
743 return false;
748 bool
749 BNetworkAddress::IsMulticastNodeLocal() const
751 switch (fAddress.ss_family) {
752 case AF_INET6:
753 return IN6_IS_ADDR_MC_NODELOCAL(
754 &((sockaddr_in6&)fAddress).sin6_addr);
756 default:
757 return false;
762 bool
763 BNetworkAddress::IsMulticastLinkLocal() const
765 switch (fAddress.ss_family) {
766 case AF_INET6:
767 return IN6_IS_ADDR_MC_LINKLOCAL(
768 &((sockaddr_in6&)fAddress).sin6_addr);
770 default:
771 return false;
776 bool
777 BNetworkAddress::IsMulticastSiteLocal() const
779 switch (fAddress.ss_family) {
780 case AF_INET6:
781 return IN6_IS_ADDR_MC_SITELOCAL(
782 &((sockaddr_in6&)fAddress).sin6_addr);
784 default:
785 return false;
790 bool
791 BNetworkAddress::IsMulticastOrgLocal() const
793 switch (fAddress.ss_family) {
794 case AF_INET6:
795 return IN6_IS_ADDR_MC_ORGLOCAL(
796 &((sockaddr_in6&)fAddress).sin6_addr);
798 default:
799 return false;
804 bool
805 BNetworkAddress::IsLinkLocal() const
807 // TODO: ipv4
808 switch (fAddress.ss_family) {
809 case AF_INET6:
810 return IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
812 default:
813 return false;
818 bool
819 BNetworkAddress::IsSiteLocal() const
821 switch (fAddress.ss_family) {
822 case AF_INET6:
823 return IN6_IS_ADDR_SITELOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
825 default:
826 return false;
831 bool
832 BNetworkAddress::IsLocal() const
834 BNetworkRoster& roster = BNetworkRoster::Default();
836 BNetworkInterface interface;
837 uint32 cookie = 0;
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;
846 if (Equals(address.Address(), false))
847 return true;
851 return false;
855 ssize_t
856 BNetworkAddress::PrefixLength() const
858 switch (fAddress.ss_family) {
859 case AF_INET:
861 sockaddr_in& mask = (sockaddr_in&)fAddress;
863 uint32 hostMask = ntohl(mask.sin_addr.s_addr);
864 return addr_bitcount(hostMask);
867 case AF_INET6:
869 sockaddr_in6& mask = (sockaddr_in6&)fAddress;
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++;
881 return 128;
884 default:
885 return B_NOT_SUPPORTED;
890 uint32
891 BNetworkAddress::LinkLevelIndex() const
893 return ((sockaddr_dl&)fAddress).sdl_index;
897 BString
898 BNetworkAddress::LinkLevelInterface() const
900 sockaddr_dl& address = (sockaddr_dl&)fAddress;
901 if (address.sdl_nlen == 0)
902 return "";
904 BString name;
905 name.SetTo((const char*)address.sdl_data, address.sdl_nlen);
907 return name;
911 uint8
912 BNetworkAddress::LinkLevelType() const
914 return ((sockaddr_dl&)fAddress).sdl_type;
918 uint16
919 BNetworkAddress::LinkLevelFrameType() const
921 return ntohs(((sockaddr_dl&)fAddress).sdl_e_type);
925 uint8*
926 BNetworkAddress::LinkLevelAddress() const
928 return LLADDR(&(sockaddr_dl&)fAddress);
932 size_t
933 BNetworkAddress::LinkLevelAddressLength() const
935 return ((sockaddr_dl&)fAddress).sdl_alen;
939 status_t
940 BNetworkAddress::ResolveForDestination(const BNetworkAddress& destination)
942 if (!IsWildcard())
943 return B_OK;
944 if (destination.fAddress.ss_family != fAddress.ss_family)
945 return B_BAD_VALUE;
947 char buffer[2048];
948 memset(buffer, 0, sizeof(buffer));
950 route_entry* route = (route_entry*)buffer;
951 route->destination = (sockaddr*)&destination.fAddress;
953 int socket = ::socket(fAddress.ss_family, SOCK_DGRAM, 0);
954 if (socket < 0)
955 return errno;
957 if (ioctl(socket, SIOCGETRT, route, sizeof(buffer)) != 0) {
958 close(socket);
959 return errno;
962 uint16 port = Port();
963 memcpy(&fAddress, route->source, sizeof(sockaddr_storage));
964 SetPort(port);
966 close(socket);
967 return B_OK;
971 status_t
972 BNetworkAddress::ResolveTo(const BNetworkAddress& address)
974 if (!IsWildcard())
975 return B_OK;
976 if (address.fAddress.ss_family != fAddress.ss_family)
977 return B_BAD_VALUE;
979 uint16 port = Port();
980 *this = address;
981 SetPort(port);
983 return B_OK;
987 BString
988 BNetworkAddress::ToString(bool includePort) const
990 char buffer[512];
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;
998 case AF_INET6:
999 inet_ntop(AF_INET6, &((sockaddr_in6&)fAddress).sin6_addr,
1000 buffer, sizeof(buffer));
1001 break;
1003 case AF_LINK:
1005 uint8 *byte = LinkLevelAddress();
1006 char* target = buffer;
1007 int bytesLeft = sizeof(buffer);
1008 target[0] = '\0';
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--;
1018 int bytesWritten = snprintf(target, bytesLeft, "%02x", byte[i]);
1019 if (bytesWritten >= bytesLeft)
1020 break;
1022 target += bytesWritten;
1023 bytesLeft -= bytesWritten;
1025 break;
1028 default:
1029 return "";
1032 BString address = buffer;
1033 if (includePort && Port() != 0) {
1034 if (fAddress.ss_family == AF_INET6) {
1035 address = "[";
1036 address += buffer;
1037 address += "]";
1040 snprintf(buffer, sizeof(buffer), ":%u", Port());
1041 address += buffer;
1044 return address;
1048 BString
1049 BNetworkAddress::HostName() const
1051 // TODO: implement host name lookup
1052 return fHostName;
1056 BString
1057 BNetworkAddress::ServiceName() const
1059 // TODO: implement service lookup
1060 BString portName;
1061 portName << Port();
1062 return portName;
1066 bool
1067 BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const
1069 if (IsEmpty() && other.IsEmpty())
1070 return true;
1072 if (Family() != other.Family()
1073 || (includePort && Port() != other.Port())) {
1074 return false;
1077 switch (fAddress.ss_family) {
1078 case AF_INET:
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;
1086 case AF_INET6:
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;
1094 default:
1095 if (fAddress.ss_len != other.fAddress.ss_len)
1096 return false;
1098 return memcmp(&fAddress, &other.fAddress, fAddress.ss_len);
1103 // #pragma mark - BFlattenable implementation
1106 bool
1107 BNetworkAddress::IsFixedSize() const
1109 return false;
1113 type_code
1114 BNetworkAddress::TypeCode() const
1116 return B_NETWORK_ADDRESS_TYPE;
1120 ssize_t
1121 BNetworkAddress::FlattenedSize() const
1123 return Length();
1127 status_t
1128 BNetworkAddress::Flatten(void* buffer, ssize_t size) const
1130 if (buffer == NULL || size < FlattenedSize())
1131 return B_BAD_VALUE;
1133 memcpy(buffer, &fAddress, Length());
1134 return B_OK;
1138 status_t
1139 BNetworkAddress::Unflatten(type_code code, const void* buffer, ssize_t size)
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;
1147 memcpy(&fAddress, buffer, min_c(size, (ssize_t)sizeof(fAddress)));
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;
1153 return fStatus = B_OK;
1157 // #pragma mark - operators
1160 BNetworkAddress&
1161 BNetworkAddress::operator=(const BNetworkAddress& other)
1163 memcpy(&fAddress, &other.fAddress, other.fAddress.ss_len);
1164 fHostName = other.fHostName;
1165 fStatus = other.fStatus;
1167 return *this;
1171 bool
1172 BNetworkAddress::operator==(const BNetworkAddress& other) const
1174 return Equals(other);
1178 bool
1179 BNetworkAddress::operator!=(const BNetworkAddress& other) const
1181 return !Equals(other);
1185 bool
1186 BNetworkAddress::operator<(const BNetworkAddress& other) const
1188 if (Family() < other.Family())
1189 return true;
1190 if (Family() > other.Family())
1191 return false;
1193 int compare;
1195 switch (fAddress.ss_family) {
1196 default:
1197 case AF_INET:
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;
1206 case AF_INET6:
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;
1215 case AF_LINK:
1216 if (LinkLevelAddressLength() < other.LinkLevelAddressLength())
1217 return true;
1218 if (LinkLevelAddressLength() > other.LinkLevelAddressLength())
1219 return true;
1221 // TODO: could compare index, and name, too
1222 compare = memcmp(LinkLevelAddress(), other.LinkLevelAddress(),
1223 LinkLevelAddressLength());
1224 break;
1227 if (compare < 0)
1228 return true;
1229 if (compare > 0)
1230 return false;
1232 return Port() < other.Port();
1236 BNetworkAddress::operator const sockaddr*() const
1238 return (const sockaddr*)&fAddress;
1242 BNetworkAddress::operator const sockaddr&() const
1244 return (const sockaddr&)fAddress;
1248 BNetworkAddress::operator sockaddr*()
1250 return (sockaddr*)&fAddress;
1254 BNetworkAddress::operator const sockaddr*()
1256 return (sockaddr*)&fAddress;
1260 BNetworkAddress::operator sockaddr&()
1262 return (sockaddr&)fAddress;
1266 BNetworkAddress::operator const sockaddr&()
1268 return (sockaddr&)fAddress;
1272 // #pragma mark - private
1275 status_t
1276 BNetworkAddress::_ParseLinkAddress(const char* address)
1278 if (address == NULL)
1279 return B_BAD_VALUE;
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;
1287 linkAddress[length++] = (from_hex(address[0]) << 4)
1288 | from_hex(address[1]);
1290 if (address[2] == '\0')
1291 break;
1292 if (address[2] != ':')
1293 return B_BAD_VALUE;
1295 address += 3;
1298 fHostName = address;
1300 SetToLinkLevel(linkAddress, length);
1301 return B_OK;