1 /*
2 * Copyright (c) 2017-2018 The strace developers.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "tests.h"
29 #include "print_fields.h"
30
31 #include <stdio.h>
32 #include <stdint.h>
33 #include <string.h>
34 #include <sys/socket.h>
35 #include "netlink.h"
36 #include <linux/rtnetlink.h>
37
38 static void
init_nlattr(struct nlattr * const nla,const uint16_t nla_len,const uint16_t nla_type,const void * const src,const size_t n)39 init_nlattr(struct nlattr *const nla,
40 const uint16_t nla_len,
41 const uint16_t nla_type,
42 const void *const src,
43 const size_t n)
44 {
45 SET_STRUCT(struct nlattr, nla,
46 .nla_len = nla_len,
47 .nla_type = nla_type,
48 );
49
50 memcpy(RTA_DATA(nla), src, n);
51 }
52
53 static void
print_nlattr(const unsigned int nla_len,const char * const nla_type,bool add_data)54 print_nlattr(const unsigned int nla_len, const char *const nla_type, bool add_data)
55 {
56 printf(", %s{{nla_len=%u, nla_type=%s}, ",
57 add_data ? "[" : "", nla_len, nla_type);
58 }
59
60 #define TEST_NLATTR_EX_(fd_, nlh0_, hdrlen_, \
61 init_msg_, print_msg_, \
62 nla_type_, nla_type_str_, \
63 nla_data_len_, nla_total_len_, \
64 src_, slen_, ...) \
65 do { \
66 struct nlmsghdr *const nlh = \
67 (nlh0_) - (NLA_HDRLEN + (slen_)); \
68 struct nlattr *const TEST_NLATTR_nla = \
69 NLMSG_ATTR(nlh, (hdrlen_)); \
70 const unsigned int nla_len = \
71 NLA_HDRLEN + (nla_data_len_); \
72 const unsigned int msg_len = \
73 NLMSG_SPACE(hdrlen_) + NLA_HDRLEN + (nla_total_len_); \
74 \
75 (init_msg_)(nlh, msg_len); \
76 init_nlattr(TEST_NLATTR_nla, nla_len, (nla_type_), \
77 (src_), (slen_)); \
78 \
79 const char *const errstr = \
80 sprintrc(sendto((fd_), nlh, msg_len, \
81 MSG_DONTWAIT, NULL, 0)); \
82 \
83 printf("sendto(%d, {", (fd_)); \
84 (print_msg_)(msg_len); \
85 print_nlattr(nla_len, (nla_type_str_), \
86 (nla_total_len_) > (nla_data_len_)); \
87 \
88 { __VA_ARGS__; } \
89 \
90 if ((nla_total_len_) > (nla_data_len_)) \
91 printf("]"); \
92 \
93 printf("}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n", \
94 msg_len, errstr); \
95 } while (0)
96
97 #define TEST_NLATTR_(fd_, nlh0_, hdrlen_, \
98 init_msg_, print_msg_, \
99 nla_type_, nla_type_str_, \
100 nla_data_len_, src_, slen_, ...) \
101 TEST_NLATTR_EX_((fd_), (nlh0_), (hdrlen_), \
102 (init_msg_), (print_msg_), \
103 (nla_type_), (nla_type_str_), \
104 (nla_data_len_), (nla_data_len_), \
105 (src_), (slen_), __VA_ARGS__)
106
107 #define TEST_NLATTR(fd_, nlh0_, hdrlen_, \
108 init_msg_, print_msg_, \
109 nla_type_, \
110 nla_data_len_, src_, slen_, ...) \
111 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
112 (init_msg_), (print_msg_), \
113 (nla_type_), #nla_type_, \
114 (nla_data_len_), (src_), (slen_), __VA_ARGS__)
115
116 #define TEST_NLATTR_OBJECT_EX_(fd_, nlh0_, hdrlen_, \
117 init_msg_, print_msg_, \
118 nla_type_, nla_type_str_, \
119 pattern_, obj_, fallback_func, ...) \
120 do { \
121 const unsigned int plen = \
122 sizeof(obj_) - 1 > DEFAULT_STRLEN \
123 ? DEFAULT_STRLEN : (int) sizeof(obj_) - 1; \
124 /* len < sizeof(obj_) */ \
125 if (plen > 0) \
126 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
127 (init_msg_), (print_msg_), \
128 (nla_type_), (nla_type_str_), \
129 plen, (pattern_), plen, \
130 (fallback_func)((pattern_), plen)); \
131 /* short read of sizeof(obj_) */ \
132 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
133 (init_msg_), (print_msg_), \
134 (nla_type_), (nla_type_str_), \
135 sizeof(obj_), \
136 (pattern_), sizeof(obj_) - 1, \
137 printf("%p", \
138 RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_))))); \
139 /* sizeof(obj_) */ \
140 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
141 (init_msg_), (print_msg_), \
142 (nla_type_), (nla_type_str_), \
143 sizeof(obj_), \
144 &(obj_), sizeof(obj_), \
145 __VA_ARGS__); \
146 } while (0)
147
148 #define TEST_NLATTR_OBJECT_EX(fd_, nlh0_, hdrlen_, \
149 init_msg_, print_msg_, \
150 nla_type_, \
151 pattern_, obj_, fallback_func, ...) \
152 TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \
153 (init_msg_), (print_msg_), \
154 (nla_type_), #nla_type_, \
155 (pattern_), (obj_), (fallback_func), \
156 __VA_ARGS__)
157
158 #define TEST_NLATTR_OBJECT(fd_, nlh0_, hdrlen_, \
159 init_msg_, print_msg_, \
160 nla_type_, pattern_, obj_, ...) \
161 TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \
162 (init_msg_), (print_msg_), \
163 (nla_type_), #nla_type_, \
164 (pattern_), (obj_), print_quoted_hex, \
165 __VA_ARGS__)
166
167 #define TEST_NLATTR_ARRAY(fd_, nlh0_, hdrlen_, \
168 init_msg_, print_msg_, \
169 nla_type_, pattern_, obj_, print_elem_) \
170 do { \
171 const unsigned int plen = \
172 sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN \
173 ? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1; \
174 /* len < sizeof((obj_)[0]) */ \
175 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
176 (init_msg_), (print_msg_), \
177 (nla_type_), #nla_type_, \
178 plen, (pattern_), plen, \
179 print_quoted_hex((pattern_), plen)); \
180 /* sizeof((obj_)[0]) < len < sizeof(obj_) */ \
181 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
182 (init_msg_), (print_msg_), \
183 (nla_type_), #nla_type_, \
184 sizeof(obj_) - 1, \
185 &(obj_), sizeof(obj_) - 1, \
186 printf("["); \
187 size_t i; \
188 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \
189 if (i) printf(", "); \
190 (print_elem_)(&(obj_)[i], i); \
191 } \
192 printf("]")); \
193 /* short read of sizeof(obj_) */ \
194 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
195 (init_msg_), (print_msg_), \
196 (nla_type_), #nla_type_, \
197 sizeof(obj_), \
198 &(obj_), sizeof(obj_) - 1, \
199 printf("["); \
200 size_t i; \
201 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \
202 if (i) printf(", "); \
203 (print_elem_)(&(obj_)[i], i); \
204 } \
205 printf(", ... /* %p */]", \
206 RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_))) \
207 + sizeof(obj_) - sizeof((obj_)[0]))); \
208 /* sizeof(obj_) */ \
209 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
210 (init_msg_), (print_msg_), \
211 (nla_type_), #nla_type_, \
212 sizeof(obj_), \
213 &(obj_), sizeof(obj_), \
214 printf("["); \
215 size_t i; \
216 for (i = 0; i < ARRAY_SIZE(obj_); ++i) { \
217 if (i) printf(", "); \
218 (print_elem_)(&(obj_)[i], i); \
219 } \
220 printf("]")); \
221 } while (0)
222
223 #define TEST_NESTED_NLATTR_OBJECT_EX_(fd_, nlh0_, hdrlen_, \
224 init_msg_, print_msg_, \
225 nla_type_, nla_type_str_, \
226 pattern_, obj_, fallback_func, \
227 depth_, ...) \
228 do { \
229 const unsigned int plen = \
230 sizeof(obj_) - 1 > DEFAULT_STRLEN \
231 ? DEFAULT_STRLEN : (int) sizeof(obj_) - 1; \
232 /* len < sizeof(obj_) */ \
233 if (plen > 0) \
234 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
235 (hdrlen_) + NLA_HDRLEN * depth_, \
236 (init_msg_), (print_msg_), \
237 (nla_type_), (nla_type_str_), \
238 plen, (pattern_), plen, \
239 (fallback_func)((pattern_), plen); \
240 size_t i; \
241 for (i = 0; i < depth_; ++i) \
242 printf("}")); \
243 /* short read of sizeof(obj_) */ \
244 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
245 (hdrlen_) + NLA_HDRLEN * depth_, \
246 (init_msg_), (print_msg_), \
247 (nla_type_), (nla_type_str_), \
248 sizeof(obj_), \
249 (pattern_), sizeof(obj_) - 1, \
250 printf("%p", RTA_DATA(TEST_NLATTR_nla)); \
251 size_t i; \
252 for (i = 0; i < depth_; ++i) \
253 printf("}")); \
254 /* sizeof(obj_) */ \
255 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
256 (hdrlen_) + NLA_HDRLEN * depth_, \
257 (init_msg_), (print_msg_), \
258 (nla_type_), (nla_type_str_), \
259 sizeof(obj_), \
260 &(obj_), sizeof(obj_), \
261 __VA_ARGS__; \
262 size_t i; \
263 for (i = 0; i < depth_; ++i) \
264 printf("}")); \
265 } while (0)
266
267 #define TEST_NESTED_NLATTR_OBJECT_EX(fd_, nlh0_, hdrlen_, \
268 init_msg_, print_msg_, \
269 nla_type_, pattern_, obj_, \
270 depth_, ...) \
271 TEST_NESTED_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \
272 (init_msg_), (print_msg_), \
273 (nla_type_), #nla_type_, \
274 (pattern_), (obj_), \
275 print_quoted_hex, (depth_), \
276 __VA_ARGS__)
277
278 #define TEST_NESTED_NLATTR_OBJECT(fd_, nlh0_, hdrlen_, \
279 init_msg_, print_msg_, \
280 nla_type_, pattern_, obj_, ...) \
281 TEST_NESTED_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \
282 (init_msg_), (print_msg_), \
283 (nla_type_), #nla_type_, \
284 (pattern_), (obj_), \
285 print_quoted_hex, 1, \
286 __VA_ARGS__)
287
288 #define TEST_NESTED_NLATTR_ARRAY_EX(fd_, nlh0_, hdrlen_, \
289 init_msg_, print_msg_, \
290 nla_type_, pattern_, obj_, depth_, \
291 print_elem_) \
292 do { \
293 const unsigned int plen = \
294 sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN \
295 ? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1; \
296 /* len < sizeof((obj_)[0]) */ \
297 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
298 (hdrlen_) + NLA_HDRLEN * depth_, \
299 (init_msg_), (print_msg_), \
300 (nla_type_), #nla_type_, \
301 plen, (pattern_), plen, \
302 print_quoted_hex((pattern_), plen); \
303 for (size_t i = 0; i < depth_; ++i) \
304 printf("}")); \
305 /* sizeof((obj_)[0]) < len < sizeof(obj_) */ \
306 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
307 (hdrlen_) + NLA_HDRLEN * depth_, \
308 (init_msg_), (print_msg_), \
309 (nla_type_), #nla_type_, \
310 sizeof(obj_) - 1, \
311 &(obj_), sizeof(obj_) - 1, \
312 printf("["); \
313 size_t i; \
314 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \
315 if (i) printf(", "); \
316 (print_elem_)(&(obj_)[i], i); \
317 } \
318 printf("]"); \
319 for (i = 0; i < depth_; ++i) \
320 printf("}")); \
321 /* short read of sizeof(obj_) */ \
322 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
323 (hdrlen_) + NLA_HDRLEN * depth_, \
324 (init_msg_), (print_msg_), \
325 (nla_type_), #nla_type_, \
326 sizeof(obj_), \
327 &(obj_), sizeof(obj_) - 1, \
328 printf("["); \
329 size_t i; \
330 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \
331 if (i) printf(", "); \
332 (print_elem_)(&(obj_)[i], i); \
333 } \
334 printf(", ... /* %p */]", \
335 RTA_DATA(TEST_NLATTR_nla) \
336 + sizeof(obj_) - sizeof((obj_)[0])); \
337 for (i = 0; i < depth_; ++i) \
338 printf("}")); \
339 /* sizeof(obj_) */ \
340 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
341 (hdrlen_) + NLA_HDRLEN * depth_, \
342 (init_msg_), (print_msg_), \
343 (nla_type_), #nla_type_, \
344 sizeof(obj_), \
345 &(obj_), sizeof(obj_), \
346 printf("["); \
347 size_t i; \
348 for (i = 0; i < ARRAY_SIZE(obj_); ++i) { \
349 if (i) printf(", "); \
350 (print_elem_)(&(obj_)[i], i); \
351 } \
352 printf("]"); \
353 for (i = 0; i < depth_; ++i) \
354 printf("}")); \
355 } while (0)
356
357 #define TEST_NESTED_NLATTR_ARRAY(fd_, nlh0_, hdrlen_, \
358 init_msg_, print_msg_, \
359 nla_type_, pattern_, obj_, print_elem_)\
360 TEST_NESTED_NLATTR_ARRAY_EX((fd_), (nlh0_), (hdrlen_), \
361 (init_msg_), (print_msg_), \
362 nla_type_, (pattern_), (obj_), 1, \
363 (print_elem_))
364