1 /*
2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4 * Copyright (c) 2016-2021 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9
10 #include "defs.h"
11 #include "netlink.h"
12 #include "netlink_route.h"
13
14 #include <linux/rtnetlink.h>
15
16 #include "xlat/nl_route_types.h"
17
18 static void
19 decode_family(struct tcb *const tcp, const uint8_t family,
20 const kernel_ulong_t addr, const unsigned int len)
21 {
22 tprint_struct_begin();
23 tprints_field_name("family");
24 printxval(addrfams, family, "AF_???");
25 if (len > sizeof(family)) {
26 tprint_struct_next();
27 tprints_field_name("data");
28 printstr_ex(tcp, addr + sizeof(family),
29 len - sizeof(family), QUOTE_FORCE_HEX);
30 }
31 tprint_struct_end();
32 }
33
34 typedef DECL_NETLINK_ROUTE_DECODER((*netlink_route_decoder_t));
35
36 static const netlink_route_decoder_t route_decoders[] = {
37 [RTM_NEWLINK - RTM_BASE] = decode_ifinfomsg,
38 [RTM_DELLINK - RTM_BASE] = decode_ifinfomsg,
39 [RTM_GETLINK - RTM_BASE] = decode_ifinfomsg,
40 [RTM_SETLINK - RTM_BASE] = decode_ifinfomsg,
41
42 [RTM_NEWADDR - RTM_BASE] = decode_ifaddrmsg,
43 [RTM_DELADDR - RTM_BASE] = decode_ifaddrmsg,
44 [RTM_GETADDR - RTM_BASE] = decode_ifaddrmsg,
45
46 [RTM_NEWROUTE - RTM_BASE] = decode_rtmsg,
47 [RTM_DELROUTE - RTM_BASE] = decode_rtmsg,
48 [RTM_GETROUTE - RTM_BASE] = decode_rtmsg,
49
50 [RTM_NEWNEIGH - RTM_BASE] = decode_ndmsg,
51 [RTM_DELNEIGH - RTM_BASE] = decode_ndmsg,
52 [RTM_GETNEIGH - RTM_BASE] = decode_rtm_getneigh,
53
54 [RTM_NEWRULE - RTM_BASE] = decode_fib_rule_hdr,
55 [RTM_DELRULE - RTM_BASE] = decode_fib_rule_hdr,
56 [RTM_GETRULE - RTM_BASE] = decode_fib_rule_hdr,
57
58 [RTM_NEWQDISC - RTM_BASE] = decode_tcmsg,
59 [RTM_DELQDISC - RTM_BASE] = decode_tcmsg,
60 [RTM_GETQDISC - RTM_BASE] = decode_tcmsg,
61
62 [RTM_NEWTCLASS - RTM_BASE] = decode_tcmsg,
63 [RTM_DELTCLASS - RTM_BASE] = decode_tcmsg,
64 [RTM_GETTCLASS - RTM_BASE] = decode_tcmsg,
65
66 [RTM_NEWTFILTER - RTM_BASE] = decode_tcmsg,
67 [RTM_DELTFILTER - RTM_BASE] = decode_tcmsg,
68 [RTM_GETTFILTER - RTM_BASE] = decode_tcmsg,
69
70 [RTM_NEWACTION - RTM_BASE] = decode_tcamsg,
71 [RTM_DELACTION - RTM_BASE] = decode_tcamsg,
72 [RTM_GETACTION - RTM_BASE] = decode_tcamsg,
73
74 /* RTM_NEWPREFIX */
75
76 [RTM_GETMULTICAST - RTM_BASE] = decode_ifaddrmsg,
77
78 [RTM_GETANYCAST - RTM_BASE] = decode_ifaddrmsg,
79
80 [RTM_NEWNEIGHTBL - RTM_BASE] = decode_ndtmsg,
81 [RTM_GETNEIGHTBL - RTM_BASE] = decode_ndtmsg,
82 [RTM_SETNEIGHTBL - RTM_BASE] = decode_ndtmsg,
83
84 /* RTM_NEWNDUSEROPT */
85
86 [RTM_NEWADDRLABEL - RTM_BASE] = decode_ifaddrlblmsg,
87 [RTM_DELADDRLABEL - RTM_BASE] = decode_ifaddrlblmsg,
88 [RTM_GETADDRLABEL - RTM_BASE] = decode_ifaddrlblmsg,
89
90 [RTM_GETDCB - RTM_BASE] = decode_dcbmsg,
91 [RTM_SETDCB - RTM_BASE] = decode_dcbmsg,
92
93 [RTM_NEWNETCONF - RTM_BASE] = decode_netconfmsg,
94 [RTM_DELNETCONF - RTM_BASE] = decode_netconfmsg,
95 [RTM_GETNETCONF - RTM_BASE] = decode_netconfmsg,
96
97 [RTM_NEWMDB - RTM_BASE] = decode_br_port_msg,
98 [RTM_DELMDB - RTM_BASE] = decode_br_port_msg,
99 [RTM_GETMDB - RTM_BASE] = decode_br_port_msg,
100
101 [RTM_NEWNSID - RTM_BASE] = decode_nsid,
102 [RTM_DELNSID - RTM_BASE] = decode_nsid,
103 [RTM_GETNSID - RTM_BASE] = decode_nsid,
104
105 [RTM_NEWSTATS - RTM_BASE] = decode_ifstatsmsg,
106 [RTM_GETSTATS - RTM_BASE] = decode_ifstatsmsg,
107
108 [RTM_NEWCACHEREPORT - RTM_BASE] = decode_cachereport,
109
110 [RTM_NEWCHAIN - RTM_BASE] = decode_tcmsg,
111 [RTM_DELCHAIN - RTM_BASE] = decode_tcmsg,
112 [RTM_GETCHAIN - RTM_BASE] = decode_tcmsg,
113
114 [RTM_NEWNEXTHOP - RTM_BASE] = decode_nhmsg,
115 [RTM_DELNEXTHOP - RTM_BASE] = decode_nhmsg,
116 [RTM_GETNEXTHOP - RTM_BASE] = decode_nhmsg,
117 };
118
119 bool
120 decode_netlink_route(struct tcb *const tcp,
121 const struct nlmsghdr *const nlmsghdr,
122 const kernel_ulong_t addr,
123 const unsigned int len)
124 {
125 uint8_t family;
126
127 if (nlmsghdr->nlmsg_type == NLMSG_DONE)
128 return false;
129
130 if (!umove_or_printaddr(tcp, addr, &family)) {
131 const unsigned int index = nlmsghdr->nlmsg_type - RTM_BASE;
132
133 if (index < ARRAY_SIZE(route_decoders)
134 && route_decoders[index]) {
135 route_decoders[index](tcp, nlmsghdr, family, addr, len);
136 } else {
137 decode_family(tcp, family, addr, len);
138 }
139 }
140
141 return true;
142 }