DF-0743 / fix.diff
diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c --- a/sys/netinet/ip_gre.c +++ b/sys/netinet/ip_gre.c @@ -130,7 +130,8 @@ gre_input2(struct mbuf *m ,int hlen, u_char proto) { static const uint32_t af = AF_INET; - struct greip *gip = mtod(m, struct greip *); + struct ip *ip = mtod(m, struct ip *); + struct gre_h *gh; /* GRE header at ip_hl*4 (IP-options aware) */ int isr; struct gre_softc *sc; u_short flags; @@ -145,10 +146,15 @@ switch (proto) { case IPPROTO_GRE: + /* The GRE header follows the outer IP header, whose length is + * ip_hl*4 (>= 20 when IP options are present). Do NOT overlay + * struct greip (which assumes a fixed 20-byte IP header) -- read + * the GRE fields at the correct ip_hl-derived offset. */ + gh = (struct gre_h *)((caddr_t)ip + hlen); hlen += sizeof (struct gre_h); /* process GRE flags as packet can be of variable len */ - flags = ntohs(gip->gi_flags); + flags = ntohs(gh->flags); /* Checksum & Offset are present */ if ((flags & GRE_CP) | (flags & GRE_RP)) @@ -161,7 +167,7 @@ if (flags & GRE_SP) hlen +=4; - switch (ntohs(gip->gi_ptype)) { /* ethertypes */ + switch (ntohs(gh->ptype)) { /* ethertypes */ case ETHERTYPE_IP: case WCCP_PROTOCOL_TYPE: isr = NETISR_IP; @@ -207,7 +213,7 @@ static const uint32_t af = AF_INET; struct mbuf *m = *mp; struct ip *ip = mtod(m, struct ip *); - struct mobip_h *mip = mtod(m, struct mobip_h *); + struct mobile_h *mh = (struct mobile_h *)((caddr_t)ip + (ip->ip_hl << 2)); struct gre_softc *sc; int msiz; @@ -220,16 +226,16 @@ IFNET_STAT_INC(&sc->sc_if, ipackets, 1); IFNET_STAT_INC(&sc->sc_if, ibytes, m->m_pkthdr.len); - if(ntohs(mip->mh.proto) & MOB_H_SBIT) { + if(ntohs(mh->proto) & MOB_H_SBIT) { msiz = MOB_H_SIZ_L; - mip->mi.ip_src.s_addr = mip->mh.osrc; + ip->ip_src.s_addr = mh->osrc; } else { msiz = MOB_H_SIZ_S; } - mip->mi.ip_dst.s_addr = mip->mh.odst; - mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); + ip->ip_dst.s_addr = mh->odst; + ip->ip_p = (ntohs(mh->proto) >> 8); - if (gre_in_cksum((u_short*)&mip->mh,msiz) != 0) { + if (gre_in_cksum((u_short*)mh,msiz) != 0) { m_freem(m); return(IPPROTO_DONE); } |