mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 09:00:55 +00:00
Merge pull request #8890 from rameshabhinay/ospf6_auth_trailer
OSPF6: Support OSPF6 authentication trailer RFC 7166
This commit is contained in:
commit
6142a17949
@ -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])
|
||||
|
||||
|
@ -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
|
||||
|
155
lib/keychain.c
155
lib/keychain.c
@ -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);
|
||||
}
|
||||
|
@ -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
1000
ospf6d/ospf6_auth_trailer.c
Normal file
File diff suppressed because it is too large
Load Diff
93
ospf6d/ospf6_auth_trailer.h
Normal file
93
ospf6d/ospf6_auth_trailer.h
Normal 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__ */
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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));
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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
@ -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";
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user