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