An Overlay-based
Virtual Network Substrate
SpoVNet

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

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

Fixed tons of warnings when using CXXFLAGS="-Wall"!

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