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/sock_diag.h>
     37 #include <linux/netlink_diag.h>
     38 
     39 #include "xlat/netlink_diag_attrs.h"
     40 #include "xlat/netlink_diag_show.h"
     41 #include "xlat/netlink_socket_flags.h"
     42 #include "xlat/netlink_states.h"
     43 
     44 DECL_NETLINK_DIAG_DECODER(decode_netlink_diag_req)
     45 {
     46 	struct netlink_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 			if (NDIAG_PROTO_ALL == req.sdiag_protocol)
     56 				tprintf("%s=%s",
     57 					"sdiag_protocol", "NDIAG_PROTO_ALL");
     58 			else
     59 				PRINT_FIELD_XVAL("", req, sdiag_protocol,
     60 						 netlink_protocols,
     61 						 "NETLINK_???");
     62 			PRINT_FIELD_U(", ", req, ndiag_ino);
     63 			PRINT_FIELD_FLAGS(", ", req, ndiag_show,
     64 					  netlink_diag_show, "NDIAG_SHOW_???");
     65 			PRINT_FIELD_COOKIE(", ", req, ndiag_cookie);
     66 		}
     67 	} else
     68 		tprints("...");
     69 	tprints("}");
     70 }
     71 
     72 static bool
     73 print_group(struct tcb *const tcp,
     74 	    void *const elem_buf,
     75 	    const size_t elem_size,
     76 	    void *const opaque_data)
     77 {
     78 	if (elem_size < sizeof(kernel_ulong_t))
     79 		tprintf("%#0*x", (int) elem_size * 2 + 2,
     80 			*(unsigned int *) elem_buf);
     81 	else
     82 		tprintf("%#0*" PRI_klx, (int) elem_size * 2 + 2,
     83 			*(kernel_ulong_t *) elem_buf);
     84 
     85 	return true;
     86 }
     87 
     88 static bool
     89 decode_netlink_diag_groups(struct tcb *const tcp,
     90 			   const kernel_ulong_t addr,
     91 			   const unsigned int len,
     92 			   const void *const opaque_data)
     93 {
     94 	kernel_ulong_t buf;
     95 	const size_t nmemb = len / current_wordsize;
     96 
     97 	if (!nmemb)
     98 		return false;
     99 
    100 	print_array(tcp, addr, nmemb, &buf, current_wordsize,
    101 		    umoven_or_printaddr, print_group, 0);
    102 
    103 	return true;
    104 }
    105 
    106 static bool
    107 decode_netlink_diag_ring(struct tcb *const tcp,
    108 			 const kernel_ulong_t addr,
    109 			 const unsigned int len,
    110 			 const void *const opaque_data)
    111 {
    112 	struct netlink_diag_ring ndr;
    113 
    114 	if (len < sizeof(ndr))
    115 		return false;
    116 	if (umove_or_printaddr(tcp, addr, &ndr))
    117 		return true;
    118 
    119 	PRINT_FIELD_U("{", ndr, ndr_block_size);
    120 	PRINT_FIELD_U(", ", ndr, ndr_block_nr);
    121 	PRINT_FIELD_U(", ", ndr, ndr_frame_size);
    122 	PRINT_FIELD_U(", ", ndr, ndr_frame_nr);
    123 	tprints("}");
    124 
    125 	return true;
    126 }
    127 
    128 static bool
    129 decode_netlink_diag_flags(struct tcb *const tcp,
    130 			  const kernel_ulong_t addr,
    131 			  const unsigned int len,
    132 			  const void *const opaque_data)
    133 {
    134 	uint32_t flags;
    135 
    136 	if (len < sizeof(flags))
    137 		return false;
    138 	if (umove_or_printaddr(tcp, addr, &flags))
    139 		return true;
    140 
    141 	printflags(netlink_socket_flags, flags, "NDIAG_FLAG_???");
    142 
    143 	return true;
    144 }
    145 
    146 static const nla_decoder_t netlink_diag_msg_nla_decoders[] = {
    147 	[NETLINK_DIAG_MEMINFO]	= decode_nla_meminfo,
    148 	[NETLINK_DIAG_GROUPS]	= decode_netlink_diag_groups,
    149 	[NETLINK_DIAG_RX_RING]	= decode_netlink_diag_ring,
    150 	[NETLINK_DIAG_TX_RING]	= decode_netlink_diag_ring,
    151 	[NETLINK_DIAG_FLAGS]	= decode_netlink_diag_flags
    152 };
    153 
    154 DECL_NETLINK_DIAG_DECODER(decode_netlink_diag_msg)
    155 {
    156 	struct netlink_diag_msg msg = { .ndiag_family = family };
    157 	size_t offset = sizeof(msg.ndiag_family);
    158 	bool decode_nla = false;
    159 
    160 	PRINT_FIELD_XVAL("{", msg, ndiag_family, addrfams, "AF_???");
    161 	tprints(", ");
    162 	if (len >= sizeof(msg)) {
    163 		if (!umoven_or_printaddr(tcp, addr + offset,
    164 					 sizeof(msg) - offset,
    165 					 (char *) &msg + offset)) {
    166 			PRINT_FIELD_XVAL("", msg, ndiag_type,
    167 					 socktypes, "SOCK_???");
    168 			PRINT_FIELD_XVAL(", ", msg, ndiag_protocol,
    169 					 netlink_protocols, "NETLINK_???");
    170 			PRINT_FIELD_XVAL(", ", msg, ndiag_state,
    171 					 netlink_states, "NETLINK_???");
    172 			PRINT_FIELD_U(", ", msg, ndiag_portid);
    173 			PRINT_FIELD_U(", ", msg, ndiag_dst_portid);
    174 			PRINT_FIELD_U(", ", msg, ndiag_dst_group);
    175 			PRINT_FIELD_U(", ", msg, ndiag_ino);
    176 			PRINT_FIELD_COOKIE(", ", msg, ndiag_cookie);
    177 			decode_nla = true;
    178 		}
    179 	} else
    180 		tprints("...");
    181 	tprints("}");
    182 
    183 	offset = NLMSG_ALIGN(sizeof(msg));
    184 	if (decode_nla && len > offset) {
    185 		tprints(", ");
    186 		decode_nlattr(tcp, addr + offset, len - offset,
    187 			      netlink_diag_attrs, "NETLINK_DIAG_???",
    188 			      netlink_diag_msg_nla_decoders,
    189 			      ARRAY_SIZE(netlink_diag_msg_nla_decoders), NULL);
    190 	}
    191 }
    192