summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2004-03-01 15:34:29 +0000
committerume <ume@FreeBSD.org>2004-03-01 15:34:29 +0000
commit82ed053e22d6a963ffa27132857d3067abaa39ca (patch)
tree27c28681b7641b83e29dbfe15cce3a7db9ecf78c
parent16b335106f4500b821afd926442836fce9e5e3f9 (diff)
downloadFreeBSD-src-82ed053e22d6a963ffa27132857d3067abaa39ca.zip
FreeBSD-src-82ed053e22d6a963ffa27132857d3067abaa39ca.tar.gz
- reject incoming packets to an interface-local multicast address from
the wire. - added a generic scope check, and removed checks for loopback src/dst addresses. Obtained from: KAME
-rw-r--r--sys/netinet6/ip6_input.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index d42a444..3485e8b 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -244,6 +244,8 @@ ip6_input(m)
u_int32_t rtalert = ~0;
int nxt, ours = 0;
struct ifnet *deliverifp = NULL;
+ struct sockaddr_in6 sa6;
+ u_int32_t srczone, dstzone;
#ifdef PFIL_HOOKS
struct in6_addr odst;
#endif
@@ -387,9 +389,14 @@ ip6_input(m)
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
goto bad;
}
- if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
- IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) &&
- (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
+ if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) &&
+ !(m->m_flags & M_LOOP)) {
+ /*
+ * In this case, the packet should come from the loopback
+ * interface. However, we cannot just check the if_flags,
+ * because ip6_mloopback() passes the "actual" interface
+ * as the outgoing/incoming interface.
+ */
ip6stat.ip6s_badscope++;
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
goto bad;
@@ -429,7 +436,12 @@ ip6_input(m)
}
#endif
- /* drop packets if interface ID portion is already filled */
+ /*
+ * Drop packets if the link ID portion is already filled.
+ * XXX: this is technically not a good behavior. But, we internally
+ * use the field to disambiguate link-local addresses, so we cannot
+ * be generous against those a bit strange addresses.
+ */
if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) &&
ip6->ip6_src.s6_addr16[1]) {
@@ -444,12 +456,42 @@ ip6_input(m)
}
}
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
- ip6->ip6_src.s6_addr16[1]
- = htons(m->m_pkthdr.rcvif->if_index);
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
- ip6->ip6_dst.s6_addr16[1]
- = htons(m->m_pkthdr.rcvif->if_index);
+ /*
+ * construct source and destination address structures with
+ * disambiguating their scope zones (if there is ambiguity).
+ * XXX: sin6_family and sin6_len will NOT be referred to, but we fill
+ * in these fields just in case.
+ */
+ if (in6_addr2zoneid(m->m_pkthdr.rcvif, &ip6->ip6_src, &srczone) ||
+ in6_addr2zoneid(m->m_pkthdr.rcvif, &ip6->ip6_dst, &dstzone)) {
+ /*
+ * Note that these generic checks cover cases that src or
+ * dst are the loopback address and the receiving interface
+ * is not loopback.
+ */
+ ip6stat.ip6s_badscope++;
+ goto bad;
+ }
+
+ bzero(&sa6, sizeof(sa6));
+ sa6.sin6_family = AF_INET6;
+ sa6.sin6_len = sizeof(struct sockaddr_in6);
+
+ sa6.sin6_addr = ip6->ip6_src;
+ sa6.sin6_scope_id = srczone;
+ if (in6_embedscope(&ip6->ip6_src, &sa6, NULL, NULL)) {
+ /* XXX: should not happen */
+ ip6stat.ip6s_badscope++;
+ goto bad;
+ }
+
+ sa6.sin6_addr = ip6->ip6_dst;
+ sa6.sin6_scope_id = dstzone;
+ if (in6_embedscope(&ip6->ip6_dst, &sa6, NULL, NULL)) {
+ /* XXX: should not happen */
+ ip6stat.ip6s_badscope++;
+ goto bad;
+ }
/*
* Multicast check
OpenPOWER on IntegriCloud