source: source/ariba/utility/transport/tcpip/protlib/address.h@ 5284

Last change on this file since 5284 was 5284, checked in by mies, 15 years ago

+ added new transport modules and adapted ariba to them
+ exchange endpoint descriptors an link establishment
+ clean up of base communication
+ link establishment with in the presence of multiple endpoints
+ local discovery for ipv6, ipv4 and bluetooth mac addresses

File size: 36.4 KB
Line 
1/// ----------------------------------------*- mode: C++; -*--
2/// @file address.h
3/// GIST address objects
4/// ----------------------------------------------------------
5/// $Id: address.h 3063 2008-07-02 08:02:45Z bless $
6/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/address.h $
7// ===========================================================
8//
9// Copyright (C) 2005-2007, all rights reserved by
10// - Institute of Telematics, Universitaet Karlsruhe (TH)
11//
12// More information and contact:
13// https://projekte.tm.uka.de/trac/NSIS
14//
15// This program is free software; you can redistribute it and/or modify
16// it under the terms of the GNU General Public License as published by
17// the Free Software Foundation; version 2 of the License
18//
19// This program is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22// GNU General Public License for more details.
23//
24// You should have received a copy of the GNU General Public License along
25// with this program; if not, write to the Free Software Foundation, Inc.,
26// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27//
28// ===========================================================
29/** @ingroup ieaddress
30 *
31 * GIST address objects
32 */
33
34#ifndef PROTLIB__ADDRESS_H
35#define PROTLIB__ADDRESS_H
36
37#include "protlib_types.h"
38#include "ie.h"
39
40#include <ext/hash_map>
41#include <netinet/in.h>
42#include <set>
43
44#include "logfile.h"
45#include "threadsafe_db.h"
46
47namespace protlib {
48 using namespace log;
49
50/// Address base class
51/** This is the base class for IP host and application addresses, router,
52 * interface and user identification and AS numbers.
53 */
54class address {
55 public:
56 virtual address* new_instance() const = 0;
57 virtual address* copy() const = 0;
58 virtual bool operator==(const address& address) const = 0;
59
60 inline bool operator!=(const address& address) const {
61 return (!(*this==address));
62 }
63
64
65 enum subtype_t {
66 /** 255 is not a valid subtype and is used to register for all
67 * subtypes.
68 * @note This is no valid subtype because it is not in 0..64.
69 */
70 all_subtypes = 255,
71 // @{
72 /// address subtypes
73 /** These are the address-specific subtypes. */
74 IPv4HostAddress = 1,
75 IPv6HostAddress = 2,
76 IPv4NetAddress = 3,
77 IPv6NetAddress = 4,
78 IPv4ApplAddress = 5,
79 IPv6ApplAddress = 6,
80 IPv6Unspecified = 7,
81 UDSAddress = 8,
82 FlowAddressSpec = 12,
83 AS16 = 14,
84 AS32 = 15,
85 IEEE48 = 16,
86 EUI48 = 17,
87 EUI64 = 18,
88 NAI = 32,
89 X509 = 33
90 // @}
91 }; // end subtype_t
92
93 virtual ~address() {};
94
95 subtype_t get_type() const { return subtype; };
96
97 protected:
98 /// constructor with subtype
99 address(subtype_t st);
100 /// virtual destructor
101
102 void throw_nomem_error() const;
103
104 subtype_t subtype;
105};
106
107// forward declaration
108class netaddress;
109
110/// IP Host Address
111/** This class can hold IPv4 and IPv6 Host Addresses. */
112class hostaddress : public address {
113
114 public:
115 virtual hostaddress* new_instance() const;
116 virtual hostaddress* copy() const;
117 virtual bool operator==(const address& ie) const;
118
119 /// constructor
120 hostaddress();
121 /// copy constructor
122 hostaddress(const hostaddress& h);
123 /// assignment
124 hostaddress& operator=(const hostaddress& h);
125 /// constructor from string
126 hostaddress(const char *str, bool *res = NULL);
127 /// constructor from in6_addr
128 hostaddress(const struct in6_addr& ipv6addr);
129 /// destructor
130 virtual ~hostaddress();
131 /// set IPv4 from string
132 bool set_ipv4(const char *str);
133 /// set IPv4 from in_addr
134 void set_ip(const struct in_addr &in);
135 /// set IPv6 from string
136 bool set_ipv6(const char *str);
137 /// set IPv6 from in6_addr
138 void set_ip(const struct in6_addr &in);
139 /// set IPv4 or IPv6 from string
140 bool set_ip(const char *str);
141 bool set_ip(const string& str);
142 /// set IP from hostaddress
143 void set_ip(const hostaddress& h);
144 /// is IP unspecified
145 bool is_ip_unspec() const;
146 /// get ip address as string
147 const char *get_ip_str() const;
148 /// get ip address as string
149 const char *get_ip_str(char *str) const;
150 /// is it IPv4
151 bool is_ipv4() const;
152 /// is it IPv6
153 bool is_ipv6() const;
154 /// is bogus source (e.g. localhost, multicast)
155 bool is_bogus_source() const;
156 /// is it a 4to6-mapped address?
157 bool is_mapped_ip() const;
158 /// get as in_addr?
159 bool get_ip(struct in_addr& in) const;
160 /// get as in6_addr?
161 bool get_ip(struct in6_addr& in) const;
162 /// get as in6_addr?
163 const struct in6_addr *get_ip() const { return ipv4flag ? 0 : &ipv6addr; };
164 /// convert to iPv6
165 virtual void convert_to_ipv6();
166 /// are they equivalent
167 virtual bool equiv(const hostaddress& h) const;
168 /// lookup host name
169 string get_host_name(bool *res = NULL) const;
170 /// hash function
171 virtual size_t get_hash() const;
172 /// match against IP address
173 virtual int match_against(const hostaddress& ha) const;
174 /// match against network prefix
175 virtual int match_against(const netaddress& na) const;
176protected:
177 /// IPv4 flag
178 bool ipv4flag;
179 /// set subtype and IPv4 flag
180 virtual void set_subtype(bool ipv4);
181 /// IP buffer
182 /** I in protected and NOT private scope because subclasses have to
183 * (de)serialize it.
184 */
185 union {
186 /// IPv4 address
187 struct in_addr ipv4addr;
188 /// IPv6 address
189 struct in6_addr ipv6addr;
190 }; // end union
191public:
192 /// clear IP buffer (sets IP address to undefined/any and deletes any outstring)
193 void clear_ip();
194private:
195 /// pointer to IP string representation
196 mutable char *outstring;
197}; // end hostaddress
198
199inline ostream &operator<<(ostream &out, const hostaddress &addr) {
200 return out << addr.get_ip_str();
201}
202
203inline
204hostaddress::hostaddress(const struct in6_addr& ipv6addr)
205 : address(IPv6HostAddress),
206 ipv4flag(false),
207 ipv6addr(ipv6addr),
208 outstring(NULL)
209{ set_subtype(false); }
210
211
212/// ========================================================
213/// IP Application Address
214/// ========================================================
215/** Consists of a IP Host Address and a port number. */
216class appladdress : public hostaddress {
217 public:
218 virtual appladdress* new_instance() const;
219 virtual appladdress* copy() const;
220 virtual bool operator==(const address& ie) const;
221
222 /// hash function
223 virtual size_t get_hash() const;
224
225 protected:
226 /// set subtype and IPv4 flag
227 virtual void set_subtype(bool ipv4);
228
229 public:
230 /// constructor
231 appladdress();
232 /// copy constructor
233 appladdress(const appladdress& app);
234 ///constructor for use as Unix Domain Address
235 appladdress(string socket);
236 ///constructor for use to specify a explicit socket number (used when no addressing for peer can be derived)
237 appladdress(int socket);
238 /// constructor from hostaddress, protocol ID and port
239 appladdress(const hostaddress& h, protocol_t prot, port_t p);
240 /// constructor from sockaddr_in6 sockaddr
241 appladdress(const sockaddr_in6& sockaddr, protocol_t prot);
242 /// constructor from hostaddress, protocol name and port
243 appladdress(const hostaddress& h, const char* pname, port_t p, bool *res = NULL);
244 /// constructor from string, protocol ID and port
245 appladdress(const char* str, protocol_t prot, port_t p, bool *res = NULL);
246 /// constructor from string, protocol name and port
247 appladdress(const char* str, const char* pname, port_t p, bool *res = NULL);
248 /// constructor from string, protocol name and port name
249 appladdress(const char* str, const char* pname, const char* portname, bool *res = NULL);
250 /// assignment
251 appladdress& operator=(const appladdress& app);
252 /// virtual destructor
253 virtual ~appladdress() {};
254
255
256 /// are they equivalent
257 ///virtual bool equiv(const appladdress& h) const { return hostaddress::equiv(h); }
258
259 /// set port
260 port_t set_port(port_t p);
261 /// set port
262 port_t set_port(const char* pname, bool *res = NULL);
263 /// set port
264 port_t set_port(const string& pname, bool *res = NULL);
265 /// get port
266 port_t get_port() const;
267
268 /// get sockaddr_in6
269 void get_sockaddr(struct sockaddr_in6& sockaddr) const;
270 /// get port name
271 string get_port_name(bool *res = NULL) const;
272 /// set protocol by ID
273 protocol_t set_protocol(protocol_t p);
274 /// set protocol by name
275 protocol_t set_protocol(const char* pname, bool *res = NULL);
276 /// set protocol by name
277 protocol_t set_protocol(const string& pname, bool *res = NULL);
278 /// get protocol ID
279 protocol_t get_protocol() const;
280 /// get protocol name
281 string get_protocol_name(bool *res = NULL) const;
282 /// get prefix
283 inline
284 uint8 get_prefix() const {
285 return prefix;
286 }
287
288 /// set prefix
289 inline
290 void set_prefix(uint8 prfx) {
291 prefix=prfx;
292 }
293
294 /// set IP TTL
295 inline
296 void set_ip_ttl(uint16 ttl) {
297 ip_ttl = ttl;
298 }
299
300
301 /// unset IP TTL
302 inline
303 void unset_ip_ttl() {
304 ip_ttl = 0;
305 }
306
307
308 /// get IP TTL, if == 0, no IP TTL should be set
309 inline
310 uint16 get_ip_ttl() const {
311 return ip_ttl;
312 }
313
314
315 /// set RAO value
316 inline
317 void set_rao(uint16 value) {
318 rao_presence = true;
319 rao = value;
320 }
321
322 /// unset RAO value
323 inline
324 void unset_rao() {
325 rao_presence = false;
326 rao = 0;
327 }
328
329 /// get RAO value
330 inline
331 uint16 get_rao() const {
332 return rao;
333 }
334
335
336 /// test if RAO present
337 inline
338 bool rao_present() const {
339 return rao_presence;
340 }
341
342 /// set outgoing Interface index
343 inline
344 void set_if_index(uint16 value) {
345 if_index = value;
346 }
347
348 /// get outgoing Interface index
349 inline
350 uint16 get_if_index() const {
351 return if_index;
352 }
353
354 /// unset outgoing Interface index
355 inline
356 void unset_if_index() {
357 if_index = 0;
358 }
359
360
361
362
363
364 private:
365 protocol_t proto;
366 port_t port;
367 uint8 prefix;
368
369 uint16 rao;
370 uint16 ip_ttl;
371 bool rao_presence;
372 uint16 if_index;
373
374 }; // end appladdress
375
376
377inline
378appladdress::appladdress(const sockaddr_in6& sockaddr, protocol_t prot)
379 : hostaddress(sockaddr.sin6_addr), proto(prot), port(ntohs(sockaddr.sin6_port)), rao(0), ip_ttl(0), rao_presence(false), if_index(0)
380{
381 //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for sockaddr_in6");
382}
383
384/** Constructor sets address type and clears port sets prefix to 32 (ipv4). */
385inline
386appladdress::appladdress() : hostaddress(),
387 proto(0),
388 port(0),
389 prefix(32),
390 rao(0),
391 ip_ttl(0),
392 rao_presence(false),
393 if_index(0)
394
395{
396 //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for bool ipv4=" << ipv4);
397 set_subtype(ipv4flag);
398} // end constructor
399
400inline
401appladdress::appladdress(const appladdress& app) : hostaddress(app),
402 proto(app.proto),
403 port(app.port),
404 prefix(app.prefix),
405 rao(app.rao),
406 ip_ttl(app.ip_ttl),
407 rao_presence(app.rao_presence),
408 if_index(app.if_index)
409
410{
411 //Log(DEBUG_LOG,LOG_NORMAL,"appladdress", "Copy address constructor called for appladdress& app:" << app);
412 //DLog("appladdress", "UDSsocket copied: " << uds_socket);
413 //DLog("appladdress", "ip_ttl: " << ip_ttl << " if_index: " << if_index);
414
415
416 set_subtype(ipv4flag);
417} // end copy constructor
418
419/** Initialize with the given host address, protocol ID and port number. */
420inline
421appladdress::appladdress(const hostaddress& h, protocol_t prot, port_t p)
422 : hostaddress(h),
423 proto(prot),
424 port(p),
425 prefix(0),
426 rao(0),
427 ip_ttl(0),
428 rao_presence(false),
429 if_index(0)
430{
431 //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for (const hostaddress& h, protocol_t prot, port_t p)");
432
433 set_subtype(ipv4flag);
434} // end constructor(hostaddress,prot,port)
435
436/** Initialize with the given host address, protocol name and port number.
437 * If no protocol ID can be found in the protocol database, it is set to 0.
438 */
439inline
440appladdress::appladdress(const hostaddress& h, const char* pname, port_t p, bool *res)
441 : hostaddress(h),
442 proto(tsdb::getprotobyname(pname,res)),
443 port(p),
444 prefix(0),
445 rao(0),
446 ip_ttl(0),
447 rao_presence(false),
448 if_index(0)
449
450{
451 //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for (const hostaddress& h, const char* pname, port_t p, bool *res)");
452
453 set_subtype(ipv4flag);
454} // end constructor(hostaddress,pname,port)
455
456/** Initialize from string, protocol ID and port.
457 * If the string does not contain a vaild IP address, it is set to all 0 by
458 * the hostaddress constructor.
459 */
460inline
461appladdress::appladdress(const char* str, protocol_t prot, port_t p, bool *res)
462 : hostaddress(str,res),
463 proto(prot),
464 port(p),
465 prefix(0),
466 rao(0),
467 ip_ttl(0),
468 rao_presence(false),
469 if_index(0)
470{
471 set_subtype(ipv4flag);
472} // end constructor(string,prot,port)
473
474/** Initialize from string, protocol name and port.
475 * If the string does not contain a vaild IP address, it is set to all 0 by
476 * the hostaddress constructor.
477 * If no protocol ID can be found in the protocol database, it is set to 0.
478 */
479inline
480appladdress::appladdress(const char* str, const char* pname, port_t p, bool *res)
481 : hostaddress(str,res),
482 port(p),
483 prefix(0),
484 rao(0),
485 ip_ttl(0),
486 rao_presence(false),
487 if_index(0)
488{
489 //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for (const char* str, const char* pname, port_t p, bool *res)");
490
491 register bool tmpres = false;
492 proto = tsdb::getprotobyname(pname,&tmpres);
493 if (res) *res = ((*res) && tmpres);
494 set_subtype(ipv4flag);
495} // end constructor(string,pname,port)
496
497/** Initialize from string, protocol name and port name.
498 * If the string does not contain a vaild IP address, it is set to all 0 by
499 * the hostaddress constructor.
500 * If no protocol ID can be found in the protocol database, it is set to 0.
501 * If no port number can be found in the service database, it is set to 0.
502 */
503inline
504appladdress::appladdress(const char* str, const char* pname, const char* portname, bool *res)
505 : hostaddress(str,res),
506 prefix(0),
507 rao(0),
508 ip_ttl(0),
509 rao_presence(false),
510 if_index(0)
511{
512 //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for (const char* str, const char* pname, const char* portname, bool *res)");
513
514 bool res1 = false;
515 bool res2 = false;
516 proto = tsdb::getprotobyname(pname,&res1);
517 port = tsdb::get_portnumber(portname,proto,&res2);
518 if (res) *res = ((*res) && res1 && res2);
519 set_subtype(ipv4flag);
520 prefix = 0;
521} // end constructor(string,pname,portname)
522
523/** Assigns the given application address by using hostaddress::operator=(). */
524inline
525appladdress&
526appladdress::operator=(const appladdress& app)
527{
528 hostaddress::operator=(app);
529 proto = app.proto;
530 port = app.port;
531 prefix = app.prefix;
532 ip_ttl = app.ip_ttl;
533 rao_presence = app.rao_presence;
534 rao = app.rao;
535 if_index = app.if_index;
536 return *this;
537} // end operator=
538
539
540/** Set port and return old value. */
541inline
542port_t appladdress::set_port(port_t p) {
543 register port_t op = port;
544 port = p;
545 return op;
546} // end set_port
547
548
549
550/** Set port and return old value.
551 * If the port name is not found in the service database, port is set to 0.
552 */
553inline
554port_t appladdress::set_port(const char* pname, bool *res) {
555 register port_t op = port;
556 port = tsdb::get_portnumber(pname,proto,res);
557 return op;
558} // end set_port
559
560/** Set port and return old value.
561 * If the port name is not found in the service database, port is set to 0.
562 */
563inline
564port_t appladdress::set_port(const string& pname, bool *res) {
565 register port_t op = port;
566 port = tsdb::get_portnumber(pname,proto,res);
567 return op;
568} // end set_port
569
570inline
571port_t appladdress::get_port() const { return port; }
572
573inline
574string appladdress::get_port_name(bool *res) const {
575 return tsdb::get_portname(port,proto,res);
576} // end get_port_name
577
578/** Set protocol ID and return old value. */
579inline
580protocol_t appladdress::set_protocol(protocol_t p) {
581 register protocol_t o = proto;
582 proto = p;
583 return o;
584} // end set_protocol
585
586/** Set protocol ID and return old value.
587 * If no protocol ID can be found in the protocol database, it is set to 0.
588 */
589inline
590protocol_t appladdress::set_protocol(const char* pname, bool *res) {
591 register protocol_t o = proto;
592 proto = tsdb::getprotobyname(pname,res);
593 return o;
594} // end set_protocol
595
596/** Set protocol ID and return old value.
597 * If no protocol ID can be found in the protocol database, it is set to 0.
598 */
599inline
600protocol_t appladdress::set_protocol(const string& pname, bool *res) {
601 register protocol_t o = proto;
602 proto = tsdb::getprotobyname(pname,res);
603 return o;
604} // end set_protocol
605
606inline
607protocol_t appladdress::get_protocol() const { return proto; }
608
609inline
610string appladdress::get_protocol_name(bool *res) const {
611 return tsdb::getprotobynumber(proto,res);
612} // end get_protocol_name
613
614inline
615size_t appladdress::get_hash() const {
616 uint32 tmp = (proto<<16)+port;
617 return (hostaddress::get_hash() ^ tmp);
618} // end get_hash
619
620inline
621void
622appladdress::get_sockaddr(struct sockaddr_in6& sa) const
623{
624 if (!ipv4flag)
625 {
626 sa.sin6_family= PF_INET6;
627 sa.sin6_port = htons(port);
628 sa.sin6_addr = ipv6addr;
629 }
630}
631
632/// Network Prefix (or net address)
633/** Holds an IP address and a prefix length in bits. */
634class netaddress : public hostaddress {
635/***** inherited from IE ****/
636public:
637 virtual netaddress* new_instance() const;
638 virtual netaddress* copy() const;
639 virtual bool operator==(const address& ie) const;
640
641 /// convert to iPv6
642 virtual void convert_to_ipv6();
643 /// hash function
644 virtual size_t get_hash() const;
645 virtual int match_against(const netaddress& na) const;
646protected:
647 /// set subtype and IPv4 flag
648 virtual void set_subtype(bool ipv4);
649/***** new members *****/
650public:
651 /// constructor
652 netaddress();
653 /// copy constructor
654 netaddress(const netaddress& na);
655 /// constructor from hostaddress and prefix length
656 netaddress(const hostaddress& h, prefix_length_t len = 128);
657 /// constructor from string
658 netaddress(const char* str, bool *res = NULL);
659 /// constructor from string and prefix length
660 netaddress(const char* str, prefix_length_t len, bool *res = NULL);
661 /// assignment
662 netaddress& operator=(const netaddress& na);
663 /// assignment
664 netaddress& operator=(const hostaddress& ha);
665
666 // set prefix length
667 prefix_length_t set_pref_len(prefix_length_t len);
668 // get prefix length
669 prefix_length_t get_pref_len() const;
670 /// comparison for prefixmap
671 bool operator<(const netaddress& na) const;
672
673 int rdx_cmp(const netaddress *na, int *pos) const;
674private:
675 prefix_length_t prefix_length;
676}; // end netaddress
677
678inline ostream &operator<<(ostream &out, const netaddress &addr) {
679 return out << addr.get_ip_str() << "/" << (int)addr.get_pref_len();
680}
681
682/// Unix Domain Socket Address
683/** This class can hold a Unix Domain Socket Address OR a Socket Number. */
684class udsaddress : public address {
685
686 public:
687 virtual udsaddress* new_instance() const;
688 virtual udsaddress* copy() const;
689 virtual bool operator==(const address& ie) const;
690
691 /// constructor
692 udsaddress() : address(UDSAddress) { uds_socket = ""; socknum=0;};
693 /// copy constructor
694 udsaddress(const udsaddress& h) : address(UDSAddress) { uds_socket = string(h.uds_socket.c_str()); socknum = h.socknum; };
695 /// assignment
696 udsaddress& operator=(const udsaddress& uds) {
697 uds_socket = string(uds.uds_socket);
698 socknum = uds.socknum;
699 return *this;
700 };
701 /// constructor from string
702 udsaddress(string sockstring): address(UDSAddress) { uds_socket = string(sockstring.c_str()); socknum=0; };
703 /// constructor from int
704 udsaddress(int num): address(UDSAddress) { socknum = num; uds_socket=""; };
705 /// constructor from both
706 udsaddress(string sockstring, int num): address(UDSAddress) { socknum = num; uds_socket=string(sockstring.c_str()); };
707 /// destructor
708 virtual ~udsaddress() {};
709
710 /// hash function
711 virtual size_t get_hash() const;
712
713private:
714 /// uds socket string
715 string uds_socket;
716 /// socket number
717 int socknum;
718
719public:
720
721/** Set UDS socket path. */
722inline
723void set_udssocket(string socket) {
724 uds_socket = socket;
725} // end set_uds socket path
726
727
728/** Get UDS socket path. */
729inline
730const string get_udssocket() const {
731 return uds_socket;
732} // end get_udspath
733
734
735/** Set Socket Number */
736inline
737void set_socknum(int socket) {
738 socknum = socket;
739} // end set_socknum
740
741/** Get Socket Number */
742inline
743const int get_socknum() const {
744 return socknum;
745} // end get_socknum
746
747
748
749}; // end udsaddress
750
751template <typename _dT>
752class RadixTrie {
753public:
754 typedef _dT data_type;
755
756 struct node {
757 node(netaddress *k, data_type *d) : key(k), data(d) {
758 left = right = this;
759 index = 0;
760 }
761 ~node() {
762 if (data)
763 delete data;
764 if (key)
765 delete key;
766 if (left != 0 && left->index > index)
767 delete left;
768 if (right != 0 && right->index > index)
769 delete right;
770 }
771 node *left;
772 node *right;
773 netaddress *key;
774 data_type *data;
775 int index;
776 };
777
778 RadixTrie() {
779 netaddress *def;
780 def = new netaddress("0.0.0.0", (prefix_length_t)0);
781 v4head = new node(def, 0);
782 def = new netaddress("::", (prefix_length_t)0);
783 v6head = new node(def, 0);
784 }
785
786 ~RadixTrie() {
787 delete v4head;
788 delete v6head;
789 }
790
791 node *insert(netaddress &key, data_type &dat) {
792 node *a, *b, *c, *n, *m;
793 int cmp, pos = 0;
794
795 c = a = key.is_ipv4() ? v4head : v6head;
796
797 // search the tree as long as there are bits left in key
798 while (key.get_pref_len() > a->index) {
799
800 // compare key to key in node a from position a->index
801 pos = a->index - 1;
802 cmp = key.rdx_cmp(a->key, &pos);
803 if (pos < 0)
804 abort();
805
806 // in case of a perfect match
807 if ((cmp == 0) &&
808 (a->key->get_pref_len() == key.get_pref_len())) {
809 // replace data in node
810 if (a->data)
811 delete a->data;
812 a->data = &dat;
813 return a;
814 }
815
816 if (cmp == 0)
817 break;
818
819 // select node to continue the search based on the
820 // first different bit between a and key
821 b = cmp < 0 ? a->left : a->right;
822
823 // we reached a dead end
824 if (b->index <= a->index)
825 break;
826
827 // the first difference was before a's bitmask ended
828 // we must not make any more progress
829 if (pos <= a->key->get_pref_len())
830 break;
831
832 c = a;
833 a = b;
834 }
835
836 // first check if a and key share a common prefix
837 if ((key.get_pref_len() == a->key->get_pref_len()) ||
838 (pos > a->index && pos <= a->key->get_pref_len())) {
839 int opos = pos;
840
841 // make sure we didn't just miss the perfect match
842 pos = a->index;
843 cmp = key.rdx_cmp(a->key, &pos);
844 if (cmp == 0 &&
845 (a->key->get_pref_len() == key.get_pref_len())) {
846 // replace data in node
847 if (a->data)
848 delete a->data;
849 a->data = &dat;
850 return a;
851 }
852
853 // create a node with that prefix
854 pos = opos;
855 n = new node(new netaddress(key), 0);
856 n->key->set_pref_len(pos - 1);
857
858 // hook it to the previous node(c)
859 pos = c->index;
860 cmp = n->key->rdx_cmp(c->key, &pos);
861 n->index = pos;
862 if (n->index <= c->index) {
863 cout << "DEAD NODE INSERTION!!!" << endl;
864 abort();
865 }
866 if (cmp < 0) {
867 if (c->left != a) {
868 cout << "TREE CORRUPTION!!!" << endl;
869 abort();
870 }
871 c->left = n;
872 } else {
873 if (c->right != a) {
874 cout << "TREE CORRUPTION!!!" << endl;
875 abort();
876 }
877 c->right = n;
878 }
879
880 // hook the current node(a) to the common prefix
881 // node(n)
882 pos = n->index;
883 cmp = a->key->rdx_cmp(n->key, &pos);
884 a->index = pos;
885 if (a->index <= n->index) {
886 cout << "DEAD NODE INSERTION!!!" << endl;
887 abort();
888 }
889 if (cmp < 0)
890 n->left = a;
891 else
892 n->right = a;
893
894 // create a new node(m) for the insert
895 m = new node(new netaddress(key), &dat);
896 // hook node(m) to the common prefix node(n)
897 pos = n->index;
898 cmp = m->key->rdx_cmp(n->key, &pos);
899 m->index = pos;
900 if (cmp < 0) {
901 if (n->left == a) {
902 cout << "OVERWRITE!!!" << endl;
903 abort();
904 }
905 n->left = m;
906 } else {
907 if (n->right == a) {
908 cout << "OVERWRITE!!!" << endl;
909 abort();
910 }
911 n->right = m;
912 }
913
914 return m;
915 }
916
917 // c is a prefix of key, key is a prefix of a
918 if (a->index >= pos) {
919 // create a new node for the key
920 n = new node(new netaddress(key), &dat);
921 // hook it to the previous node(c)
922 n->index = pos;
923 if (n->index <= c->index) {
924 cout << "DEAD NODE INSERTION!!!" << endl;
925 abort();
926 }
927 if (cmp < 0) {
928 if (c->left != a) {
929 cout << "TREE CORRUPTION!!!" << endl;
930 abort();
931 }
932 c->left = n;
933 } else {
934 if (c->right != a) {
935 cout << "TREE CORRUPTION!!!" << endl;
936 abort();
937 }
938 c->right = n;
939 }
940
941 // hook the current node(a) to the newly created
942 // node(n)
943 pos = n->index;
944 cmp = a->key->rdx_cmp(n->key, &pos);
945 a->index = pos;
946 if (a->index <= c->index) {
947 cout << "DEAD NODE INSERTION!!!" << endl;
948 abort();
949 }
950 if (cmp < 0)
951 n->left = a;
952 else
953 n->right = a;
954
955 return n;
956 }
957
958 // reached a deadend, simply add a new node
959 n = new node(new netaddress(key), &dat);
960 n->index = pos;
961 if (n->index <= a->index) {
962 cout << "DEAD NODE INSERTION!!!" << endl;
963 abort();
964 }
965 if (b->index <= a->index) {
966 if (cmp < 0)
967 a->left = n;
968 else
969 a->right = n;
970 } else {
971 cout << "TREE CORRUPTION!!!" << endl;
972 abort();
973 }
974
975 return n;
976 }
977
978 node *lookup_node(netaddress &key, bool lpfm = true,
979 bool with_data = true) {
980 node *a, *b, *c, *lpfn;
981 int cmp, pos = 0;
982
983 lpfn = 0;
984 c = b = a = key.is_ipv4() ? v4head : v6head;
985 if (lpfm) {
986 if (!with_data)
987 lpfn = a;
988 else if (a->data)
989 lpfn = a;
990 }
991
992 // search the tree as long as there are bits left in key
993 while (key.get_pref_len() > a->index) {
994
995 // compare key to key in node a from pos
996 pos--;
997 cmp = key.rdx_cmp(a->key, &pos);
998
999 // all of key consumed
1000 if (cmp == 0) {
1001 // key is less specific than a
1002 if (key.get_pref_len() <
1003 a->key->get_pref_len())
1004 return lpfm ? lpfn : NULL;
1005
1006 // key is an exact match for a
1007 if (key.get_pref_len() >=
1008 a->key->get_pref_len()) {
1009 if (!with_data)
1010 return a;
1011 if (a->data)
1012 return a;
1013 return lpfm ? lpfn : NULL;
1014 }
1015 }
1016
1017 // all of a consumed -> a is a prefix of key
1018 if (pos > a->key->get_pref_len()) {
1019 if (!with_data)
1020 lpfn = a;
1021 else if (a->data)
1022 lpfn = a;
1023 }
1024
1025 // select node to continue the search based on the
1026 // first different bit between a and key
1027 b = cmp < 0 ? a->left : a->right;
1028
1029 // we reached a dead end
1030 if (b->index <= a->index)
1031 break;
1032
1033 c = a;
1034 a = b;
1035 }
1036
1037 return lpfm ? lpfn : NULL;
1038 }
1039
1040 data_type *lookup(netaddress &key, bool lpfm = true) {
1041 node *n = lookup_node(key, lpfm);
1042
1043 return n ? n->data : NULL;
1044 }
1045
1046 bool remove(netaddress &key) {
1047 node *n = lookup_node(key);
1048
1049 if (n && n->data) {
1050 delete n->data;
1051 n->data = NULL;
1052 }
1053
1054 return (n != 0);
1055 }
1056
1057 bool remove_all(netaddress &key) {
1058 node *n = lookup_node(key, false, false);
1059
1060 if (n == 0)
1061 return false;
1062
1063 if (n->data) {
1064 delete n->data;
1065 n->data = NULL;
1066 }
1067
1068 if (n->left->index > n->index) {
1069 delete n->left;
1070 n->left = n;
1071 }
1072 if (n->right->index > n->index) {
1073 delete n->right;
1074 n->right = n;
1075 }
1076
1077 return true;
1078 }
1079
1080 void print() {
1081 cout << "v4_TREE: " << endl;
1082 print_node(v4head);
1083 cout << "v6_TREE: " << endl;
1084 print_node(v6head);
1085 }
1086
1087 void print_node(node *x, bool decent = true) {
1088 if (x && x->key) {
1089 cout << "node: " << x << " key: " << *x->key;
1090 if (x->data != 0)
1091 cout << " data: " << x->data;
1092 else
1093 cout << " data: NULL";
1094 cout << " index: " << x->index << endl;
1095 cout << "\tleft: " << x->left << " right: " << x->right << endl;
1096 if (decent) {
1097 if (x->left->index > x->index)
1098 print_node(x->left);
1099 if (x->right->index > x->index)
1100 print_node(x->right);
1101 }
1102 }
1103 }
1104
1105private:
1106 struct node *v4head;
1107 struct node *v6head;
1108};
1109
1110
1111/*
1112 * AddressList
1113 */
1114
1115class AddressList {
1116public:
1117 class AddrProperty {
1118 public:
1119 AddrProperty(const char *name) {
1120 pname = new string(name);
1121 }
1122 ~AddrProperty() {
1123 delete pname;
1124 };
1125
1126 string *pname;
1127 };
1128
1129 // Default properties, N.B. Ignore will remove all other properties
1130 static AddrProperty *LocalAddr_P;
1131 static AddrProperty *ConfiguredAddr_P;
1132
1133private:
1134 // This is special
1135 static AddrProperty *IgnoreAddr_P;
1136 static AddrProperty *AnyAddr_P;
1137
1138public:
1139 struct ltstr {
1140 bool operator()(const char* s1, const char* s2) const
1141 { return strcmp(s1, s2) < 0; }
1142 };
1143 struct ltna {
1144 bool operator()(const netaddress &s1, const netaddress &s2)
1145 const {
1146 if (s1.is_ipv4() != s2.is_ipv4())
1147 return (s1.is_ipv4());
1148 int cmp, pos = 0;
1149 cmp = s1.rdx_cmp(&s2, &pos);
1150 return (cmp < 0);
1151 }
1152
1153 };
1154 typedef set<char *, ltstr> iflist_t;
1155 typedef set<netaddress, ltna> addrlist_t;
1156
1157 AddressList();
1158 ~AddressList();
1159
1160 // Configure by interfaces
1161 // Return a list of all local interfaces, which are monitored
1162 iflist_t *get_interfaces();
1163 // Begin interface list (otherwise the following have no effect)
1164 // If start_empty is true use an empty list, otherwise add all
1165 // currently configured interfaces
1166 bool by_interface(bool start_empty = true);
1167 // Add interface to monitoring
1168 bool add_interface(char *name);
1169 // Remove interface from monitoring
1170 bool del_interface(char *name);
1171
1172 // Manage properties
1173 // If 'all' is true operate on all matching addresses as well
1174 bool add_property(netaddress &na, AddrProperty *p = ConfiguredAddr_P,
1175 bool propagate = true);
1176 bool del_property(netaddress &na, AddrProperty *p = ConfiguredAddr_P,
1177 bool propagate = true);
1178 inline bool purge_properties(netaddress &na, bool prop = true) {
1179 return del_property(na, AnyAddr_P, prop);
1180 };
1181 bool add_host_prop(const char *name, AddrProperty *p = ConfiguredAddr_P);
1182 bool del_host_prop(const char *name, AddrProperty *p = ConfiguredAddr_P);
1183 inline bool purge_host_prop(const char *name) {
1184 return del_host_prop(name, AnyAddr_P);
1185 }
1186
1187 // Special property
1188 bool ignore(netaddress &na, bool propagate = true);
1189 bool unignore(netaddress &na, bool propagate = true);
1190 bool ignore_bogons(void);
1191 bool ignore_locals(void);
1192 bool ignore_loopback(void);
1193
1194 // Check if the given address has the given property
1195 bool addr_is(netaddress &na, AddrProperty *prop);
1196 bool addr_is(const hostaddress &ha, AddrProperty *prop) {
1197 netaddress na(ha);
1198 return addr_is(na, prop);
1199 }
1200 // Check if the given address is in a network with the given property
1201 bool addr_is_in(netaddress &na, AddrProperty *prop);
1202 bool addr_is_in(const hostaddress &ha, AddrProperty *prop) {
1203 netaddress na(ha);
1204 return addr_is_in(na, prop);
1205 }
1206
1207 addrlist_t *get_addrs(AddrProperty *prop = LocalAddr_P);
1208 netaddress *get_first(AddrProperty *p = LocalAddr_P, bool IPv4 = true);
1209
1210 netaddress *get_src_addr(const netaddress &dest, uint32_t *prefs);
1211private:
1212 typedef map<AddrProperty *, bool> propmap_t;
1213 typedef RadixTrie<propmap_t> addr2prop_t;
1214
1215 iflist_t *interfaces;
1216 addr2prop_t prop_trie;
1217
1218 // Backends for public functions
1219 void getifaddrs_iflist(iflist_t &list);
1220 bool getifaddrs_is_local(netaddress &na);
1221 void getifaddrs_get_addrs(addrlist_t &list);
1222
1223 void bequeath(addr2prop_t::node *head, AddrProperty *p,
1224 bool add = true);
1225 void collect(addr2prop_t::node *head, AddrProperty *p,
1226 addrlist_t &list);
1227 addr2prop_t::node *collect_first(addr2prop_t::node *head,
1228 AddrProperty *p);
1229};
1230
1231inline ostream &operator<<(ostream &out, const AddressList::AddrProperty &prop) {
1232 return out << *prop.pname;
1233}
1234
1235
1236/************************************* inline methods ***********************************/
1237
1238inline
1239size_t
1240hostaddress::get_hash() const
1241{
1242 return (ipv6addr.s6_addr32[0] ^ ipv6addr.s6_addr32[1] ^ ipv6addr.s6_addr32[2] ^ ipv6addr.s6_addr32[3]);
1243} // end get_hash
1244
1245/***** new in hostaddress *****/
1246
1247
1248/** Initialize a hostaddress object.
1249 * This calls virtual member set_subtype and therefore sets subtype in all
1250 * derived class which overwrite this member function correctly.
1251 */
1252inline
1253hostaddress::hostaddress()
1254 : address(IPv6HostAddress),
1255 ipv4flag(false),
1256 outstring(NULL)
1257{
1258 clear_ip();
1259 set_subtype(false);
1260} // end constructor hostaddress
1261
1262
1263/** Assign h to this object. */
1264inline
1265hostaddress&
1266hostaddress::operator=(const hostaddress& h) {
1267 address::operator=(h);
1268 this->set_ip(h);
1269 if (outstring)
1270 delete outstring;
1271 outstring= 0;
1272 return *this;
1273} // end operator=
1274
1275/** Copy constructor for hostaddress objects */
1276inline
1277hostaddress::hostaddress(const hostaddress& h) :
1278 address(h),
1279 outstring(NULL)
1280{
1281 this->set_ip(h);
1282
1283 //Log(DEBUG_LOG,LOG_NORMAL,"hostaddress","hostaddress constructor called for const hostaddress& h:"); // << h << " outstring:" << static_cast<void*>(outstring) << " h.outstring:" << static_cast<void*>(h.outstring));
1284
1285} // end copy constructor hostaddress
1286
1287/** Check if this is an IPv4 address. */
1288inline
1289bool
1290hostaddress::is_ipv4() const {
1291 return ipv4flag;
1292} // end is_ipv4
1293
1294/** Check if this is an IPv6 address. */
1295inline
1296bool
1297hostaddress::is_ipv6() const {
1298 return (!ipv4flag);
1299} // end is_ipv6
1300
1301/** Check if this is a 6to4 mapped address. */
1302inline
1303bool
1304hostaddress::is_mapped_ip() const
1305{
1306 return (ipv4flag) ? false : IN6_IS_ADDR_V4MAPPED(ipv6addr.s6_addr);
1307} // end is_mapped_ip
1308
1309inline
1310bool
1311hostaddress::set_ip(const string& str) { return set_ip(str.c_str()); }
1312
1313inline
1314/** Delete outstring if it exists. */
1315hostaddress::~hostaddress() {
1316 if (outstring)
1317 {
1318 delete[] outstring;
1319 outstring= 0;
1320 }
1321} // end destructor hostaddress
1322
1323/** Set IPv4 or IPv6 from string or leave object unchanged.
1324 * This changes object type.
1325 * @return true on success.
1326 */
1327inline
1328bool
1329hostaddress::set_ip(const char *str)
1330{
1331 return (!str) ? false :
1332 ( strchr(str,':') ? set_ipv6(str) : set_ipv4(str)); // which IP version?
1333
1334} // end set_ipv
1335
1336
1337/** Lookup the host name associated with the current IP address. */
1338inline
1339string hostaddress::get_host_name(bool *res) const
1340{
1341 return ipv4flag ? tsdb::get_hostname(ipv4addr,res) : tsdb::get_hostname(ipv6addr,res);
1342} // end get_host_name
1343
1344/***** inherited from hostaddress *****/
1345
1346/** Set subtype and IPv4 flag. This does NOT clear the outstring buffer.
1347 * Use clear_ip().
1348 */
1349inline
1350void
1351appladdress::set_subtype(bool ipv4)
1352{
1353 ipv4flag = ipv4;
1354 subtype = (ipv4) ? IPv4ApplAddress : IPv6ApplAddress;
1355} // end set_subtype
1356
1357inline
1358prefix_length_t netaddress::get_pref_len() const { return prefix_length; }
1359
1360inline
1361size_t netaddress::get_hash() const {
1362 return (hostaddress::get_hash() ^ prefix_length);
1363} // end get_hash
1364
1365inline
1366int
1367netaddress::match_against(const netaddress& na) const
1368{
1369 // compare prefix lengths
1370 return (prefix_length<na.prefix_length) ? -1 : hostaddress::match_against(na);
1371} // end match_against
1372
1373
1374inline
1375ostream &operator<<(ostream &out, const appladdress &addr) {
1376 if (addr.is_mapped_ip()) return out << "[IPv4-mapped address]: " << addr.get_ip_str() << ":" << (int)addr.get_port() << ", " << addr.get_protocol_name();
1377 return out << "[IP address]: " << addr.get_ip_str() << ":" << (int)addr.get_port() << ", " << addr.get_protocol_name();
1378}
1379
1380inline
1381ostream &operator<<(ostream &out, const udsaddress &addr) {
1382 if (addr.get_socknum()) return out << "[Socketnumber]: " << addr.get_socknum();
1383 return out << "[Unix Domain Socket]: " << addr.get_udssocket();
1384}
1385
1386
1387
1388
1389
1390
1391inline
1392size_t udsaddress::get_hash() const {
1393 size_t tmp2 = 1;
1394 for (unsigned int i = 0; i<uds_socket.size(); i++) {
1395 tmp2 = tmp2 * (int) uds_socket[i];
1396 }
1397 return (tmp2 ^ socknum);
1398} // end get_hash
1399
1400
1401
1402} // end namespace protlib
1403
1404/*********************************** hash functions ***********************************/
1405
1406namespace __gnu_cxx {
1407/// hostaddress hasher
1408template <> struct hash<protlib::hostaddress> {
1409 inline size_t operator()(const protlib::hostaddress& addr) const { return addr.get_hash(); }
1410}; // end hostaddress hasher
1411
1412/// appladdress hasher
1413template <> struct hash<protlib::appladdress> {
1414 inline size_t operator()(const protlib::appladdress& addr) const { return addr.get_hash(); }
1415}; // end appladdress hasher
1416
1417/// udsaddress hasher
1418template <> struct hash<protlib::udsaddress> {
1419 inline size_t operator()(const protlib::udsaddress& addr) const { return addr.get_hash(); }
1420}; // end udsaddress hasher
1421
1422
1423
1424
1425/// netaddress hasher
1426template <> struct hash<protlib::netaddress> {
1427 inline size_t operator() (const protlib::netaddress& addr) const { return addr.get_hash(); }
1428}; // end netaddress hasher
1429
1430} // end namespace __gnu_cxx
1431
1432
1433namespace std {
1434
1435/// hostaddress equal_to
1436template <> struct equal_to<protlib::hostaddress> {
1437 inline bool operator()(const protlib::hostaddress& addr1, const protlib::hostaddress& addr2) const { return addr1.equiv(addr2); }
1438}; // end hostaddress equal_to
1439
1440/// appladdress equal_to
1441template <> struct equal_to<protlib::appladdress> {
1442 inline bool operator()(const protlib::appladdress& addr1, const protlib::appladdress& addr2) const { return addr1.equiv(addr2); }
1443}; // end appladdress equal_to
1444
1445/// netaddress equal_to
1446template <> struct equal_to<protlib::netaddress> {
1447 inline bool operator()(const protlib::netaddress& addr1, const protlib::netaddress& addr2) const { return addr1.equiv(addr2); }
1448
1449}; // end netaddress equal_to
1450
1451} // end namespace std
1452#endif // PROTLIB__ADDRESS_H
Note: See TracBrowser for help on using the repository browser.