[network-manager-applet] editor: pppoe: add support for new-style pppoe connections



commit 3c83f844ced4f620993054cddb19b22fe459fa0b
Author: Beniamino Galvani <bgalvani redhat com>
Date:   Mon Aug 7 18:14:46 2017 +0200

    editor: pppoe: add support for new-style pppoe connections
    
    Add support for the new type of pppoe connections that have an
    arbitrary parent device type. When libnm does not support the new
    PPPoE 'parent' property, we keep the previous behavior.
    
    When libnm is new enough and we find an old-style connection, its
    'interface-name' is used as parent interface and we pick an unused ppp
    interface name. In this way, old connections are converted to the new
    convention upon save.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=559134

 src/connection-editor/ce-page-dsl.ui         |   72 ++++++++++++--
 src/connection-editor/nm-connection-editor.c |    2 -
 src/connection-editor/page-dsl.c             |  134 +++++++++++++++++++++++++-
 3 files changed, 193 insertions(+), 15 deletions(-)
---
diff --git a/src/connection-editor/ce-page-dsl.ui b/src/connection-editor/ce-page-dsl.ui
index 47b174d..b29e439 100644
--- a/src/connection-editor/ce-page-dsl.ui
+++ b/src/connection-editor/ce-page-dsl.ui
@@ -20,7 +20,7 @@
       </object>
       <packing>
         <property name="left_attach">0</property>
-        <property name="top_attach">0</property>
+        <property name="top_attach">2</property>
       </packing>
     </child>
     <child>
@@ -31,7 +31,7 @@
       </object>
       <packing>
         <property name="left_attach">1</property>
-        <property name="top_attach">0</property>
+        <property name="top_attach">2</property>
       </packing>
     </child>
     <child>
@@ -42,7 +42,7 @@
       </object>
       <packing>
         <property name="left_attach">1</property>
-        <property name="top_attach">1</property>
+        <property name="top_attach">3</property>
       </packing>
     </child>
     <child>
@@ -56,7 +56,7 @@
       </object>
       <packing>
         <property name="left_attach">0</property>
-        <property name="top_attach">1</property>
+        <property name="top_attach">3</property>
       </packing>
     </child>
     <child>
@@ -71,7 +71,7 @@
       </object>
       <packing>
         <property name="left_attach">1</property>
-        <property name="top_attach">3</property>
+        <property name="top_attach">5</property>
       </packing>
     </child>
     <child>
@@ -82,7 +82,7 @@
       </object>
       <packing>
         <property name="left_attach">1</property>
-        <property name="top_attach">2</property>
+        <property name="top_attach">4</property>
       </packing>
     </child>
     <child>
@@ -96,9 +96,65 @@
       </object>
       <packing>
         <property name="left_attach">0</property>
-        <property name="top_attach">2</property>
+        <property name="top_attach">4</property>
       </packing>
     </child>
-    <placeholder/>
+    <child>
+      <object class="GtkLabel" id="dsl_interface_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">PPP _interface:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">dsl_interface</property>
+        <property name="xalign">0</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">P_arent interface:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">dsl_parent</property>
+        <property name="xalign">0</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkEntry" id="dsl_interface">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkComboBoxText" id="dsl_parent">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="has_entry">True</property>
+        <child internal-child="entry">
+          <object class="GtkEntry">
+            <property name="can_focus">True</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">0</property>
+      </packing>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
   </object>
 </interface>
diff --git a/src/connection-editor/nm-connection-editor.c b/src/connection-editor/nm-connection-editor.c
index 208f39d..e6f2ccf 100644
--- a/src/connection-editor/nm-connection-editor.c
+++ b/src/connection-editor/nm-connection-editor.c
@@ -998,8 +998,6 @@ nm_connection_editor_set_connection (NMConnectionEditor *editor,
        } else if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
                if (!add_page (editor, ce_page_dsl_new, editor->connection, error))
                        goto out;
-               if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
-                       goto out;
                if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
                        goto out;
        } else if (!strcmp (connection_type, NM_SETTING_GSM_SETTING_NAME) || 
diff --git a/src/connection-editor/page-dsl.c b/src/connection-editor/page-dsl.c
index b5e6255..438f46c 100644
--- a/src/connection-editor/page-dsl.c
+++ b/src/connection-editor/page-dsl.c
@@ -23,9 +23,11 @@
 #include "nm-default.h"
 
 #include <string.h>
+#include <linux/if.h>
 
 #include "page-dsl.h"
 #include "nm-connection-editor.h"
+#include "nm-utils/nm-shared-utils.h"
 
 G_DEFINE_TYPE (CEPageDsl, ce_page_dsl, CE_TYPE_PAGE)
 
@@ -34,11 +36,47 @@ G_DEFINE_TYPE (CEPageDsl, ce_page_dsl, CE_TYPE_PAGE)
 typedef struct {
        NMSettingPppoe *setting;
 
+       GtkComboBoxText *parent;
+       GtkEntry *interface;
+       GtkLabel *interface_label;
+
        GtkEntry *username;
        GtkEntry *password;
        GtkEntry *service;
 } CEPageDslPrivate;
 
+/* The parent property is available in libnm 1.10, but since we only
+ * require 1.8 at the moment, enable it only when detected at runtime.
+ */
+static gboolean parent_supported;
+
+static void
+find_unused_interface_name (NMClient *client, char *buf, gsize size)
+{
+       const GPtrArray *connections;
+       NMConnection *con;
+       const char *iface;
+       gint64 num, ppp_num = 0;
+       int i;
+
+       connections = nm_client_get_connections (client);
+       for (i = 0; i < connections->len; i++) {
+               con = connections->pdata[i];
+
+               if (!nm_connection_is_type (con, NM_SETTING_PPPOE_SETTING_NAME))
+                       continue;
+
+               iface = nm_connection_get_interface_name (con);
+               if (iface && g_str_has_prefix (iface, "ppp")) {
+                       num = _nm_utils_ascii_str_to_int64 (iface + 3, 10, 0, G_MAXUINT32, -1);
+                       if (num >= ppp_num)
+                               ppp_num = num + 1;
+               }
+       }
+
+       g_snprintf (buf, size, "ppp%u", (unsigned) ppp_num);
+}
+
 static void
 dsl_private_init (CEPageDsl *self)
 {
@@ -47,6 +85,9 @@ dsl_private_init (CEPageDsl *self)
 
        builder = CE_PAGE (self)->builder;
 
+       priv->parent = GTK_COMBO_BOX_TEXT (gtk_builder_get_object (builder, "dsl_parent"));
+       priv->interface = GTK_ENTRY (gtk_builder_get_object (builder, "dsl_interface"));
+       priv->interface_label = GTK_LABEL (gtk_builder_get_object (builder, "dsl_interface_label"));
        priv->username = GTK_ENTRY (gtk_builder_get_object (builder, "dsl_username"));
        priv->password = GTK_ENTRY (gtk_builder_get_object (builder, "dsl_password"));
        priv->service = GTK_ENTRY (gtk_builder_get_object (builder, "dsl_service"));
@@ -57,7 +98,38 @@ populate_ui (CEPageDsl *self, NMConnection *connection)
 {
        CEPageDslPrivate *priv = CE_PAGE_DSL_GET_PRIVATE (self);
        NMSettingPppoe *setting = priv->setting;
-       const char *str;
+       gs_free char *parent = NULL;
+       const char *str = NULL;
+       char ifname[IFNAMSIZ];
+
+       gtk_widget_set_visible (GTK_WIDGET (priv->interface), parent_supported);
+       gtk_widget_set_visible (GTK_WIDGET (priv->interface_label), parent_supported);
+
+       if (parent_supported)
+               g_object_get (setting, "parent", &parent, NULL);
+
+       if (parent) {
+               ce_page_setup_device_combo (CE_PAGE (self), GTK_COMBO_BOX (priv->parent),
+                                           G_TYPE_NONE, parent,
+                                           NULL, NULL);
+
+               str = nm_connection_get_interface_name (CE_PAGE (self)->connection);
+               if (str)
+                       gtk_entry_set_text (priv->interface, str);
+       } else {
+               str = nm_connection_get_interface_name (CE_PAGE (self)->connection);
+               ce_page_setup_device_combo (CE_PAGE (self), GTK_COMBO_BOX (priv->parent),
+                                           G_TYPE_NONE, str,
+                                           NULL, NULL);
+       }
+
+       if (parent_supported) {
+               str = gtk_entry_get_text (priv->interface);
+               if (!str || !str[0]) {
+                       find_unused_interface_name (CE_PAGE (self)->client, ifname, sizeof (ifname));
+                       gtk_entry_set_text (priv->interface, ifname);
+               }
+       }
 
        str = nm_setting_pppoe_get_username (setting);
        if (str)
@@ -98,6 +170,8 @@ finish_setup (CEPageDsl *self, gpointer unused, GError *error, gpointer user_dat
 
        populate_ui (self, parent->connection);
 
+       g_signal_connect (priv->parent, "changed", G_CALLBACK (stuff_changed), self);
+       g_signal_connect (priv->interface, "changed", G_CALLBACK (stuff_changed), self);
        g_signal_connect (priv->username, "changed", G_CALLBACK (stuff_changed), self);
        g_signal_connect (priv->password, "changed", G_CALLBACK (stuff_changed), self);
        g_signal_connect (priv->service, "changed", G_CALLBACK (stuff_changed), self);
@@ -150,9 +224,42 @@ static void
 ui_to_setting (CEPageDsl *self)
 {
        CEPageDslPrivate *priv = CE_PAGE_DSL_GET_PRIVATE (self);
-       const char *username;
-       const char *password;
-       const char *service;
+       const char *interface, *username, *password, *service;
+       gs_free char *parent = NULL;
+       NMSettingConnection *s_con;
+       GtkWidget *entry;
+
+       s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
+       g_return_if_fail (s_con);
+
+       if (parent_supported) {
+               interface = gtk_entry_get_text (priv->interface);
+               g_object_set (s_con,
+                             NM_SETTING_CONNECTION_INTERFACE_NAME,
+                             interface && interface[0] ? interface : NULL,
+                             NULL);
+
+               nm_connection_remove_setting (CE_PAGE (self)->connection, NM_TYPE_SETTING_WIRED);
+
+               entry = gtk_bin_get_child (GTK_BIN (priv->parent));
+               if (entry) {
+                       ce_page_device_entry_get (GTK_ENTRY (entry), ARPHRD_ETHER, TRUE,
+                                                 &parent, NULL, NULL, NULL);
+               }
+               g_object_set (priv->setting,
+                             "parent", parent,
+                             NULL);
+       } else {
+               entry = gtk_bin_get_child (GTK_BIN (priv->parent));
+               if (entry) {
+                       ce_page_device_entry_get (GTK_ENTRY (entry), ARPHRD_ETHER, TRUE,
+                                                 &parent, NULL, NULL, NULL);
+               }
+               g_object_set (s_con,
+                             NM_SETTING_CONNECTION_INTERFACE_NAME,
+                             parent && parent[0] ? parent : NULL,
+                             NULL);
+       }
 
        username = gtk_entry_get_text (priv->username);
        if (username && strlen (username) < 1)
@@ -178,6 +285,21 @@ ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
 {
        CEPageDsl *self = CE_PAGE_DSL (page);
        CEPageDslPrivate *priv = CE_PAGE_DSL_GET_PRIVATE (self);
+       gs_free char *parent = NULL;
+       GtkWidget *entry;
+
+       if (parent_supported) {
+               entry = gtk_bin_get_child (GTK_BIN (priv->parent));
+               if (entry) {
+                       ce_page_device_entry_get (GTK_ENTRY (entry), ARPHRD_ETHER, TRUE,
+                                                 &parent, NULL, NULL, NULL);
+                       if (!parent || !parent[0]) {
+                               g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC,
+                                                    _("missing parent interface"));
+                               return FALSE;
+                       }
+               }
+       }
 
        ui_to_setting (self);
        return nm_setting_verify (NM_SETTING (priv->setting), connection, error);
@@ -198,8 +320,10 @@ ce_page_dsl_class_init (CEPageDslClass *dsl_class)
 
        /* virtual methods */
        parent_class->ce_page_validate_v = ce_page_validate_v;
-}
 
+       parent_supported = !!nm_g_object_class_find_property_from_gtype (NM_TYPE_SETTING_PPPOE,
+                                                                        "parent");
+}
 
 void
 dsl_connection_new (FUNC_TAG_PAGE_NEW_CONNECTION_IMPL,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]