summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-01-06 21:05:00 +0100
committerThomas Haller <thaller@redhat.com>2014-01-30 17:04:36 +0100
commit84dc64c8affd658077fa3967d42374d6c3a2951c (patch)
treee46bdc1197f76e658deaabf0856df9444e1d33b6
parent616fdb35eacafea30948a056c64dee96870d7d5e (diff)
downloadNetworkManager-84dc64c8affd658077fa3967d42374d6c3a2951c.tar.gz
core/rdisc: limit the number of autoconf addresses to 'max_addresses'
NetworkManager uses the sysctl value 'max_addresses' as the kernel does. There is however a difference in what addresses are taken into account. The kernel counts all addresses on the interface (including temporary, private addresses and user configured ones). NM instead only limits the number of public autoconf addresses to 'max_addresses'. This is because it is difficult for NM to count all addresses (which can come from different sources) and it is not necessarily a more logical behavior. Only be aware, that NM uses the same config value as the kernel, but counts differently. Especially, the kernel might reach the limit earlier then NM in the presence of temporary addresses or addresses not from SLAAC. Note, that the kernel uses 'max_addresses' only to limit public, autoconf addresses. So this limit does not affect NM adding as many addresses as it wants. Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--src/devices/nm-device.c23
-rw-r--r--src/rdisc/nm-fake-rdisc.c3
-rw-r--r--src/rdisc/nm-fake-rdisc.h2
-rw-r--r--src/rdisc/nm-lndp-rdisc.c10
-rw-r--r--src/rdisc/nm-lndp-rdisc.h2
-rw-r--r--src/rdisc/nm-rdisc.h1
-rw-r--r--src/rdisc/tests/rdisc.c4
7 files changed, 38 insertions, 7 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 35103e54fa..90ffff4b32 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -477,6 +477,21 @@ restore_ip6_properties (NMDevice *self)
}
}
+static gint32
+sysctl_get_ipv6_max_addresses (const char *dev)
+{
+ gint32 max_addresses = 16;
+ char *path;
+
+ g_return_val_if_fail (dev && *dev, max_addresses);
+
+ path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/max_addresses", dev);
+ max_addresses = nm_platform_sysctl_get_int32 (path, max_addresses);
+ g_free (path);
+
+ return max_addresses;
+}
+
/*
* Get driver info from SIOCETHTOOL ioctl() for 'iface'
* Returns driver and firmware versions to 'driver_version and' 'firmware_version'
@@ -3320,6 +3335,11 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
/* Rebuild address list from router discovery cache. */
nm_ip6_config_reset_addresses (priv->ac_ip6_config);
+ /* rdisc->addresses contains at most max_addresses entries.
+ * This is different from what the kernel does, which
+ * also counts static and temporary addresses when checking
+ * max_addresses.
+ **/
for (i = 0; i < rdisc->addresses->len; i++) {
NMRDiscAddress *discovered_address = &g_array_index (rdisc->addresses, NMRDiscAddress, i);
NMPlatformIP6Address address;
@@ -3428,7 +3448,8 @@ addrconf6_start (NMDevice *self)
priv->ac_ip6_config = NULL;
}
- priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface);
+ priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface,
+ sysctl_get_ipv6_max_addresses (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 f39c5a208c..38faa5078a 100644
--- a/src/rdisc/nm-fake-rdisc.c
+++ b/src/rdisc/nm-fake-rdisc.c
@@ -36,7 +36,7 @@ G_DEFINE_TYPE (NMFakeRDisc, nm_fake_rdisc, NM_TYPE_RDISC)
/******************************************************************/
NMRDisc *
-nm_fake_rdisc_new (int ifindex, const char *ifname)
+nm_fake_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses)
{
NMRDisc *rdisc = g_object_new (NM_TYPE_FAKE_RDISC, NULL);
@@ -44,6 +44,7 @@ nm_fake_rdisc_new (int ifindex, const char *ifname)
rdisc->ifindex = ifindex;
rdisc->ifname = g_strdup (ifname);
+ rdisc->max_addresses = max_addresses;
return rdisc;
}
diff --git a/src/rdisc/nm-fake-rdisc.h b/src/rdisc/nm-fake-rdisc.h
index 248283b22b..cff9ee4494 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);
+NMRDisc *nm_fake_rdisc_new (int ifindex, const char *ifname, gint32 max_addressses);
#endif /* NM_FAKE_RDISC_H */
diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c
index 04b52067fc..e7124f1b7a 100644
--- a/src/rdisc/nm-lndp-rdisc.c
+++ b/src/rdisc/nm-lndp-rdisc.c
@@ -48,7 +48,7 @@ G_DEFINE_TYPE (NMLNDPRDisc, nm_lndp_rdisc, NM_TYPE_RDISC)
/******************************************************************/
NMRDisc *
-nm_lndp_rdisc_new (int ifindex, const char *ifname)
+nm_lndp_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses)
{
NMRDisc *rdisc;
NMLNDPRDiscPrivate *priv;
@@ -59,6 +59,7 @@ nm_lndp_rdisc_new (int ifindex, const char *ifname)
rdisc->ifindex = ifindex;
rdisc->ifname = g_strdup (ifname);
+ rdisc->max_addresses = max_addresses;
priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
error = ndp_open (&priv->ndp);
@@ -113,6 +114,13 @@ add_address (NMRDisc *rdisc, const NMRDiscAddress *new)
}
}
+ /* we create at most max_addresses autoconf addresses. This is different from
+ * what the kernel does, because it considers *all* addresses (including
+ * static and other temporary addresses).
+ **/
+ if (rdisc->max_addresses && rdisc->addresses->len >= rdisc->max_addresses)
+ return FALSE;
+
g_array_insert_val (rdisc->addresses, i, *new);
return TRUE;
}
diff --git a/src/rdisc/nm-lndp-rdisc.h b/src/rdisc/nm-lndp-rdisc.h
index eb6a1df6d9..30d53db409 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);
+NMRDisc *nm_lndp_rdisc_new (int ifindex, const char *ifname, gint32 max_addresses);
#endif /* NM_LNDP_RDISC_H */
diff --git a/src/rdisc/nm-rdisc.h b/src/rdisc/nm-rdisc.h
index 75262d862b..4690a5f5e7 100644
--- a/src/rdisc/nm-rdisc.h
+++ b/src/rdisc/nm-rdisc.h
@@ -106,6 +106,7 @@ typedef struct {
int ifindex;
char *ifname;
GBytes *lladdr;
+ gint32 max_addresses;
NMRDiscDHCPLevel dhcp_level;
GArray *gateways;
diff --git a/src/rdisc/tests/rdisc.c b/src/rdisc/tests/rdisc.c
index fc6e86be08..6a0591af54 100644
--- a/src/rdisc/tests/rdisc.c
+++ b/src/rdisc/tests/rdisc.c
@@ -12,7 +12,7 @@ main (int argc, char **argv)
{
GMainLoop *loop;
NMRDisc *rdisc;
- NMRDisc *(*new) (int ifindex, const char *ifname) = nm_lndp_rdisc_new;
+ NMRDisc *(*new) (int ifindex, const char *ifname, gint32 max_addresses) = nm_lndp_rdisc_new;
int ifindex = 1;
char ifname[IF_NAMESIZE];
char mac[6] = { 0x02, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
@@ -34,7 +34,7 @@ main (int argc, char **argv)
}
}
- rdisc = new (ifindex, ifname);
+ rdisc = new (ifindex, ifname, 0);
if (!rdisc)
return EXIT_FAILURE;