X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/102e97f31733741a73135d716be6fb305e8842fd..8a27f1c965140ec72dd069582960c64ba9ecf534:/sys/netinet/in.c diff --git a/sys/netinet/in.c b/sys/netinet/in.c index e802bb8310..8693d696bb 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -230,7 +231,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, switch (cmd) { case SIOCALIFADDR: case SIOCDLIFADDR: - if (td && (error = suser(td)) != 0) + if (td && (error = priv_check(td, PRIV_ROOT)) != 0) return error; /* FALLTHROUGH */ case SIOCGLIFADDR: @@ -454,10 +455,11 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, struct ifaddr_container *ifac; struct in_ifaddr_container *iac; struct sockaddr_in oldaddr; - int hostIsNew, iaIsNew, maskIsNew; + int hostIsNew, iaIsNew, maskIsNew, ifpWasUp; int error = 0; iaIsNew = 0; + ifpWasUp = 0; /* * Find address for this interface, if it exists. @@ -487,6 +489,9 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, } } } + + if (ifp->if_flags & IFF_UP) + ifpWasUp = 1; } switch (cmd) { @@ -514,7 +519,7 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, case SIOCSIFADDR: case SIOCSIFNETMASK: case SIOCSIFDSTADDR: - if (td && (error = suser(td)) != 0) + if (td && (error = priv_check(td, PRIV_ROOT)) != 0) return error; if (ifp == NULL) @@ -569,7 +574,7 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, break; case SIOCSIFBRDADDR: - if (td && (error = suser(td)) != 0) + if (td && (error = priv_check(td, PRIV_ROOT)) != 0) return error; /* FALLTHROUGH */ @@ -643,6 +648,14 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, iaIsNew ? IFADDR_EVENT_ADD : IFADDR_EVENT_CHANGE, &ia->ia_ifa); } + if (!ifpWasUp && (ifp->if_flags & IFF_UP)) { + /* + * Interface is brought up by in_ifinit() + * (via ifp->if_ioctl). We act as if the + * interface got IFF_UP flag turned on. + */ + if_up(ifp); + } return (0); case SIOCSIFNETMASK: @@ -692,6 +705,10 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, iaIsNew ? IFADDR_EVENT_ADD : IFADDR_EVENT_CHANGE, &ia->ia_ifa); } + if (!ifpWasUp && (ifp->if_flags & IFF_UP)) { + /* See the comment in SIOCSIFADDR */ + if_up(ifp); + } return (error); case SIOCDIFADDR: @@ -747,6 +764,24 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, ifa_destroy(&ia->ia_ifa); + if ((cmd == SIOCAIFADDR || cmd == SIOCSIFADDR) && + !ifpWasUp && (ifp->if_flags & IFF_UP)) { + /* + * Though the address assignment failed, the + * interface is brought up by in_ifinit() + * (via ifp->if_ioctl). With the hope that + * the interface has some valid addresses, we + * act as if IFF_UP flag was just set on the + * interface. + * + * NOTE: + * This could only be done after the failed + * address is unlinked from the global address + * list. + */ + if_up(ifp); + } + return (error); }