mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-03 12:50:17 +01:00
If a connection is given but no device, the correct device will be automatically determined. If a device is given but not a connection, a connection will be automatically chose from among that device's available connections. Adds the cli command "nmcli dev connect <ifname>".
This commit is contained in:
commit
732012cc8c
12 changed files with 387 additions and 67 deletions
|
|
@ -502,6 +502,13 @@ _nmcli_complete_COMMAND_CONNECTION()
|
|||
fi
|
||||
words=("${words[@]:2}")
|
||||
;;
|
||||
ifname)
|
||||
if [[ ${#words[@]} -eq 2 ]]; then
|
||||
_nmcli_list_nl "$(_nmcli_NM_devices)"
|
||||
return 0
|
||||
fi
|
||||
words=("${words[@]:2}")
|
||||
;;
|
||||
*)
|
||||
COMMAND_CONNECTION_TYPE=
|
||||
COMMAND_CONNECTION_ID="${words[0]}"
|
||||
|
|
@ -601,12 +608,18 @@ _nmcli()
|
|||
;;
|
||||
u|up)
|
||||
if [[ ${#words[@]} -eq 3 ]]; then
|
||||
_nmcli_list_nl "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_id)")"
|
||||
_nmcli_list_nl "$(printf "ifname\nid\nuuid\npath\n%s" "$(_nmcli_con_id)")"
|
||||
elif [[ ${#words[@]} -gt 3 ]]; then
|
||||
local COMMAND_CONNECTION_TYPE=''
|
||||
words=("${words[@]:2}")
|
||||
OPTIONS=(id uuid path)
|
||||
OPTIONS=(ifname id uuid path)
|
||||
_nmcli_complete_COMMAND_CONNECTION && return 0
|
||||
OPTIONS=(ifname ap nsp)
|
||||
|
||||
if [[ "$COMMAND_CONNECTION_TYPE" = "ifname" ]]; then
|
||||
OPTIONS=(ap nsp)
|
||||
else
|
||||
OPTIONS=(ifname ap nsp)
|
||||
fi
|
||||
_nmcli_complete_COMMAND_ARGS
|
||||
fi
|
||||
;;
|
||||
|
|
@ -841,12 +854,13 @@ _nmcli()
|
|||
;;
|
||||
d|de|dev|devi|devic|device)
|
||||
if [[ ${#words[@]} -eq 2 ]]; then
|
||||
_nmcli_list "status show disconnect wifi wimax help"
|
||||
_nmcli_list "status show connect disconnect wifi wimax help"
|
||||
elif [[ ${#words[@]} -gt 2 ]]; then
|
||||
case "$command" in
|
||||
s|st|sta|stat|statu|status)
|
||||
;;
|
||||
sh|sho|show| \
|
||||
c|co|con|conn|conne|connec|connect| \
|
||||
d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect)
|
||||
if [[ ${#words[@]} -eq 3 ]]; then
|
||||
_nmcli_list_nl "$(_nmcli_NM_devices)"
|
||||
|
|
|
|||
|
|
@ -218,9 +218,9 @@ usage (void)
|
|||
" show configured [[ id | uuid | path ] <ID>]\n\n"
|
||||
" show active [[ id | uuid | path | apath ] <ID>]\n\n"
|
||||
#if WITH_WIMAX
|
||||
" up [ id | uuid | path ] <ID> [ifname <ifname>] [ap <BSSID>] [nsp <name>]\n\n"
|
||||
" up [[ id | uuid | path ] <ID>] [ifname <ifname>] [ap <BSSID>] [nsp <name>]\n\n"
|
||||
#else
|
||||
" up [ id | uuid | path ] <ID> [ifname <ifname>] [ap <BSSID>]\n\n"
|
||||
" up [[ id | uuid | path ] <ID>] [ifname <ifname>] [ap <BSSID>]\n\n"
|
||||
#endif
|
||||
" down [ id | uuid | path | apath ] <ID>\n\n"
|
||||
" add COMMON_OPTIONS TYPE_SPECIFIC_OPTIONS IP_OPTIONS\n\n"
|
||||
|
|
@ -1517,18 +1517,31 @@ nmc_activate_connection (NmCli *nmc,
|
|||
GError *local = NULL;
|
||||
|
||||
g_return_val_if_fail (nmc != NULL, FALSE);
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection) || ifname, FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
if (nm_connection_get_virtual_iface_name (connection))
|
||||
is_virtual = TRUE;
|
||||
if (connection) {
|
||||
if (nm_connection_get_virtual_iface_name (connection))
|
||||
is_virtual = TRUE;
|
||||
|
||||
device_found = find_device_for_connection (nmc, connection, ifname, ap, nsp, &device, &spec_object, &local);
|
||||
/* Virtual connection may not have their interfaces created yet */
|
||||
if (!device_found && !is_virtual) {
|
||||
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_CON_ACTIVATION,
|
||||
"%s", local && local->message ? local->message : _("unknown error"));
|
||||
g_clear_error (&local);
|
||||
device_found = find_device_for_connection (nmc, connection, ifname, ap, nsp, &device, &spec_object, &local);
|
||||
/* Virtual connection may not have their interfaces created yet */
|
||||
if (!device_found && !is_virtual) {
|
||||
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_CON_ACTIVATION,
|
||||
"%s", local && local->message ? local->message : _("unknown error"));
|
||||
g_clear_error (&local);
|
||||
return FALSE;
|
||||
}
|
||||
} else if (ifname) {
|
||||
device = nm_client_get_device_by_iface (nmc->client, ifname);
|
||||
if (!device) {
|
||||
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_CON_ACTIVATION,
|
||||
_("unknown device '%s'."), ifname);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_CON_ACTIVATION,
|
||||
_("no connection and no device given."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1554,7 +1567,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
|
|||
const char *nsp = NULL;
|
||||
GError *error = NULL;
|
||||
const char *selector = NULL;
|
||||
const char *name;
|
||||
const char *name = NULL;
|
||||
char *line = NULL;
|
||||
|
||||
/*
|
||||
|
|
@ -1570,12 +1583,8 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
|
|||
name = line ? line : "";
|
||||
// TODO: enhancement: when just Enter is pressed (line is NULL), list
|
||||
// available connections so that the user can select one
|
||||
} else {
|
||||
g_string_printf (nmc->return_text, _("Error: No connection specified."));
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
} else if (strcmp (*argv, "ifname") != 0) {
|
||||
if ( strcmp (*argv, "id") == 0
|
||||
|| strcmp (*argv, "uuid") == 0
|
||||
|| strcmp (*argv, "path") == 0) {
|
||||
|
|
@ -1589,16 +1598,11 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
|
|||
name = *argv;
|
||||
}
|
||||
name = *argv;
|
||||
next_arg (&argc, &argv);
|
||||
}
|
||||
|
||||
connection = find_connection (nmc->system_connections, selector, name);
|
||||
|
||||
if (!connection) {
|
||||
g_string_printf (nmc->return_text, _("Error: Unknown connection: %s."), name);
|
||||
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||
goto error;
|
||||
}
|
||||
next_arg (&argc, &argv);
|
||||
if (name)
|
||||
connection = find_connection (nmc->system_connections, selector, name);
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp (*argv, "ifname") == 0) {
|
||||
|
|
|
|||
|
|
@ -262,12 +262,13 @@ usage (void)
|
|||
fprintf (stderr,
|
||||
_("Usage: nmcli device { COMMAND | help }\n\n"
|
||||
#if WITH_WIMAX
|
||||
" COMMAND := { status | show | disconnect | wifi | wimax }\n\n"
|
||||
" COMMAND := { status | show | connect | disconnect | wifi | wimax }\n\n"
|
||||
#else
|
||||
" COMMAND := { status | show | disconnect | wifi }\n\n"
|
||||
" COMMAND := { status | show | connect | disconnect | wifi }\n\n"
|
||||
#endif
|
||||
" status\n\n"
|
||||
" show [<ifname>]\n\n"
|
||||
" connect <ifname>\n\n"
|
||||
" disconnect <ifname>\n\n"
|
||||
" wifi [list [ifname <ifname>] [bssid <BSSID>]]\n\n"
|
||||
" wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>] [bssid <BSSID>] [name <name>]\n\n"
|
||||
|
|
@ -1142,20 +1143,6 @@ error:
|
|||
return nmc->return_value;
|
||||
}
|
||||
|
||||
static void
|
||||
device_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
NmCli *nmc = (NmCli *) user_data;
|
||||
NMDeviceState state;
|
||||
|
||||
state = nm_device_get_state (device);
|
||||
|
||||
if (state == NM_DEVICE_STATE_DISCONNECTED) {
|
||||
g_string_printf (nmc->return_text, _("Success: Device '%s' successfully disconnected."), nm_device_get_iface (device));
|
||||
quit ();
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout_cb (gpointer user_data)
|
||||
{
|
||||
|
|
@ -1179,6 +1166,160 @@ progress_cb (gpointer user_data)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
connected_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
NmCli *nmc = (NmCli *) user_data;
|
||||
NMDeviceState state;
|
||||
|
||||
state = nm_device_get_state (device);
|
||||
|
||||
if (state == NM_DEVICE_STATE_ACTIVATED) {
|
||||
g_string_printf (nmc->return_text, _("Success: Device '%s' successfully activated."), nm_device_get_iface (device));
|
||||
quit ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
connect_device_cb (NMClient *client, NMActiveConnection *active, GError *error, gpointer user_data)
|
||||
{
|
||||
NmCli *nmc = (NmCli *) user_data;
|
||||
const GPtrArray *devices;
|
||||
NMDevice *device;
|
||||
NMDeviceState state;
|
||||
|
||||
if (error) {
|
||||
g_string_printf (nmc->return_text, _("Error: Device activation failed: %s"),
|
||||
error->message ? error->message : _("(unknown)"));
|
||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
||||
quit ();
|
||||
} else {
|
||||
g_assert (active);
|
||||
devices = nm_active_connection_get_devices (active);
|
||||
g_assert (devices && devices->len);
|
||||
device = g_ptr_array_index (devices, 0);
|
||||
g_assert (device);
|
||||
|
||||
state = nm_device_get_state (device);
|
||||
|
||||
if (nmc->nowait_flag || state == NM_DEVICE_STATE_ACTIVATED) {
|
||||
/* Don't want to wait or device already activated */
|
||||
if (state == NM_DEVICE_STATE_ACTIVATED && nmc->print_output == NMC_PRINT_PRETTY) {
|
||||
nmc_terminal_erase_line ();
|
||||
printf (_("Device '%s' has been connected.\n"), nm_device_get_iface (device));
|
||||
}
|
||||
quit ();
|
||||
} else {
|
||||
g_signal_connect (device, "notify::state", G_CALLBACK (connected_state_cb), nmc);
|
||||
/* Start timer not to loop forever if "notify::state" signal is not issued */
|
||||
g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static NMCResultCode
|
||||
do_device_connect (NmCli *nmc, int argc, char **argv)
|
||||
{
|
||||
NMDevice **devices;
|
||||
NMDevice *device = NULL;
|
||||
const char *ifname = NULL;
|
||||
char *ifname_ask = NULL;
|
||||
int i;
|
||||
|
||||
/* Set default timeout for connect operation. */
|
||||
if (nmc->timeout == -1)
|
||||
nmc->timeout = 90;
|
||||
|
||||
if (argc == 0) {
|
||||
if (nmc->ask) {
|
||||
ifname = ifname_ask = nmc_get_user_input (_("Interface: "));
|
||||
// TODO: list available devices when just Enter is pressed ?
|
||||
}
|
||||
if (!ifname_ask) {
|
||||
g_string_printf (nmc->return_text, _("Error: No interface specified."));
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
ifname = *argv;
|
||||
}
|
||||
|
||||
if (!ifname) {
|
||||
g_string_printf (nmc->return_text, _("Error: No interface specified."));
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (next_arg (&argc, &argv) == 0) {
|
||||
g_string_printf (nmc->return_text, _("Error: extra argument not allowed: '%s'."), *argv);
|
||||
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
nmc->get_client (nmc);
|
||||
if (!nm_client_get_manager_running (nmc->client)) {
|
||||
g_string_printf (nmc->return_text, _("Error: NetworkManager is not running."));
|
||||
nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!nmc_versions_match (nmc))
|
||||
goto error;
|
||||
|
||||
devices = get_devices_sorted (nmc->client);
|
||||
for (i = 0; devices[i]; i++) {
|
||||
NMDevice *candidate = devices[i];
|
||||
const char *dev_iface = nm_device_get_iface (candidate);
|
||||
|
||||
if (!g_strcmp0 (dev_iface, ifname))
|
||||
device = candidate;
|
||||
}
|
||||
g_free (devices);
|
||||
|
||||
if (!device) {
|
||||
g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), ifname);
|
||||
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use nowait_flag instead of should_wait, because exiting has to be postponed
|
||||
* till connect_device_cb() is called, giving NM time to check our permissions.
|
||||
*/
|
||||
nmc->nowait_flag = (nmc->timeout == 0);
|
||||
nmc->should_wait = TRUE;
|
||||
nm_client_activate_connection (nmc->client,
|
||||
NULL, /* let NM find a connection automatically */
|
||||
device,
|
||||
NULL,
|
||||
connect_device_cb,
|
||||
nmc);
|
||||
|
||||
/* Start progress indication */
|
||||
if (nmc->print_output == NMC_PRINT_PRETTY)
|
||||
progress_id = g_timeout_add (120, progress_cb, device);
|
||||
|
||||
error:
|
||||
g_free (ifname_ask);
|
||||
|
||||
return nmc->return_value;
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
NmCli *nmc = (NmCli *) user_data;
|
||||
NMDeviceState state;
|
||||
|
||||
state = nm_device_get_state (device);
|
||||
|
||||
if (state == NM_DEVICE_STATE_DISCONNECTED) {
|
||||
g_string_printf (nmc->return_text, _("Success: Device '%s' successfully disconnected."), nm_device_get_iface (device));
|
||||
quit ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect_device_cb (NMDevice *device, GError *error, gpointer user_data)
|
||||
{
|
||||
|
|
@ -1204,7 +1345,7 @@ disconnect_device_cb (NMDevice *device, GError *error, gpointer user_data)
|
|||
}
|
||||
quit ();
|
||||
} else {
|
||||
g_signal_connect (device, "notify::state", G_CALLBACK (device_state_cb), nmc);
|
||||
g_signal_connect (device, "notify::state", G_CALLBACK (disconnect_state_cb), nmc);
|
||||
/* Start timer not to loop forever if "notify::state" signal is not issued */
|
||||
g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc);
|
||||
}
|
||||
|
|
@ -2296,6 +2437,9 @@ do_devices (NmCli *nmc, int argc, char **argv)
|
|||
nmc->multiline_output = TRUE; /* multiline mode is default for 'device show' */
|
||||
nmc->return_value = do_devices_show (nmc, argc-1, argv+1);
|
||||
}
|
||||
else if (matches (*argv, "connect") == 0) {
|
||||
nmc->return_value = do_device_connect (nmc, argc-1, argv+1);
|
||||
}
|
||||
else if (matches (*argv, "disconnect") == 0) {
|
||||
nmc->return_value = do_device_disconnect (nmc, argc-1, argv+1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,12 +41,17 @@
|
|||
</tp:docstring>
|
||||
<arg name="connection" type="o" direction="in">
|
||||
<tp:docstring>
|
||||
The connection to activate the devices with.
|
||||
The connection to activate. If "/" is given, a valid device path must
|
||||
be given, and NetworkManager picks the best connection to activate for
|
||||
the given device. VPN connections must always pass a valid connection
|
||||
path.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg name="device" type="o" direction="in">
|
||||
<tp:docstring>
|
||||
The object path of device to be activated for physical connections. This parameter is ignored for VPN connections, because the specific_object (if provided) specifies the device to use.
|
||||
The object path of device to be activated for physical connections.
|
||||
This parameter is ignored for VPN connections, because the
|
||||
specific_object (if provided) specifies the device to use.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg name="specific_object" type="o" direction="in">
|
||||
|
|
@ -55,7 +60,7 @@
|
|||
This parameter is currently ignored for wired and mobile broadband connections,
|
||||
and the value of "/" should be used (ie, no specific object). For WiFi
|
||||
connections, pass the object path of a specific AP from the card's scan
|
||||
list, or "/" to pick and AP automatically. For VPN connections, pass
|
||||
list, or "/" to pick an AP automatically. For VPN connections, pass
|
||||
the object path of an ActiveConnection object that should serve as the
|
||||
"base" connection (to which the VPN connections lifetime will be tied),
|
||||
or pass "/" and NM will automatically use the current default device.
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ activate_nm_not_running (gpointer user_data)
|
|||
/**
|
||||
* nm_client_activate_connection:
|
||||
* @client: a #NMClient
|
||||
* @connection: an #NMConnection
|
||||
* @connection: (allow-none): an #NMConnection
|
||||
* @device: (allow-none): the #NMDevice
|
||||
* @specific_object: (allow-none): the object path of a connection-type-specific
|
||||
* object this activation should use. This parameter is currently ignored for
|
||||
|
|
@ -613,6 +613,9 @@ activate_nm_not_running (gpointer user_data)
|
|||
* #NMWimaxNsp for WiMAX connections, to which you wish to connect. If the
|
||||
* specific object is not given, NetworkManager can, in some cases, automatically
|
||||
* determine which network to connect to given the settings in @connection.
|
||||
*
|
||||
* If @connection is not given for a device-based activation, NetworkManager
|
||||
* picks the best available connection for the device and activates it.
|
||||
**/
|
||||
void
|
||||
nm_client_activate_connection (NMClient *client,
|
||||
|
|
@ -628,7 +631,8 @@ nm_client_activate_connection (NMClient *client,
|
|||
g_return_if_fail (NM_IS_CLIENT (client));
|
||||
if (device)
|
||||
g_return_if_fail (NM_IS_DEVICE (device));
|
||||
g_return_if_fail (NM_IS_CONNECTION (connection));
|
||||
if (connection)
|
||||
g_return_if_fail (NM_IS_CONNECTION (connection));
|
||||
|
||||
info = g_slice_new0 (ActivateInfo);
|
||||
info->act_fn = callback;
|
||||
|
|
@ -645,7 +649,7 @@ nm_client_activate_connection (NMClient *client,
|
|||
|
||||
dbus_g_proxy_begin_call (priv->client_proxy, "ActivateConnection",
|
||||
activate_cb, info, NULL,
|
||||
DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
|
||||
DBUS_TYPE_G_OBJECT_PATH, connection ? nm_connection_get_path (connection) : "/",
|
||||
DBUS_TYPE_G_OBJECT_PATH, device ? nm_object_get_path (NM_OBJECT (device)) : "/",
|
||||
DBUS_TYPE_G_OBJECT_PATH, specific_object ? specific_object : "/",
|
||||
G_TYPE_INVALID);
|
||||
|
|
|
|||
|
|
@ -304,14 +304,20 @@ When no command is given to the \fIconnection\fP object, the default action
|
|||
is 'nmcli connection show configured'.
|
||||
.TP
|
||||
.B up [ id | uuid | path ] <ID> [ifname <ifname>] [ap <BSSID>] [nsp <name>]
|
||||
.RE
|
||||
.RS
|
||||
.B up ifname <ifname> [ap <BSSID>] [nsp <name>]
|
||||
.RS
|
||||
.br
|
||||
Activate a connection. The connection is identified by its name, UUID or D-Bus
|
||||
path. If <ID> is ambiguous, a keyword \fIid\fP, \fIuuid\fP or \fIpath\fP can be
|
||||
used. When requiring a particular device to activate the connection on, the
|
||||
\fIifname\fP option with interface name should be given. In case of a VPN
|
||||
connection, the \fIifname\fP option specify the device of the base connection.
|
||||
The \fIap\fP option specify what particular AP should be used in case of
|
||||
a Wi\(hyFi connection.
|
||||
used. When requiring a particular device to activate the connection on, the
|
||||
\fIifname\fP option with interface name should be given. If the <ID> is not
|
||||
given an \fIifname\fP is required, and NetworkManager will activate the best
|
||||
available connection for the given \fIifname\fP. In case of a VPN connection,
|
||||
the \fIifname\fP option specifies the device of the base connection. The
|
||||
\fIap\fP option specify what particular AP should be used in case of a Wi\(hyFi
|
||||
connection.
|
||||
.br
|
||||
If '--wait' option is not specified, the default timeout will be 90 seconds.
|
||||
.br
|
||||
|
|
@ -326,6 +332,7 @@ Available options are:
|
|||
.IP \fInsp\fP 13
|
||||
\(en NSP (Network Service Provider) which the command should connect to (for WiMAX connections)
|
||||
.RE
|
||||
.RE
|
||||
.TP
|
||||
.B down [ id | uuid | path | apath ] <ID>
|
||||
.br
|
||||
|
|
@ -608,7 +615,7 @@ then \fINetworkManager\fP will reload connection files any time they change
|
|||
.B device - show and manage network interfaces
|
||||
.br
|
||||
.TP
|
||||
.SS \fICOMMAND\fP := { status | show | disconnect | wifi | wimax }
|
||||
.SS \fICOMMAND\fP := { status | show | connect | disconnect | wifi | wimax }
|
||||
.sp
|
||||
.RS
|
||||
.TP
|
||||
|
|
@ -624,6 +631,13 @@ Show detailed information about devices. Without an argument, all devices are
|
|||
examined. To get information for a specific device, the interface name has
|
||||
to be provided.
|
||||
.TP
|
||||
.B connect <ifname>
|
||||
.br
|
||||
Connect the device. NetworkManager will try to find a suitable connection that
|
||||
will be activated. It will also consider connections that are not set to auto connect.
|
||||
.br
|
||||
If '--wait' option is not specified, the default timeout will be 90 seconds.
|
||||
.TP
|
||||
.B disconnect <ifname>
|
||||
.br
|
||||
Disconnect a device and prevent the device from automatically activating further
|
||||
|
|
|
|||
|
|
@ -221,7 +221,9 @@ check_connection_compatible (NMDevice *device,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
check_connection_available (NMDevice *device, NMConnection *connection)
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
|
||||
guint32 bt_type;
|
||||
|
|
|
|||
|
|
@ -1021,13 +1021,22 @@ check_connection_compatible (NMDevice *device,
|
|||
|
||||
|
||||
static gboolean
|
||||
check_connection_available (NMDevice *device, NMConnection *connection)
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
|
||||
NMSettingWireless *s_wifi;
|
||||
const char *mode;
|
||||
GSList *ap_iter = NULL;
|
||||
|
||||
if (specific_object) {
|
||||
NMAccessPoint *ap;
|
||||
|
||||
ap = get_ap_by_path (NM_DEVICE_WIFI (device), specific_object);
|
||||
return ap ? nm_ap_check_compatible (ap, connection) : FALSE;
|
||||
}
|
||||
|
||||
s_wifi = nm_connection_get_setting_wireless (connection);
|
||||
|
||||
/* Ad-Hoc and AP connections are always available because they may be
|
||||
|
|
|
|||
|
|
@ -320,7 +320,9 @@ static gboolean nm_device_set_ip6_config (NMDevice *dev,
|
|||
|
||||
static gboolean nm_device_activate_ip6_config_commit (gpointer user_data);
|
||||
|
||||
static gboolean check_connection_available (NMDevice *device, NMConnection *connection);
|
||||
static gboolean check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object);
|
||||
|
||||
static gboolean spec_match_list (NMDevice *device, const GSList *specs);
|
||||
|
||||
|
|
@ -6613,7 +6615,7 @@ _try_add_available_connection (NMDevice *self, NMConnection *connection)
|
|||
if (nm_device_check_connection_compatible (self, connection, NULL)) {
|
||||
/* Let subclasses implement additional checks on the connection */
|
||||
if ( NM_DEVICE_GET_CLASS (self)->check_connection_available
|
||||
&& NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection)) {
|
||||
&& NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, NULL)) {
|
||||
|
||||
g_hash_table_insert (NM_DEVICE_GET_PRIVATE (self)->available_connections,
|
||||
g_object_ref (connection),
|
||||
|
|
@ -6631,7 +6633,9 @@ _del_available_connection (NMDevice *device, NMConnection *connection)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
check_connection_available (NMDevice *device, NMConnection *connection)
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object)
|
||||
{
|
||||
/* Default is to assume the connection is available unless a subclass
|
||||
* overrides this with more specific checks.
|
||||
|
|
@ -6658,6 +6662,42 @@ nm_device_recheck_available_connections (NMDevice *device)
|
|||
_signal_available_connections_changed (device);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_get_available_connections:
|
||||
* @device: the #NMDevice
|
||||
* @specific_object: a specific object path if any
|
||||
*
|
||||
* Returns a list of connections available to activate on the device, taking
|
||||
* into account any device-specific details given by @specific_object (like
|
||||
* WiFi access point path).
|
||||
*
|
||||
* Returns: caller-owned #GPtrArray of #NMConnections
|
||||
*/
|
||||
GPtrArray *
|
||||
nm_device_get_available_connections (NMDevice *device, const char *specific_object)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
GHashTableIter iter;
|
||||
guint num_available;
|
||||
NMConnection *connection = NULL;
|
||||
GPtrArray *array = NULL;
|
||||
|
||||
num_available = g_hash_table_size (priv->available_connections);
|
||||
if (num_available > 0) {
|
||||
array = g_ptr_array_sized_new (num_available);
|
||||
g_hash_table_iter_init (&iter, priv->available_connections);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) {
|
||||
/* If a specific object is given, only include connections that are
|
||||
* compatible with it.
|
||||
*/
|
||||
if ( !specific_object
|
||||
|| NM_DEVICE_GET_CLASS (device)->check_connection_available (device, connection, specific_object))
|
||||
g_ptr_array_add (array, connection);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
static void
|
||||
cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -140,11 +140,13 @@ typedef struct {
|
|||
GError **error);
|
||||
|
||||
/* Checks whether the connection is likely available to be activated,
|
||||
* including any live network information like scan lists. Returns
|
||||
* TRUE if the connection is available; FALSE if not.
|
||||
* including any live network information like scan lists. The connection
|
||||
* is checked against the object defined by @specific_object, if given.
|
||||
* Returns TRUE if the connection is available; FALSE if not.
|
||||
*/
|
||||
gboolean (* check_connection_available) (NMDevice *self,
|
||||
NMConnection *connection);
|
||||
NMConnection *connection,
|
||||
const char *specific_object);
|
||||
|
||||
gboolean (* complete_connection) (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
|
|
@ -337,6 +339,9 @@ void nm_device_add_pending_action (NMDevice *device, const char *action);
|
|||
void nm_device_remove_pending_action (NMDevice *device, const char *action);
|
||||
gboolean nm_device_has_pending_action (NMDevice *device);
|
||||
|
||||
GPtrArray *nm_device_get_available_connections (NMDevice *device,
|
||||
const char *specific_object);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
/* For testing only */
|
||||
|
|
|
|||
|
|
@ -261,6 +261,22 @@ get_nsp_by_name (NMDeviceWimax *self, const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static NMWimaxNsp *
|
||||
get_nsp_by_path (NMDeviceWimax *self, const char *path)
|
||||
{
|
||||
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
|
||||
for (iter = priv->nsp_list; iter; iter = iter->next) {
|
||||
NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
|
||||
|
||||
if (!g_strcmp0 (nm_wimax_nsp_get_dbus_path (nsp), path))
|
||||
return nsp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_availability (NMDeviceWimax *self, gboolean old_available)
|
||||
{
|
||||
|
|
@ -375,10 +391,18 @@ check_connection_compatible (NMDevice *device,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
check_connection_available (NMDevice *device, NMConnection *connection)
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
|
||||
const GSList *ns_iter = NULL;
|
||||
NMWimaxNsp *nsp;
|
||||
|
||||
if (specific_object) {
|
||||
nsp = get_nsp_by_path (NM_DEVICE_WIMAX (device), specific_object);
|
||||
return nsp ? nm_wimax_nsp_check_compatible (nsp, connection) : FALSE;
|
||||
}
|
||||
|
||||
/* Ensure the connection applies to an NSP in the scan list */
|
||||
for (ns_iter = priv->nsp_list; ns_iter; ns_iter = ns_iter->next) {
|
||||
|
|
|
|||
|
|
@ -3110,6 +3110,61 @@ impl_manager_activate_connection (NMManager *self,
|
|||
gboolean is_vpn = FALSE;
|
||||
GError *error = NULL;
|
||||
|
||||
/* Normalize object paths */
|
||||
if (g_strcmp0 (connection_path, "/") == 0)
|
||||
connection_path = NULL;
|
||||
if (g_strcmp0 (specific_object_path, "/") == 0)
|
||||
specific_object_path = NULL;
|
||||
if (g_strcmp0 (device_path, "/") == 0)
|
||||
device_path = NULL;
|
||||
|
||||
/* If the connection path is given and valid, that connection is activated.
|
||||
* Otherwise the "best" connection for the device is chosen and activated,
|
||||
* regardless of whether that connection is autoconnect-enabled or not
|
||||
* (since this is an explicit request, not an auto-activation request).
|
||||
*/
|
||||
if (!connection_path) {
|
||||
GPtrArray *available;
|
||||
guint64 best_timestamp = 0;
|
||||
guint i;
|
||||
|
||||
/* If no connection is given, find a suitable connection for the given device path */
|
||||
if (!device_path) {
|
||||
error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
|
||||
"Only devices may be activated without a specifying a connection");
|
||||
goto error;
|
||||
}
|
||||
device = nm_manager_get_device_by_path (self, device_path);
|
||||
if (!device) {
|
||||
error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
|
||||
"Cannot activate unknown device %s", device_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
available = nm_device_get_available_connections (device, specific_object_path);
|
||||
for (i = 0; available && i < available->len; i++) {
|
||||
NMSettingsConnection *candidate = g_ptr_array_index (available, i);
|
||||
guint64 candidate_timestamp = 0;
|
||||
|
||||
nm_settings_connection_get_timestamp (candidate, &candidate_timestamp);
|
||||
if (!connection_path || (candidate_timestamp > best_timestamp)) {
|
||||
connection_path = nm_connection_get_path (NM_CONNECTION (candidate));
|
||||
best_timestamp = candidate_timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
if (available)
|
||||
g_ptr_array_free (available, TRUE);
|
||||
|
||||
if (!connection_path) {
|
||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
||||
"The device has no connections available.");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (connection_path);
|
||||
connection = (NMConnection *) nm_settings_get_connection_by_path (priv->settings, connection_path);
|
||||
if (!connection) {
|
||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue