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