blob: cf13896bd0d3ea0858a2b19827bfb872ea2b8a3e [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
Dmitry V. Levine0896b02016-06-21 16:45:49 +000039#define PRINT_IFREQ_ADDR(tcp, ifr, sockaddr) \
40 do { \
41 tprints(#sockaddr "="); \
42 print_sockaddr(tcp, &((ifr)->sockaddr), \
43 sizeof((ifr)->sockaddr)); \
44 } while (0)
Roland McGrathe6a432d2005-02-02 20:25:17 +000045
Dmitry V. Levin81e45152015-01-24 20:58:23 +000046static void
47print_ifname(const char *ifname)
48{
49 print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
50}
51
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030052static void
53print_ifreq(struct tcb *tcp, const unsigned int code, const long arg,
54 const struct ifreq *ifr)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000055{
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030056 switch (code) {
57 case SIOCSIFADDR:
58 case SIOCGIFADDR:
Dmitry V. Levine0896b02016-06-21 16:45:49 +000059 PRINT_IFREQ_ADDR(tcp, ifr, ifr_addr);
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030060 break;
61 case SIOCSIFDSTADDR:
62 case SIOCGIFDSTADDR:
Dmitry V. Levine0896b02016-06-21 16:45:49 +000063 PRINT_IFREQ_ADDR(tcp, ifr, ifr_dstaddr);
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030064 break;
65 case SIOCSIFBRDADDR:
66 case SIOCGIFBRDADDR:
Dmitry V. Levine0896b02016-06-21 16:45:49 +000067 PRINT_IFREQ_ADDR(tcp, ifr, ifr_broadaddr);
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030068 break;
69 case SIOCSIFNETMASK:
70 case SIOCGIFNETMASK:
Dmitry V. Levine0896b02016-06-21 16:45:49 +000071 PRINT_IFREQ_ADDR(tcp, ifr, ifr_netmask);
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030072 break;
73 case SIOCSIFHWADDR:
74 case SIOCGIFHWADDR: {
75 /* XXX Are there other hardware addresses
76 than 6-byte MACs? */
77 const unsigned char *bytes =
78 (unsigned char *) &ifr->ifr_hwaddr.sa_data;
79 tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
80 bytes[0], bytes[1], bytes[2],
81 bytes[3], bytes[4], bytes[5]);
82 break;
83 }
84 case SIOCSIFFLAGS:
85 case SIOCGIFFLAGS:
86 tprints("ifr_flags=");
Dmitry V. Levinb0695de2016-05-16 22:05:06 +000087 printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
Dmitry V. Levinb93c1102015-07-04 14:01:08 +030088 break;
89 case SIOCSIFMETRIC:
90 case SIOCGIFMETRIC:
91 tprintf("ifr_metric=%d", ifr->ifr_metric);
92 break;
93 case SIOCSIFMTU:
94 case SIOCGIFMTU:
95 tprintf("ifr_mtu=%d", ifr->ifr_mtu);
96 break;
97 case SIOCSIFSLAVE:
98 case SIOCGIFSLAVE:
99 tprints("ifr_slave=");
100 print_ifname(ifr->ifr_slave);
101 break;
102 case SIOCSIFTXQLEN:
103 case SIOCGIFTXQLEN:
104 tprintf("ifr_qlen=%d", ifr->ifr_qlen);
105 break;
106 case SIOCSIFMAP:
107 case SIOCGIFMAP:
108 tprintf("ifr_map={mem_start=%#lx, "
109 "mem_end=%#lx, base_addr=%#x, "
110 "irq=%u, dma=%u, port=%u}",
111 ifr->ifr_map.mem_start,
112 ifr->ifr_map.mem_end,
113 (unsigned) ifr->ifr_map.base_addr,
114 (unsigned) ifr->ifr_map.irq,
115 (unsigned) ifr->ifr_map.dma,
116 (unsigned) ifr->ifr_map.port);
117 break;
118 }
119}
120
121static unsigned int
122print_ifc_len(int len)
123{
124 const unsigned int n = (unsigned int) len / sizeof(struct ifreq);
125
126 if (len < 0 || n * sizeof(struct ifreq) != (unsigned int) len)
127 tprintf("%d", len);
128 else
129 tprintf("%u * sizeof(struct ifreq)", n);
130
131 return n;
132}
133
134static int
135decode_ifconf(struct tcb *tcp, const long addr)
136{
Roland McGrath5687ff12004-07-12 07:13:06 +0000137 struct ifconf ifc;
138
139 if (entering(tcp)) {
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300140 tprints(", ");
141 if (umove_or_printaddr(tcp, addr, &ifc))
142 return RVAL_DECODED | 1;
143 if (ifc.ifc_buf) {
144 tprints("{");
145 print_ifc_len(ifc.ifc_len);
Roland McGrath5687ff12004-07-12 07:13:06 +0000146 }
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300147 return 1;
Roland McGrath5687ff12004-07-12 07:13:06 +0000148 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300150 if (syserror(tcp) || umove(tcp, addr, &ifc) < 0) {
151 if (ifc.ifc_buf)
152 tprints("}");
153 else
154 printaddr(addr);
155 return RVAL_DECODED | 1;
156 }
157
158 if (!ifc.ifc_buf) {
159 tprints("{");
160 print_ifc_len(ifc.ifc_len);
161 tprints(", NULL}");
162 return RVAL_DECODED | 1;
163 }
164
165 tprints(" => ");
166 const unsigned int nifra = print_ifc_len(ifc.ifc_len);
167 if (!nifra) {
168 tprints("}");
169 return RVAL_DECODED | 1;
170 }
171
172 struct ifreq ifra[nifra > max_strlen ? max_strlen : nifra];
173 tprints(", ");
174 if (umove_or_printaddr(tcp, (unsigned long) ifc.ifc_buf, &ifra)) {
175 tprints("}");
176 return RVAL_DECODED | 1;
177 }
178
179 tprints("[");
180 unsigned int i;
181 for (i = 0; i < ARRAY_SIZE(ifra); ++i) {
182 if (i > 0)
183 tprints(", ");
184 tprints("{ifr_name=");
185 print_ifname(ifra[i].ifr_name);
186 tprints(", ");
Dmitry V. Levine0896b02016-06-21 16:45:49 +0000187 PRINT_IFREQ_ADDR(tcp, &ifra[i], ifr_addr);
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300188 tprints("}");
189 }
190 if (i < nifra)
191 tprints(", ...");
192 tprints("]}");
193
194 return RVAL_DECODED | 1;
195}
196
197int
198sock_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
199{
200 struct ifreq ifr;
201
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000202 switch (code) {
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300203 case SIOCGIFCONF:
204 return decode_ifconf(tcp, arg);
205
206#ifdef SIOCBRADDBR
207 case SIOCBRADDBR:
208 case SIOCBRDELBR:
209 tprints(", ");
210 printstr(tcp, arg, -1);
211 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000212#endif
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300213
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000214#ifdef FIOSETOWN
215 case FIOSETOWN:
216#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000217#ifdef SIOCSPGRP
218 case SIOCSPGRP:
219#endif
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300220 tprints(", ");
221 printnum_int(tcp, arg, "%d");
222 break;
223
224#ifdef FIOGETOWN
225 case FIOGETOWN:
226#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000227#ifdef SIOCGPGRP
228 case SIOCGPGRP:
229#endif
230#ifdef SIOCATMARK
231 case SIOCATMARK:
232#endif
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300233 if (entering(tcp))
234 return 0;
235 tprints(", ");
236 printnum_int(tcp, arg, "%d");
237 break;
238
239#ifdef SIOCBRADDIF
240 case SIOCBRADDIF:
241#endif
242#ifdef SIOCBRDELIF
243 case SIOCBRDELIF:
244#endif
245 /* no arguments */
246 break;
247
Dmitry V. Levin788c0d62014-10-31 19:36:01 +0000248 case SIOCSIFNAME:
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300249 case SIOCSIFADDR:
250 case SIOCSIFDSTADDR:
251 case SIOCSIFBRDADDR:
252 case SIOCSIFNETMASK:
253 case SIOCSIFFLAGS:
254 case SIOCSIFMETRIC:
255 case SIOCSIFMTU:
256 case SIOCSIFSLAVE:
257 case SIOCSIFHWADDR:
258 case SIOCSIFTXQLEN:
259 case SIOCSIFMAP:
260 tprints(", ");
261 if (umove_or_printaddr(tcp, arg, &ifr))
262 break;
263
264 tprints("{ifr_name=");
265 print_ifname(ifr.ifr_name);
266 tprints(", ");
267 if (code == SIOCSIFNAME) {
268 tprints("ifr_newname=");
269 print_ifname(ifr.ifr_newname);
270 } else {
271 print_ifreq(tcp, code, arg, &ifr);
272 }
273 tprints("}");
274 break;
275
Roland McGrath5687ff12004-07-12 07:13:06 +0000276 case SIOCGIFNAME:
277 case SIOCGIFINDEX:
Roland McGrathe6a432d2005-02-02 20:25:17 +0000278 case SIOCGIFADDR:
279 case SIOCGIFDSTADDR:
280 case SIOCGIFBRDADDR:
281 case SIOCGIFNETMASK:
282 case SIOCGIFFLAGS:
283 case SIOCGIFMETRIC:
284 case SIOCGIFMTU:
285 case SIOCGIFSLAVE:
286 case SIOCGIFHWADDR:
Dmitry V. Levin40284242007-03-21 13:52:14 +0000287 case SIOCGIFTXQLEN:
Dmitry V. Levinecdd0bb2007-03-21 13:57:50 +0000288 case SIOCGIFMAP:
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300289 if (entering(tcp)) {
Dmitry V. Levin81e45152015-01-24 20:58:23 +0000290 tprints(", ");
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300291 if (umove_or_printaddr(tcp, arg, &ifr))
Roland McGrathe6a432d2005-02-02 20:25:17 +0000292 break;
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300293
294 if (SIOCGIFNAME == code) {
295 tprintf("{ifr_index=%d", ifr.ifr_ifindex);
296 } else {
297 tprints("{ifr_name=");
298 print_ifname(ifr.ifr_name);
299 }
300 return 1;
301 } else {
302 if (syserror(tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200303 tprints("}");
Roland McGrathe6a432d2005-02-02 20:25:17 +0000304 break;
Roland McGrathe6a432d2005-02-02 20:25:17 +0000305 }
Dmitry V. Levin62e05962009-11-03 14:38:44 +0000306
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300307 tprints(", ");
308 if (umove(tcp, arg, &ifr) < 0) {
309 tprints("???}");
310 break;
Dmitry V. Levin62e05962009-11-03 14:38:44 +0000311 }
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300312
313 if (SIOCGIFNAME == code) {
314 tprints("ifr_name=");
315 print_ifname(ifr.ifr_name);
316 } else {
317 print_ifreq(tcp, code, arg, &ifr);
Roland McGrath5687ff12004-07-12 07:13:06 +0000318 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200319 tprints("}");
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300320 break;
Roland McGrath5687ff12004-07-12 07:13:06 +0000321 }
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300322
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000323 default:
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300324 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000325 }
Dmitry V. Levinb93c1102015-07-04 14:01:08 +0300326
327 return RVAL_DECODED | 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328}