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

Last change on this file since 6849 was 6786, checked in by mies, 15 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.