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 *);