blob: 665e5673f288e278e187391faf6fd945d33a6355 [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"
paul4d38fdb2005-04-28 17:35:14 +000032#include "linklist.h"
33#include "thread.h"
34#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000035
36#include "zebra/rib.h"
37#include "zebra/rt.h"
38#include "zebra/zserv.h"
39#include "zebra/redistribute.h"
40#include "zebra/debug.h"
41
42/* Default rtm_table for all clients */
paulb21b19c2003-06-15 01:28:29 +000043extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000044
45/* Each route type's string and default distance value. */
46struct
47{
48 int key;
49 int distance;
50} route_info[] =
51{
52 {ZEBRA_ROUTE_SYSTEM, 0},
53 {ZEBRA_ROUTE_KERNEL, 0},
54 {ZEBRA_ROUTE_CONNECT, 0},
55 {ZEBRA_ROUTE_STATIC, 1},
56 {ZEBRA_ROUTE_RIP, 120},
57 {ZEBRA_ROUTE_RIPNG, 120},
58 {ZEBRA_ROUTE_OSPF, 110},
59 {ZEBRA_ROUTE_OSPF6, 110},
jardin9e867fe2003-12-23 08:56:18 +000060 {ZEBRA_ROUTE_ISIS, 115},
paul718e3742002-12-13 20:15:29 +000061 {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
62};
paul4d38fdb2005-04-28 17:35:14 +000063
64struct zebra_queue_node_t
65{
66 struct route_node *node;
67 struct rib *del;
68};
paul718e3742002-12-13 20:15:29 +000069
70/* Vector for routing table. */
71vector vrf_vector;
72
73/* Allocate new VRF. */
paula1ac18c2005-06-28 17:17:12 +000074static struct vrf *
hassofce954f2004-10-07 20:29:24 +000075vrf_alloc (const char *name)
paul718e3742002-12-13 20:15:29 +000076{
77 struct vrf *vrf;
78
79 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
80
81 /* Put name. */
82 if (name)
83 vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
84
85 /* Allocate routing table and static table. */
86 vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init ();
87 vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();
88 vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
89 vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
90
91 return vrf;
92}
93
94/* Free VRF. */
paula1ac18c2005-06-28 17:17:12 +000095static void
paul718e3742002-12-13 20:15:29 +000096vrf_free (struct vrf *vrf)
97{
98 if (vrf->name)
99 XFREE (MTYPE_VRF_NAME, vrf->name);
100 XFREE (MTYPE_VRF, vrf);
101}
102
103/* Lookup VRF by identifier. */
104struct vrf *
105vrf_lookup (u_int32_t id)
106{
107 return vector_lookup (vrf_vector, id);
108}
109
110/* Lookup VRF by name. */
paula1ac18c2005-06-28 17:17:12 +0000111static struct vrf *
paul718e3742002-12-13 20:15:29 +0000112vrf_lookup_by_name (char *name)
113{
hassofce954f2004-10-07 20:29:24 +0000114 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000115 struct vrf *vrf;
116
paul55468c82005-03-14 20:19:01 +0000117 for (i = 0; i < vector_active (vrf_vector); i++)
paul718e3742002-12-13 20:15:29 +0000118 if ((vrf = vector_slot (vrf_vector, i)) != NULL)
119 if (vrf->name && name && strcmp (vrf->name, name) == 0)
120 return vrf;
121 return NULL;
122}
123
124/* Initialize VRF. */
paula1ac18c2005-06-28 17:17:12 +0000125static void
126vrf_init (void)
paul718e3742002-12-13 20:15:29 +0000127{
128 struct vrf *default_table;
129
130 /* Allocate VRF vector. */
131 vrf_vector = vector_init (1);
132
133 /* Allocate default main table. */
134 default_table = vrf_alloc ("Default-IP-Routing-Table");
135
136 /* Default table index must be 0. */
137 vector_set_index (vrf_vector, 0, default_table);
138}
139
140/* Lookup route table. */
141struct route_table *
142vrf_table (afi_t afi, safi_t safi, u_int32_t id)
143{
144 struct vrf *vrf;
145
146 vrf = vrf_lookup (id);
147 if (! vrf)
148 return NULL;
149
150 return vrf->table[afi][safi];
151}
152
153/* Lookup static route table. */
154struct route_table *
155vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
156{
157 struct vrf *vrf;
158
159 vrf = vrf_lookup (id);
160 if (! vrf)
161 return NULL;
162
163 return vrf->stable[afi][safi];
164}
165
166/* Add nexthop to the end of the list. */
paula1ac18c2005-06-28 17:17:12 +0000167static void
paul718e3742002-12-13 20:15:29 +0000168nexthop_add (struct rib *rib, struct nexthop *nexthop)
169{
170 struct nexthop *last;
171
172 for (last = rib->nexthop; last && last->next; last = last->next)
173 ;
174 if (last)
175 last->next = nexthop;
176 else
177 rib->nexthop = nexthop;
178 nexthop->prev = last;
179
180 rib->nexthop_num++;
181}
182
183/* Delete specified nexthop from the list. */
paula1ac18c2005-06-28 17:17:12 +0000184static void
paul718e3742002-12-13 20:15:29 +0000185nexthop_delete (struct rib *rib, struct nexthop *nexthop)
186{
187 if (nexthop->next)
188 nexthop->next->prev = nexthop->prev;
189 if (nexthop->prev)
190 nexthop->prev->next = nexthop->next;
191 else
192 rib->nexthop = nexthop->next;
193 rib->nexthop_num--;
194}
195
196/* Free nexthop. */
paula1ac18c2005-06-28 17:17:12 +0000197static void
paul718e3742002-12-13 20:15:29 +0000198nexthop_free (struct nexthop *nexthop)
199{
paula4b70762003-05-16 17:19:48 +0000200 if (nexthop->ifname)
201 XFREE (0, nexthop->ifname);
paul718e3742002-12-13 20:15:29 +0000202 XFREE (MTYPE_NEXTHOP, nexthop);
203}
204
205struct nexthop *
206nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
207{
208 struct nexthop *nexthop;
209
210 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
211 memset (nexthop, 0, sizeof (struct nexthop));
212 nexthop->type = NEXTHOP_TYPE_IFINDEX;
213 nexthop->ifindex = ifindex;
214
215 nexthop_add (rib, nexthop);
216
217 return nexthop;
218}
219
220struct nexthop *
221nexthop_ifname_add (struct rib *rib, char *ifname)
222{
223 struct nexthop *nexthop;
224
225 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
226 memset (nexthop, 0, sizeof (struct nexthop));
227 nexthop->type = NEXTHOP_TYPE_IFNAME;
paula4b70762003-05-16 17:19:48 +0000228 nexthop->ifname = XSTRDUP (0, ifname);
paul718e3742002-12-13 20:15:29 +0000229
230 nexthop_add (rib, nexthop);
231
232 return nexthop;
233}
234
235struct nexthop *
236nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4)
237{
238 struct nexthop *nexthop;
239
240 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
241 memset (nexthop, 0, sizeof (struct nexthop));
242 nexthop->type = NEXTHOP_TYPE_IPV4;
243 nexthop->gate.ipv4 = *ipv4;
244
245 nexthop_add (rib, nexthop);
246
247 return nexthop;
248}
249
paula1ac18c2005-06-28 17:17:12 +0000250static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000251nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
252 unsigned int ifindex)
253{
254 struct nexthop *nexthop;
255
256 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
257 memset (nexthop, 0, sizeof (struct nexthop));
258 nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
259 nexthop->gate.ipv4 = *ipv4;
260 nexthop->ifindex = ifindex;
261
262 nexthop_add (rib, nexthop);
263
264 return nexthop;
265}
266
267#ifdef HAVE_IPV6
268struct nexthop *
269nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
270{
271 struct nexthop *nexthop;
272
273 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
274 memset (nexthop, 0, sizeof (struct nexthop));
275 nexthop->type = NEXTHOP_TYPE_IPV6;
276 nexthop->gate.ipv6 = *ipv6;
277
278 nexthop_add (rib, nexthop);
279
280 return nexthop;
281}
282
paula1ac18c2005-06-28 17:17:12 +0000283static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000284nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
285 char *ifname)
286{
287 struct nexthop *nexthop;
288
289 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
290 memset (nexthop, 0, sizeof (struct nexthop));
291 nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
292 nexthop->gate.ipv6 = *ipv6;
293 nexthop->ifname = XSTRDUP (0, ifname);
294
295 nexthop_add (rib, nexthop);
296
297 return nexthop;
298}
299
paula1ac18c2005-06-28 17:17:12 +0000300static struct nexthop *
paul718e3742002-12-13 20:15:29 +0000301nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
302 unsigned int ifindex)
303{
304 struct nexthop *nexthop;
305
306 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
307 memset (nexthop, 0, sizeof (struct nexthop));
308 nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
309 nexthop->gate.ipv6 = *ipv6;
310 nexthop->ifindex = ifindex;
311
312 nexthop_add (rib, nexthop);
313
314 return nexthop;
315}
316#endif /* HAVE_IPV6 */
317
paul595db7f2003-05-25 21:35:06 +0000318struct nexthop *
319nexthop_blackhole_add (struct rib *rib)
320{
321 struct nexthop *nexthop;
322
323 nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
324 memset (nexthop, 0, sizeof (struct nexthop));
325 nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
326 SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
327
328 nexthop_add (rib, nexthop);
329
330 return nexthop;
331}
332
paul718e3742002-12-13 20:15:29 +0000333/* If force flag is not set, do not modify falgs at all for uninstall
334 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000335static int
paul718e3742002-12-13 20:15:29 +0000336nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
337 struct route_node *top)
338{
339 struct prefix_ipv4 p;
340 struct route_table *table;
341 struct route_node *rn;
342 struct rib *match;
343 struct nexthop *newhop;
344
345 if (nexthop->type == NEXTHOP_TYPE_IPV4)
346 nexthop->ifindex = 0;
347
348 if (set)
349 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
350
351 /* Make lookup prefix. */
352 memset (&p, 0, sizeof (struct prefix_ipv4));
353 p.family = AF_INET;
354 p.prefixlen = IPV4_MAX_PREFIXLEN;
355 p.prefix = nexthop->gate.ipv4;
356
357 /* Lookup table. */
358 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
359 if (! table)
360 return 0;
361
362 rn = route_node_match (table, (struct prefix *) &p);
363 while (rn)
364 {
365 route_unlock_node (rn);
366
367 /* If lookup self prefix return immidiately. */
368 if (rn == top)
369 return 0;
370
371 /* Pick up selected route. */
372 for (match = rn->info; match; match = match->next)
373 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
374 break;
375
376 /* If there is no selected route or matched route is EGP, go up
377 tree. */
378 if (! match
379 || match->type == ZEBRA_ROUTE_BGP)
380 {
381 do {
382 rn = rn->parent;
383 } while (rn && rn->info == NULL);
384 if (rn)
385 route_lock_node (rn);
386 }
387 else
388 {
389 if (match->type == ZEBRA_ROUTE_CONNECT)
390 {
391 /* Directly point connected route. */
392 newhop = match->nexthop;
393 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
394 nexthop->ifindex = newhop->ifindex;
395
396 return 1;
397 }
398 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
399 {
400 for (newhop = match->nexthop; newhop; newhop = newhop->next)
401 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
402 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
403 {
404 if (set)
405 {
406 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
407 nexthop->rtype = newhop->type;
408 if (newhop->type == NEXTHOP_TYPE_IPV4 ||
409 newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
410 nexthop->rgate.ipv4 = newhop->gate.ipv4;
411 if (newhop->type == NEXTHOP_TYPE_IFINDEX
412 || newhop->type == NEXTHOP_TYPE_IFNAME
413 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
414 nexthop->rifindex = newhop->ifindex;
415 }
416 return 1;
417 }
418 return 0;
419 }
420 else
421 {
422 return 0;
423 }
424 }
425 }
426 return 0;
427}
428
429#ifdef HAVE_IPV6
430/* If force flag is not set, do not modify falgs at all for uninstall
431 the route from FIB. */
paula1ac18c2005-06-28 17:17:12 +0000432static int
paul718e3742002-12-13 20:15:29 +0000433nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
434 struct route_node *top)
435{
436 struct prefix_ipv6 p;
437 struct route_table *table;
438 struct route_node *rn;
439 struct rib *match;
440 struct nexthop *newhop;
441
442 if (nexthop->type == NEXTHOP_TYPE_IPV6)
443 nexthop->ifindex = 0;
444
445 if (set)
446 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
447
448 /* Make lookup prefix. */
449 memset (&p, 0, sizeof (struct prefix_ipv6));
450 p.family = AF_INET6;
451 p.prefixlen = IPV6_MAX_PREFIXLEN;
452 p.prefix = nexthop->gate.ipv6;
453
454 /* Lookup table. */
455 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
456 if (! table)
457 return 0;
458
459 rn = route_node_match (table, (struct prefix *) &p);
460 while (rn)
461 {
462 route_unlock_node (rn);
463
464 /* If lookup self prefix return immidiately. */
465 if (rn == top)
466 return 0;
467
468 /* Pick up selected route. */
469 for (match = rn->info; match; match = match->next)
470 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
471 break;
472
473 /* If there is no selected route or matched route is EGP, go up
474 tree. */
475 if (! match
476 || match->type == ZEBRA_ROUTE_BGP)
477 {
478 do {
479 rn = rn->parent;
480 } while (rn && rn->info == NULL);
481 if (rn)
482 route_lock_node (rn);
483 }
484 else
485 {
486 if (match->type == ZEBRA_ROUTE_CONNECT)
487 {
488 /* Directly point connected route. */
489 newhop = match->nexthop;
490
491 if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
492 nexthop->ifindex = newhop->ifindex;
493
494 return 1;
495 }
496 else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
497 {
498 for (newhop = match->nexthop; newhop; newhop = newhop->next)
499 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
500 && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
501 {
502 if (set)
503 {
504 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
505 nexthop->rtype = newhop->type;
506 if (newhop->type == NEXTHOP_TYPE_IPV6
507 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
508 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
509 nexthop->rgate.ipv6 = newhop->gate.ipv6;
510 if (newhop->type == NEXTHOP_TYPE_IFINDEX
511 || newhop->type == NEXTHOP_TYPE_IFNAME
512 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
513 || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
514 nexthop->rifindex = newhop->ifindex;
515 }
516 return 1;
517 }
518 return 0;
519 }
520 else
521 {
522 return 0;
523 }
524 }
525 }
526 return 0;
527}
528#endif /* HAVE_IPV6 */
529
530struct rib *
531rib_match_ipv4 (struct in_addr addr)
532{
533 struct prefix_ipv4 p;
534 struct route_table *table;
535 struct route_node *rn;
536 struct rib *match;
537 struct nexthop *newhop;
538
539 /* Lookup table. */
540 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
541 if (! table)
542 return 0;
543
544 memset (&p, 0, sizeof (struct prefix_ipv4));
545 p.family = AF_INET;
546 p.prefixlen = IPV4_MAX_PREFIXLEN;
547 p.prefix = addr;
548
549 rn = route_node_match (table, (struct prefix *) &p);
550
551 while (rn)
552 {
553 route_unlock_node (rn);
554
555 /* Pick up selected route. */
556 for (match = rn->info; match; match = match->next)
557 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
558 break;
559
560 /* If there is no selected route or matched route is EGP, go up
561 tree. */
562 if (! match
563 || match->type == ZEBRA_ROUTE_BGP)
564 {
565 do {
566 rn = rn->parent;
567 } while (rn && rn->info == NULL);
568 if (rn)
569 route_lock_node (rn);
570 }
571 else
572 {
573 if (match->type == ZEBRA_ROUTE_CONNECT)
574 /* Directly point connected route. */
575 return match;
576 else
577 {
578 for (newhop = match->nexthop; newhop; newhop = newhop->next)
579 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
580 return match;
581 return NULL;
582 }
583 }
584 }
585 return NULL;
586}
587
588struct rib *
589rib_lookup_ipv4 (struct prefix_ipv4 *p)
590{
591 struct route_table *table;
592 struct route_node *rn;
593 struct rib *match;
594 struct nexthop *nexthop;
595
596 /* Lookup table. */
597 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
598 if (! table)
599 return 0;
600
601 rn = route_node_lookup (table, (struct prefix *) p);
602
603 /* No route for this prefix. */
604 if (! rn)
605 return NULL;
606
607 /* Unlock node. */
608 route_unlock_node (rn);
609
610 /* Pick up selected route. */
611 for (match = rn->info; match; match = match->next)
612 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
613 break;
614
615 if (! match || match->type == ZEBRA_ROUTE_BGP)
616 return NULL;
617
618 if (match->type == ZEBRA_ROUTE_CONNECT)
619 return match;
620
621 for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
622 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
623 return match;
624
625 return NULL;
626}
627
628#ifdef HAVE_IPV6
629struct rib *
630rib_match_ipv6 (struct in6_addr *addr)
631{
632 struct prefix_ipv6 p;
633 struct route_table *table;
634 struct route_node *rn;
635 struct rib *match;
636 struct nexthop *newhop;
637
638 /* Lookup table. */
639 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
640 if (! table)
641 return 0;
642
643 memset (&p, 0, sizeof (struct prefix_ipv6));
644 p.family = AF_INET6;
645 p.prefixlen = IPV6_MAX_PREFIXLEN;
646 IPV6_ADDR_COPY (&p.prefix, addr);
647
648 rn = route_node_match (table, (struct prefix *) &p);
649
650 while (rn)
651 {
652 route_unlock_node (rn);
653
654 /* Pick up selected route. */
655 for (match = rn->info; match; match = match->next)
656 if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
657 break;
658
659 /* If there is no selected route or matched route is EGP, go up
660 tree. */
661 if (! match
662 || match->type == ZEBRA_ROUTE_BGP)
663 {
664 do {
665 rn = rn->parent;
666 } while (rn && rn->info == NULL);
667 if (rn)
668 route_lock_node (rn);
669 }
670 else
671 {
672 if (match->type == ZEBRA_ROUTE_CONNECT)
673 /* Directly point connected route. */
674 return match;
675 else
676 {
677 for (newhop = match->nexthop; newhop; newhop = newhop->next)
678 if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
679 return match;
680 return NULL;
681 }
682 }
683 }
684 return NULL;
685}
686#endif /* HAVE_IPV6 */
687
paula1ac18c2005-06-28 17:17:12 +0000688static int
paul718e3742002-12-13 20:15:29 +0000689nexthop_active_check (struct route_node *rn, struct rib *rib,
690 struct nexthop *nexthop, int set)
691{
692 struct interface *ifp;
693
694 switch (nexthop->type)
695 {
696 case NEXTHOP_TYPE_IFINDEX:
697 ifp = if_lookup_by_index (nexthop->ifindex);
698 if (ifp && if_is_up (ifp))
699 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
700 else
701 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
702 break;
703 case NEXTHOP_TYPE_IFNAME:
704 case NEXTHOP_TYPE_IPV6_IFNAME:
705 ifp = if_lookup_by_name (nexthop->ifname);
706 if (ifp && if_is_up (ifp))
707 {
708 if (set)
709 nexthop->ifindex = ifp->ifindex;
710 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
711 }
712 else
713 {
714 if (set)
715 nexthop->ifindex = 0;
716 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
717 }
718 break;
719 case NEXTHOP_TYPE_IPV4:
720 case NEXTHOP_TYPE_IPV4_IFINDEX:
721 if (nexthop_active_ipv4 (rib, nexthop, set, rn))
722 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
723 else
724 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
725 break;
726#ifdef HAVE_IPV6
727 case NEXTHOP_TYPE_IPV6:
728 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
729 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
730 else
731 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
732 break;
733 case NEXTHOP_TYPE_IPV6_IFINDEX:
734 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
735 {
736 ifp = if_lookup_by_index (nexthop->ifindex);
737 if (ifp && if_is_up (ifp))
738 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
739 else
740 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
741 }
742 else
743 {
744 if (nexthop_active_ipv6 (rib, nexthop, set, rn))
745 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
746 else
747 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
748 }
749 break;
750#endif /* HAVE_IPV6 */
paul595db7f2003-05-25 21:35:06 +0000751 case NEXTHOP_TYPE_BLACKHOLE:
752 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
753 break;
paul718e3742002-12-13 20:15:29 +0000754 default:
755 break;
756 }
757 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
758}
759
paula1ac18c2005-06-28 17:17:12 +0000760static int
paul718e3742002-12-13 20:15:29 +0000761nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
762{
763 struct nexthop *nexthop;
764 int active;
765
766 rib->nexthop_active_num = 0;
767 UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
768
769 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
770 {
771 active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
paul6baeb982003-10-28 03:47:15 +0000772
773 nexthop_active_check (rn, rib, nexthop, set);
774 if ((MULTIPATH_NUM == 0 || rib->nexthop_active_num < MULTIPATH_NUM)
775 && active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
776 SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
777
778 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
779 rib->nexthop_active_num++;
paul718e3742002-12-13 20:15:29 +0000780 }
781 return rib->nexthop_active_num;
782}
paul6baeb982003-10-28 03:47:15 +0000783
paul718e3742002-12-13 20:15:29 +0000784
785#define RIB_SYSTEM_ROUTE(R) \
786 ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
787
paul4d38fdb2005-04-28 17:35:14 +0000788static struct rib *
789rib_lock (struct rib *rib)
790{
791 assert (rib->lock >= 0);
792
793 rib->lock++;
794 return rib;
795}
796
797static struct rib *
798rib_unlock (struct rib *rib)
paul718e3742002-12-13 20:15:29 +0000799{
800 struct nexthop *nexthop;
801 struct nexthop *next;
paul4d38fdb2005-04-28 17:35:14 +0000802
803 assert (rib->lock > 0);
804 rib->lock--;
paul718e3742002-12-13 20:15:29 +0000805
paul4d38fdb2005-04-28 17:35:14 +0000806 if (rib->lock == 0)
paul718e3742002-12-13 20:15:29 +0000807 {
paul4d38fdb2005-04-28 17:35:14 +0000808 for (nexthop = rib->nexthop; nexthop; nexthop = next)
809 {
810 next = nexthop->next;
811 nexthop_free (nexthop);
812 }
813 XFREE (MTYPE_RIB, rib);
814 return NULL;
paul718e3742002-12-13 20:15:29 +0000815 }
paul4d38fdb2005-04-28 17:35:14 +0000816 return rib;
paul718e3742002-12-13 20:15:29 +0000817}
818
paula1ac18c2005-06-28 17:17:12 +0000819static void
paul718e3742002-12-13 20:15:29 +0000820rib_install_kernel (struct route_node *rn, struct rib *rib)
821{
822 int ret = 0;
823 struct nexthop *nexthop;
824
825 switch (PREFIX_FAMILY (&rn->p))
826 {
827 case AF_INET:
828 ret = kernel_add_ipv4 (&rn->p, rib);
829 break;
830#ifdef HAVE_IPV6
831 case AF_INET6:
832 ret = kernel_add_ipv6 (&rn->p, rib);
833 break;
834#endif /* HAVE_IPV6 */
835 }
836
837 if (ret < 0)
838 {
839 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
840 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
841 }
842}
843
844/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000845static int
paul718e3742002-12-13 20:15:29 +0000846rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
847{
848 int ret = 0;
849 struct nexthop *nexthop;
850
851 switch (PREFIX_FAMILY (&rn->p))
852 {
853 case AF_INET:
854 ret = kernel_delete_ipv4 (&rn->p, rib);
855 break;
856#ifdef HAVE_IPV6
857 case AF_INET6:
858 ret = kernel_delete_ipv6 (&rn->p, rib);
859 break;
860#endif /* HAVE_IPV6 */
861 }
862
863 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
864 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
865
866 return ret;
867}
868
869/* Uninstall the route from kernel. */
paula1ac18c2005-06-28 17:17:12 +0000870static void
paul718e3742002-12-13 20:15:29 +0000871rib_uninstall (struct route_node *rn, struct rib *rib)
872{
873 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
874 {
875 redistribute_delete (&rn->p, rib);
876 if (! RIB_SYSTEM_ROUTE (rib))
877 rib_uninstall_kernel (rn, rib);
878 UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
879 }
880}
881
882/* Core function for processing routing information base. */
paula1ac18c2005-06-28 17:17:12 +0000883static wq_item_status
paul0fb58d52005-11-14 14:31:49 +0000884rib_process (struct work_queue *wq, void *data)
paul718e3742002-12-13 20:15:29 +0000885{
paul0fb58d52005-11-14 14:31:49 +0000886 struct zebra_queue_node_t *qnode = data;
paul718e3742002-12-13 20:15:29 +0000887 struct rib *rib;
888 struct rib *next;
889 struct rib *fib = NULL;
890 struct rib *select = NULL;
paul4d38fdb2005-04-28 17:35:14 +0000891 struct rib *del = qnode->del;
892 struct route_node *rn = qnode->node;
pauld753e9e2003-01-22 19:45:50 +0000893 int installed = 0;
894 struct nexthop *nexthop = NULL;
paul4d38fdb2005-04-28 17:35:14 +0000895
896 assert (rn);
897
898 /* possibly should lock and unlock rib on each iteration. however, for
899 * now, we assume called functions are synchronous and dont delete RIBs
900 * (as the work-queue deconstructor for this function is supposed to be
901 * the canonical 'delete' path for RIBs). Further if called functions
902 * below were to made asynchronous they should themselves acquire any
903 * locks/refcounts as needed and not depend on this caller to do it for
904 * them
905 */
paul718e3742002-12-13 20:15:29 +0000906 for (rib = rn->info; rib; rib = next)
907 {
908 next = rib->next;
pauld753e9e2003-01-22 19:45:50 +0000909
paul718e3742002-12-13 20:15:29 +0000910 /* Currently installed rib. */
911 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
paul7021c422003-07-15 12:52:22 +0000912 fib = rib;
paul4d38fdb2005-04-28 17:35:14 +0000913
paul718e3742002-12-13 20:15:29 +0000914 /* Skip unreachable nexthop. */
915 if (! nexthop_active_update (rn, rib, 0))
paul7021c422003-07-15 12:52:22 +0000916 continue;
paul718e3742002-12-13 20:15:29 +0000917
918 /* Infinit distance. */
919 if (rib->distance == DISTANCE_INFINITY)
paul7021c422003-07-15 12:52:22 +0000920 continue;
paul718e3742002-12-13 20:15:29 +0000921
paulaf887b52006-01-18 14:52:52 +0000922 /* Newly selected rib, the common case. */
923 if (!select)
924 {
925 select = rib;
926 continue;
927 }
928
929 /* filter route selection in following order:
paulaf887b52006-01-18 14:52:52 +0000930 * - connected beats other types
paula8d9c1f2006-01-25 06:31:04 +0000931 * - lower distance beats higher
paulaf887b52006-01-18 14:52:52 +0000932 * - lower metric beats higher for equal distance
933 * - last, hence oldest, route wins tie break.
934 */
paula1038a12006-01-30 14:08:51 +0000935
936 /* Connected routes. Pick the last connected
937 * route of the set of lowest metric connected routes.
938 */
paula8d9c1f2006-01-25 06:31:04 +0000939 if (rib->type == ZEBRA_ROUTE_CONNECT)
940 {
paula1038a12006-01-30 14:08:51 +0000941 if (select->type != ZEBRA_ROUTE_CONNECT
paula8d9c1f2006-01-25 06:31:04 +0000942 || rib->metric <= select->metric)
paula1038a12006-01-30 14:08:51 +0000943 select = rib;
944 continue;
paula8d9c1f2006-01-25 06:31:04 +0000945 }
946 else if (select->type == ZEBRA_ROUTE_CONNECT)
947 continue;
948
949 /* higher distance loses */
950 if (rib->distance > select->distance)
951 continue;
952
953 /* lower wins */
954 if (rib->distance < select->distance)
955 {
paulaf887b52006-01-18 14:52:52 +0000956 select = rib;
paula8d9c1f2006-01-25 06:31:04 +0000957 continue;
958 }
959
960 /* metric tie-breaks equal distance */
961 if (rib->metric <= select->metric)
962 select = rib;
paul718e3742002-12-13 20:15:29 +0000963 }
paul4d38fdb2005-04-28 17:35:14 +0000964
paul718e3742002-12-13 20:15:29 +0000965 /* Deleted route check. */
966 if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
967 fib = del;
paul4d38fdb2005-04-28 17:35:14 +0000968
969 /* We possibly should lock fib and select here However, all functions
970 * below are 'inline' and not asynchronous And if any were to be
971 * converted, they should manage references themselves really.. See
972 * previous comment above.
973 */
974
paul718e3742002-12-13 20:15:29 +0000975 /* Same route is selected. */
976 if (select && select == fib)
977 {
978 if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
paul4d38fdb2005-04-28 17:35:14 +0000979 {
980 redistribute_delete (&rn->p, select);
981 if (! RIB_SYSTEM_ROUTE (select))
982 rib_uninstall_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +0000983
paul4d38fdb2005-04-28 17:35:14 +0000984 /* Set real nexthop. */
985 nexthop_active_update (rn, select, 1);
paul718e3742002-12-13 20:15:29 +0000986
paul4d38fdb2005-04-28 17:35:14 +0000987 if (! RIB_SYSTEM_ROUTE (select))
988 rib_install_kernel (rn, select);
989 redistribute_add (&rn->p, select);
990 }
pauld753e9e2003-01-22 19:45:50 +0000991 else if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +0000992 {
993 /* Housekeeping code to deal with
994 race conditions in kernel with linux
995 netlink reporting interface up before IPv4 or IPv6 protocol
996 is ready to add routes.
997 This makes sure the routes are IN the kernel.
998 */
pauld753e9e2003-01-22 19:45:50 +0000999
paul4d38fdb2005-04-28 17:35:14 +00001000 for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
1001 {
1002 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1003 installed = 1;
1004 }
1005 if (! installed)
1006 rib_install_kernel (rn, select);
1007 }
1008 return WQ_SUCCESS;
paul718e3742002-12-13 20:15:29 +00001009 }
1010
1011 /* Uninstall old rib from forwarding table. */
1012 if (fib)
1013 {
1014 redistribute_delete (&rn->p, fib);
1015 if (! RIB_SYSTEM_ROUTE (fib))
1016 rib_uninstall_kernel (rn, fib);
1017 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1018
1019 /* Set real nexthop. */
1020 nexthop_active_update (rn, fib, 1);
1021 }
1022
1023 /* Install new rib into forwarding table. */
1024 if (select)
1025 {
1026 /* Set real nexthop. */
1027 nexthop_active_update (rn, select, 1);
1028
1029 if (! RIB_SYSTEM_ROUTE (select))
paul4d38fdb2005-04-28 17:35:14 +00001030 rib_install_kernel (rn, select);
paul718e3742002-12-13 20:15:29 +00001031 SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
1032 redistribute_add (&rn->p, select);
1033 }
paul4d38fdb2005-04-28 17:35:14 +00001034
1035 return WQ_SUCCESS;
1036
1037}
1038
1039/* Add work queue item to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001040static void
paul4d38fdb2005-04-28 17:35:14 +00001041rib_queue_add_qnode (struct zebra_t *zebra, struct zebra_queue_node_t *qnode)
1042{
1043 route_lock_node (qnode->node);
1044
1045 if (IS_ZEBRA_DEBUG_EVENT)
1046 zlog_info ("rib_queue_add_qnode: work queue added");
1047
1048 assert (zebra && qnode && qnode->node);
1049
1050 if (qnode->del)
1051 rib_lock (qnode->del);
1052
1053 if (zebra->ribq == NULL)
1054 {
1055 zlog_err ("rib_queue_add_qnode: ribq work_queue does not exist!");
1056 route_unlock_node (qnode->node);
1057 return;
1058 }
1059
1060 work_queue_add (zebra->ribq, qnode);
1061
1062 return;
1063}
1064
1065/* Add route node and rib to work queue and schedule processing */
paula1ac18c2005-06-28 17:17:12 +00001066static void
paul4d38fdb2005-04-28 17:35:14 +00001067rib_queue_add (struct zebra_t *zebra, struct route_node *rn, struct rib *del)
1068{
1069 struct zebra_queue_node_t *qnode;
1070
1071 assert (zebra && rn);
1072
1073 qnode = (struct zebra_queue_node_t *)
1074 XCALLOC (MTYPE_RIB_QUEUE, sizeof (struct zebra_queue_node_t));
1075
1076 if (qnode == NULL)
1077 {
1078 zlog_err ("rib_queue_add: failed to allocate queue node memory, %s",
1079 strerror (errno));
1080 return;
1081 }
1082
1083 qnode->node = rn;
1084 qnode->del = del;
1085
1086 rib_queue_add_qnode (zebra, qnode);
1087
1088 return;
1089}
1090
1091/* free zebra_queue_node_t */
paula1ac18c2005-06-28 17:17:12 +00001092static void
paul0fb58d52005-11-14 14:31:49 +00001093rib_queue_qnode_del (struct work_queue *wq, void *data)
paul4d38fdb2005-04-28 17:35:14 +00001094{
paul0fb58d52005-11-14 14:31:49 +00001095 struct zebra_queue_node_t *qnode = data;
paul4d38fdb2005-04-28 17:35:14 +00001096 route_unlock_node (qnode->node);
1097
1098 if (qnode->del)
1099 rib_unlock (qnode->del);
1100
1101 XFREE (MTYPE_RIB_QUEUE, qnode);
1102}
1103
1104/* initialise zebra rib work queue */
paula1ac18c2005-06-28 17:17:12 +00001105static void
paul4d38fdb2005-04-28 17:35:14 +00001106rib_queue_init (struct zebra_t *zebra)
1107{
1108 assert (zebra);
1109
1110 if (! (zebra->ribq = work_queue_new (zebra->master,
1111 "zebra_rib_work_queue")))
1112 {
1113 zlog_err ("rib_queue_init: could not initialise work queue!");
1114 return;
1115 }
1116
1117 /* fill in the work queue spec */
paul0fb58d52005-11-14 14:31:49 +00001118 zebra->ribq->spec.workfunc = &rib_process;
paul4d38fdb2005-04-28 17:35:14 +00001119 zebra->ribq->spec.errorfunc = NULL;
paul0fb58d52005-11-14 14:31:49 +00001120 zebra->ribq->spec.del_item_data = &rib_queue_qnode_del;
paul4d38fdb2005-04-28 17:35:14 +00001121 /* XXX: TODO: These should be runtime configurable via vty */
1122 zebra->ribq->spec.max_retries = 3;
paul4d38fdb2005-04-28 17:35:14 +00001123
1124 return;
paul718e3742002-12-13 20:15:29 +00001125}
1126
1127/* Add RIB to head of the route node. */
paula1ac18c2005-06-28 17:17:12 +00001128static void
paul718e3742002-12-13 20:15:29 +00001129rib_addnode (struct route_node *rn, struct rib *rib)
1130{
1131 struct rib *head;
paul4d38fdb2005-04-28 17:35:14 +00001132
1133 assert (rib && rn);
1134
1135 rib_lock (rib);
1136 route_lock_node (rn);
1137
paul718e3742002-12-13 20:15:29 +00001138 head = rn->info;
1139 if (head)
1140 head->prev = rib;
1141 rib->next = head;
1142 rn->info = rib;
1143}
1144
paula1ac18c2005-06-28 17:17:12 +00001145static void
paul718e3742002-12-13 20:15:29 +00001146rib_delnode (struct route_node *rn, struct rib *rib)
1147{
paul4d38fdb2005-04-28 17:35:14 +00001148 assert (rn && rib);
1149
paul718e3742002-12-13 20:15:29 +00001150 if (rib->next)
1151 rib->next->prev = rib->prev;
1152 if (rib->prev)
1153 rib->prev->next = rib->next;
1154 else
1155 rn->info = rib->next;
paul4d38fdb2005-04-28 17:35:14 +00001156
1157 rib_unlock (rib);
1158 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001159}
1160
1161int
1162rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1163 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1164 u_int32_t metric, u_char distance)
1165{
1166 struct rib *rib;
1167 struct rib *same = NULL;
1168 struct route_table *table;
1169 struct route_node *rn;
1170 struct nexthop *nexthop;
1171
1172 /* Lookup table. */
1173 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1174 if (! table)
1175 return 0;
1176
1177 /* Make it sure prefixlen is applied to the prefix. */
1178 apply_mask_ipv4 (p);
1179
1180 /* Set default distance by route type. */
1181 if (distance == 0)
1182 {
1183 distance = route_info[type].distance;
1184
1185 /* iBGP distance is 200. */
1186 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1187 distance = 200;
1188 }
1189
1190 /* Lookup route node.*/
1191 rn = route_node_get (table, (struct prefix *) p);
1192
1193 /* If same type of route are installed, treat it as a implicit
1194 withdraw. */
1195 for (rib = rn->info; rib; rib = rib->next)
1196 {
hassoebf1ead2005-09-21 14:58:20 +00001197 if (rib->type != type)
1198 continue;
1199 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001200 {
1201 same = rib;
1202 break;
1203 }
hassoebf1ead2005-09-21 14:58:20 +00001204 /* Duplicate connected route comes in. */
1205 else if ((nexthop = rib->nexthop) &&
1206 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1207 nexthop->ifindex == ifindex)
1208 {
1209 rib->refcnt++;
1210 return 0 ;
1211 }
paul718e3742002-12-13 20:15:29 +00001212 }
1213
1214 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001215 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
paul718e3742002-12-13 20:15:29 +00001216 rib->type = type;
1217 rib->distance = distance;
1218 rib->flags = flags;
1219 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001220 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001221 rib->nexthop_num = 0;
1222 rib->uptime = time (NULL);
1223
1224 /* Nexthop settings. */
1225 if (gate)
1226 {
1227 if (ifindex)
1228 nexthop_ipv4_ifindex_add (rib, gate, ifindex);
1229 else
1230 nexthop_ipv4_add (rib, gate);
1231 }
1232 else
1233 nexthop_ifindex_add (rib, ifindex);
1234
1235 /* If this route is kernel route, set FIB flag to the route. */
1236 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1237 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1238 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1239
1240 /* Link new rib to node.*/
1241 rib_addnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00001242
paul718e3742002-12-13 20:15:29 +00001243 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001244 rib_queue_add (&zebrad, rn, same);
1245
paul718e3742002-12-13 20:15:29 +00001246 /* Free implicit route.*/
1247 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001248 rib_delnode (rn, same);
1249
1250 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001251 return 0;
1252}
1253
1254int
1255rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
1256{
1257 struct route_table *table;
1258 struct route_node *rn;
1259 struct rib *same;
1260 struct nexthop *nexthop;
paul4d38fdb2005-04-28 17:35:14 +00001261
paul718e3742002-12-13 20:15:29 +00001262 /* Lookup table. */
1263 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1264 if (! table)
1265 return 0;
paul718e3742002-12-13 20:15:29 +00001266 /* Make it sure prefixlen is applied to the prefix. */
1267 apply_mask_ipv4 (p);
1268
1269 /* Set default distance by route type. */
1270 if (rib->distance == 0)
1271 {
1272 rib->distance = route_info[rib->type].distance;
1273
1274 /* iBGP distance is 200. */
1275 if (rib->type == ZEBRA_ROUTE_BGP
1276 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
1277 rib->distance = 200;
1278 }
1279
1280 /* Lookup route node.*/
1281 rn = route_node_get (table, (struct prefix *) p);
1282
1283 /* If same type of route are installed, treat it as a implicit
1284 withdraw. */
1285 for (same = rn->info; same; same = same->next)
1286 {
1287 if (same->type == rib->type && same->table == rib->table
1288 && same->type != ZEBRA_ROUTE_CONNECT)
paul4d38fdb2005-04-28 17:35:14 +00001289 break;
paul718e3742002-12-13 20:15:29 +00001290 }
paul4d38fdb2005-04-28 17:35:14 +00001291
paul718e3742002-12-13 20:15:29 +00001292 /* If this route is kernel route, set FIB flag to the route. */
1293 if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
1294 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1295 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1296
1297 /* Link new rib to node.*/
1298 rib_addnode (rn, rib);
1299
1300 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001301 rib_queue_add (&zebrad, rn, same);
paul718e3742002-12-13 20:15:29 +00001302
1303 /* Free implicit route.*/
1304 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001305 rib_delnode (rn, same);
1306
1307 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001308 return 0;
1309}
1310
hassoebf1ead2005-09-21 14:58:20 +00001311/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001312int
1313rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
1314 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1315{
1316 struct route_table *table;
1317 struct route_node *rn;
1318 struct rib *rib;
1319 struct rib *fib = NULL;
1320 struct rib *same = NULL;
1321 struct nexthop *nexthop;
1322 char buf1[BUFSIZ];
1323 char buf2[BUFSIZ];
1324
1325 /* Lookup table. */
1326 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1327 if (! table)
1328 return 0;
1329
1330 /* Apply mask. */
1331 apply_mask_ipv4 (p);
1332
paul5ec90d22003-06-19 01:41:37 +00001333 if (IS_ZEBRA_DEBUG_KERNEL && gate)
ajsb6178002004-12-07 21:12:56 +00001334 zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
paul5ec90d22003-06-19 01:41:37 +00001335 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1336 p->prefixlen,
1337 inet_ntoa (*gate),
1338 ifindex);
1339
paul718e3742002-12-13 20:15:29 +00001340 /* Lookup route node. */
1341 rn = route_node_lookup (table, (struct prefix *) p);
1342 if (! rn)
1343 {
1344 if (IS_ZEBRA_DEBUG_KERNEL)
1345 {
1346 if (gate)
ajsb6178002004-12-07 21:12:56 +00001347 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001348 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1349 p->prefixlen,
1350 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1351 ifindex);
1352 else
ajsb6178002004-12-07 21:12:56 +00001353 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001354 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1355 p->prefixlen,
1356 ifindex);
1357 }
1358 return ZEBRA_ERR_RTNOEXIST;
1359 }
1360
1361 /* Lookup same type route. */
1362 for (rib = rn->info; rib; rib = rib->next)
1363 {
1364 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1365 fib = rib;
1366
hassoebf1ead2005-09-21 14:58:20 +00001367 if (rib->type != type)
1368 continue;
1369 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1370 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001371 {
hassoebf1ead2005-09-21 14:58:20 +00001372 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001373 {
hassoebf1ead2005-09-21 14:58:20 +00001374 rib->refcnt--;
1375 route_unlock_node (rn);
1376 route_unlock_node (rn);
1377 return 0;
paul718e3742002-12-13 20:15:29 +00001378 }
hassoebf1ead2005-09-21 14:58:20 +00001379 same = rib;
1380 break;
paul718e3742002-12-13 20:15:29 +00001381 }
hassoebf1ead2005-09-21 14:58:20 +00001382 /* Make sure that the route found has the same gateway. */
1383 else if (gate == NULL ||
1384 ((nexthop = rib->nexthop) &&
1385 (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
1386 IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
paul5ec90d22003-06-19 01:41:37 +00001387 {
hassoebf1ead2005-09-21 14:58:20 +00001388 same = rib;
1389 break;
paul718e3742002-12-13 20:15:29 +00001390 }
1391 }
1392
1393 /* If same type of route can't be found and this message is from
1394 kernel. */
1395 if (! same)
1396 {
1397 if (fib && type == ZEBRA_ROUTE_KERNEL)
1398 {
1399 /* Unset flags. */
1400 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1401 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1402
1403 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1404 }
1405 else
1406 {
1407 if (IS_ZEBRA_DEBUG_KERNEL)
1408 {
1409 if (gate)
ajsb6178002004-12-07 21:12:56 +00001410 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001411 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1412 p->prefixlen,
1413 inet_ntop (AF_INET, gate, buf2, BUFSIZ),
1414 ifindex,
1415 type);
1416 else
ajsb6178002004-12-07 21:12:56 +00001417 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001418 inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
1419 p->prefixlen,
1420 ifindex,
1421 type);
1422 }
1423 route_unlock_node (rn);
1424 return ZEBRA_ERR_RTNOEXIST;
1425 }
1426 }
paul4d38fdb2005-04-28 17:35:14 +00001427
1428 /* Process changes. */
1429 rib_queue_add (&zebrad, rn, same);
paul718e3742002-12-13 20:15:29 +00001430
1431 if (same)
1432 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001433
paul718e3742002-12-13 20:15:29 +00001434 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001435 return 0;
1436}
1437
1438/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001439static void
paul718e3742002-12-13 20:15:29 +00001440static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
1441{
1442 struct rib *rib;
1443 struct route_node *rn;
1444 struct route_table *table;
1445
1446 /* Lookup table. */
1447 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1448 if (! table)
1449 return;
1450
1451 /* Lookup existing route */
1452 rn = route_node_get (table, p);
1453 for (rib = rn->info; rib; rib = rib->next)
1454 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1455 break;
1456
1457 if (rib)
1458 {
1459 /* Same distance static route is there. Update it with new
1460 nexthop. */
paul718e3742002-12-13 20:15:29 +00001461 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001462 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001463 {
1464 case STATIC_IPV4_GATEWAY:
1465 nexthop_ipv4_add (rib, &si->gate.ipv4);
1466 break;
1467 case STATIC_IPV4_IFNAME:
1468 nexthop_ifname_add (rib, si->gate.ifname);
1469 break;
1470 case STATIC_IPV4_BLACKHOLE:
1471 nexthop_blackhole_add (rib);
1472 break;
paul4d38fdb2005-04-28 17:35:14 +00001473 }
1474 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001475 }
1476 else
1477 {
1478 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00001479 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1480
paul718e3742002-12-13 20:15:29 +00001481 rib->type = ZEBRA_ROUTE_STATIC;
1482 rib->distance = si->distance;
1483 rib->metric = 0;
1484 rib->nexthop_num = 0;
Paul Jakma171eee32006-07-27 16:11:02 +00001485 rib->table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00001486
1487 switch (si->type)
paul7021c422003-07-15 12:52:22 +00001488 {
1489 case STATIC_IPV4_GATEWAY:
1490 nexthop_ipv4_add (rib, &si->gate.ipv4);
1491 break;
1492 case STATIC_IPV4_IFNAME:
1493 nexthop_ifname_add (rib, si->gate.ifname);
1494 break;
1495 case STATIC_IPV4_BLACKHOLE:
1496 nexthop_blackhole_add (rib);
1497 break;
1498 }
paul718e3742002-12-13 20:15:29 +00001499
hasso81dfcaa2003-05-25 19:21:25 +00001500 /* Save the flags of this static routes (reject, blackhole) */
1501 rib->flags = si->flags;
1502
paul718e3742002-12-13 20:15:29 +00001503 /* Link this rib to the tree. */
1504 rib_addnode (rn, rib);
1505
1506 /* Process this prefix. */
paul4d38fdb2005-04-28 17:35:14 +00001507 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001508 }
1509}
1510
paula1ac18c2005-06-28 17:17:12 +00001511static int
paul718e3742002-12-13 20:15:29 +00001512static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
1513{
1514 if (nexthop->type == NEXTHOP_TYPE_IPV4
1515 && si->type == STATIC_IPV4_GATEWAY
1516 && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
1517 return 1;
1518 if (nexthop->type == NEXTHOP_TYPE_IFNAME
1519 && si->type == STATIC_IPV4_IFNAME
1520 && strcmp (nexthop->ifname, si->gate.ifname) == 0)
1521 return 1;
paul595db7f2003-05-25 21:35:06 +00001522 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
1523 && si->type == STATIC_IPV4_BLACKHOLE)
1524 return 1;
paule8e19462006-01-19 20:16:55 +00001525 return 0;
paul718e3742002-12-13 20:15:29 +00001526}
1527
1528/* Uninstall static route from RIB. */
paula1ac18c2005-06-28 17:17:12 +00001529static void
paul718e3742002-12-13 20:15:29 +00001530static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
1531{
1532 struct route_node *rn;
1533 struct rib *rib;
1534 struct nexthop *nexthop;
1535 struct route_table *table;
1536
1537 /* Lookup table. */
1538 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
1539 if (! table)
1540 return;
paul4d38fdb2005-04-28 17:35:14 +00001541
paul718e3742002-12-13 20:15:29 +00001542 /* Lookup existing route with type and distance. */
1543 rn = route_node_lookup (table, p);
1544 if (! rn)
1545 return;
1546
1547 for (rib = rn->info; rib; rib = rib->next)
1548 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
1549 break;
1550
1551 if (! rib)
1552 {
1553 route_unlock_node (rn);
1554 return;
1555 }
1556
1557 /* Lookup nexthop. */
1558 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1559 if (static_ipv4_nexthop_same (nexthop, si))
1560 break;
1561
1562 /* Can't find nexthop. */
1563 if (! nexthop)
1564 {
1565 route_unlock_node (rn);
1566 return;
1567 }
1568
1569 /* Check nexthop. */
1570 if (rib->nexthop_num == 1)
1571 {
paul4d38fdb2005-04-28 17:35:14 +00001572 rib_queue_add (&zebrad, rn, rib);
paul718e3742002-12-13 20:15:29 +00001573 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00001574 }
1575 else
1576 {
paul6baeb982003-10-28 03:47:15 +00001577 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1578 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00001579 nexthop_delete (rib, nexthop);
1580 nexthop_free (nexthop);
1581 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00001582 }
paul718e3742002-12-13 20:15:29 +00001583 /* Unlock node. */
1584 route_unlock_node (rn);
1585}
1586
1587/* Add static route into static route configuration. */
1588int
hasso39db97e2004-10-12 20:50:58 +00001589static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
hasso81dfcaa2003-05-25 19:21:25 +00001590 u_char flags, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00001591{
1592 u_char type = 0;
1593 struct route_node *rn;
1594 struct static_ipv4 *si;
1595 struct static_ipv4 *pp;
1596 struct static_ipv4 *cp;
1597 struct static_ipv4 *update = NULL;
1598 struct route_table *stable;
1599
1600 /* Lookup table. */
1601 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1602 if (! stable)
1603 return -1;
1604
1605 /* Lookup static route prefix. */
1606 rn = route_node_get (stable, p);
1607
1608 /* Make flags. */
1609 if (gate)
1610 type = STATIC_IPV4_GATEWAY;
paul368aa3f2003-05-25 23:24:50 +00001611 else if (ifname)
paul718e3742002-12-13 20:15:29 +00001612 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001613 else
1614 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001615
1616 /* Do nothing if there is a same static route. */
1617 for (si = rn->info; si; si = si->next)
1618 {
1619 if (type == si->type
1620 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1621 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1622 {
1623 if (distance == si->distance)
1624 {
1625 route_unlock_node (rn);
1626 return 0;
1627 }
1628 else
1629 update = si;
1630 }
1631 }
1632
1633 /* Distance chaged. */
1634 if (update)
1635 static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
1636
1637 /* Make new static route structure. */
1638 si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
1639 memset (si, 0, sizeof (struct static_ipv4));
1640
1641 si->type = type;
1642 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00001643 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00001644
1645 if (gate)
1646 si->gate.ipv4 = *gate;
1647 if (ifname)
1648 si->gate.ifname = XSTRDUP (0, ifname);
1649
1650 /* Add new static route information to the tree with sort by
1651 distance value and gateway address. */
1652 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
1653 {
1654 if (si->distance < cp->distance)
1655 break;
1656 if (si->distance > cp->distance)
1657 continue;
1658 if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
1659 {
1660 if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
1661 break;
1662 if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
1663 continue;
1664 }
1665 }
1666
1667 /* Make linked list. */
1668 if (pp)
1669 pp->next = si;
1670 else
1671 rn->info = si;
1672 if (cp)
1673 cp->prev = si;
1674 si->prev = pp;
1675 si->next = cp;
1676
1677 /* Install into rib. */
1678 static_install_ipv4 (p, si);
1679
1680 return 1;
1681}
1682
1683/* Delete static route from static route configuration. */
1684int
hasso39db97e2004-10-12 20:50:58 +00001685static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
paul718e3742002-12-13 20:15:29 +00001686 u_char distance, u_int32_t vrf_id)
1687{
1688 u_char type = 0;
1689 struct route_node *rn;
1690 struct static_ipv4 *si;
1691 struct route_table *stable;
1692
1693 /* Lookup table. */
1694 stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
1695 if (! stable)
1696 return -1;
1697
1698 /* Lookup static route prefix. */
1699 rn = route_node_lookup (stable, p);
1700 if (! rn)
1701 return 0;
1702
1703 /* Make flags. */
1704 if (gate)
1705 type = STATIC_IPV4_GATEWAY;
1706 else if (ifname)
1707 type = STATIC_IPV4_IFNAME;
paul595db7f2003-05-25 21:35:06 +00001708 else
1709 type = STATIC_IPV4_BLACKHOLE;
paul718e3742002-12-13 20:15:29 +00001710
1711 /* Find same static route is the tree */
1712 for (si = rn->info; si; si = si->next)
1713 if (type == si->type
1714 && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
1715 && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
1716 break;
1717
1718 /* Can't find static route. */
1719 if (! si)
1720 {
1721 route_unlock_node (rn);
1722 return 0;
1723 }
1724
1725 /* Install into rib. */
1726 static_uninstall_ipv4 (p, si);
1727
1728 /* Unlink static route from linked list. */
1729 if (si->prev)
1730 si->prev->next = si->next;
1731 else
1732 rn->info = si->next;
1733 if (si->next)
1734 si->next->prev = si->prev;
paul143a3852003-09-29 20:06:13 +00001735 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001736
1737 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00001738 if (ifname)
1739 XFREE (0, si->gate.ifname);
paul718e3742002-12-13 20:15:29 +00001740 XFREE (MTYPE_STATIC_IPV4, si);
1741
paul143a3852003-09-29 20:06:13 +00001742 route_unlock_node (rn);
1743
paul718e3742002-12-13 20:15:29 +00001744 return 1;
1745}
1746
1747
1748#ifdef HAVE_IPV6
paula1ac18c2005-06-28 17:17:12 +00001749static int
paul718e3742002-12-13 20:15:29 +00001750rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
1751 struct in6_addr *gate, unsigned int ifindex, int table)
1752{
hasso726f9b22003-05-25 21:04:54 +00001753 if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
1754#if defined (MUSICA) || defined (LINUX)
1755 /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
1756 if (p->prefixlen == 96)
1757 return 0;
1758#endif /* MUSICA */
paul718e3742002-12-13 20:15:29 +00001759 return 1;
hasso726f9b22003-05-25 21:04:54 +00001760 }
paul718e3742002-12-13 20:15:29 +00001761 if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
1762 && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
1763 {
1764 kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
1765 return 1;
1766 }
1767 return 0;
1768}
1769
1770int
1771rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
hassobe61c4e2005-08-27 06:05:47 +00001772 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
1773 u_int32_t metric, u_char distance)
paul718e3742002-12-13 20:15:29 +00001774{
1775 struct rib *rib;
1776 struct rib *same = NULL;
1777 struct route_table *table;
1778 struct route_node *rn;
1779 struct nexthop *nexthop;
1780
paul718e3742002-12-13 20:15:29 +00001781 /* Lookup table. */
1782 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1783 if (! table)
1784 return 0;
1785
1786 /* Make sure mask is applied. */
1787 apply_mask_ipv6 (p);
1788
1789 /* Set default distance by route type. */
hassobe61c4e2005-08-27 06:05:47 +00001790 if (!distance)
1791 distance = route_info[type].distance;
paul718e3742002-12-13 20:15:29 +00001792
1793 if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
1794 distance = 200;
1795
1796 /* Filter bogus route. */
1797 if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
1798 return 0;
1799
1800 /* Lookup route node.*/
1801 rn = route_node_get (table, (struct prefix *) p);
1802
1803 /* If same type of route are installed, treat it as a implicit
1804 withdraw. */
1805 for (rib = rn->info; rib; rib = rib->next)
1806 {
hassoebf1ead2005-09-21 14:58:20 +00001807 if (rib->type != type)
1808 continue;
1809 if (rib->type != ZEBRA_ROUTE_CONNECT)
paul718e3742002-12-13 20:15:29 +00001810 {
1811 same = rib;
paul718e3742002-12-13 20:15:29 +00001812 break;
1813 }
hassoebf1ead2005-09-21 14:58:20 +00001814 else if ((nexthop = rib->nexthop) &&
1815 nexthop->type == NEXTHOP_TYPE_IFINDEX &&
1816 nexthop->ifindex == ifindex)
1817 {
1818 rib->refcnt++;
1819 return 0;
1820 }
paul718e3742002-12-13 20:15:29 +00001821 }
1822
1823 /* Allocate new rib structure. */
paul4d38fdb2005-04-28 17:35:14 +00001824 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1825
paul718e3742002-12-13 20:15:29 +00001826 rib->type = type;
1827 rib->distance = distance;
1828 rib->flags = flags;
1829 rib->metric = metric;
paulb5f45022003-11-02 07:28:05 +00001830 rib->table = vrf_id;
paul718e3742002-12-13 20:15:29 +00001831 rib->nexthop_num = 0;
1832 rib->uptime = time (NULL);
1833
1834 /* Nexthop settings. */
1835 if (gate)
1836 {
1837 if (ifindex)
1838 nexthop_ipv6_ifindex_add (rib, gate, ifindex);
1839 else
1840 nexthop_ipv6_add (rib, gate);
1841 }
1842 else
1843 nexthop_ifindex_add (rib, ifindex);
1844
1845 /* If this route is kernel route, set FIB flag to the route. */
1846 if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
1847 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1848 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1849
1850 /* Link new rib to node.*/
1851 rib_addnode (rn, rib);
1852
1853 /* Process this route node. */
paul4d38fdb2005-04-28 17:35:14 +00001854 rib_queue_add (&zebrad, rn, same);
1855
paul718e3742002-12-13 20:15:29 +00001856 /* Free implicit route.*/
1857 if (same)
paul4d38fdb2005-04-28 17:35:14 +00001858 rib_delnode (rn, same);
1859
1860 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001861 return 0;
1862}
1863
hassoebf1ead2005-09-21 14:58:20 +00001864/* XXX factor with rib_delete_ipv6 */
paul718e3742002-12-13 20:15:29 +00001865int
1866rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
1867 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
1868{
1869 struct route_table *table;
1870 struct route_node *rn;
1871 struct rib *rib;
1872 struct rib *fib = NULL;
1873 struct rib *same = NULL;
1874 struct nexthop *nexthop;
1875 char buf1[BUFSIZ];
1876 char buf2[BUFSIZ];
1877
1878 /* Apply mask. */
1879 apply_mask_ipv6 (p);
1880
1881 /* Lookup table. */
1882 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1883 if (! table)
1884 return 0;
paul4d38fdb2005-04-28 17:35:14 +00001885
paul718e3742002-12-13 20:15:29 +00001886 /* Lookup route node. */
1887 rn = route_node_lookup (table, (struct prefix *) p);
1888 if (! rn)
1889 {
1890 if (IS_ZEBRA_DEBUG_KERNEL)
1891 {
1892 if (gate)
ajsb6178002004-12-07 21:12:56 +00001893 zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001894 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1895 p->prefixlen,
1896 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1897 ifindex);
1898 else
ajsb6178002004-12-07 21:12:56 +00001899 zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001900 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1901 p->prefixlen,
1902 ifindex);
1903 }
1904 return ZEBRA_ERR_RTNOEXIST;
1905 }
1906
1907 /* Lookup same type route. */
1908 for (rib = rn->info; rib; rib = rib->next)
1909 {
1910 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
1911 fib = rib;
1912
hassoebf1ead2005-09-21 14:58:20 +00001913 if (rib->type != type)
1914 continue;
1915 if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
1916 nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +00001917 {
hassoebf1ead2005-09-21 14:58:20 +00001918 if (rib->refcnt)
paul718e3742002-12-13 20:15:29 +00001919 {
hassoebf1ead2005-09-21 14:58:20 +00001920 rib->refcnt--;
1921 route_unlock_node (rn);
1922 route_unlock_node (rn);
1923 return 0;
paul718e3742002-12-13 20:15:29 +00001924 }
hassoebf1ead2005-09-21 14:58:20 +00001925 same = rib;
1926 break;
paul718e3742002-12-13 20:15:29 +00001927 }
hassoebf1ead2005-09-21 14:58:20 +00001928 /* Make sure that the route found has the same gateway. */
1929 else if (gate == NULL ||
1930 ((nexthop = rib->nexthop) &&
1931 (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
1932 IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
paul718e3742002-12-13 20:15:29 +00001933 {
hassoebf1ead2005-09-21 14:58:20 +00001934 same = rib;
1935 break;
paul718e3742002-12-13 20:15:29 +00001936 }
1937 }
1938
1939 /* If same type of route can't be found and this message is from
1940 kernel. */
1941 if (! same)
1942 {
1943 if (fib && type == ZEBRA_ROUTE_KERNEL)
1944 {
1945 /* Unset flags. */
1946 for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
1947 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1948
1949 UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
1950 }
1951 else
1952 {
1953 if (IS_ZEBRA_DEBUG_KERNEL)
1954 {
1955 if (gate)
ajsb6178002004-12-07 21:12:56 +00001956 zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001957 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1958 p->prefixlen,
1959 inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
1960 ifindex,
1961 type);
1962 else
ajsb6178002004-12-07 21:12:56 +00001963 zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
paul718e3742002-12-13 20:15:29 +00001964 inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
1965 p->prefixlen,
1966 ifindex,
1967 type);
1968 }
1969 route_unlock_node (rn);
1970 return ZEBRA_ERR_RTNOEXIST;
1971 }
1972 }
1973
paul4d38fdb2005-04-28 17:35:14 +00001974 /* Process changes. */
1975 rib_queue_add (&zebrad, rn, same);
1976
paul718e3742002-12-13 20:15:29 +00001977 if (same)
1978 rib_delnode (rn, same);
paul4d38fdb2005-04-28 17:35:14 +00001979
paul718e3742002-12-13 20:15:29 +00001980 route_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +00001981 return 0;
1982}
1983
1984/* Install static route into rib. */
paula1ac18c2005-06-28 17:17:12 +00001985static void
paul718e3742002-12-13 20:15:29 +00001986static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
1987{
1988 struct rib *rib;
1989 struct route_table *table;
1990 struct route_node *rn;
1991
1992 /* Lookup table. */
1993 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
1994 if (! table)
1995 return;
1996
1997 /* Lookup existing route */
1998 rn = route_node_get (table, p);
1999 for (rib = rn->info; rib; rib = rib->next)
2000 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2001 break;
2002
2003 if (rib)
2004 {
2005 /* Same distance static route is there. Update it with new
2006 nexthop. */
paul718e3742002-12-13 20:15:29 +00002007 route_unlock_node (rn);
2008
2009 switch (si->type)
2010 {
2011 case STATIC_IPV6_GATEWAY:
2012 nexthop_ipv6_add (rib, &si->ipv6);
2013 break;
2014 case STATIC_IPV6_IFNAME:
2015 nexthop_ifname_add (rib, si->ifname);
2016 break;
2017 case STATIC_IPV6_GATEWAY_IFNAME:
2018 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2019 break;
2020 }
paul4d38fdb2005-04-28 17:35:14 +00002021 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002022 }
2023 else
2024 {
2025 /* This is new static route. */
paul4d38fdb2005-04-28 17:35:14 +00002026 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
2027
paul718e3742002-12-13 20:15:29 +00002028 rib->type = ZEBRA_ROUTE_STATIC;
2029 rib->distance = si->distance;
2030 rib->metric = 0;
2031 rib->nexthop_num = 0;
2032
2033 switch (si->type)
2034 {
2035 case STATIC_IPV6_GATEWAY:
2036 nexthop_ipv6_add (rib, &si->ipv6);
2037 break;
2038 case STATIC_IPV6_IFNAME:
2039 nexthop_ifname_add (rib, si->ifname);
2040 break;
2041 case STATIC_IPV6_GATEWAY_IFNAME:
2042 nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
2043 break;
2044 }
2045
hasso81dfcaa2003-05-25 19:21:25 +00002046 /* Save the flags of this static routes (reject, blackhole) */
2047 rib->flags = si->flags;
2048
paul718e3742002-12-13 20:15:29 +00002049 /* Link this rib to the tree. */
2050 rib_addnode (rn, rib);
2051
2052 /* Process this prefix. */
paul4d38fdb2005-04-28 17:35:14 +00002053 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002054 }
2055}
2056
paula1ac18c2005-06-28 17:17:12 +00002057static int
paul718e3742002-12-13 20:15:29 +00002058static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
2059{
2060 if (nexthop->type == NEXTHOP_TYPE_IPV6
2061 && si->type == STATIC_IPV6_GATEWAY
2062 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
2063 return 1;
2064 if (nexthop->type == NEXTHOP_TYPE_IFNAME
2065 && si->type == STATIC_IPV6_IFNAME
2066 && strcmp (nexthop->ifname, si->ifname) == 0)
2067 return 1;
2068 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
2069 && si->type == STATIC_IPV6_GATEWAY_IFNAME
2070 && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
2071 && strcmp (nexthop->ifname, si->ifname) == 0)
2072 return 1;
paule8e19462006-01-19 20:16:55 +00002073 return 0;
paul718e3742002-12-13 20:15:29 +00002074}
2075
paula1ac18c2005-06-28 17:17:12 +00002076static void
paul718e3742002-12-13 20:15:29 +00002077static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
2078{
2079 struct route_table *table;
2080 struct route_node *rn;
2081 struct rib *rib;
2082 struct nexthop *nexthop;
2083
2084 /* Lookup table. */
2085 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2086 if (! table)
2087 return;
2088
2089 /* Lookup existing route with type and distance. */
2090 rn = route_node_lookup (table, (struct prefix *) p);
2091 if (! rn)
2092 return;
2093
2094 for (rib = rn->info; rib; rib = rib->next)
2095 if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
2096 break;
2097 if (! rib)
2098 {
2099 route_unlock_node (rn);
2100 return;
2101 }
2102
2103 /* Lookup nexthop. */
2104 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2105 if (static_ipv6_nexthop_same (nexthop, si))
2106 break;
2107
2108 /* Can't find nexthop. */
2109 if (! nexthop)
2110 {
2111 route_unlock_node (rn);
2112 return;
2113 }
2114
2115 /* Check nexthop. */
2116 if (rib->nexthop_num == 1)
2117 {
2118 rib_delnode (rn, rib);
paul4d38fdb2005-04-28 17:35:14 +00002119 rib_queue_add (&zebrad, rn, rib);
paul718e3742002-12-13 20:15:29 +00002120 }
2121 else
2122 {
paul6baeb982003-10-28 03:47:15 +00002123 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
2124 rib_uninstall (rn, rib);
paul319572c2005-09-21 12:30:08 +00002125 nexthop_delete (rib, nexthop);
2126 nexthop_free (nexthop);
2127 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002128 }
paul718e3742002-12-13 20:15:29 +00002129 /* Unlock node. */
2130 route_unlock_node (rn);
2131}
2132
2133/* Add static route into static route configuration. */
2134int
2135static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002136 const char *ifname, u_char flags, u_char distance,
2137 u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002138{
2139 struct route_node *rn;
2140 struct static_ipv6 *si;
2141 struct static_ipv6 *pp;
2142 struct static_ipv6 *cp;
2143 struct route_table *stable;
2144
2145 /* Lookup table. */
2146 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2147 if (! stable)
2148 return -1;
Paul Jakma27b47252006-07-02 16:38:54 +00002149
2150 if (!gate &&
2151 (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
2152 return -1;
2153
2154 if (!ifname &&
2155 (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
2156 return -1;
paul718e3742002-12-13 20:15:29 +00002157
2158 /* Lookup static route prefix. */
2159 rn = route_node_get (stable, p);
2160
2161 /* Do nothing if there is a same static route. */
2162 for (si = rn->info; si; si = si->next)
2163 {
2164 if (distance == si->distance
2165 && type == si->type
2166 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2167 && (! ifname || strcmp (ifname, si->ifname) == 0))
2168 {
2169 route_unlock_node (rn);
2170 return 0;
2171 }
2172 }
2173
2174 /* Make new static route structure. */
2175 si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
2176 memset (si, 0, sizeof (struct static_ipv6));
2177
2178 si->type = type;
2179 si->distance = distance;
hasso81dfcaa2003-05-25 19:21:25 +00002180 si->flags = flags;
paul718e3742002-12-13 20:15:29 +00002181
2182 switch (type)
2183 {
2184 case STATIC_IPV6_GATEWAY:
2185 si->ipv6 = *gate;
2186 break;
2187 case STATIC_IPV6_IFNAME:
2188 si->ifname = XSTRDUP (0, ifname);
2189 break;
2190 case STATIC_IPV6_GATEWAY_IFNAME:
2191 si->ipv6 = *gate;
2192 si->ifname = XSTRDUP (0, ifname);
2193 break;
2194 }
2195
2196 /* Add new static route information to the tree with sort by
2197 distance value and gateway address. */
2198 for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
2199 {
2200 if (si->distance < cp->distance)
2201 break;
2202 if (si->distance > cp->distance)
2203 continue;
2204 }
2205
2206 /* Make linked list. */
2207 if (pp)
2208 pp->next = si;
2209 else
2210 rn->info = si;
2211 if (cp)
2212 cp->prev = si;
2213 si->prev = pp;
2214 si->next = cp;
2215
2216 /* Install into rib. */
2217 static_install_ipv6 (p, si);
2218
2219 return 1;
2220}
2221
2222/* Delete static route from static route configuration. */
2223int
2224static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
hasso39db97e2004-10-12 20:50:58 +00002225 const char *ifname, u_char distance, u_int32_t vrf_id)
paul718e3742002-12-13 20:15:29 +00002226{
2227 struct route_node *rn;
2228 struct static_ipv6 *si;
2229 struct route_table *stable;
2230
2231 /* Lookup table. */
2232 stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
2233 if (! stable)
2234 return -1;
2235
2236 /* Lookup static route prefix. */
2237 rn = route_node_lookup (stable, p);
2238 if (! rn)
2239 return 0;
2240
2241 /* Find same static route is the tree */
2242 for (si = rn->info; si; si = si->next)
2243 if (distance == si->distance
2244 && type == si->type
2245 && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
2246 && (! ifname || strcmp (ifname, si->ifname) == 0))
2247 break;
2248
2249 /* Can't find static route. */
2250 if (! si)
2251 {
2252 route_unlock_node (rn);
2253 return 0;
2254 }
2255
2256 /* Install into rib. */
2257 static_uninstall_ipv6 (p, si);
2258
2259 /* Unlink static route from linked list. */
2260 if (si->prev)
2261 si->prev->next = si->next;
2262 else
2263 rn->info = si->next;
2264 if (si->next)
2265 si->next->prev = si->prev;
2266
2267 /* Free static route configuration. */
paula0f6acd2003-05-14 18:29:13 +00002268 if (ifname)
2269 XFREE (0, si->ifname);
paul718e3742002-12-13 20:15:29 +00002270 XFREE (MTYPE_STATIC_IPV6, si);
2271
2272 return 1;
2273}
2274#endif /* HAVE_IPV6 */
2275
2276/* RIB update function. */
2277void
paula1ac18c2005-06-28 17:17:12 +00002278rib_update (void)
paul718e3742002-12-13 20:15:29 +00002279{
2280 struct route_node *rn;
2281 struct route_table *table;
paul4d38fdb2005-04-28 17:35:14 +00002282
paul718e3742002-12-13 20:15:29 +00002283 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
2284 if (table)
2285 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002286 if (rn->info)
2287 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002288
2289 table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
2290 if (table)
2291 for (rn = route_top (table); rn; rn = route_next (rn))
paul4d38fdb2005-04-28 17:35:14 +00002292 if (rn->info)
2293 rib_queue_add (&zebrad, rn, NULL);
paul718e3742002-12-13 20:15:29 +00002294}
2295
2296/* Interface goes up. */
paula1ac18c2005-06-28 17:17:12 +00002297static void
paul718e3742002-12-13 20:15:29 +00002298rib_if_up (struct interface *ifp)
2299{
2300 rib_update ();
2301}
2302
2303/* Interface goes down. */
paula1ac18c2005-06-28 17:17:12 +00002304static void
paul718e3742002-12-13 20:15:29 +00002305rib_if_down (struct interface *ifp)
2306{
2307 rib_update ();
2308}
2309
2310/* Remove all routes which comes from non main table. */
paula1ac18c2005-06-28 17:17:12 +00002311static void
paul718e3742002-12-13 20:15:29 +00002312rib_weed_table (struct route_table *table)
2313{
2314 struct route_node *rn;
2315 struct rib *rib;
2316 struct rib *next;
2317
2318 if (table)
2319 for (rn = route_top (table); rn; rn = route_next (rn))
2320 for (rib = rn->info; rib; rib = next)
2321 {
2322 next = rib->next;
2323
paulb21b19c2003-06-15 01:28:29 +00002324 if (rib->table != zebrad.rtm_table_default &&
paul718e3742002-12-13 20:15:29 +00002325 rib->table != RT_TABLE_MAIN)
paul4d38fdb2005-04-28 17:35:14 +00002326 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002327 }
2328}
2329
2330/* Delete all routes from non main table. */
2331void
paula1ac18c2005-06-28 17:17:12 +00002332rib_weed_tables (void)
paul718e3742002-12-13 20:15:29 +00002333{
2334 rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2335 rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2336}
2337
2338/* Delete self installed routes after zebra is relaunched. */
paula1ac18c2005-06-28 17:17:12 +00002339static void
paul718e3742002-12-13 20:15:29 +00002340rib_sweep_table (struct route_table *table)
2341{
2342 struct route_node *rn;
2343 struct rib *rib;
2344 struct rib *next;
2345 int ret = 0;
2346
2347 if (table)
2348 for (rn = route_top (table); rn; rn = route_next (rn))
2349 for (rib = rn->info; rib; rib = next)
2350 {
2351 next = rib->next;
2352
2353 if (rib->type == ZEBRA_ROUTE_KERNEL &&
2354 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
2355 {
2356 ret = rib_uninstall_kernel (rn, rib);
2357 if (! ret)
paul4d38fdb2005-04-28 17:35:14 +00002358 rib_delnode (rn, rib);
paul718e3742002-12-13 20:15:29 +00002359 }
2360 }
2361}
2362
2363/* Sweep all RIB tables. */
2364void
paula1ac18c2005-06-28 17:17:12 +00002365rib_sweep_route (void)
paul718e3742002-12-13 20:15:29 +00002366{
2367 rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2368 rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2369}
2370
2371/* Close RIB and clean up kernel routes. */
paula1ac18c2005-06-28 17:17:12 +00002372static void
paul718e3742002-12-13 20:15:29 +00002373rib_close_table (struct route_table *table)
2374{
2375 struct route_node *rn;
2376 struct rib *rib;
2377
2378 if (table)
2379 for (rn = route_top (table); rn; rn = route_next (rn))
2380 for (rib = rn->info; rib; rib = rib->next)
2381 if (! RIB_SYSTEM_ROUTE (rib)
2382 && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
2383 rib_uninstall_kernel (rn, rib);
2384}
2385
2386/* Close all RIB tables. */
2387void
paula1ac18c2005-06-28 17:17:12 +00002388rib_close (void)
paul718e3742002-12-13 20:15:29 +00002389{
2390 rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
2391 rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
2392}
2393
2394/* Routing information base initialize. */
2395void
paula1ac18c2005-06-28 17:17:12 +00002396rib_init (void)
paul718e3742002-12-13 20:15:29 +00002397{
paul4d38fdb2005-04-28 17:35:14 +00002398 rib_queue_init (&zebrad);
paul718e3742002-12-13 20:15:29 +00002399 /* VRF initialization. */
2400 vrf_init ();
2401}