blob: 86d93fc23c0fd6c31fa6b2845a339ede3569607a [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
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>
Wichert Akkerman7987cdf2000-07-05 16:05:39 +00005 * Copyright (c) 1996-2000 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * 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.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000029 */
30
31#include "defs.h"
Dmitry V. Levin4b38ce92016-06-27 00:02:41 +000032#include "msghdr.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000033#include <sys/stat.h>
34#include <sys/socket.h>
Dmitry V. Levinb2fa2be2014-11-21 20:46:16 +000035#include <sys/uio.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <sys/un.h>
37#include <netinet/in.h>
Wichert Akkerman8c7122c2001-02-16 19:59:55 +000038#ifdef HAVE_NETINET_TCP_H
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +010039# include <netinet/tcp.h>
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000040#endif
Wichert Akkerman8c7122c2001-02-16 19:59:55 +000041#ifdef HAVE_NETINET_UDP_H
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +010042# include <netinet/udp.h>
Wichert Akkerman8c7122c2001-02-16 19:59:55 +000043#endif
Holger Hans Peter Freyther7fea79b2011-01-14 11:08:12 +010044#ifdef HAVE_NETINET_SCTP_H
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +010045# include <netinet/sctp.h>
Holger Hans Peter Freyther7fea79b2011-01-14 11:08:12 +010046#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000047#include <arpa/inet.h>
Wichert Akkermanf1850652001-02-16 20:29:03 +000048#include <net/if.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049#include <asm/types.h>
Dmitry V. Levinebda41a2016-06-19 22:02:45 +000050#ifdef HAVE_NETIPX_IPX_H
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +010051# include <netipx/ipx.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000052#else
Denys Vlasenkoa6d91de2012-03-16 12:02:22 +010053# include <linux/ipx.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000054#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000055
Mike Frysinger54646b82015-08-19 13:29:27 -040056#if defined(HAVE_LINUX_IP_VS_H)
57# include <linux/ip_vs.h>
58#endif
Dmitry V. Levinb10ee4e2016-06-14 13:53:47 +000059#include <linux/netlink.h>
Mike Frysinger54646b82015-08-19 13:29:27 -040060#if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H)
61# include <linux/netfilter_arp/arp_tables.h>
62#endif
63#if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H)
64# include <linux/netfilter_bridge/ebtables.h>
65#endif
66#if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H)
67# include <linux/netfilter_ipv4/ip_tables.h>
68#endif
69#if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H)
70# include <linux/netfilter_ipv6/ip6_tables.h>
71#endif
Dmitry V. Levin4f689a12016-06-15 21:35:48 +000072#include <linux/if_packet.h>
Dmitry V. Levind06010b2016-06-15 21:27:41 +000073#include <linux/icmp.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000074
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000075#include "xlat/socktypes.h"
76#include "xlat/sock_type_flags.h"
Dmitry V. Levin8a550d72008-11-10 17:21:23 +000077#ifndef SOCK_TYPE_MASK
78# define SOCK_TYPE_MASK 0xf
79#endif
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +000080
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000081#include "xlat/socketlayers.h"
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +000082
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000083#include "xlat/inet_protocols.h"
Masatake YAMATO2394a3d2014-03-11 23:37:37 +090084
Dmitry V. Levin94573042016-06-14 13:53:47 +000085#if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG
86# define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
Masatake YAMATO2394a3d2014-03-11 23:37:37 +090087#endif
Dmitry V. Levin94573042016-06-14 13:53:47 +000088#include "xlat/netlink_protocols.h"
Masatake YAMATO2394a3d2014-03-11 23:37:37 +090089
Dmitry V. Levine96aee72016-06-25 13:47:54 +000090#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
91# include <bluetooth/bluetooth.h>
Lubomir Rintelc400a1c2014-10-03 11:40:28 +020092# include "xlat/bt_protocols.h"
93#endif
94
Dmitry V. Levin45ae9372016-06-23 17:38:18 +000095void
Dmitry V. Levinae280932015-06-05 20:13:21 +000096print_ifindex(unsigned int ifindex)
97{
98#ifdef HAVE_IF_INDEXTONAME
99 char buf[IFNAMSIZ + 1];
100
101 if (if_indextoname(ifindex, buf)) {
102 tprints("if_nametoindex(");
103 print_quoted_string(buf, sizeof(buf), QUOTE_0_TERMINATED);
104 tprints(")");
105 return;
106 }
107#endif
108 tprintf("%u", ifindex);
109}
110
Fabien Siron2850f742016-07-06 15:49:22 +0000111static void
112decode_sockbuf(struct tcb *tcp, int fd, long addr, long addrlen)
113{
114
115 switch (verbose(tcp) ? getfdproto(tcp, fd) : SOCK_PROTO_UNKNOWN) {
116 case SOCK_PROTO_NETLINK:
117 decode_netlink(tcp, addr, addrlen);
118 break;
119 default:
120 printstr(tcp, addr, addrlen);
121 }
122}
123
Dmitry V. Levin8a550d72008-11-10 17:21:23 +0000124/*
125 * low bits of the socket type define real socket type,
126 * other bits are socket type flags.
127 */
128static void
Dmitry V. Levin9134aab2016-05-14 21:46:05 +0000129tprint_sock_type(unsigned int flags)
Dmitry V. Levin8a550d72008-11-10 17:21:23 +0000130{
131 const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK);
132
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200133 if (str) {
Denys Vlasenko5940e652011-09-01 09:55:05 +0200134 tprints(str);
Dmitry V. Levin8a550d72008-11-10 17:21:23 +0000135 flags &= ~SOCK_TYPE_MASK;
136 if (!flags)
137 return;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200138 tprints("|");
Dmitry V. Levin8a550d72008-11-10 17:21:23 +0000139 }
140 printflags(sock_type_flags, flags, "SOCK_???");
141}
142
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000143SYS_FUNC(socket)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144{
Dmitry V. Levin71fe62e2016-04-04 01:35:28 +0000145 printxval(addrfams, tcp->u_arg[0], "AF_???");
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000146 tprints(", ");
147 tprint_sock_type(tcp->u_arg[1]);
148 tprints(", ");
149 switch (tcp->u_arg[0]) {
Dmitry V. Levin71fe62e2016-04-04 01:35:28 +0000150 case AF_INET:
Dmitry V. Levin71fe62e2016-04-04 01:35:28 +0000151 case AF_INET6:
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000152 printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???");
153 break;
Dmitry V. Levineb1c22b2016-06-19 22:02:45 +0000154
Dmitry V. Levin71fe62e2016-04-04 01:35:28 +0000155 case AF_NETLINK:
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000156 printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???");
157 break;
Dmitry V. Levinbc4102e2016-06-19 22:02:45 +0000158
Dmitry V. Levin43369fc2016-06-21 16:43:30 +0000159#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
Dmitry V. Levin71fe62e2016-04-04 01:35:28 +0000160 case AF_BLUETOOTH:
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000161 printxval(bt_protocols, tcp->u_arg[2], "BTPROTO_???");
162 break;
Lubomir Rintelc400a1c2014-10-03 11:40:28 +0200163#endif
Dmitry V. Levinbc4102e2016-06-19 22:02:45 +0000164
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000165 default:
166 tprintf("%lu", tcp->u_arg[2]);
167 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168 }
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000169
Dmitry V. Levin3d463be2015-08-02 01:41:26 +0000170 return RVAL_DECODED | RVAL_FD;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000171}
172
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000173SYS_FUNC(bind)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174{
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000175 printfd(tcp, tcp->u_arg[0]);
176 tprints(", ");
Dmitry V. Levin42e566a2016-06-25 11:31:48 +0000177 decode_sockaddr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000178 tprintf(", %lu", tcp->u_arg[2]);
179
180 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000181}
182
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000183SYS_FUNC(listen)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184{
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000185 printfd(tcp, tcp->u_arg[0]);
186 tprints(", ");
187 tprintf("%lu", tcp->u_arg[1]);
188
189 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000190}
191
Dmitry V. Levind07eac32016-07-09 21:52:43 +0000192static bool
193fetch_socklen(struct tcb *tcp, int *plen,
194 const unsigned long sockaddr, const unsigned long socklen)
195{
196 return verbose(tcp) && sockaddr && socklen
197 && umove(tcp, socklen, plen) == 0;
198}
199
Paolo Bonzini705ff102009-08-14 12:34:05 +0200200static int
Dmitry V. Levind1cedf02016-07-09 21:52:34 +0000201decode_sockname(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000202{
Dmitry V. Levind07eac32016-07-09 21:52:43 +0000203 int ulen, rlen;
204
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205 if (entering(tcp)) {
Philippe Ombredanne894c7e32014-02-01 09:57:45 -0800206 printfd(tcp, tcp->u_arg[0]);
207 tprints(", ");
Dmitry V. Levind07eac32016-07-09 21:52:43 +0000208 if (fetch_socklen(tcp, &ulen, tcp->u_arg[1], tcp->u_arg[2])) {
209 /* abuse of auxstr to retain state */
210 tcp->auxstr = (void *) (long) ulen;
211 return 0;
212 } else {
213 printaddr(tcp->u_arg[1]);
214 tprints(", ");
215 printaddr(tcp->u_arg[2]);
216 return RVAL_DECODED;
217 }
Paolo Bonzini705ff102009-08-14 12:34:05 +0200218 }
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000219
Dmitry V. Levind07eac32016-07-09 21:52:43 +0000220 ulen = (long) tcp->auxstr;
221 tcp->auxstr = NULL;
222
223 if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &rlen) < 0) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000224 printaddr(tcp->u_arg[1]);
Dmitry V. Levind07eac32016-07-09 21:52:43 +0000225 tprintf(", [%d]", ulen);
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000226 } else {
Dmitry V. Levind07eac32016-07-09 21:52:43 +0000227 decode_sockaddr(tcp, tcp->u_arg[1], ulen > rlen ? rlen : ulen);
228 tprintf(", [%d]", rlen);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229 }
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000230
Dmitry V. Levind1cedf02016-07-09 21:52:34 +0000231 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232}
233
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000234SYS_FUNC(accept)
Paolo Bonzini705ff102009-08-14 12:34:05 +0200235{
Dmitry V. Levind1cedf02016-07-09 21:52:34 +0000236 return decode_sockname(tcp) | RVAL_FD;
Paolo Bonzini705ff102009-08-14 12:34:05 +0200237}
238
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000239SYS_FUNC(accept4)
Paolo Bonzini705ff102009-08-14 12:34:05 +0200240{
Dmitry V. Levind1cedf02016-07-09 21:52:34 +0000241 int rc = decode_sockname(tcp);
242
243 if (rc & RVAL_DECODED) {
244 tprints(", ");
245 printflags(sock_type_flags, tcp->u_arg[3], "SOCK_???");
246 }
247
248 return rc | RVAL_FD;
Paolo Bonzini705ff102009-08-14 12:34:05 +0200249}
Paolo Bonzini705ff102009-08-14 12:34:05 +0200250
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000251SYS_FUNC(send)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000252{
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000253 printfd(tcp, tcp->u_arg[0]);
254 tprints(", ");
Fabien Siron2850f742016-07-06 15:49:22 +0000255 decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000256 tprintf(", %lu, ", tcp->u_arg[2]);
257 /* flags */
258 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
259
260 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000261}
262
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000263SYS_FUNC(sendto)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000264{
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000265 printfd(tcp, tcp->u_arg[0]);
266 tprints(", ");
Fabien Siron2850f742016-07-06 15:49:22 +0000267 decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000268 tprintf(", %lu, ", tcp->u_arg[2]);
269 /* flags */
270 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
271 /* to address */
272 tprints(", ");
Dmitry V. Levin42e566a2016-06-25 11:31:48 +0000273 decode_sockaddr(tcp, tcp->u_arg[4], tcp->u_arg[5]);
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000274 /* to length */
275 tprintf(", %lu", tcp->u_arg[5]);
276
277 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000278}
279
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000280SYS_FUNC(sendmsg)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000281{
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000282 printfd(tcp, tcp->u_arg[0]);
283 tprints(", ");
Dmitry V. Levin3e514c02016-06-26 23:57:29 +0000284 decode_msghdr(tcp, tcp->u_arg[1], (unsigned long) -1L);
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000285 /* flags */
286 tprints(", ");
287 printflags(msg_flags, tcp->u_arg[2], "MSG_???");
288
289 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000290}
291
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000292SYS_FUNC(sendmmsg)
Dmitry V. Levin7af9f352012-03-11 23:59:29 +0000293{
294 if (entering(tcp)) {
295 /* sockfd */
Philippe Ombredanne894c7e32014-02-01 09:57:45 -0800296 printfd(tcp, tcp->u_arg[0]);
297 tprints(", ");
Dmitry V. Levin7af9f352012-03-11 23:59:29 +0000298 if (!verbose(tcp)) {
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000299 printaddr(tcp->u_arg[1]);
Dmitry V. Levin9a8216e2016-06-27 00:02:50 +0000300 /* vlen */
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000301 tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
Dmitry V. Levin9a8216e2016-06-27 00:02:50 +0000302 /* flags */
Dmitry V. Levin7af9f352012-03-11 23:59:29 +0000303 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
Dmitry V. Levin9a8216e2016-06-27 00:02:50 +0000304 return RVAL_DECODED;
Dmitry V. Levin7af9f352012-03-11 23:59:29 +0000305 }
306 } else {
Dmitry V. Levin9a8216e2016-06-27 00:02:50 +0000307 decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval, false);
308 /* vlen */
309 tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
310 /* flags */
311 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
Dmitry V. Levin7af9f352012-03-11 23:59:29 +0000312 }
313 return 0;
314}
315
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000316SYS_FUNC(recv)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000317{
318 if (entering(tcp)) {
Philippe Ombredanne894c7e32014-02-01 09:57:45 -0800319 printfd(tcp, tcp->u_arg[0]);
320 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 } else {
Fabien Siron2850f742016-07-06 15:49:22 +0000322 if (syserror(tcp)) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000323 printaddr(tcp->u_arg[1]);
Fabien Siron2850f742016-07-06 15:49:22 +0000324 } else {
325 decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
326 tcp->u_rval);
327 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328
329 tprintf(", %lu, ", tcp->u_arg[2]);
Roland McGrathb2dee132005-06-01 19:02:36 +0000330 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000331 }
332 return 0;
333}
334
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000335SYS_FUNC(recvfrom)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000336{
337 int fromlen;
338
339 if (entering(tcp)) {
Philippe Ombredanne894c7e32014-02-01 09:57:45 -0800340 printfd(tcp, tcp->u_arg[0]);
341 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000342 } else {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000343 /* buf */
Denys Vlasenko383386d2015-07-30 13:29:20 +0200344 if (syserror(tcp)) {
Dmitry V. Levin52dc1502015-07-30 13:53:42 +0000345 printaddr(tcp->u_arg[1]);
Denys Vlasenko383386d2015-07-30 13:29:20 +0200346 } else {
Fabien Siron2850f742016-07-06 15:49:22 +0000347 decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
348 tcp->u_rval);
Denys Vlasenko383386d2015-07-30 13:29:20 +0200349 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000350 /* len */
351 tprintf(", %lu, ", tcp->u_arg[2]);
352 /* flags */
Roland McGrathb2dee132005-06-01 19:02:36 +0000353 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200354 tprints(", ");
Dmitry V. Levin52dc1502015-07-30 13:53:42 +0000355 if (syserror(tcp) || !tcp->u_arg[4] || !tcp->u_arg[5] ||
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000356 umove(tcp, tcp->u_arg[5], &fromlen) < 0) {
Denys Vlasenko383386d2015-07-30 13:29:20 +0200357 /* from address, len */
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000358 printaddr(tcp->u_arg[4]);
359 tprints(", ");
360 printaddr(tcp->u_arg[5]);
361 return 0;
362 }
Denys Vlasenko383386d2015-07-30 13:29:20 +0200363 /* from address */
Dmitry V. Levin42e566a2016-06-25 11:31:48 +0000364 decode_sockaddr(tcp, tcp->u_arg[4], fromlen);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000365 /* from length */
366 tprintf(", [%u]", fromlen);
367 }
368 return 0;
369}
370
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000371SYS_FUNC(recvmsg)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000372{
373 if (entering(tcp)) {
Philippe Ombredanne894c7e32014-02-01 09:57:45 -0800374 printfd(tcp, tcp->u_arg[0]);
375 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000376 } else {
Dmitry V. Levin00244b92015-01-28 01:52:25 +0000377 if (syserror(tcp))
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000378 printaddr(tcp->u_arg[1]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000379 else
Dmitry V. Levin3e514c02016-06-26 23:57:29 +0000380 decode_msghdr(tcp, tcp->u_arg[1], tcp->u_rval);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000381 /* flags */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200382 tprints(", ");
Roland McGrathb2dee132005-06-01 19:02:36 +0000383 printflags(msg_flags, tcp->u_arg[2], "MSG_???");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000384 }
385 return 0;
386}
387
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000388SYS_FUNC(recvmmsg)
Andreas Schwab0873f292010-02-12 21:39:12 +0100389{
Dmitry V. Levin2950de32015-09-18 17:44:16 +0000390 static char str[sizeof("left") + TIMESPEC_TEXT_BUFSIZE];
Dmitry V. Levine6591032010-03-29 20:45:48 +0400391
Denys Vlasenkoa1d541e2012-01-20 11:04:04 +0100392 if (entering(tcp)) {
Philippe Ombredanne894c7e32014-02-01 09:57:45 -0800393 printfd(tcp, tcp->u_arg[0]);
394 tprints(", ");
Dmitry V. Levine6591032010-03-29 20:45:48 +0400395 if (verbose(tcp)) {
Denys Vlasenkoa1d541e2012-01-20 11:04:04 +0100396 /* Abusing tcp->auxstr as temp storage.
Dmitry V. Levin2950de32015-09-18 17:44:16 +0000397 * Will be used and cleared on syscall exit.
Denys Vlasenkoa1d541e2012-01-20 11:04:04 +0100398 */
Dmitry V. Levin2950de32015-09-18 17:44:16 +0000399 tcp->auxstr = sprint_timespec(tcp, tcp->u_arg[4]);
Dmitry V. Levine6591032010-03-29 20:45:48 +0400400 } else {
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000401 printaddr(tcp->u_arg[1]);
Dmitry V. Levin9a8216e2016-06-27 00:02:50 +0000402 /* vlen */
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000403 tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
Dmitry V. Levin9a8216e2016-06-27 00:02:50 +0000404 /* flags */
Dmitry V. Levine6591032010-03-29 20:45:48 +0400405 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200406 tprints(", ");
Dmitry V. Levine6591032010-03-29 20:45:48 +0400407 print_timespec(tcp, tcp->u_arg[4]);
408 }
409 return 0;
410 } else {
411 if (verbose(tcp)) {
Dmitry V. Levin9a8216e2016-06-27 00:02:50 +0000412 decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval, true);
413 /* vlen */
414 tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
415 /* flags */
416 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
Dmitry V. Levin2950de32015-09-18 17:44:16 +0000417 tprints(", ");
Dmitry V. Levine6591032010-03-29 20:45:48 +0400418 /* timeout on entrance */
Dmitry V. Levin2950de32015-09-18 17:44:16 +0000419 tprints(tcp->auxstr);
Dmitry V. Levine6591032010-03-29 20:45:48 +0400420 tcp->auxstr = NULL;
421 }
422 if (syserror(tcp))
423 return 0;
424 if (tcp->u_rval == 0) {
425 tcp->auxstr = "Timeout";
426 return RVAL_STR;
427 }
428 if (!verbose(tcp))
429 return 0;
430 /* timeout on exit */
Dmitry V. Levin2950de32015-09-18 17:44:16 +0000431 snprintf(str, sizeof(str), "left %s",
432 sprint_timespec(tcp, tcp->u_arg[4]));
Dmitry V. Levine6591032010-03-29 20:45:48 +0400433 tcp->auxstr = str;
434 return RVAL_STR;
Andreas Schwab0873f292010-02-12 21:39:12 +0100435 }
Andreas Schwab0873f292010-02-12 21:39:12 +0100436}
Andreas Schwab0873f292010-02-12 21:39:12 +0100437
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000438#include "xlat/shutdown_modes.h"
Sebastian Pipping9cd38502011-03-03 01:12:25 +0100439
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000440SYS_FUNC(shutdown)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000441{
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000442 printfd(tcp, tcp->u_arg[0]);
443 tprints(", ");
444 printxval(shutdown_modes, tcp->u_arg[1], "SHUT_???");
445
446 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000447}
448
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000449SYS_FUNC(getsockname)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000450{
Dmitry V. Levind1cedf02016-07-09 21:52:34 +0000451 return decode_sockname(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000452}
453
Dmitry V. Levin2a4f0522015-08-02 01:54:48 +0000454static void
455printpair_fd(struct tcb *tcp, const int i0, const int i1)
456{
457 tprints("[");
458 printfd(tcp, i0);
459 tprints(", ");
460 printfd(tcp, i1);
461 tprints("]");
462}
463
464static void
465decode_pair_fd(struct tcb *tcp, const long addr)
466{
467 int pair[2];
468
469 if (umove_or_printaddr(tcp, addr, &pair))
470 return;
471
472 printpair_fd(tcp, pair[0], pair[1]);
473}
474
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000475static int
476do_pipe(struct tcb *tcp, int flags_arg)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000477{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000478 if (exiting(tcp)) {
Dmitry V. Levin9b388852016-02-12 16:37:31 +0000479 decode_pair_fd(tcp, tcp->u_arg[0]);
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000480 if (flags_arg >= 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200481 tprints(", ");
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000482 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
483 }
484 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000485 return 0;
486}
487
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000488SYS_FUNC(pipe)
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000489{
Dmitry V. Levin9b388852016-02-12 16:37:31 +0000490#ifdef HAVE_GETRVAL2
491 if (exiting(tcp) && !syserror(tcp))
492 printpair_fd(tcp, tcp->u_rval, getrval2(tcp));
493 return 0;
494#else
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000495 return do_pipe(tcp, -1);
Dmitry V. Levin9b388852016-02-12 16:37:31 +0000496#endif
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000497}
498
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000499SYS_FUNC(pipe2)
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000500{
501 return do_pipe(tcp, 1);
502}
Dmitry V. Levin4371b102008-11-10 22:53:02 +0000503
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000504SYS_FUNC(socketpair)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000506 if (entering(tcp)) {
Dmitry V. Levin71fe62e2016-04-04 01:35:28 +0000507 printxval(addrfams, tcp->u_arg[0], "AF_???");
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200508 tprints(", ");
Dmitry V. Levin1e42f2d2014-09-10 17:48:28 +0000509 tprint_sock_type(tcp->u_arg[1]);
Dmitry V. Levin033fb912014-03-11 22:50:39 +0000510 tprintf(", %lu", tcp->u_arg[2]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511 } else {
Dmitry V. Levinb6795082015-07-06 22:33:39 +0000512 tprints(", ");
Dmitry V. Levin2a4f0522015-08-02 01:54:48 +0000513 decode_pair_fd(tcp, tcp->u_arg[3]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514 }
515 return 0;
516}
517
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000518#include "xlat/sockoptions.h"
519#include "xlat/sockipoptions.h"
Mike Frysinger54646b82015-08-19 13:29:27 -0400520#include "xlat/getsockipoptions.h"
521#include "xlat/setsockipoptions.h"
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000522#include "xlat/sockipv6options.h"
Mike Frysinger54646b82015-08-19 13:29:27 -0400523#include "xlat/getsockipv6options.h"
524#include "xlat/setsockipv6options.h"
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000525#include "xlat/sockipxoptions.h"
526#include "xlat/sockrawoptions.h"
527#include "xlat/sockpacketoptions.h"
528#include "xlat/socksctpoptions.h"
529#include "xlat/socktcpoptions.h"
530
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000531static void
Dmitry V. Levinf40ea792016-04-01 01:03:20 +0000532print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level,
533 unsigned int name, bool is_getsockopt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534{
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000535 printfd(tcp, fd);
536 tprints(", ");
John Hughes38ae88d2002-05-23 11:48:58 +0000537 printxval(socketlayers, level, "SOL_??");
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200538 tprints(", ");
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000539
John Hughes38ae88d2002-05-23 11:48:58 +0000540 switch (level) {
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100541 case SOL_SOCKET:
John Hughes38ae88d2002-05-23 11:48:58 +0000542 printxval(sockoptions, name, "SO_???");
John Hughes38ae88d2002-05-23 11:48:58 +0000543 break;
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100544 case SOL_IP:
Mike Frysinger54646b82015-08-19 13:29:27 -0400545 printxvals(name, "IP_???", sockipoptions,
546 is_getsockopt ? getsockipoptions : setsockipoptions, NULL);
John Hughes38ae88d2002-05-23 11:48:58 +0000547 break;
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100548 case SOL_IPV6:
Mike Frysinger54646b82015-08-19 13:29:27 -0400549 printxvals(name, "IPV6_???", sockipv6options,
550 is_getsockopt ? getsockipv6options : setsockipv6options, NULL);
Roland McGrath4f6ba692004-08-31 07:01:26 +0000551 break;
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100552 case SOL_IPX:
John Hughes38ae88d2002-05-23 11:48:58 +0000553 printxval(sockipxoptions, name, "IPX_???");
554 break;
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100555 case SOL_PACKET:
John Hughes38ae88d2002-05-23 11:48:58 +0000556 printxval(sockpacketoptions, name, "PACKET_???");
John Hughes38ae88d2002-05-23 11:48:58 +0000557 break;
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100558 case SOL_TCP:
John Hughes38ae88d2002-05-23 11:48:58 +0000559 printxval(socktcpoptions, name, "TCP_???");
560 break;
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100561 case SOL_SCTP:
Holger Hans Peter Freyther7fea79b2011-01-14 11:08:12 +0100562 printxval(socksctpoptions, name, "SCTP_???");
563 break;
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100564 case SOL_RAW:
John Hughes38ae88d2002-05-23 11:48:58 +0000565 printxval(sockrawoptions, name, "RAW_???");
John Hughes38ae88d2002-05-23 11:48:58 +0000566 break;
John Hughes38ae88d2002-05-23 11:48:58 +0000567
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000568 /* Other SOL_* protocol levels still need work. */
John Hughes38ae88d2002-05-23 11:48:58 +0000569
Denys Vlasenko989ebc92012-03-17 04:42:07 +0100570 default:
John Hughes38ae88d2002-05-23 11:48:58 +0000571 tprintf("%u", name);
572 }
573
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000574 tprints(", ");
575}
576
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000577static void
578print_linger(struct tcb *tcp, long addr, int len)
579{
580 struct linger linger;
581
582 if (len != sizeof(linger) ||
583 umove(tcp, addr, &linger) < 0) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000584 printaddr(addr);
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000585 return;
586 }
587
588 tprintf("{onoff=%d, linger=%d}",
589 linger.l_onoff,
590 linger.l_linger);
591}
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000592
593#ifdef SO_PEERCRED
594static void
595print_ucred(struct tcb *tcp, long addr, int len)
596{
597 struct ucred uc;
598
599 if (len != sizeof(uc) ||
600 umove(tcp, addr, &uc) < 0) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000601 printaddr(addr);
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000602 } else {
603 tprintf("{pid=%u, uid=%u, gid=%u}",
604 (unsigned) uc.pid,
605 (unsigned) uc.uid,
606 (unsigned) uc.gid);
607 }
608}
609#endif /* SO_PEERCRED */
610
611#ifdef PACKET_STATISTICS
612static void
613print_tpacket_stats(struct tcb *tcp, long addr, int len)
614{
615 struct tpacket_stats stats;
616
617 if (len != sizeof(stats) ||
618 umove(tcp, addr, &stats) < 0) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000619 printaddr(addr);
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000620 } else {
621 tprintf("{packets=%u, drops=%u}",
622 stats.tp_packets,
623 stats.tp_drops);
624 }
625}
626#endif /* PACKET_STATISTICS */
627
Dmitry V. Levinfba9db22016-06-15 21:29:07 +0000628#include "xlat/icmpfilterflags.h"
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000629
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000630static void
Dmitry V. Levineb5c2332016-05-06 00:06:15 +0000631print_icmp_filter(struct tcb *tcp, const long addr, int len)
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000632{
Dmitry V. Levineb5c2332016-05-06 00:06:15 +0000633 struct icmp_filter filter = {};
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000634
Dmitry V. Levineb5c2332016-05-06 00:06:15 +0000635 if (len > (int) sizeof(filter))
636 len = sizeof(filter);
637 else if (len <= 0) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000638 printaddr(addr);
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000639 return;
640 }
641
Dmitry V. Levineb5c2332016-05-06 00:06:15 +0000642 if (umoven_or_printaddr(tcp, addr, len, &filter))
643 return;
644
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000645 tprints("~(");
646 printflags(icmpfilterflags, ~filter.data, "ICMP_???");
647 tprints(")");
648}
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000649
650static void
Dmitry V. Levinf40ea792016-04-01 01:03:20 +0000651print_getsockopt(struct tcb *tcp, unsigned int level, unsigned int name,
652 long addr, int len)
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000653{
654 if (addr && verbose(tcp))
655 switch (level) {
656 case SOL_SOCKET:
657 switch (name) {
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000658 case SO_LINGER:
659 print_linger(tcp, addr, len);
660 goto done;
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000661#ifdef SO_PEERCRED
662 case SO_PEERCRED:
663 print_ucred(tcp, addr, len);
664 goto done;
665#endif
666 }
667 break;
668
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000669 case SOL_PACKET:
670 switch (name) {
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000671#ifdef PACKET_STATISTICS
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000672 case PACKET_STATISTICS:
673 print_tpacket_stats(tcp, addr, len);
674 goto done;
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000675#endif
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000676 }
677 break;
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000678
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000679 case SOL_RAW:
680 switch (name) {
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000681 case ICMP_FILTER:
682 print_icmp_filter(tcp, addr, len);
683 goto done;
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000684 }
685 break;
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000686 }
687
John Hughes38ae88d2002-05-23 11:48:58 +0000688 /* default arg printing */
689
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000690 if (verbose(tcp)) {
691 if (len == sizeof(int)) {
692 printnum_int(tcp, addr, "%d");
693 } else {
694 printstr(tcp, addr, len);
695 }
696 } else {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000697 printaddr(addr);
John Hughes38ae88d2002-05-23 11:48:58 +0000698 }
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000699done:
700 tprintf(", [%d]", len);
701}
702
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000703SYS_FUNC(getsockopt)
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000704{
705 if (entering(tcp)) {
706 print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
Mike Frysinger54646b82015-08-19 13:29:27 -0400707 tcp->u_arg[1], tcp->u_arg[2], true);
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000708 } else {
709 int len;
710
711 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &len) < 0) {
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000712 printaddr(tcp->u_arg[3]);
713 tprints(", ");
714 printaddr(tcp->u_arg[4]);
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000715 } else {
716 print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
717 tcp->u_arg[3], len);
718 }
John Hughes38ae88d2002-05-23 11:48:58 +0000719 }
720 return 0;
721}
722
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000723#ifdef IP_ADD_MEMBERSHIP
724static void
725print_mreq(struct tcb *tcp, long addr, unsigned int len)
726{
727 struct ip_mreq mreq;
728
729 if (len < sizeof(mreq)) {
730 printstr(tcp, addr, len);
731 return;
732 }
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000733 if (umove_or_printaddr(tcp, addr, &mreq))
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000734 return;
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000735
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000736 tprints("{imr_multiaddr=inet_addr(");
737 print_quoted_string(inet_ntoa(mreq.imr_multiaddr),
738 16, QUOTE_0_TERMINATED);
739 tprints("), imr_interface=inet_addr(");
740 print_quoted_string(inet_ntoa(mreq.imr_interface),
741 16, QUOTE_0_TERMINATED);
742 tprints(")}");
743}
744#endif /* IP_ADD_MEMBERSHIP */
745
746#ifdef IPV6_ADD_MEMBERSHIP
747static void
748print_mreq6(struct tcb *tcp, long addr, unsigned int len)
749{
750 struct ipv6_mreq mreq;
751
752 if (len < sizeof(mreq))
753 goto fail;
754
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000755 if (umove_or_printaddr(tcp, addr, &mreq))
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000756 return;
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000757
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000758 const struct in6_addr *in6 = &mreq.ipv6mr_multiaddr;
759 char address[INET6_ADDRSTRLEN];
760
761 if (!inet_ntop(AF_INET6, in6, address, sizeof(address)))
762 goto fail;
763
764 tprints("{ipv6mr_multiaddr=inet_pton(");
765 print_quoted_string(address, sizeof(address), QUOTE_0_TERMINATED);
766 tprints("), ipv6mr_interface=");
767 print_ifindex(mreq.ipv6mr_interface);
768 tprints("}");
769 return;
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000770
771fail:
772 printstr(tcp, addr, len);
773}
774#endif /* IPV6_ADD_MEMBERSHIP */
775
Dmitry V. Levina0a49092015-01-30 01:55:20 +0000776#ifdef MCAST_JOIN_GROUP
777static void
778print_group_req(struct tcb *tcp, long addr, int len)
779{
780 struct group_req greq;
781
782 if (len != sizeof(greq) ||
783 umove(tcp, addr, &greq) < 0) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000784 printaddr(addr);
Dmitry V. Levina0a49092015-01-30 01:55:20 +0000785 return;
786 }
787
Dmitry V. Levin1019f002015-11-21 02:38:59 +0000788 tprintf("{gr_interface=%u, gr_group=", greq.gr_interface);
Dmitry V. Levin3bf9c192016-06-21 16:45:40 +0000789 print_sockaddr(tcp, &greq.gr_group, sizeof(greq.gr_group));
Dmitry V. Levin1019f002015-11-21 02:38:59 +0000790 tprintf("}");
Dmitry V. Levina0a49092015-01-30 01:55:20 +0000791
792}
793#endif /* MCAST_JOIN_GROUP */
794
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000795#ifdef PACKET_RX_RING
796static void
797print_tpacket_req(struct tcb *tcp, long addr, int len)
798{
799 struct tpacket_req req;
800
801 if (len != sizeof(req) ||
802 umove(tcp, addr, &req) < 0) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000803 printaddr(addr);
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000804 } else {
805 tprintf("{block_size=%u, block_nr=%u, "
806 "frame_size=%u, frame_nr=%u}",
807 req.tp_block_size,
808 req.tp_block_nr,
809 req.tp_frame_size,
810 req.tp_frame_nr);
811 }
812}
813#endif /* PACKET_RX_RING */
814
Dmitry V. Levin02f2f092015-01-29 03:26:53 +0000815#ifdef PACKET_ADD_MEMBERSHIP
816# include "xlat/packet_mreq_type.h"
817
818static void
819print_packet_mreq(struct tcb *tcp, long addr, int len)
820{
821 struct packet_mreq mreq;
822
823 if (len != sizeof(mreq) ||
824 umove(tcp, addr, &mreq) < 0) {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000825 printaddr(addr);
Dmitry V. Levin02f2f092015-01-29 03:26:53 +0000826 } else {
827 unsigned int i;
828
829 tprintf("{mr_ifindex=%u, mr_type=", mreq.mr_ifindex);
830 printxval(packet_mreq_type, mreq.mr_type, "PACKET_MR_???");
831 tprintf(", mr_alen=%u, mr_address=", mreq.mr_alen);
832 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
833 mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
834 for (i = 0; i < mreq.mr_alen; ++i)
835 tprintf("%02x", mreq.mr_address[i]);
836 tprints("}");
837 }
838}
839#endif /* PACKET_ADD_MEMBERSHIP */
840
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000841static void
Dmitry V. Levinf40ea792016-04-01 01:03:20 +0000842print_setsockopt(struct tcb *tcp, unsigned int level, unsigned int name,
843 long addr, int len)
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000844{
845 if (addr && verbose(tcp))
846 switch (level) {
847 case SOL_SOCKET:
848 switch (name) {
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000849 case SO_LINGER:
850 print_linger(tcp, addr, len);
851 goto done;
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000852 }
853 break;
854
Dmitry V. Levina0a49092015-01-30 01:55:20 +0000855 case SOL_IP:
856 switch (name) {
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000857#ifdef IP_ADD_MEMBERSHIP
858 case IP_ADD_MEMBERSHIP:
859 case IP_DROP_MEMBERSHIP:
860 print_mreq(tcp, addr, len);
861 goto done;
862#endif /* IP_ADD_MEMBERSHIP */
Dmitry V. Levina0a49092015-01-30 01:55:20 +0000863#ifdef MCAST_JOIN_GROUP
864 case MCAST_JOIN_GROUP:
865 case MCAST_LEAVE_GROUP:
866 print_group_req(tcp, addr, len);
867 goto done;
868#endif /* MCAST_JOIN_GROUP */
869 }
Dmitry V. Levin3910d0f2015-02-08 01:19:06 +0000870 break;
Dmitry V. Levina0a49092015-01-30 01:55:20 +0000871
Dmitry V. Levin7bee4622015-06-08 14:19:46 +0000872 case SOL_IPV6:
873 switch (name) {
874#ifdef IPV6_ADD_MEMBERSHIP
875 case IPV6_ADD_MEMBERSHIP:
876 case IPV6_DROP_MEMBERSHIP:
877# ifdef IPV6_JOIN_ANYCAST
878 case IPV6_JOIN_ANYCAST:
879# endif
880# ifdef IPV6_LEAVE_ANYCAST
881 case IPV6_LEAVE_ANYCAST:
882# endif
883 print_mreq6(tcp, addr, len);
884 goto done;
885#endif /* IPV6_ADD_MEMBERSHIP */
886 }
887 break;
888
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000889 case SOL_PACKET:
890 switch (name) {
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000891#ifdef PACKET_RX_RING
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000892 case PACKET_RX_RING:
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000893# ifdef PACKET_TX_RING
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000894 case PACKET_TX_RING:
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000895# endif
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000896 print_tpacket_req(tcp, addr, len);
897 goto done;
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000898#endif /* PACKET_RX_RING */
899#ifdef PACKET_ADD_MEMBERSHIP
Dmitry V. Levin02f2f092015-01-29 03:26:53 +0000900 case PACKET_ADD_MEMBERSHIP:
901 case PACKET_DROP_MEMBERSHIP:
902 print_packet_mreq(tcp, addr, len);
903 goto done;
Dmitry V. Levin6d31c7a2015-01-29 04:42:37 +0000904#endif /* PACKET_ADD_MEMBERSHIP */
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000905 }
906 break;
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000907
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000908 case SOL_RAW:
909 switch (name) {
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000910 case ICMP_FILTER:
911 print_icmp_filter(tcp, addr, len);
912 goto done;
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000913 }
914 break;
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000915 }
916
917 /* default arg printing */
918
919 if (verbose(tcp)) {
920 if (len == sizeof(int)) {
921 printnum_int(tcp, addr, "%d");
922 } else {
923 printstr(tcp, addr, len);
924 }
925 } else {
Dmitry V. Levin6c277da2015-07-19 22:36:46 +0000926 printaddr(addr);
Dmitry V. Levin0509c8e2015-01-29 03:11:41 +0000927 }
928done:
929 tprintf(", %d", len);
930}
931
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000932SYS_FUNC(setsockopt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933{
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000934 print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
Mike Frysinger54646b82015-08-19 13:29:27 -0400935 tcp->u_arg[1], tcp->u_arg[2], false);
Dmitry V. Levin219b3a72015-07-19 22:52:47 +0000936 print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
937 tcp->u_arg[3], tcp->u_arg[4]);
938
939 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940}