mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 17:18:56 +00:00
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>
This commit is contained in:
parent
b592ec5ad0
commit
6cb85350df
@ -2587,6 +2587,7 @@ AC_DEFINE_UNQUOTED([ZEBRA_SERV_PATH], ["$frr_statedir%s%s/zserv.api"], [zebra ap
|
|||||||
AC_DEFINE_UNQUOTED([BFDD_CONTROL_SOCKET], ["$frr_statedir%s%s/bfdd.sock"], [bfdd control socket])
|
AC_DEFINE_UNQUOTED([BFDD_CONTROL_SOCKET], ["$frr_statedir%s%s/bfdd.sock"], [bfdd control socket])
|
||||||
AC_DEFINE_UNQUOTED([OSPFD_GR_STATE], ["$frr_statedir%s/ospfd-gr.json"], [ospfd GR state information])
|
AC_DEFINE_UNQUOTED([OSPFD_GR_STATE], ["$frr_statedir%s/ospfd-gr.json"], [ospfd GR state information])
|
||||||
AC_DEFINE_UNQUOTED([OSPF6D_GR_STATE], ["$frr_statedir/ospf6d-gr.json"], [ospf6d GR state information])
|
AC_DEFINE_UNQUOTED([OSPF6D_GR_STATE], ["$frr_statedir/ospf6d-gr.json"], [ospf6d GR state information])
|
||||||
|
AC_DEFINE_UNQUOTED([OSPF6_AUTH_SEQ_NUM_FILE], ["$frr_statedir/ospf6d-at-seq-no.dat"], [ospf6d AT Sequence number information])
|
||||||
AC_DEFINE_UNQUOTED([DAEMON_VTY_DIR], ["$frr_statedir%s%s"], [daemon vty directory])
|
AC_DEFINE_UNQUOTED([DAEMON_VTY_DIR], ["$frr_statedir%s%s"], [daemon vty directory])
|
||||||
AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory])
|
AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory])
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "zebra.h"
|
#include "zebra.h"
|
||||||
|
#include "config.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "ospf6d.h"
|
#include "ospf6d.h"
|
||||||
#include "vty.h"
|
#include "vty.h"
|
||||||
@ -30,14 +31,14 @@
|
|||||||
#include "ospf6_interface.h"
|
#include "ospf6_interface.h"
|
||||||
#include "ospf6_neighbor.h"
|
#include "ospf6_neighbor.h"
|
||||||
#include "ospf6_proto.h"
|
#include "ospf6_proto.h"
|
||||||
|
#include "ospf6_top.h"
|
||||||
|
#include "ospf6_area.h"
|
||||||
#include "ospf6_auth_trailer.h"
|
#include "ospf6_auth_trailer.h"
|
||||||
#include "ospf6_route.h"
|
#include "ospf6_route.h"
|
||||||
#include "ospf6_zebra.h"
|
#include "ospf6_zebra.h"
|
||||||
#include "lib/keychain.h"
|
#include "lib/keychain.h"
|
||||||
|
|
||||||
unsigned char conf_debug_ospf6_auth[2];
|
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");
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH_XOR, "OSPF6 auth hash xor");
|
||||||
|
|
||||||
/*Apad is the hexadecimal value 0x878FE1F3. */
|
/*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;
|
struct ospf6_auth_hdr *ospf6_at_hdr;
|
||||||
int at_len, oh_len, at_hdr_len, hash_len;
|
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);
|
oh_len = ntohs(ospfh->length);
|
||||||
at_len = length - oh_len;
|
at_len = length - (oh_len + lls_len);
|
||||||
if (at_len > 0) {
|
if (at_len > 0) {
|
||||||
ospf6_at_hdr = (struct ospf6_auth_hdr *)
|
ospf6_at_hdr =
|
||||||
((uint8_t *)ospfh + oh_len);
|
(struct ospf6_auth_hdr *)((uint8_t *)ospfh + oh_len);
|
||||||
at_hdr_len = ntohs(ospf6_at_hdr->length);
|
at_hdr_len = ntohs(ospf6_at_hdr->length);
|
||||||
hash_len = at_hdr_len - OSPF6_AUTH_HDR_MIN_SIZE;
|
hash_len = at_hdr_len - OSPF6_AUTH_HDR_MIN_SIZE;
|
||||||
memcpy(temp, ospf6_at_hdr->data, hash_len);
|
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,
|
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_hello *hello = NULL;
|
||||||
struct ospf6_dbdesc *dbdesc = 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;
|
uint16_t hdr_len = 0;
|
||||||
uint32_t oh_seqnum_h = 0;
|
uint32_t oh_seqnum_h = 0;
|
||||||
uint32_t oh_seqnum_l = 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);
|
on = ospf6_neighbor_lookup(oh->router_id, oi);
|
||||||
hdr_len = ntohs(oh->length);
|
hdr_len = ntohs(oh->length);
|
||||||
if (*pkt_len < hdr_len) {
|
if (*pkt_len < hdr_len) {
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX)
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
zlog_warn("RECV[%s] Wrong %s packet auth length",
|
zlog_err("RECV[%s] Received incomplete %s packet",
|
||||||
oi->interface->name,
|
oi->interface->name,
|
||||||
lookup_msg(ospf6_message_type_str, oh->type,
|
ospf6_message_type(oh->type));
|
||||||
NULL));
|
return OSPF6_AUTH_VALIDATE_FAILURE;
|
||||||
oi->at_data.rx_drop++;
|
|
||||||
return -1;
|
|
||||||
} else if (*pkt_len == hdr_len) {
|
} 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) {
|
switch (oh->type) {
|
||||||
case OSPF6_MESSAGE_TYPE_HELLO:
|
case OSPF6_MESSAGE_TYPE_HELLO:
|
||||||
hello = (struct ospf6_hello *)((uint8_t *)oh
|
hello = (struct ospf6_hello *)((uint8_t *)oh
|
||||||
+ sizeof(struct ospf6_header));
|
+ sizeof(struct ospf6_header));
|
||||||
if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT)) {
|
if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_L))
|
||||||
if (on)
|
lls_present = true;
|
||||||
on->auth_present = true;
|
|
||||||
} else {
|
|
||||||
if (on)
|
|
||||||
on->auth_present = false;
|
|
||||||
|
|
||||||
if (oi->at_data.flags != 0) {
|
if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT))
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX)
|
auth_present = true;
|
||||||
zlog_warn("RECV[%s] : Auth option miss-match in hello pkt",
|
|
||||||
oi->interface->name);
|
|
||||||
oi->at_data.rx_drop++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case OSPF6_MESSAGE_TYPE_DBDESC:
|
case OSPF6_MESSAGE_TYPE_DBDESC:
|
||||||
dbdesc = (struct ospf6_dbdesc *)((uint8_t *)oh
|
dbdesc = (struct ospf6_dbdesc *)((uint8_t *)oh
|
||||||
+ sizeof(struct ospf6_header));
|
+ 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 (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT))
|
||||||
if (on)
|
auth_present = true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case OSPF6_MESSAGE_TYPE_LSREQ:
|
case OSPF6_MESSAGE_TYPE_LSREQ:
|
||||||
case OSPF6_MESSAGE_TYPE_LSUPDATE:
|
case OSPF6_MESSAGE_TYPE_LSUPDATE:
|
||||||
case OSPF6_MESSAGE_TYPE_LSACK:
|
case OSPF6_MESSAGE_TYPE_LSACK:
|
||||||
if ((on && on->auth_present == false)
|
if (on) {
|
||||||
&& (oi->at_data.flags != 0)) {
|
lls_present = on->lls_present;
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX)
|
auth_present = on->auth_present;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX)
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
zlog_warn("RECV[%s] : Wrong packet type %d",
|
zlog_err("RECV[%s] : Wrong packet type %d",
|
||||||
oi->interface->name, oh->type);
|
oi->interface->name, oh->type);
|
||||||
return -1;
|
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));
|
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 (ntohs(ospf6_auth_info.length) > OSPF6_AUTH_HDR_FULL) {
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX)
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
zlog_warn("RECV[%s] : Auth config miss-match in %s",
|
zlog_err("RECV[%s] : Wrong auth header length in %s",
|
||||||
oi->interface->name,
|
oi->interface->name,
|
||||||
lookup_msg(ospf6_message_type_str, oh->type,
|
ospf6_message_type(oh->type));
|
||||||
NULL));
|
return OSPF6_AUTH_VALIDATE_FAILURE;
|
||||||
oi->at_data.rx_drop++;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* after authentication header validation is done
|
/* after authentication header validation is done
|
||||||
* reduce the auth hdr size from the packet length
|
* reduce the auth hdr size from the packet length
|
||||||
*/
|
*/
|
||||||
*at_len = ntohs(ospf6_auth_info.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) {
|
if (on) {
|
||||||
oh_seqnum_h = ntohl(ospf6_auth_info.seqnum_h);
|
oh_seqnum_h = ntohl(ospf6_auth_info.seqnum_h);
|
||||||
oh_seqnum_l = ntohl(ospf6_auth_info.seqnum_l);
|
oh_seqnum_l = ntohl(ospf6_auth_info.seqnum_l);
|
||||||
if ((oh_seqnum_h >= on->seqnum_h) &&
|
if ((oh_seqnum_h >= on->seqnum_h[oh->type])
|
||||||
(oh_seqnum_l > on->seqnum_l)) {
|
&& (oh_seqnum_l > on->seqnum_l[oh->type])) {
|
||||||
/* valid sequence number received */
|
/* valid sequence number received */
|
||||||
on->seqnum_h = oh_seqnum_h;
|
on->seqnum_h[oh->type] = oh_seqnum_h;
|
||||||
on->seqnum_l = oh_seqnum_l;
|
on->seqnum_l[oh->type] = oh_seqnum_l;
|
||||||
} else {
|
} else {
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX) {
|
if (IS_OSPF6_DEBUG_AUTH_RX) {
|
||||||
zlog_warn("RECV[%s] : Nbr(%s) Auth Sequence number mismatch",
|
zlog_err(
|
||||||
oi->interface->name, on->name);
|
"RECV[%s] : Nbr(%s) Auth Sequence number mismatch in %s ",
|
||||||
zlog_warn("nbr_seq_l %u, nbr_seq_h %u, hdr_seq_l %u, hdr_seq_h %u",
|
oi->interface->name, on->name,
|
||||||
on->seqnum_l, on->seqnum_h,
|
ospf6_message_type(oh->type));
|
||||||
oh_seqnum_l, oh_seqnum_h);
|
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 OSPF6_AUTH_VALIDATE_FAILURE;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return OSPF6_AUTH_VALIDATE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Starting point of packet process function. */
|
/* Starting point of packet process function. */
|
||||||
int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
|
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;
|
uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE;
|
||||||
unsigned char apad[hash_len];
|
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;
|
uint16_t auth_len = 0;
|
||||||
uint8_t hash_algo = 0;
|
uint8_t hash_algo = 0;
|
||||||
uint16_t oh_len = ntohs(oh->length);
|
uint16_t oh_len = ntohs(oh->length);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (oi->at_data.flags == 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)) {
|
if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
|
||||||
keychain = keychain_lookup(oi->at_data.keychain);
|
keychain = keychain_lookup(oi->at_data.keychain);
|
||||||
if (!keychain) {
|
if (!keychain) {
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX)
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
zlog_warn("RECV[%s]: Keychain does't exist for %s",
|
zlog_err(
|
||||||
oi->interface->name,
|
"RECV[%s]: Keychain does't exist for %s",
|
||||||
lookup_msg(ospf6_message_type_str,
|
oi->interface->name,
|
||||||
oh->type, NULL));
|
ospf6_message_type(oh->type));
|
||||||
oi->at_data.rx_drop++;
|
return OSPF6_AUTH_VALIDATE_FAILURE;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
key = key_lookup_for_accept(keychain, ntohs(ospf6_auth->id));
|
key = key_lookup_for_accept(keychain, ntohs(ospf6_auth->id));
|
||||||
if (!key) {
|
if (!key) {
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX)
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
zlog_warn("RECV[%s]: Auth, Invalid SA for %s",
|
zlog_err("RECV[%s]: Auth, Invalid SA for %s",
|
||||||
oi->interface->name,
|
oi->interface->name,
|
||||||
lookup_msg(ospf6_message_type_str,
|
ospf6_message_type(oh->type));
|
||||||
oh->type, NULL));
|
return OSPF6_AUTH_VALIDATE_FAILURE;
|
||||||
oi->at_data.rx_drop++;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key && key->string
|
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;
|
hash_algo = key->hash_algo;
|
||||||
} else {
|
} else {
|
||||||
if (IS_OSPF6_DEBUG_AUTH_RX)
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
zlog_warn("RECV[%s]: Incomplete keychain config for %s",
|
zlog_err(
|
||||||
oi->interface->name,
|
"RECV[%s]: Incomplete keychain config for %s",
|
||||||
lookup_msg(ospf6_message_type_str,
|
oi->interface->name,
|
||||||
oh->type, NULL));
|
ospf6_message_type(oh->type));
|
||||||
oi->at_data.rx_drop++;
|
return OSPF6_AUTH_VALIDATE_FAILURE;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
} else if (CHECK_FLAG(oi->at_data.flags,
|
} else if (CHECK_FLAG(oi->at_data.flags,
|
||||||
OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
|
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)
|
if (!auth_str)
|
||||||
return -2;
|
return OSPF6_AUTH_VALIDATE_FAILURE;
|
||||||
|
|
||||||
hash_len = keychain_get_hash_len(hash_algo);
|
hash_len = keychain_get_hash_len(hash_algo);
|
||||||
memset(apad, 0, sizeof(hash_len));
|
memset(apad, 0, sizeof(apad));
|
||||||
memset(temp_hash, 0, sizeof(hash_len));
|
memset(temp_hash, 0, sizeof(temp_hash));
|
||||||
|
|
||||||
/* start digest verification */
|
/* start digest verification */
|
||||||
memcpy(apad, src, ipv6_addr_size);
|
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(temp_hash, ospf6_auth->data, hash_len);
|
||||||
memcpy(ospf6_auth->data, apad, hash_len);
|
memcpy(ospf6_auth->data, apad, hash_len);
|
||||||
|
|
||||||
ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, auth_len,
|
ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str,
|
||||||
(oh_len + auth_len), hash_algo);
|
(oh_len + auth_len + lls_block_len),
|
||||||
|
hash_algo);
|
||||||
|
|
||||||
#ifdef CRYPTO_OPENSSL
|
#ifdef CRYPTO_OPENSSL
|
||||||
return !(CRYPTO_memcmp(temp_hash, ospf6_auth->data, hash_len));
|
ret = CRYPTO_memcmp(temp_hash, ospf6_auth->data, hash_len);
|
||||||
#else
|
#else
|
||||||
return !(memcmp(temp_hash, ospf6_auth->data, hash_len));
|
ret = memcmp(temp_hash, ospf6_auth->data, hash_len);
|
||||||
#endif
|
#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,
|
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;
|
uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE;
|
||||||
unsigned char apad[hash_len];
|
unsigned char apad[hash_len];
|
||||||
int ipv6_addr_size = sizeof(struct in6_addr);
|
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, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
|
||||||
if (CHECK_FLAG(oi->at_data.flags,
|
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)
|
if (IS_OSPF6_DEBUG_AUTH_TX)
|
||||||
zlog_warn("SEND[%s]: Authentication not configured for %s",
|
zlog_warn("SEND[%s]: Authentication not configured for %s",
|
||||||
oi->interface->name,
|
oi->interface->name,
|
||||||
lookup_msg(ospf6_message_type_str,
|
ospf6_message_type(oh->type));
|
||||||
oh->type, NULL));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,27 +605,33 @@ void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,
|
|||||||
if (IS_OSPF6_DEBUG_AUTH_TX)
|
if (IS_OSPF6_DEBUG_AUTH_TX)
|
||||||
zlog_warn("SEND[%s]: Authentication key is not configured for %s",
|
zlog_warn("SEND[%s]: Authentication key is not configured for %s",
|
||||||
oi->interface->name,
|
oi->interface->name,
|
||||||
lookup_msg(ospf6_message_type_str,
|
ospf6_message_type(oh->type));
|
||||||
oh->type, NULL));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_len = keychain_get_hash_len(hash_algo);
|
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) {
|
ospf6->seqnum_l++;
|
||||||
oi->at_data.seqnum_h++;
|
if (ospf6->seqnum_l == 0xFFFFFFFF) {
|
||||||
oi->at_data.seqnum_l = 0;
|
ospf6->seqnum_h++;
|
||||||
|
ospf6->seqnum_l = 0;
|
||||||
|
ospf6_auth_seqno_nvm_update(ospf6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Key must be reset. which is not handled as of now. */
|
/* Key must be reset. which is not handled as of now. */
|
||||||
if ((oi->at_data.seqnum_l == 0xFFFFFFFF)
|
if ((ospf6->seqnum_l == 0xFFFFFFFF)
|
||||||
&& (oi->at_data.seqnum_h == 0xFFFFFFFF)) {
|
&& (ospf6->seqnum_h == 0xFFFFFFFF)) {
|
||||||
oi->at_data.seqnum_l = 0;
|
ospf6->seqnum_l = 0;
|
||||||
oi->at_data.seqnum_h = 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)
|
if (src)
|
||||||
memcpy(apad, src, ipv6_addr_size);
|
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->length = htons(auth_len);
|
||||||
ospf6_auth->reserved = 0;
|
ospf6_auth->reserved = 0;
|
||||||
ospf6_auth->id = htons(key_id);
|
ospf6_auth->id = htons(key_id);
|
||||||
ospf6_auth->seqnum_h = htonl(oi->at_data.seqnum_h);
|
ospf6_auth->seqnum_h = htonl(ospf6->seqnum_h);
|
||||||
ospf6_auth->seqnum_l = htonl(oi->at_data.seqnum_l);
|
ospf6_auth->seqnum_l = htonl(ospf6->seqnum_l);
|
||||||
memcpy(ospf6_auth->data, apad, hash_len);
|
memcpy(ospf6_auth->data, apad, hash_len);
|
||||||
|
|
||||||
ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, auth_len,
|
ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, pkt_len,
|
||||||
pkt_len, hash_algo);
|
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)) {
|
if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {
|
||||||
oi->at_data.hash_algo = KEYCHAIN_ALGO_NULL;
|
oi->at_data.hash_algo = KEYCHAIN_ALGO_NULL;
|
||||||
if (oi->at_data.auth_key) {
|
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,
|
void ospf6_auth_update_digest(struct ospf6_interface *oi,
|
||||||
struct ospf6_header *oh,
|
struct ospf6_header *oh,
|
||||||
struct ospf6_auth_hdr *ospf6_auth, char *auth_str,
|
struct ospf6_auth_hdr *ospf6_auth, char *auth_str,
|
||||||
uint16_t auth_len, uint32_t pkt_len,
|
uint32_t pkt_len, enum keychain_hash_algo algo)
|
||||||
enum keychain_hash_algo algo)
|
|
||||||
{
|
{
|
||||||
|
static const uint16_t cpid = 1;
|
||||||
uint32_t hash_len = keychain_get_hash_len(algo);
|
uint32_t hash_len = keychain_get_hash_len(algo);
|
||||||
uint32_t block_s = keychain_get_block_size(algo);
|
uint32_t block_s = keychain_get_block_size(algo);
|
||||||
uint32_t k_len = strlen(auth_str);
|
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 ipad[block_s];
|
||||||
unsigned char opad[block_s];
|
unsigned char opad[block_s];
|
||||||
unsigned char ko[block_s], ks[ks_len], tmp[hash_len];
|
unsigned char ko[block_s], ks[ks_len], tmp[hash_len];
|
||||||
unsigned char *first = NULL;
|
unsigned char *first = NULL;
|
||||||
unsigned char *second = NULL;
|
unsigned char *second = NULL;
|
||||||
unsigned char *first_mes, *second_mes;
|
unsigned char first_mes[block_s + pkt_len];
|
||||||
unsigned char *first_hash, *second_hash;
|
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, auth_str, k_len);
|
||||||
memcpy(ks + k_len, &CPID, sizeof(CPID));
|
memcpy(ks + k_len, &cpid, sizeof(cpid));
|
||||||
if (ks_len > hash_len) {
|
if (ks_len > hash_len) {
|
||||||
ospf6_hash_hmac_sha_digest(algo, ks, ks_len, tmp);
|
ospf6_hash_hmac_sha_digest(algo, ks, ks_len, tmp);
|
||||||
memcpy(ko, tmp, hash_len);
|
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);
|
first = ospf6_hash_message_xor((unsigned char *)&ipad, ko, block_s);
|
||||||
second = ospf6_hash_message_xor((unsigned char *)&opad, 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, first, block_s);
|
||||||
memcpy(first_mes + block_s, oh, pkt_len);
|
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),
|
ospf6_hash_hmac_sha_digest(algo, first_mes, (block_s + pkt_len),
|
||||||
first_hash);
|
first_hash);
|
||||||
|
|
||||||
second_mes = XMALLOC(MTYPE_OSPF6_AUTH_PKT, (block_s + hash_len));
|
|
||||||
|
|
||||||
memcpy(second_mes, second, block_s);
|
memcpy(second_mes, second, block_s);
|
||||||
memcpy(second_mes + block_s, first_hash, hash_len);
|
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),
|
ospf6_hash_hmac_sha_digest(algo, second_mes, (block_s + hash_len),
|
||||||
second_hash);
|
second_hash);
|
||||||
|
|
||||||
memcpy(ospf6_auth->data, second_hash, hash_len);
|
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, first);
|
||||||
XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, second);
|
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 */
|
/* Clear interface */
|
||||||
DEFUN(clear_ipv6_ospf6_intf_auth,
|
DEFUN(clear_ipv6_ospf6_intf_auth, clear_ipv6_ospf6_intf_auth_cmd,
|
||||||
clear_ipv6_ospf6_intf_auth_cmd,
|
"clear ipv6 ospf6 [vrf VRF] auth-counters interface [IFNAME]",
|
||||||
"clear ipv6 ospf6 auth-counters interface [IFNAME]",
|
CLEAR_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
|
||||||
CLEAR_STR
|
"authentication rx/tx drop counters\n" INTERFACE_STR IFNAME_STR)
|
||||||
IP6_STR
|
|
||||||
OSPF6_STR
|
|
||||||
"authentication rx/tx drop counters\n"
|
|
||||||
INTERFACE_STR
|
|
||||||
IFNAME_STR)
|
|
||||||
{
|
{
|
||||||
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
int idx_ifname = 0;
|
||||||
int idx_ifname = 5;
|
int idx_vrf = 0;
|
||||||
struct interface *ifp;
|
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 (argc == 5) { /* Clear all the ospfv3 interfaces. */
|
if (argv_find(argv, argc, "vrf", &idx_vrf))
|
||||||
FOR_ALL_INTERFACES (vrf, ifp)
|
vrf_name = argv[idx_vrf + 1]->arg;
|
||||||
ospf6_intf_auth_clear(vty, ifp);
|
|
||||||
} else { /* Interface name is specified. */
|
if (vrf_name && strmatch(vrf_name, VRF_DEFAULT_NAME))
|
||||||
ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT);
|
vrf_name = NULL;
|
||||||
if (ifp == NULL) {
|
|
||||||
vty_out(vty, "Error: No such Interface: %s\n",
|
if (vrf_name) {
|
||||||
argv[idx_ifname]->arg);
|
vrf = vrf_lookup_by_name(vrf_name);
|
||||||
return CMD_WARNING;
|
if (vrf)
|
||||||
|
vrf_id = vrf->vrf_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
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);
|
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);
|
||||||
|
}
|
||||||
|
@ -27,12 +27,12 @@
|
|||||||
#define OSPF6_AUTH_HDR_MIN_SIZE 16
|
#define OSPF6_AUTH_HDR_MIN_SIZE 16
|
||||||
#define OSPF6_AUTH_HDR_FULL KEYCHAIN_MAX_HASH_SIZE + OSPF6_AUTH_HDR_MIN_SIZE
|
#define OSPF6_AUTH_HDR_FULL KEYCHAIN_MAX_HASH_SIZE + OSPF6_AUTH_HDR_MIN_SIZE
|
||||||
|
|
||||||
#define OSPF6_AUTHENTICATION_NULL 0
|
#define OSPF6_AUTHENTICATION_NULL 0
|
||||||
#define OSPF6_AUTHENTICATION_CRYPTOGRAPHIC 1
|
#define OSPF6_AUTHENTICATION_CRYPTOGRAPHIC 1
|
||||||
static const uint16_t CPID = 1;
|
|
||||||
|
|
||||||
/* Auth debug options */
|
/* Auth debug options */
|
||||||
extern unsigned char conf_debug_ospf6_auth[2];
|
extern unsigned char conf_debug_ospf6_auth[2];
|
||||||
|
|
||||||
#define OSPF6_AUTH_TX 0
|
#define OSPF6_AUTH_TX 0
|
||||||
#define OSPF6_AUTH_RX 1
|
#define OSPF6_AUTH_RX 1
|
||||||
#define OSPF6_DEBUG_AUTH_TX_ON() (conf_debug_ospf6_auth[OSPF6_AUTH_TX] = 1)
|
#define OSPF6_DEBUG_AUTH_TX_ON() (conf_debug_ospf6_auth[OSPF6_AUTH_TX] = 1)
|
||||||
@ -57,24 +57,37 @@ struct ospf6_auth_hdr {
|
|||||||
unsigned char data[KEYCHAIN_MAX_HASH_SIZE];
|
unsigned char data[KEYCHAIN_MAX_HASH_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ospf6_auth_err {
|
||||||
|
OSPF6_AUTH_VALIDATE_SUCCESS = 0,
|
||||||
|
OSPF6_AUTH_VALIDATE_FAILURE,
|
||||||
|
OSPF6_AUTH_PROCESS_NORMAL,
|
||||||
|
OSPF6_AUTH_FILE_EXIST,
|
||||||
|
OSPF6_AUTH_FILE_DO_NOT_EXIST
|
||||||
|
};
|
||||||
|
|
||||||
void ospf6_auth_hdr_dump_send(struct ospf6_header *ospfh, uint16_t length);
|
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);
|
||||||
unsigned char *ospf6_hash_message_xor(unsigned char *mes1, unsigned char *mes2,
|
unsigned char *ospf6_hash_message_xor(unsigned char *mes1, unsigned char *mes2,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
unsigned int ospf6_auth_len_get(struct ospf6_interface *oi);
|
unsigned int ospf6_auth_len_get(struct ospf6_interface *oi);
|
||||||
int ospf6_auth_validate_pkt(struct ospf6_interface *oi, unsigned int *pkt_len,
|
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);
|
||||||
int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
|
int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
|
||||||
struct in6_addr *src);
|
struct in6_addr *src, unsigned int lls_len);
|
||||||
void ospf6_auth_update_digest(struct ospf6_interface *oi,
|
void ospf6_auth_update_digest(struct ospf6_interface *oi,
|
||||||
struct ospf6_header *oh,
|
struct ospf6_header *oh,
|
||||||
struct ospf6_auth_hdr *ospf6_auth, char *auth_str,
|
struct ospf6_auth_hdr *ospf6_auth, char *auth_str,
|
||||||
uint16_t auth_len, uint32_t pkt_len,
|
uint32_t pkt_len, enum keychain_hash_algo algo);
|
||||||
enum keychain_hash_algo algo);
|
|
||||||
void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,
|
void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,
|
||||||
struct ospf6_header *oh, uint16_t auth_len,
|
struct ospf6_header *oh, uint16_t auth_len,
|
||||||
uint32_t pkt_len);
|
uint32_t pkt_len);
|
||||||
void install_element_ospf6_debug_auth(void);
|
void install_element_ospf6_debug_auth(void);
|
||||||
int config_write_ospf6_debug_auth(struct vty *vty);
|
int config_write_ospf6_debug_auth(struct vty *vty);
|
||||||
void install_element_ospf6_clear_intf_auth(void);
|
void install_element_ospf6_clear_intf_auth(void);
|
||||||
|
enum ospf6_auth_err ospf6_auth_nvm_file_exist(void);
|
||||||
|
void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6);
|
||||||
|
void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6);
|
||||||
|
void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6);
|
||||||
#endif /* __OSPF6_AUTH_TRAILER_H__ */
|
#endif /* __OSPF6_AUTH_TRAILER_H__ */
|
||||||
|
@ -1260,10 +1260,6 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
|
|||||||
OSPF6_AUTH_TRAILER_MANUAL_KEY))
|
OSPF6_AUTH_TRAILER_MANUAL_KEY))
|
||||||
json_object_string_add(json_auth, "authType",
|
json_object_string_add(json_auth, "authType",
|
||||||
"manualkey");
|
"manualkey");
|
||||||
json_object_int_add(json_auth, "higherSegNo",
|
|
||||||
oi->at_data.seqnum_h);
|
|
||||||
json_object_int_add(json_auth, "lowerSegNo",
|
|
||||||
oi->at_data.seqnum_l);
|
|
||||||
json_object_int_add(json_auth, "txPktDrop",
|
json_object_int_add(json_auth, "txPktDrop",
|
||||||
oi->at_data.tx_drop);
|
oi->at_data.tx_drop);
|
||||||
json_object_int_add(json_auth, "rxPktDrop",
|
json_object_int_add(json_auth, "rxPktDrop",
|
||||||
@ -1278,20 +1274,15 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
|
|||||||
OSPF6_AUTH_TRAILER_MANUAL_KEY))
|
OSPF6_AUTH_TRAILER_MANUAL_KEY))
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
" Authentication trailer is enabled with manual key\n");
|
" Authentication trailer is enabled with manual key\n");
|
||||||
|
|
||||||
vty_out(vty,
|
|
||||||
" Higher sequence no %u, Lower sequence no %u\n",
|
|
||||||
oi->at_data.seqnum_h, oi->at_data.seqnum_l);
|
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
" Packet drop Tx %u, Packet drop Rx %u\n",
|
" Packet drop Tx %u, Packet drop Rx %u\n",
|
||||||
oi->at_data.tx_drop, oi->at_data.rx_drop);
|
oi->at_data.tx_drop, oi->at_data.rx_drop);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (use_json) {
|
if (use_json)
|
||||||
json_object_string_add(json_auth, "authType", "NULL");
|
json_object_string_add(json_auth, "authType", "NULL");
|
||||||
} else {
|
else
|
||||||
vty_out(vty, " Authentication Trailer is disabled\n");
|
vty_out(vty, " Authentication Trailer is disabled\n");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_json)
|
if (use_json)
|
||||||
|
@ -35,32 +35,18 @@ extern unsigned char conf_debug_ospf6_interface;
|
|||||||
#define IS_OSPF6_DEBUG_INTERFACE (conf_debug_ospf6_interface)
|
#define IS_OSPF6_DEBUG_INTERFACE (conf_debug_ospf6_interface)
|
||||||
|
|
||||||
struct ospf6_auth_data {
|
struct ospf6_auth_data {
|
||||||
/* higher order Sequence Number */
|
/* config data */
|
||||||
uint32_t seqnum_h;
|
uint8_t hash_algo; /* hash algorithm type */
|
||||||
|
uint16_t key_id; /* key-id used as SA in auth packet */
|
||||||
|
char *auth_key; /* Auth key */
|
||||||
|
char *keychain; /* keychain name */
|
||||||
|
|
||||||
/* lower order Sequence Number */
|
/* operational data */
|
||||||
uint32_t seqnum_l;
|
uint8_t flags; /* Flags related to auth config */
|
||||||
|
|
||||||
/* Packet drop due to auth failure while sending */
|
/* Counters and Statistics */
|
||||||
uint32_t tx_drop;
|
uint32_t tx_drop; /* Pkt drop due to auth fail while sending */
|
||||||
|
uint32_t rx_drop; /* Pkt drop due to auth fail while reading */
|
||||||
/* Packet drop due to auth failure while reading */
|
|
||||||
uint32_t rx_drop;
|
|
||||||
|
|
||||||
/* hash algorithm type */
|
|
||||||
uint8_t hash_algo;
|
|
||||||
|
|
||||||
/* Flags related to auth config */
|
|
||||||
uint8_t flags;
|
|
||||||
|
|
||||||
/* key-id used as security association in auth packet */
|
|
||||||
uint16_t key_id;
|
|
||||||
|
|
||||||
/* Auth key */
|
|
||||||
char *auth_key;
|
|
||||||
|
|
||||||
/* keychain name */
|
|
||||||
char *keychain;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Interface structure */
|
/* Interface structure */
|
||||||
|
@ -2148,7 +2148,7 @@ static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
|
|||||||
char installed[64], changed[64];
|
char installed[64], changed[64];
|
||||||
struct timeval now, res;
|
struct timeval now, res;
|
||||||
char id[16], adv_router[16];
|
char id[16], adv_router[16];
|
||||||
char capa[16], options[16];
|
char capa[16], options[32];
|
||||||
|
|
||||||
brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
|
brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
|
||||||
inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name));
|
inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name));
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "linklist.h"
|
#include "linklist.h"
|
||||||
#include "lib_errors.h"
|
#include "lib_errors.h"
|
||||||
|
#include "checksum.h"
|
||||||
|
|
||||||
#include "ospf6_proto.h"
|
#include "ospf6_proto.h"
|
||||||
#include "ospf6_lsa.h"
|
#include "ospf6_lsa.h"
|
||||||
@ -48,19 +49,34 @@
|
|||||||
#include "ospf6d.h"
|
#include "ospf6d.h"
|
||||||
#include "ospf6_gr.h"
|
#include "ospf6_gr.h"
|
||||||
#include <netinet/ip6.h>
|
#include <netinet/ip6.h>
|
||||||
|
#include "lib/libospf.h"
|
||||||
|
#include "lib/keychain.h"
|
||||||
|
#include "ospf6_auth_trailer.h"
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message");
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message");
|
||||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PACKET, "OSPF6 packet");
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PACKET, "OSPF6 packet");
|
||||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6 FIFO queue");
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6 FIFO queue");
|
||||||
|
|
||||||
unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
|
unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
|
||||||
static const struct message ospf6_message_type_str[] = {
|
|
||||||
{OSPF6_MESSAGE_TYPE_HELLO, "Hello"},
|
const char *ospf6_message_type(int type)
|
||||||
{OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc"},
|
{
|
||||||
{OSPF6_MESSAGE_TYPE_LSREQ, "LSReq"},
|
switch (type) {
|
||||||
{OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate"},
|
case OSPF6_MESSAGE_TYPE_HELLO:
|
||||||
{OSPF6_MESSAGE_TYPE_LSACK, "LSAck"},
|
return "Hello";
|
||||||
{0}};
|
case OSPF6_MESSAGE_TYPE_DBDESC:
|
||||||
|
return "DbDesc";
|
||||||
|
case OSPF6_MESSAGE_TYPE_LSREQ:
|
||||||
|
return "LSReq";
|
||||||
|
case OSPF6_MESSAGE_TYPE_LSUPDATE:
|
||||||
|
return "LSUpdate";
|
||||||
|
case OSPF6_MESSAGE_TYPE_LSACK:
|
||||||
|
return "LSAck";
|
||||||
|
case OSPF6_MESSAGE_TYPE_UNKNOWN:
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Minimum (besides the standard OSPF packet header) lengths for OSPF
|
/* Minimum (besides the standard OSPF packet header) lengths for OSPF
|
||||||
packets of particular types, offset is the "type" field. */
|
packets of particular types, offset is the "type" field. */
|
||||||
@ -101,7 +117,7 @@ static void ospf6_header_print(struct ospf6_header *oh)
|
|||||||
void ospf6_hello_print(struct ospf6_header *oh, int action)
|
void ospf6_hello_print(struct ospf6_header *oh, int action)
|
||||||
{
|
{
|
||||||
struct ospf6_hello *hello;
|
struct ospf6_hello *hello;
|
||||||
char options[16];
|
char options[32];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
ospf6_header_print(oh);
|
ospf6_header_print(oh);
|
||||||
@ -136,7 +152,7 @@ void ospf6_hello_print(struct ospf6_header *oh, int action)
|
|||||||
void ospf6_dbdesc_print(struct ospf6_header *oh, int action)
|
void ospf6_dbdesc_print(struct ospf6_header *oh, int action)
|
||||||
{
|
{
|
||||||
struct ospf6_dbdesc *dbdesc;
|
struct ospf6_dbdesc *dbdesc;
|
||||||
char options[16];
|
char options[32];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
ospf6_header_print(oh);
|
ospf6_header_print(oh);
|
||||||
@ -439,6 +455,20 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (((OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT) ==
|
||||||
|
OSPF6_OPT_AT) &&
|
||||||
|
(oi->at_data.flags == 0)) ||
|
||||||
|
((OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT) !=
|
||||||
|
OSPF6_OPT_AT) &&
|
||||||
|
(oi->at_data.flags != 0))) {
|
||||||
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
|
zlog_warn(
|
||||||
|
"VRF %s: IF %s AT-bit mismatch in hello packet",
|
||||||
|
oi->interface->vrf->name, oi->interface->name);
|
||||||
|
oi->at_data.rx_drop++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find neighbor, create if not exist */
|
/* Find neighbor, create if not exist */
|
||||||
on = ospf6_neighbor_lookup(oh->router_id, oi);
|
on = ospf6_neighbor_lookup(oh->router_id, oi);
|
||||||
if (on == NULL) {
|
if (on == NULL) {
|
||||||
@ -1006,6 +1036,20 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
|
|||||||
dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
|
dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
|
||||||
+ sizeof(struct ospf6_header));
|
+ sizeof(struct ospf6_header));
|
||||||
|
|
||||||
|
if (((OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT) ==
|
||||||
|
OSPF6_OPT_AT) &&
|
||||||
|
(oi->at_data.flags == 0)) ||
|
||||||
|
((OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT) !=
|
||||||
|
OSPF6_OPT_AT) &&
|
||||||
|
(oi->at_data.flags != 0))) {
|
||||||
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
|
zlog_warn(
|
||||||
|
"VRF %s: IF %s AT-bit mismatch in dbdesc packet",
|
||||||
|
oi->interface->vrf->name, oi->interface->name);
|
||||||
|
oi->at_data.rx_drop++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Interface MTU check */
|
/* Interface MTU check */
|
||||||
if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) {
|
if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) {
|
||||||
zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
|
zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
|
||||||
@ -1412,14 +1456,15 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
|
|||||||
bytesonwire);
|
bytesonwire);
|
||||||
return MSG_NG;
|
return MSG_NG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now it is safe to access header fields. */
|
/* Now it is safe to access header fields. */
|
||||||
if (bytesonwire != ntohs(oh->length)) {
|
if (bytesonwire != ntohs(oh->length)) {
|
||||||
zlog_warn("%s: %s packet length error (%u real, %u declared)",
|
zlog_warn("%s: %s packet length error (%u real, %u declared)",
|
||||||
__func__,
|
__func__, ospf6_message_type(oh->type), bytesonwire,
|
||||||
lookup_msg(ospf6_message_type_str, oh->type, NULL),
|
ntohs(oh->length));
|
||||||
bytesonwire, ntohs(oh->length));
|
|
||||||
return MSG_NG;
|
return MSG_NG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* version check */
|
/* version check */
|
||||||
if (oh->version != OSPFV3_VERSION) {
|
if (oh->version != OSPFV3_VERSION) {
|
||||||
zlog_warn("%s: invalid (%u) protocol version", __func__,
|
zlog_warn("%s: invalid (%u) protocol version", __func__,
|
||||||
@ -1431,8 +1476,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
|
|||||||
&& bytesonwire
|
&& bytesonwire
|
||||||
< OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) {
|
< OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) {
|
||||||
zlog_warn("%s: undersized (%u B) %s packet", __func__,
|
zlog_warn("%s: undersized (%u B) %s packet", __func__,
|
||||||
bytesonwire,
|
bytesonwire, ospf6_message_type(oh->type));
|
||||||
lookup_msg(ospf6_message_type_str, oh->type, NULL));
|
|
||||||
return MSG_NG;
|
return MSG_NG;
|
||||||
}
|
}
|
||||||
/* type-specific deeper validation */
|
/* type-specific deeper validation */
|
||||||
@ -1446,7 +1490,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
|
|||||||
% 4)
|
% 4)
|
||||||
return MSG_OK;
|
return MSG_OK;
|
||||||
zlog_warn("%s: alignment error in %s packet", __func__,
|
zlog_warn("%s: alignment error in %s packet", __func__,
|
||||||
lookup_msg(ospf6_message_type_str, oh->type, NULL));
|
ospf6_message_type(oh->type));
|
||||||
return MSG_NG;
|
return MSG_NG;
|
||||||
case OSPF6_MESSAGE_TYPE_DBDESC:
|
case OSPF6_MESSAGE_TYPE_DBDESC:
|
||||||
/* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
|
/* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
|
||||||
@ -1467,7 +1511,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
|
|||||||
% OSPF6_LSREQ_LSDESC_FIX_SIZE)
|
% OSPF6_LSREQ_LSDESC_FIX_SIZE)
|
||||||
return MSG_OK;
|
return MSG_OK;
|
||||||
zlog_warn("%s: alignment error in %s packet", __func__,
|
zlog_warn("%s: alignment error in %s packet", __func__,
|
||||||
lookup_msg(ospf6_message_type_str, oh->type, NULL));
|
ospf6_message_type(oh->type));
|
||||||
return MSG_NG;
|
return MSG_NG;
|
||||||
case OSPF6_MESSAGE_TYPE_LSUPDATE:
|
case OSPF6_MESSAGE_TYPE_LSUPDATE:
|
||||||
/* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
|
/* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
|
||||||
@ -1497,7 +1541,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
|
|||||||
}
|
}
|
||||||
if (test != MSG_OK)
|
if (test != MSG_OK)
|
||||||
zlog_warn("%s: anomaly in %s packet", __func__,
|
zlog_warn("%s: anomaly in %s packet", __func__,
|
||||||
lookup_msg(ospf6_message_type_str, oh->type, NULL));
|
ospf6_message_type(oh->type));
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1727,6 +1771,9 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
|
|||||||
struct iovec iovector[2];
|
struct iovec iovector[2];
|
||||||
struct ospf6_interface *oi;
|
struct ospf6_interface *oi;
|
||||||
struct ospf6_header *oh;
|
struct ospf6_header *oh;
|
||||||
|
enum ospf6_auth_err ret = OSPF6_AUTH_PROCESS_NORMAL;
|
||||||
|
uint32_t at_len = 0;
|
||||||
|
uint32_t lls_len = 0;
|
||||||
|
|
||||||
/* initialize */
|
/* initialize */
|
||||||
memset(&src, 0, sizeof(src));
|
memset(&src, 0, sizeof(src));
|
||||||
@ -1772,6 +1819,24 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
|
|||||||
return OSPF6_READ_CONTINUE;
|
return OSPF6_READ_CONTINUE;
|
||||||
|
|
||||||
oh = (struct ospf6_header *)recvbuf;
|
oh = (struct ospf6_header *)recvbuf;
|
||||||
|
ret = ospf6_auth_validate_pkt(oi, (uint32_t *)&len, oh, &at_len,
|
||||||
|
&lls_len);
|
||||||
|
if (ret == OSPF6_AUTH_VALIDATE_SUCCESS) {
|
||||||
|
ret = ospf6_auth_check_digest(oh, oi, &src, lls_len);
|
||||||
|
if (ret == OSPF6_AUTH_VALIDATE_FAILURE) {
|
||||||
|
if (IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
|
zlog_err(
|
||||||
|
"RECV[%s]: OSPF packet auth digest miss-match on %s",
|
||||||
|
oi->interface->name,
|
||||||
|
ospf6_message_type(oh->type));
|
||||||
|
oi->at_data.rx_drop++;
|
||||||
|
return OSPF6_READ_CONTINUE;
|
||||||
|
}
|
||||||
|
} else if (ret == OSPF6_AUTH_VALIDATE_FAILURE) {
|
||||||
|
oi->at_data.rx_drop++;
|
||||||
|
return OSPF6_READ_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (ospf6_rxpacket_examin(oi, oh, len) != MSG_OK)
|
if (ospf6_rxpacket_examin(oi, oh, len) != MSG_OK)
|
||||||
return OSPF6_READ_CONTINUE;
|
return OSPF6_READ_CONTINUE;
|
||||||
|
|
||||||
@ -1782,8 +1847,7 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
|
|||||||
|
|
||||||
/* Log */
|
/* Log */
|
||||||
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) {
|
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) {
|
||||||
zlog_debug("%s received on %s",
|
zlog_debug("%s received on %s", ospf6_message_type(oh->type),
|
||||||
lookup_msg(ospf6_message_type_str, oh->type, NULL),
|
|
||||||
oi->interface->name);
|
oi->interface->name);
|
||||||
zlog_debug(" src: %pI6", &src);
|
zlog_debug(" src: %pI6", &src);
|
||||||
zlog_debug(" dst: %pI6", &dst);
|
zlog_debug(" dst: %pI6", &dst);
|
||||||
@ -1807,6 +1871,10 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
|
|||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((at_len != 0) && IS_OSPF6_DEBUG_AUTH_RX)
|
||||||
|
ospf6_auth_hdr_dump_recv(oh, (len + at_len + lls_len),
|
||||||
|
lls_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (oh->type) {
|
switch (oh->type) {
|
||||||
@ -1863,6 +1931,27 @@ int ospf6_receive(struct thread *thread)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ospf6_fill_hdr_checksum(struct ospf6_interface *oi,
|
||||||
|
struct ospf6_packet *op)
|
||||||
|
{
|
||||||
|
struct ipv6_ph ph = {};
|
||||||
|
struct ospf6_header *oh;
|
||||||
|
void *offset = NULL;
|
||||||
|
|
||||||
|
if (oi->at_data.flags != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(&ph.src, oi->linklocal_addr, sizeof(struct in6_addr));
|
||||||
|
memcpy(&ph.dst, &op->dst, sizeof(struct in6_addr));
|
||||||
|
ph.ulpl = htonl(op->length);
|
||||||
|
ph.next_hdr = IPPROTO_OSPFIGP;
|
||||||
|
|
||||||
|
/* Suppress static analysis warnings about accessing icmp6 oob */
|
||||||
|
oh = (struct ospf6_header *)STREAM_DATA(op->s);
|
||||||
|
offset = oh;
|
||||||
|
oh->checksum = in_cksum_with_ph6(&ph, offset, op->length);
|
||||||
|
}
|
||||||
|
|
||||||
static void ospf6_make_header(uint8_t type, struct ospf6_interface *oi,
|
static void ospf6_make_header(uint8_t type, struct ospf6_interface *oi,
|
||||||
struct stream *s)
|
struct stream *s)
|
||||||
{
|
{
|
||||||
@ -1873,6 +1962,7 @@ static void ospf6_make_header(uint8_t type, struct ospf6_interface *oi,
|
|||||||
oh->version = (uint8_t)OSPFV3_VERSION;
|
oh->version = (uint8_t)OSPFV3_VERSION;
|
||||||
oh->type = type;
|
oh->type = type;
|
||||||
oh->length = 0;
|
oh->length = 0;
|
||||||
|
|
||||||
oh->router_id = oi->area->ospf6->router_id;
|
oh->router_id = oi->area->ospf6->router_id;
|
||||||
oh->area_id = oi->area->area_id;
|
oh->area_id = oi->area->area_id;
|
||||||
oh->checksum = 0;
|
oh->checksum = 0;
|
||||||
@ -1904,9 +1994,48 @@ static void ospf6_fill_lsupdate_header(struct stream *s, uint32_t lsa_num)
|
|||||||
lsu->lsa_number = htonl(lsa_num);
|
lsu->lsa_number = htonl(lsa_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface *oi)
|
||||||
|
{
|
||||||
|
char *keychain_name = NULL;
|
||||||
|
struct keychain *keychain = NULL;
|
||||||
|
struct key *key = NULL;
|
||||||
|
|
||||||
|
keychain_name = oi->at_data.keychain;
|
||||||
|
keychain = keychain_lookup(keychain_name);
|
||||||
|
if (keychain) {
|
||||||
|
key = key_lookup_for_send(keychain);
|
||||||
|
if (key && key->string &&
|
||||||
|
key->hash_algo != KEYCHAIN_ALGO_NULL) {
|
||||||
|
/* storing the values so that further
|
||||||
|
* lookup can be avoided. after
|
||||||
|
* processing the digest need to reset
|
||||||
|
* these values
|
||||||
|
*/
|
||||||
|
oi->at_data.hash_algo = key->hash_algo;
|
||||||
|
oi->at_data.auth_key = XSTRDUP(
|
||||||
|
MTYPE_OSPF6_AUTH_MANUAL_KEY, key->string);
|
||||||
|
oi->at_data.key_id = key->index;
|
||||||
|
SET_FLAG(oi->at_data.flags,
|
||||||
|
OSPF6_AUTH_TRAILER_KEYCHAIN_VALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t ospf6_packet_max(struct ospf6_interface *oi)
|
static uint32_t ospf6_packet_max(struct ospf6_interface *oi)
|
||||||
{
|
{
|
||||||
|
int at_len = 0;
|
||||||
|
|
||||||
assert(oi->ifmtu > sizeof(struct ip6_hdr));
|
assert(oi->ifmtu > sizeof(struct ip6_hdr));
|
||||||
|
|
||||||
|
if (oi->at_data.flags != 0) {
|
||||||
|
if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
|
||||||
|
ospf6_auth_trailer_copy_keychain_key(oi);
|
||||||
|
|
||||||
|
at_len += OSPF6_AUTH_HDR_MIN_SIZE;
|
||||||
|
at_len += keychain_get_hash_len(oi->at_data.hash_algo);
|
||||||
|
return oi->ifmtu - (sizeof(struct ip6_hdr)) - at_len;
|
||||||
|
}
|
||||||
|
|
||||||
return oi->ifmtu - (sizeof(struct ip6_hdr));
|
return oi->ifmtu - (sizeof(struct ip6_hdr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1915,11 +2044,15 @@ static uint16_t ospf6_make_hello(struct ospf6_interface *oi, struct stream *s)
|
|||||||
struct listnode *node, *nnode;
|
struct listnode *node, *nnode;
|
||||||
struct ospf6_neighbor *on;
|
struct ospf6_neighbor *on;
|
||||||
uint16_t length = OSPF6_HELLO_MIN_SIZE;
|
uint16_t length = OSPF6_HELLO_MIN_SIZE;
|
||||||
|
uint8_t options1 = oi->area->options[1];
|
||||||
|
|
||||||
|
if (oi->at_data.flags != 0)
|
||||||
|
options1 |= OSPF6_OPT_AT;
|
||||||
|
|
||||||
stream_putl(s, oi->interface->ifindex);
|
stream_putl(s, oi->interface->ifindex);
|
||||||
stream_putc(s, oi->priority);
|
stream_putc(s, oi->priority);
|
||||||
stream_putc(s, oi->area->options[0]);
|
stream_putc(s, oi->area->options[0]);
|
||||||
stream_putc(s, oi->area->options[1]);
|
stream_putc(s, options1);
|
||||||
stream_putc(s, oi->area->options[2]);
|
stream_putc(s, oi->area->options[2]);
|
||||||
stream_putw(s, oi->hello_interval);
|
stream_putw(s, oi->hello_interval);
|
||||||
stream_putw(s, oi->dead_interval);
|
stream_putw(s, oi->dead_interval);
|
||||||
@ -1959,6 +2092,7 @@ static int ospf6_write(struct thread *thread)
|
|||||||
int len;
|
int len;
|
||||||
int64_t latency = 0;
|
int64_t latency = 0;
|
||||||
struct timeval timestamp;
|
struct timeval timestamp;
|
||||||
|
unsigned int at_len = 0;
|
||||||
|
|
||||||
if (ospf6->fd < 0) {
|
if (ospf6->fd < 0) {
|
||||||
zlog_warn("ospf6_write failed to send, fd %d", ospf6->fd);
|
zlog_warn("ospf6_write failed to send, fd %d", ospf6->fd);
|
||||||
@ -1983,17 +2117,32 @@ static int ospf6_write(struct thread *thread)
|
|||||||
|
|
||||||
oh = (struct ospf6_header *)STREAM_DATA(op->s);
|
oh = (struct ospf6_header *)STREAM_DATA(op->s);
|
||||||
|
|
||||||
|
if (oi->at_data.flags != 0) {
|
||||||
|
at_len = ospf6_auth_len_get(oi);
|
||||||
|
if (at_len) {
|
||||||
|
iovector[0].iov_len =
|
||||||
|
ntohs(oh->length) + at_len;
|
||||||
|
ospf6_auth_digest_send(oi->linklocal_addr, oi,
|
||||||
|
oh, at_len,
|
||||||
|
iovector[0].iov_len);
|
||||||
|
} else {
|
||||||
|
iovector[0].iov_len = ntohs(oh->length);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iovector[0].iov_len = ntohs(oh->length);
|
||||||
|
}
|
||||||
|
|
||||||
len = ospf6_sendmsg(oi->linklocal_addr, &op->dst,
|
len = ospf6_sendmsg(oi->linklocal_addr, &op->dst,
|
||||||
oi->interface->ifindex, iovector,
|
oi->interface->ifindex, iovector,
|
||||||
ospf6->fd);
|
ospf6->fd);
|
||||||
if (len != op->length)
|
|
||||||
|
if (len != (op->length + (int)at_len))
|
||||||
flog_err(EC_LIB_DEVELOPMENT,
|
flog_err(EC_LIB_DEVELOPMENT,
|
||||||
"Could not send entire message");
|
"Could not send entire message");
|
||||||
|
|
||||||
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) {
|
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) {
|
||||||
zlog_debug("%s send on %s",
|
zlog_debug("%s send on %s",
|
||||||
lookup_msg(ospf6_message_type_str, oh->type,
|
ospf6_message_type(oh->type),
|
||||||
NULL),
|
|
||||||
oi->interface->name);
|
oi->interface->name);
|
||||||
zlog_debug(" src: %pI6", oi->linklocal_addr);
|
zlog_debug(" src: %pI6", oi->linklocal_addr);
|
||||||
zlog_debug(" dst: %pI6", &op->dst);
|
zlog_debug(" dst: %pI6", &op->dst);
|
||||||
@ -2052,6 +2201,15 @@ static int ospf6_write(struct thread *thread)
|
|||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((oi->at_data.flags != 0) &&
|
||||||
|
(IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) &&
|
||||||
|
(IS_OSPF6_DEBUG_AUTH_TX))
|
||||||
|
ospf6_auth_hdr_dump_send(oh, iovector[0].iov_len);
|
||||||
|
|
||||||
|
/* initialize at_len to 0 for next packet */
|
||||||
|
at_len = 0;
|
||||||
|
|
||||||
/* Now delete packet from queue. */
|
/* Now delete packet from queue. */
|
||||||
ospf6_packet_delete(oi);
|
ospf6_packet_delete(oi);
|
||||||
|
|
||||||
@ -2117,6 +2275,8 @@ int ospf6_hello_send(struct thread *thread)
|
|||||||
|
|
||||||
op->dst = allspfrouters6;
|
op->dst = allspfrouters6;
|
||||||
|
|
||||||
|
ospf6_fill_hdr_checksum(oi, op);
|
||||||
|
|
||||||
/* Add packet to the top of the interface output queue, so that they
|
/* Add packet to the top of the interface output queue, so that they
|
||||||
* can't get delayed by things like long queues of LS Update packets
|
* can't get delayed by things like long queues of LS Update packets
|
||||||
*/
|
*/
|
||||||
@ -2135,6 +2295,10 @@ static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
|
|||||||
{
|
{
|
||||||
uint16_t length = OSPF6_DB_DESC_MIN_SIZE;
|
uint16_t length = OSPF6_DB_DESC_MIN_SIZE;
|
||||||
struct ospf6_lsa *lsa, *lsanext;
|
struct ospf6_lsa *lsa, *lsanext;
|
||||||
|
uint8_t options1 = on->ospf6_if->area->options[1];
|
||||||
|
|
||||||
|
if (on->ospf6_if->at_data.flags != 0)
|
||||||
|
options1 |= OSPF6_OPT_AT;
|
||||||
|
|
||||||
/* if this is initial one, initialize sequence number for DbDesc */
|
/* if this is initial one, initialize sequence number for DbDesc */
|
||||||
if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
|
if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
|
||||||
@ -2145,7 +2309,7 @@ static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
|
|||||||
/* reserved */
|
/* reserved */
|
||||||
stream_putc(s, 0); /* reserved 1 */
|
stream_putc(s, 0); /* reserved 1 */
|
||||||
stream_putc(s, on->ospf6_if->area->options[0]);
|
stream_putc(s, on->ospf6_if->area->options[0]);
|
||||||
stream_putc(s, on->ospf6_if->area->options[1]);
|
stream_putc(s, options1);
|
||||||
stream_putc(s, on->ospf6_if->area->options[2]);
|
stream_putc(s, on->ospf6_if->area->options[2]);
|
||||||
stream_putw(s, on->ospf6_if->ifmtu);
|
stream_putw(s, on->ospf6_if->ifmtu);
|
||||||
stream_putc(s, 0); /* reserved 2 */
|
stream_putc(s, 0); /* reserved 2 */
|
||||||
@ -2212,6 +2376,8 @@ int ospf6_dbdesc_send(struct thread *thread)
|
|||||||
else
|
else
|
||||||
op->dst = on->linklocal_addr;
|
op->dst = on->linklocal_addr;
|
||||||
|
|
||||||
|
ospf6_fill_hdr_checksum(on->ospf6_if, op);
|
||||||
|
|
||||||
ospf6_packet_add(on->ospf6_if, op);
|
ospf6_packet_add(on->ospf6_if, op);
|
||||||
|
|
||||||
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
||||||
@ -2319,6 +2485,7 @@ static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor *on,
|
|||||||
|
|
||||||
(*op)->length = length + OSPF6_HEADER_SIZE;
|
(*op)->length = length + OSPF6_HEADER_SIZE;
|
||||||
(*op)->dst = on->linklocal_addr;
|
(*op)->dst = on->linklocal_addr;
|
||||||
|
ospf6_fill_hdr_checksum(on->ospf6_if, *op);
|
||||||
ospf6_packet_add(on->ospf6_if, *op);
|
ospf6_packet_add(on->ospf6_if, *op);
|
||||||
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
||||||
/* new packet */
|
/* new packet */
|
||||||
@ -2388,6 +2555,7 @@ int ospf6_lsreq_send(struct thread *thread)
|
|||||||
else
|
else
|
||||||
op->dst = on->linklocal_addr;
|
op->dst = on->linklocal_addr;
|
||||||
|
|
||||||
|
ospf6_fill_hdr_checksum(on->ospf6_if, op);
|
||||||
ospf6_packet_add(on->ospf6_if, op);
|
ospf6_packet_add(on->ospf6_if, op);
|
||||||
|
|
||||||
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
||||||
@ -2425,6 +2593,7 @@ static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
|
|||||||
op->dst = alldrouters6;
|
op->dst = alldrouters6;
|
||||||
}
|
}
|
||||||
if (oi) {
|
if (oi) {
|
||||||
|
ospf6_fill_hdr_checksum(oi, op);
|
||||||
ospf6_packet_add(oi, op);
|
ospf6_packet_add(oi, op);
|
||||||
/* If ospf instance is being deleted, send the packet
|
/* If ospf instance is being deleted, send the packet
|
||||||
* immediately
|
* immediately
|
||||||
@ -2502,6 +2671,7 @@ static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor *on,
|
|||||||
else
|
else
|
||||||
(*op)->dst = on->linklocal_addr;
|
(*op)->dst = on->linklocal_addr;
|
||||||
|
|
||||||
|
ospf6_fill_hdr_checksum(on->ospf6_if, *op);
|
||||||
ospf6_packet_add(on->ospf6_if, *op);
|
ospf6_packet_add(on->ospf6_if, *op);
|
||||||
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
||||||
|
|
||||||
@ -2573,6 +2743,7 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
|
|||||||
op->dst = allspfrouters6;
|
op->dst = allspfrouters6;
|
||||||
else
|
else
|
||||||
op->dst = on->linklocal_addr;
|
op->dst = on->linklocal_addr;
|
||||||
|
ospf6_fill_hdr_checksum(on->ospf6_if, op);
|
||||||
ospf6_packet_add(on->ospf6_if, op);
|
ospf6_packet_add(on->ospf6_if, op);
|
||||||
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
||||||
} else
|
} else
|
||||||
@ -2739,6 +2910,7 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
|
|||||||
/* Set packet length, dst and queue to FIFO. */
|
/* Set packet length, dst and queue to FIFO. */
|
||||||
op->length = length;
|
op->length = length;
|
||||||
op->dst = on->linklocal_addr;
|
op->dst = on->linklocal_addr;
|
||||||
|
ospf6_fill_hdr_checksum(on->ospf6_if, op);
|
||||||
ospf6_packet_add(on->ospf6_if, op);
|
ospf6_packet_add(on->ospf6_if, op);
|
||||||
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
|
||||||
|
|
||||||
@ -2823,6 +2995,7 @@ int ospf6_lsack_send_interface(struct thread *thread)
|
|||||||
else
|
else
|
||||||
op->dst = alldrouters6;
|
op->dst = alldrouters6;
|
||||||
|
|
||||||
|
ospf6_fill_hdr_checksum(oi, op);
|
||||||
ospf6_packet_add(oi, op);
|
ospf6_packet_add(oi, op);
|
||||||
OSPF6_MESSAGE_WRITE_ON(oi);
|
OSPF6_MESSAGE_WRITE_ON(oi);
|
||||||
|
|
||||||
|
@ -23,10 +23,9 @@
|
|||||||
|
|
||||||
#define OSPF6_MESSAGE_BUFSIZ 4096
|
#define OSPF6_MESSAGE_BUFSIZ 4096
|
||||||
|
|
||||||
extern const struct message ospf6_message_type_str[];
|
|
||||||
|
|
||||||
/* Debug option */
|
/* Debug option */
|
||||||
extern unsigned char conf_debug_ospf6_message[];
|
extern unsigned char conf_debug_ospf6_message[];
|
||||||
|
|
||||||
#define OSPF6_ACTION_SEND 0x01
|
#define OSPF6_ACTION_SEND 0x01
|
||||||
#define OSPF6_ACTION_RECV 0x02
|
#define OSPF6_ACTION_RECV 0x02
|
||||||
#define OSPF6_DEBUG_MESSAGE_SEND 0x01
|
#define OSPF6_DEBUG_MESSAGE_SEND 0x01
|
||||||
@ -64,6 +63,7 @@ extern unsigned char conf_debug_ospf6_message[];
|
|||||||
#define OSPF6_MESSAGE_TYPE_LSUPDATE 0x4 /* Database update */
|
#define OSPF6_MESSAGE_TYPE_LSUPDATE 0x4 /* Database update */
|
||||||
#define OSPF6_MESSAGE_TYPE_LSACK 0x5 /* Flooding acknowledgment */
|
#define OSPF6_MESSAGE_TYPE_LSACK 0x5 /* Flooding acknowledgment */
|
||||||
#define OSPF6_MESSAGE_TYPE_ALL 0x6 /* For debug option */
|
#define OSPF6_MESSAGE_TYPE_ALL 0x6 /* For debug option */
|
||||||
|
#define OSPF6_MESSAGE_TYPE_MAX 0x6 /* same as OSPF6_MESSAGE_TYPE_ALL */
|
||||||
|
|
||||||
struct ospf6_packet {
|
struct ospf6_packet {
|
||||||
struct ospf6_packet *next;
|
struct ospf6_packet *next;
|
||||||
@ -148,8 +148,16 @@ struct ospf6_lsupdate {
|
|||||||
/* Followed by LSAs */
|
/* Followed by LSAs */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* LLS is not supported, but used to derive
|
||||||
|
* offset of Auth_trailer
|
||||||
|
*/
|
||||||
|
struct ospf6_lls_hdr {
|
||||||
|
uint16_t checksum;
|
||||||
|
uint16_t length;
|
||||||
|
};
|
||||||
|
|
||||||
/* Link State Acknowledgement */
|
/* Link State Acknowledgement */
|
||||||
#define OSPF6_LS_ACK_MIN_SIZE 0U
|
#define OSPF6_LS_ACK_MIN_SIZE 0U
|
||||||
/* It is just a sequence of LSA Headers */
|
/* It is just a sequence of LSA Headers */
|
||||||
|
|
||||||
/* Function definition */
|
/* Function definition */
|
||||||
@ -178,5 +186,5 @@ extern int ospf6_lsack_send_neighbor(struct thread *thread);
|
|||||||
|
|
||||||
extern int config_write_ospf6_debug_message(struct vty *);
|
extern int config_write_ospf6_debug_message(struct vty *);
|
||||||
extern void install_element_ospf6_debug_message(void);
|
extern void install_element_ospf6_debug_message(void);
|
||||||
|
extern const char *ospf6_message_type(int type);
|
||||||
#endif /* OSPF6_MESSAGE_H */
|
#endif /* OSPF6_MESSAGE_H */
|
||||||
|
@ -112,6 +112,7 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
|
|||||||
{
|
{
|
||||||
struct ospf6_neighbor *on;
|
struct ospf6_neighbor *on;
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
int type;
|
||||||
|
|
||||||
on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor));
|
on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor));
|
||||||
inet_ntop(AF_INET, &router_id, buf, sizeof(buf));
|
inet_ntop(AF_INET, &router_id, buf, sizeof(buf));
|
||||||
@ -131,6 +132,13 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
|
|||||||
on->lsupdate_list = ospf6_lsdb_create(on);
|
on->lsupdate_list = ospf6_lsdb_create(on);
|
||||||
on->lsack_list = ospf6_lsdb_create(on);
|
on->lsack_list = ospf6_lsdb_create(on);
|
||||||
|
|
||||||
|
for (type = 0; type < OSPF6_MESSAGE_TYPE_MAX; type++) {
|
||||||
|
on->seqnum_l[type] = 0;
|
||||||
|
on->seqnum_h[type] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
on->auth_present = false;
|
||||||
|
|
||||||
listnode_add_sort(oi->neighbor_list, on);
|
listnode_add_sort(oi->neighbor_list, on);
|
||||||
|
|
||||||
ospf6_bfd_info_nbr_create(oi, on);
|
ospf6_bfd_info_nbr_create(oi, on);
|
||||||
@ -935,8 +943,44 @@ static void ospf6_neighbor_show_detail(struct vty *vty,
|
|||||||
|
|
||||||
bfd_sess_show(vty, json_neighbor, on->bfd_session);
|
bfd_sess_show(vty, json_neighbor, on->bfd_session);
|
||||||
|
|
||||||
json_object_object_add(json, on->name, json_neighbor);
|
if (on->auth_present == true) {
|
||||||
|
json_object_string_add(json_neighbor, "authStatus",
|
||||||
|
"enabled");
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdHelloHigherSeqNo",
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_HELLO]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdHelloLowerSeqNo",
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_HELLO]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdDBDescHigherSeqNo",
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_DBDESC]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdDBDescLowerSeqNo",
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_DBDESC]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdLSReqHigherSeqNo",
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_LSREQ]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdLSReqLowerSeqNo",
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_LSREQ]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdLSUpdHigherSeqNo",
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_LSUPDATE]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdLSUpdLowerSeqNo",
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_LSUPDATE]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdLSAckHigherSeqNo",
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_LSACK]);
|
||||||
|
json_object_int_add(
|
||||||
|
json_neighbor, "recvdLSAckLowerSeqNo",
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_LSACK]);
|
||||||
|
} else
|
||||||
|
json_object_string_add(json_neighbor, "authStatus",
|
||||||
|
"disabled");
|
||||||
|
|
||||||
|
json_object_object_add(json, on->name, json_neighbor);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
vty_out(vty, " Neighbor %s\n", on->name);
|
vty_out(vty, " Neighbor %s\n", on->name);
|
||||||
@ -1022,6 +1066,27 @@ static void ospf6_neighbor_show_detail(struct vty *vty,
|
|||||||
vty_out(vty, " %s\n", lsa->name);
|
vty_out(vty, " %s\n", lsa->name);
|
||||||
|
|
||||||
bfd_sess_show(vty, NULL, on->bfd_session);
|
bfd_sess_show(vty, NULL, on->bfd_session);
|
||||||
|
|
||||||
|
if (on->auth_present == true) {
|
||||||
|
vty_out(vty, " Authentication header present\n");
|
||||||
|
vty_out(vty,
|
||||||
|
"\t\t\t hello DBDesc LSReq LSUpd LSAck\n");
|
||||||
|
vty_out(vty,
|
||||||
|
" Higher sequence no 0x%-10X 0x%-10X 0x%-10X 0x%-10X 0x%-10X\n",
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_HELLO],
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_DBDESC],
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_LSREQ],
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_LSUPDATE],
|
||||||
|
on->seqnum_h[OSPF6_MESSAGE_TYPE_LSACK]);
|
||||||
|
vty_out(vty,
|
||||||
|
" Lower sequence no 0x%-10X 0x%-10X 0x%-10X 0x%-10X 0x%-10X\n",
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_HELLO],
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_DBDESC],
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_LSREQ],
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_LSUPDATE],
|
||||||
|
on->seqnum_l[OSPF6_MESSAGE_TYPE_LSACK]);
|
||||||
|
} else
|
||||||
|
vty_out(vty, " Authentication header not present\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +144,14 @@ struct ospf6_neighbor {
|
|||||||
|
|
||||||
/* ospf6 graceful restart HELPER info */
|
/* ospf6 graceful restart HELPER info */
|
||||||
struct ospf6_helper_info gr_helper_info;
|
struct ospf6_helper_info gr_helper_info;
|
||||||
|
|
||||||
|
/* seqnum_h/l is used to compare sequence
|
||||||
|
* number in received packet Auth header
|
||||||
|
*/
|
||||||
|
uint32_t seqnum_h[OSPF6_MESSAGE_TYPE_MAX];
|
||||||
|
uint32_t seqnum_l[OSPF6_MESSAGE_TYPE_MAX];
|
||||||
|
bool auth_present;
|
||||||
|
bool lls_present;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Neighbor state */
|
/* Neighbor state */
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "ospf6_top.h"
|
#include "ospf6_top.h"
|
||||||
#include "ospf6_network.h"
|
#include "ospf6_network.h"
|
||||||
#include "ospf6d.h"
|
#include "ospf6d.h"
|
||||||
|
#include "ospf6_message.h"
|
||||||
|
|
||||||
struct in6_addr allspfrouters6;
|
struct in6_addr allspfrouters6;
|
||||||
struct in6_addr alldrouters6;
|
struct in6_addr alldrouters6;
|
||||||
@ -60,20 +61,6 @@ static void ospf6_set_transport_class(int ospf6_sock)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ospf6_set_checksum(int ospf6_sock)
|
|
||||||
{
|
|
||||||
int offset = 12;
|
|
||||||
#ifndef DISABLE_IPV6_CHECKSUM
|
|
||||||
if (setsockopt(ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM, &offset,
|
|
||||||
sizeof(offset))
|
|
||||||
< 0)
|
|
||||||
zlog_warn("Network: set IPV6_CHECKSUM failed: %s",
|
|
||||||
safe_strerror(errno));
|
|
||||||
#else
|
|
||||||
zlog_warn("Network: Don't set IPV6_CHECKSUM");
|
|
||||||
#endif /* DISABLE_IPV6_CHECKSUM */
|
|
||||||
}
|
|
||||||
|
|
||||||
void ospf6_serv_close(int *ospf6_sock)
|
void ospf6_serv_close(int *ospf6_sock)
|
||||||
{
|
{
|
||||||
if (*ospf6_sock != -1) {
|
if (*ospf6_sock != -1) {
|
||||||
@ -113,7 +100,6 @@ int ospf6_serv_sock(struct ospf6 *ospf6)
|
|||||||
ospf6_reset_mcastloop(ospf6_sock);
|
ospf6_reset_mcastloop(ospf6_sock);
|
||||||
ospf6_set_pktinfo(ospf6_sock);
|
ospf6_set_pktinfo(ospf6_sock);
|
||||||
ospf6_set_transport_class(ospf6_sock);
|
ospf6_set_transport_class(ospf6_sock);
|
||||||
ospf6_set_checksum(ospf6_sock);
|
|
||||||
|
|
||||||
ospf6->fd = ospf6_sock;
|
ospf6->fd = ospf6_sock;
|
||||||
/* setup global in6_addr, allspf6 and alldr6 for later use */
|
/* setup global in6_addr, allspf6 and alldr6 for later use */
|
||||||
|
@ -82,12 +82,16 @@ void ospf6_capability_printbuf(char capability, char *buf, int size)
|
|||||||
|
|
||||||
void ospf6_options_printbuf(uint8_t *options, char *buf, int size)
|
void ospf6_options_printbuf(uint8_t *options, char *buf, int size)
|
||||||
{
|
{
|
||||||
const char *dc, *r, *n, *mc, *e, *v6;
|
const char *dc, *r, *n, *mc, *e, *v6, *af, *at, *l;
|
||||||
dc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_DC) ? "DC" : "--");
|
dc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_DC) ? "DC" : "--");
|
||||||
r = (OSPF6_OPT_ISSET(options, OSPF6_OPT_R) ? "R" : "-");
|
r = (OSPF6_OPT_ISSET(options, OSPF6_OPT_R) ? "R" : "-");
|
||||||
n = (OSPF6_OPT_ISSET(options, OSPF6_OPT_N) ? "N" : "-");
|
n = (OSPF6_OPT_ISSET(options, OSPF6_OPT_N) ? "N" : "-");
|
||||||
mc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_MC) ? "MC" : "--");
|
mc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_MC) ? "MC" : "--");
|
||||||
e = (OSPF6_OPT_ISSET(options, OSPF6_OPT_E) ? "E" : "-");
|
e = (OSPF6_OPT_ISSET(options, OSPF6_OPT_E) ? "E" : "-");
|
||||||
v6 = (OSPF6_OPT_ISSET(options, OSPF6_OPT_V6) ? "V6" : "--");
|
v6 = (OSPF6_OPT_ISSET(options, OSPF6_OPT_V6) ? "V6" : "--");
|
||||||
snprintf(buf, size, "%s|%s|%s|%s|%s|%s", dc, r, n, mc, e, v6);
|
af = (OSPF6_OPT_ISSET_EXT(options, OSPF6_OPT_AF) ? "AF" : "--");
|
||||||
|
at = (OSPF6_OPT_ISSET_EXT(options, OSPF6_OPT_AT) ? "AT" : "--");
|
||||||
|
l = (OSPF6_OPT_ISSET_EXT(options, OSPF6_OPT_L) ? "L" : "-");
|
||||||
|
snprintf(buf, size, "%s|%s|%s|-|-|%s|%s|%s|%s|%s|%s", at, l, af, dc, r,
|
||||||
|
n, mc, e, v6);
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,20 @@
|
|||||||
|
|
||||||
/* OSPF options */
|
/* OSPF options */
|
||||||
/* present in HELLO, DD, LSA */
|
/* present in HELLO, DD, LSA */
|
||||||
#define OSPF6_OPT_SET(x,opt) ((x)[2] |= (opt))
|
#define OSPF6_OPT_SET(x, opt) ((x)[2] |= (opt))
|
||||||
#define OSPF6_OPT_ISSET(x,opt) ((x)[2] & (opt))
|
#define OSPF6_OPT_ISSET(x, opt) ((x)[2] & (opt))
|
||||||
#define OSPF6_OPT_CLEAR(x,opt) ((x)[2] &= ~(opt))
|
#define OSPF6_OPT_CLEAR(x, opt) ((x)[2] &= ~(opt))
|
||||||
|
#define OSPF6_OPT_SET_EXT(x, opt) ((x)[1] |= (opt))
|
||||||
|
#define OSPF6_OPT_ISSET_EXT(x, opt) ((x)[1] & (opt))
|
||||||
|
#define OSPF6_OPT_CLEAR_EXT(x, opt) ((x)[1] &= ~(opt))
|
||||||
#define OSPF6_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = (x)[2] = 0)
|
#define OSPF6_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = (x)[2] = 0)
|
||||||
|
|
||||||
|
#define OSPF6_OPT_AT (1 << 2) /* Authentication trailer Capability */
|
||||||
|
#define OSPF6_OPT_L (1 << 1) /* Link local signalling Capability */
|
||||||
|
#define OSPF6_OPT_AF (1 << 0) /* Address family Capability */
|
||||||
|
/* 2 bits reserved for OSPFv2 migrated options */
|
||||||
#define OSPF6_OPT_DC (1 << 5) /* Demand Circuit handling Capability */
|
#define OSPF6_OPT_DC (1 << 5) /* Demand Circuit handling Capability */
|
||||||
#define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */
|
#define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */
|
||||||
#define OSPF6_OPT_N (1 << 3) /* Handling Type-7 LSA Capability */
|
#define OSPF6_OPT_N (1 << 3) /* Handling Type-7 LSA Capability */
|
||||||
#define OSPF6_OPT_MC (1 << 2) /* Multicasting Capability */
|
#define OSPF6_OPT_MC (1 << 2) /* Multicasting Capability */
|
||||||
#define OSPF6_OPT_E (1 << 1) /* AS External Capability */
|
#define OSPF6_OPT_E (1 << 1) /* AS External Capability */
|
||||||
|
@ -1168,7 +1168,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
|
|||||||
json_object *json_routes, bool use_json)
|
json_object *json_routes, bool use_json)
|
||||||
{
|
{
|
||||||
char destination[PREFIX2STR_BUFFER], nexthop[64];
|
char destination[PREFIX2STR_BUFFER], nexthop[64];
|
||||||
char area_id[16], id[16], adv_router[16], capa[16], options[16];
|
char area_id[16], id[16], adv_router[16], capa[16], options[32];
|
||||||
char pfx_options[16];
|
char pfx_options[16];
|
||||||
struct timeval now, res;
|
struct timeval now, res;
|
||||||
char duration[64];
|
char duration[64];
|
||||||
@ -1653,7 +1653,7 @@ static void ospf6_linkstate_show_header(struct vty *vty)
|
|||||||
static void ospf6_linkstate_show(struct vty *vty, struct ospf6_route *route)
|
static void ospf6_linkstate_show(struct vty *vty, struct ospf6_route *route)
|
||||||
{
|
{
|
||||||
uint32_t router, id;
|
uint32_t router, id;
|
||||||
char routername[16], idname[16], rbits[16], options[16];
|
char routername[16], idname[16], rbits[16], options[32];
|
||||||
|
|
||||||
router = ospf6_linkstate_prefix_adv_router(&route->prefix);
|
router = ospf6_linkstate_prefix_adv_router(&route->prefix);
|
||||||
inet_ntop(AF_INET, &router, routername, sizeof(routername));
|
inet_ntop(AF_INET, &router, routername, sizeof(routername));
|
||||||
@ -1779,7 +1779,7 @@ void ospf6_brouter_show_header(struct vty *vty)
|
|||||||
void ospf6_brouter_show(struct vty *vty, struct ospf6_route *route)
|
void ospf6_brouter_show(struct vty *vty, struct ospf6_route *route)
|
||||||
{
|
{
|
||||||
uint32_t adv_router;
|
uint32_t adv_router;
|
||||||
char adv[16], rbits[16], options[16], area[16];
|
char adv[16], rbits[16], options[32], area[16];
|
||||||
|
|
||||||
adv_router = ospf6_linkstate_prefix_adv_router(&route->prefix);
|
adv_router = ospf6_linkstate_prefix_adv_router(&route->prefix);
|
||||||
inet_ntop(AF_INET, &adv_router, adv, sizeof(adv));
|
inet_ntop(AF_INET, &adv_router, adv, sizeof(adv));
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#include "ospf6_gr.h"
|
#include "ospf6_gr.h"
|
||||||
#include "lib/json.h"
|
#include "lib/json.h"
|
||||||
#include "ospf6_nssa.h"
|
#include "ospf6_nssa.h"
|
||||||
|
#include "ospf6_auth_trailer.h"
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
|
||||||
|
|
||||||
@ -445,6 +446,17 @@ static struct ospf6 *ospf6_create(const char *name)
|
|||||||
/* Make ospf protocol socket. */
|
/* Make ospf protocol socket. */
|
||||||
ospf6_serv_sock(o);
|
ospf6_serv_sock(o);
|
||||||
|
|
||||||
|
/* If sequence number is stored in persistent storage, read it.
|
||||||
|
*/
|
||||||
|
if (ospf6_auth_nvm_file_exist() == OSPF6_AUTH_FILE_EXIST) {
|
||||||
|
ospf6_auth_seqno_nvm_read(o);
|
||||||
|
o->seqnum_h = o->seqnum_h + 1;
|
||||||
|
ospf6_auth_seqno_nvm_update(o);
|
||||||
|
} else {
|
||||||
|
o->seqnum_l = o->seqnum_h = 0;
|
||||||
|
ospf6_auth_seqno_nvm_update(o);
|
||||||
|
}
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1386,6 +1398,10 @@ static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
|
|||||||
json_object_int_add(json, "numberOfAreaInRouter",
|
json_object_int_add(json, "numberOfAreaInRouter",
|
||||||
listcount(o->area_list));
|
listcount(o->area_list));
|
||||||
|
|
||||||
|
json_object_int_add(json, "AuthTrailerHigherSeqNo",
|
||||||
|
o->seqnum_h);
|
||||||
|
json_object_int_add(json, "AuthTrailerLowerSeqNo", o->seqnum_l);
|
||||||
|
|
||||||
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
|
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
|
||||||
if (CHECK_FLAG(o->config_flags,
|
if (CHECK_FLAG(o->config_flags,
|
||||||
OSPF6_LOG_ADJACENCY_DETAIL))
|
OSPF6_LOG_ADJACENCY_DETAIL))
|
||||||
@ -1466,6 +1482,10 @@ static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
|
|||||||
vty_out(vty, " Number of areas in this router is %u\n",
|
vty_out(vty, " Number of areas in this router is %u\n",
|
||||||
listcount(o->area_list));
|
listcount(o->area_list));
|
||||||
|
|
||||||
|
vty_out(vty, " Authentication Sequence number info\n");
|
||||||
|
vty_out(vty, " Higher sequence no %u, Lower sequence no %u\n",
|
||||||
|
o->seqnum_h, o->seqnum_l);
|
||||||
|
|
||||||
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
|
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
|
||||||
if (CHECK_FLAG(o->config_flags,
|
if (CHECK_FLAG(o->config_flags,
|
||||||
OSPF6_LOG_ADJACENCY_DETAIL))
|
OSPF6_LOG_ADJACENCY_DETAIL))
|
||||||
|
@ -228,6 +228,8 @@ struct ospf6 {
|
|||||||
/* Action for aggregation of external LSAs */
|
/* Action for aggregation of external LSAs */
|
||||||
int aggr_action;
|
int aggr_action;
|
||||||
|
|
||||||
|
uint32_t seqnum_l; /* lower order Sequence Number */
|
||||||
|
uint32_t seqnum_h; /* higher order Sequence Number */
|
||||||
#define OSPF6_EXTL_AGGR_DEFAULT_DELAY 5
|
#define OSPF6_EXTL_AGGR_DEFAULT_DELAY 5
|
||||||
/* For ASBR summary delay timer */
|
/* For ASBR summary delay timer */
|
||||||
uint16_t aggr_delay_interval;
|
uint16_t aggr_delay_interval;
|
||||||
|
Loading…
Reference in New Issue
Block a user