1 /* LWIP service - ifconf.c - interface configuration */
7 #include <net/if_media.h>
10 #define LOOPBACK_IFNAME "lo0" /* name of the loopback interface */
13 * Initialize the first loopback device, which is present by default.
18 const struct sockaddr_in addr
= {
19 .sin_family
= AF_INET
,
20 .sin_addr
= { htonl(INADDR_LOOPBACK
) }
22 struct sockaddr_in6 ll_addr6
= {
23 .sin6_family
= AF_INET6
,
25 const struct sockaddr_in6 lo_addr6
= {
26 .sin6_family
= AF_INET6
,
27 .sin6_addr
= IN6ADDR_LOOPBACK_INIT
29 const struct in6_addrlifetime lifetime
= {
30 .ia6t_vltime
= ND6_INFINITE_LIFETIME
,
31 .ia6t_pltime
= ND6_INFINITE_LIFETIME
33 struct sockaddr_in6 mask6
;
38 if ((r
= ifdev_create(LOOPBACK_IFNAME
)) != OK
)
39 panic("unable to create loopback interface: %d", r
);
41 if ((ifdev
= ifdev_find_by_name(LOOPBACK_IFNAME
)) == NULL
)
42 panic("unable to find loopback interface");
44 if ((r
= ifaddr_v4_add(ifdev
, &addr
, NULL
, NULL
, NULL
, 0)) != OK
)
45 panic("unable to set IPv4 address on loopback interface: %d",
48 addr_len
= sizeof(mask6
);
49 addr_put_netmask((struct sockaddr
*)&mask6
, &addr_len
, IPADDR_TYPE_V6
,
52 ll_addr6
.sin6_addr
.s6_addr
[0] = 0xfe;
53 ll_addr6
.sin6_addr
.s6_addr
[1] = 0x80;
54 ll_addr6
.sin6_addr
.s6_addr
[15] = ifdev_get_index(ifdev
);
56 if ((r
= ifaddr_v6_add(ifdev
, &ll_addr6
, &mask6
, NULL
, 0,
58 panic("unable to set IPv6 address on loopback interface: %d",
61 addr_len
= sizeof(mask6
);
62 addr_put_netmask((struct sockaddr
*)&mask6
, &addr_len
, IPADDR_TYPE_V6
,
65 if ((r
= ifaddr_v6_add(ifdev
, &lo_addr6
, &mask6
, NULL
, 0,
67 panic("unable to set IPv6 address on loopback interface: %d",
70 if ((r
= ifdev_set_ifflags(ifdev
, IFF_UP
)) != OK
)
71 panic("unable to bring up loopback interface");
75 * Process an address family independent IOCTL request with an "ifreq"
79 ifconf_ioctl_ifreq(unsigned long request
, const struct sockdriver_data
* data
)
85 if ((r
= sockdriver_copyin(data
, 0, &ifr
, sizeof(ifr
))) != OK
)
88 if (request
!= SIOCIFCREATE
) {
89 ifr
.ifr_name
[sizeof(ifr
.ifr_name
) - 1] = '\0';
91 if ((ifdev
= ifdev_find_by_name(ifr
.ifr_name
)) == NULL
)
98 ifr
.ifr_flags
= ifdev_get_ifflags(ifdev
);
100 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
104 * Unfortunately, ifr_flags is a signed integer and the sign
105 * bit is in fact used as a flag, so without explicit casting
106 * we end up setting all upper bits of the (full) integer. If
107 * NetBSD ever extends the field, this assert should trigger..
109 assert(sizeof(ifr
.ifr_flags
) == sizeof(short));
111 return ifdev_set_ifflags(ifdev
, (unsigned short)ifr
.ifr_flags
);
114 ifr
.ifr_metric
= ifdev_get_metric(ifdev
);
116 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
119 /* The metric is not used within the operating system. */
120 ifdev_set_metric(ifdev
, ifr
.ifr_metric
);
125 return ifdev_set_ifmedia(ifdev
, ifr
.ifr_media
);
128 ifr
.ifr_mtu
= ifdev_get_mtu(ifdev
);
130 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
133 return ifdev_set_mtu(ifdev
, ifr
.ifr_mtu
);
136 if (memchr(ifr
.ifr_name
, '\0', sizeof(ifr
.ifr_name
)) == NULL
)
139 return ifdev_create(ifr
.ifr_name
);
142 return ifdev_destroy(ifdev
);
145 ifr
.ifr_dlt
= ifdev_get_dlt(ifdev
);
147 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
150 ifr
.ifr_index
= ifdev_get_index(ifdev
);
152 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
160 * Process an address family independent IOCTL request with an "ifcapreq"
164 ifconf_ioctl_ifcap(unsigned long request
,
165 const struct sockdriver_data
* data
)
168 struct ifcapreq ifcr
;
171 if ((r
= sockdriver_copyin(data
, 0, &ifcr
, sizeof(ifcr
))) != OK
)
174 ifcr
.ifcr_name
[sizeof(ifcr
.ifcr_name
) - 1] = '\0';
176 if ((ifdev
= ifdev_find_by_name(ifcr
.ifcr_name
)) == NULL
)
181 return ifdev_set_ifcap(ifdev
, ifcr
.ifcr_capenable
);
184 ifdev_get_ifcap(ifdev
, &ifcr
.ifcr_capabilities
,
185 &ifcr
.ifcr_capenable
);
187 return sockdriver_copyout(data
, 0, &ifcr
, sizeof(ifcr
));
195 * Process an address family independent IOCTL request with an "ifmediareq"
199 ifconf_ioctl_ifmedia(unsigned long request
,
200 const struct sockdriver_data
* data
)
203 struct ifmediareq ifm
;
206 if ((r
= sockdriver_copyin(data
, 0, &ifm
, sizeof(ifm
))) != OK
)
209 ifm
.ifm_name
[sizeof(ifm
.ifm_name
) - 1] = '\0';
211 if ((ifdev
= ifdev_find_by_name(ifm
.ifm_name
)) == NULL
)
215 case MINIX_SIOCGIFMEDIA
:
216 if ((r
= ifdev_get_ifmedia(ifdev
, &ifm
.ifm_current
,
217 &ifm
.ifm_active
)) != OK
)
221 switch (ifdev_get_link(ifdev
)) {
223 ifm
.ifm_status
= IFM_AVALID
| IFM_ACTIVE
;
225 case LINK_STATE_DOWN
:
226 ifm
.ifm_status
= IFM_AVALID
;
234 * TODO: support for the list of supported media types. This
235 * one is not easy, because we cannot simply suspend the IOCTL
236 * and query the driver. For now, return only entry (which is
237 * the minimum for ifconfig(8) not to complain), namely the
238 * currently selected one.
240 if (ifm
.ifm_ulist
!= NULL
) {
241 if (ifm
.ifm_count
< 1)
245 * Copy out the 'list', which consists of one entry.
246 * If we were to produce multiple entries, we would
247 * have to check against the MINIX_IF_MAXMEDIA limit.
249 if ((r
= sockdriver_copyout(data
,
250 offsetof(struct minix_ifmediareq
, mifm_list
),
251 &ifm
.ifm_current
, sizeof(ifm
.ifm_current
))) != OK
)
256 return sockdriver_copyout(data
, 0, &ifm
, sizeof(ifm
));
264 * Process an address family independent IOCTL request with an "if_clonereq"
268 ifconf_ioctl_ifclone(unsigned long request
,
269 const struct sockdriver_data
* data
)
271 struct if_clonereq ifcr
;
278 if ((r
= sockdriver_copyin(data
, 0, &ifcr
, sizeof(ifcr
))) != OK
)
281 if (ifcr
.ifcr_count
< 0)
284 off
= offsetof(struct minix_if_clonereq
, mifcr_buffer
);
286 for (num
= 0; (ptr
= ifdev_enum_vtypes(num
)) != NULL
; num
++) {
287 /* Prevent overflow in case we ever have over 128 vtypes.. */
288 if (num
== MINIX_IF_MAXCLONERS
)
291 if (ifcr
.ifcr_buffer
== NULL
||
292 num
>= (unsigned int)ifcr
.ifcr_count
)
295 memset(name
, 0, sizeof(name
));
296 strlcpy(name
, ptr
, sizeof(name
));
298 if ((r
= sockdriver_copyout(data
, off
, name
,
299 sizeof(name
))) != OK
)
305 ifcr
.ifcr_total
= num
;
307 return sockdriver_copyout(data
, 0, &ifcr
, sizeof(ifcr
));
311 * Process an address family independent IOCTL request with an "if_addrprefreq"
315 ifconf_ioctl_ifaddrpref(unsigned long request
,
316 const struct sockdriver_data
* data
)
319 struct if_addrprefreq ifap
;
322 if ((r
= sockdriver_copyin(data
, 0, &ifap
, sizeof(ifap
))) != OK
)
325 ifap
.ifap_name
[sizeof(ifap
.ifap_name
) - 1] = '\0';
327 if ((ifdev
= ifdev_find_by_name(ifap
.ifap_name
)) == NULL
)
331 * For now, we simply support only a preference of 0. We do not try to
332 * look up the given address, nor do we return the looked up address.
335 case SIOCSIFADDRPREF
:
336 if (ifap
.ifap_preference
!= 0)
341 case SIOCGIFADDRPREF
:
342 ifap
.ifap_preference
= 0;
344 return sockdriver_copyout(data
, 0, &ifap
, sizeof(ifap
));
352 * Process an IOCTL request for AF_INET with an "ifreq" structure.
355 ifconf_ioctl_v4_ifreq(unsigned long request
,
356 const struct sockdriver_data
* data
)
358 struct sockaddr_in addr
, mask
, bcast
, dest
, *sin
= NULL
/*gcc*/;
364 if ((r
= sockdriver_copyin(data
, 0, &ifr
, sizeof(ifr
))) != OK
)
367 ifr
.ifr_name
[sizeof(ifr
.ifr_name
) - 1] = '\0';
369 if ((ifdev
= ifdev_find_by_name(ifr
.ifr_name
)) == NULL
)
377 /* Retrieve all addresses, then copy out the desired one. */
379 case SIOCGIFADDR
: sin
= &addr
; break;
380 case SIOCGIFNETMASK
: sin
= &mask
; break;
381 case SIOCGIFBRDADDR
: sin
= &bcast
; break;
382 case SIOCGIFDSTADDR
: sin
= &dest
; break;
387 if ((r
= ifaddr_v4_get(ifdev
, (ifaddr_v4_num_t
)0, &addr
, &mask
,
388 &bcast
, &dest
)) != OK
)
391 if (sin
->sin_len
== 0) /* not filled in */
392 return EADDRNOTAVAIL
;
394 memcpy(&ifr
.ifr_addr
, sin
, sizeof(*sin
));
396 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
398 case SIOCGIFAFLAG_IN
:
399 if ((r
= ifaddr_v4_find(ifdev
,
400 (struct sockaddr_in
*)&ifr
.ifr_addr
, &num
)) != OK
)
403 ifr
.ifr_addrflags
= ifaddr_v4_get_flags(ifdev
, num
);
405 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
409 * This one is slightly different from the rest, in that we
410 * either set or update the primary address: if we set it, we
411 * must let _add() generate a matching netmask automatically,
412 * while if we update it, _add() would fail unless we first
413 * delete the old entry.
415 sin
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
417 if ((r
= ifaddr_v4_get(ifdev
, (ifaddr_v4_num_t
)0, &addr
, &mask
,
418 &bcast
, &dest
)) == OK
) {
419 flags
= ifaddr_v4_get_flags(ifdev
, (ifaddr_v4_num_t
)0);
421 ifaddr_v4_del(ifdev
, (ifaddr_v4_num_t
)0);
424 * If setting the new address fails, reinstating the
425 * old address should always work. This is really ugly
426 * as it generates routing socket noise, but this call
427 * is deprecated anyway.
429 if ((r
= ifaddr_v4_add(ifdev
, sin
, &mask
, &bcast
,
430 &dest
, 0 /*flags*/)) != OK
)
431 (void)ifaddr_v4_add(ifdev
, &addr
, &mask
,
432 &bcast
, &dest
, flags
);
436 return ifaddr_v4_add(ifdev
, sin
, NULL
/*mask*/,
437 NULL
/*bcast*/, NULL
/*dest*/, 0 /*flags*/);
442 /* These calls only update the existing primary address. */
443 if ((r
= ifaddr_v4_get(ifdev
, (ifaddr_v4_num_t
)0, &addr
, &mask
,
444 &bcast
, &dest
)) != OK
)
447 sin
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
450 case SIOCSIFNETMASK
: memcpy(&mask
, sin
, sizeof(mask
)); break;
451 case SIOCSIFBRDADDR
: memcpy(&bcast
, sin
, sizeof(bcast
)); break;
452 case SIOCSIFDSTADDR
: memcpy(&dest
, sin
, sizeof(dest
)); break;
455 return ifaddr_v4_add(ifdev
, &addr
, &mask
, &bcast
, &dest
,
456 ifaddr_v4_get_flags(ifdev
, (ifaddr_v4_num_t
)0));
459 if ((r
= ifaddr_v4_find(ifdev
,
460 (struct sockaddr_in
*)&ifr
.ifr_addr
, &num
)) != OK
)
463 ifaddr_v4_del(ifdev
, num
);
473 * Process an IOCTL request for AF_INET with an "ifaliasreq" structure.
476 ifconf_ioctl_v4_ifalias(unsigned long request
,
477 const struct sockdriver_data
* data
)
480 struct ifaliasreq ifra
;
481 struct sockaddr_in dest
;
485 if ((r
= sockdriver_copyin(data
, 0, &ifra
, sizeof(ifra
))) != OK
)
488 ifra
.ifra_name
[sizeof(ifra
.ifra_name
) - 1] = '\0';
490 if ((ifdev
= ifdev_find_by_name(ifra
.ifra_name
)) == NULL
)
495 return ifaddr_v4_add(ifdev
,
496 (struct sockaddr_in
*)&ifra
.ifra_addr
,
497 (struct sockaddr_in
*)&ifra
.ifra_mask
,
498 (struct sockaddr_in
*)&ifra
.ifra_broadaddr
,
499 (struct sockaddr_in
*)&ifra
.ifra_dstaddr
, 0 /*flags*/);
502 if ((r
= ifaddr_v4_find(ifdev
,
503 (struct sockaddr_in
*)&ifra
.ifra_addr
, &num
)) != OK
)
507 * The broadcast and destination address are stored in the same
508 * ifaliasreq field. We cannot pass a pointer to the same
509 * field to ifaddr_v4_get(). So, use a temporary variable.
511 (void)ifaddr_v4_get(ifdev
, num
,
512 (struct sockaddr_in
*)&ifra
.ifra_addr
,
513 (struct sockaddr_in
*)&ifra
.ifra_mask
,
514 (struct sockaddr_in
*)&ifra
.ifra_broadaddr
, &dest
);
516 if (ifra
.ifra_broadaddr
.sa_len
== 0)
517 memcpy(&ifra
.ifra_dstaddr
, &dest
, sizeof(dest
));
519 return sockdriver_copyout(data
, 0, &ifra
, sizeof(ifra
));
527 * Process an IOCTL request for AF_INET.
530 ifconf_ioctl_v4(unsigned long request
, const struct sockdriver_data
* data
,
531 endpoint_t user_endpt
)
540 if (!util_is_root(user_endpt
))
548 case SIOCGIFAFLAG_IN
:
549 return ifconf_ioctl_v4_ifreq(request
, data
);
552 if (!util_is_root(user_endpt
))
557 return ifconf_ioctl_v4_ifalias(request
, data
);
566 * Process an IOCTL request for AF_INET6 with an "in6_ifreq" structure.
569 ifconf_ioctl_v6_ifreq(unsigned long request
,
570 const struct sockdriver_data
* data
)
573 struct in6_ifreq ifr
;
577 if ((r
= sockdriver_copyin(data
, 0, &ifr
, sizeof(ifr
))) != OK
)
580 ifr
.ifr_name
[sizeof(ifr
.ifr_name
) - 1] = '\0';
582 if ((ifdev
= ifdev_find_by_name(ifr
.ifr_name
)) == NULL
)
585 if ((r
= ifaddr_v6_find(ifdev
, &ifr
.ifr_addr
, &num
)) != OK
)
589 case SIOCGIFADDR_IN6
:
590 /* This IOCTL basically checks if the given address exists. */
591 ifaddr_v6_get(ifdev
, num
, &ifr
.ifr_addr
, NULL
, NULL
);
593 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
595 case SIOCDIFADDR_IN6
:
596 ifaddr_v6_del(ifdev
, num
);
600 case SIOCGIFNETMASK_IN6
:
601 ifaddr_v6_get(ifdev
, num
, NULL
, &ifr
.ifr_addr
, NULL
);
603 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
605 case SIOCGIFAFLAG_IN6
:
606 ifr
.ifr_ifru
.ifru_flags6
= ifaddr_v6_get_flags(ifdev
, num
);
608 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
610 case SIOCGIFALIFETIME_IN6
:
611 ifaddr_v6_get_lifetime(ifdev
, num
,
612 &ifr
.ifr_ifru
.ifru_lifetime
);
614 return sockdriver_copyout(data
, 0, &ifr
, sizeof(ifr
));
622 * Process an IOCTL request for AF_INET6 with an "in6_aliasreq" structure.
625 ifconf_ioctl_v6_ifalias(unsigned long request
,
626 const struct sockdriver_data
* data
)
629 struct in6_aliasreq ifra
;
632 if ((r
= sockdriver_copyin(data
, 0, &ifra
, sizeof(ifra
))) != OK
)
635 ifra
.ifra_name
[sizeof(ifra
.ifra_name
) - 1] = '\0';
637 if ((ifdev
= ifdev_find_by_name(ifra
.ifra_name
)) == NULL
)
641 case SIOCAIFADDR_IN6
:
642 return ifaddr_v6_add(ifdev
, &ifra
.ifra_addr
,
643 &ifra
.ifra_prefixmask
, &ifra
.ifra_dstaddr
,
644 ifra
.ifra_flags
, &ifra
.ifra_lifetime
);
652 * Process an IOCTL request for AF_INET6 with an "in6_ndireq" structure.
655 ifconf_ioctl_v6_ndireq(unsigned long request
,
656 const struct sockdriver_data
* data
)
659 struct in6_ndireq ndi
;
662 if ((r
= sockdriver_copyin(data
, 0, &ndi
, sizeof(ndi
))) != OK
)
665 ndi
.ifname
[sizeof(ndi
.ifname
) - 1] = '\0';
667 if ((ifdev
= ifdev_find_by_name(ndi
.ifname
)) == NULL
)
671 case SIOCGIFINFO_IN6
:
672 memset(&ndi
.ndi
, 0, sizeof(ndi
.ndi
));
674 ndi
.ndi
.linkmtu
= ifdev_get_mtu(ifdev
);
675 ndi
.ndi
.flags
= ifdev_get_nd6flags(ifdev
);
676 ndi
.ndi
.initialized
= 1;
677 /* TODO: all the other fields.. */
679 return sockdriver_copyout(data
, 0, &ndi
, sizeof(ndi
));
681 case SIOCSIFINFO_IN6
:
682 /* TODO: all the other fields.. */
685 case SIOCSIFINFO_FLAGS
:
686 return ifdev_set_nd6flags(ifdev
, ndi
.ndi
.flags
);
694 * Process an IOCTL request for AF_INET6 with an "in6_nbrinfo" structure.
697 ifconf_ioctl_v6_nbrinfo(unsigned long request
,
698 const struct sockdriver_data
* data
)
701 struct sockaddr_in6 addr
;
702 struct in6_nbrinfo nbri
;
703 lldata_ndp_num_t num
;
706 if ((r
= sockdriver_copyin(data
, 0, &nbri
, sizeof(nbri
))) != OK
)
709 nbri
.ifname
[sizeof(nbri
.ifname
) - 1] = '\0';
711 if ((ifdev
= ifdev_find_by_name(nbri
.ifname
)) == NULL
)
715 case SIOCGNBRINFO_IN6
:
717 * Convert the given in6_addr to a full sockaddr_in6, mainly
718 * for internal consistency. It would have been nice if the
719 * KAME management API had had any sort of consistency itself.
721 memset(&addr
, 0, sizeof(addr
));
722 addr
.sin6_family
= AF_INET6
;
723 memcpy(&addr
.sin6_addr
.s6_addr
, &nbri
.addr
,
724 sizeof(addr
.sin6_addr
.s6_addr
));
726 if ((r
= lldata_ndp_find(ifdev
, &addr
, &num
)) != OK
)
729 lldata_ndp_get_info(num
, &nbri
.asked
, &nbri
.isrouter
,
730 &nbri
.state
, &nbri
.expire
);
732 return sockdriver_copyout(data
, 0, &nbri
, sizeof(nbri
));
740 * Process an IOCTL request for AF_INET6.
743 ifconf_ioctl_v6(unsigned long request
, const struct sockdriver_data
* data
,
744 endpoint_t user_endpt
)
748 case SIOCDIFADDR_IN6
:
749 if (!util_is_root(user_endpt
))
753 case SIOCGIFADDR_IN6
:
754 case SIOCGIFNETMASK_IN6
:
755 case SIOCGIFAFLAG_IN6
:
756 case SIOCGIFALIFETIME_IN6
:
757 return ifconf_ioctl_v6_ifreq(request
, data
);
759 case SIOCAIFADDR_IN6
:
760 if (!util_is_root(user_endpt
))
763 return ifconf_ioctl_v6_ifalias(request
, data
);
765 case SIOCSIFINFO_IN6
:
766 case SIOCSIFINFO_FLAGS
:
767 if (!util_is_root(user_endpt
))
771 case SIOCGIFINFO_IN6
:
772 return ifconf_ioctl_v6_ndireq(request
, data
);
774 case SIOCGNBRINFO_IN6
:
775 return ifconf_ioctl_v6_nbrinfo(request
, data
);
784 * Process an IOCTL request for AF_LINK with an "if_laddrreq" structure.
787 ifconf_ioctl_dl_lifaddr(unsigned long request
,
788 const struct sockdriver_data
* data
)
791 struct if_laddrreq iflr
;
795 if ((r
= sockdriver_copyin(data
, 0, &iflr
, sizeof(iflr
))) != OK
)
798 iflr
.iflr_name
[sizeof(iflr
.iflr_name
) - 1] = '\0';
800 if ((ifdev
= ifdev_find_by_name(iflr
.iflr_name
)) == NULL
)
805 if (iflr
.flags
& IFLR_PREFIX
) {
806 /* We ignore the prefix length, like NetBSD does. */
807 if ((r
= ifaddr_dl_find(ifdev
,
808 (struct sockaddr_dlx
*)&iflr
.addr
,
809 sizeof(iflr
.addr
), &num
)) != OK
)
812 num
= (ifaddr_dl_num_t
)0; /* this always works */
814 ifaddr_dl_get(ifdev
, num
, (struct sockaddr_dlx
*)&iflr
.addr
);
815 iflr
.flags
= ifaddr_dl_get_flags(ifdev
, num
);
816 memset(&iflr
.dstaddr
, 0, sizeof(iflr
.dstaddr
));
818 return sockdriver_copyout(data
, 0, &iflr
, sizeof(iflr
));
821 return ifaddr_dl_add(ifdev
, (struct sockaddr_dlx
*)&iflr
.addr
,
822 sizeof(iflr
.addr
), iflr
.flags
);
825 if ((r
= ifaddr_dl_find(ifdev
,
826 (struct sockaddr_dlx
*)&iflr
.addr
, sizeof(iflr
.addr
),
830 return ifaddr_dl_del(ifdev
, num
);
838 * Process an IOCTL request for AF_LINK.
841 ifconf_ioctl_dl(unsigned long request
, const struct sockdriver_data
* data
,
842 endpoint_t user_endpt
)
848 if (!util_is_root(user_endpt
))
853 return ifconf_ioctl_dl_lifaddr(request
, data
);
861 * Process an IOCTL request. This routine is shared between TCP, UDP, RAW, and
862 * link sockets. The given socket may be used to obtain the target domain:
863 * AF_INET, AF_INET6, or AF_LINK.
866 ifconf_ioctl(struct sock
* sock
, unsigned long request
,
867 const struct sockdriver_data
* data
, endpoint_t user_endpt
)
871 domain
= sockevent_get_domain(sock
);
880 if (!util_is_root(user_endpt
))
889 return ifconf_ioctl_ifreq(request
, data
);
892 if (!util_is_root(user_endpt
))
897 return ifconf_ioctl_ifcap(request
, data
);
899 case MINIX_SIOCGIFMEDIA
:
900 return ifconf_ioctl_ifmedia(request
, data
);
902 case MINIX_SIOCIFGCLONERS
:
903 return ifconf_ioctl_ifclone(request
, data
);
905 case SIOCSIFADDRPREF
:
906 if (!util_is_root(user_endpt
))
910 case SIOCGIFADDRPREF
:
911 return ifconf_ioctl_ifaddrpref(request
, data
);
916 return ifconf_ioctl_v4(request
, data
, user_endpt
);
920 return ifconf_ioctl_v6(request
, data
, user_endpt
);
924 return ifconf_ioctl_dl(request
, data
, user_endpt
);