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