]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-rtnl/rtnl-types.c
networkd: add FDB support
[thirdparty/systemd.git] / src / libsystemd / sd-rtnl / rtnl-types.c
CommitLineData
d8e538ec
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <stddef.h>
23#include <stdint.h>
24#include <sys/socket.h>
25#include <linux/netlink.h>
26#include <linux/rtnetlink.h>
27#include <linux/in6.h>
28#include <linux/veth.h>
29#include <linux/if_bridge.h>
30#include <linux/if_addr.h>
31#include <linux/if.h>
32
0a827d10
SS
33#include <linux/ip.h>
34#include <linux/if_tunnel.h>
35
d8e538ec
TG
36#include "macro.h"
37#include "util.h"
38
39#include "rtnl-types.h"
0830ba61 40#include "missing.h"
d8e538ec
TG
41
42static const NLTypeSystem rtnl_link_type_system;
43
44static const NLType rtnl_link_info_data_veth_types[VETH_INFO_MAX + 1] = {
45 [VETH_INFO_PEER] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
46};
47
48
49static const NLType rtnl_link_info_data_macvlan_types[IFLA_MACVLAN_MAX + 1] = {
50 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
51 [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
52};
53
54static const NLType rtnl_link_info_data_bridge_types[IFLA_BRIDGE_MAX + 1] = {
55 [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 },
56 [IFLA_BRIDGE_MODE] = { .type = NLA_U16 },
57/*
58 [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
59 .len = sizeof(struct bridge_vlan_info), },
60*/
61};
62
63static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = {
64 [IFLA_VLAN_ID] = { .type = NLA_U16 },
65/*
66 [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) },
67 [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED },
68 [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
69*/
70 [IFLA_VLAN_PROTOCOL] = { .type = NLA_U16 },
71};
72
6ef81477
SS
73static const NLType rtnl_link_info_data_vxlan_types[IFLA_VXLAN_MAX+1] = {
74 [IFLA_VXLAN_ID] = { .type = NLA_U32 },
75 [IFLA_VXLAN_GROUP] = {.type = NLA_IN_ADDR },
76 [IFLA_VXLAN_LINK] = { .type = NLA_U32 },
77 [IFLA_VXLAN_LOCAL] = { .type = NLA_U32},
78 [IFLA_VXLAN_TTL] = { .type = NLA_U8 },
79 [IFLA_VXLAN_TOS] = { .type = NLA_U8 },
80 [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 },
81 [IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
82 [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
83 [IFLA_VXLAN_PORT_RANGE] = { .type = NLA_U32},
84 [IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
85 [IFLA_VXLAN_RSC] = { .type = NLA_U8 },
86 [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
87 [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 },
88};
89
d8e538ec
TG
90static const NLType rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = {
91 [IFLA_BOND_MODE] = { .type = NLA_U8 },
92 [IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 },
d8e538ec
TG
93 [IFLA_BOND_MIIMON] = { .type = NLA_U32 },
94 [IFLA_BOND_UPDELAY] = { .type = NLA_U32 },
95 [IFLA_BOND_DOWNDELAY] = { .type = NLA_U32 },
96 [IFLA_BOND_USE_CARRIER] = { .type = NLA_U8 },
97 [IFLA_BOND_ARP_INTERVAL] = { .type = NLA_U32 },
d8e538ec 98 [IFLA_BOND_ARP_IP_TARGET] = { .type = NLA_NESTED },
d8e538ec
TG
99 [IFLA_BOND_ARP_VALIDATE] = { .type = NLA_U32 },
100 [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NLA_U32 },
101 [IFLA_BOND_PRIMARY] = { .type = NLA_U32 },
102 [IFLA_BOND_PRIMARY_RESELECT] = { .type = NLA_U8 },
103 [IFLA_BOND_FAIL_OVER_MAC] = { .type = NLA_U8 },
104 [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NLA_U8 },
105 [IFLA_BOND_RESEND_IGMP] = { .type = NLA_U32 },
106 [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NLA_U8 },
107 [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NLA_U8 },
108 [IFLA_BOND_MIN_LINKS] = { .type = NLA_U32 },
109 [IFLA_BOND_LP_INTERVAL] = { .type = NLA_U32 },
110 [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NLA_U32 },
111 [IFLA_BOND_AD_LACP_RATE] = { .type = NLA_U8 },
112 [IFLA_BOND_AD_SELECT] = { .type = NLA_U8 },
d8e538ec 113 [IFLA_BOND_AD_INFO] = { .type = NLA_NESTED },
d8e538ec
TG
114};
115
0a827d10
SS
116static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = {
117 [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
7951dea2
SS
118 [IFLA_IPTUN_LOCAL] = { .type = NLA_IN_ADDR },
119 [IFLA_IPTUN_REMOTE] = { .type = NLA_IN_ADDR },
0a827d10
SS
120 [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
121 [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
122 [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
123 [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },
124 [IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
125 [IFLA_IPTUN_6RD_PREFIX] = { .type = NLA_IN_ADDR },
126 [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 },
127 [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 },
128 [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
129};
130
8bb088c5
SS
131static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = {
132 [IFLA_GRE_LINK] = { .type = NLA_U32 },
133 [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
134 [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
135 [IFLA_GRE_IKEY] = { .type = NLA_U32 },
136 [IFLA_GRE_OKEY] = { .type = NLA_U32 },
137 [IFLA_GRE_LOCAL] = { .type = NLA_IN_ADDR },
138 [IFLA_GRE_REMOTE] = { .type = NLA_IN_ADDR },
139 [IFLA_GRE_TTL] = { .type = NLA_U8 },
140 [IFLA_GRE_TOS] = { .type = NLA_U8 },
141 [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
142};
143
a613382b
SS
144static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
145 [IFLA_VTI_LINK] = { .type = NLA_U32 },
146 [IFLA_VTI_IKEY] = { .type = NLA_U32 },
147 [IFLA_VTI_OKEY] = { .type = NLA_U32 },
148 [IFLA_VTI_LOCAL] = { .type = NLA_IN_ADDR },
149 [IFLA_VTI_REMOTE] = { .type = NLA_IN_ADDR },
150};
151
0a827d10 152/* these strings must match the .kind entries in the kernel */
d8e538ec
TG
153static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_MAX] = {
154 [NL_UNION_LINK_INFO_DATA_BOND] = "bond",
155 [NL_UNION_LINK_INFO_DATA_BRIDGE] = "bridge",
156 [NL_UNION_LINK_INFO_DATA_VLAN] = "vlan",
157 [NL_UNION_LINK_INFO_DATA_VETH] = "veth",
9e358851 158 [NL_UNION_LINK_INFO_DATA_DUMMY] = "dummy",
d8e538ec 159 [NL_UNION_LINK_INFO_DATA_MACVLAN] = "macvlan",
6ef81477 160 [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan",
0a827d10 161 [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip",
8bb088c5 162 [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre",
0a827d10 163 [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit",
a613382b 164 [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti",
d8e538ec
TG
165};
166
167DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
168
169static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_DATA_MAX] = {
0a827d10
SS
170 [NL_UNION_LINK_INFO_DATA_BOND] = { .max = ELEMENTSOF(rtnl_link_info_data_bond_types) - 1,
171 .types = rtnl_link_info_data_bond_types },
172 [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .max = ELEMENTSOF(rtnl_link_info_data_bridge_types) - 1,
173 .types = rtnl_link_info_data_bridge_types },
174 [NL_UNION_LINK_INFO_DATA_VLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_vlan_types) - 1,
175 .types = rtnl_link_info_data_vlan_types },
176 [NL_UNION_LINK_INFO_DATA_VETH] = { .max = ELEMENTSOF(rtnl_link_info_data_veth_types) - 1,
177 .types = rtnl_link_info_data_veth_types },
178 [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_macvlan_types) - 1,
179 .types = rtnl_link_info_data_macvlan_types },
6ef81477
SS
180 [NL_UNION_LINK_INFO_DATA_VXLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_vxlan_types) - 1,
181 .types = rtnl_link_info_data_vxlan_types },
0a827d10
SS
182 [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1,
183 .types = rtnl_link_info_data_iptun_types },
8bb088c5
SS
184 [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
185 .types = rtnl_link_info_data_ipgre_types },
0a827d10
SS
186 [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1,
187 .types = rtnl_link_info_data_iptun_types },
a613382b
SS
188 [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1,
189 .types = rtnl_link_info_data_ipvti_types },
d8e538ec
TG
190};
191
192static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
193 .num = _NL_UNION_LINK_INFO_DATA_MAX,
194 .lookup = nl_union_link_info_data_from_string,
195 .type_systems = rtnl_link_info_data_type_systems,
196 .match = IFLA_INFO_KIND,
197};
198
199static const NLType rtnl_link_info_types[IFLA_INFO_MAX + 1] = {
200 [IFLA_INFO_KIND] = { .type = NLA_STRING },
201 [IFLA_INFO_DATA] = { .type = NLA_UNION, .type_system_union = &rtnl_link_info_data_type_system_union},
202/*
203 [IFLA_INFO_XSTATS],
204 [IFLA_INFO_SLAVE_KIND] = { .type = NLA_STRING },
205 [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED },
206*/
207};
208
209static const NLTypeSystem rtnl_link_info_type_system = {
210 .max = ELEMENTSOF(rtnl_link_info_types) - 1,
211 .types = rtnl_link_info_types,
212};
213
d0159fdc
SS
214static const struct NLType rtnl_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
215 [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
216 [IFLA_BRPORT_COST] = { .type = NLA_U32 },
217 [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
218 [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
219 [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
220 [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
221 [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 },
222 [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
223};
224
225static const NLTypeSystem rtnl_bridge_port_type_system = {
226 .max = ELEMENTSOF(rtnl_bridge_port_types) - 1,
227 .types = rtnl_bridge_port_types,
228};
229
230static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
d8e538ec
TG
231 [IFLA_ADDRESS] = { .type = NLA_ETHER_ADDR, },
232 [IFLA_BROADCAST] = { .type = NLA_ETHER_ADDR, },
233 [IFLA_IFNAME] = { .type = NLA_STRING, .size = IFNAMSIZ - 1, },
234 [IFLA_MTU] = { .type = NLA_U32 },
235 [IFLA_LINK] = { .type = NLA_U32 },
236/*
237 [IFLA_QDISC],
238 [IFLA_STATS],
239 [IFLA_COST],
240 [IFLA_PRIORITY],
241*/
242 [IFLA_MASTER] = { .type = NLA_U32 },
243/*
244 [IFLA_WIRELESS],
245 [IFLA_PROTINFO],
246*/
d0159fdc 247 [IFLA_PROTINFO] = { .type = NLA_NESTED, .type_system = &rtnl_bridge_port_type_system },
d8e538ec
TG
248 [IFLA_TXQLEN] = { .type = NLA_U32 },
249/*
250 [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
251*/
252 [IFLA_WEIGHT] = { .type = NLA_U32 },
253 [IFLA_OPERSTATE] = { .type = NLA_U8 },
254 [IFLA_LINKMODE] = { .type = NLA_U8 },
255 [IFLA_LINKINFO] = { .type = NLA_NESTED, .type_system = &rtnl_link_info_type_system },
256 [IFLA_NET_NS_PID] = { .type = NLA_U32 },
257 [IFLA_IFALIAS] = { .type = NLA_STRING, .size = IFALIASZ - 1 },
258/*
259 [IFLA_NUM_VF],
260 [IFLA_VFINFO_LIST] = {. type = NLA_NESTED, },
261 [IFLA_STATS64],
262 [IFLA_VF_PORTS] = { .type = NLA_NESTED },
263 [IFLA_PORT_SELF] = { .type = NLA_NESTED },
264 [IFLA_AF_SPEC] = { .type = NLA_NESTED },
265 [IFLA_VF_PORTS],
266 [IFLA_PORT_SELF],
267 [IFLA_AF_SPEC],
268*/
269 [IFLA_GROUP] = { .type = NLA_U32 },
270 [IFLA_NET_NS_FD] = { .type = NLA_U32 },
271 [IFLA_EXT_MASK] = { .type = NLA_U32 },
272 [IFLA_PROMISCUITY] = { .type = NLA_U32 },
273 [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 },
274 [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 },
275 [IFLA_CARRIER] = { .type = NLA_U8 },
276/*
277 [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
278*/
279};
280
281static const NLTypeSystem rtnl_link_type_system = {
282 .max = ELEMENTSOF(rtnl_link_types) - 1,
283 .types = rtnl_link_types,
284};
285
286static const NLType rtnl_address_types[IFA_MAX + 1] = {
287 [IFA_ADDRESS] = { .type = NLA_IN_ADDR },
288 [IFA_LOCAL] = { .type = NLA_IN_ADDR },
289 [IFA_LABEL] = { .type = NLA_STRING, .size = IFNAMSIZ - 1 },
290 [IFA_BROADCAST] = { .type = NLA_IN_ADDR }, /* 6? */
aba496a5 291 [IFA_CACHEINFO] = { .type = NLA_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) },
d8e538ec
TG
292/*
293 [IFA_ANYCAST],
d8e538ec
TG
294 [IFA_MULTICAST],
295*/
296#ifdef IFA_FLAGS
297 [IFA_FLAGS] = { .type = NLA_U32 },
298#endif
299};
300
301static const NLTypeSystem rtnl_address_type_system = {
302 .max = ELEMENTSOF(rtnl_address_types) - 1,
303 .types = rtnl_address_types,
304};
305
306static const NLType rtnl_route_types[RTA_MAX + 1] = {
307 [RTA_DST] = { .type = NLA_IN_ADDR }, /* 6? */
308 [RTA_SRC] = { .type = NLA_IN_ADDR }, /* 6? */
309 [RTA_IIF] = { .type = NLA_U32 },
310 [RTA_OIF] = { .type = NLA_U32 },
311 [RTA_GATEWAY] = { .type = NLA_IN_ADDR },
312 [RTA_PRIORITY] = { .type = NLA_U32 },
313 [RTA_PREFSRC] = { .type = NLA_IN_ADDR }, /* 6? */
314/*
315 [RTA_METRICS] = { .type = NLA_NESTED },
316 [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
317*/
318 [RTA_FLOW] = { .type = NLA_U32 }, /* 6? */
319/*
320 RTA_CACHEINFO,
321 RTA_TABLE,
322 RTA_MARK,
323 RTA_MFC_STATS,
324*/
325};
326
327static const NLTypeSystem rtnl_route_type_system = {
328 .max = ELEMENTSOF(rtnl_route_types) - 1,
329 .types = rtnl_route_types,
330};
331
e559b384
TG
332static const NLType rtnl_neigh_types[NDA_MAX + 1] = {
333 [NDA_DST] = { .type = NLA_IN_ADDR },
334 [NDA_LLADDR] = { .type = NLA_ETHER_ADDR },
b98b483b
AR
335 [NDA_CACHEINFO] = { .type = NLA_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
336 [NDA_PROBES] = { .type = NLA_U32 },
337 [NDA_VLAN] = { .type = NLA_U16 },
338 [NDA_PORT] = { .type = NLA_U16 },
339 [NDA_VNI] = { .type = NLA_U32 },
340 [NDA_IFINDEX] = { .type = NLA_U32 },
e559b384
TG
341};
342
343static const NLTypeSystem rtnl_neigh_type_system = {
344 .max = ELEMENTSOF(rtnl_neigh_types) - 1,
345 .types = rtnl_neigh_types,
346};
347
d8e538ec
TG
348static const NLType rtnl_types[RTM_MAX + 1] = {
349 [NLMSG_ERROR] = { .type = NLA_META, .size = sizeof(struct nlmsgerr) },
350 [RTM_NEWLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
351 [RTM_DELLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
352 [RTM_GETLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
353 [RTM_SETLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
354 [RTM_NEWADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
355 [RTM_DELADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
356 [RTM_GETADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
357 [RTM_NEWROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
358 [RTM_DELROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
359 [RTM_GETROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
e559b384
TG
360 [RTM_NEWNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
361 [RTM_DELNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
362 [RTM_GETNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
d8e538ec
TG
363};
364
365const NLTypeSystem rtnl_type_system = {
366 .max = ELEMENTSOF(rtnl_types) - 1,
367 .types = rtnl_types,
368};
369
370int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) {
371 const NLType *nl_type;
372
373 assert(ret);
374
375 if (!type_system)
376 type_system = &rtnl_type_system;
377
378 assert(type_system->types);
379
380 if (type > type_system->max)
381 return -ENOTSUP;
382
383 nl_type = &type_system->types[type];
384
385 if (nl_type->type == NLA_UNSPEC)
386 return -ENOTSUP;
387
388 *ret = nl_type;
389
390 return 0;
391}
392
393int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type) {
394 const NLType *nl_type;
395 int r;
396
397 assert(ret);
398
399 r = type_system_get_type(type_system, &nl_type, type);
400 if (r < 0)
401 return r;
402
403 assert_return(nl_type->type == NLA_NESTED, -EINVAL);
404
405 assert(nl_type->type_system);
406
407 *ret = nl_type->type_system;
408
409 return 0;
410}
411
412int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type) {
413 const NLType *nl_type;
414 int r;
415
416 assert(ret);
417
418 r = type_system_get_type(type_system, &nl_type, type);
419 if (r < 0)
420 return r;
421
422 assert_return(nl_type->type == NLA_UNION, -EINVAL);
423
424 assert(nl_type->type_system_union);
425
426 *ret = nl_type->type_system_union;
427
428 return 0;
429}
430
431int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key) {
432 int type;
433
434 assert(type_system_union);
435 assert(type_system_union->lookup);
436 assert(type_system_union->type_systems);
437 assert(ret);
438 assert(key);
439
440 type = type_system_union->lookup(key);
441 if (type < 0)
442 return -ENOTSUP;
443
444 assert(type < type_system_union->num);
445
446 *ret = &type_system_union->type_systems[type];
447
448 return 0;
449}