summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml16
-rw-r--r--Makefile.am5
-rw-r--r--bgpd/bgp_network.c4
-rw-r--r--bgpd/bgp_zebra.c6
-rw-r--r--configure.ac2
-rw-r--r--doc/developer/building-libyang.rst2
-rw-r--r--doc/developer/workflow.rst1
-rw-r--r--doc/user/eigrpd.rst3
-rw-r--r--doc/user/nhrpd.rst2
-rw-r--r--doc/user/ospf6d.rst1
-rw-r--r--doc/user/ospfd.rst6
-rw-r--r--doc/user/pathd.rst2
-rw-r--r--docker/centos-7/Dockerfile6
-rw-r--r--docker/centos-8/Dockerfile6
-rw-r--r--isisd/isis_snmp.c93
-rw-r--r--isisd/isis_sr.c9
-rw-r--r--lib/northbound_db.c17
-rw-r--r--lib/northbound_grpc.cpp100
-rw-r--r--lib/xref.h1
-rw-r--r--ospf6d/ospf6_top.c10
-rw-r--r--ospfd/ospf_api.c38
-rw-r--r--ospfd/ospf_api.h2
-rw-r--r--ospfd/ospf_apiserver.c14
-rw-r--r--ospfd/ospf_dump.c102
-rw-r--r--ospfd/ospf_ext.c83
-rw-r--r--ospfd/ospf_gr_helper.c16
-rw-r--r--ospfd/ospf_lsa.c9
-rw-r--r--ospfd/ospf_lsa.h7
-rw-r--r--ospfd/ospf_opaque.c3
-rw-r--r--ospfd/ospf_opaque.h1
-rw-r--r--ospfd/ospf_ri.c127
-rw-r--r--ospfd/ospf_ri.h19
-rw-r--r--ospfd/ospf_sr.c53
-rw-r--r--ospfd/ospf_sr.h1
-rw-r--r--ospfd/ospf_te.c167
-rw-r--r--ospfd/ospf_vty.c24
-rw-r--r--ospfd/ospfd.c10
-rw-r--r--pathd/path_cli.c16
-rw-r--r--pathd/path_pcep_pcc.c3
-rw-r--r--pathd/pathd.c6
-rw-r--r--tests/topotests/lib/common_config.py1
-rw-r--r--tests/topotests/lib/ospf.py12
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py85
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_single_area.py148
44 files changed, 875 insertions, 364 deletions
diff --git a/.travis.yml b/.travis.yml
index 010292bb6a..32b686c00e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,14 +5,14 @@ services:
- docker
jobs:
include:
- # - script:
- # - docker/centos-7/build.sh
- # - docker images
- # name: centos7
- # - script:
- # - docker/centos-8/build.sh
- # - docker images
- # name: centos8
+ - script:
+ - docker/centos-7/build.sh
+ - docker images
+ name: centos7
+ - script:
+ - docker/centos-8/build.sh
+ - docker images
+ name: centos8
- script:
- sudo apt install -y linux-modules-extra-$(uname -r)
- docker build -t frr-ubuntu18:latest -f docker/ubuntu18-ci/Dockerfile .
diff --git a/Makefile.am b/Makefile.am
index a5101df2f0..a38029dcfa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,6 +11,11 @@ AM_CFLAGS = \
$(SAN_FLAGS) \
$(WERROR) \
# end
+AM_CXXFLAGS = \
+ $(AC_CXXFLAGS) \
+ $(LIBYANG_CFLAGS) \
+ $(WERROR) \
+ # end
# CPPFLAGS_BASE does not contain the include path for overriding assert.h,
# therefore should be used in tools that do *not* link libfrr or do not want
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index f3857162c3..860c5fd382 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -572,7 +572,9 @@ static int bgp_accept(struct thread *thread)
peer->doppelganger = peer1;
peer1->doppelganger = peer;
peer->fd = bgp_sock;
- vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
+ frr_with_privs(&bgpd_privs) {
+ vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
+ }
bgp_peer_reg_with_nht(peer);
bgp_fsm_change_status(peer, Active);
BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 63214c5676..2bf57130be 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2609,6 +2609,9 @@ static void bgp_zebra_connected(struct zclient *zclient)
zclient_num_connects++; /* increment even if not responding */
+ /* Send the client registration */
+ bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
+
/* At this point, we may or may not have BGP instances configured, but
* we're only interested in the default VRF (others wouldn't have learnt
* the VRF from Zebra yet.)
@@ -2619,9 +2622,6 @@ static void bgp_zebra_connected(struct zclient *zclient)
bgp_zebra_instance_register(bgp);
- /* Send the client registration */
- bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, bgp->vrf_id);
-
/* tell label pool that zebra is connected */
bgp_lp_event_zebra_up();
diff --git a/configure.ac b/configure.ac
index f84a3d3c5e..6ed438ace0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ([2.69])
-AC_INIT([frr], [7.7-dev], [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [8.1-dev], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst
index a447f58309..3b33eb3879 100644
--- a/doc/developer/building-libyang.rst
+++ b/doc/developer/building-libyang.rst
@@ -10,7 +10,7 @@ The FRR project builds some binary ``libyang`` packages.
RPM packages are at our `RPM repository <https://rpm.frrouting.org>`_.
DEB packages are available as CI artifacts `here
-<https://ci1.netdef.org/browse/LIBYANG-LIBYANG-V2/latestSuccessful/artifact>`_.
+<https://ci1.netdef.org/browse/LIBYANG-LIBYANGV2/latestSuccessful/artifact>`_.
.. warning::
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index b4ddec10c9..58b9c36e01 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -1247,7 +1247,6 @@ the command :clicmd:`show pony` would be documented as follows:
.. code-block:: rest
- .. index:: show pony
.. clicmd:: show pony
Prints an ASCII pony. Example output:::
diff --git a/doc/user/eigrpd.rst b/doc/user/eigrpd.rst
index 573e2ca2e4..3650792a3e 100644
--- a/doc/user/eigrpd.rst
+++ b/doc/user/eigrpd.rst
@@ -152,8 +152,7 @@ Show EIGRP Information
Display the list of interfaces associated with a particular eigrp
instance.
-..index:: show ip eigrp [vrf NAME] neighbor
-..clicmd:: show ip eigrp [vrf NAME] neighbor
+.. clicmd:: show ip eigrp [vrf NAME] neighbor
Display the list of neighbors that have been established within
a particular eigrp instance.
diff --git a/doc/user/nhrpd.rst b/doc/user/nhrpd.rst
index cbbc2dc10a..54527a0c9a 100644
--- a/doc/user/nhrpd.rst
+++ b/doc/user/nhrpd.rst
@@ -198,13 +198,11 @@ original multicast packet.
iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j NFLOG --nflog-group 2
iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j DROP
-.. index:: nhrp multicast-nflog-group (1-65535)
.. clicmd:: nhrp multicast-nflog-group (1-65535)
Sets the nflog group that nhrpd will listen on for multicast packets. This
value must match the nflog-group value set in the iptables rule.
-.. index:: ip nhrp map multicast A.B.C.D|X:X::X:X A.B.C.D|dynamic
.. clicmd:: ip nhrp map multicast A.B.C.D|X:X::X:X A.B.C.D|dynamic
Sends multicast packets to the specified NBMA address. If dynamic is
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index d7f4a3303e..2b478d334e 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -139,7 +139,6 @@ Redistribute routes to OSPF6
Redistribute routes from other protocols into OSPFv3.
-.. index:: default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]
.. clicmd:: default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]
The command injects default route in the connected areas. The always
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index ba9917f72f..b321d99ad8 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -855,13 +855,11 @@ Traffic Engineering
flood in AREA <area-id> with Opaque Type-10, respectively in AS with Opaque
Type-11. In all case, Opaque-LSA TLV=6.
-.. index:: mpls-te export
.. clicmd:: no mpls-te export
Export Traffic Engineering Data Base to other daemons through the ZAPI
Opaque Link State messages.
-.. index:: show ip ospf mpls-te interface
.. clicmd:: show ip ospf mpls-te interface
.. clicmd:: show ip ospf mpls-te interface INTERFACE
@@ -872,16 +870,12 @@ Traffic Engineering
Show Traffic Engineering router parameters.
-.. index:: show ip ospf mpls-te database [verbose|json]
.. clicmd:: show ip ospf mpls-te database [verbose|json]
-.. index:: show ip ospf mpls-te database vertex [self-originate|adv-router ADV-ROUTER] [verbose|json]
.. clicmd:: show ip ospf mpls-te database vertex [self-originate|adv-router ADV-ROUTER] [verbose|json]
-.. index:: show ip ospf mpls-te database edge [A.B.C.D] [verbose|json]
.. clicmd:: show ip ospf mpls-te database edge [A.B.C.D] [verbose|json]
-.. index:: show ip ospf mpls-te database subnet [A.B.C.D/M] [verbose|json]
.. clicmd:: show ip ospf mpls-te database subnet [A.B.C.D/M] [verbose|json]
Show Traffic Engineering Database
diff --git a/doc/user/pathd.rst b/doc/user/pathd.rst
index c40efffc88..4c7611bc04 100644
--- a/doc/user/pathd.rst
+++ b/doc/user/pathd.rst
@@ -149,7 +149,7 @@ Configuration Commands
Delete or start a dynamic candidate path definition.
-.. clicmd:: affinity {exclude-any|include-any|include-all} BITPATTERN
+.. clicmd:: affinity <exclude-any|include-any|include-all> BITPATTERN
Delete or specify an affinity constraint for a dynamic candidate path.
diff --git a/docker/centos-7/Dockerfile b/docker/centos-7/Dockerfile
index d2ec9f974b..748b5345a1 100644
--- a/docker/centos-7/Dockerfile
+++ b/docker/centos-7/Dockerfile
@@ -5,8 +5,8 @@ RUN yum install -y rpm-build autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel bison flex pytest c-ares-devel \
python3-devel python3-sphinx systemd-devel libcap-devel \
- https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-7-x86_64-Packages/libyang1-1.0.184-0.x86_64.rpm \
- https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-7-x86_64-Packages/libyang-devel-1.0.184-0.x86_64.rpm \
+ https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-7-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el7.x86_64.rpm \
+ https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-7-x86_64-Packages/libyang2-devel-2.0.0.10.g2eb910e4-1.el7.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-devel-0.7.0-1.el7.centos.x86_64.rpm
@@ -32,7 +32,7 @@ RUN echo '%_smp_mflags %( echo "-j$(/usr/bin/getconf _NPROCESSORS_ONLN)"; )' >>
# This stage installs frr from the rpm
FROM centos:centos7
RUN mkdir -p /pkgs/rpm \
- && yum install -y https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-7-x86_64-Packages/libyang1-1.0.184-0.x86_64.rpm \
+ && yum install -y https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-7-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el7.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm
COPY --from=centos-7-builder /rpmbuild/RPMS/ /pkgs/rpm/
diff --git a/docker/centos-8/Dockerfile b/docker/centos-8/Dockerfile
index 104501aabc..e273be055b 100644
--- a/docker/centos-8/Dockerfile
+++ b/docker/centos-8/Dockerfile
@@ -5,8 +5,8 @@ RUN dnf install --enablerepo=powertools -y rpm-build git autoconf pcre-devel \
automake libtool make readline-devel texinfo net-snmp-devel pkgconfig \
groff pkgconfig json-c-devel pam-devel bison flex python3-pytest \
c-ares-devel python3-devel python3-sphinx systemd-devel libcap-devel platform-python-devel \
- https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-8-x86_64-Packages/libyang1-1.0.184-0.x86_64.rpm \
- https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-8-x86_64-Packages/libyang-devel-1.0.184-0.x86_64.rpm \
+ https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
+ https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-devel-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-devel-0.7.0-1.el7.centos.x86_64.rpm
@@ -33,7 +33,7 @@ RUN echo '%_smp_mflags %( echo "-j$(/usr/bin/getconf _NPROCESSORS_ONLN)"; )' >>
# This stage installs frr from the rpm
FROM centos:centos8
RUN mkdir -p /pkgs/rpm \
- && yum install -y https://ci1.netdef.org/artifact/LIBYANG-LY1REL/shared/build-4/CentOS-8-x86_64-Packages/libyang1-1.0.184-0.x86_64.rpm \
+ && yum install -y https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm
COPY --from=centos-8-builder /rpmbuild/RPMS/ /pkgs/rpm/
diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c
index dfc865162f..fa2f9a7669 100644
--- a/isisd/isis_snmp.c
+++ b/isisd/isis_snmp.c
@@ -616,11 +616,44 @@ static uint8_t isis_null_sysid[ISIS_SYS_ID_LEN];
#define ISIS_SNMP_ADJ_STATE_UP (3)
#define ISIS_SNMP_ADJ_STATE_FAILED (4)
+static inline uint32_t isis_snmp_adj_state(enum isis_adj_state state)
+{
+ switch (state) {
+ case ISIS_ADJ_UNKNOWN:
+ return ISIS_SNMP_ADJ_STATE_DOWN;
+ case ISIS_ADJ_INITIALIZING:
+ return ISIS_SNMP_ADJ_STATE_INITIALIZING;
+ case ISIS_ADJ_UP:
+ return ISIS_SNMP_ADJ_STATE_UP;
+ case ISIS_ADJ_DOWN:
+ return ISIS_SNMP_ADJ_STATE_FAILED;
+ }
+
+ return 0; /* not reached */
+}
+
#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1 (1)
#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2 (2)
#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2 (3)
#define ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN (4)
+static inline uint32_t isis_snmp_adj_neightype(enum isis_system_type type)
+{
+ switch (type) {
+ case ISIS_SYSTYPE_UNKNOWN:
+ case ISIS_SYSTYPE_ES:
+ return ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN;
+ case ISIS_SYSTYPE_IS:
+ return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2;
+ case ISIS_SYSTYPE_L1_IS:
+ return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1;
+ case ISIS_SYSTYPE_L2_IS:
+ return ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2;
+ }
+
+ return 0; /* not reached */
+}
+
#define ISIS_SNMP_INET_TYPE_V4 (1)
#define ISIS_SNMP_INET_TYPE_V6 (2)
@@ -2510,23 +2543,7 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
switch (v->magic) {
case ISIS_ISADJ_STATE:
-
- switch (adj->adj_state) {
- case ISIS_ADJ_UNKNOWN:
- case ISIS_ADJ_DOWN:
- val = ISIS_SNMP_ADJ_STATE_DOWN;
- break;
-
- case ISIS_ADJ_INITIALIZING:
- val = ISIS_SNMP_ADJ_STATE_INITIALIZING;
- break;
-
- case ISIS_ADJ_UP:
- val = ISIS_SNMP_ADJ_STATE_UP;
- break;
- }
-
- return SNMP_INTEGER(val);
+ return SNMP_INTEGER(isis_snmp_adj_state(adj->adj_state));
case ISIS_ISADJ_3WAYSTATE:
return SNMP_INTEGER(adj->threeway_state);
@@ -2538,27 +2555,7 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
}
case ISIS_ISADJ_NEIGHSYSTYPE:
-
- switch (adj->sys_type) {
- case ISIS_SYSTYPE_UNKNOWN:
- case ISIS_SYSTYPE_ES:
- val = ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN;
- break;
-
- case ISIS_SYSTYPE_IS:
- val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2;
- break;
-
- case ISIS_SYSTYPE_L1_IS:
- val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1;
- break;
-
- case ISIS_SYSTYPE_L2_IS:
- val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2;
- break;
- }
-
- return SNMP_INTEGER(val);
+ return SNMP_INTEGER(isis_snmp_adj_neightype(adj->sys_type));
case ISIS_ISADJ_NEIGHSYSID:
*var_len = sizeof(adj->sysid);
@@ -3345,25 +3342,7 @@ static int isis_snmp_adj_state_change_update(const struct isis_adjacency *adj)
lsp_id[ISIS_SYS_ID_LEN] = 0;
lsp_id[ISIS_SYS_ID_LEN + 1] = 0;
- val = ISIS_SNMP_ADJ_STATE_DOWN;
-
- switch (adj->adj_state) {
- case ISIS_ADJ_UNKNOWN:
- val = ISIS_SNMP_ADJ_STATE_DOWN;
- break;
-
- case ISIS_ADJ_INITIALIZING:
- val = ISIS_SNMP_ADJ_STATE_INITIALIZING;
- break;
-
- case ISIS_ADJ_UP:
- val = ISIS_SNMP_ADJ_STATE_UP;
- break;
-
- case ISIS_ADJ_DOWN:
- val = ISIS_SNMP_ADJ_STATE_FAILED;
- break;
- }
+ val = isis_snmp_adj_state(adj->adj_state);
isis_snmp_update_worker_b(
adj->circuit, ISIS_TRAP_ADJ_STATE_CHANGE,
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index c4024772f5..f7cef43d0d 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -361,9 +361,9 @@ struct sr_prefix_cfg *isis_sr_cfg_prefix_add(struct isis_area *area,
pcfg->last_hop_behavior = yang_get_default_enum(
"%s/prefix-sid-map/prefix-sid/last-hop-behavior", ISIS_SR);
- /* Set the N-flag when appropriate. */
+ /* Mark as node Sid if the prefix is host and configured in loopback */
ifp = if_lookup_prefix(prefix, VRF_DEFAULT);
- if (ifp && sr_prefix_is_node_sid(ifp, prefix) && !pcfg->n_flag_clear)
+ if (ifp && sr_prefix_is_node_sid(ifp, prefix))
pcfg->node_sid = true;
/* Save prefix-sid configuration. */
@@ -438,7 +438,7 @@ void isis_sr_prefix_cfg2subtlv(const struct sr_prefix_cfg *pcfg, bool external,
}
if (external)
SET_FLAG(psid->flags, ISIS_PREFIX_SID_READVERTISED);
- if (pcfg->node_sid)
+ if (pcfg->node_sid && !pcfg->n_flag_clear)
SET_FLAG(psid->flags, ISIS_PREFIX_SID_NODE);
/* Set SID value. */
@@ -948,8 +948,7 @@ static int sr_if_new_hook(struct interface *ifp)
if (!pcfg)
continue;
- if (sr_prefix_is_node_sid(ifp, &pcfg->prefix)
- && !pcfg->n_flag_clear) {
+ if (sr_prefix_is_node_sid(ifp, &pcfg->prefix)) {
pcfg->node_sid = true;
lsp_regenerate_schedule(area, area->is_type, 0);
}
diff --git a/lib/northbound_db.c b/lib/northbound_db.c
index 244e760b2b..dce9b2ec24 100644
--- a/lib/northbound_db.c
+++ b/lib/northbound_db.c
@@ -87,9 +87,12 @@ int nb_db_transaction_save(const struct nb_transaction *transaction,
goto exit;
client_name = nb_client_name(transaction->context->client);
- /* Always record configurations in the XML format. */
+ /*
+ * Always record configurations in the XML format, save the default
+ * values too, as this covers the case where defaults may change.
+ */
if (lyd_print_mem(&config_str, transaction->config->dnode, LYD_XML,
- LYP_FORMAT | LYP_WITHSIBLINGS)
+ LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL)
!= 0)
goto exit;
@@ -149,6 +152,7 @@ struct nb_config *nb_db_transaction_load(uint32_t transaction_id)
struct lyd_node *dnode;
const char *config_str;
struct sqlite3_stmt *ss;
+ LY_ERR err;
ss = db_prepare(
"SELECT\n"
@@ -169,10 +173,11 @@ struct nb_config *nb_db_transaction_load(uint32_t transaction_id)
if (db_loadf(ss, "%s", &config_str) != 0)
goto exit;
- dnode = lyd_parse_mem(ly_native_ctx, config_str, LYD_XML,
- LYD_OPT_CONFIG);
- if (!dnode)
- flog_warn(EC_LIB_LIBYANG, "%s: lyd_parse_mem() failed",
+ err = lyd_parse_data_mem(ly_native_ctx, config_str, LYD_XML,
+ LYD_PARSE_STRICT | LYD_PARSE_NO_STATE,
+ LYD_VALIDATE_NO_STATE, &dnode);
+ if (err || !dnode)
+ flog_warn(EC_LIB_LIBYANG, "%s: lyd_parse_data_mem() failed",
__func__);
else
config = nb_config_new(dnode);
diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp
index dc2d29c11d..c61effdda5 100644
--- a/lib/northbound_grpc.cpp
+++ b/lib/northbound_grpc.cpp
@@ -199,9 +199,8 @@ class NorthboundImpl
auto m = tag->response.add_supported_modules();
m->set_name(module->name);
- if (module->info->rev_size)
- m->set_revision(
- module->info->rev[0].date);
+ if (module->info->revision)
+ m->set_revision(module->info->revision);
m->set_organization(module->info->org);
}
@@ -1068,14 +1067,13 @@ class NorthboundImpl
const std::string &path,
const std::string &value)
{
- ly_errno = LY_SUCCESS;
- dnode = lyd_new_path(dnode, ly_native_ctx, path.c_str(),
- (void *)value.c_str(),
- (LYD_ANYDATA_VALUETYPE)0,
- LYD_PATH_OPT_UPDATE);
- if (!dnode && ly_errno != LY_SUCCESS) {
- flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed",
- __func__);
+ LY_ERR err = lyd_new_path(dnode, ly_native_ctx, path.c_str(),
+ value.c_str(), LYD_NEW_PATH_UPDATE,
+ &dnode);
+ if (err != LY_SUCCESS) {
+ flog_warn(EC_LIB_LIBYANG,
+ "%s: lyd_new_path() failed: %s", __func__,
+ ly_errmsg(ly_native_ctx));
return -1;
}
@@ -1089,7 +1087,7 @@ class NorthboundImpl
if (!dnode)
return -1;
- lyd_free(dnode);
+ lyd_free_tree(dnode);
return 0;
}
@@ -1132,46 +1130,53 @@ class NorthboundImpl
std::string(date), std::string(comment)));
}
- static int data_tree_from_dnode(frr::DataTree *dt,
- const struct lyd_node *dnode,
- LYD_FORMAT lyd_format,
- bool with_defaults)
+ static LY_ERR data_tree_from_dnode(frr::DataTree *dt,
+ const struct lyd_node *dnode,
+ LYD_FORMAT lyd_format,
+ bool with_defaults)
{
char *strp;
int options = 0;
- SET_FLAG(options, LYP_FORMAT | LYP_WITHSIBLINGS);
+ SET_FLAG(options, LYD_PRINT_WITHSIBLINGS);
if (with_defaults)
- SET_FLAG(options, LYP_WD_ALL);
+ SET_FLAG(options, LYD_PRINT_WD_ALL);
else
- SET_FLAG(options, LYP_WD_TRIM);
+ SET_FLAG(options, LYD_PRINT_WD_TRIM);
- if (lyd_print_mem(&strp, dnode, lyd_format, options) == 0) {
+ LY_ERR err = lyd_print_mem(&strp, dnode, lyd_format, options);
+ if (err == LY_SUCCESS) {
if (strp) {
dt->set_data(strp);
free(strp);
}
- return 0;
}
-
- return -1;
+ return err;
}
static struct lyd_node *dnode_from_data_tree(const frr::DataTree *dt,
bool config_only)
{
struct lyd_node *dnode;
- int options;
-
- if (config_only)
- options = LYD_OPT_CONFIG;
- else
- options = LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB;
-
- dnode = lyd_parse_mem(ly_native_ctx, dt->data().c_str(),
- encoding2lyd_format(dt->encoding()),
- options);
+ int options, opt2;
+ LY_ERR err;
+
+ if (config_only) {
+ options = LYD_PARSE_STRICT | LYD_PARSE_NO_STATE;
+ opt2 = LYD_VALIDATE_NO_STATE;
+ } else {
+ options = LYD_PARSE_STRICT;
+ opt2 = 0;
+ }
+ err = lyd_parse_data_mem(ly_native_ctx, dt->data().c_str(),
+ encoding2lyd_format(dt->encoding()),
+ options, opt2, &dnode);
+ if (err != LY_SUCCESS) {
+ flog_warn(EC_LIB_LIBYANG,
+ "%s: lyd_parse_mem() failed: %s", __func__,
+ ly_errmsg(ly_native_ctx));
+ }
return dnode;
}
@@ -1239,14 +1244,15 @@ class NorthboundImpl
// Combine configuration and state data into a single
// dnode.
//
- if (lyd_merge(dnode_state, dnode_config,
- LYD_OPT_EXPLICIT)
- != 0) {
+ if (lyd_merge_tree(&dnode_state, dnode_config,
+ LYD_MERGE_DESTRUCT)
+ != LY_SUCCESS) {
yang_dnode_free(dnode_state);
yang_dnode_free(dnode_config);
return grpc::Status(
grpc::StatusCode::INTERNAL,
- "Failed to merge configuration and state data");
+ "Failed to merge configuration and state data",
+ ly_errmsg(ly_native_ctx));
}
dnode_final = dnode_state;
@@ -1262,19 +1268,25 @@ class NorthboundImpl
// Validate data to create implicit default nodes if necessary.
int validate_opts = 0;
if (type == frr::GetRequest_DataType_CONFIG)
- validate_opts = LYD_OPT_CONFIG;
+ validate_opts = LYD_VALIDATE_NO_STATE;
else
- validate_opts = LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB;
- lyd_validate(&dnode_final, validate_opts, ly_native_ctx);
+ validate_opts = 0;
+ LY_ERR err = lyd_validate_all(&dnode_final, ly_native_ctx,
+ validate_opts, NULL);
+
+ if (err)
+ flog_warn(EC_LIB_LIBYANG,
+ "%s: lyd_validate_all() failed: %s", __func__,
+ ly_errmsg(ly_native_ctx));
// Dump data using the requested format.
- int ret = data_tree_from_dnode(dt, dnode_final, lyd_format,
- with_defaults);
+ if (!err)
+ err = data_tree_from_dnode(dt, dnode_final, lyd_format,
+ with_defaults);
yang_dnode_free(dnode_final);
- if (ret != 0)
+ if (err)
return grpc::Status(grpc::StatusCode::INTERNAL,
"Failed to dump data");
-
return grpc::Status::OK;
}
diff --git a/lib/xref.h b/lib/xref.h
index 949458b313..6cff1a3769 100644
--- a/lib/xref.h
+++ b/lib/xref.h
@@ -169,6 +169,7 @@ extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
static void __attribute__((used, _CONSTRUCTOR(1100))) \
_xref_init(void) { \
static struct xref_block _xref_block = { \
+ .next = NULL, \
.start = __start_xref_array, \
.stop = __stop_xref_array, \
}; \
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index a5c188c465..2376409ccd 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -156,6 +156,16 @@ static void ospf6_set_redist_vrf_bitmaps(struct ospf6 *ospf6, bool set)
vrf_bitmap_unset(zclient->redist[AFI_IP6][type],
ospf6->vrf_id);
}
+
+ red_list = ospf6->redist[DEFAULT_ROUTE];
+ if (red_list) {
+ if (set)
+ vrf_bitmap_set(zclient->default_information[AFI_IP6],
+ ospf6->vrf_id);
+ else
+ vrf_bitmap_unset(zclient->default_information[AFI_IP6],
+ ospf6->vrf_id);
+ }
}
/* Disable OSPF6 VRF instance */
diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c
index 7e7236a3b6..81de882754 100644
--- a/ospfd/ospf_api.c
+++ b/ospfd/ospf_api.c
@@ -58,7 +58,7 @@
/* For debugging only, will be removed */
-void api_opaque_lsa_print(struct lsa_header *data)
+void api_opaque_lsa_print(struct ospf_lsa *lsa)
{
struct opaque_lsa {
struct lsa_header header;
@@ -69,11 +69,11 @@ void api_opaque_lsa_print(struct lsa_header *data)
int opaquelen;
int i;
- ospf_lsa_header_dump(data);
+ ospf_lsa_header_dump(lsa->data);
- olsa = (struct opaque_lsa *)data;
+ olsa = (struct opaque_lsa *)lsa->data;
- opaquelen = ntohs(data->length) - OSPF_LSA_HEADER_SIZE;
+ opaquelen = lsa->size - OSPF_LSA_HEADER_SIZE;
zlog_debug("apiserver_lsa_print: opaquelen=%d", opaquelen);
for (i = 0; i < opaquelen; i++) {
@@ -111,11 +111,16 @@ struct msg *msg_new(uint8_t msgtype, void *msgbody, uint32_t seqnum,
struct msg *msg_dup(struct msg *msg)
{
struct msg *new;
+ size_t size;
assert(msg);
+ size = ntohs(msg->hdr.msglen);
+ if (size > OSPF_MAX_LSA_SIZE)
+ return NULL;
+
new = msg_new(msg->hdr.msgtype, STREAM_DATA(msg->s),
- ntohl(msg->hdr.msgseq), ntohs(msg->hdr.msglen));
+ ntohl(msg->hdr.msgseq), size);
return new;
}
@@ -400,7 +405,7 @@ struct msg *msg_read(int fd)
}
/* Allocate new message */
- msg = msg_new(hdr.msgtype, buf, ntohl(hdr.msgseq), ntohs(hdr.msglen));
+ msg = msg_new(hdr.msgtype, buf, ntohl(hdr.msgseq), bodylen);
return msg;
}
@@ -408,29 +413,34 @@ struct msg *msg_read(int fd)
int msg_write(int fd, struct msg *msg)
{
uint8_t buf[OSPF_API_MAX_MSG_SIZE];
- int l;
+ uint16_t l;
int wlen;
assert(msg);
assert(msg->s);
- /* Length of message including header */
- l = sizeof(struct apimsghdr) + ntohs(msg->hdr.msglen);
+ /* Length of OSPF LSA payload */
+ l = ntohs(msg->hdr.msglen);
+ if (l > OSPF_MAX_LSA_SIZE) {
+ zlog_warn("%s: wrong LSA size %d", __func__, l);
+ return -1;
+ }
/* Make contiguous memory buffer for message */
memcpy(buf, &msg->hdr, sizeof(struct apimsghdr));
- memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s),
- ntohs(msg->hdr.msglen));
+ memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s), l);
+ /* Total length of OSPF API Message */
+ l += sizeof(struct apimsghdr);
wlen = writen(fd, buf, l);
if (wlen < 0) {
- zlog_warn("msg_write: writen %s", safe_strerror(errno));
+ zlog_warn("%s: writen %s", __func__, safe_strerror(errno));
return -1;
} else if (wlen == 0) {
- zlog_warn("msg_write: Connection closed by peer");
+ zlog_warn("%s: Connection closed by peer", __func__);
return -1;
} else if (wlen != l) {
- zlog_warn("msg_write: Cannot write API message");
+ zlog_warn("%s: Cannot write API message", __func__);
return -1;
}
return 0;
diff --git a/ospfd/ospf_api.h b/ospfd/ospf_api.h
index 0fc683a5db..c20284aed5 100644
--- a/ospfd/ospf_api.h
+++ b/ospfd/ospf_api.h
@@ -276,7 +276,7 @@ struct apimsg {
*/
/* For debugging only. */
-extern void api_opaque_lsa_print(struct lsa_header *data);
+extern void api_opaque_lsa_print(struct ospf_lsa *lsa);
/* Messages sent by client */
extern struct msg *new_msg_register_opaque_type(uint32_t seqnum, uint8_t ltype,
diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c
index c01ecdd1d4..cbd03441ef 100644
--- a/ospfd/ospf_apiserver.c
+++ b/ospfd/ospf_apiserver.c
@@ -1156,6 +1156,7 @@ int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv,
struct msg_register_event *rmsg;
int rc;
uint32_t seqnum;
+ size_t size;
rmsg = (struct msg_register_event *)STREAM_DATA(msg->s);
@@ -1165,13 +1166,16 @@ int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv,
/* Free existing filter in apiserv. */
XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
/* Alloc new space for filter. */
+ size = ntohs(msg->hdr.msglen);
+ if (size < OSPF_MAX_LSA_SIZE) {
- apiserv->filter =
- XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, ntohs(msg->hdr.msglen));
+ apiserv->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, size);
- /* copy it over. */
- memcpy(apiserv->filter, &rmsg->filter, ntohs(msg->hdr.msglen));
- rc = OSPF_API_OK;
+ /* copy it over. */
+ memcpy(apiserv->filter, &rmsg->filter, size);
+ rc = OSPF_API_OK;
+ } else
+ rc = OSPF_API_NOMEMORY;
/* Send a reply back to client with return code */
rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index 8f31f90346..e490070d03 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -241,7 +241,7 @@ const char *ospf_timer_dump(struct thread *t, char *buf, size_t size)
static void ospf_packet_hello_dump(struct stream *s, uint16_t length)
{
struct ospf_hello *hello;
- int i;
+ int i, len;
hello = (struct ospf_hello *)stream_pnt(s);
@@ -256,9 +256,9 @@ static void ospf_packet_hello_dump(struct stream *s, uint16_t length)
zlog_debug(" DRouter %pI4", &hello->d_router);
zlog_debug(" BDRouter %pI4", &hello->bd_router);
- length -= OSPF_HEADER_SIZE + OSPF_HELLO_MIN_SIZE;
- zlog_debug(" # Neighbors %d", length / 4);
- for (i = 0; length > 0; i++, length -= sizeof(struct in_addr))
+ len = length - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE;
+ zlog_debug(" # Neighbors %d", len / 4);
+ for (i = 0; len > 0; i++, len -= sizeof(struct in_addr))
zlog_debug(" Neighbor %pI4", &hello->neighbors[i]);
}
@@ -285,7 +285,8 @@ static void ospf_router_lsa_dump(struct stream *s, uint16_t length)
{
char buf[BUFSIZ];
struct router_lsa *rl;
- int i, len;
+ struct router_link *rlnk;
+ int i, len, sum;
rl = (struct router_lsa *)stream_pnt(s);
@@ -294,16 +295,15 @@ static void ospf_router_lsa_dump(struct stream *s, uint16_t length)
ospf_router_lsa_flags_dump(rl->flags, buf, BUFSIZ));
zlog_debug(" # links %d", ntohs(rl->links));
- len = ntohs(rl->header.length) - OSPF_LSA_HEADER_SIZE - 4;
- for (i = 0; len > 0; i++) {
- zlog_debug(" Link ID %pI4", &rl->link[i].link_id);
- zlog_debug(" Link Data %pI4",
- &rl->link[i].link_data);
- zlog_debug(" Type %d", (uint8_t)rl->link[i].type);
- zlog_debug(" TOS %d", (uint8_t)rl->link[i].tos);
- zlog_debug(" metric %d", ntohs(rl->link[i].metric));
-
- len -= 12;
+ len = length - OSPF_LSA_HEADER_SIZE - 4;
+ rlnk = &rl->link[0];
+ sum = 0;
+ for (i = 0; sum < len && rlnk; sum += 12, rlnk = &rl->link[++i]) {
+ zlog_debug(" Link ID %pI4", &rlnk->link_id);
+ zlog_debug(" Link Data %pI4", &rlnk->link_data);
+ zlog_debug(" Type %d", (uint8_t)rlnk->type);
+ zlog_debug(" TOS %d", (uint8_t)rlnk->tos);
+ zlog_debug(" metric %d", ntohs(rlnk->metric));
}
}
@@ -312,10 +312,11 @@ static void ospf_network_lsa_dump(struct stream *s, uint16_t length)
struct network_lsa *nl;
int i, cnt;
+ zlog_debug(" Network-LSA");
+
nl = (struct network_lsa *)stream_pnt(s);
- cnt = (ntohs(nl->header.length) - (OSPF_LSA_HEADER_SIZE + 4)) / 4;
+ cnt = (length - (OSPF_LSA_HEADER_SIZE + 4)) / 4;
- zlog_debug(" Network-LSA");
/*
zlog_debug ("LSA total size %d", ntohs (nl->header.length));
zlog_debug ("Network-LSA size %d",
@@ -331,55 +332,53 @@ static void ospf_network_lsa_dump(struct stream *s, uint16_t length)
static void ospf_summary_lsa_dump(struct stream *s, uint16_t length)
{
struct summary_lsa *sl;
- int size;
- int i;
sl = (struct summary_lsa *)stream_pnt(s);
zlog_debug(" Summary-LSA");
zlog_debug(" Network Mask %pI4", &sl->mask);
-
- size = ntohs(sl->header.length) - OSPF_LSA_HEADER_SIZE - 4;
- for (i = 0; size > 0; size -= 4, i++)
- zlog_debug(" TOS=%d metric %d", sl->tos,
- GET_METRIC(sl->metric));
+ zlog_debug(" TOS=%d metric %d", sl->tos, GET_METRIC(sl->metric));
}
static void ospf_as_external_lsa_dump(struct stream *s, uint16_t length)
{
struct as_external_lsa *al;
- int size;
+ struct as_route *asr;
+ int size, sum;
int i;
al = (struct as_external_lsa *)stream_pnt(s);
zlog_debug(" %s", ospf_lsa_type_msg[al->header.type].str);
zlog_debug(" Network Mask %pI4", &al->mask);
- size = ntohs(al->header.length) - OSPF_LSA_HEADER_SIZE - 4;
- for (i = 0; size > 0; size -= 12, i++) {
+ size = length - OSPF_LSA_HEADER_SIZE - 4;
+ asr = &al->e[0];
+ sum = 0;
+ for (i = 0; sum < size && asr; sum += 12, asr = &al->e[++i]) {
zlog_debug(" bit %s TOS=%d metric %d",
- IS_EXTERNAL_METRIC(al->e[i].tos) ? "E" : "-",
- al->e[i].tos & 0x7f, GET_METRIC(al->e[i].metric));
- zlog_debug(" Forwarding address %pI4",
- &al->e[i].fwd_addr);
+ IS_EXTERNAL_METRIC(asr->tos) ? "E" : "-",
+ asr->tos & 0x7f, GET_METRIC(asr->metric));
+ zlog_debug(" Forwarding address %pI4", &asr->fwd_addr);
zlog_debug(" External Route Tag %" ROUTE_TAG_PRI,
- al->e[i].route_tag);
+ asr->route_tag);
}
}
static void ospf_lsa_header_list_dump(struct stream *s, uint16_t length)
{
struct lsa_header *lsa;
+ int len;
zlog_debug(" # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE);
/* LSA Headers. */
- while (length > 0) {
+ len = length;
+ while (len > 0) {
lsa = (struct lsa_header *)stream_pnt(s);
ospf_lsa_header_dump(lsa);
stream_forward_getp(s, OSPF_LSA_HEADER_SIZE);
- length -= OSPF_LSA_HEADER_SIZE;
+ len -= OSPF_LSA_HEADER_SIZE;
}
}
@@ -417,6 +416,7 @@ static void ospf_packet_ls_req_dump(struct stream *s, uint16_t length)
uint32_t ls_type;
struct in_addr ls_id;
struct in_addr adv_router;
+ int sum;
sp = stream_get_getp(s);
@@ -425,7 +425,8 @@ static void ospf_packet_ls_req_dump(struct stream *s, uint16_t length)
zlog_debug("Link State Request");
zlog_debug(" # Requests %d", length / 12);
- for (; length > 0; length -= 12) {
+ sum = 0;
+ for (; sum < length; sum += 12) {
ls_type = stream_getl(s);
ls_id.s_addr = stream_get_ipv4(s);
adv_router.s_addr = stream_get_ipv4(s);
@@ -442,23 +443,23 @@ static void ospf_packet_ls_upd_dump(struct stream *s, uint16_t length)
{
uint32_t sp;
struct lsa_header *lsa;
- int lsa_len;
+ int lsa_len, len;
uint32_t count;
- length -= OSPF_HEADER_SIZE;
+ len = length - OSPF_HEADER_SIZE;
sp = stream_get_getp(s);
count = stream_getl(s);
- length -= 4;
+ len -= 4;
zlog_debug("Link State Update");
zlog_debug(" # LSAs %d", count);
- while (length > 0 && count > 0) {
- if (length < OSPF_HEADER_SIZE || length % 4 != 0) {
+ while (len > 0 && count > 0) {
+ if ((uint16_t)len < OSPF_LSA_HEADER_SIZE || len % 4 != 0) {
zlog_debug(" Remaining %d bytes; Incorrect length.",
- length);
+ len);
break;
}
@@ -466,34 +467,39 @@ static void ospf_packet_ls_upd_dump(struct stream *s, uint16_t length)
lsa_len = ntohs(lsa->length);
ospf_lsa_header_dump(lsa);
+ /* Check that LSA length is valid */
+ if (lsa_len > len || lsa_len % 4 != 0) {
+ zlog_debug(" LSA length %d is incorrect!", lsa_len);
+ break;
+ }
switch (lsa->type) {
case OSPF_ROUTER_LSA:
- ospf_router_lsa_dump(s, length);
+ ospf_router_lsa_dump(s, lsa_len);
break;
case OSPF_NETWORK_LSA:
- ospf_network_lsa_dump(s, length);
+ ospf_network_lsa_dump(s, lsa_len);
break;
case OSPF_SUMMARY_LSA:
case OSPF_ASBR_SUMMARY_LSA:
- ospf_summary_lsa_dump(s, length);
+ ospf_summary_lsa_dump(s, lsa_len);
break;
case OSPF_AS_EXTERNAL_LSA:
- ospf_as_external_lsa_dump(s, length);
+ ospf_as_external_lsa_dump(s, lsa_len);
break;
case OSPF_AS_NSSA_LSA:
- ospf_as_external_lsa_dump(s, length);
+ ospf_as_external_lsa_dump(s, lsa_len);
break;
case OSPF_OPAQUE_LINK_LSA:
case OSPF_OPAQUE_AREA_LSA:
case OSPF_OPAQUE_AS_LSA:
- ospf_opaque_lsa_dump(s, length);
+ ospf_opaque_lsa_dump(s, lsa_len);
break;
default:
break;
}
stream_forward_getp(s, lsa_len);
- length -= lsa_len;
+ len -= lsa_len;
count--;
}
diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c
index 754e2bcbab..2d08eeece2 100644
--- a/ospfd/ospf_ext.c
+++ b/ospfd/ospf_ext.c
@@ -1715,13 +1715,23 @@ static void ospf_ext_lsa_schedule(struct ext_itf *exti, enum lsa_opcode op)
* ------------------------------------
*/
+#define check_tlv_size(size, msg) \
+ do { \
+ if (ntohs(tlvh->length) != size) { \
+ vty_out(vty, " Wrong %s TLV size: %d(%d). Abort!\n", \
+ msg, ntohs(tlvh->length), size); \
+ return size + TLV_HDR_SIZE; \
+ } \
+ } while (0)
+
/* Cisco experimental SubTLV */
static uint16_t show_vty_ext_link_rmt_itf_addr(struct vty *vty,
struct tlv_header *tlvh)
{
- struct ext_subtlv_rmt_itf_addr *top;
+ struct ext_subtlv_rmt_itf_addr *top =
+ (struct ext_subtlv_rmt_itf_addr *)tlvh;
- top = (struct ext_subtlv_rmt_itf_addr *)tlvh;
+ check_tlv_size(EXT_SUBTLV_RMT_ITF_ADDR_SIZE, "Remote Itf. Address");
vty_out(vty,
" Remote Interface Address Sub-TLV: Length %u\n Address: %pI4\n",
@@ -1736,6 +1746,8 @@ static uint16_t show_vty_ext_link_adj_sid(struct vty *vty,
{
struct ext_subtlv_adj_sid *top = (struct ext_subtlv_adj_sid *)tlvh;
+ check_tlv_size(EXT_SUBTLV_ADJ_SID_SIZE, "Adjacency SID");
+
vty_out(vty,
" Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\t%s: %u\n",
ntohs(top->header.length), top->flags, top->mtid, top->weight,
@@ -1755,6 +1767,8 @@ static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty,
struct ext_subtlv_lan_adj_sid *top =
(struct ext_subtlv_lan_adj_sid *)tlvh;
+ check_tlv_size(EXT_SUBTLV_LAN_ADJ_SID_SIZE, "Lan-Adjacency SID");
+
vty_out(vty,
" LAN-Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\tNeighbor ID: %pI4\n\t%s: %u\n",
ntohs(top->header.length), top->flags, top->mtid, top->weight,
@@ -1768,8 +1782,15 @@ static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty,
return TLV_SIZE(tlvh);
}
-static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
+static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
+ size_t buf_size)
{
+ if (TLV_SIZE(tlvh) > buf_size) {
+ vty_out(vty, " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length));
@@ -1777,13 +1798,22 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
}
/* Extended Link Sub TLVs */
-static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext)
+static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext,
+ size_t buf_size)
{
struct ext_tlv_link *top = (struct ext_tlv_link *)ext;
struct tlv_header *tlvh;
- uint16_t length = ntohs(top->header.length) - 3 * sizeof(uint32_t);
+ uint16_t length = ntohs(top->header.length);
uint16_t sum = 0;
+ /* Verify that TLV length is valid against remaining buffer size */
+ if (length > buf_size) {
+ vty_out(vty,
+ " Extended Link TLV size %d exceeds buffer size. Abort!\n",
+ length);
+ return buf_size;
+ }
+
vty_out(vty,
" Extended Link TLV: Length %u\n Link Type: 0x%x\n"
" Link ID: %pI4\n",
@@ -1791,9 +1821,11 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext)
&top->link_id);
vty_out(vty, " Link data: %pI4\n", &top->link_data);
+ /* Skip Extended TLV and parse sub-TLVs */
+ length -= EXT_TLV_LINK_SIZE;
tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
+ EXT_TLV_LINK_SIZE);
- for (; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
+ for (; sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case EXT_SUBTLV_ADJ_SID:
sum += show_vty_ext_link_adj_sid(vty, tlvh);
@@ -1805,7 +1837,7 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext)
sum += show_vty_ext_link_rmt_itf_addr(vty, tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
@@ -1821,16 +1853,16 @@ static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa)
uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case EXT_TLV_LINK:
- sum += show_vty_link_info(vty, tlvh);
+ sum += show_vty_link_info(vty, tlvh, length - sum);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
@@ -1843,6 +1875,8 @@ static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty,
struct ext_subtlv_prefix_sid *top =
(struct ext_subtlv_prefix_sid *)tlvh;
+ check_tlv_size(EXT_SUBTLV_PREFIX_SID_SIZE, "Prefix SID");
+
vty_out(vty,
" Prefix SID Sub-TLV: Length %u\n\tAlgorithm: %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\t%s: %u\n",
ntohs(top->header.length), top->algorithm, top->flags,
@@ -1857,28 +1891,39 @@ static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty,
}
/* Extended Prefix SubTLVs */
-static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext)
+static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext,
+ size_t buf_size)
{
struct ext_tlv_prefix *top = (struct ext_tlv_prefix *)ext;
struct tlv_header *tlvh;
- uint16_t length = ntohs(top->header.length) - 2 * sizeof(uint32_t);
+ uint16_t length = ntohs(top->header.length);
uint16_t sum = 0;
+ /* Verify that TLV length is valid against remaining buffer size */
+ if (length > buf_size) {
+ vty_out(vty,
+ " Extended Link TLV size %d exceeds buffer size. Abort!\n",
+ length);
+ return buf_size;
+ }
+
vty_out(vty,
" Extended Prefix TLV: Length %u\n\tRoute Type: %u\n"
"\tAddress Family: 0x%x\n\tFlags: 0x%x\n\tAddress: %pI4/%u\n",
ntohs(top->header.length), top->route_type, top->af, top->flags,
&top->address, top->pref_length);
+ /* Skip Extended Prefix TLV and parse sub-TLVs */
+ length -= EXT_TLV_PREFIX_SIZE;
tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
+ EXT_TLV_PREFIX_SIZE);
- for (; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
+ for (; sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case EXT_SUBTLV_PREFIX_SID:
sum += show_vty_ext_pref_pref_sid(vty, tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
@@ -1894,16 +1939,16 @@ static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa)
uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case EXT_TLV_PREFIX:
- sum += show_vty_pref_info(vty, tlvh);
+ sum += show_vty_pref_info(vty, tlvh, length - sum);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c
index d818878cf5..a25057a27f 100644
--- a/ospfd/ospf_gr_helper.c
+++ b/ospfd/ospf_gr_helper.c
@@ -233,19 +233,17 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
lsah = (struct lsa_header *)lsa->data;
- length = ntohs(lsah->length);
-
/* Check LSA len */
- if (length <= OSPF_LSA_HEADER_SIZE) {
+ if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
if (IS_DEBUG_OSPF_GR_HELPER)
zlog_debug("%s: Malformed packet: Invalid LSA len:%d",
__func__, length);
return OSPF_GR_FAILURE;
}
- length -= OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
/* Check TLV len against overall LSA */
@@ -996,18 +994,16 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
lsah = (struct lsa_header *)lsa->data;
- length = ntohs(lsah->length);
-
- if (length <= OSPF_LSA_HEADER_SIZE) {
+ if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
vty_out(vty, "%% Invalid LSA length: %d\n", length);
return;
}
- length -= OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
vty_out(vty, " TLV info:\n");
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
/* Check TLV len */
if (sum + TLV_SIZE(tlvh) > length) {
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 6e9df77fb8..72dc699bd9 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -175,6 +175,7 @@ struct ospf_lsa *ospf_lsa_new_and_data(size_t size)
new = ospf_lsa_new();
new->data = ospf_lsa_data_new(size);
+ new->size = size;
return new;
}
@@ -3241,22 +3242,22 @@ int ospf_lsa_different(struct ospf_lsa *l1, struct ospf_lsa *l2)
if (IS_LSA_MAXAGE(l2) && !IS_LSA_MAXAGE(l1))
return 1;
- if (l1->data->length != l2->data->length)
+ if (l1->size != l2->size)
return 1;
- if (l1->data->length == 0)
+ if (l1->size == 0)
return 1;
if (CHECK_FLAG((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED))
return 1; /* May be a stale LSA in the LSBD */
- assert(ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE);
+ assert(l1->size > OSPF_LSA_HEADER_SIZE);
p1 = (char *)l1->data;
p2 = (char *)l2->data;
if (memcmp(p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE,
- ntohs(l1->data->length) - OSPF_LSA_HEADER_SIZE)
+ l1->size - OSPF_LSA_HEADER_SIZE)
!= 0)
return 1;
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 3c1f94e628..3808700ccc 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -84,8 +84,9 @@ struct ospf_lsa {
#define OSPF_LSA_PREMATURE_AGE 0x40
#define OSPF_LSA_IN_MAXAGE 0x80
- /* LSA data. */
+ /* LSA data. and size */
struct lsa_header *data;
+ size_t size;
/* Received time stamp. */
struct timeval tv_recv;
@@ -168,7 +169,7 @@ struct router_lsa {
uint8_t flags;
uint8_t zero;
uint16_t links;
- struct {
+ struct router_link {
struct in_addr link_id;
struct in_addr link_data;
uint8_t type;
@@ -199,7 +200,7 @@ struct summary_lsa {
struct as_external_lsa {
struct lsa_header header;
struct in_addr mask;
- struct {
+ struct as_route {
uint8_t tos;
uint8_t metric[3];
struct in_addr fwd_addr;
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index ae9ab48d4a..42bf914f67 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -1204,9 +1204,10 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa,
void ospf_opaque_lsa_dump(struct stream *s, uint16_t length)
{
- struct ospf_lsa lsa;
+ struct ospf_lsa lsa = {};
lsa.data = (struct lsa_header *)stream_pnt(s);
+ lsa.size = length;
show_opaque_info_detail(NULL, &lsa, NULL);
return;
}
diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h
index c63b8ebdaf..7d401c3dcc 100644
--- a/ospfd/ospf_opaque.h
+++ b/ospfd/ospf_opaque.h
@@ -79,6 +79,7 @@
#define VALID_OPAQUE_INFO_LEN(lsahdr) \
((ntohs((lsahdr)->length) >= sizeof(struct lsa_header)) \
+ && ((ntohs((lsahdr)->length) < OSPF_MAX_LSA_SIZE)) \
&& ((ntohs((lsahdr)->length) % sizeof(uint32_t)) == 0))
/*
diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c
index 988bcd67c6..4b77943108 100644
--- a/ospfd/ospf_ri.c
+++ b/ospfd/ospf_ri.c
@@ -294,8 +294,8 @@ static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce)
pce->pce_header.header.type = htons(RI_TLV_PCE);
/* Set PCE Address */
pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS);
- pce->pce_address.header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
- pce->pce_address.address.type = htons(PCE_ADDRESS_TYPE_IPV4);
+ pce->pce_address.header.length = htons(PCE_ADDRESS_IPV4_SIZE);
+ pce->pce_address.address.type = htons(PCE_ADDRESS_IPV4);
pce->pce_address.address.value = ipv4;
return;
@@ -323,7 +323,7 @@ static void set_pce_domain(uint16_t type, uint32_t domain,
sizeof(struct ri_pce_subtlv_domain));
new->header.type = htons(RI_PCE_SUBTLV_DOMAIN);
- new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
+ new->header.length = htons(PCE_ADDRESS_IPV4_SIZE);
new->type = htons(type);
new->value = htonl(domain);
@@ -369,7 +369,7 @@ static void set_pce_neighbor(uint16_t type, uint32_t domain,
sizeof(struct ri_pce_subtlv_neighbor));
new->header.type = htons(RI_PCE_SUBTLV_NEIGHBOR);
- new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
+ new->header.length = htons(PCE_ADDRESS_IPV4_SIZE);
new->type = htons(type);
new->value = htonl(domain);
@@ -1224,10 +1224,25 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
* Followings are vty session control functions.
*------------------------------------------------------------------------*/
+#define check_tlv_size(size, msg) \
+ do { \
+ if (ntohs(tlvh->length) > size) { \
+ if (vty != NULL) \
+ vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
+ msg, ntohs(tlvh->length), size); \
+ else \
+ zlog_debug(" Wrong %s TLV size: %d(%d)\n", \
+ msg, ntohs(tlvh->length), size); \
+ return size + TLV_HDR_SIZE; \
+ } \
+ } while (0)
+
static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh)
{
struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
+ check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities");
+
if (vty != NULL)
vty_out(vty, " Router Capabilities: 0x%x\n",
ntohl(top->value));
@@ -1243,21 +1258,30 @@ static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
struct ri_pce_subtlv_address *top =
(struct ri_pce_subtlv_address *)tlvh;
- if (ntohs(top->address.type) == PCE_ADDRESS_TYPE_IPV4) {
+ if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) {
+ check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address");
if (vty != NULL)
vty_out(vty, " PCE Address: %pI4\n",
&top->address.value);
else
zlog_debug(" PCE Address: %pI4",
&top->address.value);
- } else {
+ } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) {
/* TODO: Add support to IPv6 with inet_ntop() */
+ check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address");
if (vty != NULL)
vty_out(vty, " PCE Address: 0x%x\n",
ntohl(top->address.value.s_addr));
else
zlog_debug(" PCE Address: 0x%x",
ntohl(top->address.value.s_addr));
+ } else {
+ if (vty != NULL)
+ vty_out(vty, " Wrong PCE Address type: 0x%x\n",
+ ntohl(top->address.type));
+ else
+ zlog_debug(" Wrong PCE Address type: 0x%x",
+ ntohl(top->address.type));
}
return TLV_SIZE(tlvh);
@@ -1269,6 +1293,8 @@ static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
struct ri_pce_subtlv_path_scope *top =
(struct ri_pce_subtlv_path_scope *)tlvh;
+ check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope");
+
if (vty != NULL)
vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value));
else
@@ -1283,19 +1309,29 @@ static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
struct in_addr tmp;
+ check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE, "PCE Domain");
+
if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
tmp.s_addr = top->value;
if (vty != NULL)
- vty_out(vty, " PCE domain Area: %pI4\n", &tmp);
+ vty_out(vty, " PCE Domain Area: %pI4\n", &tmp);
else
- zlog_debug(" PCE domain Area: %pI4", &tmp);
- } else {
+ zlog_debug(" PCE Domain Area: %pI4", &tmp);
+ } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
if (vty != NULL)
- vty_out(vty, " PCE domain AS: %d\n",
+ vty_out(vty, " PCE Domain AS: %d\n",
ntohl(top->value));
else
- zlog_debug(" PCE domain AS: %d", ntohl(top->value));
+ zlog_debug(" PCE Domain AS: %d", ntohl(top->value));
+ } else {
+ if (vty != NULL)
+ vty_out(vty, " Wrong PCE Domain type: %d\n",
+ ntohl(top->type));
+ else
+ zlog_debug(" Wrong PCE Domain type: %d",
+ ntohl(top->type));
}
+
return TLV_SIZE(tlvh);
}
@@ -1307,21 +1343,30 @@ static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
(struct ri_pce_subtlv_neighbor *)tlvh;
struct in_addr tmp;
+ check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE, "PCE Neighbor");
+
if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
tmp.s_addr = top->value;
if (vty != NULL)
- vty_out(vty, " PCE neighbor Area: %pI4\n",
- &tmp);
+ vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp);
else
- zlog_debug(" PCE neighbor Area: %pI4", &tmp);
- } else {
+ zlog_debug(" PCE Neighbor Area: %pI4", &tmp);
+ } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
if (vty != NULL)
- vty_out(vty, " PCE neighbor AS: %d\n",
+ vty_out(vty, " PCE Neighbor AS: %d\n",
ntohl(top->value));
else
- zlog_debug(" PCE neighbor AS: %d",
+ zlog_debug(" PCE Neighbor AS: %d",
ntohl(top->value));
+ } else {
+ if (vty != NULL)
+ vty_out(vty, " Wrong PCE Neighbor type: %d\n",
+ ntohl(top->type));
+ else
+ zlog_debug(" Wrong PCE Neighbor type: %d",
+ ntohl(top->type));
}
+
return TLV_SIZE(tlvh);
}
@@ -1331,6 +1376,8 @@ static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
struct ri_pce_subtlv_cap_flag *top =
(struct ri_pce_subtlv_cap_flag *)tlvh;
+ check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities");
+
if (vty != NULL)
vty_out(vty, " PCE Capabilities Flag: 0x%x\n",
ntohl(top->value));
@@ -1341,8 +1388,21 @@ static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
return TLV_SIZE(tlvh);
}
-static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
+static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
+ size_t buf_size)
{
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length));
@@ -1354,12 +1414,21 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
}
static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
- uint32_t total)
+ size_t buf_size)
{
struct tlv_header *tlvh;
+ uint16_t length = ntohs(ri->length);
uint16_t sum = 0;
- for (tlvh = ri; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
+ /* Verify that TLV length is valid against remaining buffer size */
+ if (length > buf_size) {
+ vty_out(vty,
+ " PCE Info TLV size %d exceeds buffer size. Abort!\n",
+ length);
+ return buf_size;
+ }
+
+ for (tlvh = ri; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case RI_PCE_SUBTLV_ADDRESS:
sum += show_vty_pce_subtlv_address(vty, tlvh);
@@ -1377,7 +1446,7 @@ static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
sum += show_vty_pce_subtlv_cap_flag(vty, tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
@@ -1391,6 +1460,8 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
(struct ri_sr_tlv_sr_algorithm *)tlvh;
int i;
+ check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm");
+
if (vty != NULL) {
vty_out(vty, " Segment Routing Algorithm TLV:\n");
for (i = 0; i < ntohs(algo->header.length); i++) {
@@ -1409,9 +1480,7 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
break;
}
}
- }
-
- else {
+ } else {
zlog_debug(" Segment Routing Algorithm TLV:");
for (i = 0; i < ntohs(algo->header.length); i++)
switch (algo->value[i]) {
@@ -1437,6 +1506,8 @@ static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
struct ri_sr_tlv_sid_label_range *range =
(struct ri_sr_tlv_sid_label_range *)tlvh;
+ check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range");
+
if (vty != NULL) {
vty_out(vty,
" Segment Routing %s Range TLV:\n"
@@ -1465,6 +1536,8 @@ static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
{
struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
+ check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth");
+
if (vty != NULL) {
vty_out(vty,
" Segment Routing MSD TLV:\n"
@@ -1486,9 +1559,9 @@ static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case RI_TLV_CAPABILITIES:
@@ -1511,7 +1584,7 @@ static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length);
break;
}
}
diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h
index 4729677bca..bbad896280 100644
--- a/ospfd/ospf_ri.h
+++ b/ospfd/ospf_ri.h
@@ -75,7 +75,7 @@
/* RFC4970: Router Information Capabilities TLV */ /* Mandatory */
#define RI_TLV_CAPABILITIES 1
-
+#define RI_TLV_CAPABILITIES_SIZE 4
struct ri_tlv_router_cap {
struct tlv_header header; /* Value length is 4 bytes. */
uint32_t value;
@@ -105,12 +105,12 @@ struct ri_tlv_pce {
struct ri_pce_subtlv_address {
/* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */
struct tlv_header header;
-#define PCE_ADDRESS_LENGTH_IPV4 8
-#define PCE_ADDRESS_LENGTH_IPV6 20
+#define PCE_ADDRESS_IPV4_SIZE 8
+#define PCE_ADDRESS_IPV6_SIZE 20
struct {
uint16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */
-#define PCE_ADDRESS_TYPE_IPV4 1
-#define PCE_ADDRESS_TYPE_IPV6 2
+#define PCE_ADDRESS_IPV4 1
+#define PCE_ADDRESS_IPV6 2
uint16_t reserved;
struct in_addr value; /* PCE address */
} address;
@@ -118,6 +118,7 @@ struct ri_pce_subtlv_address {
/* PCE Path-Scope Sub-TLV */ /* Mandatory */
#define RI_PCE_SUBTLV_PATH_SCOPE 2
+#define RI_PCE_SUBTLV_PATH_SCOPE_SIZE 4
struct ri_pce_subtlv_path_scope {
struct tlv_header header; /* Type = 2; Length = 4 bytes. */
/*
@@ -128,11 +129,11 @@ struct ri_pce_subtlv_path_scope {
};
/* PCE Domain Sub-TLV */ /* Optional */
-#define RI_PCE_SUBTLV_DOMAIN 3
-
#define PCE_DOMAIN_TYPE_AREA 1
-#define PCE_DOMAIN_TYPE_AS 2
+#define PCE_DOMAIN_TYPE_AS 2
+#define RI_PCE_SUBTLV_DOMAIN 3
+#define RI_PCE_SUBTLV_DOMAIN_SIZE 8
struct ri_pce_subtlv_domain {
struct tlv_header header; /* Type = 3; Length = 8 bytes. */
uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */
@@ -142,6 +143,7 @@ struct ri_pce_subtlv_domain {
/* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */
#define RI_PCE_SUBTLV_NEIGHBOR 4
+#define RI_PCE_SUBTLV_NEIGHBOR_SIZE 8
struct ri_pce_subtlv_neighbor {
struct tlv_header header; /* Type = 4; Length = 8 bytes. */
uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */
@@ -151,6 +153,7 @@ struct ri_pce_subtlv_neighbor {
/* PCE Capabilities Flags Sub-TLV */ /* Optional */
#define RI_PCE_SUBTLV_CAP_FLAG 5
+#define RI_PCE_SUBTLV_CAP_FLAG_SIZE 4
#define PCE_CAP_GMPLS_LINK 0x0001
#define PCE_CAP_BIDIRECTIONAL 0x0002
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index d003f3bf7c..3ce177618f 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -954,7 +954,7 @@ static inline void update_adj_sid(struct sr_nhlfe n1, struct sr_nhlfe n2)
*/
/* Extended Link SubTLVs Getter */
-static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh)
+static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
{
struct sr_link *srl;
@@ -966,13 +966,20 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh)
struct tlv_header *sub_tlvh;
uint16_t length = 0, sum = 0, i = 0;
+ /* Check TLV size */
+ if ((ntohs(tlvh->length) > size)
+ || ntohs(tlvh->length) < EXT_TLV_LINK_SIZE) {
+ zlog_warn("Wrong Extended Link TLV size. Abort!");
+ return NULL;
+ }
+
srl = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_link));
/* Initialize TLV browsing */
length = ntohs(tlvh->length) - EXT_TLV_LINK_SIZE;
sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
+ EXT_TLV_LINK_SIZE);
- for (; sum < length; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
+ for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
switch (ntohs(sub_tlvh->type)) {
case EXT_SUBTLV_ADJ_SID:
adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh;
@@ -1025,7 +1032,8 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh)
}
/* Extended Prefix SubTLVs Getter */
-static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh)
+static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh,
+ size_t size)
{
struct sr_prefix *srp;
@@ -1035,13 +1043,20 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh)
struct tlv_header *sub_tlvh;
uint16_t length = 0, sum = 0;
+ /* Check TLV size */
+ if ((ntohs(tlvh->length) > size)
+ || ntohs(tlvh->length) < EXT_TLV_PREFIX_SIZE) {
+ zlog_warn("Wrong Extended Link TLV size. Abort!");
+ return NULL;
+ }
+
srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
/* Initialize TLV browsing */
length = ntohs(tlvh->length) - EXT_TLV_PREFIX_SIZE;
sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
+ EXT_TLV_PREFIX_SIZE);
- for (; sum < length; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
+ for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
switch (ntohs(sub_tlvh->type)) {
case EXT_SUBTLV_PREFIX_SID:
psid = (struct ext_subtlv_prefix_sid *)sub_tlvh;
@@ -1353,7 +1368,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
/* Collect Router Information Sub TLVs */
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
srgb.range_size = 0;
srgb.lower_bound = 0;
@@ -1362,24 +1377,20 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
switch (ntohs(tlvh->type)) {
case RI_SR_TLV_SR_ALGORITHM:
algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
- sum += TLV_SIZE(tlvh);
break;
case RI_SR_TLV_SRGB_LABEL_RANGE:
ri_srgb = (struct ri_sr_tlv_sid_label_range *)tlvh;
- sum += TLV_SIZE(tlvh);
break;
case RI_SR_TLV_SRLB_LABEL_RANGE:
ri_srlb = (struct ri_sr_tlv_sid_label_range *)tlvh;
- sum += TLV_SIZE(tlvh);
break;
case RI_SR_TLV_NODE_MSD:
msd = ((struct ri_sr_tlv_node_msd *)(tlvh))->value;
- sum += TLV_SIZE(tlvh);
break;
default:
- sum += TLV_SIZE(tlvh);
break;
}
+ sum += TLV_SIZE(tlvh);
}
/* Check if Segment Routing Capabilities has been found */
@@ -1519,7 +1530,7 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa)
struct lsa_header *lsah = lsa->data;
struct sr_link *srl;
- uint16_t length, sum;
+ int length;
osr_debug("SR (%s): Process Extended Link LSA 8.0.0.%u from %pI4",
__func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
@@ -1546,20 +1557,19 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa)
}
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
- sum = 0;
- for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
+ for (tlvh = TLV_HDR_TOP(lsah); length > 0 && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
if (ntohs(tlvh->type) == EXT_TLV_LINK) {
/* Got Extended Link information */
- srl = get_ext_link_sid(tlvh);
+ srl = get_ext_link_sid(tlvh, length);
/* Update SID if not null */
if (srl != NULL) {
srl->instance = ntohl(lsah->id.s_addr);
update_ext_link_sid(srn, srl, lsa->flags);
}
}
- sum += TLV_SIZE(tlvh);
+ length -= TLV_SIZE(tlvh);
}
}
@@ -1753,7 +1763,7 @@ void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa)
struct lsa_header *lsah = (struct lsa_header *)lsa->data;
struct sr_prefix *srp;
- uint16_t length, sum;
+ int length;
osr_debug("SR (%s): Process Extended Prefix LSA 7.0.0.%u from %pI4",
__func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
@@ -1780,20 +1790,19 @@ void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa)
}
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
- sum = 0;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
+ for (tlvh = TLV_HDR_TOP(lsah); length > 0 && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
if (ntohs(tlvh->type) == EXT_TLV_LINK) {
/* Got Extended Link information */
- srp = get_ext_prefix_sid(tlvh);
+ srp = get_ext_prefix_sid(tlvh, length);
/* Update SID if not null */
if (srp != NULL) {
srp->instance = ntohl(lsah->id.s_addr);
update_ext_prefix_sid(srn, srp);
}
}
- sum += TLV_SIZE(tlvh);
+ length -= TLV_SIZE(tlvh);
}
}
diff --git a/ospfd/ospf_sr.h b/ospfd/ospf_sr.h
index f00d8e1b0b..ea54e3b310 100644
--- a/ospfd/ospf_sr.h
+++ b/ospfd/ospf_sr.h
@@ -100,6 +100,7 @@ struct ri_sr_tlv_sid_label_range {
/* RI Node/MSD TLV as per RFC 8476 */
#define RI_SR_TLV_NODE_MSD 12
+#define RI_SR_TLV_NODE_MSD_SIZE 4
struct ri_sr_tlv_node_msd {
struct tlv_header header;
uint8_t subtype; /* always = 1 */
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index 1929e3dea4..0946e51077 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -1882,7 +1882,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
struct ls_edge *edge;
struct ls_subnet *subnet;
struct listnode *node;
- int len;
+ int len, links;
/* Sanity Check */
if (!ted || !lsa || !lsa->data)
@@ -1932,8 +1932,9 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
subnet->status = ORPHAN;
/* Then, process Link Information */
- len = ntohs(rl->header.length) - 4;
- for (int i = 0; i < ntohs(rl->links) && len > 0; len -= 12, i++) {
+ len = lsa->size - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE;
+ links = ntohs(rl->links);
+ for (int i = 0; i < links && len > 0; len -= 12, i++) {
struct prefix p;
uint32_t metric;
@@ -2152,20 +2153,20 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
/* Initialize TLV browsing */
tlvh = TLV_HDR_TOP(lsa->data);
+ len = lsa->size - OSPF_LSA_HEADER_SIZE;
- uint32_t total_len = TLV_BODY_SIZE(lsa->data) - OSPF_LSA_HEADER_SIZE;
+ /* Check if TE Router-ID TLV is present */
+ if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR) {
+ /* if TE Router-ID is alone, we are done ... */
+ if (len == TE_LINK_SUBTLV_DEF_SIZE)
+ return 0;
- /* If TE Router-ID is only TLV we are done */
- if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR
- && total_len == sizeof(struct te_tlv_router_addr))
- return 0;
-
- /* Skip TE Router-ID if present */
- if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR)
+ /* ... otherwise, skip it */
+ len -= TE_LINK_SUBTLV_DEF_SIZE + TLV_HDR_SIZE;
tlvh = TLV_HDR_NEXT(tlvh);
+ }
- /* Check if we have a TE Link TLV */
- len = TLV_BODY_SIZE(tlvh);
+ /* Check if we have a valid TE Link TLV */
if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK))
return 0;
@@ -2467,8 +2468,9 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
&lsa->data->id, &node->router_id);
/* Initialize TLV browsing */
- len = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
+ len = lsa->size - OSPF_LSA_HEADER_SIZE;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh;
+ tlvh = TLV_HDR_NEXT(tlvh)) {
struct ri_sr_tlv_sr_algorithm *algo;
struct ri_sr_tlv_sid_label_range *range;
struct ri_sr_tlv_node_msd *msd;
@@ -3152,11 +3154,25 @@ static void ospf_te_init_ted(struct ls_ted *ted, struct ospf *ospf)
/*------------------------------------------------------------------------*
* Followings are vty session control functions.
*------------------------------------------------------------------------*/
+#define check_tlv_size(size, msg) \
+ do { \
+ if (ntohs(tlvh->length) > size) { \
+ if (vty != NULL) \
+ vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
+ msg, ntohs(tlvh->length), size); \
+ else \
+ zlog_debug(" Wrong %s TLV size: %d(%d)\n", \
+ msg, ntohs(tlvh->length), size); \
+ return size + TLV_HDR_SIZE; \
+ } \
+ } while(0)
static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
{
struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Router Address");
+
if (vty != NULL)
vty_out(vty, " Router-Address: %pI4\n", &top->value);
else
@@ -3165,10 +3181,23 @@ static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
return TLV_SIZE(tlvh);
}
-static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh)
+static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh,
+ size_t buf_size)
{
struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
if (vty != NULL)
vty_out(vty, " Link: %u octets of data\n",
ntohs(top->header.length));
@@ -3185,6 +3214,8 @@ static uint16_t show_vty_link_subtlv_link_type(struct vty *vty,
struct te_link_subtlv_link_type *top;
const char *cp = "Unknown";
+ check_tlv_size(TE_LINK_SUBTLV_TYPE_SIZE, "Link Type");
+
top = (struct te_link_subtlv_link_type *)tlvh;
switch (top->link_type.value) {
case LINK_TYPE_SUBTLV_VALUE_PTP:
@@ -3211,6 +3242,8 @@ static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
{
struct te_link_subtlv_link_id *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link ID");
+
top = (struct te_link_subtlv_link_id *)tlvh;
if (vty != NULL)
vty_out(vty, " Link-ID: %pI4\n", &top->value);
@@ -3221,11 +3254,24 @@ static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
}
static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
- struct tlv_header *tlvh)
+ struct tlv_header *tlvh,
+ size_t buf_size)
{
struct te_link_subtlv_lclif_ipaddr *top;
int i, n;
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
top = (struct te_link_subtlv_lclif_ipaddr *)tlvh;
n = ntohs(tlvh->length) / sizeof(top->value[0]);
@@ -3244,11 +3290,24 @@ static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
}
static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
- struct tlv_header *tlvh)
+ struct tlv_header *tlvh,
+ size_t buf_size)
{
struct te_link_subtlv_rmtif_ipaddr *top;
int i, n;
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh;
n = ntohs(tlvh->length) / sizeof(top->value[0]);
if (vty != NULL)
@@ -3270,6 +3329,8 @@ static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty,
{
struct te_link_subtlv_te_metric *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "TE Metric");
+
top = (struct te_link_subtlv_te_metric *)tlvh;
if (vty != NULL)
vty_out(vty, " Traffic Engineering Metric: %u\n",
@@ -3287,6 +3348,8 @@ static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty,
struct te_link_subtlv_max_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Bandwidth");
+
top = (struct te_link_subtlv_max_bw *)tlvh;
fval = ntohf(top->value);
@@ -3304,6 +3367,8 @@ static uint16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
struct te_link_subtlv_max_rsv_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Reservable Bandwidth");
+
top = (struct te_link_subtlv_max_rsv_bw *)tlvh;
fval = ntohf(top->value);
@@ -3324,6 +3389,8 @@ static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
float fval1, fval2;
int i;
+ check_tlv_size(TE_LINK_SUBTLV_UNRSV_SIZE, "Unreserved Bandwidth");
+
top = (struct te_link_subtlv_unrsv_bw *)tlvh;
if (vty != NULL)
vty_out(vty,
@@ -3353,6 +3420,8 @@ static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
{
struct te_link_subtlv_rsc_clsclr *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Resource class/color");
+
top = (struct te_link_subtlv_rsc_clsclr *)tlvh;
if (vty != NULL)
vty_out(vty, " Resource class/color: 0x%x\n",
@@ -3369,6 +3438,8 @@ static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty,
{
struct te_link_subtlv_lrrid *top;
+ check_tlv_size(TE_LINK_SUBTLV_LRRID_SIZE, "Local/Remote Router ID");
+
top = (struct te_link_subtlv_lrrid *)tlvh;
if (vty != NULL) {
@@ -3391,6 +3462,8 @@ static uint16_t show_vty_link_subtlv_llri(struct vty *vty,
{
struct te_link_subtlv_llri *top;
+ check_tlv_size(TE_LINK_SUBTLV_LLRI_SIZE, "Link Local/Remote ID");
+
top = (struct te_link_subtlv_llri *)tlvh;
if (vty != NULL) {
@@ -3413,6 +3486,8 @@ static uint16_t show_vty_link_subtlv_rip(struct vty *vty,
{
struct te_link_subtlv_rip *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote ASBR Address");
+
top = (struct te_link_subtlv_rip *)tlvh;
if (vty != NULL)
@@ -3430,6 +3505,8 @@ static uint16_t show_vty_link_subtlv_ras(struct vty *vty,
{
struct te_link_subtlv_ras *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote AS number");
+
top = (struct te_link_subtlv_ras *)tlvh;
if (vty != NULL)
@@ -3449,6 +3526,8 @@ static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty,
uint32_t delay;
uint32_t anomalous;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Average Link Delay");
+
top = (struct te_link_subtlv_av_delay *)tlvh;
delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
@@ -3470,6 +3549,8 @@ static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
uint32_t low, high;
uint32_t anomalous;
+ check_tlv_size(TE_LINK_SUBTLV_MM_DELAY_SIZE, "Min/Max Link Delay");
+
top = (struct te_link_subtlv_mm_delay *)tlvh;
low = (uint32_t)ntohl(top->low) & TE_EXT_MASK;
anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL;
@@ -3491,6 +3572,8 @@ static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty,
struct te_link_subtlv_delay_var *top;
uint32_t jitter;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Delay Variation");
+
top = (struct te_link_subtlv_delay_var *)tlvh;
jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
@@ -3510,6 +3593,8 @@ static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
uint32_t anomalous;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Loss");
+
top = (struct te_link_subtlv_pkt_loss *)tlvh;
loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
fval = (float)(loss * LOSS_PRECISION);
@@ -3531,6 +3616,8 @@ static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty,
struct te_link_subtlv_res_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Residual Bandwidth");
+
top = (struct te_link_subtlv_res_bw *)tlvh;
fval = ntohf(top->value);
@@ -3552,6 +3639,8 @@ static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
struct te_link_subtlv_ava_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Available Bandwidth");
+
top = (struct te_link_subtlv_ava_bw *)tlvh;
fval = ntohf(top->value);
@@ -3573,6 +3662,8 @@ static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
struct te_link_subtlv_use_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Utilized Bandwidth");
+
top = (struct te_link_subtlv_use_bw *)tlvh;
fval = ntohf(top->value);
@@ -3588,8 +3679,21 @@ static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
return TLV_SIZE(tlvh);
}
-static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
+static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
+ size_t buf_size)
{
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length));
@@ -3607,8 +3711,7 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
struct tlv_header *tlvh;
uint16_t sum = subtotal;
- for (tlvh = tlvh0; sum < total;
- tlvh = TLV_HDR_NEXT(tlvh)) {
+ for (tlvh = tlvh0; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case TE_LINK_SUBTLV_LINK_TYPE:
sum += show_vty_link_subtlv_link_type(vty, tlvh);
@@ -3617,10 +3720,12 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
sum += show_vty_link_subtlv_link_id(vty, tlvh);
break;
case TE_LINK_SUBTLV_LCLIF_IPADDR:
- sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh);
+ sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh,
+ total - sum);
break;
case TE_LINK_SUBTLV_RMTIF_IPADDR:
- sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh);
+ sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh,
+ total - sum);
break;
case TE_LINK_SUBTLV_TE_METRIC:
sum += show_vty_link_subtlv_te_metric(vty, tlvh);
@@ -3671,7 +3776,7 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
sum += show_vty_link_subtlv_use_bw(vty, tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
break;
}
}
@@ -3687,9 +3792,9 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
uint16_t subtotal, uint16_t total) = NULL;
sum = 0;
- total = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ total = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < total;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < total && tlvh;
tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
if (subfunc != NULL) {
sum = (*subfunc)(vty, tlvh, sum, total);
@@ -3704,12 +3809,12 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
sum += show_vty_router_addr(vty, tlvh);
break;
case TE_TLV_LINK:
- sum += show_vty_link_header(vty, tlvh);
+ sum += show_vty_link_header(vty, tlvh, total - sum);
subfunc = ospf_mpls_te_show_link_subtlv;
next = TLV_DATA(tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
break;
}
}
@@ -4081,10 +4186,12 @@ static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
show_vty_link_subtlv_link_id(vty, &lp->link_id.header);
if (TLV_TYPE(lp->lclif_ipaddr) != 0)
show_vty_link_subtlv_lclif_ipaddr(
- vty, &lp->lclif_ipaddr.header);
+ vty, &lp->lclif_ipaddr.header,
+ lp->lclif_ipaddr.header.length);
if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
show_vty_link_subtlv_rmtif_ipaddr(
- vty, &lp->rmtif_ipaddr.header);
+ vty, &lp->rmtif_ipaddr.header,
+ lp->rmtif_ipaddr.header.length);
if (TLV_TYPE(lp->rip) != 0)
show_vty_link_subtlv_rip(vty, &lp->rip.header);
if (TLV_TYPE(lp->ras) != 0)
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 50943c4ccf..04b6bdd961 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -6400,6 +6400,7 @@ static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
if (lsa != NULL) {
struct network_lsa *nl = (struct network_lsa *)lsa->data;
+ struct in_addr *addr;
show_ip_ospf_database_header(vty, lsa, json);
@@ -6410,24 +6411,25 @@ static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
json_object_int_add(json, "networkMask",
ip_masklen(nl->mask));
- length = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE - 4;
-
- for (i = 0; length > 0; i++, length -= 4)
+ length = lsa->size - OSPF_LSA_HEADER_SIZE - 4;
+ addr = &nl->routers[0];
+ for (i = 0; length > 0 && addr;
+ length -= 4, addr = &nl->routers[++i])
if (!json) {
vty_out(vty, " Attached Router: %pI4\n",
- &nl->routers[i]);
+ addr);
vty_out(vty, "\n");
} else {
json_router = json_object_new_object();
json_object_string_add(
json_router, "attachedRouterId",
- inet_ntop(AF_INET, &nl->routers[i],
- buf, sizeof(buf)));
- json_object_object_add(
- json_attached_rt,
- inet_ntop(AF_INET, &(nl->routers[i]),
- buf, sizeof(buf)),
- json_router);
+ inet_ntop(AF_INET, addr, buf,
+ sizeof(buf)));
+ json_object_object_add(json_attached_rt,
+ inet_ntop(AF_INET, addr,
+ buf,
+ sizeof(buf)),
+ json_router);
}
}
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index cc1404e5e9..7505f24aef 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -2182,6 +2182,16 @@ static void ospf_set_redist_vrf_bitmaps(struct ospf *ospf, bool set)
vrf_bitmap_unset(zclient->redist[AFI_IP][type],
ospf->vrf_id);
}
+
+ red_list = ospf->redist[DEFAULT_ROUTE];
+ if (red_list) {
+ if (set)
+ vrf_bitmap_set(zclient->default_information[AFI_IP],
+ ospf->vrf_id);
+ else
+ vrf_bitmap_unset(zclient->default_information[AFI_IP],
+ ospf->vrf_id);
+ }
}
/* Enable OSPF VRF instance */
diff --git a/pathd/path_cli.c b/pathd/path_cli.c
index 7a28449e4e..172737c9d4 100644
--- a/pathd/path_cli.c
+++ b/pathd/path_cli.c
@@ -351,8 +351,6 @@ static int segment_list_has_src_dst(
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
"ipv6_adjacency");
node_src_id = adj_src_ipv6_str;
- } else {
- return CMD_ERR_NO_MATCH;
}
/* addresses */
snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
@@ -421,8 +419,6 @@ int segment_list_has_prefix(
sizeof(buf_prefix));
pre_ipaddr.ipa_type = IPADDR_V6;
pre_ipaddr.ip._v6_addr = prefix_cli.u.prefix6;
- } else {
- return CMD_ERR_NO_MATCH;
}
snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
index_str);
@@ -524,7 +520,7 @@ DEFPY(srte_segment_list_segment, srte_segment_list_segment_cmd,
if (status != CMD_SUCCESS)
return status;
} else {
- segment_list_has_prefix(
+ status = segment_list_has_prefix(
vty, xpath, index, index_str, prefix_ipv4,
prefix_ipv4_str, prefix_ipv6, prefix_ipv6_str, has_algo,
algo, algo_str, has_iface_id, iface_id, iface_id_str);
@@ -821,9 +817,8 @@ DEFPY(srte_candidate_no_bandwidth,
return nb_cli_apply_changes(vty, NULL);
}
-DEFPY(srte_candidate_affinity_filter,
- srte_candidate_affinity_filter_cmd,
- "affinity {exclude-any|include-any|include-all}$type BITPATTERN$value",
+DEFPY(srte_candidate_affinity_filter, srte_candidate_affinity_filter_cmd,
+ "affinity <exclude-any|include-any|include-all>$type BITPATTERN$value",
"Affinity constraint\n"
"Exclude any matching link\n"
"Include any matching link\n"
@@ -846,9 +841,8 @@ DEFPY(srte_candidate_affinity_filter,
return nb_cli_apply_changes(vty, NULL);
}
-DEFPY(srte_candidate_no_affinity_filter,
- srte_candidate_no_affinity_filter_cmd,
- "no affinity {exclude-any|include-any|include-all}$type [BITPATTERN$value]",
+DEFPY(srte_candidate_no_affinity_filter, srte_candidate_no_affinity_filter_cmd,
+ "no affinity <exclude-any|include-any|include-all>$type [BITPATTERN$value]",
NO_STR
"Affinity constraint\n"
"Exclude any matching link\n"
diff --git a/pathd/path_pcep_pcc.c b/pathd/path_pcep_pcc.c
index 9af2148819..779c400b86 100644
--- a/pathd/path_pcep_pcc.c
+++ b/pathd/path_pcep_pcc.c
@@ -1273,7 +1273,8 @@ void handle_pcep_comp_reply(struct ctrl_state *ctrl_state,
* pathd API is thread safe, we could get a new path */
if (pcc_state->caps.is_stateful) {
PCEP_DEBUG("%s Delegating undefined dynamic path %s to PCE %s",
- pcc_state->tag, path->name, pcc_state->originator);
+ pcc_state->tag, req->path->name,
+ pcc_state->originator);
path = pcep_copy_path(req->path);
path->is_delegated = true;
send_report(pcc_state, path);
diff --git a/pathd/pathd.c b/pathd/pathd.c
index 2462b08306..9dc3a41638 100644
--- a/pathd/pathd.c
+++ b/pathd/pathd.c
@@ -195,14 +195,16 @@ int srte_segment_entry_set_nai(struct srte_segment_entry *segment,
struct ipaddr *remote_ip, uint32_t remote_iface,
uint8_t algo, uint8_t pref_len)
{
+
int32_t status = 0;
struct prefix pre = {0};
- segment->nai_type = type;
- memcpy(&segment->nai_local_addr, local_ip, sizeof(struct ipaddr));
if (!segment || !local_ip || !remote_ip)
return 1;
+ segment->nai_type = type;
+ memcpy(&segment->nai_local_addr, local_ip, sizeof(struct ipaddr));
+
switch (type) {
case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE:
case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE:
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index ba6004861e..5a904423c2 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -1788,6 +1788,7 @@ def create_interfaces_cfg(tgen, topo, build=False):
"network",
"priority",
"cost",
+ "mtu_ignore"
]
if "ospf" in data:
interface_data += _create_interfaces_ospf_cfg(
diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py
index 04a12d0eec..7ad64de4a1 100644
--- a/tests/topotests/lib/ospf.py
+++ b/tests/topotests/lib/ospf.py
@@ -352,6 +352,7 @@ def config_ospf_interface(tgen, topo, input_dict=None, build=False, load_config=
data_ospf_auth = ospf_data.setdefault("authentication", 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)
try:
intf = topo["routers"][router]["links"][lnk]["interface"]
@@ -400,19 +401,26 @@ def config_ospf_interface(tgen, topo, input_dict=None, build=False, load_config=
config_data.append(cmd)
# interface ospf dr priority
- if data_ospf_dr_priority in ospf_data:
+ if data_ospf_dr_priority:
cmd = "ip ospf priority {}".format(ospf_data["priority"])
if "del_action" in ospf_data:
cmd = "no {}".format(cmd)
config_data.append(cmd)
# interface ospf cost
- if data_ospf_cost in ospf_data:
+ if data_ospf_cost:
cmd = "ip ospf cost {}".format(ospf_data["cost"])
if "del_action" in ospf_data:
cmd = "no {}".format(cmd)
config_data.append(cmd)
+ # interface ospf mtu
+ if data_ospf_mtu:
+ cmd = "ip ospf mtu-ignore"
+ if 'del_action' in ospf_data:
+ cmd = "no {}".format(cmd)
+ config_data.append(cmd)
+
if build:
return config_data
else:
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
index 1432a82b12..9dfde325f6 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
@@ -62,6 +62,8 @@ from lib.ospf import (
verify_ospf_rib,
create_router_ospf,
redistribute_ospf,
+ config_ospf_interface,
+ verify_ospf_interface,
)
# Global variables
@@ -576,6 +578,89 @@ def test_ospf_redistribution_tc8_p1(request):
write_test_footer(tc_name)
+def test_ospf_cost_tc52_p0(request):
+ """OSPF Cost - verifying ospf interface cost functionality"""
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure ospf cost as 20 on interface between R0 and R1. "
+ "Configure ospf cost as 30 between interface between R0 and R2."
+ )
+
+ r0_ospf_cost = {
+ "r0": {"links": {"r1": {"ospf": {"cost": 20}}, "r2": {"ospf": {"cost": 30}}}}
+ }
+ result = config_ospf_interface(tgen, topo, r0_ospf_cost)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that cost is updated in the ospf interface between"
+ " r0 and r1 as 30 and r0 and r2 as 20"
+ )
+ dut = "r0"
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=r0_ospf_cost)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Swap the costs between interfaces on r0, between r0 and r1 to 30"
+ ", r0 and r2 to 20"
+ )
+
+ r0_ospf_cost = {
+ "r0": {"links": {"r1": {"ospf": {"cost": 30}}, "r2": {"ospf": {"cost": 20}}}}
+ }
+ result = config_ospf_interface(tgen, topo, r0_ospf_cost)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that cost is updated in the ospf interface between r0 "
+ "and r1 as 30 and r0 and r2 as 20."
+ )
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=r0_ospf_cost)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(" Un configure cost from the interface r0 - r1.")
+
+ r0_ospf_cost = {"r0": {"links": {"r1": {"ospf": {"cost": 30, "del_action": True}}}}}
+ result = config_ospf_interface(tgen, topo, r0_ospf_cost)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ input_dict = {
+ "r0": {"links": {"r1": {"ospf": {"cost": 10}}, "r2": {"ospf": {"cost": 20}}}}
+ }
+ step(
+ "Verify that cost is updated in the ospf interface between r0"
+ " and r1 as 10 and r0 and r2 as 20."
+ )
+
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(" Un configure cost from the interface r0 - r2.")
+
+ r0_ospf_cost = {"r0": {"links": {"r2": {"ospf": {"cost": 20, "del_action": True}}}}}
+ result = config_ospf_interface(tgen, topo, r0_ospf_cost)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that cost is updated in the ospf interface between r0"
+ "and r1 as 10 and r0 and r2 as 10"
+ )
+
+ input_dict = {
+ "r0": {"links": {"r1": {"ospf": {"cost": 10}}, "r2": {"ospf": {"cost": 10}}}}
+ }
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
index 6f6b119abc..e94680d974 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
@@ -101,6 +101,7 @@ TESTCASES =
2. OSPF Timers - Verify OSPF interface timer hello interval functionality
3. OSPF Timers - Verify OSPF interface timer dead interval functionality
4. Verify ospf show commands with json output.
+5. Verify NFSM events when ospf nbr changes with different MTU values.
"""
@@ -976,6 +977,153 @@ def test_ospf_dead_tc11_p0(request):
write_test_footer(tc_name)
+def test_ospf_tc4_mtu_ignore_p0(request):
+ """
+ OSPF NFSM - MTU change
+
+ Verify NFSM events when ospf nbr changes with different MTU values
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ global topo
+ step(" Bring up the base config as per the topology")
+ step("Configure OSPF on all the routers of the topology.")
+ step("Verify that OSPF neighbors are FULL.")
+ reset_config_on_routers(tgen)
+ result = verify_ospf_neighbor(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Modify the MTU to non default Value on R0 to R1 interface. "
+ "Reset ospf neighbors on R0."
+ )
+
+ rtr0 = tgen.routers()["r0"]
+ rtr1 = tgen.routers()["r1"]
+
+ r0_r1_intf = topo["routers"]["r0"]["links"]["r1"]["interface"]
+ r1_r0_intf = topo["routers"]["r1"]["links"]["r0"]["interface"]
+
+ rtr0.run("ifconfig {} mtu 1200".format(r0_r1_intf))
+
+ clear_ospf(tgen, "r0")
+
+ step(
+ "Verify that OSPF neighborship between R0 and R1 is stuck in Exstart" " State."
+ )
+ result = verify_ospf_neighbor(tgen, topo, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n OSPF nbrs are Full "
+ "instead of Exstart. Error: {}".format(tc_name, result)
+ )
+
+ step(
+ "Verify that configured MTU value is updated in the show ip " "ospf interface."
+ )
+
+ dut = "r0"
+ input_dict = {"r0": {"links": {"r1": {"ospf": {"mtuBytes": 1200}}}}}
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Modify the MTU to non default Value on R0 to R1 interface. "
+ "Reset ospf neighbors on R0."
+ )
+ rtr0.run("ifconfig {} mtu 1500".format(r0_r1_intf))
+
+ clear_ospf(tgen, "r0")
+
+ step("Verify that OSPF neighborship between R0 and R1 becomes full.")
+ result = verify_ospf_neighbor(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Configure mtu ignore and change the value of the mtu to non default"
+ " on R0 to R1 interface. Reset ospf neighbors on R0."
+ )
+ r0_ospf_mtu = {"r0": {"links": {"r1": {"ospf": {"mtu_ignore": True}}}}}
+ result = config_ospf_interface(tgen, topo, r0_ospf_mtu)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ dut = "r0"
+ input_dict = {"r0": {"links": {"r1": {"ospf": {"mtuMismatchDetect": True}}}}}
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ r1_ospf_mtu = {"r1": {"links": {"r0": {"ospf": {"mtu_ignore": True}}}}}
+ result = config_ospf_interface(tgen, topo, r1_ospf_mtu)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ rtr0.run("ifconfig {} mtu 1200".format(r0_r1_intf))
+
+ clear_ospf(tgen, "r0")
+
+ step("Verify that OSPF neighborship between R0 and R1 becomes full.")
+ result = verify_ospf_neighbor(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Unconfigure mtu-ignore command from the interface. "
+ "Reset ospf neighbors on R0."
+ )
+
+ r1_ospf_mtu = {
+ "r1": {"links": {"r0": {"ospf": {"mtu_ignore": True, "delete": True}}}}
+ }
+ result = config_ospf_interface(tgen, topo, r1_ospf_mtu)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ clear_ospf(tgen, "r0")
+
+ step(
+ "Verify that OSPF neighborship between R0 and R1 is stuck in Exstart" " State."
+ )
+ result = verify_ospf_neighbor(tgen, topo, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n OSPF nbrs are Full "
+ "instead of Exstart. Error: {}".format(tc_name, result)
+ )
+
+ step("Modify the MTU to again default valaue on R0 to R1 interface.")
+
+ rtr0.run("ifconfig {} mtu 1500".format(r0_r1_intf))
+
+ clear_ospf(tgen, "r0")
+
+ step("Verify that OSPF neighborship between R0 and R1 becomes full.")
+ result = verify_ospf_neighbor(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Configure ospf interface with jumbo MTU (9216)." "Reset ospf neighbors on R0."
+ )
+
+ rtr0.run("ifconfig {} mtu 9216".format(r0_r1_intf))
+ rtr1.run("ifconfig {} mtu 9216".format(r1_r0_intf))
+
+ clear_ospf(tgen, "r0")
+ clear_ospf(tgen, "r1")
+
+ step("Verify that OSPF neighborship between R0 and R1 becomes full.")
+ result = verify_ospf_neighbor(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that jumbo MTU is updated in the show ip ospf interface.")
+ dut = "r0"
+ input_dict = {"r0": {"links": {"r1": {"ospf": {"mtuBytes": 9216}}}}}
+ result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))