summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_damp.c8
-rw-r--r--bgpd/bgp_damp.h3
-rw-r--r--bgpd/bgp_network.c1
-rw-r--r--bgpd/bgp_route.c7
-rw-r--r--doc/ipv6.texi10
-rw-r--r--lib/sockopt.c15
-rw-r--r--vtysh/vtysh.c4
-rw-r--r--vtysh/vtysh_config.c2
-rw-r--r--zebra/interface.c9
-rw-r--r--zebra/interface.h9
-rw-r--r--zebra/rtadv.c64
-rw-r--r--zebra/rtadv.h2
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 */