]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-netlink/netlink-types.c
util-lib: split stat()/statfs()/stavfs() related calls into stat-util.[ch]
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / netlink-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
1c4baffc 39#include "netlink-types.h"
0830ba61 40#include "missing.h"
d8e538ec 41
dd906398
DH
42/* Maximum ARP IP target defined in kernel */
43#define BOND_MAX_ARP_TARGETS 16
44
45typedef enum {
46 BOND_ARP_TARGETS_0,
47 BOND_ARP_TARGETS_1,
48 BOND_ARP_TARGETS_2,
49 BOND_ARP_TARGETS_3,
50 BOND_ARP_TARGETS_4,
51 BOND_ARP_TARGETS_5,
52 BOND_ARP_TARGETS_6,
53 BOND_ARP_TARGETS_7,
54 BOND_ARP_TARGETS_8,
55 BOND_ARP_TARGETS_9,
56 BOND_ARP_TARGETS_10,
57 BOND_ARP_TARGETS_11,
58 BOND_ARP_TARGETS_12,
59 BOND_ARP_TARGETS_13,
60 BOND_ARP_TARGETS_14,
61 BOND_ARP_TARGETS_MAX = BOND_MAX_ARP_TARGETS,
62} BondArpTargets;
63
817d1cd8
DH
64struct NLType {
65 uint16_t type;
66 size_t size;
67 const NLTypeSystem *type_system;
68 const NLTypeSystemUnion *type_system_union;
69};
70
435bbb02 71struct NLTypeSystem {
c1df8dee 72 uint16_t count;
435bbb02
DH
73 const NLType *types;
74};
75
d8e538ec
TG
76static const NLTypeSystem rtnl_link_type_system;
77
979e7eb9
DH
78static const NLType empty_types[1] = {
79 /* fake array to avoid .types==NULL, which denotes invalid type-systems */
80};
81
82static const NLTypeSystem empty_type_system = {
83 .count = 0,
84 .types = empty_types,
85};
86
d8e538ec 87static const NLType rtnl_link_info_data_veth_types[VETH_INFO_MAX + 1] = {
cafbc790 88 [VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
d8e538ec
TG
89};
90
c4a5ddc9 91static const NLType rtnl_link_info_data_ipvlan_types[IFLA_IPVLAN_MAX + 1] = {
cafbc790 92 [IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 },
c4a5ddc9 93};
d8e538ec
TG
94
95static const NLType rtnl_link_info_data_macvlan_types[IFLA_MACVLAN_MAX + 1] = {
cafbc790
DH
96 [IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 },
97 [IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
d8e538ec
TG
98};
99
ced671e1 100static const NLType rtnl_link_bridge_management_types[IFLA_BRIDGE_MAX + 1] = {
cafbc790
DH
101 [IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 },
102 [IFLA_BRIDGE_MODE] = { .type = NETLINK_TYPE_U16 },
d8e538ec 103/*
cafbc790 104 [IFLA_BRIDGE_VLAN_INFO] = { .type = NETLINK_TYPE_BINARY,
d8e538ec
TG
105 .len = sizeof(struct bridge_vlan_info), },
106*/
107};
108
ced671e1
SS
109static const NLType rtnl_link_info_data_bridge_types[IFLA_BR_MAX + 1] = {
110 [IFLA_BR_FORWARD_DELAY] = { .type = NETLINK_TYPE_U32 },
111 [IFLA_BR_HELLO_TIME] = { .type = NETLINK_TYPE_U32 },
112 [IFLA_BR_MAX_AGE] = { .type = NETLINK_TYPE_U32 },
113 [IFLA_BR_AGEING_TIME] = { .type = NETLINK_TYPE_U32 },
114 [IFLA_BR_STP_STATE] = { .type = NETLINK_TYPE_U32 },
115 [IFLA_BR_PRIORITY] = { .type = NETLINK_TYPE_U16 },
116};
117
d8e538ec 118static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = {
cafbc790 119 [IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 },
d8e538ec
TG
120/*
121 [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) },
cafbc790
DH
122 [IFLA_VLAN_EGRESS_QOS] = { .type = NETLINK_TYPE_NESTED },
123 [IFLA_VLAN_INGRESS_QOS] = { .type = NETLINK_TYPE_NESTED },
d8e538ec 124*/
cafbc790 125 [IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 },
d8e538ec
TG
126};
127
6ef81477 128static const NLType rtnl_link_info_data_vxlan_types[IFLA_VXLAN_MAX+1] = {
452c9569
SS
129 [IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 },
130 [IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR },
131 [IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 },
132 [IFLA_VXLAN_LOCAL] = { .type = NETLINK_TYPE_U32},
133 [IFLA_VXLAN_TTL] = { .type = NETLINK_TYPE_U8 },
134 [IFLA_VXLAN_TOS] = { .type = NETLINK_TYPE_U8 },
135 [IFLA_VXLAN_LEARNING] = { .type = NETLINK_TYPE_U8 },
136 [IFLA_VXLAN_AGEING] = { .type = NETLINK_TYPE_U32 },
137 [IFLA_VXLAN_LIMIT] = { .type = NETLINK_TYPE_U32 },
138 [IFLA_VXLAN_PORT_RANGE] = { .type = NETLINK_TYPE_U32},
139 [IFLA_VXLAN_PROXY] = { .type = NETLINK_TYPE_U8 },
140 [IFLA_VXLAN_RSC] = { .type = NETLINK_TYPE_U8 },
141 [IFLA_VXLAN_L2MISS] = { .type = NETLINK_TYPE_U8 },
142 [IFLA_VXLAN_L3MISS] = { .type = NETLINK_TYPE_U8 },
143 [IFLA_VXLAN_PORT] = { .type = NETLINK_TYPE_U16 },
144 [IFLA_VXLAN_GROUP6] = { .type = NETLINK_TYPE_IN_ADDR },
145 [IFLA_VXLAN_LOCAL6] = { .type = NETLINK_TYPE_IN_ADDR },
146 [IFLA_VXLAN_UDP_CSUM] = { .type = NETLINK_TYPE_U8 },
147 [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
148 [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
149 [IFLA_VXLAN_REMCSUM_TX] = { .type = NETLINK_TYPE_U8 },
150 [IFLA_VXLAN_REMCSUM_RX] = { .type = NETLINK_TYPE_U8 },
151 [IFLA_VXLAN_GBP] = { .type = NETLINK_TYPE_FLAG },
152 [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
6ef81477
SS
153};
154
81bd37a8 155static const NLType rtnl_bond_arp_target_types[BOND_ARP_TARGETS_MAX + 1] = {
cafbc790
DH
156 [BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 },
157 [BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 },
158 [BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 },
159 [BOND_ARP_TARGETS_3] = { .type = NETLINK_TYPE_U32 },
160 [BOND_ARP_TARGETS_4] = { .type = NETLINK_TYPE_U32 },
161 [BOND_ARP_TARGETS_5] = { .type = NETLINK_TYPE_U32 },
162 [BOND_ARP_TARGETS_6] = { .type = NETLINK_TYPE_U32 },
163 [BOND_ARP_TARGETS_7] = { .type = NETLINK_TYPE_U32 },
164 [BOND_ARP_TARGETS_8] = { .type = NETLINK_TYPE_U32 },
165 [BOND_ARP_TARGETS_9] = { .type = NETLINK_TYPE_U32 },
166 [BOND_ARP_TARGETS_10] = { .type = NETLINK_TYPE_U32 },
167 [BOND_ARP_TARGETS_11] = { .type = NETLINK_TYPE_U32 },
168 [BOND_ARP_TARGETS_12] = { .type = NETLINK_TYPE_U32 },
169 [BOND_ARP_TARGETS_13] = { .type = NETLINK_TYPE_U32 },
170 [BOND_ARP_TARGETS_14] = { .type = NETLINK_TYPE_U32 },
171 [BOND_ARP_TARGETS_MAX] = { .type = NETLINK_TYPE_U32 },
81bd37a8
SS
172};
173
174static const NLTypeSystem rtnl_bond_arp_type_system = {
c1df8dee 175 .count = ELEMENTSOF(rtnl_bond_arp_target_types),
81bd37a8
SS
176 .types = rtnl_bond_arp_target_types,
177};
178
d8e538ec 179static const NLType rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = {
cafbc790
DH
180 [IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 },
181 [IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 },
182 [IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 },
183 [IFLA_BOND_UPDELAY] = { .type = NETLINK_TYPE_U32 },
184 [IFLA_BOND_DOWNDELAY] = { .type = NETLINK_TYPE_U32 },
185 [IFLA_BOND_USE_CARRIER] = { .type = NETLINK_TYPE_U8 },
186 [IFLA_BOND_ARP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
187 [IFLA_BOND_ARP_IP_TARGET] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_arp_type_system },
188 [IFLA_BOND_ARP_VALIDATE] = { .type = NETLINK_TYPE_U32 },
189 [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NETLINK_TYPE_U32 },
190 [IFLA_BOND_PRIMARY] = { .type = NETLINK_TYPE_U32 },
191 [IFLA_BOND_PRIMARY_RESELECT] = { .type = NETLINK_TYPE_U8 },
192 [IFLA_BOND_FAIL_OVER_MAC] = { .type = NETLINK_TYPE_U8 },
193 [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NETLINK_TYPE_U8 },
194 [IFLA_BOND_RESEND_IGMP] = { .type = NETLINK_TYPE_U32 },
195 [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NETLINK_TYPE_U8 },
196 [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NETLINK_TYPE_U8 },
197 [IFLA_BOND_MIN_LINKS] = { .type = NETLINK_TYPE_U32 },
198 [IFLA_BOND_LP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
199 [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NETLINK_TYPE_U32 },
200 [IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 },
201 [IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 },
202 [IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED },
d8e538ec
TG
203};
204
0a827d10 205static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = {
cafbc790
DH
206 [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
207 [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
208 [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
209 [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 },
210 [IFLA_IPTUN_TOS] = { .type = NETLINK_TYPE_U8 },
211 [IFLA_IPTUN_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
212 [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U16 },
213 [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 },
214 [IFLA_IPTUN_6RD_PREFIX] = { .type = NETLINK_TYPE_IN_ADDR },
215 [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NETLINK_TYPE_U32 },
216 [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
217 [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
6e74cade
ZJS
218 [IFLA_IPTUN_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
219 [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 },
220 [IFLA_IPTUN_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 },
221 [IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
0a827d10
SS
222};
223
8bb088c5 224static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = {
8aee0f1f
SS
225 [IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 },
226 [IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 },
227 [IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 },
228 [IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 },
229 [IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 },
230 [IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
231 [IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
232 [IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 },
233 [IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 },
234 [IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
235 [IFLA_GRE_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
236 [IFLA_GRE_FLAGS] = { .type = NETLINK_TYPE_U32 },
237 [IFLA_GRE_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
238 [IFLA_GRE_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 },
239 [IFLA_GRE_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 },
240 [IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
8bb088c5
SS
241};
242
a613382b 243static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
cafbc790
DH
244 [IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 },
245 [IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 },
246 [IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 },
6e74cade
ZJS
247 [IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
248 [IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
a613382b
SS
249};
250
855ee1a1 251static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
cafbc790
DH
252 [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
253 [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
254 [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
255 [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 },
256 [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U32 },
257 [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 },
258 [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NETLINK_TYPE_U8 },
6e74cade 259 [IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
855ee1a1
SS
260};
261
0a827d10 262/* these strings must match the .kind entries in the kernel */
d8e538ec
TG
263static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_MAX] = {
264 [NL_UNION_LINK_INFO_DATA_BOND] = "bond",
265 [NL_UNION_LINK_INFO_DATA_BRIDGE] = "bridge",
266 [NL_UNION_LINK_INFO_DATA_VLAN] = "vlan",
267 [NL_UNION_LINK_INFO_DATA_VETH] = "veth",
9e358851 268 [NL_UNION_LINK_INFO_DATA_DUMMY] = "dummy",
d8e538ec 269 [NL_UNION_LINK_INFO_DATA_MACVLAN] = "macvlan",
d1312575 270 [NL_UNION_LINK_INFO_DATA_MACVTAP] = "macvtap",
c4a5ddc9 271 [NL_UNION_LINK_INFO_DATA_IPVLAN] = "ipvlan",
6ef81477 272 [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan",
0a827d10 273 [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip",
8bb088c5 274 [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre",
1af2536a 275 [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = "gretap",
b16492f8
SS
276 [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = "ip6gre",
277 [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = "ip6gretap",
0a827d10 278 [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit",
a613382b 279 [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti",
9011ce77 280 [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6",
855ee1a1 281 [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl",
d8e538ec
TG
282};
283
284DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
285
286static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_DATA_MAX] = {
c1df8dee 287 [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types),
0a827d10 288 .types = rtnl_link_info_data_bond_types },
c1df8dee 289 [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types),
0a827d10 290 .types = rtnl_link_info_data_bridge_types },
c1df8dee 291 [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types),
0a827d10 292 .types = rtnl_link_info_data_vlan_types },
c1df8dee 293 [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types),
0a827d10 294 .types = rtnl_link_info_data_veth_types },
c1df8dee 295 [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
0a827d10 296 .types = rtnl_link_info_data_macvlan_types },
d1312575
SS
297 [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
298 .types = rtnl_link_info_data_macvlan_types },
c1df8dee 299 [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
c4a5ddc9 300 .types = rtnl_link_info_data_ipvlan_types },
c1df8dee 301 [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types),
6ef81477 302 .types = rtnl_link_info_data_vxlan_types },
c1df8dee 303 [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
0a827d10 304 .types = rtnl_link_info_data_iptun_types },
c1df8dee 305 [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
8bb088c5 306 .types = rtnl_link_info_data_ipgre_types },
c1df8dee 307 [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
1af2536a 308 .types = rtnl_link_info_data_ipgre_types },
c1df8dee 309 [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
b16492f8 310 .types = rtnl_link_info_data_ipgre_types },
c1df8dee 311 [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
b16492f8 312 .types = rtnl_link_info_data_ipgre_types },
c1df8dee 313 [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
0a827d10 314 .types = rtnl_link_info_data_iptun_types },
c1df8dee 315 [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
a613382b 316 .types = rtnl_link_info_data_ipvti_types },
c1df8dee 317 [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
9011ce77 318 .types = rtnl_link_info_data_ipvti_types },
c1df8dee 319 [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types),
855ee1a1
SS
320 .types = rtnl_link_info_data_ip6tnl_types },
321
d8e538ec
TG
322};
323
324static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
325 .num = _NL_UNION_LINK_INFO_DATA_MAX,
326 .lookup = nl_union_link_info_data_from_string,
327 .type_systems = rtnl_link_info_data_type_systems,
4af7b60d 328 .match_type = NL_MATCH_SIBLING,
d8e538ec
TG
329 .match = IFLA_INFO_KIND,
330};
331
332static const NLType rtnl_link_info_types[IFLA_INFO_MAX + 1] = {
cafbc790
DH
333 [IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING },
334 [IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union},
d8e538ec
TG
335/*
336 [IFLA_INFO_XSTATS],
cafbc790
DH
337 [IFLA_INFO_SLAVE_KIND] = { .type = NETLINK_TYPE_STRING },
338 [IFLA_INFO_SLAVE_DATA] = { .type = NETLINK_TYPE_NESTED },
d8e538ec
TG
339*/
340};
341
342static const NLTypeSystem rtnl_link_info_type_system = {
c1df8dee 343 .count = ELEMENTSOF(rtnl_link_info_types),
d8e538ec
TG
344 .types = rtnl_link_info_types,
345};
346
4af7b60d 347static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
cafbc790
DH
348 [IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 },
349 [IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 },
350 [IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 },
351 [IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 },
352 [IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 },
353 [IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 },
0c1f248e 354 [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 },
cafbc790
DH
355 [IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 },
356 [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
0c1f248e
SS
357 [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 },
358 [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
d0159fdc
SS
359};
360
4af7b60d 361static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = {
c1df8dee 362 [AF_BRIDGE] = { .count = ELEMENTSOF(rtnl_prot_info_bridge_port_types),
4af7b60d
TG
363 .types = rtnl_prot_info_bridge_port_types },
364};
365
366static const NLTypeSystemUnion rtnl_prot_info_type_system_union = {
367 .num = AF_MAX,
368 .type_systems = rtnl_prot_info_type_systems,
369 .match_type = NL_MATCH_PROTOCOL,
d0159fdc
SS
370};
371
c149ae08 372static const struct NLType rtnl_af_spec_inet6_types[IFLA_INET6_MAX + 1] = {
cafbc790 373 [IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 },
c149ae08
TG
374/*
375 IFLA_INET6_CONF,
376 IFLA_INET6_STATS,
377 IFLA_INET6_MCAST,
378 IFLA_INET6_CACHEINFO,
379 IFLA_INET6_ICMP6STATS,
380*/
cafbc790
DH
381 [IFLA_INET6_TOKEN] = { .type = NETLINK_TYPE_IN_ADDR },
382 [IFLA_INET6_ADDR_GEN_MODE] = { .type = NETLINK_TYPE_U8 },
c149ae08
TG
383};
384
73cb1c14 385static const NLTypeSystem rtnl_af_spec_inet6_type_system = {
c1df8dee 386 .count = ELEMENTSOF(rtnl_af_spec_inet6_types),
73cb1c14 387 .types = rtnl_af_spec_inet6_types,
c149ae08
TG
388};
389
73cb1c14 390static const NLType rtnl_af_spec_types[AF_MAX + 1] = {
cafbc790 391 [AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system },
73cb1c14
TG
392};
393
394static const NLTypeSystem rtnl_af_spec_type_system = {
c1df8dee 395 .count = ELEMENTSOF(rtnl_af_spec_types),
73cb1c14 396 .types = rtnl_af_spec_types,
c149ae08
TG
397};
398
d0159fdc 399static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
6e74cade
ZJS
400 [IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR },
401 [IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR },
402 [IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
cafbc790
DH
403 [IFLA_MTU] = { .type = NETLINK_TYPE_U32 },
404 [IFLA_LINK] = { .type = NETLINK_TYPE_U32 },
d8e538ec
TG
405/*
406 [IFLA_QDISC],
407 [IFLA_STATS],
408 [IFLA_COST],
409 [IFLA_PRIORITY],
410*/
cafbc790 411 [IFLA_MASTER] = { .type = NETLINK_TYPE_U32 },
d8e538ec
TG
412/*
413 [IFLA_WIRELESS],
d8e538ec 414*/
cafbc790
DH
415 [IFLA_PROTINFO] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_prot_info_type_system_union },
416 [IFLA_TXQLEN] = { .type = NETLINK_TYPE_U32 },
d8e538ec
TG
417/*
418 [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
419*/
cafbc790
DH
420 [IFLA_WEIGHT] = { .type = NETLINK_TYPE_U32 },
421 [IFLA_OPERSTATE] = { .type = NETLINK_TYPE_U8 },
422 [IFLA_LINKMODE] = { .type = NETLINK_TYPE_U8 },
423 [IFLA_LINKINFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_info_type_system },
424 [IFLA_NET_NS_PID] = { .type = NETLINK_TYPE_U32 },
425 [IFLA_IFALIAS] = { .type = NETLINK_TYPE_STRING, .size = IFALIASZ - 1 },
d8e538ec
TG
426/*
427 [IFLA_NUM_VF],
cafbc790 428 [IFLA_VFINFO_LIST] = {. type = NETLINK_TYPE_NESTED, },
d8e538ec 429 [IFLA_STATS64],
cafbc790
DH
430 [IFLA_VF_PORTS] = { .type = NETLINK_TYPE_NESTED },
431 [IFLA_PORT_SELF] = { .type = NETLINK_TYPE_NESTED },
c149ae08 432*/
cafbc790 433 [IFLA_AF_SPEC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_type_system },
c149ae08 434/*
d8e538ec
TG
435 [IFLA_VF_PORTS],
436 [IFLA_PORT_SELF],
437 [IFLA_AF_SPEC],
438*/
cafbc790
DH
439 [IFLA_GROUP] = { .type = NETLINK_TYPE_U32 },
440 [IFLA_NET_NS_FD] = { .type = NETLINK_TYPE_U32 },
441 [IFLA_EXT_MASK] = { .type = NETLINK_TYPE_U32 },
442 [IFLA_PROMISCUITY] = { .type = NETLINK_TYPE_U32 },
443 [IFLA_NUM_TX_QUEUES] = { .type = NETLINK_TYPE_U32 },
444 [IFLA_NUM_RX_QUEUES] = { .type = NETLINK_TYPE_U32 },
445 [IFLA_CARRIER] = { .type = NETLINK_TYPE_U8 },
d8e538ec 446/*
cafbc790 447 [IFLA_PHYS_PORT_ID] = { .type = NETLINK_TYPE_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
d8e538ec
TG
448*/
449};
450
451static const NLTypeSystem rtnl_link_type_system = {
c1df8dee 452 .count = ELEMENTSOF(rtnl_link_types),
d8e538ec
TG
453 .types = rtnl_link_types,
454};
455
de79f906
LP
456/* IFA_FLAGS was defined in kernel 3.14, but we still support older
457 * kernels where IFA_MAX is lower. */
458static const NLType rtnl_address_types[CONST_MAX(IFA_MAX, IFA_FLAGS) + 1] = {
cafbc790
DH
459 [IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR },
460 [IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
461 [IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
462 [IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
463 [IFA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) },
d8e538ec
TG
464/*
465 [IFA_ANYCAST],
d8e538ec
TG
466 [IFA_MULTICAST],
467*/
cafbc790 468 [IFA_FLAGS] = { .type = NETLINK_TYPE_U32 },
d8e538ec
TG
469};
470
471static const NLTypeSystem rtnl_address_type_system = {
c1df8dee 472 .count = ELEMENTSOF(rtnl_address_types),
d8e538ec
TG
473 .types = rtnl_address_types,
474};
475
476static const NLType rtnl_route_types[RTA_MAX + 1] = {
cafbc790
DH
477 [RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
478 [RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
479 [RTA_IIF] = { .type = NETLINK_TYPE_U32 },
480 [RTA_OIF] = { .type = NETLINK_TYPE_U32 },
481 [RTA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR },
482 [RTA_PRIORITY] = { .type = NETLINK_TYPE_U32 },
483 [RTA_PREFSRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
d8e538ec 484/*
cafbc790 485 [RTA_METRICS] = { .type = NETLINK_TYPE_NESTED },
d8e538ec
TG
486 [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
487*/
cafbc790 488 [RTA_FLOW] = { .type = NETLINK_TYPE_U32 }, /* 6? */
d8e538ec
TG
489/*
490 RTA_CACHEINFO,
491 RTA_TABLE,
492 RTA_MARK,
493 RTA_MFC_STATS,
494*/
495};
496
497static const NLTypeSystem rtnl_route_type_system = {
c1df8dee 498 .count = ELEMENTSOF(rtnl_route_types),
d8e538ec
TG
499 .types = rtnl_route_types,
500};
501
e559b384 502static const NLType rtnl_neigh_types[NDA_MAX + 1] = {
cafbc790
DH
503 [NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
504 [NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
505 [NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
506 [NDA_PROBES] = { .type = NETLINK_TYPE_U32 },
507 [NDA_VLAN] = { .type = NETLINK_TYPE_U16 },
508 [NDA_PORT] = { .type = NETLINK_TYPE_U16 },
509 [NDA_VNI] = { .type = NETLINK_TYPE_U32 },
510 [NDA_IFINDEX] = { .type = NETLINK_TYPE_U32 },
e559b384
TG
511};
512
513static const NLTypeSystem rtnl_neigh_type_system = {
c1df8dee 514 .count = ELEMENTSOF(rtnl_neigh_types),
e559b384
TG
515 .types = rtnl_neigh_types,
516};
517
d8e538ec 518static const NLType rtnl_types[RTM_MAX + 1] = {
979e7eb9
DH
519 [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 },
520 [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
cafbc790
DH
521 [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
522 [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
523 [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
524 [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
525 [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
526 [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
527 [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
528 [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
529 [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
530 [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
531 [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
532 [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
533 [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
d8e538ec
TG
534};
535
846a6b3d 536const NLTypeSystem type_system_root = {
c1df8dee 537 .count = ELEMENTSOF(rtnl_types),
d8e538ec
TG
538 .types = rtnl_types,
539};
540
817d1cd8
DH
541uint16_t type_get_type(const NLType *type) {
542 assert(type);
543 return type->type;
544}
545
546size_t type_get_size(const NLType *type) {
547 assert(type);
548 return type->size;
549}
550
c658008f
DH
551void type_get_type_system(const NLType *nl_type, const NLTypeSystem **ret) {
552 assert(nl_type);
553 assert(ret);
554 assert(nl_type->type == NETLINK_TYPE_NESTED);
555 assert(nl_type->type_system);
556
557 *ret = nl_type->type_system;
558}
559
560void type_get_type_system_union(const NLType *nl_type, const NLTypeSystemUnion **ret) {
561 assert(nl_type);
562 assert(ret);
563 assert(nl_type->type == NETLINK_TYPE_UNION);
564 assert(nl_type->type_system_union);
565
566 *ret = nl_type->type_system_union;
567}
568
c1df8dee 569uint16_t type_system_get_count(const NLTypeSystem *type_system) {
435bbb02 570 assert(type_system);
c1df8dee 571 return type_system->count;
435bbb02
DH
572}
573
d8e538ec
TG
574int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) {
575 const NLType *nl_type;
576
577 assert(ret);
846a6b3d 578 assert(type_system);
d8e538ec
TG
579 assert(type_system->types);
580
c1df8dee 581 if (type >= type_system->count)
15411c0c 582 return -EOPNOTSUPP;
d8e538ec
TG
583
584 nl_type = &type_system->types[type];
585
cafbc790 586 if (nl_type->type == NETLINK_TYPE_UNSPEC)
15411c0c 587 return -EOPNOTSUPP;
d8e538ec
TG
588
589 *ret = nl_type;
590
591 return 0;
592}
593
594int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type) {
595 const NLType *nl_type;
596 int r;
597
598 assert(ret);
599
600 r = type_system_get_type(type_system, &nl_type, type);
601 if (r < 0)
602 return r;
603
c658008f 604 type_get_type_system(nl_type, ret);
d8e538ec
TG
605 return 0;
606}
607
608int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type) {
609 const NLType *nl_type;
610 int r;
611
612 assert(ret);
613
614 r = type_system_get_type(type_system, &nl_type, type);
615 if (r < 0)
616 return r;
617
c658008f 618 type_get_type_system_union(nl_type, ret);
d8e538ec
TG
619 return 0;
620}
621
622int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key) {
623 int type;
624
625 assert(type_system_union);
f8a6ca1b 626 assert(type_system_union->match_type == NL_MATCH_SIBLING);
d8e538ec
TG
627 assert(type_system_union->lookup);
628 assert(type_system_union->type_systems);
629 assert(ret);
630 assert(key);
631
632 type = type_system_union->lookup(key);
633 if (type < 0)
15411c0c 634 return -EOPNOTSUPP;
d8e538ec
TG
635
636 assert(type < type_system_union->num);
637
638 *ret = &type_system_union->type_systems[type];
639
640 return 0;
641}
4af7b60d
TG
642
643int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol) {
644 const NLTypeSystem *type_system;
645
646 assert(type_system_union);
647 assert(type_system_union->type_systems);
f8a6ca1b 648 assert(type_system_union->match_type == NL_MATCH_PROTOCOL);
4af7b60d 649 assert(ret);
4af7b60d
TG
650
651 if (protocol >= type_system_union->num)
15411c0c 652 return -EOPNOTSUPP;
4af7b60d
TG
653
654 type_system = &type_system_union->type_systems[protocol];
e7de105c 655 if (!type_system->types)
15411c0c 656 return -EOPNOTSUPP;
4af7b60d
TG
657
658 *ret = type_system;
659
660 return 0;
661}