From owner-svn-src-all@FreeBSD.ORG Thu Sep 11 12:33:38 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 175C398D; Thu, 11 Sep 2014 12:33:38 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 02C1E288; Thu, 11 Sep 2014 12:33:38 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8BCXbGF007495; Thu, 11 Sep 2014 12:33:37 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8BCXbGB007493; Thu, 11 Sep 2014 12:33:37 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201409111233.s8BCXbGB007493@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Thu, 11 Sep 2014 12:33:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271425 - head/sys/netinet6 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Sep 2014 12:33:38 -0000 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 +#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_ */