mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-07 19:10:31 +01:00
wifi: various AP mode fixups
Scanning doesn't work well in AP mode, because then you're off-channel and not serving your clients, which isn't good for anyone. Plus, nl80211 refuses to scan in AP mode anyway, so just don't scan. Second, track the device's mode based on the connection we're activating or have activated, not based on whatever mode the kernel drivers are using that second. That is more consistent, since there's a race between when the connection starts being activated, when the device will be in INFRA mode, and when the supplicant actually gets around to changing the mode. Third, fix various other codepaths that weren't quite expecting AP mode.
This commit is contained in:
parent
6ae1def061
commit
28ebea3440
1 changed files with 68 additions and 33 deletions
|
|
@ -151,6 +151,7 @@ struct _NMDeviceWifiPrivate {
|
|||
Supplicant supplicant;
|
||||
WifiData * wifi_data;
|
||||
gboolean ssid_found;
|
||||
NM80211Mode mode;
|
||||
|
||||
guint32 failed_link_count;
|
||||
guint periodic_source_id;
|
||||
|
|
@ -727,7 +728,7 @@ periodic_update (gpointer user_data)
|
|||
return TRUE;
|
||||
|
||||
/* In AP mode we currently have nothing to do. */
|
||||
if (priv->current_ap && (nm_ap_get_mode (priv->current_ap) == NM_802_11_MODE_AP))
|
||||
if (priv->mode == NM_802_11_MODE_AP)
|
||||
return TRUE;
|
||||
|
||||
/* In IBSS mode, most newer firmware/drivers do "BSS coalescing" where
|
||||
|
|
@ -979,6 +980,8 @@ deactivate (NMDevice *dev)
|
|||
* (usually older ones) don't scan well in adhoc mode.
|
||||
*/
|
||||
wifi_utils_set_mode (priv->wifi_data, NM_802_11_MODE_INFRA);
|
||||
priv->mode = NM_802_11_MODE_INFRA;
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1603,6 +1606,10 @@ scanning_allowed (NMDeviceWifi *self)
|
|||
|
||||
g_return_val_if_fail (priv->supplicant.iface != NULL, FALSE);
|
||||
|
||||
/* Scanning not done in AP mode */
|
||||
if (priv->mode == NM_802_11_MODE_AP)
|
||||
return FALSE;
|
||||
|
||||
switch (nm_device_get_state (NM_DEVICE (self))) {
|
||||
case NM_DEVICE_STATE_UNKNOWN:
|
||||
case NM_DEVICE_STATE_UNMANAGED:
|
||||
|
|
@ -2089,10 +2096,12 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
|
|||
g_return_if_fail (properties != NULL);
|
||||
g_return_if_fail (iface != NULL);
|
||||
|
||||
/* Ignore new APs when unavailable or unamnaged */
|
||||
/* Ignore new APs when unavailable, unmanaged, or in AP mode */
|
||||
state = nm_device_get_state (NM_DEVICE (self));
|
||||
if (state <= NM_DEVICE_STATE_UNAVAILABLE)
|
||||
return;
|
||||
if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP)
|
||||
return;
|
||||
|
||||
ap = nm_ap_new_from_properties (object_path, properties);
|
||||
if (ap) {
|
||||
|
|
@ -2437,8 +2446,10 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
|
|||
|
||||
nm_log_info (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation (%s/wireless) Stage 2 of 5 (Device Configure) "
|
||||
"successful. Connected to wireless network '%s'.",
|
||||
"successful. %s '%s'.",
|
||||
nm_device_get_iface (device),
|
||||
priv->mode == NM_802_11_MODE_AP ? "Started Wi-Fi Hotspot" :
|
||||
"Connected to wireless network",
|
||||
ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)");
|
||||
nm_device_activate_schedule_stage3_ip_config_start (device);
|
||||
} else if (devstate == NM_DEVICE_STATE_ACTIVATED)
|
||||
|
|
@ -2690,23 +2701,26 @@ supplicant_connection_timeout_cb (gpointer user_data)
|
|||
connection = nm_act_request_get_connection (req);
|
||||
g_assert (connection);
|
||||
|
||||
ap = nm_device_wifi_get_activation_ap (self);
|
||||
g_assert (ap);
|
||||
|
||||
if (nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) {
|
||||
/* In Ad-Hoc mode there's nothing to check the encryption key (if any)
|
||||
* so supplicant timeouts here are almost certainly the wifi driver
|
||||
* being really stupid.
|
||||
if ( priv->mode == NM_802_11_MODE_ADHOC
|
||||
|| priv->mode == NM_802_11_MODE_AP) {
|
||||
/* In Ad-Hoc and AP modes there's nothing to check the encryption key
|
||||
* (if any), so supplicant timeouts here are almost certainly the wifi
|
||||
* driver being really stupid.
|
||||
*/
|
||||
nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation (%s/wireless): Ad-Hoc network creation took "
|
||||
"Activation (%s/wireless): %s network creation took "
|
||||
"too long, failing activation.",
|
||||
nm_device_get_iface (dev));
|
||||
nm_device_get_iface (dev),
|
||||
priv->mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc" : "Hotspot");
|
||||
nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert (priv->mode == NM_802_11_MODE_INFRA);
|
||||
ap = nm_device_wifi_get_activation_ap (self);
|
||||
g_assert (ap);
|
||||
|
||||
if (priv->ssid_found && is_encrypted (ap, connection)) {
|
||||
guint64 timestamp = 0;
|
||||
gboolean new_secrets = TRUE;
|
||||
|
|
@ -2978,6 +2992,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
NMSettingWireless *s_wireless;
|
||||
const GByteArray *cloned_mac;
|
||||
GSList *iter;
|
||||
const char *mode;
|
||||
|
||||
req = nm_device_get_act_request (NM_DEVICE (self));
|
||||
g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
|
@ -2985,6 +3000,22 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
connection = nm_act_request_get_connection (req);
|
||||
g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
s_wireless = nm_connection_get_setting_wireless (connection);
|
||||
g_assert (s_wireless);
|
||||
|
||||
mode = nm_setting_wireless_get_mode (s_wireless);
|
||||
if (g_strcmp0 (mode, "infra") == 0)
|
||||
priv->mode = NM_802_11_MODE_INFRA;
|
||||
else if (g_strcmp0 (mode, "adhoc") == 0)
|
||||
priv->mode = NM_802_11_MODE_ADHOC;
|
||||
else if (g_strcmp0 (mode, "ap") == 0) {
|
||||
priv->mode = NM_802_11_MODE_AP;
|
||||
|
||||
/* Scanning not done in AP mode; clear the scan list */
|
||||
remove_all_aps (self);
|
||||
}
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE);
|
||||
|
||||
/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
|
||||
* and turns them into open networks. It's been this way since at least
|
||||
* 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks.
|
||||
|
|
@ -2996,34 +3027,32 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
}
|
||||
|
||||
/* Set spoof MAC to the interface */
|
||||
s_wireless = nm_connection_get_setting_wireless (connection);
|
||||
g_assert (s_wireless);
|
||||
|
||||
cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
|
||||
if (cloned_mac && (cloned_mac->len == ETH_ALEN))
|
||||
_set_hw_addr (self, (const guint8 *) cloned_mac->data, "set");
|
||||
|
||||
/* If the user is trying to connect to an AP that NM doesn't yet know about
|
||||
* (hidden network or something), create an fake AP from the security
|
||||
* settings in the connection to use until the AP is recognized from the
|
||||
* scan list, which should show up when the connection is successful.
|
||||
*/
|
||||
ap = nm_device_wifi_get_activation_ap (self);
|
||||
if (ap)
|
||||
goto done;
|
||||
/* AP mode never uses a specific object or existing scanned AP */
|
||||
if (priv->mode != NM_802_11_MODE_AP) {
|
||||
ap = nm_device_wifi_get_activation_ap (self);
|
||||
if (ap)
|
||||
goto done;
|
||||
|
||||
/* Find a compatible AP in the scan list */
|
||||
for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
|
||||
NMAccessPoint *candidate = NM_AP (iter->data);
|
||||
/* Find a compatible AP in the scan list */
|
||||
for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
|
||||
NMAccessPoint *candidate = NM_AP (iter->data);
|
||||
|
||||
if (nm_ap_check_compatible (candidate, connection)) {
|
||||
ap = candidate;
|
||||
break;
|
||||
if (nm_ap_check_compatible (candidate, connection)) {
|
||||
ap = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If no compatible AP was found, create a fake AP (network is likely
|
||||
* hidden) and try to use that.
|
||||
/* If the user is trying to connect to an AP that NM doesn't yet know about
|
||||
* (hidden network or something) or starting a Hotspot, create an fake AP
|
||||
* from the security settings in the connection. This "fake" AP gets used
|
||||
* until the real one is found in the scan list (Ad-Hoc or Hidden), or until
|
||||
* the device is deactivated (Hotspot).
|
||||
*/
|
||||
if (!ap) {
|
||||
ap = nm_ap_new_fake_from_connection (connection);
|
||||
|
|
@ -3209,6 +3238,11 @@ handle_ip_config_timeout (NMDeviceWifi *self,
|
|||
|
||||
g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) {
|
||||
*chain_up = TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ap = nm_device_wifi_get_activation_ap (self);
|
||||
g_assert (ap);
|
||||
|
||||
|
|
@ -3610,8 +3644,9 @@ nm_device_wifi_new (const char *udi,
|
|||
}
|
||||
|
||||
static void
|
||||
nm_device_wifi_init (NMDeviceWifi * self)
|
||||
nm_device_wifi_init (NMDeviceWifi *self)
|
||||
{
|
||||
NM_DEVICE_WIFI_GET_PRIVATE (self)->mode = NM_802_11_MODE_INFRA;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3670,7 +3705,7 @@ get_property (GObject *object, guint prop_id,
|
|||
g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER));
|
||||
break;
|
||||
case PROP_MODE:
|
||||
g_value_set_uint (value, wifi_utils_get_mode (priv->wifi_data));
|
||||
g_value_set_uint (value, priv->mode);
|
||||
break;
|
||||
case PROP_BITRATE:
|
||||
g_value_set_uint (value, priv->rate);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue