svn commit: r246067 - user/ae/inet6/sys/netinet6
Andrey V. Elsukov
ae at FreeBSD.org
Tue Jan 29 10:46:48 UTC 2013
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 <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];
+ 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_ */
More information about the svn-src-user
mailing list