]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-rtnl/rtnl-types.c
networkd: Introduce IP6 tunnel
[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
855ee1a1
SS
156static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
157 [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
158 [IFLA_IPTUN_LOCAL] = { .type = NLA_IN_ADDR },
159 [IFLA_IPTUN_REMOTE] = { .type = NLA_IN_ADDR },
160 [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
161 [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 },
162 [IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
163 [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 },
164 [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32},
165};
166
0a827d10 167/* these strings must match the .kind entries in the kernel */
d8e538ec
TG
168static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_MAX] = {
169 [NL_UNION_LINK_INFO_DATA_BOND] = "bond",
170 [NL_UNION_LINK_INFO_DATA_BRIDGE] = "bridge",
171 [NL_UNION_LINK_INFO_DATA_VLAN] = "vlan",
172 [NL_UNION_LINK_INFO_DATA_VETH] = "veth",
9e358851 173 [NL_UNION_LINK_INFO_DATA_DUMMY] = "dummy",
d8e538ec 174 [NL_UNION_LINK_INFO_DATA_MACVLAN] = "macvlan",
c4a5ddc9 175 [NL_UNION_LINK_INFO_DATA_IPVLAN] = "ipvlan",
6ef81477 176 [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan",
0a827d10 177 [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip",
8bb088c5 178 [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre",
1af2536a 179 [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = "gretap",
0a827d10 180 [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit",
a613382b 181 [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti",
855ee1a1 182 [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl",
d8e538ec
TG
183};
184
185DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
186
187static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_DATA_MAX] = {
0a827d10
SS
188 [NL_UNION_LINK_INFO_DATA_BOND] = { .max = ELEMENTSOF(rtnl_link_info_data_bond_types) - 1,
189 .types = rtnl_link_info_data_bond_types },
190 [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .max = ELEMENTSOF(rtnl_link_info_data_bridge_types) - 1,
191 .types = rtnl_link_info_data_bridge_types },
192 [NL_UNION_LINK_INFO_DATA_VLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_vlan_types) - 1,
193 .types = rtnl_link_info_data_vlan_types },
194 [NL_UNION_LINK_INFO_DATA_VETH] = { .max = ELEMENTSOF(rtnl_link_info_data_veth_types) - 1,
195 .types = rtnl_link_info_data_veth_types },
196 [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_macvlan_types) - 1,
197 .types = rtnl_link_info_data_macvlan_types },
c4a5ddc9
TG
198 [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_ipvlan_types) - 1,
199 .types = rtnl_link_info_data_ipvlan_types },
6ef81477
SS
200 [NL_UNION_LINK_INFO_DATA_VXLAN] = { .max = ELEMENTSOF(rtnl_link_info_data_vxlan_types) - 1,
201 .types = rtnl_link_info_data_vxlan_types },
0a827d10
SS
202 [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1,
203 .types = rtnl_link_info_data_iptun_types },
8bb088c5
SS
204 [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
205 .types = rtnl_link_info_data_ipgre_types },
1af2536a
SS
206 [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
207 .types = rtnl_link_info_data_ipgre_types },
0a827d10
SS
208 [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1,
209 .types = rtnl_link_info_data_iptun_types },
a613382b
SS
210 [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1,
211 .types = rtnl_link_info_data_ipvti_types },
855ee1a1
SS
212 [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types) - 1,
213 .types = rtnl_link_info_data_ip6tnl_types },
214
d8e538ec
TG
215};
216
217static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
218 .num = _NL_UNION_LINK_INFO_DATA_MAX,
219 .lookup = nl_union_link_info_data_from_string,
220 .type_systems = rtnl_link_info_data_type_systems,
221 .match = IFLA_INFO_KIND,
222};
223
224static const NLType rtnl_link_info_types[IFLA_INFO_MAX + 1] = {
225 [IFLA_INFO_KIND] = { .type = NLA_STRING },
226 [IFLA_INFO_DATA] = { .type = NLA_UNION, .type_system_union = &rtnl_link_info_data_type_system_union},
227/*
228 [IFLA_INFO_XSTATS],
229 [IFLA_INFO_SLAVE_KIND] = { .type = NLA_STRING },
230 [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED },
231*/
232};
233
234static const NLTypeSystem rtnl_link_info_type_system = {
235 .max = ELEMENTSOF(rtnl_link_info_types) - 1,
236 .types = rtnl_link_info_types,
237};
238
d0159fdc
SS
239static const struct NLType rtnl_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
240 [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
241 [IFLA_BRPORT_COST] = { .type = NLA_U32 },
242 [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
243 [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
244 [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
245 [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
246 [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 },
247 [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
248};
249
250static const NLTypeSystem rtnl_bridge_port_type_system = {
251 .max = ELEMENTSOF(rtnl_bridge_port_types) - 1,
252 .types = rtnl_bridge_port_types,
253};
254
255static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
d8e538ec
TG
256 [IFLA_ADDRESS] = { .type = NLA_ETHER_ADDR, },
257 [IFLA_BROADCAST] = { .type = NLA_ETHER_ADDR, },
258 [IFLA_IFNAME] = { .type = NLA_STRING, .size = IFNAMSIZ - 1, },
259 [IFLA_MTU] = { .type = NLA_U32 },
260 [IFLA_LINK] = { .type = NLA_U32 },
261/*
262 [IFLA_QDISC],
263 [IFLA_STATS],
264 [IFLA_COST],
265 [IFLA_PRIORITY],
266*/
267 [IFLA_MASTER] = { .type = NLA_U32 },
268/*
269 [IFLA_WIRELESS],
270 [IFLA_PROTINFO],
271*/
d0159fdc 272 [IFLA_PROTINFO] = { .type = NLA_NESTED, .type_system = &rtnl_bridge_port_type_system },
d8e538ec
TG
273 [IFLA_TXQLEN] = { .type = NLA_U32 },
274/*
275 [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
276*/
277 [IFLA_WEIGHT] = { .type = NLA_U32 },
278 [IFLA_OPERSTATE] = { .type = NLA_U8 },
279 [IFLA_LINKMODE] = { .type = NLA_U8 },
280 [IFLA_LINKINFO] = { .type = NLA_NESTED, .type_system = &rtnl_link_info_type_system },
281 [IFLA_NET_NS_PID] = { .type = NLA_U32 },
282 [IFLA_IFALIAS] = { .type = NLA_STRING, .size = IFALIASZ - 1 },
283/*
284 [IFLA_NUM_VF],
285 [IFLA_VFINFO_LIST] = {. type = NLA_NESTED, },
286 [IFLA_STATS64],
287 [IFLA_VF_PORTS] = { .type = NLA_NESTED },
288 [IFLA_PORT_SELF] = { .type = NLA_NESTED },
289 [IFLA_AF_SPEC] = { .type = NLA_NESTED },
290 [IFLA_VF_PORTS],
291 [IFLA_PORT_SELF],
292 [IFLA_AF_SPEC],
293*/
294 [IFLA_GROUP] = { .type = NLA_U32 },
295 [IFLA_NET_NS_FD] = { .type = NLA_U32 },
296 [IFLA_EXT_MASK] = { .type = NLA_U32 },
297 [IFLA_PROMISCUITY] = { .type = NLA_U32 },
298 [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 },
299 [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 },
300 [IFLA_CARRIER] = { .type = NLA_U8 },
301/*
302 [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
303*/
304};
305
306static const NLTypeSystem rtnl_link_type_system = {
307 .max = ELEMENTSOF(rtnl_link_types) - 1,
308 .types = rtnl_link_types,
309};
310
311static const NLType rtnl_address_types[IFA_MAX + 1] = {
312 [IFA_ADDRESS] = { .type = NLA_IN_ADDR },
313 [IFA_LOCAL] = { .type = NLA_IN_ADDR },
314 [IFA_LABEL] = { .type = NLA_STRING, .size = IFNAMSIZ - 1 },
315 [IFA_BROADCAST] = { .type = NLA_IN_ADDR }, /* 6? */
aba496a5 316 [IFA_CACHEINFO] = { .type = NLA_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) },
d8e538ec
TG
317/*
318 [IFA_ANYCAST],
d8e538ec
TG
319 [IFA_MULTICAST],
320*/
321#ifdef IFA_FLAGS
322 [IFA_FLAGS] = { .type = NLA_U32 },
323#endif
324};
325
326static const NLTypeSystem rtnl_address_type_system = {
327 .max = ELEMENTSOF(rtnl_address_types) - 1,
328 .types = rtnl_address_types,
329};
330
331static const NLType rtnl_route_types[RTA_MAX + 1] = {
332 [RTA_DST] = { .type = NLA_IN_ADDR }, /* 6? */
333 [RTA_SRC] = { .type = NLA_IN_ADDR }, /* 6? */
334 [RTA_IIF] = { .type = NLA_U32 },
335 [RTA_OIF] = { .type = NLA_U32 },
336 [RTA_GATEWAY] = { .type = NLA_IN_ADDR },
337 [RTA_PRIORITY] = { .type = NLA_U32 },
338 [RTA_PREFSRC] = { .type = NLA_IN_ADDR }, /* 6? */
339/*
340 [RTA_METRICS] = { .type = NLA_NESTED },
341 [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
342*/
343 [RTA_FLOW] = { .type = NLA_U32 }, /* 6? */
344/*
345 RTA_CACHEINFO,
346 RTA_TABLE,
347 RTA_MARK,
348 RTA_MFC_STATS,
349*/
350};
351
352static const NLTypeSystem rtnl_route_type_system = {
353 .max = ELEMENTSOF(rtnl_route_types) - 1,
354 .types = rtnl_route_types,
355};
356
e559b384
TG
357static const NLType rtnl_neigh_types[NDA_MAX + 1] = {
358 [NDA_DST] = { .type = NLA_IN_ADDR },
359 [NDA_LLADDR] = { .type = NLA_ETHER_ADDR },
b98b483b
AR
360 [NDA_CACHEINFO] = { .type = NLA_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
361 [NDA_PROBES] = { .type = NLA_U32 },
362 [NDA_VLAN] = { .type = NLA_U16 },
363 [NDA_PORT] = { .type = NLA_U16 },
364 [NDA_VNI] = { .type = NLA_U32 },
365 [NDA_IFINDEX] = { .type = NLA_U32 },
e559b384
TG
366};
367
368static const NLTypeSystem rtnl_neigh_type_system = {
369 .max = ELEMENTSOF(rtnl_neigh_types) - 1,
370 .types = rtnl_neigh_types,
371};
372
d8e538ec
TG
373static const NLType rtnl_types[RTM_MAX + 1] = {
374 [NLMSG_ERROR] = { .type = NLA_META, .size = sizeof(struct nlmsgerr) },
375 [RTM_NEWLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
376 [RTM_DELLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
377 [RTM_GETLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
378 [RTM_SETLINK] = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
379 [RTM_NEWADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
380 [RTM_DELADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
381 [RTM_GETADDR] = { .type = NLA_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
382 [RTM_NEWROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
383 [RTM_DELROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
384 [RTM_GETROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
e559b384
TG
385 [RTM_NEWNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
386 [RTM_DELNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
387 [RTM_GETNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
d8e538ec
TG
388};
389
390const NLTypeSystem rtnl_type_system = {
391 .max = ELEMENTSOF(rtnl_types) - 1,
392 .types = rtnl_types,
393};
394
395int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) {
396 const NLType *nl_type;
397
398 assert(ret);
399
400 if (!type_system)
401 type_system = &rtnl_type_system;
402
403 assert(type_system->types);
404
405 if (type > type_system->max)
406 return -ENOTSUP;
407
408 nl_type = &type_system->types[type];
409
410 if (nl_type->type == NLA_UNSPEC)
411 return -ENOTSUP;
412
413 *ret = nl_type;
414
415 return 0;
416}
417
418int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type) {
419 const NLType *nl_type;
420 int r;
421
422 assert(ret);
423
424 r = type_system_get_type(type_system, &nl_type, type);
425 if (r < 0)
426 return r;
427
428 assert_return(nl_type->type == NLA_NESTED, -EINVAL);
429
430 assert(nl_type->type_system);
431
432 *ret = nl_type->type_system;
433
434 return 0;
435}
436
437int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type) {
438 const NLType *nl_type;
439 int r;
440
441 assert(ret);
442
443 r = type_system_get_type(type_system, &nl_type, type);
444 if (r < 0)
445 return r;
446
447 assert_return(nl_type->type == NLA_UNION, -EINVAL);
448
449 assert(nl_type->type_system_union);
450
451 *ret = nl_type->type_system_union;
452
453 return 0;
454}
455
456int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key) {
457 int type;
458
459 assert(type_system_union);
460 assert(type_system_union->lookup);
461 assert(type_system_union->type_systems);
462 assert(ret);
463 assert(key);
464
465 type = type_system_union->lookup(key);
466 if (type < 0)
467 return -ENOTSUP;
468
469 assert(type < type_system_union->num);
470
471 *ret = &type_system_union->type_systems[type];
472
473 return 0;
474}