1 /*
2 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <[email protected]>
3 * Copyright (c) 1996-2018 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 #include "print_fields.h"
31
32 #include <sys/socket.h>
33 #if defined ALPHA || defined SH || defined SH64
34 # include <linux/ioctl.h>
35 #endif
36 #include <linux/sockios.h>
37 #include <arpa/inet.h>
38 #include <net/if.h>
39
40 #include DEF_MPERS_TYPE(struct_ifconf)
41 #include DEF_MPERS_TYPE(struct_ifreq)
42
43 typedef struct ifconf struct_ifconf;
44 typedef struct ifreq struct_ifreq;
45
46 #include MPERS_DEFS
47
48 #include "xlat/iffflags.h"
49
50 #define XLAT_MACROS_ONLY
51 # include "xlat/arp_hardware_types.h"
52 #undef XLAT_MACROS_ONLY
53
54 static void
print_ifname(const char * ifname)55 print_ifname(const char *ifname)
56 {
57 print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
58 }
59
60 DIAG_PUSH_IGNORE_OVERRIDE_INIT
61
62 static void
print_ifreq(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg,const struct_ifreq * const ifr)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_FIELD_SOCKADDR("", *ifr, ifr_addr);
70 break;
71 case SIOCSIFDSTADDR:
72 case SIOCGIFDSTADDR:
73 PRINT_FIELD_SOCKADDR("", *ifr, ifr_dstaddr);
74 break;
75 case SIOCSIFBRDADDR:
76 case SIOCGIFBRDADDR:
77 PRINT_FIELD_SOCKADDR("", *ifr, ifr_broadaddr);
78 break;
79 case SIOCSIFNETMASK:
80 case SIOCGIFNETMASK:
81 PRINT_FIELD_SOCKADDR("", *ifr, ifr_netmask);
82 break;
83 case SIOCSIFHWADDR:
84 case SIOCGIFHWADDR: {
85 static uint8_t hwaddr_sizes[] = {
86 [0 ... ARPHRD_IEEE802_TR] = 255,
87
88 [ARPHRD_NETROM] = 7 /* AX25_ADDR_LEN */,
89 [ARPHRD_ETHER] = 6 /* ETH_ALEN */,
90 /* ARPHRD_EETHER - no actual devices in Linux */
91 [ARPHRD_AX25] = 7 /* AX25_ADDR_LEN */,
92 /* ARPHRD_PRONET - no actual devices in Linux */
93 /* ARPHRD_CHAOS - no actual devices in Linux */
94 [ARPHRD_IEEE802] = 6 /* FC_ALEN */,
95 [ARPHRD_ARCNET] = 1 /* ARCNET_ALEN */,
96 /* ARPHRD_APPLETLK - no actual devices in Linux */
97 [ARPHRD_DLCI] = sizeof(short),
98 /* ARPHRD_ATM - no explicit setting */
99 /* ARPHRD_METRICOM - no actual devices in Linux */
100 [ARPHRD_IEEE1394] = 16 /* FWNET_ALEN */,
101 [ARPHRD_EUI64] = 8 /* EUI64_ADDR_LEN */,
102 [ARPHRD_INFINIBAND] = 20 /* INFINIBAND_ALEN */,
103 [ARPHRD_SLIP] = 0,
104 /* ARPHRD_CSLIP - no actual devices in Linux */
105 /* ARPHRD_SLIP6 - no actual devices in Linux */
106 /* ARPHRD_CSLIP6 - no actual devices in Linux */
107 /* ARPHRD_RSRVD - no actual devices in Linux */
108 /* ARPHRD_ADAPT - no actual devices in Linux */
109 [ARPHRD_ROSE] = 5 /* ROSE_ADDR_LEN */,
110 [ARPHRD_X25] = 0,
111 /* ARPHRD_HWX25 - no actual devices in Linux */
112 [ARPHRD_CAN] = 0,
113 [ARPHRD_PPP] = 0,
114 /* ARPHRD_CISCO - no actual devices in Linux */
115 /* ARPHRD_LAPB - no actual devices in Linux */
116 /* ARPHRD_DDCMP - no actual devices in Linux */
117 [ARPHRD_RAWHDLC] = 0,
118 [ARPHRD_RAWIP] = 0,
119 [ARPHRD_TUNNEL] = 4 /* IPIP */,
120 [ARPHRD_TUNNEL6] = 16 /* sizeof(struct in6_addr) */,
121 /* ARPHRD_FRAD - no actual devices in Linux */
122 /* ARPHRD_SKIP - no actual devices in Linux */
123 [ARPHRD_LOOPBACK] = 6 /* ETH_ALEN */,
124 [ARPHRD_LOCALTLK] = 1 /* LTALK_ALEN */,
125 [ARPHRD_FDDI] = 6 /* FDDI_K_ALEN */,
126 /* ARPHRD_BIF - no actual devices in Linux */
127 [ARPHRD_SIT] = 4,
128 [ARPHRD_IPDDP] = 0,
129 [ARPHRD_IPGRE] = 4,
130 [ARPHRD_PIMREG] = 0,
131 [ARPHRD_HIPPI] = 6 /* HIPPI_ALEN */,
132 /* ARPHRD_ASH - no actual devices in Linux */
133 /* ARPHRD_ECONET - no actual devices in Linux */
134 [ARPHRD_IRDA] = 4 /* LAP_ALEN */,
135 /* ARPHRD_FCPP - no actual devices in Linux */
136 /* ARPHRD_FCAL - no actual devices in Linux */
137 /* ARPHRD_FCPL - no actual devices in Linux */
138 /* ARPHRD_FCFABRIC - no actual devices in Linux */
139 /* ARPHRD_IEEE802_TR - no actual devices in Linux */
140 [ARPHRD_IEEE80211] = 6 /* ETH_ALEN */,
141 [ARPHRD_IEEE80211_PRISM] = 6 /* ETH_ALEN */,
142 [ARPHRD_IEEE80211_RADIOTAP] = 6 /* ETH_ALEN */,
143 [ARPHRD_IEEE802154]
144 = 8 /* IEEE802154_EXTENDED_ADDR_LEN */,
145 [ARPHRD_IEEE802154_MONITOR]
146 = 8 /* IEEE802154_EXTENDED_ADDR_LEN */,
147 [ARPHRD_PHONET] = 1,
148 [ARPHRD_PHONET_PIPE] = 1,
149 [ARPHRD_CAIF] = 0,
150 [ARPHRD_IP6GRE] = 16 /* sizeof(struct in6_addr) */,
151 [ARPHRD_NETLINK] = 0,
152 [ARPHRD_6LOWPAN] = 8 /* EUI64_ADDR_LEN */
153 /* ^ or ETH_ALEN, depending on lltype */,
154 [ARPHRD_VSOCKMON] = 0,
155 };
156
157 uint16_t proto = ifr->ifr_hwaddr.sa_family;
158 uint8_t sz = (proto < ARRAY_SIZE(hwaddr_sizes))
159 ? hwaddr_sizes[proto] : 255;
160
161 PRINT_FIELD_XVAL_SORTED_SIZED("ifr_hwaddr={", ifr->ifr_hwaddr,
162 sa_family, arp_hardware_types,
163 arp_hardware_types_size,
164 "ARPHRD_???");
165 PRINT_FIELD_MAC_SZ(", ", ifr->ifr_hwaddr, sa_data,
166 MIN(sizeof(ifr->ifr_hwaddr.sa_data), sz));
167 tprints("}");
168 break;
169 }
170 case SIOCSIFFLAGS:
171 case SIOCGIFFLAGS:
172 tprints("ifr_flags=");
173 printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
174 break;
175 case SIOCSIFMETRIC:
176 case SIOCGIFMETRIC:
177 tprintf("ifr_metric=%d", ifr->ifr_metric);
178 break;
179 case SIOCSIFMTU:
180 case SIOCGIFMTU:
181 tprintf("ifr_mtu=%d", ifr->ifr_mtu);
182 break;
183 case SIOCSIFSLAVE:
184 case SIOCGIFSLAVE:
185 tprints("ifr_slave=");
186 print_ifname(ifr->ifr_slave);
187 break;
188 case SIOCSIFTXQLEN:
189 case SIOCGIFTXQLEN:
190 tprintf("ifr_qlen=%d", ifr->ifr_qlen);
191 break;
192 case SIOCSIFMAP:
193 case SIOCGIFMAP:
194 tprintf("ifr_map={mem_start=%#" PRI_klx ", "
195 "mem_end=%#" PRI_klx ", base_addr=%#x, "
196 "irq=%u, dma=%u, port=%u}",
197 (kernel_ulong_t) ifr->ifr_map.mem_start,
198 (kernel_ulong_t) ifr->ifr_map.mem_end,
199 (unsigned) ifr->ifr_map.base_addr,
200 (unsigned) ifr->ifr_map.irq,
201 (unsigned) ifr->ifr_map.dma,
202 (unsigned) ifr->ifr_map.port);
203 break;
204 }
205 }
206
207 DIAG_POP_IGNORE_OVERRIDE_INIT
208
209 static unsigned int
print_ifc_len(int len)210 print_ifc_len(int len)
211 {
212 const unsigned int n = (unsigned int) len / sizeof(struct_ifreq);
213
214 if (len < 0 || n * sizeof(struct_ifreq) != (unsigned int) len)
215 tprintf("%d", len);
216 else
217 tprintf("%u * sizeof(struct ifreq)", n);
218
219 return n;
220 }
221
222 static bool
print_ifconf_ifreq(struct tcb * tcp,void * elem_buf,size_t elem_size,void * dummy)223 print_ifconf_ifreq(struct tcb *tcp, void *elem_buf, size_t elem_size,
224 void *dummy)
225 {
226 struct_ifreq *ifr = elem_buf;
227
228 tprints("{ifr_name=");
229 print_ifname(ifr->ifr_name);
230 PRINT_FIELD_SOCKADDR(", ", *ifr, ifr_addr);
231 tprints("}");
232
233 return true;
234 }
235
236 /*
237 * There are two different modes of operation:
238 *
239 * - Get buffer size. In this case, the callee sets ifc_buf to NULL,
240 * and the kernel returns the buffer size in ifc_len.
241 * - Get actual data. In this case, the callee specifies the buffer address
242 * in ifc_buf and its size in ifc_len. The kernel fills the buffer with
243 * the data, and its amount is returned in ifc_len.
244 *
245 * Note that, technically, the whole struct ifconf is overwritten,
246 * so ifc_buf could be different on exit, but current ioctl handler
247 * implementation does not touch it.
248 */
249 static int
decode_ifconf(struct tcb * const tcp,const kernel_ulong_t addr)250 decode_ifconf(struct tcb *const tcp, const kernel_ulong_t addr)
251 {
252 struct_ifconf *entering_ifc = NULL;
253 struct_ifconf *ifc =
254 entering(tcp) ? malloc(sizeof(*ifc)) : alloca(sizeof(*ifc));
255
256 if (exiting(tcp)) {
257 entering_ifc = get_tcb_priv_data(tcp);
258
259 if (!entering_ifc) {
260 error_func_msg("where is my ifconf?");
261 return 0;
262 }
263 }
264
265 if (!ifc || umove(tcp, addr, ifc) < 0) {
266 if (entering(tcp)) {
267 free(ifc);
268
269 tprints(", ");
270 printaddr(addr);
271 } else {
272 /*
273 * We failed to fetch the structure on exiting syscall,
274 * print whatever was fetched on entering syscall.
275 */
276 if (!entering_ifc->ifc_buf)
277 print_ifc_len(entering_ifc->ifc_len);
278
279 tprints(", ifc_buf=");
280 printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
281
282 tprints("}");
283 }
284
285 return RVAL_IOCTL_DECODED;
286 }
287
288 if (entering(tcp)) {
289 tprints(", {ifc_len=");
290 if (ifc->ifc_buf)
291 print_ifc_len(ifc->ifc_len);
292
293 set_tcb_priv_data(tcp, ifc, free);
294
295 return 0;
296 }
297
298 /* exiting */
299
300 if (entering_ifc->ifc_buf && (entering_ifc->ifc_len != ifc->ifc_len))
301 tprints(" => ");
302 if (!entering_ifc->ifc_buf || (entering_ifc->ifc_len != ifc->ifc_len))
303 print_ifc_len(ifc->ifc_len);
304
305 tprints(", ifc_buf=");
306
307 if (!entering_ifc->ifc_buf || syserror(tcp)) {
308 printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
309 if (entering_ifc->ifc_buf != ifc->ifc_buf) {
310 tprints(" => ");
311 printaddr(ptr_to_kulong(ifc->ifc_buf));
312 }
313 } else {
314 struct_ifreq ifr;
315
316 print_array(tcp, ptr_to_kulong(ifc->ifc_buf),
317 ifc->ifc_len / sizeof(struct_ifreq),
318 &ifr, sizeof(ifr),
319 tfetch_mem, print_ifconf_ifreq, NULL);
320 }
321
322 tprints("}");
323
324 return RVAL_IOCTL_DECODED;
325 }
326
MPERS_PRINTER_DECL(int,sock_ioctl,struct tcb * tcp,const unsigned int code,const kernel_ulong_t arg)327 MPERS_PRINTER_DECL(int, sock_ioctl,
328 struct tcb *tcp, const unsigned int code,
329 const kernel_ulong_t arg)
330 {
331 struct_ifreq ifr;
332
333 switch (code) {
334 case SIOCGIFCONF:
335 return decode_ifconf(tcp, arg);
336
337 #ifdef SIOCBRADDBR
338 case SIOCBRADDBR:
339 case SIOCBRDELBR:
340 tprints(", ");
341 printstr(tcp, arg);
342 break;
343 #endif
344
345 #ifdef FIOSETOWN
346 case FIOSETOWN:
347 #endif
348 #ifdef SIOCSPGRP
349 case SIOCSPGRP:
350 #endif
351 tprints(", ");
352 printnum_int(tcp, arg, "%d");
353 break;
354
355 #ifdef FIOGETOWN
356 case FIOGETOWN:
357 #endif
358 #ifdef SIOCGPGRP
359 case SIOCGPGRP:
360 #endif
361 #ifdef SIOCATMARK
362 case SIOCATMARK:
363 #endif
364 if (entering(tcp))
365 return 0;
366 tprints(", ");
367 printnum_int(tcp, arg, "%d");
368 break;
369
370 #ifdef SIOCBRADDIF
371 case SIOCBRADDIF:
372 #endif
373 #ifdef SIOCBRDELIF
374 case SIOCBRDELIF:
375 #endif
376 /* no arguments */
377 break;
378
379 case SIOCSIFNAME:
380 case SIOCSIFADDR:
381 case SIOCSIFDSTADDR:
382 case SIOCSIFBRDADDR:
383 case SIOCSIFNETMASK:
384 case SIOCSIFFLAGS:
385 case SIOCSIFMETRIC:
386 case SIOCSIFMTU:
387 case SIOCSIFSLAVE:
388 case SIOCSIFHWADDR:
389 case SIOCSIFTXQLEN:
390 case SIOCSIFMAP:
391 tprints(", ");
392 if (umove_or_printaddr(tcp, arg, &ifr))
393 break;
394
395 tprints("{ifr_name=");
396 print_ifname(ifr.ifr_name);
397 tprints(", ");
398 if (code == SIOCSIFNAME) {
399 tprints("ifr_newname=");
400 print_ifname(ifr.ifr_newname);
401 } else {
402 print_ifreq(tcp, code, arg, &ifr);
403 }
404 tprints("}");
405 break;
406
407 case SIOCGIFNAME:
408 case SIOCGIFINDEX:
409 case SIOCGIFADDR:
410 case SIOCGIFDSTADDR:
411 case SIOCGIFBRDADDR:
412 case SIOCGIFNETMASK:
413 case SIOCGIFFLAGS:
414 case SIOCGIFMETRIC:
415 case SIOCGIFMTU:
416 case SIOCGIFSLAVE:
417 case SIOCGIFHWADDR:
418 case SIOCGIFTXQLEN:
419 case SIOCGIFMAP:
420 if (entering(tcp)) {
421 tprints(", ");
422 if (umove_or_printaddr(tcp, arg, &ifr))
423 break;
424
425 if (SIOCGIFNAME == code) {
426 tprintf("{ifr_index=%d", ifr.ifr_ifindex);
427 } else {
428 tprints("{ifr_name=");
429 print_ifname(ifr.ifr_name);
430 }
431 return 0;
432 } else {
433 if (syserror(tcp)) {
434 tprints("}");
435 break;
436 }
437
438 tprints(", ");
439 if (umove(tcp, arg, &ifr) < 0) {
440 tprints("???}");
441 break;
442 }
443
444 if (SIOCGIFNAME == code) {
445 tprints("ifr_name=");
446 print_ifname(ifr.ifr_name);
447 } else {
448 print_ifreq(tcp, code, arg, &ifr);
449 }
450 tprints("}");
451 break;
452 }
453
454 default:
455 return RVAL_DECODED;
456 }
457
458 return RVAL_IOCTL_DECODED;
459 }
460