core/platform: add check_support_kernel_extended_ifa_flags function
The kernel adds a new capability to allow user space to manage temporary IPv6 addresses. We need to detect this capability to act differently, depending on whether NM has an older kernel at hand. This capability got introduced together when extending the ifa_flags to 32 bit. So, we can check the netlink message, whether we have such an nl attribute at hand. Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
@@ -220,6 +220,17 @@ nm_platform_check_support_libnl_extended_ifa_flags ()
|
||||
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);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
@@ -466,6 +468,7 @@ int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4R
|
||||
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))
|
||||
|
Reference in New Issue
Block a user