blob: 09d2da5bd2b20a1b588d707715f58932e8838544 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Routing Information Base.
2 * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "table.h"
26#include "memory.h"
27#include "str.h"
28#include "command.h"
29#include "if.h"
30#include "log.h"
31#include "sockunion.h"
32
33#include "zebra/rib.h"
34#include "zebra/rt.h"
35#include "zebra/zserv.h"
36#include "zebra/redistribute.h"
37#include "zebra/debug.h"
38
39/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000040extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000041
42/* Each route type's string and default distance value. */
43struct
44{
45 int key;
46 int distance;
47} route_info[] =
48{
49 {ZEBRA_ROUTE_SYSTEM, 0},
50 {ZEBRA_ROUTE_KERNEL, 0},
51 {ZEBRA_ROUTE_CONNECT, 0},
52 {ZEBRA_ROUTE_STATIC, 1},
53 {ZEBRA_ROUTE_RIP, 120},
54 {ZEBRA_ROUTE_RIPNG, 120},
55 {ZEBRA_ROUTE_OSPF, 110},
56 {ZEBRA_ROUTE_OSPF6, 110},
57 {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
58};
59
60/* Vector for routing table. */
61vector vrf_vector;
62
63/* Allocate new VRF. */
64struct vrf *
65vrf_alloc (char *name)
66{
67 struct vrf *vrf;
68
69 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
70
71 /* Put name. */
72 if (name)
73 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
74
75 /* Allocate routing table and static table. */
76 vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init ();
77 vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();
78 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
79 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
80
81 return vrf;
82}
83
84/* Free VRF. */
85void
86vrf_free (struct vrf *vrf)
87{
88 if (vrf->name)
89 XFREE (MTYPE_VRF_NAME, vrf->name);
90 XFREE (MTYPE_VRF, vrf);
91}
92
93/* Lookup VRF by identifier. */
94struct vrf *
95vrf_lookup (u_int32_t id)
96{
97 return vector_lookup (vrf_vector, id);
98}
99
100/* Lookup VRF by name. */
101struct vrf *
102vrf_lookup_by_name (char *name)
103{
104 int i;
105 struct vrf *vrf;
106
107 for (i = 0; i < vector_max (vrf_vector); i++)
108 if ((vrf = vector_slot (vrf_vector, i)) != NULL)
109 if (vrf->name && name && strcmp (vrf->name, name) == 0)
110 return vrf;
111 return NULL;
112}
113
114/* Initialize VRF. */
115void
116vrf_init ()
117{
118 struct vrf *default_table;
119
120 /* Allocate VRF vector. */
121 vrf_vector = vector_init (1);
122
123 /* Allocate default main table. */
124 default_table = vrf_alloc ("Default-IP-Routing-Table");
125
126 /* Default table index must be 0. */
127 vector_set_index (vrf_vector, 0, default_table);
128}
129
130/* Lookup route table. */
131struct route_table *
132vrf_table (afi_t afi, safi_t safi, u_int32_t id)
133{
134 struct vrf *vrf;
135
136 vrf = vrf_lookup (id);
137 if (! vrf)
138 return NULL;
139
140 return vrf->table[afi][safi];
141}
142
143/* Lookup static route table. */
144struct route_table *
145vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
146{
147 struct vrf *vrf;
148
149 vrf = vrf_lookup (id);
150 if (! vrf)
151 return NULL;
152
153 return vrf->stable[afi][safi];
154}
155
156/* Add nexthop to the end of the list. */
157void
158nexthop_add (struct rib *rib, struct nexthop *nexthop)
159{
160 struct nexthop *last;
161
162 for (last = rib->nexthop; last && last->next; last = last->next)
163 ;
164 if (last)
165 last->next = nexthop;
166 else
167 rib->nexthop = nexthop;
168 nexthop->prev = last;
169
170 rib->nexthop_num++;
171}
172
173/* Delete specified nexthop from the list. */
174void
175nexthop_delete (struct rib *rib, struct nexthop *nexthop)
176{
177 if (nexthop->next)
178 nexthop->next->prev = nexthop->prev;
179 if (nexthop->prev)
180 nexthop->prev->next = nexthop->next;
181 else
182 rib->nexthop = nexthop->next;
183 rib->nexthop_num--;
184}
185
186/* Free nexthop. */
187void
188nexthop_free (struct nexthop *nexthop)
189{
paula4b70762003-05-16 17:19:48 +0000190 if (nexthop->ifname)
191 XFREE (0, nexthop->ifname);
paul718e3742002-12-13 20:15:29 +0000192 XFREE (MTYPE_NEXTHOP, nexthop);
193}
194
195struct nexthop *
196nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
197{
198 struct nexthop *nexthop;
199
200 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
201 memset (nexthop, 0, sizeof (struct nexthop));
202 nexthop->type = NEXTHOP_TYPE_IFINDEX;
203 nexthop->ifindex = ifindex;
204
205 nexthop_add (rib, nexthop);
206
207 return nexthop;
208}
209
210struct nexthop *
211nexthop_ifname_add (struct rib *rib, char *ifname)
212{
213 struct nexthop *nexthop;
214
215 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
216 memset (nexthop, 0, sizeof (struct nexthop));
217 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000218 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000219
220 nexthop_add (rib, nexthop);
221
222 return nexthop;
223}
224
225struct nexthop *
226nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4)
227{
228 struct nexthop *nexthop;
229
230 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
231 memset (nexthop, 0, sizeof (struct nexthop));
232 nexthop->type = NEXTHOP_TYPE_IPV4;
233 nexthop->gate.ipv4 = *ipv4;
234
235 nexthop_add (rib, nexthop);
236
237 return nexthop;
238}
239
240struct nexthop *
241nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
242 unsigned int ifindex)
243{
244 struct nexthop *nexthop;
245
246 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
247 memset (nexthop, 0, sizeof (struct nexthop));
248 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
249 nexthop->gate.ipv4 = *ipv4;
250 nexthop->ifindex = ifindex;
251
252 nexthop_add (rib, nexthop);
253
254 return nexthop;
255}
256
257#ifdef HAVE_IPV6
258struct nexthop *
259nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
260{
261 struct nexthop *nexthop;
262
263 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
264 memset (nexthop, 0, sizeof (struct nexthop));
265 nexthop->type = NEXTHOP_TYPE_IPV6;
266 nexthop->gate.ipv6 = *ipv6;
267
268 nexthop_add (rib, nexthop);
269
270 return nexthop;
271}
272
273struct nexthop *
274nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
275 char *ifname)
276{
277 struct nexthop *nexthop;
278
279 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
280 memset (nexthop, 0, sizeof (struct nexthop));
281 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
282 nexthop->gate.ipv6 = *ipv6;
283 nexthop->ifname = XSTRDUP (0, ifname);
284
285 nexthop_add (rib, nexthop);
286
287 return nexthop;
288}
289
290struct nexthop *
291nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
292 unsigned int ifindex)
293{
294 struct nexthop *nexthop;
295
296 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
297 memset (nexthop, 0, sizeof (struct nexthop));
298 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
299 nexthop->gate.ipv6 = *ipv6;
300 nexthop->ifindex = ifindex;
301
302 nexthop_add (rib, nexthop);
303
304 return nexthop;
305}
306#endif /* HAVE_IPV6 */
307
paul595db7f2003-05-25 21:35:06 +0000308struct nexthop *
309nexthop_blackhole_add (struct rib *rib)
310{
311 struct nexthop *nexthop;
312
313 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
314 memset (nexthop, 0, sizeof (struct nexthop));
315 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
316 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
317
318 nexthop_add (rib, nexthop);
319
320 return nexthop;
321}
322
paul718e3742002-12-13 20:15:29 +0000323/* If force flag is not set, do not modify falgs at all for uninstall
324 the route from FIB. */
325int
326nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
327 struct route_node *top)
328{
329 struct prefix_ipv4 p;
330 struct route_table *table;
331 struct route_node *rn;
332 struct rib *match;
333 struct nexthop *newhop;
334
335 if (nexthop->type == NEXTHOP_TYPE_IPV4)
336 nexthop->ifindex = 0;
337
338 if (set)
339 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
340
341 /* Make lookup prefix. */
342 memset (&p, 0, sizeof (struct prefix_ipv4));
343 p.family = AF_INET;
344 p.prefixlen = IPV4_MAX_PREFIXLEN;
345 p.prefix = nexthop->gate.ipv4;
346
347 /* Lookup table. */
348 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
349 if (! table)
350 return 0;
351
352 rn = route_node_match (table, (struct prefix *) &p);
353 while (rn)
354 {
355 route_unlock_node (rn);
356
357 /* If lookup self prefix return immidiately. */
358 if (rn == top)
359 return 0;
360
361 /* Pick up selected route. */
362 for (match = rn->info; match; match = match->next)
363 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
364 break;
365
366 /* If there is no selected route or matched route is EGP, go up
367 tree. */
368 if (! match
369 || match->type == ZEBRA_ROUTE_BGP)
370 {
371 do {
372 rn = rn->parent;
373 } while (rn && rn->info == NULL);
374 if (rn)
375 route_lock_node (rn);
376 }
377 else
378 {
379 if (match->type == ZEBRA_ROUTE_CONNECT)
380 {
381 /* Directly point connected route. */
382 newhop = match->nexthop;
383 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
384 nexthop->ifindex = newhop->ifindex;
385
386 return 1;
387 }
388 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
389 {
390 for (newhop = match->nexthop; newhop; newhop = newhop->next)
391 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
392 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
393 {
394 if (set)
395 {
396 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
397 nexthop->rtype = newhop->type;
398 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
399 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
400 nexthop->rgate.ipv4 = newhop->gate.ipv4;
401 if (newhop->type == NEXTHOP_TYPE_IFINDEX
402 || newhop->type == NEXTHOP_TYPE_IFNAME
403 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
404 nexthop->rifindex = newhop->ifindex;
405 }
406 return 1;
407 }
408 return 0;
409 }
410 else
411 {
412 return 0;
413 }
414 }
415 }
416 return 0;
417}
418
419#ifdef HAVE_IPV6
420/* If force flag is not set, do not modify falgs at all for uninstall
421 the route from FIB. */
422int
423nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
424 struct route_node *top)
425{
426 struct prefix_ipv6 p;
427 struct route_table *table;
428 struct route_node *rn;
429 struct rib *match;
430 struct nexthop *newhop;
431
432 if (nexthop->type == NEXTHOP_TYPE_IPV6)
433 nexthop->ifindex = 0;
434
435 if (set)
436 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
437
438 /* Make lookup prefix. */
439 memset (&p, 0, sizeof (struct prefix_ipv6));
440 p.family = AF_INET6;
441 p.prefixlen = IPV6_MAX_PREFIXLEN;
442 p.prefix = nexthop->gate.ipv6;
443
444 /* Lookup table. */
445 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
446 if (! table)
447 return 0;
448
449 rn = route_node_match (table, (struct prefix *) &p);
450 while (rn)
451 {
452 route_unlock_node (rn);
453
454 /* If lookup self prefix return immidiately. */
455 if (rn == top)
456 return 0;
457
458 /* Pick up selected route. */
459 for (match = rn->info; match; match = match->next)
460 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
461 break;
462
463 /* If there is no selected route or matched route is EGP, go up
464 tree. */
465 if (! match
466 || match->type == ZEBRA_ROUTE_BGP)
467 {
468 do {
469 rn = rn->parent;
470 } while (rn && rn->info == NULL);
471 if (rn)
472 route_lock_node (rn);
473 }
474 else
475 {
476 if (match->type == ZEBRA_ROUTE_CONNECT)
477 {
478 /* Directly point connected route. */
479 newhop = match->nexthop;
480
481 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
482 nexthop->ifindex = newhop->ifindex;
483
484 return 1;
485 }
486 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
487 {
488 for (newhop = match->nexthop; newhop; newhop = newhop->next)
489 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
490 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
491 {
492 if (set)
493 {
494 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
495 nexthop->rtype = newhop->type;
496 if (newhop->type == NEXTHOP_TYPE_IPV6
497 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
498 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
499 nexthop->rgate.ipv6 = newhop->gate.ipv6;
500 if (newhop->type == NEXTHOP_TYPE_IFINDEX
501 || newhop->type == NEXTHOP_TYPE_IFNAME
502 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
503 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
504 nexthop->rifindex = newhop->ifindex;
505 }
506 return 1;
507 }
508 return 0;
509 }
510 else
511 {
512 return 0;
513 }
514 }
515 }
516 return 0;
517}
518#endif /* HAVE_IPV6 */
519
520struct rib *
521rib_match_ipv4 (struct in_addr addr)
522{
523 struct prefix_ipv4 p;
524 struct route_table *table;
525 struct route_node *rn;
526 struct rib *match;
527 struct nexthop *newhop;
528
529 /* Lookup table. */
530 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
531 if (! table)
532 return 0;
533
534 memset (&p, 0, sizeof (struct prefix_ipv4));
535 p.family = AF_INET;
536 p.prefixlen = IPV4_MAX_PREFIXLEN;
537 p.prefix = addr;
538
539 rn = route_node_match (table, (struct prefix *) &p);
540
541 while (rn)
542 {
543 route_unlock_node (rn);
544
545 /* Pick up selected route. */
546 for (match = rn->info; match; match = match->next)
547 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
548 break;
549
550 /* If there is no selected route or matched route is EGP, go up
551 tree. */
552 if (! match
553 || match->type == ZEBRA_ROUTE_BGP)
554 {
555 do {
556 rn = rn->parent;
557 } while (rn && rn->info == NULL);
558 if (rn)
559 route_lock_node (rn);
560 }
561 else
562 {
563 if (match->type == ZEBRA_ROUTE_CONNECT)
564 /* Directly point connected route. */
565 return match;
566 else
567 {
568 for (newhop = match->nexthop; newhop; newhop = newhop->next)
569 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
570 return match;
571 return NULL;
572 }
573 }
574 }
575 return NULL;
576}
577
578struct rib *
579rib_lookup_ipv4 (struct prefix_ipv4 *p)
580{
581 struct route_table *table;
582 struct route_node *rn;
583 struct rib *match;
584 struct nexthop *nexthop;
585
586 /* Lookup table. */
587 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
588 if (! table)
589 return 0;
590
591 rn = route_node_lookup (table, (struct prefix *) p);
592
593 /* No route for this prefix. */
594 if (! rn)
595 return NULL;
596
597 /* Unlock node. */
598 route_unlock_node (rn);
599
600 /* Pick up selected route. */
601 for (match = rn->info; match; match = match->next)
602 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
603 break;
604
605 if (! match || match->type == ZEBRA_ROUTE_BGP)
606 return NULL;
607
608 if (match->type == ZEBRA_ROUTE_CONNECT)
609 return match;
610
611 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
612 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
613 return match;
614
615 return NULL;
616}
617
618#ifdef HAVE_IPV6
619struct rib *
620rib_match_ipv6 (struct in6_addr *addr)
621{
622 struct prefix_ipv6 p;
623 struct route_table *table;
624 struct route_node *rn;
625 struct rib *match;
626 struct nexthop *newhop;
627
628 /* Lookup table. */
629 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
630 if (! table)
631 return 0;
632
633 memset (&p, 0, sizeof (struct prefix_ipv6));
634 p.family = AF_INET6;
635 p.prefixlen = IPV6_MAX_PREFIXLEN;
636 IPV6_ADDR_COPY (&p.prefix, addr);
637
638 rn = route_node_match (table, (struct prefix *) &p);
639
640 while (rn)
641 {
642 route_unlock_node (rn);
643
644 /* Pick up selected route. */
645 for (match = rn->info; match; match = match->next)
646 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
647 break;
648
649 /* If there is no selected route or matched route is EGP, go up
650 tree. */
651 if (! match
652 || match->type == ZEBRA_ROUTE_BGP)
653 {
654 do {
655 rn = rn->parent;
656 } while (rn && rn->info == NULL);
657 if (rn)
658 route_lock_node (rn);
659 }
660 else
661 {
662 if (match->type == ZEBRA_ROUTE_CONNECT)
663 /* Directly point connected route. */
664 return match;
665 else
666 {
667 for (newhop = match->nexthop; newhop; newhop = newhop->next)
668 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
669 return match;
670 return NULL;
671 }
672 }
673 }
674 return NULL;
675}
676#endif /* HAVE_IPV6 */
677
678int
679nexthop_active_check (struct route_node *rn, struct rib *rib,
680 struct nexthop *nexthop, int set)
681{
682 struct interface *ifp;
683
684 switch (nexthop->type)
685 {
686 case NEXTHOP_TYPE_IFINDEX:
687 ifp = if_lookup_by_index (nexthop->ifindex);
688 if (ifp && if_is_up (ifp))
689 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
690 else
691 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
692 break;
693 case NEXTHOP_TYPE_IFNAME:
694 case NEXTHOP_TYPE_IPV6_IFNAME:
695 ifp = if_lookup_by_name (nexthop->ifname);
696 if (ifp && if_is_up (ifp))
697 {
698 if (set)
699 nexthop->ifindex = ifp->ifindex;
700 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
701 }
702 else
703 {
704 if (set)
705 nexthop->ifindex = 0;
706 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
707 }
708 break;
709 case NEXTHOP_TYPE_IPV4:
710 case NEXTHOP_TYPE_IPV4_IFINDEX:
711 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
712 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
713 else
714 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
715 break;
716#ifdef HAVE_IPV6
717 case NEXTHOP_TYPE_IPV6:
718 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
719 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
720 else
721 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
722 break;
723 case NEXTHOP_TYPE_IPV6_IFINDEX:
724 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
725 {
726 ifp = if_lookup_by_index (nexthop->ifindex);
727 if (ifp && if_is_up (ifp))
728 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
729 else
730 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
731 }
732 else
733 {
734 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
735 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
736 else
737 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
738 }
739 break;
740#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000741 case NEXTHOP_TYPE_BLACKHOLE:
742 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
743 break;
paul718e3742002-12-13 20:15:29 +0000744 default:
745 break;
746 }
747 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
748}
749
750int
751nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
752{
753 struct nexthop *nexthop;
754 int active;
755
756 rib->nexthop_active_num = 0;
757 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
758
759 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
760 {
761 active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
762 rib->nexthop_active_num += nexthop_active_check (rn, rib, nexthop, set);
763 if (active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
764 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
765 }
766 return rib->nexthop_active_num;
767}
768
769#define RIB_SYSTEM_ROUTE(R) \
770 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
771
772void
773newrib_free (struct rib *rib)
774{
775 struct nexthop *nexthop;
776 struct nexthop *next;
777
778 for (nexthop = rib->nexthop; nexthop; nexthop = next)
779 {
780 next = nexthop->next;
781 nexthop_free (nexthop);
782 }
783 XFREE (MTYPE_RIB, rib);
784}
785
786void
787rib_install_kernel (struct route_node *rn, struct rib *rib)
788{
789 int ret = 0;
790 struct nexthop *nexthop;
791
792 switch (PREFIX_FAMILY (&rn->p))
793 {
794 case AF_INET:
795 ret = kernel_add_ipv4 (&rn->p, rib);
796 break;
797#ifdef HAVE_IPV6
798 case AF_INET6:
799 ret = kernel_add_ipv6 (&rn->p, rib);
800 break;
801#endif /* HAVE_IPV6 */
802 }
803
804 if (ret < 0)
805 {
806 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
807 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
808 }
809}
810
811/* Uninstall the route from kernel. */
812int
813rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
814{
815 int ret = 0;
816 struct nexthop *nexthop;
817
818 switch (PREFIX_FAMILY (&rn->p))
819 {
820 case AF_INET:
821 ret = kernel_delete_ipv4 (&rn->p, rib);
822 break;
823#ifdef HAVE_IPV6
824 case AF_INET6:
825 ret = kernel_delete_ipv6 (&rn->p, rib);
826 break;
827#endif /* HAVE_IPV6 */
828 }
829
830 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
831 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
832
833 return ret;
834}
835
836/* Uninstall the route from kernel. */
837void
838rib_uninstall (struct route_node *rn, struct rib *rib)
839{
840 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
841 {
842 redistribute_delete (&rn->p, rib);
843 if (! RIB_SYSTEM_ROUTE (rib))
844 rib_uninstall_kernel (rn, rib);
845 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
846 }
847}
848
849/* Core function for processing routing information base. */
850void
851rib_process (struct route_node *rn, struct rib *del)
852{
853 struct rib *rib;
854 struct rib *next;
855 struct rib *fib = NULL;
856 struct rib *select = NULL;
pauld753e9e2003-01-22 19:45:50 +0000857 int installed = 0;
858 struct nexthop *nexthop = NULL;
paul718e3742002-12-13 20:15:29 +0000859
860 for (rib = rn->info; rib; rib = next)
861 {
862 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +0000863
paul718e3742002-12-13 20:15:29 +0000864 /* Currently installed rib. */
865 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
866 fib = rib;
867
868 /* Skip unreachable nexthop. */
869 if (! nexthop_active_update (rn, rib, 0))
870 continue;
871
872 /* Infinit distance. */
873 if (rib->distance == DISTANCE_INFINITY)
874 continue;
875
876 /* Newly selected rib. */
877 if (! select || rib->distance < select->distance
878 || rib->type == ZEBRA_ROUTE_CONNECT)
879 select = rib;
880 }
881
882 /* Deleted route check. */
883 if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
884 fib = del;
885
886 /* Same route is selected. */
887 if (select && select == fib)
888 {
889 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
890 {
891 redistribute_delete (&rn->p, select);
892 if (! RIB_SYSTEM_ROUTE (select))
893 rib_uninstall_kernel (rn, select);
894
895 /* Set real nexthop. */
896 nexthop_active_update (rn, select, 1);
897
898 if (! RIB_SYSTEM_ROUTE (select))
899 rib_install_kernel (rn, select);
900 redistribute_add (&rn->p, select);
901 }
pauld753e9e2003-01-22 19:45:50 +0000902 else if (! RIB_SYSTEM_ROUTE (select))
903 {
904 /* Housekeeping code to deal with
905 race conditions in kernel with linux
906 netlink reporting interface up before IPv4 or IPv6 protocol
907 is ready to add routes.
908 This makes sure the routes are IN the kernel.
909 */
910
911 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
912 {
913 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
914 installed = 1;
915 }
916 if (! installed) rib_install_kernel (rn, select);
917 }
paul718e3742002-12-13 20:15:29 +0000918 return;
919 }
920
921 /* Uninstall old rib from forwarding table. */
922 if (fib)
923 {
924 redistribute_delete (&rn->p, fib);
925 if (! RIB_SYSTEM_ROUTE (fib))
926 rib_uninstall_kernel (rn, fib);
927 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
928
929 /* Set real nexthop. */
930 nexthop_active_update (rn, fib, 1);
931 }
932
933 /* Install new rib into forwarding table. */
934 if (select)
935 {
936 /* Set real nexthop. */
937 nexthop_active_update (rn, select, 1);
938
939 if (! RIB_SYSTEM_ROUTE (select))
940 rib_install_kernel (rn, select);
941 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
942 redistribute_add (&rn->p, select);
943 }
944}
945
946/* Add RIB to head of the route node. */
947void
948rib_addnode (struct route_node *rn, struct rib *rib)
949{
950 struct rib *head;
951
952 head = rn->info;
953 if (head)
954 head->prev = rib;
955 rib->next = head;
956 rn->info = rib;
957}
958
959void
960rib_delnode (struct route_node *rn, struct rib *rib)
961{
962 if (rib->next)
963 rib->next->prev = rib->prev;
964 if (rib->prev)
965 rib->prev->next = rib->next;
966 else
967 rn->info = rib->next;
968}
969
970int
971rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
972 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
973 u_int32_t metric, u_char distance)
974{
975 struct rib *rib;
976 struct rib *same = NULL;
977 struct route_table *table;
978 struct route_node *rn;
979 struct nexthop *nexthop;
980
981 /* Lookup table. */
982 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
983 if (! table)
984 return 0;
985
986 /* Make it sure prefixlen is applied to the prefix. */
987 apply_mask_ipv4 (p);
988
989 /* Set default distance by route type. */
990 if (distance == 0)
991 {
992 distance = route_info[type].distance;
993
994 /* iBGP distance is 200. */
995 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
996 distance = 200;
997 }
998
999 /* Lookup route node.*/
1000 rn = route_node_get (table, (struct prefix *) p);
1001
1002 /* If same type of route are installed, treat it as a implicit
1003 withdraw. */
1004 for (rib = rn->info; rib; rib = rib->next)
1005 {
1006 if (rib->type == ZEBRA_ROUTE_CONNECT)
1007 {
1008 nexthop = rib->nexthop;
1009
1010 /* Duplicate connected route comes in. */
1011 if (rib->type == type
1012 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1013 && nexthop->ifindex == ifindex)
1014 {
1015 rib->refcnt++;
1016 return 0 ;
1017 }
1018 }
1019 else if (rib->type == type)
1020 {
1021 same = rib;
1022 rib_delnode (rn, same);
1023 route_unlock_node (rn);
1024 break;
1025 }
1026 }
1027
1028 /* Allocate new rib structure. */
1029 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1030 memset (rib, 0, sizeof (struct rib));
1031 rib->type = type;
1032 rib->distance = distance;
1033 rib->flags = flags;
1034 rib->metric = metric;
1035 rib->nexthop_num = 0;
1036 rib->uptime = time (NULL);
1037
1038 /* Nexthop settings. */
1039 if (gate)
1040 {
1041 if (ifindex)
1042 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
1043 else
1044 nexthop_ipv4_add (rib, gate);
1045 }
1046 else
1047 nexthop_ifindex_add (rib, ifindex);
1048
1049 /* If this route is kernel route, set FIB flag to the route. */
1050 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1051 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1052 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1053
1054 /* Link new rib to node.*/
1055 rib_addnode (rn, rib);
1056
1057 /* Process this route node. */
1058 rib_process (rn, same);
1059
1060 /* Free implicit route.*/
1061 if (same)
1062 newrib_free (same);
1063
1064 return 0;
1065}
1066
1067int
1068rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1069{
1070 struct route_table *table;
1071 struct route_node *rn;
1072 struct rib *same;
1073 struct nexthop *nexthop;
1074
1075 /* Lookup table. */
1076 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1077 if (! table)
1078 return 0;
1079
1080 /* Make it sure prefixlen is applied to the prefix. */
1081 apply_mask_ipv4 (p);
1082
1083 /* Set default distance by route type. */
1084 if (rib->distance == 0)
1085 {
1086 rib->distance = route_info[rib->type].distance;
1087
1088 /* iBGP distance is 200. */
1089 if (rib->type == ZEBRA_ROUTE_BGP
1090 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1091 rib->distance = 200;
1092 }
1093
1094 /* Lookup route node.*/
1095 rn = route_node_get (table, (struct prefix *) p);
1096
1097 /* If same type of route are installed, treat it as a implicit
1098 withdraw. */
1099 for (same = rn->info; same; same = same->next)
1100 {
1101 if (same->type == rib->type && same->table == rib->table
1102 && same->type != ZEBRA_ROUTE_CONNECT)
1103 {
1104 rib_delnode (rn, same);
1105 route_unlock_node (rn);
1106 break;
1107 }
1108 }
1109
1110 /* If this route is kernel route, set FIB flag to the route. */
1111 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1112 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1113 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1114
1115 /* Link new rib to node.*/
1116 rib_addnode (rn, rib);
1117
1118 /* Process this route node. */
1119 rib_process (rn, same);
1120
1121 /* Free implicit route.*/
1122 if (same)
1123 newrib_free (same);
1124
1125 return 0;
1126}
1127
1128int
1129rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1130 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1131{
1132 struct route_table *table;
1133 struct route_node *rn;
1134 struct rib *rib;
1135 struct rib *fib = NULL;
1136 struct rib *same = NULL;
1137 struct nexthop *nexthop;
1138 char buf1[BUFSIZ];
1139 char buf2[BUFSIZ];
1140
1141 /* Lookup table. */
1142 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1143 if (! table)
1144 return 0;
1145
1146 /* Apply mask. */
1147 apply_mask_ipv4 (p);
1148
paul5ec90d22003-06-19 01:41:37 +00001149 if (IS_ZEBRA_DEBUG_KERNEL && gate)
1150 zlog_info ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
1151 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1152 p->prefixlen,
1153 inet_ntoa (*gate),
1154 ifindex);
1155
paul718e3742002-12-13 20:15:29 +00001156 /* Lookup route node. */
1157 rn = route_node_lookup (table, (struct prefix *) p);
1158 if (! rn)
1159 {
1160 if (IS_ZEBRA_DEBUG_KERNEL)
1161 {
1162 if (gate)
1163 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
1164 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1165 p->prefixlen,
1166 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1167 ifindex);
1168 else
1169 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
1170 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1171 p->prefixlen,
1172 ifindex);
1173 }
1174 return ZEBRA_ERR_RTNOEXIST;
1175 }
1176
1177 /* Lookup same type route. */
1178 for (rib = rn->info; rib; rib = rib->next)
1179 {
1180 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1181 fib = rib;
1182
1183 if (rib->type == ZEBRA_ROUTE_CONNECT)
1184 {
1185 nexthop = rib->nexthop;
1186
1187 if (rib->type == type
1188 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1189 && nexthop->ifindex == ifindex)
1190 {
1191 if (rib->refcnt)
1192 {
1193 rib->refcnt--;
1194 route_unlock_node (rn);
1195 route_unlock_node (rn);
1196 return 0;
1197 }
1198 same = rib;
1199 break;
1200 }
1201 }
paul5ec90d22003-06-19 01:41:37 +00001202 else if (gate)
1203 {
1204 nexthop = rib->nexthop;
1205
1206 /* Make sure that the route found has the same gateway. */
1207 if (rib->type == type
1208 && nexthop &&
1209 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1210 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate)) )
1211 {
1212 same = rib;
1213 break;
1214 }
1215 }
paul718e3742002-12-13 20:15:29 +00001216 else
1217 {
1218 if (rib->type == type)
1219 {
1220 same = rib;
1221 break;
1222 }
1223 }
1224 }
1225
1226 /* If same type of route can't be found and this message is from
1227 kernel. */
1228 if (! same)
1229 {
1230 if (fib && type == ZEBRA_ROUTE_KERNEL)
1231 {
1232 /* Unset flags. */
1233 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1234 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1235
1236 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1237 }
1238 else
1239 {
1240 if (IS_ZEBRA_DEBUG_KERNEL)
1241 {
1242 if (gate)
1243 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
1244 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1245 p->prefixlen,
1246 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1247 ifindex,
1248 type);
1249 else
1250 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
1251 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1252 p->prefixlen,
1253 ifindex,
1254 type);
1255 }
1256 route_unlock_node (rn);
1257 return ZEBRA_ERR_RTNOEXIST;
1258 }
1259 }
1260
1261 if (same)
1262 rib_delnode (rn, same);
1263
1264 /* Process changes. */
1265 rib_process (rn, same);
1266
1267 if (same)
1268 {
1269 newrib_free (same);
1270 route_unlock_node (rn);
1271 }
1272
1273 route_unlock_node (rn);
1274
1275 return 0;
1276}
1277
1278/* Install static route into rib. */
1279void
1280static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1281{
1282 struct rib *rib;
1283 struct route_node *rn;
1284 struct route_table *table;
1285
1286 /* Lookup table. */
1287 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1288 if (! table)
1289 return;
1290
1291 /* Lookup existing route */
1292 rn = route_node_get (table, p);
1293 for (rib = rn->info; rib; rib = rib->next)
1294 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1295 break;
1296
1297 if (rib)
1298 {
1299 /* Same distance static route is there. Update it with new
1300 nexthop. */
1301 rib_uninstall (rn, rib);
1302 route_unlock_node (rn);
1303
1304 switch (si->type)
1305 {
1306 case STATIC_IPV4_GATEWAY:
1307 nexthop_ipv4_add (rib, &si->gate.ipv4);
1308 break;
1309 case STATIC_IPV4_IFNAME:
1310 nexthop_ifname_add (rib, si->gate.ifname);
1311 break;
paul595db7f2003-05-25 21:35:06 +00001312 case STATIC_IPV4_BLACKHOLE:
1313 nexthop_blackhole_add (rib);
1314 break;
paul718e3742002-12-13 20:15:29 +00001315 }
1316 rib_process (rn, NULL);
1317 }
1318 else
1319 {
1320 /* This is new static route. */
1321 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1322 memset (rib, 0, sizeof (struct rib));
1323
1324 rib->type = ZEBRA_ROUTE_STATIC;
1325 rib->distance = si->distance;
1326 rib->metric = 0;
1327 rib->nexthop_num = 0;
1328
1329 switch (si->type)
1330 {
1331 case STATIC_IPV4_GATEWAY:
1332 nexthop_ipv4_add (rib, &si->gate.ipv4);
1333 break;
1334 case STATIC_IPV4_IFNAME:
1335 nexthop_ifname_add (rib, si->gate.ifname);
1336 break;
paul595db7f2003-05-25 21:35:06 +00001337 case STATIC_IPV4_BLACKHOLE:
1338 nexthop_blackhole_add (rib);
1339 break;
paul718e3742002-12-13 20:15:29 +00001340 }
1341
hasso81dfcaa2003-05-25 19:21:25 +00001342 /* Save the flags of this static routes (reject, blackhole) */
1343 rib->flags = si->flags;
1344
paul718e3742002-12-13 20:15:29 +00001345 /* Link this rib to the tree. */
1346 rib_addnode (rn, rib);
1347
1348 /* Process this prefix. */
1349 rib_process (rn, NULL);
1350 }
1351}
1352
1353int
1354static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1355{
1356 if (nexthop->type == NEXTHOP_TYPE_IPV4
1357 && si->type == STATIC_IPV4_GATEWAY
1358 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1359 return 1;
1360 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1361 && si->type == STATIC_IPV4_IFNAME
1362 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1363 return 1;
paul595db7f2003-05-25 21:35:06 +00001364 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1365 && si->type == STATIC_IPV4_BLACKHOLE)
1366 return 1;
paul718e3742002-12-13 20:15:29 +00001367 return 0;;
1368}
1369
1370/* Uninstall static route from RIB. */
1371void
1372static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1373{
1374 struct route_node *rn;
1375 struct rib *rib;
1376 struct nexthop *nexthop;
1377 struct route_table *table;
1378
1379 /* Lookup table. */
1380 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1381 if (! table)
1382 return;
1383
1384 /* Lookup existing route with type and distance. */
1385 rn = route_node_lookup (table, p);
1386 if (! rn)
1387 return;
1388
1389 for (rib = rn->info; rib; rib = rib->next)
1390 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1391 break;
1392
1393 if (! rib)
1394 {
1395 route_unlock_node (rn);
1396 return;
1397 }
1398
1399 /* Lookup nexthop. */
1400 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1401 if (static_ipv4_nexthop_same (nexthop, si))
1402 break;
1403
1404 /* Can't find nexthop. */
1405 if (! nexthop)
1406 {
1407 route_unlock_node (rn);
1408 return;
1409 }
1410
1411 /* Check nexthop. */
1412 if (rib->nexthop_num == 1)
1413 {
1414 rib_delnode (rn, rib);
1415 rib_process (rn, rib);
1416 newrib_free (rib);
1417 route_unlock_node (rn);
1418 }
1419 else
1420 {
1421 rib_uninstall (rn, rib);
1422 nexthop_delete (rib, nexthop);
1423 nexthop_free (nexthop);
1424 rib_process (rn, rib);
1425 }
1426
1427 /* Unlock node. */
1428 route_unlock_node (rn);
1429}
1430
1431/* Add static route into static route configuration. */
1432int
1433static_add_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001434 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001435{
1436 u_char type = 0;
1437 struct route_node *rn;
1438 struct static_ipv4 *si;
1439 struct static_ipv4 *pp;
1440 struct static_ipv4 *cp;
1441 struct static_ipv4 *update = NULL;
1442 struct route_table *stable;
1443
1444 /* Lookup table. */
1445 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1446 if (! stable)
1447 return -1;
1448
1449 /* Lookup static route prefix. */
1450 rn = route_node_get (stable, p);
1451
1452 /* Make flags. */
1453 if (gate)
1454 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001455 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001456 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001457 else
1458 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001459
1460 /* Do nothing if there is a same static route. */
1461 for (si = rn->info; si; si = si->next)
1462 {
1463 if (type == si->type
1464 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1465 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1466 {
1467 if (distance == si->distance)
1468 {
1469 route_unlock_node (rn);
1470 return 0;
1471 }
1472 else
1473 update = si;
1474 }
1475 }
1476
1477 /* Distance chaged. */
1478 if (update)
1479 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1480
1481 /* Make new static route structure. */
1482 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1483 memset (si, 0, sizeof (struct static_ipv4));
1484
1485 si->type = type;
1486 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001487 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001488
1489 if (gate)
1490 si->gate.ipv4 = *gate;
1491 if (ifname)
1492 si->gate.ifname = XSTRDUP (0, ifname);
1493
1494 /* Add new static route information to the tree with sort by
1495 distance value and gateway address. */
1496 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1497 {
1498 if (si->distance < cp->distance)
1499 break;
1500 if (si->distance > cp->distance)
1501 continue;
1502 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1503 {
1504 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1505 break;
1506 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1507 continue;
1508 }
1509 }
1510
1511 /* Make linked list. */
1512 if (pp)
1513 pp->next = si;
1514 else
1515 rn->info = si;
1516 if (cp)
1517 cp->prev = si;
1518 si->prev = pp;
1519 si->next = cp;
1520
1521 /* Install into rib. */
1522 static_install_ipv4 (p, si);
1523
1524 return 1;
1525}
1526
1527/* Delete static route from static route configuration. */
1528int
1529static_delete_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
1530 u_char distance, u_int32_t vrf_id)
1531{
1532 u_char type = 0;
1533 struct route_node *rn;
1534 struct static_ipv4 *si;
1535 struct route_table *stable;
1536
1537 /* Lookup table. */
1538 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1539 if (! stable)
1540 return -1;
1541
1542 /* Lookup static route prefix. */
1543 rn = route_node_lookup (stable, p);
1544 if (! rn)
1545 return 0;
1546
1547 /* Make flags. */
1548 if (gate)
1549 type = STATIC_IPV4_GATEWAY;
1550 else if (ifname)
1551 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001552 else
1553 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001554
1555 /* Find same static route is the tree */
1556 for (si = rn->info; si; si = si->next)
1557 if (type == si->type
1558 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1559 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1560 break;
1561
1562 /* Can't find static route. */
1563 if (! si)
1564 {
1565 route_unlock_node (rn);
1566 return 0;
1567 }
1568
1569 /* Install into rib. */
1570 static_uninstall_ipv4 (p, si);
1571
1572 /* Unlink static route from linked list. */
1573 if (si->prev)
1574 si->prev->next = si->next;
1575 else
1576 rn->info = si->next;
1577 if (si->next)
1578 si->next->prev = si->prev;
1579
1580 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001581 if (ifname)
1582 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001583 XFREE (MTYPE_STATIC_IPV4, si);
1584
1585 return 1;
1586}
1587
1588
1589#ifdef HAVE_IPV6
1590int
1591rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1592 struct in6_addr *gate, unsigned int ifindex, int table)
1593{
hasso726f9b22003-05-25 21:04:54 +00001594 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1595#if defined (MUSICA) || defined (LINUX)
1596 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1597 if (p->prefixlen == 96)
1598 return 0;
1599#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001600 return 1;
hasso726f9b22003-05-25 21:04:54 +00001601 }
paul718e3742002-12-13 20:15:29 +00001602 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1603 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1604 {
1605 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1606 return 1;
1607 }
1608 return 0;
1609}
1610
1611int
1612rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1613 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1614{
1615 struct rib *rib;
1616 struct rib *same = NULL;
1617 struct route_table *table;
1618 struct route_node *rn;
1619 struct nexthop *nexthop;
1620
1621 int distance;
1622 u_int32_t metric = 0;
1623
1624 /* Lookup table. */
1625 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1626 if (! table)
1627 return 0;
1628
1629 /* Make sure mask is applied. */
1630 apply_mask_ipv6 (p);
1631
1632 /* Set default distance by route type. */
1633 distance = route_info[type].distance;
1634
1635 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1636 distance = 200;
1637
1638 /* Filter bogus route. */
1639 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1640 return 0;
1641
1642 /* Lookup route node.*/
1643 rn = route_node_get (table, (struct prefix *) p);
1644
1645 /* If same type of route are installed, treat it as a implicit
1646 withdraw. */
1647 for (rib = rn->info; rib; rib = rib->next)
1648 {
1649 if (rib->type == ZEBRA_ROUTE_CONNECT)
1650 {
1651 nexthop = rib->nexthop;
1652
1653 if (rib->type == type
1654 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1655 && nexthop->ifindex == ifindex)
1656 {
1657 rib->refcnt++;
1658 return 0;
1659 }
1660 }
1661 else if (rib->type == type)
1662 {
1663 same = rib;
1664 rib_delnode (rn, same);
1665 route_unlock_node (rn);
1666 break;
1667 }
1668 }
1669
1670 /* Allocate new rib structure. */
1671 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1672 memset (rib, 0, sizeof (struct rib));
1673 rib->type = type;
1674 rib->distance = distance;
1675 rib->flags = flags;
1676 rib->metric = metric;
1677 rib->nexthop_num = 0;
1678 rib->uptime = time (NULL);
1679
1680 /* Nexthop settings. */
1681 if (gate)
1682 {
1683 if (ifindex)
1684 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1685 else
1686 nexthop_ipv6_add (rib, gate);
1687 }
1688 else
1689 nexthop_ifindex_add (rib, ifindex);
1690
1691 /* If this route is kernel route, set FIB flag to the route. */
1692 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1693 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1694 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1695
1696 /* Link new rib to node.*/
1697 rib_addnode (rn, rib);
1698
1699 /* Process this route node. */
1700 rib_process (rn, same);
1701
1702 /* Free implicit route.*/
1703 if (same)
1704 newrib_free (same);
1705
1706 return 0;
1707}
1708
1709int
1710rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1711 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1712{
1713 struct route_table *table;
1714 struct route_node *rn;
1715 struct rib *rib;
1716 struct rib *fib = NULL;
1717 struct rib *same = NULL;
1718 struct nexthop *nexthop;
1719 char buf1[BUFSIZ];
1720 char buf2[BUFSIZ];
1721
1722 /* Apply mask. */
1723 apply_mask_ipv6 (p);
1724
1725 /* Lookup table. */
1726 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1727 if (! table)
1728 return 0;
1729
1730 /* Lookup route node. */
1731 rn = route_node_lookup (table, (struct prefix *) p);
1732 if (! rn)
1733 {
1734 if (IS_ZEBRA_DEBUG_KERNEL)
1735 {
1736 if (gate)
1737 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
1738 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1739 p->prefixlen,
1740 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1741 ifindex);
1742 else
1743 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
1744 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1745 p->prefixlen,
1746 ifindex);
1747 }
1748 return ZEBRA_ERR_RTNOEXIST;
1749 }
1750
1751 /* Lookup same type route. */
1752 for (rib = rn->info; rib; rib = rib->next)
1753 {
1754 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1755 fib = rib;
1756
1757 if (rib->type == ZEBRA_ROUTE_CONNECT)
1758 {
1759 nexthop = rib->nexthop;
1760
1761 if (rib->type == type
1762 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1763 && nexthop->ifindex == ifindex)
1764 {
1765 if (rib->refcnt)
1766 {
1767 rib->refcnt--;
1768 route_unlock_node (rn);
1769 route_unlock_node (rn);
1770 return 0;
1771 }
1772 same = rib;
1773 break;
1774 }
1775 }
1776 else
1777 {
1778 if (rib->type == type)
1779 {
1780 same = rib;
1781 break;
1782 }
1783 }
1784 }
1785
1786 /* If same type of route can't be found and this message is from
1787 kernel. */
1788 if (! same)
1789 {
1790 if (fib && type == ZEBRA_ROUTE_KERNEL)
1791 {
1792 /* Unset flags. */
1793 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1794 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1795
1796 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1797 }
1798 else
1799 {
1800 if (IS_ZEBRA_DEBUG_KERNEL)
1801 {
1802 if (gate)
1803 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
1804 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1805 p->prefixlen,
1806 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1807 ifindex,
1808 type);
1809 else
1810 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
1811 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1812 p->prefixlen,
1813 ifindex,
1814 type);
1815 }
1816 route_unlock_node (rn);
1817 return ZEBRA_ERR_RTNOEXIST;
1818 }
1819 }
1820
1821 if (same)
1822 rib_delnode (rn, same);
1823
1824 /* Process changes. */
1825 rib_process (rn, same);
1826
1827 if (same)
1828 {
1829 newrib_free (same);
1830 route_unlock_node (rn);
1831 }
1832
1833 route_unlock_node (rn);
1834
1835 return 0;
1836}
1837
1838/* Install static route into rib. */
1839void
1840static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
1841{
1842 struct rib *rib;
1843 struct route_table *table;
1844 struct route_node *rn;
1845
1846 /* Lookup table. */
1847 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1848 if (! table)
1849 return;
1850
1851 /* Lookup existing route */
1852 rn = route_node_get (table, p);
1853 for (rib = rn->info; rib; rib = rib->next)
1854 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1855 break;
1856
1857 if (rib)
1858 {
1859 /* Same distance static route is there. Update it with new
1860 nexthop. */
1861 rib_uninstall (rn, rib);
1862 route_unlock_node (rn);
1863
1864 switch (si->type)
1865 {
1866 case STATIC_IPV6_GATEWAY:
1867 nexthop_ipv6_add (rib, &si->ipv6);
1868 break;
1869 case STATIC_IPV6_IFNAME:
1870 nexthop_ifname_add (rib, si->ifname);
1871 break;
1872 case STATIC_IPV6_GATEWAY_IFNAME:
1873 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
1874 break;
1875 }
1876 rib_process (rn, NULL);
1877 }
1878 else
1879 {
1880 /* This is new static route. */
1881 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1882 memset (rib, 0, sizeof (struct rib));
1883
1884 rib->type = ZEBRA_ROUTE_STATIC;
1885 rib->distance = si->distance;
1886 rib->metric = 0;
1887 rib->nexthop_num = 0;
1888
1889 switch (si->type)
1890 {
1891 case STATIC_IPV6_GATEWAY:
1892 nexthop_ipv6_add (rib, &si->ipv6);
1893 break;
1894 case STATIC_IPV6_IFNAME:
1895 nexthop_ifname_add (rib, si->ifname);
1896 break;
1897 case STATIC_IPV6_GATEWAY_IFNAME:
1898 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
1899 break;
1900 }
1901
hasso81dfcaa2003-05-25 19:21:25 +00001902 /* Save the flags of this static routes (reject, blackhole) */
1903 rib->flags = si->flags;
1904
paul718e3742002-12-13 20:15:29 +00001905 /* Link this rib to the tree. */
1906 rib_addnode (rn, rib);
1907
1908 /* Process this prefix. */
1909 rib_process (rn, NULL);
1910 }
1911}
1912
1913int
1914static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
1915{
1916 if (nexthop->type == NEXTHOP_TYPE_IPV6
1917 && si->type == STATIC_IPV6_GATEWAY
1918 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
1919 return 1;
1920 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1921 && si->type == STATIC_IPV6_IFNAME
1922 && strcmp (nexthop->ifname, si->ifname) == 0)
1923 return 1;
1924 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1925 && si->type == STATIC_IPV6_GATEWAY_IFNAME
1926 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
1927 && strcmp (nexthop->ifname, si->ifname) == 0)
1928 return 1;
1929 return 0;;
1930}
1931
1932void
1933static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
1934{
1935 struct route_table *table;
1936 struct route_node *rn;
1937 struct rib *rib;
1938 struct nexthop *nexthop;
1939
1940 /* Lookup table. */
1941 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1942 if (! table)
1943 return;
1944
1945 /* Lookup existing route with type and distance. */
1946 rn = route_node_lookup (table, (struct prefix *) p);
1947 if (! rn)
1948 return;
1949
1950 for (rib = rn->info; rib; rib = rib->next)
1951 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1952 break;
1953 if (! rib)
1954 {
1955 route_unlock_node (rn);
1956 return;
1957 }
1958
1959 /* Lookup nexthop. */
1960 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1961 if (static_ipv6_nexthop_same (nexthop, si))
1962 break;
1963
1964 /* Can't find nexthop. */
1965 if (! nexthop)
1966 {
1967 route_unlock_node (rn);
1968 return;
1969 }
1970
1971 /* Check nexthop. */
1972 if (rib->nexthop_num == 1)
1973 {
1974 rib_delnode (rn, rib);
1975 rib_process (rn, rib);
1976 newrib_free (rib);
1977 route_unlock_node (rn);
1978 }
1979 else
1980 {
1981 rib_uninstall (rn, rib);
1982 nexthop_delete (rib, nexthop);
1983 nexthop_free (nexthop);
1984 rib_process (rn, rib);
1985 }
1986
1987 /* Unlock node. */
1988 route_unlock_node (rn);
1989}
1990
1991/* Add static route into static route configuration. */
1992int
1993static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso81dfcaa2003-05-25 19:21:25 +00001994 char *ifname, u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001995{
1996 struct route_node *rn;
1997 struct static_ipv6 *si;
1998 struct static_ipv6 *pp;
1999 struct static_ipv6 *cp;
2000 struct route_table *stable;
2001
2002 /* Lookup table. */
2003 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2004 if (! stable)
2005 return -1;
2006
2007 /* Lookup static route prefix. */
2008 rn = route_node_get (stable, p);
2009
2010 /* Do nothing if there is a same static route. */
2011 for (si = rn->info; si; si = si->next)
2012 {
2013 if (distance == si->distance
2014 && type == si->type
2015 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2016 && (! ifname || strcmp (ifname, si->ifname) == 0))
2017 {
2018 route_unlock_node (rn);
2019 return 0;
2020 }
2021 }
2022
2023 /* Make new static route structure. */
2024 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2025 memset (si, 0, sizeof (struct static_ipv6));
2026
2027 si->type = type;
2028 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002029 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002030
2031 switch (type)
2032 {
2033 case STATIC_IPV6_GATEWAY:
2034 si->ipv6 = *gate;
2035 break;
2036 case STATIC_IPV6_IFNAME:
2037 si->ifname = XSTRDUP (0, ifname);
2038 break;
2039 case STATIC_IPV6_GATEWAY_IFNAME:
2040 si->ipv6 = *gate;
2041 si->ifname = XSTRDUP (0, ifname);
2042 break;
2043 }
2044
2045 /* Add new static route information to the tree with sort by
2046 distance value and gateway address. */
2047 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2048 {
2049 if (si->distance < cp->distance)
2050 break;
2051 if (si->distance > cp->distance)
2052 continue;
2053 }
2054
2055 /* Make linked list. */
2056 if (pp)
2057 pp->next = si;
2058 else
2059 rn->info = si;
2060 if (cp)
2061 cp->prev = si;
2062 si->prev = pp;
2063 si->next = cp;
2064
2065 /* Install into rib. */
2066 static_install_ipv6 (p, si);
2067
2068 return 1;
2069}
2070
2071/* Delete static route from static route configuration. */
2072int
2073static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
2074 char *ifname, u_char distance, u_int32_t vrf_id)
2075{
2076 struct route_node *rn;
2077 struct static_ipv6 *si;
2078 struct route_table *stable;
2079
2080 /* Lookup table. */
2081 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2082 if (! stable)
2083 return -1;
2084
2085 /* Lookup static route prefix. */
2086 rn = route_node_lookup (stable, p);
2087 if (! rn)
2088 return 0;
2089
2090 /* Find same static route is the tree */
2091 for (si = rn->info; si; si = si->next)
2092 if (distance == si->distance
2093 && type == si->type
2094 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2095 && (! ifname || strcmp (ifname, si->ifname) == 0))
2096 break;
2097
2098 /* Can't find static route. */
2099 if (! si)
2100 {
2101 route_unlock_node (rn);
2102 return 0;
2103 }
2104
2105 /* Install into rib. */
2106 static_uninstall_ipv6 (p, si);
2107
2108 /* Unlink static route from linked list. */
2109 if (si->prev)
2110 si->prev->next = si->next;
2111 else
2112 rn->info = si->next;
2113 if (si->next)
2114 si->next->prev = si->prev;
2115
2116 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002117 if (ifname)
2118 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002119 XFREE (MTYPE_STATIC_IPV6, si);
2120
2121 return 1;
2122}
2123#endif /* HAVE_IPV6 */
2124
2125/* RIB update function. */
2126void
2127rib_update ()
2128{
2129 struct route_node *rn;
2130 struct route_table *table;
2131
2132 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2133 if (table)
2134 for (rn = route_top (table); rn; rn = route_next (rn))
2135 rib_process (rn, NULL);
2136
2137 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2138 if (table)
2139 for (rn = route_top (table); rn; rn = route_next (rn))
2140 rib_process (rn, NULL);
2141}
2142
2143/* Interface goes up. */
2144void
2145rib_if_up (struct interface *ifp)
2146{
2147 rib_update ();
2148}
2149
2150/* Interface goes down. */
2151void
2152rib_if_down (struct interface *ifp)
2153{
2154 rib_update ();
2155}
2156
2157/* Remove all routes which comes from non main table. */
2158void
2159rib_weed_table (struct route_table *table)
2160{
2161 struct route_node *rn;
2162 struct rib *rib;
2163 struct rib *next;
2164
2165 if (table)
2166 for (rn = route_top (table); rn; rn = route_next (rn))
2167 for (rib = rn->info; rib; rib = next)
2168 {
2169 next = rib->next;
2170
paulb21b19c2003-06-15 01:28:29 +00002171 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002172 rib->table != RT_TABLE_MAIN)
2173 {
2174 rib_delnode (rn, rib);
2175 newrib_free (rib);
2176 route_unlock_node (rn);
2177 }
2178 }
2179}
2180
2181/* Delete all routes from non main table. */
2182void
2183rib_weed_tables ()
2184{
2185 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2186 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2187}
2188
2189/* Delete self installed routes after zebra is relaunched. */
2190void
2191rib_sweep_table (struct route_table *table)
2192{
2193 struct route_node *rn;
2194 struct rib *rib;
2195 struct rib *next;
2196 int ret = 0;
2197
2198 if (table)
2199 for (rn = route_top (table); rn; rn = route_next (rn))
2200 for (rib = rn->info; rib; rib = next)
2201 {
2202 next = rib->next;
2203
2204 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2205 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2206 {
2207 ret = rib_uninstall_kernel (rn, rib);
2208 if (! ret)
2209 {
2210 rib_delnode (rn, rib);
2211 newrib_free (rib);
2212 route_unlock_node (rn);
2213 }
2214 }
2215 }
2216}
2217
2218/* Sweep all RIB tables. */
2219void
2220rib_sweep_route ()
2221{
2222 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2223 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2224}
2225
2226/* Close RIB and clean up kernel routes. */
2227void
2228rib_close_table (struct route_table *table)
2229{
2230 struct route_node *rn;
2231 struct rib *rib;
2232
2233 if (table)
2234 for (rn = route_top (table); rn; rn = route_next (rn))
2235 for (rib = rn->info; rib; rib = rib->next)
2236 if (! RIB_SYSTEM_ROUTE (rib)
2237 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2238 rib_uninstall_kernel (rn, rib);
2239}
2240
2241/* Close all RIB tables. */
2242void
2243rib_close ()
2244{
2245 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2246 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2247}
2248
2249/* Routing information base initialize. */
2250void
2251rib_init ()
2252{
2253 /* VRF initialization. */
2254 vrf_init ();
2255}