svn commit: r246067 - user/ae/inet6/sys/netinet6

Andrey V. Elsukov ae at FreeBSD.org
Tue Jan 29 10:46:48 UTC 2013


Author: ae
Date: Tue Jan 29 10:46:47 2013
New Revision: 246067
URL: http://svnweb.freebsd.org/changeset/base/246067

Log:
  Rename in6_getlinkzone into in6_getscopezone. Now it returns zone id
  for the scpecified interface and scope. For loopback address return
  link-local scope, this is also required by RFC 6724.  Change
  sa6_checkzone to reflect this.

Modified:
  user/ae/inet6/sys/netinet6/in6.h
  user/ae/inet6/sys/netinet6/in6_ifattach.c
  user/ae/inet6/sys/netinet6/scope6.c
  user/ae/inet6/sys/netinet6/scope6_var.h

Modified: user/ae/inet6/sys/netinet6/in6.h
==============================================================================
--- user/ae/inet6/sys/netinet6/in6.h	Tue Jan 29 07:46:22 2013	(r246066)
+++ user/ae/inet6/sys/netinet6/in6.h	Tue Jan 29 10:46:47 2013	(r246067)
@@ -638,7 +638,7 @@ int	in6_cksum_pseudo(struct ip6_hdr *, u
 int	in6_cksum(struct mbuf *, u_int8_t, u_int32_t, u_int32_t);
 int	in6_localaddr(struct in6_addr *);
 int	in6_localip(struct in6_addr *);
-int	in6_addrscope(struct in6_addr *);
+int	in6_addrscope(const struct in6_addr *);
 struct	in6_ifaddr *in6_ifawithifp(struct ifnet *, struct in6_addr *);
 extern void in6_if_up(struct ifnet *);
 struct sockaddr;

Modified: user/ae/inet6/sys/netinet6/in6_ifattach.c
==============================================================================
--- user/ae/inet6/sys/netinet6/in6_ifattach.c	Tue Jan 29 07:46:22 2013	(r246066)
+++ user/ae/inet6/sys/netinet6/in6_ifattach.c	Tue Jan 29 10:46:47 2013	(r246067)
@@ -478,7 +478,8 @@ in6_ifattach_linklocal(struct ifnet *ifp
 			return (-1);
 		}
 	}
-	ifra.ifra_addr.sin6_scope_id = in6_getlinkzone(ifp);
+	ifra.ifra_addr.sin6_scope_id = in6_getscopezone(ifp,
+	    IPV6_ADDR_SCOPE_LINKLOCAL);
 
 	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
 	ifra.ifra_prefixmask.sin6_family = AF_INET6;

Modified: user/ae/inet6/sys/netinet6/scope6.c
==============================================================================
--- user/ae/inet6/sys/netinet6/scope6.c	Tue Jan 29 07:46:22 2013	(r246066)
+++ user/ae/inet6/sys/netinet6/scope6.c	Tue Jan 29 10:46:47 2013	(r246067)
@@ -200,29 +200,14 @@ scope6_get(struct ifnet *ifp, struct sco
  * Get a scope of the address. Node-local, link-local, site-local or global.
  */
 int
-in6_addrscope(struct in6_addr *addr)
+in6_addrscope(const struct in6_addr *addr)
 {
 
 	if (IN6_IS_ADDR_MULTICAST(addr))
 		return (IPV6_ADDR_MC_SCOPE(addr));
-	if (IN6_IS_ADDR_LINKLOCAL(addr))
+	if (IN6_IS_ADDR_LINKLOCAL(addr) ||
+	    IN6_IS_ADDR_LOOPBACK(addr))
 		return (IPV6_ADDR_SCOPE_LINKLOCAL);
-#if 0
-	if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) {
-		/*
-		 * XXX: RFC 4007 says that ::1 should treated as having
-		 * link-local scope. But we don't allow configure it on
-		 * several loopback interfaces. So, actually it has the
-		 * global scope.
-		 */
-		if (addr->s6_addr[15] == 1) /* loopback */
-			return (IPV6_ADDR_SCOPE_LINKLOCAL);
-		/*
-		 * Regard unspecified address as global, since
-		 * it has no ambiguity.
-		 */
-	}
-#endif
 	return (IPV6_ADDR_SCOPE_GLOBAL);
 }
 
@@ -440,13 +425,18 @@ in6_getscope(struct in6_addr *in6)
 }
 
 /*
- * Return zone id for the link-local scope.
+ * Return zone id for the specified scope.
  */
 uint32_t
-in6_getlinkzone(const struct ifnet *ifp)
+in6_getscopezone(const struct ifnet *ifp, int scope)
 {
 
-	return (ifp->if_index);
+	if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL ||
+	    scope == IPV6_ADDR_SCOPE_LINKLOCAL)
+		return (ifp->if_index);
+	if (scope >= 0 && scope < IPV6_ADDR_SCOPES_COUNT)
+		return (SID(ifp)->s6id_list[scope]);
+	return (0);
 }
 
 /*
@@ -466,27 +456,27 @@ sa6_checkzone(struct sockaddr_in6 *sa6)
 
 	scope = in6_addrscope(&sa6->sin6_addr);
 	if (scope == IPV6_ADDR_SCOPE_GLOBAL) {
-		/*
-		 * Since ::1 address always configured on the lo0, we can
-		 * automagically set its zone id, when it is not specified.
-		 * Return error, when specified zone id doesn't match with
-		 * actual value.
-		 */
-		if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) {
-			if (sa6->sin6_sin6_scope_id == 0) {
-				sa6->sin6_scope_id = in6_getlinkzone(V_loif);
-				return (0);
-			}
-			if (sa6->sin6_scope_id == in6_getlinkzone(V_loif))
-				return (0);
-		}
 		/* We don't want zone id for global scope */
 		return (sa6->sin6_scope_id ? EINVAL: 0);
 	}
+	/*
+	 * Since ::1 address always configured on the lo0, we can
+	 * automatically set its zone id, when it is not specified.
+	 * Return error, when specified zone id doesn't match with
+	 * actual value.
+	 */
+	if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) {
+		if (sa6->sin6_scope_id == 0)
+			sa6->sin6_scope_id = in6_getscopezone(V_loif,
+			    IPV6_ADDR_SCOPE_LINKLOCAL);
+		if (sa6->sin6_scope_id != in6_getscopezone(V_loif,
+		    IPV6_ADDR_SCOPE_LINKLOCAL))
+			return (EADDRNOTAVAIL);
+	}
 	if (sa6->sin6_scope_id != 0)
 		return (0);
 	if (V_ip6_use_defzone != 0)
 		sa6->sin6_scope_id = V_sid_default.s6id_list[scope];
 	/* Return error if we can't determine zone id */
-	return (sa6->sin6_scope_id ? 0: EINVAL);
+	return (sa6->sin6_scope_id ? 0: EADDRNOTAVAIL);
 }

Modified: user/ae/inet6/sys/netinet6/scope6_var.h
==============================================================================
--- user/ae/inet6/sys/netinet6/scope6_var.h	Tue Jan 29 07:46:22 2013	(r246066)
+++ user/ae/inet6/sys/netinet6/scope6_var.h	Tue Jan 29 10:46:47 2013	(r246067)
@@ -36,12 +36,13 @@
 #ifdef _KERNEL
 #include <net/vnet.h>
 
+#define	IPV6_ADDR_SCOPES_COUNT	16
 struct scope6_id {
 	/*
 	 * 16 is correspondent to 4bit multicast scope field.
 	 * i.e. from node-local to global with some reserved/unassigned types.
 	 */
-	u_int32_t s6id_list[16];
+	u_int32_t s6id_list[IPV6_ADDR_SCOPES_COUNT];
 };
 
 VNET_DECLARE(int, deembed_scopeid);
@@ -57,10 +58,11 @@ int	scope6_get_default(struct scope6_id 
 u_int32_t scope6_addr2default(struct in6_addr *);
 int	sa6_embedscope(struct sockaddr_in6 *, int);
 int	sa6_recoverscope(struct sockaddr_in6 *);
+int	sa6_checkzone(struct sockaddr_in6 *);
 int	in6_setscope(struct in6_addr *, struct ifnet *, u_int32_t *);
 int	in6_clearscope(struct in6_addr *);
 uint16_t in6_getscope(struct in6_addr *);
-uint32_t in6_getlinkzone(const struct ifnet *);
+uint32_t in6_getscopezone(const struct ifnet *, int);
 #endif /* _KERNEL */
 
 #endif /* _NETINET6_SCOPE6_VAR_H_ */


More information about the svn-src-user mailing list