ucommon  7.0.0
About: GNU uCommon C++ is a portable and optimized class framework for writing C++ applications that need to use threads and support concurrent synchronization, and that use sockets, XML parsing, object serialization, thread-optimized string and data structure classes, etc..
  Fossies Dox: ucommon-7.0.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Loading...
Searching...
No Matches
address.cpp
Go to the documentation of this file.
1// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
3// Copyright (C) 2015 Cherokees of Idaho.
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18//
19// As a special exception, you may use this file as part of a free software
20// library without restriction. Specifically, if other files instantiate
21// templates or use macros or inline functions from this file, or you compile
22// this file and link it with other files to produce an executable, this
23// file does not by itself cause the resulting executable to be covered by
24// the GNU General Public License. This exception does not however
25// invalidate any other reasons why the executable file might be covered by
26// the GNU General Public License.
27//
28// This exception applies only to the code released under the name GNU
29// Common C++. If you copy code from other releases into a copy of GNU
30// Common C++, as the General Public License permits, the exception does
31// not apply to the code that you add in this way. To avoid misleading
32// anyone as to the status of such modified files, you must delete
33// this exception notice from them.
34//
35// If you write modifications of your own for GNU Common C++, it is your choice
36// whether to permit this exception to apply to your modifications.
37// If you do not wish that, delete this exception notice.
38//
39
40#include <ucommon-config.h>
41#ifdef HAVE_ENDIAN_H
42#include <endian.h>
43#endif
44#include <commoncpp/config.h>
45#include <commoncpp/export.h>
46#include <commoncpp/thread.h>
47#include <commoncpp/address.h>
48#include <cstdlib>
49
50#ifndef _MSWINDOWS_
51#include <sys/socket.h>
52#include <netinet/in.h>
53#include <arpa/inet.h>
54#endif
55
56#if defined(_MSWINDOWS_) && !defined(__BIG_ENDIAN)
57#define __LITTLE_ENDIAN 1234
58#define __BIG_ENDIAN 4321
59#define __PDP_ENDIAN 3412
60#define __BYTE_ORDER __LITTLE_ENDIAN
61#endif
62
63namespace ost {
64using std::ostream;
65
66#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
67enum {
68 MCAST_VALID_MASK = 0xF0000000,
69 MCAST_VALID_VALUE = 0xE0000000
70};
71#else
72enum {
73 MCAST_VALID_MASK = 0x000000F0,
74 MCAST_VALID_VALUE = 0x000000E0
75};
76#endif
77
78#ifndef _MSWINDOWS_
80#endif
81
82IPV4Host IPV4Host::_host_;
83
84const IPV4MulticastValidator IPV4Multicast::validator;
85
86void IPV4MulticastValidator::operator()(const in_addr address) const
87{
88#ifdef CCXX_EXCEPTIONS
89 // "0.0.0.0" is always accepted, as it is an "empty" address.
90 if ( (address.s_addr != INADDR_ANY) &&
91 (address.s_addr & MCAST_VALID_MASK) != MCAST_VALID_VALUE ) {
92 throw "Multicast address not in the valid range: from 224.0.0.1 through 239.255.255.255";
93 }
94#endif
95}
96
98validator(_validator), ipaddr(NULL), addr_count(0), hostname(NULL)
99{
100 *this = (in_addr_t)INADDR_ANY;
101}
102
103IPV4Address::IPV4Address(const char *address, const IPV4Validator *_validator) :
104validator(_validator), ipaddr(NULL), addr_count(0), hostname(NULL)
105{
106 if(address == 0 || !strcmp(address, "*"))
107 setAddress(NULL);
108 else
109 setAddress(address);
110}
111
112IPV4Address::IPV4Address(struct in_addr addr, const IPV4Validator *_validator) :
113validator(_validator), ipaddr(NULL), hostname(NULL)
114{
115 if ( this->validator ) {
116 (*validator)(addr);
117 }
118 addr_count = 1;
119 ipaddr = new struct in_addr[1];
120 ipaddr[0] = addr;
121}
122
124validator(rhs.validator), addr_count(rhs.addr_count), hostname(NULL)
125{
126 ipaddr = new struct in_addr[addr_count];
127 memcpy(ipaddr, rhs.ipaddr, sizeof(struct in_addr) * addr_count);
128}
129
131{
132 if(ipaddr) {
133 delete[] ipaddr;
134 ipaddr = NULL;
135 }
136 if(hostname) {
138 hostname = NULL;
139 }
140}
141
142struct in_addr IPV4Address::getAddress(void) const
143{
144 return ipaddr[0];
145}
146
147struct in_addr IPV4Address::getAddress(size_t i) const
148{
149 return (i < addr_count ? ipaddr[i] : ipaddr[0]);
150}
151
153{
154 struct in_addr addr;
155 memset(&addr, 0, sizeof(addr));
156 if(memcmp(&addr, &ipaddr[0], sizeof(addr)))
157 return true;
158 return false;
159}
160
162{
163 if(str == 0 || !strcmp(str, "*"))
164 str = "0.0.0.0";
165
167
168 return *this;
169}
170
172{
173 if(ipaddr)
174 delete[] ipaddr;
175 if ( validator )
176 (*validator)(addr);
177 addr_count = 1;
178 ipaddr = new struct in_addr[1];
179 ipaddr[0] = addr;
180 if(hostname)
182 hostname = NULL;
183 return *this;
184}
185
187{
188 union {
189 in_addr_t addr;
190 struct in_addr in4;
191 } aptr;
192
193 aptr.addr = addr;
194
195 if ( validator )
196 (*validator)(aptr.in4);
197
198 if(ipaddr)
199 delete[] ipaddr;
200
201 addr_count = 1;
202 ipaddr = new struct in_addr[1];
203 memcpy(ipaddr, &aptr.in4, sizeof(struct in_addr));
204 if(hostname)
206 hostname = NULL;
207 return *this;
208}
209
211{
212 if(this == &rhs) return *this;
213
215 if(ipaddr)
216 delete[] ipaddr;
217 ipaddr = new struct in_addr[addr_count];
218 memcpy(ipaddr, rhs.ipaddr, sizeof(struct in_addr) * addr_count);
219 validator = rhs.validator;
220 if(hostname)
222 hostname = NULL;
223
224 return *this;
225}
226
228{
229 const IPV4Address *smaller, *larger;
230 size_t s, l;
231
232 if(addr_count > a.addr_count) {
233 smaller = &a;
234 larger = this;
235 }
236 else {
237 smaller = this;
238 larger = &a;
239 }
240
241 // Loop through all addr's in the smaller and make sure
242 // that they are all in the larger
243 for(s = 0; s < smaller->addr_count; s++) {
244 // bool found = false;
245 for(l = 0; l < larger->addr_count &&
246 memcmp((char *)&smaller->ipaddr[s], (char *)&larger->ipaddr[l], sizeof(struct in_addr)); l++);
247 if(l == larger->addr_count) return false;
248 }
249 return true;
250}
251
253{
254 // Impliment in terms of operator==
255 return (*this == a ? false : true);
256}
257
259{
260 for(size_t i = 0; i < addr_count; i++) {
261 struct in_addr mask = ma.getAddress();
262 uint8_t *a = (uint8_t *)&ipaddr[i];
263 uint8_t *m = (uint8_t *)&mask;
264
265 for(size_t j = 0; j < sizeof(struct in_addr); ++j)
266 *(a++) &= *(m++);
267 }
268 if(hostname)
270 hostname = NULL;
271
272 return *this;
273}
274
275IPV4Host::IPV4Host(struct in_addr addr) :
277
278IPV4Host::IPV4Host(const char *host) :
279IPV4Address(host)
280{
281 char namebuf[256];
282
283 if(!host) {
284 if(this == &_host_) {
285 gethostname(namebuf, 256);
286 setAddress(namebuf);
287 }
288 else
289 *this = _host_;
290 }
291}
292
293bool IPV4Address::setIPAddress(const char *host)
294{
295 if(!host)
296 return false;
297
298#if defined(_MSWINDOWS_)
299 struct sockaddr_in addr;
300 addr.sin_addr.s_addr = inet_addr(host);
301 if ( validator )
302 (*validator)(addr.sin_addr);
303 if(addr.sin_addr.s_addr == INADDR_NONE)
304 return false;
305 *this = addr.sin_addr.s_addr;
306#else
307 struct in_addr l_addr;
308
309 int ok = inet_aton(host, &l_addr);
310 if ( validator )
311 (*validator)(l_addr);
312 if ( !ok )
313 return false;
314 *this = l_addr;
315#endif
316 return true;
317}
318
319void IPV4Address::setAddress(const char *host)
320{
321 if(hostname)
323 hostname = NULL;
324
325 if(!host) // The way this is currently used, this can never happen
326 {
327 *this = (in_addr_t)htonl(INADDR_ANY);
328 return;
329 }
330
331#ifdef _MSWINDOWS_
332 if(!stricmp(host, "localhost")) {
333 *this = (long unsigned int)inet_addr("127.0.0.1");
334 return;
335 }
336#endif
337
338 if(!setIPAddress(host)) {
339 struct hostent *hp;
340 struct in_addr **bptr;
341#if defined(__GLIBC__)
342 char hbuf[8192];
343 struct hostent hb;
344 int rtn;
345
346 if(gethostbyname_r(host, &hb, hbuf, sizeof(hbuf), &hp, &rtn))
347 hp = NULL;
348#elif defined(sun)
349 char hbuf[8192];
350 struct hostent hb;
351 int rtn;
352
353 hp = gethostbyname_r(host, &hb, hbuf, sizeof(hbuf), &rtn);
354#elif (defined(__osf__) || defined(_MSWINDOWS_))
355 hp = gethostbyname(host);
356#else
358 hp = gethostbyname(host);
360#endif
361 if(!hp) {
362 if(ipaddr)
363 delete[] ipaddr;
364 ipaddr = new struct in_addr[1];
365 memset(ipaddr, 0, sizeof(struct in_addr));
366 return;
367 }
368
369 // Count the number of IP addresses returned
370 addr_count = 0;
371 for(bptr = (struct in_addr **)hp->h_addr_list; *bptr != NULL; bptr++) {
372 addr_count++;
373 }
374
375 // Allocate enough memory
376 if(ipaddr)
377 delete[] ipaddr; // Cause this was allocated in base
378 ipaddr = new struct in_addr[addr_count];
379
380 // Now go through the list again assigning to
381 // the member ipaddr;
382 bptr = (struct in_addr **)hp->h_addr_list;
383 for(unsigned int i = 0; i < addr_count; i++) {
384 if ( validator )
385 (*validator)(*bptr[i]);
386 ipaddr[i] = *bptr[i];
387 }
388 }
389}
390
392IPV4Address(net)
393{
394}
395
396IPV4Mask::IPV4Mask(const char *mask)
397{
398 unsigned long x = 0xffffffff;
399 int l = 32 - atoi(mask);
400
401 if(setIPAddress(mask))
402 return;
403
404 if(l < 1 || l > 32) {
405#ifdef CCXX_EXCEPTIONS
407 throw((IPV4Address *)this);
408#endif
409 return;
410 }
411
412 *this = htonl(x << l);
413}
414
415const char *IPV4Address::getHostname(void) const
416{
417 struct hostent *hp = NULL;
418 struct in_addr addr0;
419
420 memset(&addr0, 0, sizeof(addr0));
421 if(!memcmp(&addr0, &ipaddr[0], sizeof(addr0)))
422 return NULL;
423
424#ifdef _MSWINDOWS_
425 memset(&addr0, 0xff, sizeof(addr0));
426 if(!memcmp(&addr0, &ipaddr[0], sizeof(addr0)))
427 return "255.255.255.255";
428 long a = inet_addr("127.0.0.1");
429 if(!memcmp(&a, &ipaddr[0], sizeof(a)))
430 return "localhost";
431#endif
432
433#if defined(__GLIBC__)
434 char hbuf[8192];
435 struct hostent hb;
436 int rtn;
437 if(gethostbyaddr_r((char *)&ipaddr[0], sizeof(addr0), AF_INET, &hb, hbuf, sizeof(hbuf), &hp, &rtn))
438 hp = NULL;
439#elif defined(sun)
440 char hbuf[8192];
441 struct hostent hb;
442 int rtn;
443 hp = gethostbyaddr_r((char *)&ipaddr[0], (int)sizeof(addr0), (int)AF_INET, &hb, hbuf, (int)sizeof(hbuf), &rtn);
444#elif defined(__osf__) || defined(_MSWINDOWS_)
445 hp = gethostbyaddr((char *)&ipaddr[0], sizeof(addr0), AF_INET);
446#else
448 hp = gethostbyaddr((char *)&ipaddr[0], sizeof(addr0), AF_INET);
450#endif
451 if(hp) {
452 if(hostname)
454 hostname = newString(hp->h_name);
455 return hostname;
456 } else {
457 return inet_ntoa(ipaddr[0]);
458 }
459}
460
462{
464 temp &= mask;
465 return temp;
466}
467
469 IPV4Address(&validator)
470{}
471
472IPV4Multicast::IPV4Multicast(const struct in_addr address) :
473 IPV4Address(address, &validator)
474{}
475
476IPV4Multicast::IPV4Multicast(const char *address) :
477 IPV4Address(address, &validator)
478{}
479
480#ifdef CCXX_IPV6
481
482#ifndef _MSWINDOWS_
483Mutex IPV6Address::mutex;
484#endif
485
486const IPV6MulticastValidator IPV6Multicast::validator;
487
488void IPV6MulticastValidator::operator()(const in6_addr address) const
489{
490#ifdef CCXX_EXCEPTIONS
491 // "0000:" is always accepted, as it is an "empty" address.
492 if ( (address.s6_addr[0] != 0 || address.s6_addr[1] != 0) &&
493 (address.s6_addr[0] != 0xff || address.s6_addr[1] < 0x1f)) {
494 throw "Multicast address not in the valid prefix ff00-ff1f:";
495 }
496#endif
497}
498
499IPV6Address::IPV6Address(const IPV6Validator *_validator) :
500validator(_validator), hostname(NULL)
501{
502 addr_count = 1;
503 ipaddr = new struct in6_addr[1];
504 memcpy(ipaddr, &in6addr_any, sizeof(struct in6_addr));
505}
506
507IPV6Address::IPV6Address(const char *address, const IPV6Validator *_validator) :
508validator(_validator), ipaddr(NULL), addr_count(0), hostname(NULL)
509{
510 if(address == 0 || !strcmp(address, "*"))
511 setAddress(NULL);
512 else
513 setAddress(address);
514}
515
516IPV6Address::IPV6Address(struct in6_addr addr, const IPV6Validator *_validator) :
517validator(_validator), ipaddr(NULL), hostname(NULL)
518{
519 if ( this->validator ) {
520 (*validator)(addr);
521 }
522 addr_count = 1;
523 ipaddr = new struct in6_addr[1];
524 memcpy(ipaddr, &addr, sizeof(struct in6_addr));
525}
526
527IPV6Address::IPV6Address(const IPV6Address &rhs) :
528 validator(rhs.validator), addr_count(rhs.addr_count), hostname(NULL) {
529 ipaddr = new struct in6_addr[addr_count];
530 memcpy(ipaddr, rhs.ipaddr, sizeof(struct in6_addr) * addr_count);
531}
532
533IPV6Address::~IPV6Address()
534{
535 if(ipaddr) {
536 delete[] ipaddr;
537 ipaddr = NULL;
538 }
539 if(hostname) {
540 delString(hostname);
541 hostname = NULL;
542 }
543}
544
545struct in6_addr IPV6Address::getAddress(void) const
546{
547 return ipaddr[0];
548}
549
550struct in6_addr IPV6Address::getAddress(size_t i) const
551{
552 return (i < addr_count ? ipaddr[i] : ipaddr[0]);
553}
554
555bool IPV6Address::isInetAddress(void) const
556{
557 struct in6_addr addr;
558 memset(&addr, 0, sizeof(addr));
559 if(!ipaddr)
560 return false;
561 if(memcmp(&addr, &ipaddr[0], sizeof(addr)))
562 return true;
563 return false;
564}
565
566IPV6Address &IPV6Address::operator=(const char *str)
567{
568 if(str == 0 || !strcmp(str, "*"))
569 str = "::";
570
571 setAddress(str);
572
573 return *this;
574}
575
576IPV6Address &IPV6Address::operator=(struct in6_addr addr)
577{
578 if(ipaddr)
579 delete[] ipaddr;
580 if ( validator )
581 (*validator)(addr);
582 addr_count = 1;
583 ipaddr = new struct in6_addr[1];
584 ipaddr[0] = addr;
585 if(hostname)
586 delString(hostname);
587 hostname = NULL;
588 return *this;
589}
590
591IPV6Address &IPV6Address::operator=(const IPV6Address &rhs)
592{
593 if(this == &rhs) return *this;
594
595 addr_count = rhs.addr_count;
596 if(ipaddr)
597 delete[] ipaddr;
598 ipaddr = new struct in6_addr[addr_count];
599 memcpy(ipaddr, rhs.ipaddr, sizeof(struct in6_addr) * addr_count);
600 validator = rhs.validator;
601 if(hostname)
602 delString(hostname);
603 hostname = NULL;
604
605 return *this;
606}
607
608bool IPV6Address::operator==(const IPV6Address &a) const
609{
610 const IPV6Address *smaller, *larger;
611 size_t s, l;
612
613 if(addr_count > a.addr_count) {
614 smaller = &a;
615 larger = this;
616 }
617 else {
618 smaller = this;
619 larger = &a;
620 }
621
622 // Loop through all addr's in the smaller and make sure
623 // that they are all in the larger
624 for(s = 0; s < smaller->addr_count; s++) {
625 // bool found = false;
626 for(l = 0; l < larger->addr_count &&
627 memcmp((char *)&smaller->ipaddr[s], (char *)&larger->ipaddr[l], sizeof(struct in6_addr)); l++);
628 if(l == larger->addr_count) return false;
629 }
630 return true;
631}
632
633bool IPV6Address::operator!=(const IPV6Address &a) const
634{
635 // Impliment in terms of operator==
636 return (*this == a ? false : true);
637}
638
639IPV6Host &IPV6Host::operator&=(const IPV6Mask &ma)
640{
641 for(size_t i = 0; i < addr_count; i++) {
642 struct in6_addr mask = ma.getAddress();
643 uint8_t *a = (uint8_t *)&ipaddr[i];
644 uint8_t *m = (uint8_t *)&mask;
645
646 for(size_t j = 0; j < sizeof(struct in6_addr); ++j)
647 *(a++) &= *(m++);
648 }
649 if(hostname)
650 delString(hostname);
651 hostname = NULL;
652
653 return *this;
654}
655
656IPV6Host::IPV6Host(struct in6_addr addr) :
657IPV6Address(addr) {}
658
659IPV6Host::IPV6Host(const char *host) :
660IPV6Address(host)
661{
662 char namebuf[256];
663
664 if(!host) {
665 gethostname(namebuf, 256);
666 setAddress(namebuf);
667 }
668}
669
670bool IPV6Address::setIPAddress(const char *host)
671{
672 if(!host)
673 return false;
674
675 struct in6_addr l_addr;
676
677#ifdef _MSWINDOWS_
678 struct sockaddr saddr;
679 int slen = sizeof(saddr);
680 struct sockaddr_in6 *paddr = (struct sockaddr_in6 *)&saddr;
681 int ok = WSAStringToAddress((LPSTR)host, AF_INET6, NULL, &saddr, &slen);
682 l_addr = paddr->sin6_addr;
683#else
684 int ok = inet_pton(AF_INET6, host, &l_addr);
685#endif
686 if ( validator )
687 (*validator)(l_addr);
688 if ( !ok )
689 return false;
690 *this = l_addr;
691 return true;
692}
693
694#if defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME2)
695
696void IPV6Address::setAddress(const char *host)
697{
698 if(hostname)
699 delString(hostname);
700 hostname = NULL;
701
702 if(!host) // The way this is currently used, this can never happen
703 host = "::";
704
705#ifdef _MSWINDOWS_
706 if(!stricmp(host, "localhost"))
707 host = "::1";
708#endif
709
710 if(!setIPAddress(host)) {
711 struct addrinfo hint, *list = NULL, *first;
712 memset(&hint, 0, sizeof(hint));
713 hint.ai_family = AF_INET6;
714 struct in6_addr *addr;
715 struct sockaddr_in6 *ip6addr;
716
717 if(getaddrinfo(host, NULL, &hint, &list) || !list) {
718 if(ipaddr)
719 delete[] ipaddr;
720 ipaddr = new struct in6_addr[1];
721 memset((void *)&ipaddr[0], 0, sizeof(struct in6_addr));
722 return;
723 }
724
725 // Count the number of IP addresses returned
726 addr_count = 0;
727 first = list;
728 while(list) {
729 ++addr_count;
730 list = list->ai_next;
731 }
732
733 // Allocate enough memory
734 if(ipaddr)
735 delete[] ipaddr; // Cause this was allocated in base
736 ipaddr = new struct in6_addr[addr_count];
737
738 // Now go through the list again assigning to
739 // the member ipaddr;
740 list = first;
741 int i = 0;
742 while(list) {
743 ip6addr = (struct sockaddr_in6 *)list->ai_addr;
744 addr = &ip6addr->sin6_addr;
745 if(validator)
746 (*validator)(*addr);
747 ipaddr[i++] = *addr;
748 list = list->ai_next;
749 }
750 freeaddrinfo(first);
751 }
752}
753
754#else
755
756void IPV6Address::setAddress(const char *host)
757{
758 if(hostname)
759 delString(hostname);
760 hostname = NULL;
761
762 if(!host) // The way this is currently used, this can never happen
763 host = "::";
764
765#ifdef _MSWINDOWS_
766 if(!stricmp(host, "localhost"))
767 host = "::1";
768#endif
769
770 if(!setIPAddress(host)) {
771 struct hostent *hp;
772 struct in6_addr **bptr;
773#if defined(__GLIBC__)
774 char hbuf[8192];
775 struct hostent hb;
776 int rtn;
777
778 if(gethostbyname2_r(host, AF_INET6, &hb, hbuf, sizeof(hbuf), &hp, &rtn))
779 hp = NULL;
780#elif defined(sun)
781 char hbuf[8192];
782 struct hostent hb;
783 int rtn;
784
785 hp = gethostbyname2_r(host, AF_INET6, &hb, hbuf, sizeof(hbuf), &rtn);
786#elif (defined(__osf__) || defined(_OSF_SOURCE) || defined(__hpux))
787 hp = gethostbyname(host);
788#elif defined(_MSWINDOWS_) && (!defined(_MSC_VER) || _MSC_VER < 1300)
789 hp = gethostbyname(host);
790#elif defined(_MSWINDOWS_)
791 hp = gethostbyname2(host, AF_INET6);
792#else
793 mutex.enterMutex();
794 hp = gethostbyname2(host, AF_INET6);
795 mutex.leaveMutex();
796#endif
797 if(!hp) {
798 if(ipaddr)
799 delete[] ipaddr;
800 ipaddr = new struct in6_addr[1];
801 memset((void *)&ipaddr[0], 0, sizeof(struct in6_addr));
802 return;
803 }
804
805 // Count the number of IP addresses returned
806 addr_count = 0;
807 for(bptr = (struct in6_addr **)hp->h_addr_list; *bptr != NULL; bptr++) {
808 addr_count++;
809 }
810
811 // Allocate enough memory
812 if(ipaddr)
813 delete[] ipaddr; // Cause this was allocated in base
814 ipaddr = new struct in6_addr[addr_count];
815
816 // Now go through the list again assigning to
817 // the member ipaddr;
818 bptr = (struct in6_addr **)hp->h_addr_list;
819 for(unsigned int i = 0; i < addr_count; i++) {
820 if ( validator )
821 (*validator)(*bptr[i]);
822 ipaddr[i] = *bptr[i];
823 }
824 }
825}
826
827#endif
828
829IPV6Broadcast::IPV6Broadcast(const char *net) :
830IPV6Address(net)
831{
832}
833
834IPV6Mask::IPV6Mask(const char *mask) :
835IPV6Address(mask)
836{
837}
838
839const char *IPV6Address::getHostname(void) const
840{
841 struct hostent *hp = NULL;
842 struct in6_addr addr0;
843 static char strbuf[64];
844
845 memset(&addr0, 0, sizeof(addr0));
846 if(!memcmp(&addr0, &ipaddr[0], sizeof(addr0)))
847 return NULL;
848
849 if(!memcmp(&in6addr_loopback, &ipaddr[0], sizeof(addr0)))
850 return "localhost";
851
852#if defined(__GLIBC__)
853 char hbuf[8192];
854 struct hostent hb;
855 int rtn;
856 if(gethostbyaddr_r((char *)&ipaddr[0], sizeof(addr0), AF_INET6, &hb, hbuf, sizeof(hbuf), &hp, &rtn))
857 hp = NULL;
858#elif defined(sun)
859 char hbuf[8192];
860 struct hostent hb;
861 int rtn;
862 hp = gethostbyaddr_r((char *)&ipaddr[0], sizeof(addr0), AF_INET6, &hb, hbuf, (int)sizeof(hbuf), &rtn);
863#elif defined(__osf__) || defined(_MSWINDOWS_)
864 hp = gethostbyaddr((char *)&ipaddr[0], sizeof(addr0), AF_INET6);
865#else
866 mutex.enterMutex();
867 hp = gethostbyaddr((char *)&ipaddr[0], sizeof(addr0), AF_INET6);
868 mutex.leaveMutex();
869#endif
870 if(hp) {
871 if(hostname)
872 delString(hostname);
873 hostname = newString(hp->h_name);
874 return hostname;
875 } else {
876#ifdef _MSWINDOWS_
877 struct sockaddr saddr;
878 struct sockaddr_in6 *paddr = (struct sockaddr_in6 *)&saddr;
879 DWORD slen = sizeof(strbuf);
880 memset(&saddr, 0, sizeof(saddr));
881 paddr->sin6_family = AF_INET6;
882 paddr->sin6_addr = ipaddr[0];
883 WSAAddressToString(&saddr, sizeof(saddr), NULL, strbuf, &slen);
884 return strbuf;
885#else
886 return inet_ntop(AF_INET6, &ipaddr[0], strbuf, sizeof(strbuf));
887#endif
888 }
889}
890
891IPV6Host operator&(const IPV6Host &addr, const IPV6Mask &mask)
892{
893 IPV6Host temp = addr;
894 temp &= mask;
895 return temp;
896}
897
898IPV6Multicast::IPV6Multicast() :
899IPV6Address(&validator)
900{}
901
902IPV6Multicast::IPV6Multicast(const char *address) :
903IPV6Address(address,&validator)
904{}
905
906#endif
907
908ostream& operator<<(ostream &os, const IPV4Address &ia)
909{
910 os << inet_ntoa(getaddress(ia));
911 return os;
912}
913
914typedef uint8_t bit_t;
915
916static void bitmask(bit_t *bits, bit_t *mask, unsigned len)
917{
918 while(len--)
919 *(bits++) &= *(mask++);
920}
921
922static void bitimask(bit_t *bits, bit_t *mask, unsigned len)
923{
924 while(len--)
925 *(bits++) |= ~(*(mask++));
926}
927
928static void bitset(bit_t *bits, unsigned blen)
929{
930 bit_t mask;
931
932 while(blen) {
933 mask = (bit_t)(1 << 7);
934 while(mask && blen) {
935 *bits |= mask;
936 mask >>= 1;
937 --blen;
938 }
939 ++bits;
940 }
941}
942
943static unsigned bitcount(bit_t *bits, unsigned len)
944{
945 unsigned count = 0;
946 bit_t mask, test;
947
948 while(len--) {
949 mask = (bit_t)(1<<7);
950 test = *bits++;
951 while(mask) {
952 if(!(mask & test))
953 return count;
954 ++count;
955 mask >>= 1;
956 }
957 }
958 return count;
959}
960
962{
963 memset(&network, 0, sizeof(network));
964 memset(&netmask, 0, sizeof(netmask));
965}
966
967IPV4Cidr::IPV4Cidr(const char *cp)
968{
969 set(cp);
970}
971
973{
974 memcpy(&network, &cidr.network, sizeof(network));
975 memcpy(&netmask, &cidr.netmask, sizeof(netmask));
976}
977
978bool IPV4Cidr::isMember(const struct in_addr &addr) const
979{
980 struct in_addr host = addr;
981
982 bitmask((bit_t *)&host, (bit_t *)&netmask, sizeof(host));
983 if(!memcmp(&host, &network, sizeof(host)))
984 return true;
985
986 return false;
987}
988
989bool IPV4Cidr::isMember(const struct sockaddr *saddr) const
990{
991 struct sockaddr_in *addr = (struct sockaddr_in *)saddr;
992 struct in_addr host;
993
994 if(saddr->sa_family != AF_INET)
995 return false;
996
997 memcpy(&host, &addr->sin_addr.s_addr, sizeof(host));
998 bitmask((bit_t *)&host, (bit_t *)&netmask, sizeof(host));
999 if(!memcmp(&host, &network, sizeof(host)))
1000 return true;
1001
1002 return false;
1003}
1004
1005struct in_addr IPV4Cidr::getBroadcast(void) const
1006{
1007 struct in_addr bcast;
1008 memcpy(&bcast, &network, sizeof(network));
1009 bitimask((bit_t *)&bcast, (bit_t *)&netmask, sizeof(bcast));
1010 return bcast;
1011}
1012
1013unsigned IPV4Cidr::getMask(const char *cp) const
1014{
1015 unsigned dcount = 0;
1016 const char *gp = cp;
1017 const char *mp = strchr(cp, '/');
1018 uint8_t dots[4];
1019#ifdef _MSWINDOWS_
1020 DWORD mask;
1021#else
1022 uint32_t mask;
1023#endif
1024
1025 if(mp) {
1026 if(!strchr(++mp, '.'))
1027 return atoi(mp);
1028
1029 mask = inet_addr(mp);
1030 return bitcount((bit_t *)&mask, sizeof(mask));
1031 }
1032
1033 memset(dots, 0, sizeof(dots));
1034 dots[0] = atoi(cp);
1035 while(*gp && dcount < 3) {
1036 if(*(gp++) == '.')
1037 dots[++dcount] = atoi(gp);
1038 }
1039
1040 if(dots[3])
1041 return 32;
1042
1043 if(dots[2])
1044 return 24;
1045
1046 if(dots[1])
1047 return 16;
1048
1049 return 8;
1050}
1051
1052void IPV4Cidr::set(const char *cp)
1053{
1055 char *ep;
1056 unsigned dots = 0;
1057#ifdef _MSWINDOWS_
1058 DWORD addr;
1059#endif
1060
1061 memset(&netmask, 0, sizeof(netmask));
1062 bitset((bit_t *)&netmask, getMask(cp));
1063 setString(cbuf, sizeof(cbuf), cp);
1064
1065 ep = (char *)strchr(cp, '/');
1066
1067 if(ep)
1068 *ep = 0;
1069
1070 cp = cbuf;
1071 while(NULL != (cp = strchr(cp, '.'))) {
1072 ++dots;
1073 ++cp;
1074 }
1075
1076 while(dots++ < 3)
1077 addString(cbuf, sizeof(cbuf), ".0");
1078
1079#ifdef _MSWINDOWS_
1080 addr = inet_addr(cbuf);
1081 memcpy(&network, &addr, sizeof(network));
1082#else
1083 inet_aton(cbuf, &network);
1084#endif
1085 bitmask((bit_t *)&network, (bit_t *)&netmask, sizeof(network));
1086}
1087
1088
1089
1090
1091#ifdef CCXX_IPV6
1092
1093IPV6Cidr::IPV6Cidr()
1094{
1095 memset(&network, 0, sizeof(network));
1096 memset(&netmask, 0, sizeof(netmask));
1097}
1098
1099IPV6Cidr::IPV6Cidr(const char *cp)
1100{
1101 set(cp);
1102}
1103
1104IPV6Cidr::IPV6Cidr(IPV6Cidr &cidr)
1105{
1106 memcpy(&network, &cidr.network, sizeof(network));
1107 memcpy(&netmask, &cidr.netmask, sizeof(netmask));
1108}
1109
1110bool IPV6Cidr::isMember(const struct in6_addr &addr) const
1111{
1112 struct in6_addr host = addr;
1113
1114 bitmask((bit_t *)&host, (bit_t *)&netmask, sizeof(host));
1115 if(!memcmp(&host, &network, sizeof(host)))
1116 return true;
1117
1118 return false;
1119}
1120
1121bool IPV6Cidr::isMember(const struct sockaddr *saddr) const
1122{
1123 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)saddr;
1124 struct in6_addr host;
1125
1126 if(saddr->sa_family != AF_INET6)
1127 return false;
1128
1129 memcpy(&host, &addr->sin6_addr, sizeof(host));
1130 bitmask((bit_t *)&host, (bit_t *)&netmask, sizeof(host));
1131 if(!memcmp(&host, &network, sizeof(host)))
1132 return true;
1133
1134 return false;
1135}
1136
1137struct in6_addr IPV6Cidr::getBroadcast(void) const
1138{
1139 struct in6_addr bcast;
1140 memcpy(&bcast, &network, sizeof(network));
1141 bitimask((bit_t *)&bcast, (bit_t *)&netmask, sizeof(bcast));
1142 return bcast;
1143}
1144
1145unsigned IPV6Cidr::getMask(const char *cp) const
1146{
1147 unsigned count = 0, rcount = 0;
1148 const char *sp = strchr(cp, '/');
1149 int flag = 0;
1150
1151 if(sp)
1152 return atoi(++sp);
1153
1154 if(!strncmp(cp, "ff00:", 5))
1155 return 8;
1156
1157 if(!strncmp(cp, "fe80:", 5))
1158 return 10;
1159
1160 if(!strncmp(cp, "2002:", 5))
1161 return 16;
1162
1163 sp = strrchr(cp, ':');
1164 while(*(++sp) == '0')
1165 ++sp;
1166 if(*sp)
1167 return 128;
1168
1169 while(*cp && count < 128) {
1170 if(*(cp++) == ':') {
1171 count+= 16;
1172 while(*cp == '0')
1173 ++cp;
1174 if(*cp == ':') {
1175 if(!flag)
1176 rcount = count;
1177 flag = 1;
1178 }
1179 else
1180 flag = 0;
1181 }
1182 }
1183 return rcount;
1184}
1185
1186void IPV6Cidr::set(const char *cp)
1187{
1189 char *ep;
1190
1191 memset(&netmask, 0, sizeof(netmask));
1192 bitset((bit_t *)&netmask, getMask(cp));
1193 setString(cbuf, sizeof(cbuf), cp);
1194 ep = (char *)strchr(cp, '/');
1195 if(ep)
1196 *ep = 0;
1197
1198#ifdef _MSWINDOWS_
1199 int slen = sizeof(network);
1200 WSAStringToAddressA(cbuf, AF_INET6, NULL, (struct sockaddr*)&network, &slen);
1201#else
1202 inet_pton(AF_INET6, cbuf, &network);
1203#endif
1204 bitmask((bit_t *)&network, (bit_t *)&netmask, sizeof(network));
1205}
1206
1207#endif
1208
1209} // namespace ost
Network addresses and sockets related classes.
#define INET_IPV6_ADDRESS_SIZE
Definition: address.h:65
#define INET_IPV4_ADDRESS_SIZE
Definition: address.h:63
static uint8_t cbuf[48]
Definition: car.cpp:41
The network name and address objects are all derived from a common IPV4Address base class.
Definition: address.h:363
IPV4Address(const IPV4Validator *validator=NULL)
Create an Internet Address object with an empty (0.0.0.0) address.
Definition: address.cpp:97
const IPV4Validator * validator
Definition: address.h:370
size_t addr_count
Definition: address.h:374
void setAddress(const char *host)
Used to specify a host name or numeric internet address.
Definition: address.cpp:319
const char * getHostname(void) const
Provide a string representation of the value (Internet Address) held in the IPV4Address object.
Definition: address.cpp:415
struct in_addr * ipaddr
Definition: address.h:373
virtual ~IPV4Address()
Destructor.
Definition: address.cpp:130
static Mutex mutex
Definition: address.h:379
bool operator!=(const IPV4Address &a) const
Compare two internet addresses to see if they are not equal (if they each refer to unique and differe...
Definition: address.cpp:252
bool isInetAddress(void) const
May be used to verify if a given IPV4Address returned by another function contains a "valid" address,...
Definition: address.cpp:152
bool setIPAddress(const char *host)
Sets the IP address from a string representation of the numeric address, ie "127.0....
Definition: address.cpp:293
char * hostname
Definition: address.h:375
bool operator==(const IPV4Address &a) const
Compare two internet addresses to see if they are equal (if they specify the physical address of the ...
Definition: address.cpp:227
struct in_addr getAddress(void) const
Provide a low level system usable struct in_addr object from the contents of IPV4Address.
Definition: address.cpp:142
IPV4Address & operator=(const char *str)
Definition: address.cpp:161
IPV4Broadcast(const char *net="255.255.255.255")
Specify the physical broadcast address to use and create a new broadcast address object based on a nu...
Definition: address.cpp:391
The CIDR class is used to support routing tables and validate address policies.
Definition: address.h:155
struct in_addr netmask network
Definition: address.h:157
void set(const char *cidr)
Set the cidr from a full or partial hostname, or from an address/mask, or a host/bits specification.
Definition: address.cpp:1052
IPV4Cidr()
Construct an empty cidr.
Definition: address.cpp:961
bool isMember(const struct sockaddr *saddr) const
See if a socket address is a member of this cidr's network.
Definition: address.cpp:989
unsigned getMask(const char *cp) const
Definition: address.cpp:1013
This object is used to hold the actual and valid internet address of a specific host machine that wil...
Definition: address.h:579
IPV4Host & operator&=(const IPV4Mask &mask)
Mask the internet host address object with a network mask address.
Definition: address.cpp:258
IPV4Host(const char *host=NULL)
Create a new host address for a specific internet host.
Definition: address.cpp:278
static IPV4Host _host_
Definition: address.h:581
Internet addresses used specifically as masking addresses (such as " 255.255.255.0") are held in the ...
Definition: address.h:537
IPV4Mask(const char *mask)
Create the mask from a null terminated ASCII string such as "255.255.255.128".
Definition: address.cpp:396
void operator()(const in_addr address) const __OVERRIDE
Application operator.
Definition: address.cpp:86
static const IPV4MulticastValidator validator
Check the address in addr is a valid multicast address.
Definition: address.h:687
IPV4Multicast()
Create an Internet Multicast Address object with an empty (0.0.0.0) address.
Definition: address.cpp:468
Classes derived from IPV4Address would require an specific validator to pass to the IPV4Address const...
Definition: address.h:93
void leaveMutex(void)
Definition: thread.h:74
void enterMutex(void)
Definition: thread.h:70
static Throw getException(void)
Get exception mode of the current thread.
Definition: thread.cpp:287
@ throwObject
throw object that cause error (throw this)
Definition: thread.h:414
A class to hold internet segment routing rules.
Definition: socket.h:168
Export interfaces for library interfaces.
Common C++ thread class and sychronization objects.
int stricmp(const char *s1, const char *s2)
Definition: cpr.cpp:95
Definition: address.cpp:63
static void bitimask(bit_t *bits, bit_t *mask, unsigned len)
Definition: address.cpp:922
static void bitmask(bit_t *bits, bit_t *mask, unsigned len)
Definition: address.cpp:916
char * addString(char *target, size_t size, const char *str)
Definition: string.h:67
@ MCAST_VALID_VALUE
Definition: address.cpp:74
@ MCAST_VALID_MASK
Definition: address.cpp:73
struct in_addr getaddress(const IPV4Address &ia)
Definition: address.h:692
char * newString(const char *src, size_t size)
Definition: strchar.cpp:49
IPV4Host operator&(const IPV4Host &addr, const IPV4Mask &mask)
Definition: address.cpp:461
static void bitset(bit_t *bits, unsigned blen)
Definition: address.cpp:928
ostream & operator<<(ostream &os, const IPV4Address &ia)
Definition: address.cpp:908
void delString(char *str)
Definition: strchar.cpp:60
static unsigned bitcount(bit_t *bits, unsigned len)
Definition: address.cpp:943
uint8_t bit_t
Definition: address.cpp:914
char * setString(char *target, size_t size, const char *str)
Definition: string.h:63
static void freeaddrinfo(struct addrinfo *aip)
Definition: socket.cpp:129
const struct sockaddr * addr(Socket::address &address)
A convenience function to convert a socket address list into a socket address.
Definition: socket.h:2089
static int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hintsp, struct addrinfo **res)
Definition: socket.cpp:215
String str(Socket &so, size_t size)
Definition: socket.cpp:3507
struct sockaddr * ai_addr
Definition: socket.cpp:90
struct addrinfo * ai_next
Definition: socket.cpp:91
static bool temp
Definition: zerofill.cpp:29