summaryrefslogtreecommitdiff
path: root/sys/netinet6/ip6_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/ip6_input.c')
-rw-r--r--sys/netinet6/ip6_input.c157
1 files changed, 100 insertions, 57 deletions
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index ae711d41b62..47422a9dd99 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ip6_input.c,v 1.12 2000/05/25 01:22:00 itojun Exp $ */
-/* $KAME: ip6_input.c,v 1.89 2000/05/19 19:59:05 itojun Exp $ */
+/* $OpenBSD: ip6_input.c,v 1.13 2000/06/13 14:50:33 itojun Exp $ */
+/* $KAME: ip6_input.c,v 1.94 2000/06/13 10:06:19 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -247,8 +247,7 @@ ip6_input(m)
if (m->m_next) {
if (m->m_flags & M_LOOP) {
ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
- }
- else if (m->m_pkthdr.rcvif->if_index <= 31)
+ } else if (m->m_pkthdr.rcvif->if_index <= 31)
ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
else
ip6stat.ip6s_m2m[0]++;
@@ -407,13 +406,18 @@ ip6_input(m)
/*
* Unicast check
*/
- if (ip6_forward_rt.ro_rt == 0 ||
- !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
- &ip6_forward_rt.ro_dst.sin6_addr)) {
+ if (ip6_forward_rt.ro_rt != NULL &&
+ (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
+ IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
+ &ip6_forward_rt.ro_dst.sin6_addr))
+ ; /* cache hit */
+ else {
if (ip6_forward_rt.ro_rt) {
+ /* route is down or destination is different */
RTFREE(ip6_forward_rt.ro_rt);
ip6_forward_rt.ro_rt = 0;
}
+
bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
@@ -526,8 +530,29 @@ ip6_input(m)
#endif
return; /* m have already been freed */
}
+
/* adjust pointer */
ip6 = mtod(m, struct ip6_hdr *);
+
+ /*
+ * if the payload length field is 0 and the next header field
+ * indicates Hop-by-Hop Options header, then a Jumbo Payload
+ * option MUST be included.
+ */
+ if (ip6->ip6_plen == 0 && plen == 0) {
+ /*
+ * Note that if a valid jumbo payload option is
+ * contained, ip6_hoptops_input() must set a valid
+ * (non-zero) payload length to the variable plen.
+ */
+ ip6stat.ip6s_badoptions++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
+ icmp6_error(m, ICMP6_PARAM_PROB,
+ ICMP6_PARAMPROB_HEADER,
+ (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
+ return;
+ }
#ifndef PULLDOWN_TEST
/* ip6_hopopts_input() ensures that mbuf is contiguous */
hbh = (struct ip6_hbh *)(ip6 + 1);
@@ -590,8 +615,7 @@ ip6_input(m)
m_freem(m);
return;
}
- }
- else if (!ours) {
+ } else if (!ours) {
ip6_forward(m, 0);
return;
}
@@ -695,6 +719,7 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
int optlen = 0;
u_int8_t *opt = opthead;
u_int16_t rtalert_val;
+ u_int32_t jumboplen;
for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
switch(*opt) {
@@ -723,57 +748,75 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
*rtalertp = ntohs(rtalert_val);
break;
case IP6OPT_JUMBO:
- /* XXX may need check for alignment */
- if (hbhlen < IP6OPT_JUMBO_LEN) {
- ip6stat.ip6s_toosmall++;
- goto bad;
- }
- if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
- /* XXX: should we discard the packet? */
- log(LOG_ERR, "length of jumbopayload opt "
- "is inconsistent(%d)",
- *(opt + 1));
- optlen = IP6OPT_JUMBO_LEN;
+ /* XXX may need check for alignment */
+ if (hbhlen < IP6OPT_JUMBO_LEN) {
+ ip6stat.ip6s_toosmall++;
+ goto bad;
+ }
+ if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
+ /* XXX: should we discard the packet? */
+ log(LOG_ERR, "length of jumbopayload opt "
+ "is inconsistent(%d)",
+ *(opt + 1));
+ optlen = IP6OPT_JUMBO_LEN;
- /*
- * We can simply cast because of the alignment
- * requirement of the jumbo payload option.
- */
-#if 0
- *plenp = ntohl(*(u_int32_t *)(opt + 2));
-#else
- bcopy(opt + 2, plenp, sizeof(*plenp));
- *plenp = htonl(*plenp);
+ /*
+ * IPv6 packets that have non 0 payload length
+ * must not contain a jumbo paylod option.
+ */
+ ip6 = mtod(m, struct ip6_hdr *);
+ if (ip6->ip6_plen) {
+ ip6stat.ip6s_badoptions++;
+ icmp6_error(m, ICMP6_PARAM_PROB,
+ ICMP6_PARAMPROB_HEADER,
+ sizeof(struct ip6_hdr) +
+ sizeof(struct ip6_hbh) +
+ opt - opthead);
+ return(-1);
+ }
+
+ /*
+ * We may see jumbolen in unaligned location, so
+ * we'd need to perform bcopy().
+ */
+ bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
+ jumboplen = (u_int32_t)htonl(jumboplen);
+
+#if 1
+ /*
+ * if there are multiple jumbo payload options,
+ * *plenp will be non-zero and the packet will be
+ * rejected.
+ * the behavior may need some debate in ipngwg -
+ * multiple options does not make sense, however,
+ * there's no explicit mention in specification.
+ */
+ if (*plenp != 0) {
+ ip6stat.ip6s_badoptions++;
+ icmp6_error(m, ICMP6_PARAM_PROB,
+ ICMP6_PARAMPROB_HEADER,
+ sizeof(struct ip6_hdr) +
+ sizeof(struct ip6_hbh) +
+ opt + 2 - opthead);
+ return(-1);
+ }
#endif
- if (*plenp <= IPV6_MAXPACKET) {
- /*
- * jumbo payload length must be larger
- * than 65535
- */
- ip6stat.ip6s_badoptions++;
- icmp6_error(m, ICMP6_PARAM_PROB,
- ICMP6_PARAMPROB_HEADER,
- sizeof(struct ip6_hdr) +
- sizeof(struct ip6_hbh) +
- opt + 2 - opthead);
- return(-1);
- }
- ip6 = mtod(m, struct ip6_hdr *);
- if (ip6->ip6_plen) {
- /*
- * IPv6 packets that have non 0 payload length
- * must not contain a jumbo paylod option.
- */
- ip6stat.ip6s_badoptions++;
- icmp6_error(m, ICMP6_PARAM_PROB,
- ICMP6_PARAMPROB_HEADER,
- sizeof(struct ip6_hdr) +
- sizeof(struct ip6_hbh) +
- opt - opthead);
- return(-1);
- }
- break;
+ /*
+ * jumbo payload length must be larger than 65535.
+ */
+ if (jumboplen <= IPV6_MAXPACKET) {
+ ip6stat.ip6s_badoptions++;
+ icmp6_error(m, ICMP6_PARAM_PROB,
+ ICMP6_PARAMPROB_HEADER,
+ sizeof(struct ip6_hdr) +
+ sizeof(struct ip6_hbh) +
+ opt + 2 - opthead);
+ return(-1);
+ }
+ *plenp = jumboplen;
+
+ break;
default: /* unknown option */
if (hbhlen < IP6OPT_MINLEN) {
ip6stat.ip6s_toosmall++;