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