back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_abr.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 443 828 53.5 %
Date: 2023-02-24 14:41:08 Functions: 17 27 63.0 %

          Line data    Source code
       1             : /*
       2             :  * Area Border Router function.
       3             :  * Copyright (C) 2004 Yasuhiro Ohara
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       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.
      11             :  *
      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.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "log.h"
      25             : #include "prefix.h"
      26             : #include "table.h"
      27             : #include "vty.h"
      28             : #include "linklist.h"
      29             : #include "command.h"
      30             : #include "thread.h"
      31             : #include "plist.h"
      32             : #include "filter.h"
      33             : 
      34             : #include "ospf6_proto.h"
      35             : #include "ospf6_route.h"
      36             : #include "ospf6_lsa.h"
      37             : #include "ospf6_route.h"
      38             : #include "ospf6_lsdb.h"
      39             : #include "ospf6_message.h"
      40             : #include "ospf6_zebra.h"
      41             : 
      42             : #include "ospf6_top.h"
      43             : #include "ospf6_area.h"
      44             : #include "ospf6_interface.h"
      45             : #include "ospf6_neighbor.h"
      46             : 
      47             : #include "ospf6_flood.h"
      48             : #include "ospf6_intra.h"
      49             : #include "ospf6_asbr.h"
      50             : #include "ospf6_abr.h"
      51             : #include "ospf6d.h"
      52             : #include "ospf6_nssa.h"
      53             : 
      54             : unsigned char conf_debug_ospf6_abr;
      55             : 
      56         498 : int ospf6_ls_origin_same(struct ospf6_path *o_path, struct ospf6_path *r_path)
      57             : {
      58         498 :         if (((o_path->origin.type == r_path->origin.type)
      59         490 :              && (o_path->origin.id == r_path->origin.id)
      60         434 :              && (o_path->origin.adv_router == r_path->origin.adv_router)))
      61             :                 return 1;
      62             :         else
      63          91 :                 return 0;
      64             : }
      65             : 
      66         580 : bool ospf6_check_and_set_router_abr(struct ospf6 *o)
      67             : {
      68         580 :         struct listnode *node;
      69         580 :         struct ospf6_area *oa;
      70         580 :         int area_count = 0;
      71         580 :         bool is_backbone = false;
      72             : 
      73        1885 :         for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
      74         725 :                 if (IS_OSPF6_DEBUG_ABR)
      75           0 :                         zlog_debug("%s, area_id %pI4", __func__, &oa->area_id);
      76         725 :                 if (IS_AREA_ENABLED(oa))
      77         619 :                         area_count++;
      78             : 
      79         725 :                 if (o->backbone == oa)
      80         361 :                         is_backbone = true;
      81             :         }
      82             : 
      83         580 :         if ((area_count > 1) && (is_backbone)) {
      84          89 :                 if (IS_OSPF6_DEBUG_ABR)
      85           0 :                         zlog_debug("%s : set flag OSPF6_FLAG_ABR", __func__);
      86          89 :                 SET_FLAG(o->flag, OSPF6_FLAG_ABR);
      87          89 :                 return true;
      88             :         } else {
      89         491 :                 if (IS_OSPF6_DEBUG_ABR)
      90           0 :                         zlog_debug("%s : reset flag OSPF6_FLAG_ABR", __func__);
      91         491 :                 UNSET_FLAG(o->flag, OSPF6_FLAG_ABR);
      92         491 :                 return false;
      93             :         }
      94             : }
      95             : 
      96         119 : static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route,
      97             :                                              struct ospf6_area *area)
      98             : {
      99         119 :         struct ospf6_interface *oi;
     100             : 
     101         119 :         oi = ospf6_interface_lookup_by_ifindex(
     102         119 :                 ospf6_route_get_first_nh_index(route), area->ospf6->vrf_id);
     103         119 :         if (oi && oi->area && oi->area == area)
     104             :                 return 1;
     105             :         else
     106         119 :                 return 0;
     107             : }
     108             : 
     109           0 : static void ospf6_abr_delete_route(struct ospf6_route *summary,
     110             :                                    struct ospf6_route_table *summary_table,
     111             :                                    struct ospf6_lsa *old)
     112             : {
     113           0 :         if (summary) {
     114           0 :                 ospf6_route_remove(summary, summary_table);
     115             :         }
     116             : 
     117           0 :         if (old && !OSPF6_LSA_IS_MAXAGE(old))
     118           0 :                 ospf6_lsa_purge(old);
     119           0 : }
     120             : 
     121           3 : void ospf6_abr_enable_area(struct ospf6_area *area)
     122             : {
     123           3 :         struct ospf6_area *oa;
     124           3 :         struct listnode *node, *nnode;
     125             : 
     126          12 :         for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa))
     127             :                 /* update B bit for each area */
     128           6 :                 OSPF6_ROUTER_LSA_SCHEDULE(oa);
     129           3 : }
     130             : 
     131          19 : void ospf6_abr_disable_area(struct ospf6_area *area)
     132             : {
     133          19 :         struct ospf6_area *oa;
     134          19 :         struct ospf6_route *ro, *nro;
     135          19 :         struct ospf6_lsa *old;
     136          19 :         struct listnode *node, *nnode;
     137             : 
     138             :         /* Withdraw all summary prefixes previously originated */
     139          21 :         for (ro = ospf6_route_head(area->summary_prefix); ro; ro = nro) {
     140           2 :                 nro = ospf6_route_next(ro);
     141           4 :                 old = ospf6_lsdb_lookup(ro->path.origin.type,
     142             :                                         ro->path.origin.id,
     143           2 :                                         area->ospf6->router_id, area->lsdb);
     144           2 :                 if (old)
     145           2 :                         ospf6_lsa_purge(old);
     146           2 :                 ospf6_route_remove(ro, area->summary_prefix);
     147             :         }
     148             : 
     149             :         /* Withdraw all summary router-routes previously originated */
     150          21 :         for (ro = ospf6_route_head(area->summary_router); ro; ro = nro) {
     151           2 :                 nro = ospf6_route_next(ro);
     152           4 :                 old = ospf6_lsdb_lookup(ro->path.origin.type,
     153             :                                         ro->path.origin.id,
     154           2 :                                         area->ospf6->router_id, area->lsdb);
     155           2 :                 if (old)
     156           2 :                         ospf6_lsa_purge(old);
     157           2 :                 ospf6_route_remove(ro, area->summary_router);
     158             :         }
     159             : 
     160             :         /* Schedule Router-LSA for each area (ABR status may change) */
     161          63 :         for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa))
     162             :                 /* update B bit for each area */
     163          25 :                 OSPF6_ROUTER_LSA_SCHEDULE(oa);
     164          19 : }
     165             : 
     166             : /* RFC 2328 12.4.3. Summary-LSAs */
     167             : /* Returns 1 if a summary LSA has been generated for the area */
     168             : /* This is used by the area/range logic to add/remove blackhole routes */
     169         744 : int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
     170             :                                         struct ospf6_area *area)
     171             : {
     172         744 :         struct ospf6_lsa *lsa, *old = NULL;
     173         744 :         struct ospf6_route *summary, *range = NULL;
     174         744 :         struct ospf6_area *route_area;
     175         744 :         char buffer[OSPF6_MAX_LSASIZE];
     176         744 :         struct ospf6_lsa_header *lsa_header;
     177         744 :         caddr_t p;
     178         744 :         struct ospf6_inter_prefix_lsa *prefix_lsa;
     179         744 :         struct ospf6_inter_router_lsa *router_lsa;
     180         744 :         struct ospf6_route_table *summary_table = NULL;
     181         744 :         uint16_t type;
     182         744 :         int is_debug = 0;
     183             : 
     184         744 :         if (IS_OSPF6_DEBUG_ABR) {
     185           0 :                 char buf[BUFSIZ];
     186             : 
     187           0 :                 if (route->type == OSPF6_DEST_TYPE_ROUTER)
     188           0 :                         inet_ntop(AF_INET,
     189           0 :                                   &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
     190             :                                   sizeof(buf));
     191             :                 else
     192           0 :                         prefix2str(&route->prefix, buf, sizeof(buf));
     193             : 
     194           0 :                 zlog_debug("%s : start area %s, route %s", __func__, area->name,
     195             :                            buf);
     196             :         }
     197             : 
     198         744 :         if (route->type == OSPF6_DEST_TYPE_ROUTER)
     199         276 :                 summary_table = area->summary_router;
     200             :         else
     201         468 :                 summary_table = area->summary_prefix;
     202             : 
     203         744 :         summary = ospf6_route_lookup(&route->prefix, summary_table);
     204         744 :         if (summary) {
     205         120 :                 old = ospf6_lsdb_lookup(summary->path.origin.type,
     206             :                                         summary->path.origin.id,
     207          60 :                                         area->ospf6->router_id, area->lsdb);
     208             :                 /* Reset the OSPF6_LSA_UNAPPROVED flag */
     209          60 :                 if (old)
     210          60 :                         UNSET_FLAG(old->flag, OSPF6_LSA_UNAPPROVED);
     211             :         }
     212             : 
     213             :         /* Only destination type network, range or ASBR are considered */
     214         744 :         if (route->type != OSPF6_DEST_TYPE_NETWORK
     215         744 :             && route->type != OSPF6_DEST_TYPE_RANGE
     216         276 :             && ((route->type != OSPF6_DEST_TYPE_ROUTER)
     217         276 :                 || !CHECK_FLAG(route->path.router_bits, OSPF6_ROUTER_BIT_E))) {
     218          77 :                 if (IS_OSPF6_DEBUG_ABR)
     219           0 :                         zlog_debug(
     220             :                                 "%s: Route type %d flag 0x%x is none of network, range nor ASBR, ignore",
     221             :                                 __func__, route->type, route->path.router_bits);
     222          77 :                 return 0;
     223             :         }
     224             : 
     225             :         /* AS External routes are never considered */
     226         667 :         if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1
     227         667 :             || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
     228         153 :                 if (IS_OSPF6_DEBUG_ABR)
     229           0 :                         zlog_debug("%s : Path type is external, skip",
     230             :                                    __func__);
     231         153 :                 return 0;
     232             :         }
     233             : 
     234             :         /* do not generate if the path's area is the same as target area */
     235         514 :         if (route->path.area_id == area->area_id) {
     236         395 :                 if (IS_OSPF6_DEBUG_ABR)
     237           0 :                         zlog_debug(
     238             :                                 "%s: The route is in the area itself, ignore",
     239             :                                 __func__);
     240         395 :                 return 0;
     241             :         }
     242             : 
     243         119 :         if (route->type == OSPF6_DEST_TYPE_NETWORK) {
     244          56 :                 bool filter = false;
     245             : 
     246          56 :                 route_area =
     247          56 :                         ospf6_area_lookup(route->path.area_id, area->ospf6);
     248          56 :                 assert(route_area);
     249             : 
     250             :                 /* Check export-list */
     251          56 :                 if (EXPORT_LIST(route_area)
     252           0 :                     && access_list_apply(EXPORT_LIST(route_area),
     253             :                                          &route->prefix)
     254             :                                == FILTER_DENY) {
     255           0 :                         if (IS_OSPF6_DEBUG_ABR)
     256           0 :                                 zlog_debug(
     257             :                                         "%s: prefix %pFX was denied by export-list",
     258             :                                         __func__, &route->prefix);
     259             :                         filter = true;
     260             :                 }
     261             : 
     262             :                 /* Check output prefix-list */
     263          56 :                 if (PREFIX_LIST_OUT(route_area)
     264           0 :                     && prefix_list_apply(PREFIX_LIST_OUT(route_area),
     265             :                                          &route->prefix)
     266             :                                != PREFIX_PERMIT) {
     267           0 :                         if (IS_OSPF6_DEBUG_ABR)
     268           0 :                                 zlog_debug(
     269             :                                         "%s: prefix %pFX was denied by prefix-list out",
     270             :                                         __func__, &route->prefix);
     271             :                         filter = true;
     272             :                 }
     273             : 
     274             :                 /* Check import-list */
     275          56 :                 if (IMPORT_LIST(area)
     276           0 :                     && access_list_apply(IMPORT_LIST(area), &route->prefix)
     277             :                                == FILTER_DENY) {
     278           0 :                         if (IS_OSPF6_DEBUG_ABR)
     279           0 :                                 zlog_debug(
     280             :                                         "%s: prefix %pFX was denied by import-list",
     281             :                                         __func__, &route->prefix);
     282             :                         filter = true;
     283             :                 }
     284             : 
     285             :                 /* Check input prefix-list */
     286          56 :                 if (PREFIX_LIST_IN(area)
     287           0 :                     && prefix_list_apply(PREFIX_LIST_IN(area), &route->prefix)
     288             :                                != PREFIX_PERMIT) {
     289           0 :                         if (IS_OSPF6_DEBUG_ABR)
     290           0 :                                 zlog_debug(
     291             :                                         "%s: prefix %pFX was denied by prefix-list in",
     292             :                                         __func__, &route->prefix);
     293             :                         filter = true;
     294             :                 }
     295             : 
     296          56 :                 if (filter) {
     297           0 :                         if (summary) {
     298           0 :                                 ospf6_route_remove(summary, summary_table);
     299           0 :                                 if (old)
     300           0 :                                         ospf6_lsa_purge(old);
     301             :                         }
     302           0 :                         return 0;
     303             :                 }
     304             :         }
     305             : 
     306             :         /* do not generate if the nexthops belongs to the target area */
     307         119 :         if (ospf6_abr_nexthops_belong_to_area(route, area)) {
     308           0 :                 if (IS_OSPF6_DEBUG_ABR)
     309           0 :                         zlog_debug(
     310             :                                 "%s: The route's nexthop is in the same area, ignore",
     311             :                                 __func__);
     312           0 :                 return 0;
     313             :         }
     314             : 
     315         119 :         if (route->type == OSPF6_DEST_TYPE_ROUTER) {
     316          63 :                 if (ADV_ROUTER_IN_PREFIX(&route->prefix)
     317          63 :                     == area->ospf6->router_id) {
     318          50 :                         if (IS_OSPF6_DEBUG_ABR)
     319           0 :                                 zlog_debug(
     320             :                                         "%s: Skipping ASBR announcement for ABR (%pI4)",
     321             :                                         __func__,
     322             :                                         &ADV_ROUTER_IN_PREFIX(&route->prefix));
     323          50 :                         return 0;
     324             :                 }
     325             :         }
     326             : 
     327          69 :         if (route->type == OSPF6_DEST_TYPE_ROUTER) {
     328          13 :                 if (IS_OSPF6_DEBUG_ABR
     329          13 :                     || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER)) {
     330           0 :                         is_debug++;
     331           0 :                         if (IS_OSPF6_DEBUG_ABR)
     332           0 :                                 zlog_debug(
     333             :                                         "Originating summary in area %s for ASBR %pI4",
     334             :                                         area->name,
     335             :                                         &ADV_ROUTER_IN_PREFIX(&route->prefix));
     336             :                 }
     337             :         } else {
     338          56 :                 if (IS_OSPF6_DEBUG_ABR
     339          56 :                     || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX))
     340             :                         is_debug++;
     341             : 
     342          56 :                 if (route->type == OSPF6_DEST_TYPE_NETWORK &&
     343          56 :                     route->path.origin.type ==
     344          56 :                     htons(OSPF6_LSTYPE_INTER_PREFIX)) {
     345           0 :                         if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
     346           0 :                                 if (is_debug)
     347           0 :                                         zlog_debug(
     348             :                                                 "%s: route %pFX with cost %u is not best, ignore.",
     349             :                                                 __func__, &route->prefix,
     350             :                                                 route->path.cost);
     351           0 :                                 return 0;
     352             :                         }
     353             :                 }
     354             : 
     355          56 :                 if (route->path.origin.type ==
     356          56 :                     htons(OSPF6_LSTYPE_INTRA_PREFIX)) {
     357          56 :                         if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
     358           0 :                                 if (is_debug)
     359           0 :                                         zlog_debug(
     360             :                                                 "%s: intra-prefix route %pFX with cost %u is not best, ignore.",
     361             :                                                 __func__, &route->prefix,
     362             :                                                 route->path.cost);
     363           0 :                                 return 0;
     364             :                         }
     365             :                 }
     366             : 
     367          56 :                 if (is_debug)
     368           0 :                         zlog_debug(
     369             :                                 "Originating summary in area %s for %pFX cost %u",
     370             :                                 area->name, &route->prefix, route->path.cost);
     371             :         }
     372             : 
     373             :         /* if this route has just removed, remove corresponding LSA */
     374          69 :         if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)) {
     375          12 :                 if (is_debug)
     376           0 :                         zlog_debug(
     377             :                                 "The route has just removed, purge previous LSA");
     378             : 
     379          12 :                 if (route->type == OSPF6_DEST_TYPE_RANGE) {
     380             :                         /* Whether the route have active longer prefix */
     381           0 :                         if (!CHECK_FLAG(route->flag,
     382             :                                         OSPF6_ROUTE_ACTIVE_SUMMARY)) {
     383           0 :                                 if (is_debug)
     384           0 :                                         zlog_debug(
     385             :                                                 "The range is not active. withdraw");
     386             : 
     387           0 :                                 ospf6_abr_delete_route(summary, summary_table,
     388             :                                                        old);
     389             :                         }
     390          12 :                 } else if (old) {
     391           8 :                         ospf6_route_remove(summary, summary_table);
     392           8 :                         ospf6_lsa_purge(old);
     393             :                 }
     394          12 :                 return 0;
     395             :         }
     396             : 
     397          57 :         if ((route->type == OSPF6_DEST_TYPE_ROUTER)
     398           9 :             && (IS_AREA_STUB(area) || IS_AREA_NSSA(area))) {
     399           0 :                 if (is_debug)
     400           0 :                         zlog_debug(
     401             :                                 "Area has been stubbed, purge Inter-Router LSA");
     402             : 
     403           0 :                 ospf6_abr_delete_route(summary, summary_table, old);
     404           0 :                 return 0;
     405             :         }
     406             : 
     407          57 :         if (area->no_summary
     408           0 :             && (route->path.subtype != OSPF6_PATH_SUBTYPE_DEFAULT_RT)) {
     409           0 :                 if (is_debug)
     410           0 :                         zlog_debug("Area has been stubbed, purge prefix LSA");
     411             : 
     412           0 :                 ospf6_abr_delete_route(summary, summary_table, old);
     413           0 :                 return 0;
     414             :         }
     415             : 
     416             :         /* do not generate if the route cost is greater or equal to LSInfinity
     417             :          */
     418          57 :         if (route->path.cost >= OSPF_LS_INFINITY) {
     419             :                 /* When we're clearing the range route because all active
     420             :                  * prefixes
     421             :                  * under the range are gone, we set the range's cost to
     422             :                  * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
     423             :                  * don't want to trigger the code here for that. This code is
     424             :                  * for
     425             :                  * handling routes that have gone to infinity. The range removal
     426             :                  * happens
     427             :                  * elsewhere.
     428             :                  */
     429           0 :                 if ((route->type != OSPF6_DEST_TYPE_RANGE)
     430           0 :                     && (route->path.cost != OSPF_AREA_RANGE_COST_UNSPEC)) {
     431           0 :                         if (is_debug)
     432           0 :                                 zlog_debug(
     433             :                                         "The cost exceeds LSInfinity, withdraw");
     434           0 :                         if (old)
     435           0 :                                 ospf6_lsa_purge(old);
     436           0 :                         return 0;
     437             :                 }
     438             :         }
     439             : 
     440             :         /* if this is a route to ASBR */
     441          57 :         if (route->type == OSPF6_DEST_TYPE_ROUTER) {
     442             :                 /* Only the preferred best path is considered */
     443           9 :                 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
     444           0 :                         if (is_debug)
     445           0 :                                 zlog_debug(
     446             :                                         "This is the secondary path to the ASBR, ignore");
     447           0 :                         ospf6_abr_delete_route(summary, summary_table, old);
     448           0 :                         return 0;
     449             :                 }
     450             : 
     451             :                 /* Do not generate if area is NSSA */
     452           9 :                 route_area =
     453           9 :                         ospf6_area_lookup(route->path.area_id, area->ospf6);
     454           9 :                 assert(route_area);
     455             : 
     456           9 :                 if (IS_AREA_NSSA(route_area)) {
     457           0 :                         if (is_debug)
     458           0 :                                 zlog_debug(
     459             :                                         "%s: The route comes from NSSA area, skip",
     460             :                                         __func__);
     461           0 :                         ospf6_abr_delete_route(summary, summary_table, old);
     462           0 :                         return 0;
     463             :                 }
     464             : 
     465             :                 /* Do not generate if the area is stub */
     466             :                 /* XXX */
     467             :         }
     468             : 
     469             :         /* if this is an intra-area route, this may be suppressed by aggregation
     470             :          */
     471          57 :         if (route->type == OSPF6_DEST_TYPE_NETWORK
     472          48 :             && route->path.type == OSPF6_PATH_TYPE_INTRA) {
     473             :                 /* search for configured address range for the route's area */
     474          48 :                 route_area =
     475          48 :                         ospf6_area_lookup(route->path.area_id, area->ospf6);
     476          48 :                 assert(route_area);
     477          48 :                 range = ospf6_route_lookup_bestmatch(&route->prefix,
     478             :                                                      route_area->range_table);
     479             : 
     480             :                 /* ranges are ignored when originate backbone routes to transit
     481             :                    area.
     482             :                    Otherwise, if ranges are configured, the route is suppressed.
     483             :                    */
     484          48 :                 if (range && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)
     485           0 :                     && (route->path.area_id != OSPF_AREA_BACKBONE
     486           0 :                         || !IS_AREA_TRANSIT(area))) {
     487           0 :                         if (is_debug)
     488           0 :                                 zlog_debug(
     489             :                                         "Suppressed by range %pFX of area %s",
     490             :                                         &range->prefix, route_area->name);
     491             :                         /* The existing summary route could be a range, don't
     492             :                          * remove it in this case
     493             :                          */
     494           0 :                         if (summary && summary->type != OSPF6_DEST_TYPE_RANGE)
     495           0 :                                 ospf6_abr_delete_route(summary, summary_table,
     496             :                                                        old);
     497           0 :                         return 0;
     498             :                 }
     499             :         }
     500             : 
     501             :         /* If this is a configured address range */
     502          57 :         if (route->type == OSPF6_DEST_TYPE_RANGE) {
     503             :                 /* If DoNotAdvertise is set */
     504           0 :                 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
     505           0 :                         if (is_debug)
     506           0 :                                 zlog_debug(
     507             :                                         "This is the range with DoNotAdvertise set. ignore");
     508           0 :                         ospf6_abr_delete_route(summary, summary_table, old);
     509           0 :                         return 0;
     510             :                 }
     511             : 
     512             :                 /* If there are no active prefixes in this range, remove */
     513           0 :                 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
     514           0 :                         if (is_debug)
     515           0 :                                 zlog_debug("The range is not active. withdraw");
     516           0 :                         ospf6_abr_delete_route(summary, summary_table, old);
     517           0 :                         return 0;
     518             :                 }
     519             :         }
     520             : 
     521             :         /* the route is going to be originated. store it in area's summary_table
     522             :          */
     523          57 :         if (summary == NULL) {
     524          12 :                 summary = ospf6_route_copy(route);
     525          12 :                 summary->path.origin.adv_router = area->ospf6->router_id;
     526             : 
     527          12 :                 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
     528           4 :                         summary->path.origin.type =
     529           4 :                                 htons(OSPF6_LSTYPE_INTER_ROUTER);
     530           4 :                         summary->path.origin.id =
     531           4 :                                 ADV_ROUTER_IN_PREFIX(&route->prefix);
     532             :                 } else {
     533           8 :                         summary->path.origin.type =
     534           8 :                                 htons(OSPF6_LSTYPE_INTER_PREFIX);
     535           8 :                         summary->path.origin.id = ospf6_new_ls_id(
     536             :                                 summary->path.origin.type,
     537             :                                 summary->path.origin.adv_router, area->lsdb);
     538             :                 }
     539          12 :                 summary = ospf6_route_add(summary, summary_table);
     540             :         } else {
     541          45 :                 summary->type = route->type;
     542          45 :                 monotime(&summary->changed);
     543             :         }
     544             : 
     545          57 :         summary->prefix_options = route->prefix_options;
     546          57 :         summary->path.router_bits = route->path.router_bits;
     547          57 :         summary->path.options[0] = route->path.options[0];
     548          57 :         summary->path.options[1] = route->path.options[1];
     549          57 :         summary->path.options[2] = route->path.options[2];
     550          57 :         summary->path.area_id = area->area_id;
     551          57 :         summary->path.type = OSPF6_PATH_TYPE_INTER;
     552          57 :         summary->path.subtype = route->path.subtype;
     553          57 :         summary->path.cost = route->path.cost;
     554             :         /* summary->nexthop[0] = route->nexthop[0]; */
     555             : 
     556             :         /* prepare buffer */
     557          57 :         memset(buffer, 0, sizeof(buffer));
     558          57 :         lsa_header = (struct ospf6_lsa_header *)buffer;
     559             : 
     560          57 :         if (route->type == OSPF6_DEST_TYPE_ROUTER) {
     561           9 :                 router_lsa = (struct ospf6_inter_router_lsa
     562             :                                       *)((caddr_t)lsa_header
     563             :                                          + sizeof(struct ospf6_lsa_header));
     564           9 :                 p = (caddr_t)router_lsa + sizeof(struct ospf6_inter_router_lsa);
     565             : 
     566             :                 /* Fill Inter-Area-Router-LSA */
     567           9 :                 router_lsa->options[0] = route->path.options[0];
     568           9 :                 router_lsa->options[1] = route->path.options[1];
     569           9 :                 router_lsa->options[2] = route->path.options[2];
     570           9 :                 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa, route->path.cost);
     571           9 :                 router_lsa->router_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
     572           9 :                 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
     573             :         } else {
     574          48 :                 prefix_lsa = (struct ospf6_inter_prefix_lsa
     575             :                                       *)((caddr_t)lsa_header
     576             :                                          + sizeof(struct ospf6_lsa_header));
     577          48 :                 p = (caddr_t)prefix_lsa + sizeof(struct ospf6_inter_prefix_lsa);
     578             : 
     579             :                 /* Fill Inter-Area-Prefix-LSA */
     580          48 :                 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost);
     581          48 :                 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
     582          48 :                 prefix_lsa->prefix.prefix_options = route->prefix_options;
     583             : 
     584             :                 /* set Prefix */
     585          48 :                 memcpy(p, &route->prefix.u.prefix6,
     586          48 :                        OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
     587          48 :                 ospf6_prefix_apply_mask(&prefix_lsa->prefix);
     588          48 :                 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
     589          48 :                 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
     590             :         }
     591             : 
     592             :         /* Fill LSA Header */
     593          57 :         lsa_header->age = 0;
     594          57 :         lsa_header->type = type;
     595          57 :         lsa_header->id = summary->path.origin.id;
     596          57 :         lsa_header->adv_router = area->ospf6->router_id;
     597         114 :         lsa_header->seqnum =
     598          57 :                 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
     599             :                                     lsa_header->adv_router, area->lsdb);
     600          57 :         lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
     601             : 
     602             :         /* LSA checksum */
     603          57 :         ospf6_lsa_checksum(lsa_header);
     604             : 
     605             :         /* create LSA */
     606          57 :         lsa = ospf6_lsa_create(lsa_header);
     607             : 
     608             :         /* Reset the unapproved flag */
     609          57 :         UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
     610             : 
     611             :         /* Originate */
     612          57 :         ospf6_lsa_originate_area(lsa, area);
     613             : 
     614          57 :         if (IS_OSPF6_DEBUG_ABR)
     615           0 :                 zlog_debug("%s : finish area %s", __func__, area->name);
     616             : 
     617             :         return 1;
     618             : }
     619             : 
     620          25 : void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
     621             : {
     622          25 :         struct listnode *node, *nnode;
     623          25 :         struct ospf6_area *oa;
     624          25 :         struct ospf6_route *range;
     625             : 
     626         100 :         for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
     627          50 :                 for (range = ospf6_route_head(oa->range_table); range;
     628           0 :                      range = ospf6_route_next(range))
     629           0 :                         OSPF6_ABR_RANGE_CLEAR_COST(range);
     630          50 :                 for (range = ospf6_route_head(oa->nssa_range_table); range;
     631           0 :                      range = ospf6_route_next(range))
     632           0 :                         OSPF6_ABR_RANGE_CLEAR_COST(range);
     633             :         }
     634          25 : }
     635             : 
     636           0 : static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
     637             :                                                     struct ospf6 *o)
     638             : {
     639           0 :         struct ospf6_route *ro;
     640           0 :         uint32_t cost = 0;
     641             : 
     642           0 :         for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
     643           0 :              ro = ospf6_route_match_next(&range->prefix, ro)) {
     644           0 :                 if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
     645           0 :                         continue;
     646           0 :                 if (ro->path.area_id != range->path.area_id)
     647           0 :                         continue;
     648           0 :                 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
     649           0 :                     && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1
     650           0 :                     && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2)
     651           0 :                         continue;
     652           0 :                 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
     653           0 :                     && ro->path.type != OSPF6_PATH_TYPE_INTRA)
     654           0 :                         continue;
     655             : 
     656           0 :                 cost = MAX(cost, ro->path.cost);
     657             :         }
     658             : 
     659           0 :         return cost;
     660             : }
     661             : 
     662             : static inline int
     663           0 : ospf6_abr_range_summary_needs_update(struct ospf6_route *range, uint32_t cost)
     664             : {
     665           0 :         int redo_summary = 0;
     666             : 
     667           0 :         if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
     668           0 :                 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
     669           0 :                 redo_summary = 1;
     670           0 :         } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
     671           0 :                 if (range->path.cost != 0) {
     672           0 :                         range->path.cost = 0;
     673           0 :                         redo_summary = 1;
     674             :                 }
     675           0 :         } else if (cost) {
     676           0 :                 if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path)
     677           0 :                      && range->path.cost != range->path.u.cost_config)) {
     678           0 :                         range->path.cost = range->path.u.cost_config;
     679           0 :                         SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
     680           0 :                         redo_summary = 1;
     681           0 :                 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path)
     682           0 :                            && range->path.cost != cost) {
     683           0 :                         range->path.cost = cost;
     684           0 :                         SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
     685           0 :                         redo_summary = 1;
     686             :                 }
     687           0 :         } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
     688             :                 /* Cost is zero, meaning no active range */
     689           0 :                 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
     690           0 :                 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
     691           0 :                 redo_summary = 1;
     692             :         }
     693             : 
     694           0 :         return (redo_summary);
     695             : }
     696             : 
     697           0 : void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
     698             : {
     699           0 :         uint32_t cost = 0;
     700           0 :         struct listnode *node, *nnode;
     701           0 :         struct ospf6_area *oa;
     702           0 :         int summary_orig = 0;
     703             : 
     704           0 :         assert(range->type == OSPF6_DEST_TYPE_RANGE);
     705           0 :         oa = ospf6_area_lookup(range->path.area_id, ospf6);
     706           0 :         assert(oa);
     707             : 
     708             :         /* update range's cost and active flag */
     709           0 :         cost = ospf6_abr_range_compute_cost(range, ospf6);
     710             : 
     711           0 :         if (IS_OSPF6_DEBUG_ABR)
     712           0 :                 zlog_debug("%s: range %pFX, cost %d", __func__, &range->prefix,
     713             :                            cost);
     714             : 
     715             :         /* Non-zero cost is a proxy for active longer prefixes in this range.
     716             :          * If there are active routes covered by this range AND either the
     717             :          * configured
     718             :          * cost has changed or the summarized cost has changed then redo
     719             :          * summaries.
     720             :          * Alternately, if there are no longer active prefixes and there are
     721             :          * summary announcements, withdraw those announcements.
     722             :          *
     723             :          * The don't advertise code relies on the path.cost being set to UNSPEC
     724             :          * to
     725             :          * work the first time. Subsequent times the path.cost is not 0 anyway
     726             :          * if there
     727             :          * were active ranges.
     728             :          */
     729           0 :         if (!ospf6_abr_range_summary_needs_update(range, cost))
     730             :                 return;
     731             : 
     732           0 :         if (IS_OSPF6_DEBUG_ABR)
     733           0 :                 zlog_debug("%s: range %pFX update", __func__, &range->prefix);
     734             : 
     735           0 :         if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) {
     736           0 :                 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
     737             :                     && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
     738           0 :                         ospf6_nssa_lsa_originate(range, oa, true);
     739           0 :                         summary_orig = 1;
     740             :                 } else {
     741           0 :                         struct ospf6_lsa *lsa;
     742             : 
     743           0 :                         lsa = ospf6_lsdb_lookup(range->path.origin.type,
     744             :                                                 range->path.origin.id,
     745             :                                                 ospf6->router_id, oa->lsdb);
     746           0 :                         if (lsa)
     747           0 :                                 ospf6_lsa_premature_aging(lsa);
     748             :                 }
     749             :         } else {
     750           0 :                 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
     751           0 :                         summary_orig +=
     752           0 :                                 ospf6_abr_originate_summary_to_area(range, oa);
     753             :                 }
     754             :         }
     755             : 
     756           0 :         if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
     757           0 :             && summary_orig) {
     758           0 :                 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
     759           0 :                         if (IS_OSPF6_DEBUG_ABR)
     760           0 :                                 zlog_debug("Add discard route");
     761             : 
     762           0 :                         ospf6_zebra_add_discard(range, ospf6);
     763             :                 }
     764             :         } else {
     765             :                 /* Summary removed or no summary generated as no
     766             :                  * specifics exist */
     767           0 :                 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
     768           0 :                         if (IS_OSPF6_DEBUG_ABR)
     769           0 :                                 zlog_debug("Delete discard route");
     770             : 
     771           0 :                         ospf6_zebra_delete_discard(range, ospf6);
     772             :                 }
     773             :         }
     774             : }
     775             : 
     776         563 : void ospf6_abr_originate_summary(struct ospf6_route *route, struct ospf6 *ospf6)
     777             : {
     778         563 :         struct listnode *node, *nnode;
     779         563 :         struct ospf6_area *oa;
     780         563 :         struct ospf6_route *range = NULL;
     781             : 
     782         563 :         if (IS_OSPF6_DEBUG_ABR) {
     783           0 :                 char buf[BUFSIZ];
     784             : 
     785           0 :                 if (route->type == OSPF6_DEST_TYPE_ROUTER)
     786           0 :                         inet_ntop(AF_INET,
     787           0 :                                   &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
     788             :                                   sizeof(buf));
     789             :                 else
     790           0 :                         prefix2str(&route->prefix, buf, sizeof(buf));
     791             : 
     792           0 :                 zlog_debug("%s: route %s", __func__, buf);
     793             :         }
     794             : 
     795         563 :         if (route->type == OSPF6_DEST_TYPE_NETWORK) {
     796         385 :                 oa = ospf6_area_lookup(route->path.area_id, ospf6);
     797         385 :                 if (!oa) {
     798           0 :                         zlog_err("OSPFv6 area lookup failed");
     799           0 :                         return;
     800             :                 }
     801             : 
     802         385 :                 range = ospf6_route_lookup_bestmatch(&route->prefix,
     803             :                                                      oa->range_table);
     804         385 :                 if (range) {
     805           0 :                         ospf6_abr_range_update(range, ospf6);
     806             :                 }
     807             :         }
     808             : 
     809        1862 :         for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
     810         736 :                 ospf6_abr_originate_summary_to_area(route, oa);
     811             : }
     812             : 
     813          25 : void ospf6_abr_defaults_to_stub(struct ospf6 *o)
     814             : {
     815          25 :         struct listnode *node, *nnode;
     816          25 :         struct ospf6_area *oa;
     817          25 :         struct ospf6_route *def, *route;
     818          25 :         int type = DEFAULT_ROUTE;
     819             : 
     820          25 :         if (!o->backbone)
     821             :                 return;
     822             : 
     823          25 :         def = ospf6_route_create(o);
     824          25 :         def->type = OSPF6_DEST_TYPE_NETWORK;
     825          25 :         def->prefix.family = AF_INET6;
     826          25 :         def->prefix.prefixlen = 0;
     827          25 :         memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
     828          25 :         def->type = OSPF6_DEST_TYPE_NETWORK;
     829          25 :         def->path.type = OSPF6_PATH_TYPE_INTER;
     830          25 :         def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
     831          25 :         def->path.area_id = o->backbone->area_id;
     832          25 :         def->path.metric_type = metric_type(o, type, 0);
     833          25 :         def->path.cost = metric_value(o, type, 0);
     834             : 
     835         100 :         for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) {
     836          50 :                 if (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa) && oa->no_summary)) {
     837             :                         /* announce defaults to stubby areas */
     838           0 :                         if (IS_OSPF6_DEBUG_ABR)
     839           0 :                                 zlog_debug(
     840             :                                         "Announcing default route into stubby area %s",
     841             :                                         oa->name);
     842           0 :                         UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
     843           0 :                         ospf6_abr_originate_summary_to_area(def, oa);
     844             :                 } else {
     845             :                         /* withdraw defaults when an area switches from stub to
     846             :                          * non-stub */
     847          50 :                         route = ospf6_route_lookup(&def->prefix,
     848             :                                                    oa->summary_prefix);
     849          50 :                         if (route
     850           0 :                             && (route->path.subtype == def->path.subtype)) {
     851           0 :                                 if (IS_OSPF6_DEBUG_ABR)
     852           0 :                                         zlog_debug(
     853             :                                                 "Withdrawing default route from non-stubby area %s",
     854             :                                                 oa->name);
     855           0 :                                 SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
     856           0 :                                 ospf6_abr_originate_summary_to_area(def, oa);
     857             :                         }
     858             :                 }
     859             :         }
     860          25 :         ospf6_route_delete(def);
     861             : }
     862             : 
     863           0 : void ospf6_abr_old_path_update(struct ospf6_route *old_route,
     864             :                                struct ospf6_route *route,
     865             :                                struct ospf6_route_table *table)
     866             : {
     867           0 :         struct ospf6_path *o_path = NULL;
     868           0 :         struct listnode *anode, *anext;
     869           0 :         struct listnode *nnode, *rnode, *rnext;
     870           0 :         struct ospf6_nexthop *nh, *rnh;
     871             : 
     872           0 :         for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) {
     873           0 :                 if (o_path->area_id != route->path.area_id
     874           0 :                     || !ospf6_ls_origin_same(o_path, &route->path))
     875           0 :                         continue;
     876             : 
     877           0 :                 if ((o_path->cost == route->path.cost) &&
     878           0 :                     (o_path->u.cost_e2 == route->path.u.cost_e2))
     879           0 :                         continue;
     880             : 
     881           0 :                 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
     882           0 :                         for (ALL_LIST_ELEMENTS(old_route->nh_list, rnode,
     883             :                                                rnext, rnh)) {
     884           0 :                                 if (!ospf6_nexthop_is_same(rnh, nh))
     885           0 :                                         continue;
     886           0 :                                 listnode_delete(old_route->nh_list, rnh);
     887           0 :                                 ospf6_nexthop_delete(rnh);
     888             :                         }
     889             : 
     890             :                 }
     891             : 
     892           0 :                 listnode_delete(old_route->paths, o_path);
     893           0 :                 ospf6_path_free(o_path);
     894             : 
     895           0 :                 for (ALL_LIST_ELEMENTS(old_route->paths, anode,
     896             :                                        anext, o_path)) {
     897           0 :                         ospf6_merge_nexthops(old_route->nh_list,
     898             :                                              o_path->nh_list);
     899             :                 }
     900             : 
     901           0 :                 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
     902           0 :                         zlog_debug("%s: paths %u nh %u", __func__,
     903             :                                    old_route->paths
     904             :                                            ? listcount(old_route->paths)
     905             :                                            : 0,
     906             :                                    old_route->nh_list
     907             :                                            ? listcount(old_route->nh_list)
     908             :                                            : 0);
     909             : 
     910           0 :                 if (table->hook_add)
     911           0 :                         (*table->hook_add)(old_route);
     912             : 
     913           0 :                 if (old_route->path.origin.id == route->path.origin.id &&
     914           0 :                     old_route->path.origin.adv_router ==
     915           0 :                     route->path.origin.adv_router) {
     916           0 :                         struct ospf6_path *h_path;
     917             : 
     918           0 :                         h_path = (struct ospf6_path *)
     919           0 :                         listgetdata(listhead(old_route->paths));
     920           0 :                         old_route->path.origin.type = h_path->origin.type;
     921           0 :                         old_route->path.origin.id = h_path->origin.id;
     922           0 :                         old_route->path.origin.adv_router =
     923           0 :                                 h_path->origin.adv_router;
     924             :                 }
     925             :         }
     926           0 : }
     927             : 
     928          10 : void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old,
     929             :                                 struct ospf6_route_table *table)
     930             : {
     931          10 :         if (IS_OSPF6_DEBUG_ABR)
     932           0 :                 zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix,
     933             :                            listcount(old->paths));
     934             : 
     935          10 :         if (listcount(old->paths) > 1) {
     936           0 :                 struct listnode *anode, *anext, *nnode, *rnode, *rnext;
     937           0 :                 struct ospf6_path *o_path;
     938           0 :                 struct ospf6_nexthop *nh, *rnh;
     939           0 :                 bool nh_updated = false;
     940             : 
     941           0 :                 for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) {
     942           0 :                         if (o_path->origin.adv_router != lsa->header->adv_router
     943           0 :                             || o_path->origin.id != lsa->header->id)
     944           0 :                                 continue;
     945           0 :                         for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
     946           0 :                                 for (ALL_LIST_ELEMENTS(old->nh_list,
     947             :                                                         rnode, rnext, rnh)) {
     948           0 :                                         if (!ospf6_nexthop_is_same(rnh, nh))
     949           0 :                                                 continue;
     950           0 :                                         if (IS_OSPF6_DEBUG_ABR)
     951           0 :                                                 zlog_debug("deleted nexthop");
     952           0 :                                         listnode_delete(old->nh_list, rnh);
     953           0 :                                         ospf6_nexthop_delete(rnh);
     954             :                                 }
     955             :                         }
     956           0 :                         listnode_delete(old->paths, o_path);
     957           0 :                         ospf6_path_free(o_path);
     958           0 :                         nh_updated = true;
     959             :                 }
     960             : 
     961           0 :                 if (nh_updated) {
     962           0 :                         if (listcount(old->paths)) {
     963           0 :                                 if (IS_OSPF6_DEBUG_ABR
     964           0 :                                     || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
     965           0 :                                         zlog_debug("%s: old %pFX updated nh %u",
     966             :                                                    __func__, &old->prefix,
     967             :                                                    old->nh_list ? listcount(
     968             :                                                            old->nh_list)
     969             :                                                                 : 0);
     970             : 
     971           0 :                                 if (table->hook_add)
     972           0 :                                         (*table->hook_add)(old);
     973             : 
     974           0 :                                 if ((old->path.origin.id == lsa->header->id) &&
     975           0 :                                     (old->path.origin.adv_router
     976           0 :                                                  == lsa->header->adv_router)) {
     977           0 :                                         struct ospf6_path *h_path;
     978             : 
     979           0 :                                         h_path = (struct ospf6_path *)
     980           0 :                                                 listgetdata(
     981             :                                                         listhead(old->paths));
     982           0 :                                         old->path.origin.type =
     983           0 :                                                 h_path->origin.type;
     984           0 :                                         old->path.origin.id = h_path->origin.id;
     985           0 :                                         old->path.origin.adv_router =
     986           0 :                                                 h_path->origin.adv_router;
     987             :                                 }
     988             :                         } else
     989           0 :                                 ospf6_route_remove(old, table);
     990             :                 }
     991             :         } else
     992          10 :                 ospf6_route_remove(old, table);
     993          10 : }
     994             : 
     995             : /* RFC 2328 16.2. Calculating the inter-area routes */
     996          92 : void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
     997             : {
     998          92 :         struct prefix prefix, abr_prefix;
     999          92 :         struct ospf6_route_table *table = NULL;
    1000          92 :         struct ospf6_route *range, *route, *old = NULL, *old_route;
    1001          92 :         struct ospf6_route *abr_entry;
    1002          92 :         uint8_t type = 0;
    1003          92 :         char options[3] = {0, 0, 0};
    1004          92 :         uint8_t prefix_options = 0;
    1005          92 :         uint32_t cost = 0;
    1006          92 :         uint8_t router_bits = 0;
    1007          92 :         char buf[PREFIX2STR_BUFFER];
    1008          92 :         int is_debug = 0;
    1009          92 :         struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
    1010          92 :         struct ospf6_inter_router_lsa *router_lsa = NULL;
    1011          92 :         bool old_entry_updated = false;
    1012          92 :         struct ospf6_path *path, *o_path, *ecmp_path;
    1013          92 :         struct listnode *anode;
    1014          92 :         bool add_route = false;
    1015             : 
    1016          92 :         memset(&prefix, 0, sizeof(prefix));
    1017             : 
    1018          92 :         if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
    1019          62 :                 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
    1020           0 :                         is_debug++;
    1021           0 :                         zlog_debug("%s: LSA %s age %d in area %s", __func__,
    1022             :                                    lsa->name, ospf6_lsa_age_current(lsa),
    1023             :                                    oa->name);
    1024             :                 }
    1025             : 
    1026          62 :                 prefix_lsa =
    1027          62 :                         (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
    1028             :                                 lsa->header);
    1029          62 :                 prefix.family = AF_INET6;
    1030          62 :                 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
    1031          62 :                 ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
    1032          62 :                                       &prefix_lsa->prefix);
    1033          62 :                 if (is_debug)
    1034           0 :                         prefix2str(&prefix, buf, sizeof(buf));
    1035          62 :                 table = oa->ospf6->route_table;
    1036          62 :                 type = OSPF6_DEST_TYPE_NETWORK;
    1037          62 :                 prefix_options = prefix_lsa->prefix.prefix_options;
    1038          62 :                 cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa);
    1039          30 :         } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
    1040          30 :                 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
    1041           0 :                         is_debug++;
    1042           0 :                         zlog_debug("%s: LSA %s age %d in area %s", __func__,
    1043             :                                    lsa->name, ospf6_lsa_age_current(lsa),
    1044             :                                    oa->name);
    1045             :                 }
    1046             : 
    1047          30 :                 router_lsa =
    1048          30 :                         (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
    1049             :                                 lsa->header);
    1050          30 :                 ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
    1051             :                                        &prefix);
    1052          30 :                 if (is_debug)
    1053           0 :                         inet_ntop(AF_INET, &router_lsa->router_id, buf,
    1054             :                                   sizeof(buf));
    1055             : 
    1056          30 :                 table = oa->ospf6->brouter_table;
    1057          30 :                 type = OSPF6_DEST_TYPE_ROUTER;
    1058          30 :                 options[0] = router_lsa->options[0];
    1059          30 :                 options[1] = router_lsa->options[1];
    1060          30 :                 options[2] = router_lsa->options[2];
    1061          30 :                 cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa);
    1062          30 :                 SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E);
    1063             :         } else
    1064           0 :                 assert(0);
    1065             : 
    1066             :         /* Find existing route */
    1067          92 :         route = ospf6_route_lookup(&prefix, table);
    1068          92 :         if (route) {
    1069          39 :                 ospf6_route_lock(route);
    1070          39 :                 if (is_debug)
    1071           0 :                         zlog_debug("%s: route %pFX, paths %d", __func__,
    1072             :                                    &prefix, listcount(route->paths));
    1073             :         }
    1074         145 :         while (route && ospf6_route_is_prefix(&prefix, route)) {
    1075          53 :                 if (route->path.area_id == oa->area_id
    1076          35 :                     && route->path.origin.type == lsa->header->type
    1077          20 :                     && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED)) {
    1078             :                         /* LSA adv. router could be part of route's
    1079             :                          * paths list. Find the existing path and set
    1080             :                          * old as the route.
    1081             :                          */
    1082          20 :                         if (listcount(route->paths) > 1) {
    1083           0 :                                 for (ALL_LIST_ELEMENTS_RO(route->paths, anode,
    1084             :                                                           o_path)) {
    1085           0 :                                         if (o_path->origin.id == lsa->header->id
    1086           0 :                                             && o_path->origin.adv_router ==
    1087           0 :                                             lsa->header->adv_router) {
    1088           0 :                                                 old = route;
    1089             : 
    1090           0 :                                                 if (is_debug)
    1091           0 :                                                         zlog_debug(
    1092             :                                                                 "%s: old entry found in paths, adv_router %pI4",
    1093             :                                                                 __func__,
    1094             :                                                                 &o_path->origin.adv_router);
    1095             : 
    1096             :                                                 break;
    1097             :                                         }
    1098             :                                 }
    1099          20 :                         } else if (route->path.origin.id == lsa->header->id &&
    1100          20 :                                    route->path.origin.adv_router ==
    1101          20 :                                    lsa->header->adv_router)
    1102          20 :                                 old = route;
    1103             :                 }
    1104          53 :                 route = ospf6_route_next(route);
    1105             :         }
    1106          92 :         if (route)
    1107          20 :                 ospf6_route_unlock(route);
    1108             : 
    1109             :         /* (1) if cost == LSInfinity or if the LSA is MaxAge */
    1110          92 :         if (cost == OSPF_LS_INFINITY) {
    1111           0 :                 if (is_debug)
    1112           0 :                         zlog_debug("cost is LS_INFINITY, ignore");
    1113           0 :                 if (old)
    1114           0 :                         ospf6_abr_old_route_remove(lsa, old, table);
    1115          72 :                 return;
    1116             :         }
    1117          92 :         if (OSPF6_LSA_IS_MAXAGE(lsa)) {
    1118          38 :                 if (is_debug)
    1119           0 :                         zlog_debug("%s: LSA %s is MaxAge, ignore", __func__,
    1120             :                                    lsa->name);
    1121          38 :                 if (old)
    1122           8 :                         ospf6_abr_old_route_remove(lsa, old, table);
    1123          38 :                 return;
    1124             :         }
    1125             : 
    1126             : 
    1127             :         /* (2) if the LSA is self-originated, ignore */
    1128          54 :         if (lsa->header->adv_router == oa->ospf6->router_id) {
    1129          12 :                 if (is_debug)
    1130           0 :                         zlog_debug("LSA %s is self-originated, ignore",
    1131             :                                    lsa->name);
    1132          12 :                 if (old)
    1133           0 :                         ospf6_route_remove(old, table);
    1134          12 :                 return;
    1135             :         }
    1136             : 
    1137             :         /* (3) if the prefix is equal to an active configured address range */
    1138             :         /*     or if the NU bit is set in the prefix */
    1139          42 :         if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
    1140             :                 /* must have been set in previous block */
    1141          27 :                 assert(prefix_lsa);
    1142             : 
    1143          27 :                 range = ospf6_route_lookup(&prefix, oa->range_table);
    1144          27 :                 if (range) {
    1145           0 :                         if (is_debug)
    1146           0 :                                 zlog_debug(
    1147             :                                         "Prefix is equal to address range, ignore");
    1148           0 :                         if (old)
    1149           0 :                                 ospf6_route_remove(old, table);
    1150           0 :                         return;
    1151             :                 }
    1152             : 
    1153          27 :                 if (CHECK_FLAG(prefix_lsa->prefix.prefix_options,
    1154             :                                OSPF6_PREFIX_OPTION_NU)
    1155             :                     || CHECK_FLAG(prefix_lsa->prefix.prefix_options,
    1156             :                                   OSPF6_PREFIX_OPTION_LA)) {
    1157           0 :                         if (is_debug)
    1158           0 :                                 zlog_debug("Prefix has NU/LA bit set, ignore");
    1159           0 :                         if (old)
    1160           0 :                                 ospf6_route_remove(old, table);
    1161           0 :                         return;
    1162             :                 }
    1163             :         }
    1164             : 
    1165          42 :         if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
    1166             :                 /* To pass test suites */
    1167          15 :                 assert(router_lsa);
    1168          15 :                 if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R)
    1169             :                     || !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) {
    1170           0 :                         if (is_debug)
    1171           0 :                                 zlog_debug("Prefix has NU/LA bit set, ignore");
    1172           0 :                         if (old)
    1173           0 :                                 ospf6_route_remove(old, table);
    1174             : 
    1175           0 :                         return;
    1176             :                 }
    1177             :                 /* Avoid infinite recursion if someone has maliciously announced
    1178             :                    an
    1179             :                    Inter-Router LSA for an ABR
    1180             :                 */
    1181          15 :                 if (lsa->header->adv_router == router_lsa->router_id) {
    1182           0 :                         if (is_debug)
    1183           0 :                                 zlog_debug(
    1184             :                                         "Ignoring Inter-Router LSA for an ABR (%s)",
    1185             :                                         buf);
    1186           0 :                         if (old)
    1187           0 :                                 ospf6_route_remove(old, table);
    1188             : 
    1189           0 :                         return;
    1190             :                 }
    1191             :         }
    1192             : 
    1193             :         /* (4) if the routing table entry for the ABR does not exist */
    1194          42 :         ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &abr_prefix);
    1195          42 :         abr_entry = ospf6_route_lookup(&abr_prefix, oa->ospf6->brouter_table);
    1196          42 :         if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id
    1197          24 :             || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE)
    1198          24 :             || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
    1199          22 :                 if (is_debug)
    1200           0 :                         zlog_debug(
    1201             :                                 "%s: ABR router entry %pFX does not exist, ignore",
    1202             :                                 __func__, &abr_prefix);
    1203          22 :                 if (old) {
    1204           4 :                         if (old->type == OSPF6_DEST_TYPE_ROUTER &&
    1205           2 :                             oa->intra_brouter_calc) {
    1206           2 :                                 if (is_debug)
    1207           0 :                                         zlog_debug(
    1208             :                                                 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
    1209             :                                                 __func__, buf, (void *)old);
    1210             :                         } else {
    1211           2 :                                 if (is_debug)
    1212           0 :                                         zlog_debug(
    1213             :                                                 "%s: remove old entry: %s %p ",
    1214             :                                                 __func__, buf, (void *)old);
    1215           2 :                                 ospf6_abr_old_route_remove(lsa, old, table);
    1216             :                         }
    1217             :                 }
    1218          22 :                 return;
    1219             :         }
    1220             : 
    1221             :         /* (5),(6): the path preference is handled by the sorting
    1222             :            in the routing table. Always install the path by substituting
    1223             :            old route (if any). */
    1224          20 :         route = ospf6_route_create(oa->ospf6);
    1225             : 
    1226          20 :         route->type = type;
    1227          20 :         route->prefix = prefix;
    1228          20 :         route->prefix_options = prefix_options;
    1229          20 :         route->path.origin.type = lsa->header->type;
    1230          20 :         route->path.origin.id = lsa->header->id;
    1231          20 :         route->path.origin.adv_router = lsa->header->adv_router;
    1232          20 :         route->path.router_bits = router_bits;
    1233          20 :         route->path.options[0] = options[0];
    1234          20 :         route->path.options[1] = options[1];
    1235          20 :         route->path.options[2] = options[2];
    1236          20 :         route->path.area_id = oa->area_id;
    1237          20 :         route->path.type = OSPF6_PATH_TYPE_INTER;
    1238          20 :         route->path.cost = abr_entry->path.cost + cost;
    1239             : 
    1240             :         /* copy brouter rechable nexthops into the route. */
    1241          20 :         ospf6_route_copy_nexthops(route, abr_entry);
    1242             : 
    1243             :         /* (7) If the routes are identical, copy the next hops over to existing
    1244             :            route. ospf6's route table implementation will otherwise string both
    1245             :            routes, but keep the older one as the best route since the routes
    1246             :            are identical.
    1247             :         */
    1248          20 :         old = ospf6_route_lookup(&prefix, table);
    1249          20 :         if (old) {
    1250          11 :                 if (is_debug)
    1251           0 :                         zlog_debug("%s: found old route %pFX, paths %d",
    1252             :                                    __func__, &prefix, listcount(old->paths));
    1253             :         }
    1254          36 :         for (old_route = old; old_route; old_route = old_route->next) {
    1255             : 
    1256             :                 /* The route linked-list is grouped in batches of prefix.
    1257             :                  * If the new prefix is not the same as the one of interest
    1258             :                  * then we have walked over the end of the batch and so we
    1259             :                  * should break rather than continuing unnecessarily.
    1260             :                  */
    1261          23 :                 if (!ospf6_route_is_same(old_route, route))
    1262             :                         break;
    1263          16 :                 if ((old_route->type != route->type)
    1264          16 :                     || (old_route->path.type != route->path.type))
    1265           8 :                         continue;
    1266             : 
    1267           8 :                 if ((ospf6_route_cmp(route, old_route) != 0)) {
    1268           0 :                         if (is_debug)
    1269           0 :                                 zlog_debug(
    1270             :                                         "%s: old %p %pFX cost %u new route cost %u are not same",
    1271             :                                         __func__, (void *)old_route, &prefix,
    1272             :                                         old_route->path.cost, route->path.cost);
    1273             : 
    1274             :                         /* Check new route's adv. router is same in one of
    1275             :                          * the paths with differed cost, if so remove the
    1276             :                          * old path as later new route will be added.
    1277             :                          */
    1278           0 :                         if (listcount(old_route->paths) > 1)
    1279           0 :                                 ospf6_abr_old_path_update(old_route, route,
    1280             :                                                           table);
    1281           0 :                         continue;
    1282             :                 }
    1283             : 
    1284           8 :                 list_delete_all_node(old_route->nh_list);
    1285           8 :                 ospf6_route_copy_nexthops(old_route, route);
    1286           8 :                 old_entry_updated = true;
    1287             : 
    1288          16 :                 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
    1289             :                                                   o_path)) {
    1290           8 :                         if (o_path->area_id == route->path.area_id
    1291           8 :                             && ospf6_ls_origin_same(o_path, &route->path))
    1292             :                                 break;
    1293             :                 }
    1294             : 
    1295             :                 /* New adv. router for a existing path add to paths list */
    1296           8 :                 if (o_path == NULL) {
    1297           0 :                         ecmp_path = ospf6_path_dup(&route->path);
    1298             : 
    1299             :                         /* Add a nh_list to new ecmp path */
    1300           0 :                         ospf6_copy_nexthops(ecmp_path->nh_list, route->nh_list);
    1301             : 
    1302             :                         /* Add the new path to route's path list */
    1303           0 :                         listnode_add_sort(old_route->paths, ecmp_path);
    1304             : 
    1305           0 :                         if (is_debug) {
    1306           0 :                                 zlog_debug(
    1307             :                                         "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
    1308             :                                         __func__, &route->prefix,
    1309             :                                         old_route->path.cost,
    1310             :                                         &ecmp_path->origin.adv_router,
    1311             :                                         listcount(ecmp_path->nh_list),
    1312             :                                         old_route->paths
    1313             :                                                 ? listcount(old_route->paths)
    1314             :                                                 : 0,
    1315             :                                         listcount(old_route->nh_list));
    1316             :                         }
    1317             :                 } else {
    1318           8 :                         struct ospf6_route *tmp_route;
    1319             : 
    1320           8 :                         tmp_route = ospf6_route_create(oa->ospf6);
    1321             : 
    1322           8 :                         ospf6_copy_nexthops(tmp_route->nh_list,
    1323             :                                             o_path->nh_list);
    1324             : 
    1325           8 :                         if (!ospf6_route_cmp_nexthops(tmp_route, route)) {
    1326             :                                 /* adv. router exists in the list, update nhs */
    1327           0 :                                 list_delete_all_node(o_path->nh_list);
    1328           0 :                                 ospf6_copy_nexthops(o_path->nh_list,
    1329             :                                                     route->nh_list);
    1330           0 :                                 ospf6_route_delete(tmp_route);
    1331             :                         } else {
    1332             :                                 /* adv. router has no change in nhs */
    1333           8 :                                 old_entry_updated = false;
    1334           8 :                                 ospf6_route_delete(tmp_route);
    1335           8 :                                 continue;
    1336             :                         }
    1337             :                 }
    1338             : 
    1339           0 :                 if (is_debug)
    1340           0 :                         zlog_debug(
    1341             :                                 "%s: Update route: %s %p old cost %u new cost %u nh %u",
    1342             :                                 __func__, buf, (void *)old_route,
    1343             :                                 old_route->path.cost, route->path.cost,
    1344             :                                 listcount(old_route->nh_list));
    1345             : 
    1346             :                 /* For Inter-Prefix route: Update RIB/FIB,
    1347             :                  * For Inter-Router trigger summary update
    1348             :                  */
    1349           0 :                 if (table->hook_add)
    1350           0 :                         (*table->hook_add)(old_route);
    1351             : 
    1352             :                 break;
    1353             :         }
    1354             : 
    1355             :         /* If the old entry is not updated and old entry not found or old entry
    1356             :          * does not match with the new entry then add the new route
    1357             :          */
    1358           0 :         if (old_entry_updated == false) {
    1359          20 :                 if ((old == NULL) || (old->type != route->type)
    1360          11 :                     || (old->path.type != route->path.type)
    1361           8 :                     || (old->path.cost != route->path.cost))
    1362          12 :                         add_route = true;
    1363             :         }
    1364             : 
    1365          12 :         if (add_route) {
    1366          12 :                 if (is_debug) {
    1367           0 :                         zlog_debug(
    1368             :                                 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
    1369             :                                 __func__, buf, route->path.cost,
    1370             :                                 listcount(route->nh_list),
    1371             :                                 &route->path.origin.adv_router);
    1372             :                 }
    1373             : 
    1374          12 :                 path = ospf6_path_dup(&route->path);
    1375          12 :                 ospf6_copy_nexthops(path->nh_list, abr_entry->nh_list);
    1376          12 :                 listnode_add_sort(route->paths, path);
    1377             :                 /* ospf6_ia_add_nw_route (table, &prefix, route); */
    1378          12 :                 ospf6_route_add(route, table);
    1379             :         } else
    1380             :                 /* if we did not add the route remove it */
    1381           8 :                 ospf6_route_delete(route);
    1382             : }
    1383             : 
    1384          74 : void ospf6_abr_examin_brouter(uint32_t router_id, struct ospf6_route *route,
    1385             :                               struct ospf6 *ospf6)
    1386             : {
    1387          74 :         struct ospf6_lsa *lsa;
    1388          74 :         struct ospf6_area *oa;
    1389          74 :         uint16_t type;
    1390             : 
    1391          74 :         oa = ospf6_area_lookup(route->path.area_id, ospf6);
    1392             :         /*
    1393             :          * It is possible to designate a non backbone
    1394             :          * area first.  If that is the case safely
    1395             :          * fall out of this function.
    1396             :          */
    1397          74 :         if (oa == NULL)
    1398           0 :                 return;
    1399             : 
    1400          74 :         type = htons(OSPF6_LSTYPE_INTER_ROUTER);
    1401          80 :         for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
    1402           6 :                 ospf6_abr_examin_summary(lsa, oa);
    1403             : 
    1404          74 :         type = htons(OSPF6_LSTYPE_INTER_PREFIX);
    1405          86 :         for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
    1406          12 :                 ospf6_abr_examin_summary(lsa, oa);
    1407             : }
    1408             : 
    1409           2 : void ospf6_abr_prefix_resummarize(struct ospf6 *o)
    1410             : {
    1411           2 :         struct ospf6_route *route;
    1412             : 
    1413           2 :         if (IS_OSPF6_DEBUG_ABR)
    1414           0 :                 zlog_debug("Re-examining Inter-Prefix Summaries");
    1415             : 
    1416           4 :         for (route = ospf6_route_head(o->route_table); route;
    1417           2 :              route = ospf6_route_next(route))
    1418           2 :                 ospf6_abr_originate_summary(route, o);
    1419             : 
    1420           2 :         if (IS_OSPF6_DEBUG_ABR)
    1421           0 :                 zlog_debug("Finished re-examining Inter-Prefix Summaries");
    1422           2 : }
    1423             : 
    1424             : 
    1425             : /* Display functions */
    1426          30 : static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
    1427             :                                                         char *buf, int buflen,
    1428             :                                                         int pos)
    1429             : {
    1430          30 :         struct ospf6_inter_prefix_lsa *prefix_lsa;
    1431          30 :         struct in6_addr in6;
    1432          30 :         char tbuf[16];
    1433             : 
    1434          30 :         if (lsa != NULL) {
    1435          30 :                 prefix_lsa =
    1436          30 :                         (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
    1437             :                                 lsa->header);
    1438             : 
    1439          30 :                 ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
    1440          30 :                 if (buf) {
    1441          30 :                         inet_ntop(AF_INET6, &in6, buf, buflen);
    1442          30 :                         snprintf(tbuf, sizeof(tbuf), "/%d",
    1443          30 :                                  prefix_lsa->prefix.prefix_length);
    1444          30 :                         strlcat(buf, tbuf, buflen);
    1445             :                 }
    1446             :         }
    1447             : 
    1448          30 :         return (buf);
    1449             : }
    1450             : 
    1451           0 : static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
    1452             :                                             struct ospf6_lsa *lsa,
    1453             :                                             json_object *json_obj,
    1454             :                                             bool use_json)
    1455             : {
    1456           0 :         struct ospf6_inter_prefix_lsa *prefix_lsa;
    1457           0 :         char buf[INET6_ADDRSTRLEN];
    1458             : 
    1459           0 :         prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
    1460             :                 lsa->header);
    1461             : 
    1462           0 :         if (use_json) {
    1463           0 :                 json_object_int_add(
    1464             :                         json_obj, "metric",
    1465           0 :                         (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
    1466           0 :                 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
    1467             :                                               buf, sizeof(buf));
    1468           0 :                 json_object_string_add(json_obj, "prefixOptions", buf);
    1469           0 :                 json_object_string_add(
    1470             :                         json_obj, "prefix",
    1471           0 :                         ospf6_inter_area_prefix_lsa_get_prefix_str(
    1472             :                                 lsa, buf, sizeof(buf), 0));
    1473             :         } else {
    1474           0 :                 vty_out(vty, "     Metric: %lu\n",
    1475           0 :                         (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
    1476             : 
    1477           0 :                 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
    1478             :                                               buf, sizeof(buf));
    1479           0 :                 vty_out(vty, "     Prefix Options: %s\n", buf);
    1480             : 
    1481           0 :                 vty_out(vty, "     Prefix: %s\n",
    1482             :                         ospf6_inter_area_prefix_lsa_get_prefix_str(
    1483             :                                 lsa, buf, sizeof(buf), 0));
    1484             :         }
    1485             : 
    1486           0 :         return 0;
    1487             : }
    1488             : 
    1489          30 : static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
    1490             :                                                         char *buf, int buflen,
    1491             :                                                         int pos)
    1492             : {
    1493          30 :         struct ospf6_inter_router_lsa *router_lsa;
    1494             : 
    1495          30 :         if (lsa != NULL) {
    1496          30 :                 router_lsa =
    1497          30 :                         (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
    1498             :                                 lsa->header);
    1499             : 
    1500             : 
    1501          30 :                 if (buf)
    1502          30 :                         inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
    1503             :         }
    1504             : 
    1505          30 :         return (buf);
    1506             : }
    1507             : 
    1508           0 : static int ospf6_inter_area_router_lsa_show(struct vty *vty,
    1509             :                                             struct ospf6_lsa *lsa,
    1510             :                                             json_object *json_obj,
    1511             :                                             bool use_json)
    1512             : {
    1513           0 :         struct ospf6_inter_router_lsa *router_lsa;
    1514           0 :         char buf[64];
    1515             : 
    1516           0 :         router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
    1517             :                 lsa->header);
    1518             : 
    1519           0 :         ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
    1520           0 :         if (use_json) {
    1521           0 :                 json_object_string_add(json_obj, "options", buf);
    1522           0 :                 json_object_int_add(
    1523             :                         json_obj, "metric",
    1524           0 :                         (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
    1525             :         } else {
    1526           0 :                 vty_out(vty, "     Options: %s\n", buf);
    1527           0 :                 vty_out(vty, "     Metric: %lu\n",
    1528           0 :                         (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
    1529             :         }
    1530             : 
    1531           0 :         inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
    1532           0 :         if (use_json)
    1533           0 :                 json_object_string_add(json_obj, "destinationRouterId", buf);
    1534             :         else
    1535           0 :                 vty_out(vty, "     Destination Router ID: %s\n", buf);
    1536             : 
    1537           0 :         return 0;
    1538             : }
    1539             : 
    1540             : /* Debug commands */
    1541           0 : DEFUN (debug_ospf6_abr,
    1542             :        debug_ospf6_abr_cmd,
    1543             :        "debug ospf6 abr",
    1544             :        DEBUG_STR
    1545             :        OSPF6_STR
    1546             :        "Debug OSPFv3 ABR function\n"
    1547             :       )
    1548             : {
    1549           0 :         OSPF6_DEBUG_ABR_ON();
    1550           0 :         return CMD_SUCCESS;
    1551             : }
    1552             : 
    1553           0 : DEFUN (no_debug_ospf6_abr,
    1554             :        no_debug_ospf6_abr_cmd,
    1555             :        "no debug ospf6 abr",
    1556             :        NO_STR
    1557             :        DEBUG_STR
    1558             :        OSPF6_STR
    1559             :        "Debug OSPFv3 ABR function\n"
    1560             :       )
    1561             : {
    1562           0 :         OSPF6_DEBUG_ABR_OFF();
    1563           0 :         return CMD_SUCCESS;
    1564             : }
    1565             : 
    1566           0 : int config_write_ospf6_debug_abr(struct vty *vty)
    1567             : {
    1568           0 :         if (IS_OSPF6_DEBUG_ABR)
    1569           0 :                 vty_out(vty, "debug ospf6 abr\n");
    1570           0 :         return 0;
    1571             : }
    1572             : 
    1573          16 : void install_element_ospf6_debug_abr(void)
    1574             : {
    1575          16 :         install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
    1576          16 :         install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
    1577          16 :         install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
    1578          16 :         install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
    1579          16 : }
    1580             : 
    1581             : static struct ospf6_lsa_handler inter_prefix_handler = {
    1582             :         .lh_type = OSPF6_LSTYPE_INTER_PREFIX,
    1583             :         .lh_name = "Inter-Prefix",
    1584             :         .lh_short_name = "IAP",
    1585             :         .lh_show = ospf6_inter_area_prefix_lsa_show,
    1586             :         .lh_get_prefix_str = ospf6_inter_area_prefix_lsa_get_prefix_str,
    1587             :         .lh_debug = 0};
    1588             : 
    1589             : static struct ospf6_lsa_handler inter_router_handler = {
    1590             :         .lh_type = OSPF6_LSTYPE_INTER_ROUTER,
    1591             :         .lh_name = "Inter-Router",
    1592             :         .lh_short_name = "IAR",
    1593             :         .lh_show = ospf6_inter_area_router_lsa_show,
    1594             :         .lh_get_prefix_str = ospf6_inter_area_router_lsa_get_prefix_str,
    1595             :         .lh_debug = 0};
    1596             : 
    1597          16 : void ospf6_abr_init(void)
    1598             : {
    1599          16 :         ospf6_install_lsa_handler(&inter_prefix_handler);
    1600          16 :         ospf6_install_lsa_handler(&inter_router_handler);
    1601          16 : }

Generated by: LCOV version v1.16-topotato