bgpd: tighten bounds checking in RR ORF msg reader
[jleu-quagga.git] / ospfd / ospf_route.c
blob267237b8f57ca366c93683122ff93d6c84cb34c5
1 /*
2 * OSPF routing table.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
23 #include <zebra.h>
25 #include "prefix.h"
26 #include "table.h"
27 #include "memory.h"
28 #include "linklist.h"
29 #include "log.h"
30 #include "if.h"
31 #include "command.h"
32 #include "sockunion.h"
34 #include "ospfd/ospfd.h"
35 #include "ospfd/ospf_interface.h"
36 #include "ospfd/ospf_asbr.h"
37 #include "ospfd/ospf_lsa.h"
38 #include "ospfd/ospf_route.h"
39 #include "ospfd/ospf_spf.h"
40 #include "ospfd/ospf_zebra.h"
41 #include "ospfd/ospf_dump.h"
43 struct ospf_route *
44 ospf_route_new ()
46 struct ospf_route *new;
48 new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
50 new->ctime = quagga_time (NULL);
51 new->mtime = new->ctime;
52 new->paths = list_new ();
53 new->paths->del = (void (*) (void *))ospf_path_free;
55 return new;
58 void
59 ospf_route_free (struct ospf_route *or)
61 if (or->paths)
62 list_delete (or->paths);
64 XFREE (MTYPE_OSPF_ROUTE, or);
67 struct ospf_path *
68 ospf_path_new ()
70 struct ospf_path *new;
72 new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path));
74 return new;
77 static struct ospf_path *
78 ospf_path_dup (struct ospf_path *path)
80 struct ospf_path *new;
82 new = ospf_path_new ();
83 memcpy (new, path, sizeof (struct ospf_path));
85 return new;
88 void
89 ospf_path_free (struct ospf_path *op)
91 XFREE (MTYPE_OSPF_PATH, op);
94 void
95 ospf_route_delete (struct route_table *rt)
97 struct route_node *rn;
98 struct ospf_route *or;
100 for (rn = route_top (rt); rn; rn = route_next (rn))
101 if ((or = rn->info) != NULL)
103 if (or->type == OSPF_DESTINATION_NETWORK)
104 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p,
105 or);
106 else if (or->type == OSPF_DESTINATION_DISCARD)
107 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
111 void
112 ospf_route_table_free (struct route_table *rt)
114 struct route_node *rn;
115 struct ospf_route *or;
117 for (rn = route_top (rt); rn; rn = route_next (rn))
118 if ((or = rn->info) != NULL)
120 ospf_route_free (or);
122 rn->info = NULL;
123 route_unlock_node (rn);
126 route_table_finish (rt);
129 /* If a prefix and a nexthop match any route in the routing table,
130 then return 1, otherwise return 0. */
132 ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
133 struct ospf_route *newor)
135 struct route_node *rn;
136 struct ospf_route *or;
137 struct ospf_path *op;
138 struct ospf_path *newop;
139 struct listnode *n1;
140 struct listnode *n2;
142 if (! rt || ! prefix)
143 return 0;
145 rn = route_node_lookup (rt, (struct prefix *) prefix);
146 if (! rn || ! rn->info)
147 return 0;
149 route_unlock_node (rn);
151 or = rn->info;
152 if (or->type == newor->type && or->cost == newor->cost)
154 if (or->type == OSPF_DESTINATION_NETWORK)
156 if (or->paths->count != newor->paths->count)
157 return 0;
159 /* Check each path. */
160 for (n1 = listhead (or->paths), n2 = listhead (newor->paths);
161 n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2))
163 op = listgetdata (n1);
164 newop = listgetdata (n2);
166 if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
167 return 0;
168 if (op->ifindex != newop->ifindex)
169 return 0;
171 return 1;
173 else if (prefix_same (&rn->p, (struct prefix *) prefix))
174 return 1;
176 return 0;
179 /* delete routes generated from AS-External routes if there is a inter/intra
180 * area route
182 static void
183 ospf_route_delete_same_ext(struct route_table *external_routes,
184 struct route_table *routes)
186 struct route_node *rn,
187 *ext_rn;
189 if ( (external_routes == NULL) || (routes == NULL) )
190 return;
192 /* Remove deleted routes */
193 for ( rn = route_top (routes); rn; rn = route_next (rn) )
195 if (rn && rn->info)
197 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
198 if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
200 if (ext_rn->info)
202 ospf_zebra_delete (p, ext_rn->info);
203 ospf_route_free( ext_rn->info);
204 ext_rn->info = NULL;
206 route_unlock_node (ext_rn);
212 /* rt: Old, cmprt: New */
213 static void
214 ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
216 struct route_node *rn;
217 struct ospf_route *or;
219 for (rn = route_top (rt); rn; rn = route_next (rn))
220 if ((or = rn->info) != NULL)
221 if (or->path_type == OSPF_PATH_INTRA_AREA ||
222 or->path_type == OSPF_PATH_INTER_AREA)
224 if (or->type == OSPF_DESTINATION_NETWORK)
226 if (! ospf_route_match_same (cmprt,
227 (struct prefix_ipv4 *) &rn->p, or))
228 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
230 else if (or->type == OSPF_DESTINATION_DISCARD)
231 if (! ospf_route_match_same (cmprt,
232 (struct prefix_ipv4 *) &rn->p, or))
233 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
237 /* Install routes to table. */
238 void
239 ospf_route_install (struct ospf *ospf, struct route_table *rt)
241 struct route_node *rn;
242 struct ospf_route *or;
244 /* rt contains new routing table, new_table contains an old one.
245 updating pointers */
246 if (ospf->old_table)
247 ospf_route_table_free (ospf->old_table);
249 ospf->old_table = ospf->new_table;
250 ospf->new_table = rt;
252 /* Delete old routes. */
253 if (ospf->old_table)
254 ospf_route_delete_uniq (ospf->old_table, rt);
255 if (ospf->old_external_route)
256 ospf_route_delete_same_ext (ospf->old_external_route, rt);
258 /* Install new routes. */
259 for (rn = route_top (rt); rn; rn = route_next (rn))
260 if ((or = rn->info) != NULL)
262 if (or->type == OSPF_DESTINATION_NETWORK)
264 if (! ospf_route_match_same (ospf->old_table,
265 (struct prefix_ipv4 *)&rn->p, or))
266 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
268 else if (or->type == OSPF_DESTINATION_DISCARD)
269 if (! ospf_route_match_same (ospf->old_table,
270 (struct prefix_ipv4 *) &rn->p, or))
271 ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
275 static void
276 ospf_intra_route_add (struct route_table *rt, struct vertex *v,
277 struct ospf_area *area)
279 struct route_node *rn;
280 struct ospf_route *or;
281 struct prefix_ipv4 p;
282 struct ospf_path *path;
283 struct vertex_parent *parent;
284 struct listnode *node, *nnode;
286 p.family = AF_INET;
287 p.prefix = v->id;
288 if (v->type == OSPF_VERTEX_ROUTER)
289 p.prefixlen = IPV4_MAX_BITLEN;
290 else
292 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
293 p.prefixlen = ip_masklen (lsa->mask);
295 apply_mask_ipv4 (&p);
297 rn = route_node_get (rt, (struct prefix *) &p);
298 if (rn->info)
300 zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id));
301 route_unlock_node (rn);
302 return;
305 or = ospf_route_new ();
307 if (v->type == OSPF_VERTEX_NETWORK)
309 or->type = OSPF_DESTINATION_NETWORK;
311 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent))
313 path = ospf_path_new ();
314 path->nexthop = parent->nexthop->router;
315 listnode_add (or->paths, path);
318 else
319 or->type = OSPF_DESTINATION_ROUTER;
321 or->id = v->id;
322 or->u.std.area_id = area->area_id;
323 or->u.std.external_routing= area->external_routing;
324 or->path_type = OSPF_PATH_INTRA_AREA;
325 or->cost = v->distance;
327 rn->info = or;
330 /* RFC2328 16.1. (4). For "router". */
331 void
332 ospf_intra_add_router (struct route_table *rt, struct vertex *v,
333 struct ospf_area *area)
335 struct route_node *rn;
336 struct ospf_route *or;
337 struct prefix_ipv4 p;
338 struct router_lsa *lsa;
340 if (IS_DEBUG_OSPF_EVENT)
341 zlog_debug ("ospf_intra_add_router: Start");
343 lsa = (struct router_lsa *) v->lsa;
345 if (IS_DEBUG_OSPF_EVENT)
346 zlog_debug ("ospf_intra_add_router: LS ID: %s",
347 inet_ntoa (lsa->header.id));
349 if (!OSPF_IS_AREA_BACKBONE(area))
350 ospf_vl_up_check (area, lsa->header.id, v);
352 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
353 area->shortcut_capability = 0;
355 /* If the newly added vertex is an area border router or AS boundary
356 router, a routing table entry is added whose destination type is
357 "router". */
358 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
360 if (IS_DEBUG_OSPF_EVENT)
361 zlog_debug ("ospf_intra_add_router: "
362 "this router is neither ASBR nor ABR, skipping it");
363 return;
366 /* Update ABR and ASBR count in this area. */
367 if (IS_ROUTER_LSA_BORDER (lsa))
368 area->abr_count++;
369 if (IS_ROUTER_LSA_EXTERNAL (lsa))
370 area->asbr_count++;
372 /* The Options field found in the associated router-LSA is copied
373 into the routing table entry's Optional capabilities field. Call
374 the newly added vertex Router X. */
375 or = ospf_route_new ();
377 or->id = v->id;
378 or->u.std.area_id = area->area_id;
379 or->u.std.external_routing = area->external_routing;
380 or->path_type = OSPF_PATH_INTRA_AREA;
381 or->cost = v->distance;
382 or->type = OSPF_DESTINATION_ROUTER;
383 or->u.std.origin = (struct lsa_header *) lsa;
384 or->u.std.options = lsa->header.options;
385 or->u.std.flags = lsa->flags;
387 /* If Router X is the endpoint of one of the calculating router's
388 virtual links, and the virtual link uses Area A as Transit area:
389 the virtual link is declared up, the IP address of the virtual
390 interface is set to the IP address of the outgoing interface
391 calculated above for Router X, and the virtual neighbor's IP
392 address is set to Router X's interface address (contained in
393 Router X's router-LSA) that points back to the root of the
394 shortest- path tree; equivalently, this is the interface that
395 points back to Router X's parent vertex on the shortest-path tree
396 (similar to the calculation in Section 16.1.1). */
398 p.family = AF_INET;
399 p.prefix = v->id;
400 p.prefixlen = IPV4_MAX_BITLEN;
402 if (IS_DEBUG_OSPF_EVENT)
403 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
404 inet_ntoa (p.prefix), p.prefixlen);
406 rn = route_node_get (rt, (struct prefix *) &p);
408 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
409 if (rn->info == NULL)
410 rn->info = list_new ();
411 else
412 route_unlock_node (rn);
414 ospf_route_copy_nexthops_from_vertex (or, v);
416 listnode_add (rn->info, or);
418 if (IS_DEBUG_OSPF_EVENT)
419 zlog_debug ("ospf_intra_add_router: Stop");
422 /* RFC2328 16.1. (4). For transit network. */
423 void
424 ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
425 struct ospf_area *area)
427 struct route_node *rn;
428 struct ospf_route *or;
429 struct prefix_ipv4 p;
430 struct network_lsa *lsa;
432 lsa = (struct network_lsa*) v->lsa;
434 /* If the newly added vertex is a transit network, the routing table
435 entry for the network is located. The entry's Destination ID is
436 the IP network number, which can be obtained by masking the
437 Vertex ID (Link State ID) with its associated subnet mask (found
438 in the body of the associated network-LSA). */
439 p.family = AF_INET;
440 p.prefix = v->id;
441 p.prefixlen = ip_masklen (lsa->mask);
442 apply_mask_ipv4 (&p);
444 rn = route_node_get (rt, (struct prefix *) &p);
446 /* If the routing table entry already exists (i.e., there is already
447 an intra-area route to the destination installed in the routing
448 table), multiple vertices have mapped to the same IP network.
449 For example, this can occur when a new Designated Router is being
450 established. In this case, the current routing table entry
451 should be overwritten if and only if the newly found path is just
452 as short and the current routing table entry's Link State Origin
453 has a smaller Link State ID than the newly added vertex' LSA. */
454 if (rn->info)
456 struct ospf_route *cur_or;
458 route_unlock_node (rn);
459 cur_or = rn->info;
461 if (v->distance > cur_or->cost ||
462 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
463 return;
465 ospf_route_free (rn->info);
468 or = ospf_route_new ();
470 or->id = v->id;
471 or->u.std.area_id = area->area_id;
472 or->u.std.external_routing = area->external_routing;
473 or->path_type = OSPF_PATH_INTRA_AREA;
474 or->cost = v->distance;
475 or->type = OSPF_DESTINATION_NETWORK;
476 or->u.std.origin = (struct lsa_header *) lsa;
478 ospf_route_copy_nexthops_from_vertex (or, v);
480 rn->info = or;
483 /* RFC2328 16.1. second stage. */
484 void
485 ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
486 struct vertex *v, struct ospf_area *area,
487 int parent_is_root)
489 u_int32_t cost;
490 struct route_node *rn;
491 struct ospf_route *or;
492 struct prefix_ipv4 p;
493 struct router_lsa *lsa;
494 struct ospf_interface *oi;
495 struct ospf_path *path;
497 if (IS_DEBUG_OSPF_EVENT)
498 zlog_debug ("ospf_intra_add_stub(): Start");
500 lsa = (struct router_lsa *) v->lsa;
502 p.family = AF_INET;
503 p.prefix = link->link_id;
504 p.prefixlen = ip_masklen (link->link_data);
505 apply_mask_ipv4 (&p);
507 if (IS_DEBUG_OSPF_EVENT)
508 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
509 inet_ntoa (p.prefix), p.prefixlen);
511 /* (1) Calculate the distance D of stub network from the root. D is
512 equal to the distance from the root to the router vertex
513 (calculated in stage 1), plus the stub network link's advertised
514 cost. */
515 cost = v->distance + ntohs (link->m[0].metric);
517 if (IS_DEBUG_OSPF_EVENT)
518 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
519 v->distance, ntohs(link->m[0].metric), cost);
521 /* PtP links with /32 masks adds host routes to remote, directly
522 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
523 * Such routes can just be ignored for the sake of tidyness.
525 if (parent_is_root && link->link_data.s_addr == 0xffffffff &&
526 ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id))
528 if (IS_DEBUG_OSPF_EVENT)
529 zlog_debug ("%s: ignoring host route %s/32 to self.",
530 __func__, inet_ntoa (link->link_id));
531 return;
534 rn = route_node_get (rt, (struct prefix *) &p);
536 /* Lookup current routing table. */
537 if (rn->info)
539 struct ospf_route *cur_or;
541 route_unlock_node (rn);
543 cur_or = rn->info;
545 if (IS_DEBUG_OSPF_EVENT)
546 zlog_debug ("ospf_intra_add_stub(): "
547 "another route to the same prefix found with cost %u",
548 cur_or->cost);
550 /* Compare this distance to the current best cost to the stub
551 network. This is done by looking up the stub network's
552 current routing table entry. If the calculated distance D is
553 larger, go on to examine the next stub network link in the
554 LSA. */
555 if (cost > cur_or->cost)
557 if (IS_DEBUG_OSPF_EVENT)
558 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
559 return;
562 /* (2) If this step is reached, the stub network's routing table
563 entry must be updated. Calculate the set of next hops that
564 would result from using the stub network link. This
565 calculation is shown in Section 16.1.1; input to this
566 calculation is the destination (the stub network) and the
567 parent vertex (the router vertex). If the distance D is the
568 same as the current routing table cost, simply add this set
569 of next hops to the routing table entry's list of next hops.
570 In this case, the routing table already has a Link State
571 Origin. If this Link State Origin is a router-LSA whose Link
572 State ID is smaller than V's Router ID, reset the Link State
573 Origin to V's router-LSA. */
575 if (cost == cur_or->cost)
577 if (IS_DEBUG_OSPF_EVENT)
578 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
580 ospf_route_copy_nexthops_from_vertex (cur_or, v);
582 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
583 cur_or->u.std.origin = (struct lsa_header *) lsa;
584 return;
587 /* Otherwise D is smaller than the routing table cost.
588 Overwrite the current routing table entry by setting the
589 routing table entry's cost to D, and by setting the entry's
590 list of next hops to the newly calculated set. Set the
591 routing table entry's Link State Origin to V's router-LSA.
592 Then go on to examine the next stub network link. */
594 if (cost < cur_or->cost)
596 if (IS_DEBUG_OSPF_EVENT)
597 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
599 cur_or->cost = cost;
601 list_delete_all_node (cur_or->paths);
603 ospf_route_copy_nexthops_from_vertex (cur_or, v);
605 cur_or->u.std.origin = (struct lsa_header *) lsa;
606 return;
610 if (IS_DEBUG_OSPF_EVENT)
611 zlog_debug ("ospf_intra_add_stub(): installing new route");
613 or = ospf_route_new ();
615 or->id = v->id;
616 or->u.std.area_id = area->area_id;
617 or->u.std.external_routing = area->external_routing;
618 or->path_type = OSPF_PATH_INTRA_AREA;
619 or->cost = cost;
620 or->type = OSPF_DESTINATION_NETWORK;
621 or->u.std.origin = (struct lsa_header *) lsa;
623 /* Nexthop is depend on connection type. */
624 if (v != area->spf)
626 if (IS_DEBUG_OSPF_EVENT)
627 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
628 ospf_route_copy_nexthops_from_vertex (or, v);
630 else
632 if (IS_DEBUG_OSPF_EVENT)
633 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
635 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
637 if (IS_DEBUG_OSPF_EVENT)
638 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
639 IF_NAME (oi));
641 path = ospf_path_new ();
642 path->nexthop.s_addr = 0;
643 path->ifindex = oi->ifp->ifindex;
644 listnode_add (or->paths, path);
646 else
648 if (IS_DEBUG_OSPF_EVENT)
649 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
653 rn->info = or;
655 if (IS_DEBUG_OSPF_EVENT)
656 zlog_debug("ospf_intra_add_stub(): Stop");
659 const char *ospf_path_type_str[] =
661 "unknown-type",
662 "intra-area",
663 "inter-area",
664 "type1-external",
665 "type2-external"
668 void
669 ospf_route_table_dump (struct route_table *rt)
671 struct route_node *rn;
672 struct ospf_route *or;
673 char buf1[BUFSIZ];
674 char buf2[BUFSIZ];
675 struct listnode *pnode;
676 struct ospf_path *path;
678 #if 0
679 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
680 zlog_debug (" Hop(s) Router(s)");
681 #endif /* 0 */
683 zlog_debug ("========== OSPF routing table ==========");
684 for (rn = route_top (rt); rn; rn = route_next (rn))
685 if ((or = rn->info) != NULL)
687 if (or->type == OSPF_DESTINATION_NETWORK)
689 zlog_debug ("N %s/%d\t%s\t%s\t%d",
690 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
691 rn->p.prefixlen,
692 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
693 BUFSIZ),
694 ospf_path_type_str[or->path_type],
695 or->cost);
696 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
697 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
699 else
700 zlog_debug ("R %s\t%s\t%s\t%d",
701 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
702 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
703 BUFSIZ),
704 ospf_path_type_str[or->path_type],
705 or->cost);
707 zlog_debug ("========================================");
710 /* This is 16.4.1 implementation.
711 o Intra-area paths using non-backbone areas are always the most preferred.
712 o The other paths, intra-area backbone paths and inter-area paths,
713 are of equal preference. */
714 static int
715 ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
716 struct ospf_route *r2)
718 u_char r1_type, r2_type;
720 r1_type = r1->path_type;
721 r2_type = r2->path_type;
723 /* If RFC1583Compat flag is on -- all paths are equal. */
724 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
725 return 0;
727 /* r1/r2 itself is backbone, and it's Inter-area path. */
728 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
729 r1_type = OSPF_PATH_INTER_AREA;
730 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
731 r2_type = OSPF_PATH_INTER_AREA;
733 return (r1_type - r2_type);
736 /* Compare two routes.
737 ret < 0 -- r1 is better.
738 ret == 0 -- r1 and r2 are the same.
739 ret > 0 -- r2 is better. */
741 ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
742 struct ospf_route *r2)
744 int ret = 0;
746 /* Path types of r1 and r2 are not the same. */
747 if ((ret = (r1->path_type - r2->path_type)))
748 return ret;
750 if (IS_DEBUG_OSPF_EVENT)
751 zlog_debug ("Route[Compare]: Path types are the same.");
752 /* Path types are the same, compare any cost. */
753 switch (r1->path_type)
755 case OSPF_PATH_INTRA_AREA:
756 case OSPF_PATH_INTER_AREA:
757 break;
758 case OSPF_PATH_TYPE1_EXTERNAL:
759 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
761 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
762 if (ret != 0)
763 return ret;
765 break;
766 case OSPF_PATH_TYPE2_EXTERNAL:
767 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
768 return ret;
770 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
772 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
773 if (ret != 0)
774 return ret;
776 break;
779 /* Anyway, compare the costs. */
780 return (r1->cost - r2->cost);
783 static int
784 ospf_path_exist (struct list *plist, struct in_addr nexthop,
785 struct ospf_interface *oi)
787 struct listnode *node, *nnode;
788 struct ospf_path *path;
790 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
791 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) &&
792 path->ifindex == oi->ifp->ifindex)
793 return 1;
795 return 0;
798 void
799 ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
800 struct vertex *v)
802 struct listnode *node;
803 struct ospf_path *path;
804 struct vertex_nexthop *nexthop;
805 struct vertex_parent *vp;
807 assert (to->paths);
809 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
811 nexthop = vp->nexthop;
813 if (nexthop->oi != NULL)
815 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
817 path = ospf_path_new ();
818 path->nexthop = nexthop->router;
819 path->ifindex = nexthop->oi->ifp->ifindex;
820 listnode_add (to->paths, path);
826 struct ospf_path *
827 ospf_path_lookup (struct list *plist, struct ospf_path *path)
829 struct listnode *node;
830 struct ospf_path *op;
832 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
834 if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop))
835 continue;
836 if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
837 continue;
838 if (op->ifindex != path->ifindex)
839 continue;
840 return op;
842 return NULL;
845 void
846 ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
848 struct listnode *node, *nnode;
849 struct ospf_path *path;
851 assert (to->paths);
853 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
854 /* The same routes are just discarded. */
855 if (!ospf_path_lookup (to->paths, path))
856 listnode_add (to->paths, ospf_path_dup (path));
859 void
860 ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
863 list_delete_all_node (to->paths);
864 ospf_route_copy_nexthops (to, from);
867 void
868 ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
869 struct ospf_route *over)
871 route_lock_node (rn);
872 ospf_route_free (rn->info);
874 ospf_route_copy_nexthops (new_or, over->paths);
875 rn->info = new_or;
876 route_unlock_node (rn);
879 void
880 ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
881 struct ospf_route *new_or, struct ospf_route *over)
883 struct route_node *rn;
885 rn = route_node_get (rt, (struct prefix *) p);
887 ospf_route_copy_nexthops (new_or, over->paths);
889 if (rn->info)
891 if (IS_DEBUG_OSPF_EVENT)
892 zlog_debug ("ospf_route_add(): something's wrong !");
893 route_unlock_node (rn);
894 return;
897 rn->info = new_or;
900 void
901 ospf_prune_unreachable_networks (struct route_table *rt)
903 struct route_node *rn, *next;
904 struct ospf_route *or;
906 if (IS_DEBUG_OSPF_EVENT)
907 zlog_debug ("Pruning unreachable networks");
909 for (rn = route_top (rt); rn; rn = next)
911 next = route_next (rn);
912 if (rn->info != NULL)
914 or = rn->info;
915 if (listcount (or->paths) == 0)
917 if (IS_DEBUG_OSPF_EVENT)
918 zlog_debug ("Pruning route to %s/%d",
919 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
921 ospf_route_free (or);
922 rn->info = NULL;
923 route_unlock_node (rn);
929 void
930 ospf_prune_unreachable_routers (struct route_table *rtrs)
932 struct route_node *rn, *next;
933 struct ospf_route *or;
934 struct listnode *node, *nnode;
935 struct list *paths;
937 if (IS_DEBUG_OSPF_EVENT)
938 zlog_debug ("Pruning unreachable routers");
940 for (rn = route_top (rtrs); rn; rn = next)
942 next = route_next (rn);
943 if ((paths = rn->info) == NULL)
944 continue;
946 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
948 if (listcount (or->paths) == 0)
950 if (IS_DEBUG_OSPF_EVENT)
952 zlog_debug ("Pruning route to rtr %s",
953 inet_ntoa (rn->p.u.prefix4));
954 zlog_debug (" via area %s",
955 inet_ntoa (or->u.std.area_id));
958 listnode_delete (paths, or);
959 ospf_route_free (or);
963 if (listcount (paths) == 0)
965 if (IS_DEBUG_OSPF_EVENT)
966 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
968 list_delete (paths);
969 rn->info = NULL;
970 route_unlock_node (rn);
976 ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
977 struct prefix_ipv4 *p)
979 struct route_node *rn;
980 struct ospf_route *or, *new_or;
982 rn = route_node_get (rt, (struct prefix *) p);
984 if (rn == NULL)
986 if (IS_DEBUG_OSPF_EVENT)
987 zlog_debug ("ospf_add_discard_route(): router installation error");
988 return 0;
991 if (rn->info) /* If the route to the same destination is found */
993 route_unlock_node (rn);
995 or = rn->info;
997 if (or->path_type == OSPF_PATH_INTRA_AREA)
999 if (IS_DEBUG_OSPF_EVENT)
1000 zlog_debug ("ospf_add_discard_route(): "
1001 "an intra-area route exists");
1002 return 0;
1005 if (or->type == OSPF_DESTINATION_DISCARD)
1007 if (IS_DEBUG_OSPF_EVENT)
1008 zlog_debug ("ospf_add_discard_route(): "
1009 "discard entry already installed");
1010 return 0;
1013 ospf_route_free (rn->info);
1016 new_or = ospf_route_new ();
1017 new_or->type = OSPF_DESTINATION_DISCARD;
1018 new_or->id.s_addr = 0;
1019 new_or->cost = 0;
1020 new_or->u.std.area_id = area->area_id;
1021 new_or->u.std.external_routing = area->external_routing;
1022 new_or->path_type = OSPF_PATH_INTER_AREA;
1023 rn->info = new_or;
1025 ospf_zebra_add_discard (p);
1027 return 1;
1030 void
1031 ospf_delete_discard_route (struct prefix_ipv4 *p)
1033 ospf_zebra_delete_discard(p);