diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2016-06-30 18:20:22 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-01-16 17:37:14 +0100 |
commit | 67adbda83e0f4ee3a03d7c40c30a1058fd76a211 (patch) | |
tree | e7d2e6492b5d0336f6092b8736abd2981b57e9fe /src | |
parent | 85103656e97bedf4cdd80c7eb1832b59f4a29686 (diff) | |
download | NetworkManager-67adbda83e0f4ee3a03d7c40c30a1058fd76a211.tar.gz |
core,libnm: introduce NMDeviceMacsec
At the moment the device only exposes the current link status, but
cannot create new links.
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/nm-device-factory.c | 1 | ||||
-rw-r--r-- | src/devices/nm-device-macsec.c | 365 | ||||
-rw-r--r-- | src/devices/nm-device-macsec.h | 54 | ||||
-rw-r--r-- | src/devices/nm-device.c | 2 |
4 files changed, 422 insertions, 0 deletions
diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index dc8e26605b..0ce2cb48c5 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -405,6 +405,7 @@ nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc call _ADD_INTERNAL (nm_ethernet_device_factory_get_type); _ADD_INTERNAL (nm_infiniband_device_factory_get_type); _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_tun_device_factory_get_type); _ADD_INTERNAL (nm_veth_device_factory_get_type); diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c new file mode 100644 index 0000000000..8558ba120c --- /dev/null +++ b/src/devices/nm-device-macsec.c @@ -0,0 +1,365 @@ +/* -*- 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-device-macsec.h" + +#include "nm-device-private.h" +#include "platform/nm-platform.h" +#include "nm-device-factory.h" +#include "nm-manager.h" +#include "nm-core-internal.h" + +#include "introspection/org.freedesktop.NetworkManager.Device.Macsec.h" + +#include "nm-device-logging.h" +_LOG_DECLARE_SELF(NMDeviceMacsec); + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceMacsec, + PROP_SCI, + PROP_CIPHER_SUITE, + PROP_ICV_LENGTH, + PROP_WINDOW, + PROP_ENCODING_SA, + PROP_ENCRYPT, + PROP_PROTECT, + PROP_INCLUDE_SCI, + PROP_ES, + PROP_SCB, + PROP_REPLAY_PROTECT, + PROP_VALIDATION, +); + +typedef struct { + NMPlatformLnkMacsec props; + gulong parent_state_id; +} NMDeviceMacsecPrivate; + +struct _NMDeviceMacsec { + NMDevice parent; + NMDeviceMacsecPrivate _priv; +}; + +struct _NMDeviceMacsecClass { + NMDeviceClass parent; +}; + +G_DEFINE_TYPE (NMDeviceMacsec, nm_device_macsec, NM_TYPE_DEVICE) + +#define NM_DEVICE_MACSEC_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceMacsec, NM_IS_DEVICE_MACSEC) + +/******************************************************************/ + +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (validation_mode_to_string, guint8, + NM_UTILS_LOOKUP_DEFAULT_WARN ("<unknown>"), + NM_UTILS_LOOKUP_STR_ITEM (0, "disable"), + NM_UTILS_LOOKUP_STR_ITEM (1, "check"), + NM_UTILS_LOOKUP_STR_ITEM (2, "strict"), +); + +static void +parent_state_changed (NMDevice *parent, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceMacsec *self = NM_DEVICE_MACSEC (user_data); + + /* We'll react to our own carrier state notifications. Ignore the parent's. */ + if (reason == NM_DEVICE_STATE_REASON_CARRIER) + return; + + 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) +{ + NMDeviceMacsec *self = NM_DEVICE_MACSEC (device); + NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); + + NM_DEVICE_CLASS (nm_device_macsec_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); + } + + /* Recheck availability now that the parent has changed */ + if (new_ifindex > 0) { + nm_device_queue_recheck_available (device, + NM_DEVICE_STATE_REASON_PARENT_CHANGED, + NM_DEVICE_STATE_REASON_PARENT_CHANGED); + } +} + +static void +update_properties (NMDevice *device) +{ + NMDeviceMacsec *self; + NMDeviceMacsecPrivate *priv; + const NMPlatformLink *plink = NULL; + const NMPlatformLnkMacsec *props = NULL; + int ifindex; + + g_return_if_fail (NM_IS_DEVICE_MACSEC (device)); + self = NM_DEVICE_MACSEC (device); + priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); + + ifindex = nm_device_get_ifindex (device); + g_return_if_fail (ifindex > 0); + props = nm_platform_link_get_lnk_macsec (NM_PLATFORM_GET, ifindex, &plink); + + if (!props) { + _LOGW (LOGD_PLATFORM, "could not get macsec properties"); + return; + } + + g_object_freeze_notify ((GObject *) device); + + if (priv->props.parent_ifindex != props->parent_ifindex) + nm_device_parent_set_ifindex (device, props->parent_ifindex); + +#define CHECK_PROPERTY_CHANGED(field, prop) \ + if (props->field != priv->props.field) \ + _notify (self, prop) + + CHECK_PROPERTY_CHANGED (sci, PROP_SCI); + CHECK_PROPERTY_CHANGED (cipher_suite, PROP_CIPHER_SUITE); + CHECK_PROPERTY_CHANGED (window, PROP_WINDOW); + CHECK_PROPERTY_CHANGED (icv_length, PROP_ICV_LENGTH); + CHECK_PROPERTY_CHANGED (encoding_sa, PROP_ENCODING_SA); + CHECK_PROPERTY_CHANGED (validation, PROP_VALIDATION); + CHECK_PROPERTY_CHANGED (encrypt, PROP_ENCRYPT); + CHECK_PROPERTY_CHANGED (protect, PROP_PROTECT); + CHECK_PROPERTY_CHANGED (include_sci, PROP_INCLUDE_SCI); + CHECK_PROPERTY_CHANGED (es, PROP_ES); + CHECK_PROPERTY_CHANGED (scb, PROP_SCB); + CHECK_PROPERTY_CHANGED (replay_protect, PROP_REPLAY_PROTECT); + + priv->props = *props; + g_object_thaw_notify ((GObject *) device); +} + +/******************************************************************/ + +static NMDeviceCapabilities +get_generic_capabilities (NMDevice *dev) +{ + /* We assume MACsec interfaces always support carrier detect */ + return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE; +} + +/******************************************************************/ + +static gboolean +is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) +{ + if (!nm_device_parent_get_device (device)) + return FALSE; + return NM_DEVICE_CLASS (nm_device_macsec_parent_class)->is_available (device, flags); +} + +static void +link_changed (NMDevice *device, + const NMPlatformLink *pllink) +{ + NM_DEVICE_CLASS (nm_device_macsec_parent_class)->link_changed (device, pllink); + update_properties (device); +} + +/******************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceMacsec *self = NM_DEVICE_MACSEC (object); + NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_SCI: + g_value_set_uint64 (value, priv->props.sci); + break; + case PROP_CIPHER_SUITE: + g_value_set_uint64 (value, priv->props.cipher_suite); + break; + case PROP_ICV_LENGTH: + g_value_set_uchar (value, priv->props.icv_length); + break; + case PROP_WINDOW: + g_value_set_uint (value, priv->props.window); + break; + case PROP_ENCODING_SA: + g_value_set_uchar (value, priv->props.encoding_sa); + break; + case PROP_ENCRYPT: + g_value_set_boolean (value, priv->props.encrypt); + break; + case PROP_PROTECT: + g_value_set_boolean (value, priv->props.protect); + break; + case PROP_INCLUDE_SCI: + g_value_set_boolean (value, priv->props.include_sci); + break; + case PROP_ES: + g_value_set_boolean (value, priv->props.es); + break; + case PROP_SCB: + g_value_set_boolean (value, priv->props.scb); + break; + case PROP_REPLAY_PROTECT: + g_value_set_boolean (value, priv->props.replay_protect); + break; + case PROP_VALIDATION: + g_value_set_string (value, + validation_mode_to_string (priv->props.validation)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_macsec_init (NMDeviceMacsec * self) +{ +} + +static void +nm_device_macsec_class_init (NMDeviceMacsecClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACSEC) + + object_class->get_property = get_property; + + parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->is_available = is_available; + parent_class->link_changed = link_changed; + parent_class->parent_changed_notify = parent_changed_notify; + + obj_properties[PROP_SCI] = + g_param_spec_uint64 (NM_DEVICE_MACSEC_SCI, "", "", + 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_CIPHER_SUITE] = + g_param_spec_uint64 (NM_DEVICE_MACSEC_CIPHER_SUITE, "", "", + 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ICV_LENGTH] = + g_param_spec_uchar (NM_DEVICE_MACSEC_ICV_LENGTH, "", "", + 0, G_MAXUINT8, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_WINDOW] = + g_param_spec_uint (NM_DEVICE_MACSEC_WINDOW, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ENCODING_SA] = + g_param_spec_uchar (NM_DEVICE_MACSEC_ENCODING_SA, "", "", + 0, 3, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_VALIDATION] = + g_param_spec_string (NM_DEVICE_MACSEC_VALIDATION, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ENCRYPT] = + g_param_spec_boolean (NM_DEVICE_MACSEC_ENCRYPT, "", "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_PROTECT] = + g_param_spec_boolean (NM_DEVICE_MACSEC_PROTECT, "", "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_INCLUDE_SCI] = + g_param_spec_boolean (NM_DEVICE_MACSEC_INCLUDE_SCI, "", "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ES] = + g_param_spec_boolean (NM_DEVICE_MACSEC_ES, "", "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_SCB] = + g_param_spec_boolean (NM_DEVICE_MACSEC_SCB, "", "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_REPLAY_PROTECT] = + g_param_spec_boolean (NM_DEVICE_MACSEC_REPLAY_PROTECT, "", "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_MACSEC_SKELETON, + NULL); +} + +/*************************************************************/ + +#define NM_TYPE_MACSEC_DEVICE_FACTORY (nm_macsec_device_factory_get_type ()) +#define NM_MACSEC_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MACSEC_DEVICE_FACTORY, NMMacsecDeviceFactory)) + +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_MACSEC, + NM_DEVICE_IFACE, iface, + NM_DEVICE_TYPE_DESC, "Macsec", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MACSEC, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_MACSEC, + NULL); +} + +NM_DEVICE_FACTORY_DEFINE_INTERNAL (MACSEC, Macsec, macsec, + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_MACSEC), + factory_class->create_device = create_device; +) diff --git a/src/devices/nm-device-macsec.h b/src/devices/nm-device-macsec.h new file mode 100644 index 0000000000..17b33bf593 --- /dev/null +++ b/src/devices/nm-device-macsec.h @@ -0,0 +1,54 @@ +/* -*- 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_MACSEC_H__ +#define __NM_DEVICE_MACSEC_H__ + +#include "nm-device.h" + +#define NM_TYPE_DEVICE_MACSEC (nm_device_macsec_get_type ()) +#define NM_DEVICE_MACSEC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_MACSEC, NMDeviceMacsec)) +#define NM_DEVICE_MACSEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_MACSEC, NMDeviceMacsecClass)) +#define NM_IS_DEVICE_MACSEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_MACSEC)) +#define NM_IS_DEVICE_MACSEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_MACSEC)) +#define NM_DEVICE_MACSEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_MACSEC, NMDeviceMacsecClass)) + +#define NM_DEVICE_MACSEC_SCI "sci" +#define NM_DEVICE_MACSEC_CIPHER_SUITE "cipher-suite" +#define NM_DEVICE_MACSEC_ICV_LENGTH "icv-length" +#define NM_DEVICE_MACSEC_WINDOW "window" +#define NM_DEVICE_MACSEC_ENCODING_SA "encoding-sa" +#define NM_DEVICE_MACSEC_VALIDATION "validation" +#define NM_DEVICE_MACSEC_ENCRYPT "encrypt" +#define NM_DEVICE_MACSEC_PROTECT "protect" +#define NM_DEVICE_MACSEC_INCLUDE_SCI "include-sci" +#define NM_DEVICE_MACSEC_ES "es" +#define NM_DEVICE_MACSEC_SCB "scb" +#define NM_DEVICE_MACSEC_REPLAY_PROTECT "replay-protect" + +/* defined in the parent class, but exposed on D-Bus by the subclass. */ +#define NM_DEVICE_MACSEC_PARENT NM_DEVICE_PARENT + +typedef struct _NMDeviceMacsec NMDeviceMacsec; +typedef struct _NMDeviceMacsecClass NMDeviceMacsecClass; + +GType nm_device_macsec_get_type (void); + +#endif /* __NM_DEVICE_MACSEC_H__ */ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index c236a85803..f0a218ee18 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1330,6 +1330,8 @@ nm_device_get_priority (NMDevice *self) case NM_DEVICE_TYPE_ETHERNET: case NM_DEVICE_TYPE_VETH: return 100; + case NM_DEVICE_TYPE_MACSEC: + return 125; case NM_DEVICE_TYPE_INFINIBAND: return 150; case NM_DEVICE_TYPE_ADSL: |