Merge pull request #8890 from rameshabhinay/ospf6_auth_trailer

OSPF6: Support OSPF6 authentication trailer RFC 7166
This commit is contained in:
Russ White 2022-02-10 14:17:13 -05:00 committed by GitHub
commit 6142a17949
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 3778 additions and 60 deletions

View 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])

View File

@ -383,6 +383,256 @@ Graceful Restart
This is an EXEC-level command.
.. _Authentication-trailer:
Authentication trailer support:
===============================
IPv4 version of OSPF supports authentication as part of the base RFC.
When IPv6 version of OSPF was developed there was IPSec support for IPv6,
Hence OSPFv3(IPv6 version of OSPF) suggest to use IPSec as authentication
and encryption mechanism. IPSec supports authentication using AH header and
Encryption using ESP.
There are few disadvantages of using IPSec with OSPFv3.
1. If encryption is enabled for OSPFv3 packets, then its not
possible to give priority to control packets.
2. IPSec has platform dependency and may not be supported
in all platforms.
3. It is performance intensive.
4. Its difficult to configure.
Some advantages of OSPFv3 authentication trailer feature.
1. It provides replay protection via sequence number.
2. It provides IPv6 source address protection.
3. No platform dependency.
4. Easy to implement and maintain.
This feature is support for ``RFC7166``.
FRR supports MD5 and SHA256 internally and relays on openssl for other hash
algorithms. If user wants to use only MD5 and SHA256, no special action is
required. If user wants complete support of authentication trailer with all
hash algorithms follow below steps.
Installing Dependencies:
------------------------
.. code-block:: console
sudo apt update
sudo apt-get install openssl
Compile:
--------
Follow normal compilation as mentioned in the build page. If you want to
use all the hash algorithms then follow the steps mentioned in note before
compiling.
.. note::
If your platform supports ``openssl``, please make sure to add
``--with-crypto=openssl`` to your configure options.
Default value is ``--with-crypto=internal``
CLI Configuration:
------------------
There are two ways in which authentication trailer can be configured for
OSPFv3. These commands are mutually exclusive, only one can be configured
at any time.
1. Using manual key configuration.
2. Using keychain.
List of hash algorithms supported:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Without openssl:
++++++++++++++++
``MD5``
``HMAC-SHA-256``
With openssl:
+++++++++++++
``MD5``
``HMAC-SHA-1``
``HMAC-SHA-256``
``HMAC-SHA-384``
``HMAC-SHA-512``
Example configuration of manual key:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Without openssl:
++++++++++++++++
.. clicmd:: ipv6 ospf6 authentication key-id (1-65535) hash-algo <md5|hmac-sha-256> key WORD
With openssl:
+++++++++++++
.. clicmd:: ipv6 ospf6 authentication key-id (1-65535) hash-algo <md5|hmac-sha-256|hmac-sha-1|hmac-sha-384|hmac-sha-512> key WORD
Example configuration of keychain:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. clicmd:: ipv6 ospf6 authentication keychain KEYCHAIN_NAME
Running configuration:
----------------------
Manual key:
^^^^^^^^^^^
.. code-block:: frr
frr# show running-config
Building configuration...
Current configuration:
!
interface ens192
ipv6 address 2001:DB8::2/64
ipv6 ospf6 authentication key-id 10 hash-algo hmac-sha-256 key abhinay
Keychain:
^^^^^^^^^
.. code-block:: frr
frr# show running-config
Building configuration...
Current configuration:
!
interface ens192
ipv6 address 2001:DB8::2/64
ipv6 ospf6 authentication keychain abhinay
Example keychain config:
^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: frr
frr#show running-config
Building configuration...
Current configuration:
!
key chain abcd
key 100
key-string password
cryptographic-algorithm sha1
exit
key 200
key-string password
cryptographic-algorithm sha256
exit
!
key chain pqr
key 300
key-string password
cryptographic-algorithm sha384
exit
key 400
key-string password
cryptographic-algorithm sha384
exit
!
Show commands:
--------------
There is an interface show command that displays if authentication trailer
is enabled or not. json output is also supported.
There is support for drop counters, which will help in debugging the feature.
.. code-block:: frr
frr# show ipv6 ospf6 interface ens192
ens192 is up, type BROADCAST
Interface ID: 5
Number of I/F scoped LSAs is 2
0 Pending LSAs for LSUpdate in Time 00:00:00 [thread off]
0 Pending LSAs for LSAck in Time 00:00:00 [thread off]
Authentication trailer is enabled with manual key ==> new info added
Packet drop Tx 0, Packet drop Rx 0
OSPFv3 supports options in hello and database description packets hence
the presence of authentication trailer needs to be stored in OSPFv3
neighbor info. Since RFC specifies that we need to handled sequence number
for every ospf6 packet type, sequence number recvd in authentication header
from the neighbor is stored in neighbor to validate the packet.
json output is also supported.
.. code-block:: frr
frr# show ipv6 ospf6 neighbor 2.2.2.2 detail
Neighbor 2.2.2.2%ens192
Area 1 via interface ens192 (ifindex 3)
0 Pending LSAs for LSUpdate in Time 00:00:00 [thread off]
0 Pending LSAs for LSAck in Time 00:00:00 [thread off]
Authentication header present ==> new info added
hello DBDesc LSReq LSUpd LSAck
Higher sequence no 0x0 0x0 0x0 0x0 0x0
Lower sequence no 0x242E 0x1DC4 0x1DC3 0x23CC 0x1DDA
Sent packet sequence number is maintained per ospf6 router for every packet
that is sent out of router, so sequence number is maintained per ospf6 process.
.. code-block:: frr
frr# show ipv6 ospf6
OSPFv3 Routing Process (0) with Router-ID 2.2.2.2
Number of areas in this router is 1
Authentication Sequence number info
Higher sequence no 3, Lower sequence no 1656
Debug command:
--------------
Below command can be used to enable ospfv3 authentication trailer
specific logs if you have to debug the feature.
.. clicmd:: debug ospf6 authentication [<tx|rx>]
Feature supports authentication trailer tx/rx drop counters for debugging,
which can be used to see if packets are getting dropped due to error in
processing authentication trailer information in OSPFv3 packet.
json output is also supported.
.. code-block:: frr
frr# show ipv6 ospf6 interface ens192
ens192 is up, type BROADCAST
Interface ID: 5
Number of I/F scoped LSAs is 2
0 Pending LSAs for LSUpdate in Time 00:00:00 [thread off]
0 Pending LSAs for LSAck in Time 00:00:00 [thread off]
Authentication trailer is enabled with manual key
Packet drop Tx 0, Packet drop Rx 0 ==> new counters
Clear command:
--------------
Below command can be used to clear the tx/rx drop counters in interface.
Below command can be used to clear all ospfv3 interface or specific
interface by specifying the interface name.
.. clicmd:: clear ipv6 ospf6 auth-counters interface [IFNAME]
.. _showing-ospf6-information:
Showing OSPF6 information

View File

@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <zebra.h>
#include "command.h"
@ -207,6 +208,7 @@ static struct key *key_get(const struct keychain *keychain, uint32_t index)
key = key_new();
key->index = index;
key->hash_algo = KEYCHAIN_ALGO_NULL;
listnode_add_sort(keychain->key, key);
return key;
@ -336,6 +338,133 @@ DEFUN (no_key_string,
return CMD_SUCCESS;
}
const struct keychain_algo_info algo_info[] = {
{KEYCHAIN_ALGO_NULL, "null", 0, 0, "NULL"},
{KEYCHAIN_ALGO_MD5, "md5", KEYCHAIN_MD5_HASH_SIZE,
KEYCHAIN_ALGO_MD5_INTERNAL_BLK_SIZE, "MD5"},
{KEYCHAIN_ALGO_HMAC_SHA1, "hmac-sha-1", KEYCHAIN_HMAC_SHA1_HASH_SIZE,
KEYCHAIN_ALGO_SHA1_INTERNAL_BLK_SIZE, "HMAC-SHA-1"},
{KEYCHAIN_ALGO_HMAC_SHA256, "hmac-sha-256",
KEYCHAIN_HMAC_SHA256_HASH_SIZE, KEYCHAIN_ALGO_SHA256_INTERNAL_BLK_SIZE,
"HMAC-SHA-256"},
{KEYCHAIN_ALGO_HMAC_SHA384, "hmac-sha-384",
KEYCHAIN_HMAC_SHA384_HASH_SIZE, KEYCHAIN_ALGO_SHA384_INTERNAL_BLK_SIZE,
"HMAC-SHA-384"},
{KEYCHAIN_ALGO_HMAC_SHA512, "hmac-sha-512",
KEYCHAIN_HMAC_SHA512_HASH_SIZE, KEYCHAIN_ALGO_SHA512_INTERNAL_BLK_SIZE,
"HMAC-SHA-512"},
{KEYCHAIN_ALGO_MAX, "max", KEYCHAIN_MAX_HASH_SIZE,
KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE, "Not defined"}
};
uint32_t keychain_get_block_size(enum keychain_hash_algo key)
{
return algo_info[key].block;
}
uint32_t keychain_get_hash_len(enum keychain_hash_algo key)
{
return algo_info[key].length;
}
const char *keychain_get_description(enum keychain_hash_algo key)
{
return algo_info[key].desc;
}
struct keychain_algo_info
keychain_get_hash_algo_info(enum keychain_hash_algo key)
{
return algo_info[key];
}
enum keychain_hash_algo keychain_get_algo_id_by_name(const char *name)
{
#ifdef CRYPTO_INTERNAL
if (!strncmp(name, "hmac-sha-2", 10))
return KEYCHAIN_ALGO_HMAC_SHA256;
else if (!strncmp(name, "m", 1))
return KEYCHAIN_ALGO_MD5;
else
return KEYCHAIN_ALGO_NULL;
#else
if (!strncmp(name, "m", 1))
return KEYCHAIN_ALGO_MD5;
else if (!strncmp(name, "hmac-sha-1", 10))
return KEYCHAIN_ALGO_HMAC_SHA1;
else if (!strncmp(name, "hmac-sha-2", 10))
return KEYCHAIN_ALGO_HMAC_SHA256;
else if (!strncmp(name, "hmac-sha-3", 10))
return KEYCHAIN_ALGO_HMAC_SHA384;
else if (!strncmp(name, "hmac-sha-5", 10))
return KEYCHAIN_ALGO_HMAC_SHA512;
else
return KEYCHAIN_ALGO_NULL;
#endif
}
const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key)
{
return algo_info[key].name;
}
DEFUN(cryptographic_algorithm, cryptographic_algorithm_cmd,
"cryptographic-algorithm "
"<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>",
"Cryptographic-algorithm\n"
"Use MD5 algorithm\n"
"Use HMAC-SHA-1 algorithm\n"
"Use HMAC-SHA-256 algorithm\n"
"Use HMAC-SHA-384 algorithm\n"
"Use HMAC-SHA-512 algorithm\n")
{
int algo_idx = 1;
uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
VTY_DECLVAR_CONTEXT_SUB(key, key);
hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg);
#ifndef CRYPTO_OPENSSL
if (hash_algo == KEYCHAIN_ALGO_NULL) {
vty_out(vty,
"Hash algorithm not supported, compile with --with-crypto=openssl\n");
return CMD_WARNING_CONFIG_FAILED;
}
#endif /* CRYPTO_OPENSSL */
key->hash_algo = hash_algo;
return CMD_SUCCESS;
}
DEFUN(no_cryptographic_algorithm, no_cryptographic_algorithm_cmd,
"no cryptographic-algorithm "
"[<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>]",
NO_STR
"Cryptographic-algorithm\n"
"Use MD5 algorithm\n"
"Use HMAC-SHA-1 algorithm\n"
"Use HMAC-SHA-256 algorithm\n"
"Use HMAC-SHA-384 algorithm\n"
"Use HMAC-SHA-512 algorithm\n")
{
int algo_idx = 2;
uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
VTY_DECLVAR_CONTEXT_SUB(key, key);
if (argc > algo_idx) {
hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg);
if (hash_algo == KEYCHAIN_ALGO_NULL) {
vty_out(vty,
"Hash algorithm not supported, try compiling with --with-crypto=openssl\n");
return CMD_WARNING_CONFIG_FAILED;
}
}
if ((hash_algo != KEYCHAIN_ALGO_NULL) && (hash_algo != key->hash_algo))
return CMD_SUCCESS;
key->hash_algo = KEYCHAIN_ALGO_NULL;
return CMD_SUCCESS;
}
/* Convert HH:MM:SS MON DAY YEAR to time_t value. -1 is returned when
given string is malformed. */
static time_t key_str2time(const char *time_str, const char *day_str,
@ -1004,6 +1133,11 @@ static int keychain_config_write(struct vty *vty)
if (key->string)
vty_out(vty, " key-string %s\n", key->string);
if (key->hash_algo != KEYCHAIN_ALGO_NULL)
vty_out(vty, " cryptographic-algorithm %s\n",
keychain_get_algo_name_by_id(
key->hash_algo));
if (key->accept.start) {
keychain_strftime(buf, BUFSIZ,
&key->accept.start);
@ -1051,10 +1185,29 @@ static int keychain_config_write(struct vty *vty)
return 0;
}
static void keychain_active_config(vector comps, struct cmd_token *token)
{
struct keychain *keychain;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain))
vector_set(comps, XSTRDUP(MTYPE_COMPLETION, keychain->name));
}
static const struct cmd_variable_handler keychain_var_handlers[] = {
{.varname = "key_chain", .completions = keychain_active_config},
{.tokenname = "KEYCHAIN_NAME", .completions = keychain_active_config},
{.tokenname = "KCHAIN_NAME", .completions = keychain_active_config},
{.completions = NULL}
};
void keychain_init(void)
{
keychain_list = list_new();
/* Register handler for keychain auto config support */
cmd_variable_handler_register(keychain_var_handlers);
install_node(&keychain_node);
install_node(&keychain_key_node);
@ -1113,4 +1266,6 @@ void keychain_init(void)
install_element(KEYCHAIN_KEY_NODE,
&send_lifetime_duration_month_day_cmd);
install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd);
install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd);
install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd);
}

View File

@ -27,6 +27,47 @@
extern "C" {
#endif
enum keychain_hash_algo {
KEYCHAIN_ALGO_NULL,
KEYCHAIN_ALGO_MD5,
KEYCHAIN_ALGO_HMAC_SHA1,
KEYCHAIN_ALGO_HMAC_SHA256,
KEYCHAIN_ALGO_HMAC_SHA384,
KEYCHAIN_ALGO_HMAC_SHA512,
KEYCHAIN_ALGO_MAX
};
#define KEYCHAIN_MD5_HASH_SIZE 16
#define KEYCHAIN_HMAC_SHA1_HASH_SIZE 20
#define KEYCHAIN_HMAC_SHA256_HASH_SIZE 32
#define KEYCHAIN_HMAC_SHA384_HASH_SIZE 48
#define KEYCHAIN_HMAC_SHA512_HASH_SIZE 64
#define KEYCHAIN_MAX_HASH_SIZE 64
#define KEYCHAIN_ALGO_MD5_INTERNAL_BLK_SIZE 16
#define KEYCHAIN_ALGO_SHA1_INTERNAL_BLK_SIZE 64
#define KEYCHAIN_ALGO_SHA256_INTERNAL_BLK_SIZE 64
#define KEYCHAIN_ALGO_SHA384_INTERNAL_BLK_SIZE 128
#define KEYCHAIN_ALGO_SHA512_INTERNAL_BLK_SIZE 128
#define KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE 128
struct keychain_algo_info {
enum keychain_hash_algo key;
const char *name;
uint32_t length;
uint32_t block;
const char *desc;
};
extern const struct keychain_algo_info algo_info[];
uint32_t keychain_get_block_size(enum keychain_hash_algo key);
uint32_t keychain_get_hash_len(enum keychain_hash_algo key);
const char *keychain_get_description(enum keychain_hash_algo key);
struct keychain_algo_info
keychain_get_hash_algo_info(enum keychain_hash_algo key);
enum keychain_hash_algo keychain_get_algo_id_by_name(const char *name);
const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key);
struct keychain {
char *name;
@ -47,7 +88,7 @@ struct key {
uint32_t index;
char *string;
enum keychain_hash_algo hash_algo;
struct key_range send;
struct key_range accept;
@ -60,7 +101,7 @@ extern struct keychain *keychain_lookup(const char *);
extern struct key *key_lookup_for_accept(const struct keychain *, uint32_t);
extern struct key *key_match_for_accept(const struct keychain *, const char *);
extern struct key *key_lookup_for_send(const struct keychain *);
const char *keychain_algo_str(enum keychain_hash_algo hash_algo);
#ifdef __cplusplus
}
#endif

1000
ospf6d/ospf6_auth_trailer.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2021 Abhinay Ramesh
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __OSPF6_AUTH_TRAILER_H__
#define __OSPF6_AUTH_TRAILER_H__
#include "lib/keychain.h"
#include "ospf6_message.h"
#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
/* 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)
#define OSPF6_DEBUG_AUTH_TX_OFF() (conf_debug_ospf6_auth[OSPF6_AUTH_TX] = 0)
#define OSPF6_DEBUG_AUTH_RX_ON() (conf_debug_ospf6_auth[OSPF6_AUTH_RX] = 1)
#define OSPF6_DEBUG_AUTH_RX_OFF() (conf_debug_ospf6_auth[OSPF6_AUTH_RX] = 0)
#define IS_OSPF6_DEBUG_AUTH_TX (conf_debug_ospf6_auth[OSPF6_AUTH_TX])
#define IS_OSPF6_DEBUG_AUTH_RX (conf_debug_ospf6_auth[OSPF6_AUTH_RX])
#define OSPF6_AUTH_TRAILER_KEYCHAIN (1 << 0)
#define OSPF6_AUTH_TRAILER_MANUAL_KEY (1 << 1)
#define OSPF6_AUTH_TRAILER_KEYCHAIN_VALID (1 << 2)
/* According to sesion 4.1 of RFC7166 defining the trailer struct */
struct ospf6_auth_hdr {
uint16_t type;
uint16_t length;
uint16_t reserved;
uint16_t id;
uint32_t seqnum_h;
uint32_t seqnum_l;
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,
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,
unsigned int *lls_block_len);
int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
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,
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__ */

View File

@ -46,8 +46,13 @@
#include "ospf6_zebra.h"
#include "ospf6_gr.h"
#include "lib/json.h"
#include "ospf6_proto.h"
#include "lib/keychain.h"
#include "ospf6_auth_trailer.h"
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface");
DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_KEYCHAIN, "OSPF6 auth keychain");
DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_MANUAL_KEY, "OSPF6 auth key");
DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names");
DEFINE_QOBJ_TYPE(ospf6_interface);
DEFINE_HOOK(ospf6_interface_change,
@ -252,6 +257,8 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
/* Compute cost. */
oi->cost = ospf6_interface_get_cost(oi);
oi->at_data.flags = 0;
return oi;
}
@ -990,6 +997,7 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
struct ospf6_lsa *lsa, *lsanext;
json_object *json_arr;
json_object *json_addr;
struct json_object *json_auth = NULL;
default_iftype = ospf6_default_iftype(ifp);
@ -1238,6 +1246,48 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
}
}
json_auth = json_object_new_object();
if (oi->at_data.flags != 0) {
if (use_json) {
if (CHECK_FLAG(oi->at_data.flags,
OSPF6_AUTH_TRAILER_KEYCHAIN)) {
json_object_string_add(json_auth, "authType",
"keychain");
json_object_string_add(json_auth,
"keychainName",
oi->at_data.keychain);
} else if (CHECK_FLAG(oi->at_data.flags,
OSPF6_AUTH_TRAILER_MANUAL_KEY))
json_object_string_add(json_auth, "authType",
"manualkey");
json_object_int_add(json_auth, "txPktDrop",
oi->at_data.tx_drop);
json_object_int_add(json_auth, "rxPktDrop",
oi->at_data.rx_drop);
} else {
if (CHECK_FLAG(oi->at_data.flags,
OSPF6_AUTH_TRAILER_KEYCHAIN))
vty_out(vty,
" Authentication Trailer is enabled with key-chain %s\n",
oi->at_data.keychain);
else if (CHECK_FLAG(oi->at_data.flags,
OSPF6_AUTH_TRAILER_MANUAL_KEY))
vty_out(vty,
" Authentication trailer is enabled with manual key\n");
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)
json_object_string_add(json_auth, "authType", "NULL");
else
vty_out(vty, " Authentication Trailer is disabled\n");
}
if (use_json)
json_object_object_add(json_obj, "authInfo", json_auth);
return 0;
}
@ -2577,6 +2627,7 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
ospf6_bfd_write_config(vty, oi);
ospf6_auth_write_config(vty, &oi->at_data);
if_vty_config_end(vty);
}
return 0;
@ -2815,3 +2866,195 @@ void install_element_ospf6_debug_interface(void)
install_element(CONFIG_NODE, &debug_ospf6_interface_cmd);
install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd);
}
void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data)
{
if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
vty_out(vty, " ipv6 ospf6 authentication keychain %s\n",
at_data->keychain);
else if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
vty_out(vty,
" ipv6 ospf6 authentication key-id %d hash-algo %s key %s\n",
at_data->key_id,
keychain_get_algo_name_by_id(at_data->hash_algo),
at_data->auth_key);
}
DEFUN(ipv6_ospf6_intf_auth_trailer_keychain,
ipv6_ospf6_intf_auth_trailer_keychain_cmd,
"ipv6 ospf6 authentication keychain KEYCHAIN_NAME",
IP6_STR OSPF6_STR
"Enable authentication on this interface\n"
"Keychain\n"
"Keychain name\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int keychain_idx = 4;
struct ospf6_interface *oi;
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
oi = ospf6_interface_create(ifp);
assert(oi);
if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
vty_out(vty,
"Manual key configured, unconfigure it before configuring key chain\n");
return CMD_WARNING_CONFIG_FAILED;
}
SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN);
if (oi->at_data.keychain)
XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
oi->at_data.keychain =
XSTRDUP(MTYPE_OSPF6_AUTH_KEYCHAIN, argv[keychain_idx]->arg);
return CMD_SUCCESS;
}
DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain,
no_ipv6_ospf6_intf_auth_trailer_keychain_cmd,
"no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]",
NO_STR IP6_STR OSPF6_STR
"Enable authentication on this interface\n"
"Keychain\n"
"Keychain name\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
oi = ospf6_interface_create(ifp);
assert(oi);
if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
return CMD_SUCCESS;
if (oi->at_data.keychain) {
oi->at_data.flags = 0;
XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
oi->at_data.keychain = NULL;
}
return CMD_SUCCESS;
}
DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd,
"ipv6 ospf6 authentication key-id (1-65535) hash-algo "
"<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
"key WORD",
IP6_STR OSPF6_STR
"Authentication\n"
"Key ID\n"
"Key ID value\n"
"Cryptographic-algorithm\n"
"Use MD5 algorithm\n"
"Use HMAC-SHA-1 algorithm\n"
"Use HMAC-SHA-256 algorithm\n"
"Use HMAC-SHA-384 algorithm\n"
"Use HMAC-SHA-512 algorithm\n"
"Password\n"
"Password string (key)\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int key_id_idx = 4;
int hash_algo_idx = 6;
int password_idx = 8;
struct ospf6_interface *oi;
uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
oi = ospf6_interface_create(ifp);
assert(oi);
if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
vty_out(vty,
"key chain configured, unconfigure it before configuring manual key\n");
return CMD_WARNING_CONFIG_FAILED;
}
hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
#ifndef CRYPTO_OPENSSL
if (hash_algo == KEYCHAIN_ALGO_NULL) {
vty_out(vty,
"Hash algorithm not supported, compile with --with-crypto=openssl\n");
return CMD_WARNING_CONFIG_FAILED;
}
#endif /* CRYPTO_OPENSSL */
SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY);
oi->at_data.hash_algo = hash_algo;
oi->at_data.key_id = (uint16_t)strtol(argv[key_id_idx]->arg, NULL, 10);
if (oi->at_data.auth_key)
XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
oi->at_data.auth_key =
XSTRDUP(MTYPE_OSPF6_AUTH_MANUAL_KEY, argv[password_idx]->arg);
return CMD_SUCCESS;
}
DEFUN(no_ipv6_ospf6_intf_auth_trailer_key,
no_ipv6_ospf6_intf_auth_trailer_key_cmd,
"no ipv6 ospf6 authentication key-id [(1-65535) hash-algo "
"<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
"key WORD]",
NO_STR IP6_STR OSPF6_STR
"Authentication\n"
"Key ID\n"
"Key ID value\n"
"Cryptographic-algorithm\n"
"Use MD5 algorithm\n"
"Use HMAC-SHA-1 algorithm\n"
"Use HMAC-SHA-256 algorithm\n"
"Use HMAC-SHA-384 algorithm\n"
"Use HMAC-SHA-512 algorithm\n"
"Password\n"
"Password string (key)\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
#ifndef CRYPTO_OPENSSL
int hash_algo_idx = 7;
uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
#endif /* CRYPTO_OPENSSL */
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
oi = ospf6_interface_create(ifp);
assert(oi);
if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
return CMD_SUCCESS;
#ifndef CRYPTO_OPENSSL
hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
if (hash_algo == KEYCHAIN_ALGO_NULL) {
vty_out(vty,
"Hash algorithm not supported, compile with --with-crypto=openssl\n");
return CMD_WARNING_CONFIG_FAILED;
}
#endif /* CRYPTO_OPENSSL */
if (oi->at_data.auth_key) {
oi->at_data.flags = 0;
XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
oi->at_data.auth_key = NULL;
}
return CMD_SUCCESS;
}
void ospf6_interface_auth_trailer_cmd_init(void)
{
/*Install OSPF6 auth trailer commands at interface level */
install_element(INTERFACE_NODE,
&ipv6_ospf6_intf_auth_trailer_keychain_cmd);
install_element(INTERFACE_NODE,
&no_ipv6_ospf6_intf_auth_trailer_keychain_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_intf_auth_trailer_key_cmd);
install_element(INTERFACE_NODE,
&no_ipv6_ospf6_intf_auth_trailer_key_cmd);
}

View File

@ -24,6 +24,9 @@
#include "qobj.h"
#include "hook.h"
#include "if.h"
#include "ospf6d.h"
DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY);
/* Debug option */
extern unsigned char conf_debug_ospf6_interface;
@ -31,6 +34,21 @@ extern unsigned char conf_debug_ospf6_interface;
#define OSPF6_DEBUG_INTERFACE_OFF() (conf_debug_ospf6_interface = 0)
#define IS_OSPF6_DEBUG_INTERFACE (conf_debug_ospf6_interface)
struct ospf6_auth_data {
/* 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 */
struct ospf6_interface {
/* IF info from zebra */
@ -95,6 +113,9 @@ struct ospf6_interface {
/* MTU mismatch check */
uint8_t mtu_ignore;
/* Authentication trailer related config */
struct ospf6_auth_data at_data;
/* Decision of DR Election */
in_addr_t drouter;
in_addr_t bdrouter;
@ -221,6 +242,9 @@ extern void install_element_ospf6_debug_interface(void);
extern int ospf6_interface_neighbor_count(struct ospf6_interface *oi);
extern uint8_t dr_election(struct ospf6_interface *oi);
extern void ospf6_interface_auth_trailer_cmd_init(void);
extern void ospf6_auth_write_config(struct vty *vty,
struct ospf6_auth_data *at_data);
DECLARE_HOOK(ospf6_interface_change,
(struct ospf6_interface * oi, int state, int old_state),
(oi, state, old_state));

View 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));

View File

@ -20,6 +20,7 @@
#include <zebra.h>
#include <lib/version.h>
#include <lib/keychain.h>
#include <stdlib.h>
#include "getopt.h"
@ -223,6 +224,7 @@ int main(int argc, char *argv[], char *envp[])
/* thread master */
master = om6->master;
keychain_init();
ospf6_vrf_init();
access_list_init();
prefix_list_init();

View 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"
@ -48,19 +49,34 @@
#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);

View File

@ -25,6 +25,7 @@
/* 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
@ -62,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;
@ -146,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 */
@ -176,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 */

View 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");
}
}

View 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 */

View 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 */

View 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);
}

View File

@ -40,13 +40,20 @@
/* 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 */

View 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));

View 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))

View 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;

View File

@ -48,6 +48,7 @@
#include "ospf6_gr.h"
#include "lib/json.h"
#include "ospf6_nssa.h"
#include "ospf6_auth_trailer.h"
DEFINE_MGROUP(OSPF6D, "ospf6d");
@ -98,6 +99,7 @@ static int config_write_ospf6_debug(struct vty *vty)
config_write_ospf6_debug_flood(vty);
config_write_ospf6_debug_nssa(vty);
config_write_ospf6_debug_gr_helper(vty);
config_write_ospf6_debug_auth(vty);
return 0;
}
@ -1458,4 +1460,7 @@ void ospf6_init(struct thread_master *master)
VIEW_NODE,
&show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_database_aggr_router_cmd);
install_element_ospf6_debug_auth();
ospf6_interface_auth_trailer_cmd_init();
install_element_ospf6_clear_intf_auth();
}

View File

@ -24,6 +24,7 @@ vtysh_scan += \
ospf6d/ospf6_top.c \
ospf6d/ospf6_zebra.c \
ospf6d/ospf6d.c \
ospf6d/ospf6_auth_trailer.c \
# end
vtysh_daemons += ospf6d
if SNMP
@ -56,6 +57,7 @@ ospf6d_libospf6_a_SOURCES = \
ospf6d/ospf6_top.c \
ospf6d/ospf6_zebra.c \
ospf6d/ospf6d.c \
ospf6d/ospf6_auth_trailer.c \
# end
noinst_HEADERS += \
@ -80,6 +82,7 @@ noinst_HEADERS += \
ospf6d/ospf6_top.h \
ospf6d/ospf6_zebra.h \
ospf6d/ospf6d.h \
ospf6d/ospf6_auth_trailer.h \
# end
ospf6d_ospf6d_LDADD = ospf6d/libospf6.a lib/libfrr.la $(LIBCAP)

View File

@ -1933,7 +1933,7 @@ def verify_ospf6_interface(tgen, topo=None, dut=None, lan=False, input_dict=None
True or False (Error Message)
"""
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
logger.debug("Entering lib API: verify_ospf6_interface")
result = False
if topo is None:
@ -2311,6 +2311,7 @@ def config_ospf6_interface(
-------
True or False
"""
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
result = False
if topo is None:
@ -2337,6 +2338,7 @@ def config_ospf6_interface(
ospf_data = input_dict[router]["links"][lnk]["ospf6"]
data_ospf_area = ospf_data.setdefault("area", None)
data_ospf_auth = ospf_data.setdefault("hash-algo", None)
data_ospf_keychain = ospf_data.setdefault("keychain", None)
data_ospf_dr_priority = ospf_data.setdefault("priority", None)
data_ospf_cost = ospf_data.setdefault("cost", None)
data_ospf_mtu = ospf_data.setdefault("mtu_ignore", None)
@ -2369,9 +2371,18 @@ def config_ospf6_interface(
ospf_data["hash-algo"],
ospf_data["key"],
)
if "del_action" in ospf_data:
cmd = "no {}".format(cmd)
config_data.append(cmd)
config_data.append(cmd)
# interface ospf auth with keychain
if data_ospf_keychain:
cmd = "ipv6 ospf6 authentication"
if "del_action" in ospf_data:
cmd = "no {}".format(cmd)
if "keychain" in ospf_data:
cmd = "{} keychain {}".format(cmd, ospf_data["keychain"])
config_data.append(cmd)
# interface ospf dr priority
if data_ospf_dr_priority:

View File

@ -0,0 +1,169 @@
{
"address_types": [
"ipv6"
],
"ipv6base": "fd00::",
"ipv6mask": 64,
"link_ip_start": {
"ipv6": "fd00::",
"v6mask": 64
},
"lo_prefix": {
"ipv6": "2001:db8:f::",
"v6mask": 128
},
"routers": {
"r0": {
"links": {
"r1": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
},
"r2": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
},
"r3": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
}
},
"ospf6": {
"router_id": "100.1.1.0",
"neighbors": {
"r1": {},
"r2": {},
"r3": {}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
},
"r1": {
"links": {
"r0": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
},
"r2": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
},
"r3": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
}
},
"ospf6": {
"router_id": "100.1.1.1",
"neighbors": {
"r0": {},
"r2": {},
"r3": {}
}
}
},
"r2": {
"links": {
"r0": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
},
"r1": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
},
"r3": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
}
},
"ospf6": {
"router_id": "100.1.1.2",
"neighbors": {
"r1": {},
"r0": {},
"r3": {}
}
}
},
"r3": {
"links": {
"r0": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
},
"r1": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
},
"r2": {
"ipv6": "auto",
"ospf6": {
"area": "0.0.0.0",
"hello_interval": 1,
"dead_interval": 4
}
}
},
"ospf6": {
"router_id": "100.1.1.3",
"neighbors": {
"r0": {},
"r1": {},
"r2": {}
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -91,7 +91,7 @@ sub scan_file {
# $protocol is VTYSH_PROTO format for redirection of user input
if ($file =~ /lib\/keychain\.c$/) {
$protocol = "VTYSH_RIPD|VTYSH_EIGRPD";
$protocol = "VTYSH_RIPD|VTYSH_EIGRPD|VTYSH_OSPF6D";
}
elsif ($file =~ /lib\/routemap\.c$/ || $file =~ /lib\/routemap_cli\.c$/) {
$protocol = "VTYSH_RMAP";

View File

@ -57,7 +57,7 @@ DECLARE_MGROUP(MVTYSH);
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_FABRICD
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_PBRD|VTYSH_FABRICD|VTYSH_VRRPD
#define VTYSH_VRF VTYSH_INTERFACE|VTYSH_STATICD
#define VTYSH_KEYS VTYSH_RIPD|VTYSH_EIGRPD
#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D
/* Daemons who can process nexthop-group configs */
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
#define VTYSH_SR VTYSH_ZEBRA|VTYSH_PATHD