Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/netinet6 Pull best address selection code out of in6_sel...
details: https://anonhg.NetBSD.org/src/rev/0cd93f1a42f4
branches: trunk
changeset: 348628:0cd93f1a42f4
user: ozaki-r <ozaki-r%NetBSD.org@localhost>
date: Mon Oct 31 04:57:10 2016 +0000
description:
Pull best address selection code out of in6_selectsrc
No functional change.
diffstat:
sys/netinet6/in6_src.c | 283 +++++++++++++++++++++++++-----------------------
1 files changed, 149 insertions(+), 134 deletions(-)
diffs (truncated from 368 to 300 lines):
diff -r 05a0a97b7729 -r 0cd93f1a42f4 sys/netinet6/in6_src.c
--- a/sys/netinet6/in6_src.c Mon Oct 31 04:16:29 2016 +0000
+++ b/sys/netinet6/in6_src.c Mon Oct 31 04:57:10 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: in6_src.c,v 1.72 2016/10/31 04:16:25 ozaki-r Exp $ */
+/* $NetBSD: in6_src.c,v 1.73 2016/10/31 04:57:10 ozaki-r Exp $ */
/* $KAME: in6_src.c,v 1.159 2005/10/19 01:40:32 t-momose Exp $ */
/*
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.72 2016/10/31 04:16:25 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.73 2016/10/31 04:57:10 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -171,138 +171,25 @@
#define BREAK(r) goto out
#endif
-int
-in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
- struct ip6_moptions *mopts, struct route *ro, struct in6_addr *laddr,
- struct ifnet **ifpp, struct psref *psref, struct in6_addr *ret_ia6)
+/*
+ * Called inside pserialize critical section. Don't sleep/block.
+ */
+static struct in6_ifaddr *
+in6_select_best_ia(struct sockaddr_in6 *dstsock, struct in6_addr *dst,
+ const struct ifnet *ifp, const struct ip6_pktopts *opts,
+ const u_int32_t odstzone)
{
- struct in6_addr dst;
- struct ifnet *ifp = NULL;
- struct in6_ifaddr *ia = NULL, *ia_best = NULL;
- struct in6_pktinfo *pi = NULL;
+ struct in6_ifaddr *ia, *ia_best = NULL;
int dst_scope = -1, best_scope = -1, best_matchlen = -1;
struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL;
- u_int32_t odstzone;
- int error;
- int prefer_tempaddr;
-#if defined(MIP6) && NMIP > 0
- u_int8_t ip6po_usecoa = 0;
-#endif /* MIP6 && NMIP > 0 */
- struct psref local_psref;
- int bound = curlwp_bind();
-#define PSREF (psref == NULL) ? &local_psref : psref
- int s;
- KASSERT((ifpp != NULL && psref != NULL) ||
- (ifpp == NULL && psref == NULL));
-
- dst = dstsock->sin6_addr; /* make a copy for local operation */
- if (ifpp)
- *ifpp = NULL;
-
- /*
- * Try to determine the outgoing interface for the given destination.
- * We do this regardless of whether the socket is bound, since the
- * caller may need this information as a side effect of the call
- * to this function (e.g., for identifying the appropriate scope zone
- * ID).
- */
- error = in6_selectif(dstsock, opts, mopts, ro, &ifp, PSREF);
- if (ifpp != NULL)
- *ifpp = ifp;
-
- /*
- * If the source address is explicitly specified by the caller,
- * check if the requested source address is indeed a unicast address
- * assigned to the node, and can be used as the packet's source
- * address. If everything is okay, use the address as source.
- */
- if (opts && (pi = opts->ip6po_pktinfo) &&
- !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) {
- struct sockaddr_in6 srcsock;
- struct in6_ifaddr *ia6;
- int _s;
- struct ifaddr *ifa;
-
- /*
- * Determine the appropriate zone id of the source based on
- * the zone of the destination and the outgoing interface.
- * If the specified address is ambiguous wrt the scope zone,
- * the interface must be specified; otherwise, ifa_ifwithaddr()
- * will fail matching the address.
- */
- memset(&srcsock, 0, sizeof(srcsock));
- srcsock.sin6_family = AF_INET6;
- srcsock.sin6_len = sizeof(srcsock);
- srcsock.sin6_addr = pi->ipi6_addr;
- if (ifp) {
- error = in6_setscope(&srcsock.sin6_addr, ifp, NULL);
- if (error != 0)
- goto exit;
- }
-
- _s = pserialize_read_enter();
- ifa = ifa_ifwithaddr(sin6tosa(&srcsock));
- if ((ia6 = ifatoia6(ifa)) == NULL ||
- ia6->ia6_flags &
- (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY)) {
- pserialize_read_exit(_s);
- error = EADDRNOTAVAIL;
- goto exit;
- }
- pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */
- if (ifpp)
- *ifpp = ifp;
- *ret_ia6 = ia6->ia_addr.sin6_addr;
- pserialize_read_exit(_s);
- goto exit;
- }
-
- /*
- * If the socket has already bound the source, just use it. We don't
- * care at the moment whether in6_selectif() succeeded above, even
- * though it would eventually cause an error.
- */
- if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr)) {
- *ret_ia6 = *laddr;
- goto exit;
- }
-
- /*
- * The outgoing interface is crucial in the general selection procedure
- * below. If it is not known at this point, we fail.
- */
- if (ifp == NULL)
- goto exit;
-
- /*
- * If the address is not yet determined, choose the best one based on
- * the outgoing interface and the destination address.
- */
-
-#if defined(MIP6) && NMIP > 0
- /*
- * a caller can specify IP6PO_USECOA to not to use a home
- * address. for example, the case that the neighbour
- * unreachability detection to the global address.
- */
- if (opts != NULL &&
- (opts->ip6po_flags & IP6PO_USECOA) != 0) {
- ip6po_usecoa = 1;
- }
-#endif /* MIP6 && NMIP > 0 */
-
- error = in6_setscope(&dst, ifp, &odstzone);
- if (error != 0)
- goto exit;
-
- s = pserialize_read_enter();
IN6_ADDRLIST_READER_FOREACH(ia) {
int new_scope = -1, new_matchlen = -1;
struct in6_addrpolicy *new_policy = NULL;
u_int32_t srczone, osrczone, dstzone;
struct in6_addr src;
struct ifnet *ifp1 = ia->ia_ifp;
+ int prefer_tempaddr;
/*
* We'll never take an address that breaks the scope zone
@@ -310,7 +197,7 @@
* does not contain the outgoing interface.
* XXX: we should probably use sin6_scope_id here.
*/
- if (in6_setscope(&dst, ifp1, &dstzone) ||
+ if (in6_setscope(dst, ifp1, &dstzone) ||
odstzone != dstzone) {
continue;
}
@@ -337,7 +224,7 @@
#endif /* MIP6 && NMIP > 0 */
/* Rule 1: Prefer same address */
- if (IN6_ARE_ADDR_EQUAL(&dst, &ia->ia_addr.sin6_addr)) {
+ if (IN6_ARE_ADDR_EQUAL(dst, &ia->ia_addr.sin6_addr)) {
ia_best = ia;
BREAK(1); /* there should be no better candidate */
}
@@ -347,7 +234,7 @@
/* Rule 2: Prefer appropriate scope */
if (dst_scope < 0)
- dst_scope = in6_addrscope(&dst);
+ dst_scope = in6_addrscope(dst);
new_scope = in6_addrscope(&ia->ia_addr.sin6_addr);
if (IN6_ARE_SCOPE_CMP(best_scope, new_scope) < 0) {
if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0)
@@ -525,7 +412,7 @@
* a large number so that it is easy to assign smaller numbers
* to more preferred rules.
*/
- new_matchlen = in6_matchlen(&ia->ia_addr.sin6_addr, &dst);
+ new_matchlen = in6_matchlen(&ia->ia_addr.sin6_addr, dst);
if (best_matchlen < new_matchlen)
REPLACE(14);
if (new_matchlen < best_matchlen)
@@ -547,7 +434,7 @@
lookup_addrsel_policy(&ia_best->ia_addr));
best_matchlen = (new_matchlen >= 0 ? new_matchlen :
in6_matchlen(&ia_best->ia_addr.sin6_addr,
- &dst));
+ dst));
next:
continue;
@@ -556,13 +443,144 @@
break;
}
- if ((ia = ia_best) == NULL) {
+ return ia_best;
+}
+#undef REPLACE
+#undef BREAK
+#undef NEXT
+
+int
+in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
+ struct ip6_moptions *mopts, struct route *ro, struct in6_addr *laddr,
+ struct ifnet **ifpp, struct psref *psref, struct in6_addr *ret_ia6)
+{
+ struct in6_addr dst;
+ struct ifnet *ifp = NULL;
+ struct in6_ifaddr *ia = NULL;
+ struct in6_pktinfo *pi = NULL;
+ u_int32_t odstzone;
+ int error;
+#if defined(MIP6) && NMIP > 0
+ u_int8_t ip6po_usecoa = 0;
+#endif /* MIP6 && NMIP > 0 */
+ struct psref local_psref;
+ int bound = curlwp_bind();
+#define PSREF (psref == NULL) ? &local_psref : psref
+ int s;
+
+ KASSERT((ifpp != NULL && psref != NULL) ||
+ (ifpp == NULL && psref == NULL));
+
+ dst = dstsock->sin6_addr; /* make a copy for local operation */
+ if (ifpp)
+ *ifpp = NULL;
+
+ /*
+ * Try to determine the outgoing interface for the given destination.
+ * We do this regardless of whether the socket is bound, since the
+ * caller may need this information as a side effect of the call
+ * to this function (e.g., for identifying the appropriate scope zone
+ * ID).
+ */
+ error = in6_selectif(dstsock, opts, mopts, ro, &ifp, PSREF);
+ if (ifpp != NULL)
+ *ifpp = ifp;
+
+ /*
+ * If the source address is explicitly specified by the caller,
+ * check if the requested source address is indeed a unicast address
+ * assigned to the node, and can be used as the packet's source
+ * address. If everything is okay, use the address as source.
+ */
+ if (opts && (pi = opts->ip6po_pktinfo) &&
+ !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) {
+ struct sockaddr_in6 srcsock;
+ struct in6_ifaddr *ia6;
+ int _s;
+ struct ifaddr *ifa;
+
+ /*
+ * Determine the appropriate zone id of the source based on
+ * the zone of the destination and the outgoing interface.
+ * If the specified address is ambiguous wrt the scope zone,
+ * the interface must be specified; otherwise, ifa_ifwithaddr()
+ * will fail matching the address.
+ */
+ memset(&srcsock, 0, sizeof(srcsock));
+ srcsock.sin6_family = AF_INET6;
+ srcsock.sin6_len = sizeof(srcsock);
+ srcsock.sin6_addr = pi->ipi6_addr;
+ if (ifp) {
+ error = in6_setscope(&srcsock.sin6_addr, ifp, NULL);
+ if (error != 0)
+ goto exit;
+ }
+
+ _s = pserialize_read_enter();
+ ifa = ifa_ifwithaddr(sin6tosa(&srcsock));
+ if ((ia6 = ifatoia6(ifa)) == NULL ||
+ ia6->ia6_flags &
+ (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY)) {
+ pserialize_read_exit(_s);
+ error = EADDRNOTAVAIL;
+ goto exit;
+ }
+ pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */
+ if (ifpp)
Home |
Main Index |
Thread Index |
Old Index