]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospf6d: Stitching the auth trailer code with rest of ospf6.
authorAbhinay Ramesh <rabhinay@vmware.com>
Sun, 30 May 2021 16:33:41 +0000 (16:33 +0000)
committerAbhinay Ramesh <rabhinay@vmware.com>
Wed, 9 Feb 2022 01:57:08 +0000 (01:57 +0000)
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>
16 files changed:
configure.ac
ospf6d/ospf6_auth_trailer.c
ospf6d/ospf6_auth_trailer.h
ospf6d/ospf6_interface.c
ospf6d/ospf6_interface.h
ospf6d/ospf6_intra.c
ospf6d/ospf6_message.c
ospf6d/ospf6_message.h
ospf6d/ospf6_neighbor.c
ospf6d/ospf6_neighbor.h
ospf6d/ospf6_network.c
ospf6d/ospf6_proto.c
ospf6d/ospf6_proto.h
ospf6d/ospf6_route.c
ospf6d/ospf6_top.c
ospf6d/ospf6_top.h

index e7bbe329b1b74621e4ab79cf3261155f4b5cef59..bdddf4b8466cacd1eda89b10329104456424dede 100644 (file)
@@ -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([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([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_DB_DIR], ["$frr_statedir"], [daemon database directory])
 
index 88d2fc240e618321e3a9d360ce5e6808bb71cc5a..2d0621cc2c26a6d06fb149d42123965aeed092a2 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "zebra.h"
+#include "config.h"
 #include "memory.h"
 #include "ospf6d.h"
 #include "vty.h"
 #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);
+}
index fa2de28efab8ded939327622091ff7d321a2508e..86ec49beba0d0e57b88d9288477727fbbdd91b81 100644 (file)
 #define OSPF6_AUTH_HDR_MIN_SIZE 16
 #define OSPF6_AUTH_HDR_FULL     KEYCHAIN_MAX_HASH_SIZE + OSPF6_AUTH_HDR_MIN_SIZE
 
-#define OSPF6_AUTHENTICATION_NULL                 0
-#define OSPF6_AUTHENTICATION_CRYPTOGRAPHIC        1
-static const uint16_t CPID = 1;
+#define OSPF6_AUTHENTICATION_NULL 0
+#define OSPF6_AUTHENTICATION_CRYPTOGRAPHIC 1
 
 /* Auth debug options */
 extern unsigned char conf_debug_ospf6_auth[2];
+
 #define OSPF6_AUTH_TX 0
 #define OSPF6_AUTH_RX 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];
 };
 
+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_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,
                                      uint32_t len);
 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);
 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,
                              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);
 void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,
                            struct ospf6_header *oh, uint16_t auth_len,
                            uint32_t pkt_len);
 void install_element_ospf6_debug_auth(void);
 int config_write_ospf6_debug_auth(struct vty *vty);
 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__ */
index 761a86444a6f1fde4b3b0250e3234f0bb9829935..f39d208bb5fb0b4a7ddec6d58bf1f7e7cefd90ef 100644 (file)
@@ -1260,10 +1260,6 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
                                              OSPF6_AUTH_TRAILER_MANUAL_KEY))
                                json_object_string_add(json_auth, "authType",
                                                       "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",
                                            oi->at_data.tx_drop);
                        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))
                                vty_out(vty,
                                        "  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,
                                "    Packet drop Tx %u, Packet drop Rx %u\n",
                                oi->at_data.tx_drop, oi->at_data.rx_drop);
                }
        } else {
-               if (use_json) {
+               if (use_json)
                        json_object_string_add(json_auth, "authType", "NULL");
-               } else {
+               else
                        vty_out(vty, "  Authentication Trailer is disabled\n");
-               }
        }
 
        if (use_json)
index d6a2b52e1291eaed1f5aa9ac2f3ed17cb4d3f0c4..59e4888a5f5a1a07d2d549d0ddfb845aef99b9c0 100644 (file)
@@ -35,32 +35,18 @@ extern unsigned char conf_debug_ospf6_interface;
 #define IS_OSPF6_DEBUG_INTERFACE (conf_debug_ospf6_interface)
 
 struct ospf6_auth_data {
-       /* higher order Sequence Number */
-       uint32_t seqnum_h;
-
-       /* lower order Sequence Number */
-       uint32_t seqnum_l;
-
-       /* Packet drop due to auth failure while sending */
-       uint32_t tx_drop;
-
-       /* 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;
+       /* config data */
+       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 */
+
+       /* operational data */
+       uint8_t flags; /* Flags related to auth config */
+
+       /* Counters and Statistics */
+       uint32_t tx_drop; /* Pkt drop due to auth fail while sending */
+       uint32_t rx_drop; /* Pkt drop due to auth fail while reading */
 };
 
 /* Interface structure */
index 6626b4bed55409975706595c30115aacec7341b5..da5cad0537e64c00901aaea4860c626ff4100b56 100644 (file)
@@ -2148,7 +2148,7 @@ static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
        char installed[64], changed[64];
        struct timeval now, res;
        char id[16], adv_router[16];
-       char capa[16], options[16];
+       char capa[16], options[32];
 
        brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
        inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name));
index 352cb137edb2866607cb88af41671916275ee9a1..c1004a7080a8838a230b56919b6753117db13521 100644 (file)
@@ -27,6 +27,7 @@
 #include "thread.h"
 #include "linklist.h"
 #include "lib_errors.h"
+#include "checksum.h"
 
 #include "ospf6_proto.h"
 #include "ospf6_lsa.h"
 #include "ospf6d.h"
 #include "ospf6_gr.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_PACKET, "OSPF6 packet");
 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6  FIFO queue");
 
 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"},
-       {OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc"},
-       {OSPF6_MESSAGE_TYPE_LSREQ, "LSReq"},
-       {OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate"},
-       {OSPF6_MESSAGE_TYPE_LSACK, "LSAck"},
-       {0}};
+
+const char *ospf6_message_type(int type)
+{
+       switch (type) {
+       case OSPF6_MESSAGE_TYPE_HELLO:
+               return "Hello";
+       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
    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)
 {
        struct ospf6_hello *hello;
-       char options[16];
+       char options[32];
        char *p;
 
        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)
 {
        struct ospf6_dbdesc *dbdesc;
-       char options[16];
+       char options[32];
        char *p;
 
        ospf6_header_print(oh);
@@ -439,6 +455,20 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
                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 */
        on = ospf6_neighbor_lookup(oh->router_id, oi);
        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
                                         + 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 */
        if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) {
                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);
                return MSG_NG;
        }
+
        /* Now it is safe to access header fields. */
        if (bytesonwire != ntohs(oh->length)) {
                zlog_warn("%s: %s packet length error (%u real, %u declared)",
-                         __func__,
-                         lookup_msg(ospf6_message_type_str, oh->type, NULL),
-                         bytesonwire, ntohs(oh->length));
+                         __func__, ospf6_message_type(oh->type), bytesonwire,
+                         ntohs(oh->length));
                return MSG_NG;
        }
+
        /* version check */
        if (oh->version != OSPFV3_VERSION) {
                zlog_warn("%s: invalid (%u) protocol version", __func__,
@@ -1431,8 +1476,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
            && bytesonwire
                       < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) {
                zlog_warn("%s: undersized (%u B) %s packet", __func__,
-                         bytesonwire,
-                         lookup_msg(ospf6_message_type_str, oh->type, NULL));
+                         bytesonwire, ospf6_message_type(oh->type));
                return MSG_NG;
        }
        /* type-specific deeper validation */
@@ -1446,7 +1490,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
                               % 4)
                        return MSG_OK;
                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;
        case OSPF6_MESSAGE_TYPE_DBDESC:
                /* 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)
                        return MSG_OK;
                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;
        case OSPF6_MESSAGE_TYPE_LSUPDATE:
                /* 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)
                zlog_warn("%s: anomaly in %s packet", __func__,
-                         lookup_msg(ospf6_message_type_str, oh->type, NULL));
+                         ospf6_message_type(oh->type));
        return test;
 }
 
@@ -1727,6 +1771,9 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
        struct iovec iovector[2];
        struct ospf6_interface *oi;
        struct ospf6_header *oh;
+       enum ospf6_auth_err ret = OSPF6_AUTH_PROCESS_NORMAL;
+       uint32_t at_len = 0;
+       uint32_t lls_len = 0;
 
        /* initialize */
        memset(&src, 0, sizeof(src));
@@ -1772,6 +1819,24 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
                return OSPF6_READ_CONTINUE;
 
        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)
                return OSPF6_READ_CONTINUE;
 
@@ -1782,8 +1847,7 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
 
        /* Log */
        if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) {
-               zlog_debug("%s received on %s",
-                          lookup_msg(ospf6_message_type_str, oh->type, NULL),
+               zlog_debug("%s received on %s", ospf6_message_type(oh->type),
                           oi->interface->name);
                zlog_debug("    src: %pI6", &src);
                zlog_debug("    dst: %pI6", &dst);
@@ -1807,6 +1871,10 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
                default:
                        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) {
@@ -1863,6 +1931,27 @@ int ospf6_receive(struct thread *thread)
        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,
                              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->type = type;
        oh->length = 0;
+
        oh->router_id = oi->area->ospf6->router_id;
        oh->area_id = oi->area->area_id;
        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);
 }
 
+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)
 {
+       int at_len = 0;
+
        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));
 }
 
@@ -1915,11 +2044,15 @@ static uint16_t ospf6_make_hello(struct ospf6_interface *oi, struct stream *s)
        struct listnode *node, *nnode;
        struct ospf6_neighbor *on;
        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_putc(s, oi->priority);
        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_putw(s, oi->hello_interval);
        stream_putw(s, oi->dead_interval);
@@ -1959,6 +2092,7 @@ static int ospf6_write(struct thread *thread)
        int len;
        int64_t latency = 0;
        struct timeval timestamp;
+       unsigned int at_len = 0;
 
        if (ospf6->fd < 0) {
                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);
 
+               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,
                                    oi->interface->ifindex, iovector,
                                    ospf6->fd);
-               if (len != op->length)
+
+               if (len != (op->length + (int)at_len))
                        flog_err(EC_LIB_DEVELOPMENT,
                                 "Could not send entire message");
 
                if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) {
                        zlog_debug("%s send on %s",
-                                  lookup_msg(ospf6_message_type_str, oh->type,
-                                             NULL),
+                                  ospf6_message_type(oh->type),
                                   oi->interface->name);
                        zlog_debug("    src: %pI6", oi->linklocal_addr);
                        zlog_debug("    dst: %pI6", &op->dst);
@@ -2052,6 +2201,15 @@ static int ospf6_write(struct thread *thread)
                        assert(0);
                        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. */
                ospf6_packet_delete(oi);
 
@@ -2117,6 +2275,8 @@ int ospf6_hello_send(struct thread *thread)
 
        op->dst = allspfrouters6;
 
+       ospf6_fill_hdr_checksum(oi, op);
+
        /* 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
         */
@@ -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;
        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 (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 */
        stream_putc(s, 0); /* reserved 1 */
        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_putw(s, on->ospf6_if->ifmtu);
        stream_putc(s, 0); /* reserved 2 */
@@ -2212,6 +2376,8 @@ int ospf6_dbdesc_send(struct thread *thread)
        else
                op->dst = on->linklocal_addr;
 
+       ospf6_fill_hdr_checksum(on->ospf6_if, op);
+
        ospf6_packet_add(on->ospf6_if, op);
 
        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)->dst = on->linklocal_addr;
+                               ospf6_fill_hdr_checksum(on->ospf6_if, *op);
                                ospf6_packet_add(on->ospf6_if, *op);
                                OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
                                /* new packet */
@@ -2388,6 +2555,7 @@ int ospf6_lsreq_send(struct thread *thread)
        else
                op->dst = on->linklocal_addr;
 
+       ospf6_fill_hdr_checksum(on->ospf6_if, op);
        ospf6_packet_add(on->ospf6_if, op);
 
        OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
@@ -2425,6 +2593,7 @@ static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
                        op->dst = alldrouters6;
        }
        if (oi) {
+               ospf6_fill_hdr_checksum(oi, op);
                ospf6_packet_add(oi, op);
                /* If ospf instance is being deleted, send the packet
                 * immediately
@@ -2502,6 +2671,7 @@ static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor *on,
                        else
                                (*op)->dst = on->linklocal_addr;
 
+                       ospf6_fill_hdr_checksum(on->ospf6_if, *op);
                        ospf6_packet_add(on->ospf6_if, *op);
                        OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
 
@@ -2573,6 +2743,7 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
                        op->dst = allspfrouters6;
                else
                        op->dst = on->linklocal_addr;
+               ospf6_fill_hdr_checksum(on->ospf6_if, op);
                ospf6_packet_add(on->ospf6_if, op);
                OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
        } else
@@ -2739,6 +2910,7 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
        /* Set packet length, dst and queue to FIFO. */
        op->length = length;
        op->dst = on->linklocal_addr;
+       ospf6_fill_hdr_checksum(on->ospf6_if, op);
        ospf6_packet_add(on->ospf6_if, op);
        OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
 
@@ -2823,6 +2995,7 @@ int ospf6_lsack_send_interface(struct thread *thread)
        else
                op->dst = alldrouters6;
 
+       ospf6_fill_hdr_checksum(oi, op);
        ospf6_packet_add(oi, op);
        OSPF6_MESSAGE_WRITE_ON(oi);
 
index 68cb4c7794021614d0791540e5045d01a699af06..437dd5685b14a90bb231270320c610e8c36d5ed7 100644 (file)
 
 #define OSPF6_MESSAGE_BUFSIZ  4096
 
-extern const struct message ospf6_message_type_str[];
-
 /* Debug option */
 extern unsigned char conf_debug_ospf6_message[];
+
 #define OSPF6_ACTION_SEND 0x01
 #define OSPF6_ACTION_RECV 0x02
 #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_LSACK    0x5  /* Flooding acknowledgment */
 #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 *next;
@@ -148,8 +148,16 @@ struct ospf6_lsupdate {
        /* 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 */
-#define OSPF6_LS_ACK_MIN_SIZE                  0U
+#define OSPF6_LS_ACK_MIN_SIZE 0U
 /* It is just a sequence of LSA Headers */
 
 /* 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 void install_element_ospf6_debug_message(void);
-
+extern const char *ospf6_message_type(int type);
 #endif /* OSPF6_MESSAGE_H */
index afa504d13c1ce665c93df15e48e727495d5fc117..5d14bfc981456d43a162e49405cfa97d86811f3a 100644 (file)
@@ -112,6 +112,7 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
 {
        struct ospf6_neighbor *on;
        char buf[16];
+       int type;
 
        on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor));
        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->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);
 
        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);
 
-               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 {
                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);
 
                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");
        }
 }
 
index de59a1ccf5778685ba69dae675c3a2d5eb30c9bd..2dd640099c2646e8cd0443d8b8f488a82660e177 100644 (file)
@@ -144,6 +144,14 @@ struct ospf6_neighbor {
 
        /* ospf6 graceful restart 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 */
index 5961cfe66adb74fc9693441c4977eec7817ac30d..7501f49fe02f2116457a169a0b6f5b79b3fa71de 100644 (file)
@@ -33,6 +33,7 @@
 #include "ospf6_top.h"
 #include "ospf6_network.h"
 #include "ospf6d.h"
+#include "ospf6_message.h"
 
 struct in6_addr allspfrouters6;
 struct in6_addr alldrouters6;
@@ -60,20 +61,6 @@ static void ospf6_set_transport_class(int ospf6_sock)
 #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)
 {
        if (*ospf6_sock != -1) {
@@ -113,7 +100,6 @@ int ospf6_serv_sock(struct ospf6 *ospf6)
        ospf6_reset_mcastloop(ospf6_sock);
        ospf6_set_pktinfo(ospf6_sock);
        ospf6_set_transport_class(ospf6_sock);
-       ospf6_set_checksum(ospf6_sock);
 
        ospf6->fd = ospf6_sock;
        /* setup global in6_addr, allspf6 and alldr6 for later use */
index e60d2c7e0e9ee670c53e7e9f08ef87a92dd1ed2e..4d0c4ee59ec2d7c6e1357e7529537b10bb9ba409 100644 (file)
@@ -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)
 {
-       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" : "--");
        r = (OSPF6_OPT_ISSET(options, OSPF6_OPT_R) ? "R" : "-");
        n = (OSPF6_OPT_ISSET(options, OSPF6_OPT_N) ? "N" : "-");
        mc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_MC) ? "MC" : "--");
        e = (OSPF6_OPT_ISSET(options, OSPF6_OPT_E) ? "E" : "-");
        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);
 }
index b98dc38b728e26fca094bce5cd866b46cfa7e98a..ea476b3a8d97441817c55aa4d6efbda2ca96818e 100644 (file)
 
 /* OSPF options */
 /* present in HELLO, DD, LSA */
-#define OSPF6_OPT_SET(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_SET(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_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_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_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_MC (1 << 2)   /* Multicasting Capability */
 #define OSPF6_OPT_E  (1 << 1)   /* AS External Capability */
index f5d60d80fa58f4fae0ad9f5375b1a8ac6fd652c9..3c74ca55c1d28621e78022b7fe4aba432f4050c8 100644 (file)
@@ -1168,7 +1168,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
                             json_object *json_routes, bool use_json)
 {
        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];
        struct timeval now, res;
        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)
 {
        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);
        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)
 {
        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);
        inet_ntop(AF_INET, &adv_router, adv, sizeof(adv));
index 57a55a6ef4c2dfb6a8633c84a3485e399862af7d..9381fa7faf70b9c97abbf3894d7d7800a89afda3 100644 (file)
@@ -54,6 +54,7 @@
 #include "ospf6_gr.h"
 #include "lib/json.h"
 #include "ospf6_nssa.h"
+#include "ospf6_auth_trailer.h"
 
 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
 
@@ -445,6 +446,17 @@ static struct ospf6 *ospf6_create(const char *name)
        /* Make ospf protocol socket. */
        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;
 }
 
@@ -1386,6 +1398,10 @@ static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
                json_object_int_add(json, "numberOfAreaInRouter",
                                    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_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",
                        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_DETAIL))
index b9f7235b464a81d8b356a9bfa4f5c7ecca129d27..f06a3254ac4989b56883abe2bbb5fe23108704db 100644 (file)
@@ -228,6 +228,8 @@ struct ospf6 {
        /* Action for aggregation of external LSAs */
        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
        /* For ASBR summary delay timer */
        uint16_t aggr_delay_interval;