1*cf84ac9aSAndroid Build Coastguard Worker /*
2*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 2016 Fabien Siron <[email protected]>
3*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 2016 Dmitry V. Levin <[email protected]>
4*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 2016-2018 The strace developers.
5*cf84ac9aSAndroid Build Coastguard Worker * All rights reserved.
6*cf84ac9aSAndroid Build Coastguard Worker *
7*cf84ac9aSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
8*cf84ac9aSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
9*cf84ac9aSAndroid Build Coastguard Worker * are met:
10*cf84ac9aSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
11*cf84ac9aSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
12*cf84ac9aSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
13*cf84ac9aSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
14*cf84ac9aSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
15*cf84ac9aSAndroid Build Coastguard Worker * 3. The name of the author may not be used to endorse or promote products
16*cf84ac9aSAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
17*cf84ac9aSAndroid Build Coastguard Worker *
18*cf84ac9aSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19*cf84ac9aSAndroid Build Coastguard Worker * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*cf84ac9aSAndroid Build Coastguard Worker * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*cf84ac9aSAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22*cf84ac9aSAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*cf84ac9aSAndroid Build Coastguard Worker * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*cf84ac9aSAndroid Build Coastguard Worker * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*cf84ac9aSAndroid Build Coastguard Worker * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*cf84ac9aSAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27*cf84ac9aSAndroid Build Coastguard Worker * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*cf84ac9aSAndroid Build Coastguard Worker */
29*cf84ac9aSAndroid Build Coastguard Worker
30*cf84ac9aSAndroid Build Coastguard Worker #include "defs.h"
31*cf84ac9aSAndroid Build Coastguard Worker #include "netlink.h"
32*cf84ac9aSAndroid Build Coastguard Worker #include "nlattr.h"
33*cf84ac9aSAndroid Build Coastguard Worker #include <linux/audit.h>
34*cf84ac9aSAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
35*cf84ac9aSAndroid Build Coastguard Worker #include <linux/xfrm.h>
36*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/netlink_ack_flags.h"
37*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/netlink_delete_flags.h"
38*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/netlink_flags.h"
39*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/netlink_get_flags.h"
40*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/netlink_new_flags.h"
41*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/netlink_protocols.h"
42*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/netlink_types.h"
43*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_acct_msg_types.h"
44*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_cthelper_msg_types.h"
45*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_ctnetlink_exp_msg_types.h"
46*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_ctnetlink_msg_types.h"
47*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_cttimeout_msg_types.h"
48*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_ipset_msg_types.h"
49*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_nft_compat_msg_types.h"
50*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_nftables_msg_types.h"
51*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_osf_msg_types.h"
52*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_queue_msg_types.h"
53*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nf_ulog_msg_types.h"
54*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nl_audit_types.h"
55*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nl_crypto_types.h"
56*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nl_netfilter_subsys_ids.h"
57*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nl_selinux_types.h"
58*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nl_sock_diag_types.h"
59*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nl_xfrm_types.h"
60*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/nlmsgerr_attrs.h"
61*cf84ac9aSAndroid Build Coastguard Worker
62*cf84ac9aSAndroid Build Coastguard Worker /*
63*cf84ac9aSAndroid Build Coastguard Worker * Fetch a struct nlmsghdr from the given address.
64*cf84ac9aSAndroid Build Coastguard Worker */
65*cf84ac9aSAndroid Build Coastguard Worker static bool
fetch_nlmsghdr(struct tcb * const tcp,struct nlmsghdr * const nlmsghdr,const kernel_ulong_t addr,const kernel_ulong_t len,const bool in_array)66*cf84ac9aSAndroid Build Coastguard Worker fetch_nlmsghdr(struct tcb *const tcp, struct nlmsghdr *const nlmsghdr,
67*cf84ac9aSAndroid Build Coastguard Worker const kernel_ulong_t addr, const kernel_ulong_t len,
68*cf84ac9aSAndroid Build Coastguard Worker const bool in_array)
69*cf84ac9aSAndroid Build Coastguard Worker {
70*cf84ac9aSAndroid Build Coastguard Worker if (len < sizeof(struct nlmsghdr)) {
71*cf84ac9aSAndroid Build Coastguard Worker printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
72*cf84ac9aSAndroid Build Coastguard Worker return false;
73*cf84ac9aSAndroid Build Coastguard Worker }
74*cf84ac9aSAndroid Build Coastguard Worker
75*cf84ac9aSAndroid Build Coastguard Worker if (tfetch_obj(tcp, addr, nlmsghdr))
76*cf84ac9aSAndroid Build Coastguard Worker return true;
77*cf84ac9aSAndroid Build Coastguard Worker
78*cf84ac9aSAndroid Build Coastguard Worker if (in_array) {
79*cf84ac9aSAndroid Build Coastguard Worker tprints("...");
80*cf84ac9aSAndroid Build Coastguard Worker printaddr_comment(addr);
81*cf84ac9aSAndroid Build Coastguard Worker } else {
82*cf84ac9aSAndroid Build Coastguard Worker printaddr(addr);
83*cf84ac9aSAndroid Build Coastguard Worker }
84*cf84ac9aSAndroid Build Coastguard Worker
85*cf84ac9aSAndroid Build Coastguard Worker return false;
86*cf84ac9aSAndroid Build Coastguard Worker }
87*cf84ac9aSAndroid Build Coastguard Worker
88*cf84ac9aSAndroid Build Coastguard Worker static int
get_fd_nl_family(struct tcb * const tcp,const int fd)89*cf84ac9aSAndroid Build Coastguard Worker get_fd_nl_family(struct tcb *const tcp, const int fd)
90*cf84ac9aSAndroid Build Coastguard Worker {
91*cf84ac9aSAndroid Build Coastguard Worker const unsigned long inode = getfdinode(tcp, fd);
92*cf84ac9aSAndroid Build Coastguard Worker if (!inode)
93*cf84ac9aSAndroid Build Coastguard Worker return -1;
94*cf84ac9aSAndroid Build Coastguard Worker
95*cf84ac9aSAndroid Build Coastguard Worker const char *const details = get_sockaddr_by_inode(tcp, fd, inode);
96*cf84ac9aSAndroid Build Coastguard Worker if (!details)
97*cf84ac9aSAndroid Build Coastguard Worker return -1;
98*cf84ac9aSAndroid Build Coastguard Worker
99*cf84ac9aSAndroid Build Coastguard Worker const char *const nl_details = STR_STRIP_PREFIX(details, "NETLINK:[");
100*cf84ac9aSAndroid Build Coastguard Worker if (nl_details == details)
101*cf84ac9aSAndroid Build Coastguard Worker return -1;
102*cf84ac9aSAndroid Build Coastguard Worker
103*cf84ac9aSAndroid Build Coastguard Worker const struct xlat *xlats = netlink_protocols;
104*cf84ac9aSAndroid Build Coastguard Worker for (; xlats->str; ++xlats) {
105*cf84ac9aSAndroid Build Coastguard Worker const char *name = STR_STRIP_PREFIX(xlats->str, "NETLINK_");
106*cf84ac9aSAndroid Build Coastguard Worker if (!strncmp(nl_details, name, strlen(name)))
107*cf84ac9aSAndroid Build Coastguard Worker return xlats->val;
108*cf84ac9aSAndroid Build Coastguard Worker }
109*cf84ac9aSAndroid Build Coastguard Worker
110*cf84ac9aSAndroid Build Coastguard Worker if (*nl_details >= '0' && *nl_details <= '9')
111*cf84ac9aSAndroid Build Coastguard Worker return atoi(nl_details);
112*cf84ac9aSAndroid Build Coastguard Worker
113*cf84ac9aSAndroid Build Coastguard Worker return -1;
114*cf84ac9aSAndroid Build Coastguard Worker }
115*cf84ac9aSAndroid Build Coastguard Worker
116*cf84ac9aSAndroid Build Coastguard Worker static void
decode_nlmsg_type_default(struct tcb * tcp,const struct xlat * const xlat,const uint16_t type,const char * const dflt)117*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_type_default(struct tcb *tcp, const struct xlat *const xlat,
118*cf84ac9aSAndroid Build Coastguard Worker const uint16_t type,
119*cf84ac9aSAndroid Build Coastguard Worker const char *const dflt)
120*cf84ac9aSAndroid Build Coastguard Worker {
121*cf84ac9aSAndroid Build Coastguard Worker printxval(xlat, type, dflt);
122*cf84ac9aSAndroid Build Coastguard Worker }
123*cf84ac9aSAndroid Build Coastguard Worker
124*cf84ac9aSAndroid Build Coastguard Worker static void
decode_nlmsg_type_generic(struct tcb * tcp,const struct xlat * const xlat,const uint16_t type,const char * const dflt)125*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_type_generic(struct tcb *tcp, const struct xlat *const xlat,
126*cf84ac9aSAndroid Build Coastguard Worker const uint16_t type,
127*cf84ac9aSAndroid Build Coastguard Worker const char *const dflt)
128*cf84ac9aSAndroid Build Coastguard Worker {
129*cf84ac9aSAndroid Build Coastguard Worker printxval(genl_families_xlat(tcp), type, dflt);
130*cf84ac9aSAndroid Build Coastguard Worker }
131*cf84ac9aSAndroid Build Coastguard Worker
132*cf84ac9aSAndroid Build Coastguard Worker static const struct {
133*cf84ac9aSAndroid Build Coastguard Worker const struct xlat *const xlat;
134*cf84ac9aSAndroid Build Coastguard Worker const char *const dflt;
135*cf84ac9aSAndroid Build Coastguard Worker } nf_nlmsg_types[] = {
136*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_CTNETLINK] = {
137*cf84ac9aSAndroid Build Coastguard Worker nf_ctnetlink_msg_types,
138*cf84ac9aSAndroid Build Coastguard Worker "IPCTNL_MSG_CT_???"
139*cf84ac9aSAndroid Build Coastguard Worker },
140*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_CTNETLINK_EXP] = {
141*cf84ac9aSAndroid Build Coastguard Worker nf_ctnetlink_exp_msg_types,
142*cf84ac9aSAndroid Build Coastguard Worker "IPCTNL_MSG_EXP_???"
143*cf84ac9aSAndroid Build Coastguard Worker },
144*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_QUEUE] = { nf_queue_msg_types, "NFQNL_MSG_???" },
145*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_ULOG] = { nf_ulog_msg_types, "NFULNL_MSG_???" },
146*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_OSF] = { nf_osf_msg_types, "OSF_MSG_???" },
147*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_IPSET] = { nf_ipset_msg_types, "IPSET_CMD_???" },
148*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_ACCT] = { nf_acct_msg_types, "NFNL_MSG_ACCT_???" },
149*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_CTNETLINK_TIMEOUT] = {
150*cf84ac9aSAndroid Build Coastguard Worker nf_cttimeout_msg_types,
151*cf84ac9aSAndroid Build Coastguard Worker "IPCTNL_MSG_TIMEOUT_???"
152*cf84ac9aSAndroid Build Coastguard Worker },
153*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_CTHELPER] = {
154*cf84ac9aSAndroid Build Coastguard Worker nf_cthelper_msg_types,
155*cf84ac9aSAndroid Build Coastguard Worker "NFNL_MSG_CTHELPER_???"
156*cf84ac9aSAndroid Build Coastguard Worker },
157*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_NFTABLES] = { nf_nftables_msg_types, "NFT_MSG_???" },
158*cf84ac9aSAndroid Build Coastguard Worker [NFNL_SUBSYS_NFT_COMPAT] = {
159*cf84ac9aSAndroid Build Coastguard Worker nf_nft_compat_msg_types,
160*cf84ac9aSAndroid Build Coastguard Worker "NFNL_MSG_COMPAT_???"
161*cf84ac9aSAndroid Build Coastguard Worker }
162*cf84ac9aSAndroid Build Coastguard Worker };
163*cf84ac9aSAndroid Build Coastguard Worker
164*cf84ac9aSAndroid Build Coastguard Worker static void
decode_nlmsg_type_netfilter(struct tcb * tcp,const struct xlat * const xlat,const uint16_t type,const char * const dflt)165*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_type_netfilter(struct tcb *tcp, const struct xlat *const xlat,
166*cf84ac9aSAndroid Build Coastguard Worker const uint16_t type,
167*cf84ac9aSAndroid Build Coastguard Worker const char *const dflt)
168*cf84ac9aSAndroid Build Coastguard Worker {
169*cf84ac9aSAndroid Build Coastguard Worker /* Reserved control nfnetlink messages first. */
170*cf84ac9aSAndroid Build Coastguard Worker const char *const text = xlookup(nl_netfilter_msg_types, type);
171*cf84ac9aSAndroid Build Coastguard Worker if (text) {
172*cf84ac9aSAndroid Build Coastguard Worker print_xlat_ex(type, text, XLAT_STYLE_DEFAULT);
173*cf84ac9aSAndroid Build Coastguard Worker return;
174*cf84ac9aSAndroid Build Coastguard Worker }
175*cf84ac9aSAndroid Build Coastguard Worker
176*cf84ac9aSAndroid Build Coastguard Worker /*
177*cf84ac9aSAndroid Build Coastguard Worker * Other netfilter message types are split
178*cf84ac9aSAndroid Build Coastguard Worker * in two pieces: 8 bits subsystem and 8 bits type.
179*cf84ac9aSAndroid Build Coastguard Worker */
180*cf84ac9aSAndroid Build Coastguard Worker const uint8_t subsys_id = (uint8_t) (type >> 8);
181*cf84ac9aSAndroid Build Coastguard Worker const uint8_t msg_type = (uint8_t) type;
182*cf84ac9aSAndroid Build Coastguard Worker
183*cf84ac9aSAndroid Build Coastguard Worker printxval(xlat, subsys_id, dflt);
184*cf84ac9aSAndroid Build Coastguard Worker
185*cf84ac9aSAndroid Build Coastguard Worker tprints("<<8|");
186*cf84ac9aSAndroid Build Coastguard Worker if (subsys_id < ARRAY_SIZE(nf_nlmsg_types))
187*cf84ac9aSAndroid Build Coastguard Worker printxval(nf_nlmsg_types[subsys_id].xlat,
188*cf84ac9aSAndroid Build Coastguard Worker msg_type, nf_nlmsg_types[subsys_id].dflt);
189*cf84ac9aSAndroid Build Coastguard Worker else
190*cf84ac9aSAndroid Build Coastguard Worker tprintf("%#x", msg_type);
191*cf84ac9aSAndroid Build Coastguard Worker }
192*cf84ac9aSAndroid Build Coastguard Worker
193*cf84ac9aSAndroid Build Coastguard Worker typedef void (*nlmsg_types_decoder_t)(struct tcb *, const struct xlat *,
194*cf84ac9aSAndroid Build Coastguard Worker uint16_t type,
195*cf84ac9aSAndroid Build Coastguard Worker const char *dflt);
196*cf84ac9aSAndroid Build Coastguard Worker
197*cf84ac9aSAndroid Build Coastguard Worker static const struct {
198*cf84ac9aSAndroid Build Coastguard Worker const nlmsg_types_decoder_t decoder;
199*cf84ac9aSAndroid Build Coastguard Worker const struct xlat *const xlat;
200*cf84ac9aSAndroid Build Coastguard Worker const char *const dflt;
201*cf84ac9aSAndroid Build Coastguard Worker } nlmsg_types[] = {
202*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_AUDIT] = { NULL, nl_audit_types, "AUDIT_???" },
203*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_CRYPTO] = { NULL, nl_crypto_types, "CRYPTO_MSG_???" },
204*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_GENERIC] = {
205*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_type_generic,
206*cf84ac9aSAndroid Build Coastguard Worker NULL,
207*cf84ac9aSAndroid Build Coastguard Worker "GENERIC_FAMILY_???"
208*cf84ac9aSAndroid Build Coastguard Worker },
209*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_NETFILTER] = {
210*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_type_netfilter,
211*cf84ac9aSAndroid Build Coastguard Worker nl_netfilter_subsys_ids,
212*cf84ac9aSAndroid Build Coastguard Worker "NFNL_SUBSYS_???"
213*cf84ac9aSAndroid Build Coastguard Worker },
214*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_ROUTE] = { NULL, nl_route_types, "RTM_???" },
215*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_SELINUX] = { NULL, nl_selinux_types, "SELNL_MSG_???" },
216*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_SOCK_DIAG] = { NULL, nl_sock_diag_types, "SOCK_DIAG_???" },
217*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_XFRM] = { NULL, nl_xfrm_types, "XFRM_MSG_???" }
218*cf84ac9aSAndroid Build Coastguard Worker };
219*cf84ac9aSAndroid Build Coastguard Worker
220*cf84ac9aSAndroid Build Coastguard Worker /*
221*cf84ac9aSAndroid Build Coastguard Worker * As all valid netlink families are positive integers, use unsigned int
222*cf84ac9aSAndroid Build Coastguard Worker * for family here to filter out -1.
223*cf84ac9aSAndroid Build Coastguard Worker */
224*cf84ac9aSAndroid Build Coastguard Worker static void
decode_nlmsg_type(struct tcb * tcp,const uint16_t type,const unsigned int family)225*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_type(struct tcb *tcp, const uint16_t type,
226*cf84ac9aSAndroid Build Coastguard Worker const unsigned int family)
227*cf84ac9aSAndroid Build Coastguard Worker {
228*cf84ac9aSAndroid Build Coastguard Worker nlmsg_types_decoder_t decoder = decode_nlmsg_type_default;
229*cf84ac9aSAndroid Build Coastguard Worker const struct xlat *xlat = netlink_types;
230*cf84ac9aSAndroid Build Coastguard Worker const char *dflt = "NLMSG_???";
231*cf84ac9aSAndroid Build Coastguard Worker
232*cf84ac9aSAndroid Build Coastguard Worker /*
233*cf84ac9aSAndroid Build Coastguard Worker * type < NLMSG_MIN_TYPE are reserved control messages
234*cf84ac9aSAndroid Build Coastguard Worker * that need no family-specific decoding.
235*cf84ac9aSAndroid Build Coastguard Worker */
236*cf84ac9aSAndroid Build Coastguard Worker if (type >= NLMSG_MIN_TYPE && family < ARRAY_SIZE(nlmsg_types)) {
237*cf84ac9aSAndroid Build Coastguard Worker if (nlmsg_types[family].decoder)
238*cf84ac9aSAndroid Build Coastguard Worker decoder = nlmsg_types[family].decoder;
239*cf84ac9aSAndroid Build Coastguard Worker if (nlmsg_types[family].xlat)
240*cf84ac9aSAndroid Build Coastguard Worker xlat = nlmsg_types[family].xlat;
241*cf84ac9aSAndroid Build Coastguard Worker if (nlmsg_types[family].dflt)
242*cf84ac9aSAndroid Build Coastguard Worker dflt = nlmsg_types[family].dflt;
243*cf84ac9aSAndroid Build Coastguard Worker }
244*cf84ac9aSAndroid Build Coastguard Worker
245*cf84ac9aSAndroid Build Coastguard Worker decoder(tcp, xlat, type, dflt);
246*cf84ac9aSAndroid Build Coastguard Worker }
247*cf84ac9aSAndroid Build Coastguard Worker
248*cf84ac9aSAndroid Build Coastguard Worker static const struct xlat *
decode_nlmsg_flags_crypto(const uint16_t type)249*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_flags_crypto(const uint16_t type)
250*cf84ac9aSAndroid Build Coastguard Worker {
251*cf84ac9aSAndroid Build Coastguard Worker switch (type) {
252*cf84ac9aSAndroid Build Coastguard Worker case CRYPTO_MSG_NEWALG:
253*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
254*cf84ac9aSAndroid Build Coastguard Worker case CRYPTO_MSG_DELALG:
255*cf84ac9aSAndroid Build Coastguard Worker case CRYPTO_MSG_DELRNG:
256*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
257*cf84ac9aSAndroid Build Coastguard Worker case CRYPTO_MSG_GETALG:
258*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
259*cf84ac9aSAndroid Build Coastguard Worker }
260*cf84ac9aSAndroid Build Coastguard Worker
261*cf84ac9aSAndroid Build Coastguard Worker return NULL;
262*cf84ac9aSAndroid Build Coastguard Worker }
263*cf84ac9aSAndroid Build Coastguard Worker
264*cf84ac9aSAndroid Build Coastguard Worker static const struct xlat *
decode_nlmsg_flags_netfilter(const uint16_t type)265*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_flags_netfilter(const uint16_t type)
266*cf84ac9aSAndroid Build Coastguard Worker {
267*cf84ac9aSAndroid Build Coastguard Worker const uint8_t subsys_id = (uint8_t) (type >> 8);
268*cf84ac9aSAndroid Build Coastguard Worker const uint8_t msg_type = (uint8_t) type;
269*cf84ac9aSAndroid Build Coastguard Worker
270*cf84ac9aSAndroid Build Coastguard Worker switch (subsys_id) {
271*cf84ac9aSAndroid Build Coastguard Worker case NFNL_SUBSYS_CTNETLINK:
272*cf84ac9aSAndroid Build Coastguard Worker switch (msg_type) {
273*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_CT_NEW:
274*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
275*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_CT_GET:
276*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_CT_GET_CTRZERO:
277*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_CT_GET_STATS_CPU:
278*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_CT_GET_STATS:
279*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_CT_GET_DYING:
280*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_CT_GET_UNCONFIRMED:
281*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
282*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_CT_DELETE:
283*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
284*cf84ac9aSAndroid Build Coastguard Worker }
285*cf84ac9aSAndroid Build Coastguard Worker break;
286*cf84ac9aSAndroid Build Coastguard Worker case NFNL_SUBSYS_CTNETLINK_EXP:
287*cf84ac9aSAndroid Build Coastguard Worker switch (msg_type) {
288*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_EXP_NEW:
289*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
290*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_EXP_GET:
291*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_EXP_GET_STATS_CPU:
292*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
293*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_EXP_DELETE:
294*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
295*cf84ac9aSAndroid Build Coastguard Worker }
296*cf84ac9aSAndroid Build Coastguard Worker break;
297*cf84ac9aSAndroid Build Coastguard Worker case NFNL_SUBSYS_ACCT:
298*cf84ac9aSAndroid Build Coastguard Worker switch (msg_type) {
299*cf84ac9aSAndroid Build Coastguard Worker case NFNL_MSG_ACCT_NEW:
300*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
301*cf84ac9aSAndroid Build Coastguard Worker case NFNL_MSG_ACCT_GET:
302*cf84ac9aSAndroid Build Coastguard Worker case NFNL_MSG_ACCT_GET_CTRZERO:
303*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
304*cf84ac9aSAndroid Build Coastguard Worker case NFNL_MSG_ACCT_DEL:
305*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
306*cf84ac9aSAndroid Build Coastguard Worker }
307*cf84ac9aSAndroid Build Coastguard Worker break;
308*cf84ac9aSAndroid Build Coastguard Worker case NFNL_SUBSYS_CTNETLINK_TIMEOUT:
309*cf84ac9aSAndroid Build Coastguard Worker switch (msg_type) {
310*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_TIMEOUT_NEW:
311*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
312*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_TIMEOUT_GET:
313*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
314*cf84ac9aSAndroid Build Coastguard Worker case IPCTNL_MSG_TIMEOUT_DELETE:
315*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
316*cf84ac9aSAndroid Build Coastguard Worker }
317*cf84ac9aSAndroid Build Coastguard Worker break;
318*cf84ac9aSAndroid Build Coastguard Worker case NFNL_SUBSYS_CTHELPER:
319*cf84ac9aSAndroid Build Coastguard Worker switch (msg_type) {
320*cf84ac9aSAndroid Build Coastguard Worker case NFNL_MSG_CTHELPER_NEW:
321*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
322*cf84ac9aSAndroid Build Coastguard Worker case NFNL_MSG_CTHELPER_GET:
323*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
324*cf84ac9aSAndroid Build Coastguard Worker case NFNL_MSG_CTHELPER_DEL:
325*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
326*cf84ac9aSAndroid Build Coastguard Worker }
327*cf84ac9aSAndroid Build Coastguard Worker break;
328*cf84ac9aSAndroid Build Coastguard Worker case NFNL_SUBSYS_NFTABLES:
329*cf84ac9aSAndroid Build Coastguard Worker switch (msg_type) {
330*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_NEWTABLE:
331*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_NEWCHAIN:
332*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_NEWRULE:
333*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_NEWSET:
334*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_NEWSETELEM:
335*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_NEWGEN:
336*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_NEWOBJ:
337*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
338*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_GETTABLE:
339*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_GETCHAIN:
340*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_GETRULE:
341*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_GETSET:
342*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_GETSETELEM:
343*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_GETGEN:
344*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_GETOBJ:
345*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_GETOBJ_RESET:
346*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
347*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_DELTABLE:
348*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_DELCHAIN:
349*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_DELRULE:
350*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_DELSET:
351*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_DELSETELEM:
352*cf84ac9aSAndroid Build Coastguard Worker case NFT_MSG_DELOBJ:
353*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
354*cf84ac9aSAndroid Build Coastguard Worker }
355*cf84ac9aSAndroid Build Coastguard Worker break;
356*cf84ac9aSAndroid Build Coastguard Worker case NFNL_SUBSYS_NFT_COMPAT:
357*cf84ac9aSAndroid Build Coastguard Worker switch (msg_type) {
358*cf84ac9aSAndroid Build Coastguard Worker case NFNL_MSG_COMPAT_GET:
359*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
360*cf84ac9aSAndroid Build Coastguard Worker }
361*cf84ac9aSAndroid Build Coastguard Worker break;
362*cf84ac9aSAndroid Build Coastguard Worker }
363*cf84ac9aSAndroid Build Coastguard Worker
364*cf84ac9aSAndroid Build Coastguard Worker return NULL;
365*cf84ac9aSAndroid Build Coastguard Worker }
366*cf84ac9aSAndroid Build Coastguard Worker
367*cf84ac9aSAndroid Build Coastguard Worker static const struct xlat *
decode_nlmsg_flags_route(const uint16_t type)368*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_flags_route(const uint16_t type)
369*cf84ac9aSAndroid Build Coastguard Worker {
370*cf84ac9aSAndroid Build Coastguard Worker /* RTM_DELACTION uses NLM_F_ROOT flags */
371*cf84ac9aSAndroid Build Coastguard Worker if (type == RTM_DELACTION)
372*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
373*cf84ac9aSAndroid Build Coastguard Worker switch (type & 3) {
374*cf84ac9aSAndroid Build Coastguard Worker case 0:
375*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
376*cf84ac9aSAndroid Build Coastguard Worker case 1:
377*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
378*cf84ac9aSAndroid Build Coastguard Worker case 2:
379*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
380*cf84ac9aSAndroid Build Coastguard Worker }
381*cf84ac9aSAndroid Build Coastguard Worker
382*cf84ac9aSAndroid Build Coastguard Worker return NULL;
383*cf84ac9aSAndroid Build Coastguard Worker }
384*cf84ac9aSAndroid Build Coastguard Worker
385*cf84ac9aSAndroid Build Coastguard Worker static const struct xlat *
decode_nlmsg_flags_sock_diag(const uint16_t type)386*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_flags_sock_diag(const uint16_t type)
387*cf84ac9aSAndroid Build Coastguard Worker {
388*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
389*cf84ac9aSAndroid Build Coastguard Worker }
390*cf84ac9aSAndroid Build Coastguard Worker
391*cf84ac9aSAndroid Build Coastguard Worker static const struct xlat *
decode_nlmsg_flags_xfrm(const uint16_t type)392*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_flags_xfrm(const uint16_t type)
393*cf84ac9aSAndroid Build Coastguard Worker {
394*cf84ac9aSAndroid Build Coastguard Worker switch (type) {
395*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_NEWSA:
396*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_NEWPOLICY:
397*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_NEWAE:
398*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_NEWSADINFO:
399*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_NEWSPDINFO:
400*cf84ac9aSAndroid Build Coastguard Worker return netlink_new_flags;
401*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_DELSA:
402*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_DELPOLICY:
403*cf84ac9aSAndroid Build Coastguard Worker return netlink_delete_flags;
404*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_GETSA:
405*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_GETPOLICY:
406*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_GETAE:
407*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_GETSADINFO:
408*cf84ac9aSAndroid Build Coastguard Worker case XFRM_MSG_GETSPDINFO:
409*cf84ac9aSAndroid Build Coastguard Worker return netlink_get_flags;
410*cf84ac9aSAndroid Build Coastguard Worker }
411*cf84ac9aSAndroid Build Coastguard Worker
412*cf84ac9aSAndroid Build Coastguard Worker return NULL;
413*cf84ac9aSAndroid Build Coastguard Worker }
414*cf84ac9aSAndroid Build Coastguard Worker
415*cf84ac9aSAndroid Build Coastguard Worker typedef const struct xlat *(*nlmsg_flags_decoder_t)(const uint16_t type);
416*cf84ac9aSAndroid Build Coastguard Worker
417*cf84ac9aSAndroid Build Coastguard Worker static const nlmsg_flags_decoder_t nlmsg_flags[] = {
418*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_CRYPTO] = decode_nlmsg_flags_crypto,
419*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_NETFILTER] = decode_nlmsg_flags_netfilter,
420*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_ROUTE] = decode_nlmsg_flags_route,
421*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_SOCK_DIAG] = decode_nlmsg_flags_sock_diag,
422*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_XFRM] = decode_nlmsg_flags_xfrm
423*cf84ac9aSAndroid Build Coastguard Worker };
424*cf84ac9aSAndroid Build Coastguard Worker
425*cf84ac9aSAndroid Build Coastguard Worker /*
426*cf84ac9aSAndroid Build Coastguard Worker * As all valid netlink families are positive integers, use unsigned int
427*cf84ac9aSAndroid Build Coastguard Worker * for family here to filter out -1.
428*cf84ac9aSAndroid Build Coastguard Worker */
429*cf84ac9aSAndroid Build Coastguard Worker static void
decode_nlmsg_flags(const uint16_t flags,const uint16_t type,const unsigned int family)430*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_flags(const uint16_t flags, const uint16_t type,
431*cf84ac9aSAndroid Build Coastguard Worker const unsigned int family)
432*cf84ac9aSAndroid Build Coastguard Worker {
433*cf84ac9aSAndroid Build Coastguard Worker const struct xlat *table = NULL;
434*cf84ac9aSAndroid Build Coastguard Worker
435*cf84ac9aSAndroid Build Coastguard Worker if (type < NLMSG_MIN_TYPE) {
436*cf84ac9aSAndroid Build Coastguard Worker if (type == NLMSG_ERROR)
437*cf84ac9aSAndroid Build Coastguard Worker table = netlink_ack_flags;
438*cf84ac9aSAndroid Build Coastguard Worker } else if (family < ARRAY_SIZE(nlmsg_flags) && nlmsg_flags[family])
439*cf84ac9aSAndroid Build Coastguard Worker table = nlmsg_flags[family](type);
440*cf84ac9aSAndroid Build Coastguard Worker
441*cf84ac9aSAndroid Build Coastguard Worker printflags_ex(flags, "NLM_F_???", XLAT_STYLE_DEFAULT,
442*cf84ac9aSAndroid Build Coastguard Worker netlink_flags, table, NULL);
443*cf84ac9aSAndroid Build Coastguard Worker }
444*cf84ac9aSAndroid Build Coastguard Worker
445*cf84ac9aSAndroid Build Coastguard Worker static void
print_nlmsghdr(struct tcb * tcp,const int fd,const int family,const struct nlmsghdr * const nlmsghdr)446*cf84ac9aSAndroid Build Coastguard Worker print_nlmsghdr(struct tcb *tcp,
447*cf84ac9aSAndroid Build Coastguard Worker const int fd,
448*cf84ac9aSAndroid Build Coastguard Worker const int family,
449*cf84ac9aSAndroid Build Coastguard Worker const struct nlmsghdr *const nlmsghdr)
450*cf84ac9aSAndroid Build Coastguard Worker {
451*cf84ac9aSAndroid Build Coastguard Worker /* print the whole structure regardless of its nlmsg_len */
452*cf84ac9aSAndroid Build Coastguard Worker
453*cf84ac9aSAndroid Build Coastguard Worker tprintf("{len=%u, type=", nlmsghdr->nlmsg_len);
454*cf84ac9aSAndroid Build Coastguard Worker
455*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_type(tcp, nlmsghdr->nlmsg_type, family);
456*cf84ac9aSAndroid Build Coastguard Worker
457*cf84ac9aSAndroid Build Coastguard Worker tprints(", flags=");
458*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsg_flags(nlmsghdr->nlmsg_flags,
459*cf84ac9aSAndroid Build Coastguard Worker nlmsghdr->nlmsg_type, family);
460*cf84ac9aSAndroid Build Coastguard Worker
461*cf84ac9aSAndroid Build Coastguard Worker tprintf(", seq=%u, pid=%u}", nlmsghdr->nlmsg_seq,
462*cf84ac9aSAndroid Build Coastguard Worker nlmsghdr->nlmsg_pid);
463*cf84ac9aSAndroid Build Coastguard Worker }
464*cf84ac9aSAndroid Build Coastguard Worker
465*cf84ac9aSAndroid Build Coastguard Worker static bool
print_cookie(struct tcb * const tcp,void * const elem_buf,const size_t elem_size,void * const opaque_data)466*cf84ac9aSAndroid Build Coastguard Worker print_cookie(struct tcb *const tcp, void *const elem_buf,
467*cf84ac9aSAndroid Build Coastguard Worker const size_t elem_size, void *const opaque_data)
468*cf84ac9aSAndroid Build Coastguard Worker {
469*cf84ac9aSAndroid Build Coastguard Worker tprintf("%" PRIu8, *(uint8_t *) elem_buf);
470*cf84ac9aSAndroid Build Coastguard Worker
471*cf84ac9aSAndroid Build Coastguard Worker return true;
472*cf84ac9aSAndroid Build Coastguard Worker }
473*cf84ac9aSAndroid Build Coastguard Worker
474*cf84ac9aSAndroid Build Coastguard Worker static bool
decode_nlmsgerr_attr_cookie(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)475*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsgerr_attr_cookie(struct tcb *const tcp,
476*cf84ac9aSAndroid Build Coastguard Worker const kernel_ulong_t addr,
477*cf84ac9aSAndroid Build Coastguard Worker const unsigned int len,
478*cf84ac9aSAndroid Build Coastguard Worker const void *const opaque_data)
479*cf84ac9aSAndroid Build Coastguard Worker {
480*cf84ac9aSAndroid Build Coastguard Worker uint8_t cookie;
481*cf84ac9aSAndroid Build Coastguard Worker const size_t nmemb = len / sizeof(cookie);
482*cf84ac9aSAndroid Build Coastguard Worker
483*cf84ac9aSAndroid Build Coastguard Worker print_array(tcp, addr, nmemb, &cookie, sizeof(cookie),
484*cf84ac9aSAndroid Build Coastguard Worker tfetch_mem, print_cookie, 0);
485*cf84ac9aSAndroid Build Coastguard Worker
486*cf84ac9aSAndroid Build Coastguard Worker return true;
487*cf84ac9aSAndroid Build Coastguard Worker }
488*cf84ac9aSAndroid Build Coastguard Worker
489*cf84ac9aSAndroid Build Coastguard Worker static const nla_decoder_t nlmsgerr_nla_decoders[] = {
490*cf84ac9aSAndroid Build Coastguard Worker [NLMSGERR_ATTR_MSG] = decode_nla_str,
491*cf84ac9aSAndroid Build Coastguard Worker [NLMSGERR_ATTR_OFFS] = decode_nla_u32,
492*cf84ac9aSAndroid Build Coastguard Worker [NLMSGERR_ATTR_COOKIE] = decode_nlmsgerr_attr_cookie
493*cf84ac9aSAndroid Build Coastguard Worker };
494*cf84ac9aSAndroid Build Coastguard Worker
495*cf84ac9aSAndroid Build Coastguard Worker static void
496*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsghdr_with_payload(struct tcb *const tcp,
497*cf84ac9aSAndroid Build Coastguard Worker const int fd,
498*cf84ac9aSAndroid Build Coastguard Worker const int family,
499*cf84ac9aSAndroid Build Coastguard Worker const struct nlmsghdr *const nlmsghdr,
500*cf84ac9aSAndroid Build Coastguard Worker const kernel_ulong_t addr,
501*cf84ac9aSAndroid Build Coastguard Worker const kernel_ulong_t len);
502*cf84ac9aSAndroid Build Coastguard Worker
503*cf84ac9aSAndroid Build Coastguard Worker static void
decode_nlmsgerr(struct tcb * const tcp,const int fd,const int family,kernel_ulong_t addr,unsigned int len,const bool capped)504*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsgerr(struct tcb *const tcp,
505*cf84ac9aSAndroid Build Coastguard Worker const int fd,
506*cf84ac9aSAndroid Build Coastguard Worker const int family,
507*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t addr,
508*cf84ac9aSAndroid Build Coastguard Worker unsigned int len,
509*cf84ac9aSAndroid Build Coastguard Worker const bool capped)
510*cf84ac9aSAndroid Build Coastguard Worker {
511*cf84ac9aSAndroid Build Coastguard Worker struct nlmsgerr err;
512*cf84ac9aSAndroid Build Coastguard Worker
513*cf84ac9aSAndroid Build Coastguard Worker if (len < sizeof(err.error)) {
514*cf84ac9aSAndroid Build Coastguard Worker printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
515*cf84ac9aSAndroid Build Coastguard Worker return;
516*cf84ac9aSAndroid Build Coastguard Worker }
517*cf84ac9aSAndroid Build Coastguard Worker
518*cf84ac9aSAndroid Build Coastguard Worker if (umove_or_printaddr(tcp, addr, &err.error))
519*cf84ac9aSAndroid Build Coastguard Worker return;
520*cf84ac9aSAndroid Build Coastguard Worker
521*cf84ac9aSAndroid Build Coastguard Worker tprints("{error=");
522*cf84ac9aSAndroid Build Coastguard Worker if (err.error < 0 && (unsigned) -err.error < nerrnos) {
523*cf84ac9aSAndroid Build Coastguard Worker tprintf("-%s", errnoent[-err.error]);
524*cf84ac9aSAndroid Build Coastguard Worker } else {
525*cf84ac9aSAndroid Build Coastguard Worker tprintf("%d", err.error);
526*cf84ac9aSAndroid Build Coastguard Worker }
527*cf84ac9aSAndroid Build Coastguard Worker
528*cf84ac9aSAndroid Build Coastguard Worker addr += offsetof(struct nlmsgerr, msg);
529*cf84ac9aSAndroid Build Coastguard Worker len -= offsetof(struct nlmsgerr, msg);
530*cf84ac9aSAndroid Build Coastguard Worker
531*cf84ac9aSAndroid Build Coastguard Worker if (len) {
532*cf84ac9aSAndroid Build Coastguard Worker tprints(", msg=");
533*cf84ac9aSAndroid Build Coastguard Worker if (fetch_nlmsghdr(tcp, &err.msg, addr, len, false)) {
534*cf84ac9aSAndroid Build Coastguard Worker unsigned int payload =
535*cf84ac9aSAndroid Build Coastguard Worker capped ? sizeof(err.msg) : err.msg.nlmsg_len;
536*cf84ac9aSAndroid Build Coastguard Worker if (payload > len)
537*cf84ac9aSAndroid Build Coastguard Worker payload = len;
538*cf84ac9aSAndroid Build Coastguard Worker
539*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsghdr_with_payload(tcp, fd, family,
540*cf84ac9aSAndroid Build Coastguard Worker &err.msg, addr, payload);
541*cf84ac9aSAndroid Build Coastguard Worker if (len > payload) {
542*cf84ac9aSAndroid Build Coastguard Worker tprints(", ");
543*cf84ac9aSAndroid Build Coastguard Worker decode_nlattr(tcp, addr + payload,
544*cf84ac9aSAndroid Build Coastguard Worker len - payload, nlmsgerr_attrs,
545*cf84ac9aSAndroid Build Coastguard Worker "NLMSGERR_ATTR_???",
546*cf84ac9aSAndroid Build Coastguard Worker nlmsgerr_nla_decoders,
547*cf84ac9aSAndroid Build Coastguard Worker ARRAY_SIZE(nlmsgerr_nla_decoders),
548*cf84ac9aSAndroid Build Coastguard Worker NULL);
549*cf84ac9aSAndroid Build Coastguard Worker }
550*cf84ac9aSAndroid Build Coastguard Worker }
551*cf84ac9aSAndroid Build Coastguard Worker }
552*cf84ac9aSAndroid Build Coastguard Worker
553*cf84ac9aSAndroid Build Coastguard Worker tprints("}");
554*cf84ac9aSAndroid Build Coastguard Worker }
555*cf84ac9aSAndroid Build Coastguard Worker
556*cf84ac9aSAndroid Build Coastguard Worker static const netlink_decoder_t netlink_decoders[] = {
557*cf84ac9aSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_CRYPTOUSER_H
558*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_CRYPTO] = decode_netlink_crypto,
559*cf84ac9aSAndroid Build Coastguard Worker #endif
560*cf84ac9aSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_NETFILTER_NFNETLINK_H
561*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_NETFILTER] = decode_netlink_netfilter,
562*cf84ac9aSAndroid Build Coastguard Worker #endif
563*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_ROUTE] = decode_netlink_route,
564*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_SELINUX] = decode_netlink_selinux,
565*cf84ac9aSAndroid Build Coastguard Worker [NETLINK_SOCK_DIAG] = decode_netlink_sock_diag
566*cf84ac9aSAndroid Build Coastguard Worker };
567*cf84ac9aSAndroid Build Coastguard Worker
568*cf84ac9aSAndroid Build Coastguard Worker static void
decode_payload(struct tcb * const tcp,const int fd,const int family,const struct nlmsghdr * const nlmsghdr,const kernel_ulong_t addr,const unsigned int len)569*cf84ac9aSAndroid Build Coastguard Worker decode_payload(struct tcb *const tcp,
570*cf84ac9aSAndroid Build Coastguard Worker const int fd,
571*cf84ac9aSAndroid Build Coastguard Worker const int family,
572*cf84ac9aSAndroid Build Coastguard Worker const struct nlmsghdr *const nlmsghdr,
573*cf84ac9aSAndroid Build Coastguard Worker const kernel_ulong_t addr,
574*cf84ac9aSAndroid Build Coastguard Worker const unsigned int len)
575*cf84ac9aSAndroid Build Coastguard Worker {
576*cf84ac9aSAndroid Build Coastguard Worker if (nlmsghdr->nlmsg_type == NLMSG_ERROR) {
577*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsgerr(tcp, fd, family, addr, len,
578*cf84ac9aSAndroid Build Coastguard Worker nlmsghdr->nlmsg_flags & NLM_F_CAPPED);
579*cf84ac9aSAndroid Build Coastguard Worker return;
580*cf84ac9aSAndroid Build Coastguard Worker }
581*cf84ac9aSAndroid Build Coastguard Worker
582*cf84ac9aSAndroid Build Coastguard Worker /*
583*cf84ac9aSAndroid Build Coastguard Worker * While most of NLMSG_DONE messages indeed have payloads
584*cf84ac9aSAndroid Build Coastguard Worker * containing just a single integer, there are few exceptions,
585*cf84ac9aSAndroid Build Coastguard Worker * so pass payloads of NLMSG_DONE messages to family-specific
586*cf84ac9aSAndroid Build Coastguard Worker * netlink payload decoders.
587*cf84ac9aSAndroid Build Coastguard Worker *
588*cf84ac9aSAndroid Build Coastguard Worker * Other types of reserved control messages need no family-specific
589*cf84ac9aSAndroid Build Coastguard Worker * netlink payload decoding.
590*cf84ac9aSAndroid Build Coastguard Worker */
591*cf84ac9aSAndroid Build Coastguard Worker if ((nlmsghdr->nlmsg_type >= NLMSG_MIN_TYPE
592*cf84ac9aSAndroid Build Coastguard Worker || nlmsghdr->nlmsg_type == NLMSG_DONE)
593*cf84ac9aSAndroid Build Coastguard Worker && (unsigned int) family < ARRAY_SIZE(netlink_decoders)
594*cf84ac9aSAndroid Build Coastguard Worker && netlink_decoders[family]
595*cf84ac9aSAndroid Build Coastguard Worker && netlink_decoders[family](tcp, nlmsghdr, addr, len)) {
596*cf84ac9aSAndroid Build Coastguard Worker return;
597*cf84ac9aSAndroid Build Coastguard Worker }
598*cf84ac9aSAndroid Build Coastguard Worker
599*cf84ac9aSAndroid Build Coastguard Worker if (nlmsghdr->nlmsg_type == NLMSG_DONE && len == sizeof(int)) {
600*cf84ac9aSAndroid Build Coastguard Worker int num;
601*cf84ac9aSAndroid Build Coastguard Worker
602*cf84ac9aSAndroid Build Coastguard Worker if (!umove_or_printaddr(tcp, addr, &num))
603*cf84ac9aSAndroid Build Coastguard Worker tprintf("%d", num);
604*cf84ac9aSAndroid Build Coastguard Worker return;
605*cf84ac9aSAndroid Build Coastguard Worker }
606*cf84ac9aSAndroid Build Coastguard Worker
607*cf84ac9aSAndroid Build Coastguard Worker printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
608*cf84ac9aSAndroid Build Coastguard Worker }
609*cf84ac9aSAndroid Build Coastguard Worker
610*cf84ac9aSAndroid Build Coastguard Worker static void
decode_nlmsghdr_with_payload(struct tcb * const tcp,const int fd,const int family,const struct nlmsghdr * const nlmsghdr,const kernel_ulong_t addr,const kernel_ulong_t len)611*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsghdr_with_payload(struct tcb *const tcp,
612*cf84ac9aSAndroid Build Coastguard Worker const int fd,
613*cf84ac9aSAndroid Build Coastguard Worker const int family,
614*cf84ac9aSAndroid Build Coastguard Worker const struct nlmsghdr *const nlmsghdr,
615*cf84ac9aSAndroid Build Coastguard Worker const kernel_ulong_t addr,
616*cf84ac9aSAndroid Build Coastguard Worker const kernel_ulong_t len)
617*cf84ac9aSAndroid Build Coastguard Worker {
618*cf84ac9aSAndroid Build Coastguard Worker const unsigned int nlmsg_len = MIN(nlmsghdr->nlmsg_len, len);
619*cf84ac9aSAndroid Build Coastguard Worker
620*cf84ac9aSAndroid Build Coastguard Worker if (nlmsg_len > NLMSG_HDRLEN)
621*cf84ac9aSAndroid Build Coastguard Worker tprints("{");
622*cf84ac9aSAndroid Build Coastguard Worker
623*cf84ac9aSAndroid Build Coastguard Worker print_nlmsghdr(tcp, fd, family, nlmsghdr);
624*cf84ac9aSAndroid Build Coastguard Worker
625*cf84ac9aSAndroid Build Coastguard Worker if (nlmsg_len > NLMSG_HDRLEN) {
626*cf84ac9aSAndroid Build Coastguard Worker tprints(", ");
627*cf84ac9aSAndroid Build Coastguard Worker decode_payload(tcp, fd, family, nlmsghdr, addr + NLMSG_HDRLEN,
628*cf84ac9aSAndroid Build Coastguard Worker nlmsg_len - NLMSG_HDRLEN);
629*cf84ac9aSAndroid Build Coastguard Worker tprints("}");
630*cf84ac9aSAndroid Build Coastguard Worker }
631*cf84ac9aSAndroid Build Coastguard Worker }
632*cf84ac9aSAndroid Build Coastguard Worker
633*cf84ac9aSAndroid Build Coastguard Worker void
decode_netlink(struct tcb * const tcp,const int fd,kernel_ulong_t addr,kernel_ulong_t len)634*cf84ac9aSAndroid Build Coastguard Worker decode_netlink(struct tcb *const tcp,
635*cf84ac9aSAndroid Build Coastguard Worker const int fd,
636*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t addr,
637*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t len)
638*cf84ac9aSAndroid Build Coastguard Worker {
639*cf84ac9aSAndroid Build Coastguard Worker const int family = get_fd_nl_family(tcp, fd);
640*cf84ac9aSAndroid Build Coastguard Worker
641*cf84ac9aSAndroid Build Coastguard Worker if (family == NETLINK_KOBJECT_UEVENT) {
642*cf84ac9aSAndroid Build Coastguard Worker decode_netlink_kobject_uevent(tcp, addr, len);
643*cf84ac9aSAndroid Build Coastguard Worker return;
644*cf84ac9aSAndroid Build Coastguard Worker }
645*cf84ac9aSAndroid Build Coastguard Worker
646*cf84ac9aSAndroid Build Coastguard Worker struct nlmsghdr nlmsghdr;
647*cf84ac9aSAndroid Build Coastguard Worker bool is_array = false;
648*cf84ac9aSAndroid Build Coastguard Worker unsigned int elt;
649*cf84ac9aSAndroid Build Coastguard Worker
650*cf84ac9aSAndroid Build Coastguard Worker for (elt = 0; fetch_nlmsghdr(tcp, &nlmsghdr, addr, len, is_array);
651*cf84ac9aSAndroid Build Coastguard Worker elt++) {
652*cf84ac9aSAndroid Build Coastguard Worker if (abbrev(tcp) && elt == max_strlen) {
653*cf84ac9aSAndroid Build Coastguard Worker tprints("...");
654*cf84ac9aSAndroid Build Coastguard Worker break;
655*cf84ac9aSAndroid Build Coastguard Worker }
656*cf84ac9aSAndroid Build Coastguard Worker
657*cf84ac9aSAndroid Build Coastguard Worker unsigned int nlmsg_len = NLMSG_ALIGN(nlmsghdr.nlmsg_len);
658*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t next_addr = 0;
659*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t next_len = 0;
660*cf84ac9aSAndroid Build Coastguard Worker
661*cf84ac9aSAndroid Build Coastguard Worker if (nlmsghdr.nlmsg_len >= NLMSG_HDRLEN) {
662*cf84ac9aSAndroid Build Coastguard Worker next_len = (len >= nlmsg_len) ? len - nlmsg_len : 0;
663*cf84ac9aSAndroid Build Coastguard Worker
664*cf84ac9aSAndroid Build Coastguard Worker if (next_len && addr + nlmsg_len > addr)
665*cf84ac9aSAndroid Build Coastguard Worker next_addr = addr + nlmsg_len;
666*cf84ac9aSAndroid Build Coastguard Worker }
667*cf84ac9aSAndroid Build Coastguard Worker
668*cf84ac9aSAndroid Build Coastguard Worker if (!is_array && next_addr) {
669*cf84ac9aSAndroid Build Coastguard Worker tprints("[");
670*cf84ac9aSAndroid Build Coastguard Worker is_array = true;
671*cf84ac9aSAndroid Build Coastguard Worker }
672*cf84ac9aSAndroid Build Coastguard Worker
673*cf84ac9aSAndroid Build Coastguard Worker decode_nlmsghdr_with_payload(tcp, fd, family,
674*cf84ac9aSAndroid Build Coastguard Worker &nlmsghdr, addr, len);
675*cf84ac9aSAndroid Build Coastguard Worker
676*cf84ac9aSAndroid Build Coastguard Worker if (!next_addr)
677*cf84ac9aSAndroid Build Coastguard Worker break;
678*cf84ac9aSAndroid Build Coastguard Worker
679*cf84ac9aSAndroid Build Coastguard Worker tprints(", ");
680*cf84ac9aSAndroid Build Coastguard Worker addr = next_addr;
681*cf84ac9aSAndroid Build Coastguard Worker len = next_len;
682*cf84ac9aSAndroid Build Coastguard Worker }
683*cf84ac9aSAndroid Build Coastguard Worker
684*cf84ac9aSAndroid Build Coastguard Worker if (is_array) {
685*cf84ac9aSAndroid Build Coastguard Worker tprints("]");
686*cf84ac9aSAndroid Build Coastguard Worker }
687*cf84ac9aSAndroid Build Coastguard Worker }
688