back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_lsa.c (source / functions) Hit Total Coverage
Test: test_ospf6_p2xp.py::PtMPBasic Lines: 275 627 43.9 %
Date: 2023-02-24 18:38:14 Functions: 34 50 68.0 %

          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 other stuffs */
      24             : #include "log.h"
      25             : #include "linklist.h"
      26             : #include "vector.h"
      27             : #include "vty.h"
      28             : #include "command.h"
      29             : #include "memory.h"
      30             : #include "thread.h"
      31             : #include "checksum.h"
      32             : #include "frrstr.h"
      33             : 
      34             : #include "ospf6_proto.h"
      35             : #include "ospf6_lsa.h"
      36             : #include "ospf6_lsdb.h"
      37             : #include "ospf6_message.h"
      38             : #include "ospf6_asbr.h"
      39             : #include "ospf6_zebra.h"
      40             : 
      41             : #include "ospf6_top.h"
      42             : #include "ospf6_area.h"
      43             : #include "ospf6_interface.h"
      44             : #include "ospf6_neighbor.h"
      45             : 
      46             : #include "ospf6_flood.h"
      47             : #include "ospf6d.h"
      48             : 
      49             : #include "ospf6d/ospf6_lsa_clippy.c"
      50             : 
      51          12 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA,         "OSPF6 LSA");
      52          12 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_HEADER,  "OSPF6 LSA header");
      53          12 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary");
      54             : 
      55             : static struct ospf6_lsa_handler *lsa_handlers[OSPF6_LSTYPE_SIZE];
      56             : 
      57         392 : struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa)
      58             : {
      59         392 :         struct ospf6 *ospf6 = NULL;
      60             : 
      61         392 :         switch (OSPF6_LSA_SCOPE(lsa->header->type)) {
      62          69 :         case OSPF6_SCOPE_LINKLOCAL:
      63          69 :                 ospf6 = OSPF6_INTERFACE(lsa->lsdb->data)->area->ospf6;
      64          69 :                 break;
      65         323 :         case OSPF6_SCOPE_AREA:
      66         323 :                 ospf6 = OSPF6_AREA(lsa->lsdb->data)->ospf6;
      67         323 :                 break;
      68           0 :         case OSPF6_SCOPE_AS:
      69           0 :                 ospf6 = OSPF6_PROCESS(lsa->lsdb->data);
      70           0 :                 break;
      71             :         default:
      72           0 :                 assert(0);
      73             :                 break;
      74             :         }
      75         392 :         return ospf6;
      76             : }
      77             : 
      78           0 : static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
      79             :                                   json_object *json_obj, bool use_json)
      80             : {
      81           0 :         uint8_t *start, *end, *current;
      82             : 
      83           0 :         start = (uint8_t *)lsa->header + sizeof(struct ospf6_lsa_header);
      84           0 :         end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
      85             : 
      86           0 :         if (use_json) {
      87           0 :                 json_object_string_add(json_obj, "lsaType", "unknown");
      88             :         } else {
      89           0 :                 vty_out(vty, "        Unknown contents:\n");
      90           0 :                 for (current = start; current < end; current++) {
      91           0 :                         if ((current - start) % 16 == 0)
      92           0 :                                 vty_out(vty, "\n        ");
      93           0 :                         else if ((current - start) % 4 == 0)
      94           0 :                                 vty_out(vty, " ");
      95             : 
      96           0 :                         vty_out(vty, "%02x", *current);
      97             :                 }
      98             : 
      99           0 :                 vty_out(vty, "\n\n");
     100             :         }
     101           0 :         return 0;
     102             : }
     103             : 
     104             : static struct ospf6_lsa_handler unknown_handler = {
     105             :         .lh_type = OSPF6_LSTYPE_UNKNOWN,
     106             :         .lh_name = "Unknown",
     107             :         .lh_short_name = "Unk",
     108             :         .lh_show = ospf6_unknown_lsa_show,
     109             :         .lh_get_prefix_str = NULL,
     110             :         .lh_debug = 0 /* No default debug */
     111             : };
     112             : 
     113          40 : void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler)
     114             : {
     115             :         /* type in handler is host byte order */
     116          40 :         unsigned int index = handler->lh_type & OSPF6_LSTYPE_FCODE_MASK;
     117             : 
     118          40 :         assertf(index < array_size(lsa_handlers), "index=%x", index);
     119          40 :         assertf(lsa_handlers[index] == NULL, "old=%s, new=%s",
     120             :                 lsa_handlers[index]->lh_name, handler->lh_name);
     121             : 
     122          40 :         lsa_handlers[index] = handler;
     123          40 : }
     124             : 
     125        4460 : struct ospf6_lsa_handler *ospf6_get_lsa_handler(uint16_t type)
     126             : {
     127        4460 :         struct ospf6_lsa_handler *handler = NULL;
     128         133 :         unsigned int index = ntohs(type) & OSPF6_LSTYPE_FCODE_MASK;
     129             : 
     130        4460 :         if (index < array_size(lsa_handlers))
     131        4456 :                 handler = lsa_handlers[index];
     132             : 
     133        4456 :         if (handler == NULL)
     134           4 :                 handler = &unknown_handler;
     135             : 
     136        2723 :         return handler;
     137             : }
     138             : 
     139        1737 : const char *ospf6_lstype_name(uint16_t type)
     140             : {
     141        1737 :         static char buf[8];
     142        1737 :         const struct ospf6_lsa_handler *handler;
     143             : 
     144        1737 :         handler = ospf6_get_lsa_handler(type);
     145        1737 :         if (handler && handler != &unknown_handler)
     146        1737 :                 return handler->lh_name;
     147             : 
     148           0 :         snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
     149           0 :         return buf;
     150             : }
     151             : 
     152           0 : const char *ospf6_lstype_short_name(uint16_t type)
     153             : {
     154           0 :         static char buf[8];
     155           0 :         const struct ospf6_lsa_handler *handler;
     156             : 
     157           0 :         handler = ospf6_get_lsa_handler(type);
     158           0 :         if (handler)
     159           0 :                 return handler->lh_short_name;
     160             : 
     161             :         snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
     162             :         return buf;
     163             : }
     164             : 
     165        1784 : uint8_t ospf6_lstype_debug(uint16_t type)
     166             : {
     167        1784 :         const struct ospf6_lsa_handler *handler;
     168        1768 :         handler = ospf6_get_lsa_handler(type);
     169        1784 :         return handler->lh_debug;
     170             : }
     171             : 
     172           0 : int metric_type(struct ospf6 *ospf6, int type, uint8_t instance)
     173             : {
     174           0 :         struct ospf6_redist *red;
     175             : 
     176           0 :         red = ospf6_redist_lookup(ospf6, type, instance);
     177             : 
     178           0 :         return ((!red || red->dmetric.type < 0) ? DEFAULT_METRIC_TYPE
     179           0 :                                                 : red->dmetric.type);
     180             : }
     181             : 
     182           0 : int metric_value(struct ospf6 *ospf6, int type, uint8_t instance)
     183             : {
     184           0 :         struct ospf6_redist *red;
     185             : 
     186           0 :         red = ospf6_redist_lookup(ospf6, type, instance);
     187           0 :         if (!red || red->dmetric.value < 0) {
     188           0 :                 if (type == DEFAULT_ROUTE) {
     189           0 :                         if (ospf6->default_originate == DEFAULT_ORIGINATE_ZEBRA)
     190             :                                 return DEFAULT_DEFAULT_ORIGINATE_METRIC;
     191             :                         else
     192           0 :                                 return DEFAULT_DEFAULT_ALWAYS_METRIC;
     193             :                 } else
     194             :                         return DEFAULT_DEFAULT_METRIC;
     195             :         }
     196             : 
     197             :         return red->dmetric.value;
     198             : }
     199             : 
     200             : /* RFC2328: Section 13.2 */
     201          25 : int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
     202             : {
     203          25 :         int len;
     204             : 
     205          25 :         assert(OSPF6_LSA_IS_SAME(lsa1, lsa2));
     206             : 
     207             :         /* XXX, Options ??? */
     208             : 
     209          25 :         ospf6_lsa_age_current(lsa1);
     210          25 :         ospf6_lsa_age_current(lsa2);
     211          25 :         if (ntohs(lsa1->header->age) == OSPF_LSA_MAXAGE
     212           0 :             && ntohs(lsa2->header->age) != OSPF_LSA_MAXAGE)
     213             :                 return 1;
     214          25 :         if (ntohs(lsa1->header->age) != OSPF_LSA_MAXAGE
     215          25 :             && ntohs(lsa2->header->age) == OSPF_LSA_MAXAGE)
     216             :                 return 1;
     217             : 
     218             :         /* compare body */
     219          18 :         if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
     220             :                 return 1;
     221             : 
     222           6 :         len = ntohs(lsa1->header->length) - sizeof(struct ospf6_lsa_header);
     223           6 :         return memcmp(lsa1->header + 1, lsa2->header + 1, len);
     224             : }
     225             : 
     226         148 : int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
     227             : {
     228         148 :         int length;
     229             : 
     230         148 :         if (OSPF6_LSA_IS_MAXAGE(lsa1) ^ OSPF6_LSA_IS_MAXAGE(lsa2))
     231             :                 return 1;
     232         118 :         if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
     233             :                 return 1;
     234             :         /* Going beyond LSA headers to compare the payload only makes sense,
     235             :          * when both LSAs aren't header-only. */
     236          42 :         if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY)
     237          42 :             != CHECK_FLAG(lsa2->flag, OSPF6_LSA_HEADERONLY)) {
     238           0 :                 zlog_warn(
     239             :                         "%s: only one of two (%s, %s) LSAs compared is header-only",
     240             :                         __func__, lsa1->name, lsa2->name);
     241           0 :                 return 1;
     242             :         }
     243          42 :         if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY))
     244             :                 return 0;
     245             : 
     246          42 :         length = OSPF6_LSA_SIZE(lsa1->header) - sizeof(struct ospf6_lsa_header);
     247             :         /* Once upper layer verifies LSAs received, length underrun should
     248             :          * become a warning. */
     249          42 :         if (length <= 0)
     250             :                 return 0;
     251             : 
     252          42 :         return memcmp(OSPF6_LSA_HEADER_END(lsa1->header),
     253             :                       OSPF6_LSA_HEADER_END(lsa2->header), length);
     254             : }
     255             : 
     256             : /* ospf6 age functions */
     257             : /* calculate birth */
     258         712 : void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
     259             : {
     260         712 :         struct timeval now;
     261             : 
     262         712 :         assert(lsa && lsa->header);
     263             : 
     264         712 :         monotime(&now);
     265             : 
     266         712 :         lsa->birth.tv_sec = now.tv_sec - ntohs(lsa->header->age);
     267         712 :         lsa->birth.tv_usec = now.tv_usec;
     268             : 
     269         712 :         return;
     270             : }
     271             : 
     272             : /* this function calculates current age from its birth,
     273             :    then update age field of LSA header. return value is current age */
     274        3842 : uint16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa)
     275             : {
     276        3842 :         struct timeval now;
     277        3842 :         uint32_t ulage;
     278        3842 :         uint16_t age;
     279             : 
     280        3842 :         assert(lsa);
     281        3842 :         assert(lsa->header);
     282             : 
     283             :         /* current time */
     284        3842 :         monotime(&now);
     285             : 
     286        3842 :         if (ntohs(lsa->header->age) >= OSPF_LSA_MAXAGE) {
     287             :                 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
     288             :                    relative time, we cannot compare against lsa birth time, so
     289             :                    we catch this special case here. */
     290         339 :                 lsa->header->age = htons(OSPF_LSA_MAXAGE);
     291         339 :                 return OSPF_LSA_MAXAGE;
     292             :         }
     293             :         /* calculate age */
     294        3503 :         ulage = now.tv_sec - lsa->birth.tv_sec;
     295             : 
     296             :         /* if over MAXAGE, set to it */
     297        3503 :         age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
     298             : 
     299        3503 :         lsa->header->age = htons(age);
     300        3503 :         return age;
     301             : }
     302             : 
     303             : /* update age field of LSA header with adding InfTransDelay */
     304         344 : void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa, uint32_t transdelay)
     305             : {
     306         344 :         unsigned short age;
     307             : 
     308         344 :         age = ospf6_lsa_age_current(lsa) + transdelay;
     309         344 :         if (age > OSPF_LSA_MAXAGE)
     310             :                 age = OSPF_LSA_MAXAGE;
     311         344 :         lsa->header->age = htons(age);
     312         344 : }
     313             : 
     314           8 : void ospf6_lsa_premature_aging(struct ospf6_lsa *lsa)
     315             : {
     316             :         /* log */
     317          16 :         if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
     318           0 :                 zlog_debug("LSA: Premature aging: %s", lsa->name);
     319             : 
     320           8 :         THREAD_OFF(lsa->expire);
     321           8 :         THREAD_OFF(lsa->refresh);
     322             : 
     323             :         /*
     324             :          * We clear the LSA from the neighbor retx lists now because it
     325             :          * will not get deleted later. Essentially, changing the age to
     326             :          * MaxAge will prevent this LSA from being matched with its
     327             :          * existing entries in the retx list thereby causing those entries
     328             :          * to be silently replaced with its MaxAged version, but with ever
     329             :          * increasing retx count causing this LSA to remain forever and
     330             :          * for the MaxAge remover thread to be called forever too.
     331             :          *
     332             :          * The reason the previous entry silently disappears is that when
     333             :          * entry is added to a neighbor's retx list, it replaces the existing
     334             :          * entry. But since the ospf6_lsdb_add() routine is generic and not
     335             :          * aware
     336             :          * of the special semantics of retx count, the retx count is not
     337             :          * decremented when its replaced. Attempting to add the incr and decr
     338             :          * retx count routines as the hook_add and hook_remove for the retx
     339             :          * lists
     340             :          * have a problem because the hook_remove routine is called for MaxAge
     341             :          * entries (as will be the case in a traditional LSDB, unlike in this
     342             :          * case
     343             :          * where an LSDB is used as an efficient tree structure to store all
     344             :          * kinds
     345             :          * of data) that are added instead of calling the hook_add routine.
     346             :          */
     347             : 
     348           8 :         ospf6_flood_clear(lsa);
     349             : 
     350           8 :         lsa->header->age = htons(OSPF_LSA_MAXAGE);
     351           8 :         thread_execute(master, ospf6_lsa_expire, lsa, 0);
     352           8 : }
     353             : 
     354             : /* check which is more recent. if a is more recent, return -1;
     355             :    if the same, return 0; otherwise(b is more recent), return 1 */
     356         360 : int ospf6_lsa_compare(struct ospf6_lsa *a, struct ospf6_lsa *b)
     357             : {
     358         360 :         int32_t seqnuma, seqnumb;
     359         360 :         uint16_t cksuma, cksumb;
     360         360 :         uint16_t agea, ageb;
     361             : 
     362         360 :         assert(a && a->header);
     363         360 :         assert(b && b->header);
     364         360 :         assert(OSPF6_LSA_IS_SAME(a, b));
     365             : 
     366         360 :         seqnuma = (int32_t)ntohl(a->header->seqnum);
     367         360 :         seqnumb = (int32_t)ntohl(b->header->seqnum);
     368             : 
     369             :         /* compare by sequence number */
     370         360 :         if (seqnuma > seqnumb)
     371             :                 return -1;
     372         243 :         if (seqnuma < seqnumb)
     373             :                 return 1;
     374             : 
     375             :         /* Checksum */
     376         229 :         cksuma = ntohs(a->header->checksum);
     377         229 :         cksumb = ntohs(b->header->checksum);
     378         229 :         if (cksuma > cksumb)
     379             :                 return -1;
     380         229 :         if (cksuma < cksumb)
     381             :                 return 0;
     382             : 
     383             :         /* Update Age */
     384         229 :         agea = ospf6_lsa_age_current(a);
     385         229 :         ageb = ospf6_lsa_age_current(b);
     386             : 
     387             :         /* MaxAge check */
     388         229 :         if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
     389             :                 return -1;
     390         199 :         else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
     391             :                 return 1;
     392             : 
     393             :         /* Age check */
     394         199 :         if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
     395             :                 return 1;
     396         199 :         else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
     397             :                 return -1;
     398             : 
     399             :         /* neither recent */
     400             :         return 0;
     401             : }
     402             : 
     403         712 : char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size)
     404             : {
     405         712 :         char id[16], adv_router[16];
     406         712 :         inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
     407         712 :         inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
     408             :                   sizeof(adv_router));
     409        1424 :         snprintf(buf, size, "[%s Id:%s Adv:%s]",
     410         712 :                  ospf6_lstype_name(lsa->header->type), id, adv_router);
     411         712 :         return buf;
     412             : }
     413             : 
     414           0 : void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header)
     415             : {
     416           0 :         char id[16], adv_router[16];
     417           0 :         inet_ntop(AF_INET, &header->id, id, sizeof(id));
     418           0 :         inet_ntop(AF_INET, &header->adv_router, adv_router, sizeof(adv_router));
     419           0 :         zlog_debug("    [%s Id:%s Adv:%s]", ospf6_lstype_name(header->type), id,
     420             :                    adv_router);
     421           0 :         zlog_debug("    Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
     422             :                    ntohs(header->age), (unsigned long)ntohl(header->seqnum),
     423             :                    ntohs(header->checksum), ntohs(header->length));
     424           0 : }
     425             : 
     426           0 : void ospf6_lsa_header_print(struct ospf6_lsa *lsa)
     427             : {
     428           0 :         ospf6_lsa_age_current(lsa);
     429           0 :         ospf6_lsa_header_print_raw(lsa->header);
     430           0 : }
     431             : 
     432           0 : void ospf6_lsa_show_summary_header(struct vty *vty)
     433             : {
     434           0 :         vty_out(vty, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId",
     435             :                 "AdvRouter", "Age", "SeqNum", "Payload");
     436           0 : }
     437             : 
     438           0 : void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa,
     439             :                             json_object *json_array, bool use_json)
     440             : {
     441           0 :         char adv_router[16], id[16];
     442           0 :         int type;
     443           0 :         const struct ospf6_lsa_handler *handler;
     444           0 :         char buf[64];
     445           0 :         int cnt = 0;
     446           0 :         json_object *json_obj = NULL;
     447             : 
     448           0 :         assert(lsa);
     449           0 :         assert(lsa->header);
     450             : 
     451           0 :         inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
     452           0 :         inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
     453             :                   sizeof(adv_router));
     454             : 
     455           0 :         type = ntohs(lsa->header->type);
     456           0 :         handler = ospf6_get_lsa_handler(lsa->header->type);
     457             : 
     458           0 :         if (use_json)
     459           0 :                 json_obj = json_object_new_object();
     460             : 
     461           0 :         switch (type) {
     462           0 :         case OSPF6_LSTYPE_INTER_PREFIX:
     463             :         case OSPF6_LSTYPE_INTER_ROUTER:
     464             :         case OSPF6_LSTYPE_AS_EXTERNAL:
     465             :         case OSPF6_LSTYPE_TYPE_7:
     466           0 :                 if (use_json) {
     467           0 :                         json_object_string_add(
     468             :                                 json_obj, "type",
     469           0 :                                 ospf6_lstype_short_name(lsa->header->type));
     470           0 :                         json_object_string_add(json_obj, "lsId", id);
     471           0 :                         json_object_string_add(json_obj, "advRouter",
     472             :                                                adv_router);
     473           0 :                         json_object_int_add(json_obj, "age",
     474           0 :                                             ospf6_lsa_age_current(lsa));
     475           0 :                         json_object_int_add(
     476             :                                 json_obj, "seqNum",
     477           0 :                                 (unsigned long)ntohl(lsa->header->seqnum));
     478           0 :                         json_object_string_add(
     479             :                                 json_obj, "payload",
     480           0 :                                 handler->lh_get_prefix_str(lsa, buf,
     481             :                                                            sizeof(buf), 0));
     482           0 :                         json_object_array_add(json_array, json_obj);
     483             :                 } else
     484           0 :                         vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n",
     485           0 :                                 ospf6_lstype_short_name(lsa->header->type), id,
     486           0 :                                 adv_router, ospf6_lsa_age_current(lsa),
     487           0 :                                 (unsigned long)ntohl(lsa->header->seqnum),
     488           0 :                                 handler->lh_get_prefix_str(lsa, buf,
     489             :                                                            sizeof(buf), 0));
     490             :                 break;
     491             :         case OSPF6_LSTYPE_ROUTER:
     492             :         case OSPF6_LSTYPE_NETWORK:
     493             :         case OSPF6_LSTYPE_GROUP_MEMBERSHIP:
     494             :         case OSPF6_LSTYPE_LINK:
     495             :         case OSPF6_LSTYPE_INTRA_PREFIX:
     496           0 :                 while (handler->lh_get_prefix_str(lsa, buf, sizeof(buf), cnt)
     497           0 :                        != NULL) {
     498           0 :                         if (use_json) {
     499           0 :                                 json_object_string_add(
     500             :                                         json_obj, "type",
     501             :                                         ospf6_lstype_short_name(
     502           0 :                                                 lsa->header->type));
     503           0 :                                 json_object_string_add(json_obj, "lsId", id);
     504           0 :                                 json_object_string_add(json_obj, "advRouter",
     505             :                                                        adv_router);
     506           0 :                                 json_object_int_add(json_obj, "age",
     507           0 :                                                     ospf6_lsa_age_current(lsa));
     508           0 :                                 json_object_int_add(
     509             :                                         json_obj, "seqNum",
     510           0 :                                         (unsigned long)ntohl(
     511             :                                                 lsa->header->seqnum));
     512           0 :                                 json_object_string_add(json_obj, "payload",
     513             :                                                        buf);
     514           0 :                                 json_object_array_add(json_array, json_obj);
     515           0 :                                 json_obj = json_object_new_object();
     516             :                         } else
     517           0 :                                 vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n",
     518             :                                         ospf6_lstype_short_name(
     519           0 :                                                 lsa->header->type),
     520             :                                         id, adv_router,
     521           0 :                                         ospf6_lsa_age_current(lsa),
     522           0 :                                         (unsigned long)ntohl(
     523             :                                                 lsa->header->seqnum),
     524             :                                         buf);
     525           0 :                         cnt++;
     526             :                 }
     527           0 :                 if (use_json)
     528           0 :                         json_object_free(json_obj);
     529             :                 break;
     530           0 :         default:
     531           0 :                 if (use_json) {
     532           0 :                         json_object_string_add(
     533             :                                 json_obj, "type",
     534           0 :                                 ospf6_lstype_short_name(lsa->header->type));
     535           0 :                         json_object_string_add(json_obj, "lsId", id);
     536           0 :                         json_object_string_add(json_obj, "advRouter",
     537             :                                                adv_router);
     538           0 :                         json_object_int_add(json_obj, "age",
     539           0 :                                             ospf6_lsa_age_current(lsa));
     540           0 :                         json_object_int_add(
     541             :                                 json_obj, "seqNum",
     542           0 :                                 (unsigned long)ntohl(lsa->header->seqnum));
     543           0 :                         json_object_array_add(json_array, json_obj);
     544             :                 } else
     545           0 :                         vty_out(vty, "%-4s %-15s%-15s%4hu %8lx\n",
     546           0 :                                 ospf6_lstype_short_name(lsa->header->type), id,
     547           0 :                                 adv_router, ospf6_lsa_age_current(lsa),
     548           0 :                                 (unsigned long)ntohl(lsa->header->seqnum));
     549             :                 break;
     550             :         }
     551           0 : }
     552             : 
     553           0 : void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa,
     554             :                          json_object *json_array, bool use_json)
     555             : {
     556           0 :         uint8_t *start = NULL;
     557           0 :         uint8_t *end = NULL;
     558           0 :         uint8_t *current = NULL;
     559           0 :         char byte[4];
     560           0 :         char *header_str = NULL;
     561           0 :         char adv_router[INET6_ADDRSTRLEN];
     562           0 :         char id[INET6_ADDRSTRLEN];
     563           0 :         json_object *json = NULL;
     564             : 
     565           0 :         start = (uint8_t *)lsa->header;
     566           0 :         end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
     567             : 
     568           0 :         if (use_json) {
     569           0 :                 json = json_object_new_object();
     570           0 :                 size_t header_str_sz = (2 * (end - start)) + 1;
     571             : 
     572           0 :                 header_str = XMALLOC(MTYPE_OSPF6_LSA_HEADER, header_str_sz);
     573             : 
     574           0 :                 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
     575           0 :                 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
     576             :                           sizeof(adv_router));
     577             : 
     578           0 :                 frrstr_hex(header_str, header_str_sz, start, end - start);
     579             : 
     580           0 :                 json_object_string_add(json, "linkStateId", id);
     581           0 :                 json_object_string_add(json, "advertisingRouter", adv_router);
     582           0 :                 json_object_string_add(json, "header", header_str);
     583           0 :                 json_object_array_add(json_array, json);
     584             : 
     585           0 :                 XFREE(MTYPE_OSPF6_LSA_HEADER, header_str);
     586             :         } else {
     587           0 :                 vty_out(vty, "\n%s:\n", lsa->name);
     588             : 
     589           0 :                 for (current = start; current < end; current++) {
     590           0 :                         if ((current - start) % 16 == 0)
     591           0 :                                 vty_out(vty, "\n        ");
     592           0 :                         else if ((current - start) % 4 == 0)
     593           0 :                                 vty_out(vty, " ");
     594             : 
     595           0 :                         snprintf(byte, sizeof(byte), "%02x", *current);
     596           0 :                         vty_out(vty, "%s", byte);
     597             :                 }
     598             : 
     599           0 :                 vty_out(vty, "\n\n");
     600             :         }
     601             : 
     602           0 :         return;
     603             : }
     604             : 
     605           0 : void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa,
     606             :                              json_object *json_array, bool use_json)
     607             : {
     608           0 :         char adv_router[64], id[64];
     609           0 :         json_object *json_obj;
     610             : 
     611           0 :         assert(lsa && lsa->header);
     612             : 
     613           0 :         inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
     614           0 :         inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
     615             :                   sizeof(adv_router));
     616             : 
     617           0 :         if (use_json) {
     618           0 :                 json_obj = json_object_new_object();
     619           0 :                 json_object_int_add(json_obj, "age",
     620           0 :                                     ospf6_lsa_age_current(lsa));
     621           0 :                 json_object_string_add(json_obj, "type",
     622           0 :                                        ospf6_lstype_name(lsa->header->type));
     623           0 :                 json_object_string_add(json_obj, "linkStateId", id);
     624           0 :                 json_object_string_add(json_obj, "advertisingRouter",
     625             :                                        adv_router);
     626           0 :                 json_object_int_add(json_obj, "lsSequenceNumber",
     627           0 :                                     (unsigned long)ntohl(lsa->header->seqnum));
     628           0 :                 json_object_int_add(json_obj, "checksum",
     629           0 :                                     ntohs(lsa->header->checksum));
     630           0 :                 json_object_int_add(json_obj, "length",
     631           0 :                                     ntohs(lsa->header->length));
     632           0 :                 json_object_int_add(json_obj, "flag", lsa->flag);
     633           0 :                 json_object_int_add(json_obj, "lock", lsa->lock);
     634           0 :                 json_object_int_add(json_obj, "reTxCount", lsa->retrans_count);
     635             : 
     636             :                 /* Threads Data not added */
     637           0 :                 json_object_array_add(json_array, json_obj);
     638             :         } else {
     639           0 :                 vty_out(vty, "\n");
     640           0 :                 vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa),
     641           0 :                         ospf6_lstype_name(lsa->header->type));
     642           0 :                 vty_out(vty, "Link State ID: %s\n", id);
     643           0 :                 vty_out(vty, "Advertising Router: %s\n", adv_router);
     644           0 :                 vty_out(vty, "LS Sequence Number: %#010lx\n",
     645           0 :                         (unsigned long)ntohl(lsa->header->seqnum));
     646           0 :                 vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
     647           0 :                         ntohs(lsa->header->checksum),
     648           0 :                         ntohs(lsa->header->length));
     649           0 :                 vty_out(vty, "Flag: %x \n", lsa->flag);
     650           0 :                 vty_out(vty, "Lock: %d \n", lsa->lock);
     651           0 :                 vty_out(vty, "ReTx Count: %d\n", lsa->retrans_count);
     652           0 :                 vty_out(vty, "Threads: Expire: %p, Refresh: %p\n", lsa->expire,
     653             :                         lsa->refresh);
     654           0 :                 vty_out(vty, "\n");
     655             :         }
     656           0 :         return;
     657             : }
     658             : 
     659         806 : void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
     660             :                     json_object *json_array, bool use_json)
     661             : {
     662         806 :         char adv_router[64], id[64];
     663         806 :         const struct ospf6_lsa_handler *handler;
     664         806 :         struct timeval now, res;
     665         806 :         char duration[64];
     666         806 :         json_object *json_obj = NULL;
     667             : 
     668         806 :         assert(lsa && lsa->header);
     669             : 
     670         806 :         inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
     671         806 :         inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
     672             :                   sizeof(adv_router));
     673             : 
     674         806 :         monotime(&now);
     675         806 :         timersub(&now, &lsa->installed, &res);
     676         806 :         timerstring(&res, duration, sizeof(duration));
     677         806 :         if (use_json) {
     678         806 :                 json_obj = json_object_new_object();
     679         806 :                 json_object_int_add(json_obj, "age",
     680         806 :                                     ospf6_lsa_age_current(lsa));
     681         806 :                 json_object_string_add(json_obj, "type",
     682         806 :                                        ospf6_lstype_name(lsa->header->type));
     683         806 :                 json_object_string_add(json_obj, "linkStateId", id);
     684         806 :                 json_object_string_add(json_obj, "advertisingRouter",
     685             :                                        adv_router);
     686         806 :                 json_object_int_add(json_obj, "lsSequenceNumber",
     687         806 :                                     (unsigned long)ntohl(lsa->header->seqnum));
     688         806 :                 json_object_int_add(json_obj, "checksum",
     689         806 :                                     ntohs(lsa->header->checksum));
     690         806 :                 json_object_int_add(json_obj, "length",
     691         806 :                                     ntohs(lsa->header->length));
     692         806 :                 json_object_string_add(json_obj, "duration", duration);
     693             :         } else {
     694           0 :                 vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa),
     695           0 :                         ospf6_lstype_name(lsa->header->type));
     696           0 :                 vty_out(vty, "Link State ID: %s\n", id);
     697           0 :                 vty_out(vty, "Advertising Router: %s\n", adv_router);
     698           0 :                 vty_out(vty, "LS Sequence Number: %#010lx\n",
     699           0 :                         (unsigned long)ntohl(lsa->header->seqnum));
     700           0 :                 vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
     701           0 :                         ntohs(lsa->header->checksum),
     702           0 :                         ntohs(lsa->header->length));
     703           0 :                 vty_out(vty, "Duration: %s\n", duration);
     704             :         }
     705             : 
     706         806 :         handler = ospf6_get_lsa_handler(lsa->header->type);
     707             : 
     708         806 :         if (handler->lh_show != NULL)
     709         806 :                 handler->lh_show(vty, lsa, json_obj, use_json);
     710             :         else {
     711           0 :                 assert(unknown_handler.lh_show != NULL);
     712           0 :                 unknown_handler.lh_show(vty, lsa, json_obj, use_json);
     713             :         }
     714             : 
     715         806 :         if (use_json)
     716         806 :                 json_object_array_add(json_array, json_obj);
     717             :         else
     718           0 :                 vty_out(vty, "\n");
     719         806 : }
     720             : 
     721         712 : struct ospf6_lsa *ospf6_lsa_alloc(size_t lsa_length)
     722             : {
     723         712 :         struct ospf6_lsa *lsa;
     724             : 
     725         712 :         lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
     726         712 :         lsa->header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, lsa_length);
     727             : 
     728         712 :         return lsa;
     729             : }
     730             : 
     731             : /* OSPFv3 LSA creation/deletion function */
     732         589 : struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
     733             : {
     734         589 :         struct ospf6_lsa *lsa = NULL;
     735         589 :         uint16_t lsa_size = 0;
     736             : 
     737             :         /* size of the entire LSA */
     738         589 :         lsa_size = ntohs(header->length); /* XXX vulnerable */
     739             : 
     740         589 :         lsa = ospf6_lsa_alloc(lsa_size);
     741             : 
     742             :         /* copy LSA from original header */
     743         589 :         memcpy(lsa->header, header, lsa_size);
     744             : 
     745             :         /* dump string */
     746         589 :         ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
     747             : 
     748             :         /* calculate birth of this lsa */
     749         589 :         ospf6_lsa_age_set(lsa);
     750             : 
     751         589 :         return lsa;
     752             : }
     753             : 
     754         123 : struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
     755             : {
     756         123 :         struct ospf6_lsa *lsa = NULL;
     757             : 
     758         123 :         lsa = ospf6_lsa_alloc(sizeof(struct ospf6_lsa_header));
     759             : 
     760         123 :         memcpy(lsa->header, header, sizeof(struct ospf6_lsa_header));
     761             : 
     762         123 :         SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
     763             : 
     764             :         /* dump string */
     765         123 :         ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
     766             : 
     767             :         /* calculate birth of this lsa */
     768         123 :         ospf6_lsa_age_set(lsa);
     769             : 
     770         123 :         return lsa;
     771             : }
     772             : 
     773         712 : void ospf6_lsa_delete(struct ospf6_lsa *lsa)
     774             : {
     775         712 :         assert(lsa->lock == 0);
     776             : 
     777             :         /* cancel threads */
     778         712 :         THREAD_OFF(lsa->expire);
     779         712 :         THREAD_OFF(lsa->refresh);
     780             : 
     781             :         /* do free */
     782         712 :         XFREE(MTYPE_OSPF6_LSA_HEADER, lsa->header);
     783         712 :         XFREE(MTYPE_OSPF6_LSA, lsa);
     784         712 : }
     785             : 
     786         365 : struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa)
     787             : {
     788         365 :         struct ospf6_lsa *copy = NULL;
     789             : 
     790         365 :         ospf6_lsa_age_current(lsa);
     791         365 :         if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
     792          25 :                 copy = ospf6_lsa_create_headeronly(lsa->header);
     793             :         else
     794         340 :                 copy = ospf6_lsa_create(lsa->header);
     795         365 :         assert(copy->lock == 0);
     796             : 
     797         365 :         copy->birth = lsa->birth;
     798         365 :         copy->originated = lsa->originated;
     799         365 :         copy->received = lsa->received;
     800         365 :         copy->installed = lsa->installed;
     801         365 :         copy->lsdb = lsa->lsdb;
     802         365 :         copy->rn = NULL;
     803             : 
     804         365 :         return copy;
     805             : }
     806             : 
     807             : /* increment reference counter of struct ospf6_lsa */
     808        2745 : struct ospf6_lsa *ospf6_lsa_lock(struct ospf6_lsa *lsa)
     809             : {
     810        2745 :         lsa->lock++;
     811        2745 :         return lsa;
     812             : }
     813             : 
     814             : /* decrement reference counter of struct ospf6_lsa */
     815        2745 : struct ospf6_lsa *ospf6_lsa_unlock(struct ospf6_lsa *lsa)
     816             : {
     817             :         /* decrement reference counter */
     818        2745 :         assert(lsa->lock > 0);
     819        2745 :         lsa->lock--;
     820             : 
     821        2745 :         if (lsa->lock != 0)
     822             :                 return lsa;
     823             : 
     824         477 :         ospf6_lsa_delete(lsa);
     825         477 :         return NULL;
     826             : }
     827             : 
     828             : 
     829             : /* ospf6 lsa expiry */
     830           8 : void ospf6_lsa_expire(struct thread *thread)
     831             : {
     832           8 :         struct ospf6_lsa *lsa;
     833           8 :         struct ospf6 *ospf6;
     834             : 
     835           8 :         lsa = (struct ospf6_lsa *)THREAD_ARG(thread);
     836             : 
     837           8 :         assert(lsa && lsa->header);
     838           8 :         assert(OSPF6_LSA_IS_MAXAGE(lsa));
     839           8 :         assert(!lsa->refresh);
     840             : 
     841           8 :         lsa->expire = (struct thread *)NULL;
     842             : 
     843          16 :         if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) {
     844           0 :                 zlog_debug("LSA Expire:");
     845           0 :                 ospf6_lsa_header_print(lsa);
     846             :         }
     847             : 
     848           8 :         if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
     849             :                 return; /* dbexchange will do something ... */
     850           8 :         ospf6 = ospf6_get_by_lsdb(lsa);
     851           8 :         assert(ospf6);
     852             : 
     853             :         /* reinstall lsa */
     854           8 :         ospf6_install_lsa(lsa);
     855             : 
     856             :         /* reflood lsa */
     857           8 :         ospf6_flood(NULL, lsa);
     858             : 
     859             :         /* schedule maxage remover */
     860           8 :         ospf6_maxage_remove(ospf6);
     861             : }
     862             : 
     863           0 : void ospf6_lsa_refresh(struct thread *thread)
     864             : {
     865           0 :         struct ospf6_lsa *old, *self, *new;
     866           0 :         struct ospf6_lsdb *lsdb_self;
     867             : 
     868           0 :         old = (struct ospf6_lsa *)THREAD_ARG(thread);
     869           0 :         assert(old && old->header);
     870             : 
     871           0 :         old->refresh = (struct thread *)NULL;
     872             : 
     873           0 :         lsdb_self = ospf6_get_scoped_lsdb_self(old);
     874           0 :         self = ospf6_lsdb_lookup(old->header->type, old->header->id,
     875           0 :                                  old->header->adv_router, lsdb_self);
     876           0 :         if (self == NULL) {
     877           0 :                 if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type))
     878           0 :                         zlog_debug("Refresh: could not find self LSA, flush %s",
     879             :                                    old->name);
     880           0 :                 ospf6_lsa_premature_aging(old);
     881           0 :                 return;
     882             :         }
     883             : 
     884             :         /* Reset age, increment LS sequence number. */
     885           0 :         self->header->age = htons(0);
     886           0 :         self->header->seqnum =
     887           0 :                 ospf6_new_ls_seqnum(self->header->type, self->header->id,
     888             :                                     self->header->adv_router, old->lsdb);
     889           0 :         ospf6_lsa_checksum(self->header);
     890             : 
     891           0 :         new = ospf6_lsa_create(self->header);
     892           0 :         new->lsdb = old->lsdb;
     893           0 :         thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME,
     894             :                          &new->refresh);
     895             : 
     896             :         /* store it in the LSDB for self-originated LSAs */
     897           0 :         ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self);
     898             : 
     899           0 :         if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) {
     900           0 :                 zlog_debug("LSA Refresh:");
     901           0 :                 ospf6_lsa_header_print(new);
     902             :         }
     903             : 
     904           0 :         ospf6_install_lsa(new);
     905           0 :         ospf6_flood(NULL, new);
     906             : }
     907             : 
     908           8 : void ospf6_flush_self_originated_lsas_now(struct ospf6 *ospf6)
     909             : {
     910           8 :         struct listnode *node, *nnode;
     911           8 :         struct ospf6_area *oa;
     912           8 :         struct ospf6_lsa *lsa;
     913           8 :         const struct route_node *end = NULL;
     914           8 :         uint32_t type, adv_router;
     915           8 :         struct ospf6_interface *oi;
     916             : 
     917           8 :         ospf6->inst_shutdown = 1;
     918             : 
     919          24 :         for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
     920           8 :                 end = ospf6_lsdb_head(oa->lsdb_self, 0, 0, ospf6->router_id,
     921             :                                       &lsa);
     922          16 :                 while (lsa) {
     923             :                         /* RFC 2328 (14.1):  Set MAXAGE */
     924           8 :                         lsa->header->age = htons(OSPF_LSA_MAXAGE);
     925             :                         /* Flood MAXAGE LSA*/
     926           8 :                         ospf6_flood(NULL, lsa);
     927             : 
     928           8 :                         lsa = ospf6_lsdb_next(end, lsa);
     929             :                 }
     930             : 
     931          26 :                 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
     932             :                         /* virtual links have no interface LSDBs */
     933          10 :                         if (!oi->lsdb_self)
     934           0 :                                 continue;
     935             : 
     936          10 :                         end = ospf6_lsdb_head(oi->lsdb_self, 0, 0,
     937             :                                               ospf6->router_id, &lsa);
     938          15 :                         while (lsa) {
     939             :                                 /* RFC 2328 (14.1):  Set MAXAGE */
     940           5 :                                 lsa->header->age = htons(OSPF_LSA_MAXAGE);
     941             :                                 /* Flood MAXAGE LSA*/
     942           5 :                                 ospf6_flood(NULL, lsa);
     943             : 
     944           5 :                                 lsa = ospf6_lsdb_next(end, lsa);
     945             :                         }
     946             :                 }
     947             :         }
     948             : 
     949           8 :         type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
     950           8 :         adv_router = ospf6->router_id;
     951           8 :         for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
     952             :                 /* RFC 2328 (14.1):  Set MAXAGE */
     953           0 :                 lsa->header->age = htons(OSPF_LSA_MAXAGE);
     954           0 :                 ospf6_flood(NULL, lsa);
     955             :         }
     956           8 : }
     957             : 
     958             : /* Fletcher Checksum -- Refer to RFC1008. */
     959             : 
     960             : /* All the offsets are zero-based. The offsets in the RFC1008 are
     961             :    one-based. */
     962          38 : unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
     963             : {
     964          38 :         uint8_t *buffer = (uint8_t *)&lsa_header->type;
     965          38 :         int type_offset =
     966          38 :                 buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
     967             : 
     968             :         /* Skip the AGE field */
     969          38 :         uint16_t len = ntohs(lsa_header->length) - type_offset;
     970             : 
     971             :         /* Checksum offset starts from "type" field, not the beginning of the
     972             :            lsa_header struct. The offset is 14, rather than 16. */
     973          38 :         int checksum_offset = (uint8_t *)&lsa_header->checksum - buffer;
     974             : 
     975          38 :         return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
     976             : }
     977             : 
     978         211 : int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
     979             : {
     980         211 :         uint8_t *buffer = (uint8_t *)&lsa_header->type;
     981         211 :         int type_offset =
     982         211 :                 buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
     983             : 
     984             :         /* Skip the AGE field */
     985         211 :         uint16_t len = ntohs(lsa_header->length) - type_offset;
     986             : 
     987         211 :         return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
     988         211 :                 == 0);
     989             : }
     990             : 
     991           4 : void ospf6_lsa_init(void)
     992             : {
     993           4 :         ospf6_install_lsa_handler(&unknown_handler);
     994           4 : }
     995             : 
     996           4 : void ospf6_lsa_terminate(void)
     997             : {
     998           4 : }
     999             : 
    1000           0 : static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
    1001             : {
    1002           0 :         static char buf[64];
    1003           0 :         unsigned int i;
    1004           0 :         unsigned int size = strlen(h->lh_name);
    1005             : 
    1006           0 :         if (!strcmp(h->lh_name, "unknown")
    1007           0 :             && h->lh_type != OSPF6_LSTYPE_UNKNOWN) {
    1008           0 :                 snprintf(buf, sizeof(buf), "%#04hx", h->lh_type);
    1009           0 :                 return buf;
    1010             :         }
    1011             : 
    1012           0 :         for (i = 0; i < MIN(size, sizeof(buf)); i++) {
    1013           0 :                 if (!islower((unsigned char)h->lh_name[i]))
    1014           0 :                         buf[i] = tolower((unsigned char)h->lh_name[i]);
    1015             :                 else
    1016           0 :                         buf[i] = h->lh_name[i];
    1017             :         }
    1018           0 :         buf[size] = '\0';
    1019           0 :         return buf;
    1020             : }
    1021             : 
    1022           0 : void ospf6_lsa_debug_set_all(bool val)
    1023             : {
    1024           0 :         unsigned int i;
    1025           0 :         struct ospf6_lsa_handler *handler = NULL;
    1026             : 
    1027           0 :         for (i = 0; i < array_size(lsa_handlers); i++) {
    1028           0 :                 handler = lsa_handlers[i];
    1029           0 :                 if (handler == NULL)
    1030           0 :                         continue;
    1031           0 :                 if (val)
    1032           0 :                         SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL);
    1033             :                 else
    1034           0 :                         UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL);
    1035             :         }
    1036           0 : }
    1037             : 
    1038           0 : DEFPY (debug_ospf6_lsa_all,
    1039             :        debug_ospf6_lsa_all_cmd,
    1040             :        "[no$no] debug ospf6 lsa all",
    1041             :        NO_STR
    1042             :        DEBUG_STR
    1043             :        OSPF6_STR
    1044             :        "Debug Link State Advertisements (LSAs)\n"
    1045             :        "Display for all types of LSAs\n")
    1046             : {
    1047           0 :         ospf6_lsa_debug_set_all(!no);
    1048           0 :         return CMD_SUCCESS;
    1049             : }
    1050             : 
    1051           0 : DEFPY (debug_ospf6_lsa_aggregation,
    1052             :        debug_ospf6_lsa_aggregation_cmd,
    1053             :        "[no] debug ospf6 lsa aggregation",
    1054             :        NO_STR
    1055             :        DEBUG_STR
    1056             :        OSPF6_STR
    1057             :        "Debug Link State Advertisements (LSAs)\n"
    1058             :        "External LSA Aggregation\n")
    1059             : {
    1060             : 
    1061           0 :         struct ospf6_lsa_handler *handler;
    1062             : 
    1063           0 :         handler = ospf6_get_lsa_handler(OSPF6_LSTYPE_AS_EXTERNAL);
    1064           0 :         if (handler == NULL)
    1065             :                 return CMD_WARNING_CONFIG_FAILED;
    1066             : 
    1067           0 :         if (no)
    1068           0 :                 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR);
    1069             :         else
    1070           0 :                 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR);
    1071             : 
    1072           0 :         return CMD_SUCCESS;
    1073             : }
    1074             : 
    1075           0 : DEFUN (debug_ospf6_lsa_type,
    1076             :        debug_ospf6_lsa_hex_cmd,
    1077             :        "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
    1078             :        DEBUG_STR
    1079             :        OSPF6_STR
    1080             :        "Debug Link State Advertisements (LSAs)\n"
    1081             :        "Display Router LSAs\n"
    1082             :        "Display Network LSAs\n"
    1083             :        "Display Inter-Area-Prefix LSAs\n"
    1084             :        "Display Inter-Router LSAs\n"
    1085             :        "Display As-External LSAs\n"
    1086             :        "Display NSSA LSAs\n"
    1087             :        "Display Link LSAs\n"
    1088             :        "Display Intra-Area-Prefix LSAs\n"
    1089             :        "Display LSAs of unknown origin\n"
    1090             :        "Display details of LSAs\n"
    1091             :        "Dump LSAs\n"
    1092             :        "Display LSA's internal information\n")
    1093             : {
    1094           0 :         int idx_lsa = 3;
    1095           0 :         int idx_type = 4;
    1096           0 :         unsigned int i;
    1097           0 :         struct ospf6_lsa_handler *handler = NULL;
    1098             : 
    1099           0 :         for (i = 0; i < array_size(lsa_handlers); i++) {
    1100           0 :                 handler = lsa_handlers[i];
    1101           0 :                 if (handler == NULL)
    1102           0 :                         continue;
    1103           0 :                 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
    1104           0 :                             strlen(argv[idx_lsa]->arg))
    1105             :                     == 0)
    1106             :                         break;
    1107           0 :                 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
    1108             :                         break;
    1109             :                 handler = NULL;
    1110             :         }
    1111             : 
    1112           0 :         if (handler == NULL)
    1113           0 :                 handler = &unknown_handler;
    1114             : 
    1115           0 :         if (argc == 5) {
    1116           0 :                 if (strmatch(argv[idx_type]->text, "originate"))
    1117           0 :                         SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE);
    1118           0 :                 else if (strmatch(argv[idx_type]->text, "examine"))
    1119           0 :                         SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
    1120           0 :                 else if (strmatch(argv[idx_type]->text, "flooding"))
    1121           0 :                         SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
    1122             :         } else
    1123           0 :                 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
    1124             : 
    1125           0 :         return CMD_SUCCESS;
    1126             : }
    1127             : 
    1128           0 : DEFUN (no_debug_ospf6_lsa_type,
    1129             :        no_debug_ospf6_lsa_hex_cmd,
    1130             :        "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
    1131             :        NO_STR
    1132             :        DEBUG_STR
    1133             :        OSPF6_STR
    1134             :        "Debug Link State Advertisements (LSAs)\n"
    1135             :        "Display Router LSAs\n"
    1136             :        "Display Network LSAs\n"
    1137             :        "Display Inter-Area-Prefix LSAs\n"
    1138             :        "Display Inter-Router LSAs\n"
    1139             :        "Display As-External LSAs\n"
    1140             :        "Display NSSA LSAs\n"
    1141             :        "Display Link LSAs\n"
    1142             :        "Display Intra-Area-Prefix LSAs\n"
    1143             :        "Display LSAs of unknown origin\n"
    1144             :        "Display details of LSAs\n"
    1145             :        "Dump LSAs\n"
    1146             :        "Display LSA's internal information\n")
    1147             : {
    1148           0 :         int idx_lsa = 4;
    1149           0 :         int idx_type = 5;
    1150           0 :         unsigned int i;
    1151           0 :         struct ospf6_lsa_handler *handler = NULL;
    1152             : 
    1153           0 :         for (i = 0; i < array_size(lsa_handlers); i++) {
    1154           0 :                 handler = lsa_handlers[i];
    1155           0 :                 if (handler == NULL)
    1156           0 :                         continue;
    1157           0 :                 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
    1158           0 :                             strlen(argv[idx_lsa]->arg))
    1159             :                     == 0)
    1160             :                         break;
    1161           0 :                 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
    1162             :                         break;
    1163             :         }
    1164             : 
    1165           0 :         if (handler == NULL)
    1166             :                 return CMD_SUCCESS;
    1167             : 
    1168           0 :         if (argc == 6) {
    1169           0 :                 if (strmatch(argv[idx_type]->text, "originate"))
    1170           0 :                         UNSET_FLAG(handler->lh_debug,
    1171             :                                    OSPF6_LSA_DEBUG_ORIGINATE);
    1172           0 :                 if (strmatch(argv[idx_type]->text, "examine"))
    1173           0 :                         UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
    1174           0 :                 if (strmatch(argv[idx_type]->text, "flooding"))
    1175           0 :                         UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
    1176             :         } else
    1177           0 :                 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
    1178             : 
    1179             :         return CMD_SUCCESS;
    1180             : }
    1181             : 
    1182           4 : void install_element_ospf6_debug_lsa(void)
    1183             : {
    1184           4 :         install_element(ENABLE_NODE, &debug_ospf6_lsa_all_cmd);
    1185           4 :         install_element(CONFIG_NODE, &debug_ospf6_lsa_all_cmd);
    1186           4 :         install_element(ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
    1187           4 :         install_element(ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
    1188           4 :         install_element(CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
    1189           4 :         install_element(CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
    1190             : 
    1191           4 :         install_element(ENABLE_NODE, &debug_ospf6_lsa_aggregation_cmd);
    1192           4 :         install_element(CONFIG_NODE, &debug_ospf6_lsa_aggregation_cmd);
    1193           4 : }
    1194             : 
    1195           0 : int config_write_ospf6_debug_lsa(struct vty *vty)
    1196             : {
    1197           0 :         unsigned int i;
    1198           0 :         const struct ospf6_lsa_handler *handler;
    1199           0 :         bool debug_all = true;
    1200             : 
    1201           0 :         for (i = 0; i < array_size(lsa_handlers); i++) {
    1202           0 :                 handler = lsa_handlers[i];
    1203           0 :                 if (handler == NULL)
    1204           0 :                         continue;
    1205           0 :                 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ALL)
    1206             :                     < OSPF6_LSA_DEBUG_ALL) {
    1207             :                         debug_all = false;
    1208             :                         break;
    1209             :                 }
    1210             :         }
    1211             : 
    1212           0 :         if (debug_all) {
    1213           0 :                 vty_out(vty, "debug ospf6 lsa all\n");
    1214           0 :                 return 0;
    1215             :         }
    1216             : 
    1217           0 :         for (i = 0; i < array_size(lsa_handlers); i++) {
    1218           0 :                 handler = lsa_handlers[i];
    1219           0 :                 if (handler == NULL)
    1220           0 :                         continue;
    1221           0 :                 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG))
    1222           0 :                         vty_out(vty, "debug ospf6 lsa %s\n",
    1223             :                                 ospf6_lsa_handler_name(handler));
    1224           0 :                 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE))
    1225           0 :                         vty_out(vty, "debug ospf6 lsa %s originate\n",
    1226             :                                 ospf6_lsa_handler_name(handler));
    1227           0 :                 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN))
    1228           0 :                         vty_out(vty, "debug ospf6 lsa %s examine\n",
    1229             :                                 ospf6_lsa_handler_name(handler));
    1230           0 :                 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD))
    1231           0 :                         vty_out(vty, "debug ospf6 lsa %s flooding\n",
    1232             :                                 ospf6_lsa_handler_name(handler));
    1233           0 :                 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_AGGR))
    1234           0 :                         vty_out(vty, "debug ospf6 lsa aggregation\n");
    1235             :         }
    1236             : 
    1237             :         return 0;
    1238             : }

Generated by: LCOV version v1.16-topotato