• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
3  * Copyright (c) 1996-2017 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 
31 #include <sys/socket.h>
32 #if defined ALPHA || defined SH || defined SH64
33 # include <linux/ioctl.h>
34 #endif
35 #include <linux/sockios.h>
36 #include <arpa/inet.h>
37 #include <net/if.h>
38 
39 #include DEF_MPERS_TYPE(struct_ifconf)
40 #include DEF_MPERS_TYPE(struct_ifreq)
41 
42 typedef struct ifconf struct_ifconf;
43 typedef struct ifreq struct_ifreq;
44 
45 #include MPERS_DEFS
46 
47 #include "xlat/iffflags.h"
48 
49 #define PRINT_IFREQ_ADDR(tcp, ifr, sockaddr)					\
50 	do {									\
51 		tprints(#sockaddr "=");						\
52 		print_sockaddr(tcp, &((ifr)->sockaddr),				\
53 			       sizeof((ifr)->sockaddr));			\
54 	} while (0)
55 
56 static void
print_ifname(const char * ifname)57 print_ifname(const char *ifname)
58 {
59 	print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
60 }
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_IFREQ_ADDR(tcp, ifr, ifr_addr);
70 		break;
71 	case SIOCSIFDSTADDR:
72 	case SIOCGIFDSTADDR:
73 		PRINT_IFREQ_ADDR(tcp, ifr, ifr_dstaddr);
74 		break;
75 	case SIOCSIFBRDADDR:
76 	case SIOCGIFBRDADDR:
77 		PRINT_IFREQ_ADDR(tcp, ifr, ifr_broadaddr);
78 		break;
79 	case SIOCSIFNETMASK:
80 	case SIOCGIFNETMASK:
81 		PRINT_IFREQ_ADDR(tcp, ifr, ifr_netmask);
82 		break;
83 	case SIOCSIFHWADDR:
84 	case SIOCGIFHWADDR: {
85 		/* XXX Are there other hardware addresses
86 		   than 6-byte MACs?  */
87 		const unsigned char *bytes =
88 			(unsigned char *) &ifr->ifr_hwaddr.sa_data;
89 		tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
90 			bytes[0], bytes[1], bytes[2],
91 			bytes[3], bytes[4], bytes[5]);
92 		break;
93 	}
94 	case SIOCSIFFLAGS:
95 	case SIOCGIFFLAGS:
96 		tprints("ifr_flags=");
97 		printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
98 		break;
99 	case SIOCSIFMETRIC:
100 	case SIOCGIFMETRIC:
101 		tprintf("ifr_metric=%d", ifr->ifr_metric);
102 		break;
103 	case SIOCSIFMTU:
104 	case SIOCGIFMTU:
105 		tprintf("ifr_mtu=%d", ifr->ifr_mtu);
106 		break;
107 	case SIOCSIFSLAVE:
108 	case SIOCGIFSLAVE:
109 		tprints("ifr_slave=");
110 		print_ifname(ifr->ifr_slave);
111 		break;
112 	case SIOCSIFTXQLEN:
113 	case SIOCGIFTXQLEN:
114 		tprintf("ifr_qlen=%d", ifr->ifr_qlen);
115 		break;
116 	case SIOCSIFMAP:
117 	case SIOCGIFMAP:
118 		tprintf("ifr_map={mem_start=%#" PRI_klx ", "
119 			"mem_end=%#" PRI_klx ", base_addr=%#x, "
120 			"irq=%u, dma=%u, port=%u}",
121 			(kernel_ulong_t) ifr->ifr_map.mem_start,
122 			(kernel_ulong_t) ifr->ifr_map.mem_end,
123 			(unsigned) ifr->ifr_map.base_addr,
124 			(unsigned) ifr->ifr_map.irq,
125 			(unsigned) ifr->ifr_map.dma,
126 			(unsigned) ifr->ifr_map.port);
127 		break;
128 	}
129 }
130 
131 static unsigned int
print_ifc_len(int len)132 print_ifc_len(int len)
133 {
134 	const unsigned int n = (unsigned int) len / sizeof(struct_ifreq);
135 
136 	if (len < 0 || n * sizeof(struct_ifreq) != (unsigned int) len)
137 		tprintf("%d", len);
138 	else
139 		tprintf("%u * sizeof(struct ifreq)", n);
140 
141 	return n;
142 }
143 
144 static bool
print_ifconf_ifreq(struct tcb * tcp,void * elem_buf,size_t elem_size,void * dummy)145 print_ifconf_ifreq(struct tcb *tcp, void *elem_buf, size_t elem_size,
146 		   void *dummy)
147 {
148 	struct_ifreq *ifr = elem_buf;
149 
150 	tprints("{ifr_name=");
151 	print_ifname(ifr->ifr_name);
152 	tprints(", ");
153 	PRINT_IFREQ_ADDR(tcp, ifr, ifr_addr);
154 	tprints("}");
155 
156 	return true;
157 }
158 
159 /*
160  * There are two different modes of operation:
161  *
162  * - Get buffer size.  In this case, the callee sets ifc_buf to NULL,
163  *   and the kernel returns the buffer size in ifc_len.
164  * - Get actual data.  In this case, the callee specifies the buffer address
165  *   in ifc_buf and its size in ifc_len.  The kernel fills the buffer with
166  *   the data, and its amount is returned in ifc_len.
167  *
168  * Note that, technically, the whole struct ifconf is overwritten,
169  * so ifc_buf could be different on exit, but current ioctl handler
170  * implementation does not touch it.
171  */
172 static int
decode_ifconf(struct tcb * const tcp,const kernel_ulong_t addr)173 decode_ifconf(struct tcb *const tcp, const kernel_ulong_t addr)
174 {
175 	struct_ifconf *entering_ifc = NULL;
176 	struct_ifconf *ifc =
177 		entering(tcp) ? malloc(sizeof(*ifc)) : alloca(sizeof(*ifc));
178 
179 	if (exiting(tcp)) {
180 		entering_ifc = get_tcb_priv_data(tcp);
181 
182 		if (!entering_ifc) {
183 			error_msg("decode_ifconf: where is my ifconf?");
184 			return 0;
185 		}
186 	}
187 
188 	if (!ifc || umove(tcp, addr, ifc) < 0) {
189 		if (entering(tcp)) {
190 			free(ifc);
191 
192 			tprints(", ");
193 			printaddr(addr);
194 		} else {
195 			/*
196 			 * We failed to fetch the structure on exiting syscall,
197 			 * print whatever was fetched on entering syscall.
198 			 */
199 			if (!entering_ifc->ifc_buf)
200 				print_ifc_len(entering_ifc->ifc_len);
201 
202 			tprints(", ifc_buf=");
203 			printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
204 
205 			tprints("}");
206 		}
207 
208 		return RVAL_DECODED | 1;
209 	}
210 
211 	if (entering(tcp)) {
212 		tprints(", {ifc_len=");
213 		if (ifc->ifc_buf)
214 			print_ifc_len(ifc->ifc_len);
215 
216 		set_tcb_priv_data(tcp, ifc, free);
217 
218 		return 1;
219 	}
220 
221 	/* exiting */
222 
223 	if (entering_ifc->ifc_buf && (entering_ifc->ifc_len != ifc->ifc_len))
224 		tprints(" => ");
225 	if (!entering_ifc->ifc_buf || (entering_ifc->ifc_len != ifc->ifc_len))
226 		print_ifc_len(ifc->ifc_len);
227 
228 	tprints(", ifc_buf=");
229 
230 	if (!entering_ifc->ifc_buf || syserror(tcp)) {
231 		printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
232 		if (entering_ifc->ifc_buf != ifc->ifc_buf) {
233 			tprints(" => ");
234 			printaddr(ptr_to_kulong(ifc->ifc_buf));
235 		}
236 	} else {
237 		struct_ifreq ifr;
238 
239 		print_array(tcp, ptr_to_kulong(ifc->ifc_buf),
240 			    ifc->ifc_len / sizeof(struct_ifreq),
241 			    &ifr, sizeof(ifr),
242 			    umoven_or_printaddr, print_ifconf_ifreq, NULL);
243 	}
244 
245 	tprints("}");
246 
247 	return RVAL_DECODED | 1;
248 }
249 
MPERS_PRINTER_DECL(int,sock_ioctl,struct tcb * tcp,const unsigned int code,const kernel_ulong_t arg)250 MPERS_PRINTER_DECL(int, sock_ioctl,
251 		   struct tcb *tcp, const unsigned int code,
252 		   const kernel_ulong_t arg)
253 {
254 	struct_ifreq ifr;
255 
256 	switch (code) {
257 	case SIOCGIFCONF:
258 		return decode_ifconf(tcp, arg);
259 
260 #ifdef SIOCBRADDBR
261 	case SIOCBRADDBR:
262 	case SIOCBRDELBR:
263 		tprints(", ");
264 		printstr(tcp, arg);
265 		break;
266 #endif
267 
268 #ifdef FIOSETOWN
269 	case FIOSETOWN:
270 #endif
271 #ifdef SIOCSPGRP
272 	case SIOCSPGRP:
273 #endif
274 		tprints(", ");
275 		printnum_int(tcp, arg, "%d");
276 		break;
277 
278 #ifdef FIOGETOWN
279 	case FIOGETOWN:
280 #endif
281 #ifdef SIOCGPGRP
282 	case SIOCGPGRP:
283 #endif
284 #ifdef SIOCATMARK
285 	case SIOCATMARK:
286 #endif
287 		if (entering(tcp))
288 			return 0;
289 		tprints(", ");
290 		printnum_int(tcp, arg, "%d");
291 		break;
292 
293 #ifdef SIOCBRADDIF
294 	case SIOCBRADDIF:
295 #endif
296 #ifdef SIOCBRDELIF
297 	case SIOCBRDELIF:
298 #endif
299 		/* no arguments */
300 		break;
301 
302 	case SIOCSIFNAME:
303 	case SIOCSIFADDR:
304 	case SIOCSIFDSTADDR:
305 	case SIOCSIFBRDADDR:
306 	case SIOCSIFNETMASK:
307 	case SIOCSIFFLAGS:
308 	case SIOCSIFMETRIC:
309 	case SIOCSIFMTU:
310 	case SIOCSIFSLAVE:
311 	case SIOCSIFHWADDR:
312 	case SIOCSIFTXQLEN:
313 	case SIOCSIFMAP:
314 		tprints(", ");
315 		if (umove_or_printaddr(tcp, arg, &ifr))
316 			break;
317 
318 		tprints("{ifr_name=");
319 		print_ifname(ifr.ifr_name);
320 		tprints(", ");
321 		if (code == SIOCSIFNAME) {
322 			tprints("ifr_newname=");
323 			print_ifname(ifr.ifr_newname);
324 		} else {
325 			print_ifreq(tcp, code, arg, &ifr);
326 		}
327 		tprints("}");
328 		break;
329 
330 	case SIOCGIFNAME:
331 	case SIOCGIFINDEX:
332 	case SIOCGIFADDR:
333 	case SIOCGIFDSTADDR:
334 	case SIOCGIFBRDADDR:
335 	case SIOCGIFNETMASK:
336 	case SIOCGIFFLAGS:
337 	case SIOCGIFMETRIC:
338 	case SIOCGIFMTU:
339 	case SIOCGIFSLAVE:
340 	case SIOCGIFHWADDR:
341 	case SIOCGIFTXQLEN:
342 	case SIOCGIFMAP:
343 		if (entering(tcp)) {
344 			tprints(", ");
345 			if (umove_or_printaddr(tcp, arg, &ifr))
346 				break;
347 
348 			if (SIOCGIFNAME == code) {
349 				tprintf("{ifr_index=%d", ifr.ifr_ifindex);
350 			} else {
351 				tprints("{ifr_name=");
352 				print_ifname(ifr.ifr_name);
353 			}
354 			return 1;
355 		} else {
356 			if (syserror(tcp)) {
357 				tprints("}");
358 				break;
359 			}
360 
361 			tprints(", ");
362 			if (umove(tcp, arg, &ifr) < 0) {
363 				tprints("???}");
364 				break;
365 			}
366 
367 			if (SIOCGIFNAME == code) {
368 				tprints("ifr_name=");
369 				print_ifname(ifr.ifr_name);
370 			} else {
371 				print_ifreq(tcp, code, arg, &ifr);
372 			}
373 			tprints("}");
374 			break;
375 		}
376 
377 	default:
378 		return RVAL_DECODED;
379 	}
380 
381 	return RVAL_DECODED | 1;
382 }
383