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