sigh. whoever wrote that co^Wmess^Wdesaster better never gets close to
me, physically. 

the below doesn't break on 0.0.0.0 any more. problem found by sthen
with pppoe.

note to self: diff is in the main tree on luke

Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.225
diff -u -p -r1.225 if.c
--- net/if.c    27 Aug 2010 17:08:01 -0000      1.225
+++ net/if.c    23 Sep 2010 02:41:12 -0000
@@ -2196,6 +2196,12 @@ ifa_del(struct ifnet *ifp, struct ifaddr
        TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
 }
 
+void
+ifa_update_broadaddr(struct ifnet *ifp, struct ifaddr *ifa, struct sockaddr 
*sa)
+{
+       ifa->ifa_broadaddr = sa;
+}
+
 int
 ifai_cmp(struct ifaddr_item *a, struct ifaddr_item *b)
 {
@@ -2210,6 +2216,8 @@ ifa_item_insert(struct sockaddr *sa, str
 {
        struct ifaddr_item      *ifai, *p;
 
+       if (!sa->sa_family)
+               return;
        ifai = pool_get(&ifaddr_item_pl, PR_WAITOK);
        ifai->ifai_addr = sa;
        ifai->ifai_ifa = ifa;
Index: net/if.h
===================================================================
RCS file: /cvs/src/sys/net/if.h,v
retrieving revision 1.118
diff -u -p -r1.118 if.h
--- net/if.h    27 Aug 2010 17:08:01 -0000      1.118
+++ net/if.h    23 Sep 2010 02:41:12 -0000
@@ -848,5 +848,7 @@ int looutput(struct ifnet *,
 void   lortrequest(int, struct rtentry *, struct rt_addrinfo *);
 void   ifa_add(struct ifnet *, struct ifaddr *);
 void   ifa_del(struct ifnet *, struct ifaddr *);
+void   ifa_update_broadaddr(struct ifnet *, struct ifaddr *,
+           struct sockaddr *);
 #endif /* _KERNEL */
 #endif /* _NET_IF_H_ */
Index: net/if_spppsubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_spppsubr.c,v
retrieving revision 1.82
diff -u -p -r1.82 if_spppsubr.c
--- net/if_spppsubr.c   13 Sep 2010 08:53:06 -0000      1.82
+++ net/if_spppsubr.c   23 Sep 2010 02:41:12 -0000
@@ -4743,7 +4743,7 @@ sppp_set_ip_addrs(struct sppp *sp, u_int
                                *dest = new_dst; /* fix dstaddr in place */
                        }
                }
-               if (!(error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 0)))
+               if (!(error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 0, 0)))
                        dohooks(ifp->if_addrhooks, 0);
                if (debug && error) {
                        log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addrs: in_ifinit "
@@ -4795,7 +4795,7 @@ sppp_clear_ip_addrs(struct sppp *sp)
                if (sp->ipcp.flags & IPCP_HISADDR_DYN)
                        /* replace peer addr in place */
                        dest->sin_addr.s_addr = sp->ipcp.saved_hisaddr;
-               if (!in_ifinit(ifp, ifatoia(ifa), &new_sin, 0))
+               if (!in_ifinit(ifp, ifatoia(ifa), &new_sin, 0, 0))
                        dohooks(ifp->if_addrhooks, 0);
                sppp_update_gw(ifp);
        }
Index: netinet/in.c
===================================================================
RCS file: /cvs/src/sys/netinet/in.c,v
retrieving revision 1.60
diff -u -p -r1.60 in.c
--- netinet/in.c        13 Jan 2010 10:45:21 -0000      1.60
+++ netinet/in.c        23 Sep 2010 02:41:12 -0000
@@ -271,7 +271,6 @@ in_control(so, cmd, data, ifp)
                        LIST_INIT(&ia->ia_multiaddrs);
                        if ((ifp->if_flags & IFF_LOOPBACK) == 0)
                                in_interfaces++;
-                       ifa_add(ifp, (struct ifaddr *)ia);
                        splx(s);
 
                        newifaddr = 1;
@@ -351,12 +350,14 @@ in_control(so, cmd, data, ifp)
        case SIOCSIFBRDADDR:
                if ((ifp->if_flags & IFF_BROADCAST) == 0)
                        return (EINVAL);
-               ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr);
+               ifa_update_broadaddr(ifp, (struct ifaddr *)ia,
+                   &ifr->ifr_broadaddr);
                break;
 
        case SIOCSIFADDR:
                s = splsoftnet();
-               error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1);
+               error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1,
+                   newifaddr);
                if (!error)
                        dohooks(ifp->if_addrhooks, 0);
                else if (newifaddr) {
@@ -396,13 +397,14 @@ in_control(so, cmd, data, ifp)
                        ia->ia_dstaddr = ifra->ifra_dstaddr;
                        maskIsNew  = 1; /* We lie; but the effect's the same */
                }
-               if (ifra->ifra_addr.sin_family == AF_INET &&
-                   (hostIsNew || maskIsNew)) {
-                       error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
-               }
                if ((ifp->if_flags & IFF_BROADCAST) &&
                    (ifra->ifra_broadaddr.sin_family == AF_INET))
                        ia->ia_broadaddr = ifra->ifra_broadaddr;
+               if (ifra->ifra_addr.sin_family == AF_INET &&
+                   (hostIsNew || maskIsNew)) {
+                       error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0,
+                           newifaddr);
+               }
                if (!error)
                        dohooks(ifp->if_addrhooks, 0);
                else if (newifaddr) {
@@ -652,18 +654,22 @@ in_ifscrub(ifp, ia)
  * and routing table entry.
  */
 int
-in_ifinit(ifp, ia, sin, scrub)
+in_ifinit(ifp, ia, sin, scrub, newaddr)
        struct ifnet *ifp;
        struct in_ifaddr *ia;
        struct sockaddr_in *sin;
        int scrub;
+       int newaddr;
 {
        u_int32_t i = sin->sin_addr.s_addr;
        struct sockaddr_in oldaddr;
        int s = splnet(), flags = RTF_UP, error;
 
+       if (!newaddr)
+               ifa_del(ifp, (struct ifaddr *)ia);
        oldaddr = ia->ia_addr;
        ia->ia_addr = *sin;
+
        /*
         * Give the interface a chance to initialize
         * if this is its first address,
@@ -719,6 +725,7 @@ in_ifinit(ifp, ia, sin, scrub)
                flags |= RTF_HOST;
        }
        error = in_addprefix(ia, flags);
+
        /*
         * If the interface supports multicast, join the "all hosts"
         * multicast group on that interface.
@@ -729,6 +736,9 @@ in_ifinit(ifp, ia, sin, scrub)
                addr.s_addr = INADDR_ALLHOSTS_GROUP;
                ia->ia_allhosts = in_addmulti(&addr, ifp);
        }
+
+       ifa_add(ifp, (struct ifaddr *)ia);
+
        return (error);
 }
 
Index: netinet/in_var.h
===================================================================
RCS file: /cvs/src/sys/netinet/in_var.h,v
retrieving revision 1.15
diff -u -p -r1.15 in_var.h
--- netinet/in_var.h    13 Jan 2010 07:05:28 -0000      1.15
+++ netinet/in_var.h    23 Sep 2010 02:41:12 -0000
@@ -207,7 +207,7 @@ do {                                                        
                \
 } while (/* CONSTCOND */ 0)
 
 int    in_ifinit(struct ifnet *,
-           struct in_ifaddr *, struct sockaddr_in *, int);
+           struct in_ifaddr *, struct sockaddr_in *, int, int);
 struct in_multi *in_addmulti(struct in_addr *, struct ifnet *);
 void   in_delmulti(struct in_multi *);
 void   in_ifscrub(struct ifnet *, struct in_ifaddr *);

Reply via email to