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) 2017-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.h"
     32 #include "netlink_sock_diag.h"
     33 #include "nlattr.h"
     34 #include "print_fields.h"
     35 
     36 #include <linux/filter.h>
     37 #include <linux/sock_diag.h>
     38 #include <linux/packet_diag.h>
     39 
     40 #include "xlat/packet_diag_attrs.h"
     41 #include "xlat/packet_diag_info_flags.h"
     42 #include "xlat/packet_diag_show.h"
     43 
     44 DECL_NETLINK_DIAG_DECODER(decode_packet_diag_req)
     45 {
     46 	struct packet_diag_req req = { .sdiag_family = family };
     47 	const size_t offset = sizeof(req.sdiag_family);
     48 
     49 	PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
     50 	tprints(", ");
     51 	if (len >= sizeof(req)) {
     52 		if (!umoven_or_printaddr(tcp, addr + offset,
     53 					 sizeof(req) - offset,
     54 					 (char *) &req + offset)) {
     55 			PRINT_FIELD_XVAL("", req, sdiag_protocol,
     56 					 ethernet_protocols, "ETH_P_???");
     57 			PRINT_FIELD_U(", ", req, pdiag_ino);
     58 			PRINT_FIELD_FLAGS(", ", req, pdiag_show,
     59 					  packet_diag_show, "PACKET_SHOW_???");
     60 			PRINT_FIELD_COOKIE(", ", req, pdiag_cookie);
     61 		}
     62 	} else
     63 		tprints("...");
     64 	tprints("}");
     65 }
     66 
     67 static bool
     68 decode_packet_diag_info(struct tcb *const tcp,
     69 			const kernel_ulong_t addr,
     70 			const unsigned int len,
     71 			const void *const opaque_data)
     72 {
     73 	struct packet_diag_info pinfo;
     74 
     75 	if (len < sizeof(pinfo))
     76 		return false;
     77 	if (umove_or_printaddr(tcp, addr, &pinfo))
     78 		return true;
     79 
     80 	PRINT_FIELD_U("{", pinfo, pdi_index);
     81 	PRINT_FIELD_U(", ", pinfo, pdi_version);
     82 	PRINT_FIELD_U(", ", pinfo, pdi_reserve);
     83 	PRINT_FIELD_U(", ", pinfo, pdi_copy_thresh);
     84 	PRINT_FIELD_U(", ", pinfo, pdi_tstamp);
     85 	PRINT_FIELD_FLAGS(", ", pinfo, pdi_flags,
     86 			  packet_diag_info_flags, "PDI_???");
     87 	tprints("}");
     88 
     89 	return true;
     90 }
     91 
     92 static bool
     93 print_packet_diag_mclist(struct tcb *const tcp, void *const elem_buf,
     94 			 const size_t elem_size, void *const opaque_data)
     95 {
     96 	struct packet_diag_mclist *dml = elem_buf;
     97 	uint16_t alen = dml->pdmc_alen > sizeof(dml->pdmc_addr) ?
     98 		sizeof(dml->pdmc_addr) : dml->pdmc_alen;
     99 
    100 	PRINT_FIELD_IFINDEX("{", *dml, pdmc_index);
    101 	PRINT_FIELD_U(", ", *dml, pdmc_count);
    102 	PRINT_FIELD_U(", ", *dml, pdmc_type);
    103 	PRINT_FIELD_U(", ", *dml, pdmc_alen);
    104 	PRINT_FIELD_STRING(", ", *dml, pdmc_addr, alen, QUOTE_FORCE_HEX);
    105 	tprints("}");
    106 
    107 	return true;
    108 }
    109 
    110 static bool
    111 decode_packet_diag_mclist(struct tcb *const tcp,
    112 			  const kernel_ulong_t addr,
    113 			  const unsigned int len,
    114 			  const void *const opaque_data)
    115 {
    116 	struct packet_diag_mclist dml;
    117 	const size_t nmemb = len / sizeof(dml);
    118 
    119 	if (!nmemb)
    120 		return false;
    121 
    122 	print_array(tcp, addr, nmemb, &dml, sizeof(dml),
    123 		    umoven_or_printaddr, print_packet_diag_mclist, 0);
    124 
    125 	return true;
    126 }
    127 
    128 static bool
    129 decode_packet_diag_ring(struct tcb *const tcp,
    130 			const kernel_ulong_t addr,
    131 			const unsigned int len,
    132 			const void *const opaque_data)
    133 {
    134 	struct packet_diag_ring pdr;
    135 
    136 	if (len < sizeof(pdr))
    137 		return false;
    138 	if (umove_or_printaddr(tcp, addr, &pdr))
    139 		return true;
    140 
    141 	PRINT_FIELD_U("{", pdr, pdr_block_size);
    142 	PRINT_FIELD_U(", ", pdr, pdr_block_nr);
    143 	PRINT_FIELD_U(", ", pdr, pdr_frame_size);
    144 	PRINT_FIELD_U(", ", pdr, pdr_frame_nr);
    145 	PRINT_FIELD_U(", ", pdr, pdr_retire_tmo);
    146 	PRINT_FIELD_U(", ", pdr, pdr_sizeof_priv);
    147 	PRINT_FIELD_U(", ", pdr, pdr_features);
    148 	tprints("}");
    149 
    150 	return true;
    151 }
    152 
    153 static bool
    154 decode_packet_diag_filter(struct tcb *const tcp,
    155 			  const kernel_ulong_t addr,
    156 			  const unsigned int len,
    157 			  const void *const opaque_data)
    158 {
    159 	const unsigned int nmemb = len / sizeof(struct sock_filter);
    160 	if (!nmemb || (unsigned short) nmemb != nmemb)
    161 		return false;
    162 
    163 	print_sock_fprog(tcp, addr, nmemb);
    164 
    165 	return true;
    166 }
    167 
    168 static const nla_decoder_t packet_diag_msg_nla_decoders[] = {
    169 	[PACKET_DIAG_INFO]	= decode_packet_diag_info,
    170 	[PACKET_DIAG_MCLIST]	= decode_packet_diag_mclist,
    171 	[PACKET_DIAG_RX_RING]	= decode_packet_diag_ring,
    172 	[PACKET_DIAG_TX_RING]	= decode_packet_diag_ring,
    173 	[PACKET_DIAG_FANOUT]	= decode_nla_u32,
    174 	[PACKET_DIAG_UID]	= decode_nla_u32,
    175 	[PACKET_DIAG_MEMINFO]	= decode_nla_meminfo,
    176 	[PACKET_DIAG_FILTER]	= decode_packet_diag_filter
    177 };
    178 
    179 DECL_NETLINK_DIAG_DECODER(decode_packet_diag_msg)
    180 {
    181 	struct packet_diag_msg msg = { .pdiag_family = family };
    182 	size_t offset = sizeof(msg.pdiag_family);
    183 	bool decode_nla = false;
    184 
    185 	PRINT_FIELD_XVAL("{", msg, pdiag_family, addrfams, "AF_???");
    186 	tprints(", ");
    187 	if (len >= sizeof(msg)) {
    188 		if (!umoven_or_printaddr(tcp, addr + offset,
    189 					 sizeof(msg) - offset,
    190 					 (char *) &msg + offset)) {
    191 			PRINT_FIELD_XVAL("", msg, pdiag_type,
    192 					 socktypes, "SOCK_???");
    193 			PRINT_FIELD_U(", ", msg, pdiag_num);
    194 			PRINT_FIELD_U(", ", msg, pdiag_ino);
    195 			PRINT_FIELD_COOKIE(", ", msg, pdiag_cookie);
    196 			decode_nla = true;
    197 		}
    198 	} else
    199 		tprints("...");
    200 	tprints("}");
    201 
    202 	offset = NLMSG_ALIGN(sizeof(msg));
    203 	if (decode_nla && len > offset) {
    204 		tprints(", ");
    205 		decode_nlattr(tcp, addr + offset, len - offset,
    206 			      packet_diag_attrs, "PACKET_DIAG_???",
    207 			      packet_diag_msg_nla_decoders,
    208 			      ARRAY_SIZE(packet_diag_msg_nla_decoders), NULL);
    209 	}
    210 }
    211