From fae01935bb7b0de6b107981497b479c2c5a75fc2 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Wed, 15 Apr 2020 12:37:17 +0000 Subject: [PATCH 1/2] zebra: add ability to set hoplimit for IPv6 RAs Reported by testing agency that rfc 4861 section 6.2.1 states that all implementations must have a configuration knob to change the setting of the advertised hop limit. This fix adds that capability. Ticket: CM-29200 Signed-off-by: Don Slice --- zebra/interface.c | 2 +- zebra/interface.h | 1 + zebra/rtadv.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++- zebra/subdir.am | 3 +++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index 59cbfc685455..7ab7e11f0ee7 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -153,7 +153,7 @@ static int if_zebra_new_hook(struct interface *ifp) rtadv->AdvLinkMTU = 0; rtadv->AdvReachableTime = 0; rtadv->AdvRetransTimer = 0; - rtadv->AdvCurHopLimit = 0; + rtadv->AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT; rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */ rtadv->HomeAgentPreference = 0; diff --git a/zebra/interface.h b/zebra/interface.h index b7e90a0c31ed..2021e301cd01 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -117,6 +117,7 @@ struct rtadvconf { Default: The value specified in the "Assigned Numbers" RFC [ASSIGNED] that was in effect at the time of implementation. */ int AdvCurHopLimit; +#define RTADV_DEFAULT_HOPLIMIT 64 /* 64 hops */ /* The value to be placed in the Router Lifetime field of Router Advertisements sent from the interface, in seconds. MUST be diff --git a/zebra/rtadv.c b/zebra/rtadv.c index a22e39dc4896..11434edfcf54 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -46,6 +46,10 @@ #include "zebra/zebra_errors.h" #include "zebra/zebra_router.h" +#ifndef VTYSH_EXTRACT_PL +#include "zebra/rtadv_clippy.c" +#endif + extern struct zebra_privs_t zserv_privs; #if defined(HAVE_RTADV) @@ -230,7 +234,7 @@ static void rtadv_send_packet(int sock, struct interface *ifp, rtadv->nd_ra_code = 0; rtadv->nd_ra_cksum = 0; - rtadv->nd_ra_curhoplimit = 64; + rtadv->nd_ra_curhoplimit = zif->rtadv.AdvCurHopLimit; /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */ rtadv->nd_ra_flags_reserved = zif->rtadv.AdvDefaultLifetime == 0 @@ -1231,6 +1235,53 @@ DEFUN (no_ipv6_nd_ra_fast_retrans, return CMD_SUCCESS; } +DEFPY (ipv6_nd_ra_hop_limit, + ipv6_nd_ra_hop_limit_cmd, + "ipv6 nd ra-hop-limit (0-255)$hopcount", + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "Advertisement Hop Limit\n" + "Advertisement Hop Limit in hops (default:64)\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + vty_out(vty, + "Cannot configure IPv6 Router Advertisements on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + zif->rtadv.AdvCurHopLimit = hopcount; + + return CMD_SUCCESS; +} + +DEFPY (no_ipv6_nd_ra_hop_limit, + no_ipv6_nd_ra_hop_limit_cmd, + "no ipv6 nd ra-hop-limit [(0-255)]", + NO_STR + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "Advertisement Hop Limit\n" + "Advertisement Hop Limit in hops\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + vty_out(vty, + "Cannot configure IPv6 Router Advertisements on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + zif->rtadv.AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT; + + return CMD_SUCCESS; +} + DEFUN (ipv6_nd_suppress_ra, ipv6_nd_suppress_ra_cmd, "ipv6 nd suppress-ra", @@ -2178,6 +2229,8 @@ static int nd_dump_vty(struct vty *vty, struct interface *ifp) vty_out(vty, " ND advertised retransmit interval is %d milliseconds\n", rtadv->AdvRetransTimer); + vty_out(vty, " ND advertised hop-count limit is %d hops\n", + rtadv->AdvCurHopLimit); vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n", zif->ra_sent, zif->ra_rcvd); interval = rtadv->MaxRtrAdvInterval; @@ -2269,6 +2322,10 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp) if (!zif->rtadv.UseFastRexmit) vty_out(vty, " no ipv6 nd ra-fast-retrans\n"); + if (zif->rtadv.AdvCurHopLimit != RTADV_DEFAULT_HOPLIMIT) + vty_out(vty, " ipv6 nd ra-hop-limit %d\n", + zif->rtadv.AdvCurHopLimit); + if (zif->rtadv.AdvDefaultLifetime != -1) vty_out(vty, " ipv6 nd ra-lifetime %d\n", zif->rtadv.AdvDefaultLifetime); @@ -2437,6 +2494,8 @@ void rtadv_cmd_init(void) install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd); install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd); install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd); install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd); install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); diff --git a/zebra/subdir.am b/zebra/subdir.am index 71094cb52c95..7a524a1ea97f 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -120,6 +120,9 @@ zebra/zebra_vty.$(OBJEXT): zebra/zebra_vty_clippy.c zebra/zebra_routemap_clippy.c: $(CLIPPY_DEPS) zebra/zebra_routemap.$(OBJEXT): zebra/zebra_routemap_clippy.c +zebra/rtadv_clippy.c: $(CLIPPY_DEPS) +zebra/rtadv.$(OBJEXT): zebra/rtadv_clippy.c + noinst_HEADERS += \ zebra/connected.h \ zebra/debug.h \ From 2a3a98386af7e5a17ace990f959d5b27aa10b103 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Wed, 15 Apr 2020 18:52:33 +0000 Subject: [PATCH 2/2] doc: Documentation for ipv6 nd ra-hop-limit command Signed-off-by: Don Slice --- doc/user/ipv6.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/user/ipv6.rst b/doc/user/ipv6.rst index f3f064b85044..8af54ee23d4f 100644 --- a/doc/user/ipv6.rst +++ b/doc/user/ipv6.rst @@ -90,6 +90,17 @@ Router Advertisement and neighbor establishment. Default: enabled +.. index:: + single: ipv6 nd ra-hop-limit (0-255) + single: no ipv6 nd ra-hop-limit [(0-255)] +.. clicmd:: [no] ipv6 nd ra-hop-limit [(0-255)] + + The value to be placed in the hop count field of router advertisements sent + from the interface, in hops. Indicates the maximum diameter of the network. + Setting the value to zero indicates that the value is unspecified by this + router. Must be between zero or 255 hops. + Default: ``64`` + .. index:: single: ipv6 nd ra-lifetime (0-9000) single: no ipv6 nd ra-lifetime [(0-9000)]