xref: /haiku/src/kits/network/libnetapi/NetworkAddress.cpp (revision a5a3b2d9a3d95cbae71eaf371708c73a1780ac0d)
1 /*
2  * Copyright 2010-2015, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <NetworkAddress.h>
8 
9 #include <NetworkInterface.h>
10 #include <NetworkRoster.h>
11 
12 #include <arpa/inet.h>
13 #include <ctype.h>
14 #include <errno.h>
15 #include <netinet/in.h>
16 #include <stdio.h>
17 #include <sys/sockio.h>
18 
19 
20 /* The GCC builtin below only exists in > GCC 3.4
21  * Benefits include faster execution time as the builtin
22  * uses a bitcounting cpu instruction if it exists
23  */
24 #if __GNUC__ > 3
25 #	define addr_bitcount(bitfield) __builtin_popcount(bitfield)
26 #else
27 static ssize_t
28 addr_bitcount(uint32 bitfield)
29 {
30 	ssize_t result = 0;
31 	for (uint8 i = 32; i > 0; i--) {
32 		if ((bitfield & (1 << (i - 1))) == 0)
33 			break;
34 		result++;
35 	}
36 	return result;
37 }
38 #endif
39 
40 
41 static uint8
42 from_hex(char hex)
43 {
44 	if (isdigit(hex))
45 		return hex - '0';
46 
47 	return tolower(hex) - 'a' + 10;
48 }
49 
50 
51 // #pragma mark -
52 
53 
54 BNetworkAddress::BNetworkAddress()
55 {
56 	Unset();
57 }
58 
59 
60 BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags)
61 {
62 	fStatus = SetTo(host, port, flags);
63 }
64 
65 
66 BNetworkAddress::BNetworkAddress(const char* host, const char* service,
67 	uint32 flags)
68 {
69 	fStatus = SetTo(host, service, flags);
70 }
71 
72 
73 BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port,
74 	uint32 flags)
75 {
76 	fStatus = SetTo(family, host, port, flags);
77 }
78 
79 
80 BNetworkAddress::BNetworkAddress(int family, const char* host,
81 	const char* service, uint32 flags)
82 {
83 	fStatus = SetTo(family, host, service, flags);
84 }
85 
86 
87 BNetworkAddress::BNetworkAddress(const sockaddr& address)
88 {
89 	SetTo(address);
90 }
91 
92 
93 BNetworkAddress::BNetworkAddress(const sockaddr_storage& address)
94 {
95 	SetTo(address);
96 }
97 
98 
99 BNetworkAddress::BNetworkAddress(const sockaddr_in& address)
100 {
101 	SetTo(address);
102 }
103 
104 
105 BNetworkAddress::BNetworkAddress(const sockaddr_in6& address)
106 {
107 	SetTo(address);
108 }
109 
110 
111 BNetworkAddress::BNetworkAddress(const sockaddr_dl& address)
112 {
113 	SetTo(address);
114 }
115 
116 
117 BNetworkAddress::BNetworkAddress(in_addr_t address, uint16 port)
118 {
119 	SetTo(address, port);
120 }
121 
122 
123 BNetworkAddress::BNetworkAddress(const in6_addr& address, uint16 port)
124 {
125 	SetTo(address, port);
126 }
127 
128 
129 BNetworkAddress::BNetworkAddress(const BNetworkAddress& other)
130 	:
131 	fAddress(other.fAddress),
132 	fStatus(other.fStatus)
133 {
134 }
135 
136 
137 BNetworkAddress::~BNetworkAddress()
138 {
139 }
140 
141 
142 status_t
143 BNetworkAddress::InitCheck() const
144 {
145 	return fStatus;
146 }
147 
148 
149 void
150 BNetworkAddress::Unset()
151 {
152 	fAddress.ss_family = AF_UNSPEC;
153 	fAddress.ss_len = 2;
154 	fStatus = B_OK;
155 }
156 
157 
158 status_t
159 BNetworkAddress::SetTo(const char* host, uint16 port, uint32 flags)
160 {
161 	BReference<const BNetworkAddressResolver> resolver
162 		= BNetworkAddressResolver::Resolve(host, port, flags);
163 	if (resolver.Get() == NULL)
164 		return B_NO_MEMORY;
165 	status_t status = resolver->InitCheck();
166 	if (status != B_OK)
167 		return status;
168 
169 	// Prefer IPv6 addresses
170 
171 	uint32 cookie = 0;
172 	status = resolver->GetNextAddress(AF_INET6, &cookie, *this);
173 	if (status == B_OK) {
174 		fStatus = B_OK;
175 		return B_OK;
176 	}
177 
178 	cookie = 0;
179 	status = resolver->GetNextAddress(&cookie, *this);
180 	if (status != B_OK)
181 		Unset();
182 	fStatus = status;
183 	return status;
184 }
185 
186 
187 status_t
188 BNetworkAddress::SetTo(const char* host, const char* service, uint32 flags)
189 {
190 	BReference<const BNetworkAddressResolver> resolver
191 		= BNetworkAddressResolver::Resolve(host, service, flags);
192 	if (resolver.Get() == NULL)
193 		return B_NO_MEMORY;
194 	status_t status = resolver->InitCheck();
195 	if (status != B_OK)
196 		return status;
197 
198 	// Prefer IPv6 addresses
199 
200 	uint32 cookie = 0;
201 	status = resolver->GetNextAddress(AF_INET6, &cookie, *this);
202 	if (status == B_OK) {
203 		fStatus = B_OK;
204 		return B_OK;
205 	}
206 
207 	cookie = 0;
208 	status = resolver->GetNextAddress(&cookie, *this);
209 	if (status != B_OK)
210 		Unset();
211 	fStatus = status;
212 	return status;
213 }
214 
215 
216 status_t
217 BNetworkAddress::SetTo(int family, const char* host, uint16 port, uint32 flags)
218 {
219 	if (family == AF_LINK) {
220 		if (port != 0)
221 			return B_BAD_VALUE;
222 		return _ParseLinkAddress(host);
223 			// SetToLinkAddress takes care of setting fStatus
224 	}
225 
226 	BReference<const BNetworkAddressResolver> resolver
227 		= BNetworkAddressResolver::Resolve(family, host, port, flags);
228 	if (resolver.Get() == NULL)
229 		return B_NO_MEMORY;
230 	status_t status = resolver->InitCheck();
231 	if (status != B_OK)
232 		return status;
233 
234 	uint32 cookie = 0;
235 	status = resolver->GetNextAddress(&cookie, *this);
236 	if (status != B_OK)
237 		Unset();
238 	fStatus = status;
239 	return status;
240 }
241 
242 
243 status_t
244 BNetworkAddress::SetTo(int family, const char* host, const char* service,
245 	uint32 flags)
246 {
247 	if (family == AF_LINK) {
248 		if (service != NULL)
249 			return B_BAD_VALUE;
250 		return _ParseLinkAddress(host);
251 			// SetToLinkAddress takes care of setting fStatus
252 	}
253 
254 	BReference<const BNetworkAddressResolver> resolver
255 		= BNetworkAddressResolver::Resolve(family, host, service, flags);
256 	if (resolver.Get() == NULL)
257 		return B_NO_MEMORY;
258 	status_t status = resolver->InitCheck();
259 	if (status != B_OK)
260 		return status;
261 
262 	uint32 cookie = 0;
263 	status = resolver->GetNextAddress(&cookie, *this);
264 	if (status != B_OK)
265 		Unset();
266 	fStatus = status;
267 	return status;
268 }
269 
270 
271 void
272 BNetworkAddress::SetTo(const sockaddr& address)
273 {
274 	if (address.sa_family == AF_UNSPEC) {
275 		Unset();
276 		return;
277 	}
278 
279 	size_t length = min_c(sizeof(sockaddr_storage), address.sa_len);
280 	switch (address.sa_family) {
281 		case AF_INET:
282 			length = sizeof(sockaddr_in);
283 			break;
284 		case AF_INET6:
285 			length = sizeof(sockaddr_in6);
286 			break;
287 		case AF_LINK:
288 		{
289 			sockaddr_dl& link = (sockaddr_dl&)address;
290 			length = sizeof(sockaddr_dl) - sizeof(link.sdl_data) + link.sdl_alen
291 				+ link.sdl_nlen + link.sdl_slen;
292 			break;
293 		}
294 	}
295 
296 	SetTo(address, length);
297 }
298 
299 
300 void
301 BNetworkAddress::SetTo(const sockaddr& address, size_t length)
302 {
303 	if (address.sa_family == AF_UNSPEC || length == 0) {
304 		Unset();
305 		return;
306 	}
307 
308 	memcpy(&fAddress, &address, length);
309 	fAddress.ss_len = length;
310 	fStatus = B_OK;
311 }
312 
313 
314 void
315 BNetworkAddress::SetTo(const sockaddr_storage& address)
316 {
317 	SetTo((sockaddr&)address);
318 }
319 
320 
321 void
322 BNetworkAddress::SetTo(const sockaddr_in& address)
323 {
324 	SetTo((sockaddr&)address);
325 }
326 
327 
328 void
329 BNetworkAddress::SetTo(const sockaddr_in6& address)
330 {
331 	SetTo((sockaddr&)address);
332 }
333 
334 
335 void
336 BNetworkAddress::SetTo(const sockaddr_dl& address)
337 {
338 	SetTo((sockaddr&)address);
339 }
340 
341 
342 void
343 BNetworkAddress::SetTo(in_addr_t inetAddress, uint16 port)
344 {
345 	memset(&fAddress, 0, sizeof(sockaddr_storage));
346 
347 	fAddress.ss_family = AF_INET;
348 	fAddress.ss_len = sizeof(sockaddr_in);
349 	SetAddress(inetAddress);
350 	SetPort(port);
351 
352 	fStatus = B_OK;
353 }
354 
355 
356 void
357 BNetworkAddress::SetTo(const in6_addr& inet6Address, uint16 port)
358 {
359 	memset(&fAddress, 0, sizeof(sockaddr_storage));
360 
361 	fAddress.ss_family = AF_INET6;
362 	fAddress.ss_len = sizeof(sockaddr_in6);
363 	SetAddress(inet6Address);
364 	SetPort(port);
365 
366 	fStatus = B_OK;
367 }
368 
369 
370 void
371 BNetworkAddress::SetTo(const BNetworkAddress& other)
372 {
373 	fAddress = other.fAddress;
374 	fStatus = other.fStatus;
375 }
376 
377 
378 status_t
379 BNetworkAddress::SetToBroadcast(int family, uint16 port)
380 {
381 	if (family != AF_INET)
382 		return fStatus = B_NOT_SUPPORTED;
383 
384 	SetTo(INADDR_BROADCAST, port);
385 	return fStatus;
386 }
387 
388 
389 status_t
390 BNetworkAddress::SetToLocal(int family, uint16 port)
391 {
392 	// TODO: choose a local address from the network interfaces
393 	return fStatus = B_NOT_SUPPORTED;
394 }
395 
396 
397 status_t
398 BNetworkAddress::SetToLoopback(int family, uint16 port)
399 {
400 	switch (family) {
401 		// TODO: choose family depending on availability of IPv6
402 		case AF_UNSPEC:
403 		case AF_INET:
404 			SetTo(htonl(INADDR_LOOPBACK), port);
405 			break;
406 
407 		case AF_INET6:
408 			SetTo(in6addr_loopback, port);
409 			break;
410 
411 		default:
412 			return fStatus = B_NOT_SUPPORTED;
413 	}
414 
415 	return fStatus;
416 }
417 
418 
419 status_t
420 BNetworkAddress::SetToMask(int family, uint32 prefixLength)
421 {
422 	switch (family) {
423 		case AF_INET:
424 		{
425 			if (prefixLength > 32)
426 				return B_BAD_VALUE;
427 
428 			sockaddr_in& mask = (sockaddr_in&)fAddress;
429 			memset(&fAddress, 0, sizeof(sockaddr_storage));
430 			mask.sin_family = AF_INET;
431 			mask.sin_len = sizeof(sockaddr_in);
432 
433 			uint32 hostMask = 0;
434 			for (uint8 i = 32; i > 32 - prefixLength; i--)
435 				hostMask |= 1 << (i - 1);
436 
437 			mask.sin_addr.s_addr = htonl(hostMask);
438 			break;
439 		}
440 
441 		case AF_INET6:
442 		{
443 			if (prefixLength > 128)
444 				return B_BAD_VALUE;
445 
446 			sockaddr_in6& mask = (sockaddr_in6&)fAddress;
447 			memset(&fAddress, 0, sizeof(sockaddr_storage));
448 			mask.sin6_family = AF_INET6;
449 			mask.sin6_len = sizeof(sockaddr_in6);
450 
451 			for (uint8 i = 0; i < sizeof(in6_addr); i++, prefixLength -= 8) {
452 				if (prefixLength < 8) {
453 					mask.sin6_addr.s6_addr[i]
454 						= (uint8)(0xff << (8 - prefixLength));
455 					break;
456 				}
457 
458 				mask.sin6_addr.s6_addr[i] = 0xff;
459 			}
460 			break;
461 		}
462 
463 		default:
464 			return B_NOT_SUPPORTED;
465 	}
466 
467 	return fStatus = B_OK;
468 }
469 
470 
471 status_t
472 BNetworkAddress::SetToWildcard(int family, uint16 port)
473 {
474 	switch (family) {
475 		case AF_INET:
476 			SetTo(INADDR_ANY, port);
477 			break;
478 
479 		case AF_INET6:
480 			SetTo(in6addr_any, port);
481 			break;
482 
483 		default:
484 			return B_NOT_SUPPORTED;
485 	}
486 
487 	return fStatus;
488 }
489 
490 
491 status_t
492 BNetworkAddress::SetAddress(in_addr_t inetAddress)
493 {
494 	if (Family() != AF_INET)
495 		return B_BAD_VALUE;
496 
497 	sockaddr_in& address = (sockaddr_in&)fAddress;
498 	address.sin_addr.s_addr = inetAddress;
499 	return B_OK;
500 }
501 
502 
503 status_t
504 BNetworkAddress::SetAddress(const in6_addr& inet6Address)
505 {
506 	if (Family() != AF_INET6)
507 		return B_BAD_VALUE;
508 
509 	sockaddr_in6& address = (sockaddr_in6&)fAddress;
510 	memcpy(address.sin6_addr.s6_addr, &inet6Address,
511 		sizeof(address.sin6_addr.s6_addr));
512 	return B_OK;
513 }
514 
515 
516 void
517 BNetworkAddress::SetPort(uint16 port)
518 {
519 	switch (fAddress.ss_family) {
520 		case AF_INET:
521 			((sockaddr_in&)fAddress).sin_port = htons(port);
522 			break;
523 
524 		case AF_INET6:
525 			((sockaddr_in6&)fAddress).sin6_port = htons(port);
526 			break;
527 
528 		default:
529 			break;
530 	}
531 }
532 
533 
534 void
535 BNetworkAddress::SetToLinkLevel(uint8* address, size_t length)
536 {
537 	sockaddr_dl& link = (sockaddr_dl&)fAddress;
538 	memset(&link, 0, sizeof(sockaddr_dl));
539 
540 	link.sdl_family = AF_LINK;
541 	link.sdl_alen = length;
542 	memcpy(LLADDR(&link), address, length);
543 
544 	link.sdl_len = sizeof(sockaddr_dl);
545 	if (length > sizeof(link.sdl_data))
546 		link.sdl_len += length - sizeof(link.sdl_data);
547 
548 	fStatus = B_OK;
549 }
550 
551 
552 void
553 BNetworkAddress::SetToLinkLevel(const char* name)
554 {
555 	sockaddr_dl& link = (sockaddr_dl&)fAddress;
556 	memset(&link, 0, sizeof(sockaddr_dl));
557 
558 	size_t length = strlen(name);
559 	if (length > sizeof(fAddress) - sizeof(sockaddr_dl) + sizeof(link.sdl_data))
560 		length = sizeof(fAddress) - sizeof(sockaddr_dl) + sizeof(link.sdl_data);
561 
562 	link.sdl_family = AF_LINK;
563 	link.sdl_nlen = length;
564 
565 	memcpy(link.sdl_data, name, link.sdl_nlen);
566 
567 	link.sdl_len = sizeof(sockaddr_dl);
568 	if (link.sdl_nlen > sizeof(link.sdl_data))
569 		link.sdl_len += link.sdl_nlen - sizeof(link.sdl_data);
570 
571 	fStatus = B_OK;
572 }
573 
574 
575 void
576 BNetworkAddress::SetToLinkLevel(uint32 index)
577 {
578 	sockaddr_dl& link = (sockaddr_dl&)fAddress;
579 	memset(&link, 0, sizeof(sockaddr_dl));
580 
581 	link.sdl_family = AF_LINK;
582 	link.sdl_len = sizeof(sockaddr_dl);
583 	link.sdl_index = index;
584 
585 	fStatus = B_OK;
586 }
587 
588 
589 void
590 BNetworkAddress::SetLinkLevelIndex(uint32 index)
591 {
592 	sockaddr_dl& link = (sockaddr_dl&)fAddress;
593 	link.sdl_index = index;
594 }
595 
596 
597 void
598 BNetworkAddress::SetLinkLevelType(uint8 type)
599 {
600 	sockaddr_dl& link = (sockaddr_dl&)fAddress;
601 	link.sdl_type = type;
602 }
603 
604 
605 void
606 BNetworkAddress::SetLinkLevelFrameType(uint16 frameType)
607 {
608 	sockaddr_dl& link = (sockaddr_dl&)fAddress;
609 	link.sdl_e_type = htons(frameType);
610 }
611 
612 
613 int
614 BNetworkAddress::Family() const
615 {
616 	return fAddress.ss_family;
617 }
618 
619 
620 uint16
621 BNetworkAddress::Port() const
622 {
623 	switch (fAddress.ss_family) {
624 		case AF_INET:
625 			return ntohs(((sockaddr_in&)fAddress).sin_port);
626 
627 		case AF_INET6:
628 			return ntohs(((sockaddr_in6&)fAddress).sin6_port);
629 
630 		default:
631 			return 0;
632 	}
633 }
634 
635 
636 size_t
637 BNetworkAddress::Length() const
638 {
639 	return fAddress.ss_len;
640 }
641 
642 
643 const sockaddr&
644 BNetworkAddress::SockAddr() const
645 {
646 	return (const sockaddr&)fAddress;
647 }
648 
649 
650 sockaddr&
651 BNetworkAddress::SockAddr()
652 {
653 	return (sockaddr&)fAddress;
654 }
655 
656 
657 bool
658 BNetworkAddress::IsEmpty() const
659 {
660 	if (fAddress.ss_len == 0)
661 		return true;
662 
663 	switch (fAddress.ss_family) {
664 		case AF_UNSPEC:
665 			return true;
666 		case AF_INET:
667 		{
668 			sockaddr_in& sin = (sockaddr_in&)fAddress;
669 			return sin.sin_addr.s_addr == INADDR_ANY && sin.sin_port == 0;
670 		}
671 		case AF_INET6:
672 		{
673 			sockaddr_in6& sin6 = (sockaddr_in6&)fAddress;
674 			return IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)
675 				&& sin6.sin6_port == 0;
676 		}
677 
678 		default:
679 			return false;
680 	}
681 }
682 
683 
684 bool
685 BNetworkAddress::IsWildcard() const
686 {
687 	switch (fAddress.ss_family) {
688 		case AF_INET:
689 			return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_ANY;
690 
691 		case AF_INET6:
692 			return !memcmp(&((sockaddr_in6&)fAddress).sin6_addr, &in6addr_any,
693 				sizeof(in6_addr));
694 
695 		default:
696 			return false;
697 	}
698 }
699 
700 
701 bool
702 BNetworkAddress::IsBroadcast() const
703 {
704 	switch (fAddress.ss_family) {
705 		case AF_INET:
706 			return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_BROADCAST;
707 
708 		case AF_INET6:
709 			// There is no broadcast in IPv6, only multicast/anycast
710 			return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
711 
712 		default:
713 			return false;
714 	}
715 }
716 
717 
718 bool
719 BNetworkAddress::IsMulticast() const
720 {
721 	switch (fAddress.ss_family) {
722 		case AF_INET:
723 			return IN_MULTICAST(((sockaddr_in&)fAddress).sin_addr.s_addr);
724 
725 		case AF_INET6:
726 			return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
727 
728 		default:
729 			return false;
730 	}
731 }
732 
733 
734 bool
735 BNetworkAddress::IsMulticastGlobal() const
736 {
737 	switch (fAddress.ss_family) {
738 		case AF_INET6:
739 			return IN6_IS_ADDR_MC_GLOBAL(&((sockaddr_in6&)fAddress).sin6_addr);
740 
741 		default:
742 			return false;
743 	}
744 }
745 
746 
747 bool
748 BNetworkAddress::IsMulticastNodeLocal() const
749 {
750 	switch (fAddress.ss_family) {
751 		case AF_INET6:
752 			return IN6_IS_ADDR_MC_NODELOCAL(
753 				&((sockaddr_in6&)fAddress).sin6_addr);
754 
755 		default:
756 			return false;
757 	}
758 }
759 
760 
761 bool
762 BNetworkAddress::IsMulticastLinkLocal() const
763 {
764 	switch (fAddress.ss_family) {
765 		case AF_INET6:
766 			return IN6_IS_ADDR_MC_LINKLOCAL(
767 				&((sockaddr_in6&)fAddress).sin6_addr);
768 
769 		default:
770 			return false;
771 	}
772 }
773 
774 
775 bool
776 BNetworkAddress::IsMulticastSiteLocal() const
777 {
778 	switch (fAddress.ss_family) {
779 		case AF_INET6:
780 			return IN6_IS_ADDR_MC_SITELOCAL(
781 				&((sockaddr_in6&)fAddress).sin6_addr);
782 
783 		default:
784 			return false;
785 	}
786 }
787 
788 
789 bool
790 BNetworkAddress::IsMulticastOrgLocal() const
791 {
792 	switch (fAddress.ss_family) {
793 		case AF_INET6:
794 			return IN6_IS_ADDR_MC_ORGLOCAL(
795 				&((sockaddr_in6&)fAddress).sin6_addr);
796 
797 		default:
798 			return false;
799 	}
800 }
801 
802 
803 bool
804 BNetworkAddress::IsLinkLocal() const
805 {
806 	// TODO: ipv4
807 	switch (fAddress.ss_family) {
808 		case AF_INET6:
809 			return IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
810 
811 		default:
812 			return false;
813 	}
814 }
815 
816 
817 bool
818 BNetworkAddress::IsSiteLocal() const
819 {
820 	switch (fAddress.ss_family) {
821 		case AF_INET6:
822 			return IN6_IS_ADDR_SITELOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
823 
824 		default:
825 			return false;
826 	}
827 }
828 
829 
830 bool
831 BNetworkAddress::IsLocal() const
832 {
833 	BNetworkRoster& roster = BNetworkRoster::Default();
834 
835 	BNetworkInterface interface;
836 	uint32 cookie = 0;
837 
838 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
839 		int32 count = interface.CountAddresses();
840 		for (int32 j = 0; j < count; j++) {
841 			BNetworkInterfaceAddress address;
842 			if (interface.GetAddressAt(j, address) != B_OK)
843 				break;
844 
845 			if (Equals(address.Address(), false))
846 				return true;
847 		}
848 	}
849 
850 	return false;
851 }
852 
853 
854 ssize_t
855 BNetworkAddress::PrefixLength() const
856 {
857 	switch (fAddress.ss_family) {
858 		case AF_INET:
859 		{
860 			sockaddr_in& mask = (sockaddr_in&)fAddress;
861 
862 			uint32 hostMask = ntohl(mask.sin_addr.s_addr);
863 			return addr_bitcount(hostMask);
864 		}
865 
866 		case AF_INET6:
867 		{
868 			sockaddr_in6& mask = (sockaddr_in6&)fAddress;
869 
870 			// TODO : see if we can use the optimized addr_bitcount for this
871 			ssize_t result = 0;
872 			for (uint8 i = 0; i < sizeof(in6_addr); i++) {
873 				for (uint8 j = 0; j < 8; j++) {
874 					if (!(mask.sin6_addr.s6_addr[i] & (1 << j)))
875 						return result;
876 					result++;
877 				}
878 			}
879 
880 			return 128;
881 		}
882 
883 		default:
884 			return B_NOT_SUPPORTED;
885 	}
886 }
887 
888 
889 uint32
890 BNetworkAddress::LinkLevelIndex() const
891 {
892 	return ((sockaddr_dl&)fAddress).sdl_index;
893 }
894 
895 
896 BString
897 BNetworkAddress::LinkLevelInterface() const
898 {
899 	sockaddr_dl& address = (sockaddr_dl&)fAddress;
900 	if (address.sdl_nlen == 0)
901 		return "";
902 
903 	BString name;
904 	name.SetTo((const char*)address.sdl_data, address.sdl_nlen);
905 
906 	return name;
907 }
908 
909 
910 uint8
911 BNetworkAddress::LinkLevelType() const
912 {
913 	return ((sockaddr_dl&)fAddress).sdl_type;
914 }
915 
916 
917 uint16
918 BNetworkAddress::LinkLevelFrameType() const
919 {
920 	return ntohs(((sockaddr_dl&)fAddress).sdl_e_type);
921 }
922 
923 
924 uint8*
925 BNetworkAddress::LinkLevelAddress() const
926 {
927 	return LLADDR(&(sockaddr_dl&)fAddress);
928 }
929 
930 
931 size_t
932 BNetworkAddress::LinkLevelAddressLength() const
933 {
934 	return ((sockaddr_dl&)fAddress).sdl_alen;
935 }
936 
937 
938 status_t
939 BNetworkAddress::ResolveForDestination(const BNetworkAddress& destination)
940 {
941 	if (!IsWildcard())
942 		return B_OK;
943 	if (destination.fAddress.ss_family != fAddress.ss_family)
944 		return B_BAD_VALUE;
945 
946 	char buffer[2048];
947 	memset(buffer, 0, sizeof(buffer));
948 
949 	route_entry* route = (route_entry*)buffer;
950 	route->destination = (sockaddr*)&destination.fAddress;
951 
952 	int socket = ::socket(fAddress.ss_family, SOCK_DGRAM, 0);
953 	if (socket < 0)
954 		return errno;
955 
956 	if (ioctl(socket, SIOCGETRT, route, sizeof(buffer)) != 0) {
957 		close(socket);
958 		return errno;
959 	}
960 
961 	uint16 port = Port();
962 	memcpy(&fAddress, route->source, sizeof(sockaddr_storage));
963 	SetPort(port);
964 
965 	return B_OK;
966 }
967 
968 
969 status_t
970 BNetworkAddress::ResolveTo(const BNetworkAddress& address)
971 {
972 	if (!IsWildcard())
973 		return B_OK;
974 	if (address.fAddress.ss_family != fAddress.ss_family)
975 		return B_BAD_VALUE;
976 
977 	uint16 port = Port();
978 	*this = address;
979 	SetPort(port);
980 
981 	return B_OK;
982 }
983 
984 
985 BString
986 BNetworkAddress::ToString(bool includePort) const
987 {
988 	char buffer[512];
989 
990 	switch (fAddress.ss_family) {
991 		case AF_INET:
992 			inet_ntop(AF_INET, &((sockaddr_in&)fAddress).sin_addr, buffer,
993 				sizeof(buffer));
994 			break;
995 
996 		case AF_INET6:
997 			inet_ntop(AF_INET6, &((sockaddr_in6&)fAddress).sin6_addr,
998 				buffer, sizeof(buffer));
999 			break;
1000 
1001 		case AF_LINK:
1002 		{
1003 			uint8 *byte = LinkLevelAddress();
1004 			char* target = buffer;
1005 			int bytesLeft = sizeof(buffer);
1006 			target[0] = '\0';
1007 
1008 			for (size_t i = 0; i < LinkLevelAddressLength(); i++) {
1009 				if (i != 0 && bytesLeft > 1) {
1010 					target[0] = ':';
1011 					target[1] = '\0';
1012 					target++;
1013 					bytesLeft--;
1014 				}
1015 
1016 				int bytesWritten = snprintf(target, bytesLeft, "%02x", byte[i]);
1017 				if (bytesWritten >= bytesLeft)
1018 					break;
1019 
1020 				target += bytesWritten;
1021 				bytesLeft -= bytesWritten;
1022 			}
1023 			break;
1024 		}
1025 
1026 		default:
1027 			return "";
1028 	}
1029 
1030 	BString address = buffer;
1031 	if (includePort && Port() != 0) {
1032 		if (fAddress.ss_family == AF_INET6) {
1033 			address = "[";
1034 			address += buffer;
1035 			address += "]";
1036 		}
1037 
1038 		snprintf(buffer, sizeof(buffer), ":%u", Port());
1039 		address += buffer;
1040 	}
1041 
1042 	return address;
1043 }
1044 
1045 
1046 BString
1047 BNetworkAddress::HostName() const
1048 {
1049 	// TODO: implement host name lookup
1050 	return ToString(false);
1051 }
1052 
1053 
1054 BString
1055 BNetworkAddress::ServiceName() const
1056 {
1057 	// TODO: implement service lookup
1058 	BString portName;
1059 	portName << Port();
1060 	return portName;
1061 }
1062 
1063 
1064 bool
1065 BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const
1066 {
1067 	if (IsEmpty() && other.IsEmpty())
1068 		return true;
1069 
1070 	if (Family() != other.Family()
1071 			|| (includePort && Port() != other.Port())) {
1072 		return false;
1073 	}
1074 
1075 	switch (fAddress.ss_family) {
1076 		case AF_INET:
1077 		{
1078 			sockaddr_in& address = (sockaddr_in&)fAddress;
1079 			sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress;
1080 			return memcmp(&address.sin_addr, &otherAddress.sin_addr,
1081 				sizeof(address.sin_addr)) == 0;
1082 		}
1083 
1084 		case AF_INET6:
1085 		{
1086 			sockaddr_in6& address = (sockaddr_in6&)fAddress;
1087 			sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress;
1088 			return memcmp(&address.sin6_addr, &otherAddress.sin6_addr,
1089 				sizeof(address.sin6_addr)) == 0;
1090 		}
1091 
1092 		default:
1093 			if (fAddress.ss_len != other.fAddress.ss_len)
1094 				return false;
1095 
1096 			return memcmp(&fAddress, &other.fAddress, fAddress.ss_len);
1097 	}
1098 }
1099 
1100 
1101 // #pragma mark - BFlattenable implementation
1102 
1103 
1104 bool
1105 BNetworkAddress::IsFixedSize() const
1106 {
1107 	return false;
1108 }
1109 
1110 
1111 type_code
1112 BNetworkAddress::TypeCode() const
1113 {
1114 	return B_NETWORK_ADDRESS_TYPE;
1115 }
1116 
1117 
1118 ssize_t
1119 BNetworkAddress::FlattenedSize() const
1120 {
1121 	return Length();
1122 }
1123 
1124 
1125 status_t
1126 BNetworkAddress::Flatten(void* buffer, ssize_t size) const
1127 {
1128 	if (buffer == NULL || size < FlattenedSize())
1129 		return B_BAD_VALUE;
1130 
1131 	memcpy(buffer, &fAddress, Length());
1132 	return B_OK;
1133 }
1134 
1135 
1136 status_t
1137 BNetworkAddress::Unflatten(type_code code, const void* buffer, ssize_t size)
1138 {
1139 	// 2 bytes minimum for family, and length
1140 	if (buffer == NULL || size < 2)
1141 		return fStatus = B_BAD_VALUE;
1142 	if (!AllowsTypeCode(code))
1143 		return fStatus = B_BAD_TYPE;
1144 
1145 	memcpy(&fAddress, buffer, min_c(size, (ssize_t)sizeof(fAddress)));
1146 
1147 	// check if this can contain a valid address
1148 	if (fAddress.ss_family != AF_UNSPEC && size < (ssize_t)sizeof(sockaddr))
1149 		return fStatus = B_BAD_VALUE;
1150 
1151 	return fStatus = B_OK;
1152 }
1153 
1154 
1155 // #pragma mark - operators
1156 
1157 
1158 BNetworkAddress&
1159 BNetworkAddress::operator=(const BNetworkAddress& other)
1160 {
1161 	memcpy(&fAddress, &other.fAddress, other.fAddress.ss_len);
1162 	fStatus = other.fStatus;
1163 
1164 	return *this;
1165 }
1166 
1167 
1168 bool
1169 BNetworkAddress::operator==(const BNetworkAddress& other) const
1170 {
1171 	return Equals(other);
1172 }
1173 
1174 
1175 bool
1176 BNetworkAddress::operator!=(const BNetworkAddress& other) const
1177 {
1178 	return !Equals(other);
1179 }
1180 
1181 
1182 bool
1183 BNetworkAddress::operator<(const BNetworkAddress& other) const
1184 {
1185 	if (Family() < other.Family())
1186 		return true;
1187 	if (Family() > other.Family())
1188 		return false;
1189 
1190 	int compare;
1191 
1192 	switch (fAddress.ss_family) {
1193 		default:
1194 		case AF_INET:
1195 		{
1196 			sockaddr_in& address = (sockaddr_in&)fAddress;
1197 			sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress;
1198 			compare = memcmp(&address.sin_addr, &otherAddress.sin_addr,
1199 				sizeof(address.sin_addr));
1200 			break;
1201 		}
1202 
1203 		case AF_INET6:
1204 		{
1205 			sockaddr_in6& address = (sockaddr_in6&)fAddress;
1206 			sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress;
1207 			compare = memcmp(&address.sin6_addr, &otherAddress.sin6_addr,
1208 				sizeof(address.sin6_addr));
1209 			break;
1210 		}
1211 
1212 		case AF_LINK:
1213 			if (LinkLevelAddressLength() < other.LinkLevelAddressLength())
1214 				return true;
1215 			if (LinkLevelAddressLength() > other.LinkLevelAddressLength())
1216 				return true;
1217 
1218 			// TODO: could compare index, and name, too
1219 			compare = memcmp(LinkLevelAddress(), other.LinkLevelAddress(),
1220 				LinkLevelAddressLength());
1221 			break;
1222 	}
1223 
1224 	if (compare < 0)
1225 		return true;
1226 	if (compare > 0)
1227 		return false;
1228 
1229 	return Port() < other.Port();
1230 }
1231 
1232 
1233 BNetworkAddress::operator const sockaddr*() const
1234 {
1235 	return (const sockaddr*)&fAddress;
1236 }
1237 
1238 
1239 BNetworkAddress::operator const sockaddr&() const
1240 {
1241 	return (const sockaddr&)fAddress;
1242 }
1243 
1244 
1245 BNetworkAddress::operator sockaddr*()
1246 {
1247 	return (sockaddr*)&fAddress;
1248 }
1249 
1250 
1251 BNetworkAddress::operator const sockaddr*()
1252 {
1253 	return (sockaddr*)&fAddress;
1254 }
1255 
1256 
1257 BNetworkAddress::operator sockaddr&()
1258 {
1259 	return (sockaddr&)fAddress;
1260 }
1261 
1262 
1263 BNetworkAddress::operator const sockaddr&()
1264 {
1265 	return (sockaddr&)fAddress;
1266 }
1267 
1268 
1269 // #pragma mark - private
1270 
1271 
1272 status_t
1273 BNetworkAddress::_ParseLinkAddress(const char* address)
1274 {
1275 	if (address == NULL)
1276 		return B_BAD_VALUE;
1277 
1278 	uint8 linkAddress[128];
1279 	uint32 length = 0;
1280 	while (length < sizeof(linkAddress)) {
1281 		if (!isxdigit(address[0]) || !isxdigit(address[1]))
1282 			return B_BAD_VALUE;
1283 
1284 		linkAddress[length++] = (from_hex(address[0]) << 4)
1285 			| from_hex(address[1]);
1286 
1287 		if (address[2] == '\0')
1288 			break;
1289 		if (address[2] != ':')
1290 			return B_BAD_VALUE;
1291 
1292 		address += 3;
1293 	}
1294 
1295 	SetToLinkLevel(linkAddress, length);
1296 	return B_OK;
1297 }
1298