undo interface address addition, if in_ifinit fails.
authoritojun <itojun@openbsd.org>
Sun, 12 Mar 2000 06:46:31 +0000 (06:46 +0000)
committeritojun <itojun@openbsd.org>
Sun, 12 Mar 2000 06:46:31 +0000 (06:46 +0000)
sys/netinet/in.c

index 7d3e5b7..0f02f4c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in.c,v 1.15 2000/01/04 21:38:56 fgsch Exp $   */
+/*     $OpenBSD: in.c,v 1.16 2000/03/12 06:46:31 itojun Exp $  */
 /*     $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
 
 /*
@@ -195,6 +195,7 @@ in_control(so, cmd, data, ifp)
        struct in_aliasreq *ifra = (struct in_aliasreq *)data;
        struct sockaddr_in oldaddr;
        int error, hostIsNew, maskIsNew;
+       int newifaddr;
 
 #if NGIF > 0
        if (ifp && ifp->if_type == IFT_GIF) {
@@ -272,7 +273,10 @@ in_control(so, cmd, data, ifp)
                        LIST_INIT(&ia->ia_multiaddrs);
                        if ((ifp->if_flags & IFF_LOOPBACK) == 0)
                                in_interfaces++;
-               }
+
+                       newifaddr = 1;
+               } else
+                       newifaddr = 0;
                break;
 
        case SIOCSIFBRDADDR:
@@ -347,7 +351,16 @@ in_control(so, cmd, data, ifp)
                break;
 
        case SIOCSIFADDR:
-               return (in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1));
+               error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1);
+  undo:
+               if (error && newifaddr){
+                       TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
+                       TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
+                       FREE(ia, M_IFADDR);
+                       if ((ifp->if_flags & IFF_LOOPBACK) == 0)
+                               in_interfaces--;
+               }
+               return error;
 
        case SIOCSIFNETMASK:
                ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr =
@@ -379,8 +392,11 @@ in_control(so, cmd, data, ifp)
                        maskIsNew  = 1; /* We lie; but the effect's the same */
                }
                if (ifra->ifra_addr.sin_family == AF_INET &&
-                   (hostIsNew || maskIsNew))
+                   (hostIsNew || maskIsNew)) {
                        error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
+                       if (error)
+                               goto undo;
+               }
                if ((ifp->if_flags & IFF_BROADCAST) &&
                    (ifra->ifra_broadaddr.sin_family == AF_INET))
                        ia->ia_broadaddr = ifra->ifra_broadaddr;