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;