Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 : : * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 : : * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 : : * Copyright (c) 1996-2000 Wichert Akkerman <wichert@cistron.nl>
6 : : * Copyright (c) 1999-2017 The strace developers.
7 : : * All rights reserved.
8 : : *
9 : : * Redistribution and use in source and binary forms, with or without
10 : : * modification, are permitted provided that the following conditions
11 : : * are met:
12 : : * 1. Redistributions of source code must retain the above copyright
13 : : * notice, this list of conditions and the following disclaimer.
14 : : * 2. Redistributions in binary form must reproduce the above copyright
15 : : * notice, this list of conditions and the following disclaimer in the
16 : : * documentation and/or other materials provided with the distribution.
17 : : * 3. The name of the author may not be used to endorse or promote products
18 : : * derived from this software without specific prior written permission.
19 : : *
20 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 : : */
31 : :
32 : : #include "defs.h"
33 : : #include "print_fields.h"
34 : :
35 : : #include <sys/stat.h>
36 : : #include <sys/socket.h>
37 : : #include <sys/uio.h>
38 : : #include <sys/un.h>
39 : : #include <netinet/in.h>
40 : : #ifdef HAVE_NETINET_TCP_H
41 : : # include <netinet/tcp.h>
42 : : #endif
43 : : #ifdef HAVE_NETINET_UDP_H
44 : : # include <netinet/udp.h>
45 : : #endif
46 : : #ifdef HAVE_NETINET_SCTP_H
47 : : # include <netinet/sctp.h>
48 : : #endif
49 : : #include <arpa/inet.h>
50 : : #include <net/if.h>
51 : : #include <asm/types.h>
52 : : #ifdef HAVE_NETIPX_IPX_H
53 : : # include <netipx/ipx.h>
54 : : #else
55 : : # include <linux/ipx.h>
56 : : #endif
57 : :
58 : : #if defined(HAVE_LINUX_IP_VS_H)
59 : : # include <linux/ip_vs.h>
60 : : #endif
61 : : #include "netlink.h"
62 : : #if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H)
63 : : # include <linux/netfilter_arp/arp_tables.h>
64 : : #endif
65 : : #if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H)
66 : : # include <linux/netfilter_bridge/ebtables.h>
67 : : #endif
68 : : #if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H)
69 : : # include <linux/netfilter_ipv4/ip_tables.h>
70 : : #endif
71 : : #if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H)
72 : : # include <linux/netfilter_ipv6/ip6_tables.h>
73 : : #endif
74 : : #include <linux/if_packet.h>
75 : : #include <linux/icmp.h>
76 : :
77 : : #include "xlat/socktypes.h"
78 : : #include "xlat/sock_type_flags.h"
79 : : #ifndef SOCK_TYPE_MASK
80 : : # define SOCK_TYPE_MASK 0xf
81 : : #endif
82 : :
83 : : #include "xlat/socketlayers.h"
84 : :
85 : : #include "xlat/inet_protocols.h"
86 : :
87 : : #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
88 : : # include <bluetooth/bluetooth.h>
89 : : # include "xlat/bt_protocols.h"
90 : : #endif
91 : :
92 : : static void
93 : 432 : decode_sockbuf(struct tcb *const tcp, const int fd, const kernel_ulong_t addr,
94 : : const kernel_ulong_t addrlen)
95 : : {
96 : :
97 [ + - ][ + + ]: 432 : switch (verbose(tcp) ? getfdproto(tcp, fd) : SOCK_PROTO_UNKNOWN) {
98 : : case SOCK_PROTO_NETLINK:
99 : 392 : decode_netlink(tcp, fd, addr, addrlen);
100 : 392 : break;
101 : : default:
102 : : printstrn(tcp, addr, addrlen);
103 : : }
104 : 432 : }
105 : :
106 : : /*
107 : : * low bits of the socket type define real socket type,
108 : : * other bits are socket type flags.
109 : : */
110 : : static void
111 : 24 : tprint_sock_type(unsigned int flags)
112 : : {
113 : 24 : const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK);
114 : :
115 [ + - ]: 24 : if (str) {
116 : 24 : tprints(str);
117 : 24 : flags &= ~SOCK_TYPE_MASK;
118 [ - + ]: 24 : if (!flags)
119 : 24 : return;
120 : 0 : tprints("|");
121 : : }
122 : : printflags(sock_type_flags, flags, "SOCK_???");
123 : : }
124 : :
125 : 22 : SYS_FUNC(socket)
126 : : {
127 : 22 : printxval(addrfams, tcp->u_arg[0], "AF_???");
128 : 22 : tprints(", ");
129 : 22 : tprint_sock_type(tcp->u_arg[1]);
130 : 22 : tprints(", ");
131 [ + + + ]: 22 : switch (tcp->u_arg[0]) {
132 : : case AF_INET:
133 : : case AF_INET6:
134 : 4 : printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???");
135 : : break;
136 : :
137 : : case AF_NETLINK:
138 : 2 : printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???");
139 : : break;
140 : :
141 : : #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
142 : : case AF_BLUETOOTH:
143 : : printxval(bt_protocols, tcp->u_arg[2], "BTPROTO_???");
144 : : break;
145 : : #endif
146 : :
147 : : default:
148 : 16 : tprintf("%" PRI_klu, tcp->u_arg[2]);
149 : 16 : break;
150 : : }
151 : :
152 : 22 : return RVAL_DECODED | RVAL_FD;
153 : : }
154 : :
155 : : static bool
156 : 170 : fetch_socklen(struct tcb *const tcp, int *const plen,
157 : : const kernel_ulong_t sockaddr, const kernel_ulong_t socklen)
158 : : {
159 [ + + ]: 170 : return verbose(tcp) && sockaddr && socklen
160 [ + - ][ + + ]: 284 : && umove(tcp, socklen, plen) == 0;
161 : : }
162 : :
163 : : static int
164 : 188 : decode_sockname(struct tcb *tcp)
165 : : {
166 : : int ulen, rlen;
167 : :
168 [ + + ]: 188 : if (entering(tcp)) {
169 : 106 : printfd(tcp, tcp->u_arg[0]);
170 : 106 : tprints(", ");
171 [ + + ]: 106 : if (fetch_socklen(tcp, &ulen, tcp->u_arg[1], tcp->u_arg[2])) {
172 : 82 : set_tcb_priv_ulong(tcp, ulen);
173 : 82 : return 0;
174 : : } else {
175 : 24 : printaddr(tcp->u_arg[1]);
176 : 24 : tprints(", ");
177 : 24 : printaddr(tcp->u_arg[2]);
178 : 24 : return RVAL_DECODED;
179 : : }
180 : : }
181 : :
182 : 82 : ulen = get_tcb_priv_ulong(tcp);
183 : :
184 [ + + ][ - + ]: 82 : if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &rlen) < 0) {
185 : 8 : printaddr(tcp->u_arg[1]);
186 : 8 : tprintf(", [%d]", ulen);
187 : : } else {
188 : 74 : decode_sockaddr(tcp, tcp->u_arg[1], ulen > rlen ? rlen : ulen);
189 [ + + ]: 74 : if (ulen != rlen)
190 : 54 : tprintf(", [%d->%d]", ulen, rlen);
191 : : else
192 : 20 : tprintf(", [%d]", rlen);
193 : : }
194 : :
195 : : return RVAL_DECODED;
196 : : }
197 : :
198 : 50 : SYS_FUNC(accept)
199 : : {
200 : 50 : return decode_sockname(tcp) | RVAL_FD;
201 : : }
202 : :
203 : 26 : SYS_FUNC(accept4)
204 : : {
205 : 26 : int rc = decode_sockname(tcp);
206 : :
207 [ + + ]: 26 : if (rc & RVAL_DECODED) {
208 : 16 : tprints(", ");
209 : 16 : printflags(sock_type_flags, tcp->u_arg[3], "SOCK_???");
210 : : }
211 : :
212 : 26 : return rc | RVAL_FD;
213 : : }
214 : :
215 : 2 : SYS_FUNC(send)
216 : : {
217 : 2 : printfd(tcp, tcp->u_arg[0]);
218 : 2 : tprints(", ");
219 : 2 : decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
220 : 2 : tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
221 : : /* flags */
222 : 2 : printflags(msg_flags, tcp->u_arg[3], "MSG_???");
223 : :
224 : 2 : return RVAL_DECODED;
225 : : }
226 : :
227 : 404 : SYS_FUNC(sendto)
228 : : {
229 : 404 : printfd(tcp, tcp->u_arg[0]);
230 : 404 : tprints(", ");
231 : 404 : decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
232 : 404 : tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
233 : : /* flags */
234 : 404 : printflags(msg_flags, tcp->u_arg[3], "MSG_???");
235 : : /* to address */
236 : 404 : const int addrlen = tcp->u_arg[5];
237 : 404 : tprints(", ");
238 : 404 : decode_sockaddr(tcp, tcp->u_arg[4], addrlen);
239 : : /* to length */
240 : 404 : tprintf(", %d", addrlen);
241 : :
242 : 404 : return RVAL_DECODED;
243 : : }
244 : :
245 : 6 : SYS_FUNC(recv)
246 : : {
247 [ + + ]: 6 : if (entering(tcp)) {
248 : 3 : printfd(tcp, tcp->u_arg[0]);
249 : 3 : tprints(", ");
250 : : } else {
251 [ + + ]: 3 : if (syserror(tcp)) {
252 : 1 : printaddr(tcp->u_arg[1]);
253 : : } else {
254 : 2 : decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
255 : 2 : tcp->u_rval);
256 : : }
257 : :
258 : 3 : tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
259 : 3 : printflags(msg_flags, tcp->u_arg[3], "MSG_???");
260 : : }
261 : 6 : return 0;
262 : : }
263 : :
264 : 64 : SYS_FUNC(recvfrom)
265 : : {
266 : : int ulen, rlen;
267 : :
268 [ + + ]: 64 : if (entering(tcp)) {
269 : 32 : printfd(tcp, tcp->u_arg[0]);
270 : 32 : tprints(", ");
271 [ + + ]: 32 : if (fetch_socklen(tcp, &ulen, tcp->u_arg[4], tcp->u_arg[5])) {
272 : 10 : set_tcb_priv_ulong(tcp, ulen);
273 : : }
274 : : } else {
275 : : /* buf */
276 [ + + ]: 32 : if (syserror(tcp)) {
277 : 8 : printaddr(tcp->u_arg[1]);
278 : : } else {
279 : 24 : decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
280 : 24 : tcp->u_rval);
281 : : }
282 : : /* size */
283 : 32 : tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
284 : : /* flags */
285 : 32 : printflags(msg_flags, tcp->u_arg[3], "MSG_???");
286 : 32 : tprints(", ");
287 : :
288 : 32 : ulen = get_tcb_priv_ulong(tcp);
289 : :
290 [ + + ]: 32 : if (!fetch_socklen(tcp, &rlen, tcp->u_arg[4], tcp->u_arg[5])) {
291 : : /* from address */
292 : 22 : printaddr(tcp->u_arg[4]);
293 : 22 : tprints(", ");
294 : : /* from length */
295 : 22 : printaddr(tcp->u_arg[5]);
296 : 22 : return 0;
297 : : }
298 [ + + ]: 10 : if (syserror(tcp)) {
299 : : /* from address */
300 : 2 : printaddr(tcp->u_arg[4]);
301 : : /* from length */
302 : 2 : tprintf(", [%d]", ulen);
303 : 2 : return 0;
304 : : }
305 : : /* from address */
306 : 8 : decode_sockaddr(tcp, tcp->u_arg[4], ulen > rlen ? rlen : ulen);
307 : : /* from length */
308 [ + + ]: 8 : if (ulen != rlen)
309 : 6 : tprintf(", [%d->%d]", ulen, rlen);
310 : : else
311 : 2 : tprintf(", [%d]", rlen);
312 : : }
313 : : return 0;
314 : : }
315 : :
316 : 112 : SYS_FUNC(getsockname)
317 : : {
318 : 112 : return decode_sockname(tcp);
319 : : }
320 : :
321 : : static void
322 : 6 : printpair_fd(struct tcb *tcp, const int i0, const int i1)
323 : : {
324 : 6 : tprints("[");
325 : 6 : printfd(tcp, i0);
326 : 6 : tprints(", ");
327 : 6 : printfd(tcp, i1);
328 : 6 : tprints("]");
329 : 6 : }
330 : :
331 : : static void
332 : 8 : decode_pair_fd(struct tcb *const tcp, const kernel_ulong_t addr)
333 : : {
334 : : int pair[2];
335 : :
336 [ + + ]: 8 : if (umove_or_printaddr(tcp, addr, &pair))
337 : 2 : return;
338 : :
339 : 6 : printpair_fd(tcp, pair[0], pair[1]);
340 : : }
341 : :
342 : : static int
343 : 12 : do_pipe(struct tcb *tcp, int flags_arg)
344 : : {
345 [ + + ]: 12 : if (exiting(tcp)) {
346 : 6 : decode_pair_fd(tcp, tcp->u_arg[0]);
347 [ + + ]: 6 : if (flags_arg >= 0) {
348 : 4 : tprints(", ");
349 : 4 : printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
350 : : }
351 : : }
352 : 12 : return 0;
353 : : }
354 : :
355 : 4 : SYS_FUNC(pipe)
356 : : {
357 : : #ifdef HAVE_GETRVAL2
358 : : if (exiting(tcp) && !syserror(tcp))
359 : : printpair_fd(tcp, tcp->u_rval, getrval2(tcp));
360 : : return 0;
361 : : #else
362 : 4 : return do_pipe(tcp, -1);
363 : : #endif
364 : : }
365 : :
366 : 8 : SYS_FUNC(pipe2)
367 : : {
368 : 8 : return do_pipe(tcp, 1);
369 : : }
370 : :
371 : 4 : SYS_FUNC(socketpair)
372 : : {
373 [ + + ]: 4 : if (entering(tcp)) {
374 : 2 : printxval(addrfams, tcp->u_arg[0], "AF_???");
375 : 2 : tprints(", ");
376 : 2 : tprint_sock_type(tcp->u_arg[1]);
377 : 2 : tprintf(", %" PRI_klu, tcp->u_arg[2]);
378 : : } else {
379 : 2 : tprints(", ");
380 : 2 : decode_pair_fd(tcp, tcp->u_arg[3]);
381 : : }
382 : 4 : return 0;
383 : : }
384 : :
385 : : #include "xlat/sockoptions.h"
386 : : #include "xlat/sockipoptions.h"
387 : : #include "xlat/getsockipoptions.h"
388 : : #include "xlat/setsockipoptions.h"
389 : : #include "xlat/sockipv6options.h"
390 : : #include "xlat/getsockipv6options.h"
391 : : #include "xlat/setsockipv6options.h"
392 : : #include "xlat/sockipxoptions.h"
393 : : #include "xlat/sockrawoptions.h"
394 : : #include "xlat/sockpacketoptions.h"
395 : : #include "xlat/socksctpoptions.h"
396 : : #include "xlat/socktcpoptions.h"
397 : :
398 : : static void
399 : 180 : print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level,
400 : : unsigned int name, bool is_getsockopt)
401 : : {
402 : 180 : printfd(tcp, fd);
403 : 180 : tprints(", ");
404 : : printxval(socketlayers, level, "SOL_??");
405 : 180 : tprints(", ");
406 : :
407 [ + + + - : 180 : switch (level) {
- + - +
- ]
408 : : case SOL_SOCKET:
409 : : printxval(sockoptions, name, "SO_???");
410 : : break;
411 : : case SOL_IP:
412 [ + - ]: 40 : printxvals(name, "IP_???", sockipoptions,
413 : : is_getsockopt ? getsockipoptions : setsockipoptions, NULL);
414 : 40 : break;
415 : : case SOL_IPV6:
416 [ + - ]: 60 : printxvals(name, "IPV6_???", sockipv6options,
417 : : is_getsockopt ? getsockipv6options : setsockipv6options, NULL);
418 : 60 : break;
419 : : case SOL_IPX:
420 : : printxval(sockipxoptions, name, "IPX_???");
421 : : break;
422 : : case SOL_PACKET:
423 : : printxval(sockpacketoptions, name, "PACKET_???");
424 : : break;
425 : : case SOL_TCP:
426 : : printxval(socktcpoptions, name, "TCP_???");
427 : : break;
428 : : case SOL_SCTP:
429 : : printxval(socksctpoptions, name, "SCTP_???");
430 : : break;
431 : : case SOL_RAW:
432 : : printxval(sockrawoptions, name, "RAW_???");
433 : : break;
434 : :
435 : : /* Other SOL_* protocol levels still need work. */
436 : :
437 : : default:
438 : 0 : tprintf("%u", name);
439 : : }
440 : :
441 : 180 : tprints(", ");
442 : 180 : }
443 : :
444 : : static void
445 : 10 : print_set_linger(struct tcb *const tcp, const kernel_ulong_t addr,
446 : : const int len)
447 : : {
448 : : struct linger linger;
449 : :
450 [ + + ]: 10 : if (len < (int) sizeof(linger)) {
451 : 4 : printaddr(addr);
452 [ + + ]: 6 : } else if (!umove_or_printaddr(tcp, addr, &linger)) {
453 : 4 : PRINT_FIELD_D("{", linger, l_onoff);
454 : 4 : PRINT_FIELD_D(", ", linger, l_linger);
455 : 4 : tprints("}");
456 : : }
457 : 10 : }
458 : :
459 : : static void
460 : 8 : print_get_linger(struct tcb *const tcp, const kernel_ulong_t addr,
461 : : unsigned int len)
462 : : {
463 : : struct linger linger;
464 : :
465 [ + + ]: 8 : if (len < sizeof(linger)) {
466 [ + + ]: 4 : if (len != sizeof(linger.l_onoff)) {
467 : 2 : printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
468 : 2 : return;
469 : : }
470 : : } else {
471 : : len = sizeof(linger);
472 : : }
473 : :
474 [ - + ]: 6 : if (umoven(tcp, addr, len, &linger) < 0) {
475 : 0 : printaddr(addr);
476 : 0 : return;
477 : : }
478 : :
479 : 6 : PRINT_FIELD_D("{", linger, l_onoff);
480 [ + + ]: 6 : if (len == sizeof(linger))
481 : 4 : PRINT_FIELD_D(", ", linger, l_linger);
482 : 6 : tprints("}");
483 : : }
484 : :
485 : : #ifdef SO_PEERCRED
486 : : static void
487 : 10 : print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int len)
488 : : {
489 : : struct ucred uc;
490 : :
491 [ + + ]: 10 : if (len < sizeof(uc)) {
492 [ + + ]: 6 : if (len != sizeof(uc.pid)
493 : 6 : && len != offsetofend(struct ucred, uid)) {
494 : 2 : printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
495 : 2 : return;
496 : : }
497 : : } else {
498 : : len = sizeof(uc);
499 : : }
500 : :
501 [ - + ]: 8 : if (umoven(tcp, addr, len, &uc) < 0) {
502 : 0 : printaddr(addr);
503 : 0 : return;
504 : : }
505 : :
506 : 8 : PRINT_FIELD_D("{", uc, pid);
507 [ + + ]: 8 : if (len > sizeof(uc.pid))
508 [ + + ]: 6 : PRINT_FIELD_UID(", ", uc, uid);
509 [ + + ]: 8 : if (len == sizeof(uc))
510 [ + + ]: 4 : PRINT_FIELD_UID(", ", uc, gid);
511 : 8 : tprints("}");
512 : : }
513 : : #endif /* SO_PEERCRED */
514 : :
515 : : #ifdef PACKET_STATISTICS
516 : : static void
517 : 0 : print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr,
518 : : const int len)
519 : : {
520 : : struct tpacket_stats stats;
521 : :
522 [ # # # # ]: 0 : if (len != sizeof(stats) ||
523 : 0 : umove(tcp, addr, &stats) < 0) {
524 : 0 : printaddr(addr);
525 : : } else {
526 : 0 : PRINT_FIELD_U("{", stats, tp_packets);
527 : 0 : PRINT_FIELD_U("{", stats, tp_drops);
528 : 0 : tprints("}");
529 : : }
530 : 0 : }
531 : : #endif /* PACKET_STATISTICS */
532 : :
533 : : #include "xlat/icmpfilterflags.h"
534 : :
535 : : static void
536 : 8 : print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len)
537 : : {
538 : 8 : struct icmp_filter filter = {};
539 : :
540 [ + + ]: 8 : if (len > (int) sizeof(filter))
541 : : len = sizeof(filter);
542 [ + + ]: 6 : else if (len <= 0) {
543 : 2 : printaddr(addr);
544 : 4 : return;
545 : : }
546 : :
547 [ + + ]: 6 : if (umoven_or_printaddr(tcp, addr, len, &filter))
548 : : return;
549 : :
550 : 4 : tprints("~(");
551 : 4 : printflags(icmpfilterflags, ~filter.data, "ICMP_???");
552 : 4 : tprints(")");
553 : : }
554 : :
555 : : static void
556 : 30 : print_getsockopt(struct tcb *const tcp, const unsigned int level,
557 : : const unsigned int name, const kernel_ulong_t addr,
558 : : const int len)
559 : : {
560 [ + + ][ + - ]: 30 : if (addr && verbose(tcp))
561 [ + - - + ]: 28 : switch (level) {
562 : : case SOL_SOCKET:
563 [ + + + + ]: 26 : switch (name) {
564 : : case SO_LINGER:
565 : 8 : print_get_linger(tcp, addr, len);
566 : 8 : return;
567 : : #ifdef SO_PEERCRED
568 : : case SO_PEERCRED:
569 : 10 : print_ucred(tcp, addr, len);
570 : 10 : return;
571 : : #endif
572 : : #ifdef SO_ATTACH_FILTER
573 : : case SO_ATTACH_FILTER:
574 [ + - ][ + - ]: 4 : if (len && (unsigned short) len == (unsigned int) len)
575 : 4 : print_sock_fprog(tcp, addr, len);
576 : : else
577 : 0 : printaddr(addr);
578 : : return;
579 : : #endif /* SO_ATTACH_FILTER */
580 : : }
581 : : break;
582 : :
583 : : case SOL_PACKET:
584 [ # # ]: 0 : switch (name) {
585 : : #ifdef PACKET_STATISTICS
586 : : case PACKET_STATISTICS:
587 : 0 : print_tpacket_stats(tcp, addr, len);
588 : 0 : return;
589 : : #endif
590 : : }
591 : : break;
592 : :
593 : : case SOL_RAW:
594 [ # # ]: 0 : switch (name) {
595 : : case ICMP_FILTER:
596 : 0 : print_icmp_filter(tcp, addr, len);
597 : 0 : return;
598 : : }
599 : : break;
600 : : }
601 : :
602 : : /* default arg printing */
603 : :
604 [ + - ]: 8 : if (verbose(tcp)) {
605 [ + + ]: 8 : if (len == sizeof(int)) {
606 : 6 : printnum_int(tcp, addr, "%d");
607 : : } else {
608 : 2 : printstrn(tcp, addr, len);
609 : : }
610 : : } else {
611 : 0 : printaddr(addr);
612 : : }
613 : : }
614 : :
615 : 88 : SYS_FUNC(getsockopt)
616 : : {
617 : : int ulen, rlen;
618 : :
619 [ + + ]: 88 : if (entering(tcp)) {
620 : 48 : print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
621 : 96 : tcp->u_arg[1], tcp->u_arg[2], true);
622 : :
623 [ + - ][ + + ]: 48 : if (verbose(tcp) && tcp->u_arg[4]
624 [ + + ]: 44 : && umove(tcp, tcp->u_arg[4], &ulen) == 0) {
625 : 40 : set_tcb_priv_ulong(tcp, ulen);
626 : 40 : return 0;
627 : : } else {
628 : 8 : printaddr(tcp->u_arg[3]);
629 : 8 : tprints(", ");
630 : 8 : printaddr(tcp->u_arg[4]);
631 : 8 : return RVAL_DECODED;
632 : : }
633 : : } else {
634 : 40 : ulen = get_tcb_priv_ulong(tcp);
635 : :
636 [ + + ][ - + ]: 40 : if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) {
637 : 10 : printaddr(tcp->u_arg[3]);
638 : 10 : tprintf(", [%d]", ulen);
639 : : } else {
640 : 30 : print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
641 : : tcp->u_arg[3], rlen);
642 [ + + ]: 30 : if (ulen != rlen)
643 : 10 : tprintf(", [%d->%d]", ulen, rlen);
644 : : else
645 : 20 : tprintf(", [%d]", rlen);
646 : : }
647 : : }
648 : : return 0;
649 : : }
650 : :
651 : : #ifdef IP_ADD_MEMBERSHIP
652 : : static void
653 : 20 : print_mreq(struct tcb *const tcp, const kernel_ulong_t addr,
654 : : const int len)
655 : : {
656 : : struct ip_mreq mreq;
657 : :
658 [ + + ]: 20 : if (len < (int) sizeof(mreq)) {
659 : 8 : printaddr(addr);
660 [ + + ]: 12 : } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
661 : 8 : PRINT_FIELD_INET4_ADDR("{", mreq, imr_multiaddr);
662 : 8 : PRINT_FIELD_INET4_ADDR(", ", mreq, imr_interface);
663 : 8 : tprints("}");
664 : : }
665 : 20 : }
666 : : #endif /* IP_ADD_MEMBERSHIP */
667 : :
668 : : #ifdef IPV6_ADD_MEMBERSHIP
669 : : static void
670 : 40 : print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr,
671 : : const int len)
672 : : {
673 : : struct ipv6_mreq mreq;
674 : :
675 [ + + ]: 40 : if (len < (int) sizeof(mreq)) {
676 : 16 : printaddr(addr);
677 [ + + ]: 24 : } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
678 : 16 : PRINT_FIELD_INET_ADDR("{", mreq, ipv6mr_multiaddr, AF_INET6);
679 : 16 : PRINT_FIELD_IFINDEX(", ", mreq, ipv6mr_interface);
680 : 16 : tprints("}");
681 : : }
682 : 40 : }
683 : : #endif /* IPV6_ADD_MEMBERSHIP */
684 : :
685 : : #ifdef PACKET_RX_RING
686 : : static void
687 : 0 : print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
688 : : {
689 : : struct tpacket_req req;
690 : :
691 [ # # # # ]: 0 : if (len != sizeof(req) ||
692 : 0 : umove(tcp, addr, &req) < 0) {
693 : 0 : printaddr(addr);
694 : : } else {
695 : 0 : PRINT_FIELD_U("{", req, tp_block_size);
696 : 0 : PRINT_FIELD_U(", ", req, tp_block_nr);
697 : 0 : PRINT_FIELD_U(", ", req, tp_frame_size);
698 : 0 : PRINT_FIELD_U(", ", req, tp_frame_nr);
699 : 0 : tprints("}");
700 : : }
701 : 0 : }
702 : : #endif /* PACKET_RX_RING */
703 : :
704 : : #ifdef PACKET_ADD_MEMBERSHIP
705 : : # include "xlat/packet_mreq_type.h"
706 : :
707 : : static void
708 : 0 : print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
709 : : {
710 : : struct packet_mreq mreq;
711 : :
712 [ # # # # ]: 0 : if (len != sizeof(mreq) ||
713 : 0 : umove(tcp, addr, &mreq) < 0) {
714 : 0 : printaddr(addr);
715 : : } else {
716 : : unsigned int i;
717 : :
718 : 0 : PRINT_FIELD_IFINDEX("{", mreq, mr_ifindex);
719 : 0 : PRINT_FIELD_XVAL(", ", mreq, mr_type, packet_mreq_type,
720 : : "PACKET_MR_???");
721 : 0 : PRINT_FIELD_U(", ", mreq, mr_alen);
722 : 0 : tprints(", mr_address=");
723 [ # # ]: 0 : if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
724 : 0 : mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
725 [ # # ]: 0 : for (i = 0; i < mreq.mr_alen; ++i)
726 : 0 : tprintf("%02x", mreq.mr_address[i]);
727 : 0 : tprints("}");
728 : : }
729 : 0 : }
730 : : #endif /* PACKET_ADD_MEMBERSHIP */
731 : :
732 : : static void
733 : 132 : print_setsockopt(struct tcb *const tcp, const unsigned int level,
734 : : const unsigned int name, const kernel_ulong_t addr,
735 : : const int len)
736 : : {
737 [ + + ][ + - ]: 132 : if (addr && verbose(tcp))
738 [ + + + - : 130 : switch (level) {
+ + ]
739 : : case SOL_SOCKET:
740 [ + + + ]: 20 : switch (name) {
741 : : case SO_LINGER:
742 : 10 : print_set_linger(tcp, addr, len);
743 : 10 : return;
744 : : #ifdef SO_ATTACH_FILTER
745 : : case SO_ATTACH_FILTER:
746 : : # ifdef SO_ATTACH_REUSEPORT_CBPF
747 : : case SO_ATTACH_REUSEPORT_CBPF:
748 : : # endif
749 [ + + ]: 4 : if ((unsigned int) len == get_sock_fprog_size())
750 : 2 : decode_sock_fprog(tcp, addr);
751 : : else
752 : 2 : printaddr(addr);
753 : : return;
754 : : #endif /* SO_ATTACH_FILTER */
755 : : }
756 : : break;
757 : :
758 : : case SOL_IP:
759 [ + + - ]: 40 : switch (name) {
760 : : #ifdef IP_ADD_MEMBERSHIP
761 : : case IP_ADD_MEMBERSHIP:
762 : : case IP_DROP_MEMBERSHIP:
763 : 20 : print_mreq(tcp, addr, len);
764 : 20 : return;
765 : : #endif /* IP_ADD_MEMBERSHIP */
766 : : #ifdef MCAST_JOIN_GROUP
767 : : case MCAST_JOIN_GROUP:
768 : : case MCAST_LEAVE_GROUP:
769 : 20 : print_group_req(tcp, addr, len);
770 [ + - ][ + + ]: 80 : return;
[ - + ]
771 : : #endif /* MCAST_JOIN_GROUP */
772 : : }
773 : : break;
774 : :
775 : : case SOL_IPV6:
776 : : switch (name) {
777 : : #ifdef IPV6_ADD_MEMBERSHIP
778 : : case IPV6_ADD_MEMBERSHIP:
779 : : case IPV6_DROP_MEMBERSHIP:
780 : : # ifdef IPV6_JOIN_ANYCAST
781 : : case IPV6_JOIN_ANYCAST:
782 : : # endif
783 : : # ifdef IPV6_LEAVE_ANYCAST
784 : : case IPV6_LEAVE_ANYCAST:
785 : : # endif
786 : 40 : print_mreq6(tcp, addr, len);
787 : 40 : return;
788 : : #endif /* IPV6_ADD_MEMBERSHIP */
789 : : #ifdef MCAST_JOIN_GROUP
790 : : case MCAST_JOIN_GROUP:
791 : : case MCAST_LEAVE_GROUP:
792 : 20 : print_group_req(tcp, addr, len);
793 : 20 : return;
794 : : #endif /* MCAST_JOIN_GROUP */
795 : : }
796 : : break;
797 : :
798 : : case SOL_PACKET:
799 [ # # # ]: 0 : switch (name) {
800 : : #ifdef PACKET_RX_RING
801 : : case PACKET_RX_RING:
802 : : # ifdef PACKET_TX_RING
803 : : case PACKET_TX_RING:
804 : : # endif
805 : 0 : print_tpacket_req(tcp, addr, len);
806 : 0 : return;
807 : : #endif /* PACKET_RX_RING */
808 : : #ifdef PACKET_ADD_MEMBERSHIP
809 : : case PACKET_ADD_MEMBERSHIP:
810 : : case PACKET_DROP_MEMBERSHIP:
811 : 0 : print_packet_mreq(tcp, addr, len);
812 : 0 : return;
813 : : #endif /* PACKET_ADD_MEMBERSHIP */
814 : : }
815 : : break;
816 : :
817 : : case SOL_RAW:
818 [ + - ]: 8 : switch (name) {
819 : : case ICMP_FILTER:
820 : 8 : print_icmp_filter(tcp, addr, len);
821 : 8 : return;
822 : : }
823 : : break;
824 : : }
825 : :
826 : : /* default arg printing */
827 : :
828 [ + - ]: 10 : if (verbose(tcp)) {
829 [ + + ]: 10 : if (len == sizeof(int)) {
830 : 8 : printnum_int(tcp, addr, "%d");
831 : : } else {
832 : 2 : printstrn(tcp, addr, len);
833 : : }
834 : : } else {
835 : 0 : printaddr(addr);
836 : : }
837 : : }
838 : :
839 : 132 : SYS_FUNC(setsockopt)
840 : : {
841 : 132 : print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
842 : 264 : tcp->u_arg[1], tcp->u_arg[2], false);
843 : 132 : print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
844 : 132 : tcp->u_arg[3], tcp->u_arg[4]);
845 : 132 : tprintf(", %d", (int) tcp->u_arg[4]);
846 : :
847 : 132 : return RVAL_DECODED;
848 : : }
|