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"