blob: 05ff1e102365b5ebbd46510aeedd16ba8a52e95e [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);
paul6baeb982003-10-28 03:47:15 +0000762
763 nexthop_active_check (rn, rib, nexthop, set);
764 if ((MULTIPATH_NUM == 0 || rib->nexthop_active_num < MULTIPATH_NUM)
765 && active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
766 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
767
768 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
769 rib->nexthop_active_num++;
paul718e3742002-12-13 20:15:29 +0000770 }
771 return rib->nexthop_active_num;
772}
paul6baeb982003-10-28 03:47:15 +0000773
paul718e3742002-12-13 20:15:29 +0000774
775#define RIB_SYSTEM_ROUTE(R) \
776 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
777
778void
779newrib_free (struct rib *rib)
780{
781 struct nexthop *nexthop;
782 struct nexthop *next;
783
784 for (nexthop = rib->nexthop; nexthop; nexthop = next)
785 {
786 next = nexthop->next;
787 nexthop_free (nexthop);
788 }
789 XFREE (MTYPE_RIB, rib);
790}
791
792void
793rib_install_kernel (struct route_node *rn, struct rib *rib)
794{
795 int ret = 0;
796 struct nexthop *nexthop;
797
798 switch (PREFIX_FAMILY (&rn->p))
799 {
800 case AF_INET:
801 ret = kernel_add_ipv4 (&rn->p, rib);
802 break;
803#ifdef HAVE_IPV6
804 case AF_INET6:
805 ret = kernel_add_ipv6 (&rn->p, rib);
806 break;
807#endif /* HAVE_IPV6 */
808 }
809
810 if (ret < 0)
811 {
812 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
813 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
814 }
815}
816
817/* Uninstall the route from kernel. */
818int
819rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
820{
821 int ret = 0;
822 struct nexthop *nexthop;
823
824 switch (PREFIX_FAMILY (&rn->p))
825 {
826 case AF_INET:
827 ret = kernel_delete_ipv4 (&rn->p, rib);
828 break;
829#ifdef HAVE_IPV6
830 case AF_INET6:
831 ret = kernel_delete_ipv6 (&rn->p, rib);
832 break;
833#endif /* HAVE_IPV6 */
834 }
835
836 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
837 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
838
839 return ret;
840}
841
842/* Uninstall the route from kernel. */
843void
844rib_uninstall (struct route_node *rn, struct rib *rib)
845{
846 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
847 {
848 redistribute_delete (&rn->p, rib);
849 if (! RIB_SYSTEM_ROUTE (rib))
850 rib_uninstall_kernel (rn, rib);
851 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
852 }
853}
854
855/* Core function for processing routing information base. */
856void
857rib_process (struct route_node *rn, struct rib *del)
858{
859 struct rib *rib;
860 struct rib *next;
861 struct rib *fib = NULL;
862 struct rib *select = NULL;
pauld753e9e2003-01-22 19:45:50 +0000863 int installed = 0;
864 struct nexthop *nexthop = NULL;
paul718e3742002-12-13 20:15:29 +0000865
866 for (rib = rn->info; rib; rib = next)
867 {
868 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +0000869
paul718e3742002-12-13 20:15:29 +0000870 /* Currently installed rib. */
871 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
paul7021c422003-07-15 12:52:22 +0000872 fib = rib;
paul718e3742002-12-13 20:15:29 +0000873
874 /* Skip unreachable nexthop. */
875 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +0000876 continue;
paul718e3742002-12-13 20:15:29 +0000877
878 /* Infinit distance. */
879 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +0000880 continue;
paul718e3742002-12-13 20:15:29 +0000881
882 /* Newly selected rib. */
883 if (! select || rib->distance < select->distance
paul7021c422003-07-15 12:52:22 +0000884 || rib->type == ZEBRA_ROUTE_CONNECT)
885 select = rib;
paul718e3742002-12-13 20:15:29 +0000886 }
887
888 /* Deleted route check. */
889 if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
890 fib = del;
891
892 /* Same route is selected. */
893 if (select && select == fib)
894 {
895 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
896 {
897 redistribute_delete (&rn->p, select);
898 if (! RIB_SYSTEM_ROUTE (select))
899 rib_uninstall_kernel (rn, select);
900
901 /* Set real nexthop. */
902 nexthop_active_update (rn, select, 1);
903
904 if (! RIB_SYSTEM_ROUTE (select))
905 rib_install_kernel (rn, select);
906 redistribute_add (&rn->p, select);
907 }
pauld753e9e2003-01-22 19:45:50 +0000908 else if (! RIB_SYSTEM_ROUTE (select))
909 {
910 /* Housekeeping code to deal with
911 race conditions in kernel with linux
912 netlink reporting interface up before IPv4 or IPv6 protocol
913 is ready to add routes.
914 This makes sure the routes are IN the kernel.
915 */
916
917 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
918 {
919 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
920 installed = 1;
921 }
922 if (! installed) rib_install_kernel (rn, select);
923 }
paul718e3742002-12-13 20:15:29 +0000924 return;
925 }
926
927 /* Uninstall old rib from forwarding table. */
928 if (fib)
929 {
930 redistribute_delete (&rn->p, fib);
931 if (! RIB_SYSTEM_ROUTE (fib))
932 rib_uninstall_kernel (rn, fib);
933 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
934
935 /* Set real nexthop. */
936 nexthop_active_update (rn, fib, 1);
937 }
938
939 /* Install new rib into forwarding table. */
940 if (select)
941 {
942 /* Set real nexthop. */
943 nexthop_active_update (rn, select, 1);
944
945 if (! RIB_SYSTEM_ROUTE (select))
946 rib_install_kernel (rn, select);
947 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
948 redistribute_add (&rn->p, select);
949 }
950}
951
952/* Add RIB to head of the route node. */
953void
954rib_addnode (struct route_node *rn, struct rib *rib)
955{
956 struct rib *head;
957
958 head = rn->info;
959 if (head)
960 head->prev = rib;
961 rib->next = head;
962 rn->info = rib;
963}
964
965void
966rib_delnode (struct route_node *rn, struct rib *rib)
967{
968 if (rib->next)
969 rib->next->prev = rib->prev;
970 if (rib->prev)
971 rib->prev->next = rib->next;
972 else
973 rn->info = rib->next;
974}
975
976int
977rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
978 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
979 u_int32_t metric, u_char distance)
980{
981 struct rib *rib;
982 struct rib *same = NULL;
983 struct route_table *table;
984 struct route_node *rn;
985 struct nexthop *nexthop;
986
987 /* Lookup table. */
988 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
989 if (! table)
990 return 0;
991
992 /* Make it sure prefixlen is applied to the prefix. */
993 apply_mask_ipv4 (p);
994
995 /* Set default distance by route type. */
996 if (distance == 0)
997 {
998 distance = route_info[type].distance;
999
1000 /* iBGP distance is 200. */
1001 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1002 distance = 200;
1003 }
1004
1005 /* Lookup route node.*/
1006 rn = route_node_get (table, (struct prefix *) p);
1007
1008 /* If same type of route are installed, treat it as a implicit
1009 withdraw. */
1010 for (rib = rn->info; rib; rib = rib->next)
1011 {
1012 if (rib->type == ZEBRA_ROUTE_CONNECT)
1013 {
1014 nexthop = rib->nexthop;
1015
1016 /* Duplicate connected route comes in. */
1017 if (rib->type == type
1018 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1019 && nexthop->ifindex == ifindex)
1020 {
1021 rib->refcnt++;
1022 return 0 ;
1023 }
1024 }
1025 else if (rib->type == type)
1026 {
1027 same = rib;
1028 rib_delnode (rn, same);
1029 route_unlock_node (rn);
1030 break;
1031 }
1032 }
1033
1034 /* Allocate new rib structure. */
1035 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1036 memset (rib, 0, sizeof (struct rib));
1037 rib->type = type;
1038 rib->distance = distance;
1039 rib->flags = flags;
1040 rib->metric = metric;
1041 rib->nexthop_num = 0;
1042 rib->uptime = time (NULL);
1043
1044 /* Nexthop settings. */
1045 if (gate)
1046 {
1047 if (ifindex)
1048 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
1049 else
1050 nexthop_ipv4_add (rib, gate);
1051 }
1052 else
1053 nexthop_ifindex_add (rib, ifindex);
1054
1055 /* If this route is kernel route, set FIB flag to the route. */
1056 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1057 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1058 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1059
1060 /* Link new rib to node.*/
1061 rib_addnode (rn, rib);
1062
1063 /* Process this route node. */
1064 rib_process (rn, same);
1065
1066 /* Free implicit route.*/
1067 if (same)
1068 newrib_free (same);
1069
1070 return 0;
1071}
1072
1073int
1074rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1075{
1076 struct route_table *table;
1077 struct route_node *rn;
1078 struct rib *same;
1079 struct nexthop *nexthop;
1080
1081 /* Lookup table. */
1082 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1083 if (! table)
1084 return 0;
1085
1086 /* Make it sure prefixlen is applied to the prefix. */
1087 apply_mask_ipv4 (p);
1088
1089 /* Set default distance by route type. */
1090 if (rib->distance == 0)
1091 {
1092 rib->distance = route_info[rib->type].distance;
1093
1094 /* iBGP distance is 200. */
1095 if (rib->type == ZEBRA_ROUTE_BGP
1096 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1097 rib->distance = 200;
1098 }
1099
1100 /* Lookup route node.*/
1101 rn = route_node_get (table, (struct prefix *) p);
1102
1103 /* If same type of route are installed, treat it as a implicit
1104 withdraw. */
1105 for (same = rn->info; same; same = same->next)
1106 {
1107 if (same->type == rib->type && same->table == rib->table
1108 && same->type != ZEBRA_ROUTE_CONNECT)
1109 {
1110 rib_delnode (rn, same);
1111 route_unlock_node (rn);
1112 break;
1113 }
1114 }
1115
1116 /* If this route is kernel route, set FIB flag to the route. */
1117 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1118 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1119 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1120
1121 /* Link new rib to node.*/
1122 rib_addnode (rn, rib);
1123
1124 /* Process this route node. */
1125 rib_process (rn, same);
1126
1127 /* Free implicit route.*/
1128 if (same)
1129 newrib_free (same);
1130
1131 return 0;
1132}
1133
1134int
1135rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1136 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1137{
1138 struct route_table *table;
1139 struct route_node *rn;
1140 struct rib *rib;
1141 struct rib *fib = NULL;
1142 struct rib *same = NULL;
1143 struct nexthop *nexthop;
1144 char buf1[BUFSIZ];
1145 char buf2[BUFSIZ];
1146
1147 /* Lookup table. */
1148 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1149 if (! table)
1150 return 0;
1151
1152 /* Apply mask. */
1153 apply_mask_ipv4 (p);
1154
paul5ec90d22003-06-19 01:41:37 +00001155 if (IS_ZEBRA_DEBUG_KERNEL && gate)
1156 zlog_info ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
1157 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1158 p->prefixlen,
1159 inet_ntoa (*gate),
1160 ifindex);
1161
paul718e3742002-12-13 20:15:29 +00001162 /* Lookup route node. */
1163 rn = route_node_lookup (table, (struct prefix *) p);
1164 if (! rn)
1165 {
1166 if (IS_ZEBRA_DEBUG_KERNEL)
1167 {
1168 if (gate)
1169 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
1170 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1171 p->prefixlen,
1172 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1173 ifindex);
1174 else
1175 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
1176 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1177 p->prefixlen,
1178 ifindex);
1179 }
1180 return ZEBRA_ERR_RTNOEXIST;
1181 }
1182
1183 /* Lookup same type route. */
1184 for (rib = rn->info; rib; rib = rib->next)
1185 {
1186 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1187 fib = rib;
1188
1189 if (rib->type == ZEBRA_ROUTE_CONNECT)
1190 {
1191 nexthop = rib->nexthop;
1192
1193 if (rib->type == type
1194 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1195 && nexthop->ifindex == ifindex)
1196 {
1197 if (rib->refcnt)
1198 {
1199 rib->refcnt--;
1200 route_unlock_node (rn);
1201 route_unlock_node (rn);
1202 return 0;
1203 }
1204 same = rib;
1205 break;
1206 }
1207 }
paul5ec90d22003-06-19 01:41:37 +00001208 else if (gate)
1209 {
1210 nexthop = rib->nexthop;
1211
1212 /* Make sure that the route found has the same gateway. */
1213 if (rib->type == type
1214 && nexthop &&
1215 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1216 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate)) )
1217 {
1218 same = rib;
1219 break;
1220 }
1221 }
paul718e3742002-12-13 20:15:29 +00001222 else
1223 {
1224 if (rib->type == type)
1225 {
1226 same = rib;
1227 break;
1228 }
1229 }
1230 }
1231
1232 /* If same type of route can't be found and this message is from
1233 kernel. */
1234 if (! same)
1235 {
1236 if (fib && type == ZEBRA_ROUTE_KERNEL)
1237 {
1238 /* Unset flags. */
1239 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1240 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1241
1242 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1243 }
1244 else
1245 {
1246 if (IS_ZEBRA_DEBUG_KERNEL)
1247 {
1248 if (gate)
1249 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
1250 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1251 p->prefixlen,
1252 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1253 ifindex,
1254 type);
1255 else
1256 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
1257 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1258 p->prefixlen,
1259 ifindex,
1260 type);
1261 }
1262 route_unlock_node (rn);
1263 return ZEBRA_ERR_RTNOEXIST;
1264 }
1265 }
1266
1267 if (same)
1268 rib_delnode (rn, same);
1269
1270 /* Process changes. */
1271 rib_process (rn, same);
1272
1273 if (same)
1274 {
1275 newrib_free (same);
1276 route_unlock_node (rn);
1277 }
1278
1279 route_unlock_node (rn);
1280
1281 return 0;
1282}
1283
1284/* Install static route into rib. */
1285void
1286static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1287{
1288 struct rib *rib;
1289 struct route_node *rn;
1290 struct route_table *table;
1291
1292 /* Lookup table. */
1293 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1294 if (! table)
1295 return;
1296
1297 /* Lookup existing route */
1298 rn = route_node_get (table, p);
1299 for (rib = rn->info; rib; rib = rib->next)
1300 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1301 break;
1302
1303 if (rib)
1304 {
1305 /* Same distance static route is there. Update it with new
1306 nexthop. */
paul718e3742002-12-13 20:15:29 +00001307 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001308 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001309 {
1310 case STATIC_IPV4_GATEWAY:
1311 nexthop_ipv4_add (rib, &si->gate.ipv4);
1312 break;
1313 case STATIC_IPV4_IFNAME:
1314 nexthop_ifname_add (rib, si->gate.ifname);
1315 break;
1316 case STATIC_IPV4_BLACKHOLE:
1317 nexthop_blackhole_add (rib);
1318 break;
1319 }
paul718e3742002-12-13 20:15:29 +00001320 rib_process (rn, NULL);
1321 }
1322 else
1323 {
1324 /* This is new static route. */
1325 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1326 memset (rib, 0, sizeof (struct rib));
1327
1328 rib->type = ZEBRA_ROUTE_STATIC;
1329 rib->distance = si->distance;
1330 rib->metric = 0;
1331 rib->nexthop_num = 0;
1332
1333 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001334 {
1335 case STATIC_IPV4_GATEWAY:
1336 nexthop_ipv4_add (rib, &si->gate.ipv4);
1337 break;
1338 case STATIC_IPV4_IFNAME:
1339 nexthop_ifname_add (rib, si->gate.ifname);
1340 break;
1341 case STATIC_IPV4_BLACKHOLE:
1342 nexthop_blackhole_add (rib);
1343 break;
1344 }
paul718e3742002-12-13 20:15:29 +00001345
hasso81dfcaa2003-05-25 19:21:25 +00001346 /* Save the flags of this static routes (reject, blackhole) */
1347 rib->flags = si->flags;
1348
paul718e3742002-12-13 20:15:29 +00001349 /* Link this rib to the tree. */
1350 rib_addnode (rn, rib);
1351
1352 /* Process this prefix. */
1353 rib_process (rn, NULL);
1354 }
1355}
1356
1357int
1358static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1359{
1360 if (nexthop->type == NEXTHOP_TYPE_IPV4
1361 && si->type == STATIC_IPV4_GATEWAY
1362 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1363 return 1;
1364 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1365 && si->type == STATIC_IPV4_IFNAME
1366 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1367 return 1;
paul595db7f2003-05-25 21:35:06 +00001368 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1369 && si->type == STATIC_IPV4_BLACKHOLE)
1370 return 1;
paul718e3742002-12-13 20:15:29 +00001371 return 0;;
1372}
1373
1374/* Uninstall static route from RIB. */
1375void
1376static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1377{
1378 struct route_node *rn;
1379 struct rib *rib;
1380 struct nexthop *nexthop;
1381 struct route_table *table;
1382
1383 /* Lookup table. */
1384 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1385 if (! table)
1386 return;
1387
1388 /* Lookup existing route with type and distance. */
1389 rn = route_node_lookup (table, p);
1390 if (! rn)
1391 return;
1392
1393 for (rib = rn->info; rib; rib = rib->next)
1394 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1395 break;
1396
1397 if (! rib)
1398 {
1399 route_unlock_node (rn);
1400 return;
1401 }
1402
1403 /* Lookup nexthop. */
1404 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1405 if (static_ipv4_nexthop_same (nexthop, si))
1406 break;
1407
1408 /* Can't find nexthop. */
1409 if (! nexthop)
1410 {
1411 route_unlock_node (rn);
1412 return;
1413 }
1414
1415 /* Check nexthop. */
1416 if (rib->nexthop_num == 1)
1417 {
1418 rib_delnode (rn, rib);
1419 rib_process (rn, rib);
1420 newrib_free (rib);
1421 route_unlock_node (rn);
1422 }
1423 else
1424 {
paul6baeb982003-10-28 03:47:15 +00001425 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1426 rib_uninstall (rn, rib);
paul718e3742002-12-13 20:15:29 +00001427 nexthop_delete (rib, nexthop);
1428 nexthop_free (nexthop);
1429 rib_process (rn, rib);
1430 }
1431
1432 /* Unlock node. */
1433 route_unlock_node (rn);
1434}
1435
1436/* Add static route into static route configuration. */
1437int
1438static_add_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001439 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001440{
1441 u_char type = 0;
1442 struct route_node *rn;
1443 struct static_ipv4 *si;
1444 struct static_ipv4 *pp;
1445 struct static_ipv4 *cp;
1446 struct static_ipv4 *update = NULL;
1447 struct route_table *stable;
1448
1449 /* Lookup table. */
1450 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1451 if (! stable)
1452 return -1;
1453
1454 /* Lookup static route prefix. */
1455 rn = route_node_get (stable, p);
1456
1457 /* Make flags. */
1458 if (gate)
1459 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001460 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001461 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001462 else
1463 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001464
1465 /* Do nothing if there is a same static route. */
1466 for (si = rn->info; si; si = si->next)
1467 {
1468 if (type == si->type
1469 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1470 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1471 {
1472 if (distance == si->distance)
1473 {
1474 route_unlock_node (rn);
1475 return 0;
1476 }
1477 else
1478 update = si;
1479 }
1480 }
1481
1482 /* Distance chaged. */
1483 if (update)
1484 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1485
1486 /* Make new static route structure. */
1487 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1488 memset (si, 0, sizeof (struct static_ipv4));
1489
1490 si->type = type;
1491 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001492 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001493
1494 if (gate)
1495 si->gate.ipv4 = *gate;
1496 if (ifname)
1497 si->gate.ifname = XSTRDUP (0, ifname);
1498
1499 /* Add new static route information to the tree with sort by
1500 distance value and gateway address. */
1501 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1502 {
1503 if (si->distance < cp->distance)
1504 break;
1505 if (si->distance > cp->distance)
1506 continue;
1507 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1508 {
1509 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1510 break;
1511 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1512 continue;
1513 }
1514 }
1515
1516 /* Make linked list. */
1517 if (pp)
1518 pp->next = si;
1519 else
1520 rn->info = si;
1521 if (cp)
1522 cp->prev = si;
1523 si->prev = pp;
1524 si->next = cp;
1525
1526 /* Install into rib. */
1527 static_install_ipv4 (p, si);
1528
1529 return 1;
1530}
1531
1532/* Delete static route from static route configuration. */
1533int
1534static_delete_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
1535 u_char distance, u_int32_t vrf_id)
1536{
1537 u_char type = 0;
1538 struct route_node *rn;
1539 struct static_ipv4 *si;
1540 struct route_table *stable;
1541
1542 /* Lookup table. */
1543 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1544 if (! stable)
1545 return -1;
1546
1547 /* Lookup static route prefix. */
1548 rn = route_node_lookup (stable, p);
1549 if (! rn)
1550 return 0;
1551
1552 /* Make flags. */
1553 if (gate)
1554 type = STATIC_IPV4_GATEWAY;
1555 else if (ifname)
1556 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001557 else
1558 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001559
1560 /* Find same static route is the tree */
1561 for (si = rn->info; si; si = si->next)
1562 if (type == si->type
1563 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1564 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1565 break;
1566
1567 /* Can't find static route. */
1568 if (! si)
1569 {
1570 route_unlock_node (rn);
1571 return 0;
1572 }
1573
1574 /* Install into rib. */
1575 static_uninstall_ipv4 (p, si);
1576
1577 /* Unlink static route from linked list. */
1578 if (si->prev)
1579 si->prev->next = si->next;
1580 else
1581 rn->info = si->next;
1582 if (si->next)
1583 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001584 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001585
1586 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001587 if (ifname)
1588 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001589 XFREE (MTYPE_STATIC_IPV4, si);
1590
paul143a3852003-09-29 20:06:13 +00001591 route_unlock_node (rn);
1592
paul718e3742002-12-13 20:15:29 +00001593 return 1;
1594}
1595
1596
1597#ifdef HAVE_IPV6
1598int
1599rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1600 struct in6_addr *gate, unsigned int ifindex, int table)
1601{
hasso726f9b22003-05-25 21:04:54 +00001602 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1603#if defined (MUSICA) || defined (LINUX)
1604 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1605 if (p->prefixlen == 96)
1606 return 0;
1607#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001608 return 1;
hasso726f9b22003-05-25 21:04:54 +00001609 }
paul718e3742002-12-13 20:15:29 +00001610 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1611 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1612 {
1613 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1614 return 1;
1615 }
1616 return 0;
1617}
1618
1619int
1620rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1621 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1622{
1623 struct rib *rib;
1624 struct rib *same = NULL;
1625 struct route_table *table;
1626 struct route_node *rn;
1627 struct nexthop *nexthop;
1628
1629 int distance;
1630 u_int32_t metric = 0;
1631
1632 /* Lookup table. */
1633 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1634 if (! table)
1635 return 0;
1636
1637 /* Make sure mask is applied. */
1638 apply_mask_ipv6 (p);
1639
1640 /* Set default distance by route type. */
1641 distance = route_info[type].distance;
1642
1643 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1644 distance = 200;
1645
1646 /* Filter bogus route. */
1647 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1648 return 0;
1649
1650 /* Lookup route node.*/
1651 rn = route_node_get (table, (struct prefix *) p);
1652
1653 /* If same type of route are installed, treat it as a implicit
1654 withdraw. */
1655 for (rib = rn->info; rib; rib = rib->next)
1656 {
1657 if (rib->type == ZEBRA_ROUTE_CONNECT)
1658 {
1659 nexthop = rib->nexthop;
1660
1661 if (rib->type == type
1662 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1663 && nexthop->ifindex == ifindex)
1664 {
1665 rib->refcnt++;
1666 return 0;
1667 }
1668 }
1669 else if (rib->type == type)
1670 {
1671 same = rib;
1672 rib_delnode (rn, same);
1673 route_unlock_node (rn);
1674 break;
1675 }
1676 }
1677
1678 /* Allocate new rib structure. */
1679 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1680 memset (rib, 0, sizeof (struct rib));
1681 rib->type = type;
1682 rib->distance = distance;
1683 rib->flags = flags;
1684 rib->metric = metric;
1685 rib->nexthop_num = 0;
1686 rib->uptime = time (NULL);
1687
1688 /* Nexthop settings. */
1689 if (gate)
1690 {
1691 if (ifindex)
1692 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1693 else
1694 nexthop_ipv6_add (rib, gate);
1695 }
1696 else
1697 nexthop_ifindex_add (rib, ifindex);
1698
1699 /* If this route is kernel route, set FIB flag to the route. */
1700 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1701 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1702 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1703
1704 /* Link new rib to node.*/
1705 rib_addnode (rn, rib);
1706
1707 /* Process this route node. */
1708 rib_process (rn, same);
1709
1710 /* Free implicit route.*/
1711 if (same)
1712 newrib_free (same);
1713
1714 return 0;
1715}
1716
1717int
1718rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1719 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1720{
1721 struct route_table *table;
1722 struct route_node *rn;
1723 struct rib *rib;
1724 struct rib *fib = NULL;
1725 struct rib *same = NULL;
1726 struct nexthop *nexthop;
1727 char buf1[BUFSIZ];
1728 char buf2[BUFSIZ];
1729
1730 /* Apply mask. */
1731 apply_mask_ipv6 (p);
1732
1733 /* Lookup table. */
1734 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1735 if (! table)
1736 return 0;
1737
1738 /* Lookup route node. */
1739 rn = route_node_lookup (table, (struct prefix *) p);
1740 if (! rn)
1741 {
1742 if (IS_ZEBRA_DEBUG_KERNEL)
1743 {
1744 if (gate)
1745 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
1746 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1747 p->prefixlen,
1748 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1749 ifindex);
1750 else
1751 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
1752 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1753 p->prefixlen,
1754 ifindex);
1755 }
1756 return ZEBRA_ERR_RTNOEXIST;
1757 }
1758
1759 /* Lookup same type route. */
1760 for (rib = rn->info; rib; rib = rib->next)
1761 {
1762 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1763 fib = rib;
1764
1765 if (rib->type == ZEBRA_ROUTE_CONNECT)
1766 {
1767 nexthop = rib->nexthop;
1768
1769 if (rib->type == type
1770 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1771 && nexthop->ifindex == ifindex)
1772 {
1773 if (rib->refcnt)
1774 {
1775 rib->refcnt--;
1776 route_unlock_node (rn);
1777 route_unlock_node (rn);
1778 return 0;
1779 }
1780 same = rib;
1781 break;
1782 }
1783 }
1784 else
1785 {
1786 if (rib->type == type)
1787 {
1788 same = rib;
1789 break;
1790 }
1791 }
1792 }
1793
1794 /* If same type of route can't be found and this message is from
1795 kernel. */
1796 if (! same)
1797 {
1798 if (fib && type == ZEBRA_ROUTE_KERNEL)
1799 {
1800 /* Unset flags. */
1801 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1802 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1803
1804 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1805 }
1806 else
1807 {
1808 if (IS_ZEBRA_DEBUG_KERNEL)
1809 {
1810 if (gate)
1811 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
1812 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1813 p->prefixlen,
1814 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1815 ifindex,
1816 type);
1817 else
1818 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
1819 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1820 p->prefixlen,
1821 ifindex,
1822 type);
1823 }
1824 route_unlock_node (rn);
1825 return ZEBRA_ERR_RTNOEXIST;
1826 }
1827 }
1828
1829 if (same)
1830 rib_delnode (rn, same);
1831
1832 /* Process changes. */
1833 rib_process (rn, same);
1834
1835 if (same)
1836 {
1837 newrib_free (same);
1838 route_unlock_node (rn);
1839 }
1840
1841 route_unlock_node (rn);
1842
1843 return 0;
1844}
1845
1846/* Install static route into rib. */
1847void
1848static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
1849{
1850 struct rib *rib;
1851 struct route_table *table;
1852 struct route_node *rn;
1853
1854 /* Lookup table. */
1855 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1856 if (! table)
1857 return;
1858
1859 /* Lookup existing route */
1860 rn = route_node_get (table, p);
1861 for (rib = rn->info; rib; rib = rib->next)
1862 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1863 break;
1864
1865 if (rib)
1866 {
1867 /* Same distance static route is there. Update it with new
1868 nexthop. */
paul718e3742002-12-13 20:15:29 +00001869 route_unlock_node (rn);
1870
1871 switch (si->type)
1872 {
1873 case STATIC_IPV6_GATEWAY:
1874 nexthop_ipv6_add (rib, &si->ipv6);
1875 break;
1876 case STATIC_IPV6_IFNAME:
1877 nexthop_ifname_add (rib, si->ifname);
1878 break;
1879 case STATIC_IPV6_GATEWAY_IFNAME:
1880 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
1881 break;
1882 }
1883 rib_process (rn, NULL);
1884 }
1885 else
1886 {
1887 /* This is new static route. */
1888 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1889 memset (rib, 0, sizeof (struct rib));
1890
1891 rib->type = ZEBRA_ROUTE_STATIC;
1892 rib->distance = si->distance;
1893 rib->metric = 0;
1894 rib->nexthop_num = 0;
1895
1896 switch (si->type)
1897 {
1898 case STATIC_IPV6_GATEWAY:
1899 nexthop_ipv6_add (rib, &si->ipv6);
1900 break;
1901 case STATIC_IPV6_IFNAME:
1902 nexthop_ifname_add (rib, si->ifname);
1903 break;
1904 case STATIC_IPV6_GATEWAY_IFNAME:
1905 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
1906 break;
1907 }
1908
hasso81dfcaa2003-05-25 19:21:25 +00001909 /* Save the flags of this static routes (reject, blackhole) */
1910 rib->flags = si->flags;
1911
paul718e3742002-12-13 20:15:29 +00001912 /* Link this rib to the tree. */
1913 rib_addnode (rn, rib);
1914
1915 /* Process this prefix. */
1916 rib_process (rn, NULL);
1917 }
1918}
1919
1920int
1921static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
1922{
1923 if (nexthop->type == NEXTHOP_TYPE_IPV6
1924 && si->type == STATIC_IPV6_GATEWAY
1925 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
1926 return 1;
1927 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1928 && si->type == STATIC_IPV6_IFNAME
1929 && strcmp (nexthop->ifname, si->ifname) == 0)
1930 return 1;
1931 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1932 && si->type == STATIC_IPV6_GATEWAY_IFNAME
1933 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
1934 && strcmp (nexthop->ifname, si->ifname) == 0)
1935 return 1;
1936 return 0;;
1937}
1938
1939void
1940static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
1941{
1942 struct route_table *table;
1943 struct route_node *rn;
1944 struct rib *rib;
1945 struct nexthop *nexthop;
1946
1947 /* Lookup table. */
1948 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1949 if (! table)
1950 return;
1951
1952 /* Lookup existing route with type and distance. */
1953 rn = route_node_lookup (table, (struct prefix *) p);
1954 if (! rn)
1955 return;
1956
1957 for (rib = rn->info; rib; rib = rib->next)
1958 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1959 break;
1960 if (! rib)
1961 {
1962 route_unlock_node (rn);
1963 return;
1964 }
1965
1966 /* Lookup nexthop. */
1967 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1968 if (static_ipv6_nexthop_same (nexthop, si))
1969 break;
1970
1971 /* Can't find nexthop. */
1972 if (! nexthop)
1973 {
1974 route_unlock_node (rn);
1975 return;
1976 }
1977
1978 /* Check nexthop. */
1979 if (rib->nexthop_num == 1)
1980 {
1981 rib_delnode (rn, rib);
1982 rib_process (rn, rib);
1983 newrib_free (rib);
1984 route_unlock_node (rn);
1985 }
1986 else
1987 {
paul6baeb982003-10-28 03:47:15 +00001988 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1989 rib_uninstall (rn, rib);
paul718e3742002-12-13 20:15:29 +00001990 nexthop_delete (rib, nexthop);
1991 nexthop_free (nexthop);
1992 rib_process (rn, rib);
1993 }
1994
1995 /* Unlock node. */
1996 route_unlock_node (rn);
1997}
1998
1999/* Add static route into static route configuration. */
2000int
2001static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso81dfcaa2003-05-25 19:21:25 +00002002 char *ifname, u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002003{
2004 struct route_node *rn;
2005 struct static_ipv6 *si;
2006 struct static_ipv6 *pp;
2007 struct static_ipv6 *cp;
2008 struct route_table *stable;
2009
2010 /* Lookup table. */
2011 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2012 if (! stable)
2013 return -1;
2014
2015 /* Lookup static route prefix. */
2016 rn = route_node_get (stable, p);
2017
2018 /* Do nothing if there is a same static route. */
2019 for (si = rn->info; si; si = si->next)
2020 {
2021 if (distance == si->distance
2022 && type == si->type
2023 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2024 && (! ifname || strcmp (ifname, si->ifname) == 0))
2025 {
2026 route_unlock_node (rn);
2027 return 0;
2028 }
2029 }
2030
2031 /* Make new static route structure. */
2032 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2033 memset (si, 0, sizeof (struct static_ipv6));
2034
2035 si->type = type;
2036 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002037 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002038
2039 switch (type)
2040 {
2041 case STATIC_IPV6_GATEWAY:
2042 si->ipv6 = *gate;
2043 break;
2044 case STATIC_IPV6_IFNAME:
2045 si->ifname = XSTRDUP (0, ifname);
2046 break;
2047 case STATIC_IPV6_GATEWAY_IFNAME:
2048 si->ipv6 = *gate;
2049 si->ifname = XSTRDUP (0, ifname);
2050 break;
2051 }
2052
2053 /* Add new static route information to the tree with sort by
2054 distance value and gateway address. */
2055 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2056 {
2057 if (si->distance < cp->distance)
2058 break;
2059 if (si->distance > cp->distance)
2060 continue;
2061 }
2062
2063 /* Make linked list. */
2064 if (pp)
2065 pp->next = si;
2066 else
2067 rn->info = si;
2068 if (cp)
2069 cp->prev = si;
2070 si->prev = pp;
2071 si->next = cp;
2072
2073 /* Install into rib. */
2074 static_install_ipv6 (p, si);
2075
2076 return 1;
2077}
2078
2079/* Delete static route from static route configuration. */
2080int
2081static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
2082 char *ifname, u_char distance, u_int32_t vrf_id)
2083{
2084 struct route_node *rn;
2085 struct static_ipv6 *si;
2086 struct route_table *stable;
2087
2088 /* Lookup table. */
2089 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2090 if (! stable)
2091 return -1;
2092
2093 /* Lookup static route prefix. */
2094 rn = route_node_lookup (stable, p);
2095 if (! rn)
2096 return 0;
2097
2098 /* Find same static route is the tree */
2099 for (si = rn->info; si; si = si->next)
2100 if (distance == si->distance
2101 && type == si->type
2102 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2103 && (! ifname || strcmp (ifname, si->ifname) == 0))
2104 break;
2105
2106 /* Can't find static route. */
2107 if (! si)
2108 {
2109 route_unlock_node (rn);
2110 return 0;
2111 }
2112
2113 /* Install into rib. */
2114 static_uninstall_ipv6 (p, si);
2115
2116 /* Unlink static route from linked list. */
2117 if (si->prev)
2118 si->prev->next = si->next;
2119 else
2120 rn->info = si->next;
2121 if (si->next)
2122 si->next->prev = si->prev;
2123
2124 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002125 if (ifname)
2126 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002127 XFREE (MTYPE_STATIC_IPV6, si);
2128
2129 return 1;
2130}
2131#endif /* HAVE_IPV6 */
2132
2133/* RIB update function. */
2134void
2135rib_update ()
2136{
2137 struct route_node *rn;
2138 struct route_table *table;
2139
2140 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2141 if (table)
2142 for (rn = route_top (table); rn; rn = route_next (rn))
2143 rib_process (rn, NULL);
2144
2145 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2146 if (table)
2147 for (rn = route_top (table); rn; rn = route_next (rn))
2148 rib_process (rn, NULL);
2149}
2150
2151/* Interface goes up. */
2152void
2153rib_if_up (struct interface *ifp)
2154{
2155 rib_update ();
2156}
2157
2158/* Interface goes down. */
2159void
2160rib_if_down (struct interface *ifp)
2161{
2162 rib_update ();
2163}
2164
2165/* Remove all routes which comes from non main table. */
2166void
2167rib_weed_table (struct route_table *table)
2168{
2169 struct route_node *rn;
2170 struct rib *rib;
2171 struct rib *next;
2172
2173 if (table)
2174 for (rn = route_top (table); rn; rn = route_next (rn))
2175 for (rib = rn->info; rib; rib = next)
2176 {
2177 next = rib->next;
2178
paulb21b19c2003-06-15 01:28:29 +00002179 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002180 rib->table != RT_TABLE_MAIN)
2181 {
2182 rib_delnode (rn, rib);
2183 newrib_free (rib);
2184 route_unlock_node (rn);
2185 }
2186 }
2187}
2188
2189/* Delete all routes from non main table. */
2190void
2191rib_weed_tables ()
2192{
2193 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2194 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2195}
2196
2197/* Delete self installed routes after zebra is relaunched. */
2198void
2199rib_sweep_table (struct route_table *table)
2200{
2201 struct route_node *rn;
2202 struct rib *rib;
2203 struct rib *next;
2204 int ret = 0;
2205
2206 if (table)
2207 for (rn = route_top (table); rn; rn = route_next (rn))
2208 for (rib = rn->info; rib; rib = next)
2209 {
2210 next = rib->next;
2211
2212 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2213 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2214 {
2215 ret = rib_uninstall_kernel (rn, rib);
2216 if (! ret)
2217 {
2218 rib_delnode (rn, rib);
2219 newrib_free (rib);
2220 route_unlock_node (rn);
2221 }
2222 }
2223 }
2224}
2225
2226/* Sweep all RIB tables. */
2227void
2228rib_sweep_route ()
2229{
2230 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2231 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2232}
2233
2234/* Close RIB and clean up kernel routes. */
2235void
2236rib_close_table (struct route_table *table)
2237{
2238 struct route_node *rn;
2239 struct rib *rib;
2240
2241 if (table)
2242 for (rn = route_top (table); rn; rn = route_next (rn))
2243 for (rib = rn->info; rib; rib = rib->next)
2244 if (! RIB_SYSTEM_ROUTE (rib)
2245 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2246 rib_uninstall_kernel (rn, rib);
2247}
2248
2249/* Close all RIB tables. */
2250void
2251rib_close ()
2252{
2253 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2254 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2255}
2256
2257/* Routing information base initialize. */
2258void
2259rib_init ()
2260{
2261 /* VRF initialization. */
2262 vrf_init ();
2263}