mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-09 11:10:21 +01:00
rdisc: obey rtr_solicitations and rtr_solicitation_interval
The IPv6 spec say that when performing SLAAC, you should sent at most 3 RSes, at least 4 seconds apart. We were previously continuing to send RSes forever if we didn't get back a response. Fix that. (Since the fix involves making nm-lndp-rdisc use NMPlatform, it was necessary to rewrite the rdisc test program a bit, to not try to include <net/if.h>, which is incompatible with <linux/if.h>.)
This commit is contained in:
parent
a10bd9991f
commit
ba75ad2d95
7 changed files with 85 additions and 37 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 <string.h>
|
||||
#include <syslog.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue