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