manage IFA_ROUTE on interface address better, so that we can
provide a better support for multiple address with the same prefix better. (like 10.0.0.1/8 and 10.0.0.2/8 on the same interface) continuation of PR 13311. remove irrelevant #if 0'ed segment for PR 10427.
This commit is contained in:
parent
71aa31a75a
commit
6338419cfb
156
sys/netinet/in.c
156
sys/netinet/in.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in.c,v 1.66 2001/04/13 23:30:22 thorpej Exp $ */
|
||||
/* $NetBSD: in.c,v 1.67 2001/07/22 16:18:31 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -133,6 +133,9 @@ static void in_len2mask __P((struct in_addr *, int));
|
|||
static int in_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
|
||||
struct ifnet *, struct proc *));
|
||||
|
||||
static int in_addprefix __P((struct in_ifaddr *, int));
|
||||
static int in_scrubprefix __P((struct in_ifaddr *));
|
||||
|
||||
#ifndef SUBNETSARELOCAL
|
||||
#define SUBNETSARELOCAL 1
|
||||
#endif
|
||||
|
@ -460,22 +463,6 @@ in_control(so, cmd, data, ifp, p)
|
|||
|
||||
case SIOCSIFADDR:
|
||||
error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1);
|
||||
#if 0
|
||||
/*
|
||||
* the code chokes if we are to assign multiple addresses with
|
||||
* the same address prefix (rtinit() will return EEXIST, which
|
||||
* is not fatal actually). we will get memory leak if we
|
||||
* don't do it.
|
||||
* -> we may want to hide EEXIST from rtinit().
|
||||
*/
|
||||
undo:
|
||||
if (error && newifaddr) {
|
||||
TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
|
||||
IFAFREE(&ia->ia_ifa);
|
||||
TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
|
||||
IFAFREE(&ia->ia_ifa);
|
||||
}
|
||||
#endif
|
||||
return error;
|
||||
|
||||
case SIOCSIFNETMASK:
|
||||
|
@ -509,10 +496,6 @@ in_control(so, cmd, data, ifp, p)
|
|||
if (ifra->ifra_addr.sin_family == AF_INET &&
|
||||
(hostIsNew || maskIsNew)) {
|
||||
error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
|
||||
#if 0
|
||||
if (error)
|
||||
goto undo;
|
||||
#endif
|
||||
}
|
||||
if ((ifp->if_flags & IFF_BROADCAST) &&
|
||||
(ifra->ifra_broadaddr.sin_family == AF_INET))
|
||||
|
@ -787,13 +770,7 @@ in_ifscrub(ifp, ia)
|
|||
struct in_ifaddr *ia;
|
||||
{
|
||||
|
||||
if ((ia->ia_flags & IFA_ROUTE) == 0)
|
||||
return;
|
||||
if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
|
||||
rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
|
||||
else
|
||||
rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
|
||||
ia->ia_flags &= ~IFA_ROUTE;
|
||||
in_scrubprefix(ia);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -874,12 +851,7 @@ in_ifinit(ifp, ia, sin, scrub)
|
|||
return (0);
|
||||
flags |= RTF_HOST;
|
||||
}
|
||||
error = rtinit(&ia->ia_ifa, (int)RTM_ADD, flags);
|
||||
if (!error)
|
||||
ia->ia_flags |= IFA_ROUTE;
|
||||
/* XXX check if the subnet route points to the same interface */
|
||||
if (error == EEXIST)
|
||||
error = 0;
|
||||
error = in_addprefix(ia, flags);
|
||||
/*
|
||||
* recover multicast kludge entry, if there is.
|
||||
*/
|
||||
|
@ -906,6 +878,122 @@ bad:
|
|||
return (error);
|
||||
}
|
||||
|
||||
#define rtinitflags(x) \
|
||||
(((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) && \
|
||||
(x)->ia_dstaddr.sin_family == AF_INET) ? RTF_HOST : 0)
|
||||
|
||||
/*
|
||||
* add a route to prefix ("connected route" in cisco terminology).
|
||||
* does nothing if there's some interface address with the same prefix already.
|
||||
*/
|
||||
static int
|
||||
in_addprefix(target, flags)
|
||||
struct in_ifaddr *target;
|
||||
int flags;
|
||||
{
|
||||
struct in_ifaddr *ia;
|
||||
struct in_addr prefix, mask, p;
|
||||
int error;
|
||||
|
||||
if ((flags & RTF_HOST) != 0)
|
||||
prefix = target->ia_dstaddr.sin_addr;
|
||||
else
|
||||
prefix = target->ia_addr.sin_addr;
|
||||
mask = target->ia_sockmask.sin_addr;
|
||||
prefix.s_addr &= mask.s_addr;
|
||||
|
||||
for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) {
|
||||
/* easy one first */
|
||||
if (mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
|
||||
continue;
|
||||
|
||||
if (rtinitflags(ia))
|
||||
p = ia->ia_dstaddr.sin_addr;
|
||||
else
|
||||
p = ia->ia_addr.sin_addr;
|
||||
p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
|
||||
if (prefix.s_addr != p.s_addr)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* if we got a matching prefix route inserted by other
|
||||
* interface adderss, we don't need to bother
|
||||
*/
|
||||
if (ia->ia_flags & IFA_ROUTE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* noone seem to have prefix route. insert it.
|
||||
*/
|
||||
error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
|
||||
if (!error)
|
||||
target->ia_flags |= IFA_ROUTE;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove a route to prefix ("connected route" in cisco terminology).
|
||||
* re-installs the route by using another interface address, if there's one
|
||||
* with the same prefix (otherwise we lose the route mistakenly).
|
||||
*/
|
||||
static int
|
||||
in_scrubprefix(target)
|
||||
struct in_ifaddr *target;
|
||||
{
|
||||
struct in_ifaddr *ia;
|
||||
struct in_addr prefix, mask, p;
|
||||
int error;
|
||||
|
||||
if ((target->ia_flags & IFA_ROUTE) == 0)
|
||||
return 0;
|
||||
|
||||
if (rtinitflags(target))
|
||||
prefix = target->ia_dstaddr.sin_addr;
|
||||
else
|
||||
prefix = target->ia_addr.sin_addr;
|
||||
mask = target->ia_sockmask.sin_addr;
|
||||
prefix.s_addr &= mask.s_addr;
|
||||
|
||||
for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) {
|
||||
/* easy one first */
|
||||
if (mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
|
||||
continue;
|
||||
|
||||
if (rtinitflags(ia))
|
||||
p = ia->ia_dstaddr.sin_addr;
|
||||
else
|
||||
p = ia->ia_addr.sin_addr;
|
||||
p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
|
||||
if (prefix.s_addr != p.s_addr)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* if we got a matching prefix route, move IFA_ROUTE to him
|
||||
*/
|
||||
if ((ia->ia_flags & IFA_ROUTE) == 0) {
|
||||
rtinit(&(target->ia_ifa), (int)RTM_DELETE,
|
||||
rtinitflags(target));
|
||||
target->ia_flags &= ~IFA_ROUTE;
|
||||
|
||||
error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
|
||||
rtinitflags(ia) | RTF_UP);
|
||||
if (error == 0)
|
||||
ia->ia_flags |= IFA_ROUTE;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* noone seem to have prefix route. remove it.
|
||||
*/
|
||||
rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
|
||||
target->ia_flags &= ~IFA_ROUTE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef rtinitflags
|
||||
|
||||
/*
|
||||
* Return 1 if the address might be a local broadcast address.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue