1 /*
2 * Copyright 2010-2015, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include <NetworkAddress.h>
8
9 #include <NetworkInterface.h>
10 #include <NetworkRoster.h>
11
12 #include <arpa/inet.h>
13 #include <ctype.h>
14 #include <errno.h>
15 #include <netinet/in.h>
16 #include <stdio.h>
17 #include <sys/sockio.h>
18
19
20 /* The GCC builtin below only exists in > GCC 3.4
21 * Benefits include faster execution time as the builtin
22 * uses a bitcounting cpu instruction if it exists
23 */
24 #if __GNUC__ > 3
25 # define addr_bitcount(bitfield) __builtin_popcount(bitfield)
26 #else
27 static ssize_t
addr_bitcount(uint32 bitfield)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
from_hex(char hex)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
BNetworkAddress()54 BNetworkAddress::BNetworkAddress()
55 {
56 Unset();
57 }
58
59
BNetworkAddress(const char * host,uint16 port,uint32 flags)60 BNetworkAddress::BNetworkAddress(const char* host, uint16 port, uint32 flags)
61 {
62 fStatus = SetTo(host, port, flags);
63 }
64
65
BNetworkAddress(const char * host,const char * service,uint32 flags)66 BNetworkAddress::BNetworkAddress(const char* host, const char* service,
67 uint32 flags)
68 {
69 fStatus = SetTo(host, service, flags);
70 }
71
72
BNetworkAddress(int family,const char * host,uint16 port,uint32 flags)73 BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port,
74 uint32 flags)
75 {
76 fStatus = SetTo(family, host, port, flags);
77 }
78
79
BNetworkAddress(int family,const char * host,const char * service,uint32 flags)80 BNetworkAddress::BNetworkAddress(int family, const char* host,
81 const char* service, uint32 flags)
82 {
83 fStatus = SetTo(family, host, service, flags);
84 }
85
86
BNetworkAddress(const sockaddr & address)87 BNetworkAddress::BNetworkAddress(const sockaddr& address)
88 {
89 SetTo(address);
90 }
91
92
BNetworkAddress(const sockaddr_storage & address)93 BNetworkAddress::BNetworkAddress(const sockaddr_storage& address)
94 {
95 SetTo(address);
96 }
97
98
BNetworkAddress(const sockaddr_in & address)99 BNetworkAddress::BNetworkAddress(const sockaddr_in& address)
100 {
101 SetTo(address);
102 }
103
104
BNetworkAddress(const sockaddr_in6 & address)105 BNetworkAddress::BNetworkAddress(const sockaddr_in6& address)
106 {
107 SetTo(address);
108 }
109
110
BNetworkAddress(const sockaddr_dl & address)111 BNetworkAddress::BNetworkAddress(const sockaddr_dl& address)
112 {
113 SetTo(address);
114 }
115
116
BNetworkAddress(in_addr_t address,uint16 port)117 BNetworkAddress::BNetworkAddress(in_addr_t address, uint16 port)
118 {
119 SetTo(address, port);
120 }
121
122
BNetworkAddress(const in6_addr & address,uint16 port)123 BNetworkAddress::BNetworkAddress(const in6_addr& address, uint16 port)
124 {
125 SetTo(address, port);
126 }
127
128
BNetworkAddress(const BNetworkAddress & other)129 BNetworkAddress::BNetworkAddress(const BNetworkAddress& other)
130 :
131 fAddress(other.fAddress),
132 fStatus(other.fStatus),
133 fHostName(other.fHostName)
134 {
135 }
136
137
~BNetworkAddress()138 BNetworkAddress::~BNetworkAddress()
139 {
140 }
141
142
143 status_t
InitCheck() const144 BNetworkAddress::InitCheck() const
145 {
146 return fStatus;
147 }
148
149
150 void
Unset()151 BNetworkAddress::Unset()
152 {
153 fAddress.ss_family = AF_UNSPEC;
154 fAddress.ss_len = 2;
155 fHostName = "";
156 fStatus = B_OK;
157 }
158
159
160 status_t
SetTo(const char * host,uint16 port,uint32 flags)161 BNetworkAddress::SetTo(const char* host, uint16 port, uint32 flags)
162 {
163 BReference<const BNetworkAddressResolver> resolver
164 = BNetworkAddressResolver::Resolve(host, port, flags);
165 if (!resolver.IsSet())
166 return B_NO_MEMORY;
167 status_t status = resolver->InitCheck();
168 if (status != B_OK)
169 return status;
170
171 // Prefer IPv6 addresses
172
173 uint32 cookie = 0;
174 status = resolver->GetNextAddress(AF_INET6, &cookie, *this);
175 if (status != B_OK) {
176 cookie = 0;
177 status = resolver->GetNextAddress(&cookie, *this);
178 if (status != B_OK)
179 Unset();
180 }
181 fHostName = host;
182 fStatus = status;
183 return status;
184 }
185
186
187 status_t
SetTo(const char * host,const char * service,uint32 flags)188 BNetworkAddress::SetTo(const char* host, const char* service, uint32 flags)
189 {
190 BReference<const BNetworkAddressResolver> resolver
191 = BNetworkAddressResolver::Resolve(host, service, flags);
192 if (!resolver.IsSet())
193 return B_NO_MEMORY;
194 status_t status = resolver->InitCheck();
195 if (status != B_OK)
196 return status;
197
198 // Prefer IPv6 addresses
199
200 uint32 cookie = 0;
201 status = resolver->GetNextAddress(AF_INET6, &cookie, *this);
202 if (status != B_OK) {
203 cookie = 0;
204 status = resolver->GetNextAddress(&cookie, *this);
205 if (status != B_OK)
206 Unset();
207 }
208 fHostName = host;
209 fStatus = status;
210 return status;
211 }
212
213
214 status_t
SetTo(int family,const char * host,uint16 port,uint32 flags)215 BNetworkAddress::SetTo(int family, const char* host, uint16 port, uint32 flags)
216 {
217 if (family == AF_LINK) {
218 if (port != 0)
219 return B_BAD_VALUE;
220 return _ParseLinkAddress(host);
221 // SetToLinkAddress takes care of setting fStatus
222 }
223
224 BReference<const BNetworkAddressResolver> resolver
225 = BNetworkAddressResolver::Resolve(family, host, port, flags);
226 if (!resolver.IsSet())
227 return B_NO_MEMORY;
228 status_t status = resolver->InitCheck();
229 if (status != B_OK)
230 return status;
231
232 uint32 cookie = 0;
233 status = resolver->GetNextAddress(&cookie, *this);
234 if (status != B_OK)
235 Unset();
236 fHostName = host;
237 fStatus = status;
238 return status;
239 }
240
241
242 status_t
SetTo(int family,const char * host,const char * service,uint32 flags)243 BNetworkAddress::SetTo(int family, const char* host, const char* service,
244 uint32 flags)
245 {
246 if (family == AF_LINK) {
247 if (service != NULL)
248 return B_BAD_VALUE;
249 return _ParseLinkAddress(host);
250 // SetToLinkAddress takes care of setting fStatus
251 }
252
253 BReference<const BNetworkAddressResolver> resolver
254 = BNetworkAddressResolver::Resolve(family, host, service, flags);
255 if (!resolver.IsSet())
256 return B_NO_MEMORY;
257 status_t status = resolver->InitCheck();
258 if (status != B_OK)
259 return status;
260
261 uint32 cookie = 0;
262 status = resolver->GetNextAddress(&cookie, *this);
263 if (status != B_OK)
264 Unset();
265 fHostName = host;
266 fStatus = status;
267 return status;
268 }
269
270
271 void
SetTo(const sockaddr & address)272 BNetworkAddress::SetTo(const sockaddr& address)
273 {
274 if (address.sa_family == AF_UNSPEC) {
275 Unset();
276 return;
277 }
278
279 size_t length = min_c(sizeof(sockaddr_storage), address.sa_len);
280 switch (address.sa_family) {
281 case AF_INET:
282 length = sizeof(sockaddr_in);
283 break;
284 case AF_INET6:
285 length = sizeof(sockaddr_in6);
286 break;
287 case AF_LINK:
288 {
289 sockaddr_dl& link = (sockaddr_dl&)address;
290 length = sizeof(sockaddr_dl) - sizeof(link.sdl_data) + link.sdl_alen
291 + link.sdl_nlen + link.sdl_slen;
292 break;
293 }
294 }
295
296 SetTo(address, length);
297 }
298
299
300 void
SetTo(const sockaddr & address,size_t length)301 BNetworkAddress::SetTo(const sockaddr& address, size_t length)
302 {
303 if (address.sa_family == AF_UNSPEC || length == 0) {
304 Unset();
305 return;
306 }
307
308 memcpy(&fAddress, &address, length);
309 fAddress.ss_len = length;
310 fStatus = B_OK;
311 }
312
313
314 void
SetTo(const sockaddr_storage & address)315 BNetworkAddress::SetTo(const sockaddr_storage& address)
316 {
317 SetTo((sockaddr&)address);
318 }
319
320
321 void
SetTo(const sockaddr_in & address)322 BNetworkAddress::SetTo(const sockaddr_in& address)
323 {
324 SetTo((sockaddr&)address);
325 }
326
327
328 void
SetTo(const sockaddr_in6 & address)329 BNetworkAddress::SetTo(const sockaddr_in6& address)
330 {
331 SetTo((sockaddr&)address);
332 }
333
334
335 void
SetTo(const sockaddr_dl & address)336 BNetworkAddress::SetTo(const sockaddr_dl& address)
337 {
338 SetTo((sockaddr&)address);
339 }
340
341
342 void
SetTo(in_addr_t inetAddress,uint16 port)343 BNetworkAddress::SetTo(in_addr_t inetAddress, uint16 port)
344 {
345 memset(&fAddress, 0, sizeof(sockaddr_storage));
346
347 fAddress.ss_family = AF_INET;
348 fAddress.ss_len = sizeof(sockaddr_in);
349 SetAddress(inetAddress);
350 SetPort(port);
351
352 fStatus = B_OK;
353 }
354
355
356 void
SetTo(const in6_addr & inet6Address,uint16 port)357 BNetworkAddress::SetTo(const in6_addr& inet6Address, uint16 port)
358 {
359 memset(&fAddress, 0, sizeof(sockaddr_storage));
360
361 fAddress.ss_family = AF_INET6;
362 fAddress.ss_len = sizeof(sockaddr_in6);
363 SetAddress(inet6Address);
364 SetPort(port);
365
366 fStatus = B_OK;
367 }
368
369
370 void
SetTo(const BNetworkAddress & other)371 BNetworkAddress::SetTo(const BNetworkAddress& other)
372 {
373 fAddress = other.fAddress;
374 fStatus = other.fStatus;
375 fHostName = other.fHostName;
376 }
377
378
379 status_t
SetToBroadcast(int family,uint16 port)380 BNetworkAddress::SetToBroadcast(int family, uint16 port)
381 {
382 if (family != AF_INET)
383 return fStatus = B_NOT_SUPPORTED;
384
385 SetTo(INADDR_BROADCAST, port);
386 return fStatus;
387 }
388
389
390 status_t
SetToLocal(int family,uint16 port)391 BNetworkAddress::SetToLocal(int family, uint16 port)
392 {
393 // TODO: choose a local address from the network interfaces
394 return fStatus = B_NOT_SUPPORTED;
395 }
396
397
398 status_t
SetToLoopback(int family,uint16 port)399 BNetworkAddress::SetToLoopback(int family, uint16 port)
400 {
401 switch (family) {
402 // TODO: choose family depending on availability of IPv6
403 case AF_UNSPEC:
404 case AF_INET:
405 SetTo(htonl(INADDR_LOOPBACK), port);
406 break;
407
408 case AF_INET6:
409 SetTo(in6addr_loopback, port);
410 break;
411
412 default:
413 return fStatus = B_NOT_SUPPORTED;
414 }
415
416 return fStatus;
417 }
418
419
420 status_t
SetToMask(int family,uint32 prefixLength)421 BNetworkAddress::SetToMask(int family, uint32 prefixLength)
422 {
423 switch (family) {
424 case AF_INET:
425 {
426 if (prefixLength > 32)
427 return B_BAD_VALUE;
428
429 sockaddr_in& mask = (sockaddr_in&)fAddress;
430 memset(&fAddress, 0, sizeof(sockaddr_storage));
431 mask.sin_family = AF_INET;
432 mask.sin_len = sizeof(sockaddr_in);
433
434 uint32 hostMask = 0;
435 for (uint8 i = 32; i > 32 - prefixLength; i--)
436 hostMask |= 1 << (i - 1);
437
438 mask.sin_addr.s_addr = htonl(hostMask);
439 break;
440 }
441
442 case AF_INET6:
443 {
444 if (prefixLength > 128)
445 return B_BAD_VALUE;
446
447 sockaddr_in6& mask = (sockaddr_in6&)fAddress;
448 memset(&fAddress, 0, sizeof(sockaddr_storage));
449 mask.sin6_family = AF_INET6;
450 mask.sin6_len = sizeof(sockaddr_in6);
451
452 for (uint8 i = 0; i < sizeof(in6_addr); i++, prefixLength -= 8) {
453 if (prefixLength < 8) {
454 mask.sin6_addr.s6_addr[i]
455 = (uint8)(0xff << (8 - prefixLength));
456 break;
457 }
458
459 mask.sin6_addr.s6_addr[i] = 0xff;
460 }
461 break;
462 }
463
464 default:
465 return B_NOT_SUPPORTED;
466 }
467
468 return fStatus = B_OK;
469 }
470
471
472 status_t
SetToWildcard(int family,uint16 port)473 BNetworkAddress::SetToWildcard(int family, uint16 port)
474 {
475 switch (family) {
476 case AF_INET:
477 SetTo(INADDR_ANY, port);
478 break;
479
480 case AF_INET6:
481 SetTo(in6addr_any, port);
482 break;
483
484 default:
485 return B_NOT_SUPPORTED;
486 }
487
488 return fStatus;
489 }
490
491
492 status_t
SetAddress(in_addr_t inetAddress)493 BNetworkAddress::SetAddress(in_addr_t inetAddress)
494 {
495 if (Family() != AF_INET)
496 return B_BAD_VALUE;
497
498 sockaddr_in& address = (sockaddr_in&)fAddress;
499 address.sin_addr.s_addr = inetAddress;
500 return B_OK;
501 }
502
503
504 status_t
SetAddress(const in6_addr & inet6Address)505 BNetworkAddress::SetAddress(const in6_addr& inet6Address)
506 {
507 if (Family() != AF_INET6)
508 return B_BAD_VALUE;
509
510 sockaddr_in6& address = (sockaddr_in6&)fAddress;
511 memcpy(address.sin6_addr.s6_addr, &inet6Address,
512 sizeof(address.sin6_addr.s6_addr));
513 return B_OK;
514 }
515
516
517 void
SetPort(uint16 port)518 BNetworkAddress::SetPort(uint16 port)
519 {
520 switch (fAddress.ss_family) {
521 case AF_INET:
522 ((sockaddr_in&)fAddress).sin_port = htons(port);
523 break;
524
525 case AF_INET6:
526 ((sockaddr_in6&)fAddress).sin6_port = htons(port);
527 break;
528
529 default:
530 break;
531 }
532 }
533
534
535 void
SetToLinkLevel(const uint8 * address,size_t length)536 BNetworkAddress::SetToLinkLevel(const uint8* address, size_t length)
537 {
538 sockaddr_dl& link = (sockaddr_dl&)fAddress;
539 memset(&link, 0, sizeof(sockaddr_dl));
540
541 link.sdl_family = AF_LINK;
542 link.sdl_alen = length;
543 memcpy(LLADDR(&link), address, length);
544
545 link.sdl_len = sizeof(sockaddr_dl);
546 if (length > sizeof(link.sdl_data))
547 link.sdl_len += length - sizeof(link.sdl_data);
548
549 fStatus = B_OK;
550 }
551
552
553 void
SetToLinkLevel(const char * name)554 BNetworkAddress::SetToLinkLevel(const char* name)
555 {
556 sockaddr_dl& link = (sockaddr_dl&)fAddress;
557 memset(&link, 0, sizeof(sockaddr_dl));
558
559 size_t length = strlen(name);
560 if (length > sizeof(fAddress) - sizeof(sockaddr_dl) + sizeof(link.sdl_data))
561 length = sizeof(fAddress) - sizeof(sockaddr_dl) + sizeof(link.sdl_data);
562
563 link.sdl_family = AF_LINK;
564 link.sdl_nlen = length;
565
566 memcpy(link.sdl_data, name, link.sdl_nlen);
567
568 link.sdl_len = sizeof(sockaddr_dl);
569 if (link.sdl_nlen > sizeof(link.sdl_data))
570 link.sdl_len += link.sdl_nlen - sizeof(link.sdl_data);
571
572 fStatus = B_OK;
573 }
574
575
576 void
SetToLinkLevel(uint32 index)577 BNetworkAddress::SetToLinkLevel(uint32 index)
578 {
579 sockaddr_dl& link = (sockaddr_dl&)fAddress;
580 memset(&link, 0, sizeof(sockaddr_dl));
581
582 link.sdl_family = AF_LINK;
583 link.sdl_len = sizeof(sockaddr_dl);
584 link.sdl_index = index;
585
586 fStatus = B_OK;
587 }
588
589
590 void
SetLinkLevelIndex(uint32 index)591 BNetworkAddress::SetLinkLevelIndex(uint32 index)
592 {
593 sockaddr_dl& link = (sockaddr_dl&)fAddress;
594 link.sdl_index = index;
595 }
596
597
598 void
SetLinkLevelType(uint8 type)599 BNetworkAddress::SetLinkLevelType(uint8 type)
600 {
601 sockaddr_dl& link = (sockaddr_dl&)fAddress;
602 link.sdl_type = type;
603 }
604
605
606 void
SetLinkLevelFrameType(uint16 frameType)607 BNetworkAddress::SetLinkLevelFrameType(uint16 frameType)
608 {
609 sockaddr_dl& link = (sockaddr_dl&)fAddress;
610 link.sdl_e_type = htons(frameType);
611 }
612
613
614 int
Family() const615 BNetworkAddress::Family() const
616 {
617 return fAddress.ss_family;
618 }
619
620
621 uint16
Port() const622 BNetworkAddress::Port() const
623 {
624 switch (fAddress.ss_family) {
625 case AF_INET:
626 return ntohs(((sockaddr_in&)fAddress).sin_port);
627
628 case AF_INET6:
629 return ntohs(((sockaddr_in6&)fAddress).sin6_port);
630
631 default:
632 return 0;
633 }
634 }
635
636
637 size_t
Length() const638 BNetworkAddress::Length() const
639 {
640 return fAddress.ss_len;
641 }
642
643
644 const sockaddr&
SockAddr() const645 BNetworkAddress::SockAddr() const
646 {
647 return (const sockaddr&)fAddress;
648 }
649
650
651 sockaddr&
SockAddr()652 BNetworkAddress::SockAddr()
653 {
654 return (sockaddr&)fAddress;
655 }
656
657
658 bool
IsEmpty() const659 BNetworkAddress::IsEmpty() const
660 {
661 if (fAddress.ss_len == 0)
662 return true;
663
664 switch (fAddress.ss_family) {
665 case AF_UNSPEC:
666 return true;
667 case AF_INET:
668 {
669 sockaddr_in& sin = (sockaddr_in&)fAddress;
670 return sin.sin_addr.s_addr == INADDR_ANY && sin.sin_port == 0;
671 }
672 case AF_INET6:
673 {
674 sockaddr_in6& sin6 = (sockaddr_in6&)fAddress;
675 return IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)
676 && sin6.sin6_port == 0;
677 }
678
679 default:
680 return false;
681 }
682 }
683
684
685 bool
IsWildcard() const686 BNetworkAddress::IsWildcard() const
687 {
688 switch (fAddress.ss_family) {
689 case AF_INET:
690 return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_ANY;
691
692 case AF_INET6:
693 return !memcmp(&((sockaddr_in6&)fAddress).sin6_addr, &in6addr_any,
694 sizeof(in6_addr));
695
696 default:
697 return false;
698 }
699 }
700
701
702 bool
IsBroadcast() const703 BNetworkAddress::IsBroadcast() const
704 {
705 switch (fAddress.ss_family) {
706 case AF_INET:
707 return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_BROADCAST;
708
709 case AF_INET6:
710 // There is no broadcast in IPv6, only multicast/anycast
711 return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
712
713 default:
714 return false;
715 }
716 }
717
718
719 bool
IsMulticast() const720 BNetworkAddress::IsMulticast() const
721 {
722 switch (fAddress.ss_family) {
723 case AF_INET:
724 return IN_MULTICAST(((sockaddr_in&)fAddress).sin_addr.s_addr);
725
726 case AF_INET6:
727 return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
728
729 default:
730 return false;
731 }
732 }
733
734
735 bool
IsMulticastGlobal() const736 BNetworkAddress::IsMulticastGlobal() const
737 {
738 switch (fAddress.ss_family) {
739 case AF_INET6:
740 return IN6_IS_ADDR_MC_GLOBAL(&((sockaddr_in6&)fAddress).sin6_addr);
741
742 default:
743 return false;
744 }
745 }
746
747
748 bool
IsMulticastNodeLocal() const749 BNetworkAddress::IsMulticastNodeLocal() const
750 {
751 switch (fAddress.ss_family) {
752 case AF_INET6:
753 return IN6_IS_ADDR_MC_NODELOCAL(
754 &((sockaddr_in6&)fAddress).sin6_addr);
755
756 default:
757 return false;
758 }
759 }
760
761
762 bool
IsMulticastLinkLocal() const763 BNetworkAddress::IsMulticastLinkLocal() const
764 {
765 switch (fAddress.ss_family) {
766 case AF_INET6:
767 return IN6_IS_ADDR_MC_LINKLOCAL(
768 &((sockaddr_in6&)fAddress).sin6_addr);
769
770 default:
771 return false;
772 }
773 }
774
775
776 bool
IsMulticastSiteLocal() const777 BNetworkAddress::IsMulticastSiteLocal() const
778 {
779 switch (fAddress.ss_family) {
780 case AF_INET6:
781 return IN6_IS_ADDR_MC_SITELOCAL(
782 &((sockaddr_in6&)fAddress).sin6_addr);
783
784 default:
785 return false;
786 }
787 }
788
789
790 bool
IsMulticastOrgLocal() const791 BNetworkAddress::IsMulticastOrgLocal() const
792 {
793 switch (fAddress.ss_family) {
794 case AF_INET6:
795 return IN6_IS_ADDR_MC_ORGLOCAL(
796 &((sockaddr_in6&)fAddress).sin6_addr);
797
798 default:
799 return false;
800 }
801 }
802
803
804 bool
IsLinkLocal() const805 BNetworkAddress::IsLinkLocal() const
806 {
807 // TODO: ipv4
808 switch (fAddress.ss_family) {
809 case AF_INET6:
810 return IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
811
812 default:
813 return false;
814 }
815 }
816
817
818 bool
IsSiteLocal() const819 BNetworkAddress::IsSiteLocal() const
820 {
821 switch (fAddress.ss_family) {
822 case AF_INET6:
823 return IN6_IS_ADDR_SITELOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
824
825 default:
826 return false;
827 }
828 }
829
830
831 bool
IsLocal() const832 BNetworkAddress::IsLocal() const
833 {
834 BNetworkRoster& roster = BNetworkRoster::Default();
835
836 BNetworkInterface interface;
837 uint32 cookie = 0;
838
839 while (roster.GetNextInterface(&cookie, interface) == B_OK) {
840 int32 count = interface.CountAddresses();
841 for (int32 j = 0; j < count; j++) {
842 BNetworkInterfaceAddress address;
843 if (interface.GetAddressAt(j, address) != B_OK)
844 break;
845
846 if (Equals(address.Address(), false))
847 return true;
848 }
849 }
850
851 return false;
852 }
853
854
855 ssize_t
PrefixLength() const856 BNetworkAddress::PrefixLength() const
857 {
858 switch (fAddress.ss_family) {
859 case AF_INET:
860 {
861 sockaddr_in& mask = (sockaddr_in&)fAddress;
862
863 uint32 hostMask = ntohl(mask.sin_addr.s_addr);
864 return addr_bitcount(hostMask);
865 }
866
867 case AF_INET6:
868 {
869 sockaddr_in6& mask = (sockaddr_in6&)fAddress;
870
871 // TODO : see if we can use the optimized addr_bitcount for this
872 ssize_t result = 0;
873 for (uint8 i = 0; i < sizeof(in6_addr); i++) {
874 for (uint8 j = 0; j < 8; j++) {
875 if (!(mask.sin6_addr.s6_addr[i] & (1 << j)))
876 return result;
877 result++;
878 }
879 }
880
881 return 128;
882 }
883
884 default:
885 return B_NOT_SUPPORTED;
886 }
887 }
888
889
890 uint32
LinkLevelIndex() const891 BNetworkAddress::LinkLevelIndex() const
892 {
893 return ((sockaddr_dl&)fAddress).sdl_index;
894 }
895
896
897 BString
LinkLevelInterface() const898 BNetworkAddress::LinkLevelInterface() const
899 {
900 sockaddr_dl& address = (sockaddr_dl&)fAddress;
901 if (address.sdl_nlen == 0)
902 return "";
903
904 BString name;
905 name.SetTo((const char*)address.sdl_data, address.sdl_nlen);
906
907 return name;
908 }
909
910
911 uint8
LinkLevelType() const912 BNetworkAddress::LinkLevelType() const
913 {
914 return ((sockaddr_dl&)fAddress).sdl_type;
915 }
916
917
918 uint16
LinkLevelFrameType() const919 BNetworkAddress::LinkLevelFrameType() const
920 {
921 return ntohs(((sockaddr_dl&)fAddress).sdl_e_type);
922 }
923
924
925 uint8*
LinkLevelAddress() const926 BNetworkAddress::LinkLevelAddress() const
927 {
928 return LLADDR(&(sockaddr_dl&)fAddress);
929 }
930
931
932 size_t
LinkLevelAddressLength() const933 BNetworkAddress::LinkLevelAddressLength() const
934 {
935 return ((sockaddr_dl&)fAddress).sdl_alen;
936 }
937
938
939 status_t
ResolveForDestination(const BNetworkAddress & destination)940 BNetworkAddress::ResolveForDestination(const BNetworkAddress& destination)
941 {
942 if (!IsWildcard())
943 return B_OK;
944 if (destination.fAddress.ss_family != fAddress.ss_family)
945 return B_BAD_VALUE;
946
947 char buffer[2048];
948 memset(buffer, 0, sizeof(buffer));
949
950 route_entry* route = (route_entry*)buffer;
951 route->destination = (sockaddr*)&destination.fAddress;
952
953 int socket = ::socket(fAddress.ss_family, SOCK_DGRAM, 0);
954 if (socket < 0)
955 return errno;
956
957 if (ioctl(socket, SIOCGETRT, route, sizeof(buffer)) != 0) {
958 close(socket);
959 return errno;
960 }
961
962 uint16 port = Port();
963 memcpy(&fAddress, route->source, sizeof(sockaddr_storage));
964 SetPort(port);
965
966 close(socket);
967 return B_OK;
968 }
969
970
971 status_t
ResolveTo(const BNetworkAddress & address)972 BNetworkAddress::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
987 BString
ToString(bool includePort) const988 BNetworkAddress::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
1048 BString
HostName() const1049 BNetworkAddress::HostName() const
1050 {
1051 // TODO: implement host name lookup
1052 return fHostName;
1053 }
1054
1055
1056 BString
ServiceName() const1057 BNetworkAddress::ServiceName() const
1058 {
1059 // TODO: implement service lookup
1060 BString portName;
1061 portName << Port();
1062 return portName;
1063 }
1064
1065
1066 bool
Equals(const BNetworkAddress & other,bool includePort) const1067 BNetworkAddress::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
1106 bool
IsFixedSize() const1107 BNetworkAddress::IsFixedSize() const
1108 {
1109 return false;
1110 }
1111
1112
1113 type_code
TypeCode() const1114 BNetworkAddress::TypeCode() const
1115 {
1116 return B_NETWORK_ADDRESS_TYPE;
1117 }
1118
1119
1120 ssize_t
FlattenedSize() const1121 BNetworkAddress::FlattenedSize() const
1122 {
1123 return Length();
1124 }
1125
1126
1127 status_t
Flatten(void * buffer,ssize_t size) const1128 BNetworkAddress::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
1138 status_t
Unflatten(type_code code,const void * buffer,ssize_t size)1139 BNetworkAddress::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
1160 BNetworkAddress&
operator =(const BNetworkAddress & other)1161 BNetworkAddress::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
1171 bool
operator ==(const BNetworkAddress & other) const1172 BNetworkAddress::operator==(const BNetworkAddress& other) const
1173 {
1174 return Equals(other);
1175 }
1176
1177
1178 bool
operator !=(const BNetworkAddress & other) const1179 BNetworkAddress::operator!=(const BNetworkAddress& other) const
1180 {
1181 return !Equals(other);
1182 }
1183
1184
1185 bool
operator <(const BNetworkAddress & other) const1186 BNetworkAddress::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
operator const sockaddr*() const1236 BNetworkAddress::operator const sockaddr*() const
1237 {
1238 return (const sockaddr*)&fAddress;
1239 }
1240
1241
operator const sockaddr&() const1242 BNetworkAddress::operator const sockaddr&() const
1243 {
1244 return (const sockaddr&)fAddress;
1245 }
1246
1247
operator sockaddr*()1248 BNetworkAddress::operator sockaddr*()
1249 {
1250 return (sockaddr*)&fAddress;
1251 }
1252
1253
operator const sockaddr*()1254 BNetworkAddress::operator const sockaddr*()
1255 {
1256 return (sockaddr*)&fAddress;
1257 }
1258
1259
operator sockaddr&()1260 BNetworkAddress::operator sockaddr&()
1261 {
1262 return (sockaddr&)fAddress;
1263 }
1264
1265
operator const sockaddr&()1266 BNetworkAddress::operator const sockaddr&()
1267 {
1268 return (sockaddr&)fAddress;
1269 }
1270
1271
1272 // #pragma mark - private
1273
1274
1275 status_t
_ParseLinkAddress(const char * address)1276 BNetworkAddress::_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