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