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

Last change on this file since 9990 was 9686, checked in by mies, 14 years ago

put protlib doc to protlib module

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