ref: a859f058374606ff1d4249e53b66e1d3d20fdcb7
parent: a2c0e55e6885fde0d135831a77d227bc933d89e7
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Mar 3 04:01:23 EST 2019
devip: fix block list handling for icmp/icmp6, use proper MinAdvise for icmp6
--- a/sys/src/9/ip/icmp.c
+++ b/sys/src/9/ip/icmp.c
@@ -44,11 +44,6 @@
Maxtype = 18,
};
-enum
-{
- MinAdvise = 24, /* minimum needed for us to advise another protocol */
-};
-
char *icmpnames[Maxtype+1] =
{
[EchoReply] "EchoReply",
@@ -70,6 +65,8 @@
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 @@
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 void
icmpiput(Proto *icmp, Ipifc*, Block *bp)
{
- int n, iplen;
+ int n;
Icmp *p;
Block *r;
Proto *pr;
@@ -359,14 +355,10 @@
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]++;
@@ -373,28 +365,21 @@
netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
goto raise;
}
- iplen = nhgets(p->length);
- if(iplen > n){
- ipriv->stats[LenErrs]++;
+ if(ptclcsum(bp, ICMP_IPSIZE, n - ICMP_IPSIZE)){
ipriv->stats[InErrors]++;
- netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);
- goto raise;
- }
- if(ptclcsum(bp, ICMP_IPSIZE, iplen - 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 @@
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 @@
(*pr->advise)(pr, bp, msg);
return;
}
-
bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
goticmpkt(icmp, bp);
break;
@@ -429,7 +413,7 @@
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 @@
}
bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
}
-
goticmpkt(icmp, bp);
break;
default:
--- a/sys/src/9/ip/icmp6.c
+++ b/sys/src/9/ip/icmp6.c
@@ -67,6 +67,10 @@
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 @@
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 @@
bp = padblock(bp, IP6HDR);
}
- if(blocklen(bp) < IPICMPSZ){
+ if(BLEN(bp) < IPICMPSZ){
freeblist(bp);
return;
}
@@ -524,29 +529,20 @@
* 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);
+ netlog(icmp->f, Logicmp, "icmp hlen %d\n", pktsz);
goto err;
}
- iplen = nhgets(p->ploadlen);
- if(iplen > n - IP6HDR) {
- ipriv->stats[LenErrs6]++;
- netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);
- goto err;
- }
-
/* Rather than construct explicit pseudoheader, overwrite IPv6 header */
if(p->proto != ICMPv6) {
/* This code assumes no extension headers!!! */
@@ -557,7 +553,7 @@
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 @@
{
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 @@
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 @@
msg = unreachcode[p->code];
bp->rp += IPICMPSZ;
- if(blocklen(bp) < 8){
+ if(BLEN(bp) < MinAdvise){
ipriv->stats[LenErrs6]++;
goto raise;
}
@@ -720,7 +716,6 @@
(*pr->advise)(pr, bp, msg);
return;
}
-
bp->rp -= IPICMPSZ;
goticmpkt6(icmp, bp, 0);
break;
@@ -730,7 +725,7 @@
sprint(m2, "ttl exceeded at %I", p->src);
bp->rp += IPICMPSZ;
- if(blocklen(bp) < 8){
+ if(BLEN(bp) < MinAdvise){
ipriv->stats[LenErrs6]++;
goto raise;
}