shithub: riscv

Download patch

ref: a859f058374606ff1d4249e53b66e1d3d20fdcb7
parent: a2c0e55e6885fde0d135831a77d227bc933d89e7
author: cinap_lenrek <[email protected]>
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;
 			}