source: source/ariba/communication/modules/transport/protlib/address.h@ 5638

Last change on this file since 5638 was 5638, checked in by Christoph Mayer, 15 years ago

adress detection aufgeräumt, network info für bleutooth, data stream (hopeful crash fix), logging auf maemo nur warn, ...

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.