#include "connections.h"
#include "nm-secret-agent-simple.h"
#include "polkit-agent.h"
+#include "nm-vpn-helpers.h"
/* define some prompts for connection editor */
#define EDITOR_PROMPT_SETTING _("Setting name? ")
" delete [id | uuid | path] <ID>\n\n"
" monitor [id | uuid | path] <ID> ...\n\n"
" reload\n\n"
- " load <filename> [ <filename>... ]\n\n"));
+ " load <filename> [ <filename>... ]\n\n"
+ " import [--temporary] type <type> file <file to import>\n\n"));
}
static void
"state.\n\n"));
}
+static void
+usage_connection_import (void)
+{
+ g_printerr (_("Usage: nmcli connection import { ARGUMENTS | help }\n"
+ "\n"
+ "ARGUMENTS := [--temporary] type <type> file <file to import>\n"
+ "\n"
+ "Import an external/foreign configuration as a NetworkManager connection profile.\n"
+ "The type of the input file is specified by type option.\n"
+ "Only VPN configurations are supported at the moment. The configuration\n"
+ "is imported by NetworkManager VPN plugins.\n\n"));
+}
+
static gboolean
usage_connection_second_level (const char *cmd)
{
usage_connection_reload ();
else if (matches (cmd, "load") == 0)
usage_connection_load ();
+ else if (matches (cmd, "import") == 0)
+ usage_connection_import ();
else
ret = FALSE;
return ret;
return nmc->return_value;
}
+// FIXME: change the text when non-VPN connection types are supported
+#define PROMPT_IMPORT_TYPE PROMPT_VPN_TYPE
+#define PROMPT_IMPORT_FILE _("File to import: ")
+
+static NMCResultCode
+do_connection_import (NmCli *nmc, gboolean temporary, int argc, char **argv)
+{
+ GError *error = NULL;
+ const char *type = NULL, *filename = NULL;
+ char *type_ask = NULL, *filename_ask = NULL;
+ AddConnectionInfo *info;
+ NMConnection *connection = NULL;
+ NMVpnEditorPlugin *plugin;
+
+ if (argc == 0) {
+ if (nmc->ask) {
+ type_ask = nmc_readline (PROMPT_IMPORT_TYPE);
+ filename_ask = nmc_readline (PROMPT_IMPORT_FILE);
+ type = type_ask = type_ask ? g_strstrip (type_ask) : NULL;
+ filename = filename_ask = filename_ask ? g_strstrip (filename_ask) : NULL;
+ } else {
+ g_string_printf (nmc->return_text, _("Error: No arguments provided."));
+ nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+ goto finish;
+ }
+ }
+
+ while (argc > 0) {
+ if (strcmp (*argv, "type") == 0) {
+ if (next_arg (&argc, &argv) != 0) {
+ g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1));
+ nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+ goto finish;
+ }
+ if (!type)
+ type = *argv;
+ else
+ g_printerr (_("Warning: 'type' already specified, ignoring extra one.\n"));
+
+ } else if (strcmp (*argv, "file") == 0) {
+ if (next_arg (&argc, &argv) != 0) {
+ g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1));
+ nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+ goto finish;
+ }
+ if (!filename)
+ filename = *argv;
+ else
+ g_printerr (_("Warning: 'file' already specified, ignoring extra one.\n"));
+ } else {
+ g_string_printf (nmc->return_text, _("Unknown parameter: %s\n"), *argv);
+ nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+ goto finish;
+ }
+
+ argc--;
+ argv++;
+ }
+
+ if (!type) {
+ g_string_printf (nmc->return_text, _("Error: 'type' argument is required."));
+ nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+ goto finish;
+ }
+ if (!filename) {
+ g_string_printf (nmc->return_text, _("Error: 'file' argument is required."));
+ nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+ goto finish;
+ }
+
+ /* Import VPN configuration */
+ plugin = nm_vpn_get_plugin_by_service (type, &error);
+ if (!plugin) {
+ g_string_printf (nmc->return_text, _("Error: failed to load VPN plugin: %s."),
+ error->message);
+ nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
+ goto finish;
+ }
+
+ connection = nm_vpn_editor_plugin_import (plugin, filename, &error);
+ if (!connection) {
+ g_string_printf (nmc->return_text, _("Error: failed to import '%s': %s."),
+ filename, error->message);
+ nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
+ goto finish;
+ }
+
+ info = g_malloc0 (sizeof (AddConnectionInfo));
+ info->nmc = nmc;
+ info->con_name = g_strdup (nm_connection_get_id (connection));
+
+ /* Add the new imported connection to NetworkManager */
+ add_new_connection (!temporary,
+ nmc->client,
+ connection,
+ add_connection_cb,
+ info);
+
+ nmc->should_wait = TRUE;
+finish:
+ if (connection)
+ g_object_unref (connection);
+ g_clear_error (&error);
+ g_free (type_ask);
+ g_free (filename_ask);
+ return nmc->return_value;
+}
+
typedef struct {
NmCli *nmc;
generator_func = gen_func_connection_names;
} else if (g_strcmp0 (rl_prompt, PROMPT_ACTIVE_CONNECTIONS) == 0) {
generator_func = gen_func_active_connection_names;
+ } else if (g_strcmp0 (rl_prompt, PROMPT_IMPORT_TYPE) == 0) {
+ generator_func = gen_func_vpn_types;
+ } else if (g_strcmp0 (rl_prompt, PROMPT_IMPORT_FILE) == 0) {
+ rl_attempted_completion_over = 0;
+ rl_complete_with_tilde_expansion = 1;
}
if (generator_func)
next_arg (&argc, &argv);
}
nmc->return_value = do_connection_clone (nmc, temporary, argc, argv);
+ } else if (matches(*argv, "import") == 0) {
+ gboolean temporary = FALSE;
+
+ next_arg (&argc, &argv);
+ if (nmc_arg_is_option (*argv, "temporary")) {
+ temporary = TRUE;
+ next_arg (&argc, &argv);
+ }
+ nmc->return_value = do_connection_import (nmc, temporary, argc, argv);
} else {
usage ();
g_string_printf (nmc->return_text, _("Error: '%s' is not valid 'connection' command."), *argv);
# expects several options with parameters. This function can parse them and remove them from the words array.
_nmcli_compl_ARGS()
{
+ local aliases=${@}
local OPTIONS_ALL N_REMOVE_WORDS REMOVE_OPTIONS OPTIONS_HAS_MANDATORY i
OPTIONS_ALL=("${OPTIONS[@]}")
OPTIONS_UNKNOWN_OPTION=
N_REMOVE_WORDS=2
REMOVE_OPTIONS=("${words[0]}")
- case "${words[0]}" in
+
+ # change option name to alias
+ WORD0="${words[0]}"
+ for alias in "${aliases[@]}" ; do
+ if [[ "${WORD0}" == ${alias%%:*} ]]; then
+ WORD0=${alias#*:}
+ break
+ fi
+ done
+
+ case "${WORD0}" in
level)
if [[ "${#words[@]}" -eq 2 ]]; then
_nmcli_list "OFF ERR WARN INFO DEBUG TRACE"
username| \
service| \
password| \
- passwd-file)
+ passwd-file| \
+ file)
if [[ "${#words[@]}" -eq 2 ]]; then
return 0
fi
;;
c|co|con|conn|conne|connec|connect|connecti|connectio|connection)
if [[ ${#words[@]} -eq 2 ]]; then
- _nmcli_compl_COMMAND "$command" show up down add modify clone edit delete monitor reload load
+ _nmcli_compl_COMMAND "$command" show up down add modify clone edit delete monitor reload load import
elif [[ ${#words[@]} -gt 2 ]]; then
case "$command" in
s|sh|sho|show)
COMPREPLY=()
fi
;;
+ i|im|imp|impo|impor|import)
+ if [[ ${#words[@]} -eq 3 ]]; then
+ _nmcli_compl_COMMAND "${words[2]}" type file --temporary
+ elif [[ ${#words[@]} -gt 3 ]]; then
+ _nmcli_array_delete_at words 0 1
+
+ LONG_OPTIONS=(help temporary)
+ HELP_ONLY_AS_FIRST=1
+ _nmcli_compl_OPTIONS
+ case $? in
+ 0)
+ return 0
+ ;;
+ 1)
+ if [[ "$HELP_ONLY_AS_FIRST" == 1 ]]; then
+ _nmcli_compl_COMMAND "${words[2]}" type file
+ fi
+ return 0
+ ;;
+ esac
+
+ OPTIONS=(type file)
+ OPTIONS_MANDATORY=(type file)
+ ALIASES=("type:vpn-type")
+ _nmcli_compl_ARGS ${ALIASES[@]}
+ return 0
+ fi
+ ;;
+
esac
fi
;;