(root)/
strace-6.5/
src/
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-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_route.h"
      12  #include "nlattr.h"
      13  
      14  #include <linux/ip.h>
      15  #include <linux/rtnetlink.h>
      16  
      17  #include "xlat/ip_type_of_services.h"
      18  #include "xlat/lwtunnel_encap_types.h"
      19  #include "xlat/route_nexthop_flags.h"
      20  #include "xlat/routing_flags.h"
      21  #include "xlat/routing_protocols.h"
      22  #include "xlat/routing_table_ids.h"
      23  #include "xlat/routing_types.h"
      24  #include "xlat/rtnl_route_attrs.h"
      25  #include "xlat/rtnl_rta_metrics_attrs.h"
      26  
      27  bool
      28  decode_nla_rt_class(struct tcb *const tcp,
      29  		    const kernel_ulong_t addr,
      30  		    const unsigned int len,
      31  		    const void *const opaque_data)
      32  {
      33  	uint32_t num;
      34  
      35  	if (len < sizeof(num))
      36  		return false;
      37  	if (!umove_or_printaddr(tcp, addr, &num))
      38  		printxval(routing_table_ids, num, NULL);
      39  	return true;
      40  }
      41  
      42  bool
      43  decode_nla_rt_proto(struct tcb *const tcp,
      44  		    const kernel_ulong_t addr,
      45  		    const unsigned int len,
      46  		    const void *const opaque_data)
      47  {
      48  	uint8_t num;
      49  
      50  	if (len < sizeof(num))
      51  		return false;
      52  	if (!umove_or_printaddr(tcp, addr, &num))
      53  		printxval(routing_protocols, num, "RTPROT_???");
      54  	return true;
      55  }
      56  
      57  static bool
      58  decode_route_addr(struct tcb *const tcp,
      59  		  const kernel_ulong_t addr,
      60  		  const unsigned int len,
      61  		  const void *const opaque_data)
      62  {
      63  	const struct rtmsg *const rtmsg = opaque_data;
      64  
      65  	decode_inet_addr(tcp, addr, len, rtmsg->rtm_family, NULL);
      66  
      67  	return true;
      68  }
      69  
      70  static const nla_decoder_t rta_metrics_nla_decoders[] = {
      71  	[RTAX_LOCK]		= decode_nla_u32,
      72  	[RTAX_MTU]		= decode_nla_u32,
      73  	[RTAX_WINDOW]		= decode_nla_u32,
      74  	[RTAX_RTT]		= decode_nla_u32,
      75  	[RTAX_RTTVAR]		= decode_nla_u32,
      76  	[RTAX_SSTHRESH]		= decode_nla_u32,
      77  	[RTAX_CWND]		= decode_nla_u32,
      78  	[RTAX_ADVMSS]		= decode_nla_u32,
      79  	[RTAX_REORDERING]	= decode_nla_u32,
      80  	[RTAX_HOPLIMIT]		= decode_nla_u32,
      81  	[RTAX_INITCWND]		= decode_nla_u32,
      82  	[RTAX_FEATURES]		= decode_nla_u32,
      83  	[RTAX_RTO_MIN]		= decode_nla_u32,
      84  	[RTAX_INITRWND]		= decode_nla_u32,
      85  	[RTAX_QUICKACK]		= decode_nla_u32,
      86  	[RTAX_CC_ALGO]		= decode_nla_str
      87  };
      88  
      89  static bool
      90  decode_rta_metrics(struct tcb *const tcp,
      91  		   const kernel_ulong_t addr,
      92  		   const unsigned int len,
      93  		   const void *const opaque_data)
      94  {
      95  	decode_nlattr(tcp, addr, len, rtnl_rta_metrics_attrs,
      96  		      "RTAX_???", rta_metrics_nla_decoders,
      97  		      ARRAY_SIZE(rta_metrics_nla_decoders), opaque_data);
      98  
      99  	return true;
     100  }
     101  
     102  static bool
     103  decode_rta_multipath(struct tcb *const tcp,
     104  		     const kernel_ulong_t addr,
     105  		     const unsigned int len,
     106  		     const void *const opaque_data);
     107  
     108  static bool
     109  decode_rta_cacheinfo(struct tcb *const tcp,
     110  		     const kernel_ulong_t addr,
     111  		     const unsigned int len,
     112  		     const void *const opaque_data)
     113  {
     114  	struct rta_cacheinfo ci;
     115  
     116  	if (len < sizeof(ci))
     117  		return false;
     118  	else if (!umove_or_printaddr(tcp, addr, &ci)) {
     119  		tprint_struct_begin();
     120  		PRINT_FIELD_U(ci, rta_clntref);
     121  		tprint_struct_next();
     122  		PRINT_FIELD_U(ci, rta_lastuse);
     123  		tprint_struct_next();
     124  		PRINT_FIELD_U(ci, rta_expires);
     125  		tprint_struct_next();
     126  		PRINT_FIELD_U(ci, rta_error);
     127  		tprint_struct_next();
     128  		PRINT_FIELD_U(ci, rta_used);
     129  		tprint_struct_next();
     130  		PRINT_FIELD_X(ci, rta_id);
     131  		tprint_struct_next();
     132  		PRINT_FIELD_U(ci, rta_ts);
     133  		tprint_struct_next();
     134  		PRINT_FIELD_U(ci, rta_tsage);
     135  		tprint_struct_end();
     136  	}
     137  
     138  	return true;
     139  }
     140  
     141  static bool
     142  decode_rta_mfc_stats(struct tcb *const tcp,
     143  		     const kernel_ulong_t addr,
     144  		     const unsigned int len,
     145  		     const void *const opaque_data)
     146  {
     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  		tprint_struct_begin();
     153  		PRINT_FIELD_U(mfcs, mfcs_packets);
     154  		tprint_struct_next();
     155  		PRINT_FIELD_U(mfcs, mfcs_bytes);
     156  		tprint_struct_next();
     157  		PRINT_FIELD_U(mfcs, mfcs_wrong_if);
     158  		tprint_struct_end();
     159  	}
     160  
     161  	return true;
     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  	struct rtvia via;
     171  
     172  	if (len < sizeof(via))
     173  		return false;
     174  	else if (!umove_or_printaddr(tcp, addr, &via)) {
     175  		tprint_struct_begin();
     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  			tprint_struct_next();
     182  			decode_inet_addr(tcp, addr + offset, len - offset,
     183  					 via.rtvia_family, "rtvia_addr");
     184  		}
     185  		tprint_struct_end();
     186  	}
     187  
     188  	return true;
     189  }
     190  
     191  bool
     192  decode_nla_lwt_encap_type(struct tcb *const tcp,
     193  			  const kernel_ulong_t addr,
     194  			  const unsigned int len,
     195  			  const void *const opaque_data)
     196  {
     197  	uint16_t type;
     198  
     199  	if (len < sizeof(type))
     200  		return false;
     201  	else if (!umove_or_printaddr(tcp, addr, &type))
     202  		printxval(lwtunnel_encap_types, type, "LWTUNNEL_ENCAP_???");
     203  
     204  	return true;
     205  }
     206  
     207  static const nla_decoder_t rtmsg_nla_decoders[] = {
     208  	[RTA_DST]		= decode_route_addr,
     209  	[RTA_SRC]		= decode_route_addr,
     210  	[RTA_IIF]		= decode_nla_ifindex,
     211  	[RTA_OIF]		= decode_nla_ifindex,
     212  	[RTA_GATEWAY]		= decode_route_addr,
     213  	[RTA_PRIORITY]		= decode_nla_u32,
     214  	[RTA_PREFSRC]		= decode_route_addr,
     215  	[RTA_METRICS]		= decode_rta_metrics,
     216  	[RTA_MULTIPATH]		= decode_rta_multipath,
     217  	[RTA_PROTOINFO]		= decode_nla_u32,
     218  	[RTA_FLOW]		= decode_nla_u32,
     219  	[RTA_CACHEINFO]		= decode_rta_cacheinfo,
     220  	[RTA_SESSION]		= NULL, /* unused */
     221  	[RTA_MP_ALGO]		= decode_nla_u32,
     222  	[RTA_TABLE]		= decode_nla_rt_class,
     223  	[RTA_MARK]		= decode_nla_u32,
     224  	[RTA_MFC_STATS]		= decode_rta_mfc_stats,
     225  	[RTA_VIA]		= decode_rtvia,
     226  	[RTA_NEWDST]		= decode_route_addr,
     227  	[RTA_PREF]		= decode_nla_u8,
     228  	[RTA_ENCAP_TYPE]	= decode_nla_lwt_encap_type,
     229  	[RTA_ENCAP]		= NULL, /* unimplemented */
     230  	[RTA_EXPIRES]		= decode_nla_u64,
     231  	[RTA_PAD]		= NULL,
     232  	[RTA_UID]		= decode_nla_u32,
     233  	[RTA_TTL_PROPAGATE]	= decode_nla_u8,
     234  	[RTA_IP_PROTO]		= decode_nla_u8,
     235  	[RTA_SPORT]		= decode_nla_u16,
     236  	[RTA_DPORT]		= decode_nla_u16
     237  };
     238  
     239  /*
     240   * RTA_MULTIPATH payload is a list of struct rtnexthop-headed RTA_* netlink
     241   * attributes:
     242   *
     243   * {RTA_MULTIPATH nlattr hdr} [ [{struct rtnexthop}, {RTA_* nlattr}],
     244   *                              [{struct rtnexthop}, {RTA_* nlattr}], ... ]
     245   */
     246  static bool
     247  decode_rta_multipath(struct tcb *const tcp,
     248  		     const kernel_ulong_t addr,
     249  		     const unsigned int len,
     250  		     const void *const opaque_data)
     251  {
     252  	bool is_array = false;
     253  	struct rtnexthop nh;
     254  	kernel_ulong_t cur = addr;
     255  	kernel_ulong_t left = len;
     256  
     257  	if (len < sizeof(nh))
     258  		return false;
     259  
     260  	while (!umove_or_printaddr(tcp, cur, &nh)) {
     261  		static const size_t offset = RTNH_ALIGN(sizeof(nh));
     262  		const unsigned int rtnh_len = MIN(left, nh.rtnh_len);
     263  
     264  		if (cur == addr && nh.rtnh_len < len) {
     265  			tprint_array_begin();
     266  			is_array = true;
     267  		}
     268  
     269  		if (cur > addr)
     270  			tprint_array_next();
     271  
     272  		if (rtnh_len > offset)
     273  			tprint_array_begin();
     274  
     275  		/* print the whole structure regardless of its rtnh_len */
     276  		tprint_struct_begin();
     277  		PRINT_FIELD_U(nh, rtnh_len);
     278  		tprint_struct_next();
     279  		PRINT_FIELD_FLAGS(nh, rtnh_flags,
     280  				  route_nexthop_flags, "RTNH_F_???");
     281  		tprint_struct_next();
     282  		PRINT_FIELD_U(nh, rtnh_hops);
     283  		tprint_struct_next();
     284  		PRINT_FIELD_IFINDEX(nh, rtnh_ifindex);
     285  		tprint_struct_end();
     286  
     287  		if (rtnh_len > offset) {
     288  			tprint_array_next();
     289  			decode_nlattr(tcp, cur + offset, rtnh_len - offset,
     290  				      rtnl_route_attrs, "RTA_???",
     291  				      rtmsg_nla_decoders,
     292  				      ARRAY_SIZE(rtmsg_nla_decoders),
     293  				      opaque_data);
     294  		}
     295  
     296  		if (rtnh_len > offset)
     297  			tprint_array_end();
     298  
     299  		if (RTNH_ALIGN(rtnh_len) >= left)
     300  			break;
     301  
     302  		cur += RTNH_ALIGN(rtnh_len);
     303  		left -= RTNH_ALIGN(rtnh_len);
     304  	}
     305  
     306  	if (is_array)
     307  		tprint_array_end();
     308  
     309  	return true;
     310  }
     311  
     312  DECL_NETLINK_ROUTE_DECODER(decode_rtmsg)
     313  {
     314  	struct rtmsg rtmsg = { .rtm_family = family };
     315  	size_t offset = sizeof(rtmsg.rtm_family);
     316  	bool decode_nla = false;
     317  
     318  	tprint_struct_begin();
     319  	PRINT_FIELD_XVAL(rtmsg, rtm_family, addrfams, "AF_???");
     320  	tprint_struct_next();
     321  
     322  	if (len >= sizeof(rtmsg)) {
     323  		if (!umoven_or_printaddr(tcp, addr + offset,
     324  					 sizeof(rtmsg) - offset,
     325  					 (char *) &rtmsg + offset)) {
     326  			PRINT_FIELD_U(rtmsg, rtm_dst_len);
     327  			tprint_struct_next();
     328  			PRINT_FIELD_U(rtmsg, rtm_src_len);
     329  			tprint_struct_next();
     330  			PRINT_FIELD_FLAGS(rtmsg, rtm_tos,
     331  					  ip_type_of_services, "IPTOS_TOS_???");
     332  			tprint_struct_next();
     333  			PRINT_FIELD_XVAL(rtmsg, rtm_table,
     334  					 routing_table_ids, NULL);
     335  			tprint_struct_next();
     336  			PRINT_FIELD_XVAL(rtmsg, rtm_protocol,
     337  					 routing_protocols, "RTPROT_???");
     338  			tprint_struct_next();
     339  			PRINT_FIELD_XVAL(rtmsg, rtm_scope,
     340  					 routing_scopes, NULL);
     341  			tprint_struct_next();
     342  			PRINT_FIELD_XVAL(rtmsg, rtm_type,
     343  					 routing_types, "RTN_???");
     344  			tprint_struct_next();
     345  			PRINT_FIELD_FLAGS(rtmsg, rtm_flags,
     346  					  routing_flags, "RTM_F_???");
     347  			decode_nla = true;
     348  		}
     349  	} else
     350  		tprint_more_data_follows();
     351  	tprint_struct_end();
     352  
     353  	offset = NLMSG_ALIGN(sizeof(rtmsg));
     354  	if (decode_nla && len > offset) {
     355  		tprint_array_next();
     356  		decode_nlattr(tcp, addr + offset, len - offset,
     357  			      rtnl_route_attrs, "RTA_???",
     358  			      rtmsg_nla_decoders,
     359  			      ARRAY_SIZE(rtmsg_nla_decoders), &rtmsg);
     360  	}
     361  }