summaryrefslogtreecommitdiffstats
path: root/ospf6d/ospf6_auth_trailer.c
diff options
context:
space:
mode:
authorAbhinay Ramesh <rabhinay@vmware.com>2021-05-30 18:33:41 +0200
committerAbhinay Ramesh <rabhinay@vmware.com>2022-02-09 02:57:08 +0100
commit6cb85350df7fdcea106947fdda42a91ddebcdd5e (patch)
tree9b995fe10714480472ba3c4b842ce32d9f6e1fc2 /ospf6d/ospf6_auth_trailer.c
parentospf6d: Core functionality of auth trailer implementation.. (diff)
downloadfrr-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.c500
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);
+}