From owner-svn-src-user@FreeBSD.ORG Tue Jan 29 10:46:48 2013 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id B7340533; Tue, 29 Jan 2013 10:46:48 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 9E006EE0; Tue, 29 Jan 2013 10:46:48 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r0TAkmBd064548; Tue, 29 Jan 2013 10:46:48 GMT (envelope-from ae@svn.freebsd.org) Received: (from ae@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r0TAklAF064544; Tue, 29 Jan 2013 10:46:47 GMT (envelope-from ae@svn.freebsd.org) Message-Id: <201301291046.r0TAklAF064544@svn.freebsd.org> From: "Andrey V. Elsukov" Date: Tue, 29 Jan 2013 10:46:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r246067 - user/ae/inet6/sys/netinet6 X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 Jan 2013 10:46:48 -0000 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 +#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_ */