1 /*
2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4 * Copyright (c) 2016-2017 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_route.h"
32 #include "nlattr.h"
33 #include "print_fields.h"
34
35 #include "netlink.h"
36 #include <linux/rtnetlink.h>
37 #ifdef HAVE_LINUX_NEIGHBOUR_H
38 # include <linux/neighbour.h>
39 #endif
40
41 #include "xlat/rtnl_neightbl_attrs.h"
42 #include "xlat/rtnl_neightbl_parms_attrs.h"
43
44 static bool
decode_ndt_config(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)45 decode_ndt_config(struct tcb *const tcp,
46 const kernel_ulong_t addr,
47 const unsigned int len,
48 const void *const opaque_data)
49 {
50 #ifdef HAVE_STRUCT_NDT_CONFIG
51 struct ndt_config ndtc;
52
53 if (len < sizeof(ndtc))
54 return false;
55 else if (!umove_or_printaddr(tcp, addr, &ndtc)) {
56 PRINT_FIELD_U("{", ndtc, ndtc_key_len);
57 PRINT_FIELD_U(", ", ndtc, ndtc_entry_size);
58 PRINT_FIELD_U(", ", ndtc, ndtc_entries);
59 PRINT_FIELD_U(", ", ndtc, ndtc_last_flush);
60 PRINT_FIELD_U(", ", ndtc, ndtc_last_rand);
61 PRINT_FIELD_U(", ", ndtc, ndtc_hash_rnd);
62 PRINT_FIELD_0X(", ", ndtc, ndtc_hash_mask);
63 PRINT_FIELD_U(", ", ndtc, ndtc_hash_chain_gc);
64 PRINT_FIELD_U(", ", ndtc, ndtc_proxy_qlen);
65 tprints("}");
66 }
67
68 return true;
69 #else
70 return false;
71 #endif
72 }
73
74 static const nla_decoder_t ndt_parms_nla_decoders[] = {
75 [NDTPA_IFINDEX] = decode_nla_ifindex,
76 [NDTPA_REFCNT] = decode_nla_u32,
77 [NDTPA_REACHABLE_TIME] = decode_nla_u64,
78 [NDTPA_BASE_REACHABLE_TIME] = decode_nla_u64,
79 [NDTPA_RETRANS_TIME] = decode_nla_u64,
80 [NDTPA_GC_STALETIME] = decode_nla_u64,
81 [NDTPA_DELAY_PROBE_TIME] = decode_nla_u64,
82 [NDTPA_QUEUE_LEN] = decode_nla_u32,
83 [NDTPA_APP_PROBES] = decode_nla_u32,
84 [NDTPA_UCAST_PROBES] = decode_nla_u32,
85 [NDTPA_MCAST_PROBES] = decode_nla_u32,
86 [NDTPA_ANYCAST_DELAY] = decode_nla_u64,
87 [NDTPA_PROXY_DELAY] = decode_nla_u64,
88 [NDTPA_PROXY_QLEN] = decode_nla_u32,
89 [NDTPA_LOCKTIME] = decode_nla_u64,
90 [NDTPA_QUEUE_LENBYTES] = decode_nla_u32,
91 [NDTPA_MCAST_REPROBES] = decode_nla_u32,
92 [NDTPA_PAD] = NULL
93 };
94
95 static bool
decode_ndta_parms(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)96 decode_ndta_parms(struct tcb *const tcp,
97 const kernel_ulong_t addr,
98 const unsigned int len,
99 const void *const opaque_data)
100 {
101 decode_nlattr(tcp, addr, len, rtnl_neightbl_parms_attrs, "NDTPA_???",
102 ndt_parms_nla_decoders,
103 ARRAY_SIZE(ndt_parms_nla_decoders), opaque_data);
104
105 return true;
106 }
107
108 static bool
decode_ndt_stats(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)109 decode_ndt_stats(struct tcb *const tcp,
110 const kernel_ulong_t addr,
111 const unsigned int len,
112 const void *const opaque_data)
113 {
114 #ifdef HAVE_STRUCT_NDT_STATS
115 struct ndt_stats ndtst;
116 const unsigned int min_size =
117 offsetofend(struct ndt_stats, ndts_forced_gc_runs);
118 const unsigned int def_size = sizeof(ndtst);
119 const unsigned int size =
120 (len >= def_size) ? def_size :
121 ((len == min_size) ? min_size : 0);
122
123 if (!size)
124 return false;
125
126 if (!umoven_or_printaddr(tcp, addr, size, &ndtst)) {
127 PRINT_FIELD_U("{", ndtst, ndts_allocs);
128 PRINT_FIELD_U(", ", ndtst, ndts_destroys);
129 PRINT_FIELD_U(", ", ndtst, ndts_hash_grows);
130 PRINT_FIELD_U(", ", ndtst, ndts_res_failed);
131 PRINT_FIELD_U(", ", ndtst, ndts_lookups);
132 PRINT_FIELD_U(", ", ndtst, ndts_hits);
133 PRINT_FIELD_U(", ", ndtst, ndts_rcv_probes_mcast);
134 PRINT_FIELD_U(", ", ndtst, ndts_rcv_probes_ucast);
135 PRINT_FIELD_U(", ", ndtst, ndts_periodic_gc_runs);
136 PRINT_FIELD_U(", ", ndtst, ndts_forced_gc_runs);
137 #ifdef HAVE_STRUCT_NDT_STATS_NDTS_TABLE_FULLS
138 if (len >= def_size)
139 PRINT_FIELD_U(", ", ndtst, ndts_table_fulls);
140 #endif
141 tprints("}");
142 }
143
144 return true;
145 #else
146 return false;
147 #endif
148 }
149
150 static const nla_decoder_t ndtmsg_nla_decoders[] = {
151 [NDTA_NAME] = decode_nla_str,
152 [NDTA_THRESH1] = decode_nla_u32,
153 [NDTA_THRESH2] = decode_nla_u32,
154 [NDTA_THRESH3] = decode_nla_u32,
155 [NDTA_CONFIG] = decode_ndt_config,
156 [NDTA_PARMS] = decode_ndta_parms,
157 [NDTA_STATS] = decode_ndt_stats,
158 [NDTA_GC_INTERVAL] = decode_nla_u64,
159 [NDTA_PAD] = NULL,
160 };
161
DECL_NETLINK_ROUTE_DECODER(decode_ndtmsg)162 DECL_NETLINK_ROUTE_DECODER(decode_ndtmsg)
163 {
164 struct ndtmsg ndtmsg = { .ndtm_family = family };
165
166 PRINT_FIELD_XVAL("{", ndtmsg, ndtm_family, addrfams, "AF_???");
167 tprints("}");
168
169 const size_t offset = NLMSG_ALIGN(sizeof(ndtmsg));
170 if (len > offset) {
171 tprints(", ");
172 decode_nlattr(tcp, addr + offset, len - offset,
173 rtnl_neightbl_attrs, "NDTA_???",
174 ndtmsg_nla_decoders,
175 ARRAY_SIZE(ndtmsg_nla_decoders), NULL);
176 }
177 }
178