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