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