cli: allow creating ADSL connections with 'nmcli connection add' (rh #1264089)
authorJiří Klimeš <jklimes@redhat.com>
Fri, 18 Sep 2015 10:05:49 +0000 (12:05 +0200)
committerJiří Klimeš <jklimes@redhat.com>
Mon, 21 Sep 2015 13:21:51 +0000 (15:21 +0200)
https://bugzilla.redhat.com/show_bug.cgi?id=1264089

clients/cli/connections.c
clients/cli/nmcli-completion
man/nmcli.1.in

index 083105b..cd4fb5f 100644 (file)
@@ -390,6 +390,10 @@ usage_connection_add (void)
                      "    olpc-mesh:    ssid <SSID>\n"
                      "                  [channel <1-13>]\n"
                      "                  [dhcp-anycast <MAC address>]\n\n"
+                     "    adsl:         username <username>\n"
+                     "                  protocol pppoa|pppoe|ipoatm\n"
+                     "                  [password <password>]\n"
+                     "                  [encapsulation vcmux|llc]\n\n"
                      "  SLAVE_OPTIONS:\n"
                      "    bridge:       [priority <0-63>]\n"
                      "                  [path-cost <1-65535>]\n"
@@ -3022,6 +3026,29 @@ check_infiniband_mode (char **mode, GError **error)
        return check_valid_enumeration (mode, modes, "mode", _("InfiniBand transport mode"), error);
 }
 
+/* Checks ADSL protocol */
+static gboolean
+check_adsl_protocol (char **protocol, GError **error)
+{
+       const char *protos[] = { NM_SETTING_ADSL_PROTOCOL_PPPOA,
+                                NM_SETTING_ADSL_PROTOCOL_PPPOE,
+                                NM_SETTING_ADSL_PROTOCOL_IPOATM,
+                                NULL };
+
+       return check_valid_enumeration (protocol, protos, "protocol", _("ADSL protocol"), error);
+}
+
+/* Checks ADSL encapsulation */
+static gboolean
+check_adsl_encapsulation (char **encapsulation, GError **error)
+{
+       const char *modes[] = { NM_SETTING_ADSL_ENCAPSULATION_VCMUX,
+                               NM_SETTING_ADSL_ENCAPSULATION_LLC,
+                               NULL };
+
+       return check_valid_enumeration (encapsulation, modes, "encapsulation", _("ADSL encapsulation"), error);
+}
+
 static gboolean
 check_and_convert_vlan_flags (const char *flags, guint32 *flags_int, GError **error)
 {
@@ -4027,6 +4054,33 @@ do_questionnaire_olpc (char **channel, char **dhcp_anycast)
        }
 }
 
+#define PROMPT_ADSL_ENCAP "(" NM_SETTING_ADSL_ENCAPSULATION_VCMUX "/" NM_SETTING_ADSL_ENCAPSULATION_LLC ") [none]: "
+static void
+do_questionnaire_adsl (char **password, char **encapsulation)
+{
+       gboolean once_more;
+       GError *error = NULL;
+
+       /* Ask for optional 'adsl' arguments. */
+       if (!want_provide_opt_args (_("ADSL"), 2))
+               return;
+
+       if (!*password)
+               *password = nmc_readline (_("Password [none]: "));
+
+       if (!*encapsulation) {
+               do {
+                       *encapsulation = nmc_readline (_("ADSL encapsulation %s"), PROMPT_ADSL_ENCAP);
+                       once_more = !check_adsl_encapsulation (encapsulation, &error);
+                       if (once_more) {
+                               g_print ("%s\n", error->message);
+                               g_clear_error (&error);
+                               g_free (*encapsulation);
+                       }
+               } while (once_more);
+       }
+}
+
 static gboolean
 split_address (char* str, char **ip, char **rest)
 {
@@ -4385,6 +4439,7 @@ complete_connection_by_type (NMConnection *connection,
        NMSettingBridgePort *s_bridge_port;
        NMSettingVpn *s_vpn;
        NMSettingOlpcMesh *s_olpc_mesh;
+       NMSettingAdsl *s_adsl;
        const char *slave_type;
 
        g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@@ -5429,6 +5484,74 @@ cleanup_olpc:
                if (!success)
                        return FALSE;
 
+       } else if (!strcmp (con_type, NM_SETTING_ADSL_SETTING_NAME)) {
+               /* Build up the settings required for 'adsl' */
+               gboolean success = FALSE;
+               char *username_ask = NULL;
+               const char *username = NULL;
+               char *protocol_ask = NULL;
+               const char *protocol = NULL;
+               const char *password_c = NULL;
+               char *password = NULL;
+               const char *encapsulation_c = NULL;
+               char *encapsulation = NULL;
+               nmc_arg_t exp_args[] = { {"username",      TRUE, &username,        !ask},
+                                        {"protocol",      TRUE, &protocol,        !ask},
+                                        {"password",      TRUE, &password_c,      FALSE},
+                                        {"encapsulation", TRUE, &encapsulation_c, FALSE},
+                                        {NULL} };
+
+               if (!nmc_parse_args (exp_args, FALSE, &argc, &argv, error))
+                       return FALSE;
+
+               if (!username && ask)
+                       username = username_ask = nmc_readline (_("Username: "));
+               if (!username) {
+                       g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
+                                            _("Error: 'username' is required."));
+                       goto cleanup_adsl;
+               }
+
+#define PROMPT_ADSL_PROTO "(" NM_SETTING_ADSL_PROTOCOL_PPPOA "/" NM_SETTING_ADSL_PROTOCOL_PPPOE "/" NM_SETTING_ADSL_PROTOCOL_IPOATM "): "
+               if (!protocol && ask)
+                       protocol = protocol_ask = nmc_readline (_("Protocol %s"), PROMPT_ADSL_PROTO);
+               if (!protocol) {
+                       g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
+                                            _("Error: 'protocol' is required."));
+                       goto cleanup_adsl;
+               }
+               if (!check_adsl_protocol (&protocol_ask, error))
+                       goto cleanup_adsl;
+
+               /* Also ask for all optional arguments if '--ask' is specified. */
+               password = g_strdup (password_c);
+               encapsulation = g_strdup (encapsulation_c);
+               if (ask)
+                       do_questionnaire_adsl (&password, &encapsulation);
+
+               if (!check_adsl_encapsulation (&encapsulation, error))
+                       goto cleanup_adsl;
+
+               /* Add ADSL setting */
+               s_adsl = (NMSettingAdsl *) nm_setting_adsl_new ();
+               nm_connection_add_setting (connection, NM_SETTING (s_adsl));
+
+               g_object_set (s_adsl,
+                             NM_SETTING_ADSL_USERNAME, username,
+                             NM_SETTING_ADSL_PROTOCOL, protocol,
+                             NM_SETTING_ADSL_PASSWORD, password,
+                             NM_SETTING_ADSL_ENCAPSULATION, encapsulation,
+                             NULL);
+
+               success = TRUE;
+cleanup_adsl:
+               g_free (username_ask);
+               g_free (password);
+               g_free (protocol_ask);
+               g_free (encapsulation);
+               if (!success)
+                       return FALSE;
+
        } else if (!strcmp (con_type, NM_SETTING_GENERIC_SETTING_NAME)) {
                /* Add 'generic' setting */
                s_generic = (NMSettingGeneric *) nm_setting_generic_new ();
@@ -5812,6 +5935,20 @@ gen_func_bond_mon_mode (const char *text, int state)
        return nmc_rl_gen_func_basic (text, state, words);
 }
 
+static char *
+gen_func_adsl_proto (const char *text, int state)
+{
+       const char *words[] = { "pppoe", "pppoa", "ipoatm", NULL };
+       return nmc_rl_gen_func_basic (text, state, words);
+}
+
+static char *
+gen_func_adsl_encap (const char *text, int state)
+{
+       const char *words[] = { "vcmux", "llc", NULL };
+       return nmc_rl_gen_func_basic (text, state, words);
+}
+
 static char *
 gen_func_master_ifnames (const char *text, int state)
 {
@@ -5898,6 +6035,10 @@ nmcli_con_add_tab_completion (const char *text, int start, int end)
                generator_func = gen_func_bond_mode;
        else if (g_str_has_suffix (rl_prompt, PROMPT_BOND_MON_MODE))
                generator_func = gen_func_bond_mon_mode;
+       else if (g_str_has_suffix (rl_prompt, PROMPT_ADSL_PROTO))
+               generator_func = gen_func_adsl_proto;
+       else if (g_str_has_suffix (rl_prompt, PROMPT_ADSL_ENCAP))
+               generator_func = gen_func_adsl_encap;
 
        if (generator_func)
                match_array = rl_completion_matches (text, generator_func);
index 909c00e..2f0ccd8 100644 (file)
@@ -387,7 +387,7 @@ _nmcli_compl_ARGS()
                         # user friendly. Only complete them, if the current word already starts with an "8".
                         _nmcli_list "802-3-ethernet 802-11-wireless 802-11-olpc-mesh"
                     else
-                        _nmcli_list "ethernet wifi wimax gsm cdma infiniband bluetooth vpn olpc-mesh vlan bond bridge team pppoe"
+                        _nmcli_list "ethernet wifi wimax gsm cdma infiniband bluetooth vpn olpc-mesh vlan bond bridge team pppoe adsl"
                     fi
                     return 0
                 fi
@@ -563,6 +563,18 @@ _nmcli_compl_ARGS()
                     return 0
                 fi
                 ;;
+            encapsulation)
+                if [[ "${#words[@]}" -eq 2 ]]; then
+                    _nmcli_list "vcmux llc"
+                    return 0
+                fi
+                ;;
+            protocol)
+                if [[ "${#words[@]}" -eq 2 ]]; then
+                    _nmcli_list "pppoa pppoe ipoatm"
+                    return 0
+                fi
+                ;;
             *)
                 return 1
                 ;;
@@ -1054,6 +1066,11 @@ _nmcli()
                                     OPTIONS_TYPED=(username password service mtu mac)
                                     OPTIONS_MANDATORY=(username)
                                     ;;
+                                a|ad|ads|adsl)
+                                    OPTIONS_TYPE=adsl
+                                    OPTIONS_TYPED=(username password protocol encapsulation)
+                                    OPTIONS_MANDATORY=(username protocol)
+                                    ;;
                                 *)
                                     # for an unknown connection type, we stop completion here
                                     return 0
index 15781c4..464f23c 100644 (file)
@@ -639,6 +639,18 @@ The value can be prefixed with \fBifname/\fP, \fBuuid/\fP or \fBid/\fP to disamb
 .RE
 .RS
 .TP
+.B adsl:
+.IP "\fIusername <username>\fP" 42
+\(en ADSL user name
+.IP "\fIprotocol pppoa|pppoe|ipoatm\fP" 42
+\(en ADSL protocol
+.IP "\fI[password <password>]\fP" 42
+\(en ADSL password
+.IP "\fI[encapsulation vcmux|llc]\fP" 42
+\(en ADSL encapsulation
+.RE
+.RS
+.TP
 .B SLAVE_OPTIONS:
 .RE
 .RS