An Overlay-based
Virtual Network Substrate
SpoVNet

source: source/ariba/utility/transport/tcpip/protlib/address.cpp @ 5876

Last change on this file since 5876 was 5876, checked in by mies, 14 years ago
File size: 37.6 KB
Line 
1/// ----------------------------------------*- mode: C++; -*--
2/// @file address.cpp
3/// GIST address objects
4/// ----------------------------------------------------------
5/// $Id: address.cpp 3046 2008-06-18 14:40:43Z hiwi-laier $
6/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/address.cpp $
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 * GIST address objects
31 */
32
33#include <sys/types.h>
34#include <sys/socket.h>
35
36#include "address.h"
37#include "threadsafe_db.h"
38#include "logfile.h"
39
40#include <net/if.h>
41#include <netinet/in.h>
42#include <arpa/inet.h>
43#include <ifaddrs.h>
44#include <iomanip>
45#include <netdb.h>
46
47namespace protlib {
48
49/** @addtogroup ieaddress Address Objects
50 * @{
51 */
52  using namespace log;
53/***** class address *****/
54
55/** Set subtype. */
56address::address(subtype_t st) 
57        : subtype(st) 
58{ 
59  //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for " << (void *) this);
60}
61
62/** Log and throw a nomem_error */
63void address::throw_nomem_error() const {
64        try {
65          ERRCLog("address", "Not enough memory for address");
66        } catch(...) {}
67        throw IEError(IEError::ERROR_NO_MEM);
68} // end throw_nomem_error
69
70
71/***** class hostaddress *****/
72
73/***** inherited from IE *****/
74
75hostaddress* hostaddress::new_instance() const {
76        hostaddress* ha = NULL;
77        catch_bad_alloc(ha = new hostaddress());
78        return ha;
79} // end new_instance
80
81hostaddress* hostaddress::copy() const {
82        hostaddress* ha = NULL;
83        catch_bad_alloc(ha =  new hostaddress(*this));
84        return ha;
85} // end copy
86
87bool hostaddress::operator==(const address& ie) const {
88        const hostaddress* haddr = dynamic_cast<const hostaddress*>(&ie);
89        if (haddr) {
90#ifdef DEBUG_HARD
91          Log(DEBUG_LOG,LOG_NORMAL,"hostaddress","::operator==()" << haddr->get_ip_str()<<"=="<<this->get_ip_str());
92          if (!ipv4flag)
93            Log(DEBUG_LOG,LOG_NORMAL,"hostaddress","::operator==(), v6=" << IN6_ARE_ADDR_EQUAL(ipv6addr.s6_addr, haddr->ipv6addr.s6_addr));
94#endif
95          return ipv4flag ? (ipv4addr.s_addr==haddr->ipv4addr.s_addr) :
96                            IN6_ARE_ADDR_EQUAL(ipv6addr.s6_addr, haddr->ipv6addr.s6_addr);
97        } else return false;
98} // end operator==
99
100/***** new in hostaddress *****/
101
102
103/** Initialize hostaddress from string if possible. */
104hostaddress::hostaddress(const char *str, bool *res) 
105        : address(IPv6HostAddress),
106          ipv4flag(false), 
107          outstring(NULL)
108{
109        register bool tmpres = false;
110        clear_ip();
111        tmpres = set_ip(str);
112        if (res) *res = tmpres;
113} // end string constructor hostaddress
114
115
116/** Set IPv4 from string or leave object unchanged.
117 * This changes object type to IPv4.
118 * @return true on success.
119 */
120bool 
121hostaddress::set_ipv4(const char *str) {
122        struct in_addr in;
123        if (str && (inet_pton(AF_INET,str,&in)>0)) {
124                set_ip(in);
125                return true;
126        } else return false;
127} // end set_ipv4
128
129/** Set IPv4 address from struct in_addr.
130 * This changes object type to IPv4.
131 */
132void hostaddress::set_ip(const struct in_addr &in) {
133        clear_ip();
134        ipv4addr = in; 
135        // set subtype to IPv4
136        set_subtype(true);
137        return;
138} // end set_ip(in_addr)
139
140/** Set IPv6 from string or leave object unchanged.
141 * This changes object type to IPv6.
142 * @return true on success.
143 */
144bool hostaddress::set_ipv6(const char *str) {
145        struct in6_addr in;
146        if (str && (inet_pton(AF_INET6,str,&in)>0)) {
147                set_ip(in);
148                return true;
149        } else return false;
150} // end set_ipv6       
151
152/** Set IPv6 address from struct in6_addr.
153 * This changes object type to IPv6.
154 */
155void 
156hostaddress::set_ip(const struct in6_addr &in) {
157        clear_ip();
158        ipv6addr = in; 
159        // set subtype to IPv6
160        set_subtype(false);
161        return;
162} // end set_ip(in6_addr)
163
164
165
166void hostaddress::set_ip(const hostaddress& h) {
167        clear_ip();
168        if (h.ipv4flag) {
169                ipv4addr = h.ipv4addr;
170        } else {
171                ipv6addr = h.ipv6addr;
172        } // end if ipv4flag
173        set_subtype(h.ipv4flag);
174} // end set_ip(hostaddress)
175
176/** Check if IP address is unspecified (set to 0). */
177bool hostaddress::is_ip_unspec() const {
178        if (ipv4flag) return (ipv4addr.s_addr==0);
179        else return IN6_IS_ADDR_UNSPECIFIED(ipv6addr.s6_addr);
180        // never reached
181        return true;
182} // end is_unspec
183
184/** Get IP address as a string. The output string is kept inside the
185 * hostaddress object and should be copied if used for a longer time.
186 */
187const char* hostaddress::get_ip_str() const 
188{
189  // If outstring exists then it is valid.
190  if (outstring) 
191    return outstring;
192  else
193    outstring= (ipv4flag ? new(nothrow) char[INET_ADDRSTRLEN] : 
194                           new(nothrow) char[INET6_ADDRSTRLEN]);
195
196  if (hostaddress::get_ip_str(outstring)) 
197    return outstring;
198  else 
199  {
200    // error
201    if (outstring) 
202      delete[] outstring;
203
204    return (outstring = NULL);
205  } // end if get_ip_str()
206} // end get_ip_str
207
208/** Get IP address as a string.
209 * @param str string buffer
210 */
211const char* hostaddress::get_ip_str(char *str) const 
212{
213  if (!str) return NULL;
214  memset(str,0, ipv4flag ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
215  return ipv4flag ? inet_ntop(AF_INET,(void*)&ipv4addr,str,INET_ADDRSTRLEN) 
216                  : inet_ntop(AF_INET6,(void*)&ipv6addr,str,INET6_ADDRSTRLEN);
217} // end get_ip_str(char*)
218
219
220/** Get IP address as an in_addr if possible.
221 * @return true on success.
222 */
223bool hostaddress::get_ip(struct in_addr& in) const {
224        if (ipv4flag) {
225                in = ipv4addr;
226                return true;
227        } else if (IN6_IS_ADDR_V4MAPPED(ipv6addr.s6_addr)) {
228                memcpy(&(in.s_addr),ipv6addr.s6_addr+12,4);
229                return true;
230        } else return false;
231} // get_ip
232
233/** Get IP address as an in6_addr.
234 * If this is an IPv4 address, it is mapped to IPv6.
235 * @return true since this is always possible.
236 */
237bool hostaddress::get_ip(struct in6_addr& in) const {
238        if (ipv4flag) {
239                // map to IPv6
240                memset(in.s6_addr,0,10);
241                memset(in.s6_addr+10,255,2);
242                memcpy(in.s6_addr+12,&(ipv4addr.s_addr),4);
243        } else in = ipv6addr;
244        return true;
245} // get_ip
246
247/// returns false if address is not allowed to be used
248/// as source address: loopback, multicast, broadcast, unspecified
249bool 
250hostaddress::is_bogus_source() const
251{
252  if (ipv4flag)
253  { // IPv4
254    if ( IN_MULTICAST(ipv4addr.s_addr) || 
255         ipv4addr.s_addr == INADDR_LOOPBACK  ||
256         ipv4addr.s_addr == INADDR_ANY ||
257         ipv4addr.s_addr == INADDR_BROADCAST
258       )
259    {
260      return true;
261    }
262  }
263  else
264  { // IPv6
265    if ( ipv6addr.s6_addr == in6addr_any.s6_addr ||
266         ipv6addr.s6_addr == in6addr_loopback.s6_addr )
267      return true;
268  }
269
270  return false;
271}
272
273
274/** Convert the IP address to IPv6 by mapping it from IPv4 to IPv6 if
275 * necessary
276 */
277void hostaddress::convert_to_ipv6() {
278        if (ipv4flag) {
279                if (is_ip_unspec()) {
280                        // clear IP and set to IPv6
281                        clear_ip();
282                        set_subtype(false);
283                } else {
284                        // map to IPv6
285                        struct in6_addr in;
286                        get_ip(in);
287                        // set IP
288                        set_ip(in);
289                } // end if is_ip_unspec()
290        } // end if ipv4flag
291} // end convert_to_ipv6
292
293/** Two addresses are equivalent if they are equal after converting both to
294 * IPv6.
295 */
296bool hostaddress::equiv(const hostaddress& h) const {
297        bool thisipv4 = is_ipv4();
298        bool result = false;
299        hostaddress* ipv4haddr = NULL;
300        const hostaddress* ipv6haddr = NULL;
301        // if both IPv4 or both IPv6 then just test for equality
302        if (thisipv4==h.is_ipv4()) return operator==(h);
303        // OK, one is IPv6 and the other is IPv4 (to be converted!).
304        // Allocating memory dynamically because I do not know the concrete
305        // type of *this or h.
306        try {
307                if (thisipv4) {
308                        ipv6haddr = &h;
309                        if (h.is_mapped_ip()) ipv4haddr = this->copy();
310                } else {
311                        ipv6haddr = this;
312                        if (is_mapped_ip()) ipv4haddr = h.copy();
313                } // end if thisipv4
314        } catch(IEError&) { ipv4haddr = NULL; }
315        if (ipv4haddr) {
316                ipv4haddr->convert_to_ipv6();
317                result = ((*ipv4haddr)==(*ipv6haddr));
318                delete ipv4haddr;
319                return result;
320        } else return false;
321} // end equiv
322
323
324/** Set subtype and IPv4 flag. This does NOT clear the outstring buffer.
325 * Use clear_ip().
326 */
327void hostaddress::set_subtype(bool ipv4) {
328        ipv4flag = ipv4; 
329        subtype = ipv4flag ? IPv4HostAddress : IPv6HostAddress;
330} // end set_subtype
331
332/** Clear the IP address buffer and the outstring if it exists. */
333void hostaddress::clear_ip() {
334        // only need to clear ipv6 because of union
335        ipv6addr = in6addr_any;
336        if (outstring) {
337                delete[] outstring;
338                outstring = NULL;
339        } // end if outstring
340} // end clear_ip
341
342
343/** Match this IP address against another IP address.
344 * Two IP addresses match if they are equal.
345 * @return -1 on no match or error, e.g. when IPv4 and IPv6 are matched
346 * @return the length of the matched prefix.
347 */
348int hostaddress::match_against(const hostaddress& ha) const {
349        if (ipv4flag==ha.ipv4flag) {
350                if (operator==(ha)) {
351                        if (ipv4flag) return 32;
352                        else return 128;
353                } else return -1;
354        } else return -1;
355} // end match_against(
356
357/** Match this IP address against the given network prefix.
358 * @return -1 on no match or error, e.g. when IPv4 and IPv6 are matched
359 * @return the length of the matched prefix.
360 */
361int hostaddress::match_against(const netaddress& na) const {
362        uint32 word1 = 0;
363        uint32 word2 = 0;
364        const prefix_length_t preflen = na.get_pref_len();
365        prefix_length_t lenwords = preflen/32;
366        prefix_length_t lenbits = preflen%32;
367        // now 0<=lenwords<=4, 0<=lenbits<=31
368        prefix_length_t i;
369        const hostaddress& ha = dynamic_cast<const hostaddress&>(na);
370        if (ipv4flag==na.ipv4flag) {
371                if (ipv4flag) {
372                        if (preflen >= 32)
373                                lenbits = 32;
374                        // match IPv4
375                        word1 = ntohl(ipv4addr.s_addr);
376                        word2 = ntohl(ha.ipv4addr.s_addr);
377                        // shift right
378                        word1 >>= (32-lenbits);
379                        word2 >>= (32-lenbits);
380                        if (word1==word2) return preflen;
381                        else return -1;
382                } else {
383                        if (preflen > 128)
384                                return -1;
385                        // match IPv6
386                        // match words
387                        for (i=0;i<lenwords;i++) {
388                          word1 = ntohl(ipv6addr.s6_addr32[i]);    // RB: as long as both words are in same order we dont need ntohl?!
389                          word2 = ntohl(ha.ipv6addr.s6_addr32[i]);
390                                if (word1!=word2) return -1;
391                        } // end for i
392                        // now i points to the next word to be matched
393                        // match bits
394                        if (lenbits) {
395                                word1 = ntohl(ipv6addr.s6_addr32[i]);
396                                word2 = ntohl(ha.ipv6addr.s6_addr32[i]);
397                                // shift right
398                                word1 >>= (32-lenbits);
399                                word2 >>= (32-lenbits);
400                                if (word1==word2) return preflen;
401                                else return -1;
402                        } else {
403                                // no extra bits to match and everything OK
404                                return preflen;
405                        } // end if lenbits
406                } // end if ipv4flag
407        } else return -1;
408} // end match_against
409
410/***** class appladdress *****/
411
412/***** inherited from IE *****/
413
414appladdress* appladdress::new_instance() const {
415        appladdress* aa = NULL;
416        catch_bad_alloc(aa = new appladdress());
417        return aa;
418} // end new_instance
419
420appladdress* appladdress::copy() const {
421        appladdress* aa = NULL;
422        catch_bad_alloc(aa = new appladdress(*this));
423        return aa;
424} // end copy
425
426bool appladdress::operator==(const address& ie) const {
427        const appladdress* app = dynamic_cast<const appladdress*>(&ie);
428        if (app) {
429                // if the IEs are equal when casted to type hostaddress, then
430                // only protocols and ports have to be checked.
431                // Otherwise they are not equal.
432                if (hostaddress::operator==(ie)) {
433                    //if (proto!=app->proto) cout << "protocols not matching" << endl;
434                    //if (port !=app->port) cout << "ports not matching" << endl;
435
436                    return ((proto==app->proto) && (port==app->port));
437                } else return false;
438        } else return false;
439} // end operator==
440
441
442/***** class netaddress *****/
443
444/***** inherited from IE *****/
445
446netaddress* netaddress::new_instance() const {
447        netaddress* na = NULL;
448        catch_bad_alloc(na = new netaddress());
449        return na;
450} // end new_instance
451
452netaddress* netaddress::copy() const {
453        netaddress* na = NULL;
454        catch_bad_alloc(na = new netaddress(*this));
455        return na;
456} // end copy
457
458bool netaddress::operator==(const address& ie) const {
459        const netaddress* na = dynamic_cast<const netaddress*>(&ie);
460        if (na) {
461                // if the IEs are equal when casted to type hostaddress, then
462                // only prefix lengths have to be checked.
463                // Otherwise they are not equal.
464                if (hostaddress::operator==(ie)) {
465                    if (prefix_length!=na->prefix_length) cout << "Prefix length not matching" << endl;
466                    return (prefix_length==na->prefix_length);
467                } else return false;
468        } else return false;
469} // end operator==
470
471
472/***** inherited from hostaddress *****/
473
474/** Convert the IP address to IPv6 by mapping it from IPv4 to IPv6 if
475 * necessary. The prefix length is converted, too.
476 */
477void netaddress::convert_to_ipv6() {
478        if (ipv4flag) {
479                // map IP
480                hostaddress::convert_to_ipv6();
481                // adjust prefix length
482                set_pref_len(prefix_length+96);
483        } // end if ipv4flag
484} // end convert_to_ipv6
485
486/** Set subtype and IPv4 flag. This does NOT clear the outstring buffer.
487 * Use clear_ip().
488 * In addition the prefix length is checked and set to reasonable values.
489 */
490void netaddress::set_subtype(bool ipv4) {
491        ipv4flag = ipv4; 
492        if (ipv4) {
493                subtype = IPv4NetAddress; 
494                if (prefix_length>32) prefix_length = 32;
495        } else {
496                subtype = IPv6NetAddress;
497                if (prefix_length>128) prefix_length = 128;
498        } // end if ipv4flag
499} // end set_subtype
500
501/***** new members in netaddress *****/
502
503/** Constructor sets address type and clears prefix length. */
504netaddress::netaddress() : 
505  hostaddress(),
506  prefix_length(0)
507 {
508        set_subtype(ipv4flag);
509} // end constructor
510
511netaddress::netaddress(const netaddress& na) : hostaddress(na) {
512        prefix_length = na.prefix_length;
513        set_subtype(ipv4flag);
514} // end copy constructor
515
516/** Initialize with the given host address and prefix length.
517 * Prefix length is optional and set to 0 if missing.
518 */
519netaddress::netaddress(const hostaddress& h, prefix_length_t len) : hostaddress(h) {
520  set_subtype(ipv4flag);
521  set_pref_len(len); // this will cut the prefix value accordingly
522} // end constructor(hostaddress,len)
523
524/** Initialize from string which contains IP and prefix length separated by
525 * '/'.
526 */
527netaddress::netaddress(const char* str, bool *res) : hostaddress() {
528        bool tmpres = true; // MUST BE true
529        bool tmpres2 = false;
530        long int len = 0;
531        uint32 iplen;
532        char* i = NULL;
533        char* errptr = NULL;
534        char ipstr[INET6_ADDRSTRLEN] = {0};
535        // look for /
536        i = strchr(str,'/');
537        if (i) {
538                iplen = i-str;
539                i++;
540                // decode prefix length
541                len = strtol(i,&errptr,10);
542                if ((*i) && errptr && ((*errptr)==0)) {
543                        // prefix OK
544                        prefix_length = len;
545                } else {
546                        prefix_length = 0;
547                        tmpres = false;
548                } // end if prefix OK
549                if (iplen<=INET6_ADDRSTRLEN) {
550                        // copy IP string
551                        strncpy(ipstr,str,iplen);
552                        ipstr[INET6_ADDRSTRLEN-1] = 0;
553                        // set str to ipstr
554                        str = ipstr;
555                } // end if iplen valid
556        } else {
557                // no prefix found, OK
558                prefix_length = 0;
559        } // end if i
560        // set IP, this also sets ipvflag.
561        tmpres2 = set_ip(str);
562        if (res) *res = (tmpres && tmpres2);
563        set_subtype(ipv4flag);
564} // end constructor(string)
565
566/** Initialize from string and prefix length.
567 * If the string does not contain a valid IP address, it is set to all 0 by
568 * the hostaddress constructor.
569 */
570netaddress::netaddress(const char* str, prefix_length_t len, bool *res) : hostaddress(str,res) {
571  set_subtype(ipv4flag);
572  set_pref_len(len); // this will cut the prefix value accordingly
573} // end constructor(string,port)
574
575/** Assigns the given netaddress address by using hostaddress::operator=(). */
576netaddress& netaddress::operator=(const netaddress& na) {
577  prefix_length = na.prefix_length;
578  hostaddress::operator=(na);
579  return *this;
580} // end operator=
581
582
583/** Assigns the given netaddress address by using hostaddress::operator=(). */
584netaddress& netaddress::operator=(const hostaddress& na) {
585        hostaddress::operator=(na);
586        set_pref_len(128);
587        return *this;
588} // end operator=
589
590
591/** Set prefix length and return old value.
592 * will also cut prefix_length if needed (i.e., if len too large for addr type)
593 */
594prefix_length_t netaddress::set_pref_len(prefix_length_t len) {
595        register prefix_length_t olen = prefix_length;
596        prefix_length = ipv4flag ? ( (len>32) ? 32 : len ) :
597                                   ( (len>128) ? 128 : len );
598        return olen;
599} // end set_port
600
601
602
603/** Compare two netaddress objects. If neither a<b and b<a then a and b are
604 * considered equal.
605 */
606bool netaddress::operator<(const netaddress& na) const {
607        uint32 word1 = 0;
608        uint32 word2 = 0;
609        prefix_length_t lenwords = prefix_length/32;
610        prefix_length_t lenbits = prefix_length%32;
611        // now 0<=lenwords<=4, 0<=lenbits<=31
612        prefix_length_t i;
613        // IPv4 is always < IPv6
614        if ((!ipv4flag) && na.ipv4flag) return false;
615        else if (ipv4flag && (!na.ipv4flag)) return true;
616        // now ipv4flag == na.ipv4flag
617        else if (prefix_length<na.prefix_length) return true;
618        else if (prefix_length>na.prefix_length) return false;
619        // now prefix_length == na.prefix_length
620        else if (ipv4flag) {
621                // compare IPv4 with same prefix length
622                word1 = ntohl(ipv4addr.s_addr);
623                word2 = ntohl(na.ipv4addr.s_addr);
624                // shift right
625                word1 >>= (32-lenbits);
626                word2 >>= (32-lenbits);
627                if (word1<word2) return true;
628                else return false;
629        } else {
630                // compare IPv6 with same prefix length
631                // compare words
632                for (i=0;i<lenwords;i++) {
633                        word1 = ntohl(ipv6addr.s6_addr32[i]);
634                        word2 = ntohl(na.ipv6addr.s6_addr32[i]);
635                        if (word1<word2) return true;
636                        if (word1>word2) return false;
637                } // end for i
638                // now i points to the next word to be compared and previous words are equal
639                // compare bits
640                if (lenbits) {
641                        word1 = ntohl(ipv6addr.s6_addr32[i]);
642                        word2 = ntohl(na.ipv6addr.s6_addr32[i]);
643                        // shift right
644                        word1 >>= (32-lenbits);
645                        word2 >>= (32-lenbits);
646                        if (word1<word2) return true;
647                        else return false;
648                } else {
649                        // no extra bist to compare and everything equal
650                        return false;
651                } // end if lenbits
652        } // end if ipv4flag, prefox
653} // end match_against
654
655/**
656 * Compare function for the radix trie:
657 *
658 * Compare this and na from *pos up to max(this->prefix, na->prefix)
659 *
660 * In pos return the position where the compare ended.
661 *
662 * The return value is 0 if the strings are equal and all of this' string
663 * was consumed, otherwise the sign will indicate the bit in this' string
664 * at pos (i.e. if the search should continue left or right of na).
665 *
666 * pos < 0 indicates error
667 */
668int
669netaddress::rdx_cmp(const netaddress *na, int *pos) const
670{
671        if (na == NULL) {
672                *pos = -1;
673                return 0;
674        }
675
676        if (na->ipv4flag != ipv4flag ||
677            *pos > na->prefix_length ||
678            *pos > prefix_length) {
679                *pos = -1;
680                return 0;
681        }
682
683        if (na->prefix_length == 0) {
684                *pos = 1;
685                if (ipv4flag)
686                        return ((ntohl(ipv4addr.s_addr) & 0x80000000) == 0 ?
687                            -1 : 1);
688                else
689                        return ((htonl(ipv6addr.s6_addr32[0]) & 0x80000000) == 0 ?
690                            -1 : 1);
691        }
692
693        if (*pos < 0)
694                *pos = 0;
695
696        uint32_t w1, w2, w3;
697        int diff, i, p1, p2;
698
699        if (ipv4flag) {
700                diff = *pos;
701                w1 = ntohl(ipv4addr.s_addr);
702                w2 = ntohl(na->ipv4addr.s_addr);
703                // in w3 store the difference
704                w3 = w1 ^ w2;
705                // mask out anything after prefix_length and before *pos
706                w3 = (w3 >> (32 - prefix_length)) << (32 - prefix_length + diff);
707                if (w3 == 0 && prefix_length <= na->prefix_length) {
708                        *pos = min(prefix_length, na->prefix_length);
709                        return 0;
710                }
711                // pos = 0 means start up front, so we need to fix up to that
712                diff++;
713                while (diff <= prefix_length && diff <= na->prefix_length) {
714                        if ((w3 & 0x80000000) != 0) {
715                                *pos = diff;
716                                return (((w1 & (1 << (32 - diff))) >>
717                                    (32 - diff)) == 0 ? -1 : 1);
718                        }
719                        w3 = w3 << 1;
720                        diff++;
721                }
722                // difference past na->prefix_length
723                *pos = diff;
724                return (((w1 & (1 << (32 - diff))) >>
725                    (32 - diff)) == 0 ? -1 : 1);
726        }
727
728        diff = *pos;
729        for (i = diff / 32; i < 4; i++) {
730                diff = diff % 32;
731                w1 = ntohl(ipv6addr.s6_addr32[i]);
732                w2 = ntohl(na->ipv6addr.s6_addr32[i]);
733                w3 = w1 ^ w2;
734                p1 = (prefix_length - (i * 32));
735                p1 = p1 > 32 ? 32 : p1;
736                p2 = (na->prefix_length - (i * 32));
737                p1 = p2 > 32 ? 32 : p2;
738
739                w3 = (w3 >> (32 - p1)) << (32 - p1 + diff);
740                if (w3 == 0 && prefix_length <= na->prefix_length) {
741                        *pos = min(prefix_length, na->prefix_length);
742                        if (prefix_length <= ((i + 1) * 32))
743                                return 0;
744                }
745                // pos = 0 means start up front, so we need to fix up to that
746                diff++;
747                while (diff <= p1 && diff <= p2) {
748                        if ((w3 & 0x80000000) != 0) {
749                                *pos = diff + (i * 32);
750                                return (((w1 & (1 << (32 - diff))) >>
751                                    (32 - diff)) == 0 ? -1 : 1);
752                        }
753                        w3 = w3 << 1;
754                        diff++;
755                }
756                if (diff + (32 * i) <= prefix_length &&
757                    diff + (32 * i) <= na->prefix_length) {
758                        diff--;
759                        continue;
760                }
761                // difference past na->prefix_length
762                *pos = diff + (i * 32);
763                if (diff == 33) {
764                        diff = 1;
765                        if (i == 3)
766                                abort();
767                        w1 = ntohl(ipv6addr.s6_addr32[i+1]);
768                }
769                return (((w1 & (1 << (32 - diff))) >>
770                    (32 - diff)) == 0 ? -1 : 1);
771        }
772
773        // Not reachable, but gcc complains
774        return 0;
775}
776
777udsaddress* udsaddress::new_instance() const {
778        udsaddress* ha = NULL;
779        catch_bad_alloc(ha = new udsaddress());
780        return ha;
781} // end new_instance
782
783udsaddress* udsaddress::copy() const {
784        udsaddress* ha = NULL;
785        catch_bad_alloc(ha =  new udsaddress(*this));
786        return ha;
787} // end copy
788
789bool udsaddress::operator==(const address& ie) const {
790        const udsaddress* app = dynamic_cast<const udsaddress*>(&ie);
791        if (app) {
792            return (app->socknum == socknum) && (app->uds_socket == uds_socket);
793        } else return false;
794} // end operator==
795
796AddressList::AddrProperty *AddressList::LocalAddr_P;
797AddressList::AddrProperty *AddressList::ConfiguredAddr_P;
798AddressList::AddrProperty *AddressList::IgnoreAddr_P;
799AddressList::AddrProperty *AddressList::AnyAddr_P;
800
801AddressList::AddressList()
802{
803        if (LocalAddr_P == 0) {
804                LocalAddr_P = new AddrProperty("local");
805                ConfiguredAddr_P = new AddrProperty("configured");
806                IgnoreAddr_P = new AddrProperty("ignore");
807                AnyAddr_P = new AddrProperty("wildcard");
808        }
809        interfaces = 0;
810}
811
812AddressList::~AddressList()
813{
814        // Refcount AddressLists in order to GC properties?
815}
816
817AddressList::iflist_t *
818AddressList::get_interfaces()
819{
820        iflist_t *iflist;
821
822        if (interfaces != 0)
823                iflist = new iflist_t(*interfaces);
824        else {
825                iflist = new iflist_t();
826                getifaddrs_iflist(*iflist);
827        }
828
829        return iflist;
830}
831
832bool
833AddressList::by_interface(bool start_empty)
834{
835        if (interfaces != 0)
836                return false;
837
838        interfaces = new iflist_t();
839        if (!start_empty)
840                getifaddrs_iflist(*interfaces);
841
842        return true;
843}
844
845bool
846AddressList::add_interface(char *name)
847{
848        if (interfaces == 0)
849                return false;
850
851        return (interfaces->insert(name)).second;
852}
853
854bool
855AddressList::del_interface(char *name)
856{
857        if (interfaces == 0)
858                return false;
859
860        return (interfaces->erase(name) > 0);
861}
862
863bool
864AddressList::add_property(netaddress &na, AddrProperty *p, bool propagate)
865{
866        propmap_t *props, *lpfm_props;
867        propmap_t::iterator it;
868        addr2prop_t::node *node;
869
870        node = prop_trie.lookup_node(na, false, false);
871        if (node != NULL) {
872                props = node->data;
873                if (props == NULL) {
874                        props = new propmap_t();
875                        node->data = props;
876                }
877                props->insert(pair<AddrProperty *, bool>(p, propagate));
878               
879        } else {
880                props = new propmap_t();
881                props->insert(pair<AddrProperty *, bool>(p, propagate));
882                node = prop_trie.insert(na, *props);
883        }
884
885        if (propagate)
886                bequeath(node, p, true);
887
888        // copy lpfm properties
889        lpfm_props = prop_trie.lookup(na, true);
890        if (lpfm_props == NULL)
891                return true;
892
893        for (it = lpfm_props->begin(); it != lpfm_props->end(); it++) {
894                if ((*it).second)
895                        props->insert((*it));
896        }
897
898        return true;
899}
900
901bool
902AddressList::del_property(netaddress &na, AddrProperty *p, bool propagate)
903{
904        propmap_t *props, *lpfm_props;
905        propmap_t::iterator it;
906        addr2prop_t::node *node;
907
908        node = prop_trie.lookup_node(na, false, true);
909        if (node == NULL) {
910                // no exact match
911                if (!propagate) {
912                        node = prop_trie.lookup_node(na, true, true);
913                        if (node == NULL) {
914                                // no lpfm either, we're done
915                                return false;
916                        }
917
918                        props = node->data;
919                        it = props->find(p);
920                        if (it == props->end()) {
921                                // lpfm doesn't have p set -> done
922                                return false;
923                        }
924                }
925                // insert an empty propmap
926                props = new propmap_t();
927                node = prop_trie.insert(na, *props);
928
929                // copy other lpfm properties
930                lpfm_props = prop_trie.lookup(na, true);
931                if (p != AnyAddr_P && lpfm_props != NULL) {
932                        for (it = lpfm_props->begin(); it != lpfm_props->end();
933                            it++) {
934                                if ((*it).first != p && (*it).second)
935                                        props->insert((*it));
936                        }
937                }
938        } else {
939                props = node->data;
940                if (p == AnyAddr_P) {
941                        props->clear();
942                } else {
943                        it = props->find(p);
944                        if (it == props->end() && !propagate)
945                                return false;
946
947                        props->erase(it);
948                }
949        }
950
951        if (propagate)
952                bequeath(node, p, false);
953
954        return true;
955}
956
957bool
958AddressList::add_host_prop(const char *name, AddrProperty *p)
959{
960        netaddress na;
961        sockaddr_in *sin;
962        sockaddr_in6 *sin6;
963        struct addrinfo hints = {0}, *res, *cur;
964        int error;
965        char buf[1024];
966
967        if (name == NULL) {
968                name = buf;
969                if (gethostname(buf, sizeof(buf)) != 0)
970                        return false;
971                buf[sizeof(buf) - 1] = '\0';
972        }
973        hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
974        hints.ai_family = AF_UNSPEC;
975        error = getaddrinfo(name, NULL, &hints, &res);
976        if (error != 0)
977                return false;
978
979        for(cur = res; cur != NULL && error == 0; cur = cur->ai_next) {
980                if (cur->ai_family == AF_INET) {
981                        sin = (struct sockaddr_in *)cur->ai_addr;
982                        na.set_ip(sin->sin_addr);
983                        na.set_pref_len(32);
984                } else if (cur->ai_family == AF_INET6) {
985                        sin6 = (struct sockaddr_in6 *)cur->ai_addr;
986                        na.set_ip(sin6->sin6_addr);
987                        na.set_pref_len(128);
988                } else
989                        continue;
990
991                // cout << ++i << "XXMOB: " << na << endl;
992
993                error += add_property(na, p) ? 0 : 1;
994                // XXXMOB: for some reason we need a 'reset' here
995                //         if we want to use /etc/hosts
996                na.set_ip("127.0.0.1");
997        }
998        freeaddrinfo(res);
999
1000        return (error == 0);
1001}
1002
1003bool
1004AddressList::del_host_prop(const char *name, AddrProperty *p)
1005{
1006        netaddress na;
1007        sockaddr_in *sin;
1008        sockaddr_in6 *sin6;
1009        struct addrinfo hints = {0}, *res, *cur;
1010        int error;
1011        char buf[1024];
1012
1013        if (name == NULL) {
1014                name = buf;
1015                if (gethostname(buf, sizeof(buf)) != 0)
1016                        return false;
1017                buf[sizeof(buf) - 1] = '\0';
1018        }
1019        hints.ai_flags = AI_ADDRCONFIG;
1020        hints.ai_family = AF_UNSPEC;
1021        error = getaddrinfo(name, NULL, &hints, &res);
1022        if (error != 0)
1023                return false;
1024
1025        for(cur = res; cur != NULL && error == 0; cur = cur->ai_next) {
1026                if (cur->ai_family == AF_INET) {
1027                        sin = (struct sockaddr_in *)cur->ai_addr;
1028                        na.set_ip(sin->sin_addr);
1029                        na.set_pref_len(32);
1030                } else if (cur->ai_family == AF_INET6) {
1031                        sin6 = (struct sockaddr_in6 *)cur->ai_addr;
1032                        na.set_ip(sin6->sin6_addr);
1033                        na.set_pref_len(128);
1034                } else
1035                        continue;
1036
1037                error += del_property(na, p) ? 0 : 1;
1038        }
1039        freeaddrinfo(res);
1040
1041        return (error == 0);
1042}
1043
1044bool
1045AddressList::ignore(netaddress &na, bool propagate)
1046{
1047        del_property(na, AnyAddr_P, propagate);
1048        return add_property(na, IgnoreAddr_P);
1049}
1050
1051bool
1052AddressList::unignore(netaddress &na, bool propagate)
1053{
1054        return del_property(na, IgnoreAddr_P, propagate);
1055}
1056
1057bool
1058AddressList::ignore_bogons(void)
1059{
1060        netaddress na;
1061
1062        // according to IANA Tue Apr 17 09:14:31 PDT 2007
1063        na.set_ip("0.0.0.0");na.set_pref_len(7);
1064        ignore(na);
1065        na.set_ip("2.0.0.0");na.set_pref_len(8);
1066        ignore(na);
1067        na.set_ip("5.0.0.0");na.set_pref_len(8);
1068        ignore(na);
1069        na.set_ip("7.0.0.0");na.set_pref_len(8);
1070        ignore(na);
1071        na.set_ip("23.0.0.0");na.set_pref_len(8);
1072        ignore(na);
1073        na.set_ip("27.0.0.0");na.set_pref_len(8);
1074        ignore(na);
1075        na.set_ip("31.0.0.0");na.set_pref_len(8);
1076        ignore(na);
1077        na.set_ip("36.0.0.0");na.set_pref_len(7);
1078        ignore(na);
1079        na.set_ip("39.0.0.0");na.set_pref_len(8);
1080        ignore(na);
1081        na.set_ip("42.0.0.0");na.set_pref_len(8);
1082        ignore(na);
1083        na.set_ip("49.0.0.0");na.set_pref_len(8);
1084        ignore(na);
1085        na.set_ip("50.0.0.0");na.set_pref_len(8);
1086        ignore(na);
1087        na.set_ip("94.0.0.0");na.set_pref_len(7);
1088        ignore(na);
1089        na.set_ip("100.0.0.0");na.set_pref_len(6);
1090        ignore(na);
1091        na.set_ip("104.0.0.0");na.set_pref_len(5);
1092        ignore(na);
1093        na.set_ip("112.0.0.0");na.set_pref_len(6);
1094        ignore(na);
1095        na.set_ip("169.254.0.0");na.set_pref_len(16);
1096        ignore(na);
1097        na.set_ip("173.0.0.0");na.set_pref_len(8);
1098        ignore(na);
1099        na.set_ip("174.0.0.0");na.set_pref_len(7);
1100        ignore(na);
1101        na.set_ip("176.0.0.0");na.set_pref_len(5);
1102        ignore(na);
1103        na.set_ip("184.0.0.0");na.set_pref_len(6);
1104        ignore(na);
1105        na.set_ip("191.0.0.0");na.set_pref_len(8);
1106        ignore(na);
1107        na.set_ip("192.0.2.0");na.set_pref_len(24);
1108        ignore(na);
1109        na.set_ip("197.0.0.0");na.set_pref_len(8);
1110        ignore(na);
1111        na.set_ip("198.18.0.0");na.set_pref_len(15);
1112        ignore(na);
1113        na.set_ip("223.0.0.0");na.set_pref_len(8);
1114        ignore(na);
1115        na.set_ip("240.0.0.0");na.set_pref_len(4);
1116        ignore(na);
1117        // according to http://www.cymru.com/Documents/bogonv6-list.html#agg
1118        na.set_ip("0000::");na.set_pref_len(8);
1119        ignore(na);
1120        na.set_ip("0100::");na.set_pref_len(8);
1121        ignore(na);
1122        na.set_ip("0200::");na.set_pref_len(7);
1123        ignore(na);
1124        na.set_ip("0400::");na.set_pref_len(7);
1125        ignore(na);
1126        na.set_ip("0600::");na.set_pref_len(7);
1127        ignore(na);
1128        na.set_ip("0800::");na.set_pref_len(5);
1129        ignore(na);
1130        na.set_ip("1000::");na.set_pref_len(4);
1131        ignore(na);
1132        na.set_ip("2000::");na.set_pref_len(16);
1133        ignore(na);
1134        na.set_ip("2001:1000::");na.set_pref_len(23);
1135        ignore(na);
1136        na.set_ip("2001:1600::");na.set_pref_len(23);
1137        ignore(na);
1138        na.set_ip("2001:2000::");na.set_pref_len(20);
1139        ignore(na);
1140        na.set_ip("2001:3000::");na.set_pref_len(20);
1141        ignore(na);
1142        na.set_ip("2001:4000::");na.set_pref_len(20);
1143        ignore(na);
1144        na.set_ip("2001:5000::");na.set_pref_len(20);
1145        ignore(na);
1146        na.set_ip("2001:6000::");na.set_pref_len(20);
1147        ignore(na);
1148        na.set_ip("2001:7000::");na.set_pref_len(20);
1149        ignore(na);
1150        na.set_ip("2001:8000::");na.set_pref_len(20);
1151        ignore(na);
1152        na.set_ip("2001:9000::");na.set_pref_len(20);
1153        ignore(na);
1154        na.set_ip("2001:A000::");na.set_pref_len(20);
1155        ignore(na);
1156        na.set_ip("2001:B000::");na.set_pref_len(20);
1157        ignore(na);
1158        na.set_ip("2001:C000::");na.set_pref_len(20);
1159        ignore(na);
1160        na.set_ip("2001:D000::");na.set_pref_len(20);
1161        ignore(na);
1162        na.set_ip("2001:E000::");na.set_pref_len(20);
1163        ignore(na);
1164        na.set_ip("2001:F000::");na.set_pref_len(20);
1165        ignore(na);
1166        na.set_ip("3FFF::");na.set_pref_len(16);
1167        ignore(na);
1168        na.set_ip("4000::");na.set_pref_len(3);
1169        ignore(na);
1170        na.set_ip("6000::");na.set_pref_len(3);
1171        ignore(na);
1172        na.set_ip("8000::");na.set_pref_len(3);
1173        ignore(na);
1174        na.set_ip("A000::");na.set_pref_len(3);
1175        ignore(na);
1176        na.set_ip("C000::");na.set_pref_len(3);
1177        ignore(na);
1178        na.set_ip("E000::");na.set_pref_len(4);
1179        ignore(na);
1180        na.set_ip("F000::");na.set_pref_len(5);
1181        ignore(na);
1182        na.set_ip("F800::");na.set_pref_len(6);
1183        ignore(na);
1184        na.set_ip("FC00::");na.set_pref_len(7);
1185        ignore(na);
1186        na.set_ip("FE00::");na.set_pref_len(9);
1187        ignore(na);
1188
1189        return true;
1190}
1191
1192bool
1193AddressList::ignore_locals(void)
1194{
1195        netaddress na;
1196
1197        na.set_ip("10.0.0.0");na.set_pref_len(8);
1198        ignore(na);
1199        na.set_ip("172.16.0.0");na.set_pref_len(12);
1200        ignore(na);
1201        na.set_ip("192.168.0.0");na.set_pref_len(16);
1202        ignore(na);
1203        na.set_ip("FE80::");na.set_pref_len(10);
1204        ignore(na);
1205        na.set_ip("FEC0::");na.set_pref_len(10);
1206        ignore(na);
1207
1208        return true;
1209}
1210
1211bool
1212AddressList::ignore_loopback(void)
1213{
1214        netaddress na;
1215
1216        na.set_ip("127.0.0.0");na.set_pref_len(8);
1217        ignore(na);
1218        na.set_ip("::1");na.set_pref_len(128);
1219        ignore(na);
1220
1221        return true;
1222}
1223
1224bool
1225AddressList::addr_is(netaddress &na, AddrProperty *prop)
1226{
1227        propmap_t *props;
1228        propmap_t::iterator it;
1229
1230        if (addr_is_in(na, IgnoreAddr_P))
1231                return false;
1232
1233        props = prop_trie.lookup(na, false);
1234        if (props != NULL) {
1235                it = props->find(prop);
1236                if (it != props->end()) {
1237                        return true;
1238                }
1239        }
1240
1241        if (prop != LocalAddr_P)
1242                return false;
1243
1244        return getifaddrs_is_local(na);
1245}
1246
1247bool
1248AddressList::addr_is_in(netaddress &na, AddrProperty *prop)
1249{
1250        addr2prop_t::node *node;
1251        propmap_t *props;
1252        propmap_t::iterator it;
1253
1254        node = prop_trie.lookup_node(na, true, true);
1255        if (node == NULL)
1256                return false;
1257
1258        props = node->data;
1259        it = props->find(prop);
1260        if (it == props->end())
1261                return false;
1262
1263        if (!(*it).second && props != prop_trie.lookup(na, false))
1264                        return false;
1265
1266        return true;
1267}
1268
1269AddressList::addrlist_t *
1270AddressList::get_addrs(AddrProperty *prop)
1271{
1272        addr2prop_t::node *node;
1273        netaddress na;
1274        addrlist_t *res = new addrlist_t();
1275
1276        if (res == 0)
1277                return res;
1278
1279        if (prop == LocalAddr_P || prop == AnyAddr_P)
1280                getifaddrs_get_addrs(*res);
1281
1282        na.set_ip("0.0.0.0");
1283        na.set_pref_len(0);
1284        node = prop_trie.lookup_node(na, true, false);
1285        collect(node, prop, *res);
1286
1287        na.set_ip("::");
1288        node = prop_trie.lookup_node(na, true, false);
1289        collect(node, prop, *res);
1290
1291        return res;
1292}
1293
1294netaddress *
1295AddressList::get_first(AddrProperty *p, bool IPv4)
1296{
1297        addr2prop_t::node *node;
1298        netaddress na;
1299        addrlist_t list;
1300        addrlist_t::iterator it;
1301
1302        if (IPv4) {
1303                na.set_ip("0.0.0.0");
1304                na.set_pref_len(0);
1305        } else {
1306                na.set_ip("::");
1307                na.set_pref_len(0);
1308        }
1309
1310        node = prop_trie.lookup_node(na, true, false);
1311        node = collect_first(node, p);
1312        if (node != NULL)
1313                return new netaddress(*node->key);
1314
1315        if (p == LocalAddr_P) {
1316                getifaddrs_get_addrs(list);
1317                for (it = list.begin(); it != list.end(); it++)
1318                        if ((*it).is_ipv4() == IPv4)
1319                                return new netaddress(*it);
1320        }
1321
1322        return NULL;
1323}
1324
1325netaddress *
1326AddressList::get_src_addr(const netaddress &dest, uint32_t *prefs)
1327{
1328        netaddress *res;
1329        int sfd;
1330
1331        sfd = socket(dest.is_ipv4()?AF_INET:AF_INET6, SOCK_DGRAM, 0);
1332        if (sfd == -1)
1333                return NULL;
1334
1335#ifdef IPV6_ADDR_PREFERENCES
1336        if (prefs != NULL && setsockopt(s, IPV6_ADDR_PREFERENCES,
1337            (void *)prefs, sizeof (*prefs)) == -1) {
1338                close(sfd);
1339                return NULL;
1340        }
1341#endif
1342        if (dest.is_ipv4()) {
1343                struct sockaddr_in sin = {0};
1344                socklen_t slen = sizeof(sin);
1345                sin.sin_family = AF_INET;
1346                sin.sin_port = htons(4);
1347                dest.get_ip(sin.sin_addr);
1348                if (connect(sfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
1349                        close(sfd);
1350                        return NULL;
1351                }
1352                if (getsockname(sfd, (struct sockaddr *)&sin, &slen) == -1) {
1353                        close(sfd);
1354                        return NULL;
1355                }
1356                close(sfd);
1357                res = new netaddress();
1358                res->set_ip(sin.sin_addr);
1359                res->set_pref_len(32);
1360                return (res);
1361        } else {
1362                struct sockaddr_in6 sin6 = {0};
1363                socklen_t slen = sizeof(sin6);
1364                sin6.sin6_family = AF_INET6;
1365                sin6.sin6_port = htons(4);
1366                dest.get_ip(sin6.sin6_addr);
1367                if (connect(sfd, (struct sockaddr *)&sin6,
1368                    sizeof(sin6)) == -1) {
1369                        close(sfd);
1370                        return NULL;
1371                }
1372                if (getsockname(sfd, (struct sockaddr *)&sin6, &slen) == -1) {
1373                        close(sfd);
1374                        return NULL;
1375                }
1376                close(sfd);
1377                res = new netaddress();
1378                res->set_ip(sin6.sin6_addr);
1379                res->set_pref_len(128);
1380                return (res);
1381        }
1382}
1383
1384void
1385AddressList::getifaddrs_iflist(iflist_t &list)
1386{
1387        struct ifaddrs *ifap, *cifa;
1388
1389        if (::getifaddrs(&ifap) != 0)
1390                return;
1391
1392        for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
1393                list.insert(cifa->ifa_name);
1394        }
1395
1396        freeifaddrs(ifap);
1397}
1398
1399bool
1400AddressList::getifaddrs_is_local(netaddress &na)
1401{
1402        struct ifaddrs *ifap, *cifa;
1403
1404        if (::getifaddrs(&ifap) != 0)
1405                return false;
1406
1407        for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
1408                hostaddress ha;
1409
1410                if (cifa->ifa_addr->sa_family == AF_INET) {
1411                        ha.set_ip(
1412                            ((struct sockaddr_in *)cifa->ifa_addr)->sin_addr);
1413                } else if (cifa->ifa_addr->sa_family == AF_INET6) {
1414                        ha.set_ip(
1415                            ((struct sockaddr_in6 *)cifa->ifa_addr)->sin6_addr);
1416                } else {
1417                        continue;
1418                }
1419
1420                if (interfaces &&
1421                    interfaces->find(cifa->ifa_name) == interfaces->end())
1422                        continue;
1423
1424                if (ha.match_against(na) >= na.get_pref_len()) {
1425                        freeifaddrs(ifap);
1426                        return true;
1427                }
1428        }
1429
1430        freeifaddrs(ifap);
1431
1432        return false;
1433}
1434
1435void
1436AddressList::getifaddrs_get_addrs(addrlist_t &list)
1437{
1438        struct ifaddrs *ifap, *cifa;
1439
1440        if (::getifaddrs(&ifap) != 0)
1441                return;
1442
1443        for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
1444                hostaddress *ha;
1445                netaddress na;
1446
1447                if (interfaces &&
1448                    interfaces->find(cifa->ifa_name) == interfaces->end())
1449                        continue;
1450
1451                if (cifa->ifa_addr->sa_family == AF_INET) {
1452                        ha = new hostaddress;
1453                        ha->set_ip(
1454                            ((struct sockaddr_in *)cifa->ifa_addr)->sin_addr);
1455                        na.set_pref_len(32);
1456                } else if (cifa->ifa_addr->sa_family == AF_INET6) {
1457                        ha = new hostaddress;
1458                        ha->set_ip(
1459                            ((struct sockaddr_in6 *)cifa->ifa_addr)->sin6_addr);
1460                        na.set_pref_len(128);
1461                } else {
1462                        continue;
1463                }
1464
1465                na.set_ip(*ha);
1466                if (!addr_is_in(na, IgnoreAddr_P))
1467                        list.insert(*ha);
1468        }
1469
1470        freeifaddrs(ifap);
1471}
1472
1473void
1474AddressList::bequeath(addr2prop_t::node *head, AddrProperty *p, bool add)
1475{
1476        propmap_t *props;
1477        propmap_t::iterator it;
1478
1479        if (p == AnyAddr_P && add)
1480                return;
1481
1482        props = head->data;
1483        if (props != NULL) {
1484                if (p == AnyAddr_P) {
1485                        props->clear();
1486                } else {
1487                        if (add) {
1488                                props->insert(pair<AddrProperty *, bool>
1489                                    (p, true));
1490                        } else {
1491                                it = props->find(p);
1492                                if (it != props->end())
1493                                        props->erase(it);
1494                        }
1495                }
1496        }
1497
1498        if (head->left->index > head->index)
1499                bequeath(head->left, p, add);
1500        if (head->right->index > head->index)
1501                bequeath(head->right, p, add);
1502}
1503
1504void
1505AddressList::collect(addr2prop_t::node *head, AddrProperty *p,
1506    addrlist_t &list)
1507{
1508        propmap_t *props;
1509        propmap_t::iterator it;
1510
1511        props = head->data;
1512        if (props != NULL) {
1513                if (p == AnyAddr_P) {
1514                        it = props->begin();
1515                } else {
1516                        it = props->find(p);
1517                }
1518                if (it != props->end()) {
1519                        list.insert(*(new netaddress(*head->key)));
1520                }
1521        }
1522
1523        if (head->left->index > head->index)
1524                collect(head->left, p, list);
1525        if (head->right->index > head->index)
1526                collect(head->right, p, list);
1527       
1528}
1529
1530AddressList::addr2prop_t::node *
1531AddressList::collect_first(addr2prop_t::node *head, AddrProperty *p)
1532{
1533        addr2prop_t::node *res = NULL;
1534        propmap_t *props;
1535        propmap_t::iterator it;
1536
1537        props = head->data;
1538        if (props != NULL) {
1539                if (p == AnyAddr_P) {
1540                        it = props->begin();
1541                } else {
1542                        it = props->find(p);
1543                }
1544                if (it != props->end()) {
1545                        return head;
1546                }
1547        }
1548
1549        if (head->left->index > head->index) {
1550                res = collect_first(head->left, p);
1551                if (res != NULL)
1552                        return res;
1553        }
1554        if (head->right->index > head->index) {
1555                res = collect_first(head->right, p);
1556                if (res != NULL)
1557                        return res;
1558        }
1559
1560        return NULL;
1561}
1562
1563
1564} // end namespace protlib
Note: See TracBrowser for help on using the repository browser.