Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet6/ip6_input.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet6/ip6_input.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.56 retrieving revision 1.58 diff -u -p -r1.56 -r1.58 --- src/sys/netinet6/ip6_input.c 2002/06/09 14:43:12 1.56 +++ src/sys/netinet6/ip6_input.c 2002/09/11 02:41:25 1.58 @@ -1,4 +1,4 @@ -/* $NetBSD: ip6_input.c,v 1.56 2002/06/09 14:43:12 itojun Exp $ */ +/* $NetBSD: ip6_input.c,v 1.58 2002/09/11 02:41:25 itojun Exp $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ /* @@ -66,7 +66,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.56 2002/06/09 14:43:12 itojun Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.58 2002/09/11 02:41:25 itojun Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -269,9 +269,23 @@ ip6_input(m) IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/); #endif - if (m->m_len < sizeof(struct ip6_hdr)) { - struct ifnet *inifp; - inifp = m->m_pkthdr.rcvif; + /* + * If the IPv6 header is not aligned, slurp it up into a new + * mbuf with space for link headers, in the event we forward + * it. OTherwise, if it is aligned, make sure the entire base + * IPv6 header is in the first mbuf of the chain. + */ + if (IP6_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) { + struct ifnet *inifp = m->m_pkthdr.rcvif; + if ((m = m_copyup(m, sizeof(struct ip6_hdr), + (max_linkhdr + 3) & ~3)) == NULL) { + /* XXXJRT new stat, please */ + ip6stat.ip6s_toosmall++; + in6_ifstat_inc(inifp, ifs6_in_hdrerr); + return; + } + } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) { + struct ifnet *inifp = m->m_pkthdr.rcvif; if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { ip6stat.ip6s_toosmall++; in6_ifstat_inc(inifp, ifs6_in_hdrerr); @@ -625,6 +639,7 @@ ip6_input(m) return; } #endif + KASSERT(IP6_HDR_ALIGNED_P(hbh)); nxt = hbh->ip6h_nxt; /* @@ -789,17 +804,18 @@ ip6_hopopts_input(plenp, rtalertp, mp, o return -1; } #endif + KASSERT(IP6_HDR_ALIGNED_P(hbh)); off += hbhlen; hbhlen -= sizeof(struct ip6_hbh); opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh); if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), hbhlen, rtalertp, plenp) < 0) - return(-1); + return (-1); *offp = off; *mp = m; - return(0); + return (0); } /* @@ -959,14 +975,14 @@ ip6_unknown_opt(optp, m, off) switch (IP6OPT_TYPE(*optp)) { case IP6OPT_TYPE_SKIP: /* ignore the option */ - return((int)*(optp + 1)); + return ((int)*(optp + 1)); case IP6OPT_TYPE_DISCARD: /* silently discard */ m_freem(m); - return(-1); + return (-1); case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ ip6stat.ip6s_badoptions++; icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); - return(-1); + return (-1); case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ ip6stat.ip6s_badoptions++; ip6 = mtod(m, struct ip6_hdr *); @@ -976,11 +992,11 @@ ip6_unknown_opt(optp, m, off) else icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); - return(-1); + return (-1); } m_freem(m); /* XXX: NOTREACHED */ - return(-1); + return (-1); } /* @@ -1150,6 +1166,7 @@ ip6_savecontrol(in6p, mp, ip6, m) return; } #endif + KASSERT(IP6_HDR_ALIGNED_P(ip6e)); switch (nxt) { case IPPROTO_DSTOPTS: @@ -1226,7 +1243,7 @@ ip6_savecontrol(in6p, mp, ip6, m) * carefully. Moreover, it will not be used in the near future when * we develop `neater' mechanism to process extension headers. */ -char * +u_int8_t * ip6_get_prevhdr(m, off) struct mbuf *m; int off; @@ -1234,7 +1251,7 @@ ip6_get_prevhdr(m, off) struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); if (off == sizeof(struct ip6_hdr)) - return(&ip6->ip6_nxt); + return (&ip6->ip6_nxt); else { int len, nxt; struct ip6_ext *ip6e = NULL; @@ -1258,7 +1275,7 @@ ip6_get_prevhdr(m, off) nxt = ip6e->ip6e_nxt; } if (ip6e) - return(&ip6e->ip6e_nxt); + return (&ip6e->ip6e_nxt); else return NULL; }