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().
front
cinap_lenrek 2019-03-03 18:56:18 +01:00
parent a859f05837
commit fa97c3dd10
3 changed files with 37 additions and 49 deletions

View File

@ -408,27 +408,24 @@ ipstats(Fs *f, char *buf, int len)
static Block*
ip4reassemble(IP *ip, int offset, Block *bp)
{
int fend;
ushort id;
Fragment4 *f, *fnext;
Ip4hdr *ih;
int ovlap, fragsize, len;
ulong src, dst;
Ipfrag *fp, *fq;
ushort id;
Block *bl, **l, *prev;
int ovlap, len, fragsize, pktposn;
Fragment4 *f, *fnext;
Ipfrag *fp, *fq;
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 @@ ip4reassemble(IP *ip, int offset, Block *bp)
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 @@ ip4reassemble(IP *ip, int offset, Block *bp)
/* 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) {
/* move up ip header */
memmove(bl->rp + ovlap, bl->rp, BLEN(bl) - fq->flen);
bl->rp += ovlap;
fq->flen -= ovlap;
fq->foff += ovlap;
/* move up ip header */
memmove(bl->rp + ovlap, bl->rp, fq->hlen);
bl->rp += ovlap;
break;
}
*l = bl->next;
@ -542,10 +538,10 @@ ip4reassemble(IP *ip, int offset, Block *bp)
* 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 @@ ip4reassemble(IP *ip, int offset, Block *bp)
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 @@ ip4reassemble(IP *ip, int offset, Block *bp)
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){

View File

@ -123,7 +123,6 @@ struct Fragment6
struct Ipfrag
{
ushort hlen;
ushort foff;
ushort flen;
uchar payload[];

View File

@ -434,9 +434,9 @@ procopts(Block *bp)
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 @@ ip6reassemble(IP* ip, int uflen, Block* bp)
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 @@ ip6reassemble(IP* ip, int uflen, Block* bp)
/* 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 @@ ip6reassemble(IP* ip, int uflen, Block* bp)
}
fp = (Ipfrag*)bp->base;
fp->hlen = uflen;
fp->foff = offset & ~7;
fp->flen = fragsize;
@ -552,20 +550,20 @@ ip6reassemble(IP* ip, int uflen, Block* bp)
/* 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) {
/* move up ip and frag header */
memmove(bl->rp + ovlap, bl->rp, BLEN(bl) - fq->flen);
bl->rp += ovlap;
fq->flen -= ovlap;
fq->foff += ovlap;
/* move up ip and frag header */
memmove(bl->rp + ovlap, bl->rp, fq->hlen + IP6FHDR);
bl->rp += ovlap;
break;
}
*l = bl->next;
@ -578,13 +576,13 @@ ip6reassemble(IP* ip, int uflen, Block* bp)
* 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 @@ ip6reassemble(IP* ip, int uflen, Block* bp)
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 @@ ip6reassemble(IP* ip, int uflen, Block* bp)
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){