Call if_up(), if in_ifinit() brings interface up (via ifp->if_ioctl).
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 28 Dec 2008 05:31:41 +0000 (13:31 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 31 Dec 2008 10:14:41 +0000 (18:14 +0800)
This is done no matter whether the address assignment fails or not.

This commit is intend to fix following case:

ifconfig iface0 192.168.5.1
ifconfig iface0 down
ifconfig iface0 alias 192.168.6.1

Before this commit, 192.168.5.0/24 prefix route will not be installed.

sys/netinet/in.c

index e802bb8..979324c 100644 (file)
@@ -454,10 +454,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 +488,9 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp,
                                }
                        }
                }
+
+               if (ifp->if_flags & IFF_UP)
+                       ifpWasUp = 1;
        }
 
        switch (cmd) {
@@ -643,6 +647,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 +704,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 +763,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);
 }