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