fix ipv4 defrag + fix recursion level in defrag pseudo packet

remotes/origin/master-1.1.x
Anoop Saldanha 15 years ago committed by Victor Julien
parent 8654469133
commit 5c880b04c9

@ -32,6 +32,7 @@
#include "defrag.h" #include "defrag.h"
#include "util-unittest.h" #include "util-unittest.h"
#include "util-debug.h" #include "util-debug.h"
#include "pkt-var.h"
/* Generic validation /* Generic validation
* *
@ -519,6 +520,17 @@ void DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
return; return;
} }
/* If a fragment, pass off for re-assembly. */
if (IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1) {
Packet *rp = Defrag(tv, dtv, NULL, p);
if (rp != NULL) {
/* Got re-assembled packet, re-run through decoder. */
DecodeIPV4(tv, dtv, rp, (void *)rp->ip4h, IPV4_GET_IPLEN(rp), pq);
PacketEnqueue(pq, rp);
}
return;
}
/* do hdr test, process hdr rules */ /* do hdr test, process hdr rules */
#ifdef DEBUG #ifdef DEBUG
@ -583,16 +595,6 @@ void DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
break; break;
} }
/* If a fragment, pass off for re-assembly. */
if (IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1) {
Packet *rp = Defrag(tv, dtv, NULL, p);
if (rp != NULL) {
/* Got re-assembled packet, re-run through decoder. */
DecodeIPV4(tv, dtv, rp, GET_PKT_DATA(rp), GET_PKT_LEN(rp), pq);
PacketEnqueue(pq, rp);
}
}
return; return;
} }
@ -1552,6 +1554,436 @@ static int IPV4CalculateInvalidChecksumtest02(void)
return (csum == IPV4CalculateChecksum((uint16_t *)raw_ipv4, sizeof(raw_ipv4))); return (csum == IPV4CalculateChecksum((uint16_t *)raw_ipv4, sizeof(raw_ipv4)));
} }
/**
* \test IPV4 defrag and packet recursion level test
*/
int DecodeIPV4DefragTest01(void)
{
uint8_t pkt1[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x1c, 0xe9, 0xef, 0x20, 0x00, 0x40, 0x06,
0x9a, 0xc8, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3,
0x81, 0x5e
};
uint8_t pkt2[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x1c, 0xe9, 0xef, 0x20, 0x01, 0x40, 0x06,
0x9a, 0xc7, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10,
0x80, 0x00
};
uint8_t pkt3[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x18, 0xe9, 0xef, 0x00, 0x02, 0x40, 0x06,
0xba, 0xca, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0xb1, 0xa3, 0x00, 0x00
};
uint8_t tunnel_pkt[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x28, 0xe9, 0xef, 0x00, 0x00, 0x40, 0x06,
0xba, 0xbc, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3,
0x81, 0x5e, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10,
0x80, 0x00, 0xb1, 0xa3, 0x00, 0x00
};
Packet *p = SCMalloc(SIZE_OF_PACKET);
if (p == NULL)
return 0;
ThreadVars tv;
DecodeThreadVars dtv;
PacketQueue pq;
int result = 1;
memset(&tv, 0, sizeof(ThreadVars));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&pq, 0, sizeof(PacketQueue));
memset(p, 0, sizeof(Packet));
FlowInitConfig(FLOW_QUIET);
p->pkt = pkt1;
p->pktlen = sizeof(pkt1);
DecodeIPV4(&tv, &dtv, p, pkt1 + ETHERNET_HEADER_LEN,
sizeof(pkt1) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
PACKET_DO_RECYCLE(p);
p->pkt = pkt2;
p->pktlen = sizeof(pkt2);
DecodeIPV4(&tv, &dtv, p, pkt2 + ETHERNET_HEADER_LEN,
sizeof(pkt2) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
PACKET_DO_RECYCLE(p);
p->pkt = pkt3;
p->pktlen = sizeof(pkt3);
DecodeIPV4(&tv, &dtv, p, pkt3 + ETHERNET_HEADER_LEN,
sizeof(pkt3) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
Packet *tp = PacketDequeue(&pq);
if (tp == NULL) {
printf("Failed to get defragged pseudo packet\n");
result = 0;
goto end;
}
if (tp->recursion_level != p->recursion_level) {
printf("defragged pseudo packet's and parent packet's recursion "
"level don't match\n %d != %d",
tp->recursion_level, p->recursion_level);
result = 0;
goto end;
}
if (tp->ip4h == NULL || tp->tcph == NULL) {
printf("pseudo packet's ip header and tcp header shouldn't be NULL, "
"but it is\n");
result = 0;
goto end;
}
if (GET_PKT_LEN(tp) != sizeof(tunnel_pkt)) {
printf("defragged pseudo packet's and parent packet's pkt lens "
"don't match\n %u != %lu",
GET_PKT_LEN(tp), sizeof(tunnel_pkt));
result = 0;
goto end;
}
size_t i;
for (i = 0; i < sizeof(tunnel_pkt); i++) {
if (tunnel_pkt[i] != tp->pkt[i]) {
result = 0;
goto end;
}
}
SCFree(tp);
end:
FlowShutdown();
SCFree(p);
return result;
}
/**
* \test Don't send IPv4 fragments to the upper layer decoder and
* and packet recursion level test.
*/
int DecodeIPV4DefragTest02(void)
{
uint8_t pkt1[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x24, 0xe9, 0xef, 0x20, 0x00, 0x40, 0x06,
0x9a, 0xc8, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c,
/* first frag */
0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3,
0x81, 0x5e, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10,
0x80, 0x00,
};
uint8_t pkt2[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x2c, 0xe9, 0xef, 0x20, 0x02, 0x40, 0x06,
0xba, 0xca, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c,
/* second frag */
0xb1, 0xa3, 0x00, 0x10, 0x5b, 0xa3, 0x81, 0x5e,
0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, 0x80, 0x00,
0xb1, 0xa3, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04
};
uint8_t pkt3[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x16, 0xe9, 0xef, 0x00, 0x05, 0x40, 0x06,
0xba, 0xca, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c,
/* final frag */
0xb1, 0xa3,
};
uint8_t tunnel_pkt[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x3e, 0xe9, 0xef, 0x00, 0x00, 0x40, 0x06,
0xba, 0xae, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c,
0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3, 0x81, 0x5e,
0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, 0x80, 0x00,
0xb1, 0xa3, 0x00, 0x10, 0x5b, 0xa3, 0x81, 0x5e,
0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, 0x80, 0x00,
0xb1, 0xa3, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04,
0xb1, 0xa3,
};
Packet *p = SCMalloc(SIZE_OF_PACKET);
if (p == NULL)
return 0;
ThreadVars tv;
DecodeThreadVars dtv;
PacketQueue pq;
int result = 1;
memset(&tv, 0, sizeof(ThreadVars));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&pq, 0, sizeof(PacketQueue));
memset(p, 0, sizeof(Packet));
FlowInitConfig(FLOW_QUIET);
p->pkt = pkt1;
p->pktlen = sizeof(pkt1);
DecodeIPV4(&tv, &dtv, p, pkt1 + ETHERNET_HEADER_LEN,
sizeof(pkt1) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
PACKET_DO_RECYCLE(p);
p->pkt = pkt2;
p->pktlen = sizeof(pkt2);
DecodeIPV4(&tv, &dtv, p, pkt2 + ETHERNET_HEADER_LEN,
sizeof(pkt2) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
PACKET_DO_RECYCLE(p);
p->recursion_level = 3;
p->pkt = pkt3;
p->pktlen = sizeof(pkt3);
DecodeIPV4(&tv, &dtv, p, pkt3 + ETHERNET_HEADER_LEN,
sizeof(pkt3) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
Packet *tp = PacketDequeue(&pq);
if (tp == NULL) {
printf("Failed to get defragged pseudo packet\n");
result = 0;
goto end;
}
if (tp->recursion_level != p->recursion_level) {
printf("defragged pseudo packet's and parent packet's recursion "
"level don't match\n %d != %d",
tp->recursion_level, p->recursion_level);
result = 0;
goto end;
}
if (tp->ip4h == NULL || tp->tcph == NULL) {
printf("pseudo packet's ip header and tcp header shouldn't be NULL, "
"but it is\n");
result = 0;
goto end;
}
if (GET_PKT_LEN(tp) != sizeof(tunnel_pkt)) {
printf("defragged pseudo packet's and parent packet's pkt lens "
"don't match\n %u != %lu",
GET_PKT_LEN(tp), sizeof(tunnel_pkt));
result = 0;
goto end;
}
size_t i;
for (i = 0; i < sizeof(tunnel_pkt); i++) {
if (tunnel_pkt[i] != tp->pkt[i]) {
result = 0;
goto end;
}
}
SCFree(tp);
end:
FlowShutdown();
SCFree(p);
return result;
}
/**
* \test IPV4 defrag and flow retrieval test.
*/
int DecodeIPV4DefragTest03(void)
{
uint8_t pkt[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x28, 0xe9, 0xee, 0x00, 0x00, 0x40, 0x06,
0xba, 0xbd, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3,
0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
0x80, 0x00, 0x0c, 0xee, 0x00, 0x00
};
uint8_t pkt1[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x1c, 0xe9, 0xef, 0x20, 0x00, 0x40, 0x06,
0x9a, 0xc8, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3,
0x81, 0x5e
};
uint8_t pkt2[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x1c, 0xe9, 0xef, 0x20, 0x01, 0x40, 0x06,
0x9a, 0xc7, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10,
0x80, 0x00
};
uint8_t pkt3[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x18, 0xe9, 0xef, 0x00, 0x02, 0x40, 0x06,
0xba, 0xca, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0xb1, 0xa3, 0x00, 0x00
};
uint8_t tunnel_pkt[] = {
0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad,
0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x28, 0xe9, 0xef, 0x00, 0x00, 0x40, 0x06,
0xba, 0xbc, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00,
0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3,
0x81, 0x5e, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10,
0x80, 0x00, 0xb1, 0xa3, 0x00, 0x00
};
Flow *f = NULL;
Packet *p = SCMalloc(SIZE_OF_PACKET);
if (p == NULL)
return 0;
ThreadVars tv;
DecodeThreadVars dtv;
PacketQueue pq;
int result = 1;
memset(&tv, 0, sizeof(ThreadVars));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&pq, 0, sizeof(PacketQueue));
memset(p, 0, sizeof(Packet));
FlowInitConfig(FLOW_QUIET);
p->pkt = pkt;
p->pktlen = sizeof(pkt);
DecodeIPV4(&tv, &dtv, p, pkt + ETHERNET_HEADER_LEN,
sizeof(pkt) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph == NULL) {
printf("tcp header shouldn't be NULL, but it is\n");
result = 0;
goto end;
}
if (p->flow == NULL) {
printf("packet flow shouldn't be NULL\n");
result = 0;
goto end;
}
f = p->flow;
PACKET_DO_RECYCLE(p);
p->pkt = pkt1;
p->pktlen = sizeof(pkt1);
DecodeIPV4(&tv, &dtv, p, pkt1 + ETHERNET_HEADER_LEN,
sizeof(pkt1) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
PACKET_DO_RECYCLE(p);
p->pkt = pkt2;
p->pktlen = sizeof(pkt2);
DecodeIPV4(&tv, &dtv, p, pkt2 + ETHERNET_HEADER_LEN,
sizeof(pkt2) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
PACKET_DO_RECYCLE(p);
p->pkt = pkt3;
p->pktlen = sizeof(pkt3);
DecodeIPV4(&tv, &dtv, p, pkt3 + ETHERNET_HEADER_LEN,
sizeof(pkt3) - ETHERNET_HEADER_LEN, &pq);
if (p->tcph != NULL) {
printf("tcp header should be NULL for ip fragment, but it isn't\n");
result = 0;
goto end;
}
Packet *tp = PacketDequeue(&pq);
if (tp == NULL) {
printf("Failed to get defragged pseudo packet\n");
result = 0;
goto end;
}
if (tp->flow == NULL) {
result = 0;
goto end;
}
if (tp->flow != f) {
result = 0;
goto end;
}
if (tp->recursion_level != p->recursion_level) {
printf("defragged pseudo packet's and parent packet's recursion "
"level don't match\n %d != %d",
tp->recursion_level, p->recursion_level);
result = 0;
goto end;
}
if (tp->ip4h == NULL || tp->tcph == NULL) {
printf("pseudo packet's ip header and tcp header shouldn't be NULL, "
"but it is\n");
result = 0;
goto end;
}
if (GET_PKT_LEN(tp) != sizeof(tunnel_pkt)) {
printf("defragged pseudo packet's and parent packet's pkt lens "
"don't match\n %u != %lu",
GET_PKT_LEN(tp), sizeof(tunnel_pkt));
result = 0;
goto end;
}
size_t i;
for (i = 0; i < sizeof(tunnel_pkt); i++) {
if (tunnel_pkt[i] != tp->pkt[i]) {
result = 0;
goto end;
}
}
SCFree(tp);
end:
FlowShutdown();
SCFree(p);
return result;
}
#endif /* UNITTESTS */ #endif /* UNITTESTS */
void DecodeIPV4RegisterTests(void) { void DecodeIPV4RegisterTests(void) {
@ -1588,5 +2020,8 @@ void DecodeIPV4RegisterTests(void) {
IPV4CalculateValidChecksumtest01, 1); IPV4CalculateValidChecksumtest01, 1);
UtRegisterTest("IPV4CalculateInvalidChecksumtest02", UtRegisterTest("IPV4CalculateInvalidChecksumtest02",
IPV4CalculateInvalidChecksumtest02, 0); IPV4CalculateInvalidChecksumtest02, 0);
UtRegisterTest("DecodeIPV4DefragTest01", DecodeIPV4DefragTest01, 1);
UtRegisterTest("DecodeIPV4DefragTest02", DecodeIPV4DefragTest02, 1);
UtRegisterTest("DecodeIPV4DefragTest03", DecodeIPV4DefragTest03, 1);
#endif /* UNITTESTS */ #endif /* UNITTESTS */
} }

@ -534,17 +534,6 @@ Defrag4Reassemble(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker,
} }
} }
/* Allocate a Packet for the reassembled packet. On failure we
* SCFree all the resources held by this tracker. */
rp = PacketPseudoPktSetup(p, (uint8_t *)p->ip4h, IPV4_GET_IPLEN(p),
IPV4_GET_IPPROTO(p));
if (rp == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate packet for "
"fragmentation re-assembly, dumping fragments.");
goto remove_tracker;
}
SCLogDebug("Packet rp %p, p %p, rp->root %p", rp, p, rp->root);
int fragmentable_offset = 0; int fragmentable_offset = 0;
int fragmentable_len = 0; int fragmentable_len = 0;
int hlen = 0; int hlen = 0;
@ -555,10 +544,18 @@ Defrag4Reassemble(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker,
if (frag->data_len - frag->ltrim <= 0) if (frag->data_len - frag->ltrim <= 0)
continue; continue;
if (frag->offset == 0) { if (frag->offset == 0) {
/* This is the first packet, we use this packets link and /* Allocate a Packet for the reassembled packet. On failure we
* IPv4 header. We also copy in its data. */ * SCFree all the resources held by this tracker. */
if (PacketCopyData(rp, frag->pkt, frag->len) == -1) rp = PacketPseudoPktSetup(p, frag->pkt, frag->len,
IPV4_GET_IPPROTO(p));
if (rp == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate packet for "
"fragmentation re-assembly, dumping fragments.");
goto remove_tracker; goto remove_tracker;
}
SCLogDebug("Packet rp %p, p %p, rp->root %p", rp, p, rp->root);
rp->recursion_level = p->recursion_level;
rp->ip4h = (IPV4Hdr *)(GET_PKT_DATA(rp) + frag->ip_hdr_offset); rp->ip4h = (IPV4Hdr *)(GET_PKT_DATA(rp) + frag->ip_hdr_offset);
hlen = frag->hlen; hlen = frag->hlen;
ip_hdr_offset = frag->ip_hdr_offset; ip_hdr_offset = frag->ip_hdr_offset;

@ -965,6 +965,7 @@ int main(int argc, char **argv)
/* Load the Host-OS lookup. */ /* Load the Host-OS lookup. */
SCHInfoLoadFromConfig(); SCHInfoLoadFromConfig();
DefragInit();
if (run_mode == MODE_UNKNOWN) { if (run_mode == MODE_UNKNOWN) {
if (!engine_analysis) { if (!engine_analysis) {
@ -1342,7 +1343,6 @@ int main(int argc, char **argv)
FlowManagerThreadSpawn(); FlowManagerThreadSpawn();
StreamTcpInitConfig(STREAM_VERBOSE); StreamTcpInitConfig(STREAM_VERBOSE);
DefragInit();
/* Spawn the L7 App Detect thread */ /* Spawn the L7 App Detect thread */
//AppLayerDetectProtoThreadSpawn(); //AppLayerDetectProtoThreadSpawn();

Loading…
Cancel
Save