(root)/
strace-6.5/
src/
rtnl_nh.c
       1  /*
       2   * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com>
       3   * All rights reserved.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   */
       7  
       8  #include "defs.h"
       9  #include "netlink_route.h"
      10  #include "nlattr.h"
      11  #include "print_fields.h"
      12  
      13  #include <linux/rtnetlink.h>
      14  #include <linux/nexthop.h>
      15  
      16  #include "xlat/rtnl_nexthop_attrs.h"
      17  #include "xlat/rtnl_nexthop_grp_types.h"
      18  #include "xlat/rtnl_nha_res_bucket_attrs.h"
      19  #include "xlat/rtnl_nha_res_group_attrs.h"
      20  
      21  static bool
      22  print_nh_grp(struct tcb *const tcp, void *const elem_buf,
      23  	     const size_t elem_size, void *const opaque_data)
      24  {
      25  	struct nexthop_grp *grp = (struct nexthop_grp *) elem_buf;
      26  
      27  	tprint_struct_begin();
      28  	PRINT_FIELD_U(*grp, id);
      29  	tprint_struct_next();
      30  	PRINT_FIELD_U(*grp, weight);
      31  	if (grp->resvd1) {
      32  		tprint_struct_next();
      33  		PRINT_FIELD_X(*grp, resvd1);
      34  	}
      35  	if (grp->resvd2) {
      36  		tprint_struct_next();
      37  		PRINT_FIELD_X(*grp, resvd2);
      38  	}
      39  	tprint_struct_end();
      40  
      41  	return true;
      42  }
      43  
      44  static bool
      45  decode_nha_nh_grp(struct tcb *const tcp,
      46  		  const kernel_ulong_t addr,
      47  		  const unsigned int len,
      48  		  const void *const opaque_data)
      49  {
      50  	struct nexthop_grp elem;
      51  	const size_t nmemb = len / sizeof(elem);
      52  
      53  	if (!nmemb)
      54  		return false;
      55  
      56  	print_array(tcp, addr, nmemb, &elem, sizeof(elem),
      57  		    tfetch_mem, print_nh_grp, NULL);
      58  
      59  	return true;
      60  }
      61  
      62  static bool
      63  decode_nha_nh_grp_type(struct tcb *const tcp,
      64  		       const kernel_ulong_t addr,
      65  		       const unsigned int len,
      66  		       const void *const opaque_data)
      67  {
      68  	static const struct decode_nla_xlat_opts opts = {
      69  		.xlat = rtnl_nexthop_grp_types,
      70  		.dflt = "NEXTHOP_GRP_TYPE_???",
      71  		.size = 2,
      72  	};
      73  
      74  	return decode_nla_xval(tcp, addr, len, &opts);
      75  }
      76  
      77  static bool
      78  decode_nha_addr(struct tcb *const tcp,
      79  		const kernel_ulong_t addr,
      80  		const unsigned int len,
      81  		const void *const opaque_data)
      82  {
      83  	const struct nhmsg *const nhmsg = opaque_data;
      84  
      85  	decode_inet_addr(tcp, addr, len, nhmsg->nh_family, NULL);
      86  
      87  	return true;
      88  }
      89  
      90  static const nla_decoder_t nha_res_group_nla_decoders[] = {
      91  	[NHA_RES_GROUP_PAD]			= NULL,
      92  	[NHA_RES_GROUP_BUCKETS]			= decode_nla_u16,
      93  	[NHA_RES_GROUP_IDLE_TIMER]		= decode_nla_clock_t,
      94  	[NHA_RES_GROUP_UNBALANCED_TIMER]	= decode_nla_clock_t,
      95  	[NHA_RES_GROUP_UNBALANCED_TIME]		= decode_nla_clock_t,
      96  };
      97  
      98  static bool
      99  decode_nha_res_group(struct tcb *const tcp,
     100  		     const kernel_ulong_t addr,
     101  		     const unsigned int len,
     102  		     const void *const opaque_data)
     103  {
     104  	decode_nlattr(tcp, addr, len, rtnl_nha_res_group_attrs,
     105  		      "NHA_RES_GROUP_???",
     106  		      ARRSZ_PAIR(nha_res_group_nla_decoders), opaque_data);
     107  
     108  	return true;
     109  }
     110  
     111  static const nla_decoder_t nha_res_bucket_nla_decoders[] = {
     112  	[NHA_RES_BUCKET_PAD]		= NULL,
     113  	[NHA_RES_BUCKET_INDEX]		= decode_nla_u16,
     114  	[NHA_RES_BUCKET_IDLE_TIME]	= decode_nla_clock_t,
     115  	[NHA_RES_BUCKET_NH_ID]		= decode_nla_u32,
     116  };
     117  
     118  static bool
     119  decode_nha_res_bucket(struct tcb *const tcp,
     120  		      const kernel_ulong_t addr,
     121  		      const unsigned int len,
     122  		      const void *const opaque_data)
     123  {
     124  	decode_nlattr(tcp, addr, len, rtnl_nha_res_bucket_attrs,
     125  		      "NHA_RES_BUCKET_???",
     126  		      ARRSZ_PAIR(nha_res_bucket_nla_decoders), opaque_data);
     127  
     128  	return true;
     129  }
     130  
     131  static const nla_decoder_t nhmsg_nla_decoders[] = {
     132  	[NHA_UNSPEC]		= NULL,
     133  	[NHA_ID]		= decode_nla_u32,
     134  	[NHA_GROUP]		= decode_nha_nh_grp,
     135  	[NHA_GROUP_TYPE]	= decode_nha_nh_grp_type,
     136  	[NHA_BLACKHOLE]		= decode_nla_u32,
     137  	[NHA_OIF]		= decode_nla_ifindex,
     138  	[NHA_GATEWAY]		= decode_nha_addr,
     139  	[NHA_ENCAP_TYPE]	= decode_nla_lwt_encap_type,
     140  	[NHA_ENCAP]		= NULL, /* unimplemented */
     141  	[NHA_GROUPS]		= decode_nla_u32,
     142  	[NHA_MASTER]		= decode_nla_ifindex,
     143  	[NHA_FDB]		= decode_nla_u32,
     144  	[NHA_RES_GROUP]		= decode_nha_res_group,
     145  	[NHA_RES_BUCKET]	= decode_nha_res_bucket,
     146  };
     147  
     148  DECL_NETLINK_ROUTE_DECODER(decode_nhmsg)
     149  {
     150  	struct nhmsg nhmsg = { .nh_family = family };
     151  	size_t offset = sizeof(nhmsg.nh_family);
     152  	bool decode_nla = false;
     153  
     154  	tprint_struct_begin();
     155  	PRINT_FIELD_XVAL(nhmsg, nh_family, addrfams, "AF_???");
     156  	tprint_struct_next();
     157  
     158  	if (len >= sizeof(nhmsg)) {
     159  		if (!umoven_or_printaddr(tcp, addr + offset,
     160  					 sizeof(nhmsg) - offset,
     161  					 (char *) &nhmsg + offset)) {
     162  			PRINT_FIELD_XVAL(nhmsg, nh_scope,
     163  					 routing_scopes, NULL);
     164  			tprint_struct_next();
     165  			PRINT_FIELD_XVAL(nhmsg, nh_protocol,
     166  					 routing_protocols, "RTPROT_???");
     167  			if (nhmsg.resvd) {
     168  				tprint_struct_next();
     169  				PRINT_FIELD_X(nhmsg, resvd);
     170  			}
     171  			tprint_struct_next();
     172  			PRINT_FIELD_FLAGS(nhmsg, nh_flags,
     173  					  route_nexthop_flags, "RTNH_F_???");
     174  			decode_nla = true;
     175  		}
     176  	} else {
     177  		tprint_more_data_follows();
     178  	}
     179  	tprint_struct_end();
     180  
     181  	offset = NLMSG_ALIGN(sizeof(nhmsg));
     182  	if (decode_nla && len > offset) {
     183  		tprint_array_next();
     184  		decode_nlattr(tcp, addr + offset, len - offset,
     185  			      rtnl_nexthop_attrs, "NHA_???",
     186  			      ARRSZ_PAIR(nhmsg_nla_decoders), &nhmsg);
     187  	}
     188  }