NetworkManager/src/core/devices/nm-device-6lowpan.c
Thomas Haller ac1a9e03e4
all: move "src/" directory to "src/core/"
Currently "src/" mostly contains the source code of the daemon.
I say mostly, because that is not true, there are also the device,
settings, wwan, ppp plugins, the initrd generator, the pppd and dhcp
helper, and probably more.

Also we have source code under libnm-core/, libnm/, clients/, and
shared/ directories. That is all confusing.

We should have one "src" directory, that contains subdirectories. Those
subdirectories should contain individual parts (libraries or
applications), that possibly have dependencies on other subdirectories.
There should be a flat hierarchy of directories under src/, which
contains individual modules.

As the name "src/" is already taken, that prevents any sensible
restructuring of the code.

As a first step, move "src/" to "src/core/". This gives space to
reorganize the code better by moving individual components into "src/".

For inspiration, look at systemd's "src/" directory.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/743
2021-02-04 09:45:55 +01:00

339 lines
12 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2018 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-device-6lowpan.h"
#include "nm-device-private.h"
#include "settings/nm-settings.h"
#include "platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-6lowpan.h"
#include "nm-utils.h"
#define _NMLOG_DEVICE_TYPE NMDevice6Lowpan
#include "nm-device-logging.h"
/*****************************************************************************/
typedef struct {
gulong parent_state_id;
} NMDevice6LowpanPrivate;
struct _NMDevice6Lowpan {
NMDevice parent;
NMDevice6LowpanPrivate _priv;
};
struct _NMDevice6LowpanClass {
NMDeviceClass parent;
};
G_DEFINE_TYPE(NMDevice6Lowpan, nm_device_6lowpan, NM_TYPE_DEVICE)
#define NM_DEVICE_6LOWPAN_GET_PRIVATE(self) \
_NM_GET_PRIVATE(self, NMDevice6Lowpan, NM_IS_DEVICE_6LOWPAN, NMDevice)
/*****************************************************************************/
static void
parent_state_changed(NMDevice * parent,
NMDeviceState new_state,
NMDeviceState old_state,
NMDeviceStateReason reason,
gpointer user_data)
{
NMDevice6Lowpan *self = NM_DEVICE_6LOWPAN(user_data);
nm_device_set_unmanaged_by_flags(NM_DEVICE(self),
NM_UNMANAGED_PARENT,
!nm_device_get_managed(parent, FALSE),
reason);
}
static void
parent_changed_notify(NMDevice *device,
int old_ifindex,
NMDevice *old_parent,
int new_ifindex,
NMDevice *new_parent)
{
NMDevice6Lowpan * self = NM_DEVICE_6LOWPAN(device);
NMDevice6LowpanPrivate *priv = NM_DEVICE_6LOWPAN_GET_PRIVATE(self);
NM_DEVICE_CLASS(nm_device_6lowpan_parent_class)
->parent_changed_notify(device, old_ifindex, old_parent, new_ifindex, new_parent);
/* note that @self doesn't have to clear @parent_state_id on dispose,
* because NMDevice's dispose() will unset the parent, which in turn calls
* parent_changed_notify(). */
nm_clear_g_signal_handler(old_parent, &priv->parent_state_id);
if (new_parent) {
priv->parent_state_id = g_signal_connect(new_parent,
NM_DEVICE_STATE_CHANGED,
G_CALLBACK(parent_state_changed),
device);
/* Set parent-dependent unmanaged flag */
nm_device_set_unmanaged_by_flags(device,
NM_UNMANAGED_PARENT,
!nm_device_get_managed(new_parent, FALSE),
NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
}
if (new_ifindex > 0) {
/* Recheck availability now that the parent has changed */
nm_device_queue_recheck_available(device,
NM_DEVICE_STATE_REASON_PARENT_CHANGED,
NM_DEVICE_STATE_REASON_PARENT_CHANGED);
}
}
static gboolean
create_and_realize(NMDevice * device,
NMConnection * connection,
NMDevice * parent,
const NMPlatformLink **out_plink,
GError ** error)
{
const char * iface = nm_device_get_iface(device);
NMSetting6Lowpan *s_6lowpan;
int parent_ifindex;
int r;
s_6lowpan = NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN));
g_return_val_if_fail(s_6lowpan, FALSE);
parent_ifindex = parent ? nm_device_get_ifindex(parent) : 0;
if (parent_ifindex <= 0) {
g_set_error(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_MISSING_DEPENDENCIES,
"6LoWPAN devices can not be created without a parent interface");
g_return_val_if_fail(!parent, FALSE);
return FALSE;
}
r = nm_platform_link_6lowpan_add(nm_device_get_platform(device),
iface,
parent_ifindex,
out_plink);
if (r < 0) {
g_set_error(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create 6lowpan interface '%s' for '%s': %s",
iface,
nm_connection_get_id(connection),
nm_strerror(r));
return FALSE;
}
nm_device_parent_set_ifindex(device, parent_ifindex);
return TRUE;
}
static NMDeviceCapabilities
get_generic_capabilities(NMDevice *dev)
{
return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE;
}
static void
link_changed(NMDevice *device, const NMPlatformLink *pllink)
{
NMDevice6Lowpan *self = NM_DEVICE_6LOWPAN(device);
int parent = 0;
int ifindex;
NM_DEVICE_CLASS(nm_device_6lowpan_parent_class)->link_changed(device, pllink);
ifindex = nm_device_get_ifindex(device);
if (!nm_platform_link_6lowpan_get_properties(nm_device_get_platform(device),
ifindex,
&parent)) {
_LOGW(LOGD_DEVICE, "could not get 6lowpan properties");
return;
}
nm_device_parent_set_ifindex(device, parent);
}
static gboolean
is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
if (!nm_device_parent_get_device(device))
return FALSE;
return NM_DEVICE_CLASS(nm_device_6lowpan_parent_class)->is_available(device, flags);
}
static gboolean
complete_connection(NMDevice * device,
NMConnection * connection,
const char * specific_object,
NMConnection *const *existing_connections,
GError ** error)
{
NMSetting6Lowpan *s_6lowpan;
nm_utils_complete_generic(nm_device_get_platform(device),
connection,
NM_SETTING_6LOWPAN_SETTING_NAME,
existing_connections,
NULL,
_("6LOWPAN connection"),
NULL,
NULL,
TRUE);
s_6lowpan = NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN));
if (!s_6lowpan) {
g_set_error_literal(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INVALID_CONNECTION,
"A '6lowpan' setting is required.");
return FALSE;
}
/* If there's no 6LoWPAN interface, no parent, and no hardware address in the
* settings, then there's not enough information to complete the setting.
*/
if (!nm_setting_6lowpan_get_parent(s_6lowpan)
&& !nm_device_match_parent_hwaddr(device, connection, TRUE)) {
g_set_error_literal(
error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INVALID_CONNECTION,
"The '6lowpan' setting had no interface name, parent, or hardware address.");
return FALSE;
}
return TRUE;
}
static void
update_connection(NMDevice *device, NMConnection *connection)
{
NMSetting6Lowpan *s_6lowpan =
NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN));
if (!s_6lowpan) {
s_6lowpan = (NMSetting6Lowpan *) nm_setting_6lowpan_new();
nm_connection_add_setting(connection, (NMSetting *) s_6lowpan);
}
g_object_set(
s_6lowpan,
NM_SETTING_6LOWPAN_PARENT,
nm_device_parent_find_for_connection(device, nm_setting_6lowpan_get_parent(s_6lowpan)),
NULL);
}
/*****************************************************************************/
static void
nm_device_6lowpan_init(NMDevice6Lowpan *self)
{}
static const NMDBusInterfaceInfoExtended interface_info_device_6lowpan = {
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
NM_DBUS_INTERFACE_DEVICE_6LOWPAN,
.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Parent", "o", NM_DEVICE_PARENT), ), ),
};
static void
nm_device_6lowpan_class_init(NMDevice6LowpanClass *klass)
{
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
NMDeviceClass * device_class = NM_DEVICE_CLASS(klass);
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_6lowpan);
device_class->connection_type_supported = NM_SETTING_6LOWPAN_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_6LOWPAN_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_6LOWPAN);
device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
device_class->complete_connection = complete_connection;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
device_class->link_changed = link_changed;
device_class->is_available = is_available;
device_class->parent_changed_notify = parent_changed_notify;
device_class->update_connection = update_connection;
}
/*****************************************************************************/
#define NM_TYPE_6LOWPAN_DEVICE_FACTORY (nm_6lowpan_device_factory_get_type())
#define NM_6LOWPAN_DEVICE_FACTORY(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_6LOWPAN_DEVICE_FACTORY, NM6LowpanDeviceFactory))
static NMDevice *
create_device(NMDeviceFactory * factory,
const char * iface,
const NMPlatformLink *plink,
NMConnection * connection,
gboolean * out_ignore)
{
return g_object_new(NM_TYPE_DEVICE_6LOWPAN,
NM_DEVICE_IFACE,
iface,
NM_DEVICE_TYPE_DESC,
"6LoWPAN",
NM_DEVICE_DEVICE_TYPE,
NM_DEVICE_TYPE_6LOWPAN,
NM_DEVICE_LINK_TYPE,
NM_LINK_TYPE_6LOWPAN,
NULL);
}
static const char *
get_connection_parent(NMDeviceFactory *factory, NMConnection *connection)
{
NMSetting6Lowpan *s_6lowpan;
g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_6LOWPAN_SETTING_NAME), NULL);
s_6lowpan = NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN));
g_assert(s_6lowpan);
return nm_setting_6lowpan_get_parent(s_6lowpan);
}
static char *
get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface)
{
NMSetting6Lowpan *s_6lowpan;
const char * ifname;
g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_6LOWPAN_SETTING_NAME), NULL);
s_6lowpan = NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN));
g_assert(s_6lowpan);
if (!parent_iface)
return NULL;
ifname = nm_connection_get_interface_name(connection);
return g_strdup(ifname);
}
NM_DEVICE_FACTORY_DEFINE_INTERNAL(
6LOWPAN,
6Lowpan,
6lowpan,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_6LOWPAN)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_6LOWPAN_SETTING_NAME),
factory_class->create_device = create_device;
factory_class->get_connection_parent = get_connection_parent;
factory_class->get_connection_iface = get_connection_iface;);