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