mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-09 01:50:21 +01:00
core: Merge branch 'th/ipv6-privacy'
This branch fixes two things: - autoconf addresses were added with a /128 prefix, instead of the announced /64. This was done on purpose, to stop the kernel from adding a prefix route for the whole /64 net (in case, where RA has onlink=0). NM adds these routes himself. - temporary addresses (ipv6-privacy, rfc4941) did not work at all ever since NM is doing router discouvery in user space. Both features need help from kernel and libnl. If those versions do not support the new address flags (IFA_F_MANAGETEMPADDR and IFA_F_NOPREFIXROUTE), NM will log a message behave as before: adding /128 autoconf addresses and not private addresses. autoconf addresses as /64: https://bugzilla.redhat.com/show_bug.cgi?id=1044590 https://bugzilla.redhat.com/show_bug.cgi?id=1045118 ipv6-privacy: https://bugzilla.gnome.org/show_bug.cgi?id=705170 https://bugzilla.redhat.com/show_bug.cgi?id=1003859 https://bugzilla.redhat.com/show_bug.cgi?id=1047139 Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
commit
3bb54e2084
10 changed files with 268 additions and 31 deletions
|
|
@ -36,6 +36,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/if.h>
|
||||
#include <netlink/route/addr.h>
|
||||
|
||||
#include "libgsystem.h"
|
||||
#include "nm-glib-compat.h"
|
||||
|
|
@ -74,6 +75,14 @@
|
|||
#include "nm-device-bond.h"
|
||||
#include "nm-device-team.h"
|
||||
|
||||
/* workaround for older libnl version, that does not define these flags. */
|
||||
#ifndef IFA_F_MANAGETEMPADDR
|
||||
#define IFA_F_MANAGETEMPADDR 0x100
|
||||
#endif
|
||||
#ifndef IFA_F_NOPREFIXROUTE
|
||||
#define IFA_F_NOPREFIXROUTE 0x200
|
||||
#endif
|
||||
|
||||
static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context);
|
||||
|
||||
#include "nm-device-glue.h"
|
||||
|
|
@ -276,6 +285,7 @@ typedef struct {
|
|||
|
||||
NMRDisc * rdisc;
|
||||
gulong rdisc_config_changed_sigid;
|
||||
NMSettingIP6ConfigPrivacy rdisc_use_tempaddr;
|
||||
/* IP6 config from autoconf */
|
||||
NMIP6Config * ac_ip6_config;
|
||||
|
||||
|
|
@ -477,6 +487,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'
|
||||
|
|
@ -3291,6 +3316,53 @@ linklocal6_start (NMDevice *self)
|
|||
|
||||
static void dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release);
|
||||
|
||||
static void
|
||||
print_support_extended_ifa_flags (NMSettingIP6ConfigPrivacy use_tempaddr)
|
||||
{
|
||||
static gint8 warn = 0;
|
||||
static gint8 s_libnl = -1, s_kernel;
|
||||
|
||||
if (warn >= 2)
|
||||
return;
|
||||
|
||||
if (s_libnl == -1) {
|
||||
s_libnl = !!nm_platform_check_support_libnl_extended_ifa_flags ();
|
||||
s_kernel = !!nm_platform_check_support_kernel_extended_ifa_flags ();
|
||||
|
||||
if (s_libnl && s_kernel) {
|
||||
nm_log_dbg (LOGD_IP6, "kernel and libnl support extended IFA_FLAGS (needed by NM for IPv6 private addresses)");
|
||||
warn = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( use_tempaddr != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
|
||||
&& use_tempaddr != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) {
|
||||
if (warn == 0) {
|
||||
nm_log_dbg (LOGD_IP6, "%s%s%s %s not support extended IFA_FLAGS (needed by NM for IPv6 private addresses)",
|
||||
!s_kernel ? "kernel" : "",
|
||||
!s_kernel && !s_libnl ? " and " : "",
|
||||
!s_libnl ? "libnl" : "",
|
||||
!s_kernel && !s_libnl ? "do" : "does");
|
||||
warn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_libnl && !s_kernel) {
|
||||
nm_log_warn (LOGD_IP6, "libnl and the kernel do not support extended IFA_FLAGS needed by NM for "
|
||||
"IPv6 private addresses. This feature is not available");
|
||||
} else if (!s_libnl) {
|
||||
nm_log_warn (LOGD_IP6, "libnl does not support extended IFA_FLAGS needed by NM for "
|
||||
"IPv6 private addresses. This feature is not available");
|
||||
} else if (!s_kernel) {
|
||||
nm_log_warn (LOGD_IP6, "The kernel does not support extended IFA_FLAGS needed by NM for "
|
||||
"IPv6 private addresses. This feature is not available");
|
||||
}
|
||||
|
||||
warn = 2;
|
||||
}
|
||||
|
||||
static void
|
||||
rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device)
|
||||
{
|
||||
|
|
@ -3298,6 +3370,28 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
|
|||
NMConnection *connection;
|
||||
int i;
|
||||
NMDeviceStateReason reason;
|
||||
static int system_support = -1;
|
||||
guint ifa_flags;
|
||||
|
||||
if (system_support == -1) {
|
||||
/*
|
||||
* Check, if both libnl and the kernel are recent enough,
|
||||
* to help user space handling RA. If it's not supported,
|
||||
* we have no ipv6-privacy and must add autoconf addresses
|
||||
* as /128. The reason for the /128 is to prevent the kernel
|
||||
* from adding a prefix route for this address.
|
||||
**/
|
||||
system_support = nm_platform_check_support_libnl_extended_ifa_flags () &&
|
||||
nm_platform_check_support_kernel_extended_ifa_flags ();
|
||||
}
|
||||
|
||||
/* without system_support, these flags will be ignored.
|
||||
* Still, we set them (why not?).
|
||||
**/
|
||||
ifa_flags = IFA_F_NOPREFIXROUTE;
|
||||
if (priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
|
||||
|| priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
|
||||
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
||||
|
||||
g_return_if_fail (priv->act_request);
|
||||
connection = nm_device_get_connection (device);
|
||||
|
|
@ -3320,17 +3414,23 @@ 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;
|
||||
|
||||
memset (&address, 0, sizeof (address));
|
||||
address.address = discovered_address->address;
|
||||
address.plen = 128;
|
||||
address.plen = system_support ? 64 : 128;
|
||||
address.timestamp = discovered_address->timestamp;
|
||||
address.lifetime = discovered_address->lifetime;
|
||||
address.preferred = discovered_address->preferred;
|
||||
address.source = NM_PLATFORM_SOURCE_RDISC;
|
||||
address.flags = ifa_flags;
|
||||
|
||||
nm_ip6_config_add_address (priv->ac_ip6_config, &address);
|
||||
}
|
||||
|
|
@ -3412,7 +3512,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
|
|||
}
|
||||
|
||||
static gboolean
|
||||
addrconf6_start (NMDevice *self)
|
||||
addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMConnection *connection;
|
||||
|
|
@ -3428,12 +3528,16 @@ 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;
|
||||
}
|
||||
|
||||
priv->rdisc_use_tempaddr = use_tempaddr;
|
||||
print_support_extended_ifa_flags (use_tempaddr);
|
||||
|
||||
/* ensure link local is ready... */
|
||||
ret = linklocal6_start (self);
|
||||
if (ret == NM_ACT_STAGE_RETURN_SUCCESS)
|
||||
|
|
@ -3480,10 +3584,23 @@ addrconf6_cleanup (NMDevice *self)
|
|||
|
||||
/******************************************/
|
||||
|
||||
static NMSettingIP6ConfigPrivacy
|
||||
use_tempaddr_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
|
||||
{
|
||||
switch (use_tempaddr) {
|
||||
case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
|
||||
case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
|
||||
case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
|
||||
return use_tempaddr;
|
||||
default:
|
||||
return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or
|
||||
* /lib/sysctl.d/sysctl.conf
|
||||
*/
|
||||
static int
|
||||
static NMSettingIP6ConfigPrivacy
|
||||
ip6_use_tempaddr (void)
|
||||
{
|
||||
char *contents = NULL;
|
||||
|
|
@ -3491,12 +3608,13 @@ ip6_use_tempaddr (void)
|
|||
char *sysctl_data = NULL;
|
||||
GKeyFile *keyfile;
|
||||
GError *error = NULL;
|
||||
int tmp, ret = -1;
|
||||
gint tmp;
|
||||
NMSettingIP6ConfigPrivacy ret = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
||||
|
||||
/* Read file contents to a string. */
|
||||
if (!g_file_get_contents ("/etc/sysctl.conf", &contents, NULL, NULL))
|
||||
if (!g_file_get_contents ("/lib/sysctl.d/sysctl.conf", &contents, NULL, NULL))
|
||||
return -1;
|
||||
return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
||||
|
||||
/* Prepend a group so that we can use GKeyFile parser. */
|
||||
sysctl_data = g_strdup_printf ("%s%s", group_name, contents);
|
||||
|
|
@ -3507,7 +3625,7 @@ ip6_use_tempaddr (void)
|
|||
|
||||
tmp = g_key_file_get_integer (keyfile, "forged_group", "net.ipv6.conf.default.use_tempaddr", &error);
|
||||
if (error == NULL)
|
||||
ret = tmp;
|
||||
ret = use_tempaddr_clamp (tmp);
|
||||
|
||||
done:
|
||||
g_free (contents);
|
||||
|
|
@ -3544,7 +3662,6 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
|
||||
NMConnection *connection;
|
||||
const char *method;
|
||||
int conf_use_tempaddr;
|
||||
NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
||||
const char *ip6_privacy_str = "0\n";
|
||||
GSList *slaves;
|
||||
|
|
@ -3596,8 +3713,21 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
/* Re-enable IPv6 on the interface */
|
||||
nm_platform_sysctl_set (priv->ip6_disable_ipv6_path, "0");
|
||||
|
||||
/* Enable/disable IPv6 Privacy Extensions.
|
||||
* If a global value is configured by sysadmin (e.g. /etc/sysctl.conf),
|
||||
* use that value instead of per-connection value.
|
||||
*/
|
||||
ip6_privacy = ip6_use_tempaddr ();
|
||||
if (ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) {
|
||||
NMSettingIP6Config *s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
|
||||
if (s_ip6)
|
||||
ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (s_ip6);
|
||||
}
|
||||
ip6_privacy = use_tempaddr_clamp (ip6_privacy);
|
||||
|
||||
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
|
||||
if (!addrconf6_start (self)) {
|
||||
if (!addrconf6_start (self, ip6_privacy)) {
|
||||
/* IPv6 might be disabled; allow IPv4 to proceed */
|
||||
ret = NM_ACT_STAGE_RETURN_STOP;
|
||||
} else
|
||||
|
|
@ -3625,21 +3755,6 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
|
||||
/* Other methods (shared) aren't implemented yet */
|
||||
|
||||
/* Enable/disable IPv6 Privacy Extensions.
|
||||
* If a global value is configured by sysadmin (e.g. /etc/sysctl.conf),
|
||||
* use that value instead of per-connection value.
|
||||
*/
|
||||
conf_use_tempaddr = ip6_use_tempaddr ();
|
||||
if (conf_use_tempaddr >= 0)
|
||||
ip6_privacy = conf_use_tempaddr;
|
||||
else {
|
||||
NMSettingIP6Config *s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
|
||||
if (s_ip6)
|
||||
ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (s_ip6);
|
||||
}
|
||||
ip6_privacy = CLAMP (ip6_privacy, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
|
||||
|
||||
switch (ip6_privacy) {
|
||||
case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN:
|
||||
case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ typedef struct {
|
|||
|
||||
GUdevClient *udev_client;
|
||||
GHashTable *udev_devices;
|
||||
|
||||
int support_kernel_extended_ifa_flags;
|
||||
} NMLinuxPlatformPrivate;
|
||||
|
||||
#define NM_LINUX_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformPrivate))
|
||||
|
|
@ -429,6 +431,45 @@ ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *s
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
_check_support_kernel_extended_ifa_flags_init (NMLinuxPlatformPrivate *priv, struct nl_msg *msg)
|
||||
{
|
||||
struct nlmsghdr *msg_hdr = nlmsg_hdr (msg);
|
||||
|
||||
g_return_if_fail (priv->support_kernel_extended_ifa_flags == 0);
|
||||
g_return_if_fail (msg_hdr->nlmsg_type == RTM_NEWADDR);
|
||||
|
||||
/* the extended address flags are only set for AF_INET6 */
|
||||
if (((struct ifaddrmsg *) nlmsg_data (msg_hdr))->ifa_family != AF_INET6)
|
||||
return;
|
||||
|
||||
/* see if the nl_msg contains the IFA_FLAGS attribute. If it does,
|
||||
* we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR
|
||||
* and IFA_F_NOPREFIXROUTE (they were added together).
|
||||
**/
|
||||
priv->support_kernel_extended_ifa_flags =
|
||||
nlmsg_find_attr (msg_hdr, sizeof (struct ifaddrmsg), 8 /* IFA_FLAGS */)
|
||||
? 1 : -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_support_kernel_extended_ifa_flags (NMPlatform *platform)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), FALSE);
|
||||
|
||||
priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
|
||||
if (priv->support_kernel_extended_ifa_flags == 0) {
|
||||
g_warn_if_reached ();
|
||||
priv->support_kernel_extended_ifa_flags = -1;
|
||||
}
|
||||
|
||||
return priv->support_kernel_extended_ifa_flags > 0;
|
||||
}
|
||||
|
||||
|
||||
/* Object type specific utilities */
|
||||
|
||||
static const char *
|
||||
|
|
@ -1224,6 +1265,14 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|||
int nle;
|
||||
|
||||
event = nlmsg_hdr (msg)->nlmsg_type;
|
||||
|
||||
if (priv->support_kernel_extended_ifa_flags == 0 && event == RTM_NEWADDR) {
|
||||
/* if kernel support for extended ifa flags is still undecided, use the opportunity
|
||||
* now and use @msg to decide it. This saves a blocking net link request.
|
||||
**/
|
||||
_check_support_kernel_extended_ifa_flags_init (priv, msg);
|
||||
}
|
||||
|
||||
nl_msg_parse (msg, ref_object, &object);
|
||||
g_return_val_if_fail (object, NL_OK);
|
||||
|
||||
|
|
@ -2806,6 +2855,12 @@ setup (NMPlatform *platform)
|
|||
g_list_free (devices);
|
||||
g_object_unref (enumerator);
|
||||
|
||||
/* request all IPv6 addresses (hopeing that there is at least one), to check for
|
||||
* the IFA_FLAGS attribute. */
|
||||
nle = nl_rtgen_request (priv->nlh_event, RTM_GETADDR, AF_INET6, NLM_F_DUMP);
|
||||
if (nle != 0)
|
||||
nm_log_warn (LOGD_PLATFORM, "Netlink error: requesting RTM_GETADDR failed with %s", nl_geterror (nle));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -2910,4 +2965,6 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
|
|||
platform_class->ip6_route_delete = ip6_route_delete;
|
||||
platform_class->ip4_route_exists = ip4_route_exists;
|
||||
platform_class->ip6_route_exists = ip6_route_exists;
|
||||
|
||||
platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,14 @@
|
|||
#include "nm-logging.h"
|
||||
#include "nm-enum-types.h"
|
||||
|
||||
/* workaround for older libnl version, that does not define these flags. */
|
||||
#ifndef IFA_F_MANAGETEMPADDR
|
||||
#define IFA_F_MANAGETEMPADDR 0x100
|
||||
#endif
|
||||
#ifndef IFA_F_NOPREFIXROUTE
|
||||
#define IFA_F_NOPREFIXROUTE 0x200
|
||||
#endif
|
||||
|
||||
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
|
||||
|
||||
#define NM_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PLATFORM, NMPlatformPrivate))
|
||||
|
|
@ -196,6 +204,33 @@ reset_error (void)
|
|||
platform->error = NM_PLATFORM_ERROR_NONE;
|
||||
}
|
||||
|
||||
#define IFA_F_MANAGETEMPADDR_STR "mngtmpaddr"
|
||||
#define IFA_F_NOPREFIXROUTE_STR "noprefixroute"
|
||||
gboolean
|
||||
nm_platform_check_support_libnl_extended_ifa_flags ()
|
||||
{
|
||||
static int supported = -1;
|
||||
|
||||
/* support for extended ifa-flags was added together
|
||||
* with the IFA_F_MANAGETEMPADDR flag. So, check if libnl
|
||||
* is able to parse this flag. */
|
||||
if (supported == -1)
|
||||
supported = rtnl_addr_str2flags (IFA_F_MANAGETEMPADDR_STR) == IFA_F_MANAGETEMPADDR;
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_check_support_kernel_extended_ifa_flags ()
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE);
|
||||
|
||||
if (!klass->check_support_kernel_extended_ifa_flags)
|
||||
return FALSE;
|
||||
|
||||
return klass->check_support_kernel_extended_ifa_flags (platform);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
/**
|
||||
|
|
@ -1842,7 +1877,22 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
|
|||
s_dev = address->ifindex > 0 ? nm_platform_link_get_name (address->ifindex) : NULL;
|
||||
str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL;
|
||||
|
||||
rtnl_addr_flags2str(address->flags, s_flags, sizeof(s_flags));
|
||||
rtnl_addr_flags2str(address->flags, s_flags, sizeof (s_flags));
|
||||
|
||||
/* There are two recent flags IFA_F_MANAGETEMPADDR and IFA_F_NOPREFIXROUTE.
|
||||
* If libnl does not yet support them, add them by hand.
|
||||
* These two flags were introduced together with the extended ifa_flags,
|
||||
* so, check for that.
|
||||
**/
|
||||
if ((address->flags && IFA_F_MANAGETEMPADDR) & !nm_platform_check_support_libnl_extended_ifa_flags ()) {
|
||||
strncat (s_flags, s_flags[0] ? "," IFA_F_MANAGETEMPADDR_STR : IFA_F_MANAGETEMPADDR_STR,
|
||||
sizeof (s_flags) - strlen (s_flags) - 1);
|
||||
}
|
||||
if ((address->flags && IFA_F_NOPREFIXROUTE) & !nm_platform_check_support_libnl_extended_ifa_flags ()) {
|
||||
strncat (s_flags, s_flags[0] ? "," IFA_F_NOPREFIXROUTE_STR : IFA_F_NOPREFIXROUTE_STR,
|
||||
sizeof (s_flags) - strlen (s_flags) - 1);
|
||||
}
|
||||
|
||||
str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL;
|
||||
|
||||
g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s%s src %s",
|
||||
|
|
|
|||
|
|
@ -323,6 +323,8 @@ typedef struct {
|
|||
gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric);
|
||||
gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric);
|
||||
gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric);
|
||||
|
||||
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
|
||||
} NMPlatformClass;
|
||||
|
||||
/* NMPlatform signals
|
||||
|
|
@ -465,6 +467,9 @@ int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatform
|
|||
int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b);
|
||||
int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b);
|
||||
|
||||
gboolean nm_platform_check_support_libnl_extended_ifa_flags (void);
|
||||
gboolean nm_platform_check_support_kernel_extended_ifa_flags (void);
|
||||
|
||||
#define auto_g_free __attribute__((cleanup(put_g_free)))
|
||||
static void __attribute__((unused))
|
||||
put_g_free (void *ptr)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ typedef struct {
|
|||
int ifindex;
|
||||
char *ifname;
|
||||
GBytes *lladdr;
|
||||
gint32 max_addresses;
|
||||
|
||||
NMRDiscDHCPLevel dhcp_level;
|
||||
GArray *gateways;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue