diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/bluetooth/nm-device-bt.c | 3 | ||||
| -rw-r--r-- | src/devices/nm-acd-manager.c | 10 | ||||
| -rw-r--r-- | src/devices/nm-device-ethernet.c | 126 | ||||
| -rw-r--r-- | src/devices/nm-device-macvlan.c | 9 | ||||
| -rw-r--r-- | src/devices/wifi/nm-iwd-manager.c | 20 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.c | 43 | ||||
| -rw-r--r-- | src/dhcp/tests/test-dhcp-dhclient.c | 19 | ||||
| -rw-r--r-- | src/initrd/nmi-cmdline-reader.c | 52 | ||||
| -rw-r--r-- | src/initrd/tests/test-cmdline-reader.c | 86 | ||||
| -rw-r--r-- | src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 5 | ||||
| -rw-r--r-- | src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 5 | ||||
| -rw-r--r-- | src/supplicant/nm-supplicant-config.c | 4 | ||||
| -rw-r--r-- | src/supplicant/nm-supplicant-interface.c | 48 | ||||
| -rw-r--r-- | src/supplicant/nm-supplicant-interface.h | 11 | ||||
| -rw-r--r-- | src/supplicant/tests/test-supplicant-config.c | 1 |
15 files changed, 373 insertions, 69 deletions
diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index 0853c926..f8626011 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -550,6 +550,9 @@ ip_ifindex_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); + if (!nm_device_is_activating (device)) + return; + if (!nm_device_set_ip_ifindex (device, nm_modem_get_ip_ifindex (modem))) { nm_device_state_changed (device, diff --git a/src/devices/nm-acd-manager.c b/src/devices/nm-acd-manager.c index aca7ffd2..036c4709 100644 --- a/src/devices/nm-acd-manager.c +++ b/src/devices/nm-acd-manager.c @@ -344,6 +344,8 @@ nm_acd_manager_start_probe (NMAcdManager *self, guint timeout) if (success) self->state = STATE_PROBING; + nm_assert (!self->channel); + nm_assert (self->event_id == 0); n_acd_get_fd (self->acd, &fd); self->channel = g_io_channel_unix_new (fd); self->event_id = g_io_add_watch (self->channel, G_IO_IN, acd_event, self); @@ -389,6 +391,7 @@ nm_acd_manager_announce_addresses (NMAcdManager *self) GHashTableIter iter; AddressInfo *info; int r; + int fd; gboolean success = TRUE; r = acd_init (self); @@ -428,6 +431,13 @@ nm_acd_manager_announce_addresses (NMAcdManager *self) } } + if (!self->channel) { + nm_assert (self->event_id == 0); + n_acd_get_fd (self->acd, &fd); + self->channel = g_io_channel_unix_new (fd); + self->event_id = g_io_add_watch (self->channel, G_IO_IN, acd_event, self); + } + return success ? 0 : -NME_UNSPEC; } diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 3e84847e..8571e526 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -65,6 +65,7 @@ typedef struct Supplicant { /* signal handler ids */ gulong iface_state_id; + gulong auth_state_id; /* Timeouts and idles */ guint con_timeout_id; @@ -415,6 +416,7 @@ supplicant_interface_release (NMDeviceEthernet *self) nm_clear_g_source (&priv->supplicant_timeout_id); nm_clear_g_source (&priv->supplicant.con_timeout_id); nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id); + nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.auth_state_id); if (priv->supplicant.iface) { nm_supplicant_interface_disconnect (priv->supplicant.iface); @@ -423,6 +425,62 @@ supplicant_interface_release (NMDeviceEthernet *self) } static void +supplicant_auth_state_changed (NMSupplicantInterface *iface, + GParamSpec *pspec, + NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMSupplicantAuthState state; + + state = nm_supplicant_interface_get_auth_state (priv->supplicant.iface); + _LOGD (LOGD_CORE, "supplicant auth state changed to %u", (unsigned) state); + + if (state == NM_SUPPLICANT_AUTH_STATE_SUCCESS) { + nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id); + nm_device_update_dynamic_ip_setup (NM_DEVICE (self)); + } +} + +static gboolean +wired_auth_is_optional (NMDeviceEthernet *self) +{ + NMSetting8021x *s_8021x; + + s_8021x = nm_device_get_applied_setting (NM_DEVICE (self), NM_TYPE_SETTING_802_1X); + g_return_val_if_fail (s_8021x, FALSE); + return nm_setting_802_1x_get_optional (s_8021x); +} + +static void +wired_auth_cond_fail (NMDeviceEthernet *self, NMDeviceStateReason reason) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + + if (wired_auth_is_optional (self)) { + _LOGI (LOGD_DEVICE | LOGD_ETHER, + "Activation: (ethernet) 802.1X authentication is optional, continuing after a failure"); + if (NM_IN_SET (nm_device_get_state (device), + NM_DEVICE_STATE_CONFIG, + NM_DEVICE_STATE_NEED_AUTH)) + nm_device_activate_schedule_stage3_ip_config_start (device); + + if (!priv->supplicant.auth_state_id) { + priv->supplicant.auth_state_id = g_signal_connect (priv->supplicant.iface, + "notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE, + G_CALLBACK (supplicant_auth_state_changed), + self); + } + return; + } + + supplicant_interface_release (self); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + reason); +} + +static void wired_secrets_cb (NMActRequest *req, NMActRequestGetSecretsCallId *call_id, NMSettingsConnection *connection, @@ -451,11 +509,12 @@ wired_secrets_cb (NMActRequest *req, if (error) { _LOGW (LOGD_ETHER, "%s", error->message); - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - } else - nm_device_activate_schedule_stage1_device_prepare (device); + wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_NO_SECRETS); + return; + } + + supplicant_interface_release (self); + nm_device_activate_schedule_stage1_device_prepare (device); } static void @@ -496,19 +555,17 @@ link_timeout_cb (gpointer user_data) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMDevice *dev = NM_DEVICE (self); + NMDevice *device = NM_DEVICE (self); NMActRequest *req; NMConnection *applied_connection; const char *setting_name; priv->supplicant_timeout_id = 0; - req = nm_device_get_act_request (dev); + req = nm_device_get_act_request (device); - if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { - nm_device_state_changed (dev, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); + if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) { + wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); return FALSE; } @@ -516,7 +573,7 @@ link_timeout_cb (gpointer user_data) * ARE checked - we are likely to have wrong key. Ask the user for * another one. */ - if (nm_device_get_state (dev) != NM_DEVICE_STATE_CONFIG) + if (nm_device_get_state (device) != NM_DEVICE_STATE_CONFIG) goto time_out; nm_active_connection_clear_secrets (NM_ACTIVE_CONNECTION (req)); @@ -528,16 +585,17 @@ link_timeout_cb (gpointer user_data) _LOGI (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) disconnected during authentication, asking for new key."); - supplicant_interface_release (self); + if (!wired_auth_is_optional (self)) + supplicant_interface_release (self); - nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); wired_secrets_get_secrets (self, setting_name, NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW); return FALSE; time_out: _LOGW (LOGD_DEVICE | LOGD_ETHER, "link timed out."); - nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); return FALSE; } @@ -652,11 +710,8 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, case NM_SUPPLICANT_INTERFACE_STATE_DOWN: supplicant_interface_release (self); - if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } + if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) + wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); break; default: break; @@ -685,6 +740,15 @@ handle_auth_or_fail (NMDeviceEthernet *self, return NM_ACT_STAGE_RETURN_FAILURE; } + _LOGI (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) asking for new secrets"); + + /* Don't tear down supplicant if the authentication is optional + * because in case of a failure in getting new secrets we want to + * keep the supplicant alive. + */ + if (!wired_auth_is_optional (self)) + supplicant_interface_release (self); + wired_secrets_get_secrets (self, setting_name, NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); @@ -710,12 +774,8 @@ supplicant_connection_timeout_cb (gpointer user_data) _LOGW (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) association took too long."); - supplicant_interface_release (self); req = nm_device_get_act_request (device); - g_assert (req); - connection = nm_act_request_get_settings_connection (req); - g_assert (connection); /* Ask for new secrets only if we've never activated this connection * before. If we've connected before, don't bother the user with dialogs, @@ -724,10 +784,8 @@ supplicant_connection_timeout_cb (gpointer user_data) if (nm_settings_connection_get_timestamp (connection, ×tamp)) new_secrets = !timestamp; - if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) - _LOGW (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) asking for new secrets"); - else - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); + if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_FAILURE) + wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_NO_SECRETS); return FALSE; } @@ -850,19 +908,19 @@ pppoe_reconnect_delay (gpointer user_data) } static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMActStageReturn ret; - ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, out_failure_reason); + ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - link_negotiation_set (dev); + link_negotiation_set (device); - if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE)) + if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) return NM_ACT_STAGE_RETURN_FAILURE; /* If we're re-activating a PPPoE connection a short while after @@ -874,7 +932,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) gint32 delay = nm_utils_get_monotonic_timestamp_s () - priv->last_pppoe_time; if ( delay < PPPOE_RECONNECT_DELAY - && nm_device_get_applied_setting (dev, NM_TYPE_SETTING_PPPOE)) { + && nm_device_get_applied_setting (device, NM_TYPE_SETTING_PPPOE)) { _LOGI (LOGD_DEVICE, "delaying PPPoE reconnect for %d seconds to ensure peer is ready...", delay); g_assert (!priv->pppoe_wait_id); diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 709f98da..ee8b9974 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -270,7 +270,7 @@ create_and_realize (NMDevice *device, /*****************************************************************************/ static NMDeviceCapabilities -get_generic_capabilities (NMDevice *dev) +get_generic_capabilities (NMDevice *device) { /* We assume MACVLAN interfaces always support carrier detect */ return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE; @@ -416,16 +416,17 @@ update_connection (NMDevice *device, NMConnection *connection) } static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMActStageReturn ret; - ret = NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->act_stage1_prepare (dev, out_failure_reason); + ret = NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE)) + if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) return NM_ACT_STAGE_RETURN_FAILURE; + return NM_ACT_STAGE_RETURN_SUCCESS; } diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c index 5b550ea4..c79f6cc6 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/devices/wifi/nm-iwd-manager.c @@ -150,6 +150,11 @@ agent_dbus_method_cb (GDBusConnection *connection, network = g_dbus_object_manager_get_interface (priv->object_manager, network_path, NM_IWD_NETWORK_INTERFACE); + if (!network) { + _LOGE ("unable to find the network object"); + return; + } + device_path = get_property_string_or_null (G_DBUS_PROXY (network), "Device"); if (!device_path) { @@ -271,9 +276,22 @@ register_agent (NMIwdManager *self) GDBusInterface *agent_manager; agent_manager = g_dbus_object_manager_get_interface (priv->object_manager, - "/", + "/net/connman/iwd", NM_IWD_AGENT_MANAGER_INTERFACE); + if (!agent_manager) { + /* IWD prior to 1.0 dated 30 October, 2019 has the agent manager on a + * different path. */ + agent_manager = g_dbus_object_manager_get_interface (priv->object_manager, + "/", + NM_IWD_AGENT_MANAGER_INTERFACE); + } + + if (!agent_manager) { + _LOGE ("unable to register the IWD Agent: PSK/8021x Wi-Fi networks may not work"); + return; + } + /* Register our agent */ g_dbus_proxy_call (G_DBUS_PROXY (agent_manager), "RegisterAgent", diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c index bf3df399..98f8c13a 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/dhcp/nm-dhcp-dhclient-utils.c @@ -304,11 +304,13 @@ nm_dhcp_dhclient_create_config (const char *interface, if (orig_contents) { gs_free const char **lines = NULL; gsize line_i; - int nest = 0; + nm_auto_free_gstring GString *blocks_stack = NULL; + guint blocks_skip = 0; gboolean in_alsoreq = FALSE; gboolean in_req = FALSE; char intf[IFNAMSIZ]; + blocks_stack = g_string_new (NULL); g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path); intf[0] = '\0'; @@ -326,19 +328,38 @@ nm_dhcp_dhclient_create_config (const char *interface, if (in_req) { /* pass */ } else if (strchr (p, '{')) { - nest++; - if ( !intf[0] - && NM_STR_HAS_PREFIX (p, "interface")) - if (read_interface (p, intf, sizeof (intf))) - continue; + if ( NM_STR_HAS_PREFIX (p, "lease") + || NM_STR_HAS_PREFIX (p, "alias") + || NM_STR_HAS_PREFIX (p, "interface") + || NM_STR_HAS_PREFIX (p, "pseudo")) { + /* skip over these blocks, except 'interface' when it + * matches the current interface */ + blocks_skip++; + g_string_append_c (blocks_stack, 'b'); + if ( !intf[0] + && NM_STR_HAS_PREFIX (p, "interface")) { + if (read_interface (p, intf, sizeof (intf))) + continue; + } + } else { + /* allow other blocks (conditionals) */ + if (!strchr (p, '}')) /* '} else {' */ + g_string_append_c (blocks_stack, 'c'); + } } else if (strchr (p, '}')) { - if (nest) - nest--; - intf[0] = '\0'; - continue; + if (blocks_stack->len > 0) { + if (blocks_stack->str[blocks_stack->len - 1] == 'b') { + g_string_truncate (blocks_stack, blocks_stack->len - 1); + nm_assert(blocks_skip > 0); + blocks_skip--; + intf[0] = '\0'; + continue; + } + g_string_truncate (blocks_stack, blocks_stack->len - 1); + } } - if (nest && !intf[0]) + if (blocks_skip > 0 && !intf[0]) continue; if (intf[0] && !nm_streq (intf, interface)) diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c index 2cc7e5ca..9e51fceb 100644 --- a/src/dhcp/tests/test-dhcp-dhclient.c +++ b/src/dhcp/tests/test-dhcp-dhclient.c @@ -996,6 +996,11 @@ test_structured (void) " request subnet-mask, broadcast-address, time-offset, routers,\n" " domain-search, domain-name, domain-name-servers, host-name;\n" " require subnet-mask, domain-name-servers;\n" + " if not option domain-name = \"example.org\" {\n" + " prepend domain-name-servers 127.0.0.1;\n" + " } else {\n" + " prepend domain-name-servers 127.0.0.2;\n" + " } \n" " } \n" "\n" "pseudo \"secondary\" \"eth0\" { \n" @@ -1022,7 +1027,13 @@ test_structured (void) " interface \"eth0\";\n" " fixed-address 192.0.2.2;\n" " option subnet-mask 255.255.255.0;\n" - " } \n"; + " } \n" + "if not option domain-name = \"example.org\" {\n" + " prepend domain-name-servers 127.0.0.1;\n" + " if not option domain-name = \"useless.example.com\" {\n" + " prepend domain-name-servers 127.0.0.2;\n" + " }\n" + "}\n"; static const char *const expected = \ "# Created by NetworkManager\n" @@ -1033,6 +1044,12 @@ test_structured (void) "send dhcp-client-identifier \"sad-and-useless\";\n" "send dhcp-lease-time 8086;\n" "require subnet-mask;\n" + "if not option domain-name = \"example.org\" {\n" + "prepend domain-name-servers 127.0.0.1;\n" + "if not option domain-name = \"useless.example.com\" {\n" + "prepend domain-name-servers 127.0.0.2;\n" + "}\n" + "}\n" "\n" "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 8ae6aa36..b90ee203 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -690,21 +690,57 @@ parse_rd_peerdns (GHashTable *connections, char *argument) } static void -parse_rd_znet (GHashTable *connections, char *argument) +parse_rd_znet (GHashTable *connections, char *argument, gboolean net_ifnames) { const char *nettype; const char *subchannels[4] = { 0, 0, 0, 0 }; const char *tmp; + gs_free char *ifname = NULL; + const char *prefix; NMConnection *connection; NMSettingWired *s_wired; + static int count_ctc = 0; + static int count_eth = 0; + int index; nettype = get_word (&argument, ','); subchannels[0] = get_word (&argument, ','); subchannels[1] = get_word (&argument, ','); - if (!nm_streq0 (nettype, "ctc")) + + if (nm_streq0 (nettype, "ctc")) { + if (net_ifnames == TRUE) { + prefix = "sl"; + } else { + prefix = "ctc"; + index = count_ctc++; + } + } else { subchannels[2] = get_word (&argument, ','); + if (net_ifnames == TRUE) { + prefix = "en"; + } else { + prefix = "eth"; + index = count_eth++; + } + } + + if (net_ifnames == TRUE) { + const char *bus_id; + size_t bus_id_len; + size_t bus_id_start; - connection = get_conn (connections, NULL, NM_SETTING_WIRED_SETTING_NAME); + /* The following logic is taken from names_ccw() in systemd/src/udev/udev-builtin-net_id.c */ + bus_id = subchannels[0]; + bus_id_len = strlen (bus_id); + bus_id_start = strspn (bus_id, ".0"); + bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1; + + ifname = g_strdup_printf ("%sc%s", prefix, bus_id); + } else { + ifname = g_strdup_printf ("%s%d", prefix, index); + } + + connection = get_conn (connections, ifname, NM_SETTING_WIRED_SETTING_NAME); s_wired = nm_connection_get_setting_wired (connection); g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, nettype, @@ -742,11 +778,19 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) gboolean ignore_bootif = FALSE; gboolean neednet = FALSE; gs_free char *bootif_val = NULL; + gboolean net_ifnames = TRUE; int i; connections = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref); for (i = 0; argv[i]; i++) { + if (strcmp (argv[i], "net.ifnames=0") == 0) + net_ifnames = FALSE; + else if (g_str_has_prefix (argv[i], "net.ifnames=")) + net_ifnames = TRUE; + } + + for (i = 0; argv[i]; i++) { gs_free char *argument_clone = NULL; char *argument; @@ -777,7 +821,7 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) else if (strcmp (tag, "rd.neednet") == 0) neednet = _nm_utils_ascii_str_to_bool (argument, TRUE); else if (strcmp (tag, "rd.znet") == 0) - parse_rd_znet (connections, argument); + parse_rd_znet (connections, argument, net_ifnames); else if (strcasecmp (tag, "BOOTIF") == 0) { nm_clear_g_free (&bootif_val); bootif_val = g_strdup (argument); diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index a8a6e825..5ac82f50 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -801,9 +801,10 @@ test_rd_znet (void) { gs_unref_hashtable GHashTable *connections = NULL; const char *const*const ARGV = NM_MAKE_STRV ("ip=10.11.12.13::10.11.12.1:24:foo.example.com:enc800:none", - "rd.znet=ctc,0.0.0800,0.0.0801,layer2=0,portno=1"); - GHashTableIter h_iter; + "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1", + "rd.znet=ctc,0.0.0600,0.0.0601,layer2=0,portno=0"); NMConnection *connection; + NMSettingConnection *s_con; NMSettingWired *s_wired; const char *const*v_subchannels; const NMUtilsNamedValue s390_options[] = { @@ -814,15 +815,17 @@ test_rd_znet (void) connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); g_assert (connections); - g_assert_cmpint (g_hash_table_size (connections), ==, 1); - - g_hash_table_iter_init (&h_iter, connections); - if (!g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &connection)) - g_assert_not_reached (); - if (g_hash_table_iter_next (&h_iter, NULL, NULL)) - g_assert_not_reached (); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); + connection = g_hash_table_lookup (connections, "enc800"); g_assert (NM_IS_CONNECTION (connection)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (NM_IS_SETTING_CONNECTION (s_con)); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "enc800"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "enc800"); + s_wired = nm_connection_get_setting_wired (connection); g_assert (NM_IS_SETTING_WIRED (s_wired)); @@ -830,7 +833,8 @@ test_rd_znet (void) g_assert (v_subchannels); g_assert_cmpstr (v_subchannels[0], ==, "0.0.0800"); g_assert_cmpstr (v_subchannels[1], ==, "0.0.0801"); - g_assert_cmpstr (v_subchannels[2], ==, NULL); + g_assert_cmpstr (v_subchannels[2], ==, "0.0.0802"); + g_assert_cmpstr (v_subchannels[3], ==, NULL); g_assert_cmpint (nm_setting_wired_get_num_s390_options (s_wired), ==, G_N_ELEMENTS (s390_options)); for (i_s390_options_keys = 0; i_s390_options_keys < G_N_ELEMENTS (s390_options); i_s390_options_keys++) { @@ -853,8 +857,67 @@ test_rd_znet (void) } nmtst_assert_connection_verifies_without_normalization (connection); + + connection = g_hash_table_lookup (connections, "slc600"); + g_assert (NM_IS_CONNECTION (connection)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (NM_IS_SETTING_CONNECTION (s_con)); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "slc600"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "slc600"); + + s_wired = nm_connection_get_setting_wired (connection); + g_assert (NM_IS_SETTING_WIRED (s_wired)); + + v_subchannels = nm_setting_wired_get_s390_subchannels (s_wired); + g_assert (v_subchannels); + g_assert_cmpstr (v_subchannels[0], ==, "0.0.0600"); + g_assert_cmpstr (v_subchannels[1], ==, "0.0.0601"); + g_assert_cmpstr (v_subchannels[2], ==, NULL); + + nmtst_assert_connection_verifies_without_normalization (connection); } +static void +test_rd_znet_legacy (void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const*const ARGV = NM_MAKE_STRV ("ip=10.11.12.13::10.11.12.1:24:foo.example.com:eth0:none", + "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1", + "rd.znet=ctc,0.0.0600,0.0.0601,layer2=0,portno=0", + "net.ifnames=0"); + NMConnection *connection; + NMSettingConnection *s_con; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); + + connection = g_hash_table_lookup (connections, "eth0"); + g_assert (NM_IS_CONNECTION (connection)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (NM_IS_SETTING_CONNECTION (s_con)); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth0"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "eth0"); + + nmtst_assert_connection_verifies_without_normalization (connection); + + connection = g_hash_table_lookup (connections, "ctc0"); + g_assert (NM_IS_CONNECTION (connection)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (NM_IS_SETTING_CONNECTION (s_con)); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "ctc0"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "ctc0"); + + nmtst_assert_connection_verifies_without_normalization (connection); +} + + NMTST_DEFINE (); int main (int argc, char **argv) @@ -877,7 +940,8 @@ int main (int argc, char **argv) g_test_add_func ("/initrd/cmdline/bridge/default", test_bridge_default); g_test_add_func ("/initrd/cmdline/ibft", test_ibft); g_test_add_func ("/initrd/cmdline/ignore_extra", test_ignore_extra); - g_test_add_func ("/initrd/cmdline/rd_zdnet", test_rd_znet); + g_test_add_func ("/initrd/cmdline/rd_znet", test_rd_znet); + g_test_add_func ("/initrd/cmdline/rd_znet/legacy", test_rd_znet_legacy); return g_test_run (); } diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 9c3ae10a..020766c8 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -3604,6 +3604,11 @@ next: timeout = svGetValueInt64 (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", 10, 0, G_MAXINT32, 0); g_object_set (s_8021x, NM_SETTING_802_1X_AUTH_TIMEOUT, (int) timeout, NULL); + g_object_set (s_8021x, + NM_SETTING_802_1X_OPTIONAL, + svGetValueBoolean (ifcfg, "IEEE_8021X_OPTIONAL", FALSE), + NULL); + return g_steal_pointer (&s_8021x); } diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 38dc5c8d..f3cd71bd 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -537,6 +537,11 @@ write_8021x_setting (NMConnection *connection, vint = nm_setting_802_1x_get_auth_timeout (s_8021x); svSetValueInt64_cond (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", vint > 0, vint); + if (nm_setting_802_1x_get_optional (s_8021x)) + svSetValueBoolean (ifcfg, "IEEE_8021X_OPTIONAL", TRUE); + else + svUnsetValue (ifcfg, "IEEE_8021X_OPTIONAL"); + if (!write_8021x_certs (s_8021x, secrets, blobs, FALSE, ifcfg, error)) return FALSE; diff --git a/src/supplicant/nm-supplicant-config.c b/src/supplicant/nm-supplicant-config.c index f6e3c7da..a5a68070 100644 --- a/src/supplicant/nm-supplicant-config.c +++ b/src/supplicant/nm-supplicant-config.c @@ -881,8 +881,8 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, } } - /* Don't try to enable PMF on non-WPA networks */ - if (!NM_IN_STRSET (key_mgmt, "wpa-eap", "wpa-psk")) + /* Don't try to enable PMF on non-WPA/SAE networks */ + if (!NM_IN_STRSET (key_mgmt, "wpa-eap", "wpa-psk", "sae")) pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE; /* Check if we actually support PMF */ diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index a54b770c..be4f65dc 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -122,6 +122,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSupplicantInterface, PROP_WFD_SUPPORT, PROP_FT_SUPPORT, PROP_SHA384_SUPPORT, + PROP_AUTH_STATE, ); typedef struct { @@ -175,6 +176,7 @@ typedef struct { gint64 last_scan; /* timestamp as returned by nm_utils_get_monotonic_timestamp_ms() */ + NMSupplicantAuthState auth_state; } NMSupplicantInterfacePrivate; struct _NMSupplicantInterface { @@ -833,6 +835,12 @@ nm_supplicant_interface_get_sha384_support (NMSupplicantInterface *self) return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->sha384_support; } +NMSupplicantAuthState +nm_supplicant_interface_get_auth_state (NMSupplicantInterface *self) +{ + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->auth_state; +} + void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self, NMSupplicantFeature ap_support) @@ -1344,6 +1352,34 @@ wpas_iface_network_request (GDBusProxy *proxy, } static void +eap_changed (GDBusProxy *proxy, + const char *status, + const char *parameter, + gpointer user_data) +{ + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + NMSupplicantAuthState auth_state = NM_SUPPLICANT_AUTH_STATE_UNKNOWN; + + if (nm_streq0 (status, "started")) + auth_state = NM_SUPPLICANT_AUTH_STATE_STARTED; + else if (nm_streq0 (status, "completion")) { + if (nm_streq0 (parameter, "success")) + auth_state = NM_SUPPLICANT_AUTH_STATE_SUCCESS; + else if (nm_streq0 (parameter, "failure")) + auth_state = NM_SUPPLICANT_AUTH_STATE_FAILURE; + } + + /* the state eventually reaches one of started, success or failure + * so ignore any other intermediate (unknown) state change. */ + if ( auth_state != NM_SUPPLICANT_AUTH_STATE_UNKNOWN + && auth_state != priv->auth_state) { + priv->auth_state = auth_state; + _notify (self, PROP_AUTH_STATE); + } +} + +static void props_changed_cb (GDBusProxy *proxy, GVariant *changed_properties, GStrv invalidated_properties, @@ -1685,6 +1721,8 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ G_CALLBACK (wpas_iface_bss_removed), self); _nm_dbus_signal_connect (priv->iface_proxy, "NetworkRequest", G_VARIANT_TYPE ("(oss)"), G_CALLBACK (wpas_iface_network_request), self); + _nm_dbus_signal_connect (priv->iface_proxy, "EAP", G_VARIANT_TYPE ("(ss)"), + G_CALLBACK (eap_changed), self); /* Scan result aging parameters */ g_dbus_proxy_call (priv->iface_proxy, @@ -2761,6 +2799,9 @@ get_property (GObject *object, case PROP_P2P_AVAILABLE: g_value_set_boolean (value, priv->p2p_capable && priv->p2p_proxy_acquired); break; + case PROP_AUTH_STATE: + g_value_set_uint (value, priv->auth_state); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3053,6 +3094,13 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_AUTH_STATE] = + g_param_spec_uint (NM_SUPPLICANT_INTERFACE_AUTH_STATE, "", "", + NM_SUPPLICANT_AUTH_STATE_UNKNOWN, + _NM_SUPPLICANT_AUTH_STATE_NUM - 1, + NM_SUPPLICANT_AUTH_STATE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/supplicant/nm-supplicant-interface.h b/src/supplicant/nm-supplicant-interface.h index 653830da..e621f1a3 100644 --- a/src/supplicant/nm-supplicant-interface.h +++ b/src/supplicant/nm-supplicant-interface.h @@ -45,6 +45,14 @@ typedef enum { NM_SUPPLICANT_INTERFACE_STATE_DOWN, } NMSupplicantInterfaceState; +typedef enum { + NM_SUPPLICANT_AUTH_STATE_UNKNOWN, + NM_SUPPLICANT_AUTH_STATE_STARTED, + NM_SUPPLICANT_AUTH_STATE_SUCCESS, + NM_SUPPLICANT_AUTH_STATE_FAILURE, + _NM_SUPPLICANT_AUTH_STATE_NUM, +} NMSupplicantAuthState; + #define NM_TYPE_SUPPLICANT_INTERFACE (nm_supplicant_interface_get_type ()) #define NM_SUPPLICANT_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterface)) #define NM_SUPPLICANT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass)) @@ -71,6 +79,7 @@ typedef enum { #define NM_SUPPLICANT_INTERFACE_WFD_SUPPORT "wfd-support" #define NM_SUPPLICANT_INTERFACE_FT_SUPPORT "ft-support" #define NM_SUPPLICANT_INTERFACE_SHA384_SUPPORT "sha384-support" +#define NM_SUPPLICANT_INTERFACE_AUTH_STATE "auth-state" /* Signals */ #define NM_SUPPLICANT_INTERFACE_STATE "state" @@ -215,4 +224,6 @@ void nm_supplicant_interface_enroll_wps (NMSupplicantInterface *self, void nm_supplicant_interface_cancel_wps (NMSupplicantInterface *self); +NMSupplicantAuthState nm_supplicant_interface_get_auth_state (NMSupplicantInterface *self); + #endif /* __NM_SUPPLICANT_INTERFACE_H__ */ diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c index 819256fb..ea9bac1e 100644 --- a/src/supplicant/tests/test-supplicant-config.c +++ b/src/supplicant/tests/test-supplicant-config.c @@ -430,7 +430,6 @@ test_wifi_sae_psk (const char *psk) NMTST_EXPECT_NM_INFO ("Config: added 'proto' value 'RSN'"); NMTST_EXPECT_NM_INFO ("Config: added 'pairwise' value 'TKIP CCMP'"); NMTST_EXPECT_NM_INFO ("Config: added 'group' value 'TKIP CCMP'"); - NMTST_EXPECT_NM_INFO ("Config: added 'ieee80211w' value '0'"); config_dict = build_supplicant_config (connection, 1500, 0, TRUE, TRUE); g_test_assert_expected_messages (); |