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 * $Id$ 28 */ 29 30 #include "defs.h" 31 32 #ifdef LINUX 33 #include <sys/socket.h> 34 #include <linux/sockios.h> 35 #else 36 #include <sys/socket.h> 37 #include <sys/sockio.h> 38 #endif 39 #include <arpa/inet.h> 40 41 #if defined (ALPHA) || defined(SH) || defined(SH64) 42 #ifdef HAVE_SYS_IOCTL_H 43 #include <sys/ioctl.h> 44 #elif defined(HAVE_IOCTLS_H) 45 #include <ioctls.h> 46 #endif 47 #endif 48 #include <net/if.h> 49 50 static const struct xlat iffflags[] = { 51 { IFF_UP, "IFF_UP" }, 52 { IFF_BROADCAST, "IFF_BROADCAST" }, 53 { IFF_DEBUG, "IFF_DEBUG" }, 54 { IFF_LOOPBACK, "IFF_LOOPBACK" }, 55 { IFF_POINTOPOINT, "IFF_POINTOPOINT" }, 56 { IFF_NOTRAILERS, "IFF_NOTRAILERS" }, 57 { IFF_RUNNING, "IFF_RUNNING" }, 58 { IFF_NOARP, "IFF_NOARP" }, 59 { IFF_PROMISC, "IFF_PROMISC" }, 60 { IFF_ALLMULTI, "IFF_ALLMULTI" }, 61 { IFF_MASTER, "IFF_MASTER" }, 62 { IFF_SLAVE, "IFF_SLAVE" }, 63 { IFF_MULTICAST, "IFF_MULTICAST" }, 64 { IFF_PORTSEL, "IFF_PORTSEL" }, 65 { IFF_AUTOMEDIA, "IFF_AUTOMEDIA" }, 66 { 0, NULL } 67 }; 68 69 70 static void 71 print_addr(tcp, addr, ifr) 72 struct tcb *tcp; 73 long addr; 74 struct ifreq *ifr; 75 { 76 if (ifr->ifr_addr.sa_family == AF_INET) { 77 struct sockaddr_in *sinp; 78 sinp = (struct sockaddr_in *) &ifr->ifr_addr; 79 tprintf("inet_addr(\"%s\")", inet_ntoa(sinp->sin_addr)); 80 } else 81 printstr(tcp, addr, sizeof(ifr->ifr_addr.sa_data)); 82 } 83 84 int 85 sock_ioctl(struct tcb *tcp, long code, long arg) 86 { 87 struct ifreq ifr; 88 struct ifconf ifc; 89 const char *str = NULL; 90 unsigned char *bytes; 91 92 if (entering(tcp)) { 93 if (code == SIOCGIFCONF) { 94 if (umove(tcp, tcp->u_arg[2], &ifc) >= 0 95 && ifc.ifc_buf == NULL) 96 tprintf(", {%d -> ", ifc.ifc_len); 97 else 98 tprintf(", {"); 99 } 100 return 0; 101 } 102 103 switch (code) { 104 #ifdef SIOCSHIWAT 105 case SIOCSHIWAT: 106 #endif 107 #ifdef SIOCGHIWAT 108 case SIOCGHIWAT: 109 #endif 110 #ifdef SIOCSLOWAT 111 case SIOCSLOWAT: 112 #endif 113 #ifdef SIOCGLOWAT 114 case SIOCGLOWAT: 115 #endif 116 #ifdef FIOSETOWN 117 case FIOSETOWN: 118 #endif 119 #ifdef FIOGETOWN 120 case FIOGETOWN: 121 #endif 122 #ifdef SIOCSPGRP 123 case SIOCSPGRP: 124 #endif 125 #ifdef SIOCGPGRP 126 case SIOCGPGRP: 127 #endif 128 #ifdef SIOCATMARK 129 case SIOCATMARK: 130 #endif 131 printnum(tcp, arg, ", %#d"); 132 return 1; 133 #ifdef LINUX 134 case SIOCGIFNAME: 135 case SIOCSIFNAME: 136 case SIOCGIFINDEX: 137 case SIOCGIFADDR: 138 case SIOCSIFADDR: 139 case SIOCGIFDSTADDR: 140 case SIOCSIFDSTADDR: 141 case SIOCGIFBRDADDR: 142 case SIOCSIFBRDADDR: 143 case SIOCGIFNETMASK: 144 case SIOCSIFNETMASK: 145 case SIOCGIFFLAGS: 146 case SIOCSIFFLAGS: 147 case SIOCGIFMETRIC: 148 case SIOCSIFMETRIC: 149 case SIOCGIFMTU: 150 case SIOCSIFMTU: 151 case SIOCGIFSLAVE: 152 case SIOCSIFSLAVE: 153 case SIOCGIFHWADDR: 154 case SIOCSIFHWADDR: 155 case SIOCGIFTXQLEN: 156 case SIOCSIFTXQLEN: 157 case SIOCGIFMAP: 158 case SIOCSIFMAP: 159 if (umove(tcp, tcp->u_arg[2], &ifr) < 0) 160 tprintf(", %#lx", tcp->u_arg[2]); 161 else if (syserror(tcp)) { 162 if (code == SIOCGIFNAME || code == SIOCSIFNAME) 163 tprintf(", {ifr_index=%d, ifr_name=???}", ifr.ifr_ifindex); 164 else 165 tprintf(", {ifr_name=\"%s\", ???}", ifr.ifr_name); 166 } else if (code == SIOCGIFNAME || code == SIOCSIFNAME) 167 tprintf(", {ifr_index=%d, ifr_name=\"%s\"}", 168 ifr.ifr_ifindex, ifr.ifr_name); 169 else { 170 tprintf(", {ifr_name=\"%s\", ", ifr.ifr_name); 171 switch (code) { 172 case SIOCGIFINDEX: 173 tprintf("ifr_index=%d", ifr.ifr_ifindex); 174 break; 175 case SIOCGIFADDR: 176 case SIOCSIFADDR: 177 str = "ifr_addr"; 178 case SIOCGIFDSTADDR: 179 case SIOCSIFDSTADDR: 180 if (!str) 181 str = "ifr_dstaddr"; 182 case SIOCGIFBRDADDR: 183 case SIOCSIFBRDADDR: 184 if (!str) 185 str = "ifr_broadaddr"; 186 case SIOCGIFNETMASK: 187 case SIOCSIFNETMASK: 188 if (!str) 189 str = "ifr_netmask"; 190 tprintf("%s={", str); 191 printxval(addrfams, 192 ifr.ifr_addr.sa_family, 193 "AF_???"); 194 tprintf(", "); 195 print_addr(tcp, ((long) tcp->u_arg[2] 196 + offsetof (struct ifreq, 197 ifr_addr.sa_data)), 198 &ifr); 199 tprintf("}"); 200 break; 201 case SIOCGIFHWADDR: 202 case SIOCSIFHWADDR: 203 /* XXX Are there other hardware addresses 204 than 6-byte MACs? */ 205 bytes = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 206 tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x", 207 bytes[0], bytes[1], bytes[2], 208 bytes[3], bytes[4], bytes[5]); 209 break; 210 case SIOCGIFFLAGS: 211 case SIOCSIFFLAGS: 212 tprintf("ifr_flags="); 213 printflags(iffflags, ifr.ifr_flags, "IFF_???"); 214 break; 215 case SIOCGIFMETRIC: 216 case SIOCSIFMETRIC: 217 tprintf("ifr_metric=%d", ifr.ifr_metric); 218 break; 219 case SIOCGIFMTU: 220 case SIOCSIFMTU: 221 tprintf("ifr_mtu=%d", ifr.ifr_mtu); 222 break; 223 case SIOCGIFSLAVE: 224 case SIOCSIFSLAVE: 225 tprintf("ifr_slave=\"%s\"", ifr.ifr_slave); 226 break; 227 case SIOCGIFTXQLEN: 228 case SIOCSIFTXQLEN: 229 tprintf("ifr_qlen=%d", ifr.ifr_qlen); 230 break; 231 case SIOCGIFMAP: 232 case SIOCSIFMAP: 233 tprintf("ifr_map={mem_start=%#lx, " 234 "mem_end=%#lx, base_addr=%#x, " 235 "irq=%u, dma=%u, port=%u}", 236 ifr.ifr_map.mem_start, 237 ifr.ifr_map.mem_end, 238 (unsigned) ifr.ifr_map.base_addr, 239 (unsigned) ifr.ifr_map.irq, 240 (unsigned) ifr.ifr_map.dma, 241 (unsigned) ifr.ifr_map.port); 242 break; 243 } 244 tprintf("}"); 245 } 246 return 1; 247 case SIOCGIFCONF: 248 if (umove(tcp, tcp->u_arg[2], &ifc) < 0) { 249 tprintf("???}"); 250 return 1; 251 } 252 tprintf("%d, ", ifc.ifc_len); 253 if (syserror(tcp)) { 254 tprintf("%lx", (unsigned long) ifc.ifc_buf); 255 } else if (ifc.ifc_buf == NULL) { 256 tprintf("NULL"); 257 } else { 258 int i; 259 unsigned nifra = ifc.ifc_len / sizeof(struct ifreq); 260 struct ifreq ifra[nifra]; 261 262 if (umoven(tcp, (unsigned long) ifc.ifc_buf, 263 sizeof(ifra), (char *) ifra) < 0) { 264 tprintf("%lx}", (unsigned long) ifc.ifc_buf); 265 return 1; 266 } 267 tprintf("{"); 268 for (i = 0; i < nifra; ++i ) { 269 if (i > 0) 270 tprintf(", "); 271 tprintf("{\"%s\", {", 272 ifra[i].ifr_name); 273 if (verbose(tcp)) { 274 printxval(addrfams, 275 ifra[i].ifr_addr.sa_family, 276 "AF_???"); 277 tprintf(", "); 278 print_addr(tcp, ((long) tcp->u_arg[2] 279 + offsetof (struct ifreq, 280 ifr_addr.sa_data) 281 + ((char *) &ifra[i] 282 - (char *) &ifra[0])), 283 &ifra[i]); 284 } else 285 tprintf("..."); 286 tprintf("}}"); 287 } 288 tprintf("}"); 289 } 290 tprintf("}"); 291 return 1; 292 #endif 293 default: 294 return 0; 295 } 296 } 297