]> granicus.if.org Git - strace/blob - tests/nlattr_inet_diag_req_v2.c
strace: terminate itself if interrupted by a signal
[strace] / tests / nlattr_inet_diag_req_v2.c
1 /*
2  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
3  * Copyright (c) 2017-2018 The strace developers.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8
9 #include "tests.h"
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <sys/socket.h>
14 #include <arpa/inet.h>
15 #include <net/if.h>
16 #include <netinet/tcp.h>
17 #include "test_nlattr.h"
18 #include <linux/inet_diag.h>
19 #include <linux/rtnetlink.h>
20 #include <linux/sock_diag.h>
21
22 static const char address[] = "10.11.12.13";
23 static const unsigned int hdrlen = sizeof(struct inet_diag_req_v2);
24 static void *nlh0;
25 static char pattern[4096];
26
27 static void
28 init_inet_diag_req_v2(struct nlmsghdr *const nlh, const unsigned int msg_len)
29 {
30         SET_STRUCT(struct nlmsghdr, nlh,
31                 .nlmsg_len = msg_len,
32                 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
33                 .nlmsg_flags = NLM_F_REQUEST
34         );
35
36         struct inet_diag_req_v2 *const req = NLMSG_DATA(nlh);
37         SET_STRUCT(struct inet_diag_req_v2, req,
38                 .sdiag_family = AF_INET,
39                 .idiag_ext = 1 << (INET_DIAG_CONG - 1),
40                 .sdiag_protocol = IPPROTO_TCP,
41                 .idiag_states = 1 << TCP_CLOSE,
42                 .id.idiag_if = ifindex_lo()
43         );
44
45         if (!inet_pton(AF_INET, address, req->id.idiag_src) ||
46             !inet_pton(AF_INET, address, req->id.idiag_dst))
47                 perror_msg_and_skip("inet_pton");
48 }
49
50 static void
51 print_inet_diag_req_v2(const unsigned int msg_len)
52 {
53         printf("{len=%u, type=SOCK_DIAG_BY_FAMILY"
54                ", flags=NLM_F_REQUEST, seq=0, pid=0}"
55                ", {sdiag_family=AF_INET, sdiag_protocol=IPPROTO_TCP"
56                ", idiag_ext=1<<(INET_DIAG_CONG-1)"
57                ", idiag_states=1<<TCP_CLOSE"
58                ", id={idiag_sport=htons(0), idiag_dport=htons(0)"
59                ", idiag_src=inet_addr(\"%s\")"
60                ", idiag_dst=inet_addr(\"%s\")"
61                ", idiag_if=" IFINDEX_LO_STR
62                ", idiag_cookie=[0, 0]}}",
63                msg_len, address, address);
64 }
65
66 static void
67 test_inet_diag_bc_op(const int fd)
68 {
69         static const struct inet_diag_bc_op op = {
70                 .code = INET_DIAG_BC_S_COND,
71                 .yes = 0xaf,
72                 .no = 0xafcd
73         };
74         TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
75                            init_inet_diag_req_v2, print_inet_diag_req_v2,
76                            INET_DIAG_REQ_BYTECODE, pattern, op,
77                            printf("{code=INET_DIAG_BC_S_COND");
78                            PRINT_FIELD_U(", ", op, yes);
79                            PRINT_FIELD_U(", ", op, no);
80                            printf("}"));
81 }
82
83 static void
84 print_inet_diag_bc_op(const char *const code)
85 {
86         printf("{{code=%s, yes=0, no=0}, ", code);
87 }
88
89 static void
90 test_inet_diag_bc_s_cond(const int fd)
91 {
92         static const struct inet_diag_bc_op op = {
93                 .code = INET_DIAG_BC_S_COND,
94         };
95         static const struct inet_diag_hostcond cond = {
96                 .family = AF_UNSPEC,
97                 .prefix_len = 0xad,
98                 .port = 0xadfa
99         };
100         char buf[sizeof(op) + sizeof(cond)];
101         memcpy(buf, &op, sizeof(op));
102
103         const unsigned int plen = sizeof(cond) - 1 > DEFAULT_STRLEN ?
104                 sizeof(op) + DEFAULT_STRLEN : sizeof(buf) - 1;
105         memcpy(buf + sizeof(op), &pattern, sizeof(cond));
106         TEST_NLATTR(fd, nlh0, hdrlen,
107                     init_inet_diag_req_v2, print_inet_diag_req_v2,
108                     INET_DIAG_REQ_BYTECODE,
109                     plen, buf, plen,
110                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
111                     print_quoted_hex(buf + sizeof(op), plen - sizeof(op));
112                     printf("}"));
113
114         TEST_NLATTR(fd, nlh0, hdrlen,
115                     init_inet_diag_req_v2, print_inet_diag_req_v2,
116                     INET_DIAG_REQ_BYTECODE,
117                     sizeof(buf), buf, sizeof(buf) - 1,
118                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
119                     printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op)));
120
121         memcpy(buf + sizeof(op), &cond, sizeof(cond));
122         TEST_NLATTR(fd, nlh0, hdrlen,
123                     init_inet_diag_req_v2, print_inet_diag_req_v2,
124                     INET_DIAG_REQ_BYTECODE,
125                     sizeof(buf), buf, sizeof(buf),
126                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
127                     printf("{family=AF_UNSPEC");
128                     PRINT_FIELD_U(", ", cond, prefix_len);
129                     PRINT_FIELD_U(", ", cond, port);
130                     printf("}}"));
131 }
132
133 static void
134 print_inet_diag_hostcond(const char *const family)
135 {
136         printf("{family=%s, prefix_len=0, port=0, ", family);
137 }
138
139 static void
140 test_in_addr(const int fd)
141 {
142         static const struct inet_diag_bc_op op = {
143                 .code = INET_DIAG_BC_S_COND,
144         };
145         static const struct inet_diag_hostcond cond = {
146                 .family = AF_INET,
147         };
148         struct in_addr addr;
149         if (!inet_pton(AF_INET, address, &addr))
150                 perror_msg_and_skip("inet_pton");
151
152         char buf[sizeof(op) + sizeof(cond) + sizeof(addr)];
153         memcpy(buf, &op, sizeof(op));
154         memcpy(buf + sizeof(op), &cond, sizeof(cond));
155
156         const unsigned int plen = sizeof(addr) - 1 > DEFAULT_STRLEN ?
157                 sizeof(cond) + sizeof(cond) + DEFAULT_STRLEN : sizeof(buf) - 1;
158         memcpy(buf + sizeof(op) + sizeof(cond), &pattern, sizeof(addr));
159         TEST_NLATTR(fd, nlh0, hdrlen,
160                     init_inet_diag_req_v2, print_inet_diag_req_v2,
161                     INET_DIAG_REQ_BYTECODE,
162                     plen, buf, plen,
163                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
164                     print_inet_diag_hostcond("AF_INET");
165                     printf("addr=");
166                     print_quoted_hex(pattern, plen - sizeof(op) - sizeof(cond));
167                     printf("}}"));
168
169         TEST_NLATTR(fd, nlh0, hdrlen,
170                     init_inet_diag_req_v2, print_inet_diag_req_v2,
171                     INET_DIAG_REQ_BYTECODE,
172                     sizeof(buf), buf, sizeof(buf) - 1,
173                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
174                     print_inet_diag_hostcond("AF_INET");
175                     printf("addr=%p}}",
176                            RTA_DATA(TEST_NLATTR_nla)
177                            + sizeof(op) + sizeof(cond)));
178
179         memcpy(buf + sizeof(op) + sizeof(cond), &addr, sizeof(addr));
180         TEST_NLATTR(fd, nlh0, hdrlen,
181                     init_inet_diag_req_v2, print_inet_diag_req_v2,
182                     INET_DIAG_REQ_BYTECODE,
183                     sizeof(buf), buf, sizeof(buf),
184                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
185                     print_inet_diag_hostcond("AF_INET");
186                     printf("addr=inet_addr(\"%s\")}}", address));
187 }
188
189 static void
190 test_in6_addr(const int fd)
191 {
192         const char address6[] = "12:34:56:78:90:ab:cd:ef";
193         static const struct inet_diag_bc_op op = {
194                 .code = INET_DIAG_BC_S_COND,
195         };
196         static const struct inet_diag_hostcond cond = {
197                 .family = AF_INET6,
198         };
199         struct in6_addr addr;
200         if (!inet_pton(AF_INET6, address6, &addr))
201                 perror_msg_and_skip("inet_pton");
202
203         char buf[sizeof(op) + sizeof(cond) + sizeof(addr)];
204         memcpy(buf, &op, sizeof(op));
205         memcpy(buf + sizeof(op), &cond, sizeof(cond));
206
207         const unsigned int plen = sizeof(addr) - 1 > DEFAULT_STRLEN ?
208                 sizeof(cond) + sizeof(cond) + DEFAULT_STRLEN : sizeof(buf) - 1;
209         memcpy(buf + sizeof(op) + sizeof(cond), &pattern, sizeof(addr));
210         TEST_NLATTR(fd, nlh0, hdrlen,
211                     init_inet_diag_req_v2, print_inet_diag_req_v2,
212                     INET_DIAG_REQ_BYTECODE,
213                     plen, buf, plen,
214                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
215                     print_inet_diag_hostcond("AF_INET6");
216                     printf("addr=");
217                     print_quoted_hex(pattern, plen - sizeof(op) - sizeof(cond));
218                     printf("}}"));
219
220         TEST_NLATTR(fd, nlh0, hdrlen,
221                     init_inet_diag_req_v2, print_inet_diag_req_v2,
222                     INET_DIAG_REQ_BYTECODE,
223                     sizeof(buf), buf, sizeof(buf) - 1,
224                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
225                     print_inet_diag_hostcond("AF_INET6");
226                     printf("addr=%p}}",
227                            RTA_DATA(TEST_NLATTR_nla)
228                            + sizeof(op) + sizeof(cond)));
229
230         memcpy(buf + sizeof(op) + sizeof(cond), &addr, sizeof(addr));
231         TEST_NLATTR(fd, nlh0, hdrlen,
232                     init_inet_diag_req_v2, print_inet_diag_req_v2,
233                     INET_DIAG_REQ_BYTECODE,
234                     sizeof(buf), buf, sizeof(buf),
235                     print_inet_diag_bc_op("INET_DIAG_BC_S_COND");
236                     print_inet_diag_hostcond("AF_INET6");
237                     printf("inet_pton(AF_INET6, \"%s\", &addr)}}", address6));
238 }
239
240 static void
241 test_inet_diag_bc_dev_cond(const int fd)
242 {
243         static const struct inet_diag_bc_op op = {
244                 .code = INET_DIAG_BC_DEV_COND,
245         };
246         const uint32_t ifindex = ifindex_lo();
247         char buf[sizeof(op) + sizeof(ifindex)];
248         memcpy(buf, &op, sizeof(op));
249         memcpy(buf + sizeof(op), pattern, sizeof(ifindex));
250
251         TEST_NLATTR(fd, nlh0, hdrlen,
252                     init_inet_diag_req_v2, print_inet_diag_req_v2,
253                     INET_DIAG_REQ_BYTECODE,
254                     sizeof(buf) - 1, buf, sizeof(buf) - 1,
255                     print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
256                     print_quoted_hex(pattern, sizeof(ifindex) - 1);
257                     printf("}"));
258
259         TEST_NLATTR(fd, nlh0, hdrlen,
260                     init_inet_diag_req_v2, print_inet_diag_req_v2,
261                     INET_DIAG_REQ_BYTECODE,
262                     sizeof(buf), buf, sizeof(buf) - 1,
263                     print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
264                     printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op)));
265
266         memcpy(buf + sizeof(op), &ifindex, sizeof(ifindex));
267         TEST_NLATTR(fd, nlh0, hdrlen,
268                     init_inet_diag_req_v2, print_inet_diag_req_v2,
269                     INET_DIAG_REQ_BYTECODE,
270                     sizeof(buf), buf, sizeof(buf),
271                     print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
272                     printf(IFINDEX_LO_STR "}"));
273 }
274
275 static void
276 test_inet_diag_bc_s_le(const int fd)
277 {
278         static const struct inet_diag_bc_op op[] = {
279                 {
280                         .code = INET_DIAG_BC_S_LE,
281                 },
282                 {
283                         .code = INET_DIAG_BC_DEV_COND,
284                         .yes = 0xaf,
285                         .no = 0xafcd
286                 }
287         };
288
289         char buf[sizeof(op)];
290         memcpy(buf, op, sizeof(op[0]));
291         memcpy(buf + sizeof(op[0]), pattern, sizeof(op[1]));
292
293         const unsigned int plen = sizeof(op[1]) - 1 > DEFAULT_STRLEN ?
294                 sizeof(op[0]) + DEFAULT_STRLEN : sizeof(buf) - 1;
295         TEST_NLATTR(fd, nlh0, hdrlen,
296                     init_inet_diag_req_v2, print_inet_diag_req_v2,
297                     INET_DIAG_REQ_BYTECODE,
298                     plen, buf, plen,
299                     print_inet_diag_bc_op("INET_DIAG_BC_S_LE");
300                     print_quoted_hex(buf + sizeof(op[0]), plen - sizeof(op[0]));
301                     printf("}"));
302
303         TEST_NLATTR(fd, nlh0, hdrlen,
304                     init_inet_diag_req_v2, print_inet_diag_req_v2,
305                     INET_DIAG_REQ_BYTECODE,
306                     sizeof(buf), buf, sizeof(buf) - 1,
307                     print_inet_diag_bc_op("INET_DIAG_BC_S_LE");
308                     printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op[0])));
309
310         memcpy(buf + sizeof(op[0]), &op[1], sizeof(op[1]));
311         TEST_NLATTR(fd, nlh0, hdrlen,
312                     init_inet_diag_req_v2, print_inet_diag_req_v2,
313                     INET_DIAG_REQ_BYTECODE,
314                     sizeof(buf), buf, sizeof(buf),
315                     print_inet_diag_bc_op("INET_DIAG_BC_S_LE");
316                     printf("{code=INET_DIAG_BC_DEV_COND");
317                     PRINT_FIELD_U(", ", op[1], yes);
318                     PRINT_FIELD_U(", ", op[1], no);
319                     printf("}}"));
320 };
321
322 static void
323 test_inet_diag_bc_mark_cond(const int fd)
324 {
325         static const struct inet_diag_bc_op op = {
326                 .code = INET_DIAG_BC_MARK_COND,
327         };
328         static const struct inet_diag_markcond markcond = {
329                 .mark = 0xafbcafcd,
330                 .mask = 0xbafaacda
331         };
332         char buf[sizeof(op) + sizeof(markcond)];
333         memcpy(buf, &op, sizeof(op));
334         memcpy(buf + sizeof(op), pattern, sizeof(markcond));
335
336         const unsigned int plen = sizeof(markcond) - 1 > DEFAULT_STRLEN ?
337                 sizeof(markcond) + DEFAULT_STRLEN : sizeof(buf) - 1;
338         TEST_NLATTR(fd, nlh0, hdrlen,
339                     init_inet_diag_req_v2, print_inet_diag_req_v2,
340                     INET_DIAG_REQ_BYTECODE,
341                     plen, buf, plen,
342                     print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND");
343                     print_quoted_hex(buf + sizeof(op), plen - sizeof(op));
344                     printf("}"));
345
346         TEST_NLATTR(fd, nlh0, hdrlen,
347                     init_inet_diag_req_v2, print_inet_diag_req_v2,
348                     INET_DIAG_REQ_BYTECODE,
349                     sizeof(buf), buf, sizeof(buf) - 1,
350                     print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND");
351                     printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op)));
352
353         memcpy(buf + sizeof(op), &markcond, sizeof(markcond));
354         TEST_NLATTR(fd, nlh0, hdrlen,
355                     init_inet_diag_req_v2, print_inet_diag_req_v2,
356                     INET_DIAG_REQ_BYTECODE,
357                     sizeof(buf), buf, sizeof(buf),
358                     print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND");
359                     PRINT_FIELD_U("{", markcond, mark);
360                     PRINT_FIELD_U(", ", markcond, mask);
361                     printf("}}"));
362 }
363
364 static void
365 test_inet_diag_bc_nop(const int fd)
366 {
367         static const struct inet_diag_bc_op op = {
368                 .code = INET_DIAG_BC_AUTO,
369         };
370         char buf[sizeof(op) + 4];
371         memcpy(buf, &op, sizeof(op));
372         memcpy(buf + sizeof(op), pattern, 4);
373
374         TEST_NLATTR(fd, nlh0, hdrlen,
375                     init_inet_diag_req_v2, print_inet_diag_req_v2,
376                     INET_DIAG_REQ_BYTECODE,
377                     sizeof(buf), buf, sizeof(buf),
378                     print_inet_diag_bc_op("INET_DIAG_BC_AUTO");
379                     print_quoted_hex(buf + sizeof(op),
380                                      sizeof(buf) - sizeof(op));
381                     printf("}"));
382 }
383
384 int
385 main(void)
386 {
387         skip_if_unavailable("/proc/self/fd/");
388
389         int fd = create_nl_socket(NETLINK_SOCK_DIAG);
390         nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN +
391                         sizeof(struct inet_diag_bc_op) +
392                                 sizeof(struct inet_diag_hostcond) +
393                                 sizeof(struct in6_addr) + DEFAULT_STRLEN);
394         fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
395
396         test_inet_diag_bc_op(fd);
397         test_inet_diag_bc_s_cond(fd);
398         test_in_addr(fd);
399         test_in6_addr(fd);
400         test_inet_diag_bc_dev_cond(fd);
401         test_inet_diag_bc_s_le(fd);
402         test_inet_diag_bc_mark_cond(fd);
403         test_inet_diag_bc_nop(fd);
404
405         printf("+++ exited with 0 +++\n");
406         return 0;
407 }