Author: ae
Date: Thu Sep 11 12:33:37 2014
New Revision: 271425
URL: http://svnweb.freebsd.org/changeset/base/271425

Log:
  Introduce new scope related functions.
  
  * new macro to remove magic number - IPV6_ADDR_SCOPES_COUNT;
  * sa6_checkzone() - this function checks sockaddr_in6 structure
    for correctness of sin6_scope_id. It also can fill correct
    value sometimes.
  * in6_getscopezone() - this function returns scope zone id for
    specified interface and scope.
  * in6_getlinkifnet() - this function returns struct ifnet for
    corresponding zone id of link-local scope.
  
  Obtained from:        Yandex LLC
  Sponsored by: Yandex LLC

Modified:
  head/sys/netinet6/scope6.c
  head/sys/netinet6/scope6_var.h

Modified: head/sys/netinet6/scope6.c
==============================================================================
--- head/sys/netinet6/scope6.c  Thu Sep 11 12:30:29 2014        (r271424)
+++ head/sys/netinet6/scope6.c  Thu Sep 11 12:33:37 2014        (r271425)
@@ -467,3 +467,77 @@ in6_getscope(struct in6_addr *in6)
 
        return (0);
 }
+
+/*
+ * Return pointer to ifnet structure, corresponding to the zone id of
+ * link-local scope.
+ */
+struct ifnet*
+in6_getlinkifnet(uint32_t zoneid)
+{
+
+       return (ifnet_byindex((u_short)zoneid));
+}
+
+/*
+ * Return zone id for the specified scope.
+ */
+uint32_t
+in6_getscopezone(const struct ifnet *ifp, int scope)
+{
+
+       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);
+}
+
+/*
+ * This function is for checking sockaddr_in6 structure passed
+ * from the application level (usually).
+ *
+ * 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.
+ */
+int
+sa6_checkzone(struct sockaddr_in6 *sa6)
+{
+       int scope;
+
+       scope = in6_addrscope(&sa6->sin6_addr);
+       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);
+       }
+       /* XXX: we can validate sin6_scope_id here */
+       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: EADDRNOTAVAIL);
+}
+
+

Modified: head/sys/netinet6/scope6_var.h
==============================================================================
--- head/sys/netinet6/scope6_var.h      Thu Sep 11 12:30:29 2014        
(r271424)
+++ head/sys/netinet6/scope6_var.h      Thu Sep 11 12:33:37 2014        
(r271425)
@@ -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];
+       uint32_t s6id_list[IPV6_ADDR_SCOPES_COUNT];
 };
 
 VNET_DECLARE(int, deembed_scopeid);
@@ -56,9 +57,12 @@ 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_getscopezone(const struct ifnet *, int);
+struct ifnet* in6_getlinkifnet(uint32_t);
 #endif /* _KERNEL */
 
 #endif /* _NETINET6_SCOPE6_VAR_H_ */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to