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
12 #include "netlink_route.h"
13 #include "nlattr.h"
14 #include "netlink.h"
15 #include <netinet/in.h>
16 #include <linux/if_bridge.h>
17
18 #include "xlat/mdb_flags.h"
19 #include "xlat/mdb_states.h"
20 #include "xlat/multicast_router_types.h"
21 #include "xlat/rtnl_mdb_attrs.h"
22 #include "xlat/rtnl_mdba_mdb_attrs.h"
23 #include "xlat/rtnl_mdba_mdb_eattr_attrs.h"
24 #include "xlat/rtnl_mdba_mdb_entry_attrs.h"
25 #include "xlat/rtnl_mdba_router_attrs.h"
26 #include "xlat/rtnl_mdba_router_pattr_attrs.h"
27
28 static const nla_decoder_t mdba_mdb_eattr_nla_decoders[] = {
29 [MDBA_MDB_EATTR_TIMER] = decode_nla_clock_t,
30 };
31
32 static bool
33 decode_mdba_mdb_entry_info(struct tcb *const tcp,
34 const kernel_ulong_t addr,
35 const unsigned int len,
36 const void *const opaque_data)
37 {
38 struct br_mdb_entry entry;
39
40 if (len < sizeof(entry))
41 return false;
42 else if (!umove_or_printaddr(tcp, addr, &entry)) {
43 tprint_struct_begin();
44 PRINT_FIELD_IFINDEX(entry, ifindex);
45 tprint_struct_next();
46 PRINT_FIELD_XVAL(entry, state, mdb_states, "MDB_???");
47
48 /*
49 * Note that it's impossible to derive if flags/vid fields
50 * are present on all architectures except m68k; as a side note,
51 * v4.3-rc1~96^2~365 has introduced an ABI breakage on m68k.
52 */
53 tprint_struct_next();
54 PRINT_FIELD_FLAGS(entry, flags,
55 mdb_flags, "MDB_FLAGS_???");
56 tprint_struct_next();
57 PRINT_FIELD_U(entry, vid);
58
59 const int proto = ntohs(entry.addr.proto);
60
61 tprint_struct_next();
62 tprints_field_name("addr");
63 tprint_struct_begin();
64 print_inet_addr(proto, &entry.addr.u,
65 sizeof(entry.addr.u), "u");
66 tprint_struct_next();
67 tprints_field_name("proto");
68 tprints_arg_begin("htons");
69 printxval(addrfams, proto, "AF_???");
70 tprint_arg_end();
71 tprint_struct_end();
72 tprint_struct_end();
73 }
74
75 const size_t offset = NLMSG_ALIGN(sizeof(entry));
76 if (len > offset) {
77 tprint_array_next();
78 decode_nlattr(tcp, addr + offset, len - offset,
79 rtnl_mdba_mdb_eattr_attrs, "MDBA_MDB_EATTR_???",
80 mdba_mdb_eattr_nla_decoders,
81 ARRAY_SIZE(mdba_mdb_eattr_nla_decoders), NULL);
82 }
83
84 return true;
85 }
86
87 static const nla_decoder_t mdba_mdb_entry_nla_decoders[] = {
88 [MDBA_MDB_ENTRY_INFO] = decode_mdba_mdb_entry_info
89 };
90
91 static bool
92 decode_mdba_mdb_entry(struct tcb *const tcp,
93 const kernel_ulong_t addr,
94 const unsigned int len,
95 const void *const opaque_data)
96 {
97 decode_nlattr(tcp, addr, len, rtnl_mdba_mdb_entry_attrs,
98 "MDBA_MDB_ENTRY_???", mdba_mdb_entry_nla_decoders,
99 ARRAY_SIZE(mdba_mdb_entry_nla_decoders), NULL);
100
101 return true;
102 }
103
104 static const nla_decoder_t mdba_mdb_nla_decoders[] = {
105 [MDBA_MDB_ENTRY] = decode_mdba_mdb_entry
106 };
107
108 static bool
109 decode_mdba_mdb(struct tcb *const tcp,
110 const kernel_ulong_t addr,
111 const unsigned int len,
112 const void *const opaque_data)
113 {
114 decode_nlattr(tcp, addr, len, rtnl_mdba_mdb_attrs, "MDBA_MDB_???",
115 mdba_mdb_nla_decoders,
116 ARRAY_SIZE(mdba_mdb_nla_decoders), NULL);
117
118 return true;
119 }
120
121 static bool
122 decode_multicast_router_type(struct tcb *const tcp,
123 const kernel_ulong_t addr,
124 const unsigned int len,
125 const void *const opaque_data)
126 {
127 uint8_t type;
128
129 if (!umove_or_printaddr(tcp, addr, &type))
130 printxval(multicast_router_types, type, "MDB_RTR_TYPE_???");
131
132 return true;
133 }
134
135 static const nla_decoder_t mdba_router_pattr_nla_decoders[] = {
136 [MDBA_ROUTER_PATTR_TIMER] = decode_nla_clock_t,
137 [MDBA_ROUTER_PATTR_TYPE] = decode_multicast_router_type,
138 [MDBA_ROUTER_PATTR_INET_TIMER] = decode_nla_clock_t,
139 [MDBA_ROUTER_PATTR_INET6_TIMER] = decode_nla_clock_t,
140 };
141
142 static bool
143 decode_mdba_router_port(struct tcb *const tcp,
144 const kernel_ulong_t addr,
145 const unsigned int len,
146 const void *const opaque_data)
147 {
148 uint32_t ifindex;
149
150 if (len < sizeof(ifindex))
151 return false;
152 else if (!umove_or_printaddr(tcp, addr, &ifindex))
153 print_ifindex(ifindex);
154
155 const size_t offset = NLMSG_ALIGN(sizeof(ifindex));
156 if (len > offset) {
157 tprint_array_next();
158 decode_nlattr(tcp, addr + offset, len - offset,
159 rtnl_mdba_router_pattr_attrs,
160 "MDBA_ROUTER_PATTR_???",
161 mdba_router_pattr_nla_decoders,
162 ARRAY_SIZE(mdba_router_pattr_nla_decoders), NULL);
163 }
164
165 return true;
166 }
167
168 static const nla_decoder_t mdba_router_nla_decoders[] = {
169 [MDBA_ROUTER_PORT] = decode_mdba_router_port
170 };
171
172 static bool
173 decode_mdba_router(struct tcb *const tcp,
174 const kernel_ulong_t addr,
175 const unsigned int len,
176 const void *const opaque_data)
177 {
178 decode_nlattr(tcp, addr, len, rtnl_mdba_router_attrs, "MDBA_ROUTER_???",
179 mdba_router_nla_decoders,
180 ARRAY_SIZE(mdba_router_nla_decoders), NULL);
181
182 return true;
183 }
184
185 static const nla_decoder_t br_port_msg_nla_decoders[] = {
186 [MDBA_MDB] = decode_mdba_mdb,
187 [MDBA_ROUTER] = decode_mdba_router
188 };
189
190 DECL_NETLINK_ROUTE_DECODER(decode_br_port_msg)
191 {
192 struct br_port_msg bpm = { .family = family };
193 size_t offset = sizeof(bpm.family);
194 bool decode_nla = false;
195
196 tprint_struct_begin();
197 PRINT_FIELD_XVAL(bpm, family, addrfams, "AF_???");
198 tprint_struct_next();
199
200 if (len >= sizeof(bpm)) {
201 if (!umoven_or_printaddr(tcp, addr + offset,
202 sizeof(bpm) - offset,
203 (char *) &bpm + offset)) {
204 PRINT_FIELD_IFINDEX(bpm, ifindex);
205 decode_nla = true;
206 }
207 } else
208 tprint_more_data_follows();
209 tprint_struct_end();
210
211 offset = NLMSG_ALIGN(sizeof(bpm));
212 if (decode_nla && len > offset) {
213 tprint_array_next();
214 decode_nlattr(tcp, addr + offset, len - offset,
215 rtnl_mdb_attrs, "MDBA_???",
216 br_port_msg_nla_decoders,
217 ARRAY_SIZE(br_port_msg_nla_decoders), NULL);
218 }
219 }