]> granicus.if.org Git - strace/blob - net.c
40b5a5c3f6d31294a2dae66f3a69d176a474337d
[strace] / net.c
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  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "defs.h"
32 #include <sys/stat.h>
33 #include <sys/socket.h>
34 #include <sys/uio.h>
35 #include <sys/un.h>
36 #include <netinet/in.h>
37 #ifdef HAVE_NETINET_TCP_H
38 # include <netinet/tcp.h>
39 #endif
40 #ifdef HAVE_NETINET_UDP_H
41 # include <netinet/udp.h>
42 #endif
43 #ifdef HAVE_NETINET_SCTP_H
44 # include <netinet/sctp.h>
45 #endif
46 #include <arpa/inet.h>
47 #include <net/if.h>
48 #include <asm/types.h>
49 #if defined(__GLIBC__)
50 # include <netipx/ipx.h>
51 #else
52 # include <linux/ipx.h>
53 #endif
54
55 #if defined(HAVE_LINUX_IP_VS_H)
56 # include <linux/ip_vs.h>
57 #endif
58 #if defined(HAVE_LINUX_NETLINK_H)
59 # include <linux/netlink.h>
60 #endif
61 #if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H)
62 # include <linux/netfilter_arp/arp_tables.h>
63 #endif
64 #if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H)
65 # include <linux/netfilter_bridge/ebtables.h>
66 #endif
67 #if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H)
68 # include <linux/netfilter_ipv4/ip_tables.h>
69 #endif
70 #if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H)
71 # include <linux/netfilter_ipv6/ip6_tables.h>
72 #endif
73 #if defined(HAVE_LINUX_IF_PACKET_H)
74 # include <linux/if_packet.h>
75 #endif
76 #if defined(HAVE_LINUX_ICMP_H)
77 # include <linux/icmp.h>
78 #endif
79 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
80 # include <bluetooth/bluetooth.h>
81 # include <bluetooth/hci.h>
82 # include <bluetooth/l2cap.h>
83 # include <bluetooth/rfcomm.h>
84 # include <bluetooth/sco.h>
85 #endif
86 #ifndef PF_UNSPEC
87 # define PF_UNSPEC AF_UNSPEC
88 #endif
89
90 #include "xlat/domains.h"
91 #include "xlat/addrfams.h"
92 #include "xlat/socktypes.h"
93 #include "xlat/sock_type_flags.h"
94 #ifndef SOCK_TYPE_MASK
95 # define SOCK_TYPE_MASK 0xf
96 #endif
97
98 #include "xlat/socketlayers.h"
99
100 #include "xlat/inet_protocols.h"
101
102 #ifdef PF_NETLINK
103 # if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG
104 #  define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
105 # endif
106 # include "xlat/netlink_protocols.h"
107 #endif
108
109 #if defined(HAVE_BLUETOOTH_BLUETOOTH_H)
110 # include "xlat/bt_protocols.h"
111 #endif
112
113 #include "xlat/msg_flags.h"
114
115 #if defined(AF_PACKET) /* from e.g. linux/if_packet.h */
116 # include "xlat/af_packet_types.h"
117 #endif
118
119 static void
120 print_ifindex(unsigned int ifindex)
121 {
122 #ifdef HAVE_IF_INDEXTONAME
123         char buf[IFNAMSIZ + 1];
124
125         if (if_indextoname(ifindex, buf)) {
126                 tprints("if_nametoindex(");
127                 print_quoted_string(buf, sizeof(buf), QUOTE_0_TERMINATED);
128                 tprints(")");
129                 return;
130         }
131 #endif
132         tprintf("%u", ifindex);
133 }
134
135 void
136 printsock(struct tcb *tcp, long addr, int addrlen)
137 {
138         union {
139                 char pad[128];
140                 struct sockaddr sa;
141                 struct sockaddr_in sin;
142                 struct sockaddr_un sau;
143 #ifdef HAVE_INET_NTOP
144                 struct sockaddr_in6 sa6;
145 #endif
146 #if defined(AF_IPX)
147                 struct sockaddr_ipx sipx;
148 #endif
149 #ifdef AF_PACKET
150                 struct sockaddr_ll ll;
151 #endif
152 #ifdef AF_NETLINK
153                 struct sockaddr_nl nl;
154 #endif
155 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
156                 struct sockaddr_hci hci;
157                 struct sockaddr_l2 l2;
158                 struct sockaddr_rc rc;
159                 struct sockaddr_sco sco;
160 #endif
161         } addrbuf;
162         char string_addr[100];
163
164         if (addrlen < 2) {
165                 printaddr(addr);
166                 return;
167         }
168
169         if (addrlen > (int) sizeof(addrbuf))
170                 addrlen = sizeof(addrbuf);
171
172         memset(&addrbuf, 0, sizeof(addrbuf));
173         if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad))
174                 return;
175         addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0';
176
177         tprints("{sa_family=");
178         printxval(addrfams, addrbuf.sa.sa_family, "AF_???");
179         tprints(", ");
180
181         switch (addrbuf.sa.sa_family) {
182         case AF_UNIX:
183                 if (addrlen == 2) {
184                         tprints("NULL");
185                 } else if (addrbuf.sau.sun_path[0]) {
186                         tprints("sun_path=");
187                         print_quoted_string(addrbuf.sau.sun_path,
188                                             sizeof(addrbuf.sau.sun_path) + 1,
189                                             QUOTE_0_TERMINATED);
190                 } else {
191                         tprints("sun_path=@");
192                         print_quoted_string(addrbuf.sau.sun_path + 1,
193                                             sizeof(addrbuf.sau.sun_path),
194                                             QUOTE_0_TERMINATED);
195                 }
196                 break;
197         case AF_INET:
198                 tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")",
199                         ntohs(addrbuf.sin.sin_port), inet_ntoa(addrbuf.sin.sin_addr));
200                 break;
201 #ifdef HAVE_INET_NTOP
202         case AF_INET6:
203                 inet_ntop(AF_INET6, &addrbuf.sa6.sin6_addr, string_addr, sizeof(string_addr));
204                 tprintf("sin6_port=htons(%u), inet_pton(AF_INET6, \"%s\", &sin6_addr), sin6_flowinfo=%u",
205                                 ntohs(addrbuf.sa6.sin6_port), string_addr,
206                                 addrbuf.sa6.sin6_flowinfo);
207 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
208                 tprints(", sin6_scope_id=");
209 #if defined IN6_IS_ADDR_LINKLOCAL && defined IN6_IS_ADDR_MC_LINKLOCAL
210                 if (IN6_IS_ADDR_LINKLOCAL(&addrbuf.sa6.sin6_addr)
211                     || IN6_IS_ADDR_MC_LINKLOCAL(&addrbuf.sa6.sin6_addr))
212                         print_ifindex(addrbuf.sa6.sin6_scope_id);
213                 else
214 #endif
215                         tprintf("%u", addrbuf.sa6.sin6_scope_id);
216 #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
217                 break;
218 #endif
219 #if defined(AF_IPX)
220         case AF_IPX:
221                 {
222                         int i;
223                         tprintf("sipx_port=htons(%u), ",
224                                         ntohs(addrbuf.sipx.sipx_port));
225                         /* Yes, I know, this does not look too
226                          * strace-ish, but otherwise the IPX
227                          * addresses just look monstrous...
228                          * Anyways, feel free if you don't like
229                          * this way.. :)
230                          */
231                         tprintf("%08lx:", (unsigned long)ntohl(addrbuf.sipx.sipx_network));
232                         for (i = 0; i < IPX_NODE_LEN; i++)
233                                 tprintf("%02x", addrbuf.sipx.sipx_node[i]);
234                         tprintf("/[%02x]", addrbuf.sipx.sipx_type);
235                 }
236                 break;
237 #endif /* AF_IPX */
238 #ifdef AF_PACKET
239         case AF_PACKET:
240                 {
241                         int i;
242                         tprintf("proto=%#04x, if%d, pkttype=",
243                                         ntohs(addrbuf.ll.sll_protocol),
244                                         addrbuf.ll.sll_ifindex);
245                         printxval(af_packet_types, addrbuf.ll.sll_pkttype, "PACKET_???");
246                         tprintf(", addr(%d)={%d, ",
247                                         addrbuf.ll.sll_halen,
248                                         addrbuf.ll.sll_hatype);
249                         for (i = 0; i < addrbuf.ll.sll_halen; i++)
250                                 tprintf("%02x", addrbuf.ll.sll_addr[i]);
251                 }
252                 break;
253
254 #endif /* AF_PACKET */
255 #ifdef AF_NETLINK
256         case AF_NETLINK:
257                 tprintf("pid=%d, groups=%08x", addrbuf.nl.nl_pid, addrbuf.nl.nl_groups);
258                 break;
259 #endif /* AF_NETLINK */
260 #if defined(AF_BLUETOOTH) && defined(HAVE_BLUETOOTH_BLUETOOTH_H)
261         case AF_BLUETOOTH:
262                 tprintf("{sco_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X} or "
263                         "{rc_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, rc_channel=%d} or "
264                         "{l2_psm=htobs(%d), l2_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, l2_cid=htobs(%d)} or "
265                         "{hci_dev=htobs(%d)}",
266                         addrbuf.sco.sco_bdaddr.b[0], addrbuf.sco.sco_bdaddr.b[1],
267                         addrbuf.sco.sco_bdaddr.b[2], addrbuf.sco.sco_bdaddr.b[3],
268                         addrbuf.sco.sco_bdaddr.b[4], addrbuf.sco.sco_bdaddr.b[5],
269                         addrbuf.rc.rc_bdaddr.b[0], addrbuf.rc.rc_bdaddr.b[1],
270                         addrbuf.rc.rc_bdaddr.b[2], addrbuf.rc.rc_bdaddr.b[3],
271                         addrbuf.rc.rc_bdaddr.b[4], addrbuf.rc.rc_bdaddr.b[5],
272                         addrbuf.rc.rc_channel,
273                         btohs(addrbuf.l2.l2_psm), addrbuf.l2.l2_bdaddr.b[0],
274                         addrbuf.l2.l2_bdaddr.b[1], addrbuf.l2.l2_bdaddr.b[2],
275                         addrbuf.l2.l2_bdaddr.b[3], addrbuf.l2.l2_bdaddr.b[4],
276                         addrbuf.l2.l2_bdaddr.b[5], btohs(addrbuf.l2.l2_cid),
277                         btohs(addrbuf.hci.hci_dev));
278                 break;
279 #endif /* AF_BLUETOOTH && HAVE_BLUETOOTH_BLUETOOTH_H */
280         /* AF_AX25 AF_APPLETALK AF_NETROM AF_BRIDGE AF_AAL5
281         AF_X25 AF_ROSE etc. still need to be done */
282
283         default:
284                 tprints("sa_data=");
285                 print_quoted_string(addrbuf.sa.sa_data,
286                                     sizeof(addrbuf.sa.sa_data), 0);
287                 break;
288         }
289         tprints("}");
290 }
291
292 #ifdef HAVE_SENDMSG
293 # ifndef SCM_SECURITY
294 #  define SCM_SECURITY 0x03
295 # endif
296 # include "xlat/scmvals.h"
297
298 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
299 struct cmsghdr32 {
300         uint32_t cmsg_len;
301         int cmsg_level;
302         int cmsg_type;
303 };
304 #endif
305
306 typedef union {
307         char *ptr;
308         struct cmsghdr *cmsg;
309 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
310         struct cmsghdr32 *cmsg32;
311 #endif
312 } union_cmsghdr;
313
314 static bool
315 print_scm_rights(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
316 {
317         if (cmsg_size + sizeof(int) > cmsg_len)
318                 return false;
319
320         int *fds = (int *) (ptr + cmsg_size);
321         bool seen = false;
322
323         tprints(", [");
324         while ((char *) fds < (ptr + cmsg_len)) {
325                 if (seen)
326                         tprints(", ");
327                 else
328                         seen = true;
329                 printfd(tcp, *fds++);
330         }
331         tprints("]}");
332         return true;
333 }
334
335 static bool
336 print_scm_creds(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
337 {
338         if (cmsg_size + sizeof(struct ucred) > cmsg_len)
339                 return false;
340
341         const struct ucred *uc = (void *) (ptr + cmsg_size);
342
343         tprintf(", {pid=%u, uid=%u, gid=%u}}",
344                 (unsigned) uc->pid, (unsigned) uc->uid, (unsigned) uc->gid);
345         return true;
346 }
347
348 static bool
349 print_scm_security(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
350 {
351         if (cmsg_size + sizeof(char) > cmsg_len)
352                 return false;
353
354         const char *label = (const char *) (ptr + cmsg_size);
355         const size_t label_len = cmsg_len - cmsg_size;
356
357         tprints(", ");
358         print_quoted_string(label, label_len, 0);
359         tprints("}");
360
361         return true;
362 }
363
364 static void
365 printcmsghdr(struct tcb *tcp, unsigned long addr, size_t len)
366 {
367         const size_t cmsg_size =
368 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
369                 (current_wordsize < sizeof(long)) ? sizeof(struct cmsghdr32) :
370 #endif
371                         sizeof(struct cmsghdr);
372
373         char *buf = len < cmsg_size ? NULL : malloc(len);
374         if (!buf || umoven(tcp, addr, len, buf) < 0) {
375                 tprints(", msg_control=");
376                 printaddr(addr);
377                 free(buf);
378                 return;
379         }
380
381         union_cmsghdr u = { .ptr = buf };
382
383         tprints(", [");
384         while (len >= cmsg_size) {
385                 size_t cmsg_len =
386 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
387                         (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_len :
388 #endif
389                                 u.cmsg->cmsg_len;
390                 int cmsg_level =
391 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
392                         (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_level :
393 #endif
394                                 u.cmsg->cmsg_level;
395                 int cmsg_type =
396 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
397                         (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_type :
398 #endif
399                                 u.cmsg->cmsg_type;
400
401                 if (u.ptr != buf)
402                         tprints(", ");
403                 tprintf("{cmsg_len=%lu, cmsg_level=", (unsigned long) cmsg_len);
404                 printxval(socketlayers, cmsg_level, "SOL_???");
405                 tprints(", cmsg_type=");
406
407                 if (cmsg_len > len)
408                         cmsg_len = len;
409
410                 if (cmsg_level == SOL_SOCKET) {
411                         printxval(scmvals, cmsg_type, "SCM_???");
412                         switch (cmsg_type) {
413                         case SCM_RIGHTS:
414                                 if (print_scm_rights(tcp, cmsg_size, u.ptr, cmsg_len))
415                                         goto next_cmsg;
416                                 break;
417                         case SCM_CREDENTIALS:
418                                 if (print_scm_creds(tcp, cmsg_size, u.ptr, cmsg_len))
419                                         goto next_cmsg;
420                                 break;
421                         case SCM_SECURITY:
422                                 if (print_scm_security(tcp, cmsg_size, u.ptr, cmsg_len))
423                                         goto next_cmsg;
424                                 break;
425                         }
426                 } else {
427                         tprintf("%u", cmsg_type);
428                 }
429                 tprints(", ...}");
430 next_cmsg:
431                 if (cmsg_len < cmsg_size) {
432                         len -= cmsg_size;
433                         break;
434                 }
435                 cmsg_len = (cmsg_len + current_wordsize - 1) &
436                         (size_t) ~(current_wordsize - 1);
437                 if (cmsg_len >= len) {
438                         len = 0;
439                         break;
440                 }
441                 u.ptr += cmsg_len;
442                 len -= cmsg_len;
443         }
444         if (len)
445                 tprints(", ...");
446         tprints("]");
447         free(buf);
448 }
449
450 static void
451 do_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size)
452 {
453         tprintf("{msg_name(%d)=", msg->msg_namelen);
454         printsock(tcp, (long)msg->msg_name, msg->msg_namelen);
455
456         tprintf(", msg_iov(%lu)=", (unsigned long)msg->msg_iovlen);
457         tprint_iov_upto(tcp, (unsigned long)msg->msg_iovlen,
458                    (unsigned long)msg->msg_iov, 1, data_size);
459
460 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
461         tprintf(", msg_controllen=%lu", (unsigned long)msg->msg_controllen);
462         if (msg->msg_controllen)
463                 printcmsghdr(tcp, (unsigned long) msg->msg_control,
464                              msg->msg_controllen);
465         tprints(", msg_flags=");
466         printflags(msg_flags, msg->msg_flags, "MSG_???");
467 #else /* !HAVE_STRUCT_MSGHDR_MSG_CONTROL */
468         tprintf("msg_accrights=%#lx, msg_accrightslen=%u",
469                 (unsigned long) msg->msg_accrights, msg->msg_accrightslen);
470 #endif /* !HAVE_STRUCT_MSGHDR_MSG_CONTROL */
471         tprints("}");
472 }
473
474 struct msghdr32 {
475         uint32_t /* void* */    msg_name;
476         uint32_t /* socklen_t */msg_namelen;
477         uint32_t /* iovec* */   msg_iov;
478         uint32_t /* size_t */   msg_iovlen;
479         uint32_t /* void* */    msg_control;
480         uint32_t /* size_t */   msg_controllen;
481         uint32_t /* int */      msg_flags;
482 };
483 struct mmsghdr32 {
484         struct msghdr32         msg_hdr;
485         uint32_t /* unsigned */ msg_len;
486 };
487
488 #ifndef HAVE_STRUCT_MMSGHDR
489 struct mmsghdr {
490         struct msghdr msg_hdr;
491         unsigned msg_len;
492 };
493 #endif
494
495 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
496 static void
497 copy_from_msghdr32(struct msghdr *to_msg, struct msghdr32 *from_msg32)
498 {
499         to_msg->msg_name       = (void*)(long)from_msg32->msg_name;
500         to_msg->msg_namelen    =              from_msg32->msg_namelen;
501         to_msg->msg_iov        = (void*)(long)from_msg32->msg_iov;
502         to_msg->msg_iovlen     =              from_msg32->msg_iovlen;
503         to_msg->msg_control    = (void*)(long)from_msg32->msg_control;
504         to_msg->msg_controllen =              from_msg32->msg_controllen;
505         to_msg->msg_flags      =              from_msg32->msg_flags;
506 }
507 #endif
508
509 static bool
510 extractmsghdr(struct tcb *tcp, long addr, struct msghdr *msg)
511 {
512 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
513         if (current_wordsize == 4) {
514                 struct msghdr32 msg32;
515
516                 if (umove(tcp, addr, &msg32) < 0)
517                         return false;
518                 copy_from_msghdr32(msg, &msg32);
519         } else
520 #endif
521         if (umove(tcp, addr, msg) < 0)
522                 return false;
523         return true;
524 }
525
526 static bool
527 extractmmsghdr(struct tcb *tcp, long addr, unsigned int idx, struct mmsghdr *mmsg)
528 {
529 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
530         if (current_wordsize == 4) {
531                 struct mmsghdr32 mmsg32;
532
533                 addr += sizeof(struct mmsghdr32) * idx;
534                 if (umove(tcp, addr, &mmsg32) < 0)
535                         return false;
536
537                 copy_from_msghdr32(&mmsg->msg_hdr, &mmsg32.msg_hdr);
538                 mmsg->msg_len = mmsg32.msg_len;
539         } else
540 #endif
541         {
542                 addr += sizeof(*mmsg) * idx;
543                 if (umove(tcp, addr, mmsg) < 0)
544                         return false;
545         }
546         return true;
547 }
548
549 static void
550 printmsghdr(struct tcb *tcp, long addr, unsigned long data_size)
551 {
552         struct msghdr msg;
553
554         if (verbose(tcp) && extractmsghdr(tcp, addr, &msg))
555                 do_msghdr(tcp, &msg, data_size);
556         else
557                 printaddr(addr);
558 }
559
560 void
561 dumpiov_in_msghdr(struct tcb *tcp, long addr)
562 {
563         struct msghdr msg;
564
565         if (extractmsghdr(tcp, addr, &msg))
566                 dumpiov(tcp, msg.msg_iovlen, (long)msg.msg_iov);
567 }
568
569 static void
570 printmmsghdr(struct tcb *tcp, long addr, unsigned int idx, unsigned long msg_len)
571 {
572         struct mmsghdr mmsg;
573
574         if (extractmmsghdr(tcp, addr, idx, &mmsg)) {
575                 tprints("{");
576                 do_msghdr(tcp, &mmsg.msg_hdr, msg_len ? msg_len : mmsg.msg_len);
577                 tprintf(", %u}", mmsg.msg_len);
578         }
579         else
580                 printaddr(addr);
581 }
582
583 static void
584 decode_mmsg(struct tcb *tcp, unsigned long msg_len)
585 {
586         /* mmsgvec */
587         if (syserror(tcp)) {
588                 printaddr(tcp->u_arg[1]);
589         } else {
590                 unsigned int len = tcp->u_rval;
591                 unsigned int i;
592
593                 tprints("{");
594                 for (i = 0; i < len; ++i) {
595                         if (i)
596                                 tprints(", ");
597                         printmmsghdr(tcp, tcp->u_arg[1], i, msg_len);
598                 }
599                 tprints("}");
600         }
601         /* vlen */
602         tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
603         /* flags */
604         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
605 }
606
607 void
608 dumpiov_in_mmsghdr(struct tcb *tcp, long addr)
609 {
610         unsigned int len = tcp->u_rval;
611         unsigned int i;
612         struct mmsghdr mmsg;
613
614         for (i = 0; i < len; ++i) {
615                 if (extractmmsghdr(tcp, addr, i, &mmsg)) {
616                         tprintf(" = %lu buffers in vector %u\n",
617                                 (unsigned long)mmsg.msg_hdr.msg_iovlen, i);
618                         dumpiov(tcp, mmsg.msg_hdr.msg_iovlen,
619                                 (long)mmsg.msg_hdr.msg_iov);
620                 }
621         }
622 }
623 #endif /* HAVE_SENDMSG */
624
625 /*
626  * low bits of the socket type define real socket type,
627  * other bits are socket type flags.
628  */
629 static void
630 tprint_sock_type(int flags)
631 {
632         const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK);
633
634         if (str) {
635                 tprints(str);
636                 flags &= ~SOCK_TYPE_MASK;
637                 if (!flags)
638                         return;
639                 tprints("|");
640         }
641         printflags(sock_type_flags, flags, "SOCK_???");
642 }
643
644 SYS_FUNC(socket)
645 {
646         printxval(domains, tcp->u_arg[0], "PF_???");
647         tprints(", ");
648         tprint_sock_type(tcp->u_arg[1]);
649         tprints(", ");
650         switch (tcp->u_arg[0]) {
651         case PF_INET:
652 #ifdef PF_INET6
653         case PF_INET6:
654 #endif
655                 printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???");
656                 break;
657 #ifdef PF_IPX
658         case PF_IPX:
659                 /* BTW: I don't believe this.. */
660                 tprints("[");
661                 printxval(domains, tcp->u_arg[2], "PF_???");
662                 tprints("]");
663                 break;
664 #endif /* PF_IPX */
665 #ifdef PF_NETLINK
666         case PF_NETLINK:
667                 printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???");
668                 break;
669 #endif
670 #if defined(PF_BLUETOOTH) && defined(HAVE_BLUETOOTH_BLUETOOTH_H)
671         case PF_BLUETOOTH:
672                 printxval(bt_protocols, tcp->u_arg[2], "BTPROTO_???");
673                 break;
674 #endif
675         default:
676                 tprintf("%lu", tcp->u_arg[2]);
677                 break;
678         }
679
680         return RVAL_DECODED | RVAL_FD;
681 }
682
683 SYS_FUNC(bind)
684 {
685         printfd(tcp, tcp->u_arg[0]);
686         tprints(", ");
687         printsock(tcp, tcp->u_arg[1], tcp->u_arg[2]);
688         tprintf(", %lu", tcp->u_arg[2]);
689
690         return RVAL_DECODED;
691 }
692
693 SYS_FUNC(listen)
694 {
695         printfd(tcp, tcp->u_arg[0]);
696         tprints(", ");
697         tprintf("%lu", tcp->u_arg[1]);
698
699         return RVAL_DECODED;
700 }
701
702 static int
703 do_sockname(struct tcb *tcp, int flags_arg)
704 {
705         if (entering(tcp)) {
706                 printfd(tcp, tcp->u_arg[0]);
707                 tprints(", ");
708                 return 0;
709         }
710
711         int len;
712         if (!tcp->u_arg[2] || !verbose(tcp) || syserror(tcp) ||
713             umove(tcp, tcp->u_arg[2], &len) < 0) {
714                 printaddr(tcp->u_arg[1]);
715                 tprints(", ");
716                 printaddr(tcp->u_arg[2]);
717         } else {
718                 printsock(tcp, tcp->u_arg[1], len);
719                 tprintf(", [%d]", len);
720         }
721
722         if (flags_arg >= 0) {
723                 tprints(", ");
724                 printflags(sock_type_flags, tcp->u_arg[flags_arg],
725                            "SOCK_???");
726         }
727         return 0;
728 }
729
730 SYS_FUNC(accept)
731 {
732         do_sockname(tcp, -1);
733         return RVAL_FD;
734 }
735
736 SYS_FUNC(accept4)
737 {
738         do_sockname(tcp, 3);
739         return RVAL_FD;
740 }
741
742 SYS_FUNC(send)
743 {
744         printfd(tcp, tcp->u_arg[0]);
745         tprints(", ");
746         printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
747         tprintf(", %lu, ", tcp->u_arg[2]);
748         /* flags */
749         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
750
751         return RVAL_DECODED;
752 }
753
754 SYS_FUNC(sendto)
755 {
756         printfd(tcp, tcp->u_arg[0]);
757         tprints(", ");
758         printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
759         tprintf(", %lu, ", tcp->u_arg[2]);
760         /* flags */
761         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
762         /* to address */
763         tprints(", ");
764         printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]);
765         /* to length */
766         tprintf(", %lu", tcp->u_arg[5]);
767
768         return RVAL_DECODED;
769 }
770
771 #ifdef HAVE_SENDMSG
772
773 SYS_FUNC(sendmsg)
774 {
775         printfd(tcp, tcp->u_arg[0]);
776         tprints(", ");
777         printmsghdr(tcp, tcp->u_arg[1], (unsigned long) -1L);
778         /* flags */
779         tprints(", ");
780         printflags(msg_flags, tcp->u_arg[2], "MSG_???");
781
782         return RVAL_DECODED;
783 }
784
785 SYS_FUNC(sendmmsg)
786 {
787         if (entering(tcp)) {
788                 /* sockfd */
789                 printfd(tcp, tcp->u_arg[0]);
790                 tprints(", ");
791                 if (!verbose(tcp)) {
792                         tprintf("%#lx, %u, ",
793                                 tcp->u_arg[1], (unsigned int) tcp->u_arg[2]);
794                         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
795                 }
796         } else {
797                 if (verbose(tcp))
798                         decode_mmsg(tcp, (unsigned long) -1L);
799         }
800         return 0;
801 }
802
803 #endif /* HAVE_SENDMSG */
804
805 SYS_FUNC(recv)
806 {
807         if (entering(tcp)) {
808                 printfd(tcp, tcp->u_arg[0]);
809                 tprints(", ");
810         } else {
811                 if (syserror(tcp))
812                         printaddr(tcp->u_arg[1]);
813                 else
814                         printstr(tcp, tcp->u_arg[1], tcp->u_rval);
815
816                 tprintf(", %lu, ", tcp->u_arg[2]);
817                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
818         }
819         return 0;
820 }
821
822 SYS_FUNC(recvfrom)
823 {
824         int fromlen;
825
826         if (entering(tcp)) {
827                 printfd(tcp, tcp->u_arg[0]);
828                 tprints(", ");
829         } else {
830                 /* buf */
831                 if (syserror(tcp)) {
832                         printaddr(tcp->u_arg[1]);
833                 } else {
834                         printstr(tcp, tcp->u_arg[1], tcp->u_rval);
835                 }
836                 /* len */
837                 tprintf(", %lu, ", tcp->u_arg[2]);
838                 /* flags */
839                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
840                 tprints(", ");
841                 if (syserror(tcp) || !tcp->u_arg[4] || !tcp->u_arg[5] ||
842                     umove(tcp, tcp->u_arg[5], &fromlen) < 0) {
843                         /* from address, len */
844                         printaddr(tcp->u_arg[4]);
845                         tprints(", ");
846                         printaddr(tcp->u_arg[5]);
847                         return 0;
848                 }
849                 /* from address */
850                 printsock(tcp, tcp->u_arg[4], fromlen);
851                 /* from length */
852                 tprintf(", [%u]", fromlen);
853         }
854         return 0;
855 }
856
857 #ifdef HAVE_SENDMSG
858
859 SYS_FUNC(recvmsg)
860 {
861         if (entering(tcp)) {
862                 printfd(tcp, tcp->u_arg[0]);
863                 tprints(", ");
864         } else {
865                 if (syserror(tcp))
866                         printaddr(tcp->u_arg[1]);
867                 else
868                         printmsghdr(tcp, tcp->u_arg[1], tcp->u_rval);
869                 /* flags */
870                 tprints(", ");
871                 printflags(msg_flags, tcp->u_arg[2], "MSG_???");
872         }
873         return 0;
874 }
875
876 SYS_FUNC(recvmmsg)
877 {
878         /* +5 chars are for "left " prefix */
879         static char str[5 + TIMESPEC_TEXT_BUFSIZE];
880
881         if (entering(tcp)) {
882                 printfd(tcp, tcp->u_arg[0]);
883                 tprints(", ");
884                 if (verbose(tcp)) {
885                         sprint_timespec(str, tcp, tcp->u_arg[4]);
886                         /* Abusing tcp->auxstr as temp storage.
887                          * Will be used and freed on syscall exit.
888                          */
889                         tcp->auxstr = xstrdup(str);
890                 } else {
891                         tprintf("%#lx, %ld, ", tcp->u_arg[1], tcp->u_arg[2]);
892                         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
893                         tprints(", ");
894                         print_timespec(tcp, tcp->u_arg[4]);
895                 }
896                 return 0;
897         } else {
898                 if (verbose(tcp)) {
899                         decode_mmsg(tcp, 0);
900                         /* timeout on entrance */
901                         tprintf(", %s", tcp->auxstr ? tcp->auxstr : "{...}");
902                         free((void *) tcp->auxstr);
903                         tcp->auxstr = NULL;
904                 }
905                 if (syserror(tcp))
906                         return 0;
907                 if (tcp->u_rval == 0) {
908                         tcp->auxstr = "Timeout";
909                         return RVAL_STR;
910                 }
911                 if (!verbose(tcp))
912                         return 0;
913                 /* timeout on exit */
914                 sprint_timespec(stpcpy(str, "left "), tcp, tcp->u_arg[4]);
915                 tcp->auxstr = str;
916                 return RVAL_STR;
917         }
918 }
919
920 #endif /* HAVE_SENDMSG */
921
922 #include "xlat/shutdown_modes.h"
923
924 SYS_FUNC(shutdown)
925 {
926         printfd(tcp, tcp->u_arg[0]);
927         tprints(", ");
928         printxval(shutdown_modes, tcp->u_arg[1], "SHUT_???");
929
930         return RVAL_DECODED;
931 }
932
933 SYS_FUNC(getsockname)
934 {
935         return do_sockname(tcp, -1);
936 }
937
938 static void
939 printpair_fd(struct tcb *tcp, const int i0, const int i1)
940 {
941         tprints("[");
942         printfd(tcp, i0);
943         tprints(", ");
944         printfd(tcp, i1);
945         tprints("]");
946 }
947
948 static void
949 decode_pair_fd(struct tcb *tcp, const long addr)
950 {
951         int pair[2];
952
953         if (umove_or_printaddr(tcp, addr, &pair))
954                 return;
955
956         printpair_fd(tcp, pair[0], pair[1]);
957 }
958
959 static int
960 do_pipe(struct tcb *tcp, int flags_arg)
961 {
962         if (exiting(tcp)) {
963                 if (syserror(tcp)) {
964                         printaddr(tcp->u_arg[0]);
965                 } else {
966 #ifdef HAVE_GETRVAL2
967                         if (flags_arg < 0) {
968                                 printpair_fd(tcp, tcp->u_rval, getrval2(tcp));
969                         } else
970 #endif
971                                 decode_pair_fd(tcp, tcp->u_arg[0]);
972                 }
973                 if (flags_arg >= 0) {
974                         tprints(", ");
975                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
976                 }
977         }
978         return 0;
979 }
980
981 SYS_FUNC(pipe)
982 {
983         return do_pipe(tcp, -1);
984 }
985
986 SYS_FUNC(pipe2)
987 {
988         return do_pipe(tcp, 1);
989 }
990
991 SYS_FUNC(socketpair)
992 {
993         if (entering(tcp)) {
994                 printxval(domains, tcp->u_arg[0], "PF_???");
995                 tprints(", ");
996                 tprint_sock_type(tcp->u_arg[1]);
997                 tprintf(", %lu", tcp->u_arg[2]);
998         } else {
999                 tprints(", ");
1000                 decode_pair_fd(tcp, tcp->u_arg[3]);
1001         }
1002         return 0;
1003 }
1004
1005 #include "xlat/sockoptions.h"
1006 #include "xlat/sockipoptions.h"
1007 #include "xlat/getsockipoptions.h"
1008 #include "xlat/setsockipoptions.h"
1009 #include "xlat/sockipv6options.h"
1010 #include "xlat/getsockipv6options.h"
1011 #include "xlat/setsockipv6options.h"
1012 #include "xlat/sockipxoptions.h"
1013 #include "xlat/sockrawoptions.h"
1014 #include "xlat/sockpacketoptions.h"
1015 #include "xlat/socksctpoptions.h"
1016 #include "xlat/socktcpoptions.h"
1017
1018 static void
1019 print_sockopt_fd_level_name(struct tcb *tcp, int fd, int level, int name, bool is_getsockopt)
1020 {
1021         printfd(tcp, fd);
1022         tprints(", ");
1023         printxval(socketlayers, level, "SOL_??");
1024         tprints(", ");
1025
1026         switch (level) {
1027         case SOL_SOCKET:
1028                 printxval(sockoptions, name, "SO_???");
1029                 break;
1030         case SOL_IP:
1031                 printxvals(name, "IP_???", sockipoptions,
1032                         is_getsockopt ? getsockipoptions : setsockipoptions, NULL);
1033                 break;
1034         case SOL_IPV6:
1035                 printxvals(name, "IPV6_???", sockipv6options,
1036                         is_getsockopt ? getsockipv6options : setsockipv6options, NULL);
1037                 break;
1038         case SOL_IPX:
1039                 printxval(sockipxoptions, name, "IPX_???");
1040                 break;
1041         case SOL_PACKET:
1042                 printxval(sockpacketoptions, name, "PACKET_???");
1043                 break;
1044         case SOL_TCP:
1045                 printxval(socktcpoptions, name, "TCP_???");
1046                 break;
1047         case SOL_SCTP:
1048                 printxval(socksctpoptions, name, "SCTP_???");
1049                 break;
1050         case SOL_RAW:
1051                 printxval(sockrawoptions, name, "RAW_???");
1052                 break;
1053
1054                 /* Other SOL_* protocol levels still need work. */
1055
1056         default:
1057                 tprintf("%u", name);
1058         }
1059
1060         tprints(", ");
1061 }
1062
1063 #ifdef SO_LINGER
1064 static void
1065 print_linger(struct tcb *tcp, long addr, int len)
1066 {
1067         struct linger linger;
1068
1069         if (len != sizeof(linger) ||
1070             umove(tcp, addr, &linger) < 0) {
1071                 printaddr(addr);
1072                 return;
1073         }
1074
1075         tprintf("{onoff=%d, linger=%d}",
1076                 linger.l_onoff,
1077                 linger.l_linger);
1078 }
1079 #endif /* SO_LINGER */
1080
1081 #ifdef SO_PEERCRED
1082 static void
1083 print_ucred(struct tcb *tcp, long addr, int len)
1084 {
1085         struct ucred uc;
1086
1087         if (len != sizeof(uc) ||
1088             umove(tcp, addr, &uc) < 0) {
1089                 printaddr(addr);
1090         } else {
1091                 tprintf("{pid=%u, uid=%u, gid=%u}",
1092                         (unsigned) uc.pid,
1093                         (unsigned) uc.uid,
1094                         (unsigned) uc.gid);
1095         }
1096 }
1097 #endif /* SO_PEERCRED */
1098
1099 #ifdef PACKET_STATISTICS
1100 static void
1101 print_tpacket_stats(struct tcb *tcp, long addr, int len)
1102 {
1103         struct tpacket_stats stats;
1104
1105         if (len != sizeof(stats) ||
1106             umove(tcp, addr, &stats) < 0) {
1107                 printaddr(addr);
1108         } else {
1109                 tprintf("{packets=%u, drops=%u}",
1110                         stats.tp_packets,
1111                         stats.tp_drops);
1112         }
1113 }
1114 #endif /* PACKET_STATISTICS */
1115
1116 #ifdef ICMP_FILTER
1117 # include "xlat/icmpfilterflags.h"
1118
1119 static void
1120 print_icmp_filter(struct tcb *tcp, long addr, int len)
1121 {
1122         struct icmp_filter      filter;
1123
1124         if (len != sizeof(filter) ||
1125             umove(tcp, addr, &filter) < 0) {
1126                 printaddr(addr);
1127                 return;
1128         }
1129
1130         tprints("~(");
1131         printflags(icmpfilterflags, ~filter.data, "ICMP_???");
1132         tprints(")");
1133 }
1134 #endif /* ICMP_FILTER */
1135
1136 static void
1137 print_getsockopt(struct tcb *tcp, int level, int name, long addr, int len)
1138 {
1139         if (addr && verbose(tcp))
1140         switch (level) {
1141         case SOL_SOCKET:
1142                 switch (name) {
1143 #ifdef SO_LINGER
1144                 case SO_LINGER:
1145                         print_linger(tcp, addr, len);
1146                         goto done;
1147 #endif
1148 #ifdef SO_PEERCRED
1149                 case SO_PEERCRED:
1150                         print_ucred(tcp, addr, len);
1151                         goto done;
1152 #endif
1153                 }
1154                 break;
1155
1156         case SOL_PACKET:
1157                 switch (name) {
1158 #ifdef PACKET_STATISTICS
1159                 case PACKET_STATISTICS:
1160                         print_tpacket_stats(tcp, addr, len);
1161                         goto done;
1162 #endif
1163                 }
1164                 break;
1165
1166         case SOL_RAW:
1167                 switch (name) {
1168 #ifdef ICMP_FILTER
1169                 case ICMP_FILTER:
1170                         print_icmp_filter(tcp, addr, len);
1171                         goto done;
1172 #endif
1173                 }
1174                 break;
1175         }
1176
1177         /* default arg printing */
1178
1179         if (verbose(tcp)) {
1180                 if (len == sizeof(int)) {
1181                         printnum_int(tcp, addr, "%d");
1182                 } else {
1183                         printstr(tcp, addr, len);
1184                 }
1185         } else {
1186                 printaddr(addr);
1187         }
1188 done:
1189         tprintf(", [%d]", len);
1190 }
1191
1192 SYS_FUNC(getsockopt)
1193 {
1194         if (entering(tcp)) {
1195                 print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
1196                                             tcp->u_arg[1], tcp->u_arg[2], true);
1197         } else {
1198                 int len;
1199
1200                 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &len) < 0) {
1201                         tprintf("%#lx, %#lx",
1202                                 tcp->u_arg[3], tcp->u_arg[4]);
1203                 } else {
1204                         print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
1205                                          tcp->u_arg[3], len);
1206                 }
1207         }
1208         return 0;
1209 }
1210
1211 #ifdef IP_ADD_MEMBERSHIP
1212 static void
1213 print_mreq(struct tcb *tcp, long addr, unsigned int len)
1214 {
1215         struct ip_mreq mreq;
1216
1217         if (len < sizeof(mreq)) {
1218                 printstr(tcp, addr, len);
1219                 return;
1220         }
1221         if (umove_or_printaddr(tcp, addr, &mreq))
1222                 return;
1223
1224         tprints("{imr_multiaddr=inet_addr(");
1225         print_quoted_string(inet_ntoa(mreq.imr_multiaddr),
1226                             16, QUOTE_0_TERMINATED);
1227         tprints("), imr_interface=inet_addr(");
1228         print_quoted_string(inet_ntoa(mreq.imr_interface),
1229                             16, QUOTE_0_TERMINATED);
1230         tprints(")}");
1231 }
1232 #endif /* IP_ADD_MEMBERSHIP */
1233
1234 #ifdef IPV6_ADD_MEMBERSHIP
1235 static void
1236 print_mreq6(struct tcb *tcp, long addr, unsigned int len)
1237 {
1238         struct ipv6_mreq mreq;
1239
1240         if (len < sizeof(mreq))
1241                 goto fail;
1242
1243         if (umove_or_printaddr(tcp, addr, &mreq))
1244                 return;
1245
1246 #ifdef HAVE_INET_NTOP
1247         const struct in6_addr *in6 = &mreq.ipv6mr_multiaddr;
1248         char address[INET6_ADDRSTRLEN];
1249
1250         if (!inet_ntop(AF_INET6, in6, address, sizeof(address)))
1251                 goto fail;
1252
1253         tprints("{ipv6mr_multiaddr=inet_pton(");
1254         print_quoted_string(address, sizeof(address), QUOTE_0_TERMINATED);
1255         tprints("), ipv6mr_interface=");
1256         print_ifindex(mreq.ipv6mr_interface);
1257         tprints("}");
1258         return;
1259 #endif /* HAVE_INET_NTOP */
1260
1261 fail:
1262         printstr(tcp, addr, len);
1263 }
1264 #endif /* IPV6_ADD_MEMBERSHIP */
1265
1266 #ifdef MCAST_JOIN_GROUP
1267 static void
1268 print_group_req(struct tcb *tcp, long addr, int len)
1269 {
1270         struct group_req greq;
1271
1272         if (len != sizeof(greq) ||
1273             umove(tcp, addr, &greq) < 0) {
1274                 printaddr(addr);
1275                 return;
1276         }
1277
1278         union {
1279                 struct sockaddr *sa;
1280                 struct sockaddr_in *sin;
1281 #ifdef HAVE_INET_NTOP
1282                 struct sockaddr_in6 *sin6;
1283 #endif
1284         } a = { .sa = (struct sockaddr *) &greq.gr_group };
1285 #ifdef HAVE_INET_NTOP
1286         char str[INET6_ADDRSTRLEN];
1287 #endif
1288
1289         tprintf("{gr_interface=%u, gr_group={sa_family=", greq.gr_interface);
1290         printxval(addrfams, a.sa->sa_family, "AF_???");
1291
1292         switch (a.sa->sa_family) {
1293         case AF_INET:
1294                 tprintf(", sin_port=htons(%u), sin_addr=inet_addr(\"%s\")}}",
1295                         ntohs(a.sin->sin_port),
1296                         inet_ntoa(a.sin->sin_addr));
1297                 return;
1298 #ifdef HAVE_INET_NTOP
1299         case AF_INET6:
1300                 if (!inet_ntop(AF_INET6, &a.sin6->sin6_addr, str, sizeof(str)))
1301                         break;
1302                 tprintf(", sin6_port=htons(%u)"
1303                         ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}}",
1304                         ntohs(a.sin6->sin6_port), str);
1305                 return;
1306 #endif /* HAVE_INET_NTOP */
1307         }
1308
1309         tprints(", sa_data=");
1310         print_quoted_string(a.sa->sa_data, sizeof(a.sa->sa_data), 0);
1311         tprintf("}}");
1312
1313 }
1314 #endif /* MCAST_JOIN_GROUP */
1315
1316 #ifdef PACKET_RX_RING
1317 static void
1318 print_tpacket_req(struct tcb *tcp, long addr, int len)
1319 {
1320         struct tpacket_req req;
1321
1322         if (len != sizeof(req) ||
1323             umove(tcp, addr, &req) < 0) {
1324                 printaddr(addr);
1325         } else {
1326                 tprintf("{block_size=%u, block_nr=%u, "
1327                         "frame_size=%u, frame_nr=%u}",
1328                         req.tp_block_size,
1329                         req.tp_block_nr,
1330                         req.tp_frame_size,
1331                         req.tp_frame_nr);
1332         }
1333 }
1334 #endif /* PACKET_RX_RING */
1335
1336 #ifdef PACKET_ADD_MEMBERSHIP
1337 # include "xlat/packet_mreq_type.h"
1338
1339 static void
1340 print_packet_mreq(struct tcb *tcp, long addr, int len)
1341 {
1342         struct packet_mreq mreq;
1343
1344         if (len != sizeof(mreq) ||
1345             umove(tcp, addr, &mreq) < 0) {
1346                 printaddr(addr);
1347         } else {
1348                 unsigned int i;
1349
1350                 tprintf("{mr_ifindex=%u, mr_type=", mreq.mr_ifindex);
1351                 printxval(packet_mreq_type, mreq.mr_type, "PACKET_MR_???");
1352                 tprintf(", mr_alen=%u, mr_address=", mreq.mr_alen);
1353                 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
1354                         mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
1355                 for (i = 0; i < mreq.mr_alen; ++i)
1356                         tprintf("%02x", mreq.mr_address[i]);
1357                 tprints("}");
1358         }
1359 }
1360 #endif /* PACKET_ADD_MEMBERSHIP */
1361
1362 static void
1363 print_setsockopt(struct tcb *tcp, int level, int name, long addr, int len)
1364 {
1365         if (addr && verbose(tcp))
1366         switch (level) {
1367         case SOL_SOCKET:
1368                 switch (name) {
1369 #ifdef SO_LINGER
1370                 case SO_LINGER:
1371                         print_linger(tcp, addr, len);
1372                         goto done;
1373 #endif
1374                 }
1375                 break;
1376
1377         case SOL_IP:
1378                 switch (name) {
1379 #ifdef IP_ADD_MEMBERSHIP
1380                 case IP_ADD_MEMBERSHIP:
1381                 case IP_DROP_MEMBERSHIP:
1382                         print_mreq(tcp, addr, len);
1383                         goto done;
1384 #endif /* IP_ADD_MEMBERSHIP */
1385 #ifdef MCAST_JOIN_GROUP
1386                 case MCAST_JOIN_GROUP:
1387                 case MCAST_LEAVE_GROUP:
1388                         print_group_req(tcp, addr, len);
1389                         goto done;
1390 #endif /* MCAST_JOIN_GROUP */
1391                 }
1392                 break;
1393
1394         case SOL_IPV6:
1395                 switch (name) {
1396 #ifdef IPV6_ADD_MEMBERSHIP
1397                 case IPV6_ADD_MEMBERSHIP:
1398                 case IPV6_DROP_MEMBERSHIP:
1399 # ifdef IPV6_JOIN_ANYCAST
1400                 case IPV6_JOIN_ANYCAST:
1401 # endif
1402 # ifdef IPV6_LEAVE_ANYCAST
1403                 case IPV6_LEAVE_ANYCAST:
1404 # endif
1405                         print_mreq6(tcp, addr, len);
1406                         goto done;
1407 #endif /* IPV6_ADD_MEMBERSHIP */
1408                 }
1409                 break;
1410
1411         case SOL_PACKET:
1412                 switch (name) {
1413 #ifdef PACKET_RX_RING
1414                 case PACKET_RX_RING:
1415 # ifdef PACKET_TX_RING
1416                 case PACKET_TX_RING:
1417 # endif
1418                         print_tpacket_req(tcp, addr, len);
1419                         goto done;
1420 #endif /* PACKET_RX_RING */
1421 #ifdef PACKET_ADD_MEMBERSHIP
1422                 case PACKET_ADD_MEMBERSHIP:
1423                 case PACKET_DROP_MEMBERSHIP:
1424                         print_packet_mreq(tcp, addr, len);
1425                         goto done;
1426 #endif /* PACKET_ADD_MEMBERSHIP */
1427                 }
1428                 break;
1429
1430         case SOL_RAW:
1431                 switch (name) {
1432 #ifdef ICMP_FILTER
1433                 case ICMP_FILTER:
1434                         print_icmp_filter(tcp, addr, len);
1435                         goto done;
1436 #endif
1437                 }
1438                 break;
1439         }
1440
1441         /* default arg printing */
1442
1443         if (verbose(tcp)) {
1444                 if (len == sizeof(int)) {
1445                         printnum_int(tcp, addr, "%d");
1446                 } else {
1447                         printstr(tcp, addr, len);
1448                 }
1449         } else {
1450                 printaddr(addr);
1451         }
1452 done:
1453         tprintf(", %d", len);
1454 }
1455
1456 SYS_FUNC(setsockopt)
1457 {
1458         print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
1459                                     tcp->u_arg[1], tcp->u_arg[2], false);
1460         print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
1461                          tcp->u_arg[3], tcp->u_arg[4]);
1462
1463         return RVAL_DECODED;
1464 }