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 
     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