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