diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2003-04-22 02:52:29 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2003-04-22 02:52:29 +0000 |
commit | c7bcbfb3053ac8d50492c63e128daa1655202712 (patch) | |
tree | e4b195f10bf5cdb507298b42005c04a69a401014 /sys/netinet | |
parent | 0b65acf8b3451a16f1aeed826f1acd316e961c48 (diff) |
correct (false) assumption made about m->m_len. dhartmei ok.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_gre.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c index f6fe4d60943..38cedbc0e62 100644 --- a/sys/netinet/ip_gre.c +++ b/sys/netinet/ip_gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_gre.c,v 1.19 2002/08/16 09:32:39 itojun Exp $ */ +/* $OpenBSD: ip_gre.c,v 1.20 2003/04/22 02:52:28 itojun Exp $ */ /* $NetBSD: ip_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -103,7 +103,7 @@ gre_input2(m , hlen, proto) int hlen; u_char proto; { - register struct greip *gip = mtod(m, struct greip *); + register struct greip *gip; register int s; register struct ifqueue *ifq; struct gre_softc *sc; @@ -115,6 +115,13 @@ gre_input2(m , hlen, proto) return (0); } + if (m->m_len < sizeof(*gip)) { + m = m_pullup(m, sizeof(*gip)); + if (m == NULL) + return (ENOBUFS); + } + gip = mtod(m, struct greip *); + m->m_pkthdr.rcvif = &sc->sc_if; sc->sc_if.if_ipackets++; @@ -190,9 +197,11 @@ gre_input2(m , hlen, proto) return (0); } - m->m_data += hlen; - m->m_len -= hlen; - m->m_pkthdr.len -= hlen; + if (hlen > m->m_pkthdr.len) { + m_freem(m); + return (EINVAL); + } + m_adj(m, hlen); #if NBPFILTER > 0 if (sc->sc_if.if_bpf) { @@ -233,7 +242,7 @@ gre_input2(m , hlen, proto) void gre_input(struct mbuf *m, ...) { - register int hlen,ret; + register int hlen, ret; va_list ap; va_start(ap, m); @@ -267,16 +276,16 @@ gre_input(struct mbuf *m, ...) void gre_mobile_input(struct mbuf *m, ...) { - register struct ip *ip = mtod(m, struct ip *); - register struct mobip_h *mip = mtod(m, struct mobip_h *); + register struct ip *ip; + register struct mobip_h *mip; register struct ifqueue *ifq; struct gre_softc *sc; - register int hlen,s; + register int hlen, s; va_list ap; u_char osrc = 0; int msiz; - va_start(ap,m); + va_start(ap, m); hlen = va_arg(ap, int); va_end(ap); @@ -291,22 +300,38 @@ gre_mobile_input(struct mbuf *m, ...) return; } + if (m->m_len < sizeof(*mip)) { + m = m_pullup(m, sizeof(*mip)); + if (m == NULL) + return; + } + ip = mtod(m, struct ip *); + mip = mtod(m, struct mobip_h *); + m->m_pkthdr.rcvif = &sc->sc_if; sc->sc_if.if_ipackets++; sc->sc_if.if_ibytes += m->m_pkthdr.len; - if(ntohs(mip->mh.proto) & MOB_H_SBIT) { + if (ntohs(mip->mh.proto) & MOB_H_SBIT) { osrc = 1; msiz = MOB_H_SIZ_L; mip->mi.ip_src.s_addr = mip->mh.osrc; - } else { + } else msiz = MOB_H_SIZ_S; + + if (m->m_len < (ip->ip_hl << 2) + msiz) { + m = m_pullup(m, (ip->ip_hl << 2) + msiz); + if (m == NULL) + return; + ip = mtod(m, struct ip *); + mip = mtod(m, struct mobip_h *); } + mip->mi.ip_dst.s_addr = mip->mh.odst; mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); - if (gre_in_cksum((u_short *) &mip->mh,msiz) != 0) { + if (gre_in_cksum((u_short *) &mip->mh, msiz) != 0) { m_freem(m); return; } |