byebye in6_ifawithscope(). it was a function for old source

address selection.

Obtained from:	KAME
This commit is contained in:
ume 2003-11-05 17:19:31 +00:00
parent 4dcc0c992a
commit d2486e878b
2 changed files with 0 additions and 283 deletions

View File

@ -1858,288 +1858,6 @@ in6_prefixlen2mask(maskp, len)
maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
}
/*
* return the best address out of the same scope
*/
struct in6_ifaddr *
in6_ifawithscope(oifp, dst)
struct ifnet *oifp;
struct in6_addr *dst;
{
int dst_scope = in6_addrscope(dst), src_scope, best_scope = 0;
int blen = -1;
struct ifaddr *ifa;
struct ifnet *ifp;
struct in6_ifaddr *ifa_best = NULL;
u_int32_t dstzone, odstzone;
if (oifp == NULL) {
return (NULL);
}
if (in6_addr2zoneid(oifp, dst, &odstzone))
return (NULL);
/*
* We search for all addresses on all interfaces from the beginning.
* Comparing an interface with the outgoing interface will be done
* only at the final stage of tiebreaking.
*/
IFNET_RLOCK();
for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
{
/*
* We can never take an address that breaks the scope zone
* of the destination.
*/
if (in6_addr2zoneid(ifp, dst, &dstzone) || dstzone != odstzone)
continue;
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
{
int tlen = -1, dscopecmp, bscopecmp, matchcmp;
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
src_scope = in6_addrscope(IFA_IN6(ifa));
/*
* Don't use an address before completing DAD
* nor a duplicated address.
*/
if (((struct in6_ifaddr *)ifa)->ia6_flags &
IN6_IFF_NOTREADY)
continue;
/* XXX: is there any case to allow anycasts? */
if (((struct in6_ifaddr *)ifa)->ia6_flags &
IN6_IFF_ANYCAST)
continue;
if (((struct in6_ifaddr *)ifa)->ia6_flags &
IN6_IFF_DETACHED)
continue;
/*
* If this is the first address we find,
* keep it anyway.
*/
if (ifa_best == NULL)
goto replace;
/*
* ifa_best is never NULL beyond this line except
* within the block labeled "replace".
*/
/*
* If ifa_best has a smaller scope than dst and
* the current address has a larger one than
* (or equal to) dst, always replace ifa_best.
* Also, if the current address has a smaller scope
* than dst, ignore it unless ifa_best also has a
* smaller scope.
* Consequently, after the two if-clause below,
* the followings must be satisfied:
* (scope(src) < scope(dst) &&
* scope(best) < scope(dst))
* OR
* (scope(best) >= scope(dst) &&
* scope(src) >= scope(dst))
*/
if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0 &&
IN6_ARE_SCOPE_CMP(src_scope, dst_scope) >= 0)
goto replace; /* (A) */
if (IN6_ARE_SCOPE_CMP(src_scope, dst_scope) < 0 &&
IN6_ARE_SCOPE_CMP(best_scope, dst_scope) >= 0)
continue; /* (B) */
/*
* A deprecated address SHOULD NOT be used in new
* communications if an alternate (non-deprecated)
* address is available and has sufficient scope.
* RFC 2462, Section 5.5.4.
*/
if (((struct in6_ifaddr *)ifa)->ia6_flags &
IN6_IFF_DEPRECATED) {
/*
* Ignore any deprecated addresses if
* specified by configuration.
*/
if (!ip6_use_deprecated)
continue;
/*
* If we have already found a non-deprecated
* candidate, just ignore deprecated addresses.
*/
if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED)
== 0)
continue;
}
/*
* A non-deprecated address is always preferred
* to a deprecated one regardless of scopes and
* address matching (Note invariants ensured by the
* conditions (A) and (B) above.)
*/
if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) &&
(((struct in6_ifaddr *)ifa)->ia6_flags &
IN6_IFF_DEPRECATED) == 0)
goto replace;
/*
* When we use temporary addresses described in
* RFC 3041, we prefer temporary addresses to
* public autoconf addresses. Again, note the
* invariants from (A) and (B). Also note that we
* don't have any preference between static addresses
* and autoconf addresses (despite of whether or not
* the latter is temporary or public.)
*/
if (ip6_use_tempaddr) {
struct in6_ifaddr *ifat;
ifat = (struct in6_ifaddr *)ifa;
if ((ifa_best->ia6_flags &
(IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY))
== IN6_IFF_AUTOCONF &&
(ifat->ia6_flags &
(IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY))
== (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY)) {
goto replace;
}
if ((ifa_best->ia6_flags &
(IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY))
== (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY) &&
(ifat->ia6_flags &
(IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY))
== IN6_IFF_AUTOCONF) {
continue;
}
}
/*
* At this point, we have two cases:
* 1. we are looking at a non-deprecated address,
* and ifa_best is also non-deprecated.
* 2. we are looking at a deprecated address,
* and ifa_best is also deprecated.
* Also, we do not have to consider a case where
* the scope of if_best is larger(smaller) than dst and
* the scope of the current address is smaller(larger)
* than dst. Such a case has already been covered.
* Tiebreaking is done according to the following
* items:
* - the scope comparison between the address and
* dst (dscopecmp)
* - the scope comparison between the address and
* ifa_best (bscopecmp)
* - if the address match dst longer than ifa_best
* (matchcmp)
* - if the address is on the outgoing I/F (outI/F)
*
* Roughly speaking, the selection policy is
* - the most important item is scope. The same scope
* is best. Then search for a larger scope.
* Smaller scopes are the last resort.
* - A deprecated address is chosen only when we have
* no address that has an enough scope, but is
* prefered to any addresses of smaller scopes
* (this must be already done above.)
* - addresses on the outgoing I/F are preferred to
* ones on other interfaces if none of above
* tiebreaks. In the table below, the column "bI"
* means if the best_ifa is on the outgoing
* interface, and the column "sI" means if the ifa
* is on the outgoing interface.
* - If there is no other reasons to choose one,
* longest address match against dst is considered.
*
* The precise decision table is as follows:
* dscopecmp bscopecmp match bI oI | replace?
* N/A equal N/A Y N | No (1)
* N/A equal N/A N Y | Yes (2)
* N/A equal larger N/A | Yes (3)
* N/A equal !larger N/A | No (4)
* larger larger N/A N/A | No (5)
* larger smaller N/A N/A | Yes (6)
* smaller larger N/A N/A | Yes (7)
* smaller smaller N/A N/A | No (8)
* equal smaller N/A N/A | Yes (9)
* equal larger (already done at A above)
*/
dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
bscopecmp = IN6_ARE_SCOPE_CMP(src_scope, best_scope);
if (bscopecmp == 0) {
struct ifnet *bifp = ifa_best->ia_ifp;
if (bifp == oifp && ifp != oifp) /* (1) */
continue;
if (bifp != oifp && ifp == oifp) /* (2) */
goto replace;
/*
* Both bifp and ifp are on the outgoing
* interface, or both two are on a different
* interface from the outgoing I/F.
* now we need address matching against dst
* for tiebreaking.
*/
tlen = in6_matchlen(IFA_IN6(ifa), dst);
matchcmp = tlen - blen;
if (matchcmp > 0) /* (3) */
goto replace;
continue; /* (4) */
}
if (dscopecmp > 0) {
if (bscopecmp > 0) /* (5) */
continue;
goto replace; /* (6) */
}
if (dscopecmp < 0) {
if (bscopecmp > 0) /* (7) */
goto replace;
continue; /* (8) */
}
/* now dscopecmp must be 0 */
if (bscopecmp < 0)
goto replace; /* (9) */
replace:
ifa_best = (struct in6_ifaddr *)ifa;
blen = tlen >= 0 ? tlen :
in6_matchlen(IFA_IN6(ifa), dst);
best_scope = in6_addrscope(&ifa_best->ia_addr.sin6_addr);
}
}
IFNET_RUNLOCK();
/* count statistics for future improvements */
if (ifa_best == NULL)
ip6stat.ip6s_sources_none++;
else {
if (oifp == ifa_best->ia_ifp)
ip6stat.ip6s_sources_sameif[best_scope]++;
else
ip6stat.ip6s_sources_otherif[best_scope]++;
if (best_scope == dst_scope)
ip6stat.ip6s_sources_samescope[best_scope]++;
else
ip6stat.ip6s_sources_otherscope[best_scope]++;
if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) != 0)
ip6stat.ip6s_sources_deprecated[best_scope]++;
}
return (ifa_best);
}
/*
* return the best address out of the same scope. if no address was
* found, return the first valid address from designated IF.

View File

@ -616,7 +616,6 @@ struct cmsghdr;
int in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
int in6_localaddr __P((struct in6_addr *));
int in6_addrscope __P((struct in6_addr *));
struct in6_ifaddr *in6_ifawithscope __P((struct ifnet *, struct in6_addr *));
struct in6_ifaddr *in6_ifawithifp __P((struct ifnet *, struct in6_addr *));
extern void in6_if_up __P((struct ifnet *));
struct sockaddr;