blob: c948294697810a09ffd82833a5fd4716e12ef231 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000026 */
27
28#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000029#include <sys/socket.h>
Dmitry V. Levindeff5692016-05-13 20:22:18 +000030#if defined ALPHA || defined SH || defined SH64
31# include <linux/ioctl.h>
32#endif
Roland McGrath5687ff12004-07-12 07:13:06 +000033#include <linux/sockios.h>
Roland McGrath5687ff12004-07-12 07:13:06 +000034#include <arpa/inet.h>
Roland McGrath5687ff12004-07-12 07:13:06 +000035#include <net/if.h>
36
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000037#include "xlat/iffflags.h"
Roland McGrathe6a432d2005-02-02 20:25:17 +000038
Roland McGrathe6a432d2005-02-02 20:25:17 +000039static void
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030040print_ifreq_addr(struct tcb *tcp, const struct ifreq *ifr, const long addr)
Roland McGrathe6a432d2005-02-02 20:25:17 +000041{
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030042 tprintf("{");
43 printxval(addrfams, ifr->ifr_addr.sa_family, "AF_???");
44 tprints(", ");
Roland McGrathe6a432d2005-02-02 20:25:17 +000045 if (ifr->ifr_addr.sa_family == AF_INET) {
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030046 const struct sockaddr_in *sinp =
47 (struct sockaddr_in *) &ifr->ifr_addr;
Roland McGrathe6a432d2005-02-02 20:25:17 +000048 tprintf("inet_addr(\"%s\")", inet_ntoa(sinp->sin_addr));
49 } else
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030050 printstr(tcp, addr + offsetof(struct ifreq, ifr_addr.sa_data),
51 sizeof(ifr->ifr_addr.sa_data));
52 tprints("}");
Roland McGrathe6a432d2005-02-02 20:25:17 +000053}
54
Dmitry V. Levin81e45152015-01-24 20:58:23 +000055static void
56print_ifname(const char *ifname)
57{
58 print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
59}
60
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030061static void
62print_ifreq(struct tcb *tcp, const unsigned int code, const long arg,
63 const struct ifreq *ifr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000064{
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030065 switch (code) {
66 case SIOCSIFADDR:
67 case SIOCGIFADDR:
68 tprints("ifr_addr=");
69 print_ifreq_addr(tcp, ifr, arg);
70 break;
71 case SIOCSIFDSTADDR:
72 case SIOCGIFDSTADDR:
73 tprints("ifr_dstaddr=");
74 print_ifreq_addr(tcp, ifr, arg);
75 break;
76 case SIOCSIFBRDADDR:
77 case SIOCGIFBRDADDR:
78 tprints("ifr_broadaddr=");
79 print_ifreq_addr(tcp, ifr, arg);
80 break;
81 case SIOCSIFNETMASK:
82 case SIOCGIFNETMASK:
83 tprints("ifr_netmask=");
84 print_ifreq_addr(tcp, ifr, arg);
85 break;
86 case SIOCSIFHWADDR:
87 case SIOCGIFHWADDR: {
88 /* XXX Are there other hardware addresses
89 than 6-byte MACs? */
90 const unsigned char *bytes =
91 (unsigned char *) &ifr->ifr_hwaddr.sa_data;
92 tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
93 bytes[0], bytes[1], bytes[2],
94 bytes[3], bytes[4], bytes[5]);
95 break;
96 }
97 case SIOCSIFFLAGS:
98 case SIOCGIFFLAGS:
99 tprints("ifr_flags=");
Dmitry V. Levinb0695de2016-05-16 22:05:06 +0000100 printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300101 break;
102 case SIOCSIFMETRIC:
103 case SIOCGIFMETRIC:
104 tprintf("ifr_metric=%d", ifr->ifr_metric);
105 break;
106 case SIOCSIFMTU:
107 case SIOCGIFMTU:
108 tprintf("ifr_mtu=%d", ifr->ifr_mtu);
109 break;
110 case SIOCSIFSLAVE:
111 case SIOCGIFSLAVE:
112 tprints("ifr_slave=");
113 print_ifname(ifr->ifr_slave);
114 break;
115 case SIOCSIFTXQLEN:
116 case SIOCGIFTXQLEN:
117 tprintf("ifr_qlen=%d", ifr->ifr_qlen);
118 break;
119 case SIOCSIFMAP:
120 case SIOCGIFMAP:
121 tprintf("ifr_map={mem_start=%#lx, "
122 "mem_end=%#lx, base_addr=%#x, "
123 "irq=%u, dma=%u, port=%u}",
124 ifr->ifr_map.mem_start,
125 ifr->ifr_map.mem_end,
126 (unsigned) ifr->ifr_map.base_addr,
127 (unsigned) ifr->ifr_map.irq,
128 (unsigned) ifr->ifr_map.dma,
129 (unsigned) ifr->ifr_map.port);
130 break;
131 }
132}
133
134static unsigned int
135print_ifc_len(int len)
136{
137 const unsigned int n = (unsigned int) len / sizeof(struct ifreq);
138
139 if (len < 0 || n * sizeof(struct ifreq) != (unsigned int) len)
140 tprintf("%d", len);
141 else
142 tprintf("%u * sizeof(struct ifreq)", n);
143
144 return n;
145}
146
147static int
148decode_ifconf(struct tcb *tcp, const long addr)
149{
Roland McGrath5687ff12004-07-12 07:13:06 +0000150 struct ifconf ifc;
151
152 if (entering(tcp)) {
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300153 tprints(", ");
154 if (umove_or_printaddr(tcp, addr, &ifc))
155 return RVAL_DECODED | 1;
156 if (ifc.ifc_buf) {
157 tprints("{");
158 print_ifc_len(ifc.ifc_len);
Roland McGrath5687ff12004-07-12 07:13:06 +0000159 }
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300160 return 1;
Roland McGrath5687ff12004-07-12 07:13:06 +0000161 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300163 if (syserror(tcp) || umove(tcp, addr, &ifc) < 0) {
164 if (ifc.ifc_buf)
165 tprints("}");
166 else
167 printaddr(addr);
168 return RVAL_DECODED | 1;
169 }
170
171 if (!ifc.ifc_buf) {
172 tprints("{");
173 print_ifc_len(ifc.ifc_len);
174 tprints(", NULL}");
175 return RVAL_DECODED | 1;
176 }
177
178 tprints(" => ");
179 const unsigned int nifra = print_ifc_len(ifc.ifc_len);
180 if (!nifra) {
181 tprints("}");
182 return RVAL_DECODED | 1;
183 }
184
185 struct ifreq ifra[nifra > max_strlen ? max_strlen : nifra];
186 tprints(", ");
187 if (umove_or_printaddr(tcp, (unsigned long) ifc.ifc_buf, &ifra)) {
188 tprints("}");
189 return RVAL_DECODED | 1;
190 }
191
192 tprints("[");
193 unsigned int i;
194 for (i = 0; i < ARRAY_SIZE(ifra); ++i) {
195 if (i > 0)
196 tprints(", ");
197 tprints("{ifr_name=");
198 print_ifname(ifra[i].ifr_name);
199 tprints(", ");
200 if (verbose(tcp)) {
201 tprints("ifr_addr=");
202 print_ifreq_addr(tcp, &ifra[i],
203 addr + i * sizeof(ifra[0]));
204 } else
205 tprints("...");
206 tprints("}");
207 }
208 if (i < nifra)
209 tprints(", ...");
210 tprints("]}");
211
212 return RVAL_DECODED | 1;
213}
214
215int
216sock_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
217{
218 struct ifreq ifr;
219
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000220 switch (code) {
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300221 case SIOCGIFCONF:
222 return decode_ifconf(tcp, arg);
223
224#ifdef SIOCBRADDBR
225 case SIOCBRADDBR:
226 case SIOCBRDELBR:
227 tprints(", ");
228 printstr(tcp, arg, -1);
229 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000230#endif
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300231
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232#ifdef FIOSETOWN
233 case FIOSETOWN:
234#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235#ifdef SIOCSPGRP
236 case SIOCSPGRP:
237#endif
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300238 tprints(", ");
239 printnum_int(tcp, arg, "%d");
240 break;
241
242#ifdef FIOGETOWN
243 case FIOGETOWN:
244#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000245#ifdef SIOCGPGRP
246 case SIOCGPGRP:
247#endif
248#ifdef SIOCATMARK
249 case SIOCATMARK:
250#endif
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300251 if (entering(tcp))
252 return 0;
253 tprints(", ");
254 printnum_int(tcp, arg, "%d");
255 break;
256
257#ifdef SIOCBRADDIF
258 case SIOCBRADDIF:
259#endif
260#ifdef SIOCBRDELIF
261 case SIOCBRDELIF:
262#endif
263 /* no arguments */
264 break;
265
Dmitry V. Levin788c0d62014-10-31 19:36:01 +0000266 case SIOCSIFNAME:
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300267 case SIOCSIFADDR:
268 case SIOCSIFDSTADDR:
269 case SIOCSIFBRDADDR:
270 case SIOCSIFNETMASK:
271 case SIOCSIFFLAGS:
272 case SIOCSIFMETRIC:
273 case SIOCSIFMTU:
274 case SIOCSIFSLAVE:
275 case SIOCSIFHWADDR:
276 case SIOCSIFTXQLEN:
277 case SIOCSIFMAP:
278 tprints(", ");
279 if (umove_or_printaddr(tcp, arg, &ifr))
280 break;
281
282 tprints("{ifr_name=");
283 print_ifname(ifr.ifr_name);
284 tprints(", ");
285 if (code == SIOCSIFNAME) {
286 tprints("ifr_newname=");
287 print_ifname(ifr.ifr_newname);
288 } else {
289 print_ifreq(tcp, code, arg, &ifr);
290 }
291 tprints("}");
292 break;
293
Roland McGrath5687ff12004-07-12 07:13:06 +0000294 case SIOCGIFNAME:
295 case SIOCGIFINDEX:
Roland McGrathe6a432d2005-02-02 20:25:17 +0000296 case SIOCGIFADDR:
297 case SIOCGIFDSTADDR:
298 case SIOCGIFBRDADDR:
299 case SIOCGIFNETMASK:
300 case SIOCGIFFLAGS:
301 case SIOCGIFMETRIC:
302 case SIOCGIFMTU:
303 case SIOCGIFSLAVE:
304 case SIOCGIFHWADDR:
Dmitry V. Levin40284242007-03-21 13:52:14 +0000305 case SIOCGIFTXQLEN:
Dmitry V. Levinecdd0bb2007-03-21 13:57:50 +0000306 case SIOCGIFMAP:
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300307 if (entering(tcp)) {
Dmitry V. Levin81e45152015-01-24 20:58:23 +0000308 tprints(", ");
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300309 if (umove_or_printaddr(tcp, arg, &ifr))
Roland McGrathe6a432d2005-02-02 20:25:17 +0000310 break;
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300311
312 if (SIOCGIFNAME == code) {
313 tprintf("{ifr_index=%d", ifr.ifr_ifindex);
314 } else {
315 tprints("{ifr_name=");
316 print_ifname(ifr.ifr_name);
317 }
318 return 1;
319 } else {
320 if (syserror(tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200321 tprints("}");
Roland McGrathe6a432d2005-02-02 20:25:17 +0000322 break;
Roland McGrathe6a432d2005-02-02 20:25:17 +0000323 }
Dmitry V. Levin62e05962009-11-03 14:38:44 +0000324
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300325 tprints(", ");
326 if (umove(tcp, arg, &ifr) < 0) {
327 tprints("???}");
328 break;
Dmitry V. Levin62e05962009-11-03 14:38:44 +0000329 }
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300330
331 if (SIOCGIFNAME == code) {
332 tprints("ifr_name=");
333 print_ifname(ifr.ifr_name);
334 } else {
335 print_ifreq(tcp, code, arg, &ifr);
Roland McGrath5687ff12004-07-12 07:13:06 +0000336 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200337 tprints("}");
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300338 break;
Roland McGrath5687ff12004-07-12 07:13:06 +0000339 }
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300340
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000341 default:
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300342 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000343 }
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300344
345 return RVAL_DECODED | 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000346}