On 04/07/16(Mon) 15:52, Alexander Bluhm wrote: > On Mon, Jul 04, 2016 at 01:03:22PM +0200, Martin Pieuchot wrote: > > + if (ip6_hbhchcheck(m, &off, &nxt, &ours)) { > > + if_put(ifp); > > + return; /* m have already been freed */ > > } > > As ip6_hbhchcheck() does ip6 = mtod(m, struct ip6_hdr *) after > ip6_hopopts_input() you have to add this here, too. > > /* adjust pointer */ > ip6 = mtod(m, struct ip6_hdr *);
Updated thanks! > > +int > > +ip6_hbhchcheck(struct mbuf *m, int *offp, int *nxtp, int *oursp) > > +{ > > + struct ip6_hdr *ip6; > > + u_int32_t plen, rtalert = ~0; > > + int ours, off, nxt; > > ours may be used uninitialized. > > > + *offp = off; > > + *nxtp = nxt; > > + *oursp = ours; > > I would prefer to use the passed values as *off, *nxt, *ours directly > than to use another set of local variables. This also fixes > initialization problem. Fine, new diff doing that. Index: netinet6/ip6_input.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.161 diff -u -p -r1.161 ip6_input.c --- netinet6/ip6_input.c 5 Jul 2016 10:17:14 -0000 1.161 +++ netinet6/ip6_input.c 5 Jul 2016 10:21:10 -0000 @@ -122,6 +122,7 @@ struct ip6stat ip6stat; void ip6_init2(void *); int ip6_check_rh0hdr(struct mbuf *, int *); +int ip6_hbhchcheck(struct mbuf *, int *, int *, int *); int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); @@ -192,7 +193,6 @@ ip6_input(struct mbuf *m) struct ip6_hdr *ip6; int off, nest; u_int16_t src_scope, dst_scope; - u_int32_t plen, rtalert = ~0; int nxt, ours = 0; #if NPF > 0 struct in6_addr odst; @@ -495,78 +495,15 @@ ip6_input(struct mbuf *m) } hbhcheck: - /* - * 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); - off = sizeof(struct ip6_hdr); - if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { - struct ip6_hbh *hbh; - - if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { - if_put(ifp); - 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_hopopts_input() must set a valid - * (non-zero) payload length to the variable plen. - */ - ip6stat.ip6s_badoptions++; - icmp6_error(m, ICMP6_PARAM_PROB, - ICMP6_PARAMPROB_HEADER, - (caddr_t)&ip6->ip6_plen - (caddr_t)ip6); - if_put(ifp); - return; - } - IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), - sizeof(struct ip6_hbh)); - if (hbh == NULL) { - ip6stat.ip6s_tooshort++; - if_put(ifp); - return; - } - nxt = hbh->ip6h_nxt; - /* - * accept the packet if a router alert option is included - * and we act as an IPv6 router. - */ - if (rtalert != ~0 && ip6_forwarding) - ours = 1; - } else - nxt = ip6->ip6_nxt; - - /* - * Check that the amount of data in the buffers - * is as at least much as the IPv6 header would have us expect. - * Trim mbufs if longer than we expect. - * Drop packet if shorter than we expect. - */ - if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { - ip6stat.ip6s_tooshort++; - goto bad; - } - if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { - if (m->m_len == m->m_pkthdr.len) { - m->m_len = sizeof(struct ip6_hdr) + plen; - m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; - } else - m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); + if (ip6_hbhchcheck(m, &off, &nxt, &ours)) { + if_put(ifp); + return; /* m have already been freed */ } + /* adjust pointer */ + ip6 = mtod(m, struct ip6_hdr *); + /* * Forward if desirable. */ @@ -638,6 +575,89 @@ ip6_input(struct mbuf *m) bad: if_put(ifp); m_freem(m); +} + +int +ip6_hbhchcheck(struct mbuf *m, int *offp, int *nxtp, int *oursp) +{ + struct ip6_hdr *ip6; + u_int32_t plen, rtalert = ~0; + + ip6 = mtod(m, struct ip6_hdr *); + + /* + * 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); + *offp = sizeof(struct ip6_hdr); + if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { + struct ip6_hbh *hbh; + + if (ip6_hopopts_input(&plen, &rtalert, &m, offp)) { + return (-1); /* 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_hopopts_input() must set a valid + * (non-zero) payload length to the variable plen. + */ + ip6stat.ip6s_badoptions++; + icmp6_error(m, ICMP6_PARAM_PROB, + ICMP6_PARAMPROB_HEADER, + (caddr_t)&ip6->ip6_plen - (caddr_t)ip6); + return (-1); + } + IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), + sizeof(struct ip6_hbh)); + if (hbh == NULL) { + ip6stat.ip6s_tooshort++; + return (-1); + } + *nxtp = hbh->ip6h_nxt; + + /* + * accept the packet if a router alert option is included + * and we act as an IPv6 router. + */ + if (rtalert != ~0 && ip6_forwarding) + *oursp = 1; + } else + *nxtp = ip6->ip6_nxt; + + /* + * Check that the amount of data in the buffers + * is as at least much as the IPv6 header would have us expect. + * Trim mbufs if longer than we expect. + * Drop packet if shorter than we expect. + */ + if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { + ip6stat.ip6s_tooshort++; + m_freem(m); + return (-1); + } + if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { + if (m->m_len == m->m_pkthdr.len) { + m->m_len = sizeof(struct ip6_hdr) + plen; + m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; + } else { + m_adj(m, + sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); + } + } + + return (0); } /* scan packet for RH0 routing header. Mostly stolen from pf.c:pf_test() */