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

Last change on this file since 5993 was 5876, checked in by mies, 15 years ago
File size: 37.6 KB
RevLine 
[5284]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)) {
[5876]433 //if (proto!=app->proto) cout << "protocols not matching" << endl;
434 //if (port !=app->port) cout << "ports not matching" << endl;
[5284]435
436 return ((proto==app->proto) && (port==app->port));
437 } else return false;
438 } else return false;
439} // end operator==
440
441
442/***** class netaddress *****/
443
444/***** inherited from IE *****/
445
446netaddress* netaddress::new_instance() const {
447 netaddress* na = NULL;
448 catch_bad_alloc(na = new netaddress());
449 return na;
450} // end new_instance
451
452netaddress* netaddress::copy() const {
453 netaddress* na = NULL;
454 catch_bad_alloc(na = new netaddress(*this));
455 return na;
456} // end copy
457
458bool netaddress::operator==(const address& ie) const {
459 const netaddress* na = dynamic_cast<const netaddress*>(&ie);
460 if (na) {
461 // if the IEs are equal when casted to type hostaddress, then
462 // only prefix lengths have to be checked.
463 // Otherwise they are not equal.
464 if (hostaddress::operator==(ie)) {
465 if (prefix_length!=na->prefix_length) cout << "Prefix length not matching" << endl;
466 return (prefix_length==na->prefix_length);
467 } else return false;
468 } else return false;
469} // end operator==
470
471
472/***** inherited from hostaddress *****/
473
474/** Convert the IP address to IPv6 by mapping it from IPv4 to IPv6 if
475 * necessary. The prefix length is converted, too.
476 */
477void netaddress::convert_to_ipv6() {
478 if (ipv4flag) {
479 // map IP
480 hostaddress::convert_to_ipv6();
481 // adjust prefix length
482 set_pref_len(prefix_length+96);
483 } // end if ipv4flag
484} // end convert_to_ipv6
485
486/** Set subtype and IPv4 flag. This does NOT clear the outstring buffer.
487 * Use clear_ip().
488 * In addition the prefix length is checked and set to reasonable values.
489 */
490void netaddress::set_subtype(bool ipv4) {
491 ipv4flag = ipv4;
492 if (ipv4) {
493 subtype = IPv4NetAddress;
494 if (prefix_length>32) prefix_length = 32;
495 } else {
496 subtype = IPv6NetAddress;
497 if (prefix_length>128) prefix_length = 128;
498 } // end if ipv4flag
499} // end set_subtype
500
501/***** new members in netaddress *****/
502
503/** Constructor sets address type and clears prefix length. */
504netaddress::netaddress() :
505 hostaddress(),
506 prefix_length(0)
507 {
508 set_subtype(ipv4flag);
509} // end constructor
510
511netaddress::netaddress(const netaddress& na) : hostaddress(na) {
512 prefix_length = na.prefix_length;
513 set_subtype(ipv4flag);
514} // end copy constructor
515
516/** Initialize with the given host address and prefix length.
517 * Prefix length is optional and set to 0 if missing.
518 */
519netaddress::netaddress(const hostaddress& h, prefix_length_t len) : hostaddress(h) {
520 set_subtype(ipv4flag);
521 set_pref_len(len); // this will cut the prefix value accordingly
522} // end constructor(hostaddress,len)
523
524/** Initialize from string which contains IP and prefix length separated by
525 * '/'.
526 */
527netaddress::netaddress(const char* str, bool *res) : hostaddress() {
528 bool tmpres = true; // MUST BE true
529 bool tmpres2 = false;
530 long int len = 0;
531 uint32 iplen;
532 char* i = NULL;
533 char* errptr = NULL;
534 char ipstr[INET6_ADDRSTRLEN] = {0};
535 // look for /
536 i = strchr(str,'/');
537 if (i) {
538 iplen = i-str;
539 i++;
540 // decode prefix length
541 len = strtol(i,&errptr,10);
542 if ((*i) && errptr && ((*errptr)==0)) {
543 // prefix OK
544 prefix_length = len;
545 } else {
546 prefix_length = 0;
547 tmpres = false;
548 } // end if prefix OK
549 if (iplen<=INET6_ADDRSTRLEN) {
550 // copy IP string
551 strncpy(ipstr,str,iplen);
552 ipstr[INET6_ADDRSTRLEN-1] = 0;
553 // set str to ipstr
554 str = ipstr;
555 } // end if iplen valid
556 } else {
557 // no prefix found, OK
558 prefix_length = 0;
559 } // end if i
560 // set IP, this also sets ipvflag.
561 tmpres2 = set_ip(str);
562 if (res) *res = (tmpres && tmpres2);
563 set_subtype(ipv4flag);
564} // end constructor(string)
565
566/** Initialize from string and prefix length.
567 * If the string does not contain a valid IP address, it is set to all 0 by
568 * the hostaddress constructor.
569 */
570netaddress::netaddress(const char* str, prefix_length_t len, bool *res) : hostaddress(str,res) {
571 set_subtype(ipv4flag);
572 set_pref_len(len); // this will cut the prefix value accordingly
573} // end constructor(string,port)
574
575/** Assigns the given netaddress address by using hostaddress::operator=(). */
576netaddress& netaddress::operator=(const netaddress& na) {
577 prefix_length = na.prefix_length;
578 hostaddress::operator=(na);
579 return *this;
580} // end operator=
581
582
583/** Assigns the given netaddress address by using hostaddress::operator=(). */
584netaddress& netaddress::operator=(const hostaddress& na) {
585 hostaddress::operator=(na);
586 set_pref_len(128);
587 return *this;
588} // end operator=
589
590
591/** Set prefix length and return old value.
592 * will also cut prefix_length if needed (i.e., if len too large for addr type)
593 */
594prefix_length_t netaddress::set_pref_len(prefix_length_t len) {
595 register prefix_length_t olen = prefix_length;
596 prefix_length = ipv4flag ? ( (len>32) ? 32 : len ) :
597 ( (len>128) ? 128 : len );
598 return olen;
599} // end set_port
600
601
602
603/** Compare two netaddress objects. If neither a<b and b<a then a and b are
604 * considered equal.
605 */
606bool netaddress::operator<(const netaddress& na) const {
607 uint32 word1 = 0;
608 uint32 word2 = 0;
609 prefix_length_t lenwords = prefix_length/32;
610 prefix_length_t lenbits = prefix_length%32;
611 // now 0<=lenwords<=4, 0<=lenbits<=31
612 prefix_length_t i;
613 // IPv4 is always < IPv6
614 if ((!ipv4flag) && na.ipv4flag) return false;
615 else if (ipv4flag && (!na.ipv4flag)) return true;
616 // now ipv4flag == na.ipv4flag
617 else if (prefix_length<na.prefix_length) return true;
618 else if (prefix_length>na.prefix_length) return false;
619 // now prefix_length == na.prefix_length
620 else if (ipv4flag) {
621 // compare IPv4 with same prefix length
622 word1 = ntohl(ipv4addr.s_addr);
623 word2 = ntohl(na.ipv4addr.s_addr);
624 // shift right
625 word1 >>= (32-lenbits);
626 word2 >>= (32-lenbits);
627 if (word1<word2) return true;
628 else return false;
629 } else {
630 // compare IPv6 with same prefix length
631 // compare words
632 for (i=0;i<lenwords;i++) {
633 word1 = ntohl(ipv6addr.s6_addr32[i]);
634 word2 = ntohl(na.ipv6addr.s6_addr32[i]);
635 if (word1<word2) return true;
636 if (word1>word2) return false;
637 } // end for i
638 // now i points to the next word to be compared and previous words are equal
639 // compare bits
640 if (lenbits) {
641 word1 = ntohl(ipv6addr.s6_addr32[i]);
642 word2 = ntohl(na.ipv6addr.s6_addr32[i]);
643 // shift right
644 word1 >>= (32-lenbits);
645 word2 >>= (32-lenbits);
646 if (word1<word2) return true;
647 else return false;
648 } else {
649 // no extra bist to compare and everything equal
650 return false;
651 } // end if lenbits
652 } // end if ipv4flag, prefox
653} // end match_against
654
655/**
656 * Compare function for the radix trie:
657 *
658 * Compare this and na from *pos up to max(this->prefix, na->prefix)
659 *
660 * In pos return the position where the compare ended.
661 *
662 * The return value is 0 if the strings are equal and all of this' string
663 * was consumed, otherwise the sign will indicate the bit in this' string
664 * at pos (i.e. if the search should continue left or right of na).
665 *
666 * pos < 0 indicates error
667 */
668int
669netaddress::rdx_cmp(const netaddress *na, int *pos) const
670{
671 if (na == NULL) {
672 *pos = -1;
673 return 0;
674 }
675
676 if (na->ipv4flag != ipv4flag ||
677 *pos > na->prefix_length ||
678 *pos > prefix_length) {
679 *pos = -1;
680 return 0;
681 }
682
683 if (na->prefix_length == 0) {
684 *pos = 1;
685 if (ipv4flag)
686 return ((ntohl(ipv4addr.s_addr) & 0x80000000) == 0 ?
687 -1 : 1);
688 else
689 return ((htonl(ipv6addr.s6_addr32[0]) & 0x80000000) == 0 ?
690 -1 : 1);
691 }
692
693 if (*pos < 0)
694 *pos = 0;
695
696 uint32_t w1, w2, w3;
697 int diff, i, p1, p2;
698
699 if (ipv4flag) {
700 diff = *pos;
701 w1 = ntohl(ipv4addr.s_addr);
702 w2 = ntohl(na->ipv4addr.s_addr);
703 // in w3 store the difference
704 w3 = w1 ^ w2;
705 // mask out anything after prefix_length and before *pos
706 w3 = (w3 >> (32 - prefix_length)) << (32 - prefix_length + diff);
707 if (w3 == 0 && prefix_length <= na->prefix_length) {
708 *pos = min(prefix_length, na->prefix_length);
709 return 0;
710 }
711 // pos = 0 means start up front, so we need to fix up to that
712 diff++;
713 while (diff <= prefix_length && diff <= na->prefix_length) {
714 if ((w3 & 0x80000000) != 0) {
715 *pos = diff;
716 return (((w1 & (1 << (32 - diff))) >>
717 (32 - diff)) == 0 ? -1 : 1);
718 }
719 w3 = w3 << 1;
720 diff++;
721 }
722 // difference past na->prefix_length
723 *pos = diff;
724 return (((w1 & (1 << (32 - diff))) >>
725 (32 - diff)) == 0 ? -1 : 1);
726 }
727
728 diff = *pos;
729 for (i = diff / 32; i < 4; i++) {
730 diff = diff % 32;
731 w1 = ntohl(ipv6addr.s6_addr32[i]);
732 w2 = ntohl(na->ipv6addr.s6_addr32[i]);
733 w3 = w1 ^ w2;
734 p1 = (prefix_length - (i * 32));
735 p1 = p1 > 32 ? 32 : p1;
736 p2 = (na->prefix_length - (i * 32));
737 p1 = p2 > 32 ? 32 : p2;
738
739 w3 = (w3 >> (32 - p1)) << (32 - p1 + diff);
740 if (w3 == 0 && prefix_length <= na->prefix_length) {
741 *pos = min(prefix_length, na->prefix_length);
742 if (prefix_length <= ((i + 1) * 32))
743 return 0;
744 }
745 // pos = 0 means start up front, so we need to fix up to that
746 diff++;
747 while (diff <= p1 && diff <= p2) {
748 if ((w3 & 0x80000000) != 0) {
749 *pos = diff + (i * 32);
750 return (((w1 & (1 << (32 - diff))) >>
751 (32 - diff)) == 0 ? -1 : 1);
752 }
753 w3 = w3 << 1;
754 diff++;
755 }
756 if (diff + (32 * i) <= prefix_length &&
757 diff + (32 * i) <= na->prefix_length) {
758 diff--;
759 continue;
760 }
761 // difference past na->prefix_length
762 *pos = diff + (i * 32);
763 if (diff == 33) {
764 diff = 1;
765 if (i == 3)
766 abort();
767 w1 = ntohl(ipv6addr.s6_addr32[i+1]);
768 }
769 return (((w1 & (1 << (32 - diff))) >>
770 (32 - diff)) == 0 ? -1 : 1);
771 }
772
773 // Not reachable, but gcc complains
774 return 0;
775}
776
777udsaddress* udsaddress::new_instance() const {
778 udsaddress* ha = NULL;
779 catch_bad_alloc(ha = new udsaddress());
780 return ha;
781} // end new_instance
782
783udsaddress* udsaddress::copy() const {
784 udsaddress* ha = NULL;
785 catch_bad_alloc(ha = new udsaddress(*this));
786 return ha;
787} // end copy
788
789bool udsaddress::operator==(const address& ie) const {
790 const udsaddress* app = dynamic_cast<const udsaddress*>(&ie);
791 if (app) {
792 return (app->socknum == socknum) && (app->uds_socket == uds_socket);
793 } else return false;
794} // end operator==
795
796AddressList::AddrProperty *AddressList::LocalAddr_P;
797AddressList::AddrProperty *AddressList::ConfiguredAddr_P;
798AddressList::AddrProperty *AddressList::IgnoreAddr_P;
799AddressList::AddrProperty *AddressList::AnyAddr_P;
800
801AddressList::AddressList()
802{
803 if (LocalAddr_P == 0) {
804 LocalAddr_P = new AddrProperty("local");
805 ConfiguredAddr_P = new AddrProperty("configured");
806 IgnoreAddr_P = new AddrProperty("ignore");
807 AnyAddr_P = new AddrProperty("wildcard");
808 }
809 interfaces = 0;
810}
811
812AddressList::~AddressList()
813{
814 // Refcount AddressLists in order to GC properties?
815}
816
817AddressList::iflist_t *
818AddressList::get_interfaces()
819{
820 iflist_t *iflist;
821
822 if (interfaces != 0)
823 iflist = new iflist_t(*interfaces);
824 else {
825 iflist = new iflist_t();
826 getifaddrs_iflist(*iflist);
827 }
828
829 return iflist;
830}
831
832bool
833AddressList::by_interface(bool start_empty)
834{
835 if (interfaces != 0)
836 return false;
837
838 interfaces = new iflist_t();
839 if (!start_empty)
840 getifaddrs_iflist(*interfaces);
841
842 return true;
843}
844
845bool
846AddressList::add_interface(char *name)
847{
848 if (interfaces == 0)
849 return false;
850
851 return (interfaces->insert(name)).second;
852}
853
854bool
855AddressList::del_interface(char *name)
856{
857 if (interfaces == 0)
858 return false;
859
860 return (interfaces->erase(name) > 0);
861}
862
863bool
864AddressList::add_property(netaddress &na, AddrProperty *p, bool propagate)
865{
866 propmap_t *props, *lpfm_props;
867 propmap_t::iterator it;
868 addr2prop_t::node *node;
869
870 node = prop_trie.lookup_node(na, false, false);
871 if (node != NULL) {
872 props = node->data;
873 if (props == NULL) {
874 props = new propmap_t();
875 node->data = props;
876 }
877 props->insert(pair<AddrProperty *, bool>(p, propagate));
878
879 } else {
880 props = new propmap_t();
881 props->insert(pair<AddrProperty *, bool>(p, propagate));
882 node = prop_trie.insert(na, *props);
883 }
884
885 if (propagate)
886 bequeath(node, p, true);
887
888 // copy lpfm properties
889 lpfm_props = prop_trie.lookup(na, true);
890 if (lpfm_props == NULL)
891 return true;
892
893 for (it = lpfm_props->begin(); it != lpfm_props->end(); it++) {
894 if ((*it).second)
895 props->insert((*it));
896 }
897
898 return true;
899}
900
901bool
902AddressList::del_property(netaddress &na, AddrProperty *p, bool propagate)
903{
904 propmap_t *props, *lpfm_props;
905 propmap_t::iterator it;
906 addr2prop_t::node *node;
907
908 node = prop_trie.lookup_node(na, false, true);
909 if (node == NULL) {
910 // no exact match
911 if (!propagate) {
912 node = prop_trie.lookup_node(na, true, true);
913 if (node == NULL) {
914 // no lpfm either, we're done
915 return false;
916 }
917
918 props = node->data;
919 it = props->find(p);
920 if (it == props->end()) {
921 // lpfm doesn't have p set -> done
922 return false;
923 }
924 }
925 // insert an empty propmap
926 props = new propmap_t();
927 node = prop_trie.insert(na, *props);
928
929 // copy other lpfm properties
930 lpfm_props = prop_trie.lookup(na, true);
931 if (p != AnyAddr_P && lpfm_props != NULL) {
932 for (it = lpfm_props->begin(); it != lpfm_props->end();
933 it++) {
934 if ((*it).first != p && (*it).second)
935 props->insert((*it));
936 }
937 }
938 } else {
939 props = node->data;
940 if (p == AnyAddr_P) {
941 props->clear();
942 } else {
943 it = props->find(p);
944 if (it == props->end() && !propagate)
945 return false;
946
947 props->erase(it);
948 }
949 }
950
951 if (propagate)
952 bequeath(node, p, false);
953
954 return true;
955}
956
957bool
958AddressList::add_host_prop(const char *name, AddrProperty *p)
959{
960 netaddress na;
961 sockaddr_in *sin;
962 sockaddr_in6 *sin6;
963 struct addrinfo hints = {0}, *res, *cur;
964 int error;
965 char buf[1024];
966
967 if (name == NULL) {
968 name = buf;
969 if (gethostname(buf, sizeof(buf)) != 0)
970 return false;
971 buf[sizeof(buf) - 1] = '\0';
972 }
973 hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
974 hints.ai_family = AF_UNSPEC;
975 error = getaddrinfo(name, NULL, &hints, &res);
976 if (error != 0)
977 return false;
978
979 for(cur = res; cur != NULL && error == 0; cur = cur->ai_next) {
980 if (cur->ai_family == AF_INET) {
981 sin = (struct sockaddr_in *)cur->ai_addr;
982 na.set_ip(sin->sin_addr);
983 na.set_pref_len(32);
984 } else if (cur->ai_family == AF_INET6) {
985 sin6 = (struct sockaddr_in6 *)cur->ai_addr;
986 na.set_ip(sin6->sin6_addr);
987 na.set_pref_len(128);
988 } else
989 continue;
990
991 // cout << ++i << "XXMOB: " << na << endl;
992
993 error += add_property(na, p) ? 0 : 1;
994 // XXXMOB: for some reason we need a 'reset' here
995 // if we want to use /etc/hosts
996 na.set_ip("127.0.0.1");
997 }
998 freeaddrinfo(res);
999
1000 return (error == 0);
1001}
1002
1003bool
1004AddressList::del_host_prop(const char *name, AddrProperty *p)
1005{
1006 netaddress na;
1007 sockaddr_in *sin;
1008 sockaddr_in6 *sin6;
1009 struct addrinfo hints = {0}, *res, *cur;
1010 int error;
1011 char buf[1024];
1012
1013 if (name == NULL) {
1014 name = buf;
1015 if (gethostname(buf, sizeof(buf)) != 0)
1016 return false;
1017 buf[sizeof(buf) - 1] = '\0';
1018 }
1019 hints.ai_flags = AI_ADDRCONFIG;
1020 hints.ai_family = AF_UNSPEC;
1021 error = getaddrinfo(name, NULL, &hints, &res);
1022 if (error != 0)
1023 return false;
1024
1025 for(cur = res; cur != NULL && error == 0; cur = cur->ai_next) {
1026 if (cur->ai_family == AF_INET) {
1027 sin = (struct sockaddr_in *)cur->ai_addr;
1028 na.set_ip(sin->sin_addr);
1029 na.set_pref_len(32);
1030 } else if (cur->ai_family == AF_INET6) {
1031 sin6 = (struct sockaddr_in6 *)cur->ai_addr;
1032 na.set_ip(sin6->sin6_addr);
1033 na.set_pref_len(128);
1034 } else
1035 continue;
1036
1037 error += del_property(na, p) ? 0 : 1;
1038 }
1039 freeaddrinfo(res);
1040
1041 return (error == 0);
1042}
1043
1044bool
1045AddressList::ignore(netaddress &na, bool propagate)
1046{
1047 del_property(na, AnyAddr_P, propagate);
1048 return add_property(na, IgnoreAddr_P);
1049}
1050
1051bool
1052AddressList::unignore(netaddress &na, bool propagate)
1053{
1054 return del_property(na, IgnoreAddr_P, propagate);
1055}
1056
1057bool
1058AddressList::ignore_bogons(void)
1059{
1060 netaddress na;
1061
1062 // according to IANA Tue Apr 17 09:14:31 PDT 2007
1063 na.set_ip("0.0.0.0");na.set_pref_len(7);
1064 ignore(na);
1065 na.set_ip("2.0.0.0");na.set_pref_len(8);
1066 ignore(na);
1067 na.set_ip("5.0.0.0");na.set_pref_len(8);
1068 ignore(na);
1069 na.set_ip("7.0.0.0");na.set_pref_len(8);
1070 ignore(na);
1071 na.set_ip("23.0.0.0");na.set_pref_len(8);
1072 ignore(na);
1073 na.set_ip("27.0.0.0");na.set_pref_len(8);
1074 ignore(na);
1075 na.set_ip("31.0.0.0");na.set_pref_len(8);
1076 ignore(na);
1077 na.set_ip("36.0.0.0");na.set_pref_len(7);
1078 ignore(na);
1079 na.set_ip("39.0.0.0");na.set_pref_len(8);
1080 ignore(na);
1081 na.set_ip("42.0.0.0");na.set_pref_len(8);
1082 ignore(na);
1083 na.set_ip("49.0.0.0");na.set_pref_len(8);
1084 ignore(na);
1085 na.set_ip("50.0.0.0");na.set_pref_len(8);
1086 ignore(na);
1087 na.set_ip("94.0.0.0");na.set_pref_len(7);
1088 ignore(na);
1089 na.set_ip("100.0.0.0");na.set_pref_len(6);
1090 ignore(na);
1091 na.set_ip("104.0.0.0");na.set_pref_len(5);
1092 ignore(na);
1093 na.set_ip("112.0.0.0");na.set_pref_len(6);
1094 ignore(na);
1095 na.set_ip("169.254.0.0");na.set_pref_len(16);
1096 ignore(na);
1097 na.set_ip("173.0.0.0");na.set_pref_len(8);
1098 ignore(na);
1099 na.set_ip("174.0.0.0");na.set_pref_len(7);
1100 ignore(na);
1101 na.set_ip("176.0.0.0");na.set_pref_len(5);
1102 ignore(na);
1103 na.set_ip("184.0.0.0");na.set_pref_len(6);
1104 ignore(na);
1105 na.set_ip("191.0.0.0");na.set_pref_len(8);
1106 ignore(na);
1107 na.set_ip("192.0.2.0");na.set_pref_len(24);
1108 ignore(na);
1109 na.set_ip("197.0.0.0");na.set_pref_len(8);
1110 ignore(na);
1111 na.set_ip("198.18.0.0");na.set_pref_len(15);
1112 ignore(na);
1113 na.set_ip("223.0.0.0");na.set_pref_len(8);
1114 ignore(na);
1115 na.set_ip("240.0.0.0");na.set_pref_len(4);
1116 ignore(na);
1117 // according to http://www.cymru.com/Documents/bogonv6-list.html#agg
1118 na.set_ip("0000::");na.set_pref_len(8);
1119 ignore(na);
1120 na.set_ip("0100::");na.set_pref_len(8);
1121 ignore(na);
1122 na.set_ip("0200::");na.set_pref_len(7);
1123 ignore(na);
1124 na.set_ip("0400::");na.set_pref_len(7);
1125 ignore(na);
1126 na.set_ip("0600::");na.set_pref_len(7);
1127 ignore(na);
1128 na.set_ip("0800::");na.set_pref_len(5);
1129 ignore(na);
1130 na.set_ip("1000::");na.set_pref_len(4);
1131 ignore(na);
1132 na.set_ip("2000::");na.set_pref_len(16);
1133 ignore(na);
1134 na.set_ip("2001:1000::");na.set_pref_len(23);
1135 ignore(na);
1136 na.set_ip("2001:1600::");na.set_pref_len(23);
1137 ignore(na);
1138 na.set_ip("2001:2000::");na.set_pref_len(20);
1139 ignore(na);
1140 na.set_ip("2001:3000::");na.set_pref_len(20);
1141 ignore(na);
1142 na.set_ip("2001:4000::");na.set_pref_len(20);
1143 ignore(na);
1144 na.set_ip("2001:5000::");na.set_pref_len(20);
1145 ignore(na);
1146 na.set_ip("2001:6000::");na.set_pref_len(20);
1147 ignore(na);
1148 na.set_ip("2001:7000::");na.set_pref_len(20);
1149 ignore(na);
1150 na.set_ip("2001:8000::");na.set_pref_len(20);
1151 ignore(na);
1152 na.set_ip("2001:9000::");na.set_pref_len(20);
1153 ignore(na);
1154 na.set_ip("2001:A000::");na.set_pref_len(20);
1155 ignore(na);
1156 na.set_ip("2001:B000::");na.set_pref_len(20);
1157 ignore(na);
1158 na.set_ip("2001:C000::");na.set_pref_len(20);
1159 ignore(na);
1160 na.set_ip("2001:D000::");na.set_pref_len(20);
1161 ignore(na);
1162 na.set_ip("2001:E000::");na.set_pref_len(20);
1163 ignore(na);
1164 na.set_ip("2001:F000::");na.set_pref_len(20);
1165 ignore(na);
1166 na.set_ip("3FFF::");na.set_pref_len(16);
1167 ignore(na);
1168 na.set_ip("4000::");na.set_pref_len(3);
1169 ignore(na);
1170 na.set_ip("6000::");na.set_pref_len(3);
1171 ignore(na);
1172 na.set_ip("8000::");na.set_pref_len(3);
1173 ignore(na);
1174 na.set_ip("A000::");na.set_pref_len(3);
1175 ignore(na);
1176 na.set_ip("C000::");na.set_pref_len(3);
1177 ignore(na);
1178 na.set_ip("E000::");na.set_pref_len(4);
1179 ignore(na);
1180 na.set_ip("F000::");na.set_pref_len(5);
1181 ignore(na);
1182 na.set_ip("F800::");na.set_pref_len(6);
1183 ignore(na);
1184 na.set_ip("FC00::");na.set_pref_len(7);
1185 ignore(na);
1186 na.set_ip("FE00::");na.set_pref_len(9);
1187 ignore(na);
1188
1189 return true;
1190}
1191
1192bool
1193AddressList::ignore_locals(void)
1194{
1195 netaddress na;
1196
1197 na.set_ip("10.0.0.0");na.set_pref_len(8);
1198 ignore(na);
1199 na.set_ip("172.16.0.0");na.set_pref_len(12);
1200 ignore(na);
1201 na.set_ip("192.168.0.0");na.set_pref_len(16);
1202 ignore(na);
1203 na.set_ip("FE80::");na.set_pref_len(10);
1204 ignore(na);
1205 na.set_ip("FEC0::");na.set_pref_len(10);
1206 ignore(na);
1207
1208 return true;
1209}
1210
1211bool
1212AddressList::ignore_loopback(void)
1213{
1214 netaddress na;
1215
1216 na.set_ip("127.0.0.0");na.set_pref_len(8);
1217 ignore(na);
1218 na.set_ip("::1");na.set_pref_len(128);
1219 ignore(na);
1220
1221 return true;
1222}
1223
1224bool
1225AddressList::addr_is(netaddress &na, AddrProperty *prop)
1226{
1227 propmap_t *props;
1228 propmap_t::iterator it;
1229
1230 if (addr_is_in(na, IgnoreAddr_P))
1231 return false;
1232
1233 props = prop_trie.lookup(na, false);
1234 if (props != NULL) {
1235 it = props->find(prop);
1236 if (it != props->end()) {
1237 return true;
1238 }
1239 }
1240
1241 if (prop != LocalAddr_P)
1242 return false;
1243
1244 return getifaddrs_is_local(na);
1245}
1246
1247bool
1248AddressList::addr_is_in(netaddress &na, AddrProperty *prop)
1249{
1250 addr2prop_t::node *node;
1251 propmap_t *props;
1252 propmap_t::iterator it;
1253
1254 node = prop_trie.lookup_node(na, true, true);
1255 if (node == NULL)
1256 return false;
1257
1258 props = node->data;
1259 it = props->find(prop);
1260 if (it == props->end())
1261 return false;
1262
1263 if (!(*it).second && props != prop_trie.lookup(na, false))
1264 return false;
1265
1266 return true;
1267}
1268
1269AddressList::addrlist_t *
1270AddressList::get_addrs(AddrProperty *prop)
1271{
1272 addr2prop_t::node *node;
1273 netaddress na;
1274 addrlist_t *res = new addrlist_t();
1275
1276 if (res == 0)
1277 return res;
1278
1279 if (prop == LocalAddr_P || prop == AnyAddr_P)
1280 getifaddrs_get_addrs(*res);
1281
1282 na.set_ip("0.0.0.0");
1283 na.set_pref_len(0);
1284 node = prop_trie.lookup_node(na, true, false);
1285 collect(node, prop, *res);
1286
1287 na.set_ip("::");
1288 node = prop_trie.lookup_node(na, true, false);
1289 collect(node, prop, *res);
1290
1291 return res;
1292}
1293
1294netaddress *
1295AddressList::get_first(AddrProperty *p, bool IPv4)
1296{
1297 addr2prop_t::node *node;
1298 netaddress na;
1299 addrlist_t list;
1300 addrlist_t::iterator it;
1301
1302 if (IPv4) {
1303 na.set_ip("0.0.0.0");
1304 na.set_pref_len(0);
1305 } else {
1306 na.set_ip("::");
1307 na.set_pref_len(0);
1308 }
1309
1310 node = prop_trie.lookup_node(na, true, false);
1311 node = collect_first(node, p);
1312 if (node != NULL)
1313 return new netaddress(*node->key);
1314
1315 if (p == LocalAddr_P) {
1316 getifaddrs_get_addrs(list);
1317 for (it = list.begin(); it != list.end(); it++)
1318 if ((*it).is_ipv4() == IPv4)
1319 return new netaddress(*it);
1320 }
1321
1322 return NULL;
1323}
1324
1325netaddress *
1326AddressList::get_src_addr(const netaddress &dest, uint32_t *prefs)
1327{
1328 netaddress *res;
1329 int sfd;
1330
1331 sfd = socket(dest.is_ipv4()?AF_INET:AF_INET6, SOCK_DGRAM, 0);
1332 if (sfd == -1)
1333 return NULL;
1334
1335#ifdef IPV6_ADDR_PREFERENCES
1336 if (prefs != NULL && setsockopt(s, IPV6_ADDR_PREFERENCES,
1337 (void *)prefs, sizeof (*prefs)) == -1) {
1338 close(sfd);
1339 return NULL;
1340 }
1341#endif
1342 if (dest.is_ipv4()) {
1343 struct sockaddr_in sin = {0};
1344 socklen_t slen = sizeof(sin);
1345 sin.sin_family = AF_INET;
1346 sin.sin_port = htons(4);
1347 dest.get_ip(sin.sin_addr);
1348 if (connect(sfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
1349 close(sfd);
1350 return NULL;
1351 }
1352 if (getsockname(sfd, (struct sockaddr *)&sin, &slen) == -1) {
1353 close(sfd);
1354 return NULL;
1355 }
1356 close(sfd);
1357 res = new netaddress();
1358 res->set_ip(sin.sin_addr);
1359 res->set_pref_len(32);
1360 return (res);
1361 } else {
1362 struct sockaddr_in6 sin6 = {0};
1363 socklen_t slen = sizeof(sin6);
1364 sin6.sin6_family = AF_INET6;
1365 sin6.sin6_port = htons(4);
1366 dest.get_ip(sin6.sin6_addr);
1367 if (connect(sfd, (struct sockaddr *)&sin6,
1368 sizeof(sin6)) == -1) {
1369 close(sfd);
1370 return NULL;
1371 }
1372 if (getsockname(sfd, (struct sockaddr *)&sin6, &slen) == -1) {
1373 close(sfd);
1374 return NULL;
1375 }
1376 close(sfd);
1377 res = new netaddress();
1378 res->set_ip(sin6.sin6_addr);
1379 res->set_pref_len(128);
1380 return (res);
1381 }
1382}
1383
1384void
1385AddressList::getifaddrs_iflist(iflist_t &list)
1386{
1387 struct ifaddrs *ifap, *cifa;
1388
1389 if (::getifaddrs(&ifap) != 0)
1390 return;
1391
1392 for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
1393 list.insert(cifa->ifa_name);
1394 }
1395
1396 freeifaddrs(ifap);
1397}
1398
1399bool
1400AddressList::getifaddrs_is_local(netaddress &na)
1401{
1402 struct ifaddrs *ifap, *cifa;
1403
1404 if (::getifaddrs(&ifap) != 0)
1405 return false;
1406
1407 for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
1408 hostaddress ha;
1409
1410 if (cifa->ifa_addr->sa_family == AF_INET) {
1411 ha.set_ip(
1412 ((struct sockaddr_in *)cifa->ifa_addr)->sin_addr);
1413 } else if (cifa->ifa_addr->sa_family == AF_INET6) {
1414 ha.set_ip(
1415 ((struct sockaddr_in6 *)cifa->ifa_addr)->sin6_addr);
1416 } else {
1417 continue;
1418 }
1419
1420 if (interfaces &&
1421 interfaces->find(cifa->ifa_name) == interfaces->end())
1422 continue;
1423
1424 if (ha.match_against(na) >= na.get_pref_len()) {
1425 freeifaddrs(ifap);
1426 return true;
1427 }
1428 }
1429
1430 freeifaddrs(ifap);
1431
1432 return false;
1433}
1434
1435void
1436AddressList::getifaddrs_get_addrs(addrlist_t &list)
1437{
1438 struct ifaddrs *ifap, *cifa;
1439
1440 if (::getifaddrs(&ifap) != 0)
1441 return;
1442
1443 for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
1444 hostaddress *ha;
1445 netaddress na;
1446
1447 if (interfaces &&
1448 interfaces->find(cifa->ifa_name) == interfaces->end())
1449 continue;
1450
1451 if (cifa->ifa_addr->sa_family == AF_INET) {
1452 ha = new hostaddress;
1453 ha->set_ip(
1454 ((struct sockaddr_in *)cifa->ifa_addr)->sin_addr);
1455 na.set_pref_len(32);
1456 } else if (cifa->ifa_addr->sa_family == AF_INET6) {
1457 ha = new hostaddress;
1458 ha->set_ip(
1459 ((struct sockaddr_in6 *)cifa->ifa_addr)->sin6_addr);
1460 na.set_pref_len(128);
1461 } else {
1462 continue;
1463 }
1464
1465 na.set_ip(*ha);
1466 if (!addr_is_in(na, IgnoreAddr_P))
1467 list.insert(*ha);
1468 }
1469
1470 freeifaddrs(ifap);
1471}
1472
1473void
1474AddressList::bequeath(addr2prop_t::node *head, AddrProperty *p, bool add)
1475{
1476 propmap_t *props;
1477 propmap_t::iterator it;
1478
1479 if (p == AnyAddr_P && add)
1480 return;
1481
1482 props = head->data;
1483 if (props != NULL) {
1484 if (p == AnyAddr_P) {
1485 props->clear();
1486 } else {
1487 if (add) {
1488 props->insert(pair<AddrProperty *, bool>
1489 (p, true));
1490 } else {
1491 it = props->find(p);
1492 if (it != props->end())
1493 props->erase(it);
1494 }
1495 }
1496 }
1497
1498 if (head->left->index > head->index)
1499 bequeath(head->left, p, add);
1500 if (head->right->index > head->index)
1501 bequeath(head->right, p, add);
1502}
1503
1504void
1505AddressList::collect(addr2prop_t::node *head, AddrProperty *p,
1506 addrlist_t &list)
1507{
1508 propmap_t *props;
1509 propmap_t::iterator it;
1510
1511 props = head->data;
1512 if (props != NULL) {
1513 if (p == AnyAddr_P) {
1514 it = props->begin();
1515 } else {
1516 it = props->find(p);
1517 }
1518 if (it != props->end()) {
1519 list.insert(*(new netaddress(*head->key)));
1520 }
1521 }
1522
1523 if (head->left->index > head->index)
1524 collect(head->left, p, list);
1525 if (head->right->index > head->index)
1526 collect(head->right, p, list);
1527
1528}
1529
1530AddressList::addr2prop_t::node *
1531AddressList::collect_first(addr2prop_t::node *head, AddrProperty *p)
1532{
1533 addr2prop_t::node *res = NULL;
1534 propmap_t *props;
1535 propmap_t::iterator it;
1536
1537 props = head->data;
1538 if (props != NULL) {
1539 if (p == AnyAddr_P) {
1540 it = props->begin();
1541 } else {
1542 it = props->find(p);
1543 }
1544 if (it != props->end()) {
1545 return head;
1546 }
1547 }
1548
1549 if (head->left->index > head->index) {
1550 res = collect_first(head->left, p);
1551 if (res != NULL)
1552 return res;
1553 }
1554 if (head->right->index > head->index) {
1555 res = collect_first(head->right, p);
1556 if (res != NULL)
1557 return res;
1558 }
1559
1560 return NULL;
1561}
1562
1563
1564} // end namespace protlib
Note: See TracBrowser for help on using the repository browser.