]> granicus.if.org Git - strace/blob - sock.c
Intorduce PRINT_FIELD_NET_PORT
[strace] / sock.c
1 /*
2  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
3  * Copyright (c) 1996-2017 The strace developers.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "defs.h"
30
31 #include <sys/socket.h>
32 #if defined ALPHA || defined SH || defined SH64
33 # include <linux/ioctl.h>
34 #endif
35 #include <linux/sockios.h>
36 #include <arpa/inet.h>
37 #include <net/if.h>
38
39 #include DEF_MPERS_TYPE(struct_ifconf)
40 #include DEF_MPERS_TYPE(struct_ifreq)
41
42 typedef struct ifconf struct_ifconf;
43 typedef struct ifreq struct_ifreq;
44
45 #include MPERS_DEFS
46
47 #include "xlat/iffflags.h"
48
49 #define PRINT_IFREQ_ADDR(tcp, ifr, sockaddr)                                    \
50         do {                                                                    \
51                 tprints(#sockaddr "=");                                         \
52                 print_sockaddr(tcp, &((ifr)->sockaddr),                         \
53                                sizeof((ifr)->sockaddr));                        \
54         } while (0)
55
56 static void
57 print_ifname(const char *ifname)
58 {
59         print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
60 }
61
62 static void
63 print_ifreq(struct tcb *const tcp, const unsigned int code,
64             const kernel_ulong_t arg, const struct_ifreq *const ifr)
65 {
66         switch (code) {
67         case SIOCSIFADDR:
68         case SIOCGIFADDR:
69                 PRINT_IFREQ_ADDR(tcp, ifr, ifr_addr);
70                 break;
71         case SIOCSIFDSTADDR:
72         case SIOCGIFDSTADDR:
73                 PRINT_IFREQ_ADDR(tcp, ifr, ifr_dstaddr);
74                 break;
75         case SIOCSIFBRDADDR:
76         case SIOCGIFBRDADDR:
77                 PRINT_IFREQ_ADDR(tcp, ifr, ifr_broadaddr);
78                 break;
79         case SIOCSIFNETMASK:
80         case SIOCGIFNETMASK:
81                 PRINT_IFREQ_ADDR(tcp, ifr, ifr_netmask);
82                 break;
83         case SIOCSIFHWADDR:
84         case SIOCGIFHWADDR: {
85                 /* XXX Are there other hardware addresses
86                    than 6-byte MACs?  */
87                 const unsigned char *bytes =
88                         (unsigned char *) &ifr->ifr_hwaddr.sa_data;
89                 tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
90                         bytes[0], bytes[1], bytes[2],
91                         bytes[3], bytes[4], bytes[5]);
92                 break;
93         }
94         case SIOCSIFFLAGS:
95         case SIOCGIFFLAGS:
96                 tprints("ifr_flags=");
97                 printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
98                 break;
99         case SIOCSIFMETRIC:
100         case SIOCGIFMETRIC:
101                 tprintf("ifr_metric=%d", ifr->ifr_metric);
102                 break;
103         case SIOCSIFMTU:
104         case SIOCGIFMTU:
105                 tprintf("ifr_mtu=%d", ifr->ifr_mtu);
106                 break;
107         case SIOCSIFSLAVE:
108         case SIOCGIFSLAVE:
109                 tprints("ifr_slave=");
110                 print_ifname(ifr->ifr_slave);
111                 break;
112         case SIOCSIFTXQLEN:
113         case SIOCGIFTXQLEN:
114                 tprintf("ifr_qlen=%d", ifr->ifr_qlen);
115                 break;
116         case SIOCSIFMAP:
117         case SIOCGIFMAP:
118                 tprintf("ifr_map={mem_start=%#" PRI_klx ", "
119                         "mem_end=%#" PRI_klx ", base_addr=%#x, "
120                         "irq=%u, dma=%u, port=%u}",
121                         (kernel_ulong_t) ifr->ifr_map.mem_start,
122                         (kernel_ulong_t) ifr->ifr_map.mem_end,
123                         (unsigned) ifr->ifr_map.base_addr,
124                         (unsigned) ifr->ifr_map.irq,
125                         (unsigned) ifr->ifr_map.dma,
126                         (unsigned) ifr->ifr_map.port);
127                 break;
128         }
129 }
130
131 static unsigned int
132 print_ifc_len(int len)
133 {
134         const unsigned int n = (unsigned int) len / sizeof(struct_ifreq);
135
136         if (len < 0 || n * sizeof(struct_ifreq) != (unsigned int) len)
137                 tprintf("%d", len);
138         else
139                 tprintf("%u * sizeof(struct ifreq)", n);
140
141         return n;
142 }
143
144 static bool
145 print_ifconf_ifreq(struct tcb *tcp, void *elem_buf, size_t elem_size,
146                    void *dummy)
147 {
148         struct_ifreq *ifr = elem_buf;
149
150         tprints("{ifr_name=");
151         print_ifname(ifr->ifr_name);
152         tprints(", ");
153         PRINT_IFREQ_ADDR(tcp, ifr, ifr_addr);
154         tprints("}");
155
156         return true;
157 }
158
159 /*
160  * There are two different modes of operation:
161  *
162  * - Get buffer size.  In this case, the callee sets ifc_buf to NULL,
163  *   and the kernel returns the buffer size in ifc_len.
164  * - Get actual data.  In this case, the callee specifies the buffer address
165  *   in ifc_buf and its size in ifc_len.  The kernel fills the buffer with
166  *   the data, and its amount is returned in ifc_len.
167  *
168  * Note that, technically, the whole struct ifconf is overwritten,
169  * so ifc_buf could be different on exit, but current ioctl handler
170  * implementation does not touch it.
171  */
172 static int
173 decode_ifconf(struct tcb *const tcp, const kernel_ulong_t addr)
174 {
175         struct_ifconf *entering_ifc = NULL;
176         struct_ifconf *ifc =
177                 entering(tcp) ? malloc(sizeof(*ifc)) : alloca(sizeof(*ifc));
178
179         if (exiting(tcp)) {
180                 entering_ifc = get_tcb_priv_data(tcp);
181
182                 if (!entering_ifc) {
183                         error_msg("decode_ifconf: where is my ifconf?");
184                         return 0;
185                 }
186         }
187
188         if (!ifc || umove(tcp, addr, ifc) < 0) {
189                 if (entering(tcp)) {
190                         free(ifc);
191
192                         tprints(", ");
193                         printaddr(addr);
194                 } else {
195                         /*
196                          * We failed to fetch the structure on exiting syscall,
197                          * print whatever was fetched on entering syscall.
198                          */
199                         if (!entering_ifc->ifc_buf)
200                                 print_ifc_len(entering_ifc->ifc_len);
201
202                         tprints(", ifc_buf=");
203                         printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
204
205                         tprints("}");
206                 }
207
208                 return RVAL_DECODED | 1;
209         }
210
211         if (entering(tcp)) {
212                 tprints(", {ifc_len=");
213                 if (ifc->ifc_buf)
214                         print_ifc_len(ifc->ifc_len);
215
216                 set_tcb_priv_data(tcp, ifc, free);
217
218                 return 1;
219         }
220
221         /* exiting */
222
223         if (entering_ifc->ifc_buf && (entering_ifc->ifc_len != ifc->ifc_len))
224                 tprints(" => ");
225         if (!entering_ifc->ifc_buf || (entering_ifc->ifc_len != ifc->ifc_len))
226                 print_ifc_len(ifc->ifc_len);
227
228         tprints(", ifc_buf=");
229
230         if (!entering_ifc->ifc_buf || syserror(tcp)) {
231                 printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
232                 if (entering_ifc->ifc_buf != ifc->ifc_buf) {
233                         tprints(" => ");
234                         printaddr(ptr_to_kulong(ifc->ifc_buf));
235                 }
236         } else {
237                 struct_ifreq ifr;
238
239                 print_array(tcp, ptr_to_kulong(ifc->ifc_buf),
240                             ifc->ifc_len / sizeof(struct_ifreq),
241                             &ifr, sizeof(ifr),
242                             umoven_or_printaddr, print_ifconf_ifreq, NULL);
243         }
244
245         tprints("}");
246
247         return RVAL_DECODED | 1;
248 }
249
250 MPERS_PRINTER_DECL(int, sock_ioctl,
251                    struct tcb *tcp, const unsigned int code,
252                    const kernel_ulong_t arg)
253 {
254         struct_ifreq ifr;
255
256         switch (code) {
257         case SIOCGIFCONF:
258                 return decode_ifconf(tcp, arg);
259
260 #ifdef SIOCBRADDBR
261         case SIOCBRADDBR:
262         case SIOCBRDELBR:
263                 tprints(", ");
264                 printstr(tcp, arg);
265                 break;
266 #endif
267
268 #ifdef FIOSETOWN
269         case FIOSETOWN:
270 #endif
271 #ifdef SIOCSPGRP
272         case SIOCSPGRP:
273 #endif
274                 tprints(", ");
275                 printnum_int(tcp, arg, "%d");
276                 break;
277
278 #ifdef FIOGETOWN
279         case FIOGETOWN:
280 #endif
281 #ifdef SIOCGPGRP
282         case SIOCGPGRP:
283 #endif
284 #ifdef SIOCATMARK
285         case SIOCATMARK:
286 #endif
287                 if (entering(tcp))
288                         return 0;
289                 tprints(", ");
290                 printnum_int(tcp, arg, "%d");
291                 break;
292
293 #ifdef SIOCBRADDIF
294         case SIOCBRADDIF:
295 #endif
296 #ifdef SIOCBRDELIF
297         case SIOCBRDELIF:
298 #endif
299                 /* no arguments */
300                 break;
301
302         case SIOCSIFNAME:
303         case SIOCSIFADDR:
304         case SIOCSIFDSTADDR:
305         case SIOCSIFBRDADDR:
306         case SIOCSIFNETMASK:
307         case SIOCSIFFLAGS:
308         case SIOCSIFMETRIC:
309         case SIOCSIFMTU:
310         case SIOCSIFSLAVE:
311         case SIOCSIFHWADDR:
312         case SIOCSIFTXQLEN:
313         case SIOCSIFMAP:
314                 tprints(", ");
315                 if (umove_or_printaddr(tcp, arg, &ifr))
316                         break;
317
318                 tprints("{ifr_name=");
319                 print_ifname(ifr.ifr_name);
320                 tprints(", ");
321                 if (code == SIOCSIFNAME) {
322                         tprints("ifr_newname=");
323                         print_ifname(ifr.ifr_newname);
324                 } else {
325                         print_ifreq(tcp, code, arg, &ifr);
326                 }
327                 tprints("}");
328                 break;
329
330         case SIOCGIFNAME:
331         case SIOCGIFINDEX:
332         case SIOCGIFADDR:
333         case SIOCGIFDSTADDR:
334         case SIOCGIFBRDADDR:
335         case SIOCGIFNETMASK:
336         case SIOCGIFFLAGS:
337         case SIOCGIFMETRIC:
338         case SIOCGIFMTU:
339         case SIOCGIFSLAVE:
340         case SIOCGIFHWADDR:
341         case SIOCGIFTXQLEN:
342         case SIOCGIFMAP:
343                 if (entering(tcp)) {
344                         tprints(", ");
345                         if (umove_or_printaddr(tcp, arg, &ifr))
346                                 break;
347
348                         if (SIOCGIFNAME == code) {
349                                 tprintf("{ifr_index=%d", ifr.ifr_ifindex);
350                         } else {
351                                 tprints("{ifr_name=");
352                                 print_ifname(ifr.ifr_name);
353                         }
354                         return 1;
355                 } else {
356                         if (syserror(tcp)) {
357                                 tprints("}");
358                                 break;
359                         }
360
361                         tprints(", ");
362                         if (umove(tcp, arg, &ifr) < 0) {
363                                 tprints("???}");
364                                 break;
365                         }
366
367                         if (SIOCGIFNAME == code) {
368                                 tprints("ifr_name=");
369                                 print_ifname(ifr.ifr_name);
370                         } else {
371                                 print_ifreq(tcp, code, arg, &ifr);
372                         }
373                         tprints("}");
374                         break;
375                 }
376
377         default:
378                 return RVAL_DECODED;
379         }
380
381         return RVAL_DECODED | 1;
382 }