diff --git a/include/NetworkManager.h b/include/NetworkManager.h index 3d35a59405..d45ad07b3f 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -158,6 +158,7 @@ typedef enum { * @NM_WIFI_DEVICE_CAP_WPA: device supports WPA1 authentication * @NM_WIFI_DEVICE_CAP_RSN: device supports WPA2/RSN authentication * @NM_WIFI_DEVICE_CAP_AP: device supports Access Point mode + * @NM_WIFI_DEVICE_CAP_ADHOC: device supports Ad-Hoc mode * * 802.11 specific device encryption and authentication capabilities. **/ @@ -169,7 +170,8 @@ typedef enum { NM_WIFI_DEVICE_CAP_CIPHER_CCMP = 0x00000008, NM_WIFI_DEVICE_CAP_WPA = 0x00000010, NM_WIFI_DEVICE_CAP_RSN = 0x00000020, - NM_WIFI_DEVICE_CAP_AP = 0x00000040 + NM_WIFI_DEVICE_CAP_AP = 0x00000040, + NM_WIFI_DEVICE_CAP_ADHOC = 0x00000080 } NMDeviceWifiCapabilities; diff --git a/introspection/nm-device-wifi.xml b/introspection/nm-device-wifi.xml index f8eddd7039..dcfa20ccb9 100644 --- a/introspection/nm-device-wifi.xml +++ b/introspection/nm-device-wifi.xml @@ -122,6 +122,9 @@ The device supports Access Point mode. + + The device supports Ad-Hoc mode. + diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 67a10d43f0..925a0bd5e1 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -1016,6 +1016,7 @@ check_connection_compatible (NMDevice *device, NMSettingWireless *s_wireless; const GByteArray *mac; const GSList *mac_blacklist, *mac_blacklist_iter; + const char *mode; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); @@ -1071,8 +1072,17 @@ check_connection_compatible (NMDevice *device, return FALSE; } - /* Early exit if supplicant or device don't support AP mode */ - if (g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0) { + /* Early exit if supplicant or device doesn't support requested mode */ + mode = nm_setting_wireless_get_mode (s_wireless); + if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) { + if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) { + g_set_error_literal (error, + NM_WIFI_ERROR, + NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED, + "Ad-Hoc mode is not supported by this device."); + return FALSE; + } + } else if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) { if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_AP)) { g_set_error_literal (error, NM_WIFI_ERROR, diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h index 425b852514..368d0b800c 100644 --- a/src/nm-device-wifi.h +++ b/src/nm-device-wifi.h @@ -48,6 +48,7 @@ typedef enum { NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, /*< nick=AccessPointNotFound >*/ NM_WIFI_ERROR_SCAN_NOT_ALLOWED, /*< nick=ScanNotAllowed >*/ NM_WIFI_ERROR_AP_MODE_UNSUPPORTED, /*< nick=ApModeUnsupported >*/ + NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED, /*< nick=AdhocModeUnsupported >*/ } NMWifiError; #define NM_DEVICE_WIFI_HW_ADDRESS "hw-address" diff --git a/src/wifi/wifi-utils-nl80211.c b/src/wifi/wifi-utils-nl80211.c index 5a7103ee3a..f227d21440 100644 --- a/src/wifi/wifi-utils-nl80211.c +++ b/src/wifi/wifi-utils-nl80211.c @@ -700,10 +700,10 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg) int i; nla_for_each_nested (nl_mode, tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) { - if (nla_type (nl_mode) == NL80211_IFTYPE_AP) { + if (nla_type (nl_mode) == NL80211_IFTYPE_AP) info->caps |= NM_WIFI_DEVICE_CAP_AP; - break; - } + else if (nla_type (nl_mode) == NL80211_IFTYPE_ADHOC) + info->caps |= NM_WIFI_DEVICE_CAP_ADHOC; } } diff --git a/src/wifi/wifi-utils-wext.c b/src/wifi/wifi-utils-wext.c index 37cd94e987..6e990aed76 100644 --- a/src/wifi/wifi-utils-wext.c +++ b/src/wifi/wifi-utils-wext.c @@ -556,6 +556,12 @@ wext_get_caps (WifiDataWext *wext, struct iw_range *range) caps &= ~WPA_CAPS; } + /* There's no way to detect Ad-Hoc/AP mode support with WEXT + * (other than actually trying to do it), so just assume that + * Ad-Hoc is supported and AP isn't. + */ + caps |= NM_WIFI_DEVICE_CAP_ADHOC; + return caps; }