A bug in udp6_input() - should use proto instead of ip6->ip6_nxt
Tiwei Bie
btw at mail.ustc.edu.cn
Mon Aug 31 04:05:33 UTC 2015
I found a bug in udp6_input(). The 'proto' parameter should be used to
get the protocol number (UDP or UDPLITE), instead of ip6->ip6_nxt.
Because ip6->ip6_nxt may be the protocol number of extension header,
such as:
If a UDP packet is an "atomic" fragment, frag6_input() will return
directly, and ip6->ip6_nxt will be IPPROTO_FRAGMENT (if the first
extension header is the fragment header) instead of IPPROTO_UDP or
IPPROTO_UDPLITE:
int
frag6_input(struct mbuf **mp, int *offp, int proto)
{
......
/*
* RFC 6946: Handle "atomic" fragments (offset and m bit set to 0)
* upfront, unrelated to any reassembly. Just skip the fragment header.
*/
if ((ip6f->ip6f_offlg & ~IP6F_RESERVED_MASK) == 0) {
/* XXX-BZ we want dedicated counters for this. */
IP6STAT_INC(ip6s_reassembled);
in6_ifstat_inc(dstifp, ifs6_reass_ok);
*offp = offset;
return (ip6f->ip6f_nxt);
}
And this is the patch to fix this bug:
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 98790a8..da72f00 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -207,7 +207,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
struct sockaddr_in6 fromsa;
struct m_tag *fwd_tag;
uint16_t uh_sum;
- uint8_t nxt;
+ uint8_t nxt = proto;
ifp = m->m_pkthdr.rcvif;
ip6 = mtod(m, struct ip6_hdr *);
@@ -233,7 +233,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6);
ulen = ntohs((u_short)uh->uh_ulen);
- nxt = ip6->ip6_nxt;
cscov_partial = (nxt == IPPROTO_UDPLITE) ? 1 : 0;
if (nxt == IPPROTO_UDPLITE) {
/* Zero means checksum over the complete packet. */
Best regards,
Tiwei Bie
More information about the freebsd-net
mailing list