diff options
| author | Michael Biebl <biebl@debian.org> | 2018-10-20 01:31:18 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-10-20 01:31:18 +0200 |
| commit | b4885f208ba690090952c0ae0452dd5bc2ba0601 (patch) | |
| tree | 5c8af02da4543f7132b9bad45711a3a65e620d0d /src/devices | |
| parent | 142485af41b7cf7b0060cc682a56d3ff38cabbb6 (diff) | |
| parent | 6518e361171f64bcaaa4bf868139362ed95cc2e0 (diff) | |
Update upstream source from tag 'upstream/1.14.2'
Update to upstream version '1.14.2' with Debian dir c118292f450ace1133a5dba2777cbeb54977dbe8
Diffstat (limited to 'src/devices')
| -rw-r--r-- | src/devices/bluetooth/nm-bluez-device.c | 21 | ||||
| -rw-r--r-- | src/devices/nm-device-ethernet-utils.c | 2 | ||||
| -rw-r--r-- | src/devices/nm-device.c | 150 | ||||
| -rw-r--r-- | src/devices/nm-device.h | 29 | ||||
| -rw-r--r-- | src/devices/wifi/nm-device-iwd.c | 304 | ||||
| -rw-r--r-- | src/devices/wifi/nm-device-olpc-mesh.c | 4 | ||||
| -rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 15 | ||||
| -rw-r--r-- | src/devices/wifi/nm-iwd-manager.c | 26 | ||||
| -rw-r--r-- | src/devices/wifi/nm-iwd-manager.h | 3 | ||||
| -rw-r--r-- | src/devices/wwan/nm-modem-broadband.c | 2 |
10 files changed, 332 insertions, 224 deletions
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index b69b4320..b722f692 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -227,21 +227,12 @@ pan_connection_check_create (NMBluezDevice *self) NULL); nm_connection_add_setting (connection, setting); - /* Setting: IPv4 */ - setting = nm_setting_ip4_config_new (); - g_object_set (G_OBJECT (setting), - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE, - NULL); - nm_connection_add_setting (connection, setting); - - /* Setting: IPv6 */ - setting = nm_setting_ip6_config_new (); - g_object_set (G_OBJECT (setting), - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, - NULL); - nm_connection_add_setting (connection, setting); + if (!nm_connection_normalize (connection, NULL, NULL, &error)) { + nm_log_err (LOGD_BT, "bluez[%s] couldn't generate a connection for NAP device: %s", + priv->path, error->message); + g_error_free (error); + g_return_if_reached (); + } /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) * which then already finds the suitable connection in priv->connections. This is confusing, diff --git a/src/devices/nm-device-ethernet-utils.c b/src/devices/nm-device-ethernet-utils.c index 8bdb1991..b18eadfa 100644 --- a/src/devices/nm-device-ethernet-utils.c +++ b/src/devices/nm-device-ethernet-utils.c @@ -29,7 +29,7 @@ nm_device_ethernet_utils_get_default_wired_name (GHashTable *existing_ids) int i; /* Find the next available unique connection name */ - for (i = 1; i <= G_MAXINT; i++) { + for (i = 1; i < G_MAXINT; i++) { temp = g_strdup_printf (_("Wired connection %d"), i); if ( !existing_ids || !g_hash_table_contains (existing_ids, temp)) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 8ca899a2..26ea06bd 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -464,6 +464,7 @@ typedef struct _NMDevicePrivate { gulong state_sigid; NMDhcp4Config * config; char * pac_url; + char * root_path; bool was_active; guint grace_id; } dhcp4; @@ -2813,7 +2814,6 @@ static void concheck_cb (NMConnectivity *connectivity, NMConnectivityCheckHandle *c_handle, NMConnectivityState state, - GError *error, gpointer user_data) { _nm_unused gs_unref_object NMDevice *self_keep_alive = NULL; @@ -2834,7 +2834,7 @@ concheck_cb (NMConnectivity *connectivity, handle->c_handle = NULL; self = handle->self; - if (nm_utils_error_is_cancelled (error, FALSE)) { + if (state == NM_CONNECTIVITY_CANCELLED) { /* the only place where we nm_connectivity_check_cancel(@c_handle), is * from inside concheck_handle_complete(). This is a recursive call, * nothing to do. */ @@ -2843,15 +2843,14 @@ concheck_cb (NMConnectivity *connectivity, return; } + /* we keep NMConnectivity instance alive. It cannot be disposing. */ + nm_assert (state != NM_CONNECTIVITY_DISPOSING); + self_keep_alive = g_object_ref (self); - _LOGT (LOGD_CONCHECK, "connectivity: complete check (seq:%llu, state:%s%s%s%s)", + _LOGT (LOGD_CONCHECK, "connectivity: complete check (seq:%llu, state:%s)", (long long unsigned) handle->seq, - nm_connectivity_state_to_string (state), - NM_PRINT_FMT_QUOTED (error, ", error: ", error->message, "", "")); - - /* we keep NMConnectivity instance alive. It cannot be disposing. */ - nm_assert (!nm_utils_error_is_cancelled (error, TRUE)); + nm_connectivity_state_to_string (state)); /* keep @self alive, while we invoke callbacks. */ priv = NM_DEVICE_GET_PRIVATE (self); @@ -3506,7 +3505,8 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self) guint32 lifetime, preferred; gint32 base; - if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) + if ( IN6_IS_ADDR_UNSPECIFIED (&addr->address) + || IN6_IS_ADDR_LINKLOCAL (&addr->address)) continue; if ( addr->n_ifa_flags & IFA_F_TENTATIVE @@ -3580,6 +3580,7 @@ device_link_changed (NMDevice *self) gboolean ip_ifname_changed = FALSE; nm_auto_nmpobj const NMPObject *pllink_keep_alive = NULL; const NMPlatformLink *pllink; + const char *str; int ifindex; gboolean was_up; gboolean update_unmanaged_specs = FALSE; @@ -3594,7 +3595,23 @@ device_link_changed (NMDevice *self) pllink_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (pllink)); - nm_device_update_from_platform_link (self, pllink); + str = nm_platform_link_get_udi (nm_device_get_platform (self), pllink->ifindex); + if (!nm_streq0 (str, priv->udi)) { + g_free (priv->udi); + priv->udi = g_strdup (str); + _notify (self, PROP_UDI); + } + + if (!nm_streq0 (pllink->driver, priv->driver)) { + g_free (priv->driver); + priv->driver = g_strdup (pllink->driver); + _notify (self, PROP_DRIVER); + } + + _set_mtu (self, pllink->mtu); + + if (ifindex == nm_device_get_ip_ifindex (self)) + _stats_update_counters_from_pllink (self, pllink); had_hw_addr = (priv->hw_addr != NULL); nm_device_update_hw_address (self); @@ -4582,9 +4599,23 @@ nm_device_owns_iface (NMDevice *self, const char *iface) NMConnection * nm_device_new_default_connection (NMDevice *self) { - if (NM_DEVICE_GET_CLASS (self)->new_default_connection) - return NM_DEVICE_GET_CLASS (self)->new_default_connection (self); - return NULL; + NMConnection *connection; + GError *error = NULL; + + if (!NM_DEVICE_GET_CLASS (self)->new_default_connection) + return NULL; + + connection = NM_DEVICE_GET_CLASS (self)->new_default_connection (self); + if (!connection) + return NULL; + + if (!nm_connection_normalize (connection, NULL, NULL, &error)) { + _LOGD (LOGD_DEVICE, "device generated an invalid default connection: %s", error->message); + g_error_free (error); + g_return_val_if_reached (NULL); + } + + return connection; } static void @@ -5043,11 +5074,15 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config) nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } - if (!unconfigure_ip_config) - return; - - nm_device_set_ip_config (self, AF_INET, NULL, FALSE, NULL); - nm_device_set_ip_config (self, AF_INET6, NULL, FALSE, NULL); + if (unconfigure_ip_config) { + nm_device_set_ip_config (self, AF_INET, NULL, FALSE, NULL); + nm_device_set_ip_config (self, AF_INET6, NULL, FALSE, NULL); + } else { + if (priv->dhcp4.client) + nm_dhcp_client_stop (priv->dhcp4.client, FALSE); + if (priv->dhcp6.client) + nm_dhcp_client_stop (priv->dhcp6.client, FALSE); + } } static gboolean @@ -5451,7 +5486,7 @@ nm_device_generate_connection (NMDevice *self, klass->update_connection (self, connection); - if (!nm_connection_verify (connection, &local)) { + if (!nm_connection_normalize (connection, NULL, NULL, error)) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "generated connection does not verify: %s", local->message); @@ -6955,6 +6990,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) nm_clear_g_source (&priv->dhcp4.grace_id); g_clear_pointer (&priv->dhcp4.pac_url, g_free); + g_clear_pointer (&priv->dhcp4.root_path, g_free); if (priv->dhcp4.client) { /* Stop any ongoing DHCP transaction on this device */ @@ -7328,6 +7364,9 @@ dhcp4_state_changed (NMDhcpClient *client, priv->dhcp4.pac_url = g_strdup (g_hash_table_lookup (options, "wpad")); nm_device_set_proxy_config (self, priv->dhcp4.pac_url); + g_free (priv->dhcp4.root_path); + priv->dhcp4.root_path = g_strdup (g_hash_table_lookup (options, "root_path")); + nm_dhcp4_config_set_options (priv->dhcp4.config, options); _notify (self, PROP_DHCP4_CONFIG); @@ -10780,8 +10819,10 @@ nm_device_reactivate_ip4_config (NMDevice *self, nm_ip4_config_update_routes_metric ((NMIP4Config *) priv->wwan_ip_config_4.orig, nm_device_get_route_metric (self, AF_INET)); } - if (priv->dhcp4.client) - nm_dhcp_client_set_route_metric (priv->dhcp4.client, metric_new); + if (priv->dhcp4.client) { + nm_dhcp_client_set_route_metric (priv->dhcp4.client, + nm_device_get_route_metric (self, AF_INET)); + } } } @@ -10851,8 +10892,10 @@ nm_device_reactivate_ip6_config (NMDevice *self, nm_ip6_config_update_routes_metric ((NMIP6Config *) priv->wwan_ip_config_6.orig, nm_device_get_route_metric (self, AF_INET6)); } - if (priv->dhcp6.client) - nm_dhcp_client_set_route_metric (priv->dhcp6.client, metric_new); + if (priv->dhcp6.client) { + nm_dhcp_client_set_route_metric (priv->dhcp6.client, + nm_device_get_route_metric (self, AF_INET6)); + } } } @@ -12521,7 +12564,9 @@ nm_device_get_firmware_missing (NMDevice *self) } static void -intersect_ext_config (NMDevice *self, AppliedConfig *config) +intersect_ext_config (NMDevice *self, + AppliedConfig *config, + gboolean intersect_routes) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMIPConfig *ext; @@ -12538,10 +12583,11 @@ intersect_ext_config (NMDevice *self, AppliedConfig *config) : (NMIPConfig *) priv->ext_ip_config_6; if (config->current) - nm_ip_config_intersect (config->current, ext, penalty); + nm_ip_config_intersect (config->current, ext, intersect_routes, penalty); else { config->current = nm_ip_config_intersect_alloc (config->orig, ext, + intersect_routes, penalty); } } @@ -12552,6 +12598,7 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex; GSList *iter; + gboolean is_up; nm_assert_addr_family (addr_family); @@ -12559,6 +12606,8 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config if (!ifindex) return FALSE; + is_up = nm_platform_link_is_up (nm_device_get_platform (self), ifindex); + if (addr_family == AF_INET) { g_clear_object (&priv->ext_ip_config_4); @@ -12573,14 +12622,15 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config * by the user. */ if (priv->con_ip_config_4) { nm_ip4_config_intersect (priv->con_ip_config_4, priv->ext_ip_config_4, + is_up, default_route_metric_penalty_get (self, AF_INET)); } - intersect_ext_config (self, &priv->dev_ip4_config); - intersect_ext_config (self, &priv->wwan_ip_config_4); + intersect_ext_config (self, &priv->dev_ip4_config, is_up); + intersect_ext_config (self, &priv->wwan_ip_config_4, is_up); for (iter = priv->vpn_configs_4; iter; iter = iter->next) - nm_ip4_config_intersect (iter->data, priv->ext_ip_config_4, 0); + nm_ip4_config_intersect (iter->data, priv->ext_ip_config_4, is_up, 0); } /* Remove parts from ext_ip_config_4 to only contain the information that @@ -12624,15 +12674,16 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config * by the user. */ if (priv->con_ip_config_6) { nm_ip6_config_intersect (priv->con_ip_config_6, priv->ext_ip_config_6, + is_up, default_route_metric_penalty_get (self, AF_INET6)); } - intersect_ext_config (self, &priv->ac_ip6_config); - intersect_ext_config (self, &priv->dhcp6.ip6_config); - intersect_ext_config (self, &priv->wwan_ip_config_6); + intersect_ext_config (self, &priv->ac_ip6_config, is_up); + intersect_ext_config (self, &priv->dhcp6.ip6_config, is_up); + intersect_ext_config (self, &priv->wwan_ip_config_6, is_up); for (iter = priv->vpn_configs_6; iter; iter = iter->next) - nm_ip6_config_intersect (iter->data, priv->ext_ip_config_6, 0); + nm_ip6_config_intersect (iter->data, priv->ext_ip_config_6, is_up, 0); if ( priv->ipv6ll_has && !nm_ip6_config_lookup_address (priv->ext_ip_config_6, &priv->ipv6ll_addr)) @@ -13516,6 +13567,19 @@ nm_device_update_metered (NMDevice *self) } } +static NMDeviceCheckDevAvailableFlags +_device_check_dev_available_flags_from_con (NMDeviceCheckConAvailableFlags con_flags) +{ + NMDeviceCheckDevAvailableFlags dev_flags; + + dev_flags = NM_DEVICE_CHECK_DEV_AVAILABLE_NONE; + + if (NM_FLAGS_HAS (con_flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)) + dev_flags |= _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER; + + return dev_flags; +} + static gboolean _nm_device_check_connection_available (NMDevice *self, NMConnection *connection, @@ -13557,34 +13621,30 @@ _nm_device_check_connection_available (NMDevice *self, return FALSE; } if (state < NM_DEVICE_STATE_UNAVAILABLE) { - if (NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)) { - if (!nm_device_get_managed (self, TRUE)) { + if (!nm_device_get_managed (self, TRUE)) { + if (!nm_device_get_managed (self, FALSE)) { nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE, - "device is unmanaged"); + "device is strictly unmanaged"); return FALSE; } - } else { - if (!nm_device_get_managed (self, FALSE)) { + if (!NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED)) { nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE, - "device is unmanaged for interal request"); + "device is currently unmanaged"); return FALSE; } } } if ( state < NM_DEVICE_STATE_DISCONNECTED && !nm_device_is_software (self)) { - if (NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)) { - if (!nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)) { + if (!nm_device_is_available (self, _device_check_dev_available_flags_from_con (flags))) { + if (NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)) { nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "device is not available"); - return FALSE; - } - } else { - if (!nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) { + } else { nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "device is not available for internal request"); - return FALSE; } + return FALSE; } } diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 6342a657..8f376b20 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -167,14 +167,34 @@ typedef enum NMActStageReturn NMActStageReturn; typedef enum { /*< skip >*/ NM_DEVICE_CHECK_CON_AVAILABLE_NONE = 0, + /* since NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST is a collection of flags with more fine grained + * parts, this flag in general indicates that this is a user-request. */ _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = (1L << 0), + + /* we also consider devices which have no carrier but are still waiting for the driver + * to detect carrier. Usually, such devices are not yet available, however for a user-request + * they are. They might fail later if carrier doesn't come. */ _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER = (1L << 1), + + /* usually, a profile is only available if the Wi-Fi AP is in range. For an + * explicit user request, we also consider profiles for APs that are not (yet) + * visible. */ _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP = (1L << 2), + + /* a device can be marked as unmanaged for various reasons. Some of these reasons + * are authorative, others not. Non-authoritative reasons can be overruled by + * `nmcli device set $DEVICE managed yes`. Also, for an explicit user activation + * request we may want to consider the device as managed. This flag makes devices + * that are unmanaged appear available. */ + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED = (1L << 3), + + /* a collection of flags, that are commonly set for an explict user-request. */ NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER - | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP, + | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP + | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED, - NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (1L << 3) - 1, + NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (1L << 4) - 1, } NMDeviceCheckConAvailableFlags; struct _NMDevicePrivate; @@ -190,7 +210,12 @@ struct _NMDevice { typedef enum { /*< skip >*/ NM_DEVICE_CHECK_DEV_AVAILABLE_NONE = 0, + /* the device is considered available, even if it has no carrier. + * + * For various device types (software devices) we ignore carrier based + * on the type. So, for them, this flag has no effect anyway. */ _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER = (1L << 0), + NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER, NM_DEVICE_CHECK_DEV_AVAILABLE_ALL = (1L << 1) - 1, diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index 32d49916..1d1be742 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -229,7 +229,7 @@ vardict_from_network_type (const char *type) } static void -insert_ap_from_network (GHashTable *aps, GDBusProxy *proxy, const char *path, int16_t signal, uint32_t ap_id) +insert_ap_from_network (GHashTable *aps, const char *path, int16_t signal, uint32_t ap_id) { gs_unref_object GDBusProxy *network_proxy = NULL; gs_unref_variant GVariant *name_value = NULL, *type_value = NULL; @@ -239,19 +239,12 @@ insert_ap_from_network (GHashTable *aps, GDBusProxy *proxy, const char *path, in GVariant *rsn; uint8_t bssid[6]; NMWifiAP *ap; - GError *error; - - network_proxy = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (proxy), - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - NM_IWD_SERVICE, - path, - NM_IWD_NETWORK_INTERFACE, - NULL, &error); - if (!network_proxy) { - g_clear_error (&error); + + network_proxy = nm_iwd_manager_get_dbus_interface (nm_iwd_manager_get (), + path, + NM_IWD_NETWORK_INTERFACE); + if (!network_proxy) return; - } name_value = g_dbus_proxy_get_cached_property (network_proxy, "Name"); type_value = g_dbus_proxy_get_cached_property (network_proxy, "Type"); @@ -344,10 +337,10 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data) if (compat) { while (g_variant_iter_next (networks, "(&o&sn&s)", &path, &name, &signal, &type)) - insert_ap_from_network (new_aps, priv->dbus_station_proxy, path, signal, ap_id++); + insert_ap_from_network (new_aps, path, signal, ap_id++); } else { while (g_variant_iter_next (networks, "(&on)", &path, &signal)) - insert_ap_from_network (new_aps, priv->dbus_station_proxy, path, signal, ap_id++); + insert_ap_from_network (new_aps, path, signal, ap_id++); } g_variant_iter_free (networks); @@ -433,7 +426,7 @@ cleanup_association_attempt (NMDeviceIwd *self, gboolean disconnect) set_current_ap (self, NULL, TRUE); - if (disconnect && priv->dbus_obj) + if (disconnect && priv->dbus_station_proxy) send_disconnect (self); } @@ -827,13 +820,8 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { NMDeviceIwd *self = NM_DEVICE_IWD (device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - gs_unref_variant GVariant *value = NULL; - - if (!priv->enabled || !priv->dbus_obj) - return FALSE; - value = g_dbus_proxy_get_cached_property (priv->dbus_device_proxy, "Powered"); - return get_variant_boolean (value, "Powered"); + return priv->enabled && priv->dbus_station_proxy; } static gboolean @@ -970,8 +958,7 @@ dbus_request_scan_cb (NMDevice *device, priv = NM_DEVICE_IWD_GET_PRIVATE (self); - if ( !priv->enabled - || !priv->dbus_obj + if ( !priv->can_scan || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED || nm_device_is_activating (device)) { g_dbus_method_invocation_return_error_literal (context, @@ -1012,8 +999,7 @@ _nm_device_iwd_request_scan (NMDeviceIwd *self, NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); - if ( !priv->enabled - || !priv->dbus_obj + if ( !priv->can_scan || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED || nm_device_is_activating (device)) { g_dbus_method_invocation_return_error_literal (invocation, @@ -1255,12 +1241,7 @@ secrets_error: g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "NM secrets request failed"); - - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - - cleanup_association_attempt (self, TRUE); + /* Now wait for the Connect callback to update device state */ } static void @@ -1292,11 +1273,14 @@ network_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data) { NMDeviceIwd *self = user_data; NMDevice *device = NM_DEVICE (self); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); gs_free_error GError *error = NULL; NMConnection *connection; NMSettingWireless *s_wifi; GBytes *ssid; gs_free char *ssid_utf8 = NULL; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED; + GVariant *value; if (!_nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, G_VARIANT_TYPE ("()"), @@ -1311,6 +1295,12 @@ network_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data) "Activation: (wifi) Network.Connect failed: %s", error->message); + if (nm_utils_error_is_cancelled (error, TRUE)) + return; + + if (!NM_IN_SET (nm_device_get_state (device), NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_NEED_AUTH)) + return; + connection = nm_device_get_applied_connection (device); if (!connection) goto failed; @@ -1318,20 +1308,17 @@ network_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) dbus_error = g_dbus_error_get_remote_error (error); - /* If secrets were wrong, we'd be getting a net.connman.iwd.Failed */ if (nm_streq0 (dbus_error, "net.connman.iwd.Failed")) { nm_connection_clear_secrets (connection); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - } else if ( !nm_utils_error_is_cancelled (error, TRUE) - && nm_device_is_activating (device)) - goto failed; - - /* Call Disconnect to make sure IWD's autoconnect is disabled */ - cleanup_association_attempt (self, TRUE); + /* If secrets were wrong, we'd be getting a net.connman.iwd.Failed */ + reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + } else if (nm_streq0 (dbus_error, "net.connman.iwd.Aborted")) { + /* If agent call was cancelled we'd be getting a net.connman.iwd.Aborted */ + reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + } - return; + goto failed; } nm_assert (nm_device_get_state (device) == NM_DEVICE_STATE_CONFIG); @@ -1358,9 +1345,17 @@ network_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data) return; failed: - cleanup_association_attempt (self, FALSE); - nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + /* Call Disconnect to make sure IWD's autoconnect is disabled */ + cleanup_association_attempt (self, TRUE); + + nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, reason); + + value = g_dbus_proxy_get_cached_property (priv->dbus_station_proxy, "State"); + if (!priv->can_connect && nm_streq0 (get_variant_state (value), "disconnected")) { + priv->can_connect = true; + nm_device_emit_recheck_auto_activate (device); + } + g_variant_unref (value); } static void @@ -1430,7 +1425,6 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) NMActRequest *req; NMWifiAP *ap; NMConnection *connection; - GError *error = NULL; GDBusProxy *network_proxy; req = nm_device_get_act_request (device); @@ -1460,21 +1454,13 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) goto out; } - /* Locate the IWD Network object */ - network_proxy = g_dbus_proxy_new_for_bus_sync (NM_IWD_BUS_TYPE, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - NM_IWD_SERVICE, - nm_wifi_ap_get_supplicant_path (ap), - NM_IWD_NETWORK_INTERFACE, - NULL, &error); + network_proxy = nm_iwd_manager_get_dbus_interface (nm_iwd_manager_get (), + nm_wifi_ap_get_supplicant_path (ap), + NM_IWD_NETWORK_INTERFACE); if (!network_proxy) { _LOGE (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) could not get Network interface proxy for %s: %s", - nm_wifi_ap_get_supplicant_path (ap), - error->message); - g_clear_error (&error); + "Activation: (wifi) could not get Network interface proxy for %s", + nm_wifi_ap_get_supplicant_path (ap)); NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); goto out; } @@ -1575,7 +1561,7 @@ device_state_changed (NMDevice *device, * transition to DISCONNECTED because the device is now * ready to use. */ - if (priv->enabled && priv->dbus_obj) { + if (priv->enabled && priv->dbus_station_proxy) { nm_device_queue_recheck_available (device, NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); @@ -1632,10 +1618,11 @@ set_enabled (NMDevice *device, gboolean enabled) if (state != NM_DEVICE_STATE_UNAVAILABLE) _LOGW (LOGD_CORE, "not in expected unavailable state!"); - if (priv->dbus_obj) + if (priv->dbus_station_proxy) { nm_device_queue_recheck_available (device, NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + } } else { nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE, @@ -1753,13 +1740,6 @@ state_changed (NMDeviceIwd *self, const char *new_state) /* Don't allow scanning while connecting, disconnecting or roaming */ priv->can_scan = NM_IN_STRSET (new_state, "connected", "disconnected"); - /* Don't allow new connection until iwd exits disconnecting */ - can_connect = NM_IN_STRSET (new_state, "disconnected"); - if (can_connect != priv->can_connect) { - priv->can_connect = can_connect; - nm_device_emit_recheck_auto_activate (device); - } - if (NM_IN_STRSET (new_state, "connecting", "connected", "roaming")) { /* If we were connecting, do nothing, the confirmation of * a connection success is handled in the Device.Connect @@ -1773,40 +1753,39 @@ state_changed (NMDeviceIwd *self, const char *new_state) _LOGW (LOGD_DEVICE | LOGD_WIFI, "Unsolicited connection success, asking IWD to disconnect"); send_disconnect (self); - - return; } else if (NM_IN_STRSET (new_state, "disconnecting", "disconnected")) { - if (!iwd_connection) - return; - /* Call Disconnect on the IWD device object to make sure it * disables its own autoconnect. - * - * Note we could instead call net.connman.iwd.KnownNetworks.ForgetNetwork - * and leave the device in autoconnect. This way if NetworkManager - * changes any settings for this connection, they'd be taken into - * account on the next connection attempt. But both methods are - * a hack, we'll perhaps need an IWD API to "connect once" without - * storing anything. */ send_disconnect (self); /* - * If IWD is still handling the Connect call, let our callback - * for the dbus method handle the failure. + * If IWD is still handling the Connect call, let our Connect + * callback for the dbus method handle the failure. The main + * reason we can't handle the failure here is because the method + * callback will have more information on the specific failure + * reason. */ if (dev_state == NM_DEVICE_STATE_CONFIG) return; - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - - return; - } else if (nm_streq (new_state, "unknown")) + if (iwd_connection) + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + } else if (!nm_streq (new_state, "unknown")) { + _LOGE (LOGD_WIFI, "State %s unknown", new_state); return; + } - _LOGE (LOGD_WIFI, "State %s unknown", new_state); + /* Don't allow new connection until iwd exits disconnecting and no + * Connect callback is pending. + */ + can_connect = NM_IN_STRSET (new_state, "disconnected"); + if (can_connect != priv->can_connect) { + priv->can_connect = can_connect; + nm_device_emit_recheck_auto_activate (device); + } } static void @@ -1856,9 +1835,72 @@ station_properties_changed (GDBusProxy *proxy, GVariant *changed_properties, static void powered_changed (NMDeviceIwd *self, gboolean new_powered) { + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); + nm_device_queue_recheck_available (NM_DEVICE (self), NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + + if (new_powered) { + GDBusInterface *interface; + GVariant *value; + + if (priv->dbus_station_proxy) + return; + + interface = g_dbus_object_get_interface (priv->dbus_obj, NM_IWD_STATION_INTERFACE); + if (!interface) { + /* No Station interface on the device object. Check if the + * "State" property is present on the Device interface, that + * would mean we're dealing with an IWD version from before the + * Device/Station split (0.7 or earlier) and we can easily + * handle that by making priv->dbus_device_proxy and + * priv->dbus_station_proxy both point at the Device interface. + */ + value = g_dbus_proxy_get_cached_property (priv->dbus_device_proxy, "State"); + if (!value) { + _LOGE (LOGD_WIFI, "Interface %s not found on obj %s", + NM_IWD_STATION_INTERFACE, + g_dbus_object_get_object_path (priv->dbus_obj)); + return; + } + + g_variant_unref (value); + interface = g_object_ref (priv->dbus_device_proxy); + } + + priv->dbus_station_proxy = G_DBUS_PROXY (interface); + + value = g_dbus_proxy_get_cached_property (priv->dbus_station_proxy, "Scanning"); + priv->scanning = get_variant_boolean (value, "Scanning"); + g_variant_unref (value); + + value = g_dbus_proxy_get_cached_property (priv->dbus_station_proxy, "State"); + state_changed (self, get_variant_state (value)); + g_variant_unref (value); + + g_signal_connect (priv->dbus_station_proxy, "g-properties-changed", + G_CALLBACK (station_properties_changed), self); + + /* Call Disconnect to make sure IWD's autoconnect is disabled. + * Autoconnect is the default state after device is brought UP. + */ + if (priv->enabled) + send_disconnect (self); + } else { + if (!priv->dbus_station_proxy) + return; + + g_signal_handlers_disconnect_by_func (priv->dbus_station_proxy, + station_properties_changed, self); + g_clear_object (&priv->dbus_station_proxy); + + priv->can_scan = FALSE; + priv->scanning = FALSE; + priv->scan_requested = FALSE; + priv->can_connect = FALSE; + cleanup_association_attempt (self, FALSE); + } } static void @@ -1887,37 +1929,35 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object) NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); GDBusInterface *interface; GVariant *value; + gboolean powered; if (!nm_g_object_ref_set ((GObject **) &priv->dbus_obj, (GObject *) object)) return; + if (priv->enabled && priv->dbus_station_proxy) { + nm_device_queue_recheck_available (NM_DEVICE (self), + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + } + if (priv->dbus_device_proxy) { g_signal_handlers_disconnect_by_func (priv->dbus_device_proxy, device_properties_changed, self); g_clear_object (&priv->dbus_device_proxy); - g_signal_handlers_disconnect_by_func (priv->dbus_station_proxy, - station_properties_changed, self); - g_clear_object (&priv->dbus_station_proxy); - } - - if (priv->enabled) - nm_device_queue_recheck_available (NM_DEVICE (self), - NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - if (!object) { - priv->can_scan = FALSE; + powered_changed (self, FALSE); + } - cleanup_association_attempt (self, FALSE); + if (!object) return; - } interface = g_dbus_object_get_interface (object, NM_IWD_DEVICE_INTERFACE); if (!interface) { _LOGE (LOGD_WIFI, "Interface %s not found on obj %s", NM_IWD_DEVICE_INTERFACE, g_dbus_object_get_object_path (object)); - goto error; + g_clear_object (&priv->dbus_obj); + return; } priv->dbus_device_proxy = G_DBUS_PROXY (interface); @@ -1925,60 +1965,14 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object) g_signal_connect (priv->dbus_device_proxy, "g-properties-changed", G_CALLBACK (device_properties_changed), self); - interface = g_dbus_object_get_interface (object, NM_IWD_STATION_INTERFACE); - if (!interface) { - /* No Station interface on the device object. Check if the - * "State" property is present on the Device interface, that - * would mean we're dealing with an IWD version from before the - * Device/Station split (0.7 or earlier) and we can easily - * handle that by making priv->dbus_device_proxy and - * priv->dbus_station_proxy both point at the Device interface. - * - * TODO: handle device in a mode initially other than station - * -- also means the Station interface won't be there. - */ - value = g_dbus_proxy_get_cached_property (priv->dbus_device_proxy, "State"); - g_variant_unref (value); - if (!value) { - _LOGE (LOGD_WIFI, "Interface %s not found on obj %s", - NM_IWD_STATION_INTERFACE, - g_dbus_object_get_object_path (object)); - goto error; - } - - interface = g_object_ref (priv->dbus_device_proxy); - } - - priv->dbus_station_proxy = G_DBUS_PROXY (interface); - - value = g_dbus_proxy_get_cached_property (priv->dbus_station_proxy, "Scanning"); - priv->scanning = get_variant_boolean (value, "Scanning"); - g_variant_unref (value); - priv->scan_requested = FALSE; - - value = g_dbus_proxy_get_cached_property (priv->dbus_station_proxy, "State"); - state_changed (self, get_variant_state (value)); + value = g_dbus_proxy_get_cached_property (priv->dbus_device_proxy, "Powered"); + powered = get_variant_boolean (value, "Powered"); g_variant_unref (value); - g_signal_connect (priv->dbus_station_proxy, "g-properties-changed", - G_CALLBACK (station_properties_changed), self); - - set_powered (self, priv->enabled); - - /* Call Disconnect to make sure IWD's autoconnect is disabled. - * Autoconnect is the default state after device is brought UP. - */ - if (priv->enabled) - send_disconnect (self); - - return; -error: - g_clear_object (&priv->dbus_obj); - if (priv->dbus_device_proxy) { - g_signal_handlers_disconnect_by_func (priv->dbus_device_proxy, - device_properties_changed, self); - g_clear_object (&priv->dbus_device_proxy); - } + if (powered != priv->enabled) + set_powered (self, priv->enabled); + else if (powered) + powered_changed (self, TRUE); } gboolean diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 6f833635..9ae81139 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -279,7 +279,7 @@ companion_state_changed_cb (NMDeviceWifi *companion, } static gboolean -companion_scan_prohibited_cb (NMDeviceWifi *companion, gpointer user_data) +companion_scan_prohibited_cb (NMDeviceWifi *companion, gboolean periodic, gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); @@ -346,7 +346,7 @@ device_added_cb (NMManager *manager, NMDevice *other, gpointer user_data) nm_device_queue_recheck_available (NM_DEVICE (self), NM_DEVICE_STATE_REASON_NONE, NM_DEVICE_STATE_REASON_NONE); - nm_device_remove_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_COMPANION, TRUE); + nm_device_remove_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_COMPANION, FALSE); } } diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index ec1150bb..2ce84618 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -96,6 +96,7 @@ typedef struct { bool requested_scan:1; bool ssid_found:1; bool is_scanning:1; + bool hidden_probe_scan_warn:1; gint64 last_scan; /* milliseconds */ gint32 scheduled_scan_time; /* seconds */ @@ -1349,8 +1350,17 @@ request_wireless_scan (NMDeviceWifi *self, _LOGD (LOGD_WIFI, "wifi-scan: scanning requested"); - if (!ssids) - ssids = hidden_ssids = build_hidden_probe_list (self); + if (!ssids) { + hidden_ssids = build_hidden_probe_list (self); + if (hidden_ssids) { + if (priv->hidden_probe_scan_warn) { + priv->hidden_probe_scan_warn = FALSE; + _LOGW (LOGD_WIFI, "wifi-scan: active scanning for networks due to profiles with wifi.hidden=yes. This makes you trackable"); + } + ssids = hidden_ssids; + } else + priv->hidden_probe_scan_warn = TRUE; + } if (_LOGD_ENABLED (LOGD_WIFI)) { if (ssids) { @@ -3244,6 +3254,7 @@ nm_device_wifi_init (NMDeviceWifi *self) c_list_init (&priv->aps_lst_head); + priv->hidden_probe_scan_warn = TRUE; priv->mode = NM_802_11_MODE_INFRA; priv->wowlan_restore = NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; } diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c index 1f28d263..a3da9791 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/devices/wifi/nm-iwd-manager.c @@ -430,7 +430,16 @@ mirror_8021x_connection (NMIwdManager *self, NULL)); nm_connection_add_setting (connection, setting); - setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_802_1X, NULL)); + /* "password" and "private-key-password" may be requested by the IWD agent + * from NM and IWD will implement a specific secret cache policy so by + * default respect that policy and don't save copies of those secrets in + * NM settings. The saved values can not be used anyway because of our + * use of NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW. + */ + setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_802_1X, + NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED, + NULL)); nm_setting_802_1x_add_eap_method (NM_SETTING_802_1X (setting), "external"); nm_connection_add_setting (connection, setting); @@ -786,6 +795,21 @@ nm_iwd_manager_is_known_network (NMIwdManager *self, const char *name, return g_hash_table_contains (priv->known_networks, &kn_id); } +GDBusProxy * +nm_iwd_manager_get_dbus_interface (NMIwdManager *self, const char *path, + const char *name) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); + GDBusInterface *interface; + + if (!priv->object_manager) + return NULL; + + interface = g_dbus_object_manager_get_interface (priv->object_manager, path, name); + + return interface ? G_DBUS_PROXY (interface) : NULL; +} + /*****************************************************************************/ NM_DEFINE_SINGLETON_GETTER (NMIwdManager, nm_iwd_manager_get, diff --git a/src/devices/wifi/nm-iwd-manager.h b/src/devices/wifi/nm-iwd-manager.h index cf0e7262..57b7007a 100644 --- a/src/devices/wifi/nm-iwd-manager.h +++ b/src/devices/wifi/nm-iwd-manager.h @@ -57,4 +57,7 @@ NMIwdManager *nm_iwd_manager_get (void); gboolean nm_iwd_manager_is_known_network (NMIwdManager *self, const char *name, NMIwdNetworkSecurity security); +GDBusProxy *nm_iwd_manager_get_dbus_interface (NMIwdManager *self, const char *path, + const char *name); + #endif /* __NETWORKMANAGER_IWD_MANAGER_H__ */ diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 253574d5..04cb8599 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -1063,7 +1063,7 @@ stage3_ip6_done (NMModemBroadband *self) /* DNS servers */ dns = mm_bearer_ip_config_get_dns (self->_priv.ipv6_config); - for (i = 0; dns[i]; i++) { + for (i = 0; dns && dns[i]; i++) { struct in6_addr addr; if (inet_pton (AF_INET6, dns[i], &addr)) { |