Use sa6_checkzone_ifp() to check user's input. Remove sa6_recoverscope() and sa6_embedscope() functions. --- sys/net/if_gif.c (svn+ssh://svn.freebsd.org/base/head) (revision 261548) +++ sys/net/if_gif.c (working copy) @@ -730,6 +730,10 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t d case AF_INET6: if (src->sa_len != sizeof(struct sockaddr_in6)) return EINVAL; + error = sa6_checkzone_ifp(ifp, + (struct sockaddr_in6 *)src); + if (error) + return (error); break; #endif default: @@ -746,6 +750,10 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t d case AF_INET6: if (dst->sa_len != sizeof(struct sockaddr_in6)) return EINVAL; + error = sa6_checkzone_ifp(ifp, + (struct sockaddr_in6 *)dst); + if (error) + return (error); break; #endif default: @@ -805,13 +813,6 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t d if (src->sa_len > size) return EINVAL; bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); -#ifdef INET6 - if (dst->sa_family == AF_INET6) { - error = sa6_recoverscope((struct sockaddr_in6 *)dst); - if (error != 0) - return (error); - } -#endif break; case SIOCGIFPDSTADDR: @@ -850,13 +851,6 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t d if (error != 0) return (error); bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); -#ifdef INET6 - if (dst->sa_family == AF_INET6) { - error = sa6_recoverscope((struct sockaddr_in6 *)dst); - if (error != 0) - return (error); - } -#endif break; case SIOCSIFFLAGS: @@ -965,16 +959,6 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr #endif #ifdef INET6 case AF_INET6: - /* - * Check validity of the scope zone ID of the addresses, and - * convert it into the kernel internal form if necessary. - */ - error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_psrc, 0); - if (error != 0) - break; - error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_pdst, 0); - if (error != 0) - break; error = in6_gif_attach(sc); break; #endif