cli: reuse connections in nmcli dev wifi con
Try to locate an existing connection before creating a new one when handling "nmcli device wifi connect". This allows WPA-Enterprise networks to be activated this way, consistent with the comment that this command is equivalent to clicking on an SSID in a GUI client.
This commit is contained in:

committed by
Andrew Zaborowski

parent
0c70a9ef6d
commit
3593237527
@@ -847,14 +847,13 @@ usage_device_wifi (void)
|
|||||||
"ARGUMENTS := connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>]\n"
|
"ARGUMENTS := connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>]\n"
|
||||||
" [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n"
|
" [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Connect to a Wi-Fi network specified by SSID or BSSID. The command creates\n"
|
"Connect to a Wi-Fi network specified by SSID or BSSID. The command finds a\n"
|
||||||
"a new connection and then activates it on a device. This is a command-line\n"
|
"matching connection or creates one and then activates it on a device. This\n"
|
||||||
"counterpart of clicking an SSID in a GUI client. The command always creates\n"
|
"is a command-line counterpart of clicking an SSID in a GUI client. If a\n"
|
||||||
"a new connection and thus it is mainly useful for connecting to new Wi-Fi\n"
|
"connection for the network already exists, it is possible to bring up the\n"
|
||||||
"networks. If a connection for the network already exists, it is better to\n"
|
"existing profile as follows: nmcli con up id <name>. Note that only open,\n"
|
||||||
"bring up the existing profile as follows: nmcli con up id <name>. Note that\n"
|
"WEP and WPA-PSK networks are supported if no previous connection exists.\n"
|
||||||
"only open, WEP and WPA-PSK networks are supported at the moment. It is also\n"
|
"It is also assumed that IP configuration is obtained via DHCP.\n"
|
||||||
"assumed that IP configuration is obtained via DHCP.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"ARGUMENTS := hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>]\n"
|
"ARGUMENTS := hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>]\n"
|
||||||
" [band a|bg] [channel <channel>] [password <password>]\n"
|
" [band a|bg] [channel <channel>] [password <password>]\n"
|
||||||
@@ -1839,6 +1838,7 @@ typedef struct {
|
|||||||
NmCli *nmc;
|
NmCli *nmc;
|
||||||
NMDevice *device;
|
NMDevice *device;
|
||||||
gboolean hotspot;
|
gboolean hotspot;
|
||||||
|
gboolean create;
|
||||||
} AddAndActivateInfo;
|
} AddAndActivateInfo;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1853,15 +1853,21 @@ add_and_activate_cb (GObject *client,
|
|||||||
NMActiveConnection *active;
|
NMActiveConnection *active;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
active = nm_client_add_and_activate_connection_finish (NM_CLIENT (client), result, &error);
|
if (info->create)
|
||||||
|
active = nm_client_add_and_activate_connection_finish (NM_CLIENT (client), result, &error);
|
||||||
|
else
|
||||||
|
active = nm_client_activate_connection_finish (NM_CLIENT (client), result, &error);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
if (info->hotspot)
|
if (info->hotspot)
|
||||||
g_string_printf (nmc->return_text, _("Error: Failed to setup a Wi-Fi hotspot: %s"),
|
g_string_printf (nmc->return_text, _("Error: Failed to setup a Wi-Fi hotspot: %s"),
|
||||||
error->message);
|
error->message);
|
||||||
else
|
else if (info->create)
|
||||||
g_string_printf (nmc->return_text, _("Error: Failed to add/activate new connection: %s"),
|
g_string_printf (nmc->return_text, _("Error: Failed to add/activate new connection: %s"),
|
||||||
error->message);
|
error->message);
|
||||||
|
else
|
||||||
|
g_string_printf (nmc->return_text, _("Error: Failed to activate connection: %s"),
|
||||||
|
error->message);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
||||||
quit ();
|
quit ();
|
||||||
@@ -1871,8 +1877,10 @@ add_and_activate_cb (GObject *client,
|
|||||||
if (state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) {
|
if (state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) {
|
||||||
if (info->hotspot)
|
if (info->hotspot)
|
||||||
g_string_printf (nmc->return_text, _("Error: Failed to setup a Wi-Fi hotspot"));
|
g_string_printf (nmc->return_text, _("Error: Failed to setup a Wi-Fi hotspot"));
|
||||||
else
|
else if (info->create)
|
||||||
g_string_printf (nmc->return_text, _("Error: Failed to add/activate new connection: Unknown error"));
|
g_string_printf (nmc->return_text, _("Error: Failed to add/activate new connection: Unknown error"));
|
||||||
|
else
|
||||||
|
g_string_printf (nmc->return_text, _("Error: Failed to activate connection: Unknown error"));
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
||||||
g_object_unref (active);
|
g_object_unref (active);
|
||||||
quit ();
|
quit ();
|
||||||
@@ -1883,12 +1891,16 @@ add_and_activate_cb (GObject *client,
|
|||||||
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
||||||
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
||||||
nmc_terminal_erase_line ();
|
nmc_terminal_erase_line ();
|
||||||
if (!info->hotspot)
|
if (info->hotspot)
|
||||||
|
g_print (_("Hotspot '%s' activated on device '%s'\n"),
|
||||||
|
nm_active_connection_get_id (active), nm_device_get_iface (device));
|
||||||
|
else if (info->create)
|
||||||
g_print (_("Connection with UUID '%s' created and activated on device '%s'\n"),
|
g_print (_("Connection with UUID '%s' created and activated on device '%s'\n"),
|
||||||
nm_active_connection_get_uuid (active), nm_device_get_iface (device));
|
nm_active_connection_get_uuid (active), nm_device_get_iface (device));
|
||||||
else
|
else
|
||||||
g_print (_("Hotspot '%s' activated on device '%s'\n"),
|
g_print (_("Connection with ID '%s', UUID '%s' activated on device '%s'\n"),
|
||||||
nm_active_connection_get_id (active), nm_device_get_iface (device));
|
nm_active_connection_get_id (active), nm_active_connection_get_uuid (active),
|
||||||
|
nm_device_get_iface (device));
|
||||||
}
|
}
|
||||||
g_object_unref (active);
|
g_object_unref (active);
|
||||||
quit ();
|
quit ();
|
||||||
@@ -1947,6 +1959,7 @@ connect_device_cb (GObject *client, GAsyncResult *result, gpointer user_data)
|
|||||||
if (error) {
|
if (error) {
|
||||||
/* If no connection existed for the device, create one and activate it */
|
/* If no connection existed for the device, create one and activate it */
|
||||||
if (g_error_matches (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION)) {
|
if (g_error_matches (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION)) {
|
||||||
|
info->create = TRUE;
|
||||||
create_connect_connection_for_device (info);
|
create_connect_connection_for_device (info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3139,7 +3152,6 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||||||
NMConnection *connection = NULL;
|
NMConnection *connection = NULL;
|
||||||
NMSettingConnection *s_con;
|
NMSettingConnection *s_con;
|
||||||
NMSettingWireless *s_wifi;
|
NMSettingWireless *s_wifi;
|
||||||
NMSettingWirelessSecurity *s_wsec;
|
|
||||||
AddAndActivateInfo *info;
|
AddAndActivateInfo *info;
|
||||||
const char *param_user = NULL;
|
const char *param_user = NULL;
|
||||||
const char *ifname = NULL;
|
const char *ifname = NULL;
|
||||||
@@ -3155,6 +3167,10 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||||||
int devices_idx;
|
int devices_idx;
|
||||||
char *ssid_ask = NULL;
|
char *ssid_ask = NULL;
|
||||||
char *passwd_ask = NULL;
|
char *passwd_ask = NULL;
|
||||||
|
const GPtrArray *avail_cons;
|
||||||
|
gboolean name_match = FALSE;
|
||||||
|
gboolean existing_con = FALSE;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Set default timeout waiting for operation completion. */
|
/* Set default timeout waiting for operation completion. */
|
||||||
if (nmc->timeout == -1)
|
if (nmc->timeout == -1)
|
||||||
@@ -3384,45 +3400,75 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there are some connection data from user, create a connection and
|
avail_cons = nm_device_get_available_connections (device);
|
||||||
* fill them into proper settings. */
|
for (i = 0; i < avail_cons->len; i++) {
|
||||||
if (con_name || private || bssid2_arr || password || hidden)
|
NMRemoteConnection *avail_con = g_ptr_array_index (avail_cons, i);
|
||||||
connection = nm_simple_connection_new ();
|
const char *id = nm_connection_get_id (NM_CONNECTION (avail_con));
|
||||||
|
|
||||||
if (con_name || private) {
|
if (con_name) {
|
||||||
s_con = (NMSettingConnection *) nm_setting_connection_new ();
|
if (!id || strcmp (id, con_name))
|
||||||
nm_connection_add_setting (connection, NM_SETTING (s_con));
|
continue;
|
||||||
|
|
||||||
/* Set user provided connection name */
|
name_match = TRUE;
|
||||||
if (con_name)
|
}
|
||||||
g_object_set (s_con, NM_SETTING_CONNECTION_ID, con_name, NULL);
|
|
||||||
|
|
||||||
/* Connection will only be visible to this user when 'private' is specified */
|
if (nm_access_point_connection_valid (ap, NM_CONNECTION (avail_con))) {
|
||||||
if (private)
|
/* ap has been checked against bssid1, bssid2 and the ssid
|
||||||
nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL);
|
* and now avail_con has been checked against ap.
|
||||||
|
*/
|
||||||
|
connection = NM_CONNECTION (avail_con);
|
||||||
|
existing_con = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (bssid2_arr || hidden) {
|
|
||||||
s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
|
|
||||||
nm_connection_add_setting (connection, NM_SETTING (s_wifi));
|
|
||||||
|
|
||||||
/* 'bssid' parameter is used to restrict the connection only to the BSSID */
|
if (name_match && !existing_con) {
|
||||||
if (bssid2_arr)
|
g_string_printf (nmc->return_text, _("Error: Connection '%s' exists but properties don't match."), con_name);
|
||||||
g_object_set (s_wifi, NM_SETTING_WIRELESS_BSSID, bssid2_arr, NULL);
|
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
/* 'hidden' parameter is used to indicate that SSID is not broadcasted */
|
if (!existing_con) {
|
||||||
if (hidden) {
|
/* If there are some connection data from user, create a connection and
|
||||||
GBytes *ssid = g_bytes_new (param_user, strlen (param_user));
|
* fill them into proper settings. */
|
||||||
|
if (con_name || private || bssid2_arr || password || hidden)
|
||||||
|
connection = nm_simple_connection_new ();
|
||||||
|
|
||||||
g_object_set (s_wifi,
|
if (con_name || private) {
|
||||||
NM_SETTING_WIRELESS_SSID, ssid,
|
s_con = (NMSettingConnection *) nm_setting_connection_new ();
|
||||||
NM_SETTING_WIRELESS_HIDDEN, hidden,
|
nm_connection_add_setting (connection, NM_SETTING (s_con));
|
||||||
NULL);
|
|
||||||
g_bytes_unref (ssid);
|
|
||||||
|
|
||||||
/* Warn when the provided AP identifier looks like BSSID instead of SSID */
|
/* Set user provided connection name */
|
||||||
if (bssid1_arr)
|
if (con_name)
|
||||||
g_printerr (_("Warning: '%s' should be SSID for hidden APs; but it looks like a BSSID.\n"),
|
g_object_set (s_con, NM_SETTING_CONNECTION_ID, con_name, NULL);
|
||||||
param_user);
|
|
||||||
|
/* Connection will only be visible to this user when 'private' is specified */
|
||||||
|
if (private)
|
||||||
|
nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL);
|
||||||
|
}
|
||||||
|
if (bssid2_arr || hidden) {
|
||||||
|
s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
|
||||||
|
nm_connection_add_setting (connection, NM_SETTING (s_wifi));
|
||||||
|
|
||||||
|
/* 'bssid' parameter is used to restrict the connection only to the BSSID */
|
||||||
|
if (bssid2_arr)
|
||||||
|
g_object_set (s_wifi, NM_SETTING_WIRELESS_BSSID, bssid2_arr, NULL);
|
||||||
|
|
||||||
|
/* 'hidden' parameter is used to indicate that SSID is not broadcasted */
|
||||||
|
if (hidden) {
|
||||||
|
GBytes *ssid = g_bytes_new (param_user, strlen (param_user));
|
||||||
|
|
||||||
|
g_object_set (s_wifi,
|
||||||
|
NM_SETTING_WIRELESS_SSID, ssid,
|
||||||
|
NM_SETTING_WIRELESS_HIDDEN, hidden,
|
||||||
|
NULL);
|
||||||
|
g_bytes_unref (ssid);
|
||||||
|
|
||||||
|
/* Warn when the provided AP identifier looks like BSSID instead of SSID */
|
||||||
|
if (bssid1_arr)
|
||||||
|
g_printerr (_("Warning: '%s' should be SSID for hidden APs; but it looks like a BSSID.\n"),
|
||||||
|
param_user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3435,8 +3481,25 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||||||
if ( (ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
|
if ( (ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
|
||||||
|| ap_wpa_flags != NM_802_11_AP_SEC_NONE
|
|| ap_wpa_flags != NM_802_11_AP_SEC_NONE
|
||||||
|| ap_rsn_flags != NM_802_11_AP_SEC_NONE) {
|
|| ap_rsn_flags != NM_802_11_AP_SEC_NONE) {
|
||||||
|
const char *con_password = NULL;
|
||||||
|
NMSettingWirelessSecurity *s_wsec = NULL;
|
||||||
|
|
||||||
|
if (connection) {
|
||||||
|
s_wsec = nm_connection_get_setting_wireless_security (connection);
|
||||||
|
if (s_wsec) {
|
||||||
|
if (ap_wpa_flags == NM_802_11_AP_SEC_NONE && ap_rsn_flags == NM_802_11_AP_SEC_NONE) {
|
||||||
|
/* WEP */
|
||||||
|
con_password = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
|
||||||
|
} else if ( (ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
|
||||||
|
|| (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) {
|
||||||
|
/* WPA PSK */
|
||||||
|
con_password = nm_setting_wireless_security_get_psk (s_wsec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Ask for missing password when one is expected and '--ask' is used */
|
/* Ask for missing password when one is expected and '--ask' is used */
|
||||||
if (!password && nmc->ask) {
|
if (!password && !con_password && nmc->ask) {
|
||||||
password = passwd_ask = nmc_readline_echo (&nmc->nmc_config,
|
password = passwd_ask = nmc_readline_echo (&nmc->nmc_config,
|
||||||
nmc->nmc_config.show_secrets,
|
nmc->nmc_config.show_secrets,
|
||||||
_("Password: "));
|
_("Password: "));
|
||||||
@@ -3445,8 +3508,10 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||||||
if (password) {
|
if (password) {
|
||||||
if (!connection)
|
if (!connection)
|
||||||
connection = nm_simple_connection_new ();
|
connection = nm_simple_connection_new ();
|
||||||
s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
|
if (!s_wsec) {
|
||||||
nm_connection_add_setting (connection, NM_SETTING (s_wsec));
|
s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
|
||||||
|
nm_connection_add_setting (connection, NM_SETTING (s_wsec));
|
||||||
|
}
|
||||||
|
|
||||||
if (ap_wpa_flags == NM_802_11_AP_SEC_NONE && ap_rsn_flags == NM_802_11_AP_SEC_NONE) {
|
if (ap_wpa_flags == NM_802_11_AP_SEC_NONE && ap_rsn_flags == NM_802_11_AP_SEC_NONE) {
|
||||||
/* WEP */
|
/* WEP */
|
||||||
@@ -3462,7 +3527,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME: WPA-Enterprise is not supported yet.
|
// FIXME: Creating WPA-Enterprise connections is not supported yet.
|
||||||
// We are not able to determine and fill all the parameters for
|
// We are not able to determine and fill all the parameters for
|
||||||
// 802.1X authentication automatically without user providing
|
// 802.1X authentication automatically without user providing
|
||||||
// the data. Adding nmcli options for the 8021x setting would
|
// the data. Adding nmcli options for the 8021x setting would
|
||||||
@@ -3480,14 +3545,24 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
|
|||||||
info->nmc = nmc;
|
info->nmc = nmc;
|
||||||
info->device = device;
|
info->device = device;
|
||||||
info->hotspot = FALSE;
|
info->hotspot = FALSE;
|
||||||
|
info->create = !existing_con;
|
||||||
nm_client_add_and_activate_connection_async (nmc->client,
|
if (existing_con) {
|
||||||
connection,
|
nm_client_activate_connection_async (nmc->client,
|
||||||
device,
|
connection,
|
||||||
nm_object_get_path (NM_OBJECT (ap)),
|
device,
|
||||||
NULL,
|
nm_object_get_path (NM_OBJECT (ap)),
|
||||||
add_and_activate_cb,
|
NULL,
|
||||||
info);
|
add_and_activate_cb,
|
||||||
|
info);
|
||||||
|
} else {
|
||||||
|
nm_client_add_and_activate_connection_async (nmc->client,
|
||||||
|
connection,
|
||||||
|
device,
|
||||||
|
nm_object_get_path (NM_OBJECT (ap)),
|
||||||
|
NULL,
|
||||||
|
add_and_activate_cb,
|
||||||
|
info);
|
||||||
|
}
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
if (bssid1_arr)
|
if (bssid1_arr)
|
||||||
|
@@ -1445,14 +1445,13 @@
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Connect to a Wi-Fi network specified by SSID or BSSID. The command
|
<para>Connect to a Wi-Fi network specified by SSID or BSSID. The command
|
||||||
creates a new connection and then activates it on a device. This is a
|
finds a matching connnection or creates one and then activates it on a device.
|
||||||
command-line counterpart of clicking an SSID in a GUI client. The command
|
This is a command-line counterpart of clicking an SSID in a GUI client. If
|
||||||
always creates a new connection and thus it is mainly useful for connecting to
|
a connection for the network already exists, it is possible to bring up
|
||||||
new Wi-Fi networks. If a connection for the network already exists, it is
|
(activate) the existing profile as follows:
|
||||||
better to bring up (activate) the existing connection as follows:
|
|
||||||
<command>nmcli con up id <replaceable>name</replaceable></command>. Note that
|
<command>nmcli con up id <replaceable>name</replaceable></command>. Note that
|
||||||
only open, WEP and WPA-PSK networks are supported at the moment. It is also
|
only open, WEP and WPA-PSK networks are supported if no previous connection
|
||||||
supposed that IP configuration is obtained via DHCP.</para>
|
exists. It is also assumed that IP configuration is obtained via DHCP.</para>
|
||||||
|
|
||||||
<para>If <option>--wait</option> option is not specified, the default timeout will be 90
|
<para>If <option>--wait</option> option is not specified, the default timeout will be 90
|
||||||
seconds.</para>
|
seconds.</para>
|
||||||
|
Reference in New Issue
Block a user