]> granicus.if.org Git - strace/blob - tests/netlink_sock_diag.c
tests: extend TEST_NETLINK_OBJECT macro
[strace] / tests / netlink_sock_diag.c
1 /*
2  * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4  * Copyright (c) 2017 The strace developers.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "tests.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <unistd.h>
35 #include <sys/socket.h>
36 #include <arpa/inet.h>
37 #include <netinet/tcp.h>
38 #include "test_netlink.h"
39 #include <linux/if_ether.h>
40 #include <linux/inet_diag.h>
41 #include <linux/netlink_diag.h>
42 #include <linux/packet_diag.h>
43 #ifdef AF_SMC
44 # include <linux/smc_diag.h>
45 #endif
46 #include <linux/sock_diag.h>
47 #include <linux/unix_diag.h>
48
49 #define SMC_ACTIVE 1
50
51 #ifdef HAVE_IF_INDEXTONAME
52 /* <linux/if.h> used to conflict with <net/if.h> */
53 extern unsigned int if_nametoindex(const char *);
54 # define IFINDEX_LO     (if_nametoindex("lo"))
55 #else
56 # define IFINDEX_LO     1
57 #endif
58
59 #define TEST_SOCK_DIAG(fd_, nlh0_,                                      \
60                        family_, type_, flags_,                          \
61                        obj_, print_family_, ...)                        \
62                                                                         \
63         do {                                                            \
64                 /* family only */                                       \
65                 uint8_t family = (family_);                             \
66                 TEST_NETLINK_((fd_), (nlh0_),                           \
67                               type_, #type_,                            \
68                               flags_, #flags_,                          \
69                               sizeof(family), &family, sizeof(family),  \
70                               printf("{family=%s}", #family_));         \
71                                                                         \
72                 /* family and string */                                 \
73                 char buf[sizeof(family) + 4];                           \
74                 memcpy(buf, &family, sizeof(family));                   \
75                 memcpy(buf + sizeof(family), "1234", 4);                \
76                 TEST_NETLINK_((fd_), (nlh0_),                           \
77                               type_, #type_,                            \
78                               flags_, #flags_,                          \
79                               sizeof(buf), buf, sizeof(buf),            \
80                               (print_family_);                          \
81                               printf(", ...}"));                        \
82                                                                         \
83                 /* sizeof(obj_) */                                      \
84                 TEST_NETLINK_((fd_), (nlh0_),                           \
85                               type_, #type_,                            \
86                               flags_, #flags_,                          \
87                               sizeof(obj_), &(obj_), sizeof(obj_),      \
88                               (print_family_);                          \
89                               __VA_ARGS__);                             \
90                                                                         \
91                 /* short read of sizeof(obj_) */                        \
92                 TEST_NETLINK_((fd_), (nlh0_),                           \
93                               type_, #type_,                            \
94                               flags_, #flags_,                          \
95                               sizeof(obj_), &(obj_), sizeof(obj_) - 1,  \
96                               (print_family_);                          \
97                               printf(", %p}",                           \
98                                      NLMSG_DATA(TEST_NETLINK_nlh) + 1));\
99         } while (0)
100
101 static void
102 test_nlmsg_type(const int fd)
103 {
104         long rc;
105         struct nlmsghdr nlh = {
106                 .nlmsg_len = sizeof(nlh),
107                 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
108                 .nlmsg_flags = NLM_F_REQUEST,
109         };
110
111         rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
112         printf("sendto(%d, {len=%u, type=SOCK_DIAG_BY_FAMILY"
113                ", flags=NLM_F_REQUEST, seq=0, pid=0}"
114                ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
115                fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
116 }
117
118 static void
119 test_nlmsg_flags(const int fd)
120 {
121         long rc;
122         struct nlmsghdr nlh = {
123                 .nlmsg_len = sizeof(nlh),
124                 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
125                 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
126         };
127
128         rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
129         printf("sendto(%d, {len=%u, type=SOCK_DIAG_BY_FAMILY"
130                ", flags=NLM_F_REQUEST|NLM_F_DUMP, seq=0, pid=0}"
131                ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
132                fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
133 }
134
135 static void
136 test_odd_family_req(const int fd)
137 {
138         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
139
140         /* unspecified family only */
141         uint8_t family = 0;
142         TEST_NETLINK(fd, nlh0,
143                      SOCK_DIAG_BY_FAMILY,
144                      NLM_F_REQUEST,
145                      sizeof(family), &family, sizeof(family),
146                      printf("{family=AF_UNSPEC}"));
147
148         /* unknown family only */
149         family = 0xff;
150         TEST_NETLINK(fd, nlh0,
151                      SOCK_DIAG_BY_FAMILY,
152                      NLM_F_REQUEST,
153                      sizeof(family), &family, sizeof(family),
154                      printf("{family=%#x /* AF_??? */}", family));
155
156         /* short read of family */
157         TEST_NETLINK(fd, nlh0,
158                      SOCK_DIAG_BY_FAMILY,
159                      NLM_F_REQUEST,
160                      sizeof(family), &family, sizeof(family) - 1,
161                      printf("%p", NLMSG_DATA(TEST_NETLINK_nlh)));
162
163         /* unspecified family and string */
164         char buf[sizeof(family) + 4];
165         family = 0;
166         memcpy(buf, &family, sizeof(family));
167         memcpy(buf + sizeof(family), "1234", 4);
168         TEST_NETLINK(fd, nlh0,
169                      SOCK_DIAG_BY_FAMILY,
170                      NLM_F_REQUEST,
171                      sizeof(buf), buf, sizeof(buf),
172                      printf("{family=AF_UNSPEC, \"\\x31\\x32\\x33\\x34\"}"));
173
174         /* unknown family and string */
175         family = 0xfd;
176         memcpy(buf, &family, sizeof(family));
177         TEST_NETLINK(fd, nlh0,
178                      SOCK_DIAG_BY_FAMILY,
179                      NLM_F_REQUEST,
180                      sizeof(buf), buf, sizeof(buf),
181                      printf("{family=%#x /* AF_??? */"
182                             ", \"\\x31\\x32\\x33\\x34\"}", family));
183 }
184
185 static void
186 test_odd_family_msg(const int fd)
187 {
188         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
189
190         /* unspecified family only */
191         uint8_t family = 0;
192         TEST_NETLINK(fd, nlh0,
193                      SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
194                      sizeof(family), &family, sizeof(family),
195                      printf("{family=AF_UNSPEC}"));
196
197         /* unknown family only */
198         family = 0xff;
199         TEST_NETLINK(fd, nlh0,
200                      SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
201                      sizeof(family), &family, sizeof(family),
202                      printf("{family=%#x /* AF_??? */}", family));
203
204         /* short read of family */
205         TEST_NETLINK(fd, nlh0,
206                      SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
207                      sizeof(family), &family, sizeof(family) - 1,
208                      printf("%p", NLMSG_DATA(TEST_NETLINK_nlh)));
209
210         /* unspecified family and string */
211         char buf[sizeof(family) + 4];
212         family = 0;
213         memcpy(buf, &family, sizeof(family));
214         memcpy(buf + sizeof(family), "1234", 4);
215         TEST_NETLINK(fd, nlh0,
216                      SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
217                      sizeof(buf), buf, sizeof(buf),
218                      printf("{family=AF_UNSPEC, \"\\x31\\x32\\x33\\x34\"}"));
219
220         /* unknown family and string */
221         family = 0xfd;
222         memcpy(buf, &family, sizeof(family));
223         TEST_NETLINK(fd, nlh0,
224                      SOCK_DIAG_BY_FAMILY, NLM_F_DUMP,
225                      sizeof(buf), buf, sizeof(buf),
226                      printf("{family=%#x /* AF_??? */"
227                             ", \"\\x31\\x32\\x33\\x34\"}", family));
228 }
229
230 static void
231 test_unix_diag_req(const int fd)
232 {
233         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
234         static const struct unix_diag_req req = {
235                 .sdiag_family = AF_UNIX,
236                 .sdiag_protocol = 253,
237                 .udiag_states = 1 << TCP_ESTABLISHED | 1 << TCP_LISTEN,
238                 .udiag_ino = 0xfacefeed,
239                 .udiag_show = UDIAG_SHOW_NAME,
240                 .udiag_cookie = { 0xdeadbeef, 0xbadc0ded }
241         };
242         TEST_SOCK_DIAG(fd, nlh0, AF_UNIX,
243                        SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
244                        printf("{sdiag_family=AF_UNIX"),
245                        PRINT_FIELD_U(", ", req, sdiag_protocol);
246                        printf(", udiag_states=1<<TCP_ESTABLISHED|1<<TCP_LISTEN");
247                        PRINT_FIELD_U(", ", req, udiag_ino);
248                        printf(", udiag_show=UDIAG_SHOW_NAME");
249                        PRINT_FIELD_COOKIE(", ", req, udiag_cookie);
250                        printf("}"));
251 }
252
253 static void
254 test_unix_diag_msg(const int fd)
255 {
256         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
257         static const struct unix_diag_msg msg = {
258                 .udiag_family = AF_UNIX,
259                 .udiag_type = SOCK_STREAM,
260                 .udiag_state = TCP_FIN_WAIT1,
261                 .udiag_ino = 0xfacefeed,
262                 .udiag_cookie = { 0xdeadbeef, 0xbadc0ded }
263         };
264         TEST_SOCK_DIAG(fd, nlh0, AF_UNIX,
265                        SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
266                        printf("{udiag_family=AF_UNIX"),
267                        printf(", udiag_type=SOCK_STREAM"
268                               ", udiag_state=TCP_FIN_WAIT1");
269                        PRINT_FIELD_U(", ", msg, udiag_ino);
270                        PRINT_FIELD_COOKIE(", ", msg, udiag_cookie);
271                        printf("}"));
272 }
273
274 static void
275 test_netlink_diag_req(const int fd)
276 {
277         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
278         struct netlink_diag_req req = {
279                 .sdiag_family = AF_NETLINK,
280                 .sdiag_protocol = NDIAG_PROTO_ALL,
281                 .ndiag_ino = 0xfacefeed,
282                 .ndiag_show = NDIAG_SHOW_MEMINFO,
283                 .ndiag_cookie = { 0xdeadbeef, 0xbadc0ded }
284         };
285         TEST_SOCK_DIAG(fd, nlh0, AF_NETLINK,
286                        SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
287                        printf("{sdiag_family=AF_NETLINK"),
288                        printf(", sdiag_protocol=NDIAG_PROTO_ALL");
289                        PRINT_FIELD_U(", ", req, ndiag_ino);
290                        printf(", ndiag_show=NDIAG_SHOW_MEMINFO");
291                        PRINT_FIELD_COOKIE(", ", req, ndiag_cookie);
292                        printf("}"));
293
294         req.sdiag_protocol = NETLINK_ROUTE;
295         req.ndiag_show = NDIAG_SHOW_GROUPS;
296         TEST_SOCK_DIAG(fd, nlh0, AF_NETLINK,
297                        SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
298                        printf("{sdiag_family=AF_NETLINK"),
299                        printf(", sdiag_protocol=NETLINK_ROUTE");
300                        PRINT_FIELD_U(", ", req, ndiag_ino);
301                        printf(", ndiag_show=NDIAG_SHOW_GROUPS");
302                        PRINT_FIELD_COOKIE(", ", req, ndiag_cookie);
303                        printf("}"));
304 }
305
306 static void
307 test_netlink_diag_msg(const int fd)
308 {
309         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
310         static const struct netlink_diag_msg msg = {
311                 .ndiag_family = AF_NETLINK,
312                 .ndiag_type = SOCK_RAW,
313                 .ndiag_protocol = NETLINK_ROUTE,
314                 .ndiag_state = NETLINK_CONNECTED,
315                 .ndiag_portid = 0xbadc0ded,
316                 .ndiag_dst_portid = 0xdeadbeef,
317                 .ndiag_dst_group = 0xfacefeed,
318                 .ndiag_ino = 0xdaeefacd,
319                 .ndiag_cookie = { 0xbadc0ded, 0xdeadbeef }
320         };
321         TEST_SOCK_DIAG(fd, nlh0, AF_NETLINK,
322                        SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
323                        printf("{ndiag_family=AF_NETLINK"),
324                        printf(", ndiag_type=SOCK_RAW"
325                               ", ndiag_protocol=NETLINK_ROUTE"
326                               ", ndiag_state=NETLINK_CONNECTED");
327                        PRINT_FIELD_U(", ", msg, ndiag_portid);
328                        PRINT_FIELD_U(", ", msg, ndiag_dst_portid);
329                        PRINT_FIELD_U(", ", msg, ndiag_dst_group);
330                        PRINT_FIELD_U(", ", msg, ndiag_ino);
331                        PRINT_FIELD_COOKIE(", ", msg, ndiag_cookie);
332                        printf("}"));
333 }
334
335 static void
336 test_packet_diag_req(const int fd)
337 {
338         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
339         static const struct packet_diag_req req = {
340                 .sdiag_family = AF_PACKET,
341                 .sdiag_protocol = ETH_P_LOOP,
342                 .pdiag_ino = 0xfacefeed,
343                 .pdiag_show = PACKET_SHOW_INFO,
344                 .pdiag_cookie = { 0xdeadbeef, 0xbadc0ded }
345         };
346         TEST_SOCK_DIAG(fd, nlh0, AF_PACKET,
347                        SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
348                        printf("{sdiag_family=AF_PACKET"),
349                        printf(", sdiag_protocol=ETH_P_LOOP");
350                        PRINT_FIELD_U(", ", req, pdiag_ino);
351                        printf(", pdiag_show=PACKET_SHOW_INFO");
352                        PRINT_FIELD_COOKIE(", ", req, pdiag_cookie);
353                        printf("}"));
354 }
355
356 static void
357 test_packet_diag_msg(const int fd)
358 {
359         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
360         static const struct packet_diag_msg msg = {
361                 .pdiag_family = AF_PACKET,
362                 .pdiag_type = SOCK_STREAM,
363                 .pdiag_num = 0xbadc,
364                 .pdiag_ino = 0xfacefeed,
365                 .pdiag_cookie = { 0xdeadbeef, 0xbadc0ded }
366         };
367         TEST_SOCK_DIAG(fd, nlh0, AF_PACKET,
368                        SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
369                        printf("{pdiag_family=AF_PACKET"),
370                        printf(", pdiag_type=SOCK_STREAM");
371                        PRINT_FIELD_U(", ", msg, pdiag_num);
372                        PRINT_FIELD_U(", ", msg, pdiag_ino);
373                        PRINT_FIELD_COOKIE(", ", msg, pdiag_cookie);
374                        printf("}"));
375 }
376
377 static void
378 test_inet_diag_sockid(const int fd)
379 {
380         const char address[] = "12.34.56.78";
381         const char address6[] = "12:34:56:78:90:ab:cd:ef";
382         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
383         struct inet_diag_req_v2 req = {
384                 .sdiag_family = AF_INET,
385                 .idiag_ext = 1 << (INET_DIAG_CONG - 1),
386                 .sdiag_protocol = IPPROTO_TCP,
387                 .idiag_states = 1 << TCP_CLOSE,
388                 .id = {
389                         .idiag_sport = 0xfacd,
390                         .idiag_dport = 0xdead,
391                         .idiag_if = IFINDEX_LO,
392                         .idiag_cookie = { 0xdeadbeef, 0xbadc0ded }
393                 },
394         };
395
396         if (!inet_pton(AF_INET, address, &req.id.idiag_src) ||
397             !inet_pton(AF_INET, address, &req.id.idiag_dst))
398                 perror_msg_and_skip("inet_pton");
399
400         TEST_NETLINK(fd, nlh0,
401                      SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST,
402                      sizeof(req), &req, sizeof(req),
403                      printf("{sdiag_family=AF_INET"),
404                      printf(", sdiag_protocol=IPPROTO_TCP"
405                             ", idiag_ext=1<<(INET_DIAG_CONG-1)"
406                             ", idiag_states=1<<TCP_CLOSE"
407                             ", id={idiag_sport=htons(%u)"
408                             ", idiag_dport=htons(%u)"
409                             ", idiag_src=inet_addr(\"%s\")"
410                             ", idiag_dst=inet_addr(\"%s\")",
411                             ntohs(req.id.idiag_sport),
412                             ntohs(req.id.idiag_dport),
413                             address, address);
414                      printf(", idiag_if=if_nametoindex(\"lo\")");
415                      PRINT_FIELD_COOKIE(", ", req.id, idiag_cookie);
416                      printf("}}"));
417
418         req.sdiag_family = AF_INET6;
419         if (!inet_pton(AF_INET6, address6, &req.id.idiag_src) ||
420             !inet_pton(AF_INET6, address6, &req.id.idiag_dst))
421                 perror_msg_and_skip("inet_pton");
422
423         TEST_NETLINK(fd, nlh0,
424                      SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST,
425                      sizeof(req), &req, sizeof(req),
426                      printf("{sdiag_family=AF_INET6"),
427                      printf(", sdiag_protocol=IPPROTO_TCP"
428                             ", idiag_ext=1<<(INET_DIAG_CONG-1)"
429                             ", idiag_states=1<<TCP_CLOSE"
430                             ", id={idiag_sport=htons(%u)"
431                             ", idiag_dport=htons(%u)"
432                             ", inet_pton(AF_INET6, \"%s\", &idiag_src)"
433                             ", inet_pton(AF_INET6, \"%s\", &idiag_dst)",
434                             ntohs(req.id.idiag_sport),
435                             ntohs(req.id.idiag_dport),
436                             address6, address6);
437                      printf(", idiag_if=if_nametoindex(\"lo\")");
438                      PRINT_FIELD_COOKIE(", ", req.id, idiag_cookie);
439                      printf("}}"));
440 }
441
442 static void
443 test_inet_diag_req(const int fd)
444 {
445         const char address[] = "12.34.56.78";
446         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
447         struct inet_diag_req req = {
448                 .idiag_family = AF_INET,
449                 .idiag_src_len = 0xde,
450                 .idiag_dst_len = 0xba,
451                 .idiag_ext = 1 << (INET_DIAG_TOS - 1),
452                 .id = {
453                         .idiag_sport = 0xdead,
454                         .idiag_dport = 0xadcd,
455                         .idiag_if = IFINDEX_LO,
456                         .idiag_cookie = { 0xdeadbeef, 0xbadc0ded }
457                 },
458                 .idiag_states = 1 << TCP_LAST_ACK,
459                 .idiag_dbs = 0xfacefeed,
460         };
461
462         if (!inet_pton(AF_INET, address, &req.id.idiag_src) ||
463             !inet_pton(AF_INET, address, &req.id.idiag_dst))
464                 perror_msg_and_skip("inet_pton");
465
466         TEST_SOCK_DIAG(fd, nlh0, AF_INET,
467                        TCPDIAG_GETSOCK, NLM_F_REQUEST, req,
468                        printf("{idiag_family=AF_INET"),
469                        PRINT_FIELD_U(", ", req, idiag_src_len);
470                        PRINT_FIELD_U(", ", req, idiag_dst_len);
471                        printf(", idiag_ext=1<<(INET_DIAG_TOS-1)");
472                        printf(", id={idiag_sport=htons(%u)"
473                               ", idiag_dport=htons(%u)"
474                               ", idiag_src=inet_addr(\"%s\")"
475                               ", idiag_dst=inet_addr(\"%s\")",
476                               ntohs(req.id.idiag_sport),
477                               ntohs(req.id.idiag_dport),
478                               address, address);
479                        printf(", idiag_if=if_nametoindex(\"lo\")");
480                        PRINT_FIELD_COOKIE(", ", req.id, idiag_cookie);
481                        printf("}, idiag_states=1<<TCP_LAST_ACK");
482                        PRINT_FIELD_U(", ", req, idiag_dbs);
483                        printf("}"));
484 }
485
486 static void
487 test_inet_diag_req_v2(const int fd)
488 {
489         const char address[] = "87.65.43.21";
490         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
491         struct inet_diag_req_v2 req = {
492                 .sdiag_family = AF_INET,
493                 .idiag_ext = 1 << (INET_DIAG_CONG - 1),
494                 .sdiag_protocol = IPPROTO_TCP,
495                 .idiag_states = 1 << TCP_CLOSE,
496                 .id = {
497                         .idiag_sport = 0xfacd,
498                         .idiag_dport = 0xdead,
499                         .idiag_if = IFINDEX_LO,
500                         .idiag_cookie = { 0xdeadbeef, 0xbadc0ded }
501                 },
502         };
503
504         if (!inet_pton(AF_INET, address, &req.id.idiag_src) ||
505             !inet_pton(AF_INET, address, &req.id.idiag_dst))
506                 perror_msg_and_skip("inet_pton");
507
508         TEST_SOCK_DIAG(fd, nlh0, AF_INET,
509                        SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
510                        printf("{sdiag_family=AF_INET"),
511                        printf(", sdiag_protocol=IPPROTO_TCP"
512                               ", idiag_ext=1<<(INET_DIAG_CONG-1)"
513                               ", idiag_states=1<<TCP_CLOSE"
514                               ", id={idiag_sport=htons(%u)"
515                               ", idiag_dport=htons(%u)"
516                               ", idiag_src=inet_addr(\"%s\")"
517                               ", idiag_dst=inet_addr(\"%s\")",
518                               ntohs(req.id.idiag_sport),
519                               ntohs(req.id.idiag_dport),
520                               address, address);
521                        printf(", idiag_if=if_nametoindex(\"lo\")");
522                        PRINT_FIELD_COOKIE(", ", req.id, idiag_cookie);
523                        printf("}}"));
524 }
525
526 static void
527 test_inet_diag_msg(const int fd)
528 {
529         const char address[] = "11.22.33.44";
530         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
531         struct inet_diag_msg msg = {
532                 .idiag_family = AF_INET,
533                 .idiag_state = TCP_LISTEN,
534                 .idiag_timer = 0xfa,
535                 .idiag_retrans = 0xde,
536                 .id = {
537                         .idiag_sport = 0xfacf,
538                         .idiag_dport = 0xdead,
539                         .idiag_if = IFINDEX_LO,
540                         .idiag_cookie = { 0xdeadbeef, 0xbadc0ded }
541                 },
542                 .idiag_expires = 0xfacefeed,
543                 .idiag_rqueue = 0xdeadbeef,
544                 .idiag_wqueue = 0xadcdfafc,
545                 .idiag_uid = 0xdecefaeb,
546                 .idiag_inode = 0xbadc0ded,
547         };
548
549         if (!inet_pton(AF_INET, address, &msg.id.idiag_src) ||
550             !inet_pton(AF_INET, address, &msg.id.idiag_dst))
551                 perror_msg_and_skip("inet_pton");
552
553         TEST_SOCK_DIAG(fd, nlh0, AF_INET,
554                        SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
555                        printf("{idiag_family=AF_INET"),
556                        printf(", idiag_state=TCP_LISTEN");
557                        PRINT_FIELD_U(", ", msg, idiag_timer);
558                        PRINT_FIELD_U(", ", msg, idiag_retrans);
559                        printf(", id={idiag_sport=htons(%u)"
560                               ", idiag_dport=htons(%u)"
561                               ", idiag_src=inet_addr(\"%s\")"
562                               ", idiag_dst=inet_addr(\"%s\")",
563                               ntohs(msg.id.idiag_sport),
564                               ntohs(msg.id.idiag_dport),
565                               address, address);
566                        printf(", idiag_if=if_nametoindex(\"lo\")");
567                        PRINT_FIELD_COOKIE(", ", msg.id, idiag_cookie);
568                        PRINT_FIELD_U("}, ", msg, idiag_expires);
569                        PRINT_FIELD_U(", ", msg, idiag_rqueue);
570                        PRINT_FIELD_U(", ", msg, idiag_wqueue);
571                        PRINT_FIELD_U(", ", msg, idiag_uid);
572                        PRINT_FIELD_U(", ", msg, idiag_inode);
573                        printf("}"));
574 }
575
576 #ifdef AF_SMC
577 static void
578 test_smc_diag_req(const int fd)
579 {
580         const char address[] = "43.21.56.78";
581         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
582         struct smc_diag_req req = {
583                 .diag_family = AF_SMC,
584                 .diag_ext = 1 << (SMC_DIAG_CONNINFO - 1),
585                 .id = {
586                         .idiag_sport = 0xdead,
587                         .idiag_dport = 0xadcd,
588                         .idiag_if = IFINDEX_LO,
589                         .idiag_cookie = { 0xdeadbeef, 0xbadc0ded },
590                 },
591         };
592
593         if (!inet_pton(AF_INET, address, &req.id.idiag_src) ||
594             !inet_pton(AF_INET, address, &req.id.idiag_dst))
595                 perror_msg_and_skip("inet_pton");
596
597         TEST_SOCK_DIAG(fd, nlh0, AF_SMC,
598                        SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST, req,
599                        printf("{diag_family=AF_SMC"),
600                        printf(", diag_ext=1<<(SMC_DIAG_CONNINFO-1)");
601                        printf(", id={idiag_sport=htons(%u)"
602                               ", idiag_dport=htons(%u)"
603                               ", idiag_src=inet_addr(\"%s\")"
604                               ", idiag_dst=inet_addr(\"%s\")",
605                               ntohs(req.id.idiag_sport),
606                               ntohs(req.id.idiag_dport),
607                               address, address);
608                        printf(", idiag_if=if_nametoindex(\"lo\")");
609                        PRINT_FIELD_COOKIE(", ", req.id, idiag_cookie);
610                        printf("}}"));
611 }
612
613 static void
614 test_smc_diag_msg(const int fd)
615 {
616         const char address[] = "34.87.12.90";
617         void *const nlh0 = tail_alloc(NLMSG_HDRLEN);
618         struct smc_diag_msg msg = {
619                 .diag_family = AF_SMC,
620                 .diag_state = SMC_ACTIVE,
621                 .diag_fallback = 0xde,
622                 .diag_shutdown = 0xba,
623                 .id = {
624                         .idiag_sport = 0xdead,
625                         .idiag_dport = 0xadcd,
626                         .idiag_if = IFINDEX_LO,
627                         .idiag_cookie = { 0xdeadbeef, 0xbadc0ded },
628                 },
629                 .diag_uid = 0xadcdfafc,
630                 .diag_inode = 0xbadc0ded,
631         };
632
633         if (!inet_pton(AF_INET, address, &msg.id.idiag_src) ||
634             !inet_pton(AF_INET, address, &msg.id.idiag_dst))
635                 perror_msg_and_skip("inet_pton");
636
637         TEST_SOCK_DIAG(fd, nlh0, AF_SMC,
638                        SOCK_DIAG_BY_FAMILY, NLM_F_DUMP, msg,
639                        printf("{diag_family=AF_SMC"),
640                        printf(", diag_state=SMC_ACTIVE");
641                        PRINT_FIELD_U(", ", msg, diag_fallback);
642                        PRINT_FIELD_U(", ", msg, diag_shutdown);
643                        printf(", id={idiag_sport=htons(%u)"
644                               ", idiag_dport=htons(%u)"
645                               ", idiag_src=inet_addr(\"%s\")"
646                               ", idiag_dst=inet_addr(\"%s\")",
647                               ntohs(msg.id.idiag_sport),
648                               ntohs(msg.id.idiag_dport),
649                               address, address);
650                        printf(", idiag_if=if_nametoindex(\"lo\")");
651                        PRINT_FIELD_COOKIE(", ", msg.id, idiag_cookie);
652                        PRINT_FIELD_U("}, ", msg, diag_uid);
653                        PRINT_FIELD_U(", ", msg, diag_inode);
654                        printf("}"));
655 }
656 #endif
657
658 int
659 main(void)
660 {
661         skip_if_unavailable("/proc/self/fd/");
662
663         int fd = create_nl_socket(NETLINK_SOCK_DIAG);
664
665         test_nlmsg_type(fd);
666         test_nlmsg_flags(fd);
667         test_odd_family_req(fd);
668         test_odd_family_msg(fd);
669         test_unix_diag_req(fd);
670         test_unix_diag_msg(fd);
671         test_netlink_diag_req(fd);
672         test_netlink_diag_msg(fd);
673         test_packet_diag_req(fd);
674         test_packet_diag_msg(fd);
675         test_inet_diag_sockid(fd);
676         test_inet_diag_req(fd);
677         test_inet_diag_req_v2(fd);
678         test_inet_diag_msg(fd);
679 #ifdef AF_SMC
680         test_smc_diag_req(fd);
681         test_smc_diag_msg(fd);
682 #endif
683
684         printf("+++ exited with 0 +++\n");
685
686         return 0;
687 }