Index: sys/netinet6/ip6_input.c =================================================================== --- sys/netinet6/ip6_input.c +++ sys/netinet6/ip6_input.c @@ -420,16 +420,11 @@ 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 the payload length field is 0 and the next header field indicates + * Hop-by-Hop Options header, then this must be a jumbo payload. We do + * not support jumbo payloads, report an error to the sender. */ - if (ip6->ip6_plen == 0 && *plen == 0) { - /* - * Note that if a valid jumbo payload option is - * contained, ip6_hopopts_input() must set a valid - * (non-zero) payload length to the variable plen. - */ + if (ip6->ip6_plen == 0) { IP6STAT_INC(ip6s_badoptions); in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); @@ -850,7 +845,6 @@ /* * Process Hop-by-Hop options header if it's contained. * m may be modified in ip6_hopopts_input(). - * If a JumboPayload option is included, plen will also be modified. */ plen = (u_int32_t)ntohs(ip6->ip6_plen); if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { @@ -968,8 +962,8 @@ } /* - * Hop-by-Hop options header processing. If a valid jumbo payload option is - * included, the real payload length will be stored in plenp. + * Hop-by-Hop options header processing. If a jumbo payload option is present + * report an error. * * rtalertp - XXX: should be stored more smart way */ @@ -1007,7 +1001,7 @@ off += hbhlen; hbhlen -= sizeof(struct ip6_hbh); if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), - hbhlen, rtalertp, plenp) < 0) + hbhlen, rtalertp) < 0) return (-1); *offp = off; @@ -1027,13 +1021,11 @@ */ int ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen, - u_int32_t *rtalertp, u_int32_t *plenp) + u_int32_t *rtalertp) { - struct ip6_hdr *ip6; int optlen = 0; u_int8_t *opt = opthead; u_int16_t rtalert_val; - u_int32_t jumboplen; const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh); for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { @@ -1066,71 +1058,8 @@ *rtalertp = ntohs(rtalert_val); break; case IP6OPT_JUMBO: - /* XXX may need check for alignment */ - if (hbhlen < IP6OPT_JUMBO_LEN) { - IP6STAT_INC(ip6s_toosmall); - goto bad; - } - if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { - /* XXX stat */ - icmp6_error(m, ICMP6_PARAM_PROB, - ICMP6_PARAMPROB_HEADER, - erroff + opt + 1 - opthead); - return (-1); - } - optlen = IP6OPT_JUMBO_LEN; - - /* - * IPv6 packets that have non 0 payload length - * must not contain a jumbo payload option. - */ - ip6 = mtod(m, struct ip6_hdr *); - if (ip6->ip6_plen) { - IP6STAT_INC(ip6s_badoptions); - icmp6_error(m, ICMP6_PARAM_PROB, - ICMP6_PARAMPROB_HEADER, - erroff + 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_INC(ip6s_badoptions); - icmp6_error(m, ICMP6_PARAM_PROB, - ICMP6_PARAMPROB_HEADER, - erroff + opt + 2 - opthead); - return (-1); - } -#endif - - /* - * jumbo payload length must be larger than 65535. - */ - if (jumboplen <= IPV6_MAXPACKET) { - IP6STAT_INC(ip6s_badoptions); - icmp6_error(m, ICMP6_PARAM_PROB, - ICMP6_PARAMPROB_HEADER, - erroff + opt + 2 - opthead); - return (-1); - } - *plenp = jumboplen; - - break; + /* We do not support the jumbo payload option */ + goto bad; default: /* unknown option */ if (hbhlen < IP6OPT_MINLEN) { IP6STAT_INC(ip6s_toosmall); @@ -1453,7 +1382,6 @@ return; } #endif - /* * XXX: We copy the whole header even if a * jumbo payload option is included, the option which Index: sys/netinet6/ip6_output.c =================================================================== --- sys/netinet6/ip6_output.c +++ sys/netinet6/ip6_output.c @@ -142,7 +142,6 @@ static int ip6_copyexthdr(struct mbuf **, caddr_t, int); static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int, struct ip6_frag **); -static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t); static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *); static int ip6_getpmtu(struct route_in6 *, int, struct ifnet *, const struct in6_addr *, u_long *, int *, u_int, @@ -399,21 +398,9 @@ m->m_pkthdr.len += optlen; plen = m->m_pkthdr.len - sizeof(*ip6); - /* If this is a jumbo payload, insert a jumbo payload option. */ if (plen > IPV6_MAXPACKET) { - if (!hdrsplit) { - if ((error = ip6_splithdr(m, &exthdrs)) != 0) { - m = NULL; - goto freehdrs; - } - m = exthdrs.ip6e_ip6; - hdrsplit++; - } - /* adjust pointer */ - ip6 = mtod(m, struct ip6_hdr *); - if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0) - goto freehdrs; - ip6->ip6_plen = 0; + error = EMSGSIZE; + goto freehdrs; } else ip6->ip6_plen = htons(plen); @@ -766,7 +753,6 @@ if (exthdrs.ip6e_hbh) { struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *); u_int32_t dummy; /* XXX unused */ - u_int32_t plen = 0; /* XXX: ip6_process will check the value */ #ifdef DIAGNOSTIC if ((hbh->ip6h_len + 1) << 3 > exthdrs.ip6e_hbh->m_len) @@ -782,7 +768,7 @@ m->m_pkthdr.rcvif = ifp; if (ip6_process_hopopts(m, (u_int8_t *)(hbh + 1), ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh), - &dummy, &plen) < 0) { + &dummy) < 0) { /* m was already freed at this point */ error = EINVAL;/* better error? */ goto done; @@ -983,7 +969,7 @@ in6_ifstat_inc(ifp, ifs6_out_fragfail); goto bad; } else if (ip6->ip6_plen == 0) { - /* jumbo payload cannot be fragmented */ + /* we don't support jumbo payload return error */ error = EMSGSIZE; in6_ifstat_inc(ifp, ifs6_out_fragfail); goto bad; @@ -1132,94 +1118,6 @@ return (0); } -/* - * Insert jumbo payload option. - */ -static int -ip6_insert_jumboopt(struct ip6_exthdrs *exthdrs, u_int32_t plen) -{ - struct mbuf *mopt; - u_char *optbuf; - u_int32_t v; - -#define JUMBOOPTLEN 8 /* length of jumbo payload option and padding */ - - /* - * If there is no hop-by-hop options header, allocate new one. - * If there is one but it doesn't have enough space to store the - * jumbo payload option, allocate a cluster to store the whole options. - * Otherwise, use it to store the options. - */ - if (exthdrs->ip6e_hbh == NULL) { - mopt = m_get(M_NOWAIT, MT_DATA); - if (mopt == NULL) - return (ENOBUFS); - mopt->m_len = JUMBOOPTLEN; - optbuf = mtod(mopt, u_char *); - optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */ - exthdrs->ip6e_hbh = mopt; - } else { - struct ip6_hbh *hbh; - - mopt = exthdrs->ip6e_hbh; - if (M_TRAILINGSPACE(mopt) < JUMBOOPTLEN) { - /* - * XXX assumption: - * - exthdrs->ip6e_hbh is not referenced from places - * other than exthdrs. - * - exthdrs->ip6e_hbh is not an mbuf chain. - */ - int oldoptlen = mopt->m_len; - struct mbuf *n; - - /* - * XXX: give up if the whole (new) hbh header does - * not fit even in an mbuf cluster. - */ - if (oldoptlen + JUMBOOPTLEN > MCLBYTES) - return (ENOBUFS); - - /* - * As a consequence, we must always prepare a cluster - * at this point. - */ - n = m_getcl(M_NOWAIT, MT_DATA, 0); - if (n == NULL) - return (ENOBUFS); - n->m_len = oldoptlen + JUMBOOPTLEN; - bcopy(mtod(mopt, caddr_t), mtod(n, caddr_t), - oldoptlen); - optbuf = mtod(n, caddr_t) + oldoptlen; - m_freem(mopt); - mopt = exthdrs->ip6e_hbh = n; - } else { - optbuf = mtod(mopt, u_char *) + mopt->m_len; - mopt->m_len += JUMBOOPTLEN; - } - optbuf[0] = IP6OPT_PADN; - optbuf[1] = 1; - - /* - * Adjust the header length according to the pad and - * the jumbo payload option. - */ - hbh = mtod(mopt, struct ip6_hbh *); - hbh->ip6h_len += (JUMBOOPTLEN >> 3); - } - - /* fill in the option. */ - optbuf[2] = IP6OPT_JUMBO; - optbuf[3] = 4; - v = (u_int32_t)htonl(plen + JUMBOOPTLEN); - bcopy(&v, &optbuf[4], sizeof(u_int32_t)); - - /* finally, adjust the packet header length */ - exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN; - - return (0); -#undef JUMBOOPTLEN -} - /* * Insert fragment header and copy unfragmentable header portions. */ Index: sys/netinet6/ip6_var.h =================================================================== --- sys/netinet6/ip6_var.h +++ sys/netinet6/ip6_var.h @@ -384,8 +384,7 @@ extern int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *); -int ip6_process_hopopts(struct mbuf *, u_int8_t *, int, u_int32_t *, - u_int32_t *); +int ip6_process_hopopts(struct mbuf *, u_int8_t *, int, u_int32_t *); struct mbuf **ip6_savecontrol_v4(struct inpcb *, struct mbuf *, struct mbuf **, int *); void ip6_savecontrol(struct inpcb *, struct mbuf *, struct mbuf **); Index: sys/netinet6/udp6_usrreq.c =================================================================== --- sys/netinet6/udp6_usrreq.c +++ sys/netinet6/udp6_usrreq.c @@ -703,11 +703,6 @@ /* addr6 has been validated in udp6_send(). */ sin6 = (struct sockaddr_in6 *)addr6; - /* - * In contrast to to IPv4 we do not validate the max. packet length - * here due to IPv6 Jumbograms (RFC2675). - */ - scope_ambiguous = 0; if (sin6) { /* Protect *addr6 from overwrites. */ @@ -891,6 +886,11 @@ plen = sizeof(struct udphdr) + ulen; hlen = sizeof(struct ip6_hdr); + if (plen > IPV6_MAXPACKET) { + error = EMSGSIZE; + goto release; + } + /* * Calculate data length and get a mbuf * for UDP and IP6 headers. @@ -921,10 +921,8 @@ * the entire UDPLite packet is covered by the checksum. */ cscov_partial = (cscov == 0) ? 0 : 1; - } else if (plen <= 0xffff) + } else udp6->uh_ulen = htons((u_short)plen); - else - udp6->uh_ulen = 0; udp6->uh_sum = 0; ip6 = mtod(m, struct ip6_hdr *);