back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_auth_trailer.c (source / functions) Hit Total Coverage
Test: test_ospf6_vlink.py::VirtualLinkBasic Lines: 54 482 11.2 %
Date: 2023-02-16 02:06:43 Functions: 7 24 29.2 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2021 Abhinay Ramesh
       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             : #include "config.h"
      23             : #include "memory.h"
      24             : #include "ospf6d.h"
      25             : #include "vty.h"
      26             : #include "command.h"
      27             : #include "md5.h"
      28             : #include "sha256.h"
      29             : #include "lib/zlog.h"
      30             : #include "ospf6_message.h"
      31             : #include "ospf6_interface.h"
      32             : #include "ospf6_neighbor.h"
      33             : #include "ospf6_proto.h"
      34             : #include "ospf6_top.h"
      35             : #include "ospf6_area.h"
      36             : #include "ospf6_auth_trailer.h"
      37             : #include "ospf6_route.h"
      38             : #include "ospf6_zebra.h"
      39             : #include "lib/keychain.h"
      40             : 
      41             : unsigned char conf_debug_ospf6_auth[2];
      42          24 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH_XOR, "OSPF6 auth hash xor");
      43             : 
      44             : /*Apad is the hexadecimal value 0x878FE1F3. */
      45             : const uint8_t ospf6_hash_apad_max[KEYCHAIN_MAX_HASH_SIZE] = {
      46             :         0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1,
      47             :         0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f,
      48             :         0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87,
      49             :         0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3,
      50             :         0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1,
      51             :         0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3,
      52             : };
      53             : 
      54             : const uint8_t ospf6_hash_ipad_max[KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE] = {
      55             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      56             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      57             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      58             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      59             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      60             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      61             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      62             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      63             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      64             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      65             :         0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
      66             : };
      67             : 
      68             : const uint8_t ospf6_hash_opad_max[KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE] = {
      69             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      70             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      71             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      72             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      73             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      74             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      75             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      76             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      77             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      78             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      79             :         0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
      80             : };
      81             : 
      82           0 : void ospf6_auth_hdr_dump_send(struct ospf6_header *ospfh, uint16_t length)
      83             : {
      84           0 :         struct ospf6_auth_hdr *ospf6_at_hdr;
      85           0 :         uint16_t at_len, oh_len, at_hdr_len, hash_len;
      86           0 :         unsigned char temp[KEYCHAIN_MAX_HASH_SIZE + 1];
      87             : 
      88           0 :         oh_len = htons(ospfh->length);
      89           0 :         at_len = length - oh_len;
      90           0 :         if (at_len > 0) {
      91           0 :                 ospf6_at_hdr = (struct ospf6_auth_hdr *)
      92             :                                         ((uint8_t *)ospfh + oh_len);
      93           0 :                 at_hdr_len = htons(ospf6_at_hdr->length);
      94           0 :                 hash_len = at_hdr_len - OSPF6_AUTH_HDR_MIN_SIZE;
      95           0 :                 memcpy(temp, ospf6_at_hdr->data, hash_len);
      96           0 :                 temp[hash_len] = '\0';
      97           0 :                 zlog_debug("OSPF6 Authentication Trailer");
      98           0 :                 zlog_debug("  Type %d", htons(ospf6_at_hdr->type));
      99           0 :                 zlog_debug("  Length %d", at_hdr_len);
     100           0 :                 zlog_debug("  Reserved %d", ospf6_at_hdr->reserved);
     101           0 :                 zlog_debug("  SA ID %d", htons(ospf6_at_hdr->id));
     102           0 :                 zlog_debug("  seqnum high 0x%08x",
     103             :                            htonl(ospf6_at_hdr->seqnum_h));
     104           0 :                 zlog_debug("  seqnum high 0x%08x",
     105             :                            htonl(ospf6_at_hdr->seqnum_l));
     106           0 :                 zlog_debug("  Data %s", temp);
     107             :         }
     108           0 : }
     109             : 
     110           0 : void ospf6_auth_hdr_dump_recv(struct ospf6_header *ospfh, uint16_t length,
     111             :                               unsigned int lls_len)
     112             : {
     113           0 :         struct ospf6_auth_hdr *ospf6_at_hdr;
     114           0 :         uint16_t at_len, oh_len, at_hdr_len, hash_len;
     115           0 :         unsigned char temp[KEYCHAIN_MAX_HASH_SIZE + 1];
     116             : 
     117           0 :         oh_len = ntohs(ospfh->length);
     118           0 :         at_len = length - (oh_len + lls_len);
     119           0 :         if (at_len > 0) {
     120           0 :                 ospf6_at_hdr =
     121           0 :                         (struct ospf6_auth_hdr *)((uint8_t *)ospfh + oh_len);
     122           0 :                 at_hdr_len = ntohs(ospf6_at_hdr->length);
     123           0 :                 hash_len = at_hdr_len - (uint16_t)OSPF6_AUTH_HDR_MIN_SIZE;
     124           0 :                 if (hash_len > KEYCHAIN_MAX_HASH_SIZE) {
     125           0 :                         zlog_debug(
     126             :                                 "Specified value for hash_len %u is greater than expected %u",
     127             :                                 hash_len, KEYCHAIN_MAX_HASH_SIZE);
     128           0 :                         return;
     129             :                 }
     130           0 :                 memcpy(temp, ospf6_at_hdr->data, hash_len);
     131           0 :                 temp[hash_len] = '\0';
     132           0 :                 zlog_debug("OSPF6 Authentication Trailer");
     133           0 :                 zlog_debug("  Type %d", ntohs(ospf6_at_hdr->type));
     134           0 :                 zlog_debug("  Length %d", at_hdr_len);
     135           0 :                 zlog_debug("  Reserved %d", ospf6_at_hdr->reserved);
     136           0 :                 zlog_debug("  SA ID %d", ntohs(ospf6_at_hdr->id));
     137           0 :                 zlog_debug("  seqnum high 0x%08x",
     138             :                            ntohl(ospf6_at_hdr->seqnum_h));
     139           0 :                 zlog_debug("  seqnum high 0x%08x",
     140             :                            ntohl(ospf6_at_hdr->seqnum_l));
     141           0 :                 zlog_debug("  Data %s", temp);
     142             :         }
     143             : }
     144             : 
     145           0 : unsigned char *ospf6_hash_message_xor(unsigned char *mes1,
     146             :                                       unsigned char *mes2,
     147             :                                       uint32_t len)
     148             : {
     149           0 :         unsigned char *result;
     150           0 :         uint32_t i;
     151             : 
     152           0 :         result = XCALLOC(MTYPE_OSPF6_AUTH_HASH_XOR, len);
     153             : 
     154           0 :         for (i = 0; i < len; i++)
     155           0 :                 result[i] = mes1[i] ^ mes2[i];
     156             : 
     157           0 :         return result;
     158             : }
     159             : 
     160           0 : static void md5_digest(unsigned char *mes, uint32_t len,
     161             :                        unsigned char *digest)
     162             : {
     163             : #ifdef CRYPTO_OPENSSL
     164             :         unsigned int size = KEYCHAIN_MD5_HASH_SIZE;
     165             :         EVP_MD_CTX *ctx;
     166             : #elif CRYPTO_INTERNAL
     167           0 :         MD5_CTX ctx;
     168             : #endif
     169             : 
     170             : #ifdef CRYPTO_OPENSSL
     171             :         ctx = EVP_MD_CTX_new();
     172             :         EVP_DigestInit(ctx, EVP_md5());
     173             :         EVP_DigestUpdate(ctx, mes, len);
     174             :         EVP_DigestFinal(ctx, digest, &size);
     175             :         EVP_MD_CTX_free(ctx);
     176             : #elif CRYPTO_INTERNAL
     177           0 :         memset(&ctx, 0, sizeof(ctx));
     178           0 :         MD5Init(&ctx);
     179           0 :         MD5Update(&ctx, mes, len);
     180           0 :         MD5Final(digest, &ctx);
     181             : #endif
     182           0 : }
     183             : 
     184           0 : static void sha256_digest(unsigned char *mes, uint32_t len,
     185             :                           unsigned char *digest)
     186             : {
     187             : #ifdef CRYPTO_OPENSSL
     188             :         unsigned int size = KEYCHAIN_HMAC_SHA256_HASH_SIZE;
     189             :         EVP_MD_CTX *ctx;
     190             : #elif CRYPTO_INTERNAL
     191           0 :         SHA256_CTX ctx;
     192             : #endif
     193             : 
     194             : #ifdef CRYPTO_OPENSSL
     195             :         ctx = EVP_MD_CTX_new();
     196             :         EVP_DigestInit(ctx, EVP_sha256());
     197             :         EVP_DigestUpdate(ctx, mes, len);
     198             :         EVP_DigestFinal(ctx, digest, &size);
     199             :         EVP_MD_CTX_free(ctx);
     200             : #elif CRYPTO_INTERNAL
     201           0 :         memset(&ctx, 0, sizeof(ctx));
     202           0 :         SHA256_Init(&ctx);
     203           0 :         SHA256_Update(&ctx, mes, len);
     204           0 :         SHA256_Final(digest, &ctx);
     205             : #endif
     206           0 : }
     207             : 
     208             : #ifdef CRYPTO_OPENSSL
     209             : static void sha1_digest(unsigned char *mes, uint32_t len,
     210             :                         unsigned char *digest)
     211             : {
     212             :         EVP_MD_CTX *ctx;
     213             :         unsigned int size = KEYCHAIN_HMAC_SHA1_HASH_SIZE;
     214             : 
     215             :         ctx = EVP_MD_CTX_new();
     216             :         EVP_DigestInit(ctx, EVP_sha1());
     217             :         EVP_DigestUpdate(ctx, mes, len);
     218             :         EVP_DigestFinal(ctx, digest, &size);
     219             :         EVP_MD_CTX_free(ctx);
     220             : }
     221             : 
     222             : static void sha384_digest(unsigned char *mes, uint32_t len,
     223             :                           unsigned char *digest)
     224             : {
     225             :         EVP_MD_CTX *ctx;
     226             :         unsigned int size = KEYCHAIN_HMAC_SHA384_HASH_SIZE;
     227             : 
     228             :         ctx = EVP_MD_CTX_new();
     229             :         EVP_DigestInit(ctx, EVP_sha384());
     230             :         EVP_DigestUpdate(ctx, mes, len);
     231             :         EVP_DigestFinal(ctx, digest, &size);
     232             :         EVP_MD_CTX_free(ctx);
     233             : }
     234             : 
     235             : static void sha512_digest(unsigned char *mes, uint32_t len,
     236             :                           unsigned char *digest)
     237             : {
     238             :         EVP_MD_CTX *ctx;
     239             :         unsigned int size = KEYCHAIN_HMAC_SHA512_HASH_SIZE;
     240             : 
     241             :         ctx = EVP_MD_CTX_new();
     242             :         EVP_DigestInit(ctx, EVP_sha512());
     243             :         EVP_DigestUpdate(ctx, mes, len);
     244             :         EVP_DigestFinal(ctx, digest, &size);
     245             :         EVP_MD_CTX_free(ctx);
     246             : }
     247             : #endif /* CRYPTO_OPENSSL */
     248             : 
     249           0 : static void ospf6_hash_hmac_sha_digest(enum keychain_hash_algo key,
     250             :                                        unsigned char *mes, uint32_t len,
     251             :                                        unsigned char *digest)
     252             : {
     253           0 :         if ((key < KEYCHAIN_ALGO_NULL) || (key > KEYCHAIN_ALGO_MAX))
     254             :                 return;
     255             : 
     256           0 :         switch (key) {
     257           0 :         case KEYCHAIN_ALGO_MD5:
     258           0 :                 md5_digest(mes, len, digest);
     259           0 :                 break;
     260             :         case KEYCHAIN_ALGO_HMAC_SHA1:
     261             : #ifdef CRYPTO_OPENSSL
     262             :                 sha1_digest(mes, len, digest);
     263             : #endif
     264             :                 break;
     265           0 :         case KEYCHAIN_ALGO_HMAC_SHA256:
     266           0 :                 sha256_digest(mes, len, digest);
     267           0 :                 break;
     268             :         case KEYCHAIN_ALGO_HMAC_SHA384:
     269             : #ifdef CRYPTO_OPENSSL
     270             :                 sha384_digest(mes, len, digest);
     271             : #endif
     272             :                 break;
     273             :         case KEYCHAIN_ALGO_HMAC_SHA512:
     274             : #ifdef CRYPTO_OPENSSL
     275             :                 sha512_digest(mes, len, digest);
     276             : #endif
     277             :                 break;
     278             :         case KEYCHAIN_ALGO_NULL:
     279             :         case KEYCHAIN_ALGO_MAX:
     280             :         default:
     281             :                 /* no action */
     282             :                 break;
     283             :         }
     284             : }
     285             : 
     286           0 : uint16_t ospf6_auth_len_get(struct ospf6_interface *oi)
     287             : {
     288           0 :         uint16_t at_len = 0;
     289           0 :         char *keychain_name = NULL;
     290           0 :         struct keychain *keychain = NULL;
     291           0 :         struct key *key = NULL;
     292             : 
     293           0 :         if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
     294           0 :                 if (CHECK_FLAG(oi->at_data.flags,
     295             :                                OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {
     296           0 :                         at_len = OSPF6_AUTH_HDR_MIN_SIZE
     297           0 :                                  + keychain_get_hash_len(oi->at_data.hash_algo);
     298             :                 } else {
     299           0 :                         keychain_name = oi->at_data.keychain;
     300           0 :                         keychain = keychain_lookup(keychain_name);
     301           0 :                         if (keychain) {
     302           0 :                                 key = key_lookup_for_send(keychain);
     303           0 :                                 if (key && key->string
     304           0 :                                     && key->hash_algo != KEYCHAIN_ALGO_NULL) {
     305           0 :                                         at_len = OSPF6_AUTH_HDR_MIN_SIZE
     306           0 :                                                  + keychain_get_hash_len(
     307             :                                                            key->hash_algo);
     308             :                                 }
     309             :                         }
     310             :                 }
     311           0 :         } else if (CHECK_FLAG(oi->at_data.flags,
     312             :                               OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
     313           0 :                 at_len = OSPF6_AUTH_HDR_MIN_SIZE
     314           0 :                          + keychain_get_hash_len(oi->at_data.hash_algo);
     315             :         }
     316             : 
     317           0 :         return at_len;
     318             : }
     319             : 
     320         429 : int ospf6_auth_validate_pkt(struct ospf6_interface *oi, unsigned int *pkt_len,
     321             :                             struct ospf6_header *oh, unsigned int *at_len,
     322             :                             unsigned int *lls_block_len)
     323             : {
     324         429 :         struct ospf6_hello *hello = NULL;
     325         429 :         struct ospf6_dbdesc *dbdesc = NULL;
     326         429 :         struct ospf6_neighbor *on = NULL;
     327         429 :         struct ospf6_auth_hdr ospf6_auth_info;
     328         429 :         uint16_t hdr_len = 0;
     329         429 :         uint32_t oh_seqnum_h = 0;
     330         429 :         uint32_t oh_seqnum_l = 0;
     331         429 :         bool auth_present = false;
     332         429 :         bool lls_present = false;
     333         429 :         struct ospf6_lls_hdr *lls_hdr = NULL;
     334             : 
     335         429 :         on = ospf6_neighbor_lookup(oh->router_id, oi);
     336         429 :         hdr_len = ntohs(oh->length);
     337         429 :         if (*pkt_len < hdr_len) {
     338           0 :                 if (IS_OSPF6_DEBUG_AUTH_RX)
     339           0 :                         zlog_err("RECV[%pOI] Received incomplete %s packet",
     340             :                                  oi, ospf6_message_type(oh->type));
     341           0 :                 return OSPF6_AUTH_VALIDATE_FAILURE;
     342         429 :         } else if (*pkt_len == hdr_len) {
     343         429 :                 if (oi->at_data.flags != 0)
     344             :                         return OSPF6_AUTH_VALIDATE_FAILURE;
     345             :                 /* No auth info to be considered.
     346             :                  */
     347             :                 return OSPF6_AUTH_PROCESS_NORMAL;
     348             :         }
     349             : 
     350           0 :         switch (oh->type) {
     351           0 :         case OSPF6_MESSAGE_TYPE_HELLO:
     352           0 :                 hello = (struct ospf6_hello *)((uint8_t *)oh
     353             :                                                + sizeof(struct ospf6_header));
     354           0 :                 if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_L))
     355           0 :                         lls_present = true;
     356             : 
     357           0 :                 if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT))
     358           0 :                         auth_present = true;
     359             :                 break;
     360           0 :         case OSPF6_MESSAGE_TYPE_DBDESC:
     361           0 :                 dbdesc = (struct ospf6_dbdesc *)((uint8_t *)oh
     362             :                                                  + sizeof(struct ospf6_header));
     363           0 :                 if (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_L))
     364           0 :                         lls_present = true;
     365             : 
     366           0 :                 if (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT))
     367           0 :                         auth_present = true;
     368             :                 break;
     369           0 :         case OSPF6_MESSAGE_TYPE_LSREQ:
     370             :         case OSPF6_MESSAGE_TYPE_LSUPDATE:
     371             :         case OSPF6_MESSAGE_TYPE_LSACK:
     372           0 :                 if (on) {
     373           0 :                         lls_present = on->lls_present;
     374           0 :                         auth_present = on->auth_present;
     375             :                 }
     376             :                 break;
     377           0 :         default:
     378           0 :                 if (IS_OSPF6_DEBUG_AUTH_RX)
     379           0 :                         zlog_err("RECV[%pOI] : Wrong packet type %d",
     380             :                                  oi, oh->type);
     381             :                 return OSPF6_AUTH_VALIDATE_FAILURE;
     382             :         }
     383             : 
     384           0 :         if ((oh->type == OSPF6_MESSAGE_TYPE_HELLO)
     385           0 :             || (oh->type == OSPF6_MESSAGE_TYPE_DBDESC)) {
     386           0 :                 if (on) {
     387           0 :                         on->auth_present = auth_present;
     388           0 :                         on->lls_present = lls_present;
     389             :                 }
     390             :         }
     391             : 
     392           0 :         if ((!auth_present && (oi->at_data.flags != 0))
     393           0 :             || (auth_present && (oi->at_data.flags == 0))) {
     394           0 :                 if (IS_OSPF6_DEBUG_AUTH_RX)
     395           0 :                         zlog_err("RECV[%pOI] : Auth option miss-match in %s pkt",
     396             :                                  oi, ospf6_message_type(oh->type));
     397           0 :                 return OSPF6_AUTH_VALIDATE_FAILURE;
     398             :         }
     399             : 
     400           0 :         if (lls_present) {
     401           0 :                 lls_hdr = (struct ospf6_lls_hdr *)(oh + hdr_len);
     402           0 :                 *lls_block_len = ntohs(lls_hdr->length) * 4;
     403             :         }
     404             : 
     405           0 :         if (*lls_block_len > (*pkt_len - hdr_len)) {
     406           0 :                 if (IS_OSPF6_DEBUG_AUTH_RX)
     407           0 :                         zlog_err("RECV[%pOI] : Wrong lls data in %s packet",
     408             :                                  oi, ospf6_message_type(oh->type));
     409           0 :                 return OSPF6_AUTH_VALIDATE_FAILURE;
     410             :         }
     411             : 
     412           0 :         memset(&ospf6_auth_info, 0, sizeof(ospf6_auth_info));
     413           0 :         if ((*pkt_len - hdr_len - (*lls_block_len)) > sizeof(ospf6_auth_info)) {
     414           0 :                 if (IS_OSPF6_DEBUG_AUTH_RX)
     415           0 :                         zlog_err("RECV[%pOI] : Wrong auth data in %s packet",
     416             :                                  oi, ospf6_message_type(oh->type));
     417           0 :                 return OSPF6_AUTH_VALIDATE_FAILURE;
     418             :         }
     419             : 
     420           0 :         memcpy(&ospf6_auth_info, ((uint8_t *)oh + hdr_len + (*lls_block_len)),
     421             :                (*pkt_len - hdr_len - (*lls_block_len)));
     422           0 :         if (ntohs(ospf6_auth_info.length) > OSPF6_AUTH_HDR_FULL) {
     423           0 :                 if (IS_OSPF6_DEBUG_AUTH_RX)
     424           0 :                         zlog_err("RECV[%pOI] : Wrong auth header length in %s",
     425             :                                  oi, ospf6_message_type(oh->type));
     426           0 :                 return OSPF6_AUTH_VALIDATE_FAILURE;
     427             :         }
     428             : 
     429             :         /* after authentication header validation is done
     430             :          * reduce the auth hdr size from the packet length
     431             :          */
     432           0 :         *at_len = ntohs(ospf6_auth_info.length);
     433           0 :         *pkt_len = (*pkt_len) - (*at_len) - (*lls_block_len);
     434             : 
     435           0 :         if (on) {
     436           0 :                 oh_seqnum_h = ntohl(ospf6_auth_info.seqnum_h);
     437           0 :                 oh_seqnum_l = ntohl(ospf6_auth_info.seqnum_l);
     438           0 :                 if ((oh_seqnum_h >= on->seqnum_h[oh->type])
     439           0 :                     && (oh_seqnum_l > on->seqnum_l[oh->type])) {
     440             :                         /* valid sequence number received */
     441           0 :                         on->seqnum_h[oh->type] = oh_seqnum_h;
     442           0 :                         on->seqnum_l[oh->type] = oh_seqnum_l;
     443             :                 } else {
     444           0 :                         if (IS_OSPF6_DEBUG_AUTH_RX) {
     445           0 :                                 zlog_err(
     446             :                                         "RECV[%pOI] : Nbr(%s) Auth Sequence number mismatch in %s ",
     447             :                                         oi, on->name,
     448             :                                         ospf6_message_type(oh->type));
     449           0 :                                 zlog_err(
     450             :                                         "nbr_seq_l %u, nbr_seq_h %u, hdr_seq_l %u, hdr_seq_h %u",
     451             :                                         on->seqnum_l[oh->type],
     452             :                                         on->seqnum_h[oh->type], oh_seqnum_l,
     453             :                                         oh_seqnum_h);
     454             :                         }
     455             : 
     456           0 :                         return OSPF6_AUTH_VALIDATE_FAILURE;
     457             :                 }
     458             :         }
     459             : 
     460             :         return OSPF6_AUTH_VALIDATE_SUCCESS;
     461             : }
     462             : 
     463             : /* Starting point of packet process function. */
     464           0 : int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
     465             :                             struct in6_addr *src, unsigned int lls_block_len)
     466           0 : {
     467           0 :         uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE;
     468           0 :         unsigned char apad[hash_len];
     469           0 :         unsigned char temp_hash[hash_len];
     470           0 :         struct ospf6_auth_hdr *ospf6_auth;
     471           0 :         uint32_t ipv6_addr_size = sizeof(struct in6_addr);
     472           0 :         struct keychain *keychain = NULL;
     473           0 :         struct key *key = NULL;
     474           0 :         char *auth_str = NULL;
     475           0 :         uint16_t auth_len = 0;
     476           0 :         uint8_t hash_algo = 0;
     477           0 :         uint16_t oh_len = ntohs(oh->length);
     478           0 :         int ret = 0;
     479             : 
     480           0 :         if (oi->at_data.flags == 0)
     481             :                 return OSPF6_AUTH_PROCESS_NORMAL;
     482             : 
     483           0 :         ospf6_auth = (struct ospf6_auth_hdr *)((uint8_t *)oh +
     484           0 :                                                (oh_len + lls_block_len));
     485           0 :         if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
     486           0 :                 keychain = keychain_lookup(oi->at_data.keychain);
     487           0 :                 if (!keychain) {
     488           0 :                         if (IS_OSPF6_DEBUG_AUTH_RX)
     489           0 :                                 zlog_err(
     490             :                                         "RECV[%pOI]: Keychain doesn't exist for %s",
     491             :                                         oi, ospf6_message_type(oh->type));
     492           0 :                         return OSPF6_AUTH_VALIDATE_FAILURE;
     493             :                 }
     494             : 
     495           0 :                 key = key_lookup_for_accept(keychain, ntohs(ospf6_auth->id));
     496           0 :                 if (!key) {
     497           0 :                         if (IS_OSPF6_DEBUG_AUTH_RX)
     498           0 :                                 zlog_err("RECV[%pOI]: Auth, Invalid SA for %s",
     499             :                                          oi, ospf6_message_type(oh->type));
     500           0 :                         return OSPF6_AUTH_VALIDATE_FAILURE;
     501             :                 }
     502             : 
     503           0 :                 if (key && key->string
     504           0 :                     && key->hash_algo != KEYCHAIN_ALGO_NULL) {
     505           0 :                         auth_str = key->string;
     506           0 :                         hash_algo = key->hash_algo;
     507             :                 } else {
     508           0 :                         if (IS_OSPF6_DEBUG_AUTH_RX)
     509           0 :                                 zlog_err(
     510             :                                         "RECV[%pOI]: Incomplete keychain config for %s",
     511             :                                         oi, ospf6_message_type(oh->type));
     512           0 :                         return OSPF6_AUTH_VALIDATE_FAILURE;
     513             :                 }
     514           0 :         } else if (CHECK_FLAG(oi->at_data.flags,
     515             :                               OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
     516           0 :                 auth_str = oi->at_data.auth_key;
     517           0 :                 hash_algo = oi->at_data.hash_algo;
     518             :         }
     519             : 
     520           0 :         if (!auth_str)
     521           0 :                 return OSPF6_AUTH_VALIDATE_FAILURE;
     522             : 
     523           0 :         hash_len = keychain_get_hash_len(hash_algo);
     524           0 :         memset(apad, 0, sizeof(apad));
     525           0 :         memset(temp_hash, 0, sizeof(temp_hash));
     526             : 
     527             :         /* start digest verification */
     528           0 :         memcpy(apad, src, ipv6_addr_size);
     529           0 :         memcpy(apad + ipv6_addr_size, ospf6_hash_apad_max,
     530           0 :                (hash_len - ipv6_addr_size));
     531             : 
     532           0 :         auth_len = ntohs(ospf6_auth->length);
     533             : 
     534           0 :         memcpy(temp_hash, ospf6_auth->data, hash_len);
     535           0 :         memcpy(ospf6_auth->data, apad, hash_len);
     536             : 
     537           0 :         ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str,
     538           0 :                                  (oh_len + auth_len + lls_block_len),
     539             :                                  hash_algo);
     540             : 
     541             : #ifdef CRYPTO_OPENSSL
     542             :         ret = CRYPTO_memcmp(temp_hash, ospf6_auth->data, hash_len);
     543             : #else
     544           0 :         ret = memcmp(temp_hash, ospf6_auth->data, hash_len);
     545             : #endif
     546           0 :         if (ret == 0)
     547             :                 return OSPF6_AUTH_VALIDATE_SUCCESS;
     548             : 
     549             :         return OSPF6_AUTH_VALIDATE_FAILURE;
     550             : }
     551             : 
     552           0 : void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,
     553             :                             struct ospf6_header *oh, uint16_t auth_len,
     554             :                             uint32_t pkt_len)
     555           0 : {
     556           0 :         struct ospf6_auth_hdr *ospf6_auth;
     557           0 :         char *keychain_name = NULL;
     558           0 :         struct keychain *keychain = NULL;
     559           0 :         struct key *key = NULL;
     560           0 :         char *auth_str = NULL;
     561           0 :         uint16_t key_id = 0;
     562           0 :         enum keychain_hash_algo hash_algo = KEYCHAIN_ALGO_NULL;
     563           0 :         uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE;
     564           0 :         unsigned char apad[hash_len];
     565           0 :         int ipv6_addr_size = sizeof(struct in6_addr);
     566           0 :         struct ospf6 *ospf6 = NULL;
     567             : 
     568           0 :         if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
     569           0 :                 if (CHECK_FLAG(oi->at_data.flags,
     570             :                                OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {
     571           0 :                         auth_str = oi->at_data.auth_key;
     572           0 :                         hash_algo = oi->at_data.hash_algo;
     573           0 :                         key_id = oi->at_data.key_id;
     574             :                 } else {
     575           0 :                         keychain_name = oi->at_data.keychain;
     576           0 :                         keychain = keychain_lookup(keychain_name);
     577           0 :                         if (keychain) {
     578           0 :                                 key = key_lookup_for_send(keychain);
     579           0 :                                 if (key && key->string
     580           0 :                                     && key->hash_algo != KEYCHAIN_ALGO_NULL) {
     581           0 :                                         auth_str = key->string;
     582           0 :                                         hash_algo = key->hash_algo;
     583           0 :                                         key_id = key->index;
     584             :                                 }
     585             :                         }
     586             :                 }
     587           0 :         } else if (CHECK_FLAG(oi->at_data.flags,
     588             :                               OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
     589           0 :                 auth_str = oi->at_data.auth_key;
     590           0 :                 hash_algo = oi->at_data.hash_algo;
     591           0 :                 key_id = oi->at_data.key_id;
     592             :         } else {
     593           0 :                 if (IS_OSPF6_DEBUG_AUTH_TX)
     594           0 :                         zlog_warn("SEND[%pOI]: Authentication not configured for %s",
     595             :                                   oi, ospf6_message_type(oh->type));
     596           0 :                 return;
     597             :         }
     598             : 
     599           0 :         if (!auth_str) {
     600           0 :                 if (IS_OSPF6_DEBUG_AUTH_TX)
     601           0 :                         zlog_warn("SEND[%pOI]: Authentication key is not configured for %s",
     602             :                                   oi, ospf6_message_type(oh->type));
     603           0 :                 return;
     604             :         }
     605             : 
     606           0 :         hash_len = keychain_get_hash_len(hash_algo);
     607           0 :         if (oi->area && oi->area->ospf6)
     608           0 :                 ospf6 = oi->area->ospf6;
     609             :         else
     610             :                 return;
     611             : 
     612           0 :         ospf6->seqnum_l++;
     613           0 :         if (ospf6->seqnum_l == 0xFFFFFFFF) {
     614           0 :                 ospf6->seqnum_h++;
     615           0 :                 ospf6->seqnum_l = 0;
     616           0 :                 ospf6_auth_seqno_nvm_update(ospf6);
     617             :         }
     618             : 
     619             :         /* Key must be reset. which is not handled as of now. */
     620           0 :         if ((ospf6->seqnum_l == 0xFFFFFFFF)
     621           0 :             && (ospf6->seqnum_h == 0xFFFFFFFF)) {
     622           0 :                 ospf6->seqnum_l = 0;
     623           0 :                 ospf6->seqnum_h = 0;
     624           0 :                 zlog_err(
     625             :                         "Both Higher and Lower sequence number has wrapped. Need to reset the key");
     626             :         }
     627             : 
     628           0 :         memset(apad, 0, sizeof(apad));
     629             : 
     630           0 :         if (src)
     631           0 :                 memcpy(apad, src, ipv6_addr_size);
     632             : 
     633           0 :         memcpy(apad + ipv6_addr_size, ospf6_hash_apad_max,
     634           0 :                (hash_len - ipv6_addr_size));
     635             : 
     636           0 :         ospf6_auth =
     637           0 :                 (struct ospf6_auth_hdr *)((uint8_t *)oh + ntohs(oh->length));
     638           0 :         ospf6_auth->type = htons(OSPF6_AUTHENTICATION_CRYPTOGRAPHIC);
     639           0 :         ospf6_auth->length = htons(auth_len);
     640           0 :         ospf6_auth->reserved = 0;
     641           0 :         ospf6_auth->id = htons(key_id);
     642           0 :         ospf6_auth->seqnum_h = htonl(ospf6->seqnum_h);
     643           0 :         ospf6_auth->seqnum_l = htonl(ospf6->seqnum_l);
     644           0 :         memcpy(ospf6_auth->data, apad, hash_len);
     645             : 
     646           0 :         ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, pkt_len,
     647             :                                  hash_algo);
     648             : 
     649             :         /* There is a optimisation that is done to ensure that
     650             :          * for every packet flow keychain lib API are called
     651             :          * only once and the result are stored in oi->at_data.
     652             :          * So, After processing the flow it is reset back here.
     653             :          */
     654           0 :         if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {
     655           0 :                 oi->at_data.hash_algo = KEYCHAIN_ALGO_NULL;
     656           0 :                 if (oi->at_data.auth_key) {
     657           0 :                         XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY,
     658             :                               oi->at_data.auth_key);
     659           0 :                         oi->at_data.auth_key = NULL;
     660             :                 }
     661             : 
     662           0 :                 oi->at_data.key_id = 0;
     663           0 :                 UNSET_FLAG(oi->at_data.flags,
     664             :                            OSPF6_AUTH_TRAILER_KEYCHAIN_VALID);
     665             :         }
     666             : }
     667             : 
     668           0 : void ospf6_auth_update_digest(struct ospf6_interface *oi,
     669             :                               struct ospf6_header *oh,
     670             :                               struct ospf6_auth_hdr *ospf6_auth, char *auth_str,
     671             :                               uint32_t pkt_len, enum keychain_hash_algo algo)
     672           0 : {
     673           0 :         static const uint16_t cpid = 1;
     674           0 :         uint32_t hash_len = keychain_get_hash_len(algo);
     675           0 :         uint32_t block_s = keychain_get_block_size(algo);
     676           0 :         uint32_t k_len = strlen(auth_str);
     677           0 :         uint32_t ks_len = strlen(auth_str) + sizeof(cpid);
     678           0 :         unsigned char ipad[block_s];
     679           0 :         unsigned char opad[block_s];
     680           0 :         unsigned char ko[block_s], ks[ks_len], tmp[hash_len];
     681           0 :         unsigned char *first = NULL;
     682           0 :         unsigned char *second = NULL;
     683           0 :         unsigned char first_mes[block_s + pkt_len];
     684           0 :         unsigned char second_mes[block_s + pkt_len];
     685           0 :         unsigned char first_hash[hash_len];
     686           0 :         unsigned char second_hash[hash_len];
     687             : 
     688           0 :         memset(ko, 0, sizeof(ko));
     689           0 :         memcpy(ks, auth_str, k_len);
     690           0 :         memcpy(ks + k_len, &cpid, sizeof(cpid));
     691           0 :         if (ks_len > hash_len) {
     692           0 :                 ospf6_hash_hmac_sha_digest(algo, ks, ks_len, tmp);
     693           0 :                 memcpy(ko, tmp, hash_len);
     694             :         } else
     695           0 :                 memcpy(ko, ks, ks_len);
     696             : 
     697           0 :         memcpy(ipad, ospf6_hash_ipad_max, block_s);
     698           0 :         memcpy(opad, ospf6_hash_opad_max, block_s);
     699             : 
     700           0 :         first = ospf6_hash_message_xor((unsigned char *)&ipad, ko, block_s);
     701           0 :         second = ospf6_hash_message_xor((unsigned char *)&opad, ko, block_s);
     702             : 
     703           0 :         memcpy(first_mes, first, block_s);
     704           0 :         memcpy(first_mes + block_s, oh, pkt_len);
     705             : 
     706           0 :         ospf6_hash_hmac_sha_digest(algo, first_mes, (block_s + pkt_len),
     707             :                                    first_hash);
     708             : 
     709           0 :         memcpy(second_mes, second, block_s);
     710           0 :         memcpy(second_mes + block_s, first_hash, hash_len);
     711             : 
     712           0 :         ospf6_hash_hmac_sha_digest(algo, second_mes, (block_s + hash_len),
     713             :                                    second_hash);
     714             : 
     715           0 :         memcpy(ospf6_auth->data, second_hash, hash_len);
     716           0 :         XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, first);
     717           0 :         XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, second);
     718           0 : }
     719             : 
     720           0 : DEFUN (debug_ospf6_auth,
     721             :        debug_ospf6_auth_cmd,
     722             :        "debug ospf6 authentication [<tx|rx>]",
     723             :        DEBUG_STR
     724             :        OSPF6_STR
     725             :        "debug OSPF6 authentication\n"
     726             :        "debug authentication tx\n"
     727             :        "debug authentication rx\n")
     728             : {
     729           0 :         int auth_opt_idx = 3;
     730             : 
     731           0 :         if (argc == 4) {
     732           0 :                 if (!strncmp(argv[auth_opt_idx]->arg, "t", 1))
     733           0 :                         OSPF6_DEBUG_AUTH_TX_ON();
     734           0 :                 else if (!strncmp(argv[auth_opt_idx]->arg, "r", 1))
     735           0 :                         OSPF6_DEBUG_AUTH_RX_ON();
     736             :         } else {
     737           0 :                 OSPF6_DEBUG_AUTH_TX_ON();
     738           0 :                 OSPF6_DEBUG_AUTH_RX_ON();
     739             :         }
     740             : 
     741           0 :         return CMD_SUCCESS;
     742             : }
     743             : 
     744           0 : DEFUN (no_debug_ospf6_auth,
     745             :        no_debug_ospf6_auth_cmd,
     746             :        "no debug ospf6 authentication [<tx|rx>]",
     747             :        NO_STR
     748             :        DEBUG_STR
     749             :        OSPF6_STR
     750             :        "debug OSPF6 authentication\n"
     751             :        "debug authentication tx\n"
     752             :        "debug authentication rx\n")
     753             : {
     754           0 :         int auth_opt_idx = 3;
     755             : 
     756           0 :         if (argc == 5) {
     757           0 :                 if (!strncmp(argv[auth_opt_idx]->arg, "t", 1))
     758           0 :                         OSPF6_DEBUG_AUTH_TX_OFF();
     759           0 :                 else if (!strncmp(argv[auth_opt_idx]->arg, "r", 1))
     760           0 :                         OSPF6_DEBUG_AUTH_RX_OFF();
     761             :         } else {
     762           0 :                 OSPF6_DEBUG_AUTH_TX_OFF();
     763           0 :                 OSPF6_DEBUG_AUTH_RX_OFF();
     764             :         }
     765             : 
     766           0 :         return CMD_SUCCESS;
     767             : }
     768             : 
     769           0 : int config_write_ospf6_debug_auth(struct vty *vty)
     770             : {
     771           0 :         if (IS_OSPF6_DEBUG_AUTH_TX)
     772           0 :                 vty_out(vty, "debug ospf6 authentication tx\n");
     773           0 :         if (IS_OSPF6_DEBUG_AUTH_RX)
     774           0 :                 vty_out(vty, "debug ospf6 authentication rx\n");
     775           0 :         return 0;
     776             : }
     777             : 
     778           8 : void install_element_ospf6_debug_auth(void)
     779             : {
     780           8 :         install_element(ENABLE_NODE, &debug_ospf6_auth_cmd);
     781           8 :         install_element(ENABLE_NODE, &no_debug_ospf6_auth_cmd);
     782           8 :         install_element(CONFIG_NODE, &debug_ospf6_auth_cmd);
     783           8 :         install_element(CONFIG_NODE, &no_debug_ospf6_auth_cmd);
     784           8 : }
     785             : 
     786             : /* Clear the specified interface structure */
     787           0 : static void ospf6_intf_auth_clear(struct vty *vty, struct interface *ifp)
     788             : {
     789           0 :         struct ospf6_interface *oi;
     790             : 
     791           0 :         if (!if_is_operative(ifp))
     792             :                 return;
     793             : 
     794           0 :         if (ifp->info == NULL)
     795             :                 return;
     796             : 
     797           0 :         oi = (struct ospf6_interface *)ifp->info;
     798             : 
     799           0 :         if (IS_OSPF6_DEBUG_INTERFACE)
     800           0 :                 zlog_debug(
     801             :                         "Interface %s: clear authentication rx/tx drop counters",
     802             :                         ifp->name);
     803             : 
     804             :         /* Reset the interface rx/tx drop counters */
     805           0 :         oi->at_data.tx_drop = 0;
     806           0 :         oi->at_data.rx_drop = 0;
     807             : }
     808             : 
     809             : /* Clear interface */
     810           0 : DEFUN(clear_ipv6_ospf6_intf_auth, clear_ipv6_ospf6_intf_auth_cmd,
     811             :       "clear ipv6 ospf6 [vrf VRF] auth-counters interface [IFNAME]",
     812             :       CLEAR_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
     813             :       "authentication rx/tx drop counters\n" INTERFACE_STR IFNAME_STR)
     814             : {
     815           0 :         int idx_ifname = 0;
     816           0 :         int idx_vrf = 0;
     817           0 :         struct interface *ifp;
     818           0 :         struct listnode *node;
     819           0 :         struct ospf6 *ospf6 = NULL;
     820           0 :         char *vrf_name = NULL;
     821           0 :         vrf_id_t vrf_id = VRF_DEFAULT;
     822           0 :         struct vrf *vrf = NULL;
     823             : 
     824           0 :         if (argv_find(argv, argc, "vrf", &idx_vrf))
     825           0 :                 vrf_name = argv[idx_vrf + 1]->arg;
     826             : 
     827           0 :         if (vrf_name && strmatch(vrf_name, VRF_DEFAULT_NAME))
     828             :                 vrf_name = NULL;
     829             : 
     830           0 :         if (vrf_name) {
     831           0 :                 vrf = vrf_lookup_by_name(vrf_name);
     832           0 :                 if (vrf)
     833           0 :                         vrf_id = vrf->vrf_id;
     834             :         }
     835             : 
     836           0 :         if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) {
     837             :                 /* Clear all the ospfv3 interfaces auth data. */
     838           0 :                 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
     839           0 :                         if (vrf_id != ospf6->vrf_id)
     840           0 :                                 continue;
     841             : 
     842           0 :                         if (!vrf)
     843           0 :                                 vrf = vrf_lookup_by_id(ospf6->vrf_id);
     844           0 :                         FOR_ALL_INTERFACES (vrf, ifp)
     845           0 :                                 ospf6_intf_auth_clear(vty, ifp);
     846             :                 }
     847             :         } else {
     848             :                 /* Interface name is specified. */
     849           0 :                 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
     850           0 :                 if (ifp == NULL)
     851           0 :                         vty_out(vty, "No such interface name\n");
     852             :                 else
     853           0 :                         ospf6_intf_auth_clear(vty, ifp);
     854             :         }
     855             : 
     856           0 :         return CMD_SUCCESS;
     857             : }
     858             : 
     859           8 : void install_element_ospf6_clear_intf_auth(void)
     860             : {
     861           8 :         install_element(ENABLE_NODE, &clear_ipv6_ospf6_intf_auth_cmd);
     862           8 : }
     863             : 
     864           8 : enum ospf6_auth_err ospf6_auth_nvm_file_exist(void)
     865             : {
     866           8 :         struct stat buffer;
     867           8 :         int exist;
     868             : 
     869           8 :         exist = stat(OSPF6_AUTH_SEQ_NUM_FILE, &buffer);
     870           8 :         if (exist == 0)
     871             :                 return OSPF6_AUTH_FILE_EXIST;
     872             :         else
     873           8 :                 return OSPF6_AUTH_FILE_DO_NOT_EXIST;
     874             : }
     875             : 
     876             : /*
     877             :  * Record in non-volatile memory the given ospf6 process,
     878             :  * authentication trailer higher order sequence number.
     879             :  */
     880           8 : void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6)
     881             : {
     882           8 :         const char *inst_name;
     883           8 :         json_object *json;
     884           8 :         json_object *json_instances;
     885           8 :         json_object *json_instance;
     886             : 
     887           8 :         zlog_err("Higher order sequence number %d update for %s process",
     888             :                  ospf6->seqnum_h, ospf6->name);
     889             : 
     890           8 :         inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
     891             : 
     892           8 :         json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
     893           8 :         if (json == NULL)
     894           8 :                 json = json_object_new_object();
     895             : 
     896           8 :         json_object_object_get_ex(json, "instances", &json_instances);
     897           8 :         if (!json_instances) {
     898           8 :                 json_instances = json_object_new_object();
     899           8 :                 json_object_object_add(json, "instances", json_instances);
     900             :         }
     901             : 
     902           8 :         json_object_object_get_ex(json_instances, inst_name, &json_instance);
     903           8 :         if (!json_instance) {
     904           8 :                 json_instance = json_object_new_object();
     905           8 :                 json_object_object_add(json_instances, inst_name,
     906             :                                        json_instance);
     907             :         }
     908             : 
     909             :         /*
     910             :          * Record higher order sequence number in non volatile memory.
     911             :          */
     912           8 :         json_object_int_add(json_instance, "sequence_number", ospf6->seqnum_h);
     913             : 
     914           8 :         json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
     915             :                                 JSON_C_TO_STRING_PRETTY);
     916           8 :         json_object_free(json);
     917           8 : }
     918             : 
     919             : /*
     920             :  * Delete authentication sequence number for a given OSPF6 process
     921             :  * from non-volatile memory.
     922             :  */
     923           0 : void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6)
     924             : {
     925           0 :         const char *inst_name;
     926           0 :         json_object *json;
     927           0 :         json_object *json_instances;
     928             : 
     929           0 :         zlog_err("Higher order sequence number delete for %s process",
     930             :                  ospf6->name);
     931             : 
     932           0 :         inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
     933             : 
     934           0 :         json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
     935           0 :         if (json == NULL)
     936           0 :                 json = json_object_new_object();
     937             : 
     938           0 :         json_object_object_get_ex(json, "instances", &json_instances);
     939           0 :         if (!json_instances) {
     940           0 :                 json_instances = json_object_new_object();
     941           0 :                 json_object_object_add(json, "instances", json_instances);
     942             :         }
     943             : 
     944           0 :         json_object_object_del(json_instances, inst_name);
     945             : 
     946           0 :         json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
     947             :                                 JSON_C_TO_STRING_PRETTY);
     948           0 :         json_object_free(json);
     949           0 : }
     950             : 
     951             : 
     952             : /*
     953             :  * Fetch from non-volatile memory the stored ospf6 process
     954             :  * authentication sequence number.
     955             :  */
     956           0 : void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6)
     957             : {
     958           0 :         const char *inst_name;
     959           0 :         json_object *json;
     960           0 :         json_object *json_instances;
     961           0 :         json_object *json_instance;
     962           0 :         json_object *json_seqnum;
     963             : 
     964           0 :         inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
     965             : 
     966           0 :         json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
     967           0 :         if (json == NULL)
     968           0 :                 json = json_object_new_object();
     969             : 
     970           0 :         json_object_object_get_ex(json, "instances", &json_instances);
     971           0 :         if (!json_instances) {
     972           0 :                 json_instances = json_object_new_object();
     973           0 :                 json_object_object_add(json, "instances", json_instances);
     974             :         }
     975             : 
     976           0 :         json_object_object_get_ex(json_instances, inst_name, &json_instance);
     977           0 :         if (!json_instance) {
     978           0 :                 json_instance = json_object_new_object();
     979           0 :                 json_object_object_add(json_instances, inst_name,
     980             :                                        json_instance);
     981             :         }
     982             : 
     983           0 :         json_object_object_get_ex(json_instance, "sequence_number",
     984             :                                   &json_seqnum);
     985           0 :         ospf6->seqnum_h = json_object_get_int(json_seqnum);
     986             : 
     987           0 :         zlog_err("Higher order sequence number %d read for %s process %s",
     988             :                  ospf6->seqnum_h, ospf6->name, strerror(errno));
     989             : 
     990           0 :         json_object_object_del(json_instances, inst_name);
     991           0 :         json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
     992             :                                 JSON_C_TO_STRING_PRETTY);
     993           0 :         json_object_free(json);
     994           0 : }

Generated by: LCOV version v1.16-topotato