summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-rtnl/rtnl-types.c
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2015-02-08 12:37:05 +0100
committerTom Gundersen <teg@jklm.no>2015-02-08 17:43:39 +0100
commit4af7b60d428765c2d2c66c46f416f6dae55e9ddb (patch)
treeed1f20a91b4c4c5a87d73fbba4eb2f9c875ec65c /src/libsystemd/sd-rtnl/rtnl-types.c
parent02f500532e4823584aae43cbe762914b4a0c0254 (diff)
sd-rtnl: extend type system to allow address-family to decide the union members
So far we only supported selecting them by sibling attributes. (This stuff is all a bit crazy, but there seems to be no other way...)
Diffstat (limited to 'src/libsystemd/sd-rtnl/rtnl-types.c')
-rw-r--r--src/libsystemd/sd-rtnl/rtnl-types.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c
index d4abe4cc3b..4ef698a7f5 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -224,6 +224,7 @@ static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
.num = _NL_UNION_LINK_INFO_DATA_MAX,
.lookup = nl_union_link_info_data_from_string,
.type_systems = rtnl_link_info_data_type_systems,
+ .match_type = NL_MATCH_SIBLING,
.match = IFLA_INFO_KIND,
};
@@ -242,7 +243,7 @@ static const NLTypeSystem rtnl_link_info_type_system = {
.types = rtnl_link_info_types,
};
-static const struct NLType rtnl_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
+static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_STATE] = { .type = NLA_U8 },
[IFLA_BRPORT_COST] = { .type = NLA_U32 },
[IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
@@ -253,9 +254,15 @@ static const struct NLType rtnl_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
};
-static const NLTypeSystem rtnl_bridge_port_type_system = {
- .max = ELEMENTSOF(rtnl_bridge_port_types) - 1,
- .types = rtnl_bridge_port_types,
+static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = {
+ [AF_BRIDGE] = { .max = ELEMENTSOF(rtnl_prot_info_bridge_port_types) - 1,
+ .types = rtnl_prot_info_bridge_port_types },
+};
+
+static const NLTypeSystemUnion rtnl_prot_info_type_system_union = {
+ .num = AF_MAX,
+ .type_systems = rtnl_prot_info_type_systems,
+ .match_type = NL_MATCH_PROTOCOL,
};
static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
@@ -273,9 +280,8 @@ static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
[IFLA_MASTER] = { .type = NLA_U32 },
/*
[IFLA_WIRELESS],
- [IFLA_PROTINFO],
*/
- [IFLA_PROTINFO] = { .type = NLA_NESTED, .type_system = &rtnl_bridge_port_type_system },
+ [IFLA_PROTINFO] = { .type = NLA_UNION, .type_system_union = &rtnl_prot_info_type_system_union },
[IFLA_TXQLEN] = { .type = NLA_U32 },
/*
[IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
@@ -463,6 +469,7 @@ int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union
int type;
assert(type_system_union);
+ assert_return(type_system_union->match_type == NL_MATCH_SIBLING, -EINVAL);
assert(type_system_union->lookup);
assert(type_system_union->type_systems);
assert(ret);
@@ -478,3 +485,25 @@ int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union
return 0;
}
+
+int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol) {
+ const NLTypeSystem *type_system;
+
+ assert(type_system_union);
+ assert(type_system_union->type_systems);
+ assert(ret);
+ assert_return(type_system_union->match_type == NL_MATCH_PROTOCOL, -EINVAL);
+ assert_return(protocol < type_system_union->num, -EINVAL);
+
+ if (protocol >= type_system_union->num)
+ return -ENOTSUP;
+
+ type_system = &type_system_union->type_systems[protocol];
+
+ if (!type_system)
+ return -ENOTSUP;
+
+ *ret = type_system;
+
+ return 0;
+}