Home | History | Annotate | Download | only in strace
      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