diff options
author | Abhinay Ramesh <rabhinay@vmware.com> | 2021-05-30 18:33:41 +0200 |
---|---|---|
committer | Abhinay Ramesh <rabhinay@vmware.com> | 2022-02-09 02:57:08 +0100 |
commit | 6cb85350df7fdcea106947fdda42a91ddebcdd5e (patch) | |
tree | 9b995fe10714480472ba3c4b842ce32d9f6e1fc2 /ospf6d/ospf6_auth_trailer.c | |
parent | ospf6d: Core functionality of auth trailer implementation.. (diff) | |
download | frr-6cb85350df7fdcea106947fdda42a91ddebcdd5e.tar.xz frr-6cb85350df7fdcea106947fdda42a91ddebcdd5e.zip |
ospf6d: Stitching the auth trailer code with rest of ospf6.
Problem Statement:
==================
RFC 7166 support for OSPF6 in FRR code.
RCA:
====
This feature is newly supported in FRR
Fix:
====
Core functionality implemented in previous commit is
stitched with rest of ospf6 code as part of this commit.
Risk:
=====
Low risk
Tests Executed:
===============
Have executed the combination of commands.
Signed-off-by: Abhinay Ramesh <rabhinay@vmware.com>
Diffstat (limited to 'ospf6d/ospf6_auth_trailer.c')
-rw-r--r-- | ospf6d/ospf6_auth_trailer.c | 500 |
1 files changed, 336 insertions, 164 deletions
diff --git a/ospf6d/ospf6_auth_trailer.c b/ospf6d/ospf6_auth_trailer.c index 88d2fc240..2d0621cc2 100644 --- a/ospf6d/ospf6_auth_trailer.c +++ b/ospf6d/ospf6_auth_trailer.c @@ -19,6 +19,7 @@ */ #include "zebra.h" +#include "config.h" #include "memory.h" #include "ospf6d.h" #include "vty.h" @@ -30,14 +31,14 @@ #include "ospf6_interface.h" #include "ospf6_neighbor.h" #include "ospf6_proto.h" +#include "ospf6_top.h" +#include "ospf6_area.h" #include "ospf6_auth_trailer.h" #include "ospf6_route.h" #include "ospf6_zebra.h" #include "lib/keychain.h" unsigned char conf_debug_ospf6_auth[2]; -DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_PKT, "OSPF6 auth packet"); -DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH, "OSPF6 auth hash"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH_XOR, "OSPF6 auth hash xor"); /*Apad is the hexadecimal value 0x878FE1F3. */ @@ -106,17 +107,18 @@ void ospf6_auth_hdr_dump_send(struct ospf6_header *ospfh, uint16_t length) } } -void ospf6_auth_hdr_dump_recv(struct ospf6_header *ospfh, uint16_t length) +void ospf6_auth_hdr_dump_recv(struct ospf6_header *ospfh, uint16_t length, + unsigned int lls_len) { struct ospf6_auth_hdr *ospf6_at_hdr; int at_len, oh_len, at_hdr_len, hash_len; - unsigned char temp[KEYCHAIN_MAX_HASH_SIZE+1]; + unsigned char temp[KEYCHAIN_MAX_HASH_SIZE + 1]; oh_len = ntohs(ospfh->length); - at_len = length - oh_len; + at_len = length - (oh_len + lls_len); if (at_len > 0) { - ospf6_at_hdr = (struct ospf6_auth_hdr *) - ((uint8_t *)ospfh + oh_len); + ospf6_at_hdr = + (struct ospf6_auth_hdr *)((uint8_t *)ospfh + oh_len); at_hdr_len = ntohs(ospf6_at_hdr->length); hash_len = at_hdr_len - OSPF6_AUTH_HDR_MIN_SIZE; memcpy(temp, ospf6_at_hdr->data, hash_len); @@ -312,7 +314,8 @@ unsigned int ospf6_auth_len_get(struct ospf6_interface *oi) } int ospf6_auth_validate_pkt(struct ospf6_interface *oi, unsigned int *pkt_len, - struct ospf6_header *oh, unsigned int *at_len) + struct ospf6_header *oh, unsigned int *at_len, + unsigned int *lls_block_len) { struct ospf6_hello *hello = NULL; struct ospf6_dbdesc *dbdesc = NULL; @@ -321,132 +324,146 @@ int ospf6_auth_validate_pkt(struct ospf6_interface *oi, unsigned int *pkt_len, uint16_t hdr_len = 0; uint32_t oh_seqnum_h = 0; uint32_t oh_seqnum_l = 0; + bool auth_present = false; + bool lls_present = false; + struct ospf6_lls_hdr *lls_hdr = NULL; on = ospf6_neighbor_lookup(oh->router_id, oi); hdr_len = ntohs(oh->length); if (*pkt_len < hdr_len) { if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s] Wrong %s packet auth length", - oi->interface->name, - lookup_msg(ospf6_message_type_str, oh->type, - NULL)); - oi->at_data.rx_drop++; - return -1; + zlog_err("RECV[%s] Received incomplete %s packet", + oi->interface->name, + ospf6_message_type(oh->type)); + return OSPF6_AUTH_VALIDATE_FAILURE; } else if (*pkt_len == hdr_len) { - /* no auth data in packet + if (oi->at_data.flags != 0) + return OSPF6_AUTH_VALIDATE_FAILURE; + /* No auth info to be considered. */ - return -1; + return OSPF6_AUTH_PROCESS_NORMAL; } switch (oh->type) { case OSPF6_MESSAGE_TYPE_HELLO: hello = (struct ospf6_hello *)((uint8_t *)oh + sizeof(struct ospf6_header)); - if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT)) { - if (on) - on->auth_present = true; - } else { - if (on) - on->auth_present = false; - - if (oi->at_data.flags != 0) { - if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s] : Auth option miss-match in hello pkt", - oi->interface->name); - oi->at_data.rx_drop++; - } + if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_L)) + lls_present = true; - return -1; - } + if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT)) + auth_present = true; break; case OSPF6_MESSAGE_TYPE_DBDESC: dbdesc = (struct ospf6_dbdesc *)((uint8_t *)oh + sizeof(struct ospf6_header)); + if (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_L)) + lls_present = true; - if (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT)) { - if (on) - on->auth_present = true; - } else { - if (on) - on->auth_present = false; - - if (oi->at_data.flags != 0) { - if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s] : Auth option miss-match in DB desc pkt", - oi->interface->name); - oi->at_data.rx_drop++; - } - - return -1; - } + if (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT)) + auth_present = true; break; case OSPF6_MESSAGE_TYPE_LSREQ: case OSPF6_MESSAGE_TYPE_LSUPDATE: case OSPF6_MESSAGE_TYPE_LSACK: - if ((on && on->auth_present == false) - && (oi->at_data.flags != 0)) { - if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s] : Auth config miss-match in %s", - oi->interface->name, - lookup_msg(ospf6_message_type_str, - oh->type, NULL)); - oi->at_data.rx_drop++; - return -1; + if (on) { + lls_present = on->lls_present; + auth_present = on->auth_present; } break; default: if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s] : Wrong packet type %d", - oi->interface->name, oh->type); - return -1; + zlog_err("RECV[%s] : Wrong packet type %d", + oi->interface->name, oh->type); + return OSPF6_AUTH_VALIDATE_FAILURE; + } + + if ((oh->type == OSPF6_MESSAGE_TYPE_HELLO) + || (oh->type == OSPF6_MESSAGE_TYPE_DBDESC)) { + if (on) { + on->auth_present = auth_present; + on->lls_present = lls_present; + } + } + + if ((!auth_present && (oi->at_data.flags != 0)) + || (auth_present && (oi->at_data.flags == 0))) { + if (IS_OSPF6_DEBUG_AUTH_RX) + zlog_err("RECV[%s] : Auth option miss-match in %s pkt", + oi->interface->name, + ospf6_message_type(oh->type)); + return OSPF6_AUTH_VALIDATE_FAILURE; + } + + if (lls_present) { + lls_hdr = (struct ospf6_lls_hdr *)(oh + hdr_len); + *lls_block_len = ntohs(lls_hdr->length) * 4; + } + + if (*lls_block_len > (*pkt_len - hdr_len)) { + if (IS_OSPF6_DEBUG_AUTH_RX) + zlog_err("RECV[%s] : Wrong lls data in %s packet", + oi->interface->name, + ospf6_message_type(oh->type)); + return OSPF6_AUTH_VALIDATE_FAILURE; } memset(&ospf6_auth_info, 0, sizeof(struct ospf6_auth_hdr)); - memcpy(&ospf6_auth_info, (uint8_t *)oh + hdr_len, *pkt_len - hdr_len); + if ((*pkt_len - hdr_len - (*lls_block_len)) > sizeof(ospf6_auth_info)) { + if (IS_OSPF6_DEBUG_AUTH_RX) + zlog_err("RECV[%s] : Wrong auth data in %s packet", + oi->interface->name, + ospf6_message_type(oh->type)); + return OSPF6_AUTH_VALIDATE_FAILURE; + } + + memcpy(&ospf6_auth_info, ((uint8_t *)oh + hdr_len + (*lls_block_len)), + (*pkt_len - hdr_len - (*lls_block_len))); if (ntohs(ospf6_auth_info.length) > OSPF6_AUTH_HDR_FULL) { if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s] : Auth config miss-match in %s", - oi->interface->name, - lookup_msg(ospf6_message_type_str, oh->type, - NULL)); - oi->at_data.rx_drop++; - return -1; + zlog_err("RECV[%s] : Wrong auth header length in %s", + oi->interface->name, + ospf6_message_type(oh->type)); + return OSPF6_AUTH_VALIDATE_FAILURE; } /* after authentication header validation is done * reduce the auth hdr size from the packet length */ *at_len = ntohs(ospf6_auth_info.length); - *pkt_len = *pkt_len - *at_len; + *pkt_len = (*pkt_len) - (*at_len) - (*lls_block_len); if (on) { oh_seqnum_h = ntohl(ospf6_auth_info.seqnum_h); oh_seqnum_l = ntohl(ospf6_auth_info.seqnum_l); - if ((oh_seqnum_h >= on->seqnum_h) && - (oh_seqnum_l > on->seqnum_l)) { + if ((oh_seqnum_h >= on->seqnum_h[oh->type]) + && (oh_seqnum_l > on->seqnum_l[oh->type])) { /* valid sequence number received */ - on->seqnum_h = oh_seqnum_h; - on->seqnum_l = oh_seqnum_l; + on->seqnum_h[oh->type] = oh_seqnum_h; + on->seqnum_l[oh->type] = oh_seqnum_l; } else { if (IS_OSPF6_DEBUG_AUTH_RX) { - zlog_warn("RECV[%s] : Nbr(%s) Auth Sequence number mismatch", - oi->interface->name, on->name); - zlog_warn("nbr_seq_l %u, nbr_seq_h %u, hdr_seq_l %u, hdr_seq_h %u", - on->seqnum_l, on->seqnum_h, - oh_seqnum_l, oh_seqnum_h); + zlog_err( + "RECV[%s] : Nbr(%s) Auth Sequence number mismatch in %s ", + oi->interface->name, on->name, + ospf6_message_type(oh->type)); + zlog_err( + "nbr_seq_l %u, nbr_seq_h %u, hdr_seq_l %u, hdr_seq_h %u", + on->seqnum_l[oh->type], + on->seqnum_h[oh->type], oh_seqnum_l, + oh_seqnum_h); } - oi->at_data.rx_drop++; - return -1; + return OSPF6_AUTH_VALIDATE_FAILURE; } } - return 0; + return OSPF6_AUTH_VALIDATE_SUCCESS; } /* Starting point of packet process function. */ int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi, - struct in6_addr *src) + struct in6_addr *src, unsigned int lls_block_len) { uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE; unsigned char apad[hash_len]; @@ -459,32 +476,31 @@ int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi, uint16_t auth_len = 0; uint8_t hash_algo = 0; uint16_t oh_len = ntohs(oh->length); + int ret = 0; if (oi->at_data.flags == 0) - return -2; + return OSPF6_AUTH_PROCESS_NORMAL; - ospf6_auth = (struct ospf6_auth_hdr *)((uint8_t *)oh + oh_len); + ospf6_auth = (struct ospf6_auth_hdr *)((uint8_t *)oh + oh_len + + lls_block_len); if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) { keychain = keychain_lookup(oi->at_data.keychain); if (!keychain) { if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s]: Keychain does't exist for %s", - oi->interface->name, - lookup_msg(ospf6_message_type_str, - oh->type, NULL)); - oi->at_data.rx_drop++; - return -1; + zlog_err( + "RECV[%s]: Keychain does't exist for %s", + oi->interface->name, + ospf6_message_type(oh->type)); + return OSPF6_AUTH_VALIDATE_FAILURE; } key = key_lookup_for_accept(keychain, ntohs(ospf6_auth->id)); if (!key) { if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s]: Auth, Invalid SA for %s", - oi->interface->name, - lookup_msg(ospf6_message_type_str, - oh->type, NULL)); - oi->at_data.rx_drop++; - return -1; + zlog_err("RECV[%s]: Auth, Invalid SA for %s", + oi->interface->name, + ospf6_message_type(oh->type)); + return OSPF6_AUTH_VALIDATE_FAILURE; } if (key && key->string @@ -493,12 +509,11 @@ int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi, hash_algo = key->hash_algo; } else { if (IS_OSPF6_DEBUG_AUTH_RX) - zlog_warn("RECV[%s]: Incomplete keychain config for %s", - oi->interface->name, - lookup_msg(ospf6_message_type_str, - oh->type, NULL)); - oi->at_data.rx_drop++; - return -1; + zlog_err( + "RECV[%s]: Incomplete keychain config for %s", + oi->interface->name, + ospf6_message_type(oh->type)); + return OSPF6_AUTH_VALIDATE_FAILURE; } } else if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY)) { @@ -507,11 +522,11 @@ int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi, } if (!auth_str) - return -2; + return OSPF6_AUTH_VALIDATE_FAILURE; hash_len = keychain_get_hash_len(hash_algo); - memset(apad, 0, sizeof(hash_len)); - memset(temp_hash, 0, sizeof(hash_len)); + memset(apad, 0, sizeof(apad)); + memset(temp_hash, 0, sizeof(temp_hash)); /* start digest verification */ memcpy(apad, src, ipv6_addr_size); @@ -523,14 +538,19 @@ int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi, memcpy(temp_hash, ospf6_auth->data, hash_len); memcpy(ospf6_auth->data, apad, hash_len); - ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, auth_len, - (oh_len + auth_len), hash_algo); + ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, + (oh_len + auth_len + lls_block_len), + hash_algo); #ifdef CRYPTO_OPENSSL - return !(CRYPTO_memcmp(temp_hash, ospf6_auth->data, hash_len)); + ret = CRYPTO_memcmp(temp_hash, ospf6_auth->data, hash_len); #else - return !(memcmp(temp_hash, ospf6_auth->data, hash_len)); + ret = memcmp(temp_hash, ospf6_auth->data, hash_len); #endif + if (ret == 0) + return OSPF6_AUTH_VALIDATE_SUCCESS; + + return OSPF6_AUTH_VALIDATE_FAILURE; } void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi, @@ -547,6 +567,7 @@ void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi, uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE; unsigned char apad[hash_len]; int ipv6_addr_size = sizeof(struct in6_addr); + struct ospf6 *ospf6 = NULL; if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) { if (CHECK_FLAG(oi->at_data.flags, @@ -576,8 +597,7 @@ void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi, if (IS_OSPF6_DEBUG_AUTH_TX) zlog_warn("SEND[%s]: Authentication not configured for %s", oi->interface->name, - lookup_msg(ospf6_message_type_str, - oh->type, NULL)); + ospf6_message_type(oh->type)); return; } @@ -585,27 +605,33 @@ void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi, if (IS_OSPF6_DEBUG_AUTH_TX) zlog_warn("SEND[%s]: Authentication key is not configured for %s", oi->interface->name, - lookup_msg(ospf6_message_type_str, - oh->type, NULL)); + ospf6_message_type(oh->type)); return; } hash_len = keychain_get_hash_len(hash_algo); - oi->at_data.seqnum_l++; + if (oi->area && oi->area->ospf6) + ospf6 = oi->area->ospf6; + else + return; - if (oi->at_data.seqnum_l == 0xFFFFFFFF) { - oi->at_data.seqnum_h++; - oi->at_data.seqnum_l = 0; + ospf6->seqnum_l++; + if (ospf6->seqnum_l == 0xFFFFFFFF) { + ospf6->seqnum_h++; + ospf6->seqnum_l = 0; + ospf6_auth_seqno_nvm_update(ospf6); } /* Key must be reset. which is not handled as of now. */ - if ((oi->at_data.seqnum_l == 0xFFFFFFFF) - && (oi->at_data.seqnum_h == 0xFFFFFFFF)) { - oi->at_data.seqnum_l = 0; - oi->at_data.seqnum_h = 0; + if ((ospf6->seqnum_l == 0xFFFFFFFF) + && (ospf6->seqnum_h == 0xFFFFFFFF)) { + ospf6->seqnum_l = 0; + ospf6->seqnum_h = 0; + zlog_err( + "Both Higher and Lower sequence number has wrapped. Need to reset the key"); } - memset(apad, 0, hash_len); + memset(apad, 0, sizeof(apad)); if (src) memcpy(apad, src, ipv6_addr_size); @@ -619,13 +645,18 @@ void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi, ospf6_auth->length = htons(auth_len); ospf6_auth->reserved = 0; ospf6_auth->id = htons(key_id); - ospf6_auth->seqnum_h = htonl(oi->at_data.seqnum_h); - ospf6_auth->seqnum_l = htonl(oi->at_data.seqnum_l); + ospf6_auth->seqnum_h = htonl(ospf6->seqnum_h); + ospf6_auth->seqnum_l = htonl(ospf6->seqnum_l); memcpy(ospf6_auth->data, apad, hash_len); - ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, auth_len, - pkt_len, hash_algo); + ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, pkt_len, + hash_algo); + /* There is a optimisation that is done to ensure that + * for every packet flow keychain lib API are called + * only once and the result are stored in oi->at_data. + * So, After processing the flow it is reset back here. + */ if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) { oi->at_data.hash_algo = KEYCHAIN_ALGO_NULL; if (oi->at_data.auth_key) { @@ -643,24 +674,26 @@ void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi, void ospf6_auth_update_digest(struct ospf6_interface *oi, struct ospf6_header *oh, struct ospf6_auth_hdr *ospf6_auth, char *auth_str, - uint16_t auth_len, uint32_t pkt_len, - enum keychain_hash_algo algo) + uint32_t pkt_len, enum keychain_hash_algo algo) { + static const uint16_t cpid = 1; uint32_t hash_len = keychain_get_hash_len(algo); uint32_t block_s = keychain_get_block_size(algo); uint32_t k_len = strlen(auth_str); - uint32_t ks_len = strlen(auth_str) + sizeof(CPID); + uint32_t ks_len = strlen(auth_str) + sizeof(cpid); unsigned char ipad[block_s]; unsigned char opad[block_s]; unsigned char ko[block_s], ks[ks_len], tmp[hash_len]; unsigned char *first = NULL; unsigned char *second = NULL; - unsigned char *first_mes, *second_mes; - unsigned char *first_hash, *second_hash; + unsigned char first_mes[block_s + pkt_len]; + unsigned char second_mes[block_s + pkt_len]; + unsigned char first_hash[hash_len]; + unsigned char second_hash[hash_len]; - memset(ko, 0, block_s); + memset(ko, 0, sizeof(ko)); memcpy(ks, auth_str, k_len); - memcpy(ks + k_len, &CPID, sizeof(CPID)); + memcpy(ks + k_len, &cpid, sizeof(cpid)); if (ks_len > hash_len) { ospf6_hash_hmac_sha_digest(algo, ks, ks_len, tmp); memcpy(ko, tmp, hash_len); @@ -673,31 +706,19 @@ void ospf6_auth_update_digest(struct ospf6_interface *oi, first = ospf6_hash_message_xor((unsigned char *)&ipad, ko, block_s); second = ospf6_hash_message_xor((unsigned char *)&opad, ko, block_s); - first_mes = XMALLOC(MTYPE_OSPF6_AUTH_PKT, (block_s + pkt_len)); - memcpy(first_mes, first, block_s); memcpy(first_mes + block_s, oh, pkt_len); - first_hash = XMALLOC(MTYPE_OSPF6_AUTH_HASH, hash_len); - ospf6_hash_hmac_sha_digest(algo, first_mes, (block_s + pkt_len), first_hash); - second_mes = XMALLOC(MTYPE_OSPF6_AUTH_PKT, (block_s + hash_len)); - memcpy(second_mes, second, block_s); memcpy(second_mes + block_s, first_hash, hash_len); - second_hash = XMALLOC(MTYPE_OSPF6_AUTH_HASH, hash_len); - ospf6_hash_hmac_sha_digest(algo, second_mes, (block_s + hash_len), second_hash); memcpy(ospf6_auth->data, second_hash, hash_len); - XFREE(MTYPE_OSPF6_AUTH_PKT, first_mes); - XFREE(MTYPE_OSPF6_AUTH_PKT, second_mes); - XFREE(MTYPE_OSPF6_AUTH_HASH, first_hash); - XFREE(MTYPE_OSPF6_AUTH_HASH, second_hash); XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, first); XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, second); } @@ -792,31 +813,50 @@ static void ospf6_intf_auth_clear(struct vty *vty, struct interface *ifp) } /* Clear interface */ -DEFUN(clear_ipv6_ospf6_intf_auth, - clear_ipv6_ospf6_intf_auth_cmd, - "clear ipv6 ospf6 auth-counters interface [IFNAME]", - CLEAR_STR - IP6_STR - OSPF6_STR - "authentication rx/tx drop counters\n" - INTERFACE_STR - IFNAME_STR) +DEFUN(clear_ipv6_ospf6_intf_auth, clear_ipv6_ospf6_intf_auth_cmd, + "clear ipv6 ospf6 [vrf VRF] auth-counters interface [IFNAME]", + CLEAR_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + "authentication rx/tx drop counters\n" INTERFACE_STR IFNAME_STR) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - int idx_ifname = 5; + int idx_ifname = 0; + int idx_vrf = 0; struct interface *ifp; + struct listnode *node; + struct ospf6 *ospf6 = NULL; + char *vrf_name = NULL; + vrf_id_t vrf_id = VRF_DEFAULT; + struct vrf *vrf = NULL; + + if (argv_find(argv, argc, "vrf", &idx_vrf)) + vrf_name = argv[idx_vrf + 1]->arg; + + if (vrf_name && strmatch(vrf_name, VRF_DEFAULT_NAME)) + vrf_name = NULL; + + if (vrf_name) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) + vrf_id = vrf->vrf_id; + } - if (argc == 5) { /* Clear all the ospfv3 interfaces. */ - FOR_ALL_INTERFACES (vrf, ifp) - ospf6_intf_auth_clear(vty, ifp); - } else { /* Interface name is specified. */ - ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); - if (ifp == NULL) { - vty_out(vty, "Error: No such Interface: %s\n", - argv[idx_ifname]->arg); - return CMD_WARNING; + if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) { + /* Clear all the ospfv3 interfaces auth data. */ + for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) { + if (vrf_id != ospf6->vrf_id) + continue; + + if (!vrf) + vrf = vrf_lookup_by_id(ospf6->vrf_id); + FOR_ALL_INTERFACES (vrf, ifp) + ospf6_intf_auth_clear(vty, ifp); } - ospf6_intf_auth_clear(vty, ifp); + } else { + /* Interface name is specified. */ + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); + if (ifp == NULL) + vty_out(vty, "No such interface name\n"); + else + ospf6_intf_auth_clear(vty, ifp); } return CMD_SUCCESS; @@ -826,3 +866,135 @@ void install_element_ospf6_clear_intf_auth(void) { install_element(ENABLE_NODE, &clear_ipv6_ospf6_intf_auth_cmd); } + +enum ospf6_auth_err ospf6_auth_nvm_file_exist(void) +{ + struct stat buffer; + int exist; + + exist = stat(OSPF6_AUTH_SEQ_NUM_FILE, &buffer); + if (exist == 0) + return OSPF6_AUTH_FILE_EXIST; + else + return OSPF6_AUTH_FILE_DO_NOT_EXIST; +} + +/* + * Record in non-volatile memory the given ospf6 process, + * authentication trailer higher order sequence number. + */ +void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6) +{ + const char *inst_name; + json_object *json; + json_object *json_instances; + json_object *json_instance; + + zlog_err("Higher order sequence number %d update for %s process", + ospf6->seqnum_h, ospf6->name); + + inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; + + json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE); + if (json == NULL) + json = json_object_new_object(); + + json_object_object_get_ex(json, "instances", &json_instances); + if (!json_instances) { + json_instances = json_object_new_object(); + json_object_object_add(json, "instances", json_instances); + } + + json_object_object_get_ex(json_instances, inst_name, &json_instance); + if (!json_instance) { + json_instance = json_object_new_object(); + json_object_object_add(json_instances, inst_name, + json_instance); + } + + /* + * Record higher order sequence number in non volatile memory. + */ + json_object_int_add(json_instance, "sequence_number", ospf6->seqnum_h); + + json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json, + JSON_C_TO_STRING_PRETTY); + json_object_free(json); +} + +/* + * Delete authentication sequence number for a given OSPF6 process + * from non-volatile memory. + */ +void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6) +{ + const char *inst_name; + json_object *json; + json_object *json_instances; + + zlog_err("Higher order sequence number delete for %s process", + ospf6->name); + + inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; + + json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE); + if (json == NULL) + json = json_object_new_object(); + + json_object_object_get_ex(json, "instances", &json_instances); + if (!json_instances) { + json_instances = json_object_new_object(); + json_object_object_add(json, "instances", json_instances); + } + + json_object_object_del(json_instances, inst_name); + + json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json, + JSON_C_TO_STRING_PRETTY); + json_object_free(json); +} + + +/* + * Fetch from non-volatile memory the stored ospf6 process + * authentication sequence number. + */ +void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6) +{ + const char *inst_name; + json_object *json; + json_object *json_instances; + json_object *json_instance; + json_object *json_seqnum; + + inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; + + json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE); + if (json == NULL) + json = json_object_new_object(); + + json_object_object_get_ex(json, "instances", &json_instances); + if (!json_instances) { + json_instances = json_object_new_object(); + json_object_object_add(json, "instances", json_instances); + } + + json_object_object_get_ex(json_instances, inst_name, &json_instance); + if (!json_instance) { + json_instance = json_object_new_object(); + json_object_object_add(json_instances, inst_name, + json_instance); + } + + json_object_object_get_ex(json_instance, "sequence_number", + &json_seqnum); + ospf6->seqnum_h = json_object_get_int(json_seqnum); + + zlog_err("Higher order sequence number %d read for %s process %s", + ospf6->seqnum_h, ospf6->name, strerror(errno)); + + json_object_object_del(json_instances, inst_name); + json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json, + JSON_C_TO_STRING_PRETTY); + json_object_free(json); +} |