Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/netinet6 When choosing IPv6 source addresses, respect th...
details: https://anonhg.NetBSD.org/src/rev/a77b558858d4
branches: trunk
changeset: 754176:a77b558858d4
user: dyoung <dyoung%NetBSD.org@localhost>
date: Thu Apr 22 20:05:15 2010 +0000
description:
When choosing IPv6 source addresses, respect the ifaddr preference
level such as one might set with 'ifconfig xx0 inet6 <address>
preference <pref>'. I've been running this for many months without
any problems.
diffstat:
sys/netinet6/in6.c | 104 ++++++++++++++++++++++++++++++++--------------------
1 files changed, 63 insertions(+), 41 deletions(-)
diffs (201 lines):
diff -r 2564d946ad46 -r a77b558858d4 sys/netinet6/in6.c
--- a/sys/netinet6/in6.c Thu Apr 22 19:15:23 2010 +0000
+++ b/sys/netinet6/in6.c Thu Apr 22 20:05:15 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: in6.c,v 1.155 2010/04/07 22:59:15 oki Exp $ */
+/* $NetBSD: in6.c,v 1.156 2010/04/22 20:05:15 dyoung Exp $ */
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.155 2010/04/07 22:59:15 oki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.156 2010/04/22 20:05:15 dyoung Exp $");
#include "opt_inet.h"
#include "opt_pfil_hooks.h"
@@ -1792,6 +1792,14 @@
return error;
}
+static struct ifaddr *
+bestifa(struct ifaddr *best_ifa, struct ifaddr *ifa)
+{
+ if (best_ifa == NULL || best_ifa->ifa_preference < ifa->ifa_preference)
+ return ifa;
+ return best_ifa;
+}
+
/*
* Find an IPv6 interface link-local address specific to an interface.
*/
@@ -1809,10 +1817,7 @@
continue;
if ((((struct in6_ifaddr *)ifa)->ia6_flags & ignoreflags) != 0)
continue;
- if (best_ifa == NULL)
- best_ifa = ifa;
- else if (best_ifa->ifa_preference < ifa->ifa_preference)
- best_ifa = ifa;
+ best_ifa = bestifa(best_ifa, ifa);
}
return (struct in6_ifaddr *)best_ifa;
@@ -1825,18 +1830,28 @@
struct in6_ifaddr *
in6ifa_ifpwithaddr(const struct ifnet *ifp, const struct in6_addr *addr)
{
- struct ifaddr *ifa;
+ struct ifaddr *best_ifa = NULL, *ifa;
IFADDR_FOREACH(ifa, ifp) {
if (ifa->ifa_addr == NULL)
continue; /* just for safety */
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
- if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
- break;
+ if (!IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
+ continue;
+ best_ifa = bestifa(best_ifa, ifa);
}
- return (struct in6_ifaddr *)ifa;
+ return (struct in6_ifaddr *)best_ifa;
+}
+
+static struct in6_ifaddr *
+bestia(struct in6_ifaddr *best_ia, struct in6_ifaddr *ia)
+{
+ if (best_ia == NULL ||
+ best_ia->ia_ifa.ifa_preference < ia->ia_ifa.ifa_preference)
+ return ia;
+ return best_ia;
}
/*
@@ -1847,7 +1862,7 @@
in6ifa_ifplocaladdr(const struct ifnet *ifp, const struct in6_addr *addr)
{
struct ifaddr *ifa;
- struct in6_ifaddr *ia;
+ struct in6_ifaddr *best_ia = NULL, *ia;
IFADDR_FOREACH(ifa, ifp) {
if (ifa->ifa_addr == NULL)
@@ -1855,13 +1870,14 @@
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
ia = (struct in6_ifaddr *)ifa;
- if (IN6_ARE_MASKED_ADDR_EQUAL(addr,
+ if (!IN6_ARE_MASKED_ADDR_EQUAL(addr,
&ia->ia_addr.sin6_addr,
&ia->ia_prefixmask.sin6_addr))
- return ia;
+ continue;
+ best_ia = bestia(best_ia, ia);
}
- return NULL;
+ return best_ia;
}
/*
@@ -2043,7 +2059,7 @@
{
int dst_scope = in6_addrscope(dst), blen = -1, tlen;
struct ifaddr *ifa;
- struct in6_ifaddr *besta = 0;
+ struct in6_ifaddr *best_ia = NULL, *ia;
struct in6_ifaddr *dep[2]; /* last-resort: deprecated */
dep[0] = dep[1] = NULL;
@@ -2057,54 +2073,60 @@
IFADDR_FOREACH(ifa, ifp) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
- if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
+ ia = (struct in6_ifaddr *)ifa;
+ if (ia->ia6_flags & IN6_IFF_ANYCAST)
continue; /* XXX: is there any case to allow anycast? */
- if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
+ if (ia->ia6_flags & IN6_IFF_NOTREADY)
continue; /* don't use this interface */
- if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
+ if (ia->ia6_flags & IN6_IFF_DETACHED)
continue;
- if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
+ if (ia->ia6_flags & IN6_IFF_DEPRECATED) {
if (ip6_use_deprecated)
- dep[0] = (struct in6_ifaddr *)ifa;
+ dep[0] = ia;
continue;
}
- if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
- /*
- * call in6_matchlen() as few as possible
- */
- if (besta) {
- if (blen == -1)
- blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
- tlen = in6_matchlen(IFA_IN6(ifa), dst);
- if (tlen > blen) {
- blen = tlen;
- besta = (struct in6_ifaddr *)ifa;
- }
- } else
- besta = (struct in6_ifaddr *)ifa;
+ if (dst_scope != in6_addrscope(IFA_IN6(ifa)))
+ continue;
+ /*
+ * call in6_matchlen() as few as possible
+ */
+ if (best_ia == NULL) {
+ best_ia = ia;
+ continue;
}
+ if (blen == -1)
+ blen = in6_matchlen(&best_ia->ia_addr.sin6_addr, dst);
+ tlen = in6_matchlen(IFA_IN6(ifa), dst);
+ if (tlen > blen) {
+ blen = tlen;
+ best_ia = ia;
+ } else if (tlen == blen)
+ best_ia = bestia(best_ia, ia);
}
- if (besta)
- return besta;
+ if (best_ia != NULL)
+ return best_ia;
IFADDR_FOREACH(ifa, ifp) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
- if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
+ ia = (struct in6_ifaddr *)ifa;
+ if (ia->ia6_flags & IN6_IFF_ANYCAST)
continue; /* XXX: is there any case to allow anycast? */
- if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
+ if (ia->ia6_flags & IN6_IFF_NOTREADY)
continue; /* don't use this interface */
- if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
+ if (ia->ia6_flags & IN6_IFF_DETACHED)
continue;
- if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
+ if (ia->ia6_flags & IN6_IFF_DEPRECATED) {
if (ip6_use_deprecated)
dep[1] = (struct in6_ifaddr *)ifa;
continue;
}
- return (struct in6_ifaddr *)ifa;
+ best_ia = bestia(best_ia, ia);
}
+ if (best_ia != NULL)
+ return best_ia;
/* use the last-resort values, that are, deprecated addresses */
if (dep[0])
Home |
Main Index |
Thread Index |
Old Index