]> granicus.if.org Git - strace/blob - sock.c
evdev.c: reorder ioctl command checks
[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 #if defined ALPHA || defined SH || defined SH64
31 # include <linux/ioctl.h>
32 #endif
33 #include <linux/sockios.h>
34 #include <arpa/inet.h>
35 #include <net/if.h>
36
37 #include "xlat/iffflags.h"
38
39 static void
40 print_ifreq_addr(struct tcb *tcp, const struct ifreq *ifr, const long addr)
41 {
42         tprintf("{");
43         printxval(addrfams, ifr->ifr_addr.sa_family, "AF_???");
44         tprints(", ");
45         if (ifr->ifr_addr.sa_family == AF_INET) {
46                 const struct sockaddr_in *sinp =
47                         (struct sockaddr_in *) &ifr->ifr_addr;
48                 tprintf("inet_addr(\"%s\")", inet_ntoa(sinp->sin_addr));
49         } else
50                 printstr(tcp, addr + offsetof(struct ifreq, ifr_addr.sa_data),
51                          sizeof(ifr->ifr_addr.sa_data));
52         tprints("}");
53 }
54
55 static void
56 print_ifname(const char *ifname)
57 {
58         print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
59 }
60
61 static void
62 print_ifreq(struct tcb *tcp, const unsigned int code, const long arg,
63             const struct ifreq *ifr)
64 {
65         switch (code) {
66         case SIOCSIFADDR:
67         case SIOCGIFADDR:
68                 tprints("ifr_addr=");
69                 print_ifreq_addr(tcp, ifr, arg);
70                 break;
71         case SIOCSIFDSTADDR:
72         case SIOCGIFDSTADDR:
73                 tprints("ifr_dstaddr=");
74                 print_ifreq_addr(tcp, ifr, arg);
75                 break;
76         case SIOCSIFBRDADDR:
77         case SIOCGIFBRDADDR:
78                 tprints("ifr_broadaddr=");
79                 print_ifreq_addr(tcp, ifr, arg);
80                 break;
81         case SIOCSIFNETMASK:
82         case SIOCGIFNETMASK:
83                 tprints("ifr_netmask=");
84                 print_ifreq_addr(tcp, ifr, arg);
85                 break;
86         case SIOCSIFHWADDR:
87         case SIOCGIFHWADDR: {
88                 /* XXX Are there other hardware addresses
89                    than 6-byte MACs?  */
90                 const unsigned char *bytes =
91                         (unsigned char *) &ifr->ifr_hwaddr.sa_data;
92                 tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
93                         bytes[0], bytes[1], bytes[2],
94                         bytes[3], bytes[4], bytes[5]);
95                 break;
96         }
97         case SIOCSIFFLAGS:
98         case SIOCGIFFLAGS:
99                 tprints("ifr_flags=");
100                 printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
101                 break;
102         case SIOCSIFMETRIC:
103         case SIOCGIFMETRIC:
104                 tprintf("ifr_metric=%d", ifr->ifr_metric);
105                 break;
106         case SIOCSIFMTU:
107         case SIOCGIFMTU:
108                 tprintf("ifr_mtu=%d", ifr->ifr_mtu);
109                 break;
110         case SIOCSIFSLAVE:
111         case SIOCGIFSLAVE:
112                 tprints("ifr_slave=");
113                 print_ifname(ifr->ifr_slave);
114                 break;
115         case SIOCSIFTXQLEN:
116         case SIOCGIFTXQLEN:
117                 tprintf("ifr_qlen=%d", ifr->ifr_qlen);
118                 break;
119         case SIOCSIFMAP:
120         case SIOCGIFMAP:
121                 tprintf("ifr_map={mem_start=%#lx, "
122                         "mem_end=%#lx, base_addr=%#x, "
123                         "irq=%u, dma=%u, port=%u}",
124                         ifr->ifr_map.mem_start,
125                         ifr->ifr_map.mem_end,
126                         (unsigned) ifr->ifr_map.base_addr,
127                         (unsigned) ifr->ifr_map.irq,
128                         (unsigned) ifr->ifr_map.dma,
129                         (unsigned) ifr->ifr_map.port);
130                 break;
131         }
132 }
133
134 static unsigned int
135 print_ifc_len(int len)
136 {
137         const unsigned int n = (unsigned int) len / sizeof(struct ifreq);
138
139         if (len < 0 || n * sizeof(struct ifreq) != (unsigned int) len)
140                 tprintf("%d", len);
141         else
142                 tprintf("%u * sizeof(struct ifreq)", n);
143
144         return n;
145 }
146
147 static int
148 decode_ifconf(struct tcb *tcp, const long addr)
149 {
150         struct ifconf ifc;
151
152         if (entering(tcp)) {
153                 tprints(", ");
154                 if (umove_or_printaddr(tcp, addr, &ifc))
155                         return RVAL_DECODED | 1;
156                 if (ifc.ifc_buf) {
157                         tprints("{");
158                         print_ifc_len(ifc.ifc_len);
159                 }
160                 return 1;
161         }
162
163         if (syserror(tcp) || umove(tcp, addr, &ifc) < 0) {
164                 if (ifc.ifc_buf)
165                         tprints("}");
166                 else
167                         printaddr(addr);
168                 return RVAL_DECODED | 1;
169         }
170
171         if (!ifc.ifc_buf) {
172                 tprints("{");
173                 print_ifc_len(ifc.ifc_len);
174                 tprints(", NULL}");
175                 return RVAL_DECODED | 1;
176         }
177
178         tprints(" => ");
179         const unsigned int nifra = print_ifc_len(ifc.ifc_len);
180         if (!nifra) {
181                 tprints("}");
182                 return RVAL_DECODED | 1;
183         }
184
185         struct ifreq ifra[nifra > max_strlen ? max_strlen : nifra];
186         tprints(", ");
187         if (umove_or_printaddr(tcp, (unsigned long) ifc.ifc_buf, &ifra)) {
188                 tprints("}");
189                 return RVAL_DECODED | 1;
190         }
191
192         tprints("[");
193         unsigned int i;
194         for (i = 0; i < ARRAY_SIZE(ifra); ++i) {
195                 if (i > 0)
196                         tprints(", ");
197                 tprints("{ifr_name=");
198                 print_ifname(ifra[i].ifr_name);
199                 tprints(", ");
200                 if (verbose(tcp)) {
201                         tprints("ifr_addr=");
202                         print_ifreq_addr(tcp, &ifra[i],
203                                          addr + i * sizeof(ifra[0]));
204                 } else
205                         tprints("...");
206                 tprints("}");
207         }
208         if (i < nifra)
209                 tprints(", ...");
210         tprints("]}");
211
212         return RVAL_DECODED | 1;
213 }
214
215 int
216 sock_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
217 {
218         struct ifreq ifr;
219
220         switch (code) {
221         case SIOCGIFCONF:
222                 return decode_ifconf(tcp, arg);
223
224 #ifdef SIOCBRADDBR
225         case SIOCBRADDBR:
226         case SIOCBRDELBR:
227                 tprints(", ");
228                 printstr(tcp, arg, -1);
229                 break;
230 #endif
231
232 #ifdef FIOSETOWN
233         case FIOSETOWN:
234 #endif
235 #ifdef SIOCSPGRP
236         case SIOCSPGRP:
237 #endif
238                 tprints(", ");
239                 printnum_int(tcp, arg, "%d");
240                 break;
241
242 #ifdef FIOGETOWN
243         case FIOGETOWN:
244 #endif
245 #ifdef SIOCGPGRP
246         case SIOCGPGRP:
247 #endif
248 #ifdef SIOCATMARK
249         case SIOCATMARK:
250 #endif
251                 if (entering(tcp))
252                         return 0;
253                 tprints(", ");
254                 printnum_int(tcp, arg, "%d");
255                 break;
256
257 #ifdef SIOCBRADDIF
258         case SIOCBRADDIF:
259 #endif
260 #ifdef SIOCBRDELIF
261         case SIOCBRDELIF:
262 #endif
263                 /* no arguments */
264                 break;
265
266         case SIOCSIFNAME:
267         case SIOCSIFADDR:
268         case SIOCSIFDSTADDR:
269         case SIOCSIFBRDADDR:
270         case SIOCSIFNETMASK:
271         case SIOCSIFFLAGS:
272         case SIOCSIFMETRIC:
273         case SIOCSIFMTU:
274         case SIOCSIFSLAVE:
275         case SIOCSIFHWADDR:
276         case SIOCSIFTXQLEN:
277         case SIOCSIFMAP:
278                 tprints(", ");
279                 if (umove_or_printaddr(tcp, arg, &ifr))
280                         break;
281
282                 tprints("{ifr_name=");
283                 print_ifname(ifr.ifr_name);
284                 tprints(", ");
285                 if (code == SIOCSIFNAME) {
286                         tprints("ifr_newname=");
287                         print_ifname(ifr.ifr_newname);
288                 } else {
289                         print_ifreq(tcp, code, arg, &ifr);
290                 }
291                 tprints("}");
292                 break;
293
294         case SIOCGIFNAME:
295         case SIOCGIFINDEX:
296         case SIOCGIFADDR:
297         case SIOCGIFDSTADDR:
298         case SIOCGIFBRDADDR:
299         case SIOCGIFNETMASK:
300         case SIOCGIFFLAGS:
301         case SIOCGIFMETRIC:
302         case SIOCGIFMTU:
303         case SIOCGIFSLAVE:
304         case SIOCGIFHWADDR:
305         case SIOCGIFTXQLEN:
306         case SIOCGIFMAP:
307                 if (entering(tcp)) {
308                         tprints(", ");
309                         if (umove_or_printaddr(tcp, arg, &ifr))
310                                 break;
311
312                         if (SIOCGIFNAME == code) {
313                                 tprintf("{ifr_index=%d", ifr.ifr_ifindex);
314                         } else {
315                                 tprints("{ifr_name=");
316                                 print_ifname(ifr.ifr_name);
317                         }
318                         return 1;
319                 } else {
320                         if (syserror(tcp)) {
321                                 tprints("}");
322                                 break;
323                         }
324
325                         tprints(", ");
326                         if (umove(tcp, arg, &ifr) < 0) {
327                                 tprints("???}");
328                                 break;
329                         }
330
331                         if (SIOCGIFNAME == code) {
332                                 tprints("ifr_name=");
333                                 print_ifname(ifr.ifr_name);
334                         } else {
335                                 print_ifreq(tcp, code, arg, &ifr);
336                         }
337                         tprints("}");
338                         break;
339                 }
340
341         default:
342                 return RVAL_DECODED;
343         }
344
345         return RVAL_DECODED | 1;
346 }