An Overlay-based
Virtual Network Substrate
SpoVNet

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

Last change on this file since 7018 was 7018, checked in by mies, 14 years ago
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 <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;
692dsdsd
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.