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
27static ssize_t
28addr_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
41static uint8
42from_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
54BNetworkAddress::BNetworkAddress()
55{
56	Unset();
57}
58
59
60BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags)
61{
62	SetTo(host, port, flags);
63}
64
65
66BNetworkAddress::BNetworkAddress(const char* host, const char* service,
67	uint32 flags)
68{
69	SetTo(host, service, flags);
70}
71
72
73BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port,
74	uint32 flags)
75{
76	SetTo(family, host, port, flags);
77}
78
79
80BNetworkAddress::BNetworkAddress(int family, const char* host,
81	const char* service, uint32 flags)
82{
83	SetTo(family, host, service, flags);
84}
85
86
87BNetworkAddress::BNetworkAddress(const sockaddr& address)
88{
89	SetTo(address);
90}
91
92
93BNetworkAddress::BNetworkAddress(const sockaddr_storage& address)
94{
95	SetTo(address);
96}
97
98
99BNetworkAddress::BNetworkAddress(const sockaddr_in& address)
100{
101	SetTo(address);
102}
103
104
105BNetworkAddress::BNetworkAddress(const sockaddr_in6& address)
106{
107	SetTo(address);
108}
109
110
111BNetworkAddress::BNetworkAddress(const sockaddr_dl& address)
112{
113	SetTo(address);
114}
115
116
117BNetworkAddress::BNetworkAddress(in_addr_t address, uint16 port)
118{
119	SetTo(address, port);
120}
121
122
123BNetworkAddress::BNetworkAddress(const in6_addr& address, uint16 port)
124{
125	SetTo(address, port);
126}
127
128
129BNetworkAddress::BNetworkAddress(const BNetworkAddress& other)
130	:
131	fAddress(other.fAddress),
132	fStatus(other.fStatus)
133{
134}
135
136
137BNetworkAddress::~BNetworkAddress()
138{
139}
140
141
142status_t
143BNetworkAddress::InitCheck() const
144{
145	return fStatus;
146}
147
148
149void
150BNetworkAddress::Unset()
151{
152	fAddress.ss_family = AF_UNSPEC;
153	fAddress.ss_len = 2;
154	fStatus = B_OK;
155}
156
157
158status_t
159BNetworkAddress::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
178status_t
179BNetworkAddress::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
198status_t
199BNetworkAddress::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
217status_t
218BNetworkAddress::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
237void
238BNetworkAddress::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
266void
267BNetworkAddress::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
280void
281BNetworkAddress::SetTo(const sockaddr_storage& address)
282{
283	SetTo((sockaddr&)address);
284}
285
286
287void
288BNetworkAddress::SetTo(const sockaddr_in& address)
289{
290	SetTo((sockaddr&)address);
291}
292
293
294void
295BNetworkAddress::SetTo(const sockaddr_in6& address)
296{
297	SetTo((sockaddr&)address);
298}
299
300
301void
302BNetworkAddress::SetTo(const sockaddr_dl& address)
303{
304	SetTo((sockaddr&)address);
305}
306
307
308void
309BNetworkAddress::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
322void
323BNetworkAddress::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
336void
337BNetworkAddress::SetTo(const BNetworkAddress& other)
338{
339	fAddress = other.fAddress;
340	fStatus = other.fStatus;
341}
342
343
344status_t
345BNetworkAddress::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
355status_t
356BNetworkAddress::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
363status_t
364BNetworkAddress::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
385status_t
386BNetworkAddress::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
437status_t
438BNetworkAddress::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
457status_t
458BNetworkAddress::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
469status_t
470BNetworkAddress::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
482void
483BNetworkAddress::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
500void
501BNetworkAddress::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
516void
517BNetworkAddress::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
537void
538BNetworkAddress::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
549void
550BNetworkAddress::SetLinkLevelIndex(uint32 index)
551{
552	sockaddr_dl& link = (sockaddr_dl&)fAddress;
553	link.sdl_index = index;
554}
555
556
557void
558BNetworkAddress::SetLinkLevelType(uint8 type)
559{
560	sockaddr_dl& link = (sockaddr_dl&)fAddress;
561	link.sdl_type = type;
562}
563
564
565void
566BNetworkAddress::SetLinkLevelFrameType(uint16 frameType)
567{
568	sockaddr_dl& link = (sockaddr_dl&)fAddress;
569	link.sdl_e_type = htons(frameType);
570}
571
572
573int
574BNetworkAddress::Family() const
575{
576	return fAddress.ss_family;
577}
578
579
580uint16
581BNetworkAddress::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
596size_t
597BNetworkAddress::Length() const
598{
599	return fAddress.ss_len;
600}
601
602
603const sockaddr&
604BNetworkAddress::SockAddr() const
605{
606	return (const sockaddr&)fAddress;
607}
608
609
610sockaddr&
611BNetworkAddress::SockAddr()
612{
613	return (sockaddr&)fAddress;
614}
615
616
617bool
618BNetworkAddress::IsEmpty() const
619{
620	return fAddress.ss_len == 0 || fAddress.ss_family == AF_UNSPEC;
621}
622
623
624bool
625BNetworkAddress::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
641bool
642BNetworkAddress::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
658bool
659BNetworkAddress::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
674bool
675BNetworkAddress::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
687bool
688BNetworkAddress::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
701bool
702BNetworkAddress::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
715bool
716BNetworkAddress::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
729bool
730BNetworkAddress::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
743bool
744BNetworkAddress::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
757bool
758BNetworkAddress::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
770bool
771BNetworkAddress::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
794ssize_t
795BNetworkAddress::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
829uint32
830BNetworkAddress::LinkLevelIndex() const
831{
832	return ((sockaddr_dl&)fAddress).sdl_index;
833}
834
835
836BString
837BNetworkAddress::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
850uint8
851BNetworkAddress::LinkLevelType() const
852{
853	return ((sockaddr_dl&)fAddress).sdl_type;
854}
855
856
857uint16
858BNetworkAddress::LinkLevelFrameType() const
859{
860	return ntohs(((sockaddr_dl&)fAddress).sdl_e_type);
861}
862
863
864uint8*
865BNetworkAddress::LinkLevelAddress() const
866{
867	return LLADDR(&(sockaddr_dl&)fAddress);
868}
869
870
871size_t
872BNetworkAddress::LinkLevelAddressLength() const
873{
874	return ((sockaddr_dl&)fAddress).sdl_alen;
875}
876
877
878status_t
879BNetworkAddress::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
909status_t
910BNetworkAddress::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
925BString
926BNetworkAddress::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
986BString
987BNetworkAddress::HostName() const
988{
989	// TODO: implement host name lookup
990	return ToString(false);
991}
992
993
994BString
995BNetworkAddress::ServiceName() const
996{
997	// TODO: implement service lookup
998	BString portName;
999	portName << Port();
1000	return portName;
1001}
1002
1003
1004bool
1005BNetworkAddress::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
1043bool
1044BNetworkAddress::IsFixedSize() const
1045{
1046	return false;
1047}
1048
1049
1050type_code
1051BNetworkAddress::TypeCode() const
1052{
1053	return B_NETWORK_ADDRESS_TYPE;
1054}
1055
1056
1057ssize_t
1058BNetworkAddress::FlattenedSize() const
1059{
1060	return Length();
1061}
1062
1063
1064status_t
1065BNetworkAddress::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
1075status_t
1076BNetworkAddress::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
1097BNetworkAddress&
1098BNetworkAddress::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
1107bool
1108BNetworkAddress::operator==(const BNetworkAddress& other) const
1109{
1110	return Equals(other);
1111}
1112
1113
1114bool
1115BNetworkAddress::operator!=(const BNetworkAddress& other) const
1116{
1117	return !Equals(other);
1118}
1119
1120
1121bool
1122BNetworkAddress::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
1172BNetworkAddress::operator const sockaddr*() const
1173{
1174	return (const sockaddr*)&fAddress;
1175}
1176
1177
1178BNetworkAddress::operator const sockaddr&() const
1179{
1180	return (const sockaddr&)fAddress;
1181}
1182
1183
1184BNetworkAddress::operator sockaddr*()
1185{
1186	return (sockaddr*)&fAddress;
1187}
1188
1189
1190BNetworkAddress::operator const sockaddr*()
1191{
1192	return (sockaddr*)&fAddress;
1193}
1194
1195
1196BNetworkAddress::operator sockaddr&()
1197{
1198	return (sockaddr&)fAddress;
1199}
1200
1201
1202BNetworkAddress::operator const sockaddr&()
1203{
1204	return (sockaddr&)fAddress;
1205}
1206
1207
1208// #pragma mark - private
1209
1210
1211status_t
1212BNetworkAddress::_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