back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_intra.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 1038 1371 75.7 %
Date: 2023-02-24 19:38:44 Functions: 24 33 72.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2003 Yasuhiro Ohara
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "log.h"
      24             : #include "linklist.h"
      25             : #include "thread.h"
      26             : #include "memory.h"
      27             : #include "if.h"
      28             : #include "prefix.h"
      29             : #include "table.h"
      30             : #include "vty.h"
      31             : #include "command.h"
      32             : #include "vrf.h"
      33             : 
      34             : #include "ospf6_proto.h"
      35             : #include "ospf6_message.h"
      36             : #include "ospf6_route.h"
      37             : #include "ospf6_lsa.h"
      38             : #include "ospf6_lsdb.h"
      39             : 
      40             : #include "ospf6_top.h"
      41             : #include "ospf6_area.h"
      42             : #include "ospf6_interface.h"
      43             : #include "ospf6_neighbor.h"
      44             : #include "ospf6_intra.h"
      45             : #include "ospf6_asbr.h"
      46             : #include "ospf6_abr.h"
      47             : #include "ospf6_flood.h"
      48             : #include "ospf6d.h"
      49             : #include "ospf6_spf.h"
      50             : #include "ospf6_gr.h"
      51             : #include "ospf6_vlink.h"
      52             : 
      53             : unsigned char conf_debug_ospf6_brouter = 0;
      54             : uint32_t conf_debug_ospf6_brouter_specific_router_id;
      55             : uint32_t conf_debug_ospf6_brouter_specific_area_id;
      56             : 
      57             : #define MAX_LSA_PAYLOAD   (1024 + 256)
      58             : /******************************/
      59             : /* RFC2740 3.4.3.1 Router-LSA */
      60             : /******************************/
      61             : 
      62         680 : static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
      63             :                                          int buflen, int pos)
      64             : {
      65         680 :         struct ospf6_router_lsa *router_lsa;
      66         680 :         struct ospf6_router_lsdesc *lsdesc;
      67         680 :         char *start, *end;
      68         680 :         char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
      69             : 
      70         680 :         if (lsa) {
      71         680 :                 router_lsa = (struct ospf6_router_lsa
      72         680 :                                       *)((char *)lsa->header
      73             :                                          + sizeof(struct ospf6_lsa_header));
      74         680 :                 start = (char *)router_lsa + sizeof(struct ospf6_router_lsa);
      75         680 :                 end = (char *)lsa->header + ntohs(lsa->header->length);
      76             : 
      77         680 :                 lsdesc = (struct ospf6_router_lsdesc
      78             :                                   *)(start
      79         680 :                                      + pos * (sizeof(struct
      80             :                                                      ospf6_router_lsdesc)));
      81         680 :                 if ((char *)lsdesc + sizeof(struct ospf6_router_lsdesc)
      82             :                     <= end) {
      83         281 :                         if (buf && (buflen > INET_ADDRSTRLEN * 2)) {
      84         281 :                                 inet_ntop(AF_INET,
      85         281 :                                           &lsdesc->neighbor_interface_id, buf1,
      86             :                                           sizeof(buf1));
      87         281 :                                 inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
      88             :                                           buf2, sizeof(buf2));
      89         281 :                                 snprintf(buf, buflen, "%s/%s", buf2, buf1);
      90             : 
      91         281 :                                 return buf;
      92             :                         }
      93             :                 }
      94             :         }
      95             : 
      96             :         return NULL;
      97             : }
      98             : 
      99         292 : static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
     100             :                                  json_object *json_obj, bool use_json)
     101             : {
     102         292 :         char *start, *end, *current;
     103         292 :         char buf[32], name[32], bits[16], options[32];
     104         292 :         struct ospf6_router_lsa *router_lsa;
     105         292 :         struct ospf6_router_lsdesc *lsdesc;
     106         292 :         json_object *json_arr;
     107         292 :         json_object *json_loop;
     108             : 
     109         292 :         router_lsa =
     110         292 :                 (struct ospf6_router_lsa *)((char *)lsa->header
     111             :                                             + sizeof(struct ospf6_lsa_header));
     112             : 
     113         292 :         ospf6_capability_printbuf(router_lsa->bits, bits, sizeof(bits));
     114         292 :         ospf6_options_printbuf(router_lsa->options, options, sizeof(options));
     115         292 :         if (use_json) {
     116         292 :                 json_object_string_add(json_obj, "bits", bits);
     117         292 :                 json_object_string_add(json_obj, "options", options);
     118         292 :                 json_arr = json_object_new_array();
     119             :         } else
     120           0 :                 vty_out(vty, "    Bits: %s Options: %s\n", bits, options);
     121             : 
     122         292 :         start = (char *)router_lsa + sizeof(struct ospf6_router_lsa);
     123         292 :         end = (char *)lsa->header + ntohs(lsa->header->length);
     124         292 :         for (current = start;
     125         786 :              current + sizeof(struct ospf6_router_lsdesc) <= end;
     126             :              current += sizeof(struct ospf6_router_lsdesc)) {
     127         494 :                 lsdesc = (struct ospf6_router_lsdesc *)current;
     128             : 
     129         494 :                 if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
     130         408 :                         snprintf(name, sizeof(name), "Point-To-Point");
     131          86 :                 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
     132          86 :                         snprintf(name, sizeof(name), "Transit-Network");
     133           0 :                 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
     134           0 :                         snprintf(name, sizeof(name), "Stub-Network");
     135           0 :                 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
     136           0 :                         snprintf(name, sizeof(name), "Virtual-Link");
     137             :                 else
     138           0 :                         snprintf(name, sizeof(name), "Unknown (%#x)",
     139             :                                  lsdesc->type);
     140             : 
     141         494 :                 if (use_json) {
     142         494 :                         json_loop = json_object_new_object();
     143         494 :                         json_object_string_add(json_loop, "type", name);
     144         494 :                         json_object_int_add(json_loop, "metric",
     145         494 :                                             ntohs(lsdesc->metric));
     146         494 :                         json_object_string_addf(
     147             :                                 json_loop, "interfaceId", "%pI4",
     148         494 :                                 (in_addr_t *)&lsdesc->interface_id);
     149         494 :                         json_object_string_addf(
     150             :                                 json_loop, "neighborInterfaceId", "%pI4",
     151         494 :                                 (in_addr_t *)&lsdesc->neighbor_interface_id);
     152         494 :                         json_object_string_addf(json_loop, "neighborRouterId",
     153             :                                                 "%pI4",
     154             :                                                 &lsdesc->neighbor_router_id);
     155         494 :                         json_object_array_add(json_arr, json_loop);
     156             :                 } else {
     157           0 :                         vty_out(vty, "    Type: %s Metric: %d\n", name,
     158           0 :                                 ntohs(lsdesc->metric));
     159           0 :                         vty_out(vty, "    Interface ID: %s\n",
     160           0 :                                 inet_ntop(AF_INET, &lsdesc->interface_id, buf,
     161             :                                           sizeof(buf)));
     162           0 :                         vty_out(vty, "    Neighbor Interface ID: %s\n",
     163             :                                 inet_ntop(AF_INET,
     164           0 :                                           &lsdesc->neighbor_interface_id, buf,
     165             :                                           sizeof(buf)));
     166           0 :                         vty_out(vty, "    Neighbor Router ID: %s\n",
     167           0 :                                 inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
     168             :                                           buf, sizeof(buf)));
     169             :                 }
     170             :         }
     171         292 :         if (use_json)
     172         292 :                 json_object_object_add(json_obj, "lsaDescription", json_arr);
     173             : 
     174         292 :         return 0;
     175             : }
     176             : 
     177         105 : static void ospf6_router_lsa_options_set(struct ospf6_area *oa,
     178             :                                          struct ospf6_router_lsa *router_lsa)
     179             : {
     180         105 :         OSPF6_OPT_CLEAR_ALL(router_lsa->options);
     181         105 :         memcpy(router_lsa->options, oa->options, 3);
     182             : 
     183         105 :         if (ospf6_check_and_set_router_abr(oa->ospf6))
     184          24 :                 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B);
     185             :         else
     186          81 :                 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B);
     187             : 
     188         105 :         if (!IS_AREA_STUB(oa) && ospf6_asbr_is_asbr(oa->ospf6)) {
     189          48 :                 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E);
     190             :         } else {
     191          57 :                 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E);
     192             :         }
     193             : 
     194             :         /* If the router is ASBR and the area-type is NSSA set the
     195             :          * translate bit in router LSA.
     196             :          */
     197         105 :         if (IS_AREA_NSSA(oa)
     198           0 :             && (ospf6_asbr_is_asbr(oa->ospf6) || IS_OSPF6_ABR(oa->ospf6))) {
     199           0 :                 if (oa->NSSATranslatorRole == OSPF6_NSSA_ROLE_ALWAYS)
     200           0 :                         SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_NT);
     201             :         } else {
     202         105 :                 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_NT);
     203             :         }
     204             : 
     205         105 :         if (oa->virtual_link_full)
     206           0 :                 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_V);
     207             :         else
     208         105 :                 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_V);
     209             : 
     210         105 :         UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_W);
     211         105 : }
     212             : 
     213         308 : int ospf6_router_is_stub_router(struct ospf6_lsa *lsa)
     214             : {
     215         308 :         struct ospf6_router_lsa *rtr_lsa;
     216             : 
     217         308 :         if (lsa != NULL && OSPF6_LSA_IS_TYPE(ROUTER, lsa)) {
     218         308 :                 rtr_lsa = (struct ospf6_router_lsa
     219             :                                    *)((caddr_t)lsa->header
     220             :                                       + sizeof(struct ospf6_lsa_header));
     221             : 
     222         308 :                 if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_R)) {
     223             :                         return OSPF6_IS_STUB_ROUTER;
     224         308 :                 } else if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_V6)) {
     225           0 :                         return OSPF6_IS_STUB_ROUTER_V6;
     226             :                 }
     227             :         }
     228             : 
     229             :         return OSPF6_NOT_STUB_ROUTER;
     230             : }
     231             : 
     232         105 : void ospf6_router_lsa_originate(struct thread *thread)
     233             : {
     234         105 :         struct ospf6_area *oa;
     235             : 
     236         105 :         char buffer[OSPF6_MAX_LSASIZE];
     237         105 :         struct ospf6_lsa_header *lsa_header;
     238         105 :         struct ospf6_lsa *lsa;
     239             : 
     240         105 :         uint32_t link_state_id = 0;
     241         105 :         struct listnode *node, *nnode;
     242         105 :         struct listnode *j;
     243         105 :         struct ospf6_interface *oi;
     244         105 :         struct ospf6_neighbor *on, *drouter = NULL;
     245         105 :         struct ospf6_router_lsa *router_lsa;
     246         105 :         struct ospf6_router_lsdesc *lsdesc;
     247         105 :         uint16_t type;
     248         105 :         uint32_t router;
     249         105 :         int count;
     250             : 
     251         105 :         oa = (struct ospf6_area *)THREAD_ARG(thread);
     252             : 
     253         105 :         if (oa->ospf6->gr_info.restart_in_progress) {
     254           0 :                 if (IS_DEBUG_OSPF6_GR)
     255           0 :                         zlog_debug(
     256             :                                 "Graceful Restart in progress, don't originate LSA");
     257           0 :                 return;
     258             :         }
     259             : 
     260         105 :         if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
     261           0 :                 zlog_debug("Originate Router-LSA for Area %s", oa->name);
     262             : 
     263         105 :         memset(buffer, 0, sizeof(buffer));
     264         105 :         lsa_header = (struct ospf6_lsa_header *)buffer;
     265         105 :         router_lsa =
     266             :                 (struct ospf6_router_lsa *)((caddr_t)lsa_header
     267             :                                             + sizeof(struct ospf6_lsa_header));
     268             : 
     269         105 :         ospf6_router_lsa_options_set(oa, router_lsa);
     270             : 
     271             :         /* describe links for each interfaces */
     272         105 :         lsdesc = (struct ospf6_router_lsdesc
     273             :                           *)((caddr_t)router_lsa
     274             :                              + sizeof(struct ospf6_router_lsa));
     275             : 
     276         388 :         for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
     277             :                 /* Interfaces in state Down or Loopback are not described */
     278         198 :                 if (oi->state == OSPF6_INTERFACE_DOWN
     279         178 :                     || oi->state == OSPF6_INTERFACE_LOOPBACK)
     280          20 :                         continue;
     281             : 
     282             :                 /* Nor are interfaces without any full adjacencies described */
     283         158 :                 count = 0;
     284         453 :                 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on))
     285         137 :                         if (on->state == OSPF6_NEIGHBOR_FULL)
     286          64 :                                 count++;
     287             : 
     288         158 :                 if (count == 0)
     289         107 :                         continue;
     290             : 
     291             :                 /* Multiple Router-LSA instance according to size limit setting
     292             :                  */
     293          51 :                 if ((oa->router_lsa_size_limit != 0)
     294          51 :                     && ((size_t)((char *)lsdesc - buffer)
     295          51 :                                 + sizeof(struct ospf6_router_lsdesc)
     296          51 :                         > oa->router_lsa_size_limit)) {
     297           0 :                         if ((caddr_t)lsdesc
     298             :                             == (caddr_t)router_lsa
     299             :                                        + sizeof(struct ospf6_router_lsa)) {
     300           0 :                                 zlog_warn(
     301             :                                         "Size limit setting for Router-LSA too short");
     302           0 :                                 return;
     303             :                         }
     304             : 
     305             :                         /* Fill LSA Header */
     306           0 :                         lsa_header->age = 0;
     307           0 :                         lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
     308           0 :                         lsa_header->id = htonl(link_state_id);
     309           0 :                         lsa_header->adv_router = oa->ospf6->router_id;
     310           0 :                         lsa_header->seqnum = ospf6_new_ls_seqnum(
     311             :                                 lsa_header->type, lsa_header->id,
     312             :                                 lsa_header->adv_router, oa->lsdb);
     313           0 :                         lsa_header->length =
     314           0 :                                 htons((caddr_t)lsdesc - (caddr_t)buffer);
     315             : 
     316             :                         /* LSA checksum */
     317           0 :                         ospf6_lsa_checksum(lsa_header);
     318             : 
     319             :                         /* create LSA */
     320           0 :                         lsa = ospf6_lsa_create(lsa_header);
     321             : 
     322             :                         /* Originate */
     323           0 :                         ospf6_lsa_originate_area(lsa, oa);
     324             : 
     325             :                         /* Reset Buffer to fill next Router LSA */
     326           0 :                         memset(buffer, 0, sizeof(buffer));
     327           0 :                         lsa_header = (struct ospf6_lsa_header *)buffer;
     328           0 :                         router_lsa =
     329             :                                 (struct ospf6_router_lsa
     330             :                                          *)((caddr_t)lsa_header
     331             :                                             + sizeof(struct ospf6_lsa_header));
     332             : 
     333           0 :                         ospf6_router_lsa_options_set(oa, router_lsa);
     334             : 
     335             :                         /* describe links for each interfaces */
     336           0 :                         lsdesc = (struct ospf6_router_lsdesc
     337             :                                           *)((caddr_t)router_lsa
     338             :                                              + sizeof(struct ospf6_router_lsa));
     339             : 
     340           0 :                         link_state_id++;
     341             :                 }
     342             : 
     343             :                 /* Point-to-Point interfaces */
     344          51 :                 if (oi->type == OSPF_IFTYPE_POINTOPOINT
     345          51 :                     || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
     346          43 :                     || oi->type == OSPF_IFTYPE_VIRTUALLINK) {
     347          31 :                         for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) {
     348          15 :                                 if (on->state != OSPF6_NEIGHBOR_FULL)
     349           3 :                                         continue;
     350             : 
     351          12 :                                 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
     352          12 :                                         lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
     353             :                                 else
     354           0 :                                         lsdesc->type = OSPF6_ROUTER_LSDESC_VIRTUAL_LINK;
     355          12 :                                 lsdesc->metric = htons(ospf6_neighbor_cost(on));
     356          24 :                                 lsdesc->interface_id =
     357          12 :                                         htonl(on->vlink ? on->vlink->v_ifindex
     358             :                                                 : oi->interface->ifindex);
     359          12 :                                 lsdesc->neighbor_interface_id =
     360          12 :                                         htonl(on->ifindex);
     361          12 :                                 lsdesc->neighbor_router_id = on->router_id;
     362             : 
     363          12 :                                 lsdesc++;
     364             :                         }
     365             :                 }
     366             : 
     367             :                 /* Broadcast and NBMA interfaces */
     368          43 :                 else if (oi->type == OSPF_IFTYPE_BROADCAST) {
     369             :                         /* If this router is not DR,
     370             :                            and If this router not fully adjacent with DR,
     371             :                            this interface is not transit yet: ignore. */
     372          43 :                         if (oi->state != OSPF6_INTERFACE_DR) {
     373          23 :                                 drouter =
     374          23 :                                         ospf6_neighbor_lookup(oi->drouter, oi);
     375          23 :                                 if (drouter == NULL
     376          21 :                                     || drouter->state != OSPF6_NEIGHBOR_FULL)
     377           6 :                                         continue;
     378             :                         }
     379             : 
     380          37 :                         lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
     381          37 :                         lsdesc->metric = htons(oi->cost);
     382          37 :                         lsdesc->interface_id = htonl(oi->interface->ifindex);
     383          37 :                         if (oi->state != OSPF6_INTERFACE_DR) {
     384          17 :                                 lsdesc->neighbor_interface_id =
     385          17 :                                         htonl(drouter->ifindex);
     386          17 :                                 lsdesc->neighbor_router_id = drouter->router_id;
     387             :                         } else {
     388          20 :                                 lsdesc->neighbor_interface_id =
     389          20 :                                         htonl(oi->interface->ifindex);
     390          20 :                                 lsdesc->neighbor_router_id =
     391          20 :                                         oi->area->ospf6->router_id;
     392             :                         }
     393             : 
     394          37 :                         lsdesc++;
     395             :                 } else {
     396           0 :                         assert(0); /* Unknown interface type */
     397             :                 }
     398             : 
     399             :                 /* Virtual links */
     400             :                 /* xxx */
     401             :                 /* Point-to-Multipoint interfaces */
     402             :                 /* xxx */
     403             :         }
     404             : 
     405             :         /* Fill LSA Header */
     406         105 :         lsa_header->age = 0;
     407         105 :         lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
     408         105 :         lsa_header->id = htonl(link_state_id);
     409         105 :         lsa_header->adv_router = oa->ospf6->router_id;
     410         210 :         lsa_header->seqnum =
     411         105 :                 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
     412             :                                     lsa_header->adv_router, oa->lsdb);
     413         105 :         lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer);
     414             : 
     415             :         /* LSA checksum */
     416         105 :         ospf6_lsa_checksum(lsa_header);
     417             : 
     418             :         /* create LSA */
     419         105 :         lsa = ospf6_lsa_create(lsa_header);
     420             : 
     421             :         /* Originate */
     422         105 :         ospf6_lsa_originate_area(lsa, oa);
     423             : 
     424         105 :         link_state_id++;
     425             : 
     426             :         /* Do premature-aging of rest, undesired Router-LSAs */
     427         105 :         type = ntohs(OSPF6_LSTYPE_ROUTER);
     428         105 :         router = oa->ospf6->router_id;
     429         105 :         count = 0;
     430         210 :         for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router, lsa)) {
     431         105 :                 if (ntohl(lsa->header->id) < link_state_id)
     432         105 :                         continue;
     433           0 :                 ospf6_lsa_purge(lsa);
     434           0 :                 count++;
     435             :         }
     436             : 
     437             :         /*
     438             :          * Waiting till the LSA is actually removed from the database to trigger
     439             :          * SPF delays network convergence. Unlike IPv4, for an ABR, when all
     440             :          * interfaces associated with an area are gone, triggering an SPF right
     441             :          * away
     442             :          * helps convergence with inter-area routes.
     443             :          */
     444         105 :         if (count && !link_state_id)
     445           0 :                 ospf6_spf_schedule(oa->ospf6,
     446             :                                    OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED);
     447             : }
     448             : 
     449             : /*******************************/
     450             : /* RFC2740 3.4.3.2 Network-LSA */
     451             : /*******************************/
     452             : 
     453         676 : static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa *lsa, char *buf,
     454             :                                          int buflen, int pos)
     455             : {
     456         676 :         char *start, *end, *current;
     457         676 :         struct ospf6_network_lsa *network_lsa;
     458         676 :         struct ospf6_network_lsdesc *lsdesc;
     459             : 
     460         676 :         if (lsa) {
     461         676 :                 network_lsa = (struct ospf6_network_lsa
     462         676 :                                        *)((caddr_t)lsa->header
     463             :                                           + sizeof(struct ospf6_lsa_header));
     464             : 
     465         676 :                 start = (char *)network_lsa + sizeof(struct ospf6_network_lsa);
     466         676 :                 end = (char *)lsa->header + ntohs(lsa->header->length);
     467         676 :                 current = start + pos * (sizeof(struct ospf6_network_lsdesc));
     468             : 
     469         676 :                 if ((current + sizeof(struct ospf6_network_lsdesc)) <= end) {
     470         461 :                         lsdesc = (struct ospf6_network_lsdesc *)current;
     471         461 :                         if (buf) {
     472         461 :                                 inet_ntop(AF_INET, &lsdesc->router_id, buf,
     473             :                                           buflen);
     474         461 :                                 return buf;
     475             :                         }
     476             :                 }
     477             :         }
     478             : 
     479             :         return NULL;
     480             : }
     481             : 
     482          73 : static int ospf6_network_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
     483             :                                   json_object *json_obj, bool use_json)
     484             : {
     485          73 :         char *start, *end, *current;
     486          73 :         struct ospf6_network_lsa *network_lsa;
     487          73 :         struct ospf6_network_lsdesc *lsdesc;
     488          73 :         char buf[128], options[32];
     489          73 :         json_object *json_arr;
     490             : 
     491          73 :         network_lsa =
     492          73 :                 (struct ospf6_network_lsa *)((caddr_t)lsa->header
     493             :                                              + sizeof(struct ospf6_lsa_header));
     494             : 
     495          73 :         ospf6_options_printbuf(network_lsa->options, options, sizeof(options));
     496          73 :         if (use_json)
     497          73 :                 json_object_string_add(json_obj, "options", options);
     498             :         else
     499           0 :                 vty_out(vty, "     Options: %s\n", options);
     500             : 
     501          73 :         start = (char *)network_lsa + sizeof(struct ospf6_network_lsa);
     502          73 :         end = (char *)lsa->header + ntohs(lsa->header->length);
     503          73 :         if (use_json)
     504          73 :                 json_arr = json_object_new_array();
     505             : 
     506          73 :         for (current = start;
     507         219 :              current + sizeof(struct ospf6_network_lsdesc) <= end;
     508             :              current += sizeof(struct ospf6_network_lsdesc)) {
     509         146 :                 lsdesc = (struct ospf6_network_lsdesc *)current;
     510         146 :                 inet_ntop(AF_INET, &lsdesc->router_id, buf, sizeof(buf));
     511         146 :                 if (use_json)
     512         146 :                         json_object_array_add(json_arr,
     513             :                                               json_object_new_string(buf));
     514             :                 else
     515           0 :                         vty_out(vty, "     Attached Router: %s\n", buf);
     516             :         }
     517          73 :         if (use_json)
     518          73 :                 json_object_object_add(json_obj, "attachedRouter", json_arr);
     519             : 
     520          73 :         return 0;
     521             : }
     522             : 
     523          56 : void ospf6_network_lsa_originate(struct thread *thread)
     524             : {
     525          56 :         struct ospf6_interface *oi;
     526             : 
     527          56 :         char buffer[OSPF6_MAX_LSASIZE];
     528          56 :         struct ospf6_lsa_header *lsa_header;
     529             : 
     530          56 :         int count;
     531          56 :         struct ospf6_lsa *old, *lsa;
     532          56 :         struct ospf6_network_lsa *network_lsa;
     533          56 :         struct ospf6_network_lsdesc *lsdesc;
     534          56 :         struct ospf6_neighbor *on;
     535          56 :         struct ospf6_link_lsa *link_lsa;
     536          56 :         struct listnode *i;
     537          56 :         uint16_t type;
     538             : 
     539          56 :         oi = (struct ospf6_interface *)THREAD_ARG(thread);
     540             : 
     541             :         /* The interface must be enabled until here. A Network-LSA of a
     542             :            disabled interface (but was once enabled) should be flushed
     543             :            by ospf6_lsa_refresh (), and does not come here. */
     544          56 :         assert(oi->area);
     545          56 :         assert(oi->type != OSPF_IFTYPE_VIRTUALLINK);
     546             : 
     547          56 :         if (oi->area->ospf6->gr_info.restart_in_progress) {
     548           0 :                 if (IS_DEBUG_OSPF6_GR)
     549           0 :                         zlog_debug(
     550             :                                 "Graceful Restart in progress, don't originate LSA");
     551          43 :                 return;
     552             :         }
     553             : 
     554         112 :         old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK),
     555          56 :                                 htonl(oi->interface->ifindex),
     556             :                                 oi->area->ospf6->router_id, oi->area->lsdb);
     557             : 
     558             :         /* Do not originate Network-LSA if not DR */
     559          56 :         if (oi->state != OSPF6_INTERFACE_DR) {
     560          29 :                 if (old) {
     561          11 :                         ospf6_lsa_purge(old);
     562             :                         /*
     563             :                          * Waiting till the LSA is actually removed from the
     564             :                          * database to
     565             :                          * trigger SPF delays network convergence.
     566             :                          */
     567          11 :                         ospf6_spf_schedule(
     568          11 :                                 oi->area->ospf6,
     569             :                                 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED);
     570             :                 }
     571          29 :                 return;
     572             :         }
     573             : 
     574          27 :         if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK))
     575           0 :                 zlog_debug("Originate Network-LSA for Interface %pOI", oi);
     576             : 
     577             :         /* If none of neighbor is adjacent to us */
     578          27 :         count = 0;
     579             : 
     580          83 :         for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on))
     581          29 :                 if (on->state == OSPF6_NEIGHBOR_FULL)
     582          15 :                         count++;
     583             : 
     584          27 :         if (count == 0) {
     585          14 :                 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK))
     586           0 :                         zlog_debug("Interface stub, ignore");
     587          14 :                 if (old)
     588           0 :                         ospf6_lsa_purge(old);
     589          14 :                 return;
     590             :         }
     591             : 
     592             :         /* prepare buffer */
     593          13 :         memset(buffer, 0, sizeof(buffer));
     594          13 :         lsa_header = (struct ospf6_lsa_header *)buffer;
     595          13 :         network_lsa =
     596             :                 (struct ospf6_network_lsa *)((caddr_t)lsa_header
     597             :                                              + sizeof(struct ospf6_lsa_header));
     598             : 
     599             :         /* Collect the interface's Link-LSAs to describe
     600             :            network's optional capabilities */
     601          13 :         type = htons(OSPF6_LSTYPE_LINK);
     602          42 :         for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
     603          29 :                 link_lsa = (struct ospf6_link_lsa
     604          29 :                                     *)((caddr_t)lsa->header
     605             :                                        + sizeof(struct ospf6_lsa_header));
     606          29 :                 network_lsa->options[0] |= link_lsa->options[0];
     607          29 :                 network_lsa->options[1] |= link_lsa->options[1];
     608          29 :                 network_lsa->options[2] |= link_lsa->options[2];
     609             :         }
     610             : 
     611          13 :         lsdesc = (struct ospf6_network_lsdesc
     612             :                           *)((caddr_t)network_lsa
     613             :                              + sizeof(struct ospf6_network_lsa));
     614             : 
     615             :         /* set Link Description to the router itself */
     616          13 :         lsdesc->router_id = oi->area->ospf6->router_id;
     617          13 :         lsdesc++;
     618             : 
     619             :         /* Walk through the neighbors */
     620          43 :         for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on)) {
     621          17 :                 if (on->state != OSPF6_NEIGHBOR_FULL)
     622           2 :                         continue;
     623             : 
     624             :                 /* set this neighbor's Router-ID to LSA */
     625          15 :                 lsdesc->router_id = on->router_id;
     626          15 :                 lsdesc++;
     627             :         }
     628             : 
     629             :         /* Fill LSA Header */
     630          13 :         lsa_header->age = 0;
     631          13 :         lsa_header->type = htons(OSPF6_LSTYPE_NETWORK);
     632          13 :         lsa_header->id = htonl(oi->interface->ifindex);
     633          13 :         lsa_header->adv_router = oi->area->ospf6->router_id;
     634          26 :         lsa_header->seqnum =
     635          13 :                 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
     636             :                                     lsa_header->adv_router, oi->area->lsdb);
     637          13 :         lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer);
     638             : 
     639             :         /* LSA checksum */
     640          13 :         ospf6_lsa_checksum(lsa_header);
     641             : 
     642             :         /* create LSA */
     643          13 :         lsa = ospf6_lsa_create(lsa_header);
     644             : 
     645             :         /* Originate */
     646          13 :         ospf6_lsa_originate_area(lsa, oi->area);
     647             : }
     648             : 
     649             : 
     650             : /****************************/
     651             : /* RFC2740 3.4.3.6 Link-LSA */
     652             : /****************************/
     653             : 
     654         708 : static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf,
     655             :                                            int buflen, int pos)
     656             : {
     657         708 :         char *start, *end, *current;
     658         708 :         struct ospf6_link_lsa *link_lsa;
     659         708 :         struct in6_addr in6;
     660         708 :         struct ospf6_prefix *prefix;
     661         708 :         int cnt = 0, prefixnum;
     662             : 
     663         708 :         if (lsa) {
     664         708 :                 link_lsa = (struct ospf6_link_lsa
     665         708 :                                     *)((caddr_t)lsa->header
     666             :                                        + sizeof(struct ospf6_lsa_header));
     667             : 
     668         708 :                 if (pos == 0) {
     669         354 :                         inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf,
     670             :                                   buflen);
     671         354 :                         return (buf);
     672             :                 }
     673             : 
     674         354 :                 prefixnum = ntohl(link_lsa->prefix_num);
     675         354 :                 if (pos > prefixnum)
     676             :                         return NULL;
     677             : 
     678           0 :                 start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
     679           0 :                 end = (char *)lsa->header + ntohs(lsa->header->length);
     680           0 :                 current = start;
     681             : 
     682           0 :                 while (current + sizeof(struct ospf6_prefix) <= end) {
     683           0 :                         prefix = (struct ospf6_prefix *)current;
     684           0 :                         if (prefix->prefix_length == 0
     685           0 :                             || current + OSPF6_PREFIX_SIZE(prefix) > end) {
     686             :                                 return NULL;
     687             :                         }
     688             : 
     689           0 :                         if (cnt < (pos - 1)) {
     690           0 :                                 current += OSPF6_PREFIX_SIZE(prefix);
     691           0 :                                 cnt++;
     692             :                         } else {
     693           0 :                                 memset(&in6, 0, sizeof(in6));
     694           0 :                                 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
     695           0 :                                        OSPF6_PREFIX_SPACE(
     696             :                                                prefix->prefix_length));
     697           0 :                                 inet_ntop(AF_INET6, &in6, buf, buflen);
     698           0 :                                 return (buf);
     699             :                         }
     700             :                 }
     701             :         }
     702             :         return NULL;
     703             : }
     704             : 
     705         222 : static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
     706             :                                json_object *json_obj, bool use_json)
     707             : {
     708         222 :         char *start, *end, *current;
     709         222 :         struct ospf6_link_lsa *link_lsa;
     710         222 :         int prefixnum;
     711         222 :         char buf[128], options[32];
     712         222 :         struct ospf6_prefix *prefix;
     713         222 :         struct in6_addr in6;
     714         222 :         json_object *json_loop;
     715         222 :         json_object *json_arr = NULL;
     716         222 :         char prefix_string[133];
     717             : 
     718         222 :         link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa->header
     719             :                                              + sizeof(struct ospf6_lsa_header));
     720             : 
     721         222 :         ospf6_options_printbuf(link_lsa->options, options, sizeof(options));
     722         222 :         inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf, sizeof(buf));
     723         222 :         prefixnum = ntohl(link_lsa->prefix_num);
     724             : 
     725         222 :         if (use_json) {
     726         222 :                 json_arr = json_object_new_array();
     727         222 :                 json_object_int_add(json_obj, "priority", link_lsa->priority);
     728         222 :                 json_object_string_add(json_obj, "options", options);
     729         222 :                 json_object_string_add(json_obj, "linkLocalAddress", buf);
     730         222 :                 json_object_int_add(json_obj, "numberOfPrefix", prefixnum);
     731             :         } else {
     732           0 :                 vty_out(vty, "     Priority: %d Options: %s\n",
     733           0 :                         link_lsa->priority, options);
     734           0 :                 vty_out(vty, "     LinkLocal Address: %s\n", buf);
     735           0 :                 vty_out(vty, "     Number of Prefix: %d\n", prefixnum);
     736             :         }
     737             : 
     738         222 :         start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
     739         222 :         end = (char *)lsa->header + ntohs(lsa->header->length);
     740         472 :         for (current = start; current < end;
     741         250 :              current += OSPF6_PREFIX_SIZE(prefix)) {
     742         250 :                 prefix = (struct ospf6_prefix *)current;
     743         250 :                 if (prefix->prefix_length == 0
     744         250 :                     || current + OSPF6_PREFIX_SIZE(prefix) > end)
     745             :                         break;
     746             : 
     747         250 :                 ospf6_prefix_options_printbuf(prefix->prefix_options, buf,
     748             :                                               sizeof(buf));
     749         250 :                 if (use_json) {
     750         250 :                         json_loop = json_object_new_object();
     751         250 :                         json_object_string_add(json_loop, "prefixOption", buf);
     752             :                 } else
     753           0 :                         vty_out(vty, "     Prefix Options: %s\n", buf);
     754             : 
     755         250 :                 memset(&in6, 0, sizeof(in6));
     756         250 :                 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
     757         250 :                        OSPF6_PREFIX_SPACE(prefix->prefix_length));
     758         250 :                 inet_ntop(AF_INET6, &in6, buf, sizeof(buf));
     759         250 :                 if (use_json) {
     760         250 :                         snprintf(prefix_string, sizeof(prefix_string), "%s/%d",
     761         250 :                                  buf, prefix->prefix_length);
     762         250 :                         json_object_string_add(json_loop, "prefix",
     763             :                                                prefix_string);
     764         250 :                         json_object_array_add(json_arr, json_loop);
     765             :                 } else
     766           0 :                         vty_out(vty, "     Prefix: %s/%d\n", buf,
     767           0 :                                 prefix->prefix_length);
     768             :         }
     769         222 :         if (use_json)
     770         222 :                 json_object_object_add(json_obj, "prefix", json_arr);
     771             : 
     772         222 :         return 0;
     773             : }
     774             : 
     775         120 : void ospf6_link_lsa_originate(struct thread *thread)
     776             : {
     777         120 :         struct ospf6_interface *oi;
     778             : 
     779         120 :         char buffer[OSPF6_MAX_LSASIZE];
     780         120 :         struct ospf6_lsa_header *lsa_header;
     781         120 :         struct ospf6_lsa *old, *lsa;
     782             : 
     783         120 :         struct ospf6_link_lsa *link_lsa;
     784         120 :         struct ospf6_route *route;
     785         120 :         struct ospf6_prefix *op;
     786             : 
     787         120 :         oi = (struct ospf6_interface *)THREAD_ARG(thread);
     788             : 
     789         120 :         assert(oi->area);
     790         120 :         assert(oi->type != OSPF_IFTYPE_VIRTUALLINK);
     791             : 
     792         120 :         if (oi->area->ospf6->gr_info.restart_in_progress) {
     793           0 :                 if (IS_DEBUG_OSPF6_GR)
     794           0 :                         zlog_debug(
     795             :                                 "Graceful Restart in progress, don't originate LSA");
     796          54 :                 return;
     797             :         }
     798             : 
     799             : 
     800             :         /* find previous LSA */
     801         240 :         old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK),
     802         120 :                                 htonl(oi->interface->ifindex),
     803             :                                 oi->area->ospf6->router_id, oi->lsdb);
     804             : 
     805         120 :         if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
     806           0 :                 if (old)
     807           0 :                         ospf6_lsa_purge(old);
     808           0 :                 return;
     809             :         }
     810             : 
     811         120 :         if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
     812           0 :                 zlog_debug("Originate Link-LSA for Interface %pOI", oi);
     813             : 
     814             :         /* can't make Link-LSA if linklocal address not set */
     815         120 :         if (oi->linklocal_addr == NULL) {
     816          54 :                 if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
     817           0 :                         zlog_debug(
     818             :                                 "No Linklocal address on %pOI, defer originating",
     819             :                                 oi);
     820          54 :                 if (old)
     821           1 :                         ospf6_lsa_purge(old);
     822          54 :                 return;
     823             :         }
     824             : 
     825             :         /* prepare buffer */
     826          66 :         memset(buffer, 0, sizeof(buffer));
     827          66 :         lsa_header = (struct ospf6_lsa_header *)buffer;
     828          66 :         link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa_header
     829             :                                              + sizeof(struct ospf6_lsa_header));
     830             : 
     831             :         /* Fill Link-LSA */
     832          66 :         link_lsa->priority = oi->priority;
     833          66 :         memcpy(link_lsa->options, oi->area->options, 3);
     834          66 :         memcpy(&link_lsa->linklocal_addr, oi->linklocal_addr,
     835             :                sizeof(struct in6_addr));
     836          66 :         link_lsa->prefix_num = htonl(oi->route_connected->count);
     837             : 
     838          66 :         op = (struct ospf6_prefix *)((caddr_t)link_lsa
     839             :                                      + sizeof(struct ospf6_link_lsa));
     840             : 
     841             :         /* connected prefix to advertise */
     842          98 :         for (route = ospf6_route_head(oi->route_connected); route;
     843          32 :              route = ospf6_route_next(route)) {
     844          32 :                 op->prefix_length = route->prefix.prefixlen;
     845          32 :                 op->prefix_options = route->prefix_options;
     846          32 :                 op->prefix_metric = htons(0);
     847          32 :                 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
     848          32 :                        OSPF6_PREFIX_SPACE(op->prefix_length));
     849          32 :                 op = OSPF6_PREFIX_NEXT(op);
     850             :         }
     851             : 
     852             :         /* Fill LSA Header */
     853          66 :         lsa_header->age = 0;
     854          66 :         lsa_header->type = htons(OSPF6_LSTYPE_LINK);
     855          66 :         lsa_header->id = htonl(oi->interface->ifindex);
     856          66 :         lsa_header->adv_router = oi->area->ospf6->router_id;
     857         132 :         lsa_header->seqnum =
     858          66 :                 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
     859             :                                     lsa_header->adv_router, oi->lsdb);
     860          66 :         lsa_header->length = htons((caddr_t)op - (caddr_t)buffer);
     861             : 
     862             :         /* LSA checksum */
     863          66 :         ospf6_lsa_checksum(lsa_header);
     864             : 
     865             :         /* create LSA */
     866          66 :         lsa = ospf6_lsa_create(lsa_header);
     867             : 
     868             :         /* Originate */
     869          66 :         ospf6_lsa_originate_interface(lsa, oi);
     870             : }
     871             : 
     872             : 
     873             : /*****************************************/
     874             : /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
     875             : /*****************************************/
     876         488 : static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
     877             :                                                    char *buf, int buflen,
     878             :                                                    int pos)
     879             : {
     880         488 :         char *start, *end, *current;
     881         488 :         struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
     882         488 :         struct in6_addr in6;
     883         488 :         int prefixnum, cnt = 0;
     884         488 :         struct ospf6_prefix *prefix;
     885         488 :         char tbuf[16];
     886             : 
     887         488 :         if (lsa) {
     888         488 :                 intra_prefix_lsa =
     889             :                         (struct ospf6_intra_prefix_lsa
     890         488 :                                  *)((caddr_t)lsa->header
     891             :                                     + sizeof(struct ospf6_lsa_header));
     892             : 
     893         488 :                 prefixnum = ntohs(intra_prefix_lsa->prefix_num);
     894         488 :                 if ((pos + 1) > prefixnum)
     895             :                         return NULL;
     896             : 
     897         244 :                 start = (char *)intra_prefix_lsa
     898             :                         + sizeof(struct ospf6_intra_prefix_lsa);
     899         244 :                 end = (char *)lsa->header + ntohs(lsa->header->length);
     900         244 :                 current = start;
     901             : 
     902         244 :                 while (current + sizeof(struct ospf6_prefix) <= end) {
     903         244 :                         prefix = (struct ospf6_prefix *)current;
     904         244 :                         if (prefix->prefix_length == 0
     905         244 :                             || current + OSPF6_PREFIX_SIZE(prefix) > end) {
     906             :                                 return NULL;
     907             :                         }
     908             : 
     909         244 :                         if (cnt < pos) {
     910           0 :                                 current += OSPF6_PREFIX_SIZE(prefix);
     911           0 :                                 cnt++;
     912             :                         } else {
     913         244 :                                 memset(&in6, 0, sizeof(in6));
     914         244 :                                 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
     915         244 :                                        OSPF6_PREFIX_SPACE(
     916             :                                                prefix->prefix_length));
     917         244 :                                 inet_ntop(AF_INET6, &in6, buf, buflen);
     918         244 :                                 snprintf(tbuf, sizeof(tbuf), "/%d",
     919         244 :                                          prefix->prefix_length);
     920         244 :                                 strlcat(buf, tbuf, buflen);
     921         244 :                                 return (buf);
     922             :                         }
     923             :                 }
     924             :         }
     925             :         return NULL;
     926             : }
     927             : 
     928         219 : static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
     929             :                                        json_object *json_obj, bool use_json)
     930             : {
     931         219 :         char *start, *end, *current;
     932         219 :         struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
     933         219 :         int prefixnum;
     934         219 :         char buf[128];
     935         219 :         struct ospf6_prefix *prefix;
     936         219 :         char id[16], adv_router[16];
     937         219 :         struct in6_addr in6;
     938         219 :         json_object *json_loop;
     939         219 :         json_object *json_arr = NULL;
     940         219 :         char prefix_string[133];
     941             : 
     942         219 :         intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
     943         219 :                                     *)((caddr_t)lsa->header
     944             :                                        + sizeof(struct ospf6_lsa_header));
     945             : 
     946         219 :         prefixnum = ntohs(intra_prefix_lsa->prefix_num);
     947             : 
     948         219 :         if (use_json) {
     949         219 :                 json_arr = json_object_new_array();
     950         219 :                 json_object_int_add(json_obj, "numberOfPrefix", prefixnum);
     951             :         } else
     952           0 :                 vty_out(vty, "     Number of Prefix: %d\n", prefixnum);
     953             : 
     954         219 :         inet_ntop(AF_INET, &intra_prefix_lsa->ref_id, id, sizeof(id));
     955         219 :         inet_ntop(AF_INET, &intra_prefix_lsa->ref_adv_router, adv_router,
     956             :                   sizeof(adv_router));
     957         219 :         if (use_json) {
     958         219 :                 json_object_string_add(
     959             :                         json_obj, "reference",
     960         219 :                         ospf6_lstype_name(intra_prefix_lsa->ref_type));
     961         219 :                 json_object_string_add(json_obj, "referenceId", id);
     962         219 :                 json_object_string_add(json_obj, "referenceAdv", adv_router);
     963             :         } else
     964           0 :                 vty_out(vty, "     Reference: %s Id: %s Adv: %s\n",
     965           0 :                         ospf6_lstype_name(intra_prefix_lsa->ref_type), id,
     966             :                         adv_router);
     967             : 
     968         219 :         start = (char *)intra_prefix_lsa
     969             :                 + sizeof(struct ospf6_intra_prefix_lsa);
     970         219 :         end = (char *)lsa->header + ntohs(lsa->header->length);
     971         450 :         for (current = start; current < end;
     972         231 :              current += OSPF6_PREFIX_SIZE(prefix)) {
     973         231 :                 prefix = (struct ospf6_prefix *)current;
     974         231 :                 if (prefix->prefix_length == 0
     975         231 :                     || current + OSPF6_PREFIX_SIZE(prefix) > end)
     976             :                         break;
     977             : 
     978         231 :                 ospf6_prefix_options_printbuf(prefix->prefix_options, buf,
     979             :                                               sizeof(buf));
     980         231 :                 if (use_json) {
     981         231 :                         json_loop = json_object_new_object();
     982         231 :                         json_object_string_add(json_loop, "prefixOption", buf);
     983             :                 } else
     984           0 :                         vty_out(vty, "     Prefix Options: %s\n", buf);
     985             : 
     986         231 :                 memset(&in6, 0, sizeof(in6));
     987         231 :                 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
     988         231 :                        OSPF6_PREFIX_SPACE(prefix->prefix_length));
     989         231 :                 inet_ntop(AF_INET6, &in6, buf, sizeof(buf));
     990         231 :                 if (use_json) {
     991         231 :                         snprintf(prefix_string, sizeof(prefix_string), "%s/%d",
     992         231 :                                  buf, prefix->prefix_length);
     993         231 :                         json_object_string_add(json_loop, "prefix",
     994             :                                                prefix_string);
     995         231 :                         json_object_int_add(json_loop, "metric",
     996         231 :                                             ntohs(prefix->prefix_metric));
     997         231 :                         json_object_array_add(json_arr, json_loop);
     998             :                 } else {
     999           0 :                         vty_out(vty, "     Prefix: %s/%d\n", buf,
    1000           0 :                                 prefix->prefix_length);
    1001           0 :                         vty_out(vty, "     Metric: %d\n",
    1002           0 :                                 ntohs(prefix->prefix_metric));
    1003             :                 }
    1004             :         }
    1005         219 :         if (use_json)
    1006         219 :                 json_object_object_add(json_obj, "prefix", json_arr);
    1007             : 
    1008         219 :         return 0;
    1009             : }
    1010             : 
    1011           0 : static struct ospf6_route *ospf6_intra_vlink_find_la(struct ospf6_area *oa)
    1012             : {
    1013           0 :         bool debug = IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX);
    1014           0 :         struct connected *c;
    1015           0 :         struct listnode *i, *j;
    1016           0 :         struct in6_addr result, nh_addr;
    1017           0 :         struct ospf6_interface *oi, *oi_best = NULL;
    1018           0 :         struct ospf6_route *route;
    1019             : 
    1020           0 :         memset(&result, 0xff, sizeof(result));
    1021             : 
    1022           0 :         for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) {
    1023           0 :                 for (ALL_LIST_ELEMENTS_RO(oi->interface->connected, j, c)) {
    1024           0 :                         if (!ospf6_interface_addr_valid(oi, c, debug))
    1025           0 :                                 continue;
    1026             : 
    1027           0 :                         if (IPV6_ADDR_CMP(&c->address->u.prefix6, &result) >= 0)
    1028           0 :                                 continue;
    1029             : 
    1030           0 :                         result = c->address->u.prefix6;
    1031           0 :                         oi_best = oi;
    1032             :                 }
    1033             :         }
    1034             : 
    1035           0 :         if (!oi_best) {
    1036           0 :                 zlog_warn(
    1037             :                         "area %pI4: %zu virtual links will not work, no viable global IPv6 address",
    1038             :                         &oa->area_id, ospf6_vlink_area_vlcount(oa));
    1039           0 :                 return NULL;
    1040             :         }
    1041             : 
    1042           0 :         if (debug)
    1043           0 :                 zlog_debug(
    1044             :                         "area %pI4: %zu virtual links; adding %pI6 as local address to Intra-Prefix LSA",
    1045             :                         &oa->area_id, ospf6_vlink_area_vlcount(oa), &result);
    1046             : 
    1047           0 :         route = ospf6_route_create(oa->ospf6);
    1048           0 :         route->prefix.family = AF_INET6;
    1049           0 :         route->prefix.prefixlen = 128;
    1050           0 :         route->prefix.u.prefix6 = result;
    1051           0 :         route->prefix_options = OSPF6_PREFIX_OPTION_LA;
    1052           0 :         route->type = OSPF6_DEST_TYPE_NETWORK;
    1053           0 :         route->path.area_id = oa->area_id;
    1054           0 :         route->path.type = OSPF6_PATH_TYPE_INTRA;
    1055           0 :         route->path.cost = 0;
    1056           0 :         inet_pton(AF_INET6, "::1", &nh_addr);
    1057           0 :         ospf6_route_add_nexthop(route, oi_best->interface->ifindex, &nh_addr);
    1058             : 
    1059           0 :         return route;
    1060             : }
    1061             : 
    1062         138 : void ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
    1063             : {
    1064         138 :         struct ospf6_area *oa;
    1065             : 
    1066         138 :         char buffer[OSPF6_MAX_LSASIZE];
    1067         138 :         struct ospf6_lsa_header *lsa_header;
    1068         138 :         struct ospf6_lsa *old, *lsa, *old_next = NULL;
    1069             : 
    1070         138 :         struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
    1071         138 :         struct ospf6_interface *oi;
    1072         138 :         struct ospf6_neighbor *on;
    1073         138 :         struct ospf6_route *route;
    1074         138 :         struct ospf6_prefix *op;
    1075         138 :         struct listnode *i, *j;
    1076         138 :         int full_count = 0;
    1077         138 :         unsigned short prefix_num = 0;
    1078         138 :         struct ospf6_route_table *route_advertise;
    1079         138 :         int ls_id = 0;
    1080         138 :         bool have_la = false;
    1081             : 
    1082         138 :         oa = (struct ospf6_area *)THREAD_ARG(thread);
    1083             : 
    1084         138 :         if (oa->ospf6->gr_info.restart_in_progress) {
    1085           0 :                 if (IS_DEBUG_OSPF6_GR)
    1086           0 :                         zlog_debug(
    1087             :                                 "Graceful Restart in progress, don't originate LSA");
    1088          90 :                 return;
    1089             :         }
    1090             : 
    1091             :         /* find previous LSA */
    1092         138 :         old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX), htonl(0),
    1093             :                                 oa->ospf6->router_id, oa->lsdb);
    1094             : 
    1095         138 :         if (!IS_AREA_ENABLED(oa)) {
    1096           0 :                 if (old) {
    1097           0 :                         ospf6_lsa_purge(old);
    1098             :                         /* find previous LSA */
    1099           0 :                         old_next = ospf6_lsdb_lookup(
    1100           0 :                                 htons(OSPF6_LSTYPE_INTRA_PREFIX),
    1101           0 :                                 htonl(++ls_id), oa->ospf6->router_id, oa->lsdb);
    1102             : 
    1103           0 :                         while (old_next) {
    1104           0 :                                 ospf6_lsa_purge(old_next);
    1105           0 :                                 old_next = ospf6_lsdb_lookup(
    1106           0 :                                         htons(OSPF6_LSTYPE_INTRA_PREFIX),
    1107           0 :                                         htonl(++ls_id), oa->ospf6->router_id,
    1108             :                                         oa->lsdb);
    1109             :                         }
    1110             :                 }
    1111           0 :                 return;
    1112             :         }
    1113             : 
    1114         138 :         if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1115           0 :                 zlog_debug(
    1116             :                         "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
    1117             :                         oa->name);
    1118             : 
    1119             :         /* prepare buffer */
    1120         138 :         memset(buffer, 0, sizeof(buffer));
    1121         138 :         lsa_header = (struct ospf6_lsa_header *)buffer;
    1122         138 :         intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
    1123             :                                     *)((caddr_t)lsa_header
    1124             :                                        + sizeof(struct ospf6_lsa_header));
    1125             : 
    1126             :         /* Fill Intra-Area-Prefix-LSA */
    1127         138 :         intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
    1128         138 :         intra_prefix_lsa->ref_id = htonl(0);
    1129         138 :         intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
    1130             : 
    1131         138 :         route_advertise = ospf6_route_table_create(0, 0);
    1132             : 
    1133         524 :         for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) {
    1134         248 :                 if (oi->state == OSPF6_INTERFACE_DOWN) {
    1135         109 :                         if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1136           0 :                                 zlog_debug("  Interface %pOI is down, ignore",
    1137             :                                            oi);
    1138         109 :                         continue;
    1139             :                 }
    1140             : 
    1141         139 :                 full_count = 0;
    1142             : 
    1143         387 :                 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on))
    1144         109 :                         if (on->state == OSPF6_NEIGHBOR_FULL)
    1145          67 :                                 full_count++;
    1146             : 
    1147         139 :                 if (oi->state != OSPF6_INTERFACE_LOOPBACK
    1148         139 :                     && oi->state != OSPF6_INTERFACE_POINTTOPOINT
    1149         139 :                     && oi->state != OSPF6_INTERFACE_POINTTOMULTIPOINT
    1150         126 :                     && full_count != 0) {
    1151          42 :                         if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1152           0 :                                 zlog_debug("  Interface %pOI is not stub, ignore",
    1153             :                                            oi);
    1154          42 :                         continue;
    1155             :                 }
    1156             : 
    1157          97 :                 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1158           0 :                         zlog_debug("  Interface %pOI:", oi);
    1159             : 
    1160             :                 /* connected prefix to advertise */
    1161         153 :                 for (route = ospf6_route_head(oi->route_connected); route;
    1162          56 :                      route = ospf6_route_best_next(route)) {
    1163          56 :                         const char *la_flag = "";
    1164             : 
    1165          56 :                         if (route->prefix_options & OSPF6_PREFIX_OPTION_LA) {
    1166          13 :                                 la_flag = " (LA)";
    1167          13 :                                 have_la = true;
    1168             :                         }
    1169          56 :                         if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1170           0 :                                 zlog_debug("    include %pFX%s",
    1171             :                                            &route->prefix, la_flag);
    1172          56 :                         ospf6_route_add(ospf6_route_copy(route),
    1173             :                                         route_advertise);
    1174             :                 }
    1175             :         }
    1176             : 
    1177         138 :         if (ospf6_vlink_area_vlcount(oa) && !have_la) {
    1178             :                 /* if we're here, we have no loopback or ptp interfaces in
    1179             :                  * the area (those always create LA=1 prefixes).  So we need
    1180             :                  * to grab a local addr somewhere else.  Unfortunately,
    1181             :                  * oi->route_connected contains masked prefixes, no addrs...
    1182             :                  */
    1183             : 
    1184           0 :                 route = ospf6_intra_vlink_find_la(oa);
    1185           0 :                 if (route)
    1186           0 :                         ospf6_route_add(route, route_advertise);
    1187             :         }
    1188             : 
    1189         138 :         if (route_advertise->count == 0) {
    1190          90 :                 if (old) {
    1191           8 :                         ls_id = 0;
    1192           8 :                         ospf6_lsa_purge(old);
    1193             :                         /* find previous LSA */
    1194           8 :                         old_next = ospf6_lsdb_lookup(
    1195           8 :                                 htons(OSPF6_LSTYPE_INTRA_PREFIX),
    1196           8 :                                 htonl(++ls_id), oa->ospf6->router_id, oa->lsdb);
    1197             : 
    1198           8 :                         while (old_next) {
    1199           0 :                                 ospf6_lsa_purge(old_next);
    1200           0 :                                 old_next = ospf6_lsdb_lookup(
    1201           0 :                                         htons(OSPF6_LSTYPE_INTRA_PREFIX),
    1202           0 :                                         htonl(++ls_id), oa->ospf6->router_id,
    1203             :                                         oa->lsdb);
    1204             :                         }
    1205             :                 }
    1206          90 :                 ospf6_route_table_delete(route_advertise);
    1207          90 :                 return;
    1208             :         }
    1209             : 
    1210             :         /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
    1211             :          * has not change, Flush old LSA and Re-Originate INP,
    1212             :          * as ospf6_flood() checks if LSA is same as DB,
    1213             :          * it won't be updated to neighbor's DB.
    1214             :          */
    1215          48 :         if (oa->intra_prefix_originate) {
    1216          15 :                 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1217           0 :                         zlog_debug(
    1218             :                                 "%s: Re-originate intra prefix LSA, Current full nbrs %u",
    1219             :                                 __func__, oa->full_nbrs);
    1220          15 :                 if (old)
    1221          15 :                         ospf6_lsa_purge_multi_ls_id(oa, old);
    1222          15 :                 oa->intra_prefix_originate = 0;
    1223             :         }
    1224             : 
    1225             :         /* put prefixes to advertise */
    1226          48 :         prefix_num = 0;
    1227          48 :         op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
    1228             :                                      + sizeof(struct ospf6_intra_prefix_lsa));
    1229         104 :         for (route = ospf6_route_head(route_advertise); route;
    1230          56 :              route = ospf6_route_best_next(route)) {
    1231          56 :                 if (((caddr_t)op - (caddr_t)lsa_header) > MAX_LSA_PAYLOAD) {
    1232             : 
    1233           0 :                         intra_prefix_lsa->prefix_num = htons(prefix_num);
    1234             : 
    1235             :                         /* Fill LSA Header */
    1236           0 :                         lsa_header->age = 0;
    1237           0 :                         lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
    1238           0 :                         lsa_header->id = htonl(ls_id++);
    1239           0 :                         lsa_header->adv_router = oa->ospf6->router_id;
    1240           0 :                         lsa_header->seqnum = ospf6_new_ls_seqnum(
    1241             :                                 lsa_header->type, lsa_header->id,
    1242             :                                 lsa_header->adv_router, oa->lsdb);
    1243           0 :                         lsa_header->length =
    1244           0 :                                 htons((caddr_t)op - (caddr_t)lsa_header);
    1245             : 
    1246             :                         /* LSA checksum */
    1247           0 :                         ospf6_lsa_checksum(lsa_header);
    1248             : 
    1249             :                         /* Create LSA */
    1250           0 :                         lsa = ospf6_lsa_create(lsa_header);
    1251             : 
    1252             :                         /* Originate */
    1253           0 :                         ospf6_lsa_originate_area(lsa, oa);
    1254             : 
    1255             :                         /* Prepare next buffer */
    1256           0 :                         memset(buffer, 0, sizeof(buffer));
    1257           0 :                         lsa_header = (struct ospf6_lsa_header *)buffer;
    1258           0 :                         intra_prefix_lsa =
    1259             :                                 (struct ospf6_intra_prefix_lsa
    1260             :                                          *)((caddr_t)lsa_header
    1261             :                                             + sizeof(struct ospf6_lsa_header));
    1262             : 
    1263             :                         /* Fill Intra-Area-Prefix-LSA */
    1264           0 :                         intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
    1265           0 :                         intra_prefix_lsa->ref_id = htonl(0);
    1266           0 :                         intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
    1267             : 
    1268             :                         /* Put next set of prefixes to advertise */
    1269           0 :                         prefix_num = 0;
    1270           0 :                         op = (struct ospf6_prefix
    1271             :                                       *)((caddr_t)intra_prefix_lsa
    1272             :                                          + sizeof(struct
    1273             :                                                   ospf6_intra_prefix_lsa));
    1274             :                 }
    1275             : 
    1276          56 :                 op->prefix_length = route->prefix.prefixlen;
    1277          56 :                 op->prefix_options = route->prefix_options;
    1278          56 :                 op->prefix_metric = htons(route->path.cost);
    1279          56 :                 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
    1280          56 :                        OSPF6_PREFIX_SPACE(op->prefix_length));
    1281          56 :                 prefix_num++;
    1282             : 
    1283          56 :                 op = OSPF6_PREFIX_NEXT(op);
    1284             :         }
    1285             : 
    1286          48 :         ospf6_route_table_delete(route_advertise);
    1287             : 
    1288          48 :         if (prefix_num == 0) {
    1289           0 :                 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1290           0 :                         zlog_debug(
    1291             :                                 "Quit to Advertise Intra-Prefix: no route to advertise");
    1292           0 :                 return;
    1293             :         }
    1294             : 
    1295          48 :         intra_prefix_lsa->prefix_num = htons(prefix_num);
    1296             : 
    1297             :         /* Fill LSA Header */
    1298          48 :         lsa_header->age = 0;
    1299          48 :         lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
    1300          48 :         lsa_header->id = htonl(ls_id++);
    1301          48 :         lsa_header->adv_router = oa->ospf6->router_id;
    1302          96 :         lsa_header->seqnum =
    1303          48 :                 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
    1304             :                                     lsa_header->adv_router, oa->lsdb);
    1305          48 :         lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header);
    1306             : 
    1307             :         /* LSA checksum */
    1308          48 :         ospf6_lsa_checksum(lsa_header);
    1309             : 
    1310             :         /* create LSA */
    1311          48 :         lsa = ospf6_lsa_create(lsa_header);
    1312             : 
    1313             :         /* Originate */
    1314          48 :         ospf6_lsa_originate_area(lsa, oa);
    1315             : }
    1316             : 
    1317             : 
    1318         187 : void ospf6_intra_prefix_lsa_originate_transit(struct thread *thread)
    1319             : {
    1320         187 :         struct ospf6_interface *oi;
    1321             : 
    1322         187 :         char buffer[OSPF6_MAX_LSASIZE];
    1323         187 :         struct ospf6_lsa_header *lsa_header;
    1324         187 :         struct ospf6_lsa *old, *lsa;
    1325             : 
    1326         187 :         struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
    1327         187 :         struct ospf6_neighbor *on;
    1328         187 :         struct ospf6_route *route;
    1329         187 :         struct ospf6_prefix *op;
    1330         187 :         struct listnode *i;
    1331         187 :         int full_count = 0;
    1332         187 :         unsigned short prefix_num = 0;
    1333         187 :         struct ospf6_route_table *route_advertise;
    1334         187 :         struct ospf6_link_lsa *link_lsa;
    1335         187 :         char *start, *end, *current;
    1336         187 :         uint16_t type;
    1337             : 
    1338         187 :         oi = (struct ospf6_interface *)THREAD_ARG(thread);
    1339             : 
    1340         187 :         assert(oi->area);
    1341         187 :         assert(oi->type != OSPF_IFTYPE_VIRTUALLINK);
    1342             : 
    1343         187 :         if (oi->area->ospf6->gr_info.restart_in_progress) {
    1344           0 :                 if (IS_DEBUG_OSPF6_GR)
    1345           0 :                         zlog_debug(
    1346             :                                 "Graceful Restart in progress, don't originate LSA");
    1347         177 :                 return;
    1348             :         }
    1349             : 
    1350             :         /* find previous LSA */
    1351         374 :         old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX),
    1352         187 :                                 htonl(oi->interface->ifindex),
    1353             :                                 oi->area->ospf6->router_id, oi->area->lsdb);
    1354             : 
    1355         187 :         if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
    1356          56 :                 if (old)
    1357           4 :                         ospf6_lsa_purge(old);
    1358          56 :                 return;
    1359             :         }
    1360             : 
    1361         131 :         if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1362           0 :                 zlog_debug(
    1363             :                         "Originate Intra-Area-Prefix-LSA for interface %pOI's prefix",
    1364             :                         oi);
    1365             : 
    1366             :         /* prepare buffer */
    1367         131 :         memset(buffer, 0, sizeof(buffer));
    1368         131 :         lsa_header = (struct ospf6_lsa_header *)buffer;
    1369         131 :         intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
    1370             :                                     *)((caddr_t)lsa_header
    1371             :                                        + sizeof(struct ospf6_lsa_header));
    1372             : 
    1373             :         /* Fill Intra-Area-Prefix-LSA */
    1374         131 :         intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_NETWORK);
    1375         131 :         intra_prefix_lsa->ref_id = htonl(oi->interface->ifindex);
    1376         131 :         intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
    1377             : 
    1378         131 :         if (oi->state != OSPF6_INTERFACE_DR) {
    1379          88 :                 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1380           0 :                         zlog_debug("  Interface is not DR");
    1381          88 :                 if (old)
    1382           4 :                         ospf6_lsa_purge(old);
    1383          88 :                 return;
    1384             :         }
    1385             : 
    1386          43 :         full_count = 0;
    1387         137 :         for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on))
    1388          51 :                 if (on->state == OSPF6_NEIGHBOR_FULL)
    1389          23 :                         full_count++;
    1390             : 
    1391          43 :         if (full_count == 0) {
    1392          24 :                 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1393           0 :                         zlog_debug("  Interface is stub");
    1394          24 :                 if (old)
    1395           0 :                         ospf6_lsa_purge(old);
    1396          24 :                 return;
    1397             :         }
    1398             : 
    1399             :         /* connected prefix to advertise */
    1400          19 :         route_advertise = ospf6_route_table_create(0, 0);
    1401             : 
    1402          19 :         type = ntohs(OSPF6_LSTYPE_LINK);
    1403          65 :         for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
    1404          46 :                 if (OSPF6_LSA_IS_MAXAGE(lsa))
    1405           5 :                         continue;
    1406             : 
    1407          41 :                 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1408           0 :                         zlog_debug("  include prefix from %s", lsa->name);
    1409             : 
    1410          41 :                 if (lsa->header->adv_router != oi->area->ospf6->router_id) {
    1411          22 :                         on = ospf6_neighbor_lookup(lsa->header->adv_router, oi);
    1412          22 :                         if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL) {
    1413           4 :                                 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1414           0 :                                         zlog_debug(
    1415             :                                                 "    Neighbor not found or not Full, ignore");
    1416           4 :                                 continue;
    1417             :                         }
    1418             :                 }
    1419             : 
    1420          37 :                 link_lsa = (struct ospf6_link_lsa
    1421          37 :                                     *)((caddr_t)lsa->header
    1422             :                                        + sizeof(struct ospf6_lsa_header));
    1423             : 
    1424          37 :                 prefix_num = (unsigned short)ntohl(link_lsa->prefix_num);
    1425          37 :                 start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
    1426          37 :                 end = (char *)lsa->header + ntohs(lsa->header->length);
    1427          57 :                 for (current = start; current < end && prefix_num;
    1428          20 :                      current += OSPF6_PREFIX_SIZE(op)) {
    1429          20 :                         op = (struct ospf6_prefix *)current;
    1430          20 :                         if (op->prefix_length == 0
    1431          20 :                             || current + OSPF6_PREFIX_SIZE(op) > end)
    1432             :                                 break;
    1433             : 
    1434          20 :                         route = ospf6_route_create(oi->area->ospf6);
    1435             : 
    1436          20 :                         route->type = OSPF6_DEST_TYPE_NETWORK;
    1437          20 :                         route->prefix.family = AF_INET6;
    1438          20 :                         route->prefix.prefixlen = op->prefix_length;
    1439          20 :                         memset(&route->prefix.u.prefix6, 0,
    1440             :                                sizeof(struct in6_addr));
    1441          20 :                         memcpy(&route->prefix.u.prefix6, OSPF6_PREFIX_BODY(op),
    1442          20 :                                OSPF6_PREFIX_SPACE(op->prefix_length));
    1443          20 :                         route->prefix_options = op->prefix_options;
    1444             : 
    1445          20 :                         route->path.origin.type = lsa->header->type;
    1446          20 :                         route->path.origin.id = lsa->header->id;
    1447          20 :                         route->path.origin.adv_router = lsa->header->adv_router;
    1448          20 :                         route->path.options[0] = link_lsa->options[0];
    1449          20 :                         route->path.options[1] = link_lsa->options[1];
    1450          20 :                         route->path.options[2] = link_lsa->options[2];
    1451          20 :                         route->path.area_id = oi->area->area_id;
    1452          20 :                         route->path.type = OSPF6_PATH_TYPE_INTRA;
    1453             : 
    1454          20 :                         if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1455           0 :                                 zlog_debug("    include %pFX", &route->prefix);
    1456             : 
    1457          20 :                         ospf6_route_add(route, route_advertise);
    1458          20 :                         prefix_num--;
    1459             :                 }
    1460          37 :                 if (current != end && IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1461          46 :                         zlog_debug("Trailing garbage in %s", lsa->name);
    1462             :         }
    1463             : 
    1464          19 :         op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
    1465             :                                      + sizeof(struct ospf6_intra_prefix_lsa));
    1466             : 
    1467          19 :         prefix_num = 0;
    1468          29 :         for (route = ospf6_route_head(route_advertise); route;
    1469          10 :              route = ospf6_route_best_next(route)) {
    1470          10 :                 op->prefix_length = route->prefix.prefixlen;
    1471          10 :                 op->prefix_options = route->prefix_options;
    1472          10 :                 op->prefix_metric = htons(0);
    1473          10 :                 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
    1474          10 :                        OSPF6_PREFIX_SPACE(op->prefix_length));
    1475          10 :                 op = OSPF6_PREFIX_NEXT(op);
    1476          10 :                 prefix_num++;
    1477             :         }
    1478             : 
    1479          19 :         ospf6_route_table_delete(route_advertise);
    1480             : 
    1481          19 :         if (prefix_num == 0) {
    1482           9 :                 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
    1483           0 :                         zlog_debug(
    1484             :                                 "Quit to Advertise Intra-Prefix: no route to advertise");
    1485           9 :                 return;
    1486             :         }
    1487             : 
    1488          10 :         intra_prefix_lsa->prefix_num = htons(prefix_num);
    1489             : 
    1490             :         /* Fill LSA Header */
    1491          10 :         lsa_header->age = 0;
    1492          10 :         lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
    1493          10 :         lsa_header->id = htonl(oi->interface->ifindex);
    1494          10 :         lsa_header->adv_router = oi->area->ospf6->router_id;
    1495          20 :         lsa_header->seqnum =
    1496          10 :                 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
    1497             :                                     lsa_header->adv_router, oi->area->lsdb);
    1498          10 :         lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header);
    1499             : 
    1500             :         /* LSA checksum */
    1501          10 :         ospf6_lsa_checksum(lsa_header);
    1502             : 
    1503             :         /* create LSA */
    1504          10 :         lsa = ospf6_lsa_create(lsa_header);
    1505             : 
    1506             :         /* Originate */
    1507          10 :         ospf6_lsa_originate_area(lsa, oi->area);
    1508             : }
    1509             : 
    1510           3 : static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route,
    1511             :                                                    struct ospf6 *ospf6)
    1512             : {
    1513           3 :         struct ospf6_path *h_path;
    1514           3 :         struct ospf6_route *g_route, *nroute;
    1515             : 
    1516             :         /* Update Global ospf6 route path */
    1517           3 :         g_route = ospf6_route_lookup(&oa_route->prefix, ospf6->route_table);
    1518             : 
    1519           3 :         assert(g_route);
    1520             : 
    1521           6 :         for (ospf6_route_lock(g_route); g_route &&
    1522           3 :              ospf6_route_is_prefix(&oa_route->prefix, g_route);
    1523             :              g_route = nroute) {
    1524           3 :                 nroute = ospf6_route_next(g_route);
    1525           3 :                 if (g_route->type != oa_route->type)
    1526           0 :                         continue;
    1527           3 :                 if (g_route->path.area_id != oa_route->path.area_id)
    1528           0 :                         continue;
    1529           3 :                 if (g_route->path.type != OSPF6_PATH_TYPE_INTRA)
    1530           0 :                         continue;
    1531           3 :                 if (g_route->path.cost != oa_route->path.cost)
    1532           0 :                         continue;
    1533             : 
    1534           3 :                 if (ospf6_route_is_same_origin(g_route, oa_route)) {
    1535           3 :                         h_path = (struct ospf6_path *)listgetdata(
    1536             :                                 listhead(g_route->paths));
    1537           3 :                         g_route->path.origin.type = h_path->origin.type;
    1538           3 :                         g_route->path.origin.id = h_path->origin.id;
    1539           3 :                         g_route->path.origin.adv_router =
    1540           3 :                                 h_path->origin.adv_router;
    1541           3 :                         if (nroute)
    1542           2 :                                 ospf6_route_unlock(nroute);
    1543             :                         break;
    1544             :                 }
    1545             :         }
    1546             : 
    1547           3 :         h_path = (struct ospf6_path *)listgetdata(
    1548             :                                 listhead(oa_route->paths));
    1549           3 :         oa_route->path.origin.type = h_path->origin.type;
    1550           3 :         oa_route->path.origin.id = h_path->origin.id;
    1551           3 :         oa_route->path.origin.adv_router = h_path->origin.adv_router;
    1552           3 : }
    1553             : 
    1554         170 : void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
    1555             :                                         struct ospf6_route *old,
    1556             :                                         struct ospf6_route *route)
    1557             : {
    1558         170 :         struct ospf6_route *old_route, *ls_entry;
    1559         170 :         struct ospf6_path *ecmp_path, *o_path = NULL;
    1560         170 :         struct listnode *anode, *anext;
    1561         170 :         struct listnode *nnode, *rnode, *rnext;
    1562         170 :         struct ospf6_nexthop *nh, *rnh;
    1563         170 :         bool route_found = false;
    1564         170 :         struct interface *ifp = NULL;
    1565         170 :         struct ospf6_lsa *lsa;
    1566         170 :         struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
    1567             : 
    1568             :         /* check for old entry match with new route origin,
    1569             :          * delete old entry.
    1570             :          */
    1571         343 :         for (old_route = old; old_route; old_route = old_route->next) {
    1572         250 :                 bool route_updated = false;
    1573             : 
    1574             :                 /* The route linked-list is grouped in batches of prefix.
    1575             :                  * If the new prefix is not the same as the one of interest
    1576             :                  * then we have walked over the end of the batch and so we
    1577             :                  * should break rather than continuing unnecessarily.
    1578             :                  */
    1579         250 :                 if (!ospf6_route_is_same(old_route, route))
    1580             :                         break;
    1581         174 :                 if (old_route->path.type != route->path.type)
    1582           0 :                         continue;
    1583             : 
    1584             :                 /* Current and New route has same origin,
    1585             :                  * delete old entry.
    1586             :                  */
    1587         545 :                 for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext,
    1588             :                                                   o_path)) {
    1589             :                         /* Check old route path and route has same
    1590             :                          * origin.
    1591             :                          */
    1592         198 :                         if (o_path->area_id != route->path.area_id
    1593         198 :                             || !ospf6_ls_origin_same(o_path, &route->path))
    1594          37 :                                 continue;
    1595             : 
    1596             :                         /* Cost is not same then delete current path */
    1597         161 :                         if (o_path->cost == route->path.cost)
    1598         160 :                                 continue;
    1599             : 
    1600           1 :                         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    1601           0 :                                 zlog_debug(
    1602             :                                         "%s: route %pFX cost old %u new %u is not same, replace route",
    1603             :                                         __func__, &old_route->prefix, o_path->cost,
    1604             :                                         route->path.cost);
    1605             :                         }
    1606             : 
    1607             :                         /* Remove selected current path's nh from
    1608             :                          * effective nh list.
    1609             :                          */
    1610           3 :                         for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
    1611           3 :                                 for (ALL_LIST_ELEMENTS(old_route->nh_list,
    1612             :                                                         rnode, rnext, rnh)) {
    1613           1 :                                         if (!ospf6_nexthop_is_same(rnh, nh))
    1614           0 :                                                 continue;
    1615           1 :                                         listnode_delete(old_route->nh_list,
    1616             :                                                                 rnh);
    1617           1 :                                         ospf6_nexthop_delete(rnh);
    1618           1 :                                         route_updated = true;
    1619             :                                 }
    1620             :                         }
    1621             : 
    1622           1 :                         listnode_delete(old_route->paths, o_path);
    1623           1 :                         ospf6_path_free(o_path);
    1624             : 
    1625             :                         /* Current route's path (adv_router info) is similar
    1626             :                          * to route being added.
    1627             :                          * Replace current route's path with paths list head.
    1628             :                          * Update FIB with effective NHs.
    1629             :                          */
    1630           1 :                         if (listcount(old_route->paths)) {
    1631           0 :                                 if (route_updated) {
    1632           0 :                                         for (ALL_LIST_ELEMENTS(old_route->paths,
    1633             :                                                         anode, anext, o_path)) {
    1634           0 :                                                 ospf6_merge_nexthops(
    1635             :                                                         old_route->nh_list,
    1636             :                                                         o_path->nh_list);
    1637             :                                         }
    1638             :                                         /* Update ospf6 route table and
    1639             :                                          * RIB/FIB with effective
    1640             :                                          * nh_list
    1641             :                                          */
    1642           0 :                                         if (oa->route_table->hook_add)
    1643           0 :                                                 (*oa->route_table->hook_add)(
    1644             :                                                         old_route);
    1645             : 
    1646           0 :                                         if (old_route->path.origin.id ==
    1647           0 :                                         route->path.origin.id &&
    1648           0 :                                         old_route->path.origin.adv_router ==
    1649           0 :                                                 route->path.origin.adv_router) {
    1650           0 :                                                 ospf6_intra_prefix_update_route_origin(
    1651             :                                                         old_route, oa->ospf6);
    1652             :                                         }
    1653             :                                         break;
    1654             :                                 }
    1655             :                         } else {
    1656           1 :                                 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    1657           0 :                                         zlog_debug(
    1658             :                                                 "%s: route %pFX old cost %u new cost %u, delete old entry.",
    1659             :                                                 __func__, &old_route->prefix,
    1660             :                                                 old_route->path.cost,
    1661             :                                                 route->path.cost);
    1662             :                                 }
    1663           1 :                                 if (oa->route_table->hook_remove)
    1664           0 :                                         ospf6_route_remove(old_route,
    1665             :                                                            oa->route_table);
    1666             :                                 else
    1667           1 :                                         SET_FLAG(old_route->flag,
    1668             :                                                  OSPF6_ROUTE_REMOVE);
    1669             :                                 break;
    1670             :                         }
    1671             :                 }
    1672         174 :                 if (route_updated)
    1673             :                         break;
    1674             :         }
    1675             : 
    1676         176 :         for (old_route = old; old_route; old_route = old_route->next) {
    1677             : 
    1678             :                 /* The route linked-list is grouped in batches of prefix.
    1679             :                  * If the new prefix is not the same as the one of interest
    1680             :                  * then we have walked over the end of the batch and so we
    1681             :                  * should break rather than continuing unnecessarily.
    1682             :                  */
    1683         175 :                 if (!ospf6_route_is_same(old_route, route))
    1684             :                         break;
    1685         172 :                 if (old_route->path.type != route->path.type)
    1686           0 :                         continue;
    1687             : 
    1688             :                 /* Old Route and New Route have Equal Cost, Merge NHs */
    1689         172 :                 if (old_route->path.cost == route->path.cost) {
    1690         166 :                         route_found = true;
    1691             : 
    1692             :                         /* check if this path exists already in
    1693             :                          * route->paths list, if so, replace nh_list.
    1694             :                          */
    1695         358 :                         for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
    1696             :                                                   o_path)) {
    1697         186 :                                 if (o_path->area_id == route->path.area_id
    1698         186 :                                     && ospf6_ls_origin_same(o_path, &route->path))
    1699             :                                         break;
    1700             :                         }
    1701             :                         /* If path is not found in old_route paths's list,
    1702             :                          * add a new path to route paths list and merge
    1703             :                          * nexthops in route->path->nh_list.
    1704             :                          * Otherwise replace existing path's nh_list.
    1705             :                          */
    1706         166 :                         if (o_path == NULL) {
    1707           6 :                                 ecmp_path = ospf6_path_dup(&route->path);
    1708             : 
    1709             :                                 /* Add a nh_list to new ecmp path */
    1710           6 :                                 ospf6_copy_nexthops(ecmp_path->nh_list,
    1711             :                                                     route->nh_list);
    1712             :                                 /* Add the new path to route's path list */
    1713           6 :                                 listnode_add_sort(old_route->paths, ecmp_path);
    1714             : 
    1715           6 :                                 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    1716           0 :                                         zlog_debug(
    1717             :                                                 "%s: route %pFX %p another path added with nh %u, effective paths %u nh %u",
    1718             :                                                 __func__, &route->prefix,
    1719             :                                                 (void *)old_route,
    1720             :                                                 listcount(ecmp_path->nh_list),
    1721             :                                                 old_route->paths ? listcount(
    1722             :                                                         old_route->paths)
    1723             :                                                                  : 0,
    1724             :                                                 listcount(old_route->nh_list));
    1725             :                                 }
    1726             :                         } else {
    1727         160 :                                 list_delete_all_node(o_path->nh_list);
    1728         160 :                                 ospf6_copy_nexthops(o_path->nh_list,
    1729             :                                             route->nh_list);
    1730             : 
    1731             :                         }
    1732             : 
    1733         166 :                         list_delete_all_node(old_route->nh_list);
    1734             : 
    1735         528 :                         for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
    1736             :                                                   o_path)) {
    1737         196 :                                 ls_entry = ospf6_route_lookup(
    1738             :                                                         &o_path->ls_prefix,
    1739             :                                                         oa->spf_table);
    1740         196 :                                 if (ls_entry == NULL) {
    1741           4 :                                         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    1742           0 :                                                 zlog_debug(
    1743             :                                                         "%s: ls_prfix %pFX ls_entry not found.",
    1744             :                                                         __func__,
    1745             :                                                         &o_path->ls_prefix);
    1746           4 :                                         continue;
    1747             :                                 }
    1748         192 :                                 lsa = ospf6_lsdb_lookup(o_path->origin.type,
    1749             :                                                 o_path->origin.id,
    1750             :                                                 o_path->origin.adv_router,
    1751             :                                                 oa->lsdb);
    1752         192 :                                 if (lsa == NULL) {
    1753           0 :                                         if (IS_OSPF6_DEBUG_EXAMIN(
    1754             :                                                                 INTRA_PREFIX)) {
    1755           0 :                                                 struct prefix adv_prefix;
    1756             : 
    1757           0 :                                                 ospf6_linkstate_prefix(
    1758             :                                                 o_path->origin.adv_router,
    1759             :                                                 o_path->origin.id, &adv_prefix);
    1760           0 :                                                 zlog_debug(
    1761             :                                                         "%s: adv_router %pFX lsa not found",
    1762             :                                                         __func__, &adv_prefix);
    1763             :                                         }
    1764           0 :                                         continue;
    1765             :                                 }
    1766         192 :                                 intra_prefix_lsa =
    1767             :                                         (struct ospf6_intra_prefix_lsa *)
    1768         192 :                                         OSPF6_LSA_HEADER_END(lsa->header);
    1769             : 
    1770         192 :                                 if (intra_prefix_lsa->ref_adv_router
    1771         192 :                                      == oa->ospf6->router_id) {
    1772         129 :                                         ifp = if_lookup_prefix(
    1773             :                                                 &old_route->prefix,
    1774             :                                                 oa->ospf6->vrf_id);
    1775             :                                 }
    1776             : 
    1777         192 :                                 if (ifp) {
    1778             :                                         /* Nexthop interface found */
    1779         103 :                                         ospf6_route_add_nexthop(old_route,
    1780             :                                                                 ifp->ifindex,
    1781             :                                                                 NULL);
    1782             :                                 } else {
    1783             :                                         /* The connected interfaces between
    1784             :                                          * routers can be in different networks.
    1785             :                                          * In this case the matching interface
    1786             :                                          * is not found. Copy nexthops from the
    1787             :                                          * link state entry
    1788             :                                          */
    1789          89 :                                         ospf6_route_merge_nexthops(old_route,
    1790             :                                                                    ls_entry);
    1791             :                                 }
    1792             :                         }
    1793             : 
    1794         166 :                         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    1795           0 :                                 zlog_debug(
    1796             :                                         "%s: route %pFX %p with final effective paths %u nh %u",
    1797             :                                         __func__, &route->prefix,
    1798             :                                         (void *)old_route,
    1799             :                                         old_route->paths
    1800             :                                                 ? listcount(old_route->paths)
    1801             :                                                 : 0,
    1802             :                                         listcount(old_route->nh_list));
    1803             : 
    1804             :                         /* used in intra_route_calculation() to add to
    1805             :                          * global ospf6 route table.
    1806             :                          */
    1807         166 :                         UNSET_FLAG(old_route->flag, OSPF6_ROUTE_REMOVE);
    1808         166 :                         SET_FLAG(old_route->flag, OSPF6_ROUTE_ADD);
    1809             :                         /* Update ospf6 route table and RIB/FIB */
    1810         166 :                         if (oa->route_table->hook_add)
    1811          16 :                                 (*oa->route_table->hook_add)(old_route);
    1812             :                         /* Delete the new route its info added to existing
    1813             :                          * route.
    1814             :                          */
    1815         166 :                         ospf6_route_delete(route);
    1816             : 
    1817         166 :                         break;
    1818             :                 }
    1819             :         }
    1820             : 
    1821         166 :         if (!route_found) {
    1822             :                 /* Add new route to existing node in ospf6 route table. */
    1823           4 :                 ospf6_route_add(route, oa->route_table);
    1824             :         }
    1825         170 : }
    1826             : 
    1827         406 : void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
    1828             : {
    1829         406 :         struct ospf6_area *oa;
    1830         406 :         struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
    1831         406 :         struct prefix ls_prefix;
    1832         406 :         struct ospf6_route *route, *ls_entry, *old;
    1833         406 :         int prefix_num;
    1834         406 :         struct ospf6_prefix *op;
    1835         406 :         char *start, *current, *end;
    1836         406 :         char buf[PREFIX2STR_BUFFER];
    1837         406 :         struct interface *ifp = NULL;
    1838         406 :         int direct_connect = 0;
    1839         406 :         struct ospf6_path *path;
    1840             : 
    1841         406 :         if (OSPF6_LSA_IS_MAXAGE(lsa))
    1842         213 :                 return;
    1843             : 
    1844         328 :         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    1845           0 :                 zlog_debug("%s: LSA %s found", __func__, lsa->name);
    1846             : 
    1847         328 :         oa = OSPF6_AREA(lsa->lsdb->data);
    1848             : 
    1849         328 :         intra_prefix_lsa =
    1850         328 :                 (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
    1851             :                         lsa->header);
    1852         328 :         if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_ROUTER) ||
    1853          63 :             intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK))
    1854         328 :                 ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
    1855             :                                        intra_prefix_lsa->ref_id, &ls_prefix);
    1856             :         else {
    1857           0 :                 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    1858           0 :                         zlog_debug("Unknown reference LS-type: %#hx",
    1859             :                                    ntohs(intra_prefix_lsa->ref_type));
    1860           0 :                 return;
    1861             :         }
    1862             : 
    1863         328 :         ls_entry = ospf6_route_lookup(&ls_prefix, oa->spf_table);
    1864         328 :         if (ls_entry == NULL) {
    1865         135 :                 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    1866           0 :                         ospf6_linkstate_prefix2str(&ls_prefix, buf,
    1867             :                                                    sizeof(buf));
    1868           0 :                         zlog_debug("LS entry does not exist: %s", buf);
    1869             :                 }
    1870         135 :                 return;
    1871             :         }
    1872             : 
    1873         193 :         if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id) {
    1874             :                 /* the intra-prefix are directly connected */
    1875         110 :                 direct_connect = 1;
    1876             :         }
    1877             : 
    1878         193 :         prefix_num = ntohs(intra_prefix_lsa->prefix_num);
    1879         193 :         start = (caddr_t)intra_prefix_lsa
    1880             :                 + sizeof(struct ospf6_intra_prefix_lsa);
    1881         193 :         end = OSPF6_LSA_END(lsa->header);
    1882         414 :         for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
    1883         221 :                 op = (struct ospf6_prefix *)current;
    1884         221 :                 if (prefix_num == 0)
    1885             :                         break;
    1886         221 :                 if (end < current + OSPF6_PREFIX_SIZE(op))
    1887             :                         break;
    1888             : 
    1889             :                 /* Appendix A.4.1.1 */
    1890         221 :                 if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU)) {
    1891           0 :                         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    1892           0 :                                 ospf6_linkstate_prefix2str(
    1893             :                                         (struct prefix *)OSPF6_PREFIX_BODY(op),
    1894             :                                         buf, sizeof(buf));
    1895           0 :                                 zlog_debug(
    1896             :                                         "%s: Skipping Prefix %s has NU option set",
    1897             :                                         __func__, buf);
    1898             :                         }
    1899           0 :                         continue;
    1900             :                 }
    1901             : 
    1902         221 :                 route = ospf6_route_create(oa->ospf6);
    1903             : 
    1904         221 :                 memset(&route->prefix, 0, sizeof(struct prefix));
    1905         221 :                 route->prefix.family = AF_INET6;
    1906         221 :                 route->prefix.prefixlen = op->prefix_length;
    1907         221 :                 ospf6_prefix_in6_addr(&route->prefix.u.prefix6,
    1908             :                                       intra_prefix_lsa, op);
    1909         221 :                 route->prefix_options = op->prefix_options;
    1910             : 
    1911         221 :                 route->type = OSPF6_DEST_TYPE_NETWORK;
    1912         221 :                 route->path.origin.type = lsa->header->type;
    1913         221 :                 route->path.origin.id = lsa->header->id;
    1914         221 :                 route->path.origin.adv_router = lsa->header->adv_router;
    1915         221 :                 route->path.area_id = oa->area_id;
    1916         221 :                 route->path.type = OSPF6_PATH_TYPE_INTRA;
    1917         221 :                 route->path.metric_type = 1;
    1918         221 :                 route->path.cost =
    1919         221 :                         ls_entry->path.cost + ntohs(op->prefix_metric);
    1920         221 :                 memcpy(&route->path.ls_prefix, &ls_prefix,
    1921             :                        sizeof(struct prefix));
    1922         221 :                 if (direct_connect) {
    1923         126 :                         ifp = if_lookup_prefix(&route->prefix,
    1924         126 :                                                oa->ospf6->vrf_id);
    1925             :                 }
    1926             : 
    1927         221 :                 if (ifp) {
    1928             :                         /* Nexthop interface found */
    1929          86 :                         ospf6_route_add_nexthop(route, ifp->ifindex, NULL);
    1930             :                 } else {
    1931             :                         /* The connected interfaces between routers can be in
    1932             :                          * different networks. In this case the matching
    1933             :                          * interface is not found. Copy nexthops from the
    1934             :                          * link state entry
    1935             :                          */
    1936         135 :                         ospf6_route_copy_nexthops(route, ls_entry);
    1937             :                 }
    1938             : 
    1939         221 :                 path = ospf6_path_dup(&route->path);
    1940         221 :                 ospf6_copy_nexthops(path->nh_list, route->path.nh_list);
    1941         221 :                 listnode_add_sort(route->paths, path);
    1942             : 
    1943         221 :                 old = ospf6_route_lookup(&route->prefix, oa->route_table);
    1944         221 :                 if (old) {
    1945         170 :                         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    1946           0 :                                 prefix2str(&route->prefix, buf, sizeof(buf));
    1947           0 :                                 zlog_debug(
    1948             :                                         "%s Update route: %s old cost %u new cost %u paths %u nh %u",
    1949             :                                         __func__, buf, old->path.cost,
    1950             :                                         route->path.cost,
    1951             :                                         listcount(route->paths),
    1952             :                                         listcount(route->nh_list));
    1953             :                         }
    1954         170 :                         ospf6_intra_prefix_route_ecmp_path(oa, old, route);
    1955             :                 } else {
    1956          51 :                         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    1957           0 :                                 prefix2str(&route->prefix, buf, sizeof(buf));
    1958           0 :                                 zlog_debug(
    1959             :                                         "%s route %s add with cost %u paths %u nh %u",
    1960             :                                         __func__, buf, route->path.cost,
    1961             :                                         listcount(route->paths),
    1962             :                                         listcount(route->nh_list));
    1963             :                         }
    1964          51 :                         ospf6_route_add(route, oa->route_table);
    1965             :                 }
    1966         221 :                 prefix_num--;
    1967             :         }
    1968             : 
    1969         193 :         ospf6_vlink_prefix_update(oa, lsa->header->adv_router);
    1970             : 
    1971         193 :         if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    1972         193 :                 zlog_debug("Trailing garbage ignored");
    1973             : }
    1974             : 
    1975          20 : static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa *lsa,
    1976             :                                                   struct ospf6_area *oa,
    1977             :                                                   struct ospf6_route *route)
    1978             : {
    1979          20 :         struct listnode *anode, *anext;
    1980          20 :         struct listnode *nnode, *rnode, *rnext;
    1981          20 :         struct ospf6_nexthop *nh, *rnh;
    1982          20 :         struct ospf6_path *o_path;
    1983          20 :         bool nh_updated = false;
    1984          20 :         char buf[PREFIX2STR_BUFFER];
    1985             : 
    1986             :         /* Iterate all paths of route to find maching
    1987             :          * with LSA remove info.
    1988             :          * If route->path is same, replace
    1989             :          * from paths list.
    1990             :          */
    1991          72 :         for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path)) {
    1992          37 :                 if ((o_path->origin.type != lsa->header->type) ||
    1993          37 :                     (o_path->origin.adv_router != lsa->header->adv_router) ||
    1994           9 :                     (o_path->origin.id != lsa->header->id))
    1995          32 :                         continue;
    1996             : 
    1997           5 :                 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    1998           0 :                         prefix2str(&route->prefix, buf, sizeof(buf));
    1999           0 :                         zlog_debug(
    2000             :                                 "%s: route %s path found with cost %u nh %u to remove.",
    2001             :                                 __func__, buf, o_path->cost,
    2002             :                                 listcount(o_path->nh_list));
    2003             :                 }
    2004             : 
    2005             :                 /* Remove found path's nh_list from
    2006             :                  * the route's nh_list.
    2007             :                  */
    2008          15 :                 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
    2009          16 :                         for (ALL_LIST_ELEMENTS(route->nh_list, rnode,
    2010             :                                                rnext, rnh)) {
    2011           6 :                                 if (!ospf6_nexthop_is_same(rnh, nh))
    2012           1 :                                         continue;
    2013           5 :                                 listnode_delete(route->nh_list, rnh);
    2014           5 :                                 ospf6_nexthop_delete(rnh);
    2015             :                         }
    2016             :                 }
    2017             :                 /* Delete the path from route's
    2018             :                  * path list
    2019             :                  */
    2020           5 :                 listnode_delete(route->paths, o_path);
    2021           5 :                 ospf6_path_free(o_path);
    2022           5 :                 nh_updated = true;
    2023           5 :                 break;
    2024             :         }
    2025             : 
    2026           5 :         if (nh_updated) {
    2027             :                 /* Iterate all paths and merge nexthop,
    2028             :                  * unlesss any of the nexthop similar to
    2029             :                  * ones deleted as part of path deletion.
    2030             :                  */
    2031          16 :                 for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path))
    2032           6 :                         ospf6_merge_nexthops(route->nh_list, o_path->nh_list);
    2033             : 
    2034             : 
    2035           5 :                 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    2036           0 :                         prefix2str(&route->prefix, buf, sizeof(buf));
    2037           0 :                         zlog_debug(
    2038             :                                 "%s: route %s update paths %u nh %u", __func__,
    2039             :                                 buf, route->paths ? listcount(route->paths) : 0,
    2040             :                                 route->nh_list ? listcount(route->nh_list) : 0);
    2041             :                 }
    2042             : 
    2043             :                 /* Update Global Route table and
    2044             :                  * RIB/FIB with effective
    2045             :                  * nh_list
    2046             :                  */
    2047           5 :                 if (oa->route_table->hook_add)
    2048           5 :                         (*oa->route_table->hook_add)(route);
    2049             : 
    2050             :                 /* route's primary path is similar
    2051             :                  * to LSA, replace route's primary
    2052             :                  * path with route's paths list
    2053             :                  * head.
    2054             :                  */
    2055           5 :                 if ((route->path.origin.id == lsa->header->id) &&
    2056           3 :                     (route->path.origin.adv_router ==
    2057           3 :                                 lsa->header->adv_router)) {
    2058           3 :                         ospf6_intra_prefix_update_route_origin(route,
    2059             :                                                                oa->ospf6);
    2060             :                 }
    2061             :         }
    2062             : 
    2063          20 : }
    2064             : 
    2065          98 : void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa)
    2066             : {
    2067          98 :         struct ospf6_area *oa;
    2068          98 :         struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
    2069          98 :         struct prefix prefix;
    2070          98 :         struct ospf6_route *route, *nroute;
    2071          98 :         int prefix_num;
    2072          98 :         struct ospf6_prefix *op;
    2073          98 :         char *start, *current, *end;
    2074          98 :         char buf[PREFIX2STR_BUFFER];
    2075             : 
    2076          98 :         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    2077           0 :                 zlog_debug("%s: %s disappearing", __func__, lsa->name);
    2078             : 
    2079          98 :         oa = OSPF6_AREA(lsa->lsdb->data);
    2080             : 
    2081          98 :         intra_prefix_lsa =
    2082          98 :                 (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
    2083             :                         lsa->header);
    2084             : 
    2085          98 :         prefix_num = ntohs(intra_prefix_lsa->prefix_num);
    2086          98 :         start = (caddr_t)intra_prefix_lsa
    2087             :                 + sizeof(struct ospf6_intra_prefix_lsa);
    2088          98 :         end = OSPF6_LSA_END(lsa->header);
    2089         214 :         for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
    2090         116 :                 op = (struct ospf6_prefix *)current;
    2091         116 :                 if (prefix_num == 0)
    2092             :                         break;
    2093         116 :                 if (end < current + OSPF6_PREFIX_SIZE(op))
    2094             :                         break;
    2095         116 :                 prefix_num--;
    2096             : 
    2097         116 :                 memset(&prefix, 0, sizeof(prefix));
    2098         116 :                 prefix.family = AF_INET6;
    2099         116 :                 prefix.prefixlen = op->prefix_length;
    2100         116 :                 ospf6_prefix_in6_addr(&prefix.u.prefix6, intra_prefix_lsa, op);
    2101             : 
    2102         116 :                 route = ospf6_route_lookup(&prefix, oa->route_table);
    2103         116 :                 if (route == NULL)
    2104          45 :                         continue;
    2105             : 
    2106          71 :                 for (ospf6_route_lock(route);
    2107         145 :                      route && ospf6_route_is_prefix(&prefix, route);
    2108             :                      route = nroute) {
    2109          74 :                         nroute = ospf6_route_next(route);
    2110          74 :                         if (route->type != OSPF6_DEST_TYPE_NETWORK)
    2111           0 :                                 continue;
    2112          74 :                         if (route->path.area_id != oa->area_id)
    2113           0 :                                 continue;
    2114          74 :                         if (route->path.type != OSPF6_PATH_TYPE_INTRA)
    2115           0 :                                 continue;
    2116             :                         /* Route has multiple ECMP paths, remove matching
    2117             :                          * path. Update current route's effective nh list
    2118             :                          * after removal of one of the path.
    2119             :                          */
    2120          74 :                         if (listcount(route->paths) > 1) {
    2121          20 :                                 ospf6_intra_prefix_lsa_remove_update_route(
    2122             :                                                         lsa, oa, route);
    2123             :                         } else {
    2124             : 
    2125          54 :                                 if (route->path.origin.type != lsa->header->type
    2126          54 :                                     || route->path.origin.id != lsa->header->id
    2127          47 :                                     || route->path.origin.adv_router
    2128          47 :                                     != lsa->header->adv_router)
    2129          13 :                                         continue;
    2130             : 
    2131          41 :                                 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    2132           0 :                                         prefix2str(&route->prefix, buf,
    2133             :                                                    sizeof(buf));
    2134           0 :                                         zlog_debug(
    2135             :                                                 "%s: route remove %s with path type %u cost %u paths %u nh %u",
    2136             :                                                 __func__, buf, route->path.type,
    2137             :                                                 route->path.cost,
    2138             :                                                 listcount(route->paths),
    2139             :                                                 listcount(route->nh_list));
    2140             :                                 }
    2141          41 :                                 ospf6_route_remove(route, oa->route_table);
    2142             :                         }
    2143             :                 }
    2144          71 :                 if (route)
    2145          28 :                         ospf6_route_unlock(route);
    2146             :         }
    2147             : 
    2148          98 :         if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    2149           0 :                 zlog_debug("Trailing garbage ignored");
    2150          98 : }
    2151             : 
    2152         172 : void ospf6_intra_route_calculation(struct ospf6_area *oa)
    2153             : {
    2154         172 :         struct ospf6_route *route, *nroute;
    2155         172 :         uint16_t type;
    2156         172 :         struct ospf6_lsa *lsa;
    2157         172 :         void (*hook_add)(struct ospf6_route *) = NULL;
    2158         172 :         void (*hook_remove)(struct ospf6_route *) = NULL;
    2159         172 :         char buf[PREFIX2STR_BUFFER];
    2160             : 
    2161         172 :         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    2162           0 :                 zlog_debug("Re-examin intra-routes for area %s", oa->name);
    2163             : 
    2164         172 :         hook_add = oa->route_table->hook_add;
    2165         172 :         hook_remove = oa->route_table->hook_remove;
    2166         172 :         oa->route_table->hook_add = NULL;
    2167         172 :         oa->route_table->hook_remove = NULL;
    2168             : 
    2169         334 :         for (route = ospf6_route_head(oa->route_table); route;
    2170         162 :              route = ospf6_route_next(route))
    2171         162 :                 route->flag = OSPF6_ROUTE_REMOVE;
    2172             : 
    2173         172 :         type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
    2174         501 :         for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
    2175         329 :                 ospf6_intra_prefix_lsa_add(lsa);
    2176             : 
    2177         172 :         oa->route_table->hook_add = hook_add;
    2178         172 :         oa->route_table->hook_remove = hook_remove;
    2179             : 
    2180         361 :         for (route = ospf6_route_head(oa->route_table); route; route = nroute) {
    2181         189 :                 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
    2182           0 :                         prefix2str(&route->prefix, buf, sizeof(buf));
    2183           0 :                         zlog_debug("%s: route %s, flag 0x%x", __func__, buf,
    2184             :                                    route->flag);
    2185             :                 }
    2186             : 
    2187         189 :                 nroute = ospf6_route_next(route);
    2188         189 :                 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)
    2189             :                     && CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)) {
    2190           0 :                         UNSET_FLAG(route->flag, OSPF6_ROUTE_REMOVE);
    2191           0 :                         UNSET_FLAG(route->flag, OSPF6_ROUTE_ADD);
    2192             :                 }
    2193             : 
    2194         189 :                 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE))
    2195          12 :                         ospf6_route_remove(route, oa->route_table);
    2196         177 :                 else if (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)
    2197             :                          || CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE)) {
    2198         177 :                         if (hook_add)
    2199         177 :                                 (*hook_add)(route);
    2200         177 :                         route->flag = 0;
    2201             :                 } else {
    2202             :                         /* Redo the summaries as things might have changed */
    2203           0 :                         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    2204           0 :                                 zlog_debug("%s: Originate summary for route %s",
    2205             :                                            __func__, buf);
    2206           0 :                         ospf6_abr_originate_summary(route, oa->ospf6);
    2207           0 :                         route->flag = 0;
    2208             :                 }
    2209             :         }
    2210             : 
    2211         172 :         if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
    2212           0 :                 zlog_debug("Re-examin intra-routes for area %s: Done",
    2213             :                            oa->name);
    2214         172 : }
    2215             : 
    2216           0 : static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
    2217             : {
    2218           0 :         uint32_t brouter_id;
    2219           0 :         char brouter_name[16];
    2220           0 :         char area_name[16];
    2221           0 :         char destination[64];
    2222           0 :         char installed[64], changed[64];
    2223           0 :         struct timeval now, res;
    2224           0 :         char id[16], adv_router[16];
    2225           0 :         char capa[16], options[32];
    2226             : 
    2227           0 :         brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
    2228           0 :         inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name));
    2229           0 :         inet_ntop(AF_INET, &brouter->path.area_id, area_name,
    2230             :                   sizeof(area_name));
    2231           0 :         ospf6_linkstate_prefix2str(&brouter->prefix, destination,
    2232             :                                    sizeof(destination));
    2233             : 
    2234           0 :         monotime(&now);
    2235           0 :         timersub(&now, &brouter->installed, &res);
    2236           0 :         timerstring(&res, installed, sizeof(installed));
    2237             : 
    2238           0 :         monotime(&now);
    2239           0 :         timersub(&now, &brouter->changed, &res);
    2240           0 :         timerstring(&res, changed, sizeof(changed));
    2241             : 
    2242           0 :         inet_ntop(AF_INET, &brouter->path.origin.id, id, sizeof(id));
    2243           0 :         inet_ntop(AF_INET, &brouter->path.origin.adv_router, adv_router,
    2244             :                   sizeof(adv_router));
    2245             : 
    2246           0 :         ospf6_options_printbuf(brouter->path.options, options, sizeof(options));
    2247           0 :         ospf6_capability_printbuf(brouter->path.router_bits, capa,
    2248             :                                   sizeof(capa));
    2249             : 
    2250           0 :         zlog_info("Brouter: %s via area %s", brouter_name, area_name);
    2251           0 :         zlog_info("  memory: prev: %p this: %p next: %p parent rnode: %p",
    2252             :                   (void *)brouter->prev, (void *)brouter, (void *)brouter->next,
    2253             :                   (void *)brouter->rnode);
    2254           0 :         zlog_info("  type: %d prefix: %s installed: %s changed: %s",
    2255             :                   brouter->type, destination, installed, changed);
    2256           0 :         zlog_info("  lock: %d flags: %s%s%s%s", brouter->lock,
    2257             :                   (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
    2258             :                   (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
    2259             :                   (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
    2260             :                   (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
    2261           0 :         zlog_info("  path type: %s ls-origin %s id: %s adv-router %s",
    2262             :                   OSPF6_PATH_TYPE_NAME(brouter->path.type),
    2263             :                   ospf6_lstype_name(brouter->path.origin.type), id, adv_router);
    2264           0 :         zlog_info("  options: %s router-bits: %s metric-type: %d metric: %d/%d",
    2265             :                   options, capa, brouter->path.metric_type, brouter->path.cost,
    2266             :                   brouter->path.u.cost_e2);
    2267           0 :         zlog_info(" paths %u nh %u", listcount(brouter->paths),
    2268             :                    listcount(brouter->nh_list));
    2269           0 : }
    2270             : 
    2271         172 : void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
    2272             : {
    2273         172 :         struct ospf6_route *brouter, *nbrouter, *copy;
    2274         172 :         void (*hook_add)(struct ospf6_route *) = NULL;
    2275         172 :         void (*hook_remove)(struct ospf6_route *) = NULL;
    2276         172 :         uint32_t brouter_id;
    2277         172 :         char brouter_name[16];
    2278             : 
    2279         172 :         if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
    2280         172 :             IS_OSPF6_DEBUG_ROUTE(MEMORY))
    2281           0 :                 zlog_debug("%s: border-router calculation for area %s",
    2282             :                            __func__, oa->name);
    2283             : 
    2284         172 :         hook_add = oa->ospf6->brouter_table->hook_add;
    2285         172 :         hook_remove = oa->ospf6->brouter_table->hook_remove;
    2286         172 :         oa->ospf6->brouter_table->hook_add = NULL;
    2287         172 :         oa->ospf6->brouter_table->hook_remove = NULL;
    2288             : 
    2289             :         /* withdraw the previous router entries for the area */
    2290         369 :         for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
    2291         197 :              brouter = ospf6_route_next(brouter)) {
    2292         197 :                 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
    2293         197 :                 inet_ntop(AF_INET, &brouter_id, brouter_name,
    2294             :                           sizeof(brouter_name));
    2295             : 
    2296         197 :                 if (brouter->path.area_id != oa->area_id)
    2297          78 :                         continue;
    2298             : 
    2299         119 :                 SET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
    2300             : 
    2301         119 :                 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id)
    2302         119 :                     || IS_OSPF6_DEBUG_ROUTE(MEMORY)) {
    2303           0 :                         zlog_debug("%p: mark as removing: area %s brouter %s",
    2304             :                                    (void *)brouter, oa->name, brouter_name);
    2305           0 :                         ospf6_brouter_debug_print(brouter);
    2306             :                 }
    2307             :         }
    2308             : 
    2309         616 :         for (brouter = ospf6_route_head(oa->spf_table); brouter;
    2310         444 :              brouter = ospf6_route_next(brouter)) {
    2311         444 :                 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
    2312         444 :                 inet_ntop(AF_INET, &brouter_id, brouter_name,
    2313             :                           sizeof(brouter_name));
    2314             : 
    2315         444 :                 if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
    2316           0 :                         continue;
    2317             : 
    2318         444 :                 if (ospf6_linkstate_prefix_id(&brouter->prefix) != htonl(0))
    2319         136 :                         continue;
    2320             : 
    2321         308 :                 if (!CHECK_FLAG(brouter->path.router_bits, OSPF6_ROUTER_BIT_E)
    2322             :                     && !CHECK_FLAG(brouter->path.router_bits,
    2323             :                                    OSPF6_ROUTER_BIT_B))
    2324         171 :                         continue;
    2325             : 
    2326         137 :                 if (!OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_V6)
    2327             :                     || !OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_R))
    2328           0 :                         continue;
    2329             : 
    2330         137 :                 copy = ospf6_route_copy(brouter);
    2331         137 :                 copy->type = OSPF6_DEST_TYPE_ROUTER;
    2332         137 :                 copy->path.area_id = oa->area_id;
    2333         137 :                 ospf6_route_add(copy, oa->ospf6->brouter_table);
    2334             : 
    2335         137 :                 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id)
    2336         137 :                     || IS_OSPF6_DEBUG_ROUTE(MEMORY)) {
    2337           0 :                         zlog_debug("%p: transfer: area %s brouter %s",
    2338             :                                    (void *)brouter, oa->name, brouter_name);
    2339           0 :                         ospf6_brouter_debug_print(brouter);
    2340             :                 }
    2341             :         }
    2342             : 
    2343         172 :         oa->ospf6->brouter_table->hook_add = hook_add;
    2344         172 :         oa->ospf6->brouter_table->hook_remove = hook_remove;
    2345             : 
    2346         399 :         for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
    2347             :              brouter = nbrouter) {
    2348             : 
    2349             :                 /*
    2350             :                  * brouter may have been "deleted" in the last loop iteration.
    2351             :                  * If this is the case there is still 1 final refcount lock
    2352             :                  * taken by ospf6_route_next, that will be released by the same
    2353             :                  * call and result in deletion. To avoid heap UAF we must then
    2354             :                  * skip processing the deleted route.
    2355             :                  */
    2356         227 :                 if (brouter->lock == 1) {
    2357           0 :                         if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
    2358           0 :                                 ospf6_brouter_debug_print(brouter);
    2359           0 :                         nbrouter = ospf6_route_next(brouter);
    2360           0 :                         continue;
    2361             :                 } else {
    2362         227 :                         nbrouter = ospf6_route_next(brouter);
    2363             :                 }
    2364             : 
    2365         227 :                 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
    2366         227 :                 inet_ntop(AF_INET, &brouter_id, brouter_name,
    2367             :                           sizeof(brouter_name));
    2368             : 
    2369         227 :                 if (brouter->path.area_id != oa->area_id)
    2370          78 :                         continue;
    2371             : 
    2372         149 :                 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
    2373           0 :                         continue;
    2374             : 
    2375             :                 /* After iterating spf_table for all routers including
    2376             :                  * intra brouter, clear mark for remove flag for
    2377             :                  * inter border router if its adv router present in
    2378             :                  * SPF table.
    2379             :                  */
    2380         149 :                 if (brouter->path.type == OSPF6_PATH_TYPE_INTER) {
    2381           4 :                         struct prefix adv_prefix;
    2382             : 
    2383           4 :                         ospf6_linkstate_prefix(brouter->path.origin.adv_router,
    2384             :                                                htonl(0), &adv_prefix);
    2385             : 
    2386           4 :                         if (ospf6_route_lookup(&adv_prefix, oa->spf_table)) {
    2387           0 :                                 if (IS_OSPF6_DEBUG_BROUTER) {
    2388           0 :                                         zlog_debug(
    2389             :                                                 "%s: keep inter brouter %s as adv router 0x%x found in spf",
    2390             :                                                 __func__, brouter_name,
    2391             :                                                 brouter->path.origin
    2392             :                                                         .adv_router);
    2393           0 :                                         ospf6_brouter_debug_print(brouter);
    2394             :                                 }
    2395           0 :                                 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
    2396             :                         }
    2397             :                 }
    2398             : 
    2399         149 :                 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)
    2400             :                     && CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)) {
    2401         105 :                         UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
    2402         105 :                         UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
    2403             :                 }
    2404             : 
    2405         149 :                 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)) {
    2406          10 :                         if (IS_OSPF6_DEBUG_BROUTER
    2407          10 :                             || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
    2408             :                                        brouter_id)
    2409          10 :                             || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
    2410             :                                        oa->area_id))
    2411           0 :                                 zlog_debug(
    2412             :                                         "%s: brouter %s disappears via area %s",
    2413             :                                         __func__, brouter_name, oa->name);
    2414             :                         /* This is used to protect nbrouter from removed from
    2415             :                          * the table. For an example, ospf6_abr_examin_summary,
    2416             :                          * removes brouters which are marked for remove.
    2417             :                          */
    2418          10 :                         oa->intra_brouter_calc = true;
    2419          10 :                         ospf6_route_remove(brouter, oa->ospf6->brouter_table);
    2420          10 :                         brouter = NULL;
    2421         139 :                 } else if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)
    2422             :                            || CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE)) {
    2423          34 :                         if (IS_OSPF6_DEBUG_BROUTER
    2424          34 :                             || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
    2425             :                                        brouter_id)
    2426          34 :                             || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
    2427             :                                        oa->area_id))
    2428           0 :                                 zlog_info("%s: brouter %s appears via area %s",
    2429             :                                           __func__, brouter_name, oa->name);
    2430             : 
    2431             :                         /* newly added */
    2432          34 :                         if (hook_add)
    2433          34 :                                 (*hook_add)(brouter);
    2434             :                 } else {
    2435         105 :                         if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
    2436             :                                     brouter_id)
    2437         105 :                             || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
    2438             :                                        oa->area_id))
    2439           0 :                                 zlog_debug(
    2440             :                                         "brouter %s still exists via area %s",
    2441             :                                         brouter_name, oa->name);
    2442             :                         /* But re-originate summaries */
    2443         105 :                         ospf6_abr_originate_summary(brouter, oa->ospf6);
    2444             :                 }
    2445             : 
    2446          10 :                 if (brouter) {
    2447         139 :                         UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
    2448         139 :                         UNSET_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE);
    2449             :                 }
    2450             :                 /* Reset for nbrouter */
    2451         149 :                 oa->intra_brouter_calc = false;
    2452             :         }
    2453             : 
    2454         172 :         if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
    2455         172 :             IS_OSPF6_DEBUG_ROUTE(MEMORY))
    2456           0 :                 zlog_debug("%s: border-router calculation for area %s: done",
    2457             :                            __func__, oa->name);
    2458         172 : }
    2459             : 
    2460             : static struct ospf6_lsa_handler router_handler = {
    2461             :         .lh_type = OSPF6_LSTYPE_ROUTER,
    2462             :         .lh_name = "Router",
    2463             :         .lh_short_name = "Rtr",
    2464             :         .lh_show = ospf6_router_lsa_show,
    2465             :         .lh_get_prefix_str = ospf6_router_lsa_get_nbr_id,
    2466             :         .lh_debug = 0};
    2467             : 
    2468             : static struct ospf6_lsa_handler network_handler = {
    2469             :         .lh_type = OSPF6_LSTYPE_NETWORK,
    2470             :         .lh_name = "Network",
    2471             :         .lh_short_name = "Net",
    2472             :         .lh_show = ospf6_network_lsa_show,
    2473             :         .lh_get_prefix_str = ospf6_network_lsa_get_ar_id,
    2474             :         .lh_debug = 0};
    2475             : 
    2476             : static struct ospf6_lsa_handler link_handler = {
    2477             :         .lh_type = OSPF6_LSTYPE_LINK,
    2478             :         .lh_name = "Link",
    2479             :         .lh_short_name = "Lnk",
    2480             :         .lh_show = ospf6_link_lsa_show,
    2481             :         .lh_get_prefix_str = ospf6_link_lsa_get_prefix_str,
    2482             :         .lh_debug = 0};
    2483             : 
    2484             : static struct ospf6_lsa_handler intra_prefix_handler = {
    2485             :         .lh_type = OSPF6_LSTYPE_INTRA_PREFIX,
    2486             :         .lh_name = "Intra-Prefix",
    2487             :         .lh_short_name = "INP",
    2488             :         .lh_show = ospf6_intra_prefix_lsa_show,
    2489             :         .lh_get_prefix_str = ospf6_intra_prefix_lsa_get_prefix_str,
    2490             :         .lh_debug = 0};
    2491             : 
    2492          16 : void ospf6_intra_init(void)
    2493             : {
    2494          16 :         ospf6_install_lsa_handler(&router_handler);
    2495          16 :         ospf6_install_lsa_handler(&network_handler);
    2496          16 :         ospf6_install_lsa_handler(&link_handler);
    2497          16 :         ospf6_install_lsa_handler(&intra_prefix_handler);
    2498          16 : }
    2499             : 
    2500           0 : DEFUN (debug_ospf6_brouter,
    2501             :        debug_ospf6_brouter_cmd,
    2502             :        "debug ospf6 border-routers",
    2503             :        DEBUG_STR
    2504             :        OSPF6_STR
    2505             :        "Debug border router\n"
    2506             :       )
    2507             : {
    2508           0 :         OSPF6_DEBUG_BROUTER_ON();
    2509           0 :         return CMD_SUCCESS;
    2510             : }
    2511             : 
    2512           0 : DEFUN (no_debug_ospf6_brouter,
    2513             :        no_debug_ospf6_brouter_cmd,
    2514             :        "no debug ospf6 border-routers",
    2515             :        NO_STR
    2516             :        DEBUG_STR
    2517             :        OSPF6_STR
    2518             :        "Debug border router\n"
    2519             :       )
    2520             : {
    2521           0 :         OSPF6_DEBUG_BROUTER_OFF();
    2522           0 :         return CMD_SUCCESS;
    2523             : }
    2524             : 
    2525           0 : DEFUN (debug_ospf6_brouter_router,
    2526             :        debug_ospf6_brouter_router_cmd,
    2527             :        "debug ospf6 border-routers router-id A.B.C.D",
    2528             :        DEBUG_STR
    2529             :        OSPF6_STR
    2530             :        "Debug border router\n"
    2531             :        "Debug specific border router\n"
    2532             :        "Specify border-router's router-id\n"
    2533             :       )
    2534             : {
    2535           0 :         int idx_ipv4 = 4;
    2536           0 :         uint32_t router_id;
    2537           0 :         inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
    2538           0 :         OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id);
    2539           0 :         return CMD_SUCCESS;
    2540             : }
    2541             : 
    2542           0 : DEFUN (no_debug_ospf6_brouter_router,
    2543             :        no_debug_ospf6_brouter_router_cmd,
    2544             :        "no debug ospf6 border-routers router-id [A.B.C.D]",
    2545             :        NO_STR
    2546             :        DEBUG_STR
    2547             :        OSPF6_STR
    2548             :        "Debug border router\n"
    2549             :        "Debug specific border router\n"
    2550             :        "Specify border-router's router-id\n"
    2551             :       )
    2552             : {
    2553           0 :         OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
    2554           0 :         return CMD_SUCCESS;
    2555             : }
    2556             : 
    2557           0 : DEFUN (debug_ospf6_brouter_area,
    2558             :        debug_ospf6_brouter_area_cmd,
    2559             :        "debug ospf6 border-routers area-id A.B.C.D",
    2560             :        DEBUG_STR
    2561             :        OSPF6_STR
    2562             :        "Debug border router\n"
    2563             :        "Debug border routers in specific Area\n"
    2564             :        "Specify Area-ID\n"
    2565             :       )
    2566             : {
    2567           0 :         int idx_ipv4 = 4;
    2568           0 :         uint32_t area_id;
    2569           0 :         inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id);
    2570           0 :         OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id);
    2571           0 :         return CMD_SUCCESS;
    2572             : }
    2573             : 
    2574           0 : DEFUN (no_debug_ospf6_brouter_area,
    2575             :        no_debug_ospf6_brouter_area_cmd,
    2576             :        "no debug ospf6 border-routers area-id [A.B.C.D]",
    2577             :        NO_STR
    2578             :        DEBUG_STR
    2579             :        OSPF6_STR
    2580             :        "Debug border router\n"
    2581             :        "Debug border routers in specific Area\n"
    2582             :        "Specify Area-ID\n"
    2583             :       )
    2584             : {
    2585           0 :         OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
    2586           0 :         return CMD_SUCCESS;
    2587             : }
    2588             : 
    2589           0 : int config_write_ospf6_debug_brouter(struct vty *vty)
    2590             : {
    2591           0 :         char buf[16];
    2592           0 :         if (IS_OSPF6_DEBUG_BROUTER)
    2593           0 :                 vty_out(vty, "debug ospf6 border-routers\n");
    2594           0 :         if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER) {
    2595           0 :                 inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
    2596             :                           buf, sizeof(buf));
    2597           0 :                 vty_out(vty, "debug ospf6 border-routers router-id %s\n", buf);
    2598             :         }
    2599           0 :         if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA) {
    2600           0 :                 inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
    2601             :                           buf, sizeof(buf));
    2602           0 :                 vty_out(vty, "debug ospf6 border-routers area-id %s\n", buf);
    2603             :         }
    2604           0 :         return 0;
    2605             : }
    2606             : 
    2607          16 : void install_element_ospf6_debug_brouter(void)
    2608             : {
    2609          16 :         install_element(ENABLE_NODE, &debug_ospf6_brouter_cmd);
    2610          16 :         install_element(ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
    2611          16 :         install_element(ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
    2612          16 :         install_element(ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
    2613          16 :         install_element(ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
    2614          16 :         install_element(ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
    2615          16 :         install_element(CONFIG_NODE, &debug_ospf6_brouter_cmd);
    2616          16 :         install_element(CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
    2617          16 :         install_element(CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
    2618          16 :         install_element(CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
    2619          16 :         install_element(CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
    2620          16 :         install_element(CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);
    2621          16 : }

Generated by: LCOV version v1.16-topotato