back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_nssa.c (source / functions) Hit Total Coverage
Test: test_ospf6_vlink.py::VirtualLinkBasic Lines: 120 763 15.7 %
Date: 2023-02-16 02:06:43 Functions: 14 40 35.0 %

          Line data    Source code
       1             : /*
       2             :  * OSPFv3 Not So Stubby Area implementation.
       3             :  *
       4             :  * Copyright (C) 2021 Kaushik Nath
       5             :  * Copyright (C) 2021 Soman K.S
       6             :  *
       7             :  * This program is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 2 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * This program is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU 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; if not, write to the Free Software Foundation, Inc.,
      19             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : #include "log.h"
      24             : #include "prefix.h"
      25             : #include "table.h"
      26             : #include "vty.h"
      27             : #include "linklist.h"
      28             : #include "command.h"
      29             : #include "thread.h"
      30             : #include "plist.h"
      31             : #include "filter.h"
      32             : 
      33             : #include "ospf6_proto.h"
      34             : #include "ospf6_route.h"
      35             : #include "ospf6_lsa.h"
      36             : #include "ospf6_route.h"
      37             : #include "ospf6_lsdb.h"
      38             : #include "ospf6_message.h"
      39             : #include "ospf6_zebra.h"
      40             : 
      41             : #include "ospf6_top.h"
      42             : #include "ospf6_area.h"
      43             : #include "ospf6_interface.h"
      44             : #include "ospf6_neighbor.h"
      45             : 
      46             : #include "ospf6_flood.h"
      47             : #include "ospf6_intra.h"
      48             : #include "ospf6_abr.h"
      49             : #include "ospf6_asbr.h"
      50             : #include "ospf6d.h"
      51             : #include "ospf6_nssa.h"
      52             : #include "ospf6d/ospf6_nssa_clippy.c"
      53             : 
      54          24 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA,         "OSPF6 LSA");
      55             : unsigned char config_debug_ospf6_nssa = 0;
      56             : /* Determine whether this router is elected translator or not for area */
      57           0 : static int ospf6_abr_nssa_am_elected(struct ospf6_area *oa)
      58             : {
      59           0 :         struct ospf6_lsa *lsa;
      60           0 :         struct ospf6_router_lsa *router_lsa;
      61           0 :         in_addr_t *best = NULL;
      62           0 :         uint16_t type;
      63             : 
      64           0 :         type = htons(OSPF6_LSTYPE_ROUTER);
      65             : 
      66             :         /* Verify all the router LSA to compare the router ID */
      67           0 :         for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
      68             : 
      69           0 :                 router_lsa = (struct ospf6_router_lsa
      70           0 :                                       *)((caddr_t)lsa->header
      71             :                                          + sizeof(struct ospf6_lsa_header));
      72             : 
      73             :                 /* ignore non-ABR routers */
      74           0 :                 if (!CHECK_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B))
      75           0 :                         continue;
      76             : 
      77             :                 /* Router has Nt flag - always translate */
      78           0 :                 if (CHECK_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_NT)) {
      79           0 :                         if (IS_OSPF6_DEBUG_NSSA)
      80           0 :                                 zlog_debug("%s: router %pI4 asserts Nt",
      81             :                                            __func__, &lsa->header->id);
      82           0 :                         return 1;
      83             :                 }
      84             : 
      85           0 :                 if (best == NULL)
      86           0 :                         best = &lsa->header->adv_router;
      87           0 :                 else if (IPV4_ADDR_CMP(best, &lsa->header->adv_router) < 0)
      88           0 :                         best = &lsa->header->adv_router;
      89             :         }
      90             : 
      91           0 :         if (best == NULL) {
      92           0 :                 if (IS_OSPF6_DEBUG_NSSA)
      93           0 :                         zlog_debug("%s: best electable ABR not found",
      94             :                                    __func__);
      95           0 :                 return 0;
      96             :         }
      97             : 
      98           0 :         if (IS_OSPF6_DEBUG_NSSA)
      99           0 :                 zlog_debug("%s: best electable ABR is: %pI4", __func__, best);
     100             : 
     101           0 :         if (IPV4_ADDR_CMP(best, &oa->ospf6->router_id) <= 0) {
     102           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     103           0 :                         zlog_debug("%s: elected ABR is: %pI4", __func__, best);
     104           0 :                 return 1;
     105             :         } else {
     106           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     107           0 :                         zlog_debug("%s: not elected best %pI4, router ID %pI4",
     108             :                                    __func__, best, &oa->ospf6->router_id);
     109           0 :                 return 0;
     110             :         }
     111             : }
     112             : 
     113             : /* Flush the translated LSA when translation is disabled */
     114           0 : static void ospf6_flush_translated_lsa(struct ospf6_area *area)
     115             : {
     116           0 :         uint16_t type;
     117           0 :         struct ospf6_lsa *type7;
     118           0 :         struct ospf6_lsa *type5;
     119           0 :         struct ospf6 *ospf6 = area->ospf6;
     120             : 
     121           0 :         if (IS_OSPF6_DEBUG_NSSA)
     122           0 :                 zlog_debug("%s: start area %s", __func__, area->name);
     123             : 
     124           0 :         type = htons(OSPF6_LSTYPE_TYPE_7);
     125           0 :         for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, type7)) {
     126           0 :                 type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
     127             :                                           type7->external_lsa_id,
     128             :                                           ospf6->router_id, ospf6->lsdb);
     129           0 :                 if (type5 && CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT))
     130           0 :                         ospf6_lsa_premature_aging(type5);
     131             :         }
     132           0 :         if (IS_OSPF6_DEBUG_NSSA)
     133           0 :                 zlog_debug("%s: finish area %s", __func__, area->name);
     134           0 : }
     135             : 
     136             : /* Check NSSA status for all nssa areas */
     137          39 : void ospf6_abr_nssa_check_status(struct ospf6 *ospf6)
     138             : {
     139          39 :         struct ospf6_area *area;
     140          39 :         struct listnode *lnode, *nnode;
     141             : 
     142         133 :         for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, nnode, area)) {
     143          55 :                 uint8_t old_state = area->NSSATranslatorState;
     144             : 
     145          55 :                 if (IS_OSPF6_DEBUG_NSSA)
     146           0 :                         zlog_debug("%s: checking area %s flag %x", __func__,
     147             :                                    area->name, area->flag);
     148             : 
     149          55 :                 if (!IS_AREA_NSSA(area))
     150          55 :                         continue;
     151             : 
     152           0 :                 if (!CHECK_FLAG(area->ospf6->flag, OSPF6_FLAG_ABR)) {
     153           0 :                         if (IS_OSPF6_DEBUG_NSSA)
     154           0 :                                 zlog_debug("%s: not ABR", __func__);
     155           0 :                         area->NSSATranslatorState =
     156             :                                 OSPF6_NSSA_TRANSLATE_DISABLED;
     157           0 :                         ospf6_flush_translated_lsa(area);
     158             :                 } else {
     159             :                         /* Router is ABR */
     160           0 :                         if (area->NSSATranslatorRole == OSPF6_NSSA_ROLE_ALWAYS)
     161           0 :                                 area->NSSATranslatorState =
     162             :                                         OSPF6_NSSA_TRANSLATE_ENABLED;
     163             :                         else {
     164             :                                 /* We are a candidate for Translation */
     165           0 :                                 if (ospf6_abr_nssa_am_elected(area) > 0) {
     166           0 :                                         area->NSSATranslatorState =
     167             :                                                 OSPF6_NSSA_TRANSLATE_ENABLED;
     168           0 :                                         if (IS_OSPF6_DEBUG_NSSA)
     169           0 :                                                 zlog_debug(
     170             :                                                         "%s: elected translator",
     171             :                                                         __func__);
     172             :                                 } else {
     173           0 :                                         area->NSSATranslatorState =
     174             :                                                 OSPF6_NSSA_TRANSLATE_DISABLED;
     175           0 :                                         ospf6_flush_translated_lsa(area);
     176           0 :                                         if (IS_OSPF6_DEBUG_NSSA)
     177           0 :                                                 zlog_debug("%s: not elected",
     178             :                                                            __func__);
     179             :                                 }
     180             :                         }
     181             :                 }
     182             : 
     183             :                 /* RFC3101, 3.1:
     184             :                  * All NSSA border routers must set the E-bit in the Type-1
     185             :                  * router-LSAs of their directly attached non-stub areas, even
     186             :                  * when they are not translating.
     187             :                  */
     188           0 :                 if (old_state != area->NSSATranslatorState) {
     189           0 :                         if (old_state == OSPF6_NSSA_TRANSLATE_DISABLED) {
     190           0 :                                 ++ospf6->redist_count;
     191           0 :                                 ospf6_asbr_status_update(ospf6,
     192             :                                                          ospf6->redist_count);
     193             :                         } else {
     194           0 :                                 --ospf6->redist_count;
     195           0 :                                 ospf6_asbr_status_update(ospf6,
     196             :                                                          ospf6->redist_count);
     197             :                         }
     198             :                 }
     199             :         }
     200          39 : }
     201             : 
     202             : /* Mark the summary LSA's as unapproved, when ABR status changes.*/
     203           1 : static void ospf6_abr_unapprove_summaries(struct ospf6 *ospf6)
     204             : {
     205           1 :         struct listnode *node, *nnode;
     206           1 :         struct ospf6_area *area;
     207           1 :         struct ospf6_lsa *lsa;
     208           1 :         uint16_t type;
     209             : 
     210           1 :         if (IS_OSPF6_DEBUG_ABR)
     211           0 :                 zlog_debug("%s : Start", __func__);
     212             : 
     213           4 :         for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
     214           2 :                 if (IS_OSPF6_DEBUG_ABR)
     215           0 :                         zlog_debug("%s : considering area %pI4", __func__,
     216             :                                    &area->area_id);
     217             :                 /* Inter area router LSA */
     218           2 :                 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
     219           2 :                 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
     220             :                                            lsa)) {
     221           0 :                         if (IS_OSPF6_DEBUG_ABR)
     222           0 :                                 zlog_debug(
     223             :                                         "%s : approved unset on summary link id %pI4",
     224             :                                         __func__, &lsa->header->id);
     225           0 :                         SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
     226             :                 }
     227             :                 /* Inter area prefix LSA */
     228           2 :                 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
     229           2 :                 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
     230             :                                            lsa)) {
     231           0 :                         if (IS_OSPF6_DEBUG_ABR)
     232           0 :                                 zlog_debug(
     233             :                                         "%s : approved unset on asbr-summary link id %pI4",
     234             :                                         __func__, &lsa->header->id);
     235           0 :                         SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
     236             :                 }
     237             :         }
     238             : 
     239           1 :         if (IS_OSPF6_DEBUG_ABR)
     240           0 :                 zlog_debug("%s : Stop", __func__);
     241           1 : }
     242             : 
     243             : /* Re-advertise inter-area router LSA's */
     244           1 : void ospf6_asbr_prefix_readvertise(struct ospf6 *ospf6)
     245             : {
     246           1 :         struct ospf6_route *brouter;
     247           1 :         struct listnode *node, *nnode;
     248           1 :         struct ospf6_area *oa;
     249             : 
     250           1 :         if (IS_OSPF6_DEBUG_ABR)
     251           0 :                 zlog_debug("Re-examining Inter-Router prefixes");
     252             : 
     253             : 
     254           4 :         for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
     255           2 :                 for (brouter = ospf6_route_head(oa->ospf6->brouter_table);
     256           6 :                      brouter; brouter = ospf6_route_next(brouter))
     257           4 :                         ospf6_abr_originate_summary_to_area(brouter, oa);
     258             :         }
     259             : 
     260           1 :         if (IS_OSPF6_DEBUG_ABR)
     261           0 :                 zlog_debug("Finished re-examining Inter-Router prefixes");
     262           1 : }
     263             : 
     264             : /* Advertise prefixes configured using area <area-id> range command */
     265           1 : static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6)
     266             : {
     267           1 :         struct ospf6_area *area;
     268           1 :         struct ospf6_route *range;
     269           1 :         struct listnode *node;
     270             : 
     271           1 :         if (IS_OSPF6_DEBUG_ABR)
     272           0 :                 zlog_debug("%s: Start", __func__);
     273             : 
     274           4 :         for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
     275           2 :                 if (IS_OSPF6_DEBUG_ABR)
     276           0 :                         zlog_debug(
     277             :                                 "ospf_abr_announce_aggregates(): looking at area %pI4",
     278             :                                 &area->area_id);
     279             : 
     280           2 :                 for (range = ospf6_route_head(area->range_table); range;
     281           0 :                      range = ospf6_route_next(range))
     282           0 :                         ospf6_abr_range_update(range, ospf6);
     283             :         }
     284             : 
     285           1 :         if (IS_OSPF6_DEBUG_ABR)
     286           0 :                 zlog_debug("%s: Stop", __func__);
     287           1 : }
     288             : 
     289             : /* Flush the summary LSA's which are not approved.*/
     290           1 : void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6)
     291             : {
     292           1 :         struct listnode *node, *nnode;
     293           1 :         struct ospf6_area *area;
     294           1 :         struct ospf6_lsa *lsa;
     295           1 :         uint16_t type;
     296             : 
     297           1 :         if (IS_OSPF6_DEBUG_ABR)
     298           0 :                 zlog_debug("%s : Start", __func__);
     299             : 
     300           4 :         for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
     301           2 :                 if (IS_OSPF6_DEBUG_ABR)
     302           0 :                         zlog_debug("%s : looking at area %pI4", __func__,
     303             :                                    &area->area_id);
     304             : 
     305             :                 /* Inter area router LSA */
     306           2 :                 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
     307           2 :                 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
     308             :                                            lsa)) {
     309           0 :                         if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED))
     310           0 :                                 ospf6_lsa_premature_aging(lsa);
     311             :                 }
     312             : 
     313             :                 /* Inter area prefix LSA */
     314           2 :                 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
     315           2 :                 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
     316             :                                            lsa)) {
     317           0 :                         if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED))
     318           0 :                                 ospf6_lsa_premature_aging(lsa);
     319             :                 }
     320             :         }
     321             : 
     322           1 :         if (IS_OSPF6_DEBUG_ABR)
     323           0 :                 zlog_debug("%s : Stop", __func__);
     324           1 : }
     325             : 
     326             : /*
     327             :  * This is the function taking care about ABR stuff, i.e.
     328             :  * summary-LSA origination and flooding.
     329             :  */
     330           1 : static void ospf6_abr_task(struct ospf6 *ospf6)
     331             : {
     332           1 :         if (IS_OSPF6_DEBUG_ABR)
     333           0 :                 zlog_debug("%s : Start", __func__);
     334             : 
     335           1 :         if (ospf6->route_table == NULL || ospf6->brouter_table == NULL) {
     336           0 :                 if (IS_OSPF6_DEBUG_ABR)
     337           0 :                         zlog_debug("%s : Routing tables are not yet ready",
     338             :                                    __func__);
     339           0 :                 return;
     340             :         }
     341             : 
     342           1 :         ospf6_abr_unapprove_summaries(ospf6);
     343             : 
     344           1 :         if (IS_OSPF6_DEBUG_ABR)
     345           0 :                 zlog_debug("%s : prepare aggregates", __func__);
     346             : 
     347           1 :         ospf6_abr_range_reset_cost(ospf6);
     348             : 
     349           1 :         if (IS_OSPF6_ABR(ospf6)) {
     350           1 :                 if (IS_OSPF6_DEBUG_ABR)
     351           0 :                         zlog_debug("%s : process network RT", __func__);
     352           1 :                 ospf6_abr_prefix_resummarize(ospf6);
     353             : 
     354           1 :                 if (IS_OSPF6_DEBUG_ABR)
     355           0 :                         zlog_debug("%s : process router RT", __func__);
     356           1 :                 ospf6_asbr_prefix_readvertise(ospf6);
     357             : 
     358           1 :                 if (IS_OSPF6_DEBUG_ABR)
     359           0 :                         zlog_debug("%s : announce aggregates", __func__);
     360           1 :                 ospf6_abr_announce_aggregates(ospf6);
     361             : 
     362           1 :                 if (IS_OSPF6_DEBUG_ABR)
     363           0 :                         zlog_debug("%s : announce stub defaults", __func__);
     364           1 :                 ospf6_abr_defaults_to_stub(ospf6);
     365             : 
     366           1 :                 if (IS_OSPF6_DEBUG_ABR)
     367           0 :                         zlog_debug("%s : announce NSSA Type-7 defaults",
     368             :                                    __func__);
     369           1 :                 ospf6_abr_nssa_type_7_defaults(ospf6);
     370             :         }
     371             : 
     372           1 :         if (IS_OSPF6_DEBUG_ABR)
     373           0 :                 zlog_debug("%s : remove unapproved summaries", __func__);
     374           1 :         ospf6_abr_remove_unapproved_summaries(ospf6);
     375             : 
     376           1 :         if (IS_OSPF6_DEBUG_ABR)
     377           0 :                 zlog_debug("%s : Stop", __func__);
     378             : }
     379             : 
     380             : /* For NSSA Translations
     381             :  * Mark the translated LSA's as unapproved. */
     382           0 : static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6)
     383             : {
     384           0 :         struct ospf6_lsa *lsa;
     385           0 :         uint16_t type;
     386             : 
     387           0 :         if (IS_OSPF6_DEBUG_NSSA)
     388           0 :                 zlog_debug("%s: Start", __func__);
     389             : 
     390           0 :         type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
     391           0 :         for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) {
     392           0 :                 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) {
     393           0 :                         SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
     394           0 :                         if (IS_OSPF6_DEBUG_NSSA)
     395           0 :                                 zlog_debug(
     396             :                                         "%s : approved unset on link id %pI4",
     397             :                                         __func__, &lsa->header->id);
     398             :                 }
     399             :         }
     400             : 
     401           0 :         if (IS_OSPF6_DEBUG_NSSA)
     402           0 :                 zlog_debug("%s: Stop", __func__);
     403           0 : }
     404             : 
     405             : /* Generate the translated external lsa from NSSA lsa */
     406           0 : static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
     407             :                                                        struct ospf6_lsa *type7)
     408             : {
     409           0 :         char buffer[OSPF6_MAX_LSASIZE];
     410           0 :         struct ospf6_lsa *lsa;
     411           0 :         struct ospf6_as_external_lsa *ext, *extnew;
     412           0 :         struct ospf6_lsa_header *lsa_header;
     413           0 :         caddr_t old_ptr, new_ptr;
     414           0 :         struct ospf6_as_external_lsa *nssa;
     415           0 :         struct prefix prefix;
     416           0 :         struct ospf6 *ospf6 = area->ospf6;
     417           0 :         ptrdiff_t tag_offset = 0;
     418           0 :         route_tag_t network_order;
     419           0 :         struct ospf6_route *range;
     420             : 
     421           0 :         if (IS_OSPF6_DEBUG_NSSA)
     422           0 :                 zlog_debug("%s : Start", __func__);
     423             : 
     424           0 :         if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
     425           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     426           0 :                         zlog_debug("%s: Translation disabled for area %s",
     427             :                                    __func__, area->name);
     428           0 :                 return NULL;
     429             :         }
     430             : 
     431             :         /* find the translated Type-5 for this Type-7 */
     432           0 :         nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
     433             :                 type7->header);
     434           0 :         prefix.family = AF_INET6;
     435           0 :         prefix.prefixlen = nssa->prefix.prefix_length;
     436           0 :         ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
     437             : 
     438             :         /* Check if the Type-7 LSA should be suppressed by aggregation. */
     439           0 :         range = ospf6_route_lookup_bestmatch(&prefix, area->nssa_range_table);
     440           0 :         if (range && !prefix_same(&prefix, &range->prefix)
     441           0 :             && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
     442           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     443           0 :                         zlog_debug(
     444             :                                 "%s: LSA %s suppressed by range %pFX of area %s",
     445             :                                 __func__, type7->name, &range->prefix,
     446             :                                 area->name);
     447           0 :                 return NULL;
     448             :         }
     449             : 
     450             :         /* prepare buffer */
     451           0 :         memset(buffer, 0, sizeof(buffer));
     452           0 :         lsa_header = (struct ospf6_lsa_header *)buffer;
     453           0 :         extnew = (struct ospf6_as_external_lsa
     454             :                           *)((caddr_t)lsa_header
     455             :                              + sizeof(struct ospf6_lsa_header));
     456           0 :         ext = (struct ospf6_as_external_lsa
     457           0 :                        *)((caddr_t)(type7->header)
     458             :                           + sizeof(struct ospf6_lsa_header));
     459           0 :         old_ptr =
     460             :                 (caddr_t)((caddr_t)ext + sizeof(struct ospf6_as_external_lsa));
     461           0 :         new_ptr = (caddr_t)((caddr_t)extnew
     462             :                             + sizeof(struct ospf6_as_external_lsa));
     463             : 
     464           0 :         memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa));
     465             : 
     466             :         /* set Prefix */
     467           0 :         memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length));
     468           0 :         ospf6_prefix_apply_mask(&extnew->prefix);
     469           0 :         new_ptr += OSPF6_PREFIX_SPACE(extnew->prefix.prefix_length);
     470             : 
     471           0 :         tag_offset =
     472           0 :                 sizeof(*ext) + OSPF6_PREFIX_SPACE(ext->prefix.prefix_length);
     473             : 
     474             :         /* Forwarding address */
     475           0 :         if (CHECK_FLAG(ext->bits_metric, OSPF6_ASBR_BIT_F)) {
     476           0 :                 memcpy(new_ptr, (caddr_t)ext + tag_offset,
     477             :                        sizeof(struct in6_addr));
     478           0 :                 new_ptr += sizeof(struct in6_addr);
     479           0 :                 tag_offset += sizeof(struct in6_addr);
     480             :         }
     481             :         /* External Route Tag */
     482           0 :         if (CHECK_FLAG(ext->bits_metric, OSPF6_ASBR_BIT_T)) {
     483           0 :                 memcpy(&network_order, (caddr_t)ext + tag_offset,
     484             :                        sizeof(network_order));
     485           0 :                 network_order = htonl(network_order);
     486           0 :                 memcpy(new_ptr, &network_order, sizeof(network_order));
     487           0 :                 new_ptr += sizeof(network_order);
     488             :         }
     489             : 
     490             :         /* Fill LSA Header */
     491           0 :         lsa_header->age = 0;
     492           0 :         lsa_header->type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
     493           0 :         lsa_header->id = htonl(ospf6->external_id);
     494           0 :         ospf6->external_id++;
     495           0 :         lsa_header->adv_router = ospf6->router_id;
     496           0 :         lsa_header->seqnum =
     497           0 :                 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
     498             :                                     lsa_header->adv_router, ospf6->lsdb);
     499           0 :         lsa_header->length = htons((caddr_t)new_ptr - (caddr_t)lsa_header);
     500           0 :         type7->external_lsa_id = lsa_header->id;
     501             : 
     502             :         /* LSA checksum */
     503           0 :         ospf6_lsa_checksum(lsa_header);
     504             : 
     505             :         /* create LSA */
     506           0 :         lsa = ospf6_lsa_create(lsa_header);
     507             : 
     508           0 :         SET_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT);
     509           0 :         UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
     510             : 
     511             :         /* Originate */
     512           0 :         ospf6_lsa_originate_process(lsa, ospf6);
     513             : 
     514           0 :         if (IS_OSPF6_DEBUG_NSSA)
     515           0 :                 zlog_debug("%s: Originated type5 LSA id %pI4", __func__,
     516             :                            &lsa_header->id);
     517             :         return lsa;
     518             : }
     519             : 
     520             : /* Delete LSA from retransmission list */
     521           0 : static void ospf6_ls_retransmit_delete_nbr_as(struct ospf6 *ospf6,
     522             :                                               struct ospf6_lsa *lsa)
     523             : {
     524           0 :         struct listnode *node, *nnode;
     525           0 :         struct ospf6_area *area;
     526             : 
     527           0 :         if (IS_OSPF6_DEBUG_NSSA)
     528           0 :                 zlog_debug("%s : start lsa %s", __func__, lsa->name);
     529             : 
     530             :         /*The function ospf6_flood_clear_area removes LSA from
     531             :          * retransmit list.
     532             :          */
     533           0 :         for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area))
     534           0 :                 ospf6_flood_clear_area(lsa, area);
     535             : 
     536           0 :         if (IS_OSPF6_DEBUG_NSSA)
     537           0 :                 zlog_debug("%s : finish lsa %s", __func__, lsa->name);
     538           0 : }
     539             : 
     540             : /* Refresh translated AS-external-LSA. */
     541           0 : struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
     542             :                                                 struct ospf6_lsa *type7,
     543             :                                                 struct ospf6_lsa *type5)
     544             : {
     545           0 :         struct ospf6_lsa *new = NULL;
     546           0 :         struct prefix prefix;
     547           0 :         struct ospf6 *ospf6 = area->ospf6;
     548             : 
     549           0 :         if (IS_OSPF6_DEBUG_NSSA)
     550           0 :                 zlog_debug("%s : start area %s", __func__, area->name);
     551             : 
     552             :         /* Sanity checks. */
     553           0 :         assert(type7);
     554             : 
     555             :         /* Find the AS external LSA */
     556           0 :         if (type5 == NULL) {
     557           0 :                 struct ospf6_as_external_lsa *ext_lsa;
     558           0 :                 struct ospf6_route *match;
     559             : 
     560             :                 /* Find the AS external LSA from Type-7 LSA */
     561           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     562           0 :                         zlog_debug(
     563             :                                 "%s: try to find translated Type-5 LSA for %s",
     564             :                                 __func__, type7->name);
     565             : 
     566           0 :                 ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
     567             :                         type7->header);
     568           0 :                 prefix.family = AF_INET6;
     569           0 :                 prefix.prefixlen = ext_lsa->prefix.prefix_length;
     570           0 :                 ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa,
     571           0 :                                       &ext_lsa->prefix);
     572             : 
     573           0 :                 match = ospf6_route_lookup(&prefix, ospf6->external_table);
     574           0 :                 if (match)
     575           0 :                         type5 = ospf6_lsdb_lookup(
     576           0 :                                 htons(OSPF6_LSTYPE_AS_EXTERNAL),
     577             :                                 match->path.origin.id, ospf6->router_id,
     578             :                                 ospf6->lsdb);
     579             :         }
     580             : 
     581           0 :         if (type5) {
     582           0 :                 if (CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT)) {
     583             :                         /* Delete LSA from neighbor retransmit-list. */
     584           0 :                         ospf6_ls_retransmit_delete_nbr_as(ospf6, type5);
     585             : 
     586             :                         /* Flush the LSA */
     587           0 :                         ospf6_lsa_premature_aging(type5);
     588             :                 } else {
     589           0 :                         if (IS_OSPF6_DEBUG_NSSA)
     590           0 :                                 zlog_debug("%s: Invalid translated LSA %s",
     591             :                                            __func__, type5->name);
     592           0 :                         return NULL;
     593             :                 }
     594             :         }
     595             : 
     596             :         /* create new translated LSA */
     597           0 :         if (ospf6_lsa_age_current(type7) != OSPF_LSA_MAXAGE) {
     598           0 :                 if ((new = ospf6_lsa_translated_nssa_new(area, type7))
     599             :                     == NULL) {
     600           0 :                         if (IS_OSPF6_DEBUG_NSSA)
     601           0 :                                 zlog_debug(
     602             :                                         "%s: Could not translate Type-7 for %pI4",
     603             :                                         __func__, &type7->header->id);
     604           0 :                         return NULL;
     605             :                 }
     606             :         }
     607             : 
     608           0 :         if (IS_OSPF6_DEBUG_NSSA)
     609           0 :                 zlog_debug("%s: finish", __func__);
     610             : 
     611             :         return new;
     612             : }
     613             : 
     614           0 : static void ospf6_abr_translate_nssa(struct ospf6_area *area,
     615             :                                      struct ospf6_lsa *lsa)
     616             : {
     617             :         /* Incoming Type-7 or aggregated Type-7
     618             :          *
     619             :          * LSA is skipped if P-bit is off.
     620             :          *
     621             :          * The Type-7 is translated, Installed/Approved as a Type-5 into
     622             :          * global LSDB, then Flooded through AS
     623             :          *
     624             :          *  Later, any Unapproved Translated Type-5's are flushed/discarded
     625             :          */
     626             : 
     627           0 :         struct ospf6_lsa *old = NULL;
     628           0 :         struct ospf6_as_external_lsa *nssa_lsa;
     629           0 :         struct prefix prefix;
     630           0 :         struct ospf6_route *match;
     631           0 :         struct ospf6 *ospf6;
     632             : 
     633           0 :         ospf6 = area->ospf6;
     634           0 :         nssa_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
     635             :                 lsa->header);
     636             : 
     637           0 :         if (!CHECK_FLAG(nssa_lsa->prefix.prefix_options,
     638             :                         OSPF6_PREFIX_OPTION_P)) {
     639           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     640           0 :                         zlog_debug(
     641             :                                 "%s : LSA Id %pI4, P-bit off, NO Translation",
     642             :                                 __func__, &lsa->header->id);
     643           0 :                 return;
     644             :         }
     645             : 
     646           0 :         if (IS_OSPF6_DEBUG_NSSA)
     647           0 :                 zlog_debug(
     648             :                         "%s : LSA Id %pI4 external ID %pI4, Translating type 7 to 5",
     649             :                         __func__, &lsa->header->id, &lsa->external_lsa_id);
     650             : 
     651           0 :         prefix.family = AF_INET6;
     652           0 :         prefix.prefixlen = nssa_lsa->prefix.prefix_length;
     653           0 :         ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa_lsa, &nssa_lsa->prefix);
     654             : 
     655           0 :         if (!CHECK_FLAG(nssa_lsa->bits_metric, OSPF6_ASBR_BIT_F)) {
     656           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     657           0 :                         zlog_debug(
     658             :                                 "%s : LSA Id %pI4, Forward address is 0, NO Translation",
     659             :                                 __func__, &lsa->header->id);
     660           0 :                 return;
     661             :         }
     662             : 
     663             :         /* Find the type-5 LSA in the area-range table */
     664           0 :         match = ospf6_route_lookup_bestmatch(&prefix, area->nssa_range_table);
     665           0 :         if (match && CHECK_FLAG(match->flag, OSPF6_ROUTE_NSSA_RANGE)) {
     666           0 :                 if (prefix_same(&prefix, &match->prefix)) {
     667             :                         /* The prefix range is being removed,
     668             :                          * no need to refresh
     669             :                          */
     670           0 :                         if
     671           0 :                                 CHECK_FLAG(match->flag, OSPF6_ROUTE_REMOVE)
     672             :                         return;
     673             :                 } else {
     674           0 :                         if (!CHECK_FLAG(match->flag, OSPF6_ROUTE_REMOVE)) {
     675           0 :                                 if (IS_OSPF6_DEBUG_NSSA)
     676           0 :                                         zlog_debug(
     677             :                                                 "%s: LSA Id %pI4 suppressed by range %pFX of area %s",
     678             :                                                 __func__, &lsa->header->id,
     679             :                                                 &match->prefix, area->name);
     680             :                                 /* LSA will be suppressed by area-range command,
     681             :                                  * no need to refresh
     682             :                                  */
     683           0 :                                 return;
     684             :                         }
     685             :                 }
     686             :         }
     687             : 
     688             :         /* Find the existing AS-External LSA for this prefix */
     689           0 :         match = ospf6_route_lookup(&prefix, ospf6->route_table);
     690           0 :         if (match) {
     691           0 :                 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
     692             :                                         lsa->external_lsa_id, ospf6->router_id,
     693             :                                         ospf6->lsdb);
     694             :         }
     695             : 
     696           0 :         if (OSPF6_LSA_IS_MAXAGE(lsa)) {
     697           0 :                 if (old)
     698           0 :                         ospf6_lsa_premature_aging(old);
     699           0 :                 return;
     700             :         }
     701             : 
     702           0 :         if (old && !OSPF6_LSA_IS_MAXAGE(old)) {
     703           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     704           0 :                         zlog_debug(
     705             :                                 "%s : found old translated LSA Id %pI4, skip",
     706             :                                 __func__, &old->header->id);
     707             : 
     708           0 :                 UNSET_FLAG(old->flag, OSPF6_LSA_UNAPPROVED);
     709           0 :                 return;
     710             : 
     711             :         } else {
     712             :                 /* no existing external route for this LSA Id
     713             :                  * originate translated LSA
     714             :                  */
     715             : 
     716           0 :                 if (ospf6_lsa_translated_nssa_new(area, lsa) == NULL) {
     717           0 :                         if (IS_OSPF6_DEBUG_NSSA)
     718           0 :                                 zlog_debug(
     719             :                                         "%s : Could not translate Type-7 for %pI4 to Type-5",
     720             :                                         __func__, &lsa->header->id);
     721           0 :                         return;
     722             :                 }
     723             :         }
     724             : }
     725             : 
     726           0 : static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
     727             : {
     728             :         /* Scan through all NSSA_LSDB records for all areas;
     729             :          * If P-bit is on, translate all Type-7's to 5's and aggregate or
     730             :          * flood install as approved in Type-5 LSDB with XLATE Flag on
     731             :          * later, do same for all aggregates...  At end, DISCARD all
     732             :          * remaining UNAPPROVED Type-5's (Aggregate is for future ) */
     733             : 
     734           0 :         struct listnode *node;
     735           0 :         struct ospf6_area *oa;
     736           0 :         struct ospf6_lsa *lsa;
     737           0 :         int type;
     738             : 
     739           0 :         if (IS_OSPF6_DEBUG_NSSA)
     740           0 :                 zlog_debug("%s : Start", __func__);
     741             : 
     742           0 :         for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
     743           0 :                 if (!IS_AREA_NSSA(oa))
     744           0 :                         continue;
     745             : 
     746             :                 /* skip if not translator */
     747           0 :                 if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
     748           0 :                         zlog_debug("%s area %pI4 NSSATranslatorState %d",
     749             :                                    __func__, &oa->area_id,
     750             :                                    oa->NSSATranslatorState);
     751           0 :                         continue;
     752             :                 }
     753             : 
     754           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     755           0 :                         zlog_debug("%s : looking at area %pI4", __func__,
     756             :                                    &oa->area_id);
     757             : 
     758           0 :                 type = htons(OSPF6_LSTYPE_TYPE_7);
     759           0 :                 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
     760           0 :                         zlog_debug("%s : lsa %s , id %pI4 , adv router %pI4",
     761             :                                    __func__, lsa->name, &lsa->header->id,
     762             :                                    &lsa->header->adv_router);
     763           0 :                         ospf6_abr_translate_nssa(oa, lsa);
     764             :                 }
     765             :         }
     766             : 
     767           0 :         if (IS_OSPF6_DEBUG_NSSA)
     768           0 :                 zlog_debug("%s : Stop", __func__);
     769           0 : }
     770             : 
     771           0 : static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6)
     772             : {
     773           0 :         struct listnode *node;
     774           0 :         struct ospf6_area *area;
     775           0 :         struct ospf6_route *range;
     776             : 
     777           0 :         if (IS_OSPF6_DEBUG_NSSA)
     778           0 :                 zlog_debug("%s: Start", __func__);
     779             : 
     780           0 :         for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
     781           0 :                 if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED)
     782           0 :                         continue;
     783             : 
     784           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     785           0 :                         zlog_debug("%s: looking at area %pI4", __func__,
     786             :                                    &area->area_id);
     787             : 
     788           0 :                 for (range = ospf6_route_head(area->nssa_range_table); range;
     789           0 :                      range = ospf6_route_next(range))
     790           0 :                         ospf6_abr_range_update(range, ospf6);
     791             :         }
     792             : 
     793           0 :         if (IS_OSPF6_DEBUG_NSSA)
     794           0 :                 zlog_debug("%s: Stop", __func__);
     795           0 : }
     796             : 
     797           0 : static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
     798             : {
     799           0 :         struct ospf6_lsa *lsa;
     800           0 :         uint16_t type;
     801             : 
     802             :         /* All AREA PROCESS should have APPROVED necessary LSAs */
     803             :         /* Remove any left over and not APPROVED */
     804           0 :         if (IS_OSPF6_DEBUG_NSSA)
     805           0 :                 zlog_debug("%s: Start", __func__);
     806             : 
     807           0 :         type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
     808           0 :         for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) {
     809           0 :                 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)
     810             :                     && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
     811           0 :                         zlog_debug(
     812             :                                 "%s : removing unapproved translates, lsa : %s",
     813             :                                 __func__, lsa->name);
     814             : 
     815           0 :                         ospf6_lsa_premature_aging(lsa);
     816             :                 }
     817             :         }
     818             : 
     819           0 :         if (IS_OSPF6_DEBUG_NSSA)
     820           0 :                 zlog_debug("%s: Stop", __func__);
     821           0 : }
     822             : 
     823           0 : static void ospf6_abr_nssa_type_7_default_create(struct ospf6 *ospf6,
     824             :                                                  struct ospf6_area *oa)
     825             : {
     826           0 :         struct ospf6_route *def;
     827           0 :         int metric;
     828           0 :         int metric_type;
     829             : 
     830           0 :         if (IS_OSPF6_DEBUG_NSSA)
     831           0 :                 zlog_debug("Announcing Type-7 default route into NSSA area %s",
     832             :                            oa->name);
     833             : 
     834           0 :         def = ospf6_route_create(ospf6);
     835           0 :         def->type = OSPF6_DEST_TYPE_NETWORK;
     836           0 :         def->prefix.family = AF_INET6;
     837           0 :         def->prefix.prefixlen = 0;
     838           0 :         memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
     839           0 :         def->type = OSPF6_DEST_TYPE_NETWORK;
     840           0 :         def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
     841           0 :         if (CHECK_FLAG(ospf6->flag, OSPF6_FLAG_ABR))
     842           0 :                 def->path.area_id = ospf6->backbone->area_id;
     843             :         else
     844           0 :                 def->path.area_id = oa->area_id;
     845             : 
     846             :         /* Compute default route type and metric. */
     847           0 :         if (oa->nssa_default_originate.metric_value != -1)
     848           0 :                 metric = oa->nssa_default_originate.metric_value;
     849             :         else
     850             :                 metric = DEFAULT_DEFAULT_ALWAYS_METRIC;
     851           0 :         if (oa->nssa_default_originate.metric_type != -1)
     852           0 :                 metric_type = oa->nssa_default_originate.metric_type;
     853             :         else
     854             :                 metric_type = DEFAULT_METRIC_TYPE;
     855           0 :         def->path.metric_type = metric_type;
     856           0 :         def->path.cost = metric;
     857           0 :         if (metric_type == 1)
     858           0 :                 def->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
     859             :         else
     860           0 :                 def->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
     861             : 
     862           0 :         ospf6_nssa_lsa_originate(def, oa, false);
     863           0 :         ospf6_route_delete(def);
     864           0 : }
     865             : 
     866          24 : static void ospf6_abr_nssa_type_7_default_delete(struct ospf6 *ospf6,
     867             :                                                  struct ospf6_area *oa)
     868             : {
     869          24 :         struct ospf6_lsa *lsa;
     870             : 
     871          48 :         lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_TYPE_7), 0,
     872          24 :                                 oa->ospf6->router_id, oa->lsdb);
     873          24 :         if (lsa && !OSPF6_LSA_IS_MAXAGE(lsa)) {
     874           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     875           0 :                         zlog_debug(
     876             :                                 "Withdrawing Type-7 default route from area %s",
     877             :                                 oa->name);
     878             : 
     879           0 :                 ospf6_lsa_purge(lsa);
     880             :         }
     881          24 : }
     882             : 
     883             : /* NSSA Type-7 default route. */
     884          12 : void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6)
     885             : {
     886          12 :         struct listnode *node;
     887          12 :         struct ospf6_area *oa;
     888             : 
     889          48 :         for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
     890          24 :                 if (IS_AREA_NSSA(oa) && oa->nssa_default_originate.enabled
     891           0 :                     && (IS_OSPF6_ABR(ospf6)
     892           0 :                         || (IS_OSPF6_ASBR(ospf6)
     893           0 :                             && ospf6->nssa_default_import_check.status)))
     894           0 :                         ospf6_abr_nssa_type_7_default_create(ospf6, oa);
     895             :                 else
     896          24 :                         ospf6_abr_nssa_type_7_default_delete(ospf6, oa);
     897             :         }
     898          12 : }
     899             : 
     900           1 : static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
     901             : {
     902           1 :         if (IS_OSPF6_DEBUG_NSSA)
     903           0 :                 zlog_debug("Check for NSSA-ABR Tasks():");
     904             : 
     905           1 :         if (!IS_OSPF6_ABR(ospf6)) {
     906           0 :                 if (IS_OSPF6_DEBUG_NSSA)
     907           0 :                         zlog_debug("%s  Not ABR", __func__);
     908           0 :                 return;
     909             :         }
     910             : 
     911           1 :         if (!ospf6->anyNSSA) {
     912           1 :                 if (IS_OSPF6_DEBUG_NSSA)
     913           0 :                         zlog_debug("%s  Not NSSA", __func__);
     914           1 :                 return;
     915             :         }
     916             : 
     917             :         /* Each area must confirm TranslatorRole */
     918           0 :         if (IS_OSPF6_DEBUG_NSSA)
     919           0 :                 zlog_debug("%s: Start", __func__);
     920             : 
     921             :         /* For all Global Entries flagged "local-translate", unset APPROVED */
     922           0 :         if (IS_OSPF6_DEBUG_NSSA)
     923           0 :                 zlog_debug("%s: unapprove translates", __func__);
     924             : 
     925           0 :         ospf6_abr_unapprove_translates(ospf6);
     926             : 
     927             :         /* Originate Type-7 aggregates */
     928           0 :         if (IS_OSPF6_DEBUG_NSSA)
     929           0 :                 zlog_debug("%s: send NSSA aggregates", __func__);
     930           0 :         ospf6_abr_send_nssa_aggregates(ospf6);
     931             : 
     932             :         /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
     933             :          *  Aggregate as Type-7
     934             :          * Install or Approve in Type-5 Global LSDB
     935             :          */
     936           0 :         if (IS_OSPF6_DEBUG_NSSA)
     937           0 :                 zlog_debug("%s: process translates", __func__);
     938           0 :         ospf6_abr_process_nssa_translates(ospf6);
     939             : 
     940             :         /* Flush any unapproved previous translates from Global Data Base */
     941           0 :         if (IS_OSPF6_DEBUG_NSSA)
     942           0 :                 zlog_debug("%s: remove unapproved translates", __func__);
     943           0 :         ospf6_abr_remove_unapproved_translates(ospf6);
     944             : 
     945           0 :         if (IS_OSPF6_DEBUG_NSSA)
     946           0 :                 zlog_debug("%s: Stop", __func__);
     947             : }
     948             : 
     949           0 : int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
     950             :                              int type)
     951             : {
     952           0 :         route_map_result_t ret;
     953           0 :         struct prefix *prefix;
     954           0 :         struct ospf6_redist *red;
     955             : 
     956           0 :         if (!ospf6_zebra_is_redistribute(type, ospf6->vrf_id))
     957             :                 return 0;
     958             : 
     959           0 :         prefix = &route->prefix;
     960             : 
     961           0 :         red = ospf6_redist_lookup(ospf6, type, 0);
     962           0 :         if (!red)
     963             :                 return 0;
     964             : 
     965             :         /* Change to new redist structure */
     966           0 :         if (ROUTEMAP_NAME(red)) {
     967           0 :                 if (ROUTEMAP(red) == NULL)
     968           0 :                         ospf6_asbr_routemap_update(NULL);
     969           0 :                 if (ROUTEMAP(red) == NULL) {
     970           0 :                         zlog_warn(
     971             :                                 "route-map \"%s\" not found, suppress redistributing",
     972             :                                 ROUTEMAP_NAME(red));
     973           0 :                         return 0;
     974             :                 }
     975             :         }
     976             : 
     977             :         /*  Change to new redist structure */
     978           0 :         if (ROUTEMAP(red)) {
     979           0 :                 ret = route_map_apply(ROUTEMAP(red), prefix, route);
     980           0 :                 if (ret == RMAP_DENYMATCH) {
     981           0 :                         if (IS_OSPF6_DEBUG_ASBR)
     982           0 :                                 zlog_debug("Denied by route-map \"%s\"",
     983             :                                            ROUTEMAP_NAME(red));
     984           0 :                         return 0;
     985             :                 }
     986             :         }
     987             : 
     988             :         return 1;
     989             : }
     990             : 
     991             : /* This function performs ABR related processing */
     992           1 : static void ospf6_abr_task_timer(struct thread *thread)
     993             : {
     994           1 :         struct ospf6 *ospf6 = THREAD_ARG(thread);
     995             : 
     996           1 :         if (IS_OSPF6_DEBUG_ABR)
     997           0 :                 zlog_debug("Running ABR task on timer");
     998             : 
     999           1 :         (void)ospf6_check_and_set_router_abr(ospf6);
    1000           1 :         ospf6_abr_nssa_check_status(ospf6);
    1001           1 :         ospf6_abr_task(ospf6);
    1002             :         /* if nssa-abr, then scan Type-7 LSDB */
    1003           1 :         ospf6_abr_nssa_task(ospf6);
    1004           1 : }
    1005             : 
    1006           2 : void ospf6_schedule_abr_task(struct ospf6 *ospf6)
    1007             : {
    1008           2 :         if (thread_is_scheduled(ospf6->t_abr_task)) {
    1009           1 :                 if (IS_OSPF6_DEBUG_ABR)
    1010           0 :                         zlog_debug("ABR task already scheduled");
    1011           1 :                 return;
    1012             :         }
    1013             : 
    1014           1 :         if (IS_OSPF6_DEBUG_ABR)
    1015           0 :                 zlog_debug("Scheduling ABR task");
    1016             : 
    1017           1 :         thread_add_timer(master, ospf6_abr_task_timer, ospf6,
    1018             :                          OSPF6_ABR_TASK_DELAY, &ospf6->t_abr_task);
    1019             : }
    1020             : 
    1021             : /* Flush the NSSA LSAs from the area */
    1022           0 : static void ospf6_nssa_flush_area(struct ospf6_area *area)
    1023             : {
    1024           0 :         uint16_t type;
    1025           0 :         struct ospf6_lsa *lsa = NULL, *type5 = NULL;
    1026           0 :         struct ospf6 *ospf6 = area->ospf6;
    1027             : 
    1028           0 :         if (IS_OSPF6_DEBUG_NSSA)
    1029           0 :                 zlog_debug("%s: area %s", __func__, area->name);
    1030             : 
    1031             :         /* Flush the NSSA LSA */
    1032           0 :         type = htons(OSPF6_LSTYPE_TYPE_7);
    1033           0 :         for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) {
    1034           0 :                 lsa->header->age = htons(OSPF_LSA_MAXAGE);
    1035           0 :                 SET_FLAG(lsa->flag, OSPF6_LSA_FLUSH);
    1036           0 :                 ospf6_flood(NULL, lsa);
    1037             : 
    1038             :                 /* Flush the translated LSA */
    1039           0 :                 if (ospf6_check_and_set_router_abr(ospf6)) {
    1040           0 :                         type5 = ospf6_lsdb_lookup(
    1041           0 :                                 htons(OSPF6_LSTYPE_AS_EXTERNAL),
    1042           0 :                                 lsa->external_lsa_id, ospf6->router_id,
    1043             :                                 ospf6->lsdb);
    1044           0 :                         if (type5
    1045           0 :                             && CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT)) {
    1046           0 :                                 type5->header->age = htons(OSPF_LSA_MAXAGE);
    1047           0 :                                 SET_FLAG(type5->flag, OSPF6_LSA_FLUSH);
    1048           0 :                                 ospf6_flood(NULL, type5);
    1049             :                         }
    1050             :                 }
    1051             :         }
    1052           0 : }
    1053             : 
    1054           0 : static void ospf6_check_and_originate_type7_lsa(struct ospf6_area *area)
    1055             : {
    1056           0 :         struct ospf6_route *route;
    1057           0 :         struct route_node *rn = NULL;
    1058           0 :         struct ospf6_external_aggr_rt *aggr;
    1059             : 
    1060             :         /* Loop through the external_table to find the LSAs originated
    1061             :          * without aggregation and originate type-7 LSAs for them.
    1062             :          */
    1063           0 :         for (route = ospf6_route_head(
    1064           0 :                      area->ospf6->external_table);
    1065           0 :              route; route = ospf6_route_next(route)) {
    1066           0 :                 struct ospf6_external_info *info = route->route_option;
    1067             : 
    1068             :                 /* This means the Type-5 LSA was originated for this route */
    1069           0 :                 if (route->path.origin.id != 0 && info->type != DEFAULT_ROUTE)
    1070           0 :                         ospf6_nssa_lsa_originate(route, area, true);
    1071             :         }
    1072             : 
    1073             :         /* Loop through the aggregation table to originate type-7 LSAs
    1074             :          * for the aggregated type-5 LSAs
    1075             :          */
    1076           0 :         for (rn = route_top(area->ospf6->rt_aggr_tbl); rn;
    1077           0 :              rn = route_next(rn)) {
    1078           0 :                 if (!rn->info)
    1079           0 :                         continue;
    1080             : 
    1081           0 :                 aggr = rn->info;
    1082             : 
    1083           0 :                 if (CHECK_FLAG(aggr->aggrflags,
    1084             :                     OSPF6_EXTERNAL_AGGRT_ORIGINATED)) {
    1085           0 :                         if (IS_OSPF6_DEBUG_NSSA)
    1086           0 :                                 zlog_debug(
    1087             :                                         "Originating Type-7 LSAs for area %s",
    1088             :                                         area->name);
    1089             : 
    1090           0 :                         ospf6_nssa_lsa_originate(aggr->route, area, true);
    1091             :                 }
    1092             :         }
    1093           0 : }
    1094             : 
    1095           0 : static void ospf6_ase_lsa_refresh(struct ospf6 *o)
    1096             : {
    1097           0 :         struct ospf6_lsa *old;
    1098             : 
    1099           0 :         for (struct ospf6_route *route = ospf6_route_head(o->external_table);
    1100           0 :              route; route = ospf6_route_next(route)) {
    1101           0 :                 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
    1102             :                                         route->path.origin.id, o->router_id,
    1103             :                                         o->lsdb);
    1104           0 :                 if (old) {
    1105           0 :                         THREAD_OFF(old->refresh);
    1106           0 :                         thread_add_event(master, ospf6_lsa_refresh, old, 0,
    1107             :                                          &old->refresh);
    1108             :                 } else {
    1109           0 :                         ospf6_as_external_lsa_originate(route, o);
    1110             :                 }
    1111             :         }
    1112           0 : }
    1113             : 
    1114           0 : void ospf6_area_nssa_update(struct ospf6_area *area)
    1115             : {
    1116           0 :         if (IS_AREA_NSSA(area)) {
    1117           0 :                 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
    1118           0 :                 area->ospf6->anyNSSA++;
    1119           0 :                 OSPF6_OPT_SET(area->options, OSPF6_OPT_N);
    1120           0 :                 area->NSSATranslatorRole = OSPF6_NSSA_ROLE_CANDIDATE;
    1121           0 :         } else if (IS_AREA_ENABLED(area)) {
    1122           0 :                 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
    1123           0 :                         zlog_debug("Normal area for if %s", area->name);
    1124           0 :                 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_N);
    1125           0 :                 OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
    1126           0 :                 area->ospf6->anyNSSA--;
    1127           0 :                 area->NSSATranslatorState = OSPF6_NSSA_TRANSLATE_DISABLED;
    1128             :         }
    1129             : 
    1130             :         /* Refresh router LSA */
    1131           0 :         if (IS_AREA_NSSA(area)) {
    1132           0 :                 OSPF6_ROUTER_LSA_SCHEDULE(area);
    1133             : 
    1134             :                 /* Flush external LSAs. */
    1135           0 :                 ospf6_asbr_remove_externals_from_area(area);
    1136             : 
    1137             :                 /* Check if router is ABR */
    1138           0 :                 if (ospf6_check_and_set_router_abr(area->ospf6)) {
    1139           0 :                         if (IS_OSPF6_DEBUG_NSSA)
    1140           0 :                                 zlog_debug("Router is ABR area %s", area->name);
    1141           0 :                         ospf6_schedule_abr_task(area->ospf6);
    1142             :                 } else {
    1143             :                         /* Router is not ABR */
    1144           0 :                         if (IS_OSPF6_DEBUG_NSSA)
    1145           0 :                                 zlog_debug("NSSA area %s", area->name);
    1146             : 
    1147             :                         /* Originate NSSA LSA */
    1148           0 :                         ospf6_check_and_originate_type7_lsa(area);
    1149             :                 }
    1150             :         } else {
    1151             :                 /* Disable NSSA */
    1152           0 :                 if (IS_OSPF6_DEBUG_NSSA)
    1153           0 :                         zlog_debug("Normal area %s", area->name);
    1154           0 :                 ospf6_nssa_flush_area(area);
    1155             : 
    1156             :                 /* Check if router is ABR */
    1157           0 :                 if (ospf6_check_and_set_router_abr(area->ospf6)) {
    1158           0 :                         if (IS_OSPF6_DEBUG_NSSA)
    1159           0 :                                 zlog_debug("Router is ABR area %s", area->name);
    1160           0 :                         ospf6_schedule_abr_task(area->ospf6);
    1161           0 :                         ospf6_ase_lsa_refresh(area->ospf6);
    1162             :                 } else {
    1163           0 :                         uint16_t type;
    1164           0 :                         struct ospf6_lsa *lsa = NULL;
    1165             : 
    1166             :                         /*
    1167             :                          * Refresh all type-5 LSAs so they get installed
    1168             :                          * in the converted ares
    1169             :                          */
    1170           0 :                         if (IS_OSPF6_DEBUG_NSSA)
    1171           0 :                                 zlog_debug("Refresh type-5 LSAs, area %s",
    1172             :                                            area->name);
    1173             : 
    1174           0 :                         type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
    1175           0 :                         for (ALL_LSDB_TYPED_ADVRTR(area->ospf6->lsdb, type,
    1176             :                                                    area->ospf6->router_id,
    1177             :                                                    lsa)) {
    1178           0 :                                 if (IS_OSPF6_DEBUG_NSSA)
    1179           0 :                                         ospf6_lsa_header_print(lsa);
    1180           0 :                                 THREAD_OFF(lsa->refresh);
    1181           0 :                                 thread_add_event(master, ospf6_lsa_refresh, lsa,
    1182             :                                                  0, &lsa->refresh);
    1183             :                         }
    1184             :                 }
    1185             :         }
    1186           0 : }
    1187             : 
    1188           0 : int ospf6_area_nssa_set(struct ospf6 *ospf6, struct ospf6_area *area)
    1189             : {
    1190             : 
    1191           0 :         if (!IS_AREA_NSSA(area)) {
    1192             :                 /* Disable stub first. */
    1193           0 :                 ospf6_area_stub_unset(ospf6, area);
    1194             : 
    1195           0 :                 SET_FLAG(area->flag, OSPF6_AREA_NSSA);
    1196           0 :                 if (IS_OSPF6_DEBUG_NSSA)
    1197           0 :                         zlog_debug("area %s nssa set", area->name);
    1198           0 :                 ospf6_area_nssa_update(area);
    1199             :         }
    1200             : 
    1201           0 :         return 1;
    1202             : }
    1203             : 
    1204           0 : int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area)
    1205             : {
    1206           0 :         if (IS_AREA_NSSA(area)) {
    1207           0 :                 UNSET_FLAG(area->flag, OSPF6_AREA_NSSA);
    1208           0 :                 if (IS_OSPF6_DEBUG_NSSA)
    1209           0 :                         zlog_debug("area %s nssa reset", area->name);
    1210             : 
    1211             :                 /* Clear the table of NSSA ranges. */
    1212           0 :                 ospf6_route_table_delete(area->nssa_range_table);
    1213           0 :                 area->nssa_range_table =
    1214           0 :                         OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
    1215           0 :                 area->nssa_range_table->scope = area;
    1216             : 
    1217           0 :                 ospf6_area_nssa_update(area);
    1218             :         }
    1219             : 
    1220           0 :         return 1;
    1221             : }
    1222             : 
    1223             : /* Find the NSSA forwarding address */
    1224           0 : static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa)
    1225             : {
    1226           0 :         struct listnode *node, *nnode;
    1227           0 :         struct ospf6_interface *oi;
    1228             : 
    1229           0 :         for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
    1230           0 :                 struct in6_addr *addr;
    1231             : 
    1232           0 :                 if (!if_is_operative(oi->interface))
    1233           0 :                         continue;
    1234             : 
    1235           0 :                 addr = ospf6_interface_get_global_address(oi->interface);
    1236           0 :                 if (addr)
    1237           0 :                         return addr;
    1238             :         }
    1239             :         return NULL;
    1240             : }
    1241             : 
    1242           0 : void ospf6_nssa_lsa_originate(struct ospf6_route *route,
    1243             :                               struct ospf6_area *area, bool p_bit)
    1244             : {
    1245           0 :         char buffer[OSPF6_MAX_LSASIZE];
    1246           0 :         struct ospf6_lsa_header *lsa_header;
    1247           0 :         struct ospf6_lsa *lsa;
    1248           0 :         struct ospf6_external_info *info = route->route_option;
    1249           0 :         struct in6_addr *fwd_addr;
    1250             : 
    1251           0 :         struct ospf6_as_external_lsa *as_external_lsa;
    1252           0 :         caddr_t p;
    1253             : 
    1254           0 :         if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL))
    1255           0 :                 zlog_debug("Originate NSSA-LSA for %pFX", &route->prefix);
    1256             : 
    1257             :         /* prepare buffer */
    1258           0 :         memset(buffer, 0, sizeof(buffer));
    1259           0 :         lsa_header = (struct ospf6_lsa_header *)buffer;
    1260           0 :         as_external_lsa = (struct ospf6_as_external_lsa
    1261             :                                    *)((caddr_t)lsa_header
    1262             :                                       + sizeof(struct ospf6_lsa_header));
    1263           0 :         p = (caddr_t)((caddr_t)as_external_lsa
    1264             :                       + sizeof(struct ospf6_as_external_lsa));
    1265             : 
    1266             :         /* Fill AS-External-LSA */
    1267             :         /* Metric type */
    1268           0 :         if (route->path.metric_type == 2)
    1269           0 :                 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
    1270             :         else
    1271             :                 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
    1272             : 
    1273             :         /* external route tag */
    1274           0 :         if (info && info->tag)
    1275           0 :                 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
    1276             :         else
    1277           0 :                 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
    1278             : 
    1279             :         /* Set metric */
    1280           0 :         OSPF6_ASBR_METRIC_SET(as_external_lsa, route->path.cost);
    1281             : 
    1282             :         /* prefixlen */
    1283           0 :         as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
    1284             : 
    1285             :         /* PrefixOptions */
    1286           0 :         as_external_lsa->prefix.prefix_options = route->prefix_options;
    1287             : 
    1288             :         /* Set the P bit */
    1289           0 :         if (p_bit)
    1290           0 :                 as_external_lsa->prefix.prefix_options |= OSPF6_PREFIX_OPTION_P;
    1291             : 
    1292             :         /* don't use refer LS-type */
    1293           0 :         as_external_lsa->prefix.prefix_refer_lstype = htons(0);
    1294             : 
    1295             :         /* set Prefix */
    1296           0 :         memcpy(p, &route->prefix.u.prefix6,
    1297           0 :                OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
    1298           0 :         ospf6_prefix_apply_mask(&as_external_lsa->prefix);
    1299           0 :         p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
    1300             : 
    1301             :         /* Forwarding address */
    1302           0 :         fwd_addr = ospf6_get_nssa_fwd_addr(area);
    1303           0 :         if (fwd_addr) {
    1304           0 :                 memcpy(p, fwd_addr, sizeof(struct in6_addr));
    1305           0 :                 p += sizeof(struct in6_addr);
    1306           0 :                 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
    1307             :         } else
    1308           0 :                 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
    1309             : 
    1310             :         /* External Route Tag */
    1311           0 :         if (info
    1312           0 :             && CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) {
    1313           0 :                 route_tag_t network_order = htonl(info->tag);
    1314             : 
    1315           0 :                 memcpy(p, &network_order, sizeof(network_order));
    1316           0 :                 p += sizeof(network_order);
    1317             :         }
    1318             : 
    1319             :         /* Fill LSA Header */
    1320           0 :         lsa_header->age = 0;
    1321           0 :         lsa_header->type = htons(OSPF6_LSTYPE_TYPE_7);
    1322           0 :         lsa_header->id = route->path.origin.id;
    1323           0 :         lsa_header->adv_router = area->ospf6->router_id;
    1324           0 :         lsa_header->seqnum =
    1325           0 :                 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
    1326             :                                     lsa_header->adv_router, area->lsdb);
    1327           0 :         lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
    1328             : 
    1329             :         /* LSA checksum */
    1330           0 :         ospf6_lsa_checksum(lsa_header);
    1331             :         /* create LSA */
    1332           0 :         lsa = ospf6_lsa_create(lsa_header);
    1333             : 
    1334             :         /* Originate */
    1335           0 :         ospf6_lsa_originate_area(lsa, area);
    1336           0 : }
    1337             : 
    1338           0 : void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
    1339             :                                     struct ospf6_lsa *lsa)
    1340             : {
    1341           0 :         struct ospf6_lsa *type5 = NULL;
    1342           0 :         struct ospf6 *ospf6 = area->ospf6;
    1343             : 
    1344           0 :         if (IS_OSPF6_DEBUG_NSSA)
    1345           0 :                 zlog_debug("%s : start", __func__);
    1346             : 
    1347           0 :         if (!ospf6_check_and_set_router_abr(ospf6))
    1348             :                 return;
    1349             : 
    1350           0 :         type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
    1351             :                                   lsa->external_lsa_id, ospf6->router_id,
    1352             :                                   ospf6->lsdb);
    1353           0 :         if (!type5) {
    1354           0 :                 if (IS_OSPF6_DEBUG_NSSA)
    1355           0 :                         zlog_debug("%s : Originating type5 LSA", __func__);
    1356           0 :                 ospf6_lsa_translated_nssa_new(area, lsa);
    1357             :         }
    1358             : }
    1359             : 
    1360           0 : DEFPY (area_nssa_range,
    1361             :        area_nssa_range_cmd,
    1362             :        "area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]",
    1363             :        "OSPF6 area parameters\n"
    1364             :        "OSPF6 area ID in IP address format\n"
    1365             :        "OSPF6 area ID as a decimal value\n"
    1366             :        "Configure OSPF6 area as nssa\n"
    1367             :        "Configured address range\n"
    1368             :        "Specify IPv6 prefix\n"
    1369             :        "Do not advertise\n"
    1370             :        "User specified metric for this range\n"
    1371             :        "Advertised metric for this range\n")
    1372             : {
    1373           0 :         struct ospf6_area *oa;
    1374           0 :         struct ospf6_route *range;
    1375             : 
    1376           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1377             : 
    1378           0 :         OSPF6_CMD_AREA_GET(area, oa, ospf6);
    1379             : 
    1380           0 :         if (!IS_AREA_NSSA(oa)) {
    1381           0 :                 vty_out(vty, "%% First configure %s as an NSSA area\n", area);
    1382           0 :                 return CMD_WARNING;
    1383             :         }
    1384             : 
    1385           0 :         range = ospf6_route_lookup((struct prefix *)prefix,
    1386             :                                    oa->nssa_range_table);
    1387           0 :         if (range == NULL) {
    1388           0 :                 range = ospf6_route_create(ospf6);
    1389           0 :                 range->type = OSPF6_DEST_TYPE_RANGE;
    1390           0 :                 SET_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE);
    1391           0 :                 prefix_copy(&range->prefix, prefix);
    1392           0 :                 range->path.area_id = oa->area_id;
    1393           0 :                 range->path.metric_type = 2;
    1394           0 :                 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
    1395           0 :                 range->path.origin.type = htons(OSPF6_LSTYPE_TYPE_7);
    1396           0 :                 range->path.origin.id = htonl(ospf6->external_id++);
    1397           0 :                 range->path.origin.adv_router = ospf6->router_id;
    1398           0 :                 ospf6_route_add(range, oa->nssa_range_table);
    1399             :         }
    1400             : 
    1401             :         /* process "not-advertise" */
    1402           0 :         if (not_adv)
    1403           0 :                 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
    1404             :         else
    1405           0 :                 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
    1406             : 
    1407             :         /* process "cost" */
    1408           0 :         if (!cost_str)
    1409           0 :                 cost = OSPF_AREA_RANGE_COST_UNSPEC;
    1410           0 :         range->path.u.cost_config = cost;
    1411             : 
    1412             :         /* Redo summaries if required */
    1413           0 :         if (ospf6_check_and_set_router_abr(ospf6))
    1414           0 :                 ospf6_schedule_abr_task(ospf6);
    1415             : 
    1416             :         return CMD_SUCCESS;
    1417             : }
    1418             : 
    1419           0 : DEFPY (no_area_nssa_range,
    1420             :        no_area_nssa_range_cmd,
    1421             :        "no area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise|cost (0-16777215)>]",
    1422             :        NO_STR
    1423             :        "OSPF6 area parameters\n"
    1424             :        "OSPF6 area ID in IP address format\n"
    1425             :        "OSPF6 area ID as a decimal value\n"
    1426             :        "Configure OSPF6 area as nssa\n"
    1427             :        "Configured address range\n"
    1428             :        "Specify IPv6 prefix\n"
    1429             :        "Do not advertise\n"
    1430             :        "User specified metric for this range\n"
    1431             :        "Advertised metric for this range\n")
    1432             : {
    1433           0 :         struct ospf6_area *oa;
    1434           0 :         struct ospf6_route *range;
    1435             : 
    1436           0 :         VTY_DECLVAR_CONTEXT(ospf6, ospf6);
    1437             : 
    1438           0 :         OSPF6_CMD_AREA_GET(area, oa, ospf6);
    1439             : 
    1440           0 :         range = ospf6_route_lookup((struct prefix *)prefix,
    1441             :                                    oa->nssa_range_table);
    1442           0 :         if (range == NULL) {
    1443           0 :                 vty_out(vty, "%% range %s does not exist.\n", prefix_str);
    1444           0 :                 return CMD_SUCCESS;
    1445             :         }
    1446             : 
    1447           0 :         if (ospf6_check_and_set_router_abr(oa->ospf6)) {
    1448             :                 /* Blow away the aggregated LSA and route */
    1449           0 :                 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
    1450             : 
    1451             :                 /* Redo summaries if required */
    1452           0 :                 thread_execute(master, ospf6_abr_task_timer, ospf6, 0);
    1453             :         }
    1454             : 
    1455           0 :         ospf6_route_remove(range, oa->nssa_range_table);
    1456             : 
    1457           0 :         return CMD_SUCCESS;
    1458             : }
    1459             : 
    1460           0 : DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd,
    1461             :       "debug ospf6 nssa",
    1462             :       DEBUG_STR
    1463             :       OSPF6_STR
    1464             :       "Debug OSPFv3 NSSA function\n")
    1465             : {
    1466           0 :         OSPF6_DEBUG_NSSA_ON();
    1467           0 :         return CMD_SUCCESS;
    1468             : }
    1469             : 
    1470           0 : DEFUN(no_debug_ospf6_nssa, no_debug_ospf6_nssa_cmd,
    1471             :       "no debug ospf6 nssa",
    1472             :       NO_STR
    1473             :       DEBUG_STR
    1474             :       OSPF6_STR
    1475             :       "Debug OSPFv3 NSSA function\n")
    1476             : {
    1477           0 :         OSPF6_DEBUG_NSSA_OFF();
    1478           0 :         return CMD_SUCCESS;
    1479             : }
    1480             : 
    1481           0 : void config_write_ospf6_debug_nssa(struct vty *vty)
    1482             : {
    1483           0 :         if (IS_OSPF6_DEBUG_NSSA)
    1484           0 :                 vty_out(vty, "debug ospf6 nssa\n");
    1485           0 : }
    1486             : 
    1487           8 : void install_element_ospf6_debug_nssa(void)
    1488             : {
    1489           8 :         install_element(OSPF6_NODE, &area_nssa_range_cmd);
    1490           8 :         install_element(OSPF6_NODE, &no_area_nssa_range_cmd);
    1491             : 
    1492           8 :         install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd);
    1493           8 :         install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd);
    1494           8 :         install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd);
    1495           8 :         install_element(CONFIG_NODE, &no_debug_ospf6_nssa_cmd);
    1496           8 : }

Generated by: LCOV version v1.16-topotato