diff options
-rw-r--r-- | bgpd/bgp_damp.c | 8 | ||||
-rw-r--r-- | bgpd/bgp_damp.h | 3 | ||||
-rw-r--r-- | bgpd/bgp_network.c | 1 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 7 | ||||
-rw-r--r-- | doc/ipv6.texi | 10 | ||||
-rw-r--r-- | lib/sockopt.c | 15 | ||||
-rw-r--r-- | vtysh/vtysh.c | 4 | ||||
-rw-r--r-- | vtysh/vtysh_config.c | 2 | ||||
-rw-r--r-- | zebra/interface.c | 9 | ||||
-rw-r--r-- | zebra/interface.h | 9 | ||||
-rw-r--r-- | zebra/rtadv.c | 64 | ||||
-rw-r--r-- | zebra/rtadv.h | 2 |
12 files changed, 116 insertions, 18 deletions
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 346ba520..e21131ef 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -541,8 +541,6 @@ bgp_config_write_damp (struct vty *vty) VTY_NEWLINE); } -#define BGP_UPTIME_LEN 25 - static const char * bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len) { @@ -616,11 +614,11 @@ bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo) } const char * -bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo) +bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo, + char *timebuf, size_t len) { struct bgp_damp_info *bdi; time_t t_now, t_diff; - char timebuf[BGP_UPTIME_LEN]; int penalty; if (!binfo->extra) @@ -639,5 +637,5 @@ bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo) t_diff = t_now - bdi->t_updated; penalty = bgp_damp_decay (t_diff, bdi->penalty); - return bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN); + return bgp_get_reuse_time (penalty, timebuf, len); } diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h index e0bef4a8..e1d319b5 100644 --- a/bgpd/bgp_damp.h +++ b/bgpd/bgp_damp.h @@ -141,6 +141,7 @@ extern void bgp_damp_info_clean (void); extern int bgp_damp_decay (time_t, int); extern void bgp_config_write_damp (struct vty *); extern void bgp_damp_info_vty (struct vty *, struct bgp_info *); -extern const char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *); +extern const char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *, + char *, size_t); #endif /* _QUAGGA_BGP_DAMP_H */ diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 6d16c6ec..99f71138 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -517,6 +517,7 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address) return ret; } + listnode_add (bm->listen_sockets, (void *)sock); thread_add_read (bm->master, bgp_accept, bgp, sock); return sock; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index a44d47ab..4f3f85b3 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5810,6 +5810,7 @@ damp_route_vty_out (struct vty *vty, struct prefix *p, { struct attr *attr; int len; + char timebuf[BGP_UPTIME_LEN]; /* short status lead text */ route_vty_short_status_out (vty, binfo); @@ -5827,7 +5828,7 @@ damp_route_vty_out (struct vty *vty, struct prefix *p, else vty_out (vty, "%*s", len, " "); - vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo)); + vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN)); /* Print attribute */ attr = binfo->attr; @@ -5843,8 +5844,6 @@ damp_route_vty_out (struct vty *vty, struct prefix *p, vty_out (vty, "%s", VTY_NEWLINE); } -#define BGP_UPTIME_LEN 25 - /* flap route */ static void flap_route_vty_out (struct vty *vty, struct prefix *p, @@ -5888,7 +5887,7 @@ flap_route_vty_out (struct vty *vty, struct prefix *p, if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED) && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo)); + vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN)); else vty_out (vty, "%*s ", 8, " "); diff --git a/doc/ipv6.texi b/doc/ipv6.texi index 910253c8..a78a92fe 100644 --- a/doc/ipv6.texi +++ b/doc/ipv6.texi @@ -150,6 +150,13 @@ in milliseconds, between successive unsolicited Router Advertisements. Default: not set @end deffn +@deffn {Interface Command} {ipv6 nd router-preference (high|medium|low)} {} +@deffnx {Interface Command} {no ipv6 nd router-preference} {} +Set default router preference in IPv6 router advertisements per RFC4191. + +Default: medium +@end deffn + @example @group interface eth0 @@ -160,4 +167,5 @@ interface eth0 For more information see @cite{RFC2462 (IPv6 Stateless Address Autoconfiguration)} , @cite{RFC2461 (Neighbor Discovery for IP Version 6 (IPv6))} -and @cite{RFC3775 (Mobility Support in IPv6 (Mobile IPv6))}. +, @cite{RFC3775 (Mobility Support in IPv6 (Mobile IPv6))} +and @cite{RFC4191 (Default Router Preferences and More-Specific Routes)}. diff --git a/lib/sockopt.c b/lib/sockopt.c index 96324ffe..55c6226b 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -550,8 +550,8 @@ sockopt_tcp_signature (int sock, union sockunion *su, const char *password) if (su2->sa.sa_family == AF_INET) { sockunion_free (susock); - return -1; - }; + return 0; + } #ifdef HAVE_IPV6 /* If this does not work, then all users of this sockopt will need to @@ -580,7 +580,16 @@ sockopt_tcp_signature (int sock, union sockunion *su, const char *password) memcpy (md5sig.tcpm_key, password, keylen); sockunion_free (susock); #endif /* GNU_LINUX */ - ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig); + if ((ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig)) < 0) + { + /* ENOENT is harmless. It is returned when we clear a password for which + one was not previously set. */ + if (ENOENT == errno) + ret = 0; + else + zlog_err ("sockopt_tcp_signature: setsockopt(%d): %s", + sock, safe_strerror(errno)); + } return ret; #else /* HAVE_TCP_MD5SIG */ return -2; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index bff06323..3f189adb 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1722,8 +1722,6 @@ DEFUN (vtysh_write_terminal, vtysh_config_dump (fp); - vty_out (vty, "end%s", VTY_NEWLINE); - if (vtysh_pager_name && fp) { fflush (fp); @@ -1735,6 +1733,8 @@ DEFUN (vtysh_write_terminal, fp = NULL; } + vty_out (vty, "end%s", VTY_NEWLINE); + return CMD_SUCCESS; } diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index 70c37462..fb8a1269 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -244,6 +244,8 @@ vtysh_config_parse_line (const char *line) || strncmp (line, "enable password", strlen ("enable password")) == 0) config = config_get (AAA_NODE, line); + else if (strncmp (line, "ip protocol", strlen ("ip protocol")) == 0) + config = config_get (PROTOCOL_NODE, line); else { if (strncmp (line, "log", strlen ("log")) == 0 diff --git a/zebra/interface.c b/zebra/interface.c index 3e4867c4..9dfb6d50 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -41,6 +41,11 @@ #include "zebra/debug.h" #include "zebra/irdp.h" +#ifdef RTADV +/* Order is intentional. Matches RFC4191. This array is also used for + command matching, so only modify with care. */ +const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 }; +#endif /* RTADV */ /* Called when new interface is added. */ static int @@ -75,6 +80,7 @@ if_zebra_new_hook (struct interface *ifp) rtadv->HomeAgentPreference = 0; rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME; rtadv->AdvIntervalOption = 0; + rtadv->DefaultPreference = RTADV_PREF_MEDIUM; rtadv->AdvPrefixList = list_new (); } @@ -622,6 +628,9 @@ nd_dump_vty (struct vty *vty, struct interface *ifp) VTY_NEWLINE); vty_out (vty, " ND router advertisements live for %d seconds%s", rtadv->AdvDefaultLifetime, VTY_NEWLINE); + vty_out (vty, " ND router advertisement default router preference is " + "%s%s", rtadv_pref_strs[rtadv->DefaultPreference], + VTY_NEWLINE); if (rtadv->AdvManagedFlag) vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s", VTY_NEWLINE); diff --git a/zebra/interface.h b/zebra/interface.h index 968430ab..0cf66403 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -46,7 +46,7 @@ #endif #ifdef RTADV -/* Router advertisement parameter. From RFC2461 and RFC3775. */ +/* Router advertisement parameter. From RFC2461, RFC3775 and RFC4191. */ struct rtadvconf { /* A flag indicating whether or not the router sends periodic Router @@ -171,6 +171,13 @@ struct rtadvconf Default: FALSE */ int AdvIntervalOption; + + /* The value to be placed in the Default Router Preference field of + a router advertisement. See [RFC 4191 2.1 & 2.2] + + Default: 0 (medium) */ + int DefaultPreference; +#define RTADV_PREF_MEDIUM 0x0 /* Per RFC4191. */ }; #endif /* RTADV */ diff --git a/zebra/rtadv.c b/zebra/rtadv.c index dd2be812..ff96648a 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -206,7 +206,12 @@ rtadv_send_packet (int sock, struct interface *ifp) rtadv->nd_ra_cksum = 0; rtadv->nd_ra_curhoplimit = 64; - rtadv->nd_ra_flags_reserved = 0; + + /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */ + rtadv->nd_ra_flags_reserved = + zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference; + rtadv->nd_ra_flags_reserved <<= 3; + if (zif->rtadv.AdvManagedFlag) rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; if (zif->rtadv.AdvOtherConfigFlag) @@ -1364,6 +1369,56 @@ DEFUN (no_ipv6_nd_prefix, return CMD_SUCCESS; } + +DEFUN (ipv6_nd_router_preference, + ipv6_nd_router_preference_cmd, + "ipv6 nd router-preference (high|medium|low)", + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "Default router preference\n" + "High default router preference\n" + "Low default router preference\n" + "Medium default router preference (default)\n") +{ + struct interface *ifp; + struct zebra_if *zif; + int i = 0; + + ifp = (struct interface *) vty->index; + zif = ifp->info; + + while (0 != rtadv_pref_strs[i]) + { + if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0) + { + zif->rtadv.DefaultPreference = i; + return CMD_SUCCESS; + } + i++; + } + + return CMD_ERR_NO_MATCH; +} + +DEFUN (no_ipv6_nd_router_preference, + no_ipv6_nd_router_preference_cmd, + "no ipv6 nd router-preference", + NO_STR + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "Default router preference\n") +{ + struct interface *ifp; + struct zebra_if *zif; + + ifp = (struct interface *) vty->index; + zif = ifp->info; + + zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */ + + return CMD_SUCCESS; +} + /* Write configuration about router advertisement. */ void rtadv_config_write (struct vty *vty, struct interface *ifp) @@ -1411,6 +1466,11 @@ rtadv_config_write (struct vty *vty, struct interface *ifp) if (zif->rtadv.AdvOtherConfigFlag) vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE); + if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM) + vty_out (vty, " ipv6 nd router-preference %s%s", + rtadv_pref_strs[zif->rtadv.DefaultPreference], + VTY_NEWLINE); + for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix)) { vty_out (vty, " ipv6 nd prefix %s/%d", @@ -1532,6 +1592,8 @@ rtadv_init (void) install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd); install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd); install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd); + install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd); + install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); } static int diff --git a/zebra/rtadv.h b/zebra/rtadv.h index abd1c6fc..d8d263d0 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -94,4 +94,6 @@ struct nd_opt_homeagent_info { /* Home Agent info */ } __attribute__((__packed__)); #endif +extern const char *rtadv_pref_strs[]; + #endif /* _ZEBRA_RTADV_H */ |