blob: ccccd0ad68c926da989c45ffdd3f20a815328131 [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))
paul7021c422003-07-15 12:52:22 +0000866 fib = rib;
paul718e3742002-12-13 20:15:29 +0000867
868 /* Skip unreachable nexthop. */
869 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +0000870 continue;
paul718e3742002-12-13 20:15:29 +0000871
872 /* Infinit distance. */
873 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +0000874 continue;
paul718e3742002-12-13 20:15:29 +0000875
876 /* Newly selected rib. */
877 if (! select || rib->distance < select->distance
paul7021c422003-07-15 12:52:22 +0000878 || rib->type == ZEBRA_ROUTE_CONNECT)
879 select = rib;
paul718e3742002-12-13 20:15:29 +0000880 }
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);
paul718e3742002-12-13 20:15:29 +00001303 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001304 {
1305 case STATIC_IPV4_GATEWAY:
1306 nexthop_ipv4_add (rib, &si->gate.ipv4);
1307 break;
1308 case STATIC_IPV4_IFNAME:
1309 nexthop_ifname_add (rib, si->gate.ifname);
1310 break;
1311 case STATIC_IPV4_BLACKHOLE:
1312 nexthop_blackhole_add (rib);
1313 break;
1314 }
paul718e3742002-12-13 20:15:29 +00001315 rib_process (rn, NULL);
1316 }
1317 else
1318 {
1319 /* This is new static route. */
1320 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1321 memset (rib, 0, sizeof (struct rib));
1322
1323 rib->type = ZEBRA_ROUTE_STATIC;
1324 rib->distance = si->distance;
1325 rib->metric = 0;
1326 rib->nexthop_num = 0;
1327
1328 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001329 {
1330 case STATIC_IPV4_GATEWAY:
1331 nexthop_ipv4_add (rib, &si->gate.ipv4);
1332 break;
1333 case STATIC_IPV4_IFNAME:
1334 nexthop_ifname_add (rib, si->gate.ifname);
1335 break;
1336 case STATIC_IPV4_BLACKHOLE:
1337 nexthop_blackhole_add (rib);
1338 break;
1339 }
paul718e3742002-12-13 20:15:29 +00001340
hasso81dfcaa2003-05-25 19:21:25 +00001341 /* Save the flags of this static routes (reject, blackhole) */
1342 rib->flags = si->flags;
1343
paul718e3742002-12-13 20:15:29 +00001344 /* Link this rib to the tree. */
1345 rib_addnode (rn, rib);
1346
1347 /* Process this prefix. */
1348 rib_process (rn, NULL);
1349 }
1350}
1351
1352int
1353static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1354{
1355 if (nexthop->type == NEXTHOP_TYPE_IPV4
1356 && si->type == STATIC_IPV4_GATEWAY
1357 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1358 return 1;
1359 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1360 && si->type == STATIC_IPV4_IFNAME
1361 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1362 return 1;
paul595db7f2003-05-25 21:35:06 +00001363 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1364 && si->type == STATIC_IPV4_BLACKHOLE)
1365 return 1;
paul718e3742002-12-13 20:15:29 +00001366 return 0;;
1367}
1368
1369/* Uninstall static route from RIB. */
1370void
1371static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1372{
1373 struct route_node *rn;
1374 struct rib *rib;
1375 struct nexthop *nexthop;
1376 struct route_table *table;
1377
1378 /* Lookup table. */
1379 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1380 if (! table)
1381 return;
1382
1383 /* Lookup existing route with type and distance. */
1384 rn = route_node_lookup (table, p);
1385 if (! rn)
1386 return;
1387
1388 for (rib = rn->info; rib; rib = rib->next)
1389 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1390 break;
1391
1392 if (! rib)
1393 {
1394 route_unlock_node (rn);
1395 return;
1396 }
1397
1398 /* Lookup nexthop. */
1399 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1400 if (static_ipv4_nexthop_same (nexthop, si))
1401 break;
1402
1403 /* Can't find nexthop. */
1404 if (! nexthop)
1405 {
1406 route_unlock_node (rn);
1407 return;
1408 }
1409
1410 /* Check nexthop. */
1411 if (rib->nexthop_num == 1)
1412 {
1413 rib_delnode (rn, rib);
1414 rib_process (rn, rib);
1415 newrib_free (rib);
1416 route_unlock_node (rn);
1417 }
1418 else
1419 {
1420 rib_uninstall (rn, rib);
1421 nexthop_delete (rib, nexthop);
1422 nexthop_free (nexthop);
1423 rib_process (rn, rib);
1424 }
1425
1426 /* Unlock node. */
1427 route_unlock_node (rn);
1428}
1429
1430/* Add static route into static route configuration. */
1431int
1432static_add_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001433 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001434{
1435 u_char type = 0;
1436 struct route_node *rn;
1437 struct static_ipv4 *si;
1438 struct static_ipv4 *pp;
1439 struct static_ipv4 *cp;
1440 struct static_ipv4 *update = NULL;
1441 struct route_table *stable;
1442
1443 /* Lookup table. */
1444 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1445 if (! stable)
1446 return -1;
1447
1448 /* Lookup static route prefix. */
1449 rn = route_node_get (stable, p);
1450
1451 /* Make flags. */
1452 if (gate)
1453 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001454 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001455 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001456 else
1457 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001458
1459 /* Do nothing if there is a same static route. */
1460 for (si = rn->info; si; si = si->next)
1461 {
1462 if (type == si->type
1463 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1464 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1465 {
1466 if (distance == si->distance)
1467 {
1468 route_unlock_node (rn);
1469 return 0;
1470 }
1471 else
1472 update = si;
1473 }
1474 }
1475
1476 /* Distance chaged. */
1477 if (update)
1478 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1479
1480 /* Make new static route structure. */
1481 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1482 memset (si, 0, sizeof (struct static_ipv4));
1483
1484 si->type = type;
1485 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001486 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001487
1488 if (gate)
1489 si->gate.ipv4 = *gate;
1490 if (ifname)
1491 si->gate.ifname = XSTRDUP (0, ifname);
1492
1493 /* Add new static route information to the tree with sort by
1494 distance value and gateway address. */
1495 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1496 {
1497 if (si->distance < cp->distance)
1498 break;
1499 if (si->distance > cp->distance)
1500 continue;
1501 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1502 {
1503 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1504 break;
1505 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1506 continue;
1507 }
1508 }
1509
1510 /* Make linked list. */
1511 if (pp)
1512 pp->next = si;
1513 else
1514 rn->info = si;
1515 if (cp)
1516 cp->prev = si;
1517 si->prev = pp;
1518 si->next = cp;
1519
1520 /* Install into rib. */
1521 static_install_ipv4 (p, si);
1522
1523 return 1;
1524}
1525
1526/* Delete static route from static route configuration. */
1527int
1528static_delete_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
1529 u_char distance, u_int32_t vrf_id)
1530{
1531 u_char type = 0;
1532 struct route_node *rn;
1533 struct static_ipv4 *si;
1534 struct route_table *stable;
1535
1536 /* Lookup table. */
1537 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1538 if (! stable)
1539 return -1;
1540
1541 /* Lookup static route prefix. */
1542 rn = route_node_lookup (stable, p);
1543 if (! rn)
1544 return 0;
1545
1546 /* Make flags. */
1547 if (gate)
1548 type = STATIC_IPV4_GATEWAY;
1549 else if (ifname)
1550 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001551 else
1552 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001553
1554 /* Find same static route is the tree */
1555 for (si = rn->info; si; si = si->next)
1556 if (type == si->type
1557 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1558 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1559 break;
1560
1561 /* Can't find static route. */
1562 if (! si)
1563 {
1564 route_unlock_node (rn);
1565 return 0;
1566 }
1567
1568 /* Install into rib. */
1569 static_uninstall_ipv4 (p, si);
1570
1571 /* Unlink static route from linked list. */
1572 if (si->prev)
1573 si->prev->next = si->next;
1574 else
1575 rn->info = si->next;
1576 if (si->next)
1577 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001578 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001579
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
paul143a3852003-09-29 20:06:13 +00001585 route_unlock_node (rn);
1586
paul718e3742002-12-13 20:15:29 +00001587 return 1;
1588}
1589
1590
1591#ifdef HAVE_IPV6
1592int
1593rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1594 struct in6_addr *gate, unsigned int ifindex, int table)
1595{
hasso726f9b22003-05-25 21:04:54 +00001596 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1597#if defined (MUSICA) || defined (LINUX)
1598 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1599 if (p->prefixlen == 96)
1600 return 0;
1601#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001602 return 1;
hasso726f9b22003-05-25 21:04:54 +00001603 }
paul718e3742002-12-13 20:15:29 +00001604 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1605 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1606 {
1607 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1608 return 1;
1609 }
1610 return 0;
1611}
1612
1613int
1614rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1615 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1616{
1617 struct rib *rib;
1618 struct rib *same = NULL;
1619 struct route_table *table;
1620 struct route_node *rn;
1621 struct nexthop *nexthop;
1622
1623 int distance;
1624 u_int32_t metric = 0;
1625
1626 /* Lookup table. */
1627 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1628 if (! table)
1629 return 0;
1630
1631 /* Make sure mask is applied. */
1632 apply_mask_ipv6 (p);
1633
1634 /* Set default distance by route type. */
1635 distance = route_info[type].distance;
1636
1637 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1638 distance = 200;
1639
1640 /* Filter bogus route. */
1641 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1642 return 0;
1643
1644 /* Lookup route node.*/
1645 rn = route_node_get (table, (struct prefix *) p);
1646
1647 /* If same type of route are installed, treat it as a implicit
1648 withdraw. */
1649 for (rib = rn->info; rib; rib = rib->next)
1650 {
1651 if (rib->type == ZEBRA_ROUTE_CONNECT)
1652 {
1653 nexthop = rib->nexthop;
1654
1655 if (rib->type == type
1656 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1657 && nexthop->ifindex == ifindex)
1658 {
1659 rib->refcnt++;
1660 return 0;
1661 }
1662 }
1663 else if (rib->type == type)
1664 {
1665 same = rib;
1666 rib_delnode (rn, same);
1667 route_unlock_node (rn);
1668 break;
1669 }
1670 }
1671
1672 /* Allocate new rib structure. */
1673 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1674 memset (rib, 0, sizeof (struct rib));
1675 rib->type = type;
1676 rib->distance = distance;
1677 rib->flags = flags;
1678 rib->metric = metric;
1679 rib->nexthop_num = 0;
1680 rib->uptime = time (NULL);
1681
1682 /* Nexthop settings. */
1683 if (gate)
1684 {
1685 if (ifindex)
1686 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1687 else
1688 nexthop_ipv6_add (rib, gate);
1689 }
1690 else
1691 nexthop_ifindex_add (rib, ifindex);
1692
1693 /* If this route is kernel route, set FIB flag to the route. */
1694 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1695 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1696 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1697
1698 /* Link new rib to node.*/
1699 rib_addnode (rn, rib);
1700
1701 /* Process this route node. */
1702 rib_process (rn, same);
1703
1704 /* Free implicit route.*/
1705 if (same)
1706 newrib_free (same);
1707
1708 return 0;
1709}
1710
1711int
1712rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1713 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1714{
1715 struct route_table *table;
1716 struct route_node *rn;
1717 struct rib *rib;
1718 struct rib *fib = NULL;
1719 struct rib *same = NULL;
1720 struct nexthop *nexthop;
1721 char buf1[BUFSIZ];
1722 char buf2[BUFSIZ];
1723
1724 /* Apply mask. */
1725 apply_mask_ipv6 (p);
1726
1727 /* Lookup table. */
1728 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1729 if (! table)
1730 return 0;
1731
1732 /* Lookup route node. */
1733 rn = route_node_lookup (table, (struct prefix *) p);
1734 if (! rn)
1735 {
1736 if (IS_ZEBRA_DEBUG_KERNEL)
1737 {
1738 if (gate)
1739 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
1740 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1741 p->prefixlen,
1742 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1743 ifindex);
1744 else
1745 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
1746 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1747 p->prefixlen,
1748 ifindex);
1749 }
1750 return ZEBRA_ERR_RTNOEXIST;
1751 }
1752
1753 /* Lookup same type route. */
1754 for (rib = rn->info; rib; rib = rib->next)
1755 {
1756 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1757 fib = rib;
1758
1759 if (rib->type == ZEBRA_ROUTE_CONNECT)
1760 {
1761 nexthop = rib->nexthop;
1762
1763 if (rib->type == type
1764 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1765 && nexthop->ifindex == ifindex)
1766 {
1767 if (rib->refcnt)
1768 {
1769 rib->refcnt--;
1770 route_unlock_node (rn);
1771 route_unlock_node (rn);
1772 return 0;
1773 }
1774 same = rib;
1775 break;
1776 }
1777 }
1778 else
1779 {
1780 if (rib->type == type)
1781 {
1782 same = rib;
1783 break;
1784 }
1785 }
1786 }
1787
1788 /* If same type of route can't be found and this message is from
1789 kernel. */
1790 if (! same)
1791 {
1792 if (fib && type == ZEBRA_ROUTE_KERNEL)
1793 {
1794 /* Unset flags. */
1795 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1796 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1797
1798 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1799 }
1800 else
1801 {
1802 if (IS_ZEBRA_DEBUG_KERNEL)
1803 {
1804 if (gate)
1805 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
1806 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1807 p->prefixlen,
1808 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1809 ifindex,
1810 type);
1811 else
1812 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
1813 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1814 p->prefixlen,
1815 ifindex,
1816 type);
1817 }
1818 route_unlock_node (rn);
1819 return ZEBRA_ERR_RTNOEXIST;
1820 }
1821 }
1822
1823 if (same)
1824 rib_delnode (rn, same);
1825
1826 /* Process changes. */
1827 rib_process (rn, same);
1828
1829 if (same)
1830 {
1831 newrib_free (same);
1832 route_unlock_node (rn);
1833 }
1834
1835 route_unlock_node (rn);
1836
1837 return 0;
1838}
1839
1840/* Install static route into rib. */
1841void
1842static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
1843{
1844 struct rib *rib;
1845 struct route_table *table;
1846 struct route_node *rn;
1847
1848 /* Lookup table. */
1849 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1850 if (! table)
1851 return;
1852
1853 /* Lookup existing route */
1854 rn = route_node_get (table, p);
1855 for (rib = rn->info; rib; rib = rib->next)
1856 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1857 break;
1858
1859 if (rib)
1860 {
1861 /* Same distance static route is there. Update it with new
1862 nexthop. */
1863 rib_uninstall (rn, rib);
1864 route_unlock_node (rn);
1865
1866 switch (si->type)
1867 {
1868 case STATIC_IPV6_GATEWAY:
1869 nexthop_ipv6_add (rib, &si->ipv6);
1870 break;
1871 case STATIC_IPV6_IFNAME:
1872 nexthop_ifname_add (rib, si->ifname);
1873 break;
1874 case STATIC_IPV6_GATEWAY_IFNAME:
1875 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
1876 break;
1877 }
1878 rib_process (rn, NULL);
1879 }
1880 else
1881 {
1882 /* This is new static route. */
1883 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1884 memset (rib, 0, sizeof (struct rib));
1885
1886 rib->type = ZEBRA_ROUTE_STATIC;
1887 rib->distance = si->distance;
1888 rib->metric = 0;
1889 rib->nexthop_num = 0;
1890
1891 switch (si->type)
1892 {
1893 case STATIC_IPV6_GATEWAY:
1894 nexthop_ipv6_add (rib, &si->ipv6);
1895 break;
1896 case STATIC_IPV6_IFNAME:
1897 nexthop_ifname_add (rib, si->ifname);
1898 break;
1899 case STATIC_IPV6_GATEWAY_IFNAME:
1900 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
1901 break;
1902 }
1903
hasso81dfcaa2003-05-25 19:21:25 +00001904 /* Save the flags of this static routes (reject, blackhole) */
1905 rib->flags = si->flags;
1906
paul718e3742002-12-13 20:15:29 +00001907 /* Link this rib to the tree. */
1908 rib_addnode (rn, rib);
1909
1910 /* Process this prefix. */
1911 rib_process (rn, NULL);
1912 }
1913}
1914
1915int
1916static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
1917{
1918 if (nexthop->type == NEXTHOP_TYPE_IPV6
1919 && si->type == STATIC_IPV6_GATEWAY
1920 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
1921 return 1;
1922 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1923 && si->type == STATIC_IPV6_IFNAME
1924 && strcmp (nexthop->ifname, si->ifname) == 0)
1925 return 1;
1926 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1927 && si->type == STATIC_IPV6_GATEWAY_IFNAME
1928 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
1929 && strcmp (nexthop->ifname, si->ifname) == 0)
1930 return 1;
1931 return 0;;
1932}
1933
1934void
1935static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
1936{
1937 struct route_table *table;
1938 struct route_node *rn;
1939 struct rib *rib;
1940 struct nexthop *nexthop;
1941
1942 /* Lookup table. */
1943 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1944 if (! table)
1945 return;
1946
1947 /* Lookup existing route with type and distance. */
1948 rn = route_node_lookup (table, (struct prefix *) p);
1949 if (! rn)
1950 return;
1951
1952 for (rib = rn->info; rib; rib = rib->next)
1953 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1954 break;
1955 if (! rib)
1956 {
1957 route_unlock_node (rn);
1958 return;
1959 }
1960
1961 /* Lookup nexthop. */
1962 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1963 if (static_ipv6_nexthop_same (nexthop, si))
1964 break;
1965
1966 /* Can't find nexthop. */
1967 if (! nexthop)
1968 {
1969 route_unlock_node (rn);
1970 return;
1971 }
1972
1973 /* Check nexthop. */
1974 if (rib->nexthop_num == 1)
1975 {
1976 rib_delnode (rn, rib);
1977 rib_process (rn, rib);
1978 newrib_free (rib);
1979 route_unlock_node (rn);
1980 }
1981 else
1982 {
1983 rib_uninstall (rn, rib);
1984 nexthop_delete (rib, nexthop);
1985 nexthop_free (nexthop);
1986 rib_process (rn, rib);
1987 }
1988
1989 /* Unlock node. */
1990 route_unlock_node (rn);
1991}
1992
1993/* Add static route into static route configuration. */
1994int
1995static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso81dfcaa2003-05-25 19:21:25 +00001996 char *ifname, u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001997{
1998 struct route_node *rn;
1999 struct static_ipv6 *si;
2000 struct static_ipv6 *pp;
2001 struct static_ipv6 *cp;
2002 struct route_table *stable;
2003
2004 /* Lookup table. */
2005 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2006 if (! stable)
2007 return -1;
2008
2009 /* Lookup static route prefix. */
2010 rn = route_node_get (stable, p);
2011
2012 /* Do nothing if there is a same static route. */
2013 for (si = rn->info; si; si = si->next)
2014 {
2015 if (distance == si->distance
2016 && type == si->type
2017 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2018 && (! ifname || strcmp (ifname, si->ifname) == 0))
2019 {
2020 route_unlock_node (rn);
2021 return 0;
2022 }
2023 }
2024
2025 /* Make new static route structure. */
2026 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2027 memset (si, 0, sizeof (struct static_ipv6));
2028
2029 si->type = type;
2030 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002031 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002032
2033 switch (type)
2034 {
2035 case STATIC_IPV6_GATEWAY:
2036 si->ipv6 = *gate;
2037 break;
2038 case STATIC_IPV6_IFNAME:
2039 si->ifname = XSTRDUP (0, ifname);
2040 break;
2041 case STATIC_IPV6_GATEWAY_IFNAME:
2042 si->ipv6 = *gate;
2043 si->ifname = XSTRDUP (0, ifname);
2044 break;
2045 }
2046
2047 /* Add new static route information to the tree with sort by
2048 distance value and gateway address. */
2049 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2050 {
2051 if (si->distance < cp->distance)
2052 break;
2053 if (si->distance > cp->distance)
2054 continue;
2055 }
2056
2057 /* Make linked list. */
2058 if (pp)
2059 pp->next = si;
2060 else
2061 rn->info = si;
2062 if (cp)
2063 cp->prev = si;
2064 si->prev = pp;
2065 si->next = cp;
2066
2067 /* Install into rib. */
2068 static_install_ipv6 (p, si);
2069
2070 return 1;
2071}
2072
2073/* Delete static route from static route configuration. */
2074int
2075static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
2076 char *ifname, u_char distance, u_int32_t vrf_id)
2077{
2078 struct route_node *rn;
2079 struct static_ipv6 *si;
2080 struct route_table *stable;
2081
2082 /* Lookup table. */
2083 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2084 if (! stable)
2085 return -1;
2086
2087 /* Lookup static route prefix. */
2088 rn = route_node_lookup (stable, p);
2089 if (! rn)
2090 return 0;
2091
2092 /* Find same static route is the tree */
2093 for (si = rn->info; si; si = si->next)
2094 if (distance == si->distance
2095 && type == si->type
2096 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2097 && (! ifname || strcmp (ifname, si->ifname) == 0))
2098 break;
2099
2100 /* Can't find static route. */
2101 if (! si)
2102 {
2103 route_unlock_node (rn);
2104 return 0;
2105 }
2106
2107 /* Install into rib. */
2108 static_uninstall_ipv6 (p, si);
2109
2110 /* Unlink static route from linked list. */
2111 if (si->prev)
2112 si->prev->next = si->next;
2113 else
2114 rn->info = si->next;
2115 if (si->next)
2116 si->next->prev = si->prev;
2117
2118 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002119 if (ifname)
2120 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002121 XFREE (MTYPE_STATIC_IPV6, si);
2122
2123 return 1;
2124}
2125#endif /* HAVE_IPV6 */
2126
2127/* RIB update function. */
2128void
2129rib_update ()
2130{
2131 struct route_node *rn;
2132 struct route_table *table;
2133
2134 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2135 if (table)
2136 for (rn = route_top (table); rn; rn = route_next (rn))
2137 rib_process (rn, NULL);
2138
2139 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2140 if (table)
2141 for (rn = route_top (table); rn; rn = route_next (rn))
2142 rib_process (rn, NULL);
2143}
2144
2145/* Interface goes up. */
2146void
2147rib_if_up (struct interface *ifp)
2148{
2149 rib_update ();
2150}
2151
2152/* Interface goes down. */
2153void
2154rib_if_down (struct interface *ifp)
2155{
2156 rib_update ();
2157}
2158
2159/* Remove all routes which comes from non main table. */
2160void
2161rib_weed_table (struct route_table *table)
2162{
2163 struct route_node *rn;
2164 struct rib *rib;
2165 struct rib *next;
2166
2167 if (table)
2168 for (rn = route_top (table); rn; rn = route_next (rn))
2169 for (rib = rn->info; rib; rib = next)
2170 {
2171 next = rib->next;
2172
paulb21b19c2003-06-15 01:28:29 +00002173 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002174 rib->table != RT_TABLE_MAIN)
2175 {
2176 rib_delnode (rn, rib);
2177 newrib_free (rib);
2178 route_unlock_node (rn);
2179 }
2180 }
2181}
2182
2183/* Delete all routes from non main table. */
2184void
2185rib_weed_tables ()
2186{
2187 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2188 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2189}
2190
2191/* Delete self installed routes after zebra is relaunched. */
2192void
2193rib_sweep_table (struct route_table *table)
2194{
2195 struct route_node *rn;
2196 struct rib *rib;
2197 struct rib *next;
2198 int ret = 0;
2199
2200 if (table)
2201 for (rn = route_top (table); rn; rn = route_next (rn))
2202 for (rib = rn->info; rib; rib = next)
2203 {
2204 next = rib->next;
2205
2206 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2207 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2208 {
2209 ret = rib_uninstall_kernel (rn, rib);
2210 if (! ret)
2211 {
2212 rib_delnode (rn, rib);
2213 newrib_free (rib);
2214 route_unlock_node (rn);
2215 }
2216 }
2217 }
2218}
2219
2220/* Sweep all RIB tables. */
2221void
2222rib_sweep_route ()
2223{
2224 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2225 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2226}
2227
2228/* Close RIB and clean up kernel routes. */
2229void
2230rib_close_table (struct route_table *table)
2231{
2232 struct route_node *rn;
2233 struct rib *rib;
2234
2235 if (table)
2236 for (rn = route_top (table); rn; rn = route_next (rn))
2237 for (rib = rn->info; rib; rib = rib->next)
2238 if (! RIB_SYSTEM_ROUTE (rib)
2239 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2240 rib_uninstall_kernel (rn, rib);
2241}
2242
2243/* Close all RIB tables. */
2244void
2245rib_close ()
2246{
2247 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2248 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2249}
2250
2251/* Routing information base initialize. */
2252void
2253rib_init ()
2254{
2255 /* VRF initialization. */
2256 vrf_init ();
2257}