(root)/
strace-6.5/
src/
rtnl_neigh.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-2022 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 "netlink.h"
      15  #include <linux/neighbour.h>
      16  
      17  #include "xlat/fdb_notify_flags.h"
      18  #include "xlat/neighbor_cache_entry_ext_flags.h"
      19  #include "xlat/neighbor_cache_entry_flags.h"
      20  #include "xlat/neighbor_cache_entry_states.h"
      21  #include "xlat/rtnl_neigh_attrs.h"
      22  #include "xlat/rtnl_neigh_fdb_ext_attrs.h"
      23  
      24  static bool
      25  decode_neigh_addr(struct tcb *const tcp,
      26  		  const kernel_ulong_t addr,
      27  		  const unsigned int len,
      28  		  const void *const opaque_data)
      29  {
      30  	const struct ndmsg *const ndmsg = opaque_data;
      31  
      32  	decode_inet_addr(tcp, addr, len, ndmsg->ndm_family, NULL);
      33  
      34  	return true;
      35  }
      36  
      37  static bool
      38  decode_nda_cacheinfo(struct tcb *const tcp,
      39  		     const kernel_ulong_t addr,
      40  		     const unsigned int len,
      41  		     const void *const opaque_data)
      42  {
      43  	struct nda_cacheinfo ci;
      44  
      45  	if (len < sizeof(ci))
      46  		return false;
      47  	else if (!umove_or_printaddr(tcp, addr, &ci)) {
      48  		tprint_struct_begin();
      49  		PRINT_FIELD_U(ci, ndm_confirmed);
      50  		tprint_struct_next();
      51  		PRINT_FIELD_U(ci, ndm_used);
      52  		tprint_struct_next();
      53  		PRINT_FIELD_U(ci, ndm_updated);
      54  		tprint_struct_next();
      55  		PRINT_FIELD_U(ci, ndm_refcnt);
      56  		tprint_struct_end();
      57  	}
      58  
      59  	return true;
      60  }
      61  
      62  static bool
      63  decode_fdb_notify_flags(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  		fdb_notify_flags, "FDB_NOTIFY_???",
      70  		.size = 1,
      71  	};
      72  
      73  	return decode_nla_flags(tcp, addr, len, &opts);
      74  }
      75  
      76  static const nla_decoder_t nda_fdb_ext_attrs_nla_decoders[] = {
      77  	[NFEA_UNSPEC]		= NULL,
      78  	[NFEA_ACTIVITY_NOTIFY]	= decode_fdb_notify_flags,
      79  	[NFEA_DONT_REFRESH]	= NULL, /* flag attr, no payload is expected */
      80  };
      81  
      82  static bool
      83  decode_nda_fdb_ext_attrs(struct tcb *const tcp,
      84  			 const kernel_ulong_t addr,
      85  			 const unsigned int len,
      86  			 const void *const opaque_data)
      87  {
      88  	decode_nlattr(tcp, addr, len, rtnl_neigh_fdb_ext_attrs,
      89  		      "NFEA_???", ARRSZ_PAIR(nda_fdb_ext_attrs_nla_decoders),
      90  		      opaque_data);
      91  
      92  	return true;
      93  }
      94  
      95  static bool
      96  decode_nda_ext_flags(struct tcb *const tcp,
      97  		     const kernel_ulong_t addr,
      98  		     const unsigned int len,
      99  		     const void *const opaque_data)
     100  {
     101  	static const struct decode_nla_xlat_opts opts = {
     102  		neighbor_cache_entry_ext_flags, "NTF_EXT_???",
     103  		.size = 4,
     104  	};
     105  
     106  	return decode_nla_flags(tcp, addr, len, &opts);
     107  }
     108  
     109  static bool
     110  decode_nda_ndm_states(struct tcb *const tcp,
     111  		      const kernel_ulong_t addr,
     112  		      const unsigned int len,
     113  		      const void *const opaque_data)
     114  {
     115  	static const struct decode_nla_xlat_opts opts = {
     116  		neighbor_cache_entry_states, "NUD_???",
     117  		.size = 2,
     118  	};
     119  
     120  	return decode_nla_flags(tcp, addr, len, &opts);
     121  }
     122  
     123  static bool
     124  decode_nda_ndm_flags(struct tcb *const tcp,
     125  		     const kernel_ulong_t addr,
     126  		     const unsigned int len,
     127  		     const void *const opaque_data)
     128  {
     129  	static const struct decode_nla_xlat_opts opts = {
     130  		neighbor_cache_entry_flags, "NTF_???",
     131  		.size = 1,
     132  	};
     133  
     134  	return decode_nla_flags(tcp, addr, len, &opts);
     135  }
     136  
     137  static const nla_decoder_t ndmsg_nla_decoders[] = {
     138  	[NDA_DST]		= decode_neigh_addr,
     139  	[NDA_LLADDR]		= decode_nla_hwaddr_nofamily,
     140  	[NDA_CACHEINFO]		= decode_nda_cacheinfo,
     141  	[NDA_PROBES]		= decode_nla_u32,
     142  	[NDA_VLAN]		= decode_nla_u16,
     143  	[NDA_PORT]		= decode_nla_be16,
     144  	[NDA_VNI]		= decode_nla_u32,
     145  	[NDA_IFINDEX]		= decode_nla_ifindex,
     146  	[NDA_MASTER]		= decode_nla_ifindex,
     147  	[NDA_LINK_NETNSID]	= decode_nla_u32,
     148  	[NDA_SRC_VNI]		= decode_nla_u32,
     149  	[NDA_PROTOCOL]		= decode_nla_ip_proto,
     150  	[NDA_NH_ID]		= decode_nla_u32,
     151  	[NDA_FDB_EXT_ATTRS]	= decode_nda_fdb_ext_attrs,
     152  	[NDA_FLAGS_EXT]		= decode_nda_ext_flags,
     153  	[NDA_NDM_STATE_MASK]	= decode_nda_ndm_states,
     154  	[NDA_NDM_FLAGS_MASK]	= decode_nda_ndm_flags,
     155  };
     156  
     157  DECL_NETLINK_ROUTE_DECODER(decode_ndmsg)
     158  {
     159  	struct ndmsg ndmsg = { .ndm_family = family };
     160  	size_t offset = sizeof(ndmsg.ndm_family);
     161  	bool decode_nla = false;
     162  
     163  	tprint_struct_begin();
     164  	PRINT_FIELD_XVAL(ndmsg, ndm_family, addrfams, "AF_???");
     165  	tprint_struct_next();
     166  
     167  	if (len >= sizeof(ndmsg)) {
     168  		if (!umoven_or_printaddr(tcp, addr + offset,
     169  					 sizeof(ndmsg) - offset,
     170  					 (char *) &ndmsg + offset)) {
     171  			PRINT_FIELD_IFINDEX(ndmsg, ndm_ifindex);
     172  			tprint_struct_next();
     173  			PRINT_FIELD_FLAGS(ndmsg, ndm_state,
     174  					  neighbor_cache_entry_states,
     175  					  "NUD_???");
     176  			tprint_struct_next();
     177  			PRINT_FIELD_FLAGS(ndmsg, ndm_flags,
     178  					  neighbor_cache_entry_flags,
     179  					  "NTF_???");
     180  			tprint_struct_next();
     181  			PRINT_FIELD_XVAL(ndmsg, ndm_type,
     182  					 routing_types, "RTN_???");
     183  			decode_nla = true;
     184  		}
     185  	} else
     186  		tprint_more_data_follows();
     187  	tprint_struct_end();
     188  
     189  	offset = NLMSG_ALIGN(sizeof(ndmsg));
     190  	if (decode_nla && len > offset) {
     191  		tprint_array_next();
     192  		decode_nlattr(tcp, addr + offset, len - offset,
     193  			      rtnl_neigh_attrs, "NDA_???",
     194  			      ndmsg_nla_decoders,
     195  			      ARRAY_SIZE(ndmsg_nla_decoders), &ndmsg);
     196  	}
     197  }
     198  
     199  DECL_NETLINK_ROUTE_DECODER(decode_rtm_getneigh)
     200  {
     201  	if (family == AF_BRIDGE)
     202  		decode_ifinfomsg(tcp, nlmsghdr, family, addr, len);
     203  	else
     204  		decode_ndmsg(tcp, nlmsghdr, family, addr, len);
     205  }