summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/in6_pcb.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2005-07-25 12:31:43 +0000
committerume <ume@FreeBSD.org>2005-07-25 12:31:43 +0000
commitda2cf62b280b8450d5f8e0d810e810cdcc59a8c0 (patch)
tree5a678f63b25976c30f74f3bad9edb6f708c52930 /sys/netinet6/in6_pcb.c
parent59bc7b0da19f008a39ee92249e92f8246f04394e (diff)
downloadFreeBSD-src-da2cf62b280b8450d5f8e0d810e810cdcc59a8c0.zip
FreeBSD-src-da2cf62b280b8450d5f8e0d810e810cdcc59a8c0.tar.gz
scope cleanup. with this change
- most of the kernel code will not care about the actual encoding of scope zone IDs and won't touch "s6_addr16[1]" directly. - similarly, most of the kernel code will not care about link-local scoped addresses as a special case. - scope boundary check will be stricter. For example, the current *BSD code allows a packet with src=::1 and dst=(some global IPv6 address) to be sent outside of the node, if the application do: s = socket(AF_INET6); bind(s, "::1"); sendto(s, some_global_IPv6_addr); This is clearly wrong, since ::1 is only meaningful within a single node, but the current implementation of the *BSD kernel cannot reject this attempt. Submitted by: JINMEI Tatuya <jinmei__at__isl.rdc.toshiba.co.jp> Obtained from: KAME
Diffstat (limited to 'sys/netinet6/in6_pcb.c')
-rw-r--r--sys/netinet6/in6_pcb.c79
1 files changed, 39 insertions, 40 deletions
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 9aab2a0..5856512 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -96,6 +96,7 @@
#include <netinet6/nd6.h>
#include <netinet/in_pcb.h>
#include <netinet6/in6_pcb.h>
+#include <netinet6/scope6_var.h>
#ifdef IPSEC
#include <netinet6/ipsec.h>
@@ -139,6 +140,8 @@ in6_pcbbind(inp, nam, cred)
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
wild = 1;
if (nam) {
+ int error;
+
sin6 = (struct sockaddr_in6 *)nam;
if (nam->sa_len != sizeof(*sin6))
return (EINVAL);
@@ -148,11 +151,8 @@ in6_pcbbind(inp, nam, cred)
if (nam->sa_family != AF_INET6)
return (EAFNOSUPPORT);
- /* KAME hack: embed scopeid */
- if (in6_embedscope(&sin6->sin6_addr, sin6, inp, NULL) != 0)
- return EINVAL;
- /* this must be cleared for ifa_ifwithaddr() */
- sin6->sin6_scope_id = 0;
+ if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0)
+ return(error);
lport = sin6->sin6_port;
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
@@ -292,8 +292,9 @@ in6_pcbladdr(inp, nam, plocal_addr6)
struct in6_addr **plocal_addr6;
{
register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
- struct ifnet *ifp = NULL;
int error = 0;
+ struct ifnet *ifp = NULL;
+ int scope_ambiguous = 0;
if (nam->sa_len != sizeof (*sin6))
return (EINVAL);
@@ -302,13 +303,14 @@ in6_pcbladdr(inp, nam, plocal_addr6)
if (sin6->sin6_port == 0)
return (EADDRNOTAVAIL);
+ if (sin6->sin6_scope_id == 0 && !ip6_use_defzone)
+ scope_ambiguous = 1;
+ if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0)
+ return(error);
+
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_LOCK_ASSERT(inp);
- /* KAME hack: embed scopeid */
- if (in6_embedscope(&sin6->sin6_addr, sin6, inp, &ifp) != 0)
- return EINVAL;
-
if (in6_ifaddr) {
/*
* If the destination address is UNSPECIFIED addr,
@@ -317,26 +319,31 @@ in6_pcbladdr(inp, nam, plocal_addr6)
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
sin6->sin6_addr = in6addr_loopback;
}
- {
- /*
- * XXX: in6_selectsrc might replace the bound local address
- * with the address specified by setsockopt(IPV6_PKTINFO).
- * Is it the intended behavior?
- */
- *plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
- inp->in6p_moptions, NULL,
- &inp->in6p_laddr, &error);
- if (*plocal_addr6 == 0) {
- if (error == 0)
- error = EADDRNOTAVAIL;
- return (error);
- }
- /*
- * Don't do pcblookup call here; return interface in
- * plocal_addr6
- * and exit to caller, that will do the lookup.
- */
+
+ /*
+ * XXX: in6_selectsrc might replace the bound local address
+ * with the address specified by setsockopt(IPV6_PKTINFO).
+ * Is it the intended behavior?
+ */
+ *plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
+ inp->in6p_moptions, NULL,
+ &inp->in6p_laddr, &ifp, &error);
+ if (ifp && scope_ambiguous &&
+ (error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) {
+ return(error);
+ }
+
+ if (*plocal_addr6 == 0) {
+ if (error == 0)
+ error = EADDRNOTAVAIL;
+ return (error);
}
+ /*
+ * Don't do pcblookup call here; return interface in
+ * plocal_addr6
+ * and exit to caller, that will do the lookup.
+ */
+
return (0);
}
@@ -466,12 +473,7 @@ in6_sockaddr(port, addr_p)
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_port = port;
sin6->sin6_addr = *addr_p;
- if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
- sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
- else
- sin6->sin6_scope_id = 0; /*XXX*/
- if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
- sin6->sin6_addr.s6_addr16[1] = 0;
+ (void)sa6_recoverscope(sin6); /* XXX: should catch errors */
return (struct sockaddr *)sin6;
}
@@ -953,11 +955,8 @@ init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_family = AF_INET6;
sin6->sin6_addr = ip->ip6_src;
- if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
- sin6->sin6_addr.s6_addr16[1] = 0;
- sin6->sin6_scope_id =
- (m->m_pkthdr.rcvif && IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
- ? m->m_pkthdr.rcvif->if_index : 0;
+
+ (void)sa6_recoverscope(sin6); /* XXX: should catch errors... */
return;
}
OpenPOWER on IntegriCloud