From a859f058374606ff1d4249e53b66e1d3d20fdcb7 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 3 Mar 2019 09:01:23 +0100 Subject: [PATCH] devip: fix block list handling for icmp/icmp6, use proper MinAdvise for icmp6 --- sys/src/9/ip/icmp.c | 43 +++++++++++++------------------------------ sys/src/9/ip/icmp6.c | 43 +++++++++++++++++++------------------------ 2 files changed, 32 insertions(+), 54 deletions(-) diff --git a/sys/src/9/ip/icmp.c b/sys/src/9/ip/icmp.c index bef9d77de..8f61b073b 100644 --- a/sys/src/9/ip/icmp.c +++ b/sys/src/9/ip/icmp.c @@ -44,11 +44,6 @@ enum { /* Packet Types */ Maxtype = 18, }; -enum -{ - MinAdvise = 24, /* minimum needed for us to advise another protocol */ -}; - char *icmpnames[Maxtype+1] = { [EchoReply] "EchoReply", @@ -70,6 +65,8 @@ enum { IP_ICMPPROTO = 1, ICMP_IPSIZE = 20, ICMP_HDRSIZE = 8, + + MinAdvise = ICMP_IPSIZE+4, /* minimum needed for us to advise another protocol */ }; enum @@ -169,8 +166,7 @@ icmpkick(void *x, Block *bp) if(bp == nil) return; - - if(blocklen(bp) < ICMP_IPSIZE + ICMP_HDRSIZE){ + if(BLEN(bp) < ICMP_IPSIZE + ICMP_HDRSIZE){ freeblist(bp); return; } @@ -350,7 +346,7 @@ static char *unreachcode[] = static void icmpiput(Proto *icmp, Ipifc*, Block *bp) { - int n, iplen; + int n; Icmp *p; Block *r; Proto *pr; @@ -359,42 +355,31 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp) Icmppriv *ipriv; ipriv = icmp->priv; - ipriv->stats[InMsgs]++; - p = (Icmp *)bp->rp; - netlog(icmp->f, Logicmp, "icmpiput %s (%d) %d\n", - (p->type < nelem(icmpnames)? icmpnames[p->type]: ""), - p->type, p->code); - n = blocklen(bp); + bp = concatblock(bp); + n = BLEN(bp); if(n < ICMP_IPSIZE+ICMP_HDRSIZE){ ipriv->stats[InErrors]++; ipriv->stats[HlenErrs]++; netlog(icmp->f, Logicmp, "icmp hlen %d\n", n); goto raise; } - iplen = nhgets(p->length); - if(iplen > n){ - ipriv->stats[LenErrs]++; - ipriv->stats[InErrors]++; - netlog(icmp->f, Logicmp, "icmp length %d\n", iplen); - goto raise; - } - if(ptclcsum(bp, ICMP_IPSIZE, iplen - ICMP_IPSIZE)){ + if(ptclcsum(bp, ICMP_IPSIZE, n - ICMP_IPSIZE)){ ipriv->stats[InErrors]++; ipriv->stats[CsumErrs]++; netlog(icmp->f, Logicmp, "icmp checksum error\n"); goto raise; } + p = (Icmp *)bp->rp; + netlog(icmp->f, Logicmp, "icmpiput %s (%d) %d\n", + (p->type < nelem(icmpnames)? icmpnames[p->type]: ""), + p->type, p->code); if(p->type <= Maxtype) ipriv->in[p->type]++; switch(p->type) { case EchoRequest: - if(iplen < n) - bp = trimblock(bp, 0, iplen); - if(bp->next != nil) - bp = concatblock(bp); r = mkechoreply(bp, icmp->f); if(r == nil) goto raise; @@ -410,7 +395,7 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp) msg = unreachcode[p->code]; bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE; - if(blocklen(bp) < MinAdvise){ + if(BLEN(bp) < MinAdvise){ ipriv->stats[LenErrs]++; goto raise; } @@ -420,7 +405,6 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp) (*pr->advise)(pr, bp, msg); return; } - bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE; goticmpkt(icmp, bp); break; @@ -429,7 +413,7 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp) snprint(m2, sizeof m2, "ttl exceeded at %V", p->src); bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE; - if(blocklen(bp) < MinAdvise){ + if(BLEN(bp) < MinAdvise){ ipriv->stats[LenErrs]++; goto raise; } @@ -441,7 +425,6 @@ icmpiput(Proto *icmp, Ipifc*, Block *bp) } bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE; } - goticmpkt(icmp, bp); break; default: diff --git a/sys/src/9/ip/icmp6.c b/sys/src/9/ip/icmp6.c index 4180942a8..018528b7a 100644 --- a/sys/src/9/ip/icmp6.c +++ b/sys/src/9/ip/icmp6.c @@ -67,6 +67,10 @@ enum { Maxtype6 = 137, }; +enum { + MinAdvise = IP6HDR+4, /* minimum needed for us to advise another protocol */ +}; + /* on-the-wire packet formats */ typedef struct IPICMP IPICMP; typedef struct Ndpkt Ndpkt; @@ -189,13 +193,14 @@ static void set_cksum(Block *bp) { IPICMP *p = (IPICMP *)(bp->rp); + int n = blocklen(bp); hnputl(p->vcf, 0); /* borrow IP header as pseudoheader */ - hnputs(p->ploadlen, blocklen(bp) - IP6HDR); + hnputs(p->ploadlen, n - IP6HDR); p->proto = 0; p->ttl = ICMPv6; /* ttl gets set later */ hnputs(p->cksum, 0); - hnputs(p->cksum, ptclcsum(bp, 0, blocklen(bp))); + hnputs(p->cksum, ptclcsum(bp, 0, n)); p->proto = ICMPv6; } @@ -259,7 +264,7 @@ icmpkick6(void *x, Block *bp) bp = padblock(bp, IP6HDR); } - if(blocklen(bp) < IPICMPSZ){ + if(BLEN(bp) < IPICMPSZ){ freeblist(bp); return; } @@ -524,26 +529,17 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp) * RFC 2461, pages 39-40, pages 57-58. */ static int -valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv) +valid(Proto *icmp, Ipifc *, Block *bp, Icmppriv6 *ipriv) { - int sz, osz, unsp, n, ttl, iplen; + int sz, osz, unsp, ttl; int pktsz = BLEN(bp); uchar *packet = bp->rp; IPICMP *p = (IPICMP *) packet; Ndpkt *np; - USED(ifc); - n = blocklen(bp); - if(n < IPICMPSZ) { + if(pktsz < IPICMPSZ) { ipriv->stats[HlenErrs6]++; - netlog(icmp->f, Logicmp, "icmp hlen %d\n", n); - goto err; - } - - iplen = nhgets(p->ploadlen); - if(iplen > n - IP6HDR) { - ipriv->stats[LenErrs6]++; - netlog(icmp->f, Logicmp, "icmp length %d\n", iplen); + netlog(icmp->f, Logicmp, "icmp hlen %d\n", pktsz); goto err; } @@ -557,7 +553,7 @@ valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv) ttl = p->ttl; p->ttl = p->proto; p->proto = 0; - if(ptclcsum(bp, 0, iplen + IP6HDR)) { + if(ptclcsum(bp, 0, pktsz)) { ipriv->stats[CsumErrs6]++; netlog(icmp->f, Logicmp, "icmp checksum error\n"); goto err; @@ -678,15 +674,17 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp) { char *msg, m2[128]; uchar pktflags; - uchar *packet = bp->rp; uchar ia[IPaddrlen]; Block *r; - IPICMP *p = (IPICMP *)packet; + IPICMP *p; Icmppriv6 *ipriv = icmp->priv; Iplifc *lifc; Ndpkt* np; Proto *pr; + bp = concatblock(bp); + p = (IPICMP*)bp->rp; + if(!valid(icmp, ifc, bp, ipriv) || p->type > Maxtype6) goto raise; @@ -694,8 +692,6 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp) switch(p->type) { case EchoRequestV6: - if(bp->next != nil) - bp = concatblock(bp); r = mkechoreply6(bp, ifc); if(r == nil) goto raise; @@ -710,7 +706,7 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp) msg = unreachcode[p->code]; bp->rp += IPICMPSZ; - if(blocklen(bp) < 8){ + if(BLEN(bp) < MinAdvise){ ipriv->stats[LenErrs6]++; goto raise; } @@ -720,7 +716,6 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp) (*pr->advise)(pr, bp, msg); return; } - bp->rp -= IPICMPSZ; goticmpkt6(icmp, bp, 0); break; @@ -730,7 +725,7 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp) sprint(m2, "ttl exceeded at %I", p->src); bp->rp += IPICMPSZ; - if(blocklen(bp) < 8){ + if(BLEN(bp) < MinAdvise){ ipriv->stats[LenErrs6]++; goto raise; }