shithub: riscv

Download patch

ref: e2d310e6235b2f75bd0a1423ea424169247d5ae1
parent: 2af6b0896040ab24c2d411a36781d7588935c6cf
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Mar 3 22:13:29 EST 2019

devip: handle packet too big advise for icmp6, remove fragment header

--- a/sys/src/9/ip/icmp6.c
+++ b/sys/src/9/ip/icmp6.c
@@ -704,7 +704,7 @@
 			msg = unreachcode[Icmp6_unknown];
 		else
 			msg = unreachcode[p->code];
-
+	Advise:
 		bp->rp += IPICMPSZ;
 		if(BLEN(bp) < MinAdvise){
 			ipriv->stats[LenErrs6]++;
@@ -711,6 +711,21 @@
 			goto raise;
 		}
 		p = (IPICMP *)bp->rp;
+
+		/* get rid of fragment header if this is the first fragment */
+		if(p->proto == FH && BLEN(bp) >= MinAdvise+IP6FHDR && MinAdvise > IP6HDR){
+			Fraghdr6 *fh = (Fraghdr6*)(bp->rp + IP6HDR);
+			if((nhgets(fh->offsetRM) & ~7) == 0){	/* first fragment */
+				p->proto = fh->nexthdr;
+				/* copy down payload over fragment header */
+				bp->rp += IP6HDR;
+				bp->wp -= IP6FHDR;
+				memmove(bp->rp, bp->rp+IP6FHDR, BLEN(bp));
+				hnputs(p->ploadlen, BLEN(bp));
+				bp->rp -= IP6HDR;
+			}
+		}
+
 		pr = Fsrcvpcolx(icmp->f, p->proto);
 		if(pr != nil && pr->advise != nil) {
 			(*pr->advise)(pr, bp, msg);
@@ -722,24 +737,21 @@
 
 	case TimeExceedV6:
 		if(p->code == 0){
-			sprint(m2, "ttl exceeded at %I", p->src);
-
-			bp->rp += IPICMPSZ;
-			if(BLEN(bp) < MinAdvise){
-				ipriv->stats[LenErrs6]++;
-				goto raise;
-			}
-			p = (IPICMP *)bp->rp;
-			pr = Fsrcvpcolx(icmp->f, p->proto);
-			if(pr != nil && pr->advise != nil) {
-				(*pr->advise)(pr, bp, m2);
-				return;
-			}
-			bp->rp -= IPICMPSZ;
+			snprint(msg = m2, sizeof m2, "ttl exceeded at %I", p->src);
+			goto Advise;
 		}
+		if(p->code == 1){
+			snprint(msg = m2, sizeof m2, "frag time exceeded at %I", p->src);
+			goto Advise;
+		}
 		goticmpkt6(icmp, bp, 0);
 		break;
 
+	case PacketTooBigV6:
+		snprint(msg = m2, sizeof(m2), "packet too big for %lud mtu at %I",
+			(ulong)nhgetl(p->icmpid), p->src);
+		goto Advise;
+
 	case RouterAdvert:
 	case RouterSolicit:
 		goticmpkt6(icmp, bp, p->type);
@@ -793,7 +805,6 @@
 		freeblist(bp);
 		break;
 
-	case PacketTooBigV6:
 	default:
 		goticmpkt6(icmp, bp, 0);
 		break;