An Overlay-based
Virtual Network Substrate
SpoVNet

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

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

Changed Data to Message conversion constructor in Message to explicit
Fixed some general bugs in Data: operator<<
Fixed bug in DHTMessage: allow unspecified key/values
Added local DHT message delivery
Adapted sources to work with gcc 4.4.1

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((char*)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.