Branch data Line data Source code
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
51 : : print_ifname(const char *ifname)
52 : : {
53 : 3 : print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
54 : : }
55 : :
56 : : static void
57 : 0 : print_ifreq(struct tcb *const tcp, const unsigned int code,
58 : : const kernel_ulong_t arg, const struct_ifreq *const ifr)
59 : : {
60 [ # # # # : 0 : switch (code) {
# # # # #
# # # ]
61 : : case SIOCSIFADDR:
62 : : case SIOCGIFADDR:
63 : 0 : PRINT_FIELD_SOCKADDR("", *ifr, ifr_addr);
64 : : break;
65 : : case SIOCSIFDSTADDR:
66 : : case SIOCGIFDSTADDR:
67 : 0 : PRINT_FIELD_SOCKADDR("", *ifr, ifr_dstaddr);
68 : : break;
69 : : case SIOCSIFBRDADDR:
70 : : case SIOCGIFBRDADDR:
71 : 0 : PRINT_FIELD_SOCKADDR("", *ifr, ifr_broadaddr);
72 : : break;
73 : : case SIOCSIFNETMASK:
74 : : case SIOCGIFNETMASK:
75 : 0 : 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 : 0 : const unsigned char *bytes =
82 : : (unsigned char *) &ifr->ifr_hwaddr.sa_data;
83 : 0 : tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
84 : 0 : bytes[0], bytes[1], bytes[2],
85 : 0 : bytes[3], bytes[4], bytes[5]);
86 : : break;
87 : : }
88 : : case SIOCSIFFLAGS:
89 : : case SIOCGIFFLAGS:
90 : 0 : tprints("ifr_flags=");
91 : 0 : printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
92 : : break;
93 : : case SIOCSIFMETRIC:
94 : : case SIOCGIFMETRIC:
95 : 0 : tprintf("ifr_metric=%d", ifr->ifr_metric);
96 : : break;
97 : : case SIOCSIFMTU:
98 : : case SIOCGIFMTU:
99 : 0 : tprintf("ifr_mtu=%d", ifr->ifr_mtu);
100 : : break;
101 : : case SIOCSIFSLAVE:
102 : : case SIOCGIFSLAVE:
103 : 0 : tprints("ifr_slave=");
104 : 0 : print_ifname(ifr->ifr_slave);
105 : : break;
106 : : case SIOCSIFTXQLEN:
107 : : case SIOCGIFTXQLEN:
108 : 0 : tprintf("ifr_qlen=%d", ifr->ifr_qlen);
109 : : break;
110 : : case SIOCSIFMAP:
111 : : case SIOCGIFMAP:
112 : 0 : tprintf("ifr_map={mem_start=%#" PRI_klx ", "
113 : : "mem_end=%#" PRI_klx ", base_addr=%#x, "
114 : : "irq=%u, dma=%u, port=%u}",
115 : 0 : (kernel_ulong_t) ifr->ifr_map.mem_start,
116 : 0 : (kernel_ulong_t) ifr->ifr_map.mem_end,
117 : 0 : (unsigned) ifr->ifr_map.base_addr,
118 : 0 : (unsigned) ifr->ifr_map.irq,
119 : 0 : (unsigned) ifr->ifr_map.dma,
120 : 0 : (unsigned) ifr->ifr_map.port);
121 : : break;
122 : : }
123 : 0 : }
124 : :
125 : : static unsigned int
126 : 17 : print_ifc_len(int len)
127 : : {
128 : 17 : const unsigned int n = (unsigned int) len / sizeof(struct_ifreq);
129 : :
130 [ + - ][ + + ]: 17 : if (len < 0 || n * sizeof(struct_ifreq) != (unsigned int) len)
131 : 6 : tprintf("%d", len);
132 : : else
133 : 11 : tprintf("%u * sizeof(struct ifreq)", n);
134 : :
135 : 17 : return n;
136 : : }
137 : :
138 : : static bool
139 : 3 : print_ifconf_ifreq(struct tcb *tcp, void *elem_buf, size_t elem_size,
140 : : void *dummy)
141 : : {
142 : 3 : struct_ifreq *ifr = elem_buf;
143 : :
144 : 3 : tprints("{ifr_name=");
145 : 3 : print_ifname(ifr->ifr_name);
146 : 3 : PRINT_FIELD_SOCKADDR(", ", *ifr, ifr_addr);
147 : 3 : tprints("}");
148 : :
149 : 3 : 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
166 : 32 : decode_ifconf(struct tcb *const tcp, const kernel_ulong_t addr)
167 : : {
168 : 32 : struct_ifconf *entering_ifc = NULL;
169 [ + + ]: 32 : struct_ifconf *ifc =
170 : 32 : entering(tcp) ? malloc(sizeof(*ifc)) : alloca(sizeof(*ifc));
171 : :
172 [ + + ]: 32 : if (exiting(tcp)) {
173 : 14 : entering_ifc = get_tcb_priv_data(tcp);
174 : :
175 [ - + ]: 14 : if (!entering_ifc) {
176 : 0 : error_msg("decode_ifconf: where is my ifconf?");
177 : 0 : return 0;
178 : : }
179 : : }
180 : :
181 [ + - ][ + + ]: 32 : if (!ifc || umove(tcp, addr, ifc) < 0) {
182 [ + - ]: 4 : if (entering(tcp)) {
183 : 4 : free(ifc);
184 : :
185 : 4 : tprints(", ");
186 : 4 : 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 [ # # ]: 0 : if (!entering_ifc->ifc_buf)
193 : 0 : print_ifc_len(entering_ifc->ifc_len);
194 : :
195 : 0 : tprints(", ifc_buf=");
196 : 0 : printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
197 : :
198 : 0 : tprints("}");
199 : : }
200 : :
201 : : return RVAL_DECODED | 1;
202 : : }
203 : :
204 [ + + ]: 28 : if (entering(tcp)) {
205 : 14 : tprints(", {ifc_len=");
206 [ + + ]: 14 : if (ifc->ifc_buf)
207 : 12 : print_ifc_len(ifc->ifc_len);
208 : :
209 : 14 : set_tcb_priv_data(tcp, ifc, free);
210 : :
211 : 14 : return 1;
212 : : }
213 : :
214 : : /* exiting */
215 : :
216 [ + + ][ + + ]: 14 : if (entering_ifc->ifc_buf && (entering_ifc->ifc_len != ifc->ifc_len))
217 : 3 : tprints(" => ");
218 [ + + ][ + + ]: 14 : if (!entering_ifc->ifc_buf || (entering_ifc->ifc_len != ifc->ifc_len))
219 : 5 : print_ifc_len(ifc->ifc_len);
220 : :
221 : 14 : tprints(", ifc_buf=");
222 : :
223 [ + + ][ + + ]: 14 : if (!entering_ifc->ifc_buf || syserror(tcp)) {
224 : 7 : printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
225 [ - + ]: 7 : if (entering_ifc->ifc_buf != ifc->ifc_buf) {
226 : 0 : tprints(" => ");
227 : 0 : printaddr(ptr_to_kulong(ifc->ifc_buf));
228 : : }
229 : : } else {
230 : : struct_ifreq ifr;
231 : :
232 : 7 : print_array(tcp, ptr_to_kulong(ifc->ifc_buf),
233 : 7 : ifc->ifc_len / sizeof(struct_ifreq),
234 : : &ifr, sizeof(ifr),
235 : : umoven_or_printaddr, print_ifconf_ifreq, NULL);
236 : : }
237 : :
238 : 14 : tprints("}");
239 : :
240 : 14 : return RVAL_DECODED | 1;
241 : : }
242 : :
243 : 32 : 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 [ + - - - : 32 : switch (code) {
- - - - ]
250 : : case SIOCGIFCONF:
251 : 32 : return decode_ifconf(tcp, arg);
252 : :
253 : : #ifdef SIOCBRADDBR
254 : : case SIOCBRADDBR:
255 : : case SIOCBRDELBR:
256 : 0 : 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 : 0 : tprints(", ");
268 : 0 : printnum_int(tcp, arg, "%d");
269 : 0 : 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 [ # # ]: 0 : if (entering(tcp))
281 : : return 0;
282 : 0 : tprints(", ");
283 : 0 : printnum_int(tcp, arg, "%d");
284 : 0 : 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 : 0 : tprints(", ");
308 [ # # ]: 0 : if (umove_or_printaddr(tcp, arg, &ifr))
309 : : break;
310 : :
311 : 0 : tprints("{ifr_name=");
312 : : print_ifname(ifr.ifr_name);
313 : 0 : tprints(", ");
314 [ # # ]: 0 : if (code == SIOCSIFNAME) {
315 : 0 : tprints("ifr_newname=");
316 : : print_ifname(ifr.ifr_newname);
317 : : } else {
318 : 0 : print_ifreq(tcp, code, arg, &ifr);
319 : : }
320 : 0 : tprints("}");
321 : 0 : 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 [ # # ]: 0 : if (entering(tcp)) {
337 : 0 : tprints(", ");
338 [ # # ]: 0 : if (umove_or_printaddr(tcp, arg, &ifr))
339 : : break;
340 : :
341 [ # # ]: 0 : if (SIOCGIFNAME == code) {
342 : 0 : tprintf("{ifr_index=%d", ifr.ifr_ifindex);
343 : : } else {
344 : 0 : tprints("{ifr_name=");
345 : : print_ifname(ifr.ifr_name);
346 : : }
347 : : return 1;
348 : : } else {
349 [ # # ]: 0 : if (syserror(tcp)) {
350 : 0 : tprints("}");
351 : 0 : break;
352 : : }
353 : :
354 : 0 : tprints(", ");
355 [ # # ]: 0 : if (umove(tcp, arg, &ifr) < 0) {
356 : 0 : tprints("???}");
357 : 0 : break;
358 : : }
359 : :
360 [ # # ]: 0 : if (SIOCGIFNAME == code) {
361 : 0 : tprints("ifr_name=");
362 : : print_ifname(ifr.ifr_name);
363 : : } else {
364 : 0 : print_ifreq(tcp, code, arg, &ifr);
365 : : }
366 : 0 : tprints("}");
367 : 0 : break;
368 : : }
369 : :
370 : : default:
371 : : return RVAL_DECODED;
372 : : }
373 : :
374 : : return RVAL_DECODED | 1;
375 : : }
|