o Make rt_check() return a locked rtentry.

o Make rt_check() function more strict:
  - rt0 passed to rt_check() must not be NULL, assert this.
  - rt returned by rt_check() must be valid locked rtentry,
    if no error occured.
o Modify callers, so that they never pass NULL rt0
  to rt_check().
o Modify callers, so that they unlock rtentry.

Revisions merged:

net/if_atmsubr.c	- 1.39, 1.41
net/if_fwsubr.c		- 1.13, 1.15
net/if_iso88025subr.c	- 1.69, 1.71
net/route.c		- 1.110, 1.111
netinet6/nd6.c		- 1.51-1.53

netinet/if_ether.c intentionally not touched by this merge.

Approved by:	re (kensmith)
This commit is contained in:
glebius 2005-08-18 10:12:42 +00:00
parent 922265190b
commit 6f71a877bf
5 changed files with 77 additions and 63 deletions

View File

@ -151,13 +151,16 @@ atm_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
case AF_INET:
case AF_INET6:
{
struct rtentry *rt;
struct rtentry *rt = NULL;
/*
* check route
*/
error = rt_check(&rt, &rt0, dst);
if (error)
goto bad;
if (rt0 != NULL) {
error = rt_check(&rt, &rt0, dst);
if (error)
goto bad;
RT_UNLOCK(rt);
}
if (dst->sa_family == AF_INET6)
etype = ETHERTYPE_IPV6;

View File

@ -81,7 +81,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
{
struct fw_com *fc = IFP2FC(ifp);
int error, type;
struct rtentry *rt;
struct rtentry *rt = NULL;
struct m_tag *mtag;
union fw_encap *enc;
struct fw_hwaddr *destfw;
@ -102,9 +102,12 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
goto bad;
}
error = rt_check(&rt, &rt0, dst);
if (error)
goto bad;
if (rt0 != NULL) {
error = rt_check(&rt, &rt0, dst);
if (error)
goto bad;
RT_UNLOCK(rt);
}
/*
* For unicast, we make a tag to store the lladdr of the

View File

@ -243,7 +243,7 @@ iso88025_output(ifp, m, dst, rt0)
struct iso88025_header *th;
struct iso88025_header gen_th;
struct sockaddr_dl *sdl = NULL;
struct rtentry *rt;
struct rtentry *rt = NULL;
#ifdef MAC
error = mac_check_ifnet_transmit(ifp, m);
@ -259,9 +259,12 @@ iso88025_output(ifp, m, dst, rt0)
/* Calculate routing info length based on arp table entry */
/* XXX any better way to do this ? */
error = rt_check(&rt, &rt0, dst);
if (error)
goto bad;
if (rt0 != NULL) {
error = rt_check(&rt, &rt0, dst);
if (error)
goto bad;
RT_UNLOCK(rt);
}
if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway))
if (SDL_ISO88025(sdl)->trld_rcf != 0)

View File

@ -1262,51 +1262,52 @@ rt_check(struct rtentry **lrt, struct rtentry **lrt0, struct sockaddr *dst)
struct rtentry *rt0;
int error;
rt0 = *lrt0;
rt = rt0;
if (rt) {
/* NB: the locking here is tortuous... */
RT_LOCK(rt);
if ((rt->rt_flags & RTF_UP) == 0) {
RT_UNLOCK(rt);
rt = rtalloc1(dst, 1, 0UL);
if (rt != NULL) {
RT_REMREF(rt);
/* XXX what about if change? */
} else
senderr(EHOSTUNREACH);
rt0 = rt;
}
/* XXX BSD/OS checks dst->sa_family != AF_NS */
if (rt->rt_flags & RTF_GATEWAY) {
if (rt->rt_gwroute == NULL)
goto lookup;
rt = rt->rt_gwroute;
RT_LOCK(rt); /* NB: gwroute */
if ((rt->rt_flags & RTF_UP) == 0) {
rtfree(rt); /* unlock gwroute */
rt = rt0;
lookup:
RT_UNLOCK(rt0);
rt = rtalloc1(rt->rt_gateway, 1, 0UL);
RT_LOCK(rt0);
rt0->rt_gwroute = rt;
if (rt == NULL) {
RT_UNLOCK(rt0);
senderr(EHOSTUNREACH);
}
}
RT_UNLOCK(rt0);
}
/* XXX why are we inspecting rmx_expire? */
error = (rt->rt_flags & RTF_REJECT) &&
(rt->rt_rmx.rmx_expire == 0 ||
time_second < rt->rt_rmx.rmx_expire);
KASSERT(*lrt0 != NULL, ("rt_check"));
rt = rt0 = *lrt0;
/* NB: the locking here is tortuous... */
RT_LOCK(rt);
if ((rt->rt_flags & RTF_UP) == 0) {
RT_UNLOCK(rt);
if (error)
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
rt = rtalloc1(dst, 1, 0UL);
if (rt != NULL) {
RT_REMREF(rt);
/* XXX what about if change? */
} else
senderr(EHOSTUNREACH);
rt0 = rt;
}
*lrt = rt; /* NB: return unlocked */
/* XXX BSD/OS checks dst->sa_family != AF_NS */
if (rt->rt_flags & RTF_GATEWAY) {
if (rt->rt_gwroute == NULL)
goto lookup;
rt = rt->rt_gwroute;
RT_LOCK(rt); /* NB: gwroute */
if ((rt->rt_flags & RTF_UP) == 0) {
rtfree(rt); /* unlock gwroute */
rt = rt0;
lookup:
RT_UNLOCK(rt0);
rt = rtalloc1(rt->rt_gateway, 1, 0UL);
RT_LOCK(rt0);
rt0->rt_gwroute = rt;
if (rt == NULL) {
RT_UNLOCK(rt0);
senderr(EHOSTUNREACH);
}
}
RT_UNLOCK(rt0);
}
/* XXX why are we inspecting rmx_expire? */
error = (rt->rt_flags & RTF_REJECT) &&
(rt->rt_rmx.rmx_expire == 0 ||
time_second < rt->rt_rmx.rmx_expire);
if (error) {
RT_UNLOCK(rt);
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
}
*lrt = rt;
*lrt0 = rt0;
return (0);
bad:

View File

@ -2043,11 +2043,13 @@ nd6_storelladdr(ifp, rt0, m, dst, desten)
struct sockaddr *dst;
u_char *desten;
{
int i;
struct sockaddr_dl *sdl;
struct rtentry *rt;
int error;
if (m->m_flags & M_MCAST) {
int i;
switch (ifp->if_type) {
case IFT_ETHER:
case IFT_FDDI:
@ -2078,17 +2080,19 @@ nd6_storelladdr(ifp, rt0, m, dst, desten)
}
}
i = rt_check(&rt, &rt0, dst);
if (i) {
m_freem(m);
return i;
}
if (rt == NULL) {
if (rt0 == NULL) {
/* this could happen, if we could not allocate memory */
m_freem(m);
return (ENOMEM);
}
error = rt_check(&rt, &rt0, dst);
if (error) {
m_freem(m);
return (error);
}
RT_UNLOCK(rt);
if (rt->rt_gateway->sa_family != AF_LINK) {
printf("nd6_storelladdr: something odd happens\n");
m_freem(m);