1 /*
2 * Copyright (c) 2017 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)54 print_nlattr(const unsigned int nla_len, const char *const nla_type)
55 {
56 printf(", {{nla_len=%u, nla_type=%s}, ", nla_len, nla_type);
57 }
58
59 #define TEST_NLATTR_(fd_, nlh0_, hdrlen_, \
60 init_msg_, print_msg_, \
61 nla_type_, nla_type_str_, \
62 nla_data_len_, src_, slen_, ...) \
63 do { \
64 struct nlmsghdr *const nlh = \
65 (nlh0_) - (NLA_HDRLEN + (slen_)); \
66 struct nlattr *const TEST_NLATTR_nla = \
67 NLMSG_ATTR(nlh, (hdrlen_)); \
68 const unsigned int nla_len = \
69 NLA_HDRLEN + (nla_data_len_); \
70 const unsigned int msg_len = \
71 NLMSG_SPACE(hdrlen_) + nla_len; \
72 \
73 (init_msg_)(nlh, msg_len); \
74 init_nlattr(TEST_NLATTR_nla, nla_len, (nla_type_), \
75 (src_), (slen_)); \
76 \
77 const char *const errstr = \
78 sprintrc(sendto((fd_), nlh, msg_len, \
79 MSG_DONTWAIT, NULL, 0)); \
80 \
81 printf("sendto(%d, {", (fd_)); \
82 (print_msg_)(msg_len); \
83 print_nlattr(nla_len, (nla_type_str_)); \
84 \
85 { __VA_ARGS__; } \
86 \
87 printf("}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n", \
88 msg_len, errstr); \
89 } while (0)
90
91 #define TEST_NLATTR(fd_, nlh0_, hdrlen_, \
92 init_msg_, print_msg_, \
93 nla_type_, \
94 nla_data_len_, src_, slen_, ...) \
95 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
96 (init_msg_), (print_msg_), \
97 (nla_type_), #nla_type_, \
98 (nla_data_len_), (src_), (slen_), __VA_ARGS__)
99
100 #define TEST_NLATTR_OBJECT_EX_(fd_, nlh0_, hdrlen_, \
101 init_msg_, print_msg_, \
102 nla_type_, nla_type_str_, \
103 pattern_, obj_, fallback_func, ...) \
104 do { \
105 const unsigned int plen = \
106 sizeof(obj_) - 1 > DEFAULT_STRLEN \
107 ? DEFAULT_STRLEN : (int) sizeof(obj_) - 1; \
108 /* len < sizeof(obj_) */ \
109 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
110 (init_msg_), (print_msg_), \
111 (nla_type_), (nla_type_str_), \
112 plen, (pattern_), plen, \
113 (fallback_func)((pattern_), plen)); \
114 /* short read of sizeof(obj_) */ \
115 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
116 (init_msg_), (print_msg_), \
117 (nla_type_), (nla_type_str_), \
118 sizeof(obj_), \
119 (pattern_), sizeof(obj_) - 1, \
120 printf("%p", \
121 RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_))))); \
122 /* sizeof(obj_) */ \
123 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
124 (init_msg_), (print_msg_), \
125 (nla_type_), (nla_type_str_), \
126 sizeof(obj_), \
127 &(obj_), sizeof(obj_), \
128 __VA_ARGS__); \
129 } while (0)
130
131 #define TEST_NLATTR_OBJECT_EX(fd_, nlh0_, hdrlen_, \
132 init_msg_, print_msg_, \
133 nla_type_, \
134 pattern_, obj_, fallback_func, ...) \
135 TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \
136 (init_msg_), (print_msg_), \
137 (nla_type_), #nla_type_, \
138 (pattern_), (obj_), (fallback_func), \
139 __VA_ARGS__)
140
141 #define TEST_NLATTR_OBJECT(fd_, nlh0_, hdrlen_, \
142 init_msg_, print_msg_, \
143 nla_type_, pattern_, obj_, ...) \
144 TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \
145 (init_msg_), (print_msg_), \
146 (nla_type_), #nla_type_, \
147 (pattern_), (obj_), print_quoted_hex, \
148 __VA_ARGS__)
149
150 #define TEST_NLATTR_ARRAY(fd_, nlh0_, hdrlen_, \
151 init_msg_, print_msg_, \
152 nla_type_, pattern_, obj_, print_elem_) \
153 do { \
154 const unsigned int plen = \
155 sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN \
156 ? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1; \
157 /* len < sizeof((obj_)[0]) */ \
158 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
159 (init_msg_), (print_msg_), \
160 (nla_type_), #nla_type_, \
161 plen, (pattern_), plen, \
162 print_quoted_hex((pattern_), plen)); \
163 /* sizeof((obj_)[0]) < len < sizeof(obj_) */ \
164 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
165 (init_msg_), (print_msg_), \
166 (nla_type_), #nla_type_, \
167 sizeof(obj_) - 1, \
168 &(obj_), sizeof(obj_) - 1, \
169 printf("["); \
170 size_t i; \
171 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \
172 if (i) printf(", "); \
173 (print_elem_)(&(obj_)[i]); \
174 } \
175 printf("]")); \
176 /* short read of sizeof(obj_) */ \
177 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
178 (init_msg_), (print_msg_), \
179 (nla_type_), #nla_type_, \
180 sizeof(obj_), \
181 &(obj_), sizeof(obj_) - 1, \
182 printf("["); \
183 size_t i; \
184 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \
185 if (i) printf(", "); \
186 (print_elem_)(&(obj_)[i]); \
187 } \
188 printf(", %p]", \
189 RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_))) \
190 + sizeof((obj_)[0]))); \
191 /* sizeof(obj_) */ \
192 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \
193 (init_msg_), (print_msg_), \
194 (nla_type_), #nla_type_, \
195 sizeof(obj_), \
196 &(obj_), sizeof(obj_), \
197 printf("["); \
198 size_t i; \
199 for (i = 0; i < ARRAY_SIZE(obj_); ++i) { \
200 if (i) printf(", "); \
201 (print_elem_)(&(obj_)[i]); \
202 } \
203 printf("]")); \
204 } while (0)
205
206 #define TEST_NESTED_NLATTR_OBJECT_EX_(fd_, nlh0_, hdrlen_, \
207 init_msg_, print_msg_, \
208 nla_type_, nla_type_str_, \
209 pattern_, obj_, depth_, ...) \
210 do { \
211 const unsigned int plen = \
212 sizeof(obj_) - 1 > DEFAULT_STRLEN \
213 ? DEFAULT_STRLEN : (int) sizeof(obj_) - 1; \
214 /* len < sizeof(obj_) */ \
215 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
216 (hdrlen_) + NLA_HDRLEN * depth_, \
217 (init_msg_), (print_msg_), \
218 (nla_type_), (nla_type_str_), \
219 plen, (pattern_), plen, \
220 print_quoted_hex((pattern_), plen); \
221 size_t i; \
222 for (i = 0; i < depth_; ++i) \
223 printf("}")); \
224 /* short read of sizeof(obj_) */ \
225 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
226 (hdrlen_) + NLA_HDRLEN * depth_, \
227 (init_msg_), (print_msg_), \
228 (nla_type_), (nla_type_str_), \
229 sizeof(obj_), \
230 (pattern_), sizeof(obj_) - 1, \
231 printf("%p", RTA_DATA(TEST_NLATTR_nla)); \
232 size_t i; \
233 for (i = 0; i < depth_; ++i) \
234 printf("}")); \
235 /* sizeof(obj_) */ \
236 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \
237 (hdrlen_) + NLA_HDRLEN * depth_, \
238 (init_msg_), (print_msg_), \
239 (nla_type_), (nla_type_str_), \
240 sizeof(obj_), \
241 &(obj_), sizeof(obj_), \
242 __VA_ARGS__; \
243 size_t i; \
244 for (i = 0; i < depth_; ++i) \
245 printf("}")); \
246 } while (0)
247
248 #define TEST_NESTED_NLATTR_OBJECT_EX(fd_, nlh0_, hdrlen_, \
249 init_msg_, print_msg_, \
250 nla_type_, pattern_, obj_, \
251 depth_, ...) \
252 TEST_NESTED_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \
253 (init_msg_), (print_msg_), \
254 (nla_type_), #nla_type_, \
255 (pattern_), (obj_), (depth_), \
256 __VA_ARGS__)
257
258 #define TEST_NESTED_NLATTR_OBJECT(fd_, nlh0_, hdrlen_, \
259 init_msg_, print_msg_, \
260 nla_type_, pattern_, obj_, ...) \
261 TEST_NESTED_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \
262 (init_msg_), (print_msg_), \
263 (nla_type_), #nla_type_, \
264 (pattern_), (obj_), 1, \
265 __VA_ARGS__)
266
267 #define TEST_NESTED_NLATTR_ARRAY(fd_, nlh0_, hdrlen_, \
268 init_msg_, print_msg_, \
269 nla_type_, pattern_, obj_, print_elem_)\
270 do { \
271 const unsigned int plen = \
272 sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN \
273 ? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1; \
274 /* len < sizeof((obj_)[0]) */ \
275 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN, \
276 (hdrlen_) + NLA_HDRLEN, \
277 (init_msg_), (print_msg_), \
278 (nla_type_), #nla_type_, \
279 plen, (pattern_), plen, \
280 print_quoted_hex((pattern_), plen); \
281 printf("}")); \
282 /* sizeof((obj_)[0]) < len < sizeof(obj_) */ \
283 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN, \
284 (hdrlen_) + NLA_HDRLEN, \
285 (init_msg_), (print_msg_), \
286 (nla_type_), #nla_type_, \
287 sizeof(obj_) - 1, \
288 &(obj_), sizeof(obj_) - 1, \
289 printf("["); \
290 size_t i; \
291 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \
292 if (i) printf(", "); \
293 (print_elem_)(&(obj_)[i]); \
294 } \
295 printf("]}")); \
296 /* short read of sizeof(obj_) */ \
297 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN, \
298 (hdrlen_) + NLA_HDRLEN, \
299 (init_msg_), (print_msg_), \
300 (nla_type_), #nla_type_, \
301 sizeof(obj_), \
302 &(obj_), sizeof(obj_) - 1, \
303 printf("["); \
304 size_t i; \
305 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \
306 if (i) printf(", "); \
307 (print_elem_)(&(obj_)[i]); \
308 } \
309 printf(", %p]}", \
310 RTA_DATA(TEST_NLATTR_nla) \
311 + sizeof((obj_)[0]))); \
312 /* sizeof(obj_) */ \
313 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN, \
314 (hdrlen_) + NLA_HDRLEN, \
315 (init_msg_), (print_msg_), \
316 (nla_type_), #nla_type_, \
317 sizeof(obj_), \
318 &(obj_), sizeof(obj_), \
319 printf("["); \
320 size_t i; \
321 for (i = 0; i < ARRAY_SIZE(obj_); ++i) { \
322 if (i) printf(", "); \
323 (print_elem_)(&(obj_)[i]); \
324 } \
325 printf("]}")); \
326 } while (0)
327