Merge branch 'lr/ap'

https://bugzilla.gnome.org/show_bug.cgi?id=738439
This commit is contained in:
Lubomir Rintel
2014-10-31 15:35:20 +01:00
8 changed files with 175 additions and 54 deletions

View File

@@ -336,7 +336,8 @@ usage_connection_add (void)
" wifi: ssid <SSID>\n" " wifi: ssid <SSID>\n"
" [mac <MAC address>]\n" " [mac <MAC address>]\n"
" [cloned-mac <cloned 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" " wimax: [mac <MAC address>]\n"
" [nsp <NSP>]\n\n" " [nsp <NSP>]\n\n"
" pppoe: username <PPPoE username>\n" " pppoe: username <PPPoE username>\n"
@@ -2582,29 +2583,66 @@ check_infiniband_p_key (const char *p_key, guint32 *p_key_int, GError **error)
return TRUE; 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 static gboolean
check_valid_enumeration (char **str,
const char *strings[],
const char *what,
const char *what_desc,
GError **error)
{
char *tmp;
const char *checked_str;
if (!str || !*str)
return TRUE;
tmp = g_strstrip (g_strdup (*str));
checked_str = nmc_string_is_valid (tmp, strings, NULL);
g_free (tmp);
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: '%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) check_infiniband_mode (char **mode, GError **error)
{ {
char *tmp;
const char *checked_mode;
const char *modes[] = { "datagram", "connected", NULL }; const char *modes[] = { "datagram", "connected", NULL };
if (!mode || !*mode) return check_valid_enumeration (mode, modes, "mode", _("InfiniBand transport mode"), error);
return TRUE;
tmp = g_strstrip (g_strdup (*mode));
checked_mode = nmc_string_is_valid (tmp, modes, NULL);
g_free (tmp);
if (checked_mode) {
g_free (*mode);
*mode = g_strdup (checked_mode);
} else
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;
} }
static gboolean static gboolean
@@ -2892,10 +2930,9 @@ do_questionnaire_ethernet (gboolean ethernet, char **mtu, char **mac, char **clo
{ {
gboolean once_more; gboolean once_more;
GError *error = NULL; GError *error = NULL;
const char *type = ethernet ? _("ethernet") : _("Wi-Fi");
/* Ask for optional arguments */ /* Ask for optional arguments */
if (!want_provide_opt_args (type, 3)) if (ethernet && !want_provide_opt_args (_("ethernet"), 3))
return; return;
if (!*mtu) { if (!*mtu) {
@@ -3010,11 +3047,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 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. */ gboolean once_more;
return do_questionnaire_ethernet (FALSE, mtu, mac, cloned_mac); 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 static void
@@ -3815,10 +3877,13 @@ cleanup_ib:
char *mac = NULL; char *mac = NULL;
const char *cloned_mac_c = NULL; const char *cloned_mac_c = NULL;
char *cloned_mac = NULL; char *cloned_mac = NULL;
const char *mode_c = NULL;
char *mode = NULL;
nmc_arg_t exp_args[] = { {"ssid", TRUE, &ssid, !ask}, nmc_arg_t exp_args[] = { {"ssid", TRUE, &ssid, !ask},
{"mtu", TRUE, &mtu_c, FALSE}, {"mtu", TRUE, &mtu_c, FALSE},
{"mac", TRUE, &mac_c, FALSE}, {"mac", TRUE, &mac_c, FALSE},
{"cloned-mac", TRUE, &cloned_mac_c, FALSE}, {"cloned-mac", TRUE, &cloned_mac_c, FALSE},
{"mode", TRUE, &mode_c, FALSE},
{NULL} }; {NULL} };
if (!nmc_parse_args (exp_args, FALSE, &argc, &argv, error)) if (!nmc_parse_args (exp_args, FALSE, &argc, &argv, error))
@@ -3836,8 +3901,9 @@ cleanup_ib:
mtu = mtu_c ? g_strdup (mtu_c) : NULL; mtu = mtu_c ? g_strdup (mtu_c) : NULL;
mac = mac_c ? g_strdup (mac_c) : NULL; mac = mac_c ? g_strdup (mac_c) : NULL;
cloned_mac = cloned_mac_c ? g_strdup (cloned_mac_c) : NULL; cloned_mac = cloned_mac_c ? g_strdup (cloned_mac_c) : NULL;
mode = mode_c ? g_strdup (mode_c) : NULL;
if (ask) 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)) if (!check_and_convert_mtu (mtu, &mtu_int, error))
goto cleanup_wifi; goto cleanup_wifi;
@@ -3845,6 +3911,8 @@ cleanup_ib:
goto cleanup_wifi; goto cleanup_wifi;
if (!check_mac (cloned_mac, ARPHRD_ETHER, "cloned-mac", error)) if (!check_mac (cloned_mac, ARPHRD_ETHER, "cloned-mac", error))
goto cleanup_wifi; goto cleanup_wifi;
if (!check_wifi_mode (&mode, error))
goto cleanup_wifi;
/* Add wifi setting */ /* Add wifi setting */
s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
@@ -3859,6 +3927,9 @@ cleanup_ib:
g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS, mac, NULL); g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS, mac, NULL);
if (cloned_mac) if (cloned_mac)
g_object_set (s_wifi, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, cloned_mac, NULL); 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); g_bytes_unref (ssid_bytes);
success = TRUE; success = TRUE;
@@ -3867,6 +3938,7 @@ cleanup_wifi:
g_free (mtu); g_free (mtu);
g_free (mac); g_free (mac);
g_free (cloned_mac); g_free (cloned_mac);
g_free (mode);
if (!success) if (!success)
return FALSE; return FALSE;
@@ -5021,6 +5093,13 @@ gen_func_bool_values_l10n (const char *text, int state)
return nmc_rl_gen_func_basic (text, state, words); 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 * static char *
gen_func_ib_type (const char *text, int state) gen_func_ib_type (const char *text, int state)
{ {
@@ -5127,6 +5206,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, NULL))
|| g_str_has_suffix (rl_prompt, prompt_yes_no (FALSE, ":"))) || g_str_has_suffix (rl_prompt, prompt_yes_no (FALSE, ":")))
generator_func = gen_func_bool_values_l10n; 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)) else if (g_str_has_suffix (rl_prompt, PROMPT_IB_MODE))
generator_func = gen_func_ib_type; generator_func = gen_func_ib_type;
else if (g_str_has_suffix (rl_prompt, PROMPT_BT_TYPE)) else if (g_str_has_suffix (rl_prompt, PROMPT_BT_TYPE))

View File

@@ -410,7 +410,14 @@ _nmcli_compl_ARGS()
;; ;;
mode) mode)
if [[ "${#words[@]}" -eq 2 ]]; then if [[ "${#words[@]}" -eq 2 ]]; then
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" _nmcli_list "balance-rr active-backup balance-xor broadcast 802.3ad balance-tlb balance-alb"
esac
return 0 return 0
fi fi
;; ;;
@@ -918,7 +925,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| \ 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) wif|wifi)
OPTIONS_TYPE=wifi OPTIONS_TYPE=wifi
OPTIONS_TYPED=(ssid mac cloned-mac mtu) OPTIONS_TYPED=(ssid mac cloned-mac mtu mode)
OPTIONS_MANDATORY=(ssid) OPTIONS_MANDATORY=(ssid)
;; ;;
wim|wima|wimax) wim|wima|wimax)

View File

@@ -540,6 +540,31 @@ nmc_util_strv_to_slist (char **strv)
return g_slist_reverse (list); 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 * Wrapper function for g_strsplit_set() that removes empty strings
* from the vector as they are not useful in most cases. * from the vector as they are not useful in most cases.

View File

@@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 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 #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); 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); const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
GSList *nmc_util_strv_to_slist (char **strv); 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); char **nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens);
int nmc_string_screen_width (const char *start, const char *end); int nmc_string_screen_width (const char *start, const char *end);
void set_val_str (NmcOutputField fields_array[], guint32 index, char *value); void set_val_str (NmcOutputField fields_array[], guint32 index, char *value);

View File

@@ -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 \(en MAC address of the device this connection is locked to
.IP "\fI[cloned-mac <cloned MAC address>]\fP" 42 .IP "\fI[cloned-mac <cloned MAC address>]\fP" 42
\(en cloned MAC \(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 .IP "\fI[mtu <MTU>]\fP" 42
\(en MTU \(en MTU
.RE .RE

View File

@@ -1036,9 +1036,8 @@ complete_connection (NMDevice *device,
nm_connection_add_setting (connection, NM_SETTING (s_wifi)); nm_connection_add_setting (connection, NM_SETTING (s_wifi));
} }
if (ap) { if (ap)
ssid = nm_ap_get_ssid (ap); ssid = nm_ap_get_ssid (ap);
if (ssid == NULL) { if (ssid == NULL) {
/* The AP must be hidden. Connecting to a WiFi AP requires the SSID /* The AP must be hidden. Connecting to a WiFi AP requires the SSID
* as part of the initial handshake, so check the connection details * as part of the initial handshake, so check the connection details
@@ -1061,10 +1060,13 @@ complete_connection (NMDevice *device,
g_set_error_literal (error, g_set_error_literal (error,
NM_DEVICE_ERROR, NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INVALID_CONNECTION, NM_DEVICE_ERROR_INVALID_CONNECTION,
"A 'wireless' setting with a valid SSID is required for hidden access points."); ap
? "A 'wireless' setting with a valid SSID is required for hidden access points."
: "Cannot create 'wireless' setting due to missing SSID.");
return FALSE; return FALSE;
} }
if (ap) {
/* If the SSID is a well-known SSID, lock the connection to the AP's /* If the SSID is a well-known SSID, lock the connection to the AP's
* specific BSSID so NM doesn't autoconnect to some random wifi net. * specific BSSID so NM doesn't autoconnect to some random wifi net.
*/ */
@@ -1093,7 +1095,6 @@ complete_connection (NMDevice *device,
return FALSE; return FALSE;
} }
g_assert (ssid);
str_ssid = nm_utils_ssid_to_utf8 (ssid->data, ssid->len); str_ssid = nm_utils_ssid_to_utf8 (ssid->data, ssid->len);
nm_utils_complete_generic (connection, nm_utils_complete_generic (connection,

View File

@@ -3379,11 +3379,13 @@ make_wireless_setting (shvarFile *ifcfg,
if (!strcmp (lcase, "ad-hoc")) { if (!strcmp (lcase, "ad-hoc")) {
mode = "adhoc"; mode = "adhoc";
} else if (!strcmp (lcase, "ap")) {
mode = "ap";
} else if (!strcmp (lcase, "managed") || !strcmp (lcase, "auto")) { } else if (!strcmp (lcase, "managed") || !strcmp (lcase, "auto")) {
mode = "infrastructure"; mode = "infrastructure";
} else { } else {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid mode '%s' (not 'Ad-Hoc', 'Managed', or 'Auto')", "Invalid mode '%s' (not 'Ad-Hoc', 'Ap', 'Managed', or 'Auto')",
lcase); lcase);
g_free (lcase); g_free (lcase);
goto error; goto error;

View File

@@ -901,6 +901,8 @@ write_wireless_setting (NMConnection *connection,
} else if (!strcmp (mode, "adhoc")) { } else if (!strcmp (mode, "adhoc")) {
svSetValue (ifcfg, "MODE", "Ad-Hoc", FALSE); svSetValue (ifcfg, "MODE", "Ad-Hoc", FALSE);
adhoc = TRUE; adhoc = TRUE;
} else if (!strcmp (mode, "ap")) {
svSetValue (ifcfg, "MODE", "Ap", FALSE);
} else { } else {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"Invalid mode '%s' in '%s' setting", "Invalid mode '%s' in '%s' setting",