diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 246d805739..51181599c2 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -445,13 +445,6 @@ restore_ip6_properties (NMDevice *self) nm_device_ipv6_sysctl_set (self, key, value); } -static gint32 -sysctl_get_ipv6_max_addresses (NMDevice *self) -{ - return nm_platform_sysctl_get_int32 (ip6_property_path (self, "max_addresses"), 16); -} - - /* * Get driver info from SIOCETHTOOL ioctl() for 'iface' * Returns driver and firmware versions to 'driver_version and' 'firmware_version' @@ -3498,8 +3491,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) priv->ac_ip6_config = NULL; } - priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface, - sysctl_get_ipv6_max_addresses (self)); + priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface); if (!priv->rdisc) { nm_log_err (LOGD_IP6, "(%s): failed to start router discovery.", ip_iface); return FALSE; diff --git a/src/rdisc/nm-fake-rdisc.c b/src/rdisc/nm-fake-rdisc.c index 38faa5078a..bdd207ca46 100644 --- a/src/rdisc/nm-fake-rdisc.c +++ b/src/rdisc/nm-fake-rdisc.c @@ -36,15 +36,15 @@ G_DEFINE_TYPE (NMFakeRDisc, nm_fake_rdisc, NM_TYPE_RDISC) /******************************************************************/ NMRDisc * -nm_fake_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses) +nm_fake_rdisc_new (int ifindex, const char *ifname) { NMRDisc *rdisc = g_object_new (NM_TYPE_FAKE_RDISC, NULL); - g_assert (rdisc); - rdisc->ifindex = ifindex; rdisc->ifname = g_strdup (ifname); - rdisc->max_addresses = max_addresses; + rdisc->max_addresses = NM_RDISC_MAX_ADDRESSES_DEFAULT; + rdisc->rtr_solicitations = NM_RDISC_RTR_SOLICITATIONS_DEFAULT; + rdisc->rtr_solicitation_interval = NM_RDISC_RTR_SOLICITATION_INTERVAL_DEFAULT; return rdisc; } diff --git a/src/rdisc/nm-fake-rdisc.h b/src/rdisc/nm-fake-rdisc.h index cff9ee4494..248283b22b 100644 --- a/src/rdisc/nm-fake-rdisc.h +++ b/src/rdisc/nm-fake-rdisc.h @@ -44,6 +44,6 @@ typedef struct { GType nm_fake_rdisc_get_type (void); -NMRDisc *nm_fake_rdisc_new (int ifindex, const char *ifname, gint32 max_addressses); +NMRDisc *nm_fake_rdisc_new (int ifindex, const char *ifname); #endif /* NM_FAKE_RDISC_H */ diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c index 7235fd0118..6b43ac8bf1 100644 --- a/src/rdisc/nm-lndp-rdisc.c +++ b/src/rdisc/nm-lndp-rdisc.c @@ -40,6 +40,8 @@ typedef struct { GIOChannel *event_channel; guint event_id; guint timeout_id; + + int solicitations_left; } NMLNDPRDiscPrivate; #define NM_LNDP_RDISC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LNDP_RDISC, NMLNDPRDiscPrivate)) @@ -48,19 +50,30 @@ G_DEFINE_TYPE (NMLNDPRDisc, nm_lndp_rdisc, NM_TYPE_RDISC) /******************************************************************/ +static inline gint32 +ipv6_sysctl_get (const char *ifname, const char *property, gint32 defval) +{ + return nm_platform_sysctl_get_int32 (nm_utils_ip6_property_path (ifname, property), defval); +} + NMRDisc * -nm_lndp_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses) +nm_lndp_rdisc_new (int ifindex, const char *ifname) { NMRDisc *rdisc; NMLNDPRDiscPrivate *priv; int error; rdisc = g_object_new (NM_TYPE_LNDP_RDISC, NULL); - g_assert (rdisc); rdisc->ifindex = ifindex; rdisc->ifname = g_strdup (ifname); - rdisc->max_addresses = max_addresses; + + rdisc->max_addresses = ipv6_sysctl_get (ifname, "max_addresses", + NM_RDISC_MAX_ADDRESSES_DEFAULT); + rdisc->rtr_solicitations = ipv6_sysctl_get (ifname, "router_solicitations", + NM_RDISC_RTR_SOLICITATIONS_DEFAULT); + rdisc->rtr_solicitation_interval = ipv6_sysctl_get (ifname, "router_solicitation_interval", + NM_RDISC_RTR_SOLICITATION_INTERVAL_DEFAULT); priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc); error = ndp_open (&priv->ndp); @@ -210,8 +223,6 @@ add_dns_domain (NMRDisc *rdisc, const NMRDiscDNSDomain *new) return TRUE; } -#define RETRY 10 - static gboolean send_rs (NMRDisc *rdisc) { @@ -228,13 +239,23 @@ send_rs (NMRDisc *rdisc) error = ndp_msg_send (priv->ndp, msg); if (error) error ("(%s): cannot send router solicitation: %d.", rdisc->ifname, error); + else + priv->solicitations_left--; ndp_msg_destroy (msg); - debug ("(%s): scheduling router solicitation retry in %d seconds.", rdisc->ifname, RETRY); - priv->send_rs_id = g_timeout_add_seconds (RETRY, (GSourceFunc) send_rs, rdisc); + if (priv->solicitations_left > 0) { + debug ("(%s): scheduling router solicitation retry in %d seconds.", + rdisc->ifname, rdisc->rtr_solicitation_interval); + priv->send_rs_id = g_timeout_add_seconds (rdisc->rtr_solicitation_interval, + (GSourceFunc) send_rs, rdisc); + } else { + debug ("(%s): did not receive a router advertisement after %d solicitations.", + rdisc->ifname, rdisc->rtr_solicitations); + priv->send_rs_id = 0; + } - return FALSE; + return G_SOURCE_REMOVE; } static void @@ -245,6 +266,7 @@ solicit (NMRDisc *rdisc) if (!priv->send_rs_id) { debug ("(%s): scheduling router solicitation.", rdisc->ifname); priv->send_rs_id = g_idle_add ((GSourceFunc) send_rs, rdisc); + priv->solicitations_left = rdisc->rtr_solicitations; } } diff --git a/src/rdisc/nm-lndp-rdisc.h b/src/rdisc/nm-lndp-rdisc.h index 30d53db409..eb6a1df6d9 100644 --- a/src/rdisc/nm-lndp-rdisc.h +++ b/src/rdisc/nm-lndp-rdisc.h @@ -44,6 +44,6 @@ typedef struct { GType nm_lndp_rdisc_get_type (void); -NMRDisc *nm_lndp_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses); +NMRDisc *nm_lndp_rdisc_new (int ifindex, const char *ifname); #endif /* NM_LNDP_RDISC_H */ diff --git a/src/rdisc/nm-rdisc.h b/src/rdisc/nm-rdisc.h index 977c4ef492..fba06bc215 100644 --- a/src/rdisc/nm-rdisc.h +++ b/src/rdisc/nm-rdisc.h @@ -94,6 +94,10 @@ typedef enum { NM_RDISC_CONFIG_HOP_LIMIT = 1 << 6, } NMRDiscConfigMap; +#define NM_RDISC_MAX_ADDRESSES_DEFAULT 16 +#define NM_RDISC_RTR_SOLICITATIONS_DEFAULT 3 +#define NM_RDISC_RTR_SOLICITATION_INTERVAL_DEFAULT 4 + /** * NMRDisc: * @ifindex: Interface index @@ -108,6 +112,8 @@ typedef struct { char *ifname; GBytes *lladdr; gint32 max_addresses; + gint32 rtr_solicitations; + gint32 rtr_solicitation_interval; NMRDiscDHCPLevel dhcp_level; GArray *gateways; diff --git a/src/rdisc/tests/rdisc.c b/src/rdisc/tests/rdisc.c index 6a0591af54..13a5f82eb9 100644 --- a/src/rdisc/tests/rdisc.c +++ b/src/rdisc/tests/rdisc.c @@ -1,40 +1,68 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* rdisc.c - test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2013 Red Hat, Inc. + */ + #include #include -#include #include "nm-rdisc.h" #include "nm-fake-rdisc.h" #include "nm-lndp-rdisc.h" #include "nm-logging.h" +#include "nm-fake-platform.h" +#include "nm-linux-platform.h" + int main (int argc, char **argv) { GMainLoop *loop; NMRDisc *rdisc; - NMRDisc *(*new) (int ifindex, const char *ifname, gint32 max_addresses) = nm_lndp_rdisc_new; + NMRDisc *(*new) (int ifindex, const char *ifname); int ifindex = 1; - char ifname[IF_NAMESIZE]; + const char *ifname; char mac[6] = { 0x02, 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; - if_indextoname (ifindex, ifname); - g_type_init (); loop = g_main_loop_new (NULL, FALSE); - nm_logging_setup ("debug", NULL, NULL, NULL); + nm_logging_setup ("debug", "ip6", NULL, NULL); openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR, LOG_DAEMON); argv++; - for (; *argv; argv++) { - if (!g_strcmp0 (*argv, "--fake")) - new = nm_fake_rdisc_new; - else { - strncpy (ifname, *argv, IF_NAMESIZE); - ifindex = if_nametoindex (ifname); - } + if (!g_strcmp0 (argv[0], "--fake")) { + new = nm_fake_rdisc_new; + nm_fake_platform_setup (); + argv++; + } else { + new = nm_lndp_rdisc_new; + nm_linux_platform_setup (); } - rdisc = new (ifindex, ifname, 0); + if (argv[0]) { + ifname = argv[0]; + ifindex = nm_platform_link_get_ifindex (ifname); + } else { + ifindex = 1; + ifname = nm_platform_link_get_name (ifindex); + } + + rdisc = new (ifindex, ifname); if (!rdisc) return EXIT_FAILURE;