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