summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2017-08-05 08:05:14 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2017-08-05 08:05:14 +0200
commit220a329feaa79d535da0abcc10f94ebbe7f7be78 (patch)
tree4c88c3850717c43d3be3c5083904e915ce322de3
parent6da63230801cadd978d4a992e6825c5c2adc3324 (diff)
parent74bf32ff9a672008017c23696c0eb7e9e02e6198 (diff)
ppp: merge branch 'bg/ppp-bgo559134'
Support for PPPoE on arbitrary devices. https://bugzilla.gnome.org/show_bug.cgi?id=559134
-rw-r--r--Makefile.am8
-rw-r--r--clients/common/nm-meta-setting-desc.c6
-rw-r--r--clients/common/settings-docs.c.in1
-rw-r--r--introspection/org.freedesktop.NetworkManager.Device.Ppp.xml20
-rw-r--r--libnm-core/nm-connection.c7
-rw-r--r--libnm-core/nm-dbus-interface.h3
-rw-r--r--libnm-core/nm-setting-pppoe.c55
-rw-r--r--libnm-core/nm-setting-pppoe.h3
-rw-r--r--libnm/libnm.ver2
-rw-r--r--libnm/nm-client.c3
-rw-r--r--libnm/nm-device-ppp.c39
-rw-r--r--libnm/nm-device-ppp.h36
-rw-r--r--libnm/nm-device.c3
-rw-r--r--libnm/nm-types.h1
-rw-r--r--src/devices/bluetooth/nm-bluez-manager.c17
-rw-r--r--src/devices/nm-device-bridge.c18
-rw-r--r--src/devices/nm-device-ethernet.c22
-rw-r--r--src/devices/nm-device-factory.c59
-rw-r--r--src/devices/nm-device-factory.h8
-rw-r--r--src/devices/nm-device-ppp.c337
-rw-r--r--src/devices/nm-device-ppp.h30
-rw-r--r--src/devices/nm-device-private.h2
-rw-r--r--src/devices/nm-device.c42
-rw-r--r--src/nm-manager.c18
-rw-r--r--src/nm-manager.h2
-rw-r--r--src/nm-types.h5
-rw-r--r--src/platform/nm-linux-platform.c29
-rw-r--r--src/platform/nm-platform.c24
-rw-r--r--src/platform/nm-platform.h2
-rw-r--r--src/ppp/nm-ppp-manager.c10
30 files changed, 774 insertions, 38 deletions
diff --git a/Makefile.am b/Makefile.am
index ed9417a4d6..4e66a5e68b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -206,6 +206,8 @@ introspection_sources = \
introspection/org.freedesktop.NetworkManager.Device.Modem.h \
introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.c \
introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.h \
+ introspection/org.freedesktop.NetworkManager.Device.Ppp.c \
+ introspection/org.freedesktop.NetworkManager.Device.Ppp.h \
introspection/org.freedesktop.NetworkManager.Device.Statistics.c \
introspection/org.freedesktop.NetworkManager.Device.Statistics.h \
introspection/org.freedesktop.NetworkManager.Device.Team.c \
@@ -279,6 +281,7 @@ DBUS_INTERFACE_DOCS = \
docs/api/dbus-org.freedesktop.NetworkManager.Device.Tun.xml \
docs/api/dbus-org.freedesktop.NetworkManager.Device.Bridge.xml \
docs/api/dbus-org.freedesktop.NetworkManager.Device.OlpcMesh.xml \
+ docs/api/dbus-org.freedesktop.NetworkManager.Device.Ppp.xml \
docs/api/dbus-org.freedesktop.NetworkManager.DHCP4Config.xml \
docs/api/dbus-org.freedesktop.NetworkManager.Device.Generic.xml \
docs/api/dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml \
@@ -326,6 +329,7 @@ dbusinterfaces_DATA = \
introspection/org.freedesktop.NetworkManager.Device.Macvlan.xml \
introspection/org.freedesktop.NetworkManager.Device.Modem.xml \
introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.xml \
+ introspection/org.freedesktop.NetworkManager.Device.Ppp.xml \
introspection/org.freedesktop.NetworkManager.Device.Statistics.xml \
introspection/org.freedesktop.NetworkManager.Device.Team.xml \
introspection/org.freedesktop.NetworkManager.Device.Tun.xml \
@@ -721,6 +725,7 @@ libnm_lib_h_pub_real = \
libnm/nm-device-macvlan.h \
libnm/nm-device-modem.h \
libnm/nm-device-olpc-mesh.h \
+ libnm/nm-device-ppp.h \
libnm/nm-device-team.h \
libnm/nm-device-tun.h \
libnm/nm-device-vlan.h \
@@ -773,6 +778,7 @@ libnm_lib_c_real = \
libnm/nm-device-macvlan.c \
libnm/nm-device-modem.c \
libnm/nm-device-olpc-mesh.c \
+ libnm/nm-device-ppp.c \
libnm/nm-device-team.c \
libnm/nm-device-tun.c \
libnm/nm-device-vlan.c \
@@ -1388,6 +1394,8 @@ src_libNetworkManager_la_SOURCES = \
src/devices/nm-device-macsec.h \
src/devices/nm-device-macvlan.c \
src/devices/nm-device-macvlan.h \
+ src/devices/nm-device-ppp.c \
+ src/devices/nm-device-ppp.h \
src/devices/nm-device-tun.c \
src/devices/nm-device-tun.h \
src/devices/nm-device-veth.c \
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index 0928374eb2..9d68b23334 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -5789,6 +5789,12 @@ static const NMMetaPropertyInfo *const property_infos_OLPC_MESH[] = {
#undef _CURRENT_NM_META_SETTING_TYPE
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_PPPOE
static const NMMetaPropertyInfo *const property_infos_PPPOE[] = {
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PARENT,
+ .is_cli_option = TRUE,
+ .property_alias = "parent",
+ .prompt = N_("PPPoE parent device"),
+ .property_type = &_pt_gobject_string,
+ ),
PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_SERVICE,
.is_cli_option = TRUE,
.property_alias = "service",
diff --git a/clients/common/settings-docs.c.in b/clients/common/settings-docs.c.in
index a8afff5c0a..a4412270ac 100644
--- a/clients/common/settings-docs.c.in
+++ b/clients/common/settings-docs.c.in
@@ -280,6 +280,7 @@
#define DESCRIBE_DOC_NM_SETTING_PPP_REQUIRE_MPPE N_("If TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for the PPP session. If either 64-bit or 128-bit MPPE is not available the session will fail. Note that MPPE is not used on mobile broadband connections.")
#define DESCRIBE_DOC_NM_SETTING_PPP_REQUIRE_MPPE_128 N_("If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be required for the PPP session, and the \"require-mppe\" property must also be set to TRUE. If 128-bit MPPE is not available the session will fail.")
#define DESCRIBE_DOC_NM_SETTING_PPPOE_NAME N_("The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
+#define DESCRIBE_DOC_NM_SETTING_PPPOE_PARENT N_("If given, specifies the parent interface name on which this PPPoE connection should be created. If this property is not specified, the connection is activated on the interface specified in \"interface-name\" of NMSettingConnection.")
#define DESCRIBE_DOC_NM_SETTING_PPPOE_PASSWORD N_("Password used to authenticate with the PPPoE service.")
#define DESCRIBE_DOC_NM_SETTING_PPPOE_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
#define DESCRIBE_DOC_NM_SETTING_PPPOE_SERVICE N_("If specified, instruct PPPoE to only initiate sessions with access concentrators that provide the specified service. For most providers, this should be left blank. It is only required if there are multiple access concentrators or a specific service is known to be required.")
diff --git a/introspection/org.freedesktop.NetworkManager.Device.Ppp.xml b/introspection/org.freedesktop.NetworkManager.Device.Ppp.xml
new file mode 100644
index 0000000000..00605f7219
--- /dev/null
+++ b/introspection/org.freedesktop.NetworkManager.Device.Ppp.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/">
+ <!--
+ org.freedesktop.NetworkManager.Device.Ppp:
+ @short_description: PPP Device
+
+ -->
+ <interface name="org.freedesktop.NetworkManager.Device.Ppp">
+
+ <!--
+ PropertiesChanged:
+ @properties: A dictionary mapping property names to variant boxed values
+
+ DEPRECATED. Use the standard "PropertiesChanged" signal from "org.freedesktop.DBus.Properties" instead which exists since version NetworkManager 1.2.0.
+ -->
+ <signal name="PropertiesChanged">
+ <arg name="properties" type="a{sv}"/>
+ </signal>
+ </interface>
+</node>
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index e41e6b6662..d2e528420e 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -1952,6 +1952,13 @@ nm_connection_is_virtual (NMConnection *connection)
if (nm_streq (type, NM_SETTING_BLUETOOTH_SETTING_NAME))
return !!_nm_connection_get_setting_bluetooth_for_nap (connection);
+ if (nm_streq (type, NM_SETTING_PPPOE_SETTING_NAME)) {
+ NMSettingPppoe *s_pppoe;
+
+ s_pppoe = nm_connection_get_setting_pppoe (connection);
+ return !!nm_setting_pppoe_get_parent (s_pppoe);
+ }
+
return FALSE;
}
diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h
index dd05f5e756..b089365ccc 100644
--- a/libnm-core/nm-dbus-interface.h
+++ b/libnm-core/nm-dbus-interface.h
@@ -68,6 +68,7 @@
#define NM_DBUS_INTERFACE_DEVICE_TUN NM_DBUS_INTERFACE_DEVICE ".Tun"
#define NM_DBUS_INTERFACE_DEVICE_MACSEC NM_DBUS_INTERFACE_DEVICE ".Macsec"
#define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan"
+#define NM_DBUS_INTERFACE_DEVICE_PPP NM_DBUS_INTERFACE_DEVICE ".Ppp"
#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan"
#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre"
#define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel"
@@ -203,6 +204,7 @@ typedef enum {
* @NM_DEVICE_TYPE_VETH: a VETH interface
* @NM_DEVICE_TYPE_MACSEC: a MACsec interface
* @NM_DEVICE_TYPE_DUMMY: a dummy interface
+ * @NM_DEVICE_TYPE_PPP: a PPP interface
*
* #NMDeviceType values indicate the type of hardware represented by a
* device object.
@@ -231,6 +233,7 @@ typedef enum {
NM_DEVICE_TYPE_VETH = 20,
NM_DEVICE_TYPE_MACSEC = 21,
NM_DEVICE_TYPE_DUMMY = 22,
+ NM_DEVICE_TYPE_PPP = 23,
} NMDeviceType;
/**
diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c
index f72ee27385..3f9c2a9d6d 100644
--- a/libnm-core/nm-setting-pppoe.c
+++ b/libnm-core/nm-setting-pppoe.c
@@ -45,6 +45,7 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPPOE)
#define NM_SETTING_PPPOE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPPOE, NMSettingPppoePrivate))
typedef struct {
+ char *parent;
char *service;
char *username;
char *password;
@@ -53,6 +54,7 @@ typedef struct {
enum {
PROP_0,
+ PROP_PARENT,
PROP_SERVICE,
PROP_USERNAME,
PROP_PASSWORD,
@@ -75,6 +77,22 @@ nm_setting_pppoe_new (void)
}
/**
+ * nm_setting_pppoe_get_parent:
+ * @setting: the #NMSettingPppoe
+ *
+ * Returns: the #NMSettingPppoe:parent property of the setting
+ *
+ * Since: 1.10
+ **/
+const char *
+nm_setting_pppoe_get_parent (NMSettingPppoe *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NULL);
+
+ return NM_SETTING_PPPOE_GET_PRIVATE (setting)->parent;
+}
+
+/**
* nm_setting_pppoe_get_service:
* @setting: the #NMSettingPppoe
*
@@ -134,6 +152,7 @@ static gboolean
verify (NMSetting *setting, NMConnection *connection, GError **error)
{
NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (setting);
+ gs_free_error GError *local_error = NULL;
if (!priv->username) {
g_set_error_literal (error,
@@ -160,6 +179,16 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return FALSE;
}
+ if ( priv->parent
+ && !nm_utils_is_valid_iface_name (priv->parent, &local_error)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ "'%s': %s", priv->parent, local_error->message);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_PARENT);
+ return FALSE;
+ }
+
return TRUE;
}
@@ -192,6 +221,10 @@ set_property (GObject *object, guint prop_id,
NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (object);
switch (prop_id) {
+ case PROP_PARENT:
+ g_free (priv->parent);
+ priv->parent = g_value_dup_string (value);
+ break;
case PROP_SERVICE:
g_free (priv->service);
priv->service = g_value_dup_string (value);
@@ -220,6 +253,9 @@ get_property (GObject *object, guint prop_id,
NMSettingPppoe *setting = NM_SETTING_PPPOE (object);
switch (prop_id) {
+ case PROP_PARENT:
+ g_value_set_string (value, nm_setting_pppoe_get_parent (setting));
+ break;
case PROP_SERVICE:
g_value_set_string (value, nm_setting_pppoe_get_service (setting));
break;
@@ -267,6 +303,25 @@ nm_setting_pppoe_class_init (NMSettingPppoeClass *setting_class)
/* Properties */
/**
+ * NMSettingPppoe:parent:
+ *
+ * If given, specifies the parent interface name on which this PPPoE
+ * connection should be created. If this property is not specified,
+ * the connection is activated on the interface specified in
+ * #NMSettingConnection:interface-name of #NMSettingConnection.
+ *
+ * Since: 1.10
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PARENT,
+ g_param_spec_string (NM_SETTING_PPPOE_PARENT, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
* NMSettingPppoe:service:
*
* If specified, instruct PPPoE to only initiate sessions with access
diff --git a/libnm-core/nm-setting-pppoe.h b/libnm-core/nm-setting-pppoe.h
index b6717cde81..cab96e3b98 100644
--- a/libnm-core/nm-setting-pppoe.h
+++ b/libnm-core/nm-setting-pppoe.h
@@ -40,6 +40,7 @@ G_BEGIN_DECLS
#define NM_SETTING_PPPOE_SETTING_NAME "pppoe"
+#define NM_SETTING_PPPOE_PARENT "parent"
#define NM_SETTING_PPPOE_SERVICE "service"
#define NM_SETTING_PPPOE_USERNAME "username"
#define NM_SETTING_PPPOE_PASSWORD "password"
@@ -64,6 +65,8 @@ typedef struct {
GType nm_setting_pppoe_get_type (void);
NMSetting *nm_setting_pppoe_new (void);
+NM_AVAILABLE_IN_1_10
+const char *nm_setting_pppoe_get_parent (NMSettingPppoe *setting);
const char *nm_setting_pppoe_get_service (NMSettingPppoe *setting);
const char *nm_setting_pppoe_get_username (NMSettingPppoe *setting);
const char *nm_setting_pppoe_get_password (NMSettingPppoe *setting);
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index f1fb863d93..85ec20c929 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -1181,7 +1181,9 @@ global:
libnm_1_10_0 {
global:
nm_device_dummy_get_hw_address;
+ nm_device_ppp_get_type;
nm_setting_bridge_get_group_forward_mask;
+ nm_setting_pppoe_get_parent;
nm_setting_wireless_security_get_pmf;
nm_setting_wireless_security_get_wps_method;
nm_setting_wireless_security_pmf_get_type;
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index 38b69100f9..c8ce2d6eca 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -63,6 +63,7 @@
#include "nm-device-macvlan.h"
#include "nm-device-modem.h"
#include "nm-device-olpc-mesh.h"
+#include "nm-device-ppp.h"
#include "nm-device-team.h"
#include "nm-device-tun.h"
#include "nm-device-vlan.h"
@@ -2078,6 +2079,8 @@ obj_nm_for_gdbus_object (NMClient *self, GDBusObject *object, GDBusObjectManager
type = NM_TYPE_DEVICE_MODEM;
else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_OLPC_MESH) == 0)
type = NM_TYPE_DEVICE_OLPC_MESH;
+ else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_PPP) == 0)
+ type = NM_TYPE_DEVICE_PPP;
else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_TEAM) == 0)
type = NM_TYPE_DEVICE_TEAM;
else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_TUN) == 0)
diff --git a/libnm/nm-device-ppp.c b/libnm/nm-device-ppp.c
new file mode 100644
index 0000000000..805d142820
--- /dev/null
+++ b/libnm/nm-device-ppp.c
@@ -0,0 +1,39 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2017 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-device-ppp.h"
+#include "nm-device.h"
+
+struct _NMDevicePpp {
+ NMDevice parent;
+};
+
+struct _NMDevicePppClass {
+ NMDeviceClass parent;
+};
+
+G_DEFINE_TYPE (NMDevicePpp, nm_device_ppp, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_PPP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_PPP, NMDevicePppPrivate))
+
+static void
+nm_device_ppp_init (NMDevicePpp *device)
+{
+}
+
+static void
+nm_device_ppp_class_init (NMDevicePppClass *klass)
+{
+}
diff --git a/libnm/nm-device-ppp.h b/libnm/nm-device-ppp.h
new file mode 100644
index 0000000000..58ff5e1882
--- /dev/null
+++ b/libnm/nm-device-ppp.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2017 Red Hat, Inc.
+ */
+
+#ifndef __NM_DEVICE_PPP_H__
+#define __NM_DEVICE_PPP_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_PPP (nm_device_ppp_get_type ())
+#define NM_DEVICE_PPP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_PPP, NMDevicePpp))
+#define NM_DEVICE_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_PPP, NMDevicePppClass))
+#define NM_IS_DEVICE_PPP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_PPP))
+#define NM_IS_DEVICE_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_PPP))
+#define NM_DEVICE_PPP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_PPP, NMDevicePppClass))
+
+typedef struct _NMDevicePppClass NMDevicePppClass;
+
+GType nm_device_ppp_get_type (void);
+
+G_END_DECLS
+
+#endif /* __NM_DEVICE_PPP_H__ */
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
index 8c31e6cfa0..7f15436638 100644
--- a/libnm/nm-device.c
+++ b/libnm/nm-device.c
@@ -280,6 +280,7 @@ coerce_type (NMDeviceType type)
case NM_DEVICE_TYPE_UNUSED2:
case NM_DEVICE_TYPE_UNKNOWN:
case NM_DEVICE_TYPE_DUMMY:
+ case NM_DEVICE_TYPE_PPP:
return type;
}
return NM_DEVICE_TYPE_UNKNOWN;
@@ -1551,6 +1552,8 @@ get_type_name (NMDevice *device)
return _("MACsec");
case NM_DEVICE_TYPE_DUMMY:
return _("Dummy");
+ case NM_DEVICE_TYPE_PPP:
+ return _("PPP");
case NM_DEVICE_TYPE_GENERIC:
case NM_DEVICE_TYPE_UNUSED1:
case NM_DEVICE_TYPE_UNUSED2:
diff --git a/libnm/nm-types.h b/libnm/nm-types.h
index 84cf48f4c5..1e06d15feb 100644
--- a/libnm/nm-types.h
+++ b/libnm/nm-types.h
@@ -43,6 +43,7 @@ typedef struct _NMDeviceMacsec NMDeviceMacsec;
typedef struct _NMDeviceMacvlan NMDeviceMacvlan;
typedef struct _NMDeviceModem NMDeviceModem;
typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh;
+typedef struct _NMDevicePpp NMDevicePpp;
typedef struct _NMDeviceTeam NMDeviceTeam;
typedef struct _NMDeviceTun NMDeviceTun;
typedef struct _NMDeviceVlan NMDeviceVlan;
diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c
index 33bea4e27c..74bf027c72 100644
--- a/src/devices/bluetooth/nm-bluez-manager.c
+++ b/src/devices/bluetooth/nm-bluez-manager.c
@@ -26,6 +26,7 @@
#include <gmodule.h>
#include "devices/nm-device-factory.h"
+#include "devices/nm-device-bridge.h"
#include "nm-setting-bluetooth.h"
#include "settings/nm-settings.h"
#include "nm-bluez4-manager.h"
@@ -417,6 +418,21 @@ create_device (NMDeviceFactory *factory,
return NULL;
}
+static gboolean
+match_connection (NMDeviceFactory *factory,
+ NMConnection *connection)
+{
+ const char *type = nm_connection_get_connection_type (connection);
+
+ nm_assert (nm_streq (type, NM_SETTING_BLUETOOTH_SETTING_NAME));
+
+ if ( nm_bt_vtable_network_server
+ && _nm_connection_get_setting_bluetooth_for_nap (connection))
+ return FALSE; /* handled by the bridge factory */
+
+ return TRUE;
+}
+
/*****************************************************************************/
static void
@@ -461,5 +477,6 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass)
factory_class->get_supported_types = get_supported_types;
factory_class->create_device = create_device;
+ factory_class->match_connection = match_connection;
factory_class->start = start;
}
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index e3ba81a57d..ef5550cd6a 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -538,8 +538,24 @@ create_device (NMDeviceFactory *factory,
NULL);
}
+static gboolean
+match_connection (NMDeviceFactory *factory,
+ NMConnection *connection)
+{
+ const char *type = nm_connection_get_connection_type (connection);
+
+ if (nm_streq (type, NM_SETTING_BRIDGE_SETTING_NAME))
+ return TRUE;
+
+ nm_assert (nm_streq (type, NM_SETTING_BLUETOOTH_SETTING_NAME));
+
+ return nm_bt_vtable_network_server
+ && _nm_connection_get_setting_bluetooth_for_nap (connection);
+}
+
NM_DEVICE_FACTORY_DEFINE_INTERNAL (BRIDGE, Bridge, bridge,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_BRIDGE)
- NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BRIDGE_SETTING_NAME),
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BLUETOOTH_SETTING_NAME),
factory_class->create_device = create_device;
+ factory_class->match_connection = match_connection;
);
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index 8044ec3b85..eaa6a1f85d 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -108,7 +108,6 @@ typedef struct _NMDeviceEthernetPrivate {
/* PPPoE */
NMPPPManager *ppp_manager;
- NMIP4Config *pending_ip4_config;
gint32 last_pppoe_time;
guint pppoe_wait_id;
@@ -1353,11 +1352,6 @@ deactivate (NMDevice *device)
nm_clear_g_source (&priv->pppoe_wait_id);
- if (priv->pending_ip4_config) {
- g_object_unref (priv->pending_ip4_config);
- priv->pending_ip4_config = NULL;
- }
-
if (priv->ppp_manager) {
nm_ppp_manager_stop_sync (priv->ppp_manager);
g_clear_object (&priv->ppp_manager);
@@ -1802,8 +1796,24 @@ create_device (NMDeviceFactory *factory,
NULL);
}
+static gboolean
+match_connection (NMDeviceFactory *factory, NMConnection *connection)
+{
+ const char *type = nm_connection_get_connection_type (connection);
+ NMSettingPppoe *s_pppoe;
+
+ if (nm_streq (type, NM_SETTING_WIRED_SETTING_NAME))
+ return TRUE;
+
+ nm_assert (nm_streq (type, NM_SETTING_PPPOE_SETTING_NAME));
+ s_pppoe = nm_connection_get_setting_pppoe (connection);
+
+ return !nm_setting_pppoe_get_parent (s_pppoe);
+}
+
NM_DEVICE_FACTORY_DEFINE_INTERNAL (ETHERNET, Ethernet, ethernet,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_ETHERNET)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_PPPOE_SETTING_NAME),
factory_class->create_device = create_device;
+ factory_class->match_connection = match_connection;
);
diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c
index d0ad791acb..4e0d7939d4 100644
--- a/src/devices/nm-device-factory.c
+++ b/src/devices/nm-device-factory.c
@@ -235,34 +235,24 @@ nm_device_factory_manager_find_factory_for_link_type (NMLinkType link_type)
NMDeviceFactory *
nm_device_factory_manager_find_factory_for_connection (NMConnection *connection)
{
+ NMDeviceFactoryClass *klass;
+ NMDeviceFactory *factory;
const char *type;
+ GSList *list;
g_return_val_if_fail (factories_by_setting, NULL);
type = nm_connection_get_connection_type (connection);
+ list = g_hash_table_lookup (factories_by_setting, type);
- if ( nm_streq (type, NM_SETTING_BLUETOOTH_SETTING_NAME)
- && _nm_connection_get_setting_bluetooth_for_nap (connection)) {
- /* for Bluetooth NAP connections, we return the bridge factory
- * instead of the bluetooth factory.
- *
- * In a way, this is a hack. The more orthodox solution would
- * be that device factories don't only announce supported setting
- * types, but instead match on a full fledged NMConnection.
- *
- * However, our device-factories are known at compile time.
- * There is no need to keep this generic. We *know* which
- * factory to choose. Making this generic would not make it
- * cleaner. */
- if (!g_hash_table_lookup (factories_by_setting, type)) {
- /* we need both the bluetooth and the bridge factory
- * to make this work. */
- return NULL;
- }
- type = NM_SETTING_BRIDGE_SETTING_NAME;
+ for (; list; list = g_slist_next (list)) {
+ factory = list->data;
+ klass = NM_DEVICE_FACTORY_GET_CLASS (factory);
+ if (!klass->match_connection || klass->match_connection (factory, connection))
+ return factory;
}
- return g_hash_table_lookup (factories_by_setting, type);
+ return NULL;
}
void
@@ -283,9 +273,11 @@ nm_device_factory_manager_for_each_factory (NMDeviceFactoryManagerFactoryFunc ca
if (factories_by_setting) {
g_hash_table_iter_init (&iter, factories_by_setting);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &factory)) {
- if (!g_slist_find (list, factory))
- list = g_slist_prepend (list, factory);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &list_iter)) {
+ for (; list_iter; list_iter = g_slist_next (list_iter)) {
+ if (!g_slist_find (list, list_iter->data))
+ list = g_slist_prepend (list, list_iter->data);
+ }
}
}
@@ -303,6 +295,7 @@ _add_factory (NMDeviceFactory *factory,
{
const NMLinkType *link_types = NULL;
const char *const*setting_types = NULL;
+ GSList *list;
int i;
g_return_val_if_fail (factories_by_link, FALSE);
@@ -313,8 +306,15 @@ _add_factory (NMDeviceFactory *factory,
g_object_set_qdata_full (G_OBJECT (factory), plugin_path_quark (), g_strdup (path), g_free);
for (i = 0; link_types && link_types[i] > NM_LINK_TYPE_UNKNOWN; i++)
g_hash_table_insert (factories_by_link, GUINT_TO_POINTER (link_types[i]), g_object_ref (factory));
- for (i = 0; setting_types && setting_types[i]; i++)
- g_hash_table_insert (factories_by_setting, (char *) setting_types[i], g_object_ref (factory));
+ for (i = 0; setting_types && setting_types[i]; i++) {
+ list = g_hash_table_lookup (factories_by_setting, (char *) setting_types[i]);
+ if (list)
+ list = g_slist_append (list, g_object_ref (factory));
+ else {
+ list = g_slist_append (list, g_object_ref (factory));
+ g_hash_table_insert (factories_by_setting, (char *) setting_types[i], list);
+ }
+ }
callback (factory, user_data);
@@ -333,6 +333,12 @@ _load_internal_factory (GType factory_gtype,
_add_factory (factory, "internal", callback, user_data);
}
+static void
+factories_list_unref (GSList *list)
+{
+ g_slist_free_full (list, g_object_unref);
+}
+
void
nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc callback,
gpointer user_data)
@@ -345,7 +351,7 @@ nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc call
g_return_if_fail (factories_by_setting == NULL);
factories_by_link = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
- factories_by_setting = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+ factories_by_setting = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) factories_list_unref);
#define _ADD_INTERNAL(get_type_fcn) \
G_STMT_START { \
@@ -362,6 +368,7 @@ nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc call
_ADD_INTERNAL (nm_ip_tunnel_device_factory_get_type);
_ADD_INTERNAL (nm_macsec_device_factory_get_type);
_ADD_INTERNAL (nm_macvlan_device_factory_get_type);
+ _ADD_INTERNAL (nm_ppp_device_factory_get_type);
_ADD_INTERNAL (nm_tun_device_factory_get_type);
_ADD_INTERNAL (nm_veth_device_factory_get_type);
_ADD_INTERNAL (nm_vlan_device_factory_get_type);
diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h
index 0c590f657a..33b596e6e6 100644
--- a/src/devices/nm-device-factory.h
+++ b/src/devices/nm-device-factory.h
@@ -72,6 +72,14 @@ typedef struct {
void (*start) (NMDeviceFactory *factory);
/**
+ * match_connection:
+ * @connection: the #NMConnection
+ *
+ * Check if the factory supports the given connection.
+ */
+ gboolean (*match_connection) (NMDeviceFactory *factory, NMConnection *connection);
+
+ /**
* get_connection_parent:
* @factory: the #NMDeviceFactory
* @connection: the #NMConnection to return the parent name for, if supported
diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c
new file mode 100644
index 0000000000..7c034f5f85
--- /dev/null
+++ b/src/devices/nm-device-ppp.c
@@ -0,0 +1,337 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-device-ppp.h"
+
+#include "nm-act-request.h"
+#include "nm-device-factory.h"
+#include "nm-device-private.h"
+#include "nm-manager.h"
+#include "nm-setting-pppoe.h"
+#include "platform/nm-platform.h"
+#include "ppp/nm-ppp-manager.h"
+#include "ppp/nm-ppp-manager-call.h"
+#include "ppp/nm-ppp-status.h"
+
+#include "introspection/org.freedesktop.NetworkManager.Device.Ppp.h"
+
+#include "nm-device-logging.h"
+_LOG_DECLARE_SELF(NMDevicePpp);
+
+/*****************************************************************************/
+
+typedef struct _NMDevicePppPrivate {
+ NMPPPManager *ppp_manager;
+ NMIP4Config *pending_ip4_config;
+ char *pending_ifname;
+} NMDevicePppPrivate;
+
+struct _NMDevicePpp {
+ NMDevice parent;
+ NMDevicePppPrivate _priv;
+};
+
+struct _NMDevicePppClass {
+ NMDeviceClass parent;
+};
+
+G_DEFINE_TYPE (NMDevicePpp, nm_device_ppp, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_PPP_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDevicePpp, NM_IS_DEVICE_PPP)
+
+static gboolean
+check_connection_compatible (NMDevice *device, NMConnection *connection)
+{
+ NMSettingPppoe *s_pppoe;
+
+ if (!NM_DEVICE_CLASS (nm_device_ppp_parent_class)->check_connection_compatible (device, connection))
+ return FALSE;
+
+ if (!nm_streq0 (nm_connection_get_connection_type (connection),
+ NM_SETTING_PPPOE_SETTING_NAME))
+ return FALSE;
+
+ s_pppoe = nm_connection_get_setting_pppoe (connection);
+ nm_assert (s_pppoe);
+
+ return !!nm_setting_pppoe_get_parent (s_pppoe);
+}
+
+static NMDeviceCapabilities
+get_generic_capabilities (NMDevice *device)
+{
+ return NM_DEVICE_CAP_IS_SOFTWARE;
+}
+
+static void
+ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+
+ switch (status) {
+ case NM_PPP_STATUS_DISCONNECT:
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
+ break;
+ case NM_PPP_STATUS_DEAD:
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
+ break;
+ case NM_PPP_STATUS_RUNNING:
+ nm_device_activate_schedule_stage3_ip_config_start (device);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ppp_ip4_config (NMPPPManager *ppp_manager,
+ const char *iface,
+ NMIP4Config *config,
+ gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+ NMDevicePpp *self = NM_DEVICE_PPP (device);
+ NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self);
+
+ _LOGT (LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd");
+
+ if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) {
+ if (nm_device_activate_ip4_state_in_conf (device)) {
+ if (!nm_device_take_over_link (device, iface)) {
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ return;
+ }
+ nm_manager_remove_device (nm_manager_get (), iface);
+ nm_device_activate_schedule_ip4_config_result (device, config);
+ return;
+ }
+ } else {
+ if (priv->pending_ip4_config)
+ g_object_unref (priv->pending_ip4_config);
+ priv->pending_ip4_config = g_object_ref (config);
+ g_free (priv->pending_ifname);
+ priv->pending_ifname = g_strdup (iface);
+ }
+}
+
+static NMActStageReturn
+act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
+{
+ NMDevicePpp *self = NM_DEVICE_PPP (device);
+ NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self);
+ NMSettingPppoe *s_pppoe;
+ NMActRequest *req;
+ GError *err = NULL;
+
+ req = nm_device_get_act_request (NM_DEVICE (self));
+ g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE);
+
+ s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting ((NMDevice *) self, NM_TYPE_SETTING_PPPOE);
+ g_return_val_if_fail (s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
+
+ g_clear_object (&priv->pending_ip4_config);
+ nm_clear_g_free (&priv->pending_ifname);
+
+ priv->ppp_manager = nm_ppp_manager_create (nm_setting_pppoe_get_parent (s_pppoe), &err);
+
+ if ( !priv->ppp_manager
+ || !nm_ppp_manager_start (priv->ppp_manager, req,
+ nm_setting_pppoe_get_username (s_pppoe),
+ 30, 0, &err)) {
+ _LOGW (LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", err->message);
+ g_error_free (err);
+
+ g_clear_object (&priv->ppp_manager);
+
+ NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED);
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
+ g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED,
+ G_CALLBACK (ppp_state_changed),
+ self);
+ g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
+ G_CALLBACK (ppp_ip4_config),
+ self);
+
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+}
+
+static NMActStageReturn
+act_stage3_ip4_config_start (NMDevice *device,
+ NMIP4Config **out_config,
+ NMDeviceStateReason *out_failure_reason)
+{
+ NMDevicePpp *self = NM_DEVICE_PPP (device);
+ NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self);
+
+ if (priv->pending_ip4_config) {
+ if (!nm_device_take_over_link (device, priv->pending_ifname))
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ nm_manager_remove_device (nm_manager_get (), priv->pending_ifname);
+ if (out_config)
+ *out_config = g_steal_pointer (&priv->pending_ip4_config);
+ else
+ g_clear_object (&priv->pending_ip4_config);
+ return NM_ACT_STAGE_RETURN_SUCCESS;
+ }
+
+ /* Wait IPCP termination */
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+}
+
+static gboolean
+create_and_realize (NMDevice *device,
+ NMConnection *connection,
+ NMDevice *parent,
+ const NMPlatformLink **out_plink,
+ GError **error)
+{
+ int parent_ifindex;
+
+ if (!parent) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "PPP devices can not be created without a parent interface");
+ return FALSE;
+ }
+
+ parent_ifindex = nm_device_get_ifindex (parent);
+ g_warn_if_fail (parent_ifindex > 0);
+
+ nm_device_parent_set_ifindex (device, parent_ifindex);
+
+ /* The interface is created later */
+
+ return TRUE;
+}
+
+static void
+deactivate (NMDevice *device)
+{
+ NMDevicePpp *self = NM_DEVICE_PPP (device);
+ NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self);
+
+ if (priv->ppp_manager) {
+ nm_ppp_manager_stop_sync (priv->ppp_manager);
+ g_clear_object (&priv->ppp_manager);
+ }
+}
+
+static void
+nm_device_ppp_init (NMDevicePpp *self)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+ NMDevicePpp *self = NM_DEVICE_PPP (object);
+ NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self);
+
+ g_clear_object (&priv->pending_ip4_config);
+ nm_clear_g_free (&priv->pending_ifname);
+
+ G_OBJECT_CLASS (nm_device_ppp_parent_class)->dispose (object);
+}
+
+static void
+nm_device_ppp_class_init (NMDevicePppClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
+
+ NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_PPPOE_SETTING_NAME, NM_LINK_TYPE_PPP)
+
+ object_class->dispose = dispose;
+
+ parent_class->act_stage2_config = act_stage2_config;
+ parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
+ parent_class->check_connection_compatible = check_connection_compatible;
+ parent_class->create_and_realize = create_and_realize;
+ parent_class->deactivate = deactivate;
+ parent_class->get_generic_capabilities = get_generic_capabilities;
+
+ nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
+ NMDBUS_TYPE_DEVICE_PPP_SKELETON,
+ NULL);
+}
+
+/*****************************************************************************/
+
+#define NM_TYPE_PPP_DEVICE_FACTORY (nm_ppp_device_factory_get_type ())
+#define NM_PPP_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PPP_DEVICE_FACTORY, NMPppDeviceFactory))
+
+static NMDevice *
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ const NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
+{
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_PPP,
+ NM_DEVICE_IFACE, iface,
+ NM_DEVICE_TYPE_DESC, "Ppp",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_PPP,
+ NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_PPP,
+ NULL);
+}
+
+static gboolean
+match_connection (NMDeviceFactory *factory, NMConnection *connection)
+{
+ NMSettingPppoe *s_pppoe;
+
+ s_pppoe = nm_connection_get_setting_pppoe (connection);
+ nm_assert (s_pppoe);
+
+ return !!nm_setting_pppoe_get_parent (s_pppoe);
+}
+
+static const char *
+get_connection_parent (NMDeviceFactory *factory, NMConnection *connection)
+{
+ NMSettingPppoe *s_pppoe;
+
+ nm_assert (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME));
+
+ s_pppoe = nm_connection_get_setting_pppoe (connection);
+ nm_assert (s_pppoe);
+
+ return nm_setting_pppoe_get_parent (s_pppoe);
+}
+
+static char *
+get_connection_iface (NMDeviceFactory *factory,
+ NMConnection *connection,
+ const char *parent_iface)
+{
+ nm_assert (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME));
+
+ if (!parent_iface)
+ return NULL;
+
+ return g_strdup (nm_connection_get_interface_name (connection));
+}
+
+NM_DEVICE_FACTORY_DEFINE_INTERNAL (PPP, Ppp, ppp,
+ NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_PPP)
+ NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_PPPOE_SETTING_NAME),
+ factory_class->get_connection_parent = get_connection_parent;
+ factory_class->get_connection_iface = get_connection_iface;
+ factory_class->create_device = create_device;
+ factory_class->match_connection = match_connection;
+);
diff --git a/src/devices/nm-device-ppp.h b/src/devices/nm-device-ppp.h
new file mode 100644
index 0000000000..aaa18b9b12
--- /dev/null
+++ b/src/devices/nm-device-ppp.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ */
+
+#ifndef __NETWORKMANAGER_DEVICE_PPP_H__
+#define __NETWORKMANAGER_DEVICE_PPP_H__
+
+#define NM_TYPE_DEVICE_PPP (nm_device_ppp_get_type ())
+#define NM_DEVICE_PPP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_PPP, NMDevicePpp))
+#define NM_DEVICE_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_PPP, NMDevicePppClass))
+#define NM_IS_DEVICE_PPP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_PPP))
+#define NM_IS_DEVICE_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_PPP))
+#define NM_DEVICE_PPP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_PPP, NMDevicePppClass))
+
+typedef struct _NMDevicePpp NMDevicePpp;
+typedef struct _NMDevicePppClass NMDevicePppClass;
+
+GType nm_device_ppp_get_type (void);
+
+#endif /* __NETWORKMANAGER_DEVICE_PPP_H__ */
diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
index 05cb3f7d84..a02cab3159 100644
--- a/src/devices/nm-device-private.h
+++ b/src/devices/nm-device-private.h
@@ -57,6 +57,8 @@ gboolean nm_device_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmwar
void nm_device_take_down (NMDevice *self, gboolean block);
+gboolean nm_device_take_over_link (NMDevice *self, const char *ifname);
+
gboolean nm_device_hw_addr_set (NMDevice *device,
const char *addr,
const char *detail,
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 259f776e54..3934c18f3c 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1001,6 +1001,40 @@ nm_device_get_iface (NMDevice *self)
return NM_DEVICE_GET_PRIVATE (self)->iface;
}
+gboolean
+nm_device_take_over_link (NMDevice *self, const char *ifname)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ const NMPlatformLink *plink;
+ NMPlatform *platform;
+ gboolean up, success;
+ int ifindex;
+
+ g_return_val_if_fail (priv->ifindex <= 0, FALSE);
+
+ platform = nm_device_get_platform (self);
+ plink = nm_platform_link_get_by_ifname (platform, ifname);
+ if (!plink)
+ return FALSE;
+
+ ifindex = plink->ifindex;
+ up = NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP);
+
+ /* Rename the link to the device ifname */
+ if (up)
+ nm_platform_link_set_down (platform, ifindex);
+ success = nm_platform_link_set_name (platform, ifindex, nm_device_get_iface (self));
+ if (up)
+ nm_platform_link_set_up (platform, ifindex, NULL);
+
+ if (success) {
+ priv->ifindex = ifindex;
+ _notify (self, PROP_IFINDEX);
+ }
+
+ return success;
+}
+
int
nm_device_get_ifindex (NMDevice *self)
{
@@ -1555,6 +1589,8 @@ nm_device_get_priority (NMDevice *self)
return 425;
case NM_DEVICE_TYPE_TUN:
return 450;
+ case NM_DEVICE_TYPE_PPP:
+ return 460;
case NM_DEVICE_TYPE_VXLAN:
return 500;
case NM_DEVICE_TYPE_DUMMY:
@@ -2909,8 +2945,10 @@ nm_device_create_and_realize (NMDevice *self,
if (NM_DEVICE_GET_CLASS (self)->create_and_realize) {
if (!NM_DEVICE_GET_CLASS (self)->create_and_realize (self, connection, parent, &plink, error))
return FALSE;
- plink_copy = *plink;
- plink = &plink_copy;
+ if (plink) {
+ plink_copy = *plink;
+ plink = &plink_copy;
+ }
}
realize_start_setup (self, plink,
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 3a8ada4360..e0cce262dc 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1258,6 +1258,24 @@ nm_manager_iface_for_uuid (NMManager *self, const char *uuid)
return nm_connection_get_interface_name (NM_CONNECTION (connection));
}
+gboolean
+nm_manager_remove_device (NMManager *self, const char *ifname)
+{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+ GSList *iter;
+ NMDevice *d;
+
+ for (iter = priv->devices; iter; iter = iter->next) {
+ d = iter->data;
+ if (nm_streq0 (nm_device_get_iface (d), ifname)) {
+ remove_device (self, d, FALSE, FALSE);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/**
* system_create_virtual_device:
* @self: the #NMManager
diff --git a/src/nm-manager.h b/src/nm-manager.h
index fbbaffc314..0fdca8d458 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -124,4 +124,6 @@ gboolean nm_manager_deactivate_connection (NMManager *manager,
void nm_manager_set_capability (NMManager *self, NMCapability cap);
+gboolean nm_manager_remove_device (NMManager *self, const char *ifname);
+
#endif /* __NETWORKMANAGER_MANAGER_H__ */
diff --git a/src/nm-types.h b/src/nm-types.h
index 2cc5769467..136cc450a8 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -142,7 +142,8 @@ typedef enum {
NM_LINK_TYPE_WIMAX,
/* Software types */
- NM_LINK_TYPE_DUMMY = 0x10000,
+ NM_LINK_TYPE_BNEP = 0x10000, /* Bluetooth Ethernet emulation */
+ NM_LINK_TYPE_DUMMY,
NM_LINK_TYPE_GRE,
NM_LINK_TYPE_GRETAP,
NM_LINK_TYPE_IFB,
@@ -153,13 +154,13 @@ typedef enum {
NM_LINK_TYPE_MACVLAN,
NM_LINK_TYPE_MACVTAP,
NM_LINK_TYPE_OPENVSWITCH,
+ NM_LINK_TYPE_PPP,
NM_LINK_TYPE_SIT,
NM_LINK_TYPE_TAP,
NM_LINK_TYPE_TUN,
NM_LINK_TYPE_VETH,
NM_LINK_TYPE_VLAN,
NM_LINK_TYPE_VXLAN,
- NM_LINK_TYPE_BNEP, /* Bluetooth Ethernet emulation */
/* Software types with slaves */
NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000,
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 42a77c5066..cd45a2bf39 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -380,6 +380,7 @@ static const LinkDesc linktypes[] = {
{ NM_LINK_TYPE_WWAN_NET, "wwan", NULL, "wwan" },
{ NM_LINK_TYPE_WIMAX, "wimax", "wimax", "wimax" },
+ { NM_LINK_TYPE_BNEP, "bluetooth", NULL, "bluetooth" },
{ NM_LINK_TYPE_DUMMY, "dummy", "dummy", NULL },
{ NM_LINK_TYPE_GRE, "gre", "gre", NULL },
{ NM_LINK_TYPE_GRETAP, "gretap", "gretap", NULL },
@@ -391,13 +392,13 @@ static const LinkDesc linktypes[] = {
{ NM_LINK_TYPE_MACVLAN, "macvlan", "macvlan", NULL },
{ NM_LINK_TYPE_MACVTAP, "macvtap", "macvtap", NULL },
{ NM_LINK_TYPE_OPENVSWITCH, "openvswitch", "openvswitch", NULL },
+ { NM_LINK_TYPE_PPP, "ppp", NULL, "ppp" },
{ NM_LINK_TYPE_SIT, "sit", "sit", NULL },
{ NM_LINK_TYPE_TAP, "tap", NULL, NULL },
{ NM_LINK_TYPE_TUN, "tun", NULL, NULL },
{ NM_LINK_TYPE_VETH, "veth", "veth", NULL },
{ NM_LINK_TYPE_VLAN, "vlan", "vlan", "vlan" },
{ NM_LINK_TYPE_VXLAN, "vxlan", "vxlan", "vxlan" },
- { NM_LINK_TYPE_BNEP, "bluetooth", NULL, "bluetooth" },
{ NM_LINK_TYPE_BRIDGE, "bridge", "bridge", "bridge" },
{ NM_LINK_TYPE_BOND, "bond", "bond", "bond" },
@@ -696,6 +697,8 @@ _linktype_get_type (NMPlatform *platform,
return NM_LINK_TYPE_SIT;
else if (arptype == ARPHRD_TUNNEL6)
return NM_LINK_TYPE_IP6TNL;
+ else if (arptype == ARPHRD_PPP)
+ return NM_LINK_TYPE_PPP;
{
NMPUtilsEthtoolDriverInfo driver_info;
@@ -4463,6 +4466,29 @@ nla_put_failure:
g_return_val_if_reached (NM_PLATFORM_ERROR_UNSPECIFIED);
}
+static NMPlatformError
+link_set_name (NMPlatform *platform, int ifindex, const char *name)
+{
+ nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
+
+ _LOGD ("link: change %d: name: %s", ifindex, name);
+
+ nlmsg = _nl_msg_new_link (RTM_NEWLINK,
+ 0,
+ ifindex,
+ NULL,
+ 0,
+ 0);
+ if (!nlmsg)
+ g_return_val_if_reached (NM_PLATFORM_ERROR_UNSPECIFIED);
+
+ NLA_PUT (nlmsg, IFLA_IFNAME, strlen (name) + 1, name);
+
+ return do_change_link (platform, ifindex, nlmsg) == NM_PLATFORM_ERROR_SUCCESS;
+nla_put_failure:
+ g_return_val_if_reached (FALSE);
+}
+
static gboolean
link_get_permanent_address (NMPlatform *platform,
int ifindex,
@@ -6461,6 +6487,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_set_address = link_set_address;
platform_class->link_get_permanent_address = link_get_permanent_address;
platform_class->link_set_mtu = link_set_mtu;
+ platform_class->link_set_name = link_set_name;
platform_class->link_set_sriov_num_vfs = link_set_sriov_num_vfs;
platform_class->link_get_physical_port_id = link_get_physical_port_id;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 03dc6943b6..e7935d49fb 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1462,6 +1462,30 @@ nm_platform_link_get_mtu (NMPlatform *self, int ifindex)
}
/**
+ * nm_platform_link_set_name:
+ * @self: platform instance
+ * @ifindex: Interface index
+ * @name: The new interface name
+ *
+ * Set interface name.
+ */
+gboolean
+nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name)
+{
+ _CHECK_SELF (self, klass, FALSE);
+
+ g_return_val_if_fail (ifindex >= 0, FALSE);
+ g_return_val_if_fail (name, FALSE);
+
+ _LOGD ("link: setting '%s' (%d) name %s", nm_platform_link_get_name (self, ifindex), ifindex, name);
+
+ if (strlen (name) + 1 > IFNAMSIZ)
+ return FALSE;
+
+ return klass->link_set_name (self, ifindex, name);
+}
+
+/**
* nm_platform_link_get_physical_port_id:
* @self: platform instance
* @ifindex: Interface index
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index a40d33f43d..8e922b95e0 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -682,6 +682,7 @@ typedef struct {
size_t *length);
NMPlatformError (*link_set_address) (NMPlatform *, int ifindex, gconstpointer address, size_t length);
gboolean (*link_set_mtu) (NMPlatform *, int ifindex, guint32 mtu);
+ gboolean (*link_set_name) (NMPlatform *, int ifindex, const char *name);
gboolean (*link_set_sriov_num_vfs) (NMPlatform *, int ifindex, guint num_vfs);
char * (*link_get_physical_port_id) (NMPlatform *, int ifindex);
@@ -946,6 +947,7 @@ gboolean nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtils
gboolean nm_platform_link_get_permanent_address (NMPlatform *self, int ifindex, guint8 *buf, size_t *length);
NMPlatformError nm_platform_link_set_address (NMPlatform *self, int ifindex, const void *address, size_t length);
gboolean nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu);
+gboolean nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name);
gboolean nm_platform_link_set_sriov_num_vfs (NMPlatform *self, int ifindex, guint num_vfs);
char *nm_platform_link_get_physical_port_id (NMPlatform *self, int ifindex);
diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c
index fec7ce375f..06703366f3 100644
--- a/src/ppp/nm-ppp-manager.c
+++ b/src/ppp/nm-ppp-manager.c
@@ -678,6 +678,7 @@ create_pppd_cmd_line (NMPPPManager *self,
const char *pppd_binary = NULL;
NMCmdLine *cmd;
gboolean ppp_debug;
+ static int unit;
g_return_val_if_fail (setting != NULL, NULL);
@@ -842,6 +843,15 @@ create_pppd_cmd_line (NMPPPManager *self,
nm_cmd_line_add_string (cmd, "plugin");
nm_cmd_line_add_string (cmd, NM_PPPD_PLUGIN);
+ if (pppoe && nm_setting_pppoe_get_parent (pppoe)) {
+ /* The PPP interface is going to be renamed, so pass a
+ * different unit each time so that activations don't
+ * race with each others. */
+ nm_cmd_line_add_string (cmd, "unit");
+ nm_cmd_line_add_int (cmd, unit);
+ unit = unit < G_MAXINT ? unit + 1 : 0;
+ }
+
return cmd;
}