(root)/
strace-6.5/
src/
netlink_netlink_diag.c
       1  /*
       2   * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
       3   * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
       4   * Copyright (c) 2017-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.h"
      12  #include "netlink_sock_diag.h"
      13  #include "nlattr.h"
      14  
      15  #include <linux/sock_diag.h>
      16  #include <linux/netlink_diag.h>
      17  
      18  #include "xlat/netlink_diag_attrs.h"
      19  #include "xlat/netlink_diag_show.h"
      20  #include "xlat/netlink_socket_flags.h"
      21  #include "xlat/netlink_states.h"
      22  
      23  DECL_NETLINK_DIAG_DECODER(decode_netlink_diag_req)
      24  {
      25  	struct netlink_diag_req req = { .sdiag_family = family };
      26  	const size_t offset = sizeof(req.sdiag_family);
      27  
      28  	tprint_struct_begin();
      29  	PRINT_FIELD_XVAL(req, sdiag_family, addrfams, "AF_???");
      30  	tprint_struct_next();
      31  
      32  	if (len >= sizeof(req)) {
      33  		if (!umoven_or_printaddr(tcp, addr + offset,
      34  					 sizeof(req) - offset,
      35  					 (char *) &req + offset)) {
      36  			if (NDIAG_PROTO_ALL == req.sdiag_protocol) {
      37  				tprints_field_name("sdiag_protocol");
      38  				print_xlat(NDIAG_PROTO_ALL);
      39  			} else {
      40  				PRINT_FIELD_XVAL(req, sdiag_protocol,
      41  						 netlink_protocols,
      42  						 "NETLINK_???");
      43  			}
      44  			tprint_struct_next();
      45  			PRINT_FIELD_U(req, ndiag_ino);
      46  			tprint_struct_next();
      47  			PRINT_FIELD_FLAGS(req, ndiag_show,
      48  					  netlink_diag_show, "NDIAG_SHOW_???");
      49  			tprint_struct_next();
      50  			PRINT_FIELD_COOKIE(req, ndiag_cookie);
      51  		}
      52  	} else
      53  		tprint_more_data_follows();
      54  	tprint_struct_end();
      55  }
      56  
      57  static bool
      58  print_group(struct tcb *const tcp,
      59  	    void *const elem_buf,
      60  	    const size_t elem_size,
      61  	    void *const opaque_data)
      62  {
      63  	if (elem_size < sizeof(kernel_ulong_t)) {
      64  		unsigned int val = *(unsigned int *) elem_buf;
      65  		PRINT_VAL_0X(val);
      66  	} else {
      67  		kernel_ulong_t val = *(kernel_ulong_t *) elem_buf;
      68  		PRINT_VAL_0X(val);
      69  	}
      70  
      71  	return true;
      72  }
      73  
      74  static bool
      75  decode_netlink_diag_groups(struct tcb *const tcp,
      76  			   const kernel_ulong_t addr,
      77  			   const unsigned int len,
      78  			   const void *const opaque_data)
      79  {
      80  	kernel_ulong_t buf;
      81  	const size_t nmemb = len / current_wordsize;
      82  
      83  	if (!nmemb)
      84  		return false;
      85  
      86  	print_array(tcp, addr, nmemb, &buf, current_wordsize,
      87  		    tfetch_mem, print_group, 0);
      88  
      89  	return true;
      90  }
      91  
      92  static bool
      93  decode_netlink_diag_ring(struct tcb *const tcp,
      94  			 const kernel_ulong_t addr,
      95  			 const unsigned int len,
      96  			 const void *const opaque_data)
      97  {
      98  	struct netlink_diag_ring ndr;
      99  
     100  	if (len < sizeof(ndr))
     101  		return false;
     102  	if (umove_or_printaddr(tcp, addr, &ndr))
     103  		return true;
     104  
     105  	tprint_struct_begin();
     106  	PRINT_FIELD_U(ndr, ndr_block_size);
     107  	tprint_struct_next();
     108  	PRINT_FIELD_U(ndr, ndr_block_nr);
     109  	tprint_struct_next();
     110  	PRINT_FIELD_U(ndr, ndr_frame_size);
     111  	tprint_struct_next();
     112  	PRINT_FIELD_U(ndr, ndr_frame_nr);
     113  	tprint_struct_end();
     114  
     115  	return true;
     116  }
     117  
     118  static bool
     119  decode_netlink_diag_flags(struct tcb *const tcp,
     120  			  const kernel_ulong_t addr,
     121  			  const unsigned int len,
     122  			  const void *const opaque_data)
     123  {
     124  	uint32_t flags;
     125  
     126  	if (len < sizeof(flags))
     127  		return false;
     128  	if (umove_or_printaddr(tcp, addr, &flags))
     129  		return true;
     130  
     131  	printflags(netlink_socket_flags, flags, "NDIAG_FLAG_???");
     132  
     133  	return true;
     134  }
     135  
     136  static const nla_decoder_t netlink_diag_msg_nla_decoders[] = {
     137  	[NETLINK_DIAG_MEMINFO]	= decode_nla_meminfo,
     138  	[NETLINK_DIAG_GROUPS]	= decode_netlink_diag_groups,
     139  	[NETLINK_DIAG_RX_RING]	= decode_netlink_diag_ring,
     140  	[NETLINK_DIAG_TX_RING]	= decode_netlink_diag_ring,
     141  	[NETLINK_DIAG_FLAGS]	= decode_netlink_diag_flags
     142  };
     143  
     144  DECL_NETLINK_DIAG_DECODER(decode_netlink_diag_msg)
     145  {
     146  	struct netlink_diag_msg msg = { .ndiag_family = family };
     147  	size_t offset = sizeof(msg.ndiag_family);
     148  	bool decode_nla = false;
     149  
     150  	tprint_struct_begin();
     151  	PRINT_FIELD_XVAL(msg, ndiag_family, addrfams, "AF_???");
     152  	tprint_struct_next();
     153  
     154  	if (len >= sizeof(msg)) {
     155  		if (!umoven_or_printaddr(tcp, addr + offset,
     156  					 sizeof(msg) - offset,
     157  					 (char *) &msg + offset)) {
     158  			PRINT_FIELD_XVAL(msg, ndiag_type,
     159  					 socktypes, "SOCK_???");
     160  			tprint_struct_next();
     161  			PRINT_FIELD_XVAL(msg, ndiag_protocol,
     162  					 netlink_protocols, "NETLINK_???");
     163  			tprint_struct_next();
     164  			PRINT_FIELD_XVAL(msg, ndiag_state,
     165  					 netlink_states, "NETLINK_???");
     166  			tprint_struct_next();
     167  			PRINT_FIELD_U(msg, ndiag_portid);
     168  			tprint_struct_next();
     169  			PRINT_FIELD_U(msg, ndiag_dst_portid);
     170  			tprint_struct_next();
     171  			PRINT_FIELD_U(msg, ndiag_dst_group);
     172  			tprint_struct_next();
     173  			PRINT_FIELD_U(msg, ndiag_ino);
     174  			tprint_struct_next();
     175  			PRINT_FIELD_COOKIE(msg, ndiag_cookie);
     176  			decode_nla = true;
     177  		}
     178  	} else
     179  		tprint_more_data_follows();
     180  	tprint_struct_end();
     181  
     182  	offset = NLMSG_ALIGN(sizeof(msg));
     183  	if (decode_nla && len > offset) {
     184  		tprint_array_next();
     185  		decode_nlattr(tcp, addr + offset, len - offset,
     186  			      netlink_diag_attrs, "NETLINK_DIAG_???",
     187  			      netlink_diag_msg_nla_decoders,
     188  			      ARRAY_SIZE(netlink_diag_msg_nla_decoders), NULL);
     189  	}
     190  }