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