ref: fa97c3dd10d3b74f4774ea21b2d80fcffa7feb48
parent: a859f058374606ff1d4249e53b66e1d3d20fdcb7
author: cinap_lenrek <[email protected]>
date: Sun Mar 3 13:56:18 EST 2019
devip: simplify ip reassembly functions, getting rid of Ipfrag.hlen given that we now keep the block size consistent with the ip packet size, the variable header part of the ip packet is just: BLEN(bp) - fp->flen == fp->hlen. fix bug in ip6reassemble() in the non-fragmented case: reload ih after ip header was moved before writing ih->ploadlen. use concatbloc() instead of pullupblock().
--- a/sys/src/9/ip/ip.c
+++ b/sys/src/9/ip/ip.c
@@ -408,27 +408,24 @@
static Block*
ip4reassemble(IP *ip, int offset, Block *bp)
{
- int fend;
+ int ovlap, fragsize, len;
+ ulong src, dst;
ushort id;
+ Block *bl, **l, *prev;
Fragment4 *f, *fnext;
- Ip4hdr *ih;
- ulong src, dst;
Ipfrag *fp, *fq;
- Block *bl, **l, *prev;
- int ovlap, len, fragsize, pktposn;
+ Ip4hdr *ih;
/*
- * block lists are too hard, pullupblock into a single block
+ * block lists are too hard, concatblock into a single block
*/
- if(bp->next != nil)
- bp = pullupblock(bp, blocklen(bp));
+ bp = concatblock(bp);
ih = (Ip4hdr*)bp->rp;
src = nhgetl(ih->src);
dst = nhgetl(ih->dst);
id = nhgets(ih->id);
- len = nhgets(ih->length);
- fragsize = len - ((ih->vihl&0xF)<<2);
+ fragsize = BLEN(bp) - ((ih->vihl&0xF)<<2);
qlock(&ip->fraglock4);
@@ -467,7 +464,6 @@
fp = (Ipfrag*)bp->base;
fp->foff = (offset & 0x1fff)<<3;
fp->flen = fragsize;
- fp->hlen = len - fragsize;
/* First fragment allocates a reassembly queue */
if(f == nil) {
@@ -517,19 +513,19 @@
/* Check to see if succeeding segments overlap */
if(bp->next != nil) {
l = &bp->next;
- fend = fp->foff + fp->flen;
+ offset = fp->foff + fp->flen;
/* Take completely covered segments out */
while((bl = *l) != nil) {
fq = (Ipfrag*)bl->base;
- ovlap = fend - fq->foff;
+ ovlap = offset - fq->foff;
if(ovlap <= 0)
break;
if(ovlap < fq->flen) {
- fq->flen -= ovlap;
- fq->foff += ovlap;
/* move up ip header */
- memmove(bl->rp + ovlap, bl->rp, fq->hlen);
+ memmove(bl->rp + ovlap, bl->rp, BLEN(bl) - fq->flen);
bl->rp += ovlap;
+ fq->flen -= ovlap;
+ fq->foff += ovlap;
break;
}
*l = bl->next;
@@ -542,10 +538,10 @@
* look for a complete packet. if we get to a fragment
* without IP_MF set, we're done.
*/
- pktposn = 0;
- for(bl = f->blist; bl != nil; bl = bl->next, pktposn += fp->flen) {
+ offset = 0;
+ for(bl = f->blist; bl != nil; bl = bl->next, offset += fp->flen) {
fp = (Ipfrag*)bl->base;
- if(fp->foff != pktposn)
+ if(fp->foff != offset)
break;
ih = (Ip4hdr*)bl->rp;
@@ -553,9 +549,7 @@
continue;
bl = f->blist;
- fq = (Ipfrag*)bl->base;
- len = fq->hlen + fq->flen;
- bl->wp = bl->rp + len;
+ len = BLEN(bl);
/*
* Pullup all the fragment headers and
@@ -564,9 +558,8 @@
for(bl = bl->next; bl != nil && len < IP_MAX; bl = bl->next) {
fq = (Ipfrag*)bl->base;
fragsize = fq->flen;
+ bl->rp = bl->wp - fragsize;
len += fragsize;
- bl->rp += fq->hlen;
- bl->wp = bl->rp + fragsize;
}
if(len >= IP_MAX){
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -123,7 +123,6 @@
struct Ipfrag
{
- ushort hlen;
ushort foff;
ushort flen;
uchar payload[];
--- a/sys/src/9/ip/ipv6.c
+++ b/sys/src/9/ip/ipv6.c
@@ -434,9 +434,9 @@
static Block*
ip6reassemble(IP* ip, int uflen, Block* bp)
{
- int fend, offset, ovlap, len, fragsize, pktposn;
- uint id;
+ int offset, ovlap, fragsize, len;
uchar src[IPaddrlen], dst[IPaddrlen];
+ uint id;
Block *bl, **l, *prev;
Fraghdr6 *fraghdr;
Fragment6 *f, *fnext;
@@ -444,17 +444,15 @@
Ip6hdr* ih;
/*
- * block lists are too hard, pullupblock into a single block
+ * block lists are too hard, concatblock into a single block
*/
- if(bp->next != nil)
- bp = pullupblock(bp, blocklen(bp));
+ bp = concatblock(bp);
ih = (Ip6hdr*)bp->rp;
fraghdr = (Fraghdr6*)(bp->rp + uflen);
id = nhgetl(fraghdr->id);
offset = nhgets(fraghdr->offsetRM);
- len = nhgets(ih->ploadlen);
- fragsize = (len + IP6HDR) - (uflen + IP6FHDR);
+ fragsize = BLEN(bp) - uflen - IP6FHDR;
memmove(src, ih->src, IPaddrlen);
memmove(dst, ih->dst, IPaddrlen);
@@ -489,7 +487,8 @@
/* get rid of frag header */
memmove(bp->rp + IP6FHDR, bp->rp, uflen);
bp->rp += IP6FHDR;
- hnputs(ih->ploadlen, len-IP6FHDR);
+ ih = (Ip6hdr*)bp->rp;
+ hnputs(ih->ploadlen, BLEN(bp)-IP6HDR);
return bp;
}
@@ -500,7 +499,6 @@
}
fp = (Ipfrag*)bp->base;
- fp->hlen = uflen;
fp->foff = offset & ~7;
fp->flen = fragsize;
@@ -552,20 +550,20 @@
/* Check to see if succeeding segments overlap */
if(bp->next != nil) {
l = &bp->next;
- fend = fp->foff + fp->flen;
+ offset = fp->foff + fp->flen;
/* Take completely covered segments out */
while((bl = *l) != nil) {
fq = (Ipfrag*)bl->base;
- ovlap = fend - fq->foff;
+ ovlap = offset - fq->foff;
if(ovlap <= 0)
break;
if(ovlap < fq->flen) {
- fq->flen -= ovlap;
- fq->foff += ovlap;
/* move up ip and frag header */
- memmove(bl->rp + ovlap, bl->rp, fq->hlen + IP6FHDR);
+ memmove(bl->rp + ovlap, bl->rp, BLEN(bl) - fq->flen);
bl->rp += ovlap;
+ fq->flen -= ovlap;
+ fq->foff += ovlap;
break;
}
*l = bl->next;
@@ -578,13 +576,13 @@
* look for a complete packet. if we get to a fragment
* with the trailing bit of fraghdr->offsetRM[1] set, we're done.
*/
- pktposn = 0;
- for(bl = f->blist; bl != nil; bl = bl->next, pktposn += fp->flen) {
+ offset = 0;
+ for(bl = f->blist; bl != nil; bl = bl->next, offset += fp->flen) {
fp = (Ipfrag*)bl->base;
- if(fp->foff != pktposn)
+ if(fp->foff != offset)
break;
- fraghdr = (Fraghdr6*)(bl->rp + fp->hlen);
+ fraghdr = (Fraghdr6*)(bl->wp - fp->flen - IP6FHDR);
if(fraghdr->offsetRM[1] & 1)
continue;
@@ -592,10 +590,9 @@
fq = (Ipfrag*)bl->base;
/* get rid of frag header in first fragment */
- memmove(bl->rp + IP6FHDR, bl->rp, fq->hlen);
+ memmove(bl->rp + IP6FHDR, bl->rp, BLEN(bl) - fq->flen - IP6FHDR);
bl->rp += IP6FHDR;
- len = fq->hlen + fq->flen;
- bl->wp = bl->rp + len;
+ len = BLEN(bl);
/*
* Pullup all the fragment headers and
@@ -604,9 +601,8 @@
for(bl = bl->next; bl != nil && len < IP_MAX; bl = bl->next) {
fq = (Ipfrag*)bl->base;
fragsize = fq->flen;
+ bl->rp = bl->wp - fragsize;
len += fragsize;
- bl->rp += fq->hlen + IP6FHDR;
- bl->wp = bl->rp + fragsize;
}
if(len >= IP_MAX){