From 3de3f59ffd9fdc02332ab928352a1b8f8ae77982 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 14 Jan 2018 15:17:14 +0100 Subject: [PATCH 1/9] platform: fix wrong cleanup function in ip_route_get() Fixes: 33a2a7c3e3738b184233980a66f0093f073f97b1 --- src/platform/nm-linux-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 3b692aee10..d2fc35e20f 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -6421,7 +6421,7 @@ ip_route_get (NMPlatform *platform, int try_count = 0; WaitForNlResponseResult seq_result; int nle; - nm_auto_nlmsg NMPObject *route = NULL; + nm_auto_nmpobj NMPObject *route = NULL; nm_assert (NM_IS_LINUX_PLATFORM (platform)); nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); From 3cb81ee063bd855e010d0973f46ada08a330a6e6 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sat, 13 Jan 2018 13:26:37 +0100 Subject: [PATCH 2/9] wifi: cleanup includes - always include the corresponding header file first after "nm-default.h". - include all our other headers last. --- src/platform/wifi/wifi-utils-nl80211.c | 3 ++- src/platform/wifi/wifi-utils-wext.c | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c index a5f25b0269..c483394d0b 100644 --- a/src/platform/wifi/wifi-utils-nl80211.c +++ b/src/platform/wifi/wifi-utils-nl80211.c @@ -22,6 +22,8 @@ #include "nm-default.h" +#include "wifi-utils-nl80211.h" + #include #include #include @@ -32,7 +34,6 @@ #include #include "wifi-utils-private.h" -#include "wifi-utils-nl80211.h" #include "platform/nm-platform.h" #include "platform/nm-platform-utils.h" #include "nm-utils.h" diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c index c4d3c99962..c7c07e1426 100644 --- a/src/platform/wifi/wifi-utils-wext.c +++ b/src/platform/wifi/wifi-utils-wext.c @@ -21,17 +21,14 @@ #include "nm-default.h" +#include "wifi-utils-wext.h" + #include #include #include #include #include -#include "wifi-utils-private.h" -#include "wifi-utils-wext.h" -#include "nm-utils.h" -#include "platform/nm-platform-utils.h" - /* Hacks necessary to #include wireless.h; yay for WEXT */ #ifndef __user #define __user @@ -41,6 +38,10 @@ #include #include +#include "wifi-utils-private.h" +#include "nm-utils.h" +#include "platform/nm-platform-utils.h" + typedef struct { WifiData parent; int fd; From feb1fc2e73cab36f2875b8e769890b1f37bbd33e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 14 Jan 2018 13:38:54 +0100 Subject: [PATCH 3/9] wifi: rework WifiData to use a separate struct for function pointers Add a WifiDataClass struct, that is immutable and contains all the function pointers that were previously embedded in WifiData directly. They are not ever modified after creation, hence this allows to have a "static const" allocated instance of the VTable. Also rename wifi_data_deinit() to wifi_data_unref(). It does not only deinitialize the instance, instead it also frees it. Hence, rename it to "unref()". --- src/platform/nm-linux-platform.c | 2 +- src/platform/wifi/wifi-utils-nl80211.c | 44 ++++++++++--------- src/platform/wifi/wifi-utils-private.h | 14 +++--- src/platform/wifi/wifi-utils-wext.c | 31 +++++++------ src/platform/wifi/wifi-utils.c | 61 +++++++++++++------------- src/platform/wifi/wifi-utils.h | 2 +- 6 files changed, 82 insertions(+), 72 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index d2fc35e20f..e90c93a039 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -7053,7 +7053,7 @@ nm_linux_platform_init (NMLinuxPlatform *self) priv->delayed_action.list_master_connected = g_ptr_array_new (); priv->delayed_action.list_refresh_link = g_ptr_array_new (); priv->delayed_action.list_wait_for_nl_response = g_array_new (FALSE, TRUE, sizeof (DelayedActionWaitForNlResponseData)); - priv->wifi_data = g_hash_table_new_full (nm_direct_hash, NULL, NULL, (GDestroyNotify) wifi_utils_deinit); + priv->wifi_data = g_hash_table_new_full (nm_direct_hash, NULL, NULL, (GDestroyNotify) wifi_utils_unref); } static void diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c index c483394d0b..5b84cfa892 100644 --- a/src/platform/wifi/wifi-utils-nl80211.c +++ b/src/platform/wifi/wifi-utils-nl80211.c @@ -259,11 +259,12 @@ out: typedef struct { WifiData parent; struct nl_sock *nl_sock; - int id; struct nl_cb *nl_cb; guint32 *freqs; + int id; int num_freqs; int phy; + bool can_wowlan:1; } WifiDataNl80211; static int @@ -851,9 +852,11 @@ wifi_nl80211_get_wowlan (WifiData *data) struct nl_msg *msg; struct nl80211_wowlan_info info; + if (!nl80211->can_wowlan) + return FALSE; + msg = nl80211_alloc_msg (nl80211, NL80211_CMD_GET_WOWLAN, 0); nl80211_send_and_recv (nl80211, msg, nl80211_wowlan_handler, &info); - return info.enabled; } @@ -1063,6 +1066,22 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg) WifiData * wifi_nl80211_init (int ifindex) { + static const WifiDataClass klass = { + .struct_size = sizeof (WifiDataNl80211), + .get_mode = wifi_nl80211_get_mode, + .set_mode = wifi_nl80211_set_mode, + .set_powersave = wifi_nl80211_set_powersave, + .get_freq = wifi_nl80211_get_freq, + .find_freq = wifi_nl80211_find_freq, + .get_bssid = wifi_nl80211_get_bssid, + .get_rate = wifi_nl80211_get_rate, + .get_qual = wifi_nl80211_get_qual, + .get_wowlan = wifi_nl80211_get_wowlan, +#if HAVE_NL80211_CRITICAL_PROTOCOL_CMDS + .indicate_addressing_running = wifi_nl80211_indicate_addressing_running, +#endif + .deinit = wifi_nl80211_deinit, + }; WifiDataNl80211 *nl80211; struct nl_msg *msg; struct nl80211_device_info device_info = {}; @@ -1074,19 +1093,7 @@ wifi_nl80211_init (int ifindex) nm_sprintf_buf (ifname, "if %d", ifindex); } - nl80211 = wifi_data_new (ifindex, sizeof (*nl80211)); - nl80211->parent.get_mode = wifi_nl80211_get_mode; - nl80211->parent.set_mode = wifi_nl80211_set_mode; - nl80211->parent.set_powersave = wifi_nl80211_set_powersave; - nl80211->parent.get_freq = wifi_nl80211_get_freq; - nl80211->parent.find_freq = wifi_nl80211_find_freq; - nl80211->parent.get_bssid = wifi_nl80211_get_bssid; - nl80211->parent.get_rate = wifi_nl80211_get_rate; - nl80211->parent.get_qual = wifi_nl80211_get_qual; -#if HAVE_NL80211_CRITICAL_PROTOCOL_CMDS - nl80211->parent.indicate_addressing_running = wifi_nl80211_indicate_addressing_running; -#endif - nl80211->parent.deinit = wifi_nl80211_deinit; + nl80211 = wifi_data_new (&klass, ifindex); nl80211->nl_sock = nl_socket_alloc (); if (nl80211->nl_sock == NULL) @@ -1154,18 +1161,15 @@ wifi_nl80211_init (int ifindex) nl80211->freqs = device_info.freqs; nl80211->num_freqs = device_info.num_freqs; nl80211->parent.caps = device_info.caps; - - if (device_info.can_wowlan) - nl80211->parent.get_wowlan = wifi_nl80211_get_wowlan; + nl80211->can_wowlan = device_info.can_wowlan; _LOGI (LOGD_PLATFORM | LOGD_WIFI, "(%s): using nl80211 for WiFi device control", ifname); - return (WifiData *) nl80211; error: - wifi_utils_deinit ((WifiData *) nl80211); + wifi_utils_unref ((WifiData *) nl80211); return NULL; } diff --git a/src/platform/wifi/wifi-utils-private.h b/src/platform/wifi/wifi-utils-private.h index 11a0f060dc..59386514d7 100644 --- a/src/platform/wifi/wifi-utils-private.h +++ b/src/platform/wifi/wifi-utils-private.h @@ -24,9 +24,8 @@ #include "nm-dbus-interface.h" #include "wifi-utils.h" -struct WifiData { - int ifindex; - NMDeviceWifiCapabilities caps; +typedef struct { + gsize struct_size; NM80211Mode (*get_mode) (WifiData *data); @@ -66,9 +65,14 @@ struct WifiData { gboolean (*set_mesh_ssid) (WifiData *data, const guint8 *ssid, gsize len); gboolean (*indicate_addressing_running) (WifiData *data, gboolean running); +} WifiDataClass; + +struct WifiData { + const WifiDataClass *klass; + int ifindex; + NMDeviceWifiCapabilities caps; }; -gpointer wifi_data_new (int ifindex, gsize len); -void wifi_data_free (WifiData *data); +gpointer wifi_data_new (const WifiDataClass *klass, int ifindex); #endif /* __WIFI_UTILS_PRIVATE_H__ */ diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c index c7c07e1426..c8744f79b6 100644 --- a/src/platform/wifi/wifi-utils-wext.c +++ b/src/platform/wifi/wifi-utils-wext.c @@ -629,6 +629,21 @@ wext_get_caps (WifiDataWext *wext, const char *ifname, struct iw_range *range) WifiData * wifi_wext_init (int ifindex, gboolean check_scan) { + static const WifiDataClass klass = { + .struct_size = sizeof (WifiDataWext), + .get_mode = wifi_wext_get_mode, + .set_mode = wifi_wext_set_mode, + .set_powersave = wifi_wext_set_powersave, + .get_freq = wifi_wext_get_freq, + .find_freq = wifi_wext_find_freq, + .get_bssid = wifi_wext_get_bssid, + .get_rate = wifi_wext_get_rate, + .get_qual = wifi_wext_get_qual, + .deinit = wifi_wext_deinit, + .get_mesh_channel = wifi_wext_get_mesh_channel, + .set_mesh_channel = wifi_wext_set_mesh_channel, + .set_mesh_ssid = wifi_wext_set_mesh_ssid, + }; WifiDataWext *wext; struct iw_range range; guint32 response_len = 0; @@ -643,19 +658,7 @@ wifi_wext_init (int ifindex, gboolean check_scan) return NULL; } - wext = wifi_data_new (ifindex, sizeof (*wext)); - wext->parent.get_mode = wifi_wext_get_mode; - wext->parent.set_mode = wifi_wext_set_mode; - wext->parent.set_powersave = wifi_wext_set_powersave; - wext->parent.get_freq = wifi_wext_get_freq; - wext->parent.find_freq = wifi_wext_find_freq; - wext->parent.get_bssid = wifi_wext_get_bssid; - wext->parent.get_rate = wifi_wext_get_rate; - wext->parent.get_qual = wifi_wext_get_qual; - wext->parent.deinit = wifi_wext_deinit; - wext->parent.get_mesh_channel = wifi_wext_get_mesh_channel; - wext->parent.set_mesh_channel = wifi_wext_set_mesh_channel; - wext->parent.set_mesh_ssid = wifi_wext_set_mesh_ssid; + wext = wifi_data_new (&klass, ifindex); wext->fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (wext->fd < 0) @@ -731,7 +734,7 @@ wifi_wext_init (int ifindex, gboolean check_scan) return (WifiData *) wext; error: - wifi_utils_deinit ((WifiData *) wext); + wifi_utils_unref ((WifiData *) wext); return NULL; } diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c index d005212125..8818dc9d94 100644 --- a/src/platform/wifi/wifi-utils.c +++ b/src/platform/wifi/wifi-utils.c @@ -38,22 +38,19 @@ #include "platform/nm-platform-utils.h" gpointer -wifi_data_new (int ifindex, gsize len) +wifi_data_new (const WifiDataClass *klass, int ifindex) { WifiData *data; - data = g_malloc0 (len); + nm_assert (klass); + nm_assert (klass->struct_size > sizeof (WifiData)); + + data = g_malloc0 (klass->struct_size); + data->klass = klass; data->ifindex = ifindex; return data; } -void -wifi_data_free (WifiData *data) -{ - memset (data, 0, sizeof (*data)); - g_free (data); -} - /*****************************************************************************/ WifiData * @@ -85,14 +82,14 @@ wifi_utils_get_caps (WifiData *data) { g_return_val_if_fail (data != NULL, NM_WIFI_DEVICE_CAP_NONE); - return data->caps; + return data->caps; } NM80211Mode wifi_utils_get_mode (WifiData *data) { g_return_val_if_fail (data != NULL, NM_802_11_MODE_UNKNOWN); - return data->get_mode (data); + return data->klass->get_mode (data); } gboolean @@ -104,7 +101,7 @@ wifi_utils_set_mode (WifiData *data, const NM80211Mode mode) || (mode == NM_802_11_MODE_ADHOC), FALSE); /* nl80211 probably doesn't need this */ - return data->set_mode ? data->set_mode (data, mode) : TRUE; + return data->klass->set_mode ? data->klass->set_mode (data, mode) : TRUE; } gboolean @@ -112,14 +109,14 @@ wifi_utils_set_powersave (WifiData *data, guint32 powersave) { g_return_val_if_fail (data != NULL, FALSE); - return data->set_powersave ? data->set_powersave (data, powersave) : TRUE; + return data->klass->set_powersave ? data->klass->set_powersave (data, powersave) : TRUE; } guint32 wifi_utils_get_freq (WifiData *data) { g_return_val_if_fail (data != NULL, 0); - return data->get_freq (data); + return data->klass->get_freq (data); } guint32 @@ -127,7 +124,7 @@ wifi_utils_find_freq (WifiData *data, const guint32 *freqs) { g_return_val_if_fail (data != NULL, 0); g_return_val_if_fail (freqs != NULL, 0); - return data->find_freq (data, freqs); + return data->klass->find_freq (data, freqs); } gboolean @@ -137,38 +134,40 @@ wifi_utils_get_bssid (WifiData *data, guint8 *out_bssid) g_return_val_if_fail (out_bssid != NULL, FALSE); memset (out_bssid, 0, ETH_ALEN); - return data->get_bssid (data, out_bssid); + return data->klass->get_bssid (data, out_bssid); } guint32 wifi_utils_get_rate (WifiData *data) { g_return_val_if_fail (data != NULL, 0); - return data->get_rate (data); + return data->klass->get_rate (data); } int wifi_utils_get_qual (WifiData *data) { g_return_val_if_fail (data != NULL, 0); - return data->get_qual (data); + return data->klass->get_qual (data); } gboolean wifi_utils_get_wowlan (WifiData *data) { g_return_val_if_fail (data != NULL, 0); - if (!data->get_wowlan) + + if (!data->klass->get_wowlan) return FALSE; - return data->get_wowlan (data); + return data->klass->get_wowlan (data); } void -wifi_utils_deinit (WifiData *data) +wifi_utils_unref (WifiData *data) { g_return_if_fail (data != NULL); - data->deinit (data); - wifi_data_free (data); + + data->klass->deinit (data); + g_free (data); } gboolean @@ -191,8 +190,8 @@ guint32 wifi_utils_get_mesh_channel (WifiData *data) { g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (data->get_mesh_channel != NULL, FALSE); - return data->get_mesh_channel (data); + g_return_val_if_fail (data->klass->get_mesh_channel != NULL, FALSE); + return data->klass->get_mesh_channel (data); } gboolean @@ -200,24 +199,24 @@ wifi_utils_set_mesh_channel (WifiData *data, guint32 channel) { g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (channel <= 13, FALSE); - g_return_val_if_fail (data->set_mesh_channel != NULL, FALSE); - return data->set_mesh_channel (data, channel); + g_return_val_if_fail (data->klass->set_mesh_channel != NULL, FALSE); + return data->klass->set_mesh_channel (data, channel); } gboolean wifi_utils_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len) { g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (data->set_mesh_ssid != NULL, FALSE); - return data->set_mesh_ssid (data, ssid, len); + g_return_val_if_fail (data->klass->set_mesh_ssid != NULL, FALSE); + return data->klass->set_mesh_ssid (data, ssid, len); } gboolean wifi_utils_indicate_addressing_running (WifiData *data, gboolean running) { g_return_val_if_fail (data != NULL, FALSE); - if (data->indicate_addressing_running) - return data->indicate_addressing_running (data, running); + if (data->klass->indicate_addressing_running) + return data->klass->indicate_addressing_running (data, running); return FALSE; } diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h index 705717b078..2633e96592 100644 --- a/src/platform/wifi/wifi-utils.h +++ b/src/platform/wifi/wifi-utils.h @@ -34,7 +34,7 @@ WifiData *wifi_utils_init (int ifindex, gboolean check_scan); int wifi_utils_get_ifindex (WifiData *data); -void wifi_utils_deinit (WifiData *data); +void wifi_utils_unref (WifiData *data); NMDeviceWifiCapabilities wifi_utils_get_caps (WifiData *data); From a3f77b259cea16f32d6428cbba03f0409b1dd96e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 14 Jan 2018 14:08:38 +0100 Subject: [PATCH 4/9] wifi: always build nl80211 CRIT_PROTOCOL support netlink's API is stable, and strictly defined by the integer values that make up commands and attributes. There is little reason do disable a netlink feature based on compile time detection of the kernel headers. Either kernel supports it, or it will fail with an appropriate response. Also, support for NL80211_CMD_CRIT_PROTOCOL_START was merge to kernel in 2013. Maybe, we should now just always assume support (in the kernel headers is there). Anyway, don't do that yet, but instead avoid the defines and use the numeric values directly. --- config.h.meson | 3 --- configure.ac | 24 ------------------------ meson.build | 16 ---------------- src/platform/nm-fake-platform.c | 1 - src/platform/wifi/wifi-utils-nl80211.c | 17 +++++++++-------- 5 files changed, 9 insertions(+), 52 deletions(-) diff --git a/config.h.meson b/config.h.meson index 704c0a48d2..e07e128a65 100644 --- a/config.h.meson +++ b/config.h.meson @@ -38,9 +38,6 @@ /* Define to 1 if libsystemd is available */ #mesondefine HAVE_LIBSYSTEMD -/* Define if nl80211 has critical protocol support */ -#mesondefine HAVE_NL80211_CRITICAL_PROTOCOL_CMDS - /* Define to 1 if you have the `secure_getenv' function. */ #mesondefine HAVE_SECURE_GETENV diff --git a/configure.ac b/configure.ac index 8afebe4cc5..92e1588309 100644 --- a/configure.ac +++ b/configure.ac @@ -242,30 +242,6 @@ if test "$ac_have_nl80211" = no; then AC_MSG_ERROR(Linux kernel development header linux/nl80211.h not installed or not functional) fi -if test "$with_wifi" = "yes"; then - AC_MSG_CHECKING([Linux kernel nl80211 Critical Protocol Start/Stop]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#ifndef __user - #define __user - #endif - #include - #include - #include - #include ]], - [[unsigned a = NL80211_CMD_CRIT_PROTOCOL_START; a++;]])], - [ac_have_nl80211_critproto=yes], - [ac_have_nl80211_critproto=no]) - AC_MSG_RESULT($ac_have_nl80211_critproto) -else - ac_have_nl80211_critproto='no' -fi -if test "$ac_have_nl80211_critproto" = yes; then - AC_DEFINE(HAVE_NL80211_CRITICAL_PROTOCOL_CMDS, 1, [Define if nl80211 has critical protocol support]) -else - AC_DEFINE(HAVE_NL80211_CRITICAL_PROTOCOL_CMDS, 0, [Define if nl80211 has critical protocol support]) -fi - dnl dnl Default to using wpa_supplicant but allow IWD as wifi backend dnl diff --git a/meson.build b/meson.build index 8418cb1050..b3bb97189c 100644 --- a/meson.build +++ b/meson.build @@ -285,22 +285,6 @@ if enable_wifi ''' assert(cc.compiles(nl80211_src), 'Linux kernel development header linux/nl80211.h not installed or not functional') - - nl80211_crit_proto_src = ''' - #ifndef __user - #define __user - #endif - #include - #include - #include - #include - int main() { - unsigned a = NL80211_CMD_CRIT_PROTOCOL_START; - a++; - } - ''' - - config_h.set10('HAVE_NL80211_CRITICAL_PROTOCOL_CMDS', cc.compiles(nl80211_crit_proto_src)) endif config_h.set10('WITH_WIFI', enable_wifi) diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index be43015281..06dd7e1398 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -938,7 +938,6 @@ wifi_find_frequency (NMPlatform *platform, int ifindex, const guint32 *freqs) static void wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean running) { - ; } static guint32 diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c index 5b84cfa892..35bd415114 100644 --- a/src/platform/wifi/wifi-utils-nl80211.c +++ b/src/platform/wifi/wifi-utils-nl80211.c @@ -792,7 +792,6 @@ wifi_nl80211_get_qual (WifiData *data) return sta_info.signal; } -#if HAVE_NL80211_CRITICAL_PROTOCOL_CMDS static gboolean wifi_nl80211_indicate_addressing_running (WifiData *data, gboolean running) { @@ -801,16 +800,21 @@ wifi_nl80211_indicate_addressing_running (WifiData *data, gboolean running) int err; msg = nl80211_alloc_msg (nl80211, - running ? NL80211_CMD_CRIT_PROTOCOL_START : - NL80211_CMD_CRIT_PROTOCOL_STOP, + running + ? 98 /* NL80211_CMD_CRIT_PROTOCOL_START */ + : 99 /* NL80211_CMD_CRIT_PROTOCOL_STOP */, 0); /* Despite the DHCP name, we're using this for any type of IP addressing, * DHCPv4, DHCPv6, and IPv6 SLAAC. */ - NLA_PUT_U16 (msg, NL80211_ATTR_CRIT_PROT_ID, NL80211_CRIT_PROTO_DHCP); + NLA_PUT_U16 (msg, + 179 /* NL80211_ATTR_CRIT_PROT_ID */, + 1 /* NL80211_CRIT_PROTO_DHCP */); if (running) { /* Give DHCP 5 seconds to complete */ - NLA_PUT_U16 (msg, NL80211_ATTR_MAX_CRIT_PROT_DURATION, 5000); + NLA_PUT_U16 (msg, + 180 /* NL80211_ATTR_MAX_CRIT_PROT_DURATION */, + 5000); } err = nl80211_send_and_recv (nl80211, msg, NULL, NULL); @@ -820,7 +824,6 @@ nla_put_failure: nlmsg_free (msg); return FALSE; } -#endif struct nl80211_wowlan_info { gboolean enabled; @@ -1077,9 +1080,7 @@ wifi_nl80211_init (int ifindex) .get_rate = wifi_nl80211_get_rate, .get_qual = wifi_nl80211_get_qual, .get_wowlan = wifi_nl80211_get_wowlan, -#if HAVE_NL80211_CRITICAL_PROTOCOL_CMDS .indicate_addressing_running = wifi_nl80211_indicate_addressing_running, -#endif .deinit = wifi_nl80211_deinit, }; WifiDataNl80211 *nl80211; From cd6116e58f863202a9072b97fc32b1b50f9e1ba3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 14 Jan 2018 14:19:20 +0100 Subject: [PATCH 5/9] wifi: remove configure checks for suitable linux/nl80211.h header The check doesn't seem useful, because it does not result in a fallback or a different build. Just assume is valid. In case it is not, we will get a build failure later. That is just as good. --- configure.ac | 18 ------------------ meson.build | 17 ----------------- 2 files changed, 35 deletions(-) diff --git a/configure.ac b/configure.ac index 92e1588309..9008ef88a2 100644 --- a/configure.ac +++ b/configure.ac @@ -224,24 +224,6 @@ else fi AM_CONDITIONAL(WITH_WEXT, test x"${ac_with_wext}" = x"yes") -AC_MSG_CHECKING([Linux kernel nl80211 headers]) -AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#ifndef __user - #define __user - #endif - #include - #include - #include - #include ]], - [[int a = NL80211_RATE_INFO_BITRATE; a++;]])], - [ac_have_nl80211=yes], - [ac_have_nl80211=no]) -AC_MSG_RESULT($ac_have_nl80211) -if test "$ac_have_nl80211" = no; then - AC_MSG_ERROR(Linux kernel development header linux/nl80211.h not installed or not functional) -fi - dnl dnl Default to using wpa_supplicant but allow IWD as wifi backend dnl diff --git a/meson.build b/meson.build index b3bb97189c..6942103f27 100644 --- a/meson.build +++ b/meson.build @@ -269,23 +269,6 @@ if dist_version != '' endif enable_wifi = get_option('wifi') -if enable_wifi - nl80211_src = ''' - #ifndef __user - #define __user - #endif - #include - #include - #include - #include - int main() { - int a = NL80211_RATE_INFO_BITRATE; - a++; - } - ''' - - assert(cc.compiles(nl80211_src), 'Linux kernel development header linux/nl80211.h not installed or not functional') -endif config_h.set10('WITH_WIFI', enable_wifi) enable_iwd = get_option('iwd') From d2292cc649ac81a88e0b324d36c47caab30d9ba9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 14 Jan 2018 14:26:10 +0100 Subject: [PATCH 6/9] wifi: remove configure checks for suitable WEXT header The check doesn't seem useful, because it does not result in a fallback or a different build. Just assume is valid. In case it is not, we will get a build failure later. That is just as good. --- configure.ac | 19 ------------------- meson.build | 18 ------------------ 2 files changed, 37 deletions(-) diff --git a/configure.ac b/configure.ac index 9008ef88a2..5c694ef84c 100644 --- a/configure.ac +++ b/configure.ac @@ -199,25 +199,6 @@ if test x"$ac_with_wext" = x"yes"; then if test "$enable_wifi" != "yes"; then AC_MSG_ERROR(Enabling WEXT support and disabling Wi-Fi makes no sense) fi - AC_MSG_CHECKING([Linux kernel WEXT headers]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#ifndef __user - #define __user - #endif - #include - #include - #include - #include ]], - [[#ifndef IWEVGENIE - #error "not found" - #endif]])], - [ac_have_iwevgenie=yes], - [ac_have_iwevgenie=no]) - AC_MSG_RESULT($ac_have_iwevgenie) - if test "$ac_have_iwevgenie" = no; then - AC_MSG_ERROR(Linux kernel development header linux/wireless.h not installed or not functional) - fi AC_DEFINE(HAVE_WEXT, 1, [Define if you have Linux Wireless Extensions support]) else AC_DEFINE(HAVE_WEXT, 0, [Define if you have Linux Wireless Extensions support]) diff --git a/meson.build b/meson.build index 6942103f27..e59be17f96 100644 --- a/meson.build +++ b/meson.build @@ -277,25 +277,7 @@ if enable_iwd endif config_h.set10('WITH_IWD', enable_iwd) -# Default to using WEXT but allow it to be disabled enable_wext = get_option('wext') -if enable_wext - assert(enable_wifi, 'Enabling WEXT support and disabling Wi-Fi makes no sense') - iwevgenie_src = ''' - #ifndef __user - #define __user - #endif - #include - #include - #include - #include - #ifndef IWEVGENIE - #error "not found" - #endif - ''' - - assert(cc.compiles(iwevgenie_src), 'Linux kernel development header linux/wireless.h not installed or not functional') -endif config_h.set10('HAVE_WEXT', enable_wext) # Checks for libdl - on certain platforms its part of libc From 9562d886336ff07f07ce4a9445da08e677d18b5c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 14 Jan 2018 14:43:34 +0100 Subject: [PATCH 7/9] platform: add nm-netlink.h for netlink related helper functions Especially useful, because we don't link against libnl-genl-3.so but re-implement generic netlink support. Such code should go there so it can be used by various components. --- Makefile.am | 3 +++ src/meson.build | 1 + src/platform/nm-netlink.c | 25 +++++++++++++++++++++++++ src/platform/nm-netlink.h | 24 ++++++++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 src/platform/nm-netlink.c create mode 100644 src/platform/nm-netlink.h diff --git a/Makefile.am b/Makefile.am index 6b3bc3ad9e..5fd761f8e6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1374,6 +1374,9 @@ src_libNetworkManagerBase_la_SOURCES = \ src/NetworkManagerUtils.c \ src/NetworkManagerUtils.h \ \ + src/platform/nm-netlink.c \ + src/platform/nm-netlink.h \ + \ src/platform/nmp-netns.c \ src/platform/nmp-netns.h \ src/platform/nmp-object.c \ diff --git a/src/meson.build b/src/meson.build index db17bf1555..981a4794e4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -54,6 +54,7 @@ sources = files( 'dhcp/nm-dhcp-utils.c', 'ndisc/nm-lndp-ndisc.c', 'ndisc/nm-ndisc.c', + 'platform/nm-netlink.c', 'platform/wifi/wifi-utils-nl80211.c', 'platform/wifi/wifi-utils.c', 'platform/nm-linux-platform.c', diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c new file mode 100644 index 0000000000..34128e54c7 --- /dev/null +++ b/src/platform/nm-netlink.c @@ -0,0 +1,25 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * 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) 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-netlink.h" + +/*****************************************************************************/ diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h new file mode 100644 index 0000000000..e001c5fdaa --- /dev/null +++ b/src/platform/nm-netlink.h @@ -0,0 +1,24 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * 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) 2018 Red Hat, Inc. + */ + +#ifndef __NM_NETLINK_H__ +#define __NM_NETLINK_H__ + +#endif /* __NM_NETLINK_H__ */ From d7025818123631e893948f389ab2ec428359b238 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 14 Jan 2018 15:07:46 +0100 Subject: [PATCH 8/9] platform: move netlink functions to nm-netlink.h --- src/platform/nm-linux-platform.c | 34 +------------------- src/platform/nm-netlink.h | 44 ++++++++++++++++++++++++++ src/platform/wifi/wifi-utils-nl80211.c | 21 +----------- 3 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index e90c93a039..0128362864 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -37,14 +37,13 @@ #include #include #include -#include -#include #include #include "nm-utils.h" #include "nm-core-internal.h" #include "nm-setting-vlan.h" +#include "nm-netlink.h" #include "nm-core-utils.h" #include "nmp-object.h" #include "nmp-netns.h" @@ -952,13 +951,6 @@ _nl_addattr_l (struct nlmsghdr *n, return TRUE; } -static void -_nm_auto_nl_msg_cleanup (void *ptr) -{ - nlmsg_free (*((struct nl_msg **) ptr)); -} -#define nm_auto_nlmsg nm_auto(_nm_auto_nl_msg_cleanup) - static const char * _nl_nlmsghdr_to_str (const struct nlmsghdr *hdr, char *buf, gsize len) { @@ -1059,30 +1051,6 @@ flags_done: return b; } -static int -_nl_nla_parse (struct nlattr *tb[], int maxtype, struct nlattr *head, int len, - const struct nla_policy *policy) -{ - return nla_parse (tb, maxtype, head, len, (struct nla_policy *) policy); -} -#define nla_parse(...) _nl_nla_parse(__VA_ARGS__) - -static int -_nl_nlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], - int maxtype, const struct nla_policy *policy) -{ - return nlmsg_parse (nlh, hdrlen, tb, maxtype, (struct nla_policy *) policy); -} -#define nlmsg_parse(...) _nl_nlmsg_parse(__VA_ARGS__) - -static int -_nl_nla_parse_nested (struct nlattr *tb[], int maxtype, struct nlattr *nla, - const struct nla_policy *policy) -{ - return nla_parse_nested (tb, maxtype, nla, (struct nla_policy *) policy); -} -#define nla_parse_nested(...) _nl_nla_parse_nested(__VA_ARGS__) - /****************************************************************** * NMPObject/netlink functions ******************************************************************/ diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h index e001c5fdaa..f94e6de7ea 100644 --- a/src/platform/nm-netlink.h +++ b/src/platform/nm-netlink.h @@ -21,4 +21,48 @@ #ifndef __NM_NETLINK_H__ #define __NM_NETLINK_H__ +#include +#include + +/***************************************************************************** + * libnl3 compat code + *****************************************************************************/ + +static inline int +_nl_nla_parse (struct nlattr *tb[], int maxtype, struct nlattr *head, int len, + const struct nla_policy *policy) +{ + return nla_parse (tb, maxtype, head, len, (struct nla_policy *) policy); +} +#define nla_parse(...) _nl_nla_parse(__VA_ARGS__) + +static inline int +_nl_nlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], + int maxtype, const struct nla_policy *policy) +{ + return nlmsg_parse (nlh, hdrlen, tb, maxtype, (struct nla_policy *) policy); +} +#define nlmsg_parse(...) _nl_nlmsg_parse(__VA_ARGS__) + +static inline int +_nl_nla_parse_nested (struct nlattr *tb[], int maxtype, struct nlattr *nla, + const struct nla_policy *policy) +{ + return nla_parse_nested (tb, maxtype, nla, (struct nla_policy *) policy); +} +#define nla_parse_nested(...) _nl_nla_parse_nested(__VA_ARGS__) + +/***************************************************************************** + * helpers + *****************************************************************************/ + +static inline void +_nm_auto_nl_msg_cleanup (struct nl_msg **ptr) +{ + nlmsg_free (*ptr); +} +#define nm_auto_nlmsg nm_auto(_nm_auto_nl_msg_cleanup) + +/*****************************************************************************/ + #endif /* __NM_NETLINK_H__ */ diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c index 35bd415114..6125461175 100644 --- a/src/platform/wifi/wifi-utils-nl80211.c +++ b/src/platform/wifi/wifi-utils-nl80211.c @@ -29,10 +29,9 @@ #include #include #include -#include -#include #include +#include "platform/nm-netlink.h" #include "wifi-utils-private.h" #include "platform/nm-platform.h" #include "platform/nm-platform-utils.h" @@ -47,24 +46,6 @@ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } G_STMT_END -/*****************************************************************************/ - -static int -_nl_nla_parse (struct nlattr *tb[], int maxtype, struct nlattr *head, int len, - const struct nla_policy *policy) -{ - return nla_parse (tb, maxtype, head, len, (struct nla_policy *) policy); -} -#define nla_parse(...) _nl_nla_parse(__VA_ARGS__) - -static int -_nl_nla_parse_nested (struct nlattr *tb[], int maxtype, struct nlattr *nla, - const struct nla_policy *policy) -{ - return nla_parse_nested (tb, maxtype, nla, (struct nla_policy *) policy); -} -#define nla_parse_nested(...) _nl_nla_parse_nested(__VA_ARGS__) - /***************************************************************************** * Copied from libnl3/genl: *****************************************************************************/ From a21a5558b1e50c05e0094dda2b76c8e128873366 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 15 Jan 2018 09:27:22 +0100 Subject: [PATCH 9/9] platform: move genl functions to nm-netlink.c So they can be reused outside of wifi, like for implementing wireguard support. --- src/platform/nm-netlink.c | 97 ++++++++++++++++++++++++++ src/platform/nm-netlink.h | 17 +++++ src/platform/wifi/wifi-utils-nl80211.c | 97 -------------------------- 3 files changed, 114 insertions(+), 97 deletions(-) diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c index 34128e54c7..45bc1cf75b 100644 --- a/src/platform/nm-netlink.c +++ b/src/platform/nm-netlink.c @@ -22,4 +22,101 @@ #include "nm-netlink.h" +/***************************************************************************** + * Reimplementations/copied from libnl3/genl + *****************************************************************************/ + +void * +genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family, + int hdrlen, int flags, uint8_t cmd, uint8_t version) +{ + struct nlmsghdr *nlh; + struct genlmsghdr hdr = { + .cmd = cmd, + .version = version, + }; + + nlh = nlmsg_put (msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); + if (nlh == NULL) + return NULL; + + memcpy (nlmsg_data (nlh), &hdr, sizeof (hdr)); + + return (char *) nlmsg_data (nlh) + GENL_HDRLEN; +} + +void * +genlmsg_data (const struct genlmsghdr *gnlh) +{ + return ((unsigned char *) gnlh + GENL_HDRLEN); +} + +void * +genlmsg_user_hdr (const struct genlmsghdr *gnlh) +{ + return genlmsg_data (gnlh); +} + +struct genlmsghdr * +genlmsg_hdr (struct nlmsghdr *nlh) +{ + return nlmsg_data (nlh); +} + +void * +genlmsg_user_data (const struct genlmsghdr *gnlh, const int hdrlen) +{ + return (char *) genlmsg_user_hdr (gnlh) + NLMSG_ALIGN (hdrlen); +} + +struct nlattr * +genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen) +{ + return genlmsg_user_data (gnlh, hdrlen); +} + +int +genlmsg_len (const struct genlmsghdr *gnlh) +{ + const struct nlmsghdr *nlh; + + nlh = (const struct nlmsghdr *) ((const unsigned char *) gnlh - NLMSG_HDRLEN); + return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); +} + +int +genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen) +{ + return genlmsg_len (gnlh) - NLMSG_ALIGN (hdrlen); +} + +int +genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen) +{ + struct genlmsghdr *ghdr; + + if (!nlmsg_valid_hdr (nlh, GENL_HDRLEN)) + return 0; + + ghdr = nlmsg_data (nlh); + if (genlmsg_len (ghdr) < NLMSG_ALIGN (hdrlen)) + return 0; + + return 1; +} + +int +genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], + int maxtype, const struct nla_policy *policy) +{ + struct genlmsghdr *ghdr; + + if (!genlmsg_valid_hdr (nlh, hdrlen)) + return -NLE_MSG_TOOSHORT; + + ghdr = nlmsg_data (nlh); + return nla_parse (tb, maxtype, genlmsg_attrdata (ghdr, hdrlen), + genlmsg_attrlen (ghdr, hdrlen), policy); +} + /*****************************************************************************/ diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h index f94e6de7ea..64fcbfa4ad 100644 --- a/src/platform/nm-netlink.h +++ b/src/platform/nm-netlink.h @@ -52,6 +52,23 @@ _nl_nla_parse_nested (struct nlattr *tb[], int maxtype, struct nlattr *nla, } #define nla_parse_nested(...) _nl_nla_parse_nested(__VA_ARGS__) +/***************************************************************************** + * Reimplementations/copied from libnl3/genl + *****************************************************************************/ + +void *genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family, + int hdrlen, int flags, uint8_t cmd, uint8_t version); +void *genlmsg_data (const struct genlmsghdr *gnlh); +void *genlmsg_user_hdr (const struct genlmsghdr *gnlh); +struct genlmsghdr *genlmsg_hdr (struct nlmsghdr *nlh); +void *genlmsg_user_data (const struct genlmsghdr *gnlh, const int hdrlen); +struct nlattr *genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen); +int genlmsg_len (const struct genlmsghdr *gnlh); +int genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen); +int genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen); +int genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], + int maxtype, const struct nla_policy *policy); + /***************************************************************************** * helpers *****************************************************************************/ diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c index 6125461175..a2082b05d7 100644 --- a/src/platform/wifi/wifi-utils-nl80211.c +++ b/src/platform/wifi/wifi-utils-nl80211.c @@ -46,103 +46,6 @@ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } G_STMT_END -/***************************************************************************** - * Copied from libnl3/genl: - *****************************************************************************/ - -static void * -genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family, - int hdrlen, int flags, uint8_t cmd, uint8_t version) -{ - struct nlmsghdr *nlh; - struct genlmsghdr hdr = { - .cmd = cmd, - .version = version, - }; - - nlh = nlmsg_put (msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); - if (nlh == NULL) - return NULL; - - memcpy (nlmsg_data (nlh), &hdr, sizeof (hdr)); - - return (char *) nlmsg_data (nlh) + GENL_HDRLEN; -} - -static void * -genlmsg_data (const struct genlmsghdr *gnlh) -{ - return ((unsigned char *) gnlh + GENL_HDRLEN); -} - -static void * -genlmsg_user_hdr (const struct genlmsghdr *gnlh) -{ - return genlmsg_data (gnlh); -} - -static struct genlmsghdr * -genlmsg_hdr (struct nlmsghdr *nlh) -{ - return nlmsg_data (nlh); -} - -static void * -genlmsg_user_data (const struct genlmsghdr *gnlh, const int hdrlen) -{ - return (char *) genlmsg_user_hdr (gnlh) + NLMSG_ALIGN (hdrlen); -} - -static struct nlattr * -genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen) -{ - return genlmsg_user_data (gnlh, hdrlen); -} - -static int -genlmsg_len (const struct genlmsghdr *gnlh) -{ - const struct nlmsghdr *nlh; - - nlh = (const struct nlmsghdr *) ((const unsigned char *) gnlh - NLMSG_HDRLEN); - return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); -} - -static int -genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen) -{ - return genlmsg_len (gnlh) - NLMSG_ALIGN (hdrlen); -} - -static int -genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen) -{ - struct genlmsghdr *ghdr; - - if (!nlmsg_valid_hdr (nlh, GENL_HDRLEN)) - return 0; - - ghdr = nlmsg_data (nlh); - if (genlmsg_len (ghdr) < NLMSG_ALIGN (hdrlen)) - return 0; - - return 1; -} - -static int -genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], - int maxtype, const struct nla_policy *policy) -{ - struct genlmsghdr *ghdr; - - if (!genlmsg_valid_hdr (nlh, hdrlen)) - return -NLE_MSG_TOOSHORT; - - ghdr = nlmsg_data (nlh); - return nla_parse (tb, maxtype, genlmsg_attrdata (ghdr, hdrlen), - genlmsg_attrlen (ghdr, hdrlen), policy); -} - /***************************************************************************** * Reimplementation of libnl3/genl functions: *****************************************************************************/