Index: sys/net/if.c =================================================================== --- sys/net/if.c +++ sys/net/if.c @@ -142,6 +142,18 @@ CTASSERT(sizeof(struct ifreq) == sizeof(struct ifreq32)); CTASSERT(__offsetof(struct ifreq, ifr_ifru) == __offsetof(struct ifreq32, ifr_ifru)); + +struct ifmediareq32 { + char ifm_name[IFNAMSIZ]; + int ifm_current; + int ifm_mask; + int ifm_status; + int ifm_active; + int ifm_count; + uint32_t ifm_ulist; /* (int *) */ +}; +#define SIOCGIFMEDIA32 _IOC_NEWTYPE(SIOCGIFMEDIA, struct ifmediareq32) +#define SIOCGIFXMEDIA32 _IOC_NEWTYPE(SIOCGIFXMEDIA, struct ifmediareq32) #endif union ifreq_union { @@ -2850,14 +2862,56 @@ #define SIOCGIFCONF32 _IOWR('i', 36, struct ifconf32) #endif +static void +ifmr_init(struct ifmediareq *ifmr, caddr_t data) +{ +#ifdef COMPAT_FREEBSD32 + struct ifmediareq32 *ifmr32; + + if (SV_CURPROC_FLAG(SV_ILP32)) { + ifmr32 = (struct ifmediareq32 *)data; + memcpy(ifmr->ifm_name, ifmr32->ifm_name, + sizeof(ifmr->ifm_name)); + ifmr->ifm_current = ifmr32->ifm_current; + ifmr->ifm_mask = ifmr32->ifm_mask; + ifmr->ifm_status = ifmr32->ifm_status; + ifmr->ifm_active = ifmr32->ifm_active; + ifmr->ifm_count = ifmr32->ifm_count; + ifmr->ifm_ulist = (int *)(uintptr_t)ifmr32->ifm_ulist; + } else +#endif + memcpy(ifmr, data, sizeof(struct ifmediareq)); +} + +static void +ifmr_update(const struct ifmediareq *ifmr, caddr_t data) +{ +#ifdef COMPAT_FREEBSD32 + struct ifmediareq32 *ifmr32; + + if (SV_CURPROC_FLAG(SV_ILP32)) { + ifmr32 = (struct ifmediareq32 *)data; + ifmr32->ifm_current = ifmr->ifm_current; + ifmr32->ifm_mask = ifmr->ifm_mask; + ifmr32->ifm_status = ifmr->ifm_status; + ifmr32->ifm_active = ifmr->ifm_active; + ifmr32->ifm_count = ifmr->ifm_count; + } else +#endif + memcpy(data, ifmr, sizeof(struct ifmediareq)); +} + /* * Interface ioctls. */ int ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) { + caddr_t saved_data; + struct ifmediareq *ifmr; struct ifnet *ifp; struct ifreq *ifr; + u_long saved_cmd; int error; int oif_flags; #ifdef VIMAGE @@ -2900,9 +2954,25 @@ } #endif } - ifr = (struct ifreq *)data; switch (cmd) { + case SIOCGIFMEDIA: + case SIOCGIFXMEDIA: +#ifdef COMPAT_FREEBSD32 + case SIOCGIFMEDIA32: + case SIOCGIFXMEDIA32: +#endif + ifmr = malloc(sizeof(struct ifmediareq), M_TEMP, + M_WAITOK | M_ZERO); + ifmr_init(ifmr, data); + saved_cmd = cmd; + cmd = _IOC_NEWTYPE(cmd, struct ifmediareq); + saved_data = data; + data = (caddr_t)ifmr; + } + + ifr = (struct ifreq *)data; + switch (cmd) { #ifdef VIMAGE case SIOCSIFRVNET: error = priv_check(td, PRIV_NET_SETIFVNET); @@ -2990,6 +3060,14 @@ in6_if_up(ifp); #endif } + + if (cmd == SIOCGIFMEDIA) { + data = saved_data; + cmd = saved_cmd; + ifmr_update(ifmr, data); + free(ifmr, M_TEMP); + } + if_rele(ifp); CURVNET_RESTORE(); return (error);