1 /*
2 * IFLA_AF_SPEC netlink attribute decoding check.
3 *
4 * Copyright (c) 2018-2022 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11
12 #include <inttypes.h>
13 #include <stdio.h>
14 #include <stddef.h>
15 #include "test_nlattr.h"
16
17 #include <linux/if.h>
18 #include <linux/if_arp.h>
19 #include <linux/if_bridge.h>
20 #include <linux/if_link.h>
21 #include <linux/rtnetlink.h>
22
23 #include "xlat.h"
24 #include "xlat/addrfams.h"
25
26 #define XLAT_MACROS_ONLY
27 #include "xlat/rtnl_ifla_af_spec_inet_attrs.h"
28 #include "xlat/rtnl_ifla_af_spec_inet6_attrs.h"
29 #undef XLAT_MACROS_ONLY
30
31 static uint8_t msg_af = AF_UNIX;
32 static char msg_af_str[32] = "AF_UNIX";
33
34 #define IFLA_AF msg_af
35 #define IFLA_AF_STR msg_af_str
36 #define IFLA_ATTR IFLA_AF_SPEC
37 #include "nlattr_ifla.h"
38
39 #include "nlattr_ifla_af_inet6.h"
40
41 #define AF_SPEC_FUNCS(family_) \
42 static void \
43 init_##family_##_msg(struct nlmsghdr *const nlh, \
44 const unsigned int msg_len) \
45 { \
46 init_ifinfomsg(nlh, msg_len); \
47 \
48 struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen); \
49 nla += 1; \
50 SET_STRUCT(struct nlattr, nla, \
51 .nla_len = msg_len - NLMSG_SPACE(hdrlen) \
52 - NLA_HDRLEN, \
53 .nla_type = family_, \
54 ); \
55 } \
56 \
57 static void \
58 print_##family_##_msg(const unsigned int msg_len) \
59 { \
60 print_ifinfomsg(msg_len); \
61 printf(", [{nla_len=%u, nla_type=" #family_ "}", \
62 msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN); \
63 } \
64 /* end of AF_SPEC_FUNCS definition */
65
66 AF_SPEC_FUNCS(AF_INET)
67 AF_SPEC_FUNCS(AF_INET6)
68 AF_SPEC_FUNCS(AF_MCTP)
69
70 AF_SPEC_FUNCS(IFLA_BRIDGE_VLAN_TUNNEL_INFO)
71
72 static void
73 print_inet_conf_val(uint32_t *val, size_t idx)
74 {
75 static const char * const strs[] = {
76 "IPV4_DEVCONF_FORWARDING-1",
77 "IPV4_DEVCONF_MC_FORWARDING-1",
78 };
79
80 print_arr_val(val, idx, idx < ARRAY_SIZE(strs) ? strs[idx] : NULL);
81 }
82
83 int
84 main(void)
85 {
86 static const uint8_t unknown_msg[] = { 0xab, 0xac, 0xdb, 0xcd };
87
88 skip_if_unavailable("/proc/self/fd/");
89
90 const int fd = create_nl_socket(NETLINK_ROUTE);
91
92 const unsigned int hdrlen = sizeof(struct ifinfomsg);
93 void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), 3 * NLA_HDRLEN + 256);
94
95 static char pattern[4096];
96 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
97
98
99 /* unknown AF_* */
100 static uint8_t skip_afs[] = { AF_INET, AF_INET6, AF_MCTP };
101 size_t pos = 0;
102 static uint8_t skip_afs_msg[] = { AF_BRIDGE };
103 size_t pos2 = 0;
104 for (size_t j = 0; j < 64; j++) {
105 if (pos2 < ARRAY_SIZE(skip_afs_msg) && skip_afs_msg[pos2] == j)
106 {
107 pos2 += 1;
108 continue;
109 }
110
111 msg_af = j;
112 msg_af_str[0] = '\0';
113 strncat(msg_af_str, sprintxval(addrfams, j, "AF_???"),
114 sizeof(msg_af_str) - 1);
115 pos = 0;
116
117 for (size_t i = 0; i < 64; i++) {
118 if (pos < ARRAY_SIZE(skip_afs) && skip_afs[pos] == i) {
119 pos += 1;
120 continue;
121 }
122
123 const char *af_str = sprintxval(addrfams, i, "AF_???");
124 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
125 init_ifinfomsg,
126 print_ifinfomsg,
127 i, af_str, pattern,
128 unknown_msg,
129 print_quoted_hex, 1,
130 printf("\"\\xab\\xac\\xdb"
131 "\\xcd\""));
132 }
133 }
134
135 /* AF_INET */
136 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
137 init_AF_INET_msg, print_AF_INET_msg,
138 0, "IFLA_INET_UNSPEC", pattern,
139 unknown_msg, print_quoted_hex, 2,
140 printf("\"\\xab\\xac\\xdb\\xcd\""));
141 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
142 init_AF_INET_msg, print_AF_INET_msg,
143 2, "0x2 /* IFLA_INET_??? */", pattern,
144 unknown_msg, print_quoted_hex, 2,
145 printf("\"\\xab\\xac\\xdb\\xcd\""));
146
147 /* AF_INET: IFLA_INET_CONF */
148 uint32_t inet_conf_vals[] = { 0xdeadc0de, 0xda7aface };
149 TEST_NESTED_NLATTR_ARRAY_EX(fd, nlh0, hdrlen,
150 init_AF_INET_msg, print_AF_INET_msg,
151 IFLA_INET_CONF, pattern,
152 inet_conf_vals, 2, print_inet_conf_val);
153
154 /* AF_BRIDGE */
155 msg_af = AF_BRIDGE;
156 strcpy(msg_af_str, "AF_BRIDGE");
157
158 /* AF_BRIDGE: unknown, unimplemented */
159 static const struct strval16 unk_attrs[] = {
160 { ENUM_KNOWN(0x4, IFLA_BRIDGE_MRP) },
161 { ENUM_KNOWN(0x5, IFLA_BRIDGE_CFM) },
162 { ENUM_KNOWN(0x6, IFLA_BRIDGE_MST) },
163 { ARG_XLAT_UNKNOWN(0x7, "IFLA_BRIDGE_???") },
164 { ARG_XLAT_UNKNOWN(0xbad, "IFLA_BRIDGE_???") },
165 };
166 for (size_t i = 0; i < ARRAY_SIZE(unk_attrs); i++) {
167 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
168 init_ifinfomsg, print_ifinfomsg,
169 unk_attrs[i].val,
170 unk_attrs[i].str,
171 pattern, unknown_msg,
172 print_quoted_hex, 1,
173 printf("\"\\xab\\xac\\xdb\\xcd\"")
174 );
175 }
176
177 /* AF_BRIDGE: IFLA_BRIDGE_FLAGS */
178 static const struct strval16 bridge_flags[] = {
179 { ARG_STR(0) },
180 { ARG_STR(BRIDGE_FLAGS_MASTER) },
181 { ARG_STR(BRIDGE_FLAGS_SELF) },
182 { ARG_STR(BRIDGE_FLAGS_MASTER|BRIDGE_FLAGS_SELF) },
183 { ARG_STR(0x4) " /* BRIDGE_FLAGS_??? */" },
184 { 0xcafe, "BRIDGE_FLAGS_SELF|0xcafc" },
185 { ARG_STR(0x7eac) " /* BRIDGE_FLAGS_??? */" },
186 };
187 for (size_t i = 0; i < ARRAY_SIZE(bridge_flags); i++) {
188 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
189 init_ifinfomsg, print_ifinfomsg,
190 IFLA_BRIDGE_FLAGS,
191 "IFLA_BRIDGE_FLAGS",
192 pattern, bridge_flags[i].val,
193 print_quoted_hex, 1,
194 printf("%s", bridge_flags[i].str)
195 );
196 }
197
198 /* AF_BRIDGE: IFLA_BRIDGE_MODE */
199 static const struct strval16 bridge_modes[] = {
200 { ARG_STR(BRIDGE_MODE_VEB) },
201 { ARG_STR(BRIDGE_MODE_VEPA) },
202 { ARG_STR(0x2) " /* BRIDGE_MODE_??? */" },
203 { ARG_STR(0x3) " /* BRIDGE_MODE_??? */" },
204 { ARG_STR(0xcafe) " /* BRIDGE_MODE_??? */" },
205 { ARG_STR(0xfffe) " /* BRIDGE_MODE_??? */" },
206 { ARG_STR(BRIDGE_MODE_UNDEF) },
207 };
208 for (size_t i = 0; i < ARRAY_SIZE(bridge_flags); i++) {
209 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
210 init_ifinfomsg, print_ifinfomsg,
211 IFLA_BRIDGE_MODE,
212 "IFLA_BRIDGE_MODE",
213 pattern, bridge_modes[i].val,
214 print_quoted_hex, 1,
215 printf("%s", bridge_modes[i].str)
216 );
217 }
218
219 /* AF_BRIDGE: IFLA_BRIDGE_VLAN_INFO */
220 static const struct {
221 struct bridge_vlan_info val;
222 const char *str;
223 } bridge_vis[] = {
224 { { 0, 0 }, "{flags=0, vid=0}" },
225 { { 1, 1 }, "{flags=BRIDGE_VLAN_INFO_MASTER, vid=1}" },
226 { { 0x69, 0xface },
227 "{flags=BRIDGE_VLAN_INFO_MASTER|BRIDGE_VLAN_INFO_RANGE_BEGIN"
228 "|BRIDGE_VLAN_INFO_BRENTRY|BRIDGE_VLAN_INFO_ONLY_OPTS"
229 ", vid=64206}" },
230 { {0xef80, 0xfeed },
231 "{flags=0xef80 /* BRIDGE_VLAN_INFO_??? */, vid=65261}" },
232 { {0xcafe, 0xdead },
233 "{flags=BRIDGE_VLAN_INFO_PVID|BRIDGE_VLAN_INFO_UNTAGGED"
234 "|BRIDGE_VLAN_INFO_RANGE_BEGIN|BRIDGE_VLAN_INFO_RANGE_END"
235 "|BRIDGE_VLAN_INFO_BRENTRY|BRIDGE_VLAN_INFO_ONLY_OPTS|0xca80"
236 ", vid=57005}" },
237 };
238 char bvi_buf[12];
239
240 fill_memory_ex(bvi_buf, sizeof(bvi_buf), 'z', 0x80);
241
242 for (size_t i = 0; i < ARRAY_SIZE(bridge_vis); i++) {
243 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
244 init_ifinfomsg, print_ifinfomsg,
245 IFLA_BRIDGE_VLAN_INFO,
246 "IFLA_BRIDGE_VLAN_INFO",
247 pattern, bridge_vis[i].val,
248 print_quoted_hex, 1,
249 printf("%s", bridge_vis[i].str));
250
251 memcpy(bvi_buf, &bridge_vis[i].val, sizeof(bridge_vis[i].val));
252 TEST_NLATTR_(fd, nlh0 - NLA_HDRLEN, hdrlen + NLA_HDRLEN,
253 init_ifinfomsg, print_ifinfomsg,
254 IFLA_BRIDGE_VLAN_INFO, "IFLA_BRIDGE_VLAN_INFO",
255 sizeof(bvi_buf), bvi_buf, sizeof(bvi_buf),
256 printf("%s, \"\\x7e\\x7f\\x80\\x81\\x82"
257 "\\x83\\x84\\x85\"]",
258 bridge_vis[i].str));
259 }
260
261 /* AF_BRIDGE: IFLA_BRIDGE_TUNNEL_INFO: unknown, undecoded */
262 static const struct strval16 unk_bti_attrs[] = {
263 { ENUM_KNOWN(0, IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC) },
264 { ARG_XLAT_UNKNOWN(0x4, "IFLA_BRIDGE_VLAN_TUNNEL_???") },
265 { ARG_XLAT_UNKNOWN(0xbad, "IFLA_BRIDGE_VLAN_TUNNEL_???") },
266 };
267 for (size_t i = 0; i < ARRAY_SIZE(unk_bti_attrs); i++) {
268 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
269 init_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
270 print_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
271 unk_bti_attrs[i].val,
272 unk_bti_attrs[i].str,
273 pattern, unknown_msg,
274 print_quoted_hex, 2,
275 printf("\"\\xab\\xac\\xdb\\xcd\"")
276 );
277 }
278
279 /* AF_BRIDGE: IFLA_BRIDGE_TUNNEL_INFO: u32 attrs */
280 static const struct strval16 u32_bti_attrs[] = {
281 { ENUM_KNOWN(0x1, IFLA_BRIDGE_VLAN_TUNNEL_ID) },
282 };
283 void *nlh_u32 = midtail_alloc(NLMSG_SPACE(hdrlen),
284 NLA_HDRLEN + sizeof(uint32_t));
285 for (size_t i = 0; i < ARRAY_SIZE(u32_bti_attrs); i++) {
286 check_u32_nlattr(fd, nlh_u32, hdrlen,
287 init_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
288 print_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
289 u32_bti_attrs[i].val, u32_bti_attrs[i].str,
290 pattern, 2);
291 }
292
293 /* AF_BRIDGE: IFLA_BRIDGE_TUNNEL_INFO: u16 attrs */
294 static const struct strval16 u16_bti_attrs[] = {
295 { ENUM_KNOWN(0x1, IFLA_BRIDGE_VLAN_TUNNEL_VID) },
296 };
297 void *nlh_u16 = midtail_alloc(NLMSG_SPACE(hdrlen),
298 NLA_HDRLEN + sizeof(uint16_t));
299 for (size_t i = 0; i < ARRAY_SIZE(u16_bti_attrs); i++) {
300 check_u16_nlattr(fd, nlh_u16, hdrlen,
301 init_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
302 print_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
303 u16_bti_attrs[i].val, u16_bti_attrs[i].str,
304 pattern, 2);
305 }
306
307 /* AF_BRIDGE: IFLA_BRIDGE_TUNNEL_INFO: IFLA_BRIDGE_VLAN_TUNNEL_FLAGS */
308 static const struct strval16 bti_flags[] = {
309 { ARG_STR(0) },
310 { ARG_STR(BRIDGE_VLAN_INFO_MASTER) },
311 { ARG_STR(BRIDGE_VLAN_INFO_PVID) },
312 { ARG_STR(BRIDGE_VLAN_INFO_MASTER|BRIDGE_VLAN_INFO_PVID) },
313 { ARG_STR(0xef80) " /* BRIDGE_VLAN_INFO_??? */" },
314 { 0xcafe, "BRIDGE_VLAN_INFO_PVID|BRIDGE_VLAN_INFO_UNTAGGED"
315 "|BRIDGE_VLAN_INFO_RANGE_BEGIN"
316 "|BRIDGE_VLAN_INFO_RANGE_END|BRIDGE_VLAN_INFO_BRENTRY"
317 "|BRIDGE_VLAN_INFO_ONLY_OPTS|0xca80" },
318 };
319 for (size_t i = 0; i < ARRAY_SIZE(bti_flags); i++) {
320 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
321 init_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
322 print_IFLA_BRIDGE_VLAN_TUNNEL_INFO_msg,
323 IFLA_BRIDGE_VLAN_TUNNEL_FLAGS,
324 "IFLA_BRIDGE_VLAN_TUNNEL_FLAGS",
325 pattern, bti_flags[i].val,
326 print_quoted_hex, 2,
327 printf("%s", bti_flags[i].str)
328 );
329 }
330
331 /* AF_INET6 */
332 msg_af = AF_UNIX;
333 strcpy(msg_af_str, "AF_UNIX");
334
335 check_ifla_af_inet6(fd, nlh0, hdrlen,
336 init_AF_INET6_msg, print_AF_INET6_msg, pattern, 2);
337
338 /* AF_MCTP */
339 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
340 init_AF_MCTP_msg, print_AF_MCTP_msg,
341 0, "IFLA_MCTP_UNSPEC", pattern,
342 unknown_msg, print_quoted_hex, 2,
343 printf("\"\\xab\\xac\\xdb\\xcd\""));
344 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
345 init_AF_MCTP_msg, print_AF_MCTP_msg,
346 2, "0x2 /* IFLA_MCTP_??? */", pattern,
347 unknown_msg, print_quoted_hex, 2,
348 printf("\"\\xab\\xac\\xdb\\xcd\""));
349
350 /* AF_MCTP: IFLA_MCTP_NET */
351 check_u32_nlattr(fd, nlh0, hdrlen, init_AF_MCTP_msg, print_AF_MCTP_msg,
352 1, "IFLA_MCTP_NET", pattern, 2);
353
354 puts("+++ exited with 0 +++");
355 return 0;
356 }