NetworkManager/src/core/devices/nm-device-ppp.c
Thomas Haller 48dce1b66c
core: drop deprecated PropertiesChanged D-Bus signal (API BREAK)
D-Bus 1.3.1 (2010) introduced the standard "PropertiesChanged" signal
on "org.freedesktop.DBus.Properties". NetworkManager is old, and predates
this API. From that time, it still had it's own PropertiesChanged signal
that are emitted together with the standard ones. NetworkManager
supports the standard PropertiesChanged signal since it switched to
gdbus library in version 1.2.0 (2016).

These own signals are deprecated for a long time already ([1], 2016), and
are hopefully not used by anybody anymore. libnm-glib was using them and
relied on them, but that library is gone. libnm does not use them and neither
does plasma-nm.

Hopefully no users are left that are affected by this API break.

[1] 6fb917178a
2021-05-14 10:57:34 +02:00

372 lines
12 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2017 Red Hat, Inc.
*/
#include "src/core/nm-default-daemon.h"
#include "nm-device-ppp.h"
#include "nm-ip4-config.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 "libnm-platform/nm-platform.h"
#include "ppp/nm-ppp-manager.h"
#include "ppp/nm-ppp-manager-call.h"
#include "ppp/nm-ppp-status.h"
#define _NMLOG_DEVICE_TYPE NMDevicePpp
#include "nm-device-logging.h"
/*****************************************************************************/
typedef struct _NMDevicePppPrivate {
NMPPPManager *ppp_manager;
NMIP4Config * ip4_config;
} 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, NMDevice)
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;
default:
break;
}
}
static void
ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
{
NMDevice * device = NM_DEVICE(user_data);
NMDevicePpp * self = NM_DEVICE_PPP(device);
gs_free char *old_name = NULL;
gs_free_error GError *error = NULL;
if (!nm_device_take_over_link(device, ifindex, &old_name, &error)) {
_LOGW(LOGD_DEVICE | LOGD_PPP,
"could not take control of link %d: %s",
ifindex,
error->message);
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
return;
}
if (old_name)
nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP);
nm_device_activate_schedule_stage3_ip_config_start(device);
}
static void
ppp_ip4_config(NMPPPManager *ppp_manager, 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)) {
nm_device_activate_schedule_ip_config_result(device,
AF_INET,
NM_IP_CONFIG_CAST(config));
return;
}
} else {
if (priv->ip4_config)
g_object_unref(priv->ip4_config);
priv->ip4_config = g_object_ref(config);
}
}
static gboolean
check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingPppoe *s_pppoe;
if (!NM_DEVICE_CLASS(nm_device_ppp_parent_class)
->check_connection_compatible(device, connection, error))
return FALSE;
s_pppoe = nm_connection_get_setting_pppoe(connection);
if (!s_pppoe || !nm_setting_pppoe_get_parent(s_pppoe)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
"the connection doesn't specify a PPPoE parent interface");
return FALSE;
}
return TRUE;
}
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 * error = NULL;
req = nm_device_get_act_request(device);
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE);
g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
g_clear_object(&priv->ip4_config);
priv->ppp_manager = nm_ppp_manager_create(nm_setting_pppoe_get_parent(s_pppoe), &error);
if (priv->ppp_manager) {
nm_ppp_manager_set_route_parameters(priv->ppp_manager,
nm_device_get_route_table(device, AF_INET),
nm_device_get_route_metric(device, AF_INET),
nm_device_get_route_table(device, AF_INET6),
nm_device_get_route_metric(device, AF_INET6));
}
if (!priv->ppp_manager
|| !nm_ppp_manager_start(priv->ppp_manager,
req,
nm_setting_pppoe_get_username(s_pppoe),
30,
0,
&error)) {
_LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message);
g_error_free(error);
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_IFINDEX_SET,
G_CALLBACK(ppp_ifindex_set),
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_ip_config_start(NMDevice * device,
int addr_family,
gpointer * out_config,
NMDeviceStateReason *out_failure_reason)
{
if (addr_family == AF_INET) {
NMDevicePpp * self = NM_DEVICE_PPP(device);
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
if (priv->ip4_config) {
if (out_config)
*out_config = g_steal_pointer(&priv->ip4_config);
else
g_clear_object(&priv->ip4_config);
return NM_ACT_STAGE_RETURN_SUCCESS;
}
/* Wait IPCP termination */
return NM_ACT_STAGE_RETURN_POSTPONE;
}
return NM_DEVICE_CLASS(nm_device_ppp_parent_class)
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
}
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_MISSING_DEPENDENCIES,
"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(priv->ppp_manager, NULL, NULL, NULL);
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->ip4_config);
G_OBJECT_CLASS(nm_device_ppp_parent_class)->dispose(object);
}
static const NMDBusInterfaceInfoExtended interface_info_device_ppp = {
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(NM_DBUS_INTERFACE_DEVICE_PPP, ),
};
static void
nm_device_ppp_class_init(NMDevicePppClass *klass)
{
GObjectClass * object_class = G_OBJECT_CLASS(klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
NMDeviceClass * device_class = NM_DEVICE_CLASS(klass);
object_class->dispose = dispose;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_ppp);
device_class->connection_type_supported = NM_SETTING_PPPOE_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_PPPOE_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_PPP);
device_class->act_stage2_config = act_stage2_config;
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
device_class->check_connection_compatible = check_connection_compatible;
device_class->create_and_realize = create_and_realize;
device_class->deactivate = deactivate;
device_class->get_generic_capabilities = get_generic_capabilities;
}
/*****************************************************************************/
#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 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;);