xref: /aosp_15_r20/external/strace/msghdr.c (revision cf84ac9a129d8ea9952db616b4e9b904c4bdde56)
1*cf84ac9aSAndroid Build Coastguard Worker /*
2*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1991, 1992 Paul Kranenburg <[email protected]>
3*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1993 Branko Lankester <[email protected]>
4*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <[email protected]>
5*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 1996-2000 Wichert Akkerman <[email protected]>
6*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 2005-2016 Dmitry V. Levin <[email protected]>
7*cf84ac9aSAndroid Build Coastguard Worker  * Copyright (c) 2016-2018 The strace developers.
8*cf84ac9aSAndroid Build Coastguard Worker  * All rights reserved.
9*cf84ac9aSAndroid Build Coastguard Worker  *
10*cf84ac9aSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
11*cf84ac9aSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
12*cf84ac9aSAndroid Build Coastguard Worker  * are met:
13*cf84ac9aSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
14*cf84ac9aSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
15*cf84ac9aSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
16*cf84ac9aSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
17*cf84ac9aSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
18*cf84ac9aSAndroid Build Coastguard Worker  * 3. The name of the author may not be used to endorse or promote products
19*cf84ac9aSAndroid Build Coastguard Worker  *    derived from this software without specific prior written permission.
20*cf84ac9aSAndroid Build Coastguard Worker  *
21*cf84ac9aSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22*cf84ac9aSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23*cf84ac9aSAndroid Build Coastguard Worker  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24*cf84ac9aSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25*cf84ac9aSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26*cf84ac9aSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*cf84ac9aSAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*cf84ac9aSAndroid Build Coastguard Worker  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*cf84ac9aSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30*cf84ac9aSAndroid Build Coastguard Worker  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*cf84ac9aSAndroid Build Coastguard Worker  */
32*cf84ac9aSAndroid Build Coastguard Worker 
33*cf84ac9aSAndroid Build Coastguard Worker #include "defs.h"
34*cf84ac9aSAndroid Build Coastguard Worker #include "print_fields.h"
35*cf84ac9aSAndroid Build Coastguard Worker #include "msghdr.h"
36*cf84ac9aSAndroid Build Coastguard Worker #include <limits.h>
37*cf84ac9aSAndroid Build Coastguard Worker #include <arpa/inet.h>
38*cf84ac9aSAndroid Build Coastguard Worker #include <netinet/in.h>
39*cf84ac9aSAndroid Build Coastguard Worker 
40*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/msg_flags.h"
41*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/scmvals.h"
42*cf84ac9aSAndroid Build Coastguard Worker #include "xlat/ip_cmsg_types.h"
43*cf84ac9aSAndroid Build Coastguard Worker 
44*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_wordsize
45*cf84ac9aSAndroid Build Coastguard Worker struct cmsghdr32 {
46*cf84ac9aSAndroid Build Coastguard Worker 	uint32_t cmsg_len;
47*cf84ac9aSAndroid Build Coastguard Worker 	int cmsg_level;
48*cf84ac9aSAndroid Build Coastguard Worker 	int cmsg_type;
49*cf84ac9aSAndroid Build Coastguard Worker };
50*cf84ac9aSAndroid Build Coastguard Worker #endif
51*cf84ac9aSAndroid Build Coastguard Worker 
52*cf84ac9aSAndroid Build Coastguard Worker typedef union {
53*cf84ac9aSAndroid Build Coastguard Worker 	char *ptr;
54*cf84ac9aSAndroid Build Coastguard Worker 	struct cmsghdr *cmsg;
55*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_wordsize
56*cf84ac9aSAndroid Build Coastguard Worker 	struct cmsghdr32 *cmsg32;
57*cf84ac9aSAndroid Build Coastguard Worker #endif
58*cf84ac9aSAndroid Build Coastguard Worker } union_cmsghdr;
59*cf84ac9aSAndroid Build Coastguard Worker 
60*cf84ac9aSAndroid Build Coastguard Worker static void
print_scm_rights(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)61*cf84ac9aSAndroid Build Coastguard Worker print_scm_rights(struct tcb *tcp, const void *cmsg_data,
62*cf84ac9aSAndroid Build Coastguard Worker 		 const unsigned int data_len)
63*cf84ac9aSAndroid Build Coastguard Worker {
64*cf84ac9aSAndroid Build Coastguard Worker 	const int *fds = cmsg_data;
65*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned int nfds = data_len / sizeof(*fds);
66*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int i;
67*cf84ac9aSAndroid Build Coastguard Worker 
68*cf84ac9aSAndroid Build Coastguard Worker 	tprints("[");
69*cf84ac9aSAndroid Build Coastguard Worker 
70*cf84ac9aSAndroid Build Coastguard Worker 	for (i = 0; i < nfds; ++i) {
71*cf84ac9aSAndroid Build Coastguard Worker 		if (i)
72*cf84ac9aSAndroid Build Coastguard Worker 			tprints(", ");
73*cf84ac9aSAndroid Build Coastguard Worker 		if (abbrev(tcp) && i >= max_strlen) {
74*cf84ac9aSAndroid Build Coastguard Worker 			tprints("...");
75*cf84ac9aSAndroid Build Coastguard Worker 			break;
76*cf84ac9aSAndroid Build Coastguard Worker 		}
77*cf84ac9aSAndroid Build Coastguard Worker 		printfd(tcp, fds[i]);
78*cf84ac9aSAndroid Build Coastguard Worker 	}
79*cf84ac9aSAndroid Build Coastguard Worker 
80*cf84ac9aSAndroid Build Coastguard Worker 	tprints("]");
81*cf84ac9aSAndroid Build Coastguard Worker }
82*cf84ac9aSAndroid Build Coastguard Worker 
83*cf84ac9aSAndroid Build Coastguard Worker static void
print_scm_creds(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)84*cf84ac9aSAndroid Build Coastguard Worker print_scm_creds(struct tcb *tcp, const void *cmsg_data,
85*cf84ac9aSAndroid Build Coastguard Worker 		const unsigned int data_len)
86*cf84ac9aSAndroid Build Coastguard Worker {
87*cf84ac9aSAndroid Build Coastguard Worker 	const struct ucred *uc = cmsg_data;
88*cf84ac9aSAndroid Build Coastguard Worker 
89*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U("{", *uc, pid);
90*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_UID(", ", *uc, uid);
91*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_UID(", ", *uc, gid);
92*cf84ac9aSAndroid Build Coastguard Worker 	tprints("}");
93*cf84ac9aSAndroid Build Coastguard Worker }
94*cf84ac9aSAndroid Build Coastguard Worker 
95*cf84ac9aSAndroid Build Coastguard Worker static void
print_scm_security(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)96*cf84ac9aSAndroid Build Coastguard Worker print_scm_security(struct tcb *tcp, const void *cmsg_data,
97*cf84ac9aSAndroid Build Coastguard Worker 		   const unsigned int data_len)
98*cf84ac9aSAndroid Build Coastguard Worker {
99*cf84ac9aSAndroid Build Coastguard Worker 	print_quoted_string(cmsg_data, data_len, 0);
100*cf84ac9aSAndroid Build Coastguard Worker }
101*cf84ac9aSAndroid Build Coastguard Worker 
102*cf84ac9aSAndroid Build Coastguard Worker static void
print_scm_timestamp(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)103*cf84ac9aSAndroid Build Coastguard Worker print_scm_timestamp(struct tcb *tcp, const void *cmsg_data,
104*cf84ac9aSAndroid Build Coastguard Worker 		    const unsigned int data_len)
105*cf84ac9aSAndroid Build Coastguard Worker {
106*cf84ac9aSAndroid Build Coastguard Worker 	print_struct_timeval_data_size(cmsg_data, data_len);
107*cf84ac9aSAndroid Build Coastguard Worker }
108*cf84ac9aSAndroid Build Coastguard Worker 
109*cf84ac9aSAndroid Build Coastguard Worker static void
print_scm_timestampns(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)110*cf84ac9aSAndroid Build Coastguard Worker print_scm_timestampns(struct tcb *tcp, const void *cmsg_data,
111*cf84ac9aSAndroid Build Coastguard Worker 		      const unsigned int data_len)
112*cf84ac9aSAndroid Build Coastguard Worker {
113*cf84ac9aSAndroid Build Coastguard Worker 	print_struct_timespec_data_size(cmsg_data, data_len);
114*cf84ac9aSAndroid Build Coastguard Worker }
115*cf84ac9aSAndroid Build Coastguard Worker 
116*cf84ac9aSAndroid Build Coastguard Worker static void
print_scm_timestamping(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)117*cf84ac9aSAndroid Build Coastguard Worker print_scm_timestamping(struct tcb *tcp, const void *cmsg_data,
118*cf84ac9aSAndroid Build Coastguard Worker 		       const unsigned int data_len)
119*cf84ac9aSAndroid Build Coastguard Worker {
120*cf84ac9aSAndroid Build Coastguard Worker 	print_struct_timespec_array_data_size(cmsg_data, 3, data_len);
121*cf84ac9aSAndroid Build Coastguard Worker }
122*cf84ac9aSAndroid Build Coastguard Worker 
123*cf84ac9aSAndroid Build Coastguard Worker static void
print_cmsg_ip_pktinfo(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)124*cf84ac9aSAndroid Build Coastguard Worker print_cmsg_ip_pktinfo(struct tcb *tcp, const void *cmsg_data,
125*cf84ac9aSAndroid Build Coastguard Worker 		      const unsigned int data_len)
126*cf84ac9aSAndroid Build Coastguard Worker {
127*cf84ac9aSAndroid Build Coastguard Worker 	const struct in_pktinfo *info = cmsg_data;
128*cf84ac9aSAndroid Build Coastguard Worker 
129*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_IFINDEX("{", *info, ipi_ifindex);
130*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_INET4_ADDR(", ", *info, ipi_spec_dst);
131*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_INET4_ADDR(", ", *info, ipi_addr);
132*cf84ac9aSAndroid Build Coastguard Worker 	tprints("}");
133*cf84ac9aSAndroid Build Coastguard Worker }
134*cf84ac9aSAndroid Build Coastguard Worker 
135*cf84ac9aSAndroid Build Coastguard Worker static void
print_cmsg_uint(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)136*cf84ac9aSAndroid Build Coastguard Worker print_cmsg_uint(struct tcb *tcp, const void *cmsg_data,
137*cf84ac9aSAndroid Build Coastguard Worker 		const unsigned int data_len)
138*cf84ac9aSAndroid Build Coastguard Worker {
139*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned int *p = cmsg_data;
140*cf84ac9aSAndroid Build Coastguard Worker 
141*cf84ac9aSAndroid Build Coastguard Worker 	tprintf("[%u]", *p);
142*cf84ac9aSAndroid Build Coastguard Worker }
143*cf84ac9aSAndroid Build Coastguard Worker 
144*cf84ac9aSAndroid Build Coastguard Worker static void
print_cmsg_uint8_t(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)145*cf84ac9aSAndroid Build Coastguard Worker print_cmsg_uint8_t(struct tcb *tcp, const void *cmsg_data,
146*cf84ac9aSAndroid Build Coastguard Worker 		   const unsigned int data_len)
147*cf84ac9aSAndroid Build Coastguard Worker {
148*cf84ac9aSAndroid Build Coastguard Worker 	const uint8_t *p = cmsg_data;
149*cf84ac9aSAndroid Build Coastguard Worker 
150*cf84ac9aSAndroid Build Coastguard Worker 	tprintf("[%#x]", *p);
151*cf84ac9aSAndroid Build Coastguard Worker }
152*cf84ac9aSAndroid Build Coastguard Worker 
153*cf84ac9aSAndroid Build Coastguard Worker static void
print_cmsg_ip_opts(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)154*cf84ac9aSAndroid Build Coastguard Worker print_cmsg_ip_opts(struct tcb *tcp, const void *cmsg_data,
155*cf84ac9aSAndroid Build Coastguard Worker 		   const unsigned int data_len)
156*cf84ac9aSAndroid Build Coastguard Worker {
157*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned char *opts = cmsg_data;
158*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int i;
159*cf84ac9aSAndroid Build Coastguard Worker 
160*cf84ac9aSAndroid Build Coastguard Worker 	tprints("[");
161*cf84ac9aSAndroid Build Coastguard Worker 	for (i = 0; i < data_len; ++i) {
162*cf84ac9aSAndroid Build Coastguard Worker 		if (i)
163*cf84ac9aSAndroid Build Coastguard Worker 			tprints(", ");
164*cf84ac9aSAndroid Build Coastguard Worker 		if (abbrev(tcp) && i >= max_strlen) {
165*cf84ac9aSAndroid Build Coastguard Worker 			tprints("...");
166*cf84ac9aSAndroid Build Coastguard Worker 			break;
167*cf84ac9aSAndroid Build Coastguard Worker 		}
168*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("0x%02x", opts[i]);
169*cf84ac9aSAndroid Build Coastguard Worker 	}
170*cf84ac9aSAndroid Build Coastguard Worker 	tprints("]");
171*cf84ac9aSAndroid Build Coastguard Worker }
172*cf84ac9aSAndroid Build Coastguard Worker 
173*cf84ac9aSAndroid Build Coastguard Worker struct sock_ee {
174*cf84ac9aSAndroid Build Coastguard Worker 	uint32_t ee_errno;
175*cf84ac9aSAndroid Build Coastguard Worker 	uint8_t  ee_origin;
176*cf84ac9aSAndroid Build Coastguard Worker 	uint8_t  ee_type;
177*cf84ac9aSAndroid Build Coastguard Worker 	uint8_t  ee_code;
178*cf84ac9aSAndroid Build Coastguard Worker 	uint8_t  ee_pad;
179*cf84ac9aSAndroid Build Coastguard Worker 	uint32_t ee_info;
180*cf84ac9aSAndroid Build Coastguard Worker 	uint32_t ee_data;
181*cf84ac9aSAndroid Build Coastguard Worker 	struct sockaddr_in offender;
182*cf84ac9aSAndroid Build Coastguard Worker };
183*cf84ac9aSAndroid Build Coastguard Worker 
184*cf84ac9aSAndroid Build Coastguard Worker static void
print_cmsg_ip_recverr(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)185*cf84ac9aSAndroid Build Coastguard Worker print_cmsg_ip_recverr(struct tcb *tcp, const void *cmsg_data,
186*cf84ac9aSAndroid Build Coastguard Worker 		      const unsigned int data_len)
187*cf84ac9aSAndroid Build Coastguard Worker {
188*cf84ac9aSAndroid Build Coastguard Worker 	const struct sock_ee *const err = cmsg_data;
189*cf84ac9aSAndroid Build Coastguard Worker 
190*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U("{", *err, ee_errno);
191*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U(", ", *err, ee_origin);
192*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U(", ", *err, ee_type);
193*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U(", ", *err, ee_code);
194*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U(", ", *err, ee_info);
195*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U(", ", *err, ee_data);
196*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_SOCKADDR(", ", *err, offender);
197*cf84ac9aSAndroid Build Coastguard Worker 	tprints("}");
198*cf84ac9aSAndroid Build Coastguard Worker }
199*cf84ac9aSAndroid Build Coastguard Worker 
200*cf84ac9aSAndroid Build Coastguard Worker static void
print_cmsg_ip_origdstaddr(struct tcb * tcp,const void * cmsg_data,const unsigned int data_len)201*cf84ac9aSAndroid Build Coastguard Worker print_cmsg_ip_origdstaddr(struct tcb *tcp, const void *cmsg_data,
202*cf84ac9aSAndroid Build Coastguard Worker 			  const unsigned int data_len)
203*cf84ac9aSAndroid Build Coastguard Worker {
204*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned int addr_len =
205*cf84ac9aSAndroid Build Coastguard Worker 		data_len > sizeof(struct sockaddr_storage)
206*cf84ac9aSAndroid Build Coastguard Worker 		? sizeof(struct sockaddr_storage) : data_len;
207*cf84ac9aSAndroid Build Coastguard Worker 
208*cf84ac9aSAndroid Build Coastguard Worker 	print_sockaddr(cmsg_data, addr_len);
209*cf84ac9aSAndroid Build Coastguard Worker }
210*cf84ac9aSAndroid Build Coastguard Worker 
211*cf84ac9aSAndroid Build Coastguard Worker typedef void (* const cmsg_printer)(struct tcb *, const void *, unsigned int);
212*cf84ac9aSAndroid Build Coastguard Worker 
213*cf84ac9aSAndroid Build Coastguard Worker static const struct {
214*cf84ac9aSAndroid Build Coastguard Worker 	const cmsg_printer printer;
215*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned int min_len;
216*cf84ac9aSAndroid Build Coastguard Worker } cmsg_socket_printers[] = {
217*cf84ac9aSAndroid Build Coastguard Worker 	[SCM_RIGHTS] = { print_scm_rights, sizeof(int) },
218*cf84ac9aSAndroid Build Coastguard Worker 	[SCM_CREDENTIALS] = { print_scm_creds, sizeof(struct ucred) },
219*cf84ac9aSAndroid Build Coastguard Worker 	[SCM_SECURITY] = { print_scm_security, 1 },
220*cf84ac9aSAndroid Build Coastguard Worker 	[SCM_TIMESTAMP] = { print_scm_timestamp, 1 },
221*cf84ac9aSAndroid Build Coastguard Worker 	[SCM_TIMESTAMPNS] = { print_scm_timestampns, 1 },
222*cf84ac9aSAndroid Build Coastguard Worker 	[SCM_TIMESTAMPING] = { print_scm_timestamping, 1 }
223*cf84ac9aSAndroid Build Coastguard Worker }, cmsg_ip_printers[] = {
224*cf84ac9aSAndroid Build Coastguard Worker 	[IP_PKTINFO] = { print_cmsg_ip_pktinfo, sizeof(struct in_pktinfo) },
225*cf84ac9aSAndroid Build Coastguard Worker 	[IP_TTL] = { print_cmsg_uint, sizeof(unsigned int) },
226*cf84ac9aSAndroid Build Coastguard Worker 	[IP_TOS] = { print_cmsg_uint8_t, 1 },
227*cf84ac9aSAndroid Build Coastguard Worker 	[IP_RECVOPTS] = { print_cmsg_ip_opts, 1 },
228*cf84ac9aSAndroid Build Coastguard Worker 	[IP_RETOPTS] = { print_cmsg_ip_opts, 1 },
229*cf84ac9aSAndroid Build Coastguard Worker 	[IP_RECVERR] = { print_cmsg_ip_recverr, sizeof(struct sock_ee) },
230*cf84ac9aSAndroid Build Coastguard Worker 	[IP_ORIGDSTADDR] = { print_cmsg_ip_origdstaddr, sizeof(struct sockaddr_in) },
231*cf84ac9aSAndroid Build Coastguard Worker 	[IP_CHECKSUM] = { print_cmsg_uint, sizeof(unsigned int) },
232*cf84ac9aSAndroid Build Coastguard Worker 	[SCM_SECURITY] = { print_scm_security, 1 }
233*cf84ac9aSAndroid Build Coastguard Worker };
234*cf84ac9aSAndroid Build Coastguard Worker 
235*cf84ac9aSAndroid Build Coastguard Worker static void
print_cmsg_type_data(struct tcb * tcp,const int cmsg_level,const int cmsg_type,const void * cmsg_data,const unsigned int data_len)236*cf84ac9aSAndroid Build Coastguard Worker print_cmsg_type_data(struct tcb *tcp, const int cmsg_level, const int cmsg_type,
237*cf84ac9aSAndroid Build Coastguard Worker 		     const void *cmsg_data, const unsigned int data_len)
238*cf84ac9aSAndroid Build Coastguard Worker {
239*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned int utype = cmsg_type;
240*cf84ac9aSAndroid Build Coastguard Worker 	switch (cmsg_level) {
241*cf84ac9aSAndroid Build Coastguard Worker 	case SOL_SOCKET:
242*cf84ac9aSAndroid Build Coastguard Worker 		printxval(scmvals, cmsg_type, "SCM_???");
243*cf84ac9aSAndroid Build Coastguard Worker 		if (utype < ARRAY_SIZE(cmsg_socket_printers)
244*cf84ac9aSAndroid Build Coastguard Worker 		    && cmsg_socket_printers[utype].printer
245*cf84ac9aSAndroid Build Coastguard Worker 		    && data_len >= cmsg_socket_printers[utype].min_len) {
246*cf84ac9aSAndroid Build Coastguard Worker 			tprints(", cmsg_data=");
247*cf84ac9aSAndroid Build Coastguard Worker 			cmsg_socket_printers[utype].printer(tcp, cmsg_data, data_len);
248*cf84ac9aSAndroid Build Coastguard Worker 		}
249*cf84ac9aSAndroid Build Coastguard Worker 		break;
250*cf84ac9aSAndroid Build Coastguard Worker 	case SOL_IP:
251*cf84ac9aSAndroid Build Coastguard Worker 		printxval(ip_cmsg_types, cmsg_type, "IP_???");
252*cf84ac9aSAndroid Build Coastguard Worker 		if (utype < ARRAY_SIZE(cmsg_ip_printers)
253*cf84ac9aSAndroid Build Coastguard Worker 		    && cmsg_ip_printers[utype].printer
254*cf84ac9aSAndroid Build Coastguard Worker 		    && data_len >= cmsg_ip_printers[utype].min_len) {
255*cf84ac9aSAndroid Build Coastguard Worker 			tprints(", cmsg_data=");
256*cf84ac9aSAndroid Build Coastguard Worker 			cmsg_ip_printers[utype].printer(tcp, cmsg_data, data_len);
257*cf84ac9aSAndroid Build Coastguard Worker 		}
258*cf84ac9aSAndroid Build Coastguard Worker 		break;
259*cf84ac9aSAndroid Build Coastguard Worker 	default:
260*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("%#x", cmsg_type);
261*cf84ac9aSAndroid Build Coastguard Worker 	}
262*cf84ac9aSAndroid Build Coastguard Worker }
263*cf84ac9aSAndroid Build Coastguard Worker 
264*cf84ac9aSAndroid Build Coastguard Worker static unsigned int
get_optmem_max(struct tcb * tcp)265*cf84ac9aSAndroid Build Coastguard Worker get_optmem_max(struct tcb *tcp)
266*cf84ac9aSAndroid Build Coastguard Worker {
267*cf84ac9aSAndroid Build Coastguard Worker 	static int optmem_max;
268*cf84ac9aSAndroid Build Coastguard Worker 
269*cf84ac9aSAndroid Build Coastguard Worker 	if (!optmem_max) {
270*cf84ac9aSAndroid Build Coastguard Worker 		if (read_int_from_file(tcp, "/proc/sys/net/core/optmem_max",
271*cf84ac9aSAndroid Build Coastguard Worker 				       &optmem_max) || optmem_max <= 0) {
272*cf84ac9aSAndroid Build Coastguard Worker 			optmem_max = sizeof(long long) * (2 * IOV_MAX + 512);
273*cf84ac9aSAndroid Build Coastguard Worker 		} else {
274*cf84ac9aSAndroid Build Coastguard Worker 			optmem_max = (optmem_max + sizeof(long long) - 1)
275*cf84ac9aSAndroid Build Coastguard Worker 				     & ~(sizeof(long long) - 1);
276*cf84ac9aSAndroid Build Coastguard Worker 		}
277*cf84ac9aSAndroid Build Coastguard Worker 	}
278*cf84ac9aSAndroid Build Coastguard Worker 
279*cf84ac9aSAndroid Build Coastguard Worker 	return optmem_max;
280*cf84ac9aSAndroid Build Coastguard Worker }
281*cf84ac9aSAndroid Build Coastguard Worker 
282*cf84ac9aSAndroid Build Coastguard Worker static void
decode_msg_control(struct tcb * const tcp,const kernel_ulong_t addr,const kernel_ulong_t in_control_len)283*cf84ac9aSAndroid Build Coastguard Worker decode_msg_control(struct tcb *const tcp, const kernel_ulong_t addr,
284*cf84ac9aSAndroid Build Coastguard Worker 		   const kernel_ulong_t in_control_len)
285*cf84ac9aSAndroid Build Coastguard Worker {
286*cf84ac9aSAndroid Build Coastguard Worker 	if (!in_control_len)
287*cf84ac9aSAndroid Build Coastguard Worker 		return;
288*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", msg_control=");
289*cf84ac9aSAndroid Build Coastguard Worker 
290*cf84ac9aSAndroid Build Coastguard Worker 	const unsigned int cmsg_size =
291*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_wordsize
292*cf84ac9aSAndroid Build Coastguard Worker 		(current_wordsize < sizeof(long)) ? sizeof(struct cmsghdr32) :
293*cf84ac9aSAndroid Build Coastguard Worker #endif
294*cf84ac9aSAndroid Build Coastguard Worker 			sizeof(struct cmsghdr);
295*cf84ac9aSAndroid Build Coastguard Worker 
296*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int control_len = in_control_len > get_optmem_max(tcp)
297*cf84ac9aSAndroid Build Coastguard Worker 				   ? get_optmem_max(tcp) : in_control_len;
298*cf84ac9aSAndroid Build Coastguard Worker 	unsigned int buf_len = control_len;
299*cf84ac9aSAndroid Build Coastguard Worker 	char *buf = buf_len < cmsg_size ? NULL : malloc(buf_len);
300*cf84ac9aSAndroid Build Coastguard Worker 	if (!buf || umoven(tcp, addr, buf_len, buf) < 0) {
301*cf84ac9aSAndroid Build Coastguard Worker 		printaddr(addr);
302*cf84ac9aSAndroid Build Coastguard Worker 		free(buf);
303*cf84ac9aSAndroid Build Coastguard Worker 		return;
304*cf84ac9aSAndroid Build Coastguard Worker 	}
305*cf84ac9aSAndroid Build Coastguard Worker 
306*cf84ac9aSAndroid Build Coastguard Worker 	union_cmsghdr u = { .ptr = buf };
307*cf84ac9aSAndroid Build Coastguard Worker 
308*cf84ac9aSAndroid Build Coastguard Worker 	tprints("[");
309*cf84ac9aSAndroid Build Coastguard Worker 	while (buf_len >= cmsg_size) {
310*cf84ac9aSAndroid Build Coastguard Worker 		const kernel_ulong_t cmsg_len =
311*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_wordsize
312*cf84ac9aSAndroid Build Coastguard Worker 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_len :
313*cf84ac9aSAndroid Build Coastguard Worker #endif
314*cf84ac9aSAndroid Build Coastguard Worker 				u.cmsg->cmsg_len;
315*cf84ac9aSAndroid Build Coastguard Worker 		const int cmsg_level =
316*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_wordsize
317*cf84ac9aSAndroid Build Coastguard Worker 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_level :
318*cf84ac9aSAndroid Build Coastguard Worker #endif
319*cf84ac9aSAndroid Build Coastguard Worker 				u.cmsg->cmsg_level;
320*cf84ac9aSAndroid Build Coastguard Worker 		const int cmsg_type =
321*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_wordsize
322*cf84ac9aSAndroid Build Coastguard Worker 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_type :
323*cf84ac9aSAndroid Build Coastguard Worker #endif
324*cf84ac9aSAndroid Build Coastguard Worker 				u.cmsg->cmsg_type;
325*cf84ac9aSAndroid Build Coastguard Worker 
326*cf84ac9aSAndroid Build Coastguard Worker 		if (u.ptr != buf)
327*cf84ac9aSAndroid Build Coastguard Worker 			tprints(", ");
328*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("{cmsg_len=%" PRI_klu ", cmsg_level=", cmsg_len);
329*cf84ac9aSAndroid Build Coastguard Worker 		printxval(socketlayers, cmsg_level, "SOL_???");
330*cf84ac9aSAndroid Build Coastguard Worker 		tprints(", cmsg_type=");
331*cf84ac9aSAndroid Build Coastguard Worker 
332*cf84ac9aSAndroid Build Coastguard Worker 		kernel_ulong_t len = cmsg_len > buf_len ? buf_len : cmsg_len;
333*cf84ac9aSAndroid Build Coastguard Worker 
334*cf84ac9aSAndroid Build Coastguard Worker 		print_cmsg_type_data(tcp, cmsg_level, cmsg_type,
335*cf84ac9aSAndroid Build Coastguard Worker 				     (const void *) (u.ptr + cmsg_size),
336*cf84ac9aSAndroid Build Coastguard Worker 				     len > cmsg_size ? len - cmsg_size : 0);
337*cf84ac9aSAndroid Build Coastguard Worker 		tprints("}");
338*cf84ac9aSAndroid Build Coastguard Worker 
339*cf84ac9aSAndroid Build Coastguard Worker 		if (len < cmsg_size) {
340*cf84ac9aSAndroid Build Coastguard Worker 			buf_len -= cmsg_size;
341*cf84ac9aSAndroid Build Coastguard Worker 			break;
342*cf84ac9aSAndroid Build Coastguard Worker 		}
343*cf84ac9aSAndroid Build Coastguard Worker 		len = (cmsg_len + current_wordsize - 1) &
344*cf84ac9aSAndroid Build Coastguard Worker 			~((kernel_ulong_t) current_wordsize - 1);
345*cf84ac9aSAndroid Build Coastguard Worker 		if (len >= buf_len) {
346*cf84ac9aSAndroid Build Coastguard Worker 			buf_len = 0;
347*cf84ac9aSAndroid Build Coastguard Worker 			break;
348*cf84ac9aSAndroid Build Coastguard Worker 		}
349*cf84ac9aSAndroid Build Coastguard Worker 		u.ptr += len;
350*cf84ac9aSAndroid Build Coastguard Worker 		buf_len -= len;
351*cf84ac9aSAndroid Build Coastguard Worker 	}
352*cf84ac9aSAndroid Build Coastguard Worker 	if (buf_len) {
353*cf84ac9aSAndroid Build Coastguard Worker 		tprints(", ...");
354*cf84ac9aSAndroid Build Coastguard Worker 		printaddr_comment(addr + (control_len - buf_len));
355*cf84ac9aSAndroid Build Coastguard Worker 	} else if (control_len < in_control_len) {
356*cf84ac9aSAndroid Build Coastguard Worker 		tprints(", ...");
357*cf84ac9aSAndroid Build Coastguard Worker 	}
358*cf84ac9aSAndroid Build Coastguard Worker 	tprints("]");
359*cf84ac9aSAndroid Build Coastguard Worker 	free(buf);
360*cf84ac9aSAndroid Build Coastguard Worker }
361*cf84ac9aSAndroid Build Coastguard Worker 
362*cf84ac9aSAndroid Build Coastguard Worker void
print_struct_msghdr(struct tcb * tcp,const struct msghdr * msg,const int * const p_user_msg_namelen,const kernel_ulong_t data_size)363*cf84ac9aSAndroid Build Coastguard Worker print_struct_msghdr(struct tcb *tcp, const struct msghdr *msg,
364*cf84ac9aSAndroid Build Coastguard Worker 		    const int *const p_user_msg_namelen,
365*cf84ac9aSAndroid Build Coastguard Worker 		    const kernel_ulong_t data_size)
366*cf84ac9aSAndroid Build Coastguard Worker {
367*cf84ac9aSAndroid Build Coastguard Worker 	const int msg_namelen =
368*cf84ac9aSAndroid Build Coastguard Worker 		p_user_msg_namelen && (int) msg->msg_namelen > *p_user_msg_namelen
369*cf84ac9aSAndroid Build Coastguard Worker 		? *p_user_msg_namelen : (int) msg->msg_namelen;
370*cf84ac9aSAndroid Build Coastguard Worker 
371*cf84ac9aSAndroid Build Coastguard Worker 	tprints("{msg_name=");
372*cf84ac9aSAndroid Build Coastguard Worker 	const int family =
373*cf84ac9aSAndroid Build Coastguard Worker 		decode_sockaddr(tcp, ptr_to_kulong(msg->msg_name), msg_namelen);
374*cf84ac9aSAndroid Build Coastguard Worker 	const enum iov_decode decode =
375*cf84ac9aSAndroid Build Coastguard Worker 		(family == AF_NETLINK) ? IOV_DECODE_NETLINK : IOV_DECODE_STR;
376*cf84ac9aSAndroid Build Coastguard Worker 
377*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", msg_namelen=");
378*cf84ac9aSAndroid Build Coastguard Worker 	if (p_user_msg_namelen && *p_user_msg_namelen != (int) msg->msg_namelen)
379*cf84ac9aSAndroid Build Coastguard Worker 		tprintf("%d->", *p_user_msg_namelen);
380*cf84ac9aSAndroid Build Coastguard Worker 	tprintf("%d", msg->msg_namelen);
381*cf84ac9aSAndroid Build Coastguard Worker 
382*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", msg_iov=");
383*cf84ac9aSAndroid Build Coastguard Worker 	tprint_iov_upto(tcp, msg->msg_iovlen,
384*cf84ac9aSAndroid Build Coastguard Worker 			ptr_to_kulong(msg->msg_iov), decode, data_size);
385*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U(", ", *msg, msg_iovlen);
386*cf84ac9aSAndroid Build Coastguard Worker 
387*cf84ac9aSAndroid Build Coastguard Worker 	decode_msg_control(tcp, ptr_to_kulong(msg->msg_control),
388*cf84ac9aSAndroid Build Coastguard Worker 			   msg->msg_controllen);
389*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_U(", ", *msg, msg_controllen);
390*cf84ac9aSAndroid Build Coastguard Worker 
391*cf84ac9aSAndroid Build Coastguard Worker 	PRINT_FIELD_FLAGS(", ", *msg, msg_flags, msg_flags, "MSG_???");
392*cf84ac9aSAndroid Build Coastguard Worker 	tprints("}");
393*cf84ac9aSAndroid Build Coastguard Worker }
394*cf84ac9aSAndroid Build Coastguard Worker 
395*cf84ac9aSAndroid Build Coastguard Worker static bool
fetch_msghdr_namelen(struct tcb * const tcp,const kernel_ulong_t addr,int * const p_msg_namelen)396*cf84ac9aSAndroid Build Coastguard Worker fetch_msghdr_namelen(struct tcb *const tcp, const kernel_ulong_t addr,
397*cf84ac9aSAndroid Build Coastguard Worker 		     int *const p_msg_namelen)
398*cf84ac9aSAndroid Build Coastguard Worker {
399*cf84ac9aSAndroid Build Coastguard Worker 	struct msghdr msg;
400*cf84ac9aSAndroid Build Coastguard Worker 
401*cf84ac9aSAndroid Build Coastguard Worker 	if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg)) {
402*cf84ac9aSAndroid Build Coastguard Worker 		*p_msg_namelen = msg.msg_namelen;
403*cf84ac9aSAndroid Build Coastguard Worker 		return true;
404*cf84ac9aSAndroid Build Coastguard Worker 	} else {
405*cf84ac9aSAndroid Build Coastguard Worker 		return false;
406*cf84ac9aSAndroid Build Coastguard Worker 	}
407*cf84ac9aSAndroid Build Coastguard Worker }
408*cf84ac9aSAndroid Build Coastguard Worker 
409*cf84ac9aSAndroid Build Coastguard Worker static void
decode_msghdr(struct tcb * const tcp,const int * const p_user_msg_namelen,const kernel_ulong_t addr,const kernel_ulong_t data_size)410*cf84ac9aSAndroid Build Coastguard Worker decode_msghdr(struct tcb *const tcp, const int *const p_user_msg_namelen,
411*cf84ac9aSAndroid Build Coastguard Worker 	      const kernel_ulong_t addr, const kernel_ulong_t data_size)
412*cf84ac9aSAndroid Build Coastguard Worker {
413*cf84ac9aSAndroid Build Coastguard Worker 	struct msghdr msg;
414*cf84ac9aSAndroid Build Coastguard Worker 
415*cf84ac9aSAndroid Build Coastguard Worker 	if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg))
416*cf84ac9aSAndroid Build Coastguard Worker 		print_struct_msghdr(tcp, &msg, p_user_msg_namelen, data_size);
417*cf84ac9aSAndroid Build Coastguard Worker 	else
418*cf84ac9aSAndroid Build Coastguard Worker 		printaddr(addr);
419*cf84ac9aSAndroid Build Coastguard Worker }
420*cf84ac9aSAndroid Build Coastguard Worker 
421*cf84ac9aSAndroid Build Coastguard Worker void
dumpiov_in_msghdr(struct tcb * const tcp,const kernel_ulong_t addr,const kernel_ulong_t data_size)422*cf84ac9aSAndroid Build Coastguard Worker dumpiov_in_msghdr(struct tcb *const tcp, const kernel_ulong_t addr,
423*cf84ac9aSAndroid Build Coastguard Worker 		  const kernel_ulong_t data_size)
424*cf84ac9aSAndroid Build Coastguard Worker {
425*cf84ac9aSAndroid Build Coastguard Worker 	struct msghdr msg;
426*cf84ac9aSAndroid Build Coastguard Worker 
427*cf84ac9aSAndroid Build Coastguard Worker 	if (fetch_struct_msghdr(tcp, addr, &msg)) {
428*cf84ac9aSAndroid Build Coastguard Worker 		dumpiov_upto(tcp, msg.msg_iovlen,
429*cf84ac9aSAndroid Build Coastguard Worker 			     ptr_to_kulong(msg.msg_iov), data_size);
430*cf84ac9aSAndroid Build Coastguard Worker 	}
431*cf84ac9aSAndroid Build Coastguard Worker }
432*cf84ac9aSAndroid Build Coastguard Worker 
SYS_FUNC(sendmsg)433*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(sendmsg)
434*cf84ac9aSAndroid Build Coastguard Worker {
435*cf84ac9aSAndroid Build Coastguard Worker 	printfd(tcp, tcp->u_arg[0]);
436*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");
437*cf84ac9aSAndroid Build Coastguard Worker 	decode_msghdr(tcp, 0, tcp->u_arg[1], -1);
438*cf84ac9aSAndroid Build Coastguard Worker 	/* flags */
439*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");
440*cf84ac9aSAndroid Build Coastguard Worker 	printflags(msg_flags, tcp->u_arg[2], "MSG_???");
441*cf84ac9aSAndroid Build Coastguard Worker 
442*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_DECODED;
443*cf84ac9aSAndroid Build Coastguard Worker }
444*cf84ac9aSAndroid Build Coastguard Worker 
SYS_FUNC(recvmsg)445*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(recvmsg)
446*cf84ac9aSAndroid Build Coastguard Worker {
447*cf84ac9aSAndroid Build Coastguard Worker 	int msg_namelen;
448*cf84ac9aSAndroid Build Coastguard Worker 
449*cf84ac9aSAndroid Build Coastguard Worker 	if (entering(tcp)) {
450*cf84ac9aSAndroid Build Coastguard Worker 		printfd(tcp, tcp->u_arg[0]);
451*cf84ac9aSAndroid Build Coastguard Worker 		tprints(", ");
452*cf84ac9aSAndroid Build Coastguard Worker 		if (fetch_msghdr_namelen(tcp, tcp->u_arg[1], &msg_namelen)) {
453*cf84ac9aSAndroid Build Coastguard Worker 			set_tcb_priv_ulong(tcp, msg_namelen);
454*cf84ac9aSAndroid Build Coastguard Worker 			return 0;
455*cf84ac9aSAndroid Build Coastguard Worker 		}
456*cf84ac9aSAndroid Build Coastguard Worker 		printaddr(tcp->u_arg[1]);
457*cf84ac9aSAndroid Build Coastguard Worker 	} else {
458*cf84ac9aSAndroid Build Coastguard Worker 		msg_namelen = get_tcb_priv_ulong(tcp);
459*cf84ac9aSAndroid Build Coastguard Worker 
460*cf84ac9aSAndroid Build Coastguard Worker 		if (syserror(tcp))
461*cf84ac9aSAndroid Build Coastguard Worker 			tprintf("{msg_namelen=%d}", msg_namelen);
462*cf84ac9aSAndroid Build Coastguard Worker 		else
463*cf84ac9aSAndroid Build Coastguard Worker 			decode_msghdr(tcp, &msg_namelen, tcp->u_arg[1],
464*cf84ac9aSAndroid Build Coastguard Worker 				      tcp->u_rval);
465*cf84ac9aSAndroid Build Coastguard Worker 	}
466*cf84ac9aSAndroid Build Coastguard Worker 
467*cf84ac9aSAndroid Build Coastguard Worker 	/* flags */
468*cf84ac9aSAndroid Build Coastguard Worker 	tprints(", ");
469*cf84ac9aSAndroid Build Coastguard Worker 	printflags(msg_flags, tcp->u_arg[2], "MSG_???");
470*cf84ac9aSAndroid Build Coastguard Worker 
471*cf84ac9aSAndroid Build Coastguard Worker 	return RVAL_DECODED;
472*cf84ac9aSAndroid Build Coastguard Worker }
473