diff --git a/nfq2/conntrack.c b/nfq2/conntrack.c index 1e5ac9b..96710c7 100644 --- a/nfq2/conntrack.c +++ b/nfq2/conntrack.c @@ -394,17 +394,25 @@ bool ReasmResize(t_reassemble *reasm, size_t new_size) if (reasm->size_present > new_size) reasm->size_present = new_size; return true; } +#define REASM_MAX_NEG 0x100000 bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len) { + uint32_t dseq = seq - reasm->seq; + if (dseq && (dseq < REASM_MAX_NEG)) + return false; // fail session if a gap about to appear uint32_t neg_overlap = reasm->seq - seq; - if ((seq > reasm->seq) || (neg_overlap > reasm->size_present)) - return false; // fail session if a gap about to appear or negative overlap is beyond start position + if (neg_overlap > REASM_MAX_NEG) + return false; // too big minus - size_t szcopy; + size_t szcopy, szignore; + szignore = (neg_overlap > reasm->size_present) ? neg_overlap - reasm->size_present : 0; szcopy = reasm->size - reasm->size_present; if (len < szcopy) szcopy = len; + if (szignore>=szcopy) return true; // everyting is before the starting pos + szcopy-=szignore; + neg_overlap-=szignore; // in case of seq overlap new data replaces old - unix behavior - memcpy(reasm->packet + reasm->size_present - neg_overlap, payload, szcopy); + memcpy(reasm->packet + reasm->size_present - neg_overlap, payload+szignore, szcopy); if (szcopy>neg_overlap) { reasm->size_present += szcopy - neg_overlap; diff --git a/nfq2/conntrack.h b/nfq2/conntrack.h index af993b4..f7d1657 100644 --- a/nfq2/conntrack.h +++ b/nfq2/conntrack.h @@ -43,7 +43,7 @@ typedef struct // this structure helps to reassemble continuous packets streams. it does not support out-of-orders typedef struct { uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size. - uint32_t seq; // current seq number. if a packet comes with an unexpected seq - it fails reassemble session. + uint32_t seq; // current seq number. if a packet comes with unsupported seq overlap - it fails reassemble session. size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet' size_t size_present; // how many bytes already stored in 'packet' } t_reassemble;