Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2016 Fabien Siron <fabien.siron (at) epita.fr>
      3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com>
      4  * Copyright (c) 2016-2018 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 					 (char *) &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 }
    316