1 /*
2 * IFLA_VFINFO_LIST 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 <stddef.h>
14 #include <stdio.h>
15
16 #include <arpa/inet.h>
17
18 #include <linux/if.h>
19 #include <linux/if_arp.h>
20 #include <linux/if_link.h>
21 #include <linux/rtnetlink.h>
22
23 #include "test_nlattr.h"
24
25 #include "xlat.h"
26
27 #define IFLA_ATTR IFLA_VFINFO_LIST
28 #include "nlattr_ifla.h"
29
30 static void
31 init_vf_info_msg(struct nlmsghdr *const nlh, const unsigned int msg_len)
32 {
33 init_ifinfomsg(nlh, msg_len);
34
35 struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);
36 nla += 1;
37 SET_STRUCT(struct nlattr, nla,
38 .nla_len = msg_len - NLMSG_SPACE(hdrlen)
39 - NLA_HDRLEN,
40 .nla_type = IFLA_VF_INFO,
41 );
42 }
43
44 static void
45 print_vf_info_msg(const unsigned int msg_len)
46 {
47 print_ifinfomsg(msg_len);
48 printf(", [{nla_len=%u, nla_type=" XLAT_FMT "}",
49 msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN,
50 XLAT_ARGS(IFLA_VF_INFO));
51 }
52
53 static void
54 init_vf_stats_msg(struct nlmsghdr *const nlh, const unsigned int msg_len)
55 {
56 init_vf_info_msg(nlh, msg_len);
57
58 struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);
59 nla += 2;
60 SET_STRUCT(struct nlattr, nla,
61 .nla_len = msg_len - NLMSG_SPACE(hdrlen)
62 - NLA_HDRLEN * 2,
63 .nla_type = IFLA_VF_STATS,
64 );
65 }
66
67 static void
68 print_vf_stats_msg(const unsigned int msg_len)
69 {
70 print_vf_info_msg(msg_len);
71 printf(", [{nla_len=%u, nla_type=" XLAT_FMT "}",
72 msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN * 2,
73 XLAT_ARGS(IFLA_VF_STATS));
74 }
75
76 static void
77 init_vlan_list_msg(struct nlmsghdr *const nlh, const unsigned int msg_len)
78 {
79 init_vf_info_msg(nlh, msg_len);
80
81 struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen);
82 nla += 2;
83 SET_STRUCT(struct nlattr, nla,
84 .nla_len = msg_len - NLMSG_SPACE(hdrlen)
85 - NLA_HDRLEN * 2,
86 .nla_type = IFLA_VF_VLAN_LIST,
87 );
88 }
89
90 static void
91 print_vlan_list_msg(const unsigned int msg_len)
92 {
93 print_vf_info_msg(msg_len);
94 printf(", [{nla_len=%u, nla_type=" XLAT_FMT "}",
95 msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN * 2,
96 XLAT_ARGS(IFLA_VF_VLAN_LIST));
97 }
98
99 int
100 main(void)
101 {
102 static const uint8_t dummy[] = { 0xab, 0xac, 0xdb, 0xcd };
103
104 skip_if_unavailable("/proc/self/fd/");
105
106 const int fd = create_nl_socket(NETLINK_ROUTE);
107
108 const unsigned int hdrlen = sizeof(struct ifinfomsg);
109 void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), 2 * NLA_HDRLEN + 256);
110
111 static char pattern[4096];
112 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
113
114
115 /* unknown IFLA_VF_INFO*, IFLA_VF_INFO_UNSPEC */
116 static const struct strval16 unk_attrs[] = {
117 { ENUM_KNOWN(0, IFLA_VF_INFO_UNSPEC) },
118 { ARG_XLAT_UNKNOWN(0x2, "IFLA_VF_INFO_???") },
119 { ARG_XLAT_UNKNOWN(0x1ace, "IFLA_VF_INFO_???") },
120 };
121 for (size_t i = 0; i < ARRAY_SIZE(unk_attrs); i++) {
122 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
123 init_ifinfomsg, print_ifinfomsg,
124 unk_attrs[i].val, unk_attrs[i].str,
125 pattern, dummy, print_quoted_hex, 1,
126 printf("\"\\xab\\xac\\xdb\\xcd\""));
127 }
128
129 /* IFLA_VF_INFO: unknown, IFLA_VF_UNSPEC */
130 static const struct strval16 unk_vf_attrs[] = {
131 { ENUM_KNOWN(0, IFLA_VF_UNSPEC) },
132 { ARG_XLAT_UNKNOWN(0xe, "IFLA_VF_???") },
133 { ARG_XLAT_UNKNOWN(0x1ace, "IFLA_VF_???") },
134 };
135 for (size_t i = 0; i < ARRAY_SIZE(unk_vf_attrs); i++) {
136 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
137 init_vf_info_msg,
138 print_vf_info_msg,
139 unk_vf_attrs[i].val,
140 unk_vf_attrs[i].str,
141 pattern, dummy,
142 print_quoted_hex, 2,
143 printf("\"\\xab\\xac\\xdb\\xcd\"")
144 );
145 }
146
147 /* IFLA_VF_INFO: IFLA_VF_MAC */
148 struct ifla_vf_mac ifla_vm;
149 ifla_vm.vf = 0xdeadface;
150 fill_memory(&ifla_vm.mac, sizeof(ifla_vm.mac));
151 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
152 init_vf_info_msg, print_vf_info_msg,
153 IFLA_VF_MAC,
154 XLAT_KNOWN(0x1, "IFLA_VF_MAC"),
155 pattern, ifla_vm, print_quoted_hex, 2,
156 printf("{vf=3735943886, mac="
157 XLAT_KNOWN_FMT("\"\\x80\\x81"
158 "\\x82\\x83\\x84\\x85\\x86\\x87"
159 "\\x88\\x89\\x8a\\x8b\\x8c\\x8d"
160 "\\x8e\\x8f\\x90\\x91\\x92\\x93"
161 "\\x94\\x95\\x96\\x97\\x98\\x99"
162 "\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\"",
163 "80:81:82:83:84:85:86:87:88:89:"
164 "8a:8b:8c:8d:8e:8f:90:91:92:93:"
165 "94:95:96:97:98:99:9a:9b:9c:9d:"
166 "9e:9f") "}"));
167
168 /* IFLA_VF_INFO: IFLA_VF_VLAN */
169 struct ifla_vf_vlan ifla_vv;
170 ifla_vv.vf = 0x80a0c0e0;
171 ifla_vv.vlan = 0x81a1c1e1;
172 ifla_vv.qos = 0x82a2c2e2;
173 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
174 init_vf_info_msg, print_vf_info_msg,
175 IFLA_VF_VLAN,
176 XLAT_KNOWN(0x2, "IFLA_VF_VLAN"),
177 pattern, ifla_vv, print_quoted_hex, 2,
178 printf("{vf=2158018784, vlan=2174861793"
179 ", qos=2191704802}"));
180
181 /* IFLA_VF_INFO: IFLA_VF_TX_RATE */
182 struct ifla_vf_tx_rate ifla_vtr;
183 ifla_vtr.vf = 0x80a0c0e0;
184 ifla_vtr.rate = 0x81a1c1e1;
185 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
186 init_vf_info_msg, print_vf_info_msg,
187 IFLA_VF_TX_RATE,
188 XLAT_KNOWN(0x3, "IFLA_VF_TX_RATE"),
189 pattern, ifla_vtr, print_quoted_hex, 2,
190 printf("{vf=2158018784"
191 ", rate=2174861793}"));
192
193 /* IFLA_VF_INFO: IFLA_VF_SPOOFCHK */
194 struct ifla_vf_spoofchk ifla_vsc;
195 ifla_vsc.vf = 0x80a0c0e0;
196 ifla_vsc.setting = 0x81a1c1e1;
197 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
198 init_vf_info_msg, print_vf_info_msg,
199 IFLA_VF_SPOOFCHK,
200 XLAT_KNOWN(0x4, "IFLA_VF_SPOOFCHK"),
201 pattern, ifla_vsc, print_quoted_hex, 2,
202 printf("{vf=2158018784"
203 ", setting=2174861793}"));
204
205 /* IFLA_VF_INFO: IFLA_VF_LINK_STATE */
206 static const struct strval32 states[] = {
207 { ENUM_KNOWN(0, IFLA_VF_LINK_STATE_AUTO) },
208 { ENUM_KNOWN(0x1, IFLA_VF_LINK_STATE_ENABLE) },
209 { ENUM_KNOWN(0x2, IFLA_VF_LINK_STATE_DISABLE) },
210 { ARG_STR(0x3) NRAW(" /* IFLA_VF_LINK_STATE_??? */") },
211 { ARG_STR(0x4) NRAW(" /* IFLA_VF_LINK_STATE_??? */") },
212 { ARG_STR(0xfade) NRAW(" /* IFLA_VF_LINK_STATE_??? */") },
213 };
214 struct ifla_vf_link_state ifla_vls;
215 ifla_vls.vf = 0xbeeffeed;
216
217 for (size_t i = 0; i < ARRAY_SIZE(states); i++) {
218 ifla_vls.link_state = states[i].val;
219 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
220 init_vf_info_msg,
221 print_vf_info_msg,
222 IFLA_VF_LINK_STATE,
223 XLAT_KNOWN(0x5,
224 "IFLA_VF_LINK_STATE"),
225 pattern, ifla_vls,
226 print_quoted_hex, 2,
227 printf("{vf=3203399405"
228 ", link_state=%s}",
229 states[i].str));
230 }
231
232 /* IFLA_VF_INFO: IFLA_VF_RATE */
233 struct ifla_vf_rate ifla_vr;
234 ifla_vr.vf = 0x80a0c0e0;
235 ifla_vr.min_tx_rate = 0x81a1c1e1;
236 ifla_vr.max_tx_rate = 0x82a2c2e2;
237 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
238 init_vf_info_msg, print_vf_info_msg,
239 IFLA_VF_RATE,
240 XLAT_KNOWN(0x6, "IFLA_VF_RATE"),
241 pattern, ifla_vr, print_quoted_hex, 2,
242 printf("{vf=2158018784"
243 ", min_tx_rate=2174861793"
244 ", max_tx_rate=2191704802}"));
245
246 /* IFLA_VF_INFO: IFLA_VF_RSS_QUERY_EN */
247 struct ifla_vf_rss_query_en ifla_vrqe;
248 ifla_vrqe.vf = 0x80a0c0e0;
249 ifla_vrqe.setting = 0x81a1c1e1;
250 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
251 init_vf_info_msg, print_vf_info_msg,
252 IFLA_VF_RSS_QUERY_EN,
253 XLAT_KNOWN(0x7, "IFLA_VF_RSS_QUERY_EN"),
254 pattern, ifla_vrqe, print_quoted_hex, 2,
255 printf("{vf=2158018784"
256 ", setting=2174861793}"));
257
258 /* IFLA_VF_INFO: IFLA_VF_STATS: unknown, IFLA_VF_STATS_PAD */
259 static const struct strval16 unk_vs_attrs[] = {
260 { ENUM_KNOWN(0x6, IFLA_VF_STATS_PAD) },
261 { ARG_XLAT_UNKNOWN(0x9, "IFLA_VF_STATS_???") },
262 { ARG_XLAT_UNKNOWN(0x1ace, "IFLA_VF_STATS_???") },
263 };
264 for (size_t i = 0; i < ARRAY_SIZE(unk_vs_attrs); i++) {
265 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
266 init_vf_stats_msg,
267 print_vf_stats_msg,
268 unk_vs_attrs[i].val,
269 unk_vs_attrs[i].str,
270 pattern, dummy,
271 print_quoted_hex, 3,
272 printf("\"\\xab\\xac\\xdb\\xcd\"")
273 );
274 }
275
276 /* IFLA_VF_INFO: IFLA_VF_STATS: u64 attrs */
277 static const struct strval16 u64_vs_attrs[] = {
278 { ENUM_KNOWN(0, IFLA_VF_STATS_RX_PACKETS) },
279 { ENUM_KNOWN(0x1, IFLA_VF_STATS_TX_PACKETS) },
280 { ENUM_KNOWN(0x2, IFLA_VF_STATS_RX_BYTES) },
281 { ENUM_KNOWN(0x3, IFLA_VF_STATS_TX_BYTES) },
282 { ENUM_KNOWN(0x4, IFLA_VF_STATS_BROADCAST) },
283 { ENUM_KNOWN(0x5, IFLA_VF_STATS_MULTICAST) },
284 { ENUM_KNOWN(0x7, IFLA_VF_STATS_RX_DROPPED) },
285 { ENUM_KNOWN(0x8, IFLA_VF_STATS_TX_DROPPED) },
286 };
287 void *nlh_vs_u64 = midtail_alloc(NLMSG_SPACE(hdrlen),
288 3 * NLA_HDRLEN + sizeof(uint64_t));
289
290 for (size_t i = 0; i < ARRAY_SIZE(u64_vs_attrs); i++) {
291 check_u64_nlattr(fd, nlh_vs_u64, hdrlen,
292 init_vf_stats_msg, print_vf_stats_msg,
293 u64_vs_attrs[i].val, u64_vs_attrs[i].str,
294 pattern, 3);
295 }
296
297 /* IFLA_VF_INFO: IFLA_VF_TRUST */
298 struct ifla_vf_trust ifla_vt;
299 ifla_vt.vf = 0x80a0c0e0;
300 ifla_vt.setting = 0x81a1c1e1;
301 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
302 init_vf_info_msg, print_vf_info_msg,
303 IFLA_VF_TRUST,
304 XLAT_KNOWN(0x9, "IFLA_VF_TRUST"),
305 pattern, ifla_vt, print_quoted_hex, 2,
306 printf("{vf=2158018784"
307 ", setting=2174861793}"));
308
309 /* IFLA_VF_INFO: IFLA_VF_IB_NODE_GUID, IFLA_VF_IB_PORT_GUID */
310 static const struct strval16 guid_attrs[] = {
311 { ENUM_KNOWN(0xa, IFLA_VF_IB_NODE_GUID) },
312 { ENUM_KNOWN(0xb, IFLA_VF_IB_PORT_GUID) },
313 };
314 struct ifla_vf_guid ifla_vg;
315 ifla_vg.vf = 0xfacecafe;
316 ifla_vg.guid = 0xbadc0deddeedbabeULL;
317
318 for (size_t i = 0; i < ARRAY_SIZE(guid_attrs); i++) {
319 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
320 init_vf_info_msg,
321 print_vf_info_msg,
322 guid_attrs[i].val,
323 guid_attrs[i].str,
324 pattern, ifla_vg,
325 print_quoted_hex, 2,
326 printf("{vf=4207856382"
327 ", guid=0xbadc0deddeedbabe"
328 "}"));
329 }
330
331 /* IFLA_VF_INFO: IFLA_VF_VLAN_LIST: unknown, IFLA_VF_VLAN_INFO_UNSPEC */
332 static const struct strval16 unk_vl_attrs[] = {
333 { ENUM_KNOWN(0, IFLA_VF_VLAN_INFO_UNSPEC) },
334 { ARG_XLAT_UNKNOWN(0x2, "IFLA_VF_VLAN_INFO_???") },
335 { ARG_XLAT_UNKNOWN(0x1ace, "IFLA_VF_VLAN_INFO_???") },
336 };
337 for (size_t i = 0; i < ARRAY_SIZE(unk_vl_attrs); i++) {
338 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
339 init_vlan_list_msg,
340 print_vlan_list_msg,
341 unk_vl_attrs[i].val,
342 unk_vl_attrs[i].str,
343 pattern, dummy,
344 print_quoted_hex, 3,
345 printf("\"\\xab\\xac\\xdb\\xcd\"")
346 );
347 }
348
349 /* IFLA_VF_INFO: IFLA_VF_VLAN_LIST: IFLA_VF_VLAN_INFO */
350 static const struct strval16 eth_protos[] = {
351 { ARG_STR(0) NRAW(" /* ETH_P_??? */") },
352 { ARG_XLAT_KNOWN(0x8, "ETH_P_PPP_MP") },
353 { ARG_XLAT_KNOWN(0x800, "ETH_P_IP") },
354 { ARG_STR(0xf) NRAW(" /* ETH_P_??? */") },
355 { ARG_STR(0xfb) NRAW(" /* ETH_P_??? */") },
356 { ARG_XLAT_KNOWN(0xfbfb, "ETH_P_AF_IUCV") },
357 { ARG_STR(0xffff) NRAW(" /* ETH_P_??? */") },
358 };
359 struct ifla_vf_vlan_info ifla_vvi;
360 ifla_vvi.vf = 0x80a0c0e0;
361 ifla_vvi.vlan = 0x81a1c1e1;
362 ifla_vvi.qos = 0x82a2c2e2;
363
364 for (size_t i = 0; i < ARRAY_SIZE(eth_protos); i++) {
365 ifla_vvi.vlan_proto = htons(eth_protos[i].val);
366 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
367 init_vlan_list_msg,
368 print_vlan_list_msg,
369 IFLA_VF_VLAN_INFO,
370 XLAT_KNOWN(0x1,
371 "IFLA_VF_VLAN_INFO"),
372 pattern, ifla_vvi,
373 print_quoted_hex, 3,
374 printf("{vf=2158018784"
375 ", vlan=2174861793"
376 ", qos=2191704802"
377 ", vlan_proto=htons(%s)}",
378 eth_protos[i].str));
379 }
380
381 /* IFLA_VF_INFO: IFLA_VF_BROADCAST */
382 struct ifla_vf_broadcast ifla_vb;
383 fill_memory(&ifla_vb.broadcast, sizeof(ifla_vb.broadcast));
384 TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,
385 init_vf_info_msg, print_vf_info_msg,
386 IFLA_VF_BROADCAST,
387 XLAT_KNOWN(0xd, "IFLA_VF_BROADCAST"),
388 pattern, ifla_vb, print_quoted_hex, 2,
389 printf("{broadcast="
390 XLAT_KNOWN_FMT("\"\\x80\\x81"
391 "\\x82\\x83\\x84\\x85\\x86\\x87"
392 "\\x88\\x89\\x8a\\x8b\\x8c\\x8d"
393 "\\x8e\\x8f\\x90\\x91\\x92\\x93"
394 "\\x94\\x95\\x96\\x97\\x98\\x99"
395 "\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\"",
396 "80:81:82:83:84:85:86:87:88:89:"
397 "8a:8b:8c:8d:8e:8f:90:91:92:93:"
398 "94:95:96:97:98:99:9a:9b:9c:9d:"
399 "9e:9f") "}"));
400
401 puts("+++ exited with 0 +++");
402 return 0;
403 }