1 //  $Id$
2 // Copyright (c) 2001,2002                        RIPE NCC
3 //
4 // All Rights Reserved
5 //
6 // Permission to use, copy, modify, and distribute this software and its
7 // documentation for any purpose and without fee is hereby granted,
8 // provided that the above copyright notice appear in all copies and that
9 // both that copyright notice and this permission notice appear in
10 // supporting documentation, and that the name of the author not be
11 // used in advertising or publicity pertaining to distribution of the
12 // software without specific, written prior permission.
13 //
14 // THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 // ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
16 // AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
17 // DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
18 // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 //
21 //
22 //  Copyright (c) 1994 by the University of Southern California
23 //  All rights reserved.
24 //
25 //    Permission is hereby granted, free of charge, to any person obtaining a copy
26 //    of this software and associated documentation files (the "Software"), to deal
27 //    in the Software without restriction, including without limitation the rights
28 //    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29 //    copies of the Software, and to permit persons to whom the Software is
30 //    furnished to do so, subject to the following conditions:
31 //
32 //    The above copyright notice and this permission notice shall be included in
33 //    all copies or substantial portions of the Software.
34 //
35 //    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 //    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 //    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38 //    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39 //    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40 //    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41 //    THE SOFTWARE.
42 //
43 //  Questions concerning this software should be directed to
44 //  irrtoolset@cs.usc.edu.
45 //
46 //  Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>
47 
48 #include "config.h"
49 
50 #ifndef AUTNUM_H
51 #define AUTNUM_H
52 
53 #include "rpsl/object.hh"
54 #include "dataset/SetOfUInt.hh"
55 #include "rpsl/List.hh"
56 #include "rpsl/schema.hh"
57 #include "irr/irr.hh"
58 #include "rpsl/prefix.hh"
59 #include "rpsl/rpsl_policy.hh"
60 #include <vector>
61 #include <string>
62 
63 using namespace std;
64 
65 #define INVALID_AS    ~0
66 
67 class Peering : public ListNode {
68 public:
69    ASt      peerAS;
70    MPPrefix peerIP;
71    MPPrefix localIP;
72 
73 public:
Peering(ASt _peerAS,const MPPrefix & _peerIP,const MPPrefix & _localIP)74    Peering(ASt _peerAS, const MPPrefix &_peerIP, const MPPrefix &_localIP)
75       : ListNode(), peerAS(_peerAS), peerIP(_peerIP), localIP(_localIP) {
76    }
Peering(const Peering & b)77    Peering(const Peering &b)
78       : ListNode(), peerAS(b.peerAS), peerIP(b.peerIP), localIP(b.localIP) {
79    }
~Peering()80    ~Peering() {
81    }
82 
operator <(const Peering & b) const83    bool operator < (const Peering &b) const {
84       return (peerAS < b.peerAS)
85 	 || (peerAS == b.peerAS && peerIP < b.peerIP)
86 	 || (peerAS == b.peerAS && peerIP == b.peerIP && localIP < b.localIP);
87    }
operator ==(const Peering & b) const88    bool operator == (const Peering &b) const {
89       return peerAS == b.peerAS && peerIP == b.peerIP && localIP == b.localIP;
90    }
91 };
92 
93 class AutNum : public Object {
94    friend class AutNumPeeringIterator;
95 private:
96    SortedList<Peering> *peerings;
97    void gatherPeerings(PolicyExpr *policy, SortedList<Peering> *peerings);
98    void gatherPeerings(PolicyPeering *peering, SortedList<Peering> *peerings);
99    void gatherASes(Filter *f, SetOfUInt *result);
100    void gatherRouters(Filter *f, MPPrefixRanges *result);
101 
102 public:
AutNum()103    AutNum() : Object(), peerings(NULL) {}
AutNum(Buffer & buf)104    AutNum(Buffer &buf) : Object(buf), peerings(NULL) {}
AutNum(const AutNum & au)105    AutNum(const AutNum &au) : Object(au), peerings(NULL) {
106    }
~AutNum()107    ~AutNum() {
108       if (peerings)
109 	 delete peerings;
110    }
111 
112    void gatherPeerings();
113    ASt asno(void) const;
114 };
115 
116 
117 class FilterAction : public ListNode {
118 public:
119    Filter       *filter;
120    PolicyActionList *action;
121 public:
FilterAction(Filter * f,PolicyActionList * a)122    FilterAction(Filter *f, PolicyActionList *a) : filter(f), action(a) {}
123 
FilterAction(const FilterAction & b)124    FilterAction(const FilterAction &b) {
125       filter = (Filter *) b.filter->dup();
126       action = (PolicyActionList *) b.action->dup();
127    }
128 
~FilterAction()129    ~FilterAction() {
130       delete filter;
131       delete action;
132    }
133 };
134 
isPeeringMatching(Filter * f,const ASt as)135 static bool isPeeringMatching(Filter *f, const ASt as) {
136    if (typeid(*f) == typeid(FilterASNO))
137       return ((FilterASNO *) f)->asno == as;
138    if (typeid(*f) == typeid(FilterASNAME)) {
139       SymID set = ((FilterASNAME *) f)->asname;
140       if (symbols.isASAny(set))
141 	 return true;
142       if (!irr)
143 	 return false;
144       const SetOfUInt *asSet = irr->expandASSet(set);
145       return (asSet && asSet->contains(as));
146    }
147    if (typeid(*f) == typeid(FilterAND))
148       return isPeeringMatching(((FilterAND *) f)->f1, as)
149 	 && isPeeringMatching(((FilterAND *) f)->f2, as);
150    if (typeid(*f) == typeid(FilterEXCEPT))
151       return isPeeringMatching(((FilterEXCEPT *) f)->f1, as)
152 	 && ! isPeeringMatching(((FilterEXCEPT *) f)->f2, as);
153    if (typeid(*f) == typeid(FilterOR))
154       return isPeeringMatching(((FilterOR *) f)->f1, as)
155 	 || isPeeringMatching(((FilterOR *) f)->f2, as);
156    assert(false);
157    return false;
158 }
159 
160 // REIMPLEMENTED
isPeeringMatching(Filter * f,const MPPrefix * ip)161 static bool isPeeringMatching(Filter *f, const MPPrefix *ip) {
162 
163    if (typeid(*f) == typeid(FilterANY))
164       return true;
165    if (typeid(*f) == typeid(FilterRouter)) {
166       return ((*((FilterRouter *) f)->ip) == *ip);
167    }
168    if (typeid(*f) == typeid(FilterRouterName)) {
169       char *dns = ((FilterRouterName *) f)->name;
170       if (!irr)
171 	 return false;
172       const InetRtr *rtr = irr->getInetRtr(dns);
173       if (!rtr)
174 	 return false;
175       AttrIterator<AttrIfAddr> itr(rtr, "ifaddr");
176       while (itr) {
177         if (ip->ipv4 && itr()->ifaddr->ipv4) {
178 	        if (itr()->ifaddr->ipv4->get_ipaddr() == ip->ipv4->get_ipaddr())
179 	          return true;
180         }
181 	    itr++;
182       }
183       AttrIterator<AttrIfAddr> itr1(rtr, "interface");
184       while (itr1) {
185          if (itr1()->ifaddr->ipv4 && ip->ipv4) {
186             if (itr1()->ifaddr->ipv4->get_ipaddr() == ip->ipv4->get_ipaddr())
187                return true;
188          }
189          if (itr1()->ifaddr->ipv6 && ip->ipv6) {
190             if (itr1()->ifaddr->get_ipaddr() == ip->get_ipaddr())
191                return true;
192          }
193          itr1++;
194       }
195 
196       return false;
197    }
198    if (typeid(*f) == typeid(FilterRTRSNAME)) {
199       SymID set = ((FilterRTRSNAME *) f)->rtrsname;
200       if (!irr)
201 	 return false;
202 
203       const MPPrefixRanges *rtrSet = irr->expandRtrSet(set);
204       return (rtrSet && rtrSet->contains(*ip));
205    }
206    if (typeid(*f) == typeid(FilterAND))
207       return isPeeringMatching(((FilterAND *) f)->f1, ip)
208 	 && isPeeringMatching(((FilterAND *) f)->f2, ip);
209    if (typeid(*f) == typeid(FilterEXCEPT))
210       return isPeeringMatching(((FilterEXCEPT *) f)->f1, ip)
211 	 && ! isPeeringMatching(((FilterEXCEPT *) f)->f2, ip);
212    if (typeid(*f) == typeid(FilterOR))
213       return isPeeringMatching(((FilterOR *) f)->f1, ip)
214 	 || isPeeringMatching(((FilterOR *) f)->f2, ip);
215    //if (typeid(*f) == typeid(FilterANY))
216    //   return true;
217    assert(false);
218    return false;
219 }
220 
isPeeringMatching(PolicyPeering * prng,SymID pset,const ASt peerAS,const MPPrefix * peerIP,const MPPrefix * ip)221 static bool isPeeringMatching(PolicyPeering *prng, SymID pset,
222 		const ASt peerAS, const MPPrefix *peerIP, const MPPrefix *ip) {
223 
224    if (!prng)
225       return false;
226 
227    if (prng->prngSet) {
228       if (pset)
229 	 return prng->prngSet == pset;
230       else {
231 	 const PeeringSet *peers = irr->getPeeringSet(prng->prngSet);
232 	 if (!peers)
233 	    return false;
234 	 for (AttrIterator<AttrPeering> itr(peers, "peering"); itr; itr++)
235 	    if (isPeeringMatching(itr()->peering, pset, peerAS, peerIP, ip))
236 	       return true;
237    for (AttrIterator<AttrPeering> itr(peers, "mp-peering"); itr; itr++)
238       if (isPeeringMatching(itr()->peering, pset, peerAS, peerIP, ip))
239          return true;
240 
241 	 return false;
242       }
243    }
244 
245    if (pset)
246       return false;
247 
248    if (prng->peerRtrs && peerIP && !isPeeringMatching(prng->peerRtrs, peerIP))
249       return false;
250 
251    if (prng->localRtrs && ip && !isPeeringMatching(prng->localRtrs, ip))
252       return false;
253 
254    if (prng->peerASes && peerAS != INVALID_AS
255        && !isPeeringMatching(prng->peerASes, peerAS))
256       return false;
257 
258    return true;
259 }
260 
261 // partly reimplemented
262 class AutNumDefaultIterator : public AttrIterator<AttrDefault> {
263 private:
264    const ASt peerAS;
265    const MPPrefix *peerIP;
266    const MPPrefix *ip;
267 
268 protected:
isMatching(Attr * attr)269    virtual bool isMatching(Attr *attr) {
270       return isPeeringMatching(((AttrDefault *) attr)->peering,
271 			       NULL, peerAS, peerIP, ip);
272    }
273 
274 public:
AutNumDefaultIterator(const AutNum * an,const ASt _peerAS=INVALID_AS,const char * attrib="default",const MPPrefix * _peerIP=NULL,const MPPrefix * _ip=NULL)275    AutNumDefaultIterator(const AutNum *an,
276 			 const ASt _peerAS = INVALID_AS,
277 			 const char *attrib = "default",
278 			 const MPPrefix *_peerIP = NULL,
279 			 const MPPrefix *_ip = NULL):
280      AttrIterator<AttrDefault>(an, attrib),
281      peerAS(_peerAS), peerIP(_peerIP), ip(_ip) {}
282 };
283 
284 template <class AttrType>
285 class AutNumImportExportIterator : public AttrIterator<AttrType> {
286 private:
287   const ASt peerAS;
288 
289 protected:
isMatching(Attr * attr)290   virtual bool isMatching(Attr *attr) {
291     if (!attr) return false;
292     PolicyExpr *policy = ((AttrType *)attr)->policy;
293     return isMatching(policy);
294   }
isMatching(PolicyExpr * policy)295   virtual bool isMatching(PolicyExpr *policy) {
296     if (typeid(*policy) == typeid(PolicyTerm))
297       {
298       PolicyTerm *pt = (PolicyTerm *)policy;
299       for (ListIterator<PolicyFactor> i(*pt); i; ++i)
300         // modified and commented out by katie@ripe.net
301 	for (ListIterator<PolicyPeeringAction> j(*(i->peeringActionList)); j; ++j)
302           // isPeeringMatching for extracting AS from peering-sets and as-sets as peerings
303 	  if (j->peering && isPeeringMatching(j->peering, NULL, peerAS, NULL, NULL)) return true;
304     }
305     else
306       if (typeid(*policy) == typeid(PolicyRefine))
307 	{
308 	PolicyRefine *pr = (PolicyRefine *)policy;
309 	if (pr->left && isMatching(pr->left)) return true;
310 	if (pr->right && isMatching(pr->right)) return true;
311 	}
312       else
313 	if (typeid(*policy) == typeid(PolicyExcept))
314 	  {
315 	  PolicyExcept *pe = (PolicyExcept *)policy;
316 	  if (pe->left && isMatching(pe->left)) return true;
317 	  if (pe->right && isMatching(pe->right)) return true;
318 	  }
319 	else
320 	  {
321 	  std::cerr << "Internal Error!" << std::endl;
322 	  abort();
323 	  }
324     return false;
325   }
326 
327 public:
AutNumImportExportIterator(const AutNum * an,const char * attrib,const ASt _peerAS)328    AutNumImportExportIterator(const AutNum *an,
329 			      const char *attrib,
330 			      const ASt _peerAS) :
331       AttrIterator<AttrType>(an, attrib),
332       peerAS(_peerAS) {
333 	// Has to be called here again in order to get things right!
334 	// It's not perfect but it works
335 	this->first();
336    }
337 };
338 
339 
340 class AutNumImportIterator : public AutNumImportExportIterator<AttrImport> {
341 public:
AutNumImportIterator(const AutNum * an,const ASt _peerAS)342   AutNumImportIterator(const AutNum *an, const ASt _peerAS) :
343     AutNumImportExportIterator<AttrImport>(an, "import", _peerAS) {}
344 };
345 
346 
347 class AutNumExportIterator : public AutNumImportExportIterator<AttrExport> {
348 public:
AutNumExportIterator(const AutNum * an,const ASt _peerAS)349   AutNumExportIterator(const AutNum *an, const ASt _peerAS) :
350     AutNumImportExportIterator<AttrExport>(an, "export", _peerAS) {}
351 };
352 
353 
354 template<class AttrType>
355 class AutNumSelector {
356 private:
357    ItemList *afi_list;
358    List<FilterAction> filterActionList;
359    FilterAction      *current;
360 public:
AutNumSelector(const AutNum * an,const char * attrib,SymID pset,const ASt peerAS,const MPPrefix * peerIP,const MPPrefix * ip,const char * fProtName="BGP4",const char * iProtName="BGP4")361    AutNumSelector(const AutNum *an, const char *attrib, SymID pset,
362                   const ASt peerAS, const MPPrefix *peerIP, const MPPrefix *ip,
363                   const char *fProtName = "BGP4", const char *iProtName = "BGP4"):
364       current(NULL), afi_list(new ItemList) {
365       AttrIterator<AttrType> itr(an, attrib);
366       const AttrType *import;
367       List<FilterAction> *list;
368       const AttrProtocol *fProt=schema.searchProtocol(fProtName);
369       const AttrProtocol *iProt=schema.searchProtocol(iProtName);
370       ItemList *tmp_afi_list = new ItemList;
371 
372       for (import = itr.first(); import; import = itr.next()) {
373          if (import->fromProt == fProt && import->intoProt == iProt) {
374             list = select(import->policy, pset, peerAS, peerIP, ip, &tmp_afi_list);
375             if (list) {
376                filterActionList.splice(*list);
377                afi_list->merge(*tmp_afi_list);
378                delete list;
379                delete tmp_afi_list;
380                tmp_afi_list = new ItemList;
381             }
382          }
383       }
384       delete tmp_afi_list;
385    }
386 
first()387    FilterAction *first() {
388       current = filterActionList.head();
389       return current;
390    }
391 
next()392    FilterAction *next() {
393       if (current)
394          current = filterActionList.next(current);
395       return current;
396    }
397 
get_fa_list()398    List<FilterAction> *get_fa_list() {
399       return &filterActionList;
400    }
401 
get_afi_list()402    ItemList *get_afi_list() {
403      return afi_list;
404    }
405 
406 private:
select(PolicyExpr * policy,SymID pset,const ASt peerAS,const MPPrefix * peerIP,const MPPrefix * ip,ItemList ** tmp_afi_list,Filter ** combinedFilter=NULL)407    List<FilterAction> *select(PolicyExpr *policy, SymID pset,
408                                   const ASt peerAS, const MPPrefix *peerIP,
409                                   const MPPrefix *ip, ItemList **tmp_afi_list,
410                                   Filter **combinedFilter = NULL) {
411       if (typeid(*policy) == typeid(PolicyTerm)) {
412          List<FilterAction> *list = new List<FilterAction>;
413          PolicyTerm   *pt = (PolicyTerm *) policy;
414          PolicyFactor *pf;
415          PolicyPeeringAction *pa;
416          bool          noMatch;
417          ItemList *afi;
418 
419          for (pf = pt->head(); pf; pf = pt->next(pf)) {
420             noMatch = true;
421             for (pa = pf->peeringActionList->head();
422                  pa;
423                  pa = pf->peeringActionList->next(pa)) {
424                if (noMatch && isPeeringMatching(pa->peering, pset,peerAS,peerIP,ip)) {
425                   list->append((new FilterAction((Filter *)
426                                                  pf->filter->dup(),
427                                                  (PolicyActionList *)
428                                                  pa->action->dup())));
429                   // save the afi
430                   afi = ((FilterAFI *) pf->filter)->afi_list;
431                   (*tmp_afi_list)->merge(*(new ItemList (*afi)));
432                   // rpsl specification order rule dictates only one match here
433                   // so break out of this if statement
434                   noMatch = false;
435                   if (!combinedFilter)
436                      break;
437                }
438                if (combinedFilter) {
439                   if (*combinedFilter)
440                      *combinedFilter =
441                         new FilterOR(*combinedFilter, (Filter *) pf->filter->dup());
442                   else
443                      *combinedFilter = (Filter *) pf->filter->dup();
444                }
445             }
446          }
447 
448          if (! list->isEmpty())
449             return list;
450          else {
451             delete list;
452             return NULL;
453          }
454       }
455 
456       if (typeid(*policy) == typeid(PolicyRefine)) {
457          PolicyRefine *pr = (PolicyRefine *) policy;
458          List<FilterAction> *left;
459          List<FilterAction> *rght;
460          ItemList *afi_list_left = new ItemList;
461          ItemList *afi_list_right = new ItemList;
462 
463          if (combinedFilter) {
464             Filter  *leftFilter = NULL;
465             Filter  *rghtFilter = NULL;
466             left = select(pr->left, pset, peerAS, peerIP, ip, &afi_list_left, &leftFilter);
467             rght = select(pr->right, pset, peerAS, peerIP, ip, &afi_list_right, &rghtFilter);
468             *combinedFilter = new FilterAND(leftFilter, rghtFilter);
469          } else {
470             left = select(pr->left, pset, peerAS, peerIP, ip, &afi_list_left, NULL);
471             rght = select(pr->right, pset, peerAS, peerIP, ip, &afi_list_right, NULL);
472          }
473 
474          afi_list_left->_and(*afi_list_right);
475          (*tmp_afi_list)->merge(*afi_list_left);
476 
477          if (!left || !rght) {
478             if (left)
479                delete left;
480             if (rght)
481                delete rght;
482             return NULL;
483          }
484 
485          List<FilterAction> *list = new List<FilterAction>;
486          FilterAction *l, *r;
487          Filter  *fltr;
488          PolicyActionList  *actn, *actn2;
489 
490          for (l = left->head(); l; l = left->next(l))
491             for (r = rght->head(); r; r = rght->next(r)) {
492                fltr = new FilterAND((Filter  *) l->filter->dup(),
493                                          (Filter  *) r->filter->dup());
494                actn = (PolicyActionList *) l->action->dup();
495                actn2 = (PolicyActionList *) r->action->dup();
496                actn->splice(*actn2);
497                delete actn2;
498 
499                list->append((new FilterAction(fltr, actn)));
500             }
501 
502          delete left;
503          delete rght;
504 
505          return list;
506       }
507 
508       if (typeid(*policy) == typeid(PolicyExcept)) {
509          PolicyExcept *pe = (PolicyExcept *) policy;
510          Filter  *leftFilter = NULL;
511          Filter  *rghtFilter = NULL;
512          ItemList *afi_list_left = new ItemList;
513          ItemList *afi_list_right = new ItemList;
514 
515          List<FilterAction> *left = select(pe->left, pset, peerAS, peerIP, ip, &afi_list_left,
516                                                &leftFilter);
517          List<FilterAction> *rght = select(pe->right, pset, peerAS, peerIP, ip, &afi_list_right,
518                                                &rghtFilter);
519 
520          if (combinedFilter)
521             *combinedFilter = (Filter  *) leftFilter->dup();
522 
523          if (!left && !rght) {
524             delete leftFilter;
525             delete rghtFilter;
526             return NULL;
527          }
528 
529          if (left) {
530             FilterAction *filterAction;
531             for (filterAction = left->head();
532                  filterAction;
533                  filterAction = left->next(filterAction))
534                filterAction->filter = new FilterAND(filterAction->filter,
535                   new FilterNOT((Filter  *) rghtFilter->dup()));
536             ItemList *t = new ItemList (*afi_list_right);
537             t->_not();
538             afi_list_left->_and(*t);
539             delete t;
540          }
541          delete rghtFilter;
542 
543          if (rght) {
544             FilterAction *filterAction;
545             for (filterAction = rght->head();
546                  filterAction;
547                  filterAction = rght->next(filterAction))
548                filterAction->filter = new FilterAND(filterAction->filter,
549                                    (Filter  *) leftFilter->dup());
550             afi_list_right->_and(*afi_list_left);
551          }
552          delete leftFilter;
553 
554          if (!left) {
555             (*tmp_afi_list)->merge(*afi_list_right);
556             return rght;
557          }
558 
559          if (!rght) {
560             (*tmp_afi_list)->merge(*afi_list_left);
561             return left;
562          }
563 
564          rght->splice(*left);
565          (*tmp_afi_list)->merge(*afi_list_left);
566          (*tmp_afi_list)->merge(*afi_list_right);
567          delete left;
568          return rght;
569       }
570 
571       assert(0);
572       return NULL;
573    }
574 };
575 
576 class AutNumPeeringIterator {
577 private:
578    AutNum  *o;
579    Peering *currentPeering;
580 public:
AutNumPeeringIterator(const AutNum * an)581    AutNumPeeringIterator(const AutNum *an) : o((AutNum *) an) {
582       if (o)
583 	 o->gatherPeerings();
584       first();
585    }
first()586    const Peering *first() {
587       if (!o)
588 	 return (Peering *) NULL;
589       currentPeering = o->peerings->head();
590       return currentPeering;
591    }
next()592    const Peering *next() {
593       if (! (o && currentPeering))
594 	 return (Peering *) NULL;
595       currentPeering = o->peerings->next(currentPeering);
596       return currentPeering;
597    }
operator ++(int)598    const AutNumPeeringIterator &operator++(int) {
599       next();
600       return *this;
601    }
operator Peering*() const602    operator Peering*() const { return currentPeering; }
operator ()(void) const603    Peering* operator()(void) const { return currentPeering; }
604 };
605 
606 class Interface : public ListNode {
607 
608 public:
609   AttrIfAddr interface;
610 
611 public:
Interface(AttrIfAddr _interface)612    Interface(AttrIfAddr _interface)
613       : ListNode(), interface(_interface) {
614    }
Interface(const Interface & b)615    Interface(const Interface &b)
616       : ListNode(), interface(b.interface) {
617    }
~Interface()618    ~Interface() {
619    }
620 
operator <(const Interface & b) const621    bool operator < (const Interface &b) const {
622       return (*(interface.ifaddr) < *(b.interface.ifaddr));
623    }
624 
operator ==(const Interface & b) const625    bool operator == (const Interface &b) const {
626       return (*(interface.ifaddr) == *(b.interface.ifaddr));
627    }
628 };
629 
630 class InterfaceIterator {
631 private:
632       SortedList<Interface> *ifaces;
633       Interface *current;
634 
635 public:
InterfaceIterator(const InetRtr * inetrtr)636       InterfaceIterator (const InetRtr *inetrtr) {
637         ifaces = new SortedList<Interface>;
638         for (AttrIterator<AttrIfAddr> itr(inetrtr, "ifaddr"); itr; itr++) {
639           ifaces->insertSortedNoDups(new Interface(*itr));
640         }
641         for (AttrIterator<AttrIfAddr> itr1(inetrtr, "interface"); itr1; itr1++) {
642           ifaces->insertSortedNoDups(new Interface(*itr1));
643         }
644       }
first()645       Interface *first() {
646         current = ifaces->head();
647         return current;
648       }
649 
next()650       Interface *next() {
651       if (current)
652         current = ifaces->next(current);
653         return current;
654       }
655 };
656 
657 class Peer : public ListNode {
658 public:
659    AttrPeer peer;
660 
661 public:
Peer(AttrPeer _peer)662    Peer(AttrPeer _peer)
663       : ListNode(), peer(_peer) {
664    }
Peer(const Peer & b)665    Peer(const Peer &b)
666       : ListNode(), peer(b.peer) {
667    }
~Peer()668    ~Peer() {
669    }
670 
operator <(const Peer & b) const671    bool operator < (const Peer &b) const {
672       return (*(peer.peer) < *(b.peer.peer));
673    }
674 
operator ==(const Peer & b) const675    bool operator == (const Peer &b) const {
676       return (*(peer.peer) == *(b.peer.peer));
677    }
678 };
679 
680 class PeerIterator {
681 private:
682       SortedList<Peer> *peers;
683       Peer *current;
684 
685 public:
PeerIterator(const InetRtr * inetrtr)686       PeerIterator (const InetRtr *inetrtr) {
687         peers = new SortedList<Peer>;
688         for (AttrIterator<AttrPeer> itr(inetrtr, "peer"); itr; itr++) {
689           peers->insertSortedNoDups(new Peer(*itr));
690         }
691         for (AttrIterator<AttrPeer> itr1(inetrtr, "mp-peer"); itr1; itr1++) {
692           peers->insertSortedNoDups(new Peer(*itr1));
693         }
694       }
first()695       Peer *first() {
696         current =peers->head();
697         return current;
698       }
699 
next()700       Peer *next() {
701       if (current)
702         current = peers->next(current);
703         return current;
704       }
705 };
706 
707 #endif   // AUTNUM_H
708