65#define DEFAULT_DEFRAG_HASH_SIZE 0xffff
66#define DEFAULT_DEFRAG_POOL_SIZE 0xffff
72#define TIMEOUT_DEFAULT 60
77#define TIMEOUT_MAX (60 * 60 * 24)
109DefragFragReset(
Frag *frag)
111 if (frag->
pkt != NULL)
113 memset(frag, 0,
sizeof(*frag));
120DefragFragInit(
void *data,
void *initdata)
124 memset(frag, 0,
sizeof(*frag));
141 DefragFragReset(frag);
155DefragContextNew(
void)
164 intmax_t tracker_pool_size;
165 if (!
SCConfGetInt(
"defrag.trackers", &tracker_pool_size) || tracker_pool_size == 0) {
170 intmax_t frag_pool_size;
171 if (!
SCConfGetInt(
"defrag.max-frags", &frag_pool_size) || frag_pool_size == 0 ||
172 frag_pool_size > UINT32_MAX) {
175 uint32_t frag_pool_prealloc = (uint32_t)frag_pool_size / 2;
177 DefragFragInit, dc, NULL, NULL);
179 FatalError(
"Defrag: Failed to initialize fragment pool.");
182 FatalError(
"Defrag: Failed to initialize frag pool mutex.");
191 FatalError(
"defrag: Timeout less than minimum allowed value.");
194 FatalError(
"defrag: Timeout greater than maximum allowed value.");
196 dc->
timeout = (uint32_t)timeout;
201 SCLogDebug(
"\tMaximum defrag trackers: %"PRIuMAX, tracker_pool_size);
202 SCLogDebug(
"\tPreallocated defrag trackers: %"PRIuMAX, tracker_pool_size);
203 SCLogDebug(
"\tMaximum fragments: %"PRIuMAX, (uintmax_t)frag_pool_size);
204 SCLogDebug(
"\tPreallocated fragments: %"PRIuMAX, (uintmax_t)frag_pool_prealloc);
238 }
else if (first->
offset != 0) {
243 goto error_remove_tracker;
262 const IPV4Hdr *oip4h = PacketGetIPv4(p);
268 goto error_remove_tracker;
274 int fragmentable_offset = 0;
275 uint16_t fragmentable_len = 0;
277 int ip_hdr_offset = 0;
280 uint16_t prev_offset = 0;
284 SCLogDebug(
"frag %p, data_len %u, offset %u, pcap_cnt %"PRIu64,
289 if (!more_frags && frag->
offset > prev_offset) {
300 goto error_remove_tracker;
312 int pkt_end = fragmentable_offset + frag->
offset + frag->
data_len;
315 "fragmented packet, exceeds size of packet buffer.");
316 goto error_remove_tracker;
322 goto error_remove_tracker;
326 "fragmentable_len exceeds UINT16_MAX");
327 goto error_remove_tracker;
342 prev_offset = frag->
offset;
345 SCLogDebug(
"ip_hdr_offset %u, hlen %" PRIu16
", fragmentable_len %" PRIu16, ip_hdr_offset, hlen,
351 ip4h->
ip_len = htons(fragmentable_len + hlen);
354 SET_PKT_LEN(rp, ip_hdr_offset + hlen + fragmentable_len);
387 }
else if (first->
offset != 0) {
392 goto error_remove_tracker;
422 const IPV6Hdr *oip6h = PacketGetIPv6(p);
429 goto error_remove_tracker;
435 uint16_t unfragmentable_len = 0;
436 int fragmentable_offset = 0;
437 uint16_t fragmentable_len = 0;
438 int ip_hdr_offset = 0;
439 uint8_t next_hdr = 0;
442 uint16_t prev_offset = 0;
446 if (!more_frags && frag->
offset > prev_offset) {
454 IPV6FragHdr *frag_hdr = (IPV6FragHdr *)(frag->
pkt +
456 next_hdr = frag_hdr->ip6fh_nxt;
462 goto error_remove_tracker;
466 goto error_remove_tracker;
480 unfragmentable_len = (uint16_t)(fragmentable_offset - ip_hdr_offset -
IPV6_HEADER_LEN);
481 if (unfragmentable_len >= fragmentable_offset)
482 goto error_remove_tracker;
488 goto error_remove_tracker;
502 prev_offset = frag->
offset;
507 ip6h->s_ip6_plen = htons(fragmentable_len + unfragmentable_len);
512 if (unfragmentable_len == 0)
513 ip6h->s_ip6_nxt = next_hdr;
515 unfragmentable_len + fragmentable_len);
556 uint16_t frag_offset;
563 uint16_t data_offset;
573 uint16_t ip_hdr_offset;
576 uint16_t frag_hdr_offset = 0;
579 int af = tracker->
af;
583 uint32_t ip6_nh_set_offset = 0;
584 uint8_t ip6_nh_set_value = 0;
590 if (tracker->
af == AF_INET) {
591 const IPV4Hdr *ip4h = PacketGetIPv4(p);
595 data_offset = (uint16_t)((uint8_t *)ip4h + hlen -
GET_PKT_DATA(p));
597 frag_end = frag_offset + data_len;
598 ip_hdr_offset = (uint16_t)((uint8_t *)ip4h -
GET_PKT_DATA(p));
607 else if (tracker->
af == AF_INET6) {
608 const IPV6Hdr *ip6h = PacketGetIPv6(p);
613 frag_end = frag_offset + data_len;
614 ip_hdr_offset = (uint16_t)((uint8_t *)ip6h -
GET_PKT_DATA(p));
617 SCLogDebug(
"mf %s frag_offset %u data_offset %u, data_len %u, "
618 "frag_end %u, ip_hdr_offset %u, frag_hdr_offset %u",
619 more_frags ?
"true" :
"false", frag_offset, data_offset,
620 data_len, frag_end, ip_hdr_offset, frag_hdr_offset);
624 SCLogDebug(
"we have exthdrs before fraghdr %u bytes",
633 SCLogDebug(
"offset %d, value %u", ip6_nh_set_offset, ip6_nh_set_value);
652 bool overlap =
false;
657 .
offset = frag_offset - 1,
662 next = IP_FRAGMENTS_RB_NEXT(prev);
664 prev = IP_FRAGMENTS_RB_PREV(
next);
667 next = IP_FRAGMENTS_RB_NEXT(prev);
670 while (prev != NULL) {
678 switch (tracker->
policy) {
681 if (prev->
offset <= frag_offset) {
687 if (prev_end > frag_end) {
692 ltrim = prev_end - frag_offset;
694 if ((
next != NULL) && (frag_end >
next->offset)) {
695 next->ltrim = frag_end -
next->offset;
710 uint16_t prev_ltrim = frag_end - prev->
offset;
711 if (prev_ltrim > prev->
ltrim) {
712 prev->
ltrim = prev_ltrim;
716 if ((
next != NULL) && (frag_end >
next->offset)) {
717 next->ltrim = frag_end -
next->offset;
731 if (prev->
offset + prev->
ltrim < frag_offset + ltrim &&
744 if (frag_offset + ltrim < prev->
offset + prev->
ltrim &&
755 if (frag_offset + ltrim <= prev->
offset + prev->
ltrim &&
764 if (frag_offset + ltrim >= prev->
offset + ltrim &&
771 if (frag_offset + ltrim < prev->
offset + ltrim &&
784 if (frag_offset + ltrim > prev->
offset + prev->
ltrim &&
793 if (frag_offset + ltrim == prev->
offset + ltrim &&
801 if (frag_offset >= prev->
offset) {
804 if ((frag_offset < prev->
offset) &&
812 if ((frag_offset >= prev->
offset) &&
816 if (frag_offset < prev->
offset) {
825 if (frag_offset <= prev->
offset) {
826 if (frag_end > prev->
offset) {
849 DefragFragReset(prev);
858 if (ltrim >= data_len) {
874 if (
tv != NULL &&
dtv != NULL) {
877 goto error_remove_tracker;
880 if (new->pkt == NULL) {
889 goto error_remove_tracker;
896 if (ip6_nh_set_offset > 0 && frag_offset == 0 && ltrim == 0) {
897 if (new->len > ip6_nh_set_offset) {
898 SCLogDebug(
"updating frag to have 'correct' nh value: %u -> %u",
899 new->pkt[ip6_nh_set_offset], ip6_nh_set_value);
900 new->pkt[ip6_nh_set_offset] = ip6_nh_set_value;
905 new->offset = frag_offset + ltrim;
906 new->data_offset = data_offset;
907 new->data_len = data_len - ltrim;
908 new->frag_hdr_offset = frag_hdr_offset;
909 new->more_frags = more_frags;
911 new->pcap_cnt = pcap_cnt;
913 if (new->offset == 0) {
925 if (tracker->
af == AF_INET) {
926 r = Defrag4Reassemble(
tv, tracker, p);
927 if (r != NULL &&
tv != NULL &&
dtv != NULL) {
941 else if (tracker->
af == AF_INET6) {
942 r = Defrag6Reassemble(
tv, tracker, p);
943 if (r != NULL &&
tv != NULL &&
dtv != NULL) {
989 if (PacketIsIPv4(p)) {
991 }
else if (PacketIsIPv6(p)) {
996 return default_policy;
1039 return default_policy;
1065 uint16_t frag_offset;
1070 if (PacketIsIPv4(p)) {
1071 const IPV4Hdr *ip4h = PacketGetIPv4(p);
1075 }
else if (PacketIsIPv6(p)) {
1083 if (frag_offset == 0 && more_frags == 0) {
1087 if (
af == AF_INET) {
1089 }
else if (
af == AF_INET6) {
1094 tracker = DefragGetTracker(
tv,
dtv, p);
1095 if (tracker == NULL) {
1096 if (
tv != NULL &&
dtv != NULL) {
1102 Packet *rp = DefragInsertFrag(
tv,
dtv, tracker, p);
1111 intmax_t tracker_pool_size;
1112 if (!
SCConfGetInt(
"defrag.trackers", &tracker_pool_size)) {
1120 defrag_context = DefragContextNew();
1121 if (defrag_context == NULL) {
1122 FatalError(
"Failed to allocate memory for the Defrag module.");
1132 DefragContextDestroy(defrag_context);
1133 defrag_context = NULL;
1150static Packet *BuildIpv4TestPacket(
1151 uint8_t
proto, uint16_t
id, uint16_t off,
int mf,
const char content,
int content_len)
1165 struct timeval tval;
1166 gettimeofday(&tval, NULL);
1171 ip4h.
ip_len = htons(hlen + content_len);
1172 ip4h.
ip_id = htons(
id);
1176 ip4h.
ip_off = htons(off);
1180 ip4h.s_ip_src.s_addr = 0x01010101;
1181 ip4h.s_ip_dst.s_addr = 0x02020202;
1189 pcontent =
SCCalloc(1, content_len);
1192 memset(pcontent, content, content_len);
1216static int BuildIpv4TestPacketWithContent(
Packet **packet, uint8_t
proto, uint16_t
id, uint16_t off,
1217 int mf,
const uint8_t *content,
int content_len)
1229 struct timeval tval;
1230 gettimeofday(&tval, NULL);
1234 ip4h.
ip_len = htons(hlen + content_len);
1235 ip4h.
ip_id = htons(
id);
1239 ip4h.
ip_off = htons(off);
1243 ip4h.s_ip_src.s_addr = 0x01010101;
1244 ip4h.s_ip_dst.s_addr = 0x02020202;
1271static Packet *BuildIpv6TestPacket(
1272 uint8_t
proto, uint32_t
id, uint16_t off,
int mf,
const uint8_t content,
int content_len)
1284 struct timeval tval;
1285 gettimeofday(&tval, NULL);
1288 ip6h.s_ip6_nxt = 44;
1289 ip6h.s_ip6_hlim = 2;
1292 ip6h.s_ip6_src[0] = 0x01010101;
1293 ip6h.s_ip6_src[1] = 0x01010101;
1294 ip6h.s_ip6_src[2] = 0x01010101;
1295 ip6h.s_ip6_src[3] = 0x01010101;
1296 ip6h.s_ip6_dst[0] = 0x02020202;
1297 ip6h.s_ip6_dst[1] = 0x02020202;
1298 ip6h.s_ip6_dst[2] = 0x02020202;
1299 ip6h.s_ip6_dst[3] = 0x02020202;
1308 fh->ip6fh_nxt =
proto;
1309 fh->ip6fh_ident = htonl(
id);
1310 fh->ip6fh_offlg = htons((off << 3) | mf);
1314 pcontent =
SCCalloc(1, content_len);
1317 memset(pcontent, content, content_len);
1322 ip6p->s_ip6_plen = htons(
sizeof(IPV6FragHdr) + content_len);
1342static Packet *BuildIpv6TestPacketWithContent(
1343 uint8_t
proto, uint32_t
id, uint16_t off,
int mf,
const uint8_t *content,
int content_len)
1354 struct timeval tval;
1355 gettimeofday(&tval, NULL);
1358 ip6h.s_ip6_nxt = 44;
1359 ip6h.s_ip6_hlim = 2;
1362 ip6h.s_ip6_src[0] = 0x01010101;
1363 ip6h.s_ip6_src[1] = 0x01010101;
1364 ip6h.s_ip6_src[2] = 0x01010101;
1365 ip6h.s_ip6_src[3] = 0x01010101;
1366 ip6h.s_ip6_dst[0] = 0x02020202;
1367 ip6h.s_ip6_dst[1] = 0x02020202;
1368 ip6h.s_ip6_dst[2] = 0x02020202;
1369 ip6h.s_ip6_dst[3] = 0x02020202;
1378 fh->ip6fh_nxt =
proto;
1379 fh->ip6fh_ident = htonl(
id);
1380 fh->ip6fh_offlg = htons((off << 3) | mf);
1387 ip6p->s_ip6_plen = htons(
sizeof(IPV6FragHdr) + content_len);
1411static int DefragInOrderSimpleTest(
void)
1413 Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1414 Packet *reassembled = NULL;
1419 p1 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 0, 1,
'A', 8);
1421 p2 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 1, 1,
'B', 8);
1423 p3 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 2, 0,
'C', 3);
1436 for (
int i = 20; i < 20 + 8; i++) {
1441 for (
int i = 28; i < 28 + 8; i++) {
1446 for (
int i = 36; i < 36 + 3; i++) {
1462static int DefragReverseSimpleTest(
void)
1464 Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1465 Packet *reassembled = NULL;
1470 p1 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 0, 1,
'A', 8);
1472 p2 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 1, 1,
'B', 8);
1474 p3 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 2, 0,
'C', 3);
1486 for (
int i = 20; i < 20 + 8; i++) {
1491 for (
int i = 28; i < 28 + 8; i++) {
1496 for (
int i = 36; i < 36 + 3; i++) {
1513static int DefragInOrderSimpleIpv6Test(
void)
1515 Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1516 Packet *reassembled = NULL;
1521 p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 0, 1,
'A', 8);
1523 p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 1, 1,
'B', 8);
1525 p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 2, 0,
'C', 3);
1533 const IPV6Hdr *ip6h = PacketGetIPv6(reassembled);
1537 for (
int i = 40; i < 40 + 8; i++) {
1542 for (
int i = 48; i < 48 + 8; i++) {
1547 for (
int i = 56; i < 56 + 3; i++) {
1560static int DefragReverseSimpleIpv6Test(
void)
1563 Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1564 Packet *reassembled = NULL;
1569 dc = DefragContextNew();
1572 p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 0, 1,
'A', 8);
1574 p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 1, 1,
'B', 8);
1576 p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 2, 0,
'C', 3);
1585 for (
int i = 40; i < 40 + 8; i++) {
1590 for (
int i = 48; i < 48 + 8; i++) {
1595 for (
int i = 56; i < 56 + 3; i++) {
1599 DefragContextDestroy(dc);
1609static int DefragDoSturgesNovakTest(
int policy, uint8_t *expected,
size_t expected_len)
1621 memset(packets, 0x00,
sizeof(packets));
1628 packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 0, 1,
'A', 24);
1631 packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 32 >> 3, 1,
'B', 16);
1634 packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 48 >> 3, 1,
'C', 24);
1637 packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 80 >> 3, 1,
'D', 8);
1640 packets[4] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 104 >> 3, 1,
'E', 16);
1643 packets[5] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 120 >> 3, 1,
'F', 24);
1646 packets[6] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 144 >> 3, 1,
'G', 16);
1649 packets[7] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 160 >> 3, 1,
'H', 16);
1652 packets[8] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 176 >> 3, 1,
'I', 8);
1659 packets[9] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 8 >> 3, 1,
'J', 32);
1662 packets[10] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 48 >> 3, 1,
'K', 24);
1665 packets[11] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 72 >> 3, 1,
'L', 24);
1668 packets[12] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 96 >> 3, 1,
'M', 24);
1671 packets[13] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 128 >> 3, 1,
'N', 8);
1674 packets[14] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 152 >> 3, 1,
'O', 8);
1677 packets[15] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 160 >> 3, 1,
'P', 8);
1680 packets[16] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 176 >> 3, 0,
'Q', 16);
1682 default_policy = policy;
1685 for (i = 0; i < 9; i++) {
1691 for (; i < 16; i++) {
1708 if (memcmp(expected,
GET_PKT_DATA(reassembled) + 20, expected_len) != 0) {
1709 printf(
"Expected:\n");
1720 for (i = 0; i < 17; i++) {
1727static int DefragDoSturgesNovakIpv6Test(
int policy, uint8_t *expected,
size_t expected_len)
1739 memset(packets, 0x00,
sizeof(packets));
1746 packets[0] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 0, 1,
'A', 24);
1749 packets[1] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 32 >> 3, 1,
'B', 16);
1752 packets[2] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 48 >> 3, 1,
'C', 24);
1755 packets[3] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 80 >> 3, 1,
'D', 8);
1758 packets[4] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 104 >> 3, 1,
'E', 16);
1761 packets[5] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 120 >> 3, 1,
'F', 24);
1764 packets[6] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 144 >> 3, 1,
'G', 16);
1767 packets[7] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 160 >> 3, 1,
'H', 16);
1770 packets[8] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 176 >> 3, 1,
'I', 8);
1777 packets[9] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 8 >> 3, 1,
'J', 32);
1780 packets[10] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 48 >> 3, 1,
'K', 24);
1783 packets[11] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 72 >> 3, 1,
'L', 24);
1786 packets[12] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 96 >> 3, 1,
'M', 24);
1789 packets[13] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 128 >> 3, 1,
'N', 8);
1792 packets[14] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 152 >> 3, 1,
'O', 8);
1795 packets[15] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 160 >> 3, 1,
'P', 8);
1798 packets[16] = BuildIpv6TestPacket(IPPROTO_ICMPV6,
id, 176 >> 3, 0,
'Q', 16);
1800 default_policy = policy;
1803 for (i = 0; i < 9; i++) {
1809 for (; i < 16; i++) {
1830 for (i = 0; i < 17; i++) {
1845#define D_1 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'
1846#define D_2 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'
1847#define D_3 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'
1848#define D_3_1 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D'
1849#define D_3_2 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'
1850#define D_3_3 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'
1851#define D_3_4 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'
1852#define D_3_5 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H'
1853#define D_3_6 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I'
1854#define D_4 'J', 'J', 'J', 'J', 'J', 'J', 'J', 'J'
1855#define D_5 'K', 'K', 'K', 'K', 'K', 'K', 'K', 'K'
1856#define D_6 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
1857#define D_7 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M'
1858#define D_8 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N'
1859#define D_9 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'
1860#define D_10 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'
1861#define D_11 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q'
1864DefragSturgesNovakBsdTest(
void)
1867 uint8_t expected[] = {
1899static int DefragSturgesNovakBsdIpv6Test(
void)
1902 uint8_t expected[] = {
1933static int DefragSturgesNovakLinuxIpv4Test(
void)
1936 uint8_t expected[] = {
1968static int DefragSturgesNovakLinuxIpv6Test(
void)
1971 uint8_t expected[] = {
2002static int DefragSturgesNovakWindowsIpv4Test(
void)
2005 uint8_t expected[] = {
2037static int DefragSturgesNovakWindowsIpv6Test(
void)
2040 uint8_t expected[] = {
2071static int DefragSturgesNovakSolarisTest(
void)
2074 uint8_t expected[] = {
2106static int DefragSturgesNovakSolarisIpv6Test(
void)
2109 uint8_t expected[] = {
2140static int DefragSturgesNovakFirstTest(
void)
2143 uint8_t expected[] = {
2175static int DefragSturgesNovakFirstIpv6Test(
void)
2178 uint8_t expected[] = {
2209DefragSturgesNovakLastTest(
void)
2212 uint8_t expected[] = {
2244static int DefragSturgesNovakLastIpv6Test(
void)
2247 uint8_t expected[] = {
2278static int DefragTimeoutTest(
void)
2288 for (i = 0; i < 16; i++) {
2289 Packet *p = BuildIpv4TestPacket(IPPROTO_ICMP, i, 0, 1,
'A' + i, 16);
2299 Packet *p = BuildIpv4TestPacket(IPPROTO_ICMP, 99, 0, 1,
'A' + i, 16);
2324static int DefragNoDataIpv4Test(
void)
2332 dc = DefragContextNew();
2336 p = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 1, 0,
'A', 0);
2346 DefragContextDestroy(dc);
2353static int DefragTooLargeIpv4Test(
void)
2360 dc = DefragContextNew();
2365 p = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 8183, 0,
'A', 71);
2378 DefragContextDestroy(dc);
2390static int DefragVlanTest(
void)
2392 Packet *p1 = NULL, *p2 = NULL, *r = NULL;
2396 p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1,
'A', 8);
2398 p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0,
'B', 8);
2422static int DefragVlanQinQTest(
void)
2424 Packet *p1 = NULL, *p2 = NULL, *r = NULL;
2428 p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1,
'A', 8);
2430 p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0,
'B', 8);
2456static int DefragVlanQinQinQTest(
void)
2462 Packet *p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1,
'A', 8);
2464 Packet *p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0,
'B', 8);
2488static int DefragTrackerReuseTest(
void)
2498 p1 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 0, 0,
'A', 8);
2511 FAIL_IF(tracker2 != tracker1);
2524 FAIL_IF(tracker2 != tracker1);
2541static int DefragMfIpv4Test(
void)
2548 Packet *p1 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 2, 1,
'C', 8);
2549 Packet *p2 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 0, 1,
'A', 8);
2550 Packet *p3 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 1, 0,
'B', 8);
2551 FAIL_IF(p1 == NULL || p2 == NULL || p3 == NULL);
2568 uint8_t expected_payload[] =
"AAAAAAAABBBBBBBB";
2588static int DefragMfIpv6Test(
void)
2595 Packet *p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 2, 1,
'C', 8);
2596 Packet *p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 0, 1,
'A', 8);
2597 Packet *p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 1, 0,
'B', 8);
2598 FAIL_IF(p1 == NULL || p2 == NULL || p3 == NULL);
2615 uint8_t expected_payload[] =
"AAAAAAAABBBBBBBB";
2630static int DefragTestBadProto(
void)
2632 Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
2637 p1 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 0, 1,
'A', 8);
2639 p2 = BuildIpv4TestPacket(IPPROTO_UDP,
id, 1, 1,
'B', 8);
2641 p3 = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 2, 0,
'C', 3);
2660static int DefragTestJeremyLinux(
void)
2663 uint8_t expected[] =
"AAAAAAAA"
2684 packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 0, 1,
'A', 24);
2685 packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 40 >> 3, 1,
'B', 48);
2686 packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 24 >> 3, 1,
'C', 48);
2687 packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP,
id, 88 >> 3, 0,
'D', 14);
2703 for (i = 0; i < 4; i++) {
2722static int DefragBsdFragmentAfterNoMfIpv4Test(
void)
2728 packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 24 >> 3, 0,
'A', 16);
2729 packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 8 >> 3, 1,
'B', 16);
2730 packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 16 >> 3, 1,
'C', 16);
2731 packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 0, 1,
'D', 8);
2746 uint8_t expected[] = {
2747 'D',
'D',
'D',
'D',
'D',
'D',
'D',
'D',
2748 'B',
'B',
'B',
'B',
'B',
'B',
'B',
'B',
2749 'B',
'B',
'B',
'B',
'B',
'B',
'B',
'B',
2750 'C',
'C',
'C',
'C',
'C',
'C',
'C',
'C',
2751 'A',
'A',
'A',
'A',
'A',
'A',
'A',
'A',
2755 if (memcmp(expected,
GET_PKT_DATA(r) + 20,
sizeof(expected)) != 0) {
2756 printf(
"Expected:\n");
2767static int DefragBsdFragmentAfterNoMfIpv6Test(
void)
2773 packets[0] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 24 >> 3, 0,
'A', 16);
2774 packets[1] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 8 >> 3, 1,
'B', 16);
2775 packets[2] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 16 >> 3, 1,
'C', 16);
2776 packets[3] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 0, 1,
'D', 8);
2791 uint8_t expected[] = {
2792 'D',
'D',
'D',
'D',
'D',
'D',
'D',
'D',
2793 'B',
'B',
'B',
'B',
'B',
'B',
'B',
'B',
2794 'B',
'B',
'B',
'B',
'B',
'B',
'B',
'B',
2795 'C',
'C',
'C',
'C',
'C',
'C',
'C',
'C',
2796 'A',
'A',
'A',
'A',
'A',
'A',
'A',
'A',
2800 if (memcmp(expected,
GET_PKT_DATA(r) + 40,
sizeof(expected)) != 0) {
2801 printf(
"Expected:\n");
2812static int DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2(
void)
2820 &packets[0], IPPROTO_ICMP, 6, 16 >> 3, 1, (uint8_t *)
"AABBCCDDAABBDDCC", 16));
2824 &packets[1], IPPROTO_ICMP, 6, 8 >> 3, 1, (uint8_t *)
"AACCBBDDAACCDDBB", 16));
2828 &packets[2], IPPROTO_ICMP, 6, 0, 1, (uint8_t *)
"ZZZZZZZZ", 8));
2832 &packets[3], IPPROTO_ICMP, 6, 32 >> 3, 0, (uint8_t *)
"DDCCBBAA", 8));
2847 const uint8_t expected[] = {
2852 'A',
'A',
'C',
'C',
'B',
'B',
'D',
'D',
2853 'A',
'A',
'C',
'C',
'D',
'D',
'B',
'B',
2854 'A',
'A',
'B',
'B',
'D',
'D',
'C',
'C',
2855 'D',
'D',
'C',
'C',
'B',
'B',
'A',
'A',
2865static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2(
void)
2872 packets[0] = BuildIpv6TestPacketWithContent(
2873 IPPROTO_ICMP, 6, 16 >> 3, 1, (uint8_t *)
"AABBCCDDAABBDDCC", 16);
2876 packets[1] = BuildIpv6TestPacketWithContent(
2877 IPPROTO_ICMP, 6, 8 >> 3, 1, (uint8_t *)
"AACCBBDDAACCDDBB", 16);
2880 packets[2] = BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 6, 0, 1, (uint8_t *)
"ZZZZZZZZ", 8);
2884 BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 6, 32 >> 3, 0, (uint8_t *)
"DDCCBBAA", 8);
2899 const uint8_t expected[] = {
2904 'A',
'A',
'C',
'C',
'B',
'B',
'D',
'D',
2905 'A',
'A',
'C',
'C',
'D',
'D',
'B',
'B',
2906 'A',
'A',
'B',
'B',
'D',
'D',
'C',
'C',
2907 'D',
'D',
'C',
'C',
'B',
'B',
'A',
'A',
2929static int DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test(
void)
2935 packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 8 >> 3, 0,
'E', 24);
2936 packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1,
'M', 24);
2945 const uint8_t expected[] = {
2946 'M',
'M',
'M',
'M',
'M',
'M',
'M',
'M',
2947 'M',
'M',
'M',
'M',
'M',
'M',
'M',
'M',
2948 'M',
'M',
'M',
'M',
'M',
'M',
'M',
'M',
2949 'E',
'E',
'E',
'E',
'E',
'E',
'E',
'E',
2953 if (memcmp(expected,
GET_PKT_DATA(r) + 20,
sizeof(expected)) != 0) {
2954 printf(
"Expected:\n");
2964static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test(
void)
2970 packets[0] = BuildIpv6TestPacket(IPPROTO_ICMP, 1, 8 >> 3, 0,
'E', 24);
2971 packets[1] = BuildIpv6TestPacket(IPPROTO_ICMP, 1, 0, 1,
'M', 24);
2980 const uint8_t expected[] = {
2981 'M',
'M',
'M',
'M',
'M',
'M',
'M',
'M',
2982 'M',
'M',
'M',
'M',
'M',
'M',
'M',
'M',
2983 'M',
'M',
'M',
'M',
'M',
'M',
'M',
'M',
2984 'E',
'E',
'E',
'E',
'E',
'E',
'E',
'E',
2988 if (memcmp(expected,
GET_PKT_DATA(r) + 40,
sizeof(expected)) != 0) {
2989 printf(
"Expected:\n");
3010static int DefragBsdMissingFragmentIpv4Test(
void)
3017 &packets[0], IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)
"AABBCCDDAABBDDCC", 16));
3020 &packets[1], IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)
"AACCBBDD", 8));
3023 &packets[2], IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)
"AACCDDBBAADDBBCC", 16));
3027 &packets[3], IPPROTO_ICMP, 189, 0, 1, (uint8_t *)
"ZZZZZZZZ", 8));
3030 &packets[4], IPPROTO_ICMP, 189, 48 >> 3, 0, (uint8_t *)
"DDCCBBAA", 8));
3051 for (
int i = 0; i < 5; i++) {
3060static int DefragBsdMissingFragmentIpv6Test(
void)
3066 packets[0] = BuildIpv6TestPacketWithContent(
3067 IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)
"AABBCCDDAABBDDCC", 16);
3070 BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)
"AACCBBDD", 8);
3072 packets[2] = BuildIpv6TestPacketWithContent(
3073 IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)
"AACCDDBBAADDBBCC", 16);
3076 packets[3] = BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 0, 1, (uint8_t *)
"ZZZZZZZZ", 8);
3079 BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 48 >> 3, 0, (uint8_t *)
"DDCCBBAA", 8);
3100 for (
int i = 0; i < 5; i++) {
3114 UtRegisterTest(
"DefragInOrderSimpleTest", DefragInOrderSimpleTest);
3115 UtRegisterTest(
"DefragReverseSimpleTest", DefragReverseSimpleTest);
3116 UtRegisterTest(
"DefragSturgesNovakBsdTest", DefragSturgesNovakBsdTest);
3118 DefragSturgesNovakLinuxIpv4Test);
3120 DefragSturgesNovakWindowsIpv4Test);
3122 DefragSturgesNovakSolarisTest);
3123 UtRegisterTest(
"DefragSturgesNovakFirstTest", DefragSturgesNovakFirstTest);
3124 UtRegisterTest(
"DefragSturgesNovakLastTest", DefragSturgesNovakLastTest);
3127 UtRegisterTest(
"DefragTooLargeIpv4Test", DefragTooLargeIpv4Test);
3129 UtRegisterTest(
"DefragInOrderSimpleIpv6Test", DefragInOrderSimpleIpv6Test);
3130 UtRegisterTest(
"DefragReverseSimpleIpv6Test", DefragReverseSimpleIpv6Test);
3131 UtRegisterTest(
"DefragSturgesNovakBsdIpv6Test", DefragSturgesNovakBsdIpv6Test);
3132 UtRegisterTest(
"DefragSturgesNovakLinuxIpv6Test", DefragSturgesNovakLinuxIpv6Test);
3133 UtRegisterTest(
"DefragSturgesNovakWindowsIpv6Test", DefragSturgesNovakWindowsIpv6Test);
3134 UtRegisterTest(
"DefragSturgesNovakSolarisIpv6Test", DefragSturgesNovakSolarisIpv6Test);
3135 UtRegisterTest(
"DefragSturgesNovakFirstIpv6Test", DefragSturgesNovakFirstIpv6Test);
3136 UtRegisterTest(
"DefragSturgesNovakLastIpv6Test", DefragSturgesNovakLastIpv6Test);
3141 UtRegisterTest(
"DefragTrackerReuseTest", DefragTrackerReuseTest);
3149 UtRegisterTest(
"DefragBsdFragmentAfterNoMfIpv4Test", DefragBsdFragmentAfterNoMfIpv4Test);
3150 UtRegisterTest(
"DefragBsdFragmentAfterNoMfIpv6Test", DefragBsdFragmentAfterNoMfIpv6Test);
3151 UtRegisterTest(
"DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test",
3152 DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test);
3153 UtRegisterTest(
"DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test",
3154 DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test);
3155 UtRegisterTest(
"DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2",
3156 DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2);
3157 UtRegisterTest(
"DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2",
3158 DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2);
3159 UtRegisterTest(
"DefragBsdMissingFragmentIpv4Test", DefragBsdMissingFragmentIpv4Test);
3160 UtRegisterTest(
"DefragBsdMissingFragmentIpv6Test", DefragBsdMissingFragmentIpv6Test);
struct HtpBodyChunk_ * next
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
int SCConfSet(const char *name, const char *val)
Set a configuration value.
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
@ IPV6_FRAG_PKT_TOO_LARGE
@ IPV4_FRAG_PKT_TOO_LARGE
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
#define IPV4_GET_RAW_FRAGOFFSET(ip4h)
#define IPV4_GET_RAW_IPLEN(ip4h)
#define IPV4_MAXPACKET_LEN
#define IPV4_GET_RAW_IPTTL(ip4h)
#define IPV4_GET_RAW_VER(ip4h)
#define IPV4_GET_RAW_HLEN(ip4h)
#define IPV4_GET_RAW_FLAG_MF(ip4h)
#define IPV4_GET_RAW_IPID(ip4h)
#define IPV4_GET_RAW_IPPROTO(ip4h)
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
void DecodeIPV6FragHeader(Packet *p, const uint8_t *pkt, uint16_t hdrextlen, uint16_t plen, uint16_t prev_hdrextlen)
#define IPV6_GET_RAW_PLEN(ip6h)
#define IPV6_EXTHDR_GET_FH_OFFSET(p)
#define IPV6_GET_RAW_VER(ip6h)
#define IPV6_GET_RAW_NH(ip6h)
#define IPV6_SET_RAW_VER(ip6h, value)
#define IPV6_EXTHDR_GET_FH_FLAG(p)
#define IPV6_EXTHDR_GET_FH_NH(p)
#define GET_IPV6_DST_ADDR(p)
#define SET_IPV6_SRC_ADDR(ip6h, a)
#define SET_PKT_LEN(p, len)
#define PKT_REBUILT_FRAGMENT
#define PKT_SET_SRC(p, src_val)
#define ENGINE_ISSET_EVENT(p, e)
#define SET_IPV4_SRC_ADDR(ip4h, a)
#define SET_IPV6_DST_ADDR(ip6h, a)
#define SET_IPV4_DST_ADDR(ip4h, a)
#define ENGINE_SET_EVENT(p, e)
#define GET_IPV4_DST_ADDR_PTR(p)
void DefragPolicyLoadFromConfig(void)
void DefragTreeDestroy(void)
void DefragSetDefaultTimeout(int timeout)
void DefragTrackerRelease(DefragTracker *t)
DefragTracker * DefragLookupTrackerFromHash(Packet *p)
look up a tracker in the hash
DefragTracker * DefragGetTrackerFromHash(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
void DefragInitConfig(bool quiet)
initialize the configuration
void DefragHashShutdown(void)
shutdown the flow engine
uint8_t DefragGetOsPolicy(Packet *p)
Get the defrag policy based on the destination address of the packet.
int DefragRbFragCompare(struct Frag_ *a, struct Frag_ *b)
#define DEFAULT_DEFRAG_POOL_SIZE
@ DEFRAG_POLICY_BSD_RIGHT
void DefragTrackerFreeFrags(DefragTracker *tracker)
Free all frags associated with a tracker.
Packet * Defrag(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Entry point for IPv4 and IPv6 fragments.
void DefragRegisterTests(void)
DecodeThreadVars test_dtv
#define DEFAULT_DEFRAG_HASH_SIZE
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
void PacketDefragPktSetupParent(Packet *parent)
inform defrag "parent" that a pseudo packet is now associated to it.
int PacketCopyDataOffset(Packet *p, uint32_t offset, const uint8_t *data, uint32_t datalen)
Copy data to Packet payload at given offset.
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
uint32_t default_packet_size
Packet * PacketDefragPktSetup(Packet *parent, const uint8_t *pkt, uint32_t len, uint8_t proto)
Setup a pseudo packet (reassembled frags)
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
void PacketFree(Packet *p)
Return a malloced packet.
Pool * PoolInit(uint32_t size, uint32_t prealloc_size, uint32_t elt_size, void *(*Alloc)(void), int(*Init)(void *, void *), void *InitData, void(*Cleanup)(void *), void(*Free)(void *))
Init a Pool.
void PoolReturn(Pool *p, void *data)
void PacketInit(Packet *p)
Initialize a packet structure for use.
Structure to hold thread specific data for all decode modules.
uint16_t counter_defrag_max_hit
uint16_t counter_defrag_ipv4_reassembled
uint16_t counter_defrag_ipv6_fragments
uint16_t counter_defrag_ipv6_reassembled
uint16_t counter_defrag_ipv4_fragments
uint16_t counter_defrag_no_frags
struct IP_FRAGMENTS fragment_tree
uint16_t fh_header_offset
uint16_t fh_prev_hdr_offset
struct PacketL3::@31::@32 ip6
uint16_t vlan_id[VLAN_MAX_LAYERS]
Per thread variable structure.
#define SCMutexUnlock(mut)
#define SCMutexInit(mut, mutattrs)
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
#define RB_FOREACH(x, name, head)
#define RB_FOREACH_FROM(x, name, y)
#define RB_NFIND(name, x, y)
#define RB_FOREACH_SAFE(x, name, head, y)
#define RB_REMOVE(name, x, y)
#define RB_GENERATE(name, type, field, cmp)
uint16_t FixChecksum(uint16_t sum, uint16_t old, uint16_t new)
Fix-up an IP checksum.
int SCHInfoGetIPv6HostOSFlavour(uint8_t *addr)
Retrieves the host os flavour, given an ipv6 address in the raw address format.
int SCHInfoGetIPv4HostOSFlavour(uint8_t *addr)
Retrieves the host os flavour, given an ipv4 address in the raw address format.
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
#define SCTIME_FROM_SECS(s)
#define SCTIME_ADD_SECS(ts, s)
#define SCTIME_FROM_TIMEVAL(tv)
#define DEBUG_VALIDATE_BUG_ON(exp)