]> granicus.if.org Git - strace/blob - rtnl_route.c
Add PAF_ARRAY_TRUNCATED flag for print_array_ex
[strace] / rtnl_route.c
1 /*
2  * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4  * Copyright (c) 2016-2018 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_route.h"
12 #include "nlattr.h"
13 #include "print_fields.h"
14
15 #include <linux/ip.h>
16 #include "netlink.h"
17 #include <linux/rtnetlink.h>
18
19 #include "xlat/ip_type_of_services.h"
20 #include "xlat/lwtunnel_encap_types.h"
21 #include "xlat/route_nexthop_flags.h"
22 #include "xlat/routing_flags.h"
23 #include "xlat/routing_protocols.h"
24 #include "xlat/routing_table_ids.h"
25 #include "xlat/routing_types.h"
26 #include "xlat/rtnl_route_attrs.h"
27 #include "xlat/rtnl_rta_metrics_attrs.h"
28
29 bool
30 decode_nla_rt_class(struct tcb *const tcp,
31                     const kernel_ulong_t addr,
32                     const unsigned int len,
33                     const void *const opaque_data)
34 {
35         uint32_t num;
36
37         if (len < sizeof(num))
38                 return false;
39         if (!umove_or_printaddr(tcp, addr, &num))
40                 printxval(routing_table_ids, num, NULL);
41         return true;
42 }
43
44 bool
45 decode_nla_rt_proto(struct tcb *const tcp,
46                     const kernel_ulong_t addr,
47                     const unsigned int len,
48                     const void *const opaque_data)
49 {
50         uint8_t num;
51
52         if (len < sizeof(num))
53                 return false;
54         if (!umove_or_printaddr(tcp, addr, &num))
55                 printxval(routing_protocols, num, "RTPROT_???");
56         return true;
57 }
58
59 static bool
60 decode_route_addr(struct tcb *const tcp,
61                   const kernel_ulong_t addr,
62                   const unsigned int len,
63                   const void *const opaque_data)
64 {
65         const struct rtmsg *const rtmsg = opaque_data;
66
67         decode_inet_addr(tcp, addr, len, rtmsg->rtm_family, NULL);
68
69         return true;
70 }
71
72 static const nla_decoder_t rta_metrics_nla_decoders[] = {
73         [RTAX_LOCK]             = decode_nla_u32,
74         [RTAX_MTU]              = decode_nla_u32,
75         [RTAX_WINDOW]           = decode_nla_u32,
76         [RTAX_RTT]              = decode_nla_u32,
77         [RTAX_RTTVAR]           = decode_nla_u32,
78         [RTAX_SSTHRESH]         = decode_nla_u32,
79         [RTAX_CWND]             = decode_nla_u32,
80         [RTAX_ADVMSS]           = decode_nla_u32,
81         [RTAX_REORDERING]       = decode_nla_u32,
82         [RTAX_HOPLIMIT]         = decode_nla_u32,
83         [RTAX_INITCWND]         = decode_nla_u32,
84         [RTAX_FEATURES]         = decode_nla_u32,
85         [RTAX_RTO_MIN]          = decode_nla_u32,
86         [RTAX_INITRWND]         = decode_nla_u32,
87         [RTAX_QUICKACK]         = decode_nla_u32,
88         [RTAX_CC_ALGO]          = decode_nla_str
89 };
90
91 static bool
92 decode_rta_metrics(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_rta_metrics_attrs,
98                       "RTAX_???", rta_metrics_nla_decoders,
99                       ARRAY_SIZE(rta_metrics_nla_decoders), opaque_data);
100
101         return true;
102 }
103
104 static bool
105 decode_rta_multipath(struct tcb *const tcp,
106                      const kernel_ulong_t addr,
107                      const unsigned int len,
108                      const void *const opaque_data);
109
110 static bool
111 decode_rta_cacheinfo(struct tcb *const tcp,
112                      const kernel_ulong_t addr,
113                      const unsigned int len,
114                      const void *const opaque_data)
115 {
116         struct rta_cacheinfo ci;
117
118         if (len < sizeof(ci))
119                 return false;
120         else if (!umove_or_printaddr(tcp, addr, &ci)) {
121                 PRINT_FIELD_U("{", ci, rta_clntref);
122                 PRINT_FIELD_U(", ", ci, rta_lastuse);
123                 PRINT_FIELD_U(", ", ci, rta_expires);
124                 PRINT_FIELD_U(", ", ci, rta_error);
125                 PRINT_FIELD_U(", ", ci, rta_used);
126                 PRINT_FIELD_X(", ", ci, rta_id);
127                 PRINT_FIELD_U(", ", ci, rta_ts);
128                 PRINT_FIELD_U(", ", ci, rta_tsage);
129                 tprints("}");
130         }
131
132         return true;
133 }
134
135 static bool
136 decode_rta_mfc_stats(struct tcb *const tcp,
137                      const kernel_ulong_t addr,
138                      const unsigned int len,
139                      const void *const opaque_data)
140 {
141 #ifdef HAVE_STRUCT_RTA_MFC_STATS
142         struct rta_mfc_stats mfcs;
143
144         if (len < sizeof(mfcs))
145                 return false;
146         else if (!umove_or_printaddr(tcp, addr, &mfcs)) {
147                 PRINT_FIELD_U("{", mfcs, mfcs_packets);
148                 PRINT_FIELD_U(", ", mfcs, mfcs_bytes);
149                 PRINT_FIELD_U(", ", mfcs, mfcs_wrong_if);
150                 tprints("}");
151         }
152
153         return true;
154 #else
155         return false;
156 #endif
157 }
158
159 static bool
160 decode_rtvia(struct tcb *const tcp,
161              const kernel_ulong_t addr,
162              const unsigned int len,
163              const void *const opaque_data)
164 {
165 #ifdef HAVE_STRUCT_RTVIA
166         struct rtvia via;
167
168         if (len < sizeof(via))
169                 return false;
170         else if (!umove_or_printaddr(tcp, addr, &via)) {
171                 PRINT_FIELD_XVAL("{", via, rtvia_family, addrfams, "AF_???");
172
173                 const unsigned int offset = offsetof(struct rtvia, rtvia_addr);
174
175                 if (len > offset) {
176                         tprints(", ");
177                         decode_inet_addr(tcp, addr + offset, len - offset,
178                                          via.rtvia_family, "rtvia_addr");
179                 }
180                 tprints("}");
181         }
182
183         return true;
184 #else
185         return false;
186 #endif
187 }
188
189 static bool
190 decode_rta_encap_type(struct tcb *const tcp,
191                       const kernel_ulong_t addr,
192                       const unsigned int len,
193                       const void *const opaque_data)
194 {
195         uint16_t type;
196
197         if (len < sizeof(type))
198                 return false;
199         else if (!umove_or_printaddr(tcp, addr, &type))
200                 printxval(lwtunnel_encap_types, type, "LWTUNNEL_ENCAP_???");
201
202         return true;
203 }
204
205 static const nla_decoder_t rtmsg_nla_decoders[] = {
206         [RTA_DST]               = decode_route_addr,
207         [RTA_SRC]               = decode_route_addr,
208         [RTA_IIF]               = decode_nla_ifindex,
209         [RTA_OIF]               = decode_nla_ifindex,
210         [RTA_GATEWAY]           = decode_route_addr,
211         [RTA_PRIORITY]          = decode_nla_u32,
212         [RTA_PREFSRC]           = decode_route_addr,
213         [RTA_METRICS]           = decode_rta_metrics,
214         [RTA_MULTIPATH]         = decode_rta_multipath,
215         [RTA_PROTOINFO]         = decode_nla_u32,
216         [RTA_FLOW]              = decode_nla_u32,
217         [RTA_CACHEINFO]         = decode_rta_cacheinfo,
218         [RTA_SESSION]           = NULL, /* unused */
219         [RTA_MP_ALGO]           = decode_nla_u32,
220         [RTA_TABLE]             = decode_nla_rt_class,
221         [RTA_MARK]              = decode_nla_u32,
222         [RTA_MFC_STATS]         = decode_rta_mfc_stats,
223         [RTA_VIA]               = decode_rtvia,
224         [RTA_NEWDST]            = decode_route_addr,
225         [RTA_PREF]              = decode_nla_u8,
226         [RTA_ENCAP_TYPE]        = decode_rta_encap_type,
227         [RTA_ENCAP]             = NULL, /* unimplemented */
228         [RTA_EXPIRES]           = decode_nla_u64,
229         [RTA_PAD]               = NULL,
230         [RTA_UID]               = decode_nla_u32,
231         [RTA_TTL_PROPAGATE]     = decode_nla_u8,
232         [RTA_IP_PROTO]          = decode_nla_u8,
233         [RTA_SPORT]             = decode_nla_u16,
234         [RTA_DPORT]             = decode_nla_u16
235 };
236
237 static bool
238 decode_rta_multipath(struct tcb *const tcp,
239                      const kernel_ulong_t addr,
240                      const unsigned int len,
241                      const void *const opaque_data)
242 {
243         struct rtnexthop nh;
244
245         if (len < sizeof(nh))
246                 return false;
247         else if (!umove_or_printaddr(tcp, addr, &nh)) {
248                 /* print the whole structure regardless of its rtnh_len */
249                 PRINT_FIELD_U("{", nh, rtnh_len);
250                 PRINT_FIELD_FLAGS(", ", nh, rtnh_flags,
251                                   route_nexthop_flags, "RTNH_F_???");
252                 PRINT_FIELD_U(", ", nh, rtnh_hops);
253                 PRINT_FIELD_IFINDEX(", ", nh, rtnh_ifindex);
254                 tprints("}");
255
256                 const unsigned short rtnh_len = MIN(len, nh.rtnh_len);
257                 const size_t offset = RTNH_ALIGN(sizeof(nh));
258                 if (rtnh_len > offset) {
259                         tprints(", ");
260                         decode_nlattr(tcp, addr + offset, rtnh_len - offset,
261                                       rtnl_route_attrs, "RTA_???",
262                                       rtmsg_nla_decoders,
263                                       ARRAY_SIZE(rtmsg_nla_decoders),
264                                       opaque_data);
265                 }
266         }
267
268         return true;
269 }
270
271 DECL_NETLINK_ROUTE_DECODER(decode_rtmsg)
272 {
273         struct rtmsg rtmsg = { .rtm_family = family };
274         size_t offset = sizeof(rtmsg.rtm_family);
275         bool decode_nla = false;
276
277         PRINT_FIELD_XVAL("{", rtmsg, rtm_family, addrfams, "AF_???");
278
279         tprints(", ");
280         if (len >= sizeof(rtmsg)) {
281                 if (!umoven_or_printaddr(tcp, addr + offset,
282                                          sizeof(rtmsg) - offset,
283                                          (char *) &rtmsg + offset)) {
284                         PRINT_FIELD_U("", rtmsg, rtm_dst_len);
285                         PRINT_FIELD_U(", ", rtmsg, rtm_src_len);
286                         PRINT_FIELD_FLAGS(", ", rtmsg, rtm_tos,
287                                           ip_type_of_services, "IPTOS_TOS_???");
288                         PRINT_FIELD_XVAL(", ", rtmsg, rtm_table,
289                                          routing_table_ids, NULL);
290                         PRINT_FIELD_XVAL(", ", rtmsg, rtm_protocol,
291                                          routing_protocols, "RTPROT_???");
292                         PRINT_FIELD_XVAL(", ", rtmsg, rtm_scope,
293                                          routing_scopes, NULL);
294                         PRINT_FIELD_XVAL(", ", rtmsg, rtm_type,
295                                          routing_types, "RTN_???");
296                         PRINT_FIELD_FLAGS(", ", rtmsg, rtm_flags,
297                                           routing_flags, "RTM_F_???");
298                         decode_nla = true;
299                 }
300         } else
301                 tprints("...");
302         tprints("}");
303
304         offset = NLMSG_ALIGN(sizeof(rtmsg));
305         if (decode_nla && len > offset) {
306                 tprints(", ");
307                 decode_nlattr(tcp, addr + offset, len - offset,
308                               rtnl_route_attrs, "RTA_???",
309                               rtmsg_nla_decoders,
310                               ARRAY_SIZE(rtmsg_nla_decoders), &rtmsg);
311         }
312 }