diff --git a/Makefile.am b/Makefile.am index e407d38725..bcd403bd9c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,7 +31,8 @@ DISTCHECK_CONFIGURE_FLAGS = \ --with-docs=yes \ --enable-more-warnings=yes \ --with-udev-dir=$$dc_install_base/lib/udev \ - --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) + --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) \ + --with-wext=no DISTCLEANFILES = intltool-extract intltool-merge intltool-update diff --git a/configure.ac b/configure.ac index 5bdb6c57d4..69e064056e 100644 --- a/configure.ac +++ b/configure.ac @@ -213,25 +213,35 @@ if ! test x"$ac_distver" = x""; then AC_DEFINE_UNQUOTED(NM_DIST_VERSION, "$ac_distver", [Define the distribution version string]) 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) +dnl +dnl Default to using WEXT but allow it to be disabled +dnl +AC_ARG_WITH(wext, AS_HELP_STRING([--with-wext=yes], [Enable or disable Linux Wireless Extensions]), ac_with_wext=$withval, ac_with_wext="yes") +if test x"$ac_with_wext" = x"yes"; then + 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]) fi +AM_CONDITIONAL(WITH_WEXT, test x"${ac_with_wext}" = x"yes") AC_MSG_CHECKING([Linux kernel nl80211 headers]) AC_COMPILE_IFELSE( @@ -709,6 +719,7 @@ src/ppp-manager/Makefile src/dnsmasq-manager/Makefile src/modem-manager/Makefile src/bluez-manager/Makefile +src/wifi/Makefile src/firewall-manager/Makefile src/settings/Makefile src/settings/plugins/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 00e1997c90..2e74f09419 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,6 +12,7 @@ SUBDIRS= \ modem-manager \ bluez-manager \ firewall-manager \ + wifi \ settings if WITH_WIMAX @@ -36,6 +37,7 @@ INCLUDES = -I${top_srcdir} \ -I$(top_srcdir)/src/bluez-manager \ -I$(top_srcdir)/src/firewall-manager \ -I$(top_srcdir)/src/settings \ + -I$(top_srcdir)/src/wifi \ -I${top_srcdir}/libnm-util \ -I${top_builddir}/libnm-util \ -I${top_srcdir}/callouts @@ -118,13 +120,6 @@ NetworkManager_SOURCES = \ nm-device-private.h \ nm-device-ethernet.c \ nm-device-ethernet.h \ - wifi-utils.c \ - wifi-utils.h \ - wifi-utils-private.h \ - wifi-utils-wext.c \ - wifi-utils-wext.h \ - wifi-utils-nl80211.c \ - wifi-utils-nl80211.h \ nm-device-wifi.c \ nm-device-wifi.h \ nm-device-wired.c \ @@ -304,6 +299,7 @@ NetworkManager_LDADD = \ ./ppp-manager/libppp-manager.la \ ./modem-manager/libmodem-manager.la \ ./bluez-manager/libbluez-manager.la \ + ./wifi/libwifi-utils.la \ ./firewall-manager/libfirewall-manager.la \ ./settings/libsettings.la \ ./backends/libnmbackend.la \ diff --git a/src/nm-manager.c b/src/nm-manager.c index 146d491c9b..e95a92cec0 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2115,9 +2115,6 @@ load_device_factories (NMManager *self) static gboolean is_wireless (GUdevDevice *device) { - char phy80211_path[255]; - struct stat s; - const char *path; const char *tmp; /* Check devtype, newer kernels (2.6.32+) have this */ @@ -2125,14 +2122,9 @@ is_wireless (GUdevDevice *device) if (g_strcmp0 (tmp, "wlan") == 0) return TRUE; - /* Check for nl80211 sysfs paths */ - path = g_udev_device_get_sysfs_path (device); - snprintf (phy80211_path, sizeof (phy80211_path), "%s/phy80211", path); - if ((stat (phy80211_path, &s) == 0 && (s.st_mode & S_IFDIR))) - return TRUE; - /* Otherwise hit up WEXT directly */ - return wifi_utils_is_wifi (g_udev_device_get_name (device)); + return wifi_utils_is_wifi (g_udev_device_get_name (device), + g_udev_device_get_sysfs_path (device)); } static gboolean diff --git a/src/settings/plugins/ifcfg-rh/Makefile.am b/src/settings/plugins/ifcfg-rh/Makefile.am index d9008bd65b..8b5b0f24bb 100644 --- a/src/settings/plugins/ifcfg-rh/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/Makefile.am @@ -23,6 +23,7 @@ libifcfg_rh_io_la_SOURCES = \ utils.h INCLUDES = \ + -I$(top_srcdir)/src/wifi \ -I$(top_srcdir)/src/settings \ -I$(top_srcdir)/include \ -I$(top_builddir)/include \ @@ -38,6 +39,7 @@ libifcfg_rh_io_la_CPPFLAGS = \ -DSBINDIR=\"$(sbindir)\" libifcfg_rh_io_la_LIBADD = \ + $(top_builddir)/src/wifi/libwifi-utils.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(GLIB_LIBS) \ $(NSS_LIBS) diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 058385d4de..22333bdad7 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -48,6 +47,8 @@ #include #include +#include "wifi-utils.h" + #include "common.h" #include "shvar.h" #include "utils.h" @@ -3544,47 +3545,6 @@ infiniband_connection_from_ifcfg (const char *file, return connection; } -static gboolean -is_wireless_device (const char *iface) -{ - int fd; - struct iw_range range; - struct iwreq wrq; - gboolean is_wireless = FALSE; - - g_return_val_if_fail (iface != NULL, FALSE); - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd == -1) - return FALSE; - - memset (&wrq, 0, sizeof (struct iwreq)); - memset (&range, 0, sizeof (struct iw_range)); - strncpy (wrq.ifr_name, iface, IFNAMSIZ); - wrq.u.data.pointer = (caddr_t) ⦥ - wrq.u.data.length = sizeof (struct iw_range); - - if (ioctl (fd, SIOCGIWRANGE, &wrq) == 0) - is_wireless = TRUE; - else { - if (errno == EOPNOTSUPP) - is_wireless = FALSE; - else { - /* Sigh... some wired devices (kvm/qemu) return EINVAL when the - * device is down even though it's not a wireless device. So try - * IWNAME as a fallback. - */ - memset (&wrq, 0, sizeof (struct iwreq)); - strncpy (wrq.ifr_name, iface, IFNAMSIZ); - if (ioctl (fd, SIOCGIWNAME, &wrq) == 0) - is_wireless = TRUE; - } - } - - close (fd); - return is_wireless; -} - static void handle_bond_option (NMSettingBond *s_bond, const char *key, @@ -4012,7 +3972,7 @@ connection_from_file (const char *filename, else if (is_vlan_device (device, parsed)) type = g_strdup (TYPE_VLAN); /* Test wireless extensions */ - else if (is_wireless_device (device)) + else if (wifi_utils_is_wifi (device, NULL)) type = g_strdup (TYPE_WIRELESS); else type = g_strdup (TYPE_ETHERNET); diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/Makefile.am index 6b99561144..1c433ff5e4 100644 --- a/src/settings/plugins/ifcfg-rh/tests/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.am @@ -21,6 +21,7 @@ test_ifcfg_rh_CPPFLAGS = \ test_ifcfg_rh_LDADD = \ $(top_builddir)/libnm-glib/libnm-glib.la \ $(top_builddir)/libnm-util/libnm-util.la \ + $(top_builddir)/src/wifi/libwifi-utils.la \ $(builddir)/../libifcfg-rh-io.la \ $(DBUS_LIBS) diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index b4157a5e94..042ef9ee07 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -19,6 +19,7 @@ * Copyright (C) 2006 - 2008 Novell, Inc. */ +#include #include #include #include @@ -804,6 +805,12 @@ interface_add_cb (DBusGProxy *proxy, } } +#if HAVE_WEXT +#define DEFAULT_WIFI_DRIVER "nl80211,wext" +#else +#define DEFAULT_WIFI_DRIVER "nl80211" +#endif + static void interface_add (NMSupplicantInterface *self, gboolean is_wireless) { @@ -832,7 +839,7 @@ interface_add (NMSupplicantInterface *self, gboolean is_wireless) driver = g_new0 (GValue, 1); g_value_init (driver, G_TYPE_STRING); - g_value_set_string (driver, is_wireless ? "nl80211,wext" : "wired"); + g_value_set_string (driver, is_wireless ? DEFAULT_WIFI_DRIVER : "wired"); g_hash_table_insert (hash, "Driver", driver); ifname = g_new0 (GValue, 1); diff --git a/src/wifi-utils-nl80211.c b/src/wifi/wifi-utils-nl80211.c similarity index 87% rename from src/wifi-utils-nl80211.c rename to src/wifi/wifi-utils-nl80211.c index ed2675439d..6411602c0a 100644 --- a/src/wifi-utils-nl80211.c +++ b/src/wifi/wifi-utils-nl80211.c @@ -73,17 +73,16 @@ static int error_handler (struct sockaddr_nl *nla, struct nlmsgerr *err, return NL_SKIP; } -static struct nl_msg *nl80211_alloc_msg (WifiDataNl80211 *nl80211, - guint32 cmd, guint32 flags) +static struct nl_msg * +_nl80211_alloc_msg (int id, int ifindex, guint32 cmd, guint32 flags) { - struct nl_msg *msg = nlmsg_alloc (); - if (!msg) - return NULL; - - genlmsg_put (msg, 0, 0, nl80211->id, 0, flags, cmd, 0); - - NLA_PUT_U32 (msg, NL80211_ATTR_IFINDEX, nl80211->parent.ifindex); + struct nl_msg *msg; + msg = nlmsg_alloc (); + if (msg) { + genlmsg_put (msg, 0, 0, id, 0, flags, cmd, 0); + NLA_PUT_U32 (msg, NL80211_ATTR_IFINDEX, ifindex); + } return msg; nla_put_failure: @@ -91,44 +90,59 @@ static struct nl_msg *nl80211_alloc_msg (WifiDataNl80211 *nl80211, return NULL; } -static int nl80211_send_and_recv (WifiDataNl80211 *nl80211, - struct nl_msg *msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) +static struct nl_msg * +nl80211_alloc_msg (WifiDataNl80211 *nl80211, guint32 cmd, guint32 flags) +{ + return _nl80211_alloc_msg (nl80211->id, nl80211->parent.ifindex, cmd, flags); +} + +/* NOTE: this function consumes 'msg' */ +static int +_nl80211_send_and_recv (struct nl_sock *nl_sock, + struct nl_cb *nl_cb, + struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) { struct nl_cb *cb; int err; - if (msg == NULL) - return -ENOMEM; - + g_return_val_if_fail (msg != NULL, -ENOMEM); g_return_val_if_fail (valid_handler != NULL, -EINVAL); - cb = nl_cb_clone (nl80211->nl_cb); + cb = nl_cb_clone (nl_cb); if (!cb) { err = -ENOMEM; goto out; } - err = nl_send_auto_complete (nl80211->nl_sock, msg); + err = nl_send_auto_complete (nl_sock, msg); if (err < 0) goto out; err = 1; - nl_cb_err (cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set (cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); while (err > 0) - nl_recvmsgs (nl80211->nl_sock, cb); + nl_recvmsgs (nl_sock, cb); + out: nl_cb_put (cb); nlmsg_free (msg); return err; } +static int +nl80211_send_and_recv (WifiDataNl80211 *nl80211, + struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) +{ + return _nl80211_send_and_recv (nl80211->nl_sock, nl80211->nl_cb, msg, valid_handler, valid_data); +} static void wifi_nl80211_deinit (WifiData *parent) @@ -186,9 +200,6 @@ wifi_nl80211_get_mode (WifiData *data) return NM_802_11_MODE_UNKNOWN; return iface_info.mode; - return NM_802_11_MODE_INFRA; - return NM_802_11_MODE_ADHOC; - return NM_802_11_MODE_UNKNOWN; } static gboolean @@ -730,3 +741,69 @@ error: wifi_utils_deinit ((WifiData *) nl80211); return NULL; } + +static int +iface_to_index (struct nl_sock *nl_sock, const char *iface) +{ + struct nl_cache *link_cache; + int err, ifindex; + + /* name to index */ + err = rtnl_link_alloc_cache (nl_sock, &link_cache); + if (err < 0) { + nm_log_warn (LOGD_HW, "failed to allocate link cache"); + return -1; + } + nl_cache_mngt_provide (link_cache); + nl_cache_refill (nl_sock, link_cache); + ifindex = rtnl_link_name2i (link_cache, iface); + nl_cache_free (link_cache); + + return ifindex; +} + +gboolean +wifi_nl80211_is_wifi (const char *iface) +{ + struct nl_sock *nl_sock; + struct nl_cb *nl_cb = NULL; + struct nl_msg *msg = NULL; + int id, ifindex; + struct nl80211_iface_info iface_info = { + .mode = NM_802_11_MODE_UNKNOWN, + }; + gboolean is_wifi = FALSE; + + nl_sock = nl_socket_alloc (); + if (nl_sock == NULL) + return FALSE; + + ifindex = iface_to_index (nl_sock, iface); + if (index < 0) + return FALSE; + + if (genl_connect (nl_sock)) + goto error; + + id = genl_ctrl_resolve (nl_sock, "nl80211"); + if (id < 0) + goto error; + + nl_cb = nl_cb_alloc (NL_CB_DEFAULT); + if (nl_cb) { + msg = _nl80211_alloc_msg (id, ifindex, NL80211_CMD_GET_INTERFACE, 0); + if (_nl80211_send_and_recv (nl_sock, + nl_cb, + msg, + nl80211_iface_info_handler, + &iface_info) >= 0) + is_wifi = (iface_info.mode != NM_802_11_MODE_UNKNOWN); + } + + error: + if (nl_cb) + nl_cb_put (nl_cb); + nl_socket_free (nl_sock); + return is_wifi; +} + diff --git a/src/wifi-utils-nl80211.h b/src/wifi/wifi-utils-nl80211.h similarity index 95% rename from src/wifi-utils-nl80211.h rename to src/wifi/wifi-utils-nl80211.h index 371aa4eadc..2a7fe874a2 100644 --- a/src/wifi-utils-nl80211.h +++ b/src/wifi/wifi-utils-nl80211.h @@ -25,4 +25,6 @@ WifiData *wifi_nl80211_init (const char *iface, int ifindex); +gboolean wifi_nl80211_is_wifi (const char *iface); + #endif /* WIFI_UTILS_NL80211_H */ diff --git a/src/wifi-utils-private.h b/src/wifi/wifi-utils-private.h similarity index 100% rename from src/wifi-utils-private.h rename to src/wifi/wifi-utils-private.h diff --git a/src/wifi-utils-wext.c b/src/wifi/wifi-utils-wext.c similarity index 100% rename from src/wifi-utils-wext.c rename to src/wifi/wifi-utils-wext.c diff --git a/src/wifi-utils-wext.h b/src/wifi/wifi-utils-wext.h similarity index 100% rename from src/wifi-utils-wext.h rename to src/wifi/wifi-utils-wext.h diff --git a/src/wifi-utils.c b/src/wifi/wifi-utils.c similarity index 88% rename from src/wifi-utils.c rename to src/wifi/wifi-utils.c index a9b946fcbe..a99a4b7bc9 100644 --- a/src/wifi-utils.c +++ b/src/wifi/wifi-utils.c @@ -20,13 +20,17 @@ */ #include +#include +#include #include #include #include "wifi-utils.h" #include "wifi-utils-private.h" -#include "wifi-utils-wext.h" #include "wifi-utils-nl80211.h" +#if HAVE_WEXT +#include "wifi-utils-wext.h" +#endif gpointer wifi_data_new (const char *iface, int ifindex, gsize len) @@ -58,10 +62,12 @@ wifi_utils_init (const char *iface, int ifindex, gboolean check_scan) g_return_val_if_fail (ifindex > 0, NULL); ret = wifi_nl80211_init (iface, ifindex); - if (ret != NULL) - return ret; - - return wifi_wext_init (iface, ifindex, check_scan); + if (ret == NULL) { +#if HAVE_WEXT + ret = wifi_wext_init (iface, ifindex, check_scan); +#endif + } + return ret; } NMDeviceWifiCapabilities @@ -151,12 +157,27 @@ wifi_utils_deinit (WifiData *data) } gboolean -wifi_utils_is_wifi (const char *iface) +wifi_utils_is_wifi (const char *iface, const char *sysfs_path) { + char phy80211_path[255]; + struct stat s; + g_return_val_if_fail (iface != NULL, FALSE); + if (sysfs_path) { + /* Check for nl80211 sysfs paths */ + snprintf (phy80211_path, sizeof (phy80211_path), "%s/phy80211", sysfs_path); + if ((stat (phy80211_path, &s) == 0 && (s.st_mode & S_IFDIR))) + return TRUE; + } + + if (wifi_nl80211_is_wifi (iface)) + return TRUE; + +#if HAVE_WEXT if (wifi_wext_is_wifi (iface)) return TRUE; +#endif return FALSE; } diff --git a/src/wifi-utils.h b/src/wifi/wifi-utils.h similarity index 96% rename from src/wifi-utils.h rename to src/wifi/wifi-utils.h index 66bb0971e6..09583e7bd4 100644 --- a/src/wifi-utils.h +++ b/src/wifi/wifi-utils.h @@ -29,7 +29,7 @@ typedef struct WifiData WifiData; -gboolean wifi_utils_is_wifi (const char *iface); +gboolean wifi_utils_is_wifi (const char *iface, const char *sysfs_path); WifiData *wifi_utils_init (const char *iface, int ifindex, gboolean check_scan);