blob: 16102e54e70f36228638d9a51691d75a98356b03 [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;
paulb5f45022003-11-02 07:28:05 +00001041 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001042 rib->nexthop_num = 0;
1043 rib->uptime = time (NULL);
1044
1045 /* Nexthop settings. */
1046 if (gate)
1047 {
1048 if (ifindex)
1049 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
1050 else
1051 nexthop_ipv4_add (rib, gate);
1052 }
1053 else
1054 nexthop_ifindex_add (rib, ifindex);
1055
1056 /* If this route is kernel route, set FIB flag to the route. */
1057 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1058 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1059 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1060
1061 /* Link new rib to node.*/
1062 rib_addnode (rn, rib);
1063
1064 /* Process this route node. */
1065 rib_process (rn, same);
1066
1067 /* Free implicit route.*/
1068 if (same)
1069 newrib_free (same);
1070
1071 return 0;
1072}
1073
1074int
1075rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1076{
1077 struct route_table *table;
1078 struct route_node *rn;
1079 struct rib *same;
1080 struct nexthop *nexthop;
1081
1082 /* Lookup table. */
1083 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1084 if (! table)
1085 return 0;
1086
1087 /* Make it sure prefixlen is applied to the prefix. */
1088 apply_mask_ipv4 (p);
1089
1090 /* Set default distance by route type. */
1091 if (rib->distance == 0)
1092 {
1093 rib->distance = route_info[rib->type].distance;
1094
1095 /* iBGP distance is 200. */
1096 if (rib->type == ZEBRA_ROUTE_BGP
1097 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1098 rib->distance = 200;
1099 }
1100
1101 /* Lookup route node.*/
1102 rn = route_node_get (table, (struct prefix *) p);
1103
1104 /* If same type of route are installed, treat it as a implicit
1105 withdraw. */
1106 for (same = rn->info; same; same = same->next)
1107 {
1108 if (same->type == rib->type && same->table == rib->table
1109 && same->type != ZEBRA_ROUTE_CONNECT)
1110 {
1111 rib_delnode (rn, same);
1112 route_unlock_node (rn);
1113 break;
1114 }
1115 }
1116
1117 /* If this route is kernel route, set FIB flag to the route. */
1118 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1119 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1120 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1121
1122 /* Link new rib to node.*/
1123 rib_addnode (rn, rib);
1124
1125 /* Process this route node. */
1126 rib_process (rn, same);
1127
1128 /* Free implicit route.*/
1129 if (same)
1130 newrib_free (same);
1131
1132 return 0;
1133}
1134
1135int
1136rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1137 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1138{
1139 struct route_table *table;
1140 struct route_node *rn;
1141 struct rib *rib;
1142 struct rib *fib = NULL;
1143 struct rib *same = NULL;
1144 struct nexthop *nexthop;
1145 char buf1[BUFSIZ];
1146 char buf2[BUFSIZ];
1147
1148 /* Lookup table. */
1149 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1150 if (! table)
1151 return 0;
1152
1153 /* Apply mask. */
1154 apply_mask_ipv4 (p);
1155
paul5ec90d22003-06-19 01:41:37 +00001156 if (IS_ZEBRA_DEBUG_KERNEL && gate)
1157 zlog_info ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
1158 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1159 p->prefixlen,
1160 inet_ntoa (*gate),
1161 ifindex);
1162
paul718e3742002-12-13 20:15:29 +00001163 /* Lookup route node. */
1164 rn = route_node_lookup (table, (struct prefix *) p);
1165 if (! rn)
1166 {
1167 if (IS_ZEBRA_DEBUG_KERNEL)
1168 {
1169 if (gate)
1170 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
1171 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1172 p->prefixlen,
1173 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1174 ifindex);
1175 else
1176 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
1177 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1178 p->prefixlen,
1179 ifindex);
1180 }
1181 return ZEBRA_ERR_RTNOEXIST;
1182 }
1183
1184 /* Lookup same type route. */
1185 for (rib = rn->info; rib; rib = rib->next)
1186 {
1187 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1188 fib = rib;
1189
1190 if (rib->type == ZEBRA_ROUTE_CONNECT)
1191 {
1192 nexthop = rib->nexthop;
1193
1194 if (rib->type == type
1195 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1196 && nexthop->ifindex == ifindex)
1197 {
1198 if (rib->refcnt)
1199 {
1200 rib->refcnt--;
1201 route_unlock_node (rn);
1202 route_unlock_node (rn);
1203 return 0;
1204 }
1205 same = rib;
1206 break;
1207 }
1208 }
paul5ec90d22003-06-19 01:41:37 +00001209 else if (gate)
1210 {
1211 nexthop = rib->nexthop;
1212
1213 /* Make sure that the route found has the same gateway. */
1214 if (rib->type == type
1215 && nexthop &&
1216 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1217 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate)) )
1218 {
1219 same = rib;
1220 break;
1221 }
1222 }
paul718e3742002-12-13 20:15:29 +00001223 else
1224 {
1225 if (rib->type == type)
1226 {
1227 same = rib;
1228 break;
1229 }
1230 }
1231 }
1232
1233 /* If same type of route can't be found and this message is from
1234 kernel. */
1235 if (! same)
1236 {
1237 if (fib && type == ZEBRA_ROUTE_KERNEL)
1238 {
1239 /* Unset flags. */
1240 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1241 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1242
1243 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1244 }
1245 else
1246 {
1247 if (IS_ZEBRA_DEBUG_KERNEL)
1248 {
1249 if (gate)
1250 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
1251 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1252 p->prefixlen,
1253 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1254 ifindex,
1255 type);
1256 else
1257 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
1258 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1259 p->prefixlen,
1260 ifindex,
1261 type);
1262 }
1263 route_unlock_node (rn);
1264 return ZEBRA_ERR_RTNOEXIST;
1265 }
1266 }
1267
1268 if (same)
1269 rib_delnode (rn, same);
1270
1271 /* Process changes. */
1272 rib_process (rn, same);
1273
1274 if (same)
1275 {
1276 newrib_free (same);
1277 route_unlock_node (rn);
1278 }
1279
1280 route_unlock_node (rn);
1281
1282 return 0;
1283}
1284
1285/* Install static route into rib. */
1286void
1287static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1288{
1289 struct rib *rib;
1290 struct route_node *rn;
1291 struct route_table *table;
1292
1293 /* Lookup table. */
1294 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1295 if (! table)
1296 return;
1297
1298 /* Lookup existing route */
1299 rn = route_node_get (table, p);
1300 for (rib = rn->info; rib; rib = rib->next)
1301 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1302 break;
1303
1304 if (rib)
1305 {
1306 /* Same distance static route is there. Update it with new
1307 nexthop. */
paul718e3742002-12-13 20:15:29 +00001308 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001309 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001310 {
1311 case STATIC_IPV4_GATEWAY:
1312 nexthop_ipv4_add (rib, &si->gate.ipv4);
1313 break;
1314 case STATIC_IPV4_IFNAME:
1315 nexthop_ifname_add (rib, si->gate.ifname);
1316 break;
1317 case STATIC_IPV4_BLACKHOLE:
1318 nexthop_blackhole_add (rib);
1319 break;
1320 }
paul718e3742002-12-13 20:15:29 +00001321 rib_process (rn, NULL);
1322 }
1323 else
1324 {
1325 /* This is new static route. */
1326 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1327 memset (rib, 0, sizeof (struct rib));
1328
1329 rib->type = ZEBRA_ROUTE_STATIC;
1330 rib->distance = si->distance;
1331 rib->metric = 0;
1332 rib->nexthop_num = 0;
1333
1334 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001335 {
1336 case STATIC_IPV4_GATEWAY:
1337 nexthop_ipv4_add (rib, &si->gate.ipv4);
1338 break;
1339 case STATIC_IPV4_IFNAME:
1340 nexthop_ifname_add (rib, si->gate.ifname);
1341 break;
1342 case STATIC_IPV4_BLACKHOLE:
1343 nexthop_blackhole_add (rib);
1344 break;
1345 }
paul718e3742002-12-13 20:15:29 +00001346
hasso81dfcaa2003-05-25 19:21:25 +00001347 /* Save the flags of this static routes (reject, blackhole) */
1348 rib->flags = si->flags;
1349
paul718e3742002-12-13 20:15:29 +00001350 /* Link this rib to the tree. */
1351 rib_addnode (rn, rib);
1352
1353 /* Process this prefix. */
1354 rib_process (rn, NULL);
1355 }
1356}
1357
1358int
1359static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1360{
1361 if (nexthop->type == NEXTHOP_TYPE_IPV4
1362 && si->type == STATIC_IPV4_GATEWAY
1363 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1364 return 1;
1365 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1366 && si->type == STATIC_IPV4_IFNAME
1367 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1368 return 1;
paul595db7f2003-05-25 21:35:06 +00001369 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1370 && si->type == STATIC_IPV4_BLACKHOLE)
1371 return 1;
paul718e3742002-12-13 20:15:29 +00001372 return 0;;
1373}
1374
1375/* Uninstall static route from RIB. */
1376void
1377static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1378{
1379 struct route_node *rn;
1380 struct rib *rib;
1381 struct nexthop *nexthop;
1382 struct route_table *table;
1383
1384 /* Lookup table. */
1385 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1386 if (! table)
1387 return;
1388
1389 /* Lookup existing route with type and distance. */
1390 rn = route_node_lookup (table, p);
1391 if (! rn)
1392 return;
1393
1394 for (rib = rn->info; rib; rib = rib->next)
1395 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1396 break;
1397
1398 if (! rib)
1399 {
1400 route_unlock_node (rn);
1401 return;
1402 }
1403
1404 /* Lookup nexthop. */
1405 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1406 if (static_ipv4_nexthop_same (nexthop, si))
1407 break;
1408
1409 /* Can't find nexthop. */
1410 if (! nexthop)
1411 {
1412 route_unlock_node (rn);
1413 return;
1414 }
1415
1416 /* Check nexthop. */
1417 if (rib->nexthop_num == 1)
1418 {
1419 rib_delnode (rn, rib);
1420 rib_process (rn, rib);
1421 newrib_free (rib);
1422 route_unlock_node (rn);
1423 }
1424 else
1425 {
paul6baeb982003-10-28 03:47:15 +00001426 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1427 rib_uninstall (rn, rib);
paul718e3742002-12-13 20:15:29 +00001428 nexthop_delete (rib, nexthop);
1429 nexthop_free (nexthop);
1430 rib_process (rn, rib);
1431 }
1432
1433 /* Unlock node. */
1434 route_unlock_node (rn);
1435}
1436
1437/* Add static route into static route configuration. */
1438int
1439static_add_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001440 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001441{
1442 u_char type = 0;
1443 struct route_node *rn;
1444 struct static_ipv4 *si;
1445 struct static_ipv4 *pp;
1446 struct static_ipv4 *cp;
1447 struct static_ipv4 *update = NULL;
1448 struct route_table *stable;
1449
1450 /* Lookup table. */
1451 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1452 if (! stable)
1453 return -1;
1454
1455 /* Lookup static route prefix. */
1456 rn = route_node_get (stable, p);
1457
1458 /* Make flags. */
1459 if (gate)
1460 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001461 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001462 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001463 else
1464 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001465
1466 /* Do nothing if there is a same static route. */
1467 for (si = rn->info; si; si = si->next)
1468 {
1469 if (type == si->type
1470 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1471 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1472 {
1473 if (distance == si->distance)
1474 {
1475 route_unlock_node (rn);
1476 return 0;
1477 }
1478 else
1479 update = si;
1480 }
1481 }
1482
1483 /* Distance chaged. */
1484 if (update)
1485 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1486
1487 /* Make new static route structure. */
1488 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1489 memset (si, 0, sizeof (struct static_ipv4));
1490
1491 si->type = type;
1492 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001493 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001494
1495 if (gate)
1496 si->gate.ipv4 = *gate;
1497 if (ifname)
1498 si->gate.ifname = XSTRDUP (0, ifname);
1499
1500 /* Add new static route information to the tree with sort by
1501 distance value and gateway address. */
1502 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1503 {
1504 if (si->distance < cp->distance)
1505 break;
1506 if (si->distance > cp->distance)
1507 continue;
1508 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1509 {
1510 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1511 break;
1512 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1513 continue;
1514 }
1515 }
1516
1517 /* Make linked list. */
1518 if (pp)
1519 pp->next = si;
1520 else
1521 rn->info = si;
1522 if (cp)
1523 cp->prev = si;
1524 si->prev = pp;
1525 si->next = cp;
1526
1527 /* Install into rib. */
1528 static_install_ipv4 (p, si);
1529
1530 return 1;
1531}
1532
1533/* Delete static route from static route configuration. */
1534int
1535static_delete_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname,
1536 u_char distance, u_int32_t vrf_id)
1537{
1538 u_char type = 0;
1539 struct route_node *rn;
1540 struct static_ipv4 *si;
1541 struct route_table *stable;
1542
1543 /* Lookup table. */
1544 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1545 if (! stable)
1546 return -1;
1547
1548 /* Lookup static route prefix. */
1549 rn = route_node_lookup (stable, p);
1550 if (! rn)
1551 return 0;
1552
1553 /* Make flags. */
1554 if (gate)
1555 type = STATIC_IPV4_GATEWAY;
1556 else if (ifname)
1557 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001558 else
1559 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001560
1561 /* Find same static route is the tree */
1562 for (si = rn->info; si; si = si->next)
1563 if (type == si->type
1564 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1565 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1566 break;
1567
1568 /* Can't find static route. */
1569 if (! si)
1570 {
1571 route_unlock_node (rn);
1572 return 0;
1573 }
1574
1575 /* Install into rib. */
1576 static_uninstall_ipv4 (p, si);
1577
1578 /* Unlink static route from linked list. */
1579 if (si->prev)
1580 si->prev->next = si->next;
1581 else
1582 rn->info = si->next;
1583 if (si->next)
1584 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001585 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001586
1587 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001588 if (ifname)
1589 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001590 XFREE (MTYPE_STATIC_IPV4, si);
1591
paul143a3852003-09-29 20:06:13 +00001592 route_unlock_node (rn);
1593
paul718e3742002-12-13 20:15:29 +00001594 return 1;
1595}
1596
1597
1598#ifdef HAVE_IPV6
1599int
1600rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1601 struct in6_addr *gate, unsigned int ifindex, int table)
1602{
hasso726f9b22003-05-25 21:04:54 +00001603 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1604#if defined (MUSICA) || defined (LINUX)
1605 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1606 if (p->prefixlen == 96)
1607 return 0;
1608#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001609 return 1;
hasso726f9b22003-05-25 21:04:54 +00001610 }
paul718e3742002-12-13 20:15:29 +00001611 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1612 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1613 {
1614 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1615 return 1;
1616 }
1617 return 0;
1618}
1619
1620int
1621rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1622 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1623{
1624 struct rib *rib;
1625 struct rib *same = NULL;
1626 struct route_table *table;
1627 struct route_node *rn;
1628 struct nexthop *nexthop;
1629
1630 int distance;
1631 u_int32_t metric = 0;
1632
1633 /* Lookup table. */
1634 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1635 if (! table)
1636 return 0;
1637
1638 /* Make sure mask is applied. */
1639 apply_mask_ipv6 (p);
1640
1641 /* Set default distance by route type. */
1642 distance = route_info[type].distance;
1643
1644 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1645 distance = 200;
1646
1647 /* Filter bogus route. */
1648 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1649 return 0;
1650
1651 /* Lookup route node.*/
1652 rn = route_node_get (table, (struct prefix *) p);
1653
1654 /* If same type of route are installed, treat it as a implicit
1655 withdraw. */
1656 for (rib = rn->info; rib; rib = rib->next)
1657 {
1658 if (rib->type == ZEBRA_ROUTE_CONNECT)
1659 {
1660 nexthop = rib->nexthop;
1661
1662 if (rib->type == type
1663 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1664 && nexthop->ifindex == ifindex)
1665 {
1666 rib->refcnt++;
1667 return 0;
1668 }
1669 }
1670 else if (rib->type == type)
1671 {
1672 same = rib;
1673 rib_delnode (rn, same);
1674 route_unlock_node (rn);
1675 break;
1676 }
1677 }
1678
1679 /* Allocate new rib structure. */
1680 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1681 memset (rib, 0, sizeof (struct rib));
1682 rib->type = type;
1683 rib->distance = distance;
1684 rib->flags = flags;
1685 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001686 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001687 rib->nexthop_num = 0;
1688 rib->uptime = time (NULL);
1689
1690 /* Nexthop settings. */
1691 if (gate)
1692 {
1693 if (ifindex)
1694 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1695 else
1696 nexthop_ipv6_add (rib, gate);
1697 }
1698 else
1699 nexthop_ifindex_add (rib, ifindex);
1700
1701 /* If this route is kernel route, set FIB flag to the route. */
1702 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1703 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1704 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1705
1706 /* Link new rib to node.*/
1707 rib_addnode (rn, rib);
1708
1709 /* Process this route node. */
1710 rib_process (rn, same);
1711
1712 /* Free implicit route.*/
1713 if (same)
1714 newrib_free (same);
1715
1716 return 0;
1717}
1718
1719int
1720rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1721 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1722{
1723 struct route_table *table;
1724 struct route_node *rn;
1725 struct rib *rib;
1726 struct rib *fib = NULL;
1727 struct rib *same = NULL;
1728 struct nexthop *nexthop;
1729 char buf1[BUFSIZ];
1730 char buf2[BUFSIZ];
1731
1732 /* Apply mask. */
1733 apply_mask_ipv6 (p);
1734
1735 /* Lookup table. */
1736 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1737 if (! table)
1738 return 0;
1739
1740 /* Lookup route node. */
1741 rn = route_node_lookup (table, (struct prefix *) p);
1742 if (! rn)
1743 {
1744 if (IS_ZEBRA_DEBUG_KERNEL)
1745 {
1746 if (gate)
1747 zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
1748 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1749 p->prefixlen,
1750 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1751 ifindex);
1752 else
1753 zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
1754 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1755 p->prefixlen,
1756 ifindex);
1757 }
1758 return ZEBRA_ERR_RTNOEXIST;
1759 }
1760
1761 /* Lookup same type route. */
1762 for (rib = rn->info; rib; rib = rib->next)
1763 {
1764 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1765 fib = rib;
1766
1767 if (rib->type == ZEBRA_ROUTE_CONNECT)
1768 {
1769 nexthop = rib->nexthop;
1770
1771 if (rib->type == type
1772 && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
1773 && nexthop->ifindex == ifindex)
1774 {
1775 if (rib->refcnt)
1776 {
1777 rib->refcnt--;
1778 route_unlock_node (rn);
1779 route_unlock_node (rn);
1780 return 0;
1781 }
1782 same = rib;
1783 break;
1784 }
1785 }
1786 else
1787 {
1788 if (rib->type == type)
1789 {
1790 same = rib;
1791 break;
1792 }
1793 }
1794 }
1795
1796 /* If same type of route can't be found and this message is from
1797 kernel. */
1798 if (! same)
1799 {
1800 if (fib && type == ZEBRA_ROUTE_KERNEL)
1801 {
1802 /* Unset flags. */
1803 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1804 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1805
1806 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1807 }
1808 else
1809 {
1810 if (IS_ZEBRA_DEBUG_KERNEL)
1811 {
1812 if (gate)
1813 zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
1814 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1815 p->prefixlen,
1816 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1817 ifindex,
1818 type);
1819 else
1820 zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
1821 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1822 p->prefixlen,
1823 ifindex,
1824 type);
1825 }
1826 route_unlock_node (rn);
1827 return ZEBRA_ERR_RTNOEXIST;
1828 }
1829 }
1830
1831 if (same)
1832 rib_delnode (rn, same);
1833
1834 /* Process changes. */
1835 rib_process (rn, same);
1836
1837 if (same)
1838 {
1839 newrib_free (same);
1840 route_unlock_node (rn);
1841 }
1842
1843 route_unlock_node (rn);
1844
1845 return 0;
1846}
1847
1848/* Install static route into rib. */
1849void
1850static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
1851{
1852 struct rib *rib;
1853 struct route_table *table;
1854 struct route_node *rn;
1855
1856 /* Lookup table. */
1857 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1858 if (! table)
1859 return;
1860
1861 /* Lookup existing route */
1862 rn = route_node_get (table, p);
1863 for (rib = rn->info; rib; rib = rib->next)
1864 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1865 break;
1866
1867 if (rib)
1868 {
1869 /* Same distance static route is there. Update it with new
1870 nexthop. */
paul718e3742002-12-13 20:15:29 +00001871 route_unlock_node (rn);
1872
1873 switch (si->type)
1874 {
1875 case STATIC_IPV6_GATEWAY:
1876 nexthop_ipv6_add (rib, &si->ipv6);
1877 break;
1878 case STATIC_IPV6_IFNAME:
1879 nexthop_ifname_add (rib, si->ifname);
1880 break;
1881 case STATIC_IPV6_GATEWAY_IFNAME:
1882 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
1883 break;
1884 }
1885 rib_process (rn, NULL);
1886 }
1887 else
1888 {
1889 /* This is new static route. */
1890 rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
1891 memset (rib, 0, sizeof (struct rib));
1892
1893 rib->type = ZEBRA_ROUTE_STATIC;
1894 rib->distance = si->distance;
1895 rib->metric = 0;
1896 rib->nexthop_num = 0;
1897
1898 switch (si->type)
1899 {
1900 case STATIC_IPV6_GATEWAY:
1901 nexthop_ipv6_add (rib, &si->ipv6);
1902 break;
1903 case STATIC_IPV6_IFNAME:
1904 nexthop_ifname_add (rib, si->ifname);
1905 break;
1906 case STATIC_IPV6_GATEWAY_IFNAME:
1907 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
1908 break;
1909 }
1910
hasso81dfcaa2003-05-25 19:21:25 +00001911 /* Save the flags of this static routes (reject, blackhole) */
1912 rib->flags = si->flags;
1913
paul718e3742002-12-13 20:15:29 +00001914 /* Link this rib to the tree. */
1915 rib_addnode (rn, rib);
1916
1917 /* Process this prefix. */
1918 rib_process (rn, NULL);
1919 }
1920}
1921
1922int
1923static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
1924{
1925 if (nexthop->type == NEXTHOP_TYPE_IPV6
1926 && si->type == STATIC_IPV6_GATEWAY
1927 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
1928 return 1;
1929 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1930 && si->type == STATIC_IPV6_IFNAME
1931 && strcmp (nexthop->ifname, si->ifname) == 0)
1932 return 1;
1933 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1934 && si->type == STATIC_IPV6_GATEWAY_IFNAME
1935 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
1936 && strcmp (nexthop->ifname, si->ifname) == 0)
1937 return 1;
1938 return 0;;
1939}
1940
1941void
1942static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
1943{
1944 struct route_table *table;
1945 struct route_node *rn;
1946 struct rib *rib;
1947 struct nexthop *nexthop;
1948
1949 /* Lookup table. */
1950 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1951 if (! table)
1952 return;
1953
1954 /* Lookup existing route with type and distance. */
1955 rn = route_node_lookup (table, (struct prefix *) p);
1956 if (! rn)
1957 return;
1958
1959 for (rib = rn->info; rib; rib = rib->next)
1960 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1961 break;
1962 if (! rib)
1963 {
1964 route_unlock_node (rn);
1965 return;
1966 }
1967
1968 /* Lookup nexthop. */
1969 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1970 if (static_ipv6_nexthop_same (nexthop, si))
1971 break;
1972
1973 /* Can't find nexthop. */
1974 if (! nexthop)
1975 {
1976 route_unlock_node (rn);
1977 return;
1978 }
1979
1980 /* Check nexthop. */
1981 if (rib->nexthop_num == 1)
1982 {
1983 rib_delnode (rn, rib);
1984 rib_process (rn, rib);
1985 newrib_free (rib);
1986 route_unlock_node (rn);
1987 }
1988 else
1989 {
paul6baeb982003-10-28 03:47:15 +00001990 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1991 rib_uninstall (rn, rib);
paul718e3742002-12-13 20:15:29 +00001992 nexthop_delete (rib, nexthop);
1993 nexthop_free (nexthop);
1994 rib_process (rn, rib);
1995 }
1996
1997 /* Unlock node. */
1998 route_unlock_node (rn);
1999}
2000
2001/* Add static route into static route configuration. */
2002int
2003static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso81dfcaa2003-05-25 19:21:25 +00002004 char *ifname, u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002005{
2006 struct route_node *rn;
2007 struct static_ipv6 *si;
2008 struct static_ipv6 *pp;
2009 struct static_ipv6 *cp;
2010 struct route_table *stable;
2011
2012 /* Lookup table. */
2013 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2014 if (! stable)
2015 return -1;
2016
2017 /* Lookup static route prefix. */
2018 rn = route_node_get (stable, p);
2019
2020 /* Do nothing if there is a same static route. */
2021 for (si = rn->info; si; si = si->next)
2022 {
2023 if (distance == si->distance
2024 && type == si->type
2025 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2026 && (! ifname || strcmp (ifname, si->ifname) == 0))
2027 {
2028 route_unlock_node (rn);
2029 return 0;
2030 }
2031 }
2032
2033 /* Make new static route structure. */
2034 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2035 memset (si, 0, sizeof (struct static_ipv6));
2036
2037 si->type = type;
2038 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002039 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002040
2041 switch (type)
2042 {
2043 case STATIC_IPV6_GATEWAY:
2044 si->ipv6 = *gate;
2045 break;
2046 case STATIC_IPV6_IFNAME:
2047 si->ifname = XSTRDUP (0, ifname);
2048 break;
2049 case STATIC_IPV6_GATEWAY_IFNAME:
2050 si->ipv6 = *gate;
2051 si->ifname = XSTRDUP (0, ifname);
2052 break;
2053 }
2054
2055 /* Add new static route information to the tree with sort by
2056 distance value and gateway address. */
2057 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2058 {
2059 if (si->distance < cp->distance)
2060 break;
2061 if (si->distance > cp->distance)
2062 continue;
2063 }
2064
2065 /* Make linked list. */
2066 if (pp)
2067 pp->next = si;
2068 else
2069 rn->info = si;
2070 if (cp)
2071 cp->prev = si;
2072 si->prev = pp;
2073 si->next = cp;
2074
2075 /* Install into rib. */
2076 static_install_ipv6 (p, si);
2077
2078 return 1;
2079}
2080
2081/* Delete static route from static route configuration. */
2082int
2083static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
2084 char *ifname, u_char distance, u_int32_t vrf_id)
2085{
2086 struct route_node *rn;
2087 struct static_ipv6 *si;
2088 struct route_table *stable;
2089
2090 /* Lookup table. */
2091 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2092 if (! stable)
2093 return -1;
2094
2095 /* Lookup static route prefix. */
2096 rn = route_node_lookup (stable, p);
2097 if (! rn)
2098 return 0;
2099
2100 /* Find same static route is the tree */
2101 for (si = rn->info; si; si = si->next)
2102 if (distance == si->distance
2103 && type == si->type
2104 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2105 && (! ifname || strcmp (ifname, si->ifname) == 0))
2106 break;
2107
2108 /* Can't find static route. */
2109 if (! si)
2110 {
2111 route_unlock_node (rn);
2112 return 0;
2113 }
2114
2115 /* Install into rib. */
2116 static_uninstall_ipv6 (p, si);
2117
2118 /* Unlink static route from linked list. */
2119 if (si->prev)
2120 si->prev->next = si->next;
2121 else
2122 rn->info = si->next;
2123 if (si->next)
2124 si->next->prev = si->prev;
2125
2126 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002127 if (ifname)
2128 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002129 XFREE (MTYPE_STATIC_IPV6, si);
2130
2131 return 1;
2132}
2133#endif /* HAVE_IPV6 */
2134
2135/* RIB update function. */
2136void
2137rib_update ()
2138{
2139 struct route_node *rn;
2140 struct route_table *table;
2141
2142 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2143 if (table)
2144 for (rn = route_top (table); rn; rn = route_next (rn))
2145 rib_process (rn, NULL);
2146
2147 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2148 if (table)
2149 for (rn = route_top (table); rn; rn = route_next (rn))
2150 rib_process (rn, NULL);
2151}
2152
2153/* Interface goes up. */
2154void
2155rib_if_up (struct interface *ifp)
2156{
2157 rib_update ();
2158}
2159
2160/* Interface goes down. */
2161void
2162rib_if_down (struct interface *ifp)
2163{
2164 rib_update ();
2165}
2166
2167/* Remove all routes which comes from non main table. */
2168void
2169rib_weed_table (struct route_table *table)
2170{
2171 struct route_node *rn;
2172 struct rib *rib;
2173 struct rib *next;
2174
2175 if (table)
2176 for (rn = route_top (table); rn; rn = route_next (rn))
2177 for (rib = rn->info; rib; rib = next)
2178 {
2179 next = rib->next;
2180
paulb21b19c2003-06-15 01:28:29 +00002181 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002182 rib->table != RT_TABLE_MAIN)
2183 {
2184 rib_delnode (rn, rib);
2185 newrib_free (rib);
2186 route_unlock_node (rn);
2187 }
2188 }
2189}
2190
2191/* Delete all routes from non main table. */
2192void
2193rib_weed_tables ()
2194{
2195 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2196 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2197}
2198
2199/* Delete self installed routes after zebra is relaunched. */
2200void
2201rib_sweep_table (struct route_table *table)
2202{
2203 struct route_node *rn;
2204 struct rib *rib;
2205 struct rib *next;
2206 int ret = 0;
2207
2208 if (table)
2209 for (rn = route_top (table); rn; rn = route_next (rn))
2210 for (rib = rn->info; rib; rib = next)
2211 {
2212 next = rib->next;
2213
2214 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2215 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2216 {
2217 ret = rib_uninstall_kernel (rn, rib);
2218 if (! ret)
2219 {
2220 rib_delnode (rn, rib);
2221 newrib_free (rib);
2222 route_unlock_node (rn);
2223 }
2224 }
2225 }
2226}
2227
2228/* Sweep all RIB tables. */
2229void
2230rib_sweep_route ()
2231{
2232 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2233 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2234}
2235
2236/* Close RIB and clean up kernel routes. */
2237void
2238rib_close_table (struct route_table *table)
2239{
2240 struct route_node *rn;
2241 struct rib *rib;
2242
2243 if (table)
2244 for (rn = route_top (table); rn; rn = route_next (rn))
2245 for (rib = rn->info; rib; rib = rib->next)
2246 if (! RIB_SYSTEM_ROUTE (rib)
2247 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2248 rib_uninstall_kernel (rn, rib);
2249}
2250
2251/* Close all RIB tables. */
2252void
2253rib_close ()
2254{
2255 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2256 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2257}
2258
2259/* Routing information base initialize. */
2260void
2261rib_init ()
2262{
2263 /* VRF initialization. */
2264 vrf_init ();
2265}