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