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