xref: /minix3/minix/net/lwip/ifconf.c (revision ef8d499e2d2af900e9b2ab297171d7b088652482)
1*ef8d499eSDavid van Moolenbroek /* LWIP service - ifconf.c - interface configuration */
2*ef8d499eSDavid van Moolenbroek 
3*ef8d499eSDavid van Moolenbroek #include "lwip.h"
4*ef8d499eSDavid van Moolenbroek #include "ifaddr.h"
5*ef8d499eSDavid van Moolenbroek #include "lldata.h"
6*ef8d499eSDavid van Moolenbroek 
7*ef8d499eSDavid van Moolenbroek #include <net/if_media.h>
8*ef8d499eSDavid van Moolenbroek #include <minix/if.h>
9*ef8d499eSDavid van Moolenbroek 
10*ef8d499eSDavid van Moolenbroek #define LOOPBACK_IFNAME		"lo0"	/* name of the loopback interface */
11*ef8d499eSDavid van Moolenbroek 
12*ef8d499eSDavid van Moolenbroek /*
13*ef8d499eSDavid van Moolenbroek  * Initialize the first loopback device, which is present by default.
14*ef8d499eSDavid van Moolenbroek  */
15*ef8d499eSDavid van Moolenbroek void
ifconf_init(void)16*ef8d499eSDavid van Moolenbroek ifconf_init(void)
17*ef8d499eSDavid van Moolenbroek {
18*ef8d499eSDavid van Moolenbroek 	const struct sockaddr_in addr = {
19*ef8d499eSDavid van Moolenbroek 	    .sin_family = AF_INET,
20*ef8d499eSDavid van Moolenbroek 	    .sin_addr = { htonl(INADDR_LOOPBACK) }
21*ef8d499eSDavid van Moolenbroek 	};
22*ef8d499eSDavid van Moolenbroek 	struct sockaddr_in6 ll_addr6 = {
23*ef8d499eSDavid van Moolenbroek 	    .sin6_family = AF_INET6,
24*ef8d499eSDavid van Moolenbroek 	};
25*ef8d499eSDavid van Moolenbroek 	const struct sockaddr_in6 lo_addr6 = {
26*ef8d499eSDavid van Moolenbroek 	    .sin6_family = AF_INET6,
27*ef8d499eSDavid van Moolenbroek 	    .sin6_addr = IN6ADDR_LOOPBACK_INIT
28*ef8d499eSDavid van Moolenbroek 	};
29*ef8d499eSDavid van Moolenbroek 	const struct in6_addrlifetime lifetime = {
30*ef8d499eSDavid van Moolenbroek 	    .ia6t_vltime = ND6_INFINITE_LIFETIME,
31*ef8d499eSDavid van Moolenbroek 	    .ia6t_pltime = ND6_INFINITE_LIFETIME
32*ef8d499eSDavid van Moolenbroek 	};
33*ef8d499eSDavid van Moolenbroek 	struct sockaddr_in6 mask6;
34*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
35*ef8d499eSDavid van Moolenbroek 	socklen_t addr_len;
36*ef8d499eSDavid van Moolenbroek 	int r;
37*ef8d499eSDavid van Moolenbroek 
38*ef8d499eSDavid van Moolenbroek 	if ((r = ifdev_create(LOOPBACK_IFNAME)) != OK)
39*ef8d499eSDavid van Moolenbroek 		panic("unable to create loopback interface: %d", r);
40*ef8d499eSDavid van Moolenbroek 
41*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(LOOPBACK_IFNAME)) == NULL)
42*ef8d499eSDavid van Moolenbroek 		panic("unable to find loopback interface");
43*ef8d499eSDavid van Moolenbroek 
44*ef8d499eSDavid van Moolenbroek 	if ((r = ifaddr_v4_add(ifdev, &addr, NULL, NULL, NULL, 0)) != OK)
45*ef8d499eSDavid van Moolenbroek 		panic("unable to set IPv4 address on loopback interface: %d",
46*ef8d499eSDavid van Moolenbroek 		    r);
47*ef8d499eSDavid van Moolenbroek 
48*ef8d499eSDavid van Moolenbroek 	addr_len = sizeof(mask6);
49*ef8d499eSDavid van Moolenbroek 	addr_put_netmask((struct sockaddr *)&mask6, &addr_len, IPADDR_TYPE_V6,
50*ef8d499eSDavid van Moolenbroek 	    64 /*prefix*/);
51*ef8d499eSDavid van Moolenbroek 
52*ef8d499eSDavid van Moolenbroek 	ll_addr6.sin6_addr.s6_addr[0] = 0xfe;
53*ef8d499eSDavid van Moolenbroek 	ll_addr6.sin6_addr.s6_addr[1] = 0x80;
54*ef8d499eSDavid van Moolenbroek 	ll_addr6.sin6_addr.s6_addr[15] = ifdev_get_index(ifdev);
55*ef8d499eSDavid van Moolenbroek 
56*ef8d499eSDavid van Moolenbroek 	if ((r = ifaddr_v6_add(ifdev, &ll_addr6, &mask6, NULL, 0,
57*ef8d499eSDavid van Moolenbroek 	    &lifetime)) != OK)
58*ef8d499eSDavid van Moolenbroek 		panic("unable to set IPv6 address on loopback interface: %d",
59*ef8d499eSDavid van Moolenbroek 		    r);
60*ef8d499eSDavid van Moolenbroek 
61*ef8d499eSDavid van Moolenbroek 	addr_len = sizeof(mask6);
62*ef8d499eSDavid van Moolenbroek 	addr_put_netmask((struct sockaddr *)&mask6, &addr_len, IPADDR_TYPE_V6,
63*ef8d499eSDavid van Moolenbroek 	    128 /*prefix*/);
64*ef8d499eSDavid van Moolenbroek 
65*ef8d499eSDavid van Moolenbroek 	if ((r = ifaddr_v6_add(ifdev, &lo_addr6, &mask6, NULL, 0,
66*ef8d499eSDavid van Moolenbroek 	    &lifetime)) != OK)
67*ef8d499eSDavid van Moolenbroek 		panic("unable to set IPv6 address on loopback interface: %d",
68*ef8d499eSDavid van Moolenbroek 		    r);
69*ef8d499eSDavid van Moolenbroek 
70*ef8d499eSDavid van Moolenbroek 	if ((r = ifdev_set_ifflags(ifdev, IFF_UP)) != OK)
71*ef8d499eSDavid van Moolenbroek 		panic("unable to bring up loopback interface");
72*ef8d499eSDavid van Moolenbroek }
73*ef8d499eSDavid van Moolenbroek 
74*ef8d499eSDavid van Moolenbroek /*
75*ef8d499eSDavid van Moolenbroek  * Process an address family independent IOCTL request with an "ifreq"
76*ef8d499eSDavid van Moolenbroek  * structure.
77*ef8d499eSDavid van Moolenbroek  */
78*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_ifreq(unsigned long request,const struct sockdriver_data * data)79*ef8d499eSDavid van Moolenbroek ifconf_ioctl_ifreq(unsigned long request, const struct sockdriver_data * data)
80*ef8d499eSDavid van Moolenbroek {
81*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
82*ef8d499eSDavid van Moolenbroek 	struct ifreq ifr;
83*ef8d499eSDavid van Moolenbroek 	int r;
84*ef8d499eSDavid van Moolenbroek 
85*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifr, sizeof(ifr))) != OK)
86*ef8d499eSDavid van Moolenbroek 		return r;
87*ef8d499eSDavid van Moolenbroek 
88*ef8d499eSDavid van Moolenbroek 	if (request != SIOCIFCREATE) {
89*ef8d499eSDavid van Moolenbroek 		ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
90*ef8d499eSDavid van Moolenbroek 
91*ef8d499eSDavid van Moolenbroek 		if ((ifdev = ifdev_find_by_name(ifr.ifr_name)) == NULL)
92*ef8d499eSDavid van Moolenbroek 			return ENXIO;
93*ef8d499eSDavid van Moolenbroek 	} else
94*ef8d499eSDavid van Moolenbroek 		ifdev = NULL;
95*ef8d499eSDavid van Moolenbroek 
96*ef8d499eSDavid van Moolenbroek 	switch (request) {
97*ef8d499eSDavid van Moolenbroek 	case SIOCGIFFLAGS:
98*ef8d499eSDavid van Moolenbroek 		ifr.ifr_flags = ifdev_get_ifflags(ifdev);
99*ef8d499eSDavid van Moolenbroek 
100*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
101*ef8d499eSDavid van Moolenbroek 
102*ef8d499eSDavid van Moolenbroek 	case SIOCSIFFLAGS:
103*ef8d499eSDavid van Moolenbroek 		/*
104*ef8d499eSDavid van Moolenbroek 		 * Unfortunately, ifr_flags is a signed integer and the sign
105*ef8d499eSDavid van Moolenbroek 		 * bit is in fact used as a flag, so without explicit casting
106*ef8d499eSDavid van Moolenbroek 		 * we end up setting all upper bits of the (full) integer.  If
107*ef8d499eSDavid van Moolenbroek 		 * NetBSD ever extends the field, this assert should trigger..
108*ef8d499eSDavid van Moolenbroek 		 */
109*ef8d499eSDavid van Moolenbroek 		assert(sizeof(ifr.ifr_flags) == sizeof(short));
110*ef8d499eSDavid van Moolenbroek 
111*ef8d499eSDavid van Moolenbroek 		return ifdev_set_ifflags(ifdev, (unsigned short)ifr.ifr_flags);
112*ef8d499eSDavid van Moolenbroek 
113*ef8d499eSDavid van Moolenbroek 	case SIOCGIFMETRIC:
114*ef8d499eSDavid van Moolenbroek 		ifr.ifr_metric = ifdev_get_metric(ifdev);
115*ef8d499eSDavid van Moolenbroek 
116*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
117*ef8d499eSDavid van Moolenbroek 
118*ef8d499eSDavid van Moolenbroek 	case SIOCSIFMETRIC:
119*ef8d499eSDavid van Moolenbroek 		/* The metric is not used within the operating system. */
120*ef8d499eSDavid van Moolenbroek 		ifdev_set_metric(ifdev, ifr.ifr_metric);
121*ef8d499eSDavid van Moolenbroek 
122*ef8d499eSDavid van Moolenbroek 		return OK;
123*ef8d499eSDavid van Moolenbroek 
124*ef8d499eSDavid van Moolenbroek 	case SIOCSIFMEDIA:
125*ef8d499eSDavid van Moolenbroek 		return ifdev_set_ifmedia(ifdev, ifr.ifr_media);
126*ef8d499eSDavid van Moolenbroek 
127*ef8d499eSDavid van Moolenbroek 	case SIOCGIFMTU:
128*ef8d499eSDavid van Moolenbroek 		ifr.ifr_mtu = ifdev_get_mtu(ifdev);
129*ef8d499eSDavid van Moolenbroek 
130*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
131*ef8d499eSDavid van Moolenbroek 
132*ef8d499eSDavid van Moolenbroek 	case SIOCSIFMTU:
133*ef8d499eSDavid van Moolenbroek 		return ifdev_set_mtu(ifdev, ifr.ifr_mtu);
134*ef8d499eSDavid van Moolenbroek 
135*ef8d499eSDavid van Moolenbroek 	case SIOCIFCREATE:
136*ef8d499eSDavid van Moolenbroek 		if (memchr(ifr.ifr_name, '\0', sizeof(ifr.ifr_name)) == NULL)
137*ef8d499eSDavid van Moolenbroek 			return EINVAL;
138*ef8d499eSDavid van Moolenbroek 
139*ef8d499eSDavid van Moolenbroek 		return ifdev_create(ifr.ifr_name);
140*ef8d499eSDavid van Moolenbroek 
141*ef8d499eSDavid van Moolenbroek 	case SIOCIFDESTROY:
142*ef8d499eSDavid van Moolenbroek 		return ifdev_destroy(ifdev);
143*ef8d499eSDavid van Moolenbroek 
144*ef8d499eSDavid van Moolenbroek 	case SIOCGIFDLT:
145*ef8d499eSDavid van Moolenbroek 		ifr.ifr_dlt = ifdev_get_dlt(ifdev);
146*ef8d499eSDavid van Moolenbroek 
147*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
148*ef8d499eSDavid van Moolenbroek 
149*ef8d499eSDavid van Moolenbroek 	case SIOCGIFINDEX:
150*ef8d499eSDavid van Moolenbroek 		ifr.ifr_index = ifdev_get_index(ifdev);
151*ef8d499eSDavid van Moolenbroek 
152*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
153*ef8d499eSDavid van Moolenbroek 
154*ef8d499eSDavid van Moolenbroek 	default:
155*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
156*ef8d499eSDavid van Moolenbroek 	}
157*ef8d499eSDavid van Moolenbroek }
158*ef8d499eSDavid van Moolenbroek 
159*ef8d499eSDavid van Moolenbroek /*
160*ef8d499eSDavid van Moolenbroek  * Process an address family independent IOCTL request with an "ifcapreq"
161*ef8d499eSDavid van Moolenbroek  * structure.
162*ef8d499eSDavid van Moolenbroek  */
163*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_ifcap(unsigned long request,const struct sockdriver_data * data)164*ef8d499eSDavid van Moolenbroek ifconf_ioctl_ifcap(unsigned long request,
165*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
166*ef8d499eSDavid van Moolenbroek {
167*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
168*ef8d499eSDavid van Moolenbroek 	struct ifcapreq ifcr;
169*ef8d499eSDavid van Moolenbroek 	int r;
170*ef8d499eSDavid van Moolenbroek 
171*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifcr, sizeof(ifcr))) != OK)
172*ef8d499eSDavid van Moolenbroek 		return r;
173*ef8d499eSDavid van Moolenbroek 
174*ef8d499eSDavid van Moolenbroek 	ifcr.ifcr_name[sizeof(ifcr.ifcr_name) - 1] = '\0';
175*ef8d499eSDavid van Moolenbroek 
176*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(ifcr.ifcr_name)) == NULL)
177*ef8d499eSDavid van Moolenbroek 		return ENXIO;
178*ef8d499eSDavid van Moolenbroek 
179*ef8d499eSDavid van Moolenbroek 	switch (request) {
180*ef8d499eSDavid van Moolenbroek 	case SIOCSIFCAP:
181*ef8d499eSDavid van Moolenbroek 		return ifdev_set_ifcap(ifdev, ifcr.ifcr_capenable);
182*ef8d499eSDavid van Moolenbroek 
183*ef8d499eSDavid van Moolenbroek 	case SIOCGIFCAP:
184*ef8d499eSDavid van Moolenbroek 		ifdev_get_ifcap(ifdev, &ifcr.ifcr_capabilities,
185*ef8d499eSDavid van Moolenbroek 		    &ifcr.ifcr_capenable);
186*ef8d499eSDavid van Moolenbroek 
187*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifcr, sizeof(ifcr));
188*ef8d499eSDavid van Moolenbroek 
189*ef8d499eSDavid van Moolenbroek 	default:
190*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
191*ef8d499eSDavid van Moolenbroek 	}
192*ef8d499eSDavid van Moolenbroek }
193*ef8d499eSDavid van Moolenbroek 
194*ef8d499eSDavid van Moolenbroek /*
195*ef8d499eSDavid van Moolenbroek  * Process an address family independent IOCTL request with an "ifmediareq"
196*ef8d499eSDavid van Moolenbroek  * structure.
197*ef8d499eSDavid van Moolenbroek  */
198*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_ifmedia(unsigned long request,const struct sockdriver_data * data)199*ef8d499eSDavid van Moolenbroek ifconf_ioctl_ifmedia(unsigned long request,
200*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
201*ef8d499eSDavid van Moolenbroek {
202*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
203*ef8d499eSDavid van Moolenbroek 	struct ifmediareq ifm;
204*ef8d499eSDavid van Moolenbroek 	int r;
205*ef8d499eSDavid van Moolenbroek 
206*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifm, sizeof(ifm))) != OK)
207*ef8d499eSDavid van Moolenbroek 		return r;
208*ef8d499eSDavid van Moolenbroek 
209*ef8d499eSDavid van Moolenbroek 	ifm.ifm_name[sizeof(ifm.ifm_name) - 1] = '\0';
210*ef8d499eSDavid van Moolenbroek 
211*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(ifm.ifm_name)) == NULL)
212*ef8d499eSDavid van Moolenbroek 		return ENXIO;
213*ef8d499eSDavid van Moolenbroek 
214*ef8d499eSDavid van Moolenbroek 	switch (request) {
215*ef8d499eSDavid van Moolenbroek 	case MINIX_SIOCGIFMEDIA:
216*ef8d499eSDavid van Moolenbroek 		if ((r = ifdev_get_ifmedia(ifdev, &ifm.ifm_current,
217*ef8d499eSDavid van Moolenbroek 		    &ifm.ifm_active)) != OK)
218*ef8d499eSDavid van Moolenbroek 			return r;
219*ef8d499eSDavid van Moolenbroek 		ifm.ifm_mask = 0;
220*ef8d499eSDavid van Moolenbroek 
221*ef8d499eSDavid van Moolenbroek 		switch (ifdev_get_link(ifdev)) {
222*ef8d499eSDavid van Moolenbroek 		case LINK_STATE_UP:
223*ef8d499eSDavid van Moolenbroek 			ifm.ifm_status = IFM_AVALID | IFM_ACTIVE;
224*ef8d499eSDavid van Moolenbroek 			break;
225*ef8d499eSDavid van Moolenbroek 		case LINK_STATE_DOWN:
226*ef8d499eSDavid van Moolenbroek 			ifm.ifm_status = IFM_AVALID;
227*ef8d499eSDavid van Moolenbroek 			break;
228*ef8d499eSDavid van Moolenbroek 		default:
229*ef8d499eSDavid van Moolenbroek 			ifm.ifm_status = 0;
230*ef8d499eSDavid van Moolenbroek 			break;
231*ef8d499eSDavid van Moolenbroek 		}
232*ef8d499eSDavid van Moolenbroek 
233*ef8d499eSDavid van Moolenbroek 		/*
234*ef8d499eSDavid van Moolenbroek 		 * TODO: support for the list of supported media types.  This
235*ef8d499eSDavid van Moolenbroek 		 * one is not easy, because we cannot simply suspend the IOCTL
236*ef8d499eSDavid van Moolenbroek 		 * and query the driver.  For now, return only entry (which is
237*ef8d499eSDavid van Moolenbroek 		 * the minimum for ifconfig(8) not to complain), namely the
238*ef8d499eSDavid van Moolenbroek 		 * currently selected one.
239*ef8d499eSDavid van Moolenbroek 		 */
240*ef8d499eSDavid van Moolenbroek 		if (ifm.ifm_ulist != NULL) {
241*ef8d499eSDavid van Moolenbroek 			if (ifm.ifm_count < 1)
242*ef8d499eSDavid van Moolenbroek 				return ENOMEM;
243*ef8d499eSDavid van Moolenbroek 
244*ef8d499eSDavid van Moolenbroek 			/*
245*ef8d499eSDavid van Moolenbroek 			 * Copy out the 'list', which consists of one entry.
246*ef8d499eSDavid van Moolenbroek 			 * If we were to produce multiple entries, we would
247*ef8d499eSDavid van Moolenbroek 			 * have to check against the MINIX_IF_MAXMEDIA limit.
248*ef8d499eSDavid van Moolenbroek 			 */
249*ef8d499eSDavid van Moolenbroek 			if ((r = sockdriver_copyout(data,
250*ef8d499eSDavid van Moolenbroek 			    offsetof(struct minix_ifmediareq, mifm_list),
251*ef8d499eSDavid van Moolenbroek 			    &ifm.ifm_current, sizeof(ifm.ifm_current))) != OK)
252*ef8d499eSDavid van Moolenbroek 				return r;
253*ef8d499eSDavid van Moolenbroek 		}
254*ef8d499eSDavid van Moolenbroek 		ifm.ifm_count = 1;
255*ef8d499eSDavid van Moolenbroek 
256*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifm, sizeof(ifm));
257*ef8d499eSDavid van Moolenbroek 
258*ef8d499eSDavid van Moolenbroek 	default:
259*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
260*ef8d499eSDavid van Moolenbroek 	}
261*ef8d499eSDavid van Moolenbroek }
262*ef8d499eSDavid van Moolenbroek 
263*ef8d499eSDavid van Moolenbroek /*
264*ef8d499eSDavid van Moolenbroek  * Process an address family independent IOCTL request with an "if_clonereq"
265*ef8d499eSDavid van Moolenbroek  * structure.
266*ef8d499eSDavid van Moolenbroek  */
267*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_ifclone(unsigned long request,const struct sockdriver_data * data)268*ef8d499eSDavid van Moolenbroek ifconf_ioctl_ifclone(unsigned long request,
269*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
270*ef8d499eSDavid van Moolenbroek {
271*ef8d499eSDavid van Moolenbroek 	struct if_clonereq ifcr;
272*ef8d499eSDavid van Moolenbroek 	const char *ptr;
273*ef8d499eSDavid van Moolenbroek 	char name[IFNAMSIZ];
274*ef8d499eSDavid van Moolenbroek 	size_t off;
275*ef8d499eSDavid van Moolenbroek 	unsigned int num;
276*ef8d499eSDavid van Moolenbroek 	int r;
277*ef8d499eSDavid van Moolenbroek 
278*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifcr, sizeof(ifcr))) != OK)
279*ef8d499eSDavid van Moolenbroek 		return r;
280*ef8d499eSDavid van Moolenbroek 
281*ef8d499eSDavid van Moolenbroek 	if (ifcr.ifcr_count < 0)
282*ef8d499eSDavid van Moolenbroek 		return EINVAL;
283*ef8d499eSDavid van Moolenbroek 
284*ef8d499eSDavid van Moolenbroek 	off = offsetof(struct minix_if_clonereq, mifcr_buffer);
285*ef8d499eSDavid van Moolenbroek 
286*ef8d499eSDavid van Moolenbroek 	for (num = 0; (ptr = ifdev_enum_vtypes(num)) != NULL; num++) {
287*ef8d499eSDavid van Moolenbroek 		/* Prevent overflow in case we ever have over 128 vtypes.. */
288*ef8d499eSDavid van Moolenbroek 		if (num == MINIX_IF_MAXCLONERS)
289*ef8d499eSDavid van Moolenbroek 			break;
290*ef8d499eSDavid van Moolenbroek 
291*ef8d499eSDavid van Moolenbroek 		if (ifcr.ifcr_buffer == NULL ||
292*ef8d499eSDavid van Moolenbroek 		    num >= (unsigned int)ifcr.ifcr_count)
293*ef8d499eSDavid van Moolenbroek 			continue;
294*ef8d499eSDavid van Moolenbroek 
295*ef8d499eSDavid van Moolenbroek 		memset(name, 0, sizeof(name));
296*ef8d499eSDavid van Moolenbroek 		strlcpy(name, ptr, sizeof(name));
297*ef8d499eSDavid van Moolenbroek 
298*ef8d499eSDavid van Moolenbroek 		if ((r = sockdriver_copyout(data, off, name,
299*ef8d499eSDavid van Moolenbroek 		    sizeof(name))) != OK)
300*ef8d499eSDavid van Moolenbroek 			return r;
301*ef8d499eSDavid van Moolenbroek 
302*ef8d499eSDavid van Moolenbroek 		off += sizeof(name);
303*ef8d499eSDavid van Moolenbroek 	}
304*ef8d499eSDavid van Moolenbroek 
305*ef8d499eSDavid van Moolenbroek 	ifcr.ifcr_total = num;
306*ef8d499eSDavid van Moolenbroek 
307*ef8d499eSDavid van Moolenbroek 	return sockdriver_copyout(data, 0, &ifcr, sizeof(ifcr));
308*ef8d499eSDavid van Moolenbroek }
309*ef8d499eSDavid van Moolenbroek 
310*ef8d499eSDavid van Moolenbroek /*
311*ef8d499eSDavid van Moolenbroek  * Process an address family independent IOCTL request with an "if_addrprefreq"
312*ef8d499eSDavid van Moolenbroek  * structure.
313*ef8d499eSDavid van Moolenbroek  */
314*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_ifaddrpref(unsigned long request,const struct sockdriver_data * data)315*ef8d499eSDavid van Moolenbroek ifconf_ioctl_ifaddrpref(unsigned long request,
316*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
317*ef8d499eSDavid van Moolenbroek {
318*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
319*ef8d499eSDavid van Moolenbroek 	struct if_addrprefreq ifap;
320*ef8d499eSDavid van Moolenbroek 	int r;
321*ef8d499eSDavid van Moolenbroek 
322*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifap, sizeof(ifap))) != OK)
323*ef8d499eSDavid van Moolenbroek 		return r;
324*ef8d499eSDavid van Moolenbroek 
325*ef8d499eSDavid van Moolenbroek 	ifap.ifap_name[sizeof(ifap.ifap_name) - 1] = '\0';
326*ef8d499eSDavid van Moolenbroek 
327*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(ifap.ifap_name)) == NULL)
328*ef8d499eSDavid van Moolenbroek 		return ENXIO;
329*ef8d499eSDavid van Moolenbroek 
330*ef8d499eSDavid van Moolenbroek 	/*
331*ef8d499eSDavid van Moolenbroek 	 * For now, we simply support only a preference of 0.  We do not try to
332*ef8d499eSDavid van Moolenbroek 	 * look up the given address, nor do we return the looked up address.
333*ef8d499eSDavid van Moolenbroek 	 */
334*ef8d499eSDavid van Moolenbroek 	switch (request) {
335*ef8d499eSDavid van Moolenbroek 	case SIOCSIFADDRPREF:
336*ef8d499eSDavid van Moolenbroek 		if (ifap.ifap_preference != 0)
337*ef8d499eSDavid van Moolenbroek 			return EINVAL;
338*ef8d499eSDavid van Moolenbroek 
339*ef8d499eSDavid van Moolenbroek 		return OK;
340*ef8d499eSDavid van Moolenbroek 
341*ef8d499eSDavid van Moolenbroek 	case SIOCGIFADDRPREF:
342*ef8d499eSDavid van Moolenbroek 		ifap.ifap_preference = 0;
343*ef8d499eSDavid van Moolenbroek 
344*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifap, sizeof(ifap));
345*ef8d499eSDavid van Moolenbroek 
346*ef8d499eSDavid van Moolenbroek 	default:
347*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
348*ef8d499eSDavid van Moolenbroek 	}
349*ef8d499eSDavid van Moolenbroek }
350*ef8d499eSDavid van Moolenbroek 
351*ef8d499eSDavid van Moolenbroek /*
352*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_INET with an "ifreq" structure.
353*ef8d499eSDavid van Moolenbroek  */
354*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_v4_ifreq(unsigned long request,const struct sockdriver_data * data)355*ef8d499eSDavid van Moolenbroek ifconf_ioctl_v4_ifreq(unsigned long request,
356*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
357*ef8d499eSDavid van Moolenbroek {
358*ef8d499eSDavid van Moolenbroek 	struct sockaddr_in addr, mask, bcast, dest, *sin = NULL /*gcc*/;
359*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
360*ef8d499eSDavid van Moolenbroek 	struct ifreq ifr;
361*ef8d499eSDavid van Moolenbroek 	ifaddr_v4_num_t num;
362*ef8d499eSDavid van Moolenbroek 	int r, flags;
363*ef8d499eSDavid van Moolenbroek 
364*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifr, sizeof(ifr))) != OK)
365*ef8d499eSDavid van Moolenbroek 		return r;
366*ef8d499eSDavid van Moolenbroek 
367*ef8d499eSDavid van Moolenbroek 	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
368*ef8d499eSDavid van Moolenbroek 
369*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(ifr.ifr_name)) == NULL)
370*ef8d499eSDavid van Moolenbroek 		return ENXIO;
371*ef8d499eSDavid van Moolenbroek 
372*ef8d499eSDavid van Moolenbroek 	switch (request) {
373*ef8d499eSDavid van Moolenbroek 	case SIOCGIFADDR:
374*ef8d499eSDavid van Moolenbroek 	case SIOCGIFNETMASK:
375*ef8d499eSDavid van Moolenbroek 	case SIOCGIFBRDADDR:
376*ef8d499eSDavid van Moolenbroek 	case SIOCGIFDSTADDR:
377*ef8d499eSDavid van Moolenbroek 		/* Retrieve all addresses, then copy out the desired one. */
378*ef8d499eSDavid van Moolenbroek 		switch (request) {
379*ef8d499eSDavid van Moolenbroek 		case SIOCGIFADDR:	sin = &addr; break;
380*ef8d499eSDavid van Moolenbroek 		case SIOCGIFNETMASK:	sin = &mask; break;
381*ef8d499eSDavid van Moolenbroek 		case SIOCGIFBRDADDR:	sin = &bcast; break;
382*ef8d499eSDavid van Moolenbroek 		case SIOCGIFDSTADDR:	sin = &dest; break;
383*ef8d499eSDavid van Moolenbroek 		}
384*ef8d499eSDavid van Moolenbroek 
385*ef8d499eSDavid van Moolenbroek 		sin->sin_len = 0;
386*ef8d499eSDavid van Moolenbroek 
387*ef8d499eSDavid van Moolenbroek 		if ((r = ifaddr_v4_get(ifdev, (ifaddr_v4_num_t)0, &addr, &mask,
388*ef8d499eSDavid van Moolenbroek 		    &bcast, &dest)) != OK)
389*ef8d499eSDavid van Moolenbroek 			return r;
390*ef8d499eSDavid van Moolenbroek 
391*ef8d499eSDavid van Moolenbroek 		if (sin->sin_len == 0) /* not filled in */
392*ef8d499eSDavid van Moolenbroek 			return EADDRNOTAVAIL;
393*ef8d499eSDavid van Moolenbroek 
394*ef8d499eSDavid van Moolenbroek 		memcpy(&ifr.ifr_addr, sin, sizeof(*sin));
395*ef8d499eSDavid van Moolenbroek 
396*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
397*ef8d499eSDavid van Moolenbroek 
398*ef8d499eSDavid van Moolenbroek 	case SIOCGIFAFLAG_IN:
399*ef8d499eSDavid van Moolenbroek 		if ((r = ifaddr_v4_find(ifdev,
400*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifr.ifr_addr, &num)) != OK)
401*ef8d499eSDavid van Moolenbroek 			return r;
402*ef8d499eSDavid van Moolenbroek 
403*ef8d499eSDavid van Moolenbroek 		ifr.ifr_addrflags = ifaddr_v4_get_flags(ifdev, num);
404*ef8d499eSDavid van Moolenbroek 
405*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
406*ef8d499eSDavid van Moolenbroek 
407*ef8d499eSDavid van Moolenbroek 	case SIOCSIFADDR:
408*ef8d499eSDavid van Moolenbroek 		/*
409*ef8d499eSDavid van Moolenbroek 		 * This one is slightly different from the rest, in that we
410*ef8d499eSDavid van Moolenbroek 		 * either set or update the primary address: if we set it, we
411*ef8d499eSDavid van Moolenbroek 		 * must let _add() generate a matching netmask automatically,
412*ef8d499eSDavid van Moolenbroek 		 * while if we update it, _add() would fail unless we first
413*ef8d499eSDavid van Moolenbroek 		 * delete the old entry.
414*ef8d499eSDavid van Moolenbroek 		 */
415*ef8d499eSDavid van Moolenbroek 		sin = (struct sockaddr_in *)&ifr.ifr_addr;
416*ef8d499eSDavid van Moolenbroek 
417*ef8d499eSDavid van Moolenbroek 		if ((r = ifaddr_v4_get(ifdev, (ifaddr_v4_num_t)0, &addr, &mask,
418*ef8d499eSDavid van Moolenbroek 		    &bcast, &dest)) == OK) {
419*ef8d499eSDavid van Moolenbroek 			flags = ifaddr_v4_get_flags(ifdev, (ifaddr_v4_num_t)0);
420*ef8d499eSDavid van Moolenbroek 
421*ef8d499eSDavid van Moolenbroek 			ifaddr_v4_del(ifdev, (ifaddr_v4_num_t)0);
422*ef8d499eSDavid van Moolenbroek 
423*ef8d499eSDavid van Moolenbroek 			/*
424*ef8d499eSDavid van Moolenbroek 			 * If setting the new address fails, reinstating the
425*ef8d499eSDavid van Moolenbroek 			 * old address should always work.  This is really ugly
426*ef8d499eSDavid van Moolenbroek 			 * as it generates routing socket noise, but this call
427*ef8d499eSDavid van Moolenbroek 			 * is deprecated anyway.
428*ef8d499eSDavid van Moolenbroek 			 */
429*ef8d499eSDavid van Moolenbroek 			if ((r = ifaddr_v4_add(ifdev, sin, &mask, &bcast,
430*ef8d499eSDavid van Moolenbroek 			    &dest, 0 /*flags*/)) != OK)
431*ef8d499eSDavid van Moolenbroek 				(void)ifaddr_v4_add(ifdev, &addr, &mask,
432*ef8d499eSDavid van Moolenbroek 				    &bcast, &dest, flags);
433*ef8d499eSDavid van Moolenbroek 
434*ef8d499eSDavid van Moolenbroek 			return r;
435*ef8d499eSDavid van Moolenbroek 		} else
436*ef8d499eSDavid van Moolenbroek 			return ifaddr_v4_add(ifdev, sin, NULL /*mask*/,
437*ef8d499eSDavid van Moolenbroek 			    NULL /*bcast*/, NULL /*dest*/, 0 /*flags*/);
438*ef8d499eSDavid van Moolenbroek 
439*ef8d499eSDavid van Moolenbroek 	case SIOCSIFNETMASK:
440*ef8d499eSDavid van Moolenbroek 	case SIOCSIFBRDADDR:
441*ef8d499eSDavid van Moolenbroek 	case SIOCSIFDSTADDR:
442*ef8d499eSDavid van Moolenbroek 		/* These calls only update the existing primary address. */
443*ef8d499eSDavid van Moolenbroek 		if ((r = ifaddr_v4_get(ifdev, (ifaddr_v4_num_t)0, &addr, &mask,
444*ef8d499eSDavid van Moolenbroek 		    &bcast, &dest)) != OK)
445*ef8d499eSDavid van Moolenbroek 			return r;
446*ef8d499eSDavid van Moolenbroek 
447*ef8d499eSDavid van Moolenbroek 		sin = (struct sockaddr_in *)&ifr.ifr_addr;
448*ef8d499eSDavid van Moolenbroek 
449*ef8d499eSDavid van Moolenbroek 		switch (request) {
450*ef8d499eSDavid van Moolenbroek 		case SIOCSIFNETMASK: memcpy(&mask, sin, sizeof(mask)); break;
451*ef8d499eSDavid van Moolenbroek 		case SIOCSIFBRDADDR: memcpy(&bcast, sin, sizeof(bcast)); break;
452*ef8d499eSDavid van Moolenbroek 		case SIOCSIFDSTADDR: memcpy(&dest, sin, sizeof(dest)); break;
453*ef8d499eSDavid van Moolenbroek 		}
454*ef8d499eSDavid van Moolenbroek 
455*ef8d499eSDavid van Moolenbroek 		return ifaddr_v4_add(ifdev, &addr, &mask, &bcast, &dest,
456*ef8d499eSDavid van Moolenbroek 		    ifaddr_v4_get_flags(ifdev, (ifaddr_v4_num_t)0));
457*ef8d499eSDavid van Moolenbroek 
458*ef8d499eSDavid van Moolenbroek 	case SIOCDIFADDR:
459*ef8d499eSDavid van Moolenbroek 		if ((r = ifaddr_v4_find(ifdev,
460*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifr.ifr_addr, &num)) != OK)
461*ef8d499eSDavid van Moolenbroek 			return r;
462*ef8d499eSDavid van Moolenbroek 
463*ef8d499eSDavid van Moolenbroek 		ifaddr_v4_del(ifdev, num);
464*ef8d499eSDavid van Moolenbroek 
465*ef8d499eSDavid van Moolenbroek 		return OK;
466*ef8d499eSDavid van Moolenbroek 
467*ef8d499eSDavid van Moolenbroek 	default:
468*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
469*ef8d499eSDavid van Moolenbroek 	}
470*ef8d499eSDavid van Moolenbroek }
471*ef8d499eSDavid van Moolenbroek 
472*ef8d499eSDavid van Moolenbroek /*
473*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_INET with an "ifaliasreq" structure.
474*ef8d499eSDavid van Moolenbroek  */
475*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_v4_ifalias(unsigned long request,const struct sockdriver_data * data)476*ef8d499eSDavid van Moolenbroek ifconf_ioctl_v4_ifalias(unsigned long request,
477*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
478*ef8d499eSDavid van Moolenbroek {
479*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
480*ef8d499eSDavid van Moolenbroek 	struct ifaliasreq ifra;
481*ef8d499eSDavid van Moolenbroek 	struct sockaddr_in dest;
482*ef8d499eSDavid van Moolenbroek 	ifaddr_v4_num_t num;
483*ef8d499eSDavid van Moolenbroek 	int r;
484*ef8d499eSDavid van Moolenbroek 
485*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifra, sizeof(ifra))) != OK)
486*ef8d499eSDavid van Moolenbroek 		return r;
487*ef8d499eSDavid van Moolenbroek 
488*ef8d499eSDavid van Moolenbroek 	ifra.ifra_name[sizeof(ifra.ifra_name) - 1] = '\0';
489*ef8d499eSDavid van Moolenbroek 
490*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(ifra.ifra_name)) == NULL)
491*ef8d499eSDavid van Moolenbroek 		return ENXIO;
492*ef8d499eSDavid van Moolenbroek 
493*ef8d499eSDavid van Moolenbroek 	switch (request) {
494*ef8d499eSDavid van Moolenbroek 	case SIOCAIFADDR:
495*ef8d499eSDavid van Moolenbroek 		return ifaddr_v4_add(ifdev,
496*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifra.ifra_addr,
497*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifra.ifra_mask,
498*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifra.ifra_broadaddr,
499*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifra.ifra_dstaddr, 0 /*flags*/);
500*ef8d499eSDavid van Moolenbroek 
501*ef8d499eSDavid van Moolenbroek 	case SIOCGIFALIAS:
502*ef8d499eSDavid van Moolenbroek 		if ((r = ifaddr_v4_find(ifdev,
503*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifra.ifra_addr, &num)) != OK)
504*ef8d499eSDavid van Moolenbroek 			return r;
505*ef8d499eSDavid van Moolenbroek 
506*ef8d499eSDavid van Moolenbroek 		/*
507*ef8d499eSDavid van Moolenbroek 		 * The broadcast and destination address are stored in the same
508*ef8d499eSDavid van Moolenbroek 		 * ifaliasreq field.  We cannot pass a pointer to the same
509*ef8d499eSDavid van Moolenbroek 		 * field to ifaddr_v4_get().  So, use a temporary variable.
510*ef8d499eSDavid van Moolenbroek 		 */
511*ef8d499eSDavid van Moolenbroek 		(void)ifaddr_v4_get(ifdev, num,
512*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifra.ifra_addr,
513*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifra.ifra_mask,
514*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_in *)&ifra.ifra_broadaddr, &dest);
515*ef8d499eSDavid van Moolenbroek 
516*ef8d499eSDavid van Moolenbroek 		if (ifra.ifra_broadaddr.sa_len == 0)
517*ef8d499eSDavid van Moolenbroek 			memcpy(&ifra.ifra_dstaddr, &dest, sizeof(dest));
518*ef8d499eSDavid van Moolenbroek 
519*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifra, sizeof(ifra));
520*ef8d499eSDavid van Moolenbroek 
521*ef8d499eSDavid van Moolenbroek 	default:
522*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
523*ef8d499eSDavid van Moolenbroek 	}
524*ef8d499eSDavid van Moolenbroek }
525*ef8d499eSDavid van Moolenbroek 
526*ef8d499eSDavid van Moolenbroek /*
527*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_INET.
528*ef8d499eSDavid van Moolenbroek  */
529*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_v4(unsigned long request,const struct sockdriver_data * data,endpoint_t user_endpt)530*ef8d499eSDavid van Moolenbroek ifconf_ioctl_v4(unsigned long request, const struct sockdriver_data * data,
531*ef8d499eSDavid van Moolenbroek 	endpoint_t user_endpt)
532*ef8d499eSDavid van Moolenbroek {
533*ef8d499eSDavid van Moolenbroek 
534*ef8d499eSDavid van Moolenbroek 	switch (request) {
535*ef8d499eSDavid van Moolenbroek 	case SIOCSIFADDR:
536*ef8d499eSDavid van Moolenbroek 	case SIOCSIFDSTADDR:
537*ef8d499eSDavid van Moolenbroek 	case SIOCSIFBRDADDR:
538*ef8d499eSDavid van Moolenbroek 	case SIOCSIFNETMASK:
539*ef8d499eSDavid van Moolenbroek 	case SIOCDIFADDR:
540*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
541*ef8d499eSDavid van Moolenbroek 			return EPERM;
542*ef8d499eSDavid van Moolenbroek 
543*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
544*ef8d499eSDavid van Moolenbroek 	case SIOCGIFADDR:
545*ef8d499eSDavid van Moolenbroek 	case SIOCGIFDSTADDR:
546*ef8d499eSDavid van Moolenbroek 	case SIOCGIFBRDADDR:
547*ef8d499eSDavid van Moolenbroek 	case SIOCGIFNETMASK:
548*ef8d499eSDavid van Moolenbroek 	case SIOCGIFAFLAG_IN:
549*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_v4_ifreq(request, data);
550*ef8d499eSDavid van Moolenbroek 
551*ef8d499eSDavid van Moolenbroek 	case SIOCAIFADDR:
552*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
553*ef8d499eSDavid van Moolenbroek 			return EPERM;
554*ef8d499eSDavid van Moolenbroek 
555*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
556*ef8d499eSDavid van Moolenbroek 	case SIOCGIFALIAS:
557*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_v4_ifalias(request, data);
558*ef8d499eSDavid van Moolenbroek 
559*ef8d499eSDavid van Moolenbroek 	default:
560*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
561*ef8d499eSDavid van Moolenbroek 	}
562*ef8d499eSDavid van Moolenbroek }
563*ef8d499eSDavid van Moolenbroek 
564*ef8d499eSDavid van Moolenbroek #ifdef INET6
565*ef8d499eSDavid van Moolenbroek /*
566*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_INET6 with an "in6_ifreq" structure.
567*ef8d499eSDavid van Moolenbroek  */
568*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_v6_ifreq(unsigned long request,const struct sockdriver_data * data)569*ef8d499eSDavid van Moolenbroek ifconf_ioctl_v6_ifreq(unsigned long request,
570*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
571*ef8d499eSDavid van Moolenbroek {
572*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
573*ef8d499eSDavid van Moolenbroek 	struct in6_ifreq ifr;
574*ef8d499eSDavid van Moolenbroek 	ifaddr_v6_num_t num;
575*ef8d499eSDavid van Moolenbroek 	int r;
576*ef8d499eSDavid van Moolenbroek 
577*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifr, sizeof(ifr))) != OK)
578*ef8d499eSDavid van Moolenbroek 		return r;
579*ef8d499eSDavid van Moolenbroek 
580*ef8d499eSDavid van Moolenbroek 	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
581*ef8d499eSDavid van Moolenbroek 
582*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(ifr.ifr_name)) == NULL)
583*ef8d499eSDavid van Moolenbroek 		return ENXIO;
584*ef8d499eSDavid van Moolenbroek 
585*ef8d499eSDavid van Moolenbroek 	if ((r = ifaddr_v6_find(ifdev, &ifr.ifr_addr, &num)) != OK)
586*ef8d499eSDavid van Moolenbroek 		return r;
587*ef8d499eSDavid van Moolenbroek 
588*ef8d499eSDavid van Moolenbroek 	switch (request) {
589*ef8d499eSDavid van Moolenbroek 	case SIOCGIFADDR_IN6:
590*ef8d499eSDavid van Moolenbroek 		/* This IOCTL basically checks if the given address exists. */
591*ef8d499eSDavid van Moolenbroek 		ifaddr_v6_get(ifdev, num, &ifr.ifr_addr, NULL, NULL);
592*ef8d499eSDavid van Moolenbroek 
593*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
594*ef8d499eSDavid van Moolenbroek 
595*ef8d499eSDavid van Moolenbroek 	case SIOCDIFADDR_IN6:
596*ef8d499eSDavid van Moolenbroek 		ifaddr_v6_del(ifdev, num);
597*ef8d499eSDavid van Moolenbroek 
598*ef8d499eSDavid van Moolenbroek 		return OK;
599*ef8d499eSDavid van Moolenbroek 
600*ef8d499eSDavid van Moolenbroek 	case SIOCGIFNETMASK_IN6:
601*ef8d499eSDavid van Moolenbroek 		ifaddr_v6_get(ifdev, num, NULL, &ifr.ifr_addr, NULL);
602*ef8d499eSDavid van Moolenbroek 
603*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
604*ef8d499eSDavid van Moolenbroek 
605*ef8d499eSDavid van Moolenbroek 	case SIOCGIFAFLAG_IN6:
606*ef8d499eSDavid van Moolenbroek 		ifr.ifr_ifru.ifru_flags6 = ifaddr_v6_get_flags(ifdev, num);
607*ef8d499eSDavid van Moolenbroek 
608*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
609*ef8d499eSDavid van Moolenbroek 
610*ef8d499eSDavid van Moolenbroek 	case SIOCGIFALIFETIME_IN6:
611*ef8d499eSDavid van Moolenbroek 		ifaddr_v6_get_lifetime(ifdev, num,
612*ef8d499eSDavid van Moolenbroek 		    &ifr.ifr_ifru.ifru_lifetime);
613*ef8d499eSDavid van Moolenbroek 
614*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ifr, sizeof(ifr));
615*ef8d499eSDavid van Moolenbroek 
616*ef8d499eSDavid van Moolenbroek 	default:
617*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
618*ef8d499eSDavid van Moolenbroek 	}
619*ef8d499eSDavid van Moolenbroek }
620*ef8d499eSDavid van Moolenbroek 
621*ef8d499eSDavid van Moolenbroek /*
622*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_INET6 with an "in6_aliasreq" structure.
623*ef8d499eSDavid van Moolenbroek  */
624*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_v6_ifalias(unsigned long request,const struct sockdriver_data * data)625*ef8d499eSDavid van Moolenbroek ifconf_ioctl_v6_ifalias(unsigned long request,
626*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
627*ef8d499eSDavid van Moolenbroek {
628*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
629*ef8d499eSDavid van Moolenbroek 	struct in6_aliasreq ifra;
630*ef8d499eSDavid van Moolenbroek 	int r;
631*ef8d499eSDavid van Moolenbroek 
632*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ifra, sizeof(ifra))) != OK)
633*ef8d499eSDavid van Moolenbroek 		return r;
634*ef8d499eSDavid van Moolenbroek 
635*ef8d499eSDavid van Moolenbroek 	ifra.ifra_name[sizeof(ifra.ifra_name) - 1] = '\0';
636*ef8d499eSDavid van Moolenbroek 
637*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(ifra.ifra_name)) == NULL)
638*ef8d499eSDavid van Moolenbroek 		return ENXIO;
639*ef8d499eSDavid van Moolenbroek 
640*ef8d499eSDavid van Moolenbroek 	switch (request) {
641*ef8d499eSDavid van Moolenbroek 	case SIOCAIFADDR_IN6:
642*ef8d499eSDavid van Moolenbroek 		return ifaddr_v6_add(ifdev, &ifra.ifra_addr,
643*ef8d499eSDavid van Moolenbroek 		    &ifra.ifra_prefixmask, &ifra.ifra_dstaddr,
644*ef8d499eSDavid van Moolenbroek 		    ifra.ifra_flags, &ifra.ifra_lifetime);
645*ef8d499eSDavid van Moolenbroek 
646*ef8d499eSDavid van Moolenbroek 	default:
647*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
648*ef8d499eSDavid van Moolenbroek 	}
649*ef8d499eSDavid van Moolenbroek }
650*ef8d499eSDavid van Moolenbroek 
651*ef8d499eSDavid van Moolenbroek /*
652*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_INET6 with an "in6_ndireq" structure.
653*ef8d499eSDavid van Moolenbroek  */
654*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_v6_ndireq(unsigned long request,const struct sockdriver_data * data)655*ef8d499eSDavid van Moolenbroek ifconf_ioctl_v6_ndireq(unsigned long request,
656*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
657*ef8d499eSDavid van Moolenbroek {
658*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
659*ef8d499eSDavid van Moolenbroek 	struct in6_ndireq ndi;
660*ef8d499eSDavid van Moolenbroek 	int r;
661*ef8d499eSDavid van Moolenbroek 
662*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &ndi, sizeof(ndi))) != OK)
663*ef8d499eSDavid van Moolenbroek 		return r;
664*ef8d499eSDavid van Moolenbroek 
665*ef8d499eSDavid van Moolenbroek 	ndi.ifname[sizeof(ndi.ifname) - 1] = '\0';
666*ef8d499eSDavid van Moolenbroek 
667*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(ndi.ifname)) == NULL)
668*ef8d499eSDavid van Moolenbroek 		return ENXIO;
669*ef8d499eSDavid van Moolenbroek 
670*ef8d499eSDavid van Moolenbroek 	switch (request) {
671*ef8d499eSDavid van Moolenbroek 	case SIOCGIFINFO_IN6:
672*ef8d499eSDavid van Moolenbroek 		memset(&ndi.ndi, 0, sizeof(ndi.ndi));
673*ef8d499eSDavid van Moolenbroek 
674*ef8d499eSDavid van Moolenbroek 		ndi.ndi.linkmtu = ifdev_get_mtu(ifdev);
675*ef8d499eSDavid van Moolenbroek 		ndi.ndi.flags = ifdev_get_nd6flags(ifdev);
676*ef8d499eSDavid van Moolenbroek 		ndi.ndi.initialized = 1;
677*ef8d499eSDavid van Moolenbroek 		/* TODO: all the other fields.. */
678*ef8d499eSDavid van Moolenbroek 
679*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &ndi, sizeof(ndi));
680*ef8d499eSDavid van Moolenbroek 
681*ef8d499eSDavid van Moolenbroek 	case SIOCSIFINFO_IN6:
682*ef8d499eSDavid van Moolenbroek 		/* TODO: all the other fields.. */
683*ef8d499eSDavid van Moolenbroek 
684*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
685*ef8d499eSDavid van Moolenbroek 	case SIOCSIFINFO_FLAGS:
686*ef8d499eSDavid van Moolenbroek 		return ifdev_set_nd6flags(ifdev, ndi.ndi.flags);
687*ef8d499eSDavid van Moolenbroek 
688*ef8d499eSDavid van Moolenbroek 	default:
689*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
690*ef8d499eSDavid van Moolenbroek 	}
691*ef8d499eSDavid van Moolenbroek }
692*ef8d499eSDavid van Moolenbroek 
693*ef8d499eSDavid van Moolenbroek /*
694*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_INET6 with an "in6_nbrinfo" structure.
695*ef8d499eSDavid van Moolenbroek  */
696*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_v6_nbrinfo(unsigned long request,const struct sockdriver_data * data)697*ef8d499eSDavid van Moolenbroek ifconf_ioctl_v6_nbrinfo(unsigned long request,
698*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
699*ef8d499eSDavid van Moolenbroek {
700*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
701*ef8d499eSDavid van Moolenbroek 	struct sockaddr_in6 addr;
702*ef8d499eSDavid van Moolenbroek 	struct in6_nbrinfo nbri;
703*ef8d499eSDavid van Moolenbroek 	lldata_ndp_num_t num;
704*ef8d499eSDavid van Moolenbroek 	int r;
705*ef8d499eSDavid van Moolenbroek 
706*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &nbri, sizeof(nbri))) != OK)
707*ef8d499eSDavid van Moolenbroek 		return r;
708*ef8d499eSDavid van Moolenbroek 
709*ef8d499eSDavid van Moolenbroek 	nbri.ifname[sizeof(nbri.ifname) - 1] = '\0';
710*ef8d499eSDavid van Moolenbroek 
711*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(nbri.ifname)) == NULL)
712*ef8d499eSDavid van Moolenbroek 		return ENXIO;
713*ef8d499eSDavid van Moolenbroek 
714*ef8d499eSDavid van Moolenbroek 	switch (request) {
715*ef8d499eSDavid van Moolenbroek 	case SIOCGNBRINFO_IN6:
716*ef8d499eSDavid van Moolenbroek 		/*
717*ef8d499eSDavid van Moolenbroek 		 * Convert the given in6_addr to a full sockaddr_in6, mainly
718*ef8d499eSDavid van Moolenbroek 		 * for internal consistency.  It would have been nice if the
719*ef8d499eSDavid van Moolenbroek 		 * KAME management API had had any sort of consistency itself.
720*ef8d499eSDavid van Moolenbroek 		 */
721*ef8d499eSDavid van Moolenbroek 		memset(&addr, 0, sizeof(addr));
722*ef8d499eSDavid van Moolenbroek 		addr.sin6_family = AF_INET6;
723*ef8d499eSDavid van Moolenbroek 		memcpy(&addr.sin6_addr.s6_addr, &nbri.addr,
724*ef8d499eSDavid van Moolenbroek 		    sizeof(addr.sin6_addr.s6_addr));
725*ef8d499eSDavid van Moolenbroek 
726*ef8d499eSDavid van Moolenbroek 		if ((r = lldata_ndp_find(ifdev, &addr, &num)) != OK)
727*ef8d499eSDavid van Moolenbroek 			return r;
728*ef8d499eSDavid van Moolenbroek 
729*ef8d499eSDavid van Moolenbroek 		lldata_ndp_get_info(num, &nbri.asked, &nbri.isrouter,
730*ef8d499eSDavid van Moolenbroek 		    &nbri.state, &nbri.expire);
731*ef8d499eSDavid van Moolenbroek 
732*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &nbri, sizeof(nbri));
733*ef8d499eSDavid van Moolenbroek 
734*ef8d499eSDavid van Moolenbroek 	default:
735*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
736*ef8d499eSDavid van Moolenbroek 	}
737*ef8d499eSDavid van Moolenbroek }
738*ef8d499eSDavid van Moolenbroek 
739*ef8d499eSDavid van Moolenbroek /*
740*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_INET6.
741*ef8d499eSDavid van Moolenbroek  */
742*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_v6(unsigned long request,const struct sockdriver_data * data,endpoint_t user_endpt)743*ef8d499eSDavid van Moolenbroek ifconf_ioctl_v6(unsigned long request, const struct sockdriver_data * data,
744*ef8d499eSDavid van Moolenbroek 	endpoint_t user_endpt)
745*ef8d499eSDavid van Moolenbroek {
746*ef8d499eSDavid van Moolenbroek 
747*ef8d499eSDavid van Moolenbroek 	switch (request) {
748*ef8d499eSDavid van Moolenbroek 	case SIOCDIFADDR_IN6:
749*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
750*ef8d499eSDavid van Moolenbroek 			return EPERM;
751*ef8d499eSDavid van Moolenbroek 
752*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
753*ef8d499eSDavid van Moolenbroek 	case SIOCGIFADDR_IN6:
754*ef8d499eSDavid van Moolenbroek 	case SIOCGIFNETMASK_IN6:
755*ef8d499eSDavid van Moolenbroek 	case SIOCGIFAFLAG_IN6:
756*ef8d499eSDavid van Moolenbroek 	case SIOCGIFALIFETIME_IN6:
757*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_v6_ifreq(request, data);
758*ef8d499eSDavid van Moolenbroek 
759*ef8d499eSDavid van Moolenbroek 	case SIOCAIFADDR_IN6:
760*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
761*ef8d499eSDavid van Moolenbroek 			return EPERM;
762*ef8d499eSDavid van Moolenbroek 
763*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_v6_ifalias(request, data);
764*ef8d499eSDavid van Moolenbroek 
765*ef8d499eSDavid van Moolenbroek 	case SIOCSIFINFO_IN6:
766*ef8d499eSDavid van Moolenbroek 	case SIOCSIFINFO_FLAGS:
767*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
768*ef8d499eSDavid van Moolenbroek 			return EPERM;
769*ef8d499eSDavid van Moolenbroek 
770*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
771*ef8d499eSDavid van Moolenbroek 	case SIOCGIFINFO_IN6:
772*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_v6_ndireq(request, data);
773*ef8d499eSDavid van Moolenbroek 
774*ef8d499eSDavid van Moolenbroek 	case SIOCGNBRINFO_IN6:
775*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_v6_nbrinfo(request, data);
776*ef8d499eSDavid van Moolenbroek 
777*ef8d499eSDavid van Moolenbroek 	default:
778*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
779*ef8d499eSDavid van Moolenbroek 	}
780*ef8d499eSDavid van Moolenbroek }
781*ef8d499eSDavid van Moolenbroek #endif /* INET6 */
782*ef8d499eSDavid van Moolenbroek 
783*ef8d499eSDavid van Moolenbroek /*
784*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_LINK with an "if_laddrreq" structure.
785*ef8d499eSDavid van Moolenbroek  */
786*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_dl_lifaddr(unsigned long request,const struct sockdriver_data * data)787*ef8d499eSDavid van Moolenbroek ifconf_ioctl_dl_lifaddr(unsigned long request,
788*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data)
789*ef8d499eSDavid van Moolenbroek {
790*ef8d499eSDavid van Moolenbroek 	struct ifdev *ifdev;
791*ef8d499eSDavid van Moolenbroek 	struct if_laddrreq iflr;
792*ef8d499eSDavid van Moolenbroek 	ifaddr_dl_num_t num;
793*ef8d499eSDavid van Moolenbroek 	int r;
794*ef8d499eSDavid van Moolenbroek 
795*ef8d499eSDavid van Moolenbroek 	if ((r = sockdriver_copyin(data, 0, &iflr, sizeof(iflr))) != OK)
796*ef8d499eSDavid van Moolenbroek 		return r;
797*ef8d499eSDavid van Moolenbroek 
798*ef8d499eSDavid van Moolenbroek 	iflr.iflr_name[sizeof(iflr.iflr_name) - 1] = '\0';
799*ef8d499eSDavid van Moolenbroek 
800*ef8d499eSDavid van Moolenbroek 	if ((ifdev = ifdev_find_by_name(iflr.iflr_name)) == NULL)
801*ef8d499eSDavid van Moolenbroek 		return ENXIO;
802*ef8d499eSDavid van Moolenbroek 
803*ef8d499eSDavid van Moolenbroek 	switch (request) {
804*ef8d499eSDavid van Moolenbroek 	case SIOCGLIFADDR:
805*ef8d499eSDavid van Moolenbroek 		if (iflr.flags & IFLR_PREFIX) {
806*ef8d499eSDavid van Moolenbroek 			/* We ignore the prefix length, like NetBSD does. */
807*ef8d499eSDavid van Moolenbroek 			if ((r = ifaddr_dl_find(ifdev,
808*ef8d499eSDavid van Moolenbroek 			    (struct sockaddr_dlx *)&iflr.addr,
809*ef8d499eSDavid van Moolenbroek 			    sizeof(iflr.addr), &num)) != OK)
810*ef8d499eSDavid van Moolenbroek 				return r;
811*ef8d499eSDavid van Moolenbroek 		} else
812*ef8d499eSDavid van Moolenbroek 			num = (ifaddr_dl_num_t)0; /* this always works */
813*ef8d499eSDavid van Moolenbroek 
814*ef8d499eSDavid van Moolenbroek 		ifaddr_dl_get(ifdev, num, (struct sockaddr_dlx *)&iflr.addr);
815*ef8d499eSDavid van Moolenbroek 		iflr.flags = ifaddr_dl_get_flags(ifdev, num);
816*ef8d499eSDavid van Moolenbroek 		memset(&iflr.dstaddr, 0, sizeof(iflr.dstaddr));
817*ef8d499eSDavid van Moolenbroek 
818*ef8d499eSDavid van Moolenbroek 		return sockdriver_copyout(data, 0, &iflr, sizeof(iflr));
819*ef8d499eSDavid van Moolenbroek 
820*ef8d499eSDavid van Moolenbroek 	case SIOCALIFADDR:
821*ef8d499eSDavid van Moolenbroek 		return ifaddr_dl_add(ifdev, (struct sockaddr_dlx *)&iflr.addr,
822*ef8d499eSDavid van Moolenbroek 		    sizeof(iflr.addr), iflr.flags);
823*ef8d499eSDavid van Moolenbroek 
824*ef8d499eSDavid van Moolenbroek 	case SIOCDLIFADDR:
825*ef8d499eSDavid van Moolenbroek 		if ((r = ifaddr_dl_find(ifdev,
826*ef8d499eSDavid van Moolenbroek 		    (struct sockaddr_dlx *)&iflr.addr, sizeof(iflr.addr),
827*ef8d499eSDavid van Moolenbroek 		    &num)) != OK)
828*ef8d499eSDavid van Moolenbroek 			return r;
829*ef8d499eSDavid van Moolenbroek 
830*ef8d499eSDavid van Moolenbroek 		return ifaddr_dl_del(ifdev, num);
831*ef8d499eSDavid van Moolenbroek 
832*ef8d499eSDavid van Moolenbroek 	default:
833*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
834*ef8d499eSDavid van Moolenbroek 	}
835*ef8d499eSDavid van Moolenbroek }
836*ef8d499eSDavid van Moolenbroek 
837*ef8d499eSDavid van Moolenbroek /*
838*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request for AF_LINK.
839*ef8d499eSDavid van Moolenbroek  */
840*ef8d499eSDavid van Moolenbroek static int
ifconf_ioctl_dl(unsigned long request,const struct sockdriver_data * data,endpoint_t user_endpt)841*ef8d499eSDavid van Moolenbroek ifconf_ioctl_dl(unsigned long request, const struct sockdriver_data * data,
842*ef8d499eSDavid van Moolenbroek 	endpoint_t user_endpt)
843*ef8d499eSDavid van Moolenbroek {
844*ef8d499eSDavid van Moolenbroek 
845*ef8d499eSDavid van Moolenbroek 	switch (request) {
846*ef8d499eSDavid van Moolenbroek 	case SIOCALIFADDR:
847*ef8d499eSDavid van Moolenbroek 	case SIOCDLIFADDR:
848*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
849*ef8d499eSDavid van Moolenbroek 			return EPERM;
850*ef8d499eSDavid van Moolenbroek 
851*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
852*ef8d499eSDavid van Moolenbroek 	case SIOCGLIFADDR:
853*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_dl_lifaddr(request, data);
854*ef8d499eSDavid van Moolenbroek 
855*ef8d499eSDavid van Moolenbroek 	default:
856*ef8d499eSDavid van Moolenbroek 		return ENOTTY;
857*ef8d499eSDavid van Moolenbroek 	}
858*ef8d499eSDavid van Moolenbroek }
859*ef8d499eSDavid van Moolenbroek 
860*ef8d499eSDavid van Moolenbroek /*
861*ef8d499eSDavid van Moolenbroek  * Process an IOCTL request.  This routine is shared between TCP, UDP, RAW, and
862*ef8d499eSDavid van Moolenbroek  * link sockets.  The given socket may be used to obtain the target domain:
863*ef8d499eSDavid van Moolenbroek  * AF_INET, AF_INET6, or AF_LINK.
864*ef8d499eSDavid van Moolenbroek  */
865*ef8d499eSDavid van Moolenbroek int
ifconf_ioctl(struct sock * sock,unsigned long request,const struct sockdriver_data * data,endpoint_t user_endpt)866*ef8d499eSDavid van Moolenbroek ifconf_ioctl(struct sock * sock, unsigned long request,
867*ef8d499eSDavid van Moolenbroek 	const struct sockdriver_data * data, endpoint_t user_endpt)
868*ef8d499eSDavid van Moolenbroek {
869*ef8d499eSDavid van Moolenbroek 	int domain;
870*ef8d499eSDavid van Moolenbroek 
871*ef8d499eSDavid van Moolenbroek 	domain = sockevent_get_domain(sock);
872*ef8d499eSDavid van Moolenbroek 
873*ef8d499eSDavid van Moolenbroek 	switch (request) {
874*ef8d499eSDavid van Moolenbroek 	case SIOCSIFFLAGS:
875*ef8d499eSDavid van Moolenbroek 	case SIOCSIFMETRIC:
876*ef8d499eSDavid van Moolenbroek 	case SIOCSIFMEDIA:
877*ef8d499eSDavid van Moolenbroek 	case SIOCSIFMTU:
878*ef8d499eSDavid van Moolenbroek 	case SIOCIFCREATE:
879*ef8d499eSDavid van Moolenbroek 	case SIOCIFDESTROY:
880*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
881*ef8d499eSDavid van Moolenbroek 			return EPERM;
882*ef8d499eSDavid van Moolenbroek 
883*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
884*ef8d499eSDavid van Moolenbroek 	case SIOCGIFFLAGS:
885*ef8d499eSDavid van Moolenbroek 	case SIOCGIFMETRIC:
886*ef8d499eSDavid van Moolenbroek 	case SIOCGIFMTU:
887*ef8d499eSDavid van Moolenbroek 	case SIOCGIFDLT:
888*ef8d499eSDavid van Moolenbroek 	case SIOCGIFINDEX:
889*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_ifreq(request, data);
890*ef8d499eSDavid van Moolenbroek 
891*ef8d499eSDavid van Moolenbroek 	case SIOCSIFCAP:
892*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
893*ef8d499eSDavid van Moolenbroek 			return EPERM;
894*ef8d499eSDavid van Moolenbroek 
895*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
896*ef8d499eSDavid van Moolenbroek 	case SIOCGIFCAP:
897*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_ifcap(request, data);
898*ef8d499eSDavid van Moolenbroek 
899*ef8d499eSDavid van Moolenbroek 	case MINIX_SIOCGIFMEDIA:
900*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_ifmedia(request, data);
901*ef8d499eSDavid van Moolenbroek 
902*ef8d499eSDavid van Moolenbroek 	case MINIX_SIOCIFGCLONERS:
903*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_ifclone(request, data);
904*ef8d499eSDavid van Moolenbroek 
905*ef8d499eSDavid van Moolenbroek 	case SIOCSIFADDRPREF:
906*ef8d499eSDavid van Moolenbroek 		if (!util_is_root(user_endpt))
907*ef8d499eSDavid van Moolenbroek 			return EPERM;
908*ef8d499eSDavid van Moolenbroek 
909*ef8d499eSDavid van Moolenbroek 		/* FALLTHROUGH */
910*ef8d499eSDavid van Moolenbroek 	case SIOCGIFADDRPREF:
911*ef8d499eSDavid van Moolenbroek 		return ifconf_ioctl_ifaddrpref(request, data);
912*ef8d499eSDavid van Moolenbroek 
913*ef8d499eSDavid van Moolenbroek 	default:
914*ef8d499eSDavid van Moolenbroek 		switch (domain) {
915*ef8d499eSDavid van Moolenbroek 		case AF_INET:
916*ef8d499eSDavid van Moolenbroek 			return ifconf_ioctl_v4(request, data, user_endpt);
917*ef8d499eSDavid van Moolenbroek 
918*ef8d499eSDavid van Moolenbroek #ifdef INET6
919*ef8d499eSDavid van Moolenbroek 		case AF_INET6:
920*ef8d499eSDavid van Moolenbroek 			return ifconf_ioctl_v6(request, data, user_endpt);
921*ef8d499eSDavid van Moolenbroek #endif /* INET6 */
922*ef8d499eSDavid van Moolenbroek 
923*ef8d499eSDavid van Moolenbroek 		case AF_LINK:
924*ef8d499eSDavid van Moolenbroek 			return ifconf_ioctl_dl(request, data, user_endpt);
925*ef8d499eSDavid van Moolenbroek 
926*ef8d499eSDavid van Moolenbroek 		default:
927*ef8d499eSDavid van Moolenbroek 			return ENOTTY;
928*ef8d499eSDavid van Moolenbroek 		}
929*ef8d499eSDavid van Moolenbroek 	}
930*ef8d499eSDavid van Moolenbroek }
931