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
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	fStatus = SetTo(host, port, flags);
63}
64
65
66BNetworkAddress::BNetworkAddress(const char* host, const char* service,
67	uint32 flags)
68{
69	fStatus = SetTo(host, service, flags);
70}
71
72
73BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port,
74	uint32 flags)
75{
76	fStatus = SetTo(family, host, port, flags);
77}
78
79
80BNetworkAddress::BNetworkAddress(int family, const char* host,
81	const char* service, uint32 flags)
82{
83	fStatus = 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	fHostName(other.fHostName)
134{
135}
136
137
138BNetworkAddress::~BNetworkAddress()
139{
140}
141
142
143status_t
144BNetworkAddress::InitCheck() const
145{
146	return fStatus;
147}
148
149
150void
151BNetworkAddress::Unset()
152{
153	fAddress.ss_family = AF_UNSPEC;
154	fAddress.ss_len = 2;
155	fHostName = "";
156	fStatus = B_OK;
157}
158
159
160status_t
161BNetworkAddress::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
187status_t
188BNetworkAddress::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
214status_t
215BNetworkAddress::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
242status_t
243BNetworkAddress::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
271void
272BNetworkAddress::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
300void
301BNetworkAddress::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
314void
315BNetworkAddress::SetTo(const sockaddr_storage& address)
316{
317	SetTo((sockaddr&)address);
318}
319
320
321void
322BNetworkAddress::SetTo(const sockaddr_in& address)
323{
324	SetTo((sockaddr&)address);
325}
326
327
328void
329BNetworkAddress::SetTo(const sockaddr_in6& address)
330{
331	SetTo((sockaddr&)address);
332}
333
334
335void
336BNetworkAddress::SetTo(const sockaddr_dl& address)
337{
338	SetTo((sockaddr&)address);
339}
340
341
342void
343BNetworkAddress::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
356void
357BNetworkAddress::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
370void
371BNetworkAddress::SetTo(const BNetworkAddress& other)
372{
373	fAddress = other.fAddress;
374	fStatus = other.fStatus;
375	fHostName = other.fHostName;
376}
377
378
379status_t
380BNetworkAddress::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
390status_t
391BNetworkAddress::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
398status_t
399BNetworkAddress::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
420status_t
421BNetworkAddress::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
472status_t
473BNetworkAddress::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
492status_t
493BNetworkAddress::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
504status_t
505BNetworkAddress::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
517void
518BNetworkAddress::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
535void
536BNetworkAddress::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
553void
554BNetworkAddress::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
576void
577BNetworkAddress::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
590void
591BNetworkAddress::SetLinkLevelIndex(uint32 index)
592{
593	sockaddr_dl& link = (sockaddr_dl&)fAddress;
594	link.sdl_index = index;
595}
596
597
598void
599BNetworkAddress::SetLinkLevelType(uint8 type)
600{
601	sockaddr_dl& link = (sockaddr_dl&)fAddress;
602	link.sdl_type = type;
603}
604
605
606void
607BNetworkAddress::SetLinkLevelFrameType(uint16 frameType)
608{
609	sockaddr_dl& link = (sockaddr_dl&)fAddress;
610	link.sdl_e_type = htons(frameType);
611}
612
613
614int
615BNetworkAddress::Family() const
616{
617	return fAddress.ss_family;
618}
619
620
621uint16
622BNetworkAddress::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
637size_t
638BNetworkAddress::Length() const
639{
640	return fAddress.ss_len;
641}
642
643
644const sockaddr&
645BNetworkAddress::SockAddr() const
646{
647	return (const sockaddr&)fAddress;
648}
649
650
651sockaddr&
652BNetworkAddress::SockAddr()
653{
654	return (sockaddr&)fAddress;
655}
656
657
658bool
659BNetworkAddress::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
685bool
686BNetworkAddress::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
702bool
703BNetworkAddress::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
719bool
720BNetworkAddress::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
735bool
736BNetworkAddress::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
748bool
749BNetworkAddress::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
762bool
763BNetworkAddress::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
776bool
777BNetworkAddress::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
790bool
791BNetworkAddress::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
804bool
805BNetworkAddress::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
818bool
819BNetworkAddress::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
831bool
832BNetworkAddress::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
855ssize_t
856BNetworkAddress::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
890uint32
891BNetworkAddress::LinkLevelIndex() const
892{
893	return ((sockaddr_dl&)fAddress).sdl_index;
894}
895
896
897BString
898BNetworkAddress::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
911uint8
912BNetworkAddress::LinkLevelType() const
913{
914	return ((sockaddr_dl&)fAddress).sdl_type;
915}
916
917
918uint16
919BNetworkAddress::LinkLevelFrameType() const
920{
921	return ntohs(((sockaddr_dl&)fAddress).sdl_e_type);
922}
923
924
925uint8*
926BNetworkAddress::LinkLevelAddress() const
927{
928	return LLADDR(&(sockaddr_dl&)fAddress);
929}
930
931
932size_t
933BNetworkAddress::LinkLevelAddressLength() const
934{
935	return ((sockaddr_dl&)fAddress).sdl_alen;
936}
937
938
939status_t
940BNetworkAddress::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	close(socket);
967	return B_OK;
968}
969
970
971status_t
972BNetworkAddress::ResolveTo(const BNetworkAddress& address)
973{
974	if (!IsWildcard())
975		return B_OK;
976	if (address.fAddress.ss_family != fAddress.ss_family)
977		return B_BAD_VALUE;
978
979	uint16 port = Port();
980	*this = address;
981	SetPort(port);
982
983	return B_OK;
984}
985
986
987BString
988BNetworkAddress::ToString(bool includePort) const
989{
990	char buffer[512];
991
992	switch (fAddress.ss_family) {
993		case AF_INET:
994			inet_ntop(AF_INET, &((sockaddr_in&)fAddress).sin_addr, buffer,
995				sizeof(buffer));
996			break;
997
998		case AF_INET6:
999			inet_ntop(AF_INET6, &((sockaddr_in6&)fAddress).sin6_addr,
1000				buffer, sizeof(buffer));
1001			break;
1002
1003		case AF_LINK:
1004		{
1005			uint8 *byte = LinkLevelAddress();
1006			char* target = buffer;
1007			int bytesLeft = sizeof(buffer);
1008			target[0] = '\0';
1009
1010			for (size_t i = 0; i < LinkLevelAddressLength(); i++) {
1011				if (i != 0 && bytesLeft > 1) {
1012					target[0] = ':';
1013					target[1] = '\0';
1014					target++;
1015					bytesLeft--;
1016				}
1017
1018				int bytesWritten = snprintf(target, bytesLeft, "%02x", byte[i]);
1019				if (bytesWritten >= bytesLeft)
1020					break;
1021
1022				target += bytesWritten;
1023				bytesLeft -= bytesWritten;
1024			}
1025			break;
1026		}
1027
1028		default:
1029			return "";
1030	}
1031
1032	BString address = buffer;
1033	if (includePort && Port() != 0) {
1034		if (fAddress.ss_family == AF_INET6) {
1035			address = "[";
1036			address += buffer;
1037			address += "]";
1038		}
1039
1040		snprintf(buffer, sizeof(buffer), ":%u", Port());
1041		address += buffer;
1042	}
1043
1044	return address;
1045}
1046
1047
1048BString
1049BNetworkAddress::HostName() const
1050{
1051	// TODO: implement host name lookup
1052	return fHostName;
1053}
1054
1055
1056BString
1057BNetworkAddress::ServiceName() const
1058{
1059	// TODO: implement service lookup
1060	BString portName;
1061	portName << Port();
1062	return portName;
1063}
1064
1065
1066bool
1067BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const
1068{
1069	if (IsEmpty() && other.IsEmpty())
1070		return true;
1071
1072	if (Family() != other.Family()
1073			|| (includePort && Port() != other.Port())) {
1074		return false;
1075	}
1076
1077	switch (fAddress.ss_family) {
1078		case AF_INET:
1079		{
1080			sockaddr_in& address = (sockaddr_in&)fAddress;
1081			sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress;
1082			return memcmp(&address.sin_addr, &otherAddress.sin_addr,
1083				sizeof(address.sin_addr)) == 0;
1084		}
1085
1086		case AF_INET6:
1087		{
1088			sockaddr_in6& address = (sockaddr_in6&)fAddress;
1089			sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress;
1090			return memcmp(&address.sin6_addr, &otherAddress.sin6_addr,
1091				sizeof(address.sin6_addr)) == 0;
1092		}
1093
1094		default:
1095			if (fAddress.ss_len != other.fAddress.ss_len)
1096				return false;
1097
1098			return memcmp(&fAddress, &other.fAddress, fAddress.ss_len);
1099	}
1100}
1101
1102
1103// #pragma mark - BFlattenable implementation
1104
1105
1106bool
1107BNetworkAddress::IsFixedSize() const
1108{
1109	return false;
1110}
1111
1112
1113type_code
1114BNetworkAddress::TypeCode() const
1115{
1116	return B_NETWORK_ADDRESS_TYPE;
1117}
1118
1119
1120ssize_t
1121BNetworkAddress::FlattenedSize() const
1122{
1123	return Length();
1124}
1125
1126
1127status_t
1128BNetworkAddress::Flatten(void* buffer, ssize_t size) const
1129{
1130	if (buffer == NULL || size < FlattenedSize())
1131		return B_BAD_VALUE;
1132
1133	memcpy(buffer, &fAddress, Length());
1134	return B_OK;
1135}
1136
1137
1138status_t
1139BNetworkAddress::Unflatten(type_code code, const void* buffer, ssize_t size)
1140{
1141	// 2 bytes minimum for family, and length
1142	if (buffer == NULL || size < 2)
1143		return fStatus = B_BAD_VALUE;
1144	if (!AllowsTypeCode(code))
1145		return fStatus = B_BAD_TYPE;
1146
1147	memcpy(&fAddress, buffer, min_c(size, (ssize_t)sizeof(fAddress)));
1148
1149	// check if this can contain a valid address
1150	if (fAddress.ss_family != AF_UNSPEC && size < (ssize_t)sizeof(sockaddr))
1151		return fStatus = B_BAD_VALUE;
1152
1153	return fStatus = B_OK;
1154}
1155
1156
1157// #pragma mark - operators
1158
1159
1160BNetworkAddress&
1161BNetworkAddress::operator=(const BNetworkAddress& other)
1162{
1163	memcpy(&fAddress, &other.fAddress, other.fAddress.ss_len);
1164	fHostName = other.fHostName;
1165	fStatus = other.fStatus;
1166
1167	return *this;
1168}
1169
1170
1171bool
1172BNetworkAddress::operator==(const BNetworkAddress& other) const
1173{
1174	return Equals(other);
1175}
1176
1177
1178bool
1179BNetworkAddress::operator!=(const BNetworkAddress& other) const
1180{
1181	return !Equals(other);
1182}
1183
1184
1185bool
1186BNetworkAddress::operator<(const BNetworkAddress& other) const
1187{
1188	if (Family() < other.Family())
1189		return true;
1190	if (Family() > other.Family())
1191		return false;
1192
1193	int compare;
1194
1195	switch (fAddress.ss_family) {
1196		default:
1197		case AF_INET:
1198		{
1199			sockaddr_in& address = (sockaddr_in&)fAddress;
1200			sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress;
1201			compare = memcmp(&address.sin_addr, &otherAddress.sin_addr,
1202				sizeof(address.sin_addr));
1203			break;
1204		}
1205
1206		case AF_INET6:
1207		{
1208			sockaddr_in6& address = (sockaddr_in6&)fAddress;
1209			sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress;
1210			compare = memcmp(&address.sin6_addr, &otherAddress.sin6_addr,
1211				sizeof(address.sin6_addr));
1212			break;
1213		}
1214
1215		case AF_LINK:
1216			if (LinkLevelAddressLength() < other.LinkLevelAddressLength())
1217				return true;
1218			if (LinkLevelAddressLength() > other.LinkLevelAddressLength())
1219				return true;
1220
1221			// TODO: could compare index, and name, too
1222			compare = memcmp(LinkLevelAddress(), other.LinkLevelAddress(),
1223				LinkLevelAddressLength());
1224			break;
1225	}
1226
1227	if (compare < 0)
1228		return true;
1229	if (compare > 0)
1230		return false;
1231
1232	return Port() < other.Port();
1233}
1234
1235
1236BNetworkAddress::operator const sockaddr*() const
1237{
1238	return (const sockaddr*)&fAddress;
1239}
1240
1241
1242BNetworkAddress::operator const sockaddr&() const
1243{
1244	return (const sockaddr&)fAddress;
1245}
1246
1247
1248BNetworkAddress::operator sockaddr*()
1249{
1250	return (sockaddr*)&fAddress;
1251}
1252
1253
1254BNetworkAddress::operator const sockaddr*()
1255{
1256	return (sockaddr*)&fAddress;
1257}
1258
1259
1260BNetworkAddress::operator sockaddr&()
1261{
1262	return (sockaddr&)fAddress;
1263}
1264
1265
1266BNetworkAddress::operator const sockaddr&()
1267{
1268	return (sockaddr&)fAddress;
1269}
1270
1271
1272// #pragma mark - private
1273
1274
1275status_t
1276BNetworkAddress::_ParseLinkAddress(const char* address)
1277{
1278	if (address == NULL)
1279		return B_BAD_VALUE;
1280
1281	uint8 linkAddress[128];
1282	uint32 length = 0;
1283	while (length < sizeof(linkAddress)) {
1284		if (!isxdigit(address[0]) || !isxdigit(address[1]))
1285			return B_BAD_VALUE;
1286
1287		linkAddress[length++] = (from_hex(address[0]) << 4)
1288			| from_hex(address[1]);
1289
1290		if (address[2] == '\0')
1291			break;
1292		if (address[2] != ':')
1293			return B_BAD_VALUE;
1294
1295		address += 3;
1296	}
1297
1298	fHostName = address;
1299
1300	SetToLinkLevel(linkAddress, length);
1301	return B_OK;
1302}
1303