Commit 1c9b16b2 authored by Lubomir Rintel's avatar Lubomir Rintel 🥕

cli: Add mode option for wifi connecitons

Only default (infrastructure) mode connections can be created and as it's not
possible to write mode=ap connections with ifcfg-rh plugins, they can't be
switched to mode=ap.
parent 3a6c618a
......@@ -336,7 +336,8 @@ usage_connection_add (void)
" wifi: ssid <SSID>\n"
" [mac <MAC address>]\n"
" [cloned-mac <cloned MAC address>]\n"
" [mtu <MTU>]\n\n"
" [mtu <MTU>]\n"
" [mode infrastructure|ap|adhoc]\n\n"
" wimax: [mac <MAC address>]\n"
" [nsp <NSP>]\n\n"
" pppoe: username <PPPoE username>\n"
......@@ -2565,29 +2566,66 @@ check_infiniband_p_key (const char *p_key, guint32 *p_key_int, GError **error)
return TRUE;
}
/* Checks InfiniBand mode.
* It accepts shortcuts and normalizes them ('mode' argument is modified on success).
/**
* check_valid_enumeration:
* @str: string to check against string array @strings
* @strings: string array to check @str againt
* @what: what parameter @str belongs to (used in error message)
* @what_desc: longer description of @what parameter (used in error message)
* @error: location to store an error, or %NULL
*
* Check whether @str is one of the string of @strings array. It accepts
* shortcuts and normalizes them (@str argument is modified on success).
*
* Returns: %TRUE on success, %FALSE on failure
*/
static gboolean
check_infiniband_mode (char **mode, GError **error)
check_valid_enumeration (char **str,
const char *strings[],
const char *what,
const char *what_desc,
GError **error)
{
char *tmp;
const char *checked_mode;
const char *modes[] = { "datagram", "connected", NULL };
const char *checked_str;
if (!mode || !*mode)
if (!str || !*str)
return TRUE;
tmp = g_strstrip (g_strdup (*mode));
checked_mode = nmc_string_is_valid (tmp, modes, NULL);
tmp = g_strstrip (g_strdup (*str));
checked_str = nmc_string_is_valid (tmp, strings, NULL);
g_free (tmp);
if (checked_mode) {
g_free (*mode);
*mode = g_strdup (checked_mode);
} else
if (checked_str) {
g_free (*str);
*str = g_strdup (checked_str);
} else {
char *options;
options = nmc_util_strv_for_display (strings);
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("Error: 'mode': '%s' is not a valid InfiniBand transport mode [datagram, connected]."), *mode);
return !!checked_mode;
_("Error: '%s': '%s' is not a valid %s %s."),
what, *str, what_desc, options);
g_free (options);
}
return !!checked_str;
}
/* Checks Wi-Fi mode. */
static gboolean
check_wifi_mode (char **mode, GError **error)
{
const char *modes[] = { "infrastructure", "ap", "adhoc", NULL };
return check_valid_enumeration (mode, modes, "mode", _("Wi-Fi mode"), error);
}
/* Checks InfiniBand mode. */
static gboolean
check_infiniband_mode (char **mode, GError **error)
{
const char *modes[] = { "datagram", "connected", NULL };
return check_valid_enumeration (mode, modes, "mode", _("InfiniBand transport mode"), error);
}
static gboolean
......@@ -2879,10 +2917,9 @@ do_questionnaire_ethernet (gboolean ethernet, char **mtu, char **mac, char **clo
{
gboolean once_more;
GError *error = NULL;
const char *type = ethernet ? _("ethernet") : _("Wi-Fi");
/* Ask for optional arguments */
if (!want_provide_opt_args (type, 3))
if (ethernet && !want_provide_opt_args (_("ethernet"), 3))
return;
if (!*mtu) {
......@@ -2997,11 +3034,36 @@ do_questionnaire_infiniband (char **mtu, char **mac, char **mode, char **parent,
}
}
#define WORD_INFRA "infrastructure"
#define WORD_AP "ap"
#define WORD_ADHOC "adhoc"
#define PROMPT_WIFI_MODE "(" WORD_INFRA "/" WORD_AP "/" WORD_ADHOC ") [" WORD_INFRA "]: "
static void
do_questionnaire_wifi (char **mtu, char **mac, char **cloned_mac)
do_questionnaire_wifi (char **mtu, char **mac, char **cloned_mac, char **mode)
{
/* At present, the optional Wi-Fi arguments are the same as for ethernet. */
return do_questionnaire_ethernet (FALSE, mtu, mac, cloned_mac);
gboolean once_more;
GError *error = NULL;
/* Ask for optional arguments */
if (!want_provide_opt_args (_("Wi-Fi"), 4))
return;
/* Most optional Wi-Fi arguments are the same as for ethernet. */
do_questionnaire_ethernet (FALSE, mtu, mac, cloned_mac);
if (!*mode) {
do {
*mode = nmc_readline (_("Mode %s"), PROMPT_WIFI_MODE);
if (!*mode)
*mode = g_strdup ("infrastructure");
once_more = !check_wifi_mode (mode, &error);
if (once_more) {
g_print ("%s\n", error->message);
g_clear_error (&error);
g_free (*mode);
}
} while (once_more);
}
}
static void
......@@ -3802,10 +3864,13 @@ cleanup_ib:
char *mac = NULL;
const char *cloned_mac_c = NULL;
char *cloned_mac = NULL;
const char *mode_c = NULL;
char *mode = NULL;
nmc_arg_t exp_args[] = { {"ssid", TRUE, &ssid, !ask},
{"mtu", TRUE, &mtu_c, FALSE},
{"mac", TRUE, &mac_c, FALSE},
{"cloned-mac", TRUE, &cloned_mac_c, FALSE},
{"mode", TRUE, &mode_c, FALSE},
{NULL} };
if (!nmc_parse_args (exp_args, FALSE, &argc, &argv, error))
......@@ -3823,8 +3888,9 @@ cleanup_ib:
mtu = mtu_c ? g_strdup (mtu_c) : NULL;
mac = mac_c ? g_strdup (mac_c) : NULL;
cloned_mac = cloned_mac_c ? g_strdup (cloned_mac_c) : NULL;
mode = mode_c ? g_strdup (mode_c) : NULL;
if (ask)
do_questionnaire_wifi (&mtu, &mac, &cloned_mac);
do_questionnaire_wifi (&mtu, &mac, &cloned_mac, &mode);
if (!check_and_convert_mtu (mtu, &mtu_int, error))
goto cleanup_wifi;
......@@ -3832,6 +3898,8 @@ cleanup_ib:
goto cleanup_wifi;
if (!check_mac (cloned_mac, ARPHRD_ETHER, "cloned-mac", error))
goto cleanup_wifi;
if (!check_wifi_mode (&mode, error))
goto cleanup_wifi;
/* Add wifi setting */
s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
......@@ -3846,6 +3914,9 @@ cleanup_ib:
g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS, mac, NULL);
if (cloned_mac)
g_object_set (s_wifi, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, cloned_mac, NULL);
if (mode)
g_object_set (s_wifi, NM_SETTING_WIRELESS_MODE, mode, NULL);
g_bytes_unref (ssid_bytes);
success = TRUE;
......@@ -3854,6 +3925,7 @@ cleanup_wifi:
g_free (mtu);
g_free (mac);
g_free (cloned_mac);
g_free (mode);
if (!success)
return FALSE;
......@@ -5008,6 +5080,13 @@ gen_func_bool_values_l10n (const char *text, int state)
return nmc_rl_gen_func_basic (text, state, words);
}
static char *
gen_func_wifi_mode (const char *text, int state)
{
const char *words[] = { "infrastructure", "ap", "adhoc", NULL };
return nmc_rl_gen_func_basic (text, state, words);
}
static char *
gen_func_ib_type (const char *text, int state)
{
......@@ -5114,6 +5193,8 @@ nmcli_con_add_tab_completion (const char *text, int start, int end)
|| g_str_has_suffix (rl_prompt, prompt_yes_no (FALSE, NULL))
|| g_str_has_suffix (rl_prompt, prompt_yes_no (FALSE, ":")))
generator_func = gen_func_bool_values_l10n;
else if (g_str_has_suffix (rl_prompt, PROMPT_WIFI_MODE))
generator_func = gen_func_wifi_mode;
else if (g_str_has_suffix (rl_prompt, PROMPT_IB_MODE))
generator_func = gen_func_ib_type;
else if (g_str_has_suffix (rl_prompt, PROMPT_BT_TYPE))
......
......@@ -407,7 +407,14 @@ _nmcli_compl_ARGS()
;;
mode)
if [[ "${#words[@]}" -eq 2 ]]; then
_nmcli_list "balance-rr active-backup balance-xor broadcast 802.3ad balance-tlb balance-alb"
case "$OPTIONS_TYPE" in
"wifi")
_nmcli_list "infrastructure ap adhoc"
;;
"bond"| \
*)
_nmcli_list "balance-rr active-backup balance-xor broadcast 802.3ad balance-tlb balance-alb"
esac
return 0
fi
;;
......@@ -915,7 +922,7 @@ _nmcli()
802-11-w|802-11-wi|802-11-wir|802-11-wire|802-11-wirel|802-11-wirele|802-11-wireles|802-11-wireless| \
wif|wifi)
OPTIONS_TYPE=wifi
OPTIONS_TYPED=(ssid mac cloned-mac mtu)
OPTIONS_TYPED=(ssid mac cloned-mac mtu mode)
OPTIONS_MANDATORY=(ssid)
;;
wim|wima|wimax)
......
......@@ -540,6 +540,31 @@ nmc_util_strv_to_slist (char **strv)
return g_slist_reverse (list);
}
/*
* Convert string array (char **) to description string in the form of:
* "[string1, string2, ]"
*
* Returns: a newly allocated string. Caller must free it with g_free().
*/
char *
nmc_util_strv_for_display (const char **strv)
{
GString *result;
guint i = 0;
result = g_string_sized_new (150);
g_string_append_c (result, '[');
while (strv && strv[i]) {
if (result->len > 1)
g_string_append (result, ", ");
g_string_append (result, strv[i]);
i++;
}
g_string_append_c (result, ']');
return g_string_free (result, FALSE);
}
/*
* Wrapper function for g_strsplit_set() that removes empty strings
* from the vector as they are not useful in most cases.
......
......@@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2010 - 2014 Red Hat, Inc.
* Copyright 2010 - 2014 Red Hat, Inc.
*/
#ifndef NMC_UTILS_H
......@@ -72,6 +72,7 @@ char *nmc_get_user_input (const char *ask_str);
int nmc_string_to_arg_array (const char *line, const char *delim, char ***argv, int *argc);
const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
GSList *nmc_util_strv_to_slist (char **strv);
char * nmc_util_strv_for_display (const char **strv);
char **nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens);
int nmc_string_screen_width (const char *start, const char *end);
void set_val_str (NmcOutputField fields_array[], guint32 index, char *value);
......
......@@ -418,6 +418,8 @@ Note: use quotes around \fB*\fP to suppress shell expansion.
\(en MAC address of the device this connection is locked to
.IP "\fI[cloned-mac <cloned MAC address>]\fP" 42
\(en cloned MAC
.IP "\fI[mode infrastructure|ap|adhoc]\fP" 42
\(en Wi-Fi network mode. If blank, \fIinfrastructure\fP is assumed.
.IP "\fI[mtu <MTU>]\fP" 42
\(en MTU
.RE
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment