• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
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