Potential fix for issue 60.

- Increase the packet buffer so it can hold the link header when we
  have maximum size IP datagrams.
- Fix ip header length and pkt length calculation for re-assembled
  packets.
remotes/origin/master-1.0.x
Jason Ish 16 years ago committed by Victor Julien
parent 9d3a9273dd
commit 5076452707

@ -241,9 +241,9 @@ typedef struct Packet_
/** data linktype in host order */ /** data linktype in host order */
int datalink; int datalink;
/* storage */ /* storage: maximum ip packet size + link header */
uint8_t pkt[65536]; uint8_t pkt[65536 + 28];
uint16_t pktlen; uint32_t pktlen;
/* flow */ /* flow */
struct Flow_ *flow; struct Flow_ *flow;

@ -738,10 +738,10 @@ Defrag4Reassemble(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker,
goto remove_tracker; goto remove_tracker;
} }
int payload_len = 0;
int fragmentable_offset = 0; int fragmentable_offset = 0;
int pktlen = 0; int fragmentable_len = 0;
int hlen = 0; int hlen = 0;
int ip_hdr_offset = 0;
TAILQ_FOREACH(frag, &tracker->frags, next) { TAILQ_FOREACH(frag, &tracker->frags, next) {
if (frag->skip) if (frag->skip)
continue; continue;
@ -753,30 +753,33 @@ Defrag4Reassemble(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker,
memcpy(rp->pkt, frag->pkt, frag->len); memcpy(rp->pkt, frag->pkt, frag->len);
rp->ip4h = (IPV4Hdr *)(rp->pkt + frag->ip_hdr_offset); rp->ip4h = (IPV4Hdr *)(rp->pkt + frag->ip_hdr_offset);
hlen = frag->hlen; hlen = frag->hlen;
ip_hdr_offset = frag->ip_hdr_offset;
/* This is the start of the fragmentable portion of the /* This is the start of the fragmentable portion of the
* first packet. All fragment offsets are relative to * first packet. All fragment offsets are relative to
* this. */ * this. */
fragmentable_offset = frag->ip_hdr_offset + frag->hlen; fragmentable_offset = frag->ip_hdr_offset + frag->hlen;
fragmentable_len = frag->data_len;
pktlen = frag->ip_hdr_offset + sizeof(IPV4Hdr);
} }
else { else {
BUG_ON(fragmentable_offset + frag->offset + frag->data_len >
(int)sizeof(rp->pkt));
memcpy(rp->pkt + fragmentable_offset + frag->offset + frag->ltrim, memcpy(rp->pkt + fragmentable_offset + frag->offset + frag->ltrim,
frag->pkt + frag->data_offset + frag->ltrim, frag->pkt + frag->data_offset + frag->ltrim,
frag->data_len - frag->ltrim); frag->data_len - frag->ltrim);
payload_len += frag->data_len - frag->ltrim; if (frag->offset + frag->data_len > fragmentable_len)
fragmentable_len = frag->offset + frag->data_len;
} }
} }
BUG_ON(rp->ip4h == NULL); BUG_ON(rp->ip4h == NULL);
int old = rp->ip4h->ip_len + rp->ip4h->ip_off; int old = rp->ip4h->ip_len + rp->ip4h->ip_off;
rp->ip4h->ip_len = htons(payload_len + hlen); rp->ip4h->ip_len = htons(fragmentable_len + hlen);
rp->ip4h->ip_off = 0; rp->ip4h->ip_off = 0;
rp->ip4h->ip_csum = FixChecksum(rp->ip4h->ip_csum, rp->ip4h->ip_csum = FixChecksum(rp->ip4h->ip_csum,
old, rp->ip4h->ip_len + rp->ip4h->ip_off); old, rp->ip4h->ip_len + rp->ip4h->ip_off);
rp->pktlen = ip_hdr_offset + hlen + fragmentable_len;
rp->pktlen = pktlen + payload_len; IPV4_CACHE_INIT(rp);
remove_tracker: remove_tracker:
/* Remove the frag tracker. */ /* Remove the frag tracker. */
@ -854,9 +857,9 @@ Defrag6Reassemble(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker,
goto remove_tracker; goto remove_tracker;
} }
int payload_len = 0;
int fragmentable_offset = 0; int fragmentable_offset = 0;
int pktlen = 0; int fragmentable_len = 0;
int ip_hdr_offset = 0;
TAILQ_FOREACH(frag, &tracker->frags, next) { TAILQ_FOREACH(frag, &tracker->frags, next) {
if (frag->skip) if (frag->skip)
continue; continue;
@ -871,25 +874,25 @@ Defrag6Reassemble(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker,
frag->pkt + frag->frag_hdr_offset + sizeof(IPV6FragHdr), frag->pkt + frag->frag_hdr_offset + sizeof(IPV6FragHdr),
frag->data_len); frag->data_len);
rp->ip6h = (IPV6Hdr *)(rp->pkt + frag->ip_hdr_offset); rp->ip6h = (IPV6Hdr *)(rp->pkt + frag->ip_hdr_offset);
payload_len = ntohs(rp->ip6h->s_ip6_plen) - sizeof(IPV6FragHdr); ip_hdr_offset = frag->ip_hdr_offset;
/* This is the start of the fragmentable portion of the /* This is the start of the fragmentable portion of the
* first packet. All fragment offsets are relative to * first packet. All fragment offsets are relative to
* this. */ * this. */
fragmentable_offset = frag->frag_hdr_offset; fragmentable_offset = frag->frag_hdr_offset;
fragmentable_len = frag->data_len;
pktlen = frag->ip_hdr_offset + sizeof(IPV6Hdr);
} }
else { else {
memcpy(rp->pkt + fragmentable_offset + frag->offset + frag->ltrim, memcpy(rp->pkt + fragmentable_offset + frag->offset + frag->ltrim,
frag->pkt + frag->data_offset + frag->ltrim, frag->pkt + frag->data_offset + frag->ltrim,
frag->data_len - frag->ltrim); frag->data_len - frag->ltrim);
payload_len += frag->data_len - frag->ltrim; if (frag->offset + frag->data_len > fragmentable_len)
fragmentable_len = frag->offset + frag->data_len;
} }
} }
BUG_ON(rp->ip6h == NULL); BUG_ON(rp->ip6h == NULL);
rp->ip6h->s_ip6_plen = htons(payload_len); rp->ip6h->s_ip6_plen = htons(fragmentable_len);
rp->pktlen = pktlen + payload_len; rp->pktlen = ip_hdr_offset + sizeof(IPV6Hdr) + fragmentable_len;
remove_tracker: remove_tracker:
/* Remove the frag tracker. */ /* Remove the frag tracker. */
@ -1242,6 +1245,11 @@ DefragInOrderSimpleTest(void)
if (reassembled == NULL) if (reassembled == NULL)
goto end; goto end;
if (IPV4_GET_HLEN(reassembled) != 20)
goto end;
if (IPV4_GET_IPLEN(reassembled) != 39)
goto end;
/* 20 bytes in we should find 8 bytes of A. */ /* 20 bytes in we should find 8 bytes of A. */
for (i = 20; i < 20 + 8; i++) { for (i = 20; i < 20 + 8; i++) {
if (reassembled->pkt[i] != 'A') if (reassembled->pkt[i] != 'A')
@ -1316,6 +1324,11 @@ DefragReverseSimpleTest(void)
if (reassembled == NULL) if (reassembled == NULL)
goto end; goto end;
if (IPV4_GET_HLEN(reassembled) != 20)
goto end;
if (IPV4_GET_IPLEN(reassembled) != 39)
goto end;
/* 20 bytes in we should find 8 bytes of A. */ /* 20 bytes in we should find 8 bytes of A. */
for (i = 20; i < 20 + 8; i++) { for (i = 20; i < 20 + 8; i++) {
if (reassembled->pkt[i] != 'A') if (reassembled->pkt[i] != 'A')
@ -1390,6 +1403,9 @@ IPV6DefragInOrderSimpleTest(void)
if (reassembled == NULL) if (reassembled == NULL)
goto end; goto end;
if (IPV6_GET_PLEN(reassembled) != 19)
goto end;
/* 40 bytes in we should find 8 bytes of A. */ /* 40 bytes in we should find 8 bytes of A. */
for (i = 40; i < 40 + 8; i++) { for (i = 40; i < 40 + 8; i++) {
if (reassembled->pkt[i] != 'A') if (reassembled->pkt[i] != 'A')
@ -1588,6 +1604,12 @@ DefragDoSturgesNovakTest(int policy, u_char *expected, size_t expected_len)
Packet *reassembled = Defrag(NULL, dc, packets[16]); Packet *reassembled = Defrag(NULL, dc, packets[16]);
if (reassembled == NULL) if (reassembled == NULL)
goto end; goto end;
if (IPV4_GET_HLEN(reassembled) != 20)
goto end;
if (IPV4_GET_IPLEN(reassembled) != 20 + 192)
goto end;
if (memcmp(reassembled->pkt + 20, expected, expected_len) != 0) if (memcmp(reassembled->pkt + 20, expected, expected_len) != 0)
goto end; goto end;
free(reassembled); free(reassembled);
@ -1781,6 +1803,10 @@ IPV6DefragDoSturgesNovakTest(int policy, u_char *expected, size_t expected_len)
goto end; goto end;
if (memcmp(reassembled->pkt + 40, expected, expected_len) != 0) if (memcmp(reassembled->pkt + 40, expected, expected_len) != 0)
goto end; goto end;
if (IPV6_GET_PLEN(reassembled) != 192)
goto end;
free(reassembled); free(reassembled);
/* Make sure the tracker was released back to the pool. */ /* Make sure the tracker was released back to the pool. */

Loading…
Cancel
Save