1 /* 2 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) 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. 26 */ 27 28 #include "defs.h" 29 #include <sys/socket.h> 30 #include <linux/sockios.h> 31 #include <arpa/inet.h> 32 #if defined(ALPHA) || defined(SH) || defined(SH64) 33 # if defined(HAVE_SYS_IOCTL_H) 34 # include <sys/ioctl.h> 35 # elif defined(HAVE_IOCTLS_H) 36 # include <ioctls.h> 37 # endif 38 #endif 39 #include <net/if.h> 40 41 #include "xlat/iffflags.h" 42 43 static void 44 print_ifreq_addr(struct tcb *tcp, const struct ifreq *ifr, const long addr) 45 { 46 tprintf("{"); 47 printxval(addrfams, ifr->ifr_addr.sa_family, "AF_???"); 48 tprints(", "); 49 if (ifr->ifr_addr.sa_family == AF_INET) { 50 const struct sockaddr_in *sinp = 51 (struct sockaddr_in *) &ifr->ifr_addr; 52 tprintf("inet_addr(\"%s\")", inet_ntoa(sinp->sin_addr)); 53 } else 54 printstr(tcp, addr + offsetof(struct ifreq, ifr_addr.sa_data), 55 sizeof(ifr->ifr_addr.sa_data)); 56 tprints("}"); 57 } 58 59 static void 60 print_ifname(const char *ifname) 61 { 62 print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED); 63 } 64 65 static void 66 print_ifreq(struct tcb *tcp, const unsigned int code, const long arg, 67 const struct ifreq *ifr) 68 { 69 switch (code) { 70 case SIOCSIFADDR: 71 case SIOCGIFADDR: 72 tprints("ifr_addr="); 73 print_ifreq_addr(tcp, ifr, arg); 74 break; 75 case SIOCSIFDSTADDR: 76 case SIOCGIFDSTADDR: 77 tprints("ifr_dstaddr="); 78 print_ifreq_addr(tcp, ifr, arg); 79 break; 80 case SIOCSIFBRDADDR: 81 case SIOCGIFBRDADDR: 82 tprints("ifr_broadaddr="); 83 print_ifreq_addr(tcp, ifr, arg); 84 break; 85 case SIOCSIFNETMASK: 86 case SIOCGIFNETMASK: 87 tprints("ifr_netmask="); 88 print_ifreq_addr(tcp, ifr, arg); 89 break; 90 case SIOCSIFHWADDR: 91 case SIOCGIFHWADDR: { 92 /* XXX Are there other hardware addresses 93 than 6-byte MACs? */ 94 const unsigned char *bytes = 95 (unsigned char *) &ifr->ifr_hwaddr.sa_data; 96 tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x", 97 bytes[0], bytes[1], bytes[2], 98 bytes[3], bytes[4], bytes[5]); 99 break; 100 } 101 case SIOCSIFFLAGS: 102 case SIOCGIFFLAGS: 103 tprints("ifr_flags="); 104 printflags(iffflags, ifr->ifr_flags, "IFF_???"); 105 break; 106 case SIOCSIFMETRIC: 107 case SIOCGIFMETRIC: 108 tprintf("ifr_metric=%d", ifr->ifr_metric); 109 break; 110 case SIOCSIFMTU: 111 case SIOCGIFMTU: 112 tprintf("ifr_mtu=%d", ifr->ifr_mtu); 113 break; 114 case SIOCSIFSLAVE: 115 case SIOCGIFSLAVE: 116 tprints("ifr_slave="); 117 print_ifname(ifr->ifr_slave); 118 break; 119 case SIOCSIFTXQLEN: 120 case SIOCGIFTXQLEN: 121 tprintf("ifr_qlen=%d", ifr->ifr_qlen); 122 break; 123 case SIOCSIFMAP: 124 case SIOCGIFMAP: 125 tprintf("ifr_map={mem_start=%#lx, " 126 "mem_end=%#lx, base_addr=%#x, " 127 "irq=%u, dma=%u, port=%u}", 128 ifr->ifr_map.mem_start, 129 ifr->ifr_map.mem_end, 130 (unsigned) ifr->ifr_map.base_addr, 131 (unsigned) ifr->ifr_map.irq, 132 (unsigned) ifr->ifr_map.dma, 133 (unsigned) ifr->ifr_map.port); 134 break; 135 } 136 } 137 138 static unsigned int 139 print_ifc_len(int len) 140 { 141 const unsigned int n = (unsigned int) len / sizeof(struct ifreq); 142 143 if (len < 0 || n * sizeof(struct ifreq) != (unsigned int) len) 144 tprintf("%d", len); 145 else 146 tprintf("%u * sizeof(struct ifreq)", n); 147 148 return n; 149 } 150 151 static int 152 decode_ifconf(struct tcb *tcp, const long addr) 153 { 154 struct ifconf ifc; 155 156 if (entering(tcp)) { 157 tprints(", "); 158 if (umove_or_printaddr(tcp, addr, &ifc)) 159 return RVAL_DECODED | 1; 160 if (ifc.ifc_buf) { 161 tprints("{"); 162 print_ifc_len(ifc.ifc_len); 163 } 164 return 1; 165 } 166 167 if (syserror(tcp) || umove(tcp, addr, &ifc) < 0) { 168 if (ifc.ifc_buf) 169 tprints("}"); 170 else 171 printaddr(addr); 172 return RVAL_DECODED | 1; 173 } 174 175 if (!ifc.ifc_buf) { 176 tprints("{"); 177 print_ifc_len(ifc.ifc_len); 178 tprints(", NULL}"); 179 return RVAL_DECODED | 1; 180 } 181 182 tprints(" => "); 183 const unsigned int nifra = print_ifc_len(ifc.ifc_len); 184 if (!nifra) { 185 tprints("}"); 186 return RVAL_DECODED | 1; 187 } 188 189 struct ifreq ifra[nifra > max_strlen ? max_strlen : nifra]; 190 tprints(", "); 191 if (umove_or_printaddr(tcp, (unsigned long) ifc.ifc_buf, &ifra)) { 192 tprints("}"); 193 return RVAL_DECODED | 1; 194 } 195 196 tprints("["); 197 unsigned int i; 198 for (i = 0; i < ARRAY_SIZE(ifra); ++i) { 199 if (i > 0) 200 tprints(", "); 201 tprints("{ifr_name="); 202 print_ifname(ifra[i].ifr_name); 203 tprints(", "); 204 if (verbose(tcp)) { 205 tprints("ifr_addr="); 206 print_ifreq_addr(tcp, &ifra[i], 207 addr + i * sizeof(ifra[0])); 208 } else 209 tprints("..."); 210 tprints("}"); 211 } 212 if (i < nifra) 213 tprints(", ..."); 214 tprints("]}"); 215 216 return RVAL_DECODED | 1; 217 } 218 219 int 220 sock_ioctl(struct tcb *tcp, const unsigned int code, const long arg) 221 { 222 struct ifreq ifr; 223 224 switch (code) { 225 case SIOCGIFCONF: 226 return decode_ifconf(tcp, arg); 227 228 #ifdef SIOCBRADDBR 229 case SIOCBRADDBR: 230 case SIOCBRDELBR: 231 tprints(", "); 232 printstr(tcp, arg, -1); 233 break; 234 #endif 235 236 #ifdef FIOSETOWN 237 case FIOSETOWN: 238 #endif 239 #ifdef SIOCSPGRP 240 case SIOCSPGRP: 241 #endif 242 tprints(", "); 243 printnum_int(tcp, arg, "%d"); 244 break; 245 246 #ifdef FIOGETOWN 247 case FIOGETOWN: 248 #endif 249 #ifdef SIOCGPGRP 250 case SIOCGPGRP: 251 #endif 252 #ifdef SIOCATMARK 253 case SIOCATMARK: 254 #endif 255 if (entering(tcp)) 256 return 0; 257 tprints(", "); 258 printnum_int(tcp, arg, "%d"); 259 break; 260 261 #ifdef SIOCBRADDIF 262 case SIOCBRADDIF: 263 #endif 264 #ifdef SIOCBRDELIF 265 case SIOCBRDELIF: 266 #endif 267 /* no arguments */ 268 break; 269 270 case SIOCSIFNAME: 271 case SIOCSIFADDR: 272 case SIOCSIFDSTADDR: 273 case SIOCSIFBRDADDR: 274 case SIOCSIFNETMASK: 275 case SIOCSIFFLAGS: 276 case SIOCSIFMETRIC: 277 case SIOCSIFMTU: 278 case SIOCSIFSLAVE: 279 case SIOCSIFHWADDR: 280 case SIOCSIFTXQLEN: 281 case SIOCSIFMAP: 282 tprints(", "); 283 if (umove_or_printaddr(tcp, arg, &ifr)) 284 break; 285 286 tprints("{ifr_name="); 287 print_ifname(ifr.ifr_name); 288 tprints(", "); 289 if (code == SIOCSIFNAME) { 290 tprints("ifr_newname="); 291 print_ifname(ifr.ifr_newname); 292 } else { 293 print_ifreq(tcp, code, arg, &ifr); 294 } 295 tprints("}"); 296 break; 297 298 case SIOCGIFNAME: 299 case SIOCGIFINDEX: 300 case SIOCGIFADDR: 301 case SIOCGIFDSTADDR: 302 case SIOCGIFBRDADDR: 303 case SIOCGIFNETMASK: 304 case SIOCGIFFLAGS: 305 case SIOCGIFMETRIC: 306 case SIOCGIFMTU: 307 case SIOCGIFSLAVE: 308 case SIOCGIFHWADDR: 309 case SIOCGIFTXQLEN: 310 case SIOCGIFMAP: 311 if (entering(tcp)) { 312 tprints(", "); 313 if (umove_or_printaddr(tcp, arg, &ifr)) 314 break; 315 316 if (SIOCGIFNAME == code) { 317 tprintf("{ifr_index=%d", ifr.ifr_ifindex); 318 } else { 319 tprints("{ifr_name="); 320 print_ifname(ifr.ifr_name); 321 } 322 return 1; 323 } else { 324 if (syserror(tcp)) { 325 tprints("}"); 326 break; 327 } 328 329 tprints(", "); 330 if (umove(tcp, arg, &ifr) < 0) { 331 tprints("???}"); 332 break; 333 } 334 335 if (SIOCGIFNAME == code) { 336 tprints("ifr_name="); 337 print_ifname(ifr.ifr_name); 338 } else { 339 print_ifreq(tcp, code, arg, &ifr); 340 } 341 tprints("}"); 342 break; 343 } 344 345 default: 346 return RVAL_DECODED; 347 } 348 349 return RVAL_DECODED | 1; 350 } 351