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

Andrey V. Elsukov ae at FreeBSD.org
Mon Dec 2 05:35:51 UTC 2013


Author: ae
Date: Mon Dec  2 05:35:50 2013
New Revision: 258831
URL: http://svnweb.freebsd.org/changeset/base/258831

Log:
  Rework sa6_checkzone's checks.
  
  RFC 3493 doesn't requre sin6_scope_id must be set for multicast addresses.
  Only addresses from link-local and interface-local scopes must have it
  initialized.

Modified:
  user/ae/inet6/sys/netinet6/scope6.c

Modified: user/ae/inet6/sys/netinet6/scope6.c
==============================================================================
--- user/ae/inet6/sys/netinet6/scope6.c	Mon Dec  2 05:21:54 2013	(r258830)
+++ user/ae/inet6/sys/netinet6/scope6.c	Mon Dec  2 05:35:50 2013	(r258831)
@@ -457,8 +457,9 @@ in6_getscopezone(const struct ifnet *ifp
  * This function is for checking sockaddr_in6 structure passed
  * from the application level (usually).
  *
- * sin6_scope_id should be set for link-local unicast addresses and for
- * any multicast addresses.
+ * sin6_scope_id should be set for link-local unicast, link-local and
+ * interface-local  multicast addresses.
+ *
  * If it is zero, then look into default zone ids. If default zone id is
  * not set or disabled, then return error.
  */
@@ -468,25 +469,28 @@ sa6_checkzone(struct sockaddr_in6 *sa6)
 	int scope;
 
 	scope = in6_addrscope(&sa6->sin6_addr);
-	if (!IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
-		if (scope == IPV6_ADDR_SCOPE_GLOBAL)
-			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);
-			else if (sa6->sin6_scope_id != in6_getscopezone(
-			    V_loif, IPV6_ADDR_SCOPE_LINKLOCAL))
-				return (EADDRNOTAVAIL);
-		}
+	if (scope == IPV6_ADDR_SCOPE_GLOBAL)
+		return (sa6->sin6_scope_id ? EINVAL: 0);
+	if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr) &&
+	    scope != IPV6_ADDR_SCOPE_LINKLOCAL &&
+	    scope != IPV6_ADDR_SCOPE_INTFACELOCAL) {
+		if (sa6->sin6_scope_id == 0 && V_ip6_use_defzone != 0)
+			sa6->sin6_scope_id = V_sid_default.s6id_list[scope];
+		return (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, scope);
+		else if (sa6->sin6_scope_id != in6_getscopezone(V_loif, scope))
+			return (EADDRNOTAVAIL);
 	}
-	/* Any multicast and link-local addresses. */
+	/* XXX: we can validate sin6_scope_id here */
 	if (sa6->sin6_scope_id != 0)
 		return (0);
 	if (V_ip6_use_defzone != 0)
@@ -507,11 +511,11 @@ sa6_checkzone_ifp(struct ifnet *ifp, str
 	scope = in6_addrscope(&sa6->sin6_addr);
 	if (scope == IPV6_ADDR_SCOPE_LINKLOCAL ||
 	    scope == IPV6_ADDR_SCOPE_INTFACELOCAL) {
-		if (sa6->sin6_scope_id != 0 &&
-		    sa6->sin6_scope_id != in6_getscopezone(ifp, scope))
-			return (EADDRNOTAVAIL);
-		if (sa6->sin6_scope_id == 0)
+		if (sa6->sin6_scope_id == 0) {
 			sa6->sin6_scope_id = in6_getscopezone(ifp, scope);
+			return (0);
+		} else if (sa6->sin6_scope_id != in6_getscopezone(ifp, scope))
+			return (EADDRNOTAVAIL);
 	}
 	return (sa6_checkzone(sa6));
 }


More information about the svn-src-user mailing list