diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2016-06-30 18:20:09 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-01-16 17:37:14 +0100 |
commit | 85103656e97bedf4cdd80c7eb1832b59f4a29686 (patch) | |
tree | 05b98e8694fefa0bdc8fa8c3ae63823633dc09de /src | |
parent | 00463a6e09ba33c263112a775030eae2057e36fa (diff) | |
download | NetworkManager-85103656e97bedf4cdd80c7eb1832b59f4a29686.tar.gz |
platform: add support for macsec links
Add support for a new macsec link type and its netlink attributes to
the platform code.
Diffstat (limited to 'src')
-rw-r--r-- | src/nm-types.h | 2 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 137 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 95 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 29 | ||||
-rw-r--r-- | src/platform/nmp-object.c | 9 | ||||
-rw-r--r-- | src/platform/nmp-object.h | 7 |
6 files changed, 279 insertions, 0 deletions
diff --git a/src/nm-types.h b/src/nm-types.h index 8f0cc5849f..c323c9a786 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -129,6 +129,7 @@ typedef enum { NM_LINK_TYPE_IP6TNL, NM_LINK_TYPE_IPIP, NM_LINK_TYPE_LOOPBACK, + NM_LINK_TYPE_MACSEC, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP, NM_LINK_TYPE_OPENVSWITCH, @@ -160,6 +161,7 @@ typedef enum { NMP_OBJECT_TYPE_LNK_INFINIBAND, NMP_OBJECT_TYPE_LNK_IP6TNL, NMP_OBJECT_TYPE_LNK_IPIP, + NMP_OBJECT_TYPE_LNK_MACSEC, NMP_OBJECT_TYPE_LNK_MACVLAN, NMP_OBJECT_TYPE_LNK_MACVTAP, NMP_OBJECT_TYPE_LNK_SIT, diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 7b68d14437..ef946e39a0 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -21,6 +21,7 @@ #include "nm-linux-platform.h" +#include <endian.h> #include <errno.h> #include <unistd.h> #include <sys/socket.h> @@ -111,6 +112,25 @@ /*****************************************************************************/ +#define IFLA_MACSEC_UNSPEC 0 +#define IFLA_MACSEC_SCI 1 +#define IFLA_MACSEC_PORT 2 +#define IFLA_MACSEC_ICV_LEN 3 +#define IFLA_MACSEC_CIPHER_SUITE 4 +#define IFLA_MACSEC_WINDOW 5 +#define IFLA_MACSEC_ENCODING_SA 6 +#define IFLA_MACSEC_ENCRYPT 7 +#define IFLA_MACSEC_PROTECT 8 +#define IFLA_MACSEC_INC_SCI 9 +#define IFLA_MACSEC_ES 10 +#define IFLA_MACSEC_SCB 11 +#define IFLA_MACSEC_REPLAY_PROTECT 12 +#define IFLA_MACSEC_VALIDATION 13 +#define IFLA_MACSEC_PAD 14 +#define __IFLA_MACSEC_MAX 15 + +/*****************************************************************************/ + #define _NMLOG_PREFIX_NAME "platform-linux" #define _NMLOG_DOMAIN LOGD_PLATFORM #define _NMLOG2_DOMAIN LOGD_PLATFORM @@ -365,6 +385,7 @@ static const LinkDesc linktypes[] = { { NM_LINK_TYPE_IP6TNL, "ip6tnl", "ip6tnl", NULL }, { NM_LINK_TYPE_IPIP, "ipip", "ipip", NULL }, { NM_LINK_TYPE_LOOPBACK, "loopback", NULL, NULL }, + { NM_LINK_TYPE_MACSEC, "macsec", "macsec", NULL }, { NM_LINK_TYPE_MACVLAN, "macvlan", "macvlan", NULL }, { NM_LINK_TYPE_MACVTAP, "macvtap", "macvtap", NULL }, { NM_LINK_TYPE_OPENVSWITCH, "openvswitch", "openvswitch", NULL }, @@ -1110,6 +1131,56 @@ _parse_lnk_macvlan (const char *kind, struct nlattr *info_data) /*****************************************************************************/ static NMPObject * +_parse_lnk_macsec (const char *kind, struct nlattr *info_data) +{ + static struct nla_policy policy[__IFLA_MACSEC_MAX] = { + [IFLA_MACSEC_SCI] = { .type = NLA_U64 }, + [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 }, + [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 }, + [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 }, + [IFLA_MACSEC_ENCODING_SA] = { .type = NLA_U8 }, + [IFLA_MACSEC_ENCRYPT] = { .type = NLA_U8 }, + [IFLA_MACSEC_PROTECT] = { .type = NLA_U8 }, + [IFLA_MACSEC_INC_SCI] = { .type = NLA_U8 }, + [IFLA_MACSEC_ES] = { .type = NLA_U8 }, + [IFLA_MACSEC_SCB] = { .type = NLA_U8 }, + [IFLA_MACSEC_REPLAY_PROTECT] = { .type = NLA_U8 }, + [IFLA_MACSEC_VALIDATION] = { .type = NLA_U8 }, + }; + struct nlattr *tb[__IFLA_MACSEC_MAX]; + int err; + NMPObject *obj; + NMPlatformLnkMacsec *props; + + if (!info_data || !nm_streq0 (kind, "macsec")) + return NULL; + + err = nla_parse_nested (tb, __IFLA_MACSEC_MAX - 1, info_data, policy); + if (err < 0) + return NULL; + + obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_MACSEC, NULL); + props = &obj->lnk_macsec; + + props->sci = tb[IFLA_MACSEC_SCI] ? be64toh (nla_get_u64 (tb[IFLA_MACSEC_SCI])) : 0; + props->icv_length = tb[IFLA_MACSEC_ICV_LEN] ? nla_get_u8 (tb[IFLA_MACSEC_ICV_LEN]) : 0; + props->cipher_suite = tb [IFLA_MACSEC_CIPHER_SUITE] ? nla_get_u64 (tb[IFLA_MACSEC_CIPHER_SUITE]) : 0; + props->window = tb [IFLA_MACSEC_WINDOW] ? nla_get_u32 (tb[IFLA_MACSEC_WINDOW]) : 0; + props->encoding_sa = tb[IFLA_MACSEC_ENCODING_SA] ? !!nla_get_u8 (tb[IFLA_MACSEC_ENCODING_SA]) : 0; + props->encrypt = tb[IFLA_MACSEC_ENCRYPT] ? !!nla_get_u8 (tb[IFLA_MACSEC_ENCRYPT]) : 0; + props->protect = tb[IFLA_MACSEC_PROTECT] ? !!nla_get_u8 (tb[IFLA_MACSEC_PROTECT]) : 0; + props->include_sci = tb[IFLA_MACSEC_INC_SCI] ? !!nla_get_u8 (tb[IFLA_MACSEC_INC_SCI]) : 0; + props->es = tb[IFLA_MACSEC_ES] ? !!nla_get_u8 (tb[IFLA_MACSEC_ES]) : 0; + props->scb = tb[IFLA_MACSEC_SCB] ? !!nla_get_u8 (tb[IFLA_MACSEC_SCB]) : 0; + props->replay_protect = tb[IFLA_MACSEC_REPLAY_PROTECT] ? !!nla_get_u8 (tb[IFLA_MACSEC_REPLAY_PROTECT]) : 0; + props->validation = tb[IFLA_MACSEC_VALIDATION] ? nla_get_u8 (tb[IFLA_MACSEC_VALIDATION]) : 0; + + return obj; +} + +/*****************************************************************************/ + +static NMPObject * _parse_lnk_sit (const char *kind, struct nlattr *info_data) { static struct nla_policy policy[IFLA_IPTUN_MAX + 1] = { @@ -1555,6 +1626,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr case NM_LINK_TYPE_IPIP: lnk_data = _parse_lnk_ipip (nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_MACSEC: + lnk_data = _parse_lnk_macsec (nl_info_kind, nl_info_data); + break; case NM_LINK_TYPE_MACVLAN: case NM_LINK_TYPE_MACVTAP: lnk_data = _parse_lnk_macvlan (nl_info_kind, nl_info_data); @@ -4813,6 +4887,68 @@ nla_put_failure: } static int +link_macsec_add (NMPlatform *platform, + const char *name, + int parent, + const NMPlatformLnkMacsec *props, + const NMPlatformLink **out_link) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr *info; + struct nlattr *data; + + _LOGD ("adding macsec '%s' parent %u sci %llx", + name, + parent, + (unsigned long long) props->sci); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, + NLM_F_CREATE | NLM_F_EXCL, + 0, + name, + 0, + 0); + if (!nlmsg) + return FALSE; + + NLA_PUT_U32 (nlmsg, IFLA_LINK, parent); + + if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "macsec"); + + if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->icv_length) + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_ICV_LEN, 16); + if (props->cipher_suite) + NLA_PUT_U64 (nlmsg, IFLA_MACSEC_CIPHER_SUITE, props->cipher_suite); + if (props->replay_protect) + NLA_PUT_U32 (nlmsg, IFLA_MACSEC_WINDOW, props->window); + + NLA_PUT_U64 (nlmsg, IFLA_MACSEC_SCI, htobe64 (props->sci)); + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_ENCODING_SA, props->encoding_sa); + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_ENCRYPT, props->encrypt); + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_PROTECT, props->protect); + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_INC_SCI, props->include_sci); + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_ES, props->es); + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_SCB, props->scb); + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_REPLAY_PROTECT, props->replay_protect); + NLA_PUT_U8 (nlmsg, IFLA_MACSEC_VALIDATION, props->validation); + + nla_nest_end (nlmsg, data); + nla_nest_end (nlmsg, info); + + return do_add_link_with_lookup (platform, + NM_LINK_TYPE_MACSEC, + name, nlmsg, out_link); +nla_put_failure: + g_return_val_if_reached (FALSE); +} + +static int link_macvlan_add (NMPlatform *platform, const char *name, int parent, @@ -6654,6 +6790,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->link_gre_add = link_gre_add; platform_class->link_ip6tnl_add = link_ip6tnl_add; + platform_class->link_macsec_add = link_macsec_add; platform_class->link_macvlan_add = link_macvlan_add; platform_class->link_ipip_add = link_ipip_add; platform_class->link_sit_add = link_sit_add; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 0b23b67f14..4552f76069 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1527,6 +1527,12 @@ nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLi return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IPIP, out_link); } +const NMPlatformLnkMacsec * +nm_platform_link_get_lnk_macsec (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACSEC, out_link); +} + const NMPlatformLnkMacvlan * nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -2171,6 +2177,43 @@ nm_platform_link_ipip_add (NMPlatform *self, } /** + * nm_platform_macsec_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create a MACsec interface. + */ +NMPlatformError +nm_platform_link_macsec_add (NMPlatform *self, + const char *name, + int parent, + const NMPlatformLnkMacsec *props, + const NMPlatformLink **out_link) +{ + NMPlatformError plerr; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_MACSEC, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD ("adding macsec '%s' parent %u sci %llx", + name, + parent, + (unsigned long long) props->sci); + + if (!klass->link_macsec_add (self, name, parent, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + +/** * nm_platform_macvlan_add: * @self: platform instance * @name: name of the new interface @@ -3484,6 +3527,39 @@ nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize l } const char * +nm_platform_lnk_macsec_to_string (const NMPlatformLnkMacsec *lnk, char *buf, gsize len) +{ + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "macsec " + "sci %016llx " + "protect %s " + "cipher %016llx " + "icvlen %u " + "encodingsa %u " + "validate %u " + "encrypt %s " + "send_sci %s " + "end_station %s " + "scb %s " + "replay %s", + (unsigned long long) lnk->sci, + lnk->protect ? "on" : "off", + (unsigned long long) lnk->cipher_suite, + lnk->icv_length, + lnk->encoding_sa, + lnk->validation, + lnk->encrypt ? "on" : "off", + lnk->include_sci ? "on" : "off", + lnk->es ? "on" : "off", + lnk->scb ? "on" : "off", + lnk->replay_protect ? "on" : "off"); + return buf; +} + +const char * nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len) { if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) @@ -4065,6 +4141,25 @@ nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b } int +nm_platform_lnk_macsec_cmp (const NMPlatformLnkMacsec *a, const NMPlatformLnkMacsec *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, sci); + _CMP_FIELD (a, b, icv_length); + _CMP_FIELD (a, b, cipher_suite); + _CMP_FIELD (a, b, window); + _CMP_FIELD (a, b, encoding_sa); + _CMP_FIELD (a, b, validation); + _CMP_FIELD (a, b, encrypt); + _CMP_FIELD (a, b, protect); + _CMP_FIELD (a, b, include_sci); + _CMP_FIELD (a, b, es); + _CMP_FIELD (a, b, scb); + _CMP_FIELD (a, b, replay_protect); + return 0; +} + +int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b) { _CMP_SELF (a, b); diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 91f8ab5d6f..f0b2cc8225 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -427,6 +427,22 @@ typedef struct { } NMPlatformLnkIpIp; typedef struct { + int parent_ifindex; + guint64 sci; /* host byte order */ + guint64 cipher_suite; + guint32 window; + guint8 icv_length; + guint8 encoding_sa; + guint8 validation; + bool encrypt:1; + bool protect:1; + bool include_sci:1; + bool es:1; + bool scb:1; + bool replay_protect:1; +} NMPlatformLnkMacsec; + +typedef struct { guint mode; bool no_promisc:1; bool tap:1; @@ -588,6 +604,11 @@ typedef struct { const char *name, const NMPlatformLnkIpIp *props, const NMPlatformLink **out_link); + gboolean (*link_macsec_add) (NMPlatform *, + const char *name, + int parent, + const NMPlatformLnkMacsec *props, + const NMPlatformLink **out_link); gboolean (*link_macvlan_add) (NMPlatform *, const char *name, int parent, @@ -818,6 +839,7 @@ const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, in const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkMacsec *nm_platform_link_get_lnk_macsec (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkMacvtap *nm_platform_link_get_lnk_macvtap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkSit *nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); @@ -902,6 +924,11 @@ NMPlatformError nm_platform_link_ipip_add (NMPlatform *self, const char *name, const NMPlatformLnkIpIp *props, const NMPlatformLink **out_link); +NMPlatformError nm_platform_link_macsec_add (NMPlatform *self, + const char *name, + int parent, + const NMPlatformLnkMacsec *props, + const NMPlatformLink **out_link); NMPlatformError nm_platform_link_macvlan_add (NMPlatform *self, const char *name, int parent, @@ -956,6 +983,7 @@ const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *bu const char *nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); const char *nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len); const char *nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize len); +const char *nm_platform_lnk_macsec_to_string (const NMPlatformLnkMacsec *lnk, char *buf, gsize len); const char *nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len); const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len); const char *nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len); @@ -976,6 +1004,7 @@ int nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre * int nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b); int nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b); int nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b); +int nm_platform_lnk_macsec_cmp (const NMPlatformLnkMacsec *a, const NMPlatformLnkMacsec *b); int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b); int nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b); int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index e1e13882da..1503ca9a17 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -2230,6 +2230,15 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ipip_to_string, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ipip_cmp, }, + [NMP_OBJECT_TYPE_LNK_MACSEC - 1] = { + .obj_type = NMP_OBJECT_TYPE_LNK_MACSEC, + .sizeof_data = sizeof (NMPObjectLnkMacsec), + .sizeof_public = sizeof (NMPlatformLnkMacsec), + .obj_type_name = "macsec", + .lnk_link_type = NM_LINK_TYPE_MACSEC, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_macsec_to_string, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macsec_cmp, + }, [NMP_OBJECT_TYPE_LNK_MACVLAN - 1] = { .obj_type = NMP_OBJECT_TYPE_LNK_MACVLAN, .sizeof_data = sizeof (NMPObjectLnkMacvlan), diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 7a91583a25..dd11b98586 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -207,6 +207,10 @@ typedef struct { } NMPObjectLnkIpIp; typedef struct { + NMPlatformLnkMacsec _public; +} NMPObjectLnkMacsec; + +typedef struct { NMPlatformLnkMacvlan _public; } NMPObjectLnkMacvlan; @@ -267,6 +271,9 @@ struct _NMPObject { NMPlatformLnkIp6Tnl lnk_ip6tnl; NMPObjectLnkIp6Tnl _lnk_ip6tnl; + NMPlatformLnkMacsec lnk_macsec; + NMPObjectLnkMacsec _lnk_macsec; + NMPlatformLnkMacvlan lnk_macvlan; NMPObjectLnkMacvlan _lnk_macvlan; |