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 *	$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
50static 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
70static void
71print_addr(tcp, addr, ifr)
72struct tcb *tcp;
73long addr;
74struct 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
84int
85sock_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