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.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
34 #include <arpa/inet.h>
35 #include <linux/inet_diag.h>
36 #include <linux/netlink_diag.h>
37 #include <linux/packet_diag.h>
39 # include <linux/smc_diag.h>
41 #include <linux/unix_diag.h>
43 #include "xlat/inet_diag_extended_flags.h"
45 #include "xlat/tcp_states.h"
46 #include "xlat/tcp_state_flags.h"
48 #include "xlat/netlink_diag_show.h"
49 #include "xlat/netlink_states.h"
51 #include "xlat/packet_diag_show.h"
54 # include "xlat/smc_diag_extended_flags.h"
55 # include "xlat/smc_states.h"
58 #include "xlat/unix_diag_attrs.h"
59 #include "xlat/unix_diag_show.h"
62 decode_family(struct tcb *const tcp, const uint8_t family,
63 const kernel_ulong_t addr, const kernel_ulong_t len)
66 printxval(addrfams, family, "AF_???");
67 if (len > sizeof(family)) {
69 printstrn(tcp, addr + sizeof(family),
70 len - sizeof(family));
76 decode_unix_diag_req(struct tcb *const tcp,
77 const struct nlmsghdr *const nlmsghdr,
79 const kernel_ulong_t addr,
80 const kernel_ulong_t len)
82 struct unix_diag_req req = { .sdiag_family = family };
83 const size_t offset = sizeof(req.sdiag_family);
85 tprints("{sdiag_family=");
86 printxval(addrfams, req.sdiag_family, "AF_???");
89 if (len >= sizeof(req)) {
90 if (!umoven_or_printaddr(tcp, addr + offset,
92 (void *) &req + offset)) {
93 tprintf("sdiag_protocol=%" PRIu8 ", udiag_states=",
95 printflags(tcp_state_flags, req.udiag_states,
97 tprintf(", udiag_ino=%" PRIu32 ", udiag_show=",
99 printflags(unix_diag_show, req.udiag_show,
101 tprintf(", udiag_cookie=[%" PRIu32 ", %" PRIu32 "]",
102 req.udiag_cookie[0], req.udiag_cookie[1]);
110 decode_unix_diag_msg(struct tcb *const tcp,
111 const struct nlmsghdr *const nlmsghdr,
112 const uint8_t family,
113 const kernel_ulong_t addr,
114 const kernel_ulong_t len)
116 struct unix_diag_msg msg = { .udiag_family = family };
117 size_t offset = sizeof(msg.udiag_family);
118 bool decode_nla = false;
120 tprints("{udiag_family=");
121 printxval(addrfams, msg.udiag_family, "AF_???");
124 if (len >= sizeof(msg)) {
125 if (!umoven_or_printaddr(tcp, addr + offset,
126 sizeof(msg) - offset,
127 (void *) &msg + offset)) {
128 tprints("udiag_type=");
129 printxval(socktypes, msg.udiag_type, "SOCK_???");
130 tprintf(", udiag_state=");
131 printxval(tcp_states, msg.udiag_state, "TCP_???");
132 tprintf(", udiag_ino=%" PRIu32
133 ", udiag_cookie=[%" PRIu32 ", %" PRIu32 "]",
135 msg.udiag_cookie[0], msg.udiag_cookie[1]);
142 offset = NLMSG_ALIGN(sizeof(msg));
143 if (decode_nla && len > offset) {
145 decode_nlattr(tcp, addr + offset, len - offset,
146 unix_diag_attrs, "UNIX_DIAG_???");
151 decode_netlink_diag_req(struct tcb *const tcp,
152 const struct nlmsghdr *const nlmsghdr,
153 const uint8_t family,
154 const kernel_ulong_t addr,
155 const kernel_ulong_t len)
157 struct netlink_diag_req req = { .sdiag_family = family };
158 const size_t offset = sizeof(req.sdiag_family);
160 tprints("{sdiag_family=");
161 printxval(addrfams, req.sdiag_family, "AF_???");
164 if (len >= sizeof(req)) {
165 if (!umoven_or_printaddr(tcp, addr + offset,
166 sizeof(req) - offset,
167 (void *) &req + offset)) {
168 tprints("sdiag_protocol=");
169 if (NDIAG_PROTO_ALL == req.sdiag_protocol)
170 tprints("NDIAG_PROTO_ALL");
172 printxval(netlink_protocols,
173 req.sdiag_protocol, "NETLINK_???");
174 tprintf(", ndiag_ino=%" PRIu32 ", ndiag_show=",
176 printflags(netlink_diag_show, req.ndiag_show,
178 tprintf(", ndiag_cookie=[%" PRIu32 ", %" PRIu32 "]",
179 req.ndiag_cookie[0], req.ndiag_cookie[1]);
187 decode_netlink_diag_msg(struct tcb *const tcp,
188 const struct nlmsghdr *const nlmsghdr,
189 const uint8_t family,
190 const kernel_ulong_t addr,
191 const kernel_ulong_t len)
193 struct netlink_diag_msg msg = { .ndiag_family = family };
194 const size_t offset = sizeof(msg.ndiag_family);
196 tprints("{ndiag_family=");
197 printxval(addrfams, msg.ndiag_family, "AF_???");
200 if (len >= sizeof(msg)) {
201 if (!umoven_or_printaddr(tcp, addr + offset,
202 sizeof(msg) - offset,
203 (void *) &msg + offset)) {
204 tprints("ndiag_type=");
205 printxval(socktypes, msg.ndiag_type, "SOCK_???");
206 tprints(", ndiag_protocol=");
207 printxval(netlink_protocols, msg.ndiag_protocol,
209 tprints(", ndiag_state=");
210 printxval(netlink_states, msg.ndiag_state,
212 tprintf(", ndiag_portid=%" PRIu32
213 ", ndiag_dst_portid=%" PRIu32
214 ", ndiag_dst_group=%" PRIu32
215 ", ndiag_ino=%" PRIu32
216 ", ndiag_cookie=[%" PRIu32
219 msg.ndiag_dst_portid,
223 msg.ndiag_cookie[1]);
231 decode_packet_diag_req(struct tcb *const tcp,
232 const struct nlmsghdr *const nlmsghdr,
233 const uint8_t family,
234 const kernel_ulong_t addr,
235 const kernel_ulong_t len)
237 struct packet_diag_req req = { .sdiag_family = family };
238 const size_t offset = sizeof(req.sdiag_family);
240 tprints("{sdiag_family=");
241 printxval(addrfams, req.sdiag_family, "AF_???");
243 if (len >= sizeof(req)) {
244 if (!umoven_or_printaddr(tcp, addr + offset,
245 sizeof(req) - offset,
246 (void *) &req + offset)) {
247 tprints("sdiag_protocol=");
248 printxval(ethernet_protocols, req.sdiag_protocol,
250 tprintf(", pdiag_ino=%" PRIu32 ", pdiag_show=",
252 printflags(packet_diag_show, req.pdiag_show,
254 tprintf(", pdiag_cookie=[%" PRIu32 ", %" PRIu32 "]",
255 req.pdiag_cookie[0], req.pdiag_cookie[1]);
263 decode_packet_diag_msg(struct tcb *const tcp,
264 const struct nlmsghdr *const nlmsghdr,
265 const uint8_t family,
266 const kernel_ulong_t addr,
267 const kernel_ulong_t len)
269 struct packet_diag_msg msg = { .pdiag_family = family };
270 const size_t offset = sizeof(msg.pdiag_family);
272 tprints("{pdiag_family=");
273 printxval(addrfams, msg.pdiag_family, "AF_???");
276 if (len >= sizeof(msg)) {
277 if (!umoven_or_printaddr(tcp, addr + offset,
278 sizeof(msg) - offset,
279 (void *) &msg + offset)) {
280 tprints("pdiag_type=");
281 printxval(socktypes, msg.pdiag_type, "SOCK_???");
282 tprintf(", pdiag_num=%" PRIu16 ", pdiag_ino=%" PRIu32
283 ", pdiag_cookie=[%" PRIu32 ", %" PRIu32 "]",
284 msg.pdiag_num, msg.pdiag_ino, msg.pdiag_cookie[0],
285 msg.pdiag_cookie[1]);
293 print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
295 tprintf("{idiag_sport=htons(%u), idiag_dport=htons(%u)",
296 ntohs(id->idiag_sport), ntohs(id->idiag_dport));
299 print_inet_addr(family, id->idiag_src,
300 sizeof(id->idiag_src), "idiag_src");
302 print_inet_addr(family, id->idiag_dst,
303 sizeof(id->idiag_dst), "idiag_dst");
305 tprintf(", idiag_if=%" PRIu32
306 ", idiag_cookie=[%" PRIu32 ", %" PRIu32 "]}",
307 id->idiag_if, id->idiag_cookie[0], id->idiag_cookie[1]);
311 decode_inet_diag_req_compat(struct tcb *const tcp,
312 const struct nlmsghdr *const nlmsghdr,
313 const uint8_t family,
314 const kernel_ulong_t addr,
315 const kernel_ulong_t len)
317 struct inet_diag_req req = { .idiag_family = family };
318 const size_t offset = sizeof(req.idiag_family);
320 tprints("{idiag_family=");
321 printxval(addrfams, req.idiag_family, "AF_???");
324 if (len >= sizeof(req)) {
325 if (!umoven_or_printaddr(tcp, addr + offset,
326 sizeof(req) - offset,
327 (void *) &req + offset)) {
328 tprintf("idiag_src_len=%" PRIu8
329 ", idiag_dst_len=%" PRIu8,
332 tprints(", idiag_ext=");
333 printflags(inet_diag_extended_flags, req.idiag_ext,
334 "1<<INET_DIAG_\?\?\?-1");
336 print_inet_diag_sockid(&req.id, req.idiag_family);
337 tprints(", idiag_states=");
338 printflags(tcp_state_flags, req.idiag_states,
340 tprintf(", idiag_dbs=%" PRIu32, req.idiag_dbs);
348 decode_inet_diag_req_v2(struct tcb *const tcp,
349 const struct nlmsghdr *const nlmsghdr,
350 const uint8_t family,
351 const kernel_ulong_t addr,
352 const kernel_ulong_t len)
354 struct inet_diag_req_v2 req = { .sdiag_family = family };
355 const size_t offset = sizeof(req.sdiag_family);
357 tprints("{sdiag_family=");
358 printxval(addrfams, req.sdiag_family, "AF_???");
361 if (len >= sizeof(req)) {
362 if (!umoven_or_printaddr(tcp, addr + offset,
363 sizeof(req) - offset,
364 (void *) &req + offset)) {
365 tprints("sdiag_protocol=");
366 printxval(inet_protocols, req.sdiag_protocol,
368 tprints(", idiag_ext=");
369 printflags(inet_diag_extended_flags, req.idiag_ext,
370 "1<<INET_DIAG_\?\?\?-1");
371 tprints(", idiag_states=");
372 printflags(tcp_state_flags, req.idiag_states,
375 print_inet_diag_sockid(&req.id, req.sdiag_family);
383 decode_inet_diag_req(struct tcb *const tcp,
384 const struct nlmsghdr *const nlmsghdr,
385 const uint8_t family,
386 const kernel_ulong_t addr,
387 const kernel_ulong_t len)
389 if (nlmsghdr->nlmsg_type == TCPDIAG_GETSOCK
390 || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK)
391 return decode_inet_diag_req_compat(tcp, nlmsghdr,
394 return decode_inet_diag_req_v2(tcp, nlmsghdr,
399 decode_inet_diag_msg(struct tcb *const tcp,
400 const struct nlmsghdr *const nlmsghdr,
401 const uint8_t family,
402 const kernel_ulong_t addr,
403 const kernel_ulong_t len)
405 struct inet_diag_msg msg = { .idiag_family = family };
406 const size_t offset = sizeof(msg.idiag_family);
408 tprints("{idiag_family=");
409 printxval(addrfams, msg.idiag_family, "AF_???");
412 if (len >= sizeof(msg)) {
413 if (!umoven_or_printaddr(tcp, addr + offset,
414 sizeof(msg) - offset,
415 (void *) &msg + offset)) {
416 tprints("idiag_state=");
417 printxval(tcp_states, msg.idiag_state, "TCP_???");
418 tprintf(", idiag_timer=%" PRIu8
419 ", idiag_retrans=%" PRIu8,
420 msg.idiag_timer, msg.idiag_retrans);
422 print_inet_diag_sockid(&msg.id, msg.idiag_family);
423 tprintf(", idiag_expires=%" PRIu32
424 ", idiag_rqueue=%" PRIu32
425 ", idiag_wqueue=%" PRIu32
426 ", idiag_uid=%" PRIu32
427 ", idiag_inode=%" PRIu32,
441 decode_smc_diag_req(struct tcb *const tcp,
442 const struct nlmsghdr *const nlmsghdr,
443 const uint8_t family,
444 const kernel_ulong_t addr,
445 const kernel_ulong_t len)
447 struct smc_diag_req req = { .diag_family = family };
448 const size_t offset = sizeof(req.diag_family);
450 tprints("{diag_family=");
451 printxval(addrfams, req.diag_family, "AF_???");
454 if (len >= sizeof(req)) {
455 if (!umoven_or_printaddr(tcp, addr + offset,
456 sizeof(req) - offset,
457 (void *) &req + offset)) {
458 tprints("diag_ext=");
459 printflags(smc_diag_extended_flags, req.diag_ext,
460 "1<<SMC_DIAG_\?\?\?-1");
463 * AF_SMC protocol family socket handler
464 * keeping the AF_INET sock address.
466 print_inet_diag_sockid(&req.id, AF_INET);
474 decode_smc_diag_msg(struct tcb *const tcp,
475 const struct nlmsghdr *const nlmsghdr,
476 const uint8_t family,
477 const kernel_ulong_t addr,
478 const kernel_ulong_t len)
480 struct smc_diag_msg msg = { .diag_family = family };
481 const size_t offset = sizeof(msg.diag_family);
483 tprints("{diag_family=");
484 printxval(addrfams, msg.diag_family, "AF_???");
487 if (len >= sizeof(msg)) {
488 if (!umoven_or_printaddr(tcp, addr + offset,
489 sizeof(msg) - offset,
490 (void *) &msg + offset)) {
491 tprints("diag_state=");
492 printxval(smc_states, msg.diag_state, "SMC_???");
493 tprintf(", diag_fallback=%" PRIu8
494 ", diag_shutdown=%" PRIu8,
495 msg.diag_fallback, msg.diag_shutdown);
498 * AF_SMC protocol family socket handler
499 * keeping the AF_INET sock address.
501 print_inet_diag_sockid(&msg.id, AF_INET);
502 tprintf(", diag_uid=%" PRIu32 ", diag_inode=%" PRIu64,
503 msg.diag_uid, msg.diag_inode);
512 typedef void (*netlink_diag_decoder_t)(struct tcb *,
513 const struct nlmsghdr *,
518 static const struct {
519 const netlink_diag_decoder_t request, response;
520 } diag_decoders[] = {
521 [AF_INET] = { decode_inet_diag_req, decode_inet_diag_msg },
522 [AF_INET6] = { decode_inet_diag_req, decode_inet_diag_msg },
523 [AF_NETLINK] = { decode_netlink_diag_req, decode_netlink_diag_msg },
524 [AF_PACKET] = { decode_packet_diag_req, decode_packet_diag_msg },
526 [AF_SMC] = { decode_smc_diag_req, decode_smc_diag_msg },
528 [AF_UNIX] = { decode_unix_diag_req, decode_unix_diag_msg }
532 decode_netlink_sock_diag(struct tcb *const tcp,
533 const struct nlmsghdr *const nlmsghdr,
534 const kernel_ulong_t addr,
535 const kernel_ulong_t len)
539 if (!umove_or_printaddr(tcp, addr, &family)) {
540 if (family < ARRAY_SIZE(diag_decoders)
541 && len > sizeof(family)) {
542 const netlink_diag_decoder_t decoder =
543 (nlmsghdr->nlmsg_flags & NLM_F_REQUEST)
544 ? diag_decoders[family].request
545 : diag_decoders[family].response;
548 decoder(tcp, nlmsghdr, family, addr, len);
553 decode_family(tcp, family, addr, len);