xref: /haiku/src/kits/network/libnetapi/NetworkAddress.cpp (revision e0ef64750f3169cd634bb2f7a001e22488b05231)
1 /*
2  * Copyright 2010, 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 <errno.h>
14 #include <netinet/in.h>
15 #include <stdio.h>
16 #include <sys/sockio.h>
17 
18 
19 BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags)
20 {
21 	SetTo(host, port, flags);
22 }
23 
24 
25 BNetworkAddress::BNetworkAddress(const char* host, const char* service,
26 	uint32 flags)
27 {
28 	SetTo(host, service, flags);
29 }
30 
31 
32 BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port,
33 	uint32 flags)
34 {
35 	SetTo(family, host, port, flags);
36 }
37 
38 
39 BNetworkAddress::BNetworkAddress(int family, const char* host,
40 	const char* service, uint32 flags)
41 {
42 	SetTo(family, host, service, flags);
43 }
44 
45 
46 BNetworkAddress::BNetworkAddress(const sockaddr& address)
47 {
48 	SetTo(address);
49 }
50 
51 
52 BNetworkAddress::BNetworkAddress(const sockaddr_storage& address)
53 {
54 	SetTo(address);
55 }
56 
57 
58 BNetworkAddress::BNetworkAddress(const sockaddr_in& address)
59 {
60 	SetTo(address);
61 }
62 
63 
64 BNetworkAddress::BNetworkAddress(const sockaddr_in6& address)
65 {
66 	SetTo(address);
67 }
68 
69 
70 BNetworkAddress::BNetworkAddress(const sockaddr_dl& address)
71 {
72 	SetTo(address);
73 }
74 
75 
76 BNetworkAddress::BNetworkAddress(const in_addr_t address)
77 {
78 	SetTo(address);
79 }
80 
81 
82 BNetworkAddress::BNetworkAddress(const in6_addr* address)
83 {
84 	SetTo(address);
85 }
86 
87 
88 BNetworkAddress::BNetworkAddress(const BNetworkAddress& other)
89 	:
90 	fAddress(other.fAddress),
91 	fStatus(other.fStatus)
92 {
93 }
94 
95 
96 BNetworkAddress::BNetworkAddress(BMessage* archive)
97 {
98 	// TODO: implement me
99 	fStatus = B_NO_INIT;
100 }
101 
102 
103 BNetworkAddress::BNetworkAddress()
104 {
105 	Unset();
106 }
107 
108 
109 BNetworkAddress::~BNetworkAddress()
110 {
111 }
112 
113 
114 status_t
115 BNetworkAddress::InitCheck() const
116 {
117 	return fStatus;
118 }
119 
120 
121 void
122 BNetworkAddress::Unset()
123 {
124 	fAddress.ss_family = AF_UNSPEC;
125 	fAddress.ss_len = 2;
126 	fStatus = B_OK;
127 }
128 
129 
130 status_t
131 BNetworkAddress::SetTo(const char* host, uint16 port, uint32 flags)
132 {
133 	BNetworkAddressResolver resolver;
134 	status_t status = resolver.SetTo(host, port, flags);
135 	if (status != B_OK)
136 		return status;
137 
138 	// Prefer IPv6 addresses
139 
140 	uint32 cookie = 0;
141 	status = resolver.GetNextAddress(AF_INET6, &cookie, *this);
142 	if (status == B_OK)
143 		return B_OK;
144 
145 	cookie = 0;
146 	return resolver.GetNextAddress(&cookie, *this);
147 }
148 
149 
150 status_t
151 BNetworkAddress::SetTo(const char* host, const char* service, uint32 flags)
152 {
153 	BNetworkAddressResolver resolver;
154 	status_t status = resolver.SetTo(host, service, flags);
155 	if (status != B_OK)
156 		return status;
157 
158 	// Prefer IPv6 addresses
159 
160 	uint32 cookie = 0;
161 	status = resolver.GetNextAddress(AF_INET6, &cookie, *this);
162 	if (status == B_OK)
163 		return B_OK;
164 
165 	cookie = 0;
166 	return resolver.GetNextAddress(&cookie, *this);
167 }
168 
169 
170 status_t
171 BNetworkAddress::SetTo(int family, const char* host, uint16 port, uint32 flags)
172 {
173 	BNetworkAddressResolver resolver;
174 	status_t status = resolver.SetTo(family, host, port, flags);
175 	if (status != B_OK)
176 		return status;
177 
178 	uint32 cookie = 0;
179 	return resolver.GetNextAddress(&cookie, *this);
180 }
181 
182 
183 status_t
184 BNetworkAddress::SetTo(int family, const char* host, const char* service,
185 	uint32 flags)
186 {
187 	BNetworkAddressResolver resolver;
188 	status_t status = resolver.SetTo(family, host, service, flags);
189 	if (status != B_OK)
190 		return status;
191 
192 	uint32 cookie = 0;
193 	return resolver.GetNextAddress(&cookie, *this);
194 }
195 
196 
197 void
198 BNetworkAddress::SetTo(const sockaddr& address)
199 {
200 	if (address.sa_family == AF_UNSPEC) {
201 		Unset();
202 		return;
203 	}
204 
205 	size_t length = min_c(sizeof(sockaddr_storage), address.sa_len);
206 	switch (address.sa_family) {
207 		case AF_INET:
208 			length = sizeof(sockaddr_in);
209 			break;
210 		case AF_INET6:
211 			length = sizeof(sockaddr_in6);
212 			break;
213 		case AF_LINK:
214 		{
215 			sockaddr_dl& link = (sockaddr_dl&)address;
216 			length = sizeof(sockaddr_dl) - sizeof(link.sdl_data) + link.sdl_alen
217 				+ link.sdl_nlen + link.sdl_slen;
218 			break;
219 		}
220 	}
221 
222 	SetTo(address, length);
223 }
224 
225 
226 void
227 BNetworkAddress::SetTo(const sockaddr& address, size_t length)
228 {
229 	if (address.sa_family == AF_UNSPEC || length == 0) {
230 		Unset();
231 		return;
232 	}
233 
234 	memcpy(&fAddress, &address, length);
235 	fAddress.ss_len = length;
236 	fStatus = B_OK;
237 }
238 
239 
240 void
241 BNetworkAddress::SetTo(const sockaddr_storage& address)
242 {
243 	SetTo((sockaddr&)address);
244 }
245 
246 
247 void
248 BNetworkAddress::SetTo(const sockaddr_in& address)
249 {
250 	SetTo((sockaddr&)address);
251 }
252 
253 
254 void
255 BNetworkAddress::SetTo(const sockaddr_in6& address)
256 {
257 	SetTo((sockaddr&)address);
258 }
259 
260 
261 void
262 BNetworkAddress::SetTo(const sockaddr_dl& address)
263 {
264 	SetTo((sockaddr&)address);
265 }
266 
267 
268 void
269 BNetworkAddress::SetTo(const in_addr_t inetAddress)
270 {
271 	sockaddr_in& address = (sockaddr_in&)fAddress;
272 	memset(&fAddress, 0, sizeof(sockaddr_storage));
273 
274 	address.sin_family = AF_INET;
275 	address.sin_len = sizeof(sockaddr_in);
276 	address.sin_addr.s_addr = inetAddress;
277 	fStatus = B_OK;
278 }
279 
280 
281 void
282 BNetworkAddress::SetTo(const in6_addr* inet6Address)
283 {
284 	sockaddr_in6& address = (sockaddr_in6&)fAddress;
285 	memset(&fAddress, 0, sizeof(sockaddr_storage));
286 
287 	address.sin6_family = AF_INET6;
288 	address.sin6_len = sizeof(sockaddr_in6);
289 	memcpy(address.sin6_addr.s6_addr, inet6Address,
290 		sizeof(address.sin6_addr.s6_addr));
291 	fStatus = B_OK;
292 }
293 
294 
295 void
296 BNetworkAddress::SetTo(const BNetworkAddress& other)
297 {
298 	fAddress = other.fAddress;
299 	fStatus = other.fStatus;
300 }
301 
302 
303 status_t
304 BNetworkAddress::SetToBroadcast(int family, uint16 port)
305 {
306 	if (family != AF_INET)
307 		return fStatus = B_NOT_SUPPORTED;
308 
309 	memset(&fAddress, 0, sizeof(sockaddr_storage));
310 	fAddress.ss_family = family;
311 	((sockaddr_in&)fAddress).sin_addr.s_addr = INADDR_BROADCAST;
312 
313 	SetPort(port);
314 	return fStatus = B_OK;
315 }
316 
317 
318 status_t
319 BNetworkAddress::SetToLocal()
320 {
321 	// TODO: choose a local address from the network interfaces
322 	return B_NOT_SUPPORTED;
323 }
324 
325 
326 status_t
327 BNetworkAddress::SetToLoopback()
328 {
329 	return SetTo("localhost");
330 }
331 
332 
333 status_t
334 BNetworkAddress::SetToMask(int family, uint32 prefixLength)
335 {
336 	switch (family) {
337 		case AF_INET:
338 		{
339 			if (prefixLength > 32)
340 				return B_BAD_VALUE;
341 
342 			sockaddr_in& mask = (sockaddr_in&)fAddress;
343 			memset(&fAddress, 0, sizeof(sockaddr_storage));
344 			mask.sin_family = AF_INET;
345 			mask.sin_len = sizeof(sockaddr_in);
346 
347 			uint32 hostMask = 0;
348 			for (uint8 i = 32; i > 32 - prefixLength; i--)
349 				hostMask |= 1 << (i - 1);
350 
351 			mask.sin_addr.s_addr = htonl(hostMask);
352 			break;
353 		}
354 
355 		case AF_INET6:
356 		{
357 			if (prefixLength > 128)
358 				return B_BAD_VALUE;
359 
360 			sockaddr_in6& mask = (sockaddr_in6&)fAddress;
361 			memset(&fAddress, 0, sizeof(sockaddr_storage));
362 			mask.sin6_family = AF_INET6;
363 			mask.sin6_len = sizeof(sockaddr_in6);
364 
365 			for (uint8 i = 0; i < sizeof(in6_addr); i++, prefixLength -= 8) {
366 				if (prefixLength < 8) {
367 					mask.sin6_addr.s6_addr[i]
368 						= (uint8)(0xff << (8 - prefixLength));
369 					break;
370 				}
371 
372 				mask.sin6_addr.s6_addr[i] = 0xff;
373 			}
374 			break;
375 		}
376 
377 		default:
378 			return B_NOT_SUPPORTED;
379 	}
380 
381 	return B_OK;
382 }
383 
384 
385 status_t
386 BNetworkAddress::SetToWildcard(int family)
387 {
388 	return SetTo(family, NULL);
389 }
390 
391 
392 void
393 BNetworkAddress::SetPort(uint16 port)
394 {
395 	switch (fAddress.ss_family) {
396 		case AF_INET:
397 			((sockaddr_in&)fAddress).sin_port = htons(port);
398 			break;
399 
400 		case AF_INET6:
401 			((sockaddr_in6&)fAddress).sin6_port = htons(port);
402 			break;
403 
404 		default:
405 			break;
406 	}
407 }
408 
409 
410 void
411 BNetworkAddress::SetToLinkLevel(uint8* address, size_t length)
412 {
413 	// TODO: implement me!
414 }
415 
416 
417 void
418 BNetworkAddress::SetToLinkLevel(const char* name)
419 {
420 	// TODO: implement me!
421 }
422 
423 
424 void
425 BNetworkAddress::SetToLinkLevel(uint32 index)
426 {
427 	// TODO: implement me!
428 }
429 
430 
431 void
432 BNetworkAddress::SetLinkLevelIndex(uint32 index)
433 {
434 	// TODO: implement me!
435 }
436 
437 
438 void
439 BNetworkAddress::SetLinkLevelType(uint32 type)
440 {
441 	// TODO: implement me!
442 }
443 
444 
445 void
446 BNetworkAddress::SetLinkLevelFrameType(uint32 frameType)
447 {
448 	// TODO: implement me!
449 }
450 
451 
452 int
453 BNetworkAddress::Family() const
454 {
455 	return fAddress.ss_family;
456 }
457 
458 
459 uint16
460 BNetworkAddress::Port() const
461 {
462 	switch (fAddress.ss_family) {
463 		case AF_INET:
464 			return ntohs(((sockaddr_in&)fAddress).sin_port);
465 
466 		case AF_INET6:
467 			return ntohs(((sockaddr_in6&)fAddress).sin6_port);
468 
469 		default:
470 			return 0;
471 	}
472 }
473 
474 
475 size_t
476 BNetworkAddress::Length() const
477 {
478 	return fAddress.ss_len;
479 }
480 
481 
482 const sockaddr&
483 BNetworkAddress::SockAddr() const
484 {
485 	return (const sockaddr&)fAddress;
486 }
487 
488 
489 bool
490 BNetworkAddress::IsEmpty() const
491 {
492 	return fAddress.ss_len == 0 || fAddress.ss_family == AF_UNSPEC;
493 }
494 
495 
496 bool
497 BNetworkAddress::IsWildcard() const
498 {
499 	switch (fAddress.ss_family) {
500 		case AF_INET:
501 			return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_ANY;
502 
503 		case AF_INET6:
504 			return !memcmp(&((sockaddr_in6&)fAddress).sin6_addr, &in6addr_any,
505 				sizeof(in6_addr));
506 
507 		default:
508 			return false;
509 	}
510 }
511 
512 
513 bool
514 BNetworkAddress::IsBroadcast() const
515 {
516 	switch (fAddress.ss_family) {
517 		case AF_INET:
518 			return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_BROADCAST;
519 
520 		case AF_INET6:
521 			// There is no broadcast in IPv6, only multicast/anycast
522 			return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
523 
524 		default:
525 			return false;
526 	}
527 }
528 
529 
530 bool
531 BNetworkAddress::IsMulticast() const
532 {
533 	switch (fAddress.ss_family) {
534 		case AF_INET:
535 			return IN_MULTICAST(((sockaddr_in&)fAddress).sin_addr.s_addr);
536 
537 		case AF_INET6:
538 			return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
539 
540 		default:
541 			return false;
542 	}
543 }
544 
545 
546 bool
547 BNetworkAddress::IsMulticastGlobal() const
548 {
549 	switch (fAddress.ss_family) {
550 		case AF_INET6:
551 			return IN6_IS_ADDR_MC_GLOBAL(&((sockaddr_in6&)fAddress).sin6_addr);
552 
553 		default:
554 			return false;
555 	}
556 }
557 
558 
559 bool
560 BNetworkAddress::IsMulticastNodeLocal() const
561 {
562 	switch (fAddress.ss_family) {
563 		case AF_INET6:
564 			return IN6_IS_ADDR_MC_NODELOCAL(
565 				&((sockaddr_in6&)fAddress).sin6_addr);
566 
567 		default:
568 			return false;
569 	}
570 }
571 
572 
573 bool
574 BNetworkAddress::IsMulticastLinkLocal() const
575 {
576 	switch (fAddress.ss_family) {
577 		case AF_INET6:
578 			return IN6_IS_ADDR_MC_LINKLOCAL(
579 				&((sockaddr_in6&)fAddress).sin6_addr);
580 
581 		default:
582 			return false;
583 	}
584 }
585 
586 
587 bool
588 BNetworkAddress::IsMulticastSiteLocal() const
589 {
590 	switch (fAddress.ss_family) {
591 		case AF_INET6:
592 			return IN6_IS_ADDR_MC_SITELOCAL(
593 				&((sockaddr_in6&)fAddress).sin6_addr);
594 
595 		default:
596 			return false;
597 	}
598 }
599 
600 
601 bool
602 BNetworkAddress::IsMulticastOrgLocal() const
603 {
604 	switch (fAddress.ss_family) {
605 		case AF_INET6:
606 			return IN6_IS_ADDR_MC_ORGLOCAL(
607 				&((sockaddr_in6&)fAddress).sin6_addr);
608 
609 		default:
610 			return false;
611 	}
612 }
613 
614 
615 bool
616 BNetworkAddress::IsLinkLocal() const
617 {
618 	// TODO: ipv4
619 	switch (fAddress.ss_family) {
620 		case AF_INET6:
621 			return IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
622 
623 		default:
624 			return false;
625 	}
626 }
627 
628 
629 bool
630 BNetworkAddress::IsSiteLocal() const
631 {
632 	switch (fAddress.ss_family) {
633 		case AF_INET6:
634 			return IN6_IS_ADDR_SITELOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
635 
636 		default:
637 			return false;
638 	}
639 }
640 
641 
642 bool
643 BNetworkAddress::IsLocal() const
644 {
645 	BNetworkRoster& roster = BNetworkRoster::Default();
646 
647 	BNetworkInterface interface;
648 	uint32 cookie = 0;
649 
650 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
651 		int32 count = interface.CountAddresses();
652 		for (int32 j = 0; j < count; j++) {
653 			BNetworkInterfaceAddress address;
654 			if (interface.GetAddressAt(j, address) != B_OK)
655 				break;
656 
657 			if (Equals(address.Address(), false))
658 				return true;
659 		}
660 	}
661 
662 	return false;
663 }
664 
665 
666 ssize_t
667 BNetworkAddress::PrefixLength() const
668 {
669 	switch (fAddress.ss_family) {
670 		case AF_INET:
671 		{
672 			sockaddr_in& mask = (sockaddr_in&)fAddress;
673 
674 			ssize_t result = 0;
675 			uint32 hostMask = ntohl(mask.sin_addr.s_addr);
676 			for (uint8 i = 32; i > 0; i--) {
677 				if ((hostMask & (1 << (i - 1))) == 0)
678 					break;
679 				result++;
680 			}
681 
682 			return result;
683 		}
684 
685 		case AF_INET6:
686 		{
687 			sockaddr_in6& mask = (sockaddr_in6&)fAddress;
688 
689 			ssize_t result = 0;
690 			for (uint8 i = 0; i < sizeof(in6_addr); i++) {
691 				for (uint8 j = 0; j < 8; j++) {
692 					if (!(mask.sin6_addr.s6_addr[i] & (1 << j)))
693 						return result;
694 					result++;
695 				}
696 			}
697 
698 			return 128;
699 		}
700 
701 		default:
702 			return B_NOT_SUPPORTED;
703 	}
704 }
705 
706 
707 uint32
708 BNetworkAddress::LinkLevelIndex() const
709 {
710 	return ((sockaddr_dl&)fAddress).sdl_index;
711 }
712 
713 
714 BString
715 BNetworkAddress::LinkLevelInterface() const
716 {
717 	sockaddr_dl& address = (sockaddr_dl&)fAddress;
718 	if (address.sdl_nlen == 0)
719 		return "";
720 
721 	BString name;
722 	name.SetTo((const char*)address.sdl_data, address.sdl_nlen);
723 
724 	return name;
725 }
726 
727 
728 uint32
729 BNetworkAddress::LinkLevelType() const
730 {
731 	return ((sockaddr_dl&)fAddress).sdl_type;
732 }
733 
734 
735 uint32
736 BNetworkAddress::LinkLevelFrameType() const
737 {
738 	return ((sockaddr_dl&)fAddress).sdl_e_type;
739 }
740 
741 
742 uint8*
743 BNetworkAddress::LinkLevelAddress() const
744 {
745 	return LLADDR(&(sockaddr_dl&)fAddress);
746 }
747 
748 
749 size_t
750 BNetworkAddress::LinkLevelAddressLength() const
751 {
752 	return ((sockaddr_dl&)fAddress).sdl_alen;
753 }
754 
755 
756 status_t
757 BNetworkAddress::ResolveForDestination(const BNetworkAddress& destination)
758 {
759 	if (!IsWildcard())
760 		return B_OK;
761 	if (destination.fAddress.ss_family != fAddress.ss_family)
762 		return B_BAD_VALUE;
763 
764 	char buffer[2048];
765 	memset(buffer, 0, sizeof(buffer));
766 
767 	route_entry* route = (route_entry*)buffer;
768 	route->destination = (sockaddr*)&destination.fAddress;
769 
770 	int socket = ::socket(fAddress.ss_family, SOCK_DGRAM, 0);
771 	if (socket < 0)
772 		return errno;
773 
774 	if (ioctl(socket, SIOCGETRT, route, sizeof(buffer)) != 0) {
775 		close(socket);
776 		return errno;
777 	}
778 
779 	uint16 port = Port();
780 	memcpy(&fAddress, route->source, sizeof(sockaddr_storage));
781 	SetPort(port);
782 
783 	return B_OK;
784 }
785 
786 
787 status_t
788 BNetworkAddress::ResolveTo(const BNetworkAddress& address)
789 {
790 	if (!IsWildcard())
791 		return B_OK;
792 	if (address.fAddress.ss_family != fAddress.ss_family)
793 		return B_BAD_VALUE;
794 
795 	uint16 port = Port();
796 	*this = address;
797 	SetPort(port);
798 
799 	return B_OK;
800 }
801 
802 
803 BString
804 BNetworkAddress::ToString(bool includePort) const
805 {
806 	char buffer[512];
807 
808 	switch (fAddress.ss_family) {
809 		case AF_INET:
810 			inet_ntop(AF_INET, &((sockaddr_in&)fAddress).sin_addr, buffer,
811 				sizeof(buffer));
812 			break;
813 
814 		case AF_INET6:
815 			inet_ntop(AF_INET6, &((sockaddr_in6&)fAddress).sin6_addr,
816 				buffer, sizeof(buffer));
817 			break;
818 
819 		case AF_LINK:
820 		{
821 			uint8 *byte = LinkLevelAddress();
822 			char* target = buffer;
823 			int bytesLeft = sizeof(buffer);
824 			target[0] = '\0';
825 
826 			for (size_t i = 0; i < LinkLevelAddressLength(); i++) {
827 				if (i != 0 && bytesLeft > 1) {
828 					target[0] = ':';
829 					target[1] = '\0';
830 					target++;
831 					bytesLeft--;
832 				}
833 
834 				int bytesWritten = snprintf(target, bytesLeft, "%02x", byte[i]);
835 				if (bytesWritten >= bytesLeft)
836 					break;
837 
838 				target += bytesWritten;
839 				bytesLeft -= bytesWritten;
840 			}
841 			break;
842 		}
843 
844 		default:
845 			return "";
846 	}
847 
848 	BString address = buffer;
849 	if (includePort && Port() != 0) {
850 		if (fAddress.ss_family == AF_INET6) {
851 			address = "[";
852 			address += buffer;
853 			address += "]";
854 		}
855 
856 		snprintf(buffer, sizeof(buffer), ":%u", Port());
857 		address += buffer;
858 	}
859 
860 	return address;
861 }
862 
863 
864 BString
865 BNetworkAddress::HostName() const
866 {
867 	// TODO: implement host name lookup
868 	return ToString(false);
869 }
870 
871 
872 BString
873 BNetworkAddress::ServiceName() const
874 {
875 	// TODO: implement service lookup
876 	BString portName;
877 	portName << Port();
878 	return portName;
879 }
880 
881 
882 status_t
883 BNetworkAddress::Archive(BMessage* into, bool deep) const
884 {
885 	// TODO: implement me!
886 	return B_ERROR;
887 }
888 
889 
890 /*static*/ BArchivable*
891 BNetworkAddress::Instantiate(BMessage* archive)
892 {
893 	if (archive != NULL)
894 		return new BNetworkAddress(archive);
895 
896 	return NULL;
897 }
898 
899 
900 bool
901 BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const
902 {
903 	if (IsEmpty() && other.IsEmpty())
904 		return true;
905 
906 	if (Family() != other.Family()
907 		|| (includePort && Port() != other.Port()))
908 		return false;
909 
910 	switch (fAddress.ss_family) {
911 		case AF_INET:
912 		{
913 			sockaddr_in& address = (sockaddr_in&)fAddress;
914 			sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress;
915 			return memcmp(&address.sin_addr, &otherAddress.sin_addr,
916 				sizeof(address.sin_addr)) == 0;
917 		}
918 
919 		case AF_INET6:
920 		{
921 			sockaddr_in6& address = (sockaddr_in6&)fAddress;
922 			sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress;
923 			return memcmp(&address.sin6_addr, &otherAddress.sin6_addr,
924 				sizeof(address.sin6_addr)) == 0;
925 		}
926 
927 		default:
928 			if (fAddress.ss_len != other.fAddress.ss_len)
929 				return false;
930 
931 			return memcmp(&fAddress, &other.fAddress, fAddress.ss_len);
932 	}
933 }
934 
935 
936 BNetworkAddress&
937 BNetworkAddress::operator=(const BNetworkAddress& other)
938 {
939 	memcpy(&fAddress, &other.fAddress, other.fAddress.ss_len);
940 	fStatus = other.fStatus;
941 
942 	return *this;
943 }
944 
945 
946 bool
947 BNetworkAddress::operator==(const BNetworkAddress& other) const
948 {
949 	return Equals(other);
950 }
951 
952 
953 bool
954 BNetworkAddress::operator!=(const BNetworkAddress& other) const
955 {
956 	return !Equals(other);
957 }
958 
959 
960 bool
961 BNetworkAddress::operator<(const BNetworkAddress& other) const
962 {
963 	if (Family() < other.Family())
964 		return true;
965 	if (Family() > other.Family())
966 		return false;
967 
968 	int compare;
969 
970 	switch (fAddress.ss_family) {
971 		default:
972 		case AF_INET:
973 		{
974 			sockaddr_in& address = (sockaddr_in&)fAddress;
975 			sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress;
976 			compare = memcmp(&address.sin_addr, &otherAddress.sin_addr,
977 				sizeof(address.sin_addr));
978 			break;
979 		}
980 
981 		case AF_INET6:
982 		{
983 			sockaddr_in6& address = (sockaddr_in6&)fAddress;
984 			sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress;
985 			compare = memcmp(&address.sin6_addr, &otherAddress.sin6_addr,
986 				sizeof(address.sin6_addr));
987 			break;
988 		}
989 	}
990 
991 	if (compare < 0)
992 		return true;
993 	if (compare > 0)
994 		return false;
995 
996 	return Port() < other.Port();
997 }
998 
999 
1000 BNetworkAddress::operator const sockaddr*() const
1001 {
1002 	return (const sockaddr*)&fAddress;
1003 }
1004 
1005 
1006 BNetworkAddress::operator const sockaddr&() const
1007 {
1008 	return (const sockaddr&)fAddress;
1009 }
1010