]> granicus.if.org Git - strace/blob - sock.c
Fix preadv/pwritev offset decoding
[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 static const struct xlat iffflags[] = {
42         XLAT(IFF_UP),
43         XLAT(IFF_BROADCAST),
44         XLAT(IFF_DEBUG),
45         XLAT(IFF_LOOPBACK),
46         XLAT(IFF_POINTOPOINT),
47         XLAT(IFF_NOTRAILERS),
48         XLAT(IFF_RUNNING),
49         XLAT(IFF_NOARP),
50         XLAT(IFF_PROMISC),
51         XLAT(IFF_ALLMULTI),
52         XLAT(IFF_MASTER),
53         XLAT(IFF_SLAVE),
54         XLAT(IFF_MULTICAST),
55         XLAT(IFF_PORTSEL),
56         XLAT(IFF_AUTOMEDIA),
57         XLAT_END
58 };
59
60 static void
61 print_addr(struct tcb *tcp, long addr, struct ifreq *ifr)
62 {
63         if (ifr->ifr_addr.sa_family == AF_INET) {
64                 struct sockaddr_in *sinp;
65                 sinp = (struct sockaddr_in *) &ifr->ifr_addr;
66                 tprintf("inet_addr(\"%s\")", inet_ntoa(sinp->sin_addr));
67         } else
68                 printstr(tcp, addr, sizeof(ifr->ifr_addr.sa_data));
69 }
70
71 int
72 sock_ioctl(struct tcb *tcp, long code, long arg)
73 {
74         struct ifreq ifr;
75         struct ifconf ifc;
76         const char *str = NULL;
77         unsigned char *bytes;
78
79         if (entering(tcp)) {
80                 if (code == SIOCGIFCONF) {
81                         if (umove(tcp, tcp->u_arg[2], &ifc) >= 0
82                             && ifc.ifc_buf == NULL)
83                                 tprintf(", {%d -> ", ifc.ifc_len);
84                         else
85                                 tprints(", {");
86                 }
87                 return 0;
88         }
89
90         switch (code) {
91 #ifdef SIOCSHIWAT
92         case SIOCSHIWAT:
93 #endif
94 #ifdef SIOCGHIWAT
95         case SIOCGHIWAT:
96 #endif
97 #ifdef SIOCSLOWAT
98         case SIOCSLOWAT:
99 #endif
100 #ifdef SIOCGLOWAT
101         case SIOCGLOWAT:
102 #endif
103 #ifdef FIOSETOWN
104         case FIOSETOWN:
105 #endif
106 #ifdef FIOGETOWN
107         case FIOGETOWN:
108 #endif
109 #ifdef SIOCSPGRP
110         case SIOCSPGRP:
111 #endif
112 #ifdef SIOCGPGRP
113         case SIOCGPGRP:
114 #endif
115 #ifdef SIOCATMARK
116         case SIOCATMARK:
117 #endif
118                 printnum(tcp, arg, ", %#d");
119                 return 1;
120         case SIOCGIFNAME:
121         case SIOCSIFNAME:
122         case SIOCGIFINDEX:
123         case SIOCGIFADDR:
124         case SIOCSIFADDR:
125         case SIOCGIFDSTADDR:
126         case SIOCSIFDSTADDR:
127         case SIOCGIFBRDADDR:
128         case SIOCSIFBRDADDR:
129         case SIOCGIFNETMASK:
130         case SIOCSIFNETMASK:
131         case SIOCGIFFLAGS:
132         case SIOCSIFFLAGS:
133         case SIOCGIFMETRIC:
134         case SIOCSIFMETRIC:
135         case SIOCGIFMTU:
136         case SIOCSIFMTU:
137         case SIOCGIFSLAVE:
138         case SIOCSIFSLAVE:
139         case SIOCGIFHWADDR:
140         case SIOCSIFHWADDR:
141         case SIOCGIFTXQLEN:
142         case SIOCSIFTXQLEN:
143         case SIOCGIFMAP:
144         case SIOCSIFMAP:
145                 if (umove(tcp, tcp->u_arg[2], &ifr) < 0)
146                         tprintf(", %#lx", tcp->u_arg[2]);
147                 else if (syserror(tcp)) {
148                         if (code == SIOCGIFNAME || code == SIOCSIFNAME)
149                                 tprintf(", {ifr_index=%d, ifr_name=???}", ifr.ifr_ifindex);
150                         else
151                                 tprintf(", {ifr_name=\"%s\", ???}", ifr.ifr_name);
152                 } else if (code == SIOCGIFNAME || code == SIOCSIFNAME)
153                         tprintf(", {ifr_index=%d, ifr_name=\"%s\"}",
154                                 ifr.ifr_ifindex, ifr.ifr_name);
155                 else {
156                         tprintf(", {ifr_name=\"%s\", ", ifr.ifr_name);
157                         switch (code) {
158                         case SIOCGIFINDEX:
159                                 tprintf("ifr_index=%d", ifr.ifr_ifindex);
160                                 break;
161                         case SIOCGIFADDR:
162                         case SIOCSIFADDR:
163                                 str = "ifr_addr";
164                         case SIOCGIFDSTADDR:
165                         case SIOCSIFDSTADDR:
166                                 if (!str)
167                                         str = "ifr_dstaddr";
168                         case SIOCGIFBRDADDR:
169                         case SIOCSIFBRDADDR:
170                                 if (!str)
171                                         str = "ifr_broadaddr";
172                         case SIOCGIFNETMASK:
173                         case SIOCSIFNETMASK:
174                                 if (!str)
175                                         str = "ifr_netmask";
176                                 tprintf("%s={", str);
177                                 printxval(addrfams,
178                                           ifr.ifr_addr.sa_family,
179                                           "AF_???");
180                                 tprints(", ");
181                                 print_addr(tcp, ((long) tcp->u_arg[2]
182                                                  + offsetof(struct ifreq,
183                                                              ifr_addr.sa_data)),
184                                            &ifr);
185                                 tprints("}");
186                                 break;
187                         case SIOCGIFHWADDR:
188                         case SIOCSIFHWADDR:
189                                 /* XXX Are there other hardware addresses
190                                    than 6-byte MACs?  */
191                                 bytes = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
192                                 tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
193                                         bytes[0], bytes[1], bytes[2],
194                                         bytes[3], bytes[4], bytes[5]);
195                                 break;
196                         case SIOCGIFFLAGS:
197                         case SIOCSIFFLAGS:
198                                 tprints("ifr_flags=");
199                                 printflags(iffflags, ifr.ifr_flags, "IFF_???");
200                                 break;
201                         case SIOCGIFMETRIC:
202                         case SIOCSIFMETRIC:
203                                 tprintf("ifr_metric=%d", ifr.ifr_metric);
204                                 break;
205                         case SIOCGIFMTU:
206                         case SIOCSIFMTU:
207                                 tprintf("ifr_mtu=%d", ifr.ifr_mtu);
208                                 break;
209                         case SIOCGIFSLAVE:
210                         case SIOCSIFSLAVE:
211                                 tprintf("ifr_slave=\"%s\"", ifr.ifr_slave);
212                                 break;
213                         case SIOCGIFTXQLEN:
214                         case SIOCSIFTXQLEN:
215                                 tprintf("ifr_qlen=%d", ifr.ifr_qlen);
216                                 break;
217                         case SIOCGIFMAP:
218                         case SIOCSIFMAP:
219                                 tprintf("ifr_map={mem_start=%#lx, "
220                                         "mem_end=%#lx, base_addr=%#x, "
221                                         "irq=%u, dma=%u, port=%u}",
222                                         ifr.ifr_map.mem_start,
223                                         ifr.ifr_map.mem_end,
224                                         (unsigned) ifr.ifr_map.base_addr,
225                                         (unsigned) ifr.ifr_map.irq,
226                                         (unsigned) ifr.ifr_map.dma,
227                                         (unsigned) ifr.ifr_map.port);
228                                 break;
229                         }
230                         tprints("}");
231                 }
232                 return 1;
233         case SIOCGIFCONF:
234                 if (umove(tcp, tcp->u_arg[2], &ifc) < 0) {
235                         tprints("???}");
236                         return 1;
237                 }
238                 tprintf("%d, ", ifc.ifc_len);
239                 if (syserror(tcp)) {
240                         tprintf("%lx", (unsigned long) ifc.ifc_buf);
241                 } else if (ifc.ifc_buf == NULL) {
242                         tprints("NULL");
243                 } else {
244                         int i;
245                         unsigned nifra = ifc.ifc_len / sizeof(struct ifreq);
246                         struct ifreq ifra[nifra];
247
248                         if (umoven(tcp, (unsigned long) ifc.ifc_buf,
249                                 sizeof(ifra), (char *) ifra) < 0) {
250                                 tprintf("%lx}", (unsigned long) ifc.ifc_buf);
251                                 return 1;
252                         }
253                         tprints("{");
254                         for (i = 0; i < nifra; ++i ) {
255                                 if (i > 0)
256                                         tprints(", ");
257                                 tprintf("{\"%s\", {",
258                                         ifra[i].ifr_name);
259                                 if (verbose(tcp)) {
260                                         printxval(addrfams,
261                                                   ifra[i].ifr_addr.sa_family,
262                                                   "AF_???");
263                                         tprints(", ");
264                                         print_addr(tcp, ((long) tcp->u_arg[2]
265                                                          + offsetof(struct ifreq,
266                                                                      ifr_addr.sa_data)
267                                                          + ((char *) &ifra[i]
268                                                             - (char *) &ifra[0])),
269                                                    &ifra[i]);
270                                 } else
271                                         tprints("...");
272                                 tprints("}}");
273                         }
274                         tprints("}");
275                 }
276                 tprints("}");
277                 return 1;
278         default:
279                 return 0;
280         }
281 }
282
283 int
284 sys_socketcall(struct tcb *tcp)
285 {
286         return printargs(tcp);
287 }