/**
* \brief Reset a frag for reuse in a pool.
*/
-static void
-DefragFragReset(Frag *frag)
+static void DefragFragReset(Frag *frag)
{
if (frag->pkt != NULL)
SCFree(frag->pkt);
/**
* \brief Allocate a new frag for use in a pool.
*/
-static int
-DefragFragInit(void *data, void *initdata)
+static int DefragFragInit(void *data, void *initdata)
{
Frag *frag = data;
/**
* \brief Free all frags associated with a tracker.
*/
-void
-DefragTrackerFreeFrags(DefragTracker *tracker)
+void DefragTrackerFreeFrags(DefragTracker *tracker)
{
Frag *frag, *tmp;
/* Lock the frag pool as we'll be return items to it. */
SCMutexLock(&defrag_context->frag_pool_lock);
- RB_FOREACH_SAFE(frag, IP_FRAGMENTS, &tracker->fragment_tree, tmp) {
+ RB_FOREACH_SAFE (frag, IP_FRAGMENTS, &tracker->fragment_tree, tmp) {
RB_REMOVE(IP_FRAGMENTS, &tracker->fragment_tree, frag);
DefragFragReset(frag);
PoolReturn(defrag_context->frag_pool, frag);
* \retval On success a return an initialized DefragContext, otherwise
* NULL will be returned.
*/
-static DefragContext *
-DefragContextNew(void)
+static DefragContext *DefragContextNew(void)
{
DefragContext *dc;
frag_pool_size = DEFAULT_DEFRAG_POOL_SIZE;
}
intmax_t frag_pool_prealloc = frag_pool_size / 2;
- dc->frag_pool = PoolInit(frag_pool_size, frag_pool_prealloc,
- sizeof(Frag),
- NULL, DefragFragInit, dc, NULL, NULL);
+ dc->frag_pool = PoolInit(
+ frag_pool_size, frag_pool_prealloc, sizeof(Frag), NULL, DefragFragInit, dc, NULL, NULL);
if (dc->frag_pool == NULL) {
- FatalError(SC_ERR_FATAL,
- "Defrag: Failed to initialize fragment pool.");
+ FatalError(SC_ERR_FATAL, "Defrag: Failed to initialize fragment pool.");
}
if (SCMutexInit(&dc->frag_pool_lock, NULL) != 0) {
- FatalError(SC_ERR_FATAL,
- "Defrag: Failed to initialize frag pool mutex.");
+ FatalError(SC_ERR_FATAL, "Defrag: Failed to initialize frag pool mutex.");
}
/* Set the default timeout. */
intmax_t timeout;
if (!ConfGetInt("defrag.timeout", &timeout)) {
dc->timeout = TIMEOUT_DEFAULT;
- }
- else {
+ } else {
if (timeout < TIMEOUT_MIN) {
- FatalError(SC_ERR_FATAL,
- "defrag: Timeout less than minimum allowed value.");
- }
- else if (timeout > TIMEOUT_MAX) {
- FatalError(SC_ERR_FATAL,
- "defrag: Tiemout greater than maximum allowed value.");
+ FatalError(SC_ERR_FATAL, "defrag: Timeout less than minimum allowed value.");
+ } else if (timeout > TIMEOUT_MAX) {
+ FatalError(SC_ERR_FATAL, "defrag: Tiemout greater than maximum allowed value.");
}
dc->timeout = timeout;
}
SCLogDebug("Defrag Initialized:");
- SCLogDebug("\tTimeout: %"PRIuMAX, (uintmax_t)dc->timeout);
- SCLogDebug("\tMaximum defrag trackers: %"PRIuMAX, tracker_pool_size);
- SCLogDebug("\tPreallocated defrag trackers: %"PRIuMAX, tracker_pool_size);
- SCLogDebug("\tMaximum fragments: %"PRIuMAX, (uintmax_t)frag_pool_size);
- SCLogDebug("\tPreallocated fragments: %"PRIuMAX, (uintmax_t)frag_pool_prealloc);
+ SCLogDebug("\tTimeout: %" PRIuMAX, (uintmax_t)dc->timeout);
+ SCLogDebug("\tMaximum defrag trackers: %" PRIuMAX, tracker_pool_size);
+ SCLogDebug("\tPreallocated defrag trackers: %" PRIuMAX, tracker_pool_size);
+ SCLogDebug("\tMaximum fragments: %" PRIuMAX, (uintmax_t)frag_pool_size);
+ SCLogDebug("\tPreallocated fragments: %" PRIuMAX, (uintmax_t)frag_pool_prealloc);
return dc;
}
-static void
-DefragContextDestroy(DefragContext *dc)
+static void DefragContextDestroy(DefragContext *dc)
{
if (dc == NULL)
return;
*
* \param tracker The defragmentation tracker to reassemble from.
*/
-static Packet *
-Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
+static Packet *Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
{
Packet *rp = NULL;
* fragments are inserted in frag_offset order. */
Frag *frag = NULL;
size_t len = 0;
- RB_FOREACH_FROM(frag, IP_FRAGMENTS, first) {
+ RB_FOREACH_FROM (frag, IP_FRAGMENTS, first) {
if (frag->offset > len) {
/* This fragment starts after the end of the previous
* fragment. We have a hole. */
goto done;
- }
- else {
+ } else {
len += frag->data_len;
}
}
rp = PacketDefragPktSetup(p, NULL, 0, IPV4_GET_IPPROTO(p));
if (rp == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate packet for "
- "fragmentation re-assembly, dumping fragments.");
+ "fragmentation re-assembly, dumping fragments.");
goto error_remove_tracker;
}
PKT_SET_SRC(rp, PKT_SRC_DEFRAG);
uint16_t prev_offset = 0;
bool more_frags = 1;
- RB_FOREACH(frag, IP_FRAGMENTS, &tracker->fragment_tree) {
- SCLogDebug("frag %p, data_len %u, offset %u, pcap_cnt %"PRIu64,
- frag, frag->data_len, frag->offset, frag->pcap_cnt);
+ RB_FOREACH(frag, IP_FRAGMENTS, &tracker->fragment_tree)
+ {
+ SCLogDebug("frag %p, data_len %u, offset %u, pcap_cnt %" PRIu64, frag, frag->data_len,
+ frag->offset, frag->pcap_cnt);
/* Previous fragment has no more fragments, and this packet
* doesn't overlap. We're done. */
* this. */
fragmentable_offset = frag->ip_hdr_offset + frag->hlen;
fragmentable_len = frag->data_len;
- }
- else {
+ } else {
int pkt_end = fragmentable_offset + frag->offset + frag->data_len;
if (pkt_end > (int)MAX_PAYLOAD_SIZE) {
- SCLogWarning(SC_ERR_REASSEMBLY, "Failed re-assemble "
+ SCLogWarning(SC_ERR_REASSEMBLY,
+ "Failed re-assemble "
"fragmented packet, exceeds size of packet buffer.");
goto error_remove_tracker;
}
- if (PacketCopyDataOffset(rp,
- fragmentable_offset + frag->offset + frag->ltrim,
- frag->pkt + frag->data_offset + frag->ltrim,
- frag->data_len - frag->ltrim) == -1) {
+ if (PacketCopyDataOffset(rp, fragmentable_offset + frag->offset + frag->ltrim,
+ frag->pkt + frag->data_offset + frag->ltrim,
+ frag->data_len - frag->ltrim) == -1) {
goto error_remove_tracker;
}
if (frag->offset + frag->data_len > fragmentable_len)
prev_offset = frag->offset;
}
- SCLogDebug("ip_hdr_offset %u, hlen %u, fragmentable_len %u",
- ip_hdr_offset, hlen, fragmentable_len);
+ SCLogDebug("ip_hdr_offset %u, hlen %u, fragmentable_len %u", ip_hdr_offset, hlen,
+ fragmentable_len);
rp->ip4h = (IPV4Hdr *)(GET_PKT_DATA(rp) + ip_hdr_offset);
int old = rp->ip4h->ip_len + rp->ip4h->ip_off;
rp->ip4h->ip_len = htons(fragmentable_len + hlen);
rp->ip4h->ip_off = 0;
- rp->ip4h->ip_csum = FixChecksum(rp->ip4h->ip_csum,
- old, rp->ip4h->ip_len + rp->ip4h->ip_off);
+ rp->ip4h->ip_csum = FixChecksum(rp->ip4h->ip_csum, old, rp->ip4h->ip_len + rp->ip4h->ip_off);
SET_PKT_LEN(rp, ip_hdr_offset + hlen + fragmentable_len);
tracker->remove = 1;
*
* \param tracker The defragmentation tracker to reassemble from.
*/
-static Packet *
-Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
+static Packet *Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
{
Packet *rp = NULL;
* fragments are inserted if frag_offset order. */
size_t len = 0;
Frag *frag = NULL;
- RB_FOREACH_FROM(frag, IP_FRAGMENTS, first) {
+ RB_FOREACH_FROM (frag, IP_FRAGMENTS, first) {
if (frag->skip) {
continue;
}
goto done;
}
len = frag->data_len;
- }
- else {
+ } else {
if (frag->offset > len) {
/* This fragment starts after the end of the previous
* fragment. We have a hole. */
goto done;
- }
- else {
+ } else {
len += frag->data_len;
}
}
/* Allocate a Packet for the reassembled packet. On failure we
* SCFree all the resources held by this tracker. */
- rp = PacketDefragPktSetup(p, (uint8_t *)p->ip6h,
- IPV6_GET_PLEN(p) + sizeof(IPV6Hdr), 0);
+ rp = PacketDefragPktSetup(p, (uint8_t *)p->ip6h, IPV6_GET_PLEN(p) + sizeof(IPV6Hdr), 0);
if (rp == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate packet for "
- "fragmentation re-assembly, dumping fragments.");
+ "fragmentation re-assembly, dumping fragments.");
goto error_remove_tracker;
}
PKT_SET_SRC(rp, PKT_SRC_DEFRAG);
uint16_t prev_offset = 0;
bool more_frags = 1;
- RB_FOREACH(frag, IP_FRAGMENTS, &tracker->fragment_tree) {
+ RB_FOREACH(frag, IP_FRAGMENTS, &tracker->fragment_tree)
+ {
if (!more_frags && frag->offset > prev_offset) {
break;
}
if (frag->data_len - frag->ltrim <= 0)
continue;
if (frag->offset == 0) {
- IPV6FragHdr *frag_hdr = (IPV6FragHdr *)(frag->pkt +
- frag->frag_hdr_offset);
+ IPV6FragHdr *frag_hdr = (IPV6FragHdr *)(frag->pkt + frag->frag_hdr_offset);
next_hdr = frag_hdr->ip6fh_nxt;
/* This is the first packet, we use this packets link and
if (PacketCopyData(rp, frag->pkt, frag->frag_hdr_offset) == -1)
goto error_remove_tracker;
if (PacketCopyDataOffset(rp, frag->frag_hdr_offset,
- frag->pkt + frag->frag_hdr_offset + sizeof(IPV6FragHdr),
- frag->data_len) == -1)
+ frag->pkt + frag->frag_hdr_offset + sizeof(IPV6FragHdr),
+ frag->data_len) == -1)
goto error_remove_tracker;
ip_hdr_offset = frag->ip_hdr_offset;
unfragmentable_len = (fragmentable_offset - ip_hdr_offset) - IPV6_HEADER_LEN;
if (unfragmentable_len >= fragmentable_offset)
goto error_remove_tracker;
- }
- else {
+ } else {
if (PacketCopyDataOffset(rp, fragmentable_offset + frag->offset + frag->ltrim,
- frag->pkt + frag->data_offset + frag->ltrim,
- frag->data_len - frag->ltrim) == -1)
+ frag->pkt + frag->data_offset + frag->ltrim,
+ frag->data_len - frag->ltrim) == -1)
goto error_remove_tracker;
if (frag->offset + frag->data_len > fragmentable_len)
fragmentable_len = frag->offset + frag->data_len;
* directly after the frag header. */
if (unfragmentable_len == 0)
rp->ip6h->s_ip6_nxt = next_hdr;
- SET_PKT_LEN(rp, ip_hdr_offset + sizeof(IPV6Hdr) +
- unfragmentable_len + fragmentable_len);
+ SET_PKT_LEN(rp, ip_hdr_offset + sizeof(IPV6Hdr) + unfragmentable_len + fragmentable_len);
tracker->remove = 1;
DefragTrackerFreeFrags(tracker);
* same offset to be treated as greater than, so we don't have an
* equal return value here.
*/
-int DefragRbFragCompare(struct Frag_ *a, struct Frag_ *b) {
+int DefragRbFragCompare(struct Frag_ *a, struct Frag_ *b)
+{
if (a->offset < b->offset) {
return -1;
}
*
* \todo Allocate packet buffers from a pool.
*/
-static Packet *
-DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
+static Packet *DefragInsertFrag(
+ ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{
Packet *r = NULL;
int ltrim = 0;
ENGINE_SET_EVENT(p, IPV4_FRAG_PKT_TOO_LARGE);
return NULL;
}
- }
- else if (tracker->af == AF_INET6) {
+ } else if (tracker->af == AF_INET6) {
more_frags = IPV6_EXTHDR_GET_FH_FLAG(p);
frag_offset = IPV6_EXTHDR_GET_FH_OFFSET(p);
data_offset = p->ip6eh.fh_data_offset;
frag_hdr_offset = p->ip6eh.fh_header_offset;
SCLogDebug("mf %s frag_offset %u data_offset %u, data_len %u, "
- "frag_end %u, ip_hdr_offset %u, frag_hdr_offset %u",
- more_frags ? "true" : "false", frag_offset, data_offset,
- data_len, frag_end, ip_hdr_offset, frag_hdr_offset);
+ "frag_end %u, ip_hdr_offset %u, frag_hdr_offset %u",
+ more_frags ? "true" : "false", frag_offset, data_offset, data_len, frag_end,
+ ip_hdr_offset, frag_hdr_offset);
/* handle unfragmentable exthdrs */
if (ip_hdr_offset + IPV6_HEADER_LEN < frag_hdr_offset) {
ENGINE_SET_EVENT(p, IPV6_FRAG_PKT_TOO_LARGE);
return NULL;
}
- }
- else {
+ } else {
DEBUG_VALIDATE_BUG_ON(1);
return NULL;
}
}
switch (tracker->policy) {
- case DEFRAG_POLICY_BSD:
- if (frag_offset < prev->offset + prev->data_len) {
- if (frag_offset >= prev->offset) {
- ltrim = prev->offset + prev->data_len - frag_offset;
- }
- if ((next != NULL) && (frag_end > next->offset)) {
- next->ltrim = frag_end - next->offset;
+ case DEFRAG_POLICY_BSD:
+ if (frag_offset < prev->offset + prev->data_len) {
+ if (prev->offset <= frag_offset) {
+ /* We prefer the data from the previous
+ * fragment, so trim off the data in the new
+ * fragment that exists in the previous
+ * fragment. */
+ uint16_t prev_end = prev->offset + prev->data_len;
+ if (prev_end > frag_end) {
+ /* Just skip. */
+ /* TODO: Set overlap flag. */
+ goto done;
+ }
+ ltrim = prev_end - frag_offset;
+
+ if ((next != NULL) && (frag_end > next->offset)) {
+ next->ltrim = frag_end - next->offset;
+ }
+
+ goto insert;
+ }
+
+ /* If the end of this fragment overlaps the start
+ * of the previous fragment, then trim up the
+ * start of previous fragment so this fragment is
+ * used.
+ *
+ * See:
+ * DefragBsdSubsequentOverlapsStartOfOriginal.
+ */
+ if (frag_offset <= prev->offset && frag_end > prev->offset + prev->ltrim) {
+ uint16_t prev_ltrim = frag_end - prev->offset;
+ if (prev_ltrim > prev->ltrim) {
+ prev->ltrim = prev_ltrim;
+ }
+ }
+
+ if ((next != NULL) && (frag_end > next->offset)) {
+ next->ltrim = frag_end - next->offset;
+ }
+
+ goto insert;
}
- if ((frag_offset < prev->offset) &&
- (frag_end >= prev->offset + prev->data_len)) {
- prev->skip = 1;
+ break;
+ case DEFRAG_POLICY_LINUX:
+ /* Check if new fragment overlaps the end of previous
+ * fragment, if it does, trim the new fragment.
+ *
+ * Old: AAAAAAAA AAAAAAAA AAAAAAAA
+ * New: BBBBBBBB BBBBBBBB BBBBBBBB
+ * Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB
+ */
+ if (prev->offset + prev->ltrim < frag_offset + ltrim &&
+ prev->offset + prev->data_len > frag_offset + ltrim) {
+ ltrim += prev->offset + prev->data_len - frag_offset;
}
- goto insert;
- }
- break;
- case DEFRAG_POLICY_LINUX:
- /* Check if new fragment overlaps the end of previous
- * fragment, if it does, trim the new fragment.
- *
- * Old: AAAAAAAA AAAAAAAA AAAAAAAA
- * New: BBBBBBBB BBBBBBBB BBBBBBBB
- * Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB
- */
- if (prev->offset + prev->ltrim < frag_offset + ltrim &&
- prev->offset + prev->data_len > frag_offset + ltrim) {
- ltrim += prev->offset + prev->data_len - frag_offset;
- }
- /* Check if new fragment overlaps the beginning of
- * previous fragment, if it does, tim the previous
- * fragment.
- *
- * Old: AAAAAAAA AAAAAAAA
- * New: BBBBBBBB BBBBBBBB BBBBBBBB
- * Res: BBBBBBBB BBBBBBBB BBBBBBBB
- */
- if (frag_offset + ltrim < prev->offset + prev->ltrim &&
- frag_end > prev->offset + prev->ltrim) {
- prev->ltrim += frag_end - (prev->offset + prev->ltrim);
- goto insert;
- }
+ /* Check if new fragment overlaps the beginning of
+ * previous fragment, if it does, tim the previous
+ * fragment.
+ *
+ * Old: AAAAAAAA AAAAAAAA
+ * New: BBBBBBBB BBBBBBBB BBBBBBBB
+ * Res: BBBBBBBB BBBBBBBB BBBBBBBB
+ */
+ if (frag_offset + ltrim < prev->offset + prev->ltrim &&
+ frag_end > prev->offset + prev->ltrim) {
+ prev->ltrim += frag_end - (prev->offset + prev->ltrim);
+ goto insert;
+ }
- /* If the new fragment completely overlaps the
- * previous fragment, mark the previous to be
- * skipped. Re-assembly would succeed without doing
- * this, but this will prevent the bytes from being
- * copied just to be overwritten. */
- if (frag_offset + ltrim <= prev->offset + prev->ltrim &&
- frag_end >= prev->offset + prev->data_len) {
- prev->skip = 1;
- goto insert;
- }
+ /* If the new fragment completely overlaps the
+ * previous fragment, mark the previous to be
+ * skipped. Re-assembly would succeed without doing
+ * this, but this will prevent the bytes from being
+ * copied just to be overwritten. */
+ if (frag_offset + ltrim <= prev->offset + prev->ltrim &&
+ frag_end >= prev->offset + prev->data_len) {
+ prev->skip = 1;
+ goto insert;
+ }
- break;
- case DEFRAG_POLICY_WINDOWS:
- /* If new fragment fits inside a previous fragment, drop it. */
- if (frag_offset + ltrim >= prev->offset + ltrim &&
- frag_end <= prev->offset + prev->data_len) {
- goto done;
- }
+ break;
+ case DEFRAG_POLICY_WINDOWS:
+ /* If new fragment fits inside a previous fragment, drop it. */
+ if (frag_offset + ltrim >= prev->offset + ltrim &&
+ frag_end <= prev->offset + prev->data_len) {
+ goto done;
+ }
- /* If new fragment starts before and ends after
- * previous fragment, drop the previous fragment. */
- if (frag_offset + ltrim < prev->offset + ltrim &&
- frag_end > prev->offset + prev->data_len) {
- prev->skip = 1;
- goto insert;
- }
+ /* If new fragment starts before and ends after
+ * previous fragment, drop the previous fragment. */
+ if (frag_offset + ltrim < prev->offset + ltrim &&
+ frag_end > prev->offset + prev->data_len) {
+ prev->skip = 1;
+ goto insert;
+ }
- /* Check if new fragment overlaps the end of previous
- * fragment, if it does, trim the new fragment.
- *
- * Old: AAAAAAAA AAAAAAAA AAAAAAAA
- * New: BBBBBBBB BBBBBBBB BBBBBBBB
- * Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB
- */
- if (frag_offset + ltrim > prev->offset + prev->ltrim &&
- frag_offset + ltrim < prev->offset + prev->data_len) {
- ltrim += prev->offset + prev->data_len - frag_offset;
- goto insert;
- }
+ /* Check if new fragment overlaps the end of previous
+ * fragment, if it does, trim the new fragment.
+ *
+ * Old: AAAAAAAA AAAAAAAA AAAAAAAA
+ * New: BBBBBBBB BBBBBBBB BBBBBBBB
+ * Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB
+ */
+ if (frag_offset + ltrim > prev->offset + prev->ltrim &&
+ frag_offset + ltrim < prev->offset + prev->data_len) {
+ ltrim += prev->offset + prev->data_len - frag_offset;
+ goto insert;
+ }
- /* If new fragment starts at same offset as an
- * existing fragment, but ends after it, trim the new
- * fragment. */
- if (frag_offset + ltrim == prev->offset + ltrim &&
- frag_end > prev->offset + prev->data_len) {
- ltrim += prev->offset + prev->data_len - frag_offset;
- goto insert;
- }
- break;
- case DEFRAG_POLICY_SOLARIS:
- if (frag_offset < prev->offset + prev->data_len) {
- if (frag_offset >= prev->offset) {
- ltrim = prev->offset + prev->data_len - frag_offset;
+ /* If new fragment starts at same offset as an
+ * existing fragment, but ends after it, trim the new
+ * fragment. */
+ if (frag_offset + ltrim == prev->offset + ltrim &&
+ frag_end > prev->offset + prev->data_len) {
+ ltrim += prev->offset + prev->data_len - frag_offset;
+ goto insert;
}
- if ((frag_offset < prev->offset) &&
- (frag_end >= prev->offset + prev->data_len)) {
- prev->skip = 1;
+ break;
+ case DEFRAG_POLICY_SOLARIS:
+ if (frag_offset < prev->offset + prev->data_len) {
+ if (frag_offset >= prev->offset) {
+ ltrim = prev->offset + prev->data_len - frag_offset;
+ }
+ if ((frag_offset < prev->offset) &&
+ (frag_end >= prev->offset + prev->data_len)) {
+ prev->skip = 1;
+ }
+ goto insert;
}
- goto insert;
- }
- break;
- case DEFRAG_POLICY_FIRST:
- if ((frag_offset >= prev->offset) &&
- (frag_end <= prev->offset + prev->data_len)) {
- goto done;
- }
- if (frag_offset < prev->offset) {
- goto insert;
- }
- if (frag_offset < prev->offset + prev->data_len) {
- ltrim = prev->offset + prev->data_len - frag_offset;
- goto insert;
- }
- break;
- case DEFRAG_POLICY_LAST:
- if (frag_offset <= prev->offset) {
- if (frag_end > prev->offset) {
- prev->ltrim = frag_end - prev->offset;
+ break;
+ case DEFRAG_POLICY_FIRST:
+ if ((frag_offset >= prev->offset) &&
+ (frag_end <= prev->offset + prev->data_len)) {
+ goto done;
}
- goto insert;
- }
- break;
- default:
- break;
+ if (frag_offset < prev->offset) {
+ goto insert;
+ }
+ if (frag_offset < prev->offset + prev->data_len) {
+ ltrim = prev->offset + prev->data_len - frag_offset;
+ goto insert;
+ }
+ break;
+ case DEFRAG_POLICY_LAST:
+ if (frag_offset <= prev->offset) {
+ if (frag_end > prev->offset) {
+ prev->ltrim = frag_end - prev->offset;
+ }
+ goto insert;
+ }
+ break;
+ default:
+ break;
}
next:
r = Defrag4Reassemble(tv, tracker, p);
if (r != NULL && tv != NULL && dtv != NULL) {
StatsIncr(tv, dtv->counter_defrag_ipv4_reassembled);
- if (DecodeIPV4(tv, dtv, r, (void *)r->ip4h,
- IPV4_GET_IPLEN(r)) != TM_ECODE_OK) {
+ if (DecodeIPV4(tv, dtv, r, (void *)r->ip4h, IPV4_GET_IPLEN(r)) != TM_ECODE_OK) {
UNSET_TUNNEL_PKT(r);
r->root = NULL;
PacketDefragPktSetupParent(p);
}
}
- }
- else if (tracker->af == AF_INET6) {
+ } else if (tracker->af == AF_INET6) {
r = Defrag6Reassemble(tv, tracker, p);
if (r != NULL && tv != NULL && dtv != NULL) {
StatsIncr(tv, dtv->counter_defrag_ipv6_reassembled);
if (DecodeIPV6(tv, dtv, r, (uint8_t *)r->ip6h,
- IPV6_GET_PLEN(r) + IPV6_HEADER_LEN)
- != TM_ECODE_OK) {
+ IPV6_GET_PLEN(r) + IPV6_HEADER_LEN) != TM_ECODE_OK) {
UNSET_TUNNEL_PKT(r);
r->root = NULL;
}
}
-
done:
if (overlap) {
if (af == AF_INET) {
ENGINE_SET_EVENT(p, IPV4_FRAG_OVERLAP);
- }
- else {
+ } else {
ENGINE_SET_EVENT(p, IPV6_FRAG_OVERLAP);
}
}
*
* \retval The defrag policy to use.
*/
-uint8_t
-DefragGetOsPolicy(Packet *p)
+uint8_t DefragGetOsPolicy(Packet *p)
{
int policy = -1;
if (PKT_IS_IPV4(p)) {
policy = SCHInfoGetIPv4HostOSFlavour((uint8_t *)GET_IPV4_DST_ADDR_PTR(p));
- }
- else if (PKT_IS_IPV6(p)) {
+ } else if (PKT_IS_IPV6(p)) {
policy = SCHInfoGetIPv6HostOSFlavour((uint8_t *)GET_IPV6_DST_ADDR(p));
}
/* Map the OS policies returned from the configured host info to
* defrag specific policies. */
switch (policy) {
- /* BSD. */
- case OS_POLICY_BSD:
- case OS_POLICY_HPUX10:
- case OS_POLICY_IRIX:
- return DEFRAG_POLICY_BSD;
-
- /* BSD-Right. */
- case OS_POLICY_BSD_RIGHT:
- return DEFRAG_POLICY_BSD_RIGHT;
-
- /* Linux. */
- case OS_POLICY_OLD_LINUX:
- case OS_POLICY_LINUX:
- return DEFRAG_POLICY_LINUX;
-
- /* First. */
- case OS_POLICY_OLD_SOLARIS:
- case OS_POLICY_HPUX11:
- case OS_POLICY_MACOS:
- case OS_POLICY_FIRST:
- return DEFRAG_POLICY_FIRST;
-
- /* Solaris. */
- case OS_POLICY_SOLARIS:
- return DEFRAG_POLICY_SOLARIS;
-
- /* Windows. */
- case OS_POLICY_WINDOWS:
- case OS_POLICY_VISTA:
- case OS_POLICY_WINDOWS2K3:
- return DEFRAG_POLICY_WINDOWS;
-
- /* Last. */
- case OS_POLICY_LAST:
- return DEFRAG_POLICY_LAST;
-
- default:
- return default_policy;
+ /* BSD. */
+ case OS_POLICY_BSD:
+ case OS_POLICY_HPUX10:
+ case OS_POLICY_IRIX:
+ return DEFRAG_POLICY_BSD;
+
+ /* BSD-Right. */
+ case OS_POLICY_BSD_RIGHT:
+ return DEFRAG_POLICY_BSD_RIGHT;
+
+ /* Linux. */
+ case OS_POLICY_OLD_LINUX:
+ case OS_POLICY_LINUX:
+ return DEFRAG_POLICY_LINUX;
+
+ /* First. */
+ case OS_POLICY_OLD_SOLARIS:
+ case OS_POLICY_HPUX11:
+ case OS_POLICY_MACOS:
+ case OS_POLICY_FIRST:
+ return DEFRAG_POLICY_FIRST;
+
+ /* Solaris. */
+ case OS_POLICY_SOLARIS:
+ return DEFRAG_POLICY_SOLARIS;
+
+ /* Windows. */
+ case OS_POLICY_WINDOWS:
+ case OS_POLICY_VISTA:
+ case OS_POLICY_WINDOWS2K3:
+ return DEFRAG_POLICY_WINDOWS;
+
+ /* Last. */
+ case OS_POLICY_LAST:
+ return DEFRAG_POLICY_LAST;
+
+ default:
+ return default_policy;
}
}
/** \internal
*
* \retval NULL or a *LOCKED* tracker */
-static DefragTracker *
-DefragGetTracker(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
+static DefragTracker *DefragGetTracker(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
{
return DefragGetTrackerFromHash(p);
}
* recent fragment allowed the packet to be re-assembled, otherwise
* NULL is returned.
*/
-Packet *
-Defrag(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
+Packet *Defrag(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
{
uint16_t frag_offset;
uint8_t more_frags;
af = AF_INET;
more_frags = IPV4_GET_MF(p);
frag_offset = IPV4_GET_IPOFFSET(p);
- }
- else if (PKT_IS_IPV6(p)) {
+ } else if (PKT_IS_IPV6(p)) {
af = AF_INET6;
frag_offset = IPV6_EXTHDR_GET_FH_OFFSET(p);
more_frags = IPV6_EXTHDR_GET_FH_FLAG(p);
- }
- else {
+ } else {
return NULL;
}
if (tv != NULL && dtv != NULL) {
if (af == AF_INET) {
StatsIncr(tv, dtv->counter_defrag_ipv4_fragments);
- }
- else if (af == AF_INET6) {
+ } else if (af == AF_INET6) {
StatsIncr(tv, dtv->counter_defrag_ipv6_fragments);
}
}
return rp;
}
-void
-DefragInit(void)
+void DefragInit(void)
{
intmax_t tracker_pool_size;
if (!ConfGetInt("defrag.trackers", &tracker_pool_size)) {
/* Allocate the DefragContext. */
defrag_context = DefragContextNew();
if (defrag_context == NULL) {
- FatalError(SC_ERR_FATAL,
- "Failed to allocate memory for the Defrag module.");
+ FatalError(SC_ERR_FATAL, "Failed to allocate memory for the Defrag module.");
}
DefragSetDefaultTimeout(defrag_context->timeout);
PACKET_INITIALIZE(p);
gettimeofday(&p->ts, NULL);
- //p->ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
+ // p->ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
ip4h.ip_verhl = 4 << 4;
ip4h.ip_verhl |= hlen >> 2;
ip4h.ip_len = htons(hlen + content_len);
return NULL;
}
+/**
+ * Allocate a test packet, much like BuildIpv4TestPacket, but with
+ * the full content provided by the caller.
+ */
+static Packet *BuildIpv4TestPacketWithContent(
+ uint8_t proto, uint16_t id, uint16_t off, int mf, const uint8_t *content, int content_len)
+{
+ Packet *p = NULL;
+ int hlen = 20;
+ int ttl = 64;
+ IPV4Hdr ip4h;
+
+ p = SCCalloc(1, sizeof(*p) + default_packet_size);
+ if (unlikely(p == NULL))
+ return NULL;
+
+ PACKET_INITIALIZE(p);
+
+ gettimeofday(&p->ts, NULL);
+ ip4h.ip_verhl = 4 << 4;
+ ip4h.ip_verhl |= hlen >> 2;
+ ip4h.ip_len = htons(hlen + content_len);
+ ip4h.ip_id = htons(id);
+ if (mf)
+ ip4h.ip_off = htons(IP_MF | off);
+ else
+ ip4h.ip_off = htons(off);
+ ip4h.ip_ttl = ttl;
+ ip4h.ip_proto = proto;
+
+ ip4h.s_ip_src.s_addr = 0x01010101; /* 1.1.1.1 */
+ ip4h.s_ip_dst.s_addr = 0x02020202; /* 2.2.2.2 */
+
+ /* copy content_len crap, we need full length */
+ PacketCopyData(p, (uint8_t *)&ip4h, sizeof(ip4h));
+ p->ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
+ SET_IPV4_SRC_ADDR(p, &p->src);
+ SET_IPV4_DST_ADDR(p, &p->dst);
+
+ PacketCopyDataOffset(p, hlen, content, content_len);
+ SET_PKT_LEN(p, hlen + content_len);
+
+ p->ip4h->ip_csum = IPV4Checksum((uint16_t *)GET_PKT_DATA(p), hlen, 0);
+
+ /* Self test. */
+ if (IPV4_GET_VER(p) != 4)
+ goto error;
+ if (IPV4_GET_HLEN(p) != hlen)
+ goto error;
+ if (IPV4_GET_IPLEN(p) != hlen + content_len)
+ goto error;
+ if (IPV4_GET_IPID(p) != id)
+ goto error;
+ if (IPV4_GET_IPOFFSET(p) != off)
+ goto error;
+ if (IPV4_GET_MF(p) != mf)
+ goto error;
+ if (IPV4_GET_IPTTL(p) != ttl)
+ goto error;
+ if (IPV4_GET_IPPROTO(p) != proto)
+ goto error;
+
+ return p;
+error:
+ if (p != NULL)
+ SCFree(p);
+ return NULL;
+}
+
static Packet *BuildIpv6TestPacket(
uint8_t proto, uint32_t id, uint16_t off, int mf, const uint8_t content, int content_len)
{
return NULL;
}
+static Packet *BuildIpv6TestPacketWithContent(
+ uint8_t proto, uint32_t id, uint16_t off, int mf, const uint8_t *content, int content_len)
+{
+ Packet *p = NULL;
+ IPV6Hdr ip6h;
+
+ p = SCCalloc(1, sizeof(*p) + default_packet_size);
+ if (unlikely(p == NULL))
+ return NULL;
+
+ PACKET_INITIALIZE(p);
+
+ gettimeofday(&p->ts, NULL);
+
+ ip6h.s_ip6_nxt = 44;
+ ip6h.s_ip6_hlim = 2;
+
+ /* Source and dest address - very bogus addresses. */
+ ip6h.s_ip6_src[0] = 0x01010101;
+ ip6h.s_ip6_src[1] = 0x01010101;
+ ip6h.s_ip6_src[2] = 0x01010101;
+ ip6h.s_ip6_src[3] = 0x01010101;
+ ip6h.s_ip6_dst[0] = 0x02020202;
+ ip6h.s_ip6_dst[1] = 0x02020202;
+ ip6h.s_ip6_dst[2] = 0x02020202;
+ ip6h.s_ip6_dst[3] = 0x02020202;
+
+ /* copy content_len crap, we need full length */
+ PacketCopyData(p, (uint8_t *)&ip6h, sizeof(IPV6Hdr));
+
+ p->ip6h = (IPV6Hdr *)GET_PKT_DATA(p);
+ IPV6_SET_RAW_VER(p->ip6h, 6);
+ /* Fragmentation header. */
+ IPV6FragHdr *fh = (IPV6FragHdr *)(GET_PKT_DATA(p) + sizeof(IPV6Hdr));
+ fh->ip6fh_nxt = proto;
+ fh->ip6fh_ident = htonl(id);
+ fh->ip6fh_offlg = htons((off << 3) | mf);
+
+ DecodeIPV6FragHeader(p, (uint8_t *)fh, 8, 8 + content_len, 0);
+
+ PacketCopyDataOffset(p, sizeof(IPV6Hdr) + sizeof(IPV6FragHdr), content, content_len);
+ SET_PKT_LEN(p, sizeof(IPV6Hdr) + sizeof(IPV6FragHdr) + content_len);
+
+ p->ip6h->s_ip6_plen = htons(sizeof(IPV6FragHdr) + content_len);
+
+ SET_IPV6_SRC_ADDR(p, &p->src);
+ SET_IPV6_DST_ADDR(p, &p->dst);
+
+ /* Self test. */
+ if (IPV6_GET_VER(p) != 6)
+ goto error;
+ if (IPV6_GET_NH(p) != 44)
+ goto error;
+ if (IPV6_GET_PLEN(p) != sizeof(IPV6FragHdr) + content_len)
+ goto error;
+
+ return p;
+error:
+ if (p != NULL)
+ SCFree(p);
+ return NULL;
+}
+
/**
* Test the simplest possible re-assembly scenario. All packet in
* order and no overlaps.
FAIL_IF(IPV4_GET_IPLEN(reassembled) != 20 + 192);
FAIL_IF(expected_len != 192);
- FAIL_IF(memcmp(GET_PKT_DATA(reassembled) + 20, expected, expected_len) != 0);
+ if (memcmp(expected, GET_PKT_DATA(reassembled) + 20, expected_len) != 0) {
+ printf("Expected:\n");
+ PrintRawDataFp(stdout, expected, expected_len);
+ printf("Got:\n");
+ PrintRawDataFp(stdout, GET_PKT_DATA(reassembled) + 20, GET_PKT_LEN(reassembled) - 20);
+ FAIL;
+ }
SCFree(reassembled);
/* Make sure all frags were returned back to the pool. */
#define D_10 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'
#define D_11 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q'
-static int
-DefragSturgesNovakBsdTest(void)
+static int DefragSturgesNovakBsdTest(void)
{
/* Expected data. */
uint8_t expected[] = {
D_11,
};
- FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_BSD, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_BSD, expected, sizeof(expected)));
PASS;
}
D_11,
};
- FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_LINUX, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_LINUX, expected, sizeof(expected)));
PASS;
}
D_11,
};
- FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_WINDOWS, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_WINDOWS, expected, sizeof(expected)));
PASS;
}
D_11,
};
- FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_SOLARIS, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_SOLARIS, expected, sizeof(expected)));
PASS;
}
D_11,
};
- FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_FIRST, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_FIRST, expected, sizeof(expected)));
PASS;
}
return DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_FIRST, expected, sizeof(expected));
}
-static int
-DefragSturgesNovakLastTest(void)
+static int DefragSturgesNovakLastTest(void)
{
/* Expected data. */
uint8_t expected[] = {
D_11,
};
- FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_LAST, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_LAST, expected, sizeof(expected)));
PASS;
}
PASS;
}
+/**
+ * | 0 | 8 | 16 | 24 | 32 |
+ * |----------|----------|----------|----------|----------|
+ * | AAAAAAAA | AAAAAAAA |
+ * | | BBBBBBBB | BBBBBBBB | | |
+ * | | | CCCCCCCC | CCCCCCCC | |
+ * | DDDDDDDD | | | | |
+ *
+ * | DDDDDDDD | BBBBBBBB | BBBBBBBB | CCCCCCCC | AAAAAAAA |
+ */
static int DefragBsdFragmentAfterNoMfIpv4Test(void)
{
DefragInit();
PASS;
}
+static int DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[4];
+
+ /* Packet 1: off=16, mf=1 */
+ packets[0] = BuildIpv4TestPacketWithContent(
+ IPPROTO_ICMP, 6, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);
+
+ /* Packet 2: off=8, mf=1 */
+ packets[1] = BuildIpv4TestPacketWithContent(
+ IPPROTO_ICMP, 6, 8 >> 3, 1, (uint8_t *)"AACCBBDDAACCDDBB", 16);
+
+ /* Packet 3: off=0, mf=1: IP and ICMP header. */
+ packets[2] = BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 6, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);
+
+ /* Packet 4: off=8, mf=1 */
+ packets[3] =
+ BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 6, 32 >> 3, 0, (uint8_t *)"DDCCBBAA", 8);
+
+ Packet *r = Defrag(NULL, NULL, packets[0]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[1]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[2]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[3]);
+ FAIL_IF_NULL(r);
+
+ // clang-format off
+ const uint8_t expected[] = {
+ // AACCBBDD
+ // AACCDDBB
+ // AABBDDCC
+ // DDCCBBAA
+ 'A', 'A', 'C', 'C', 'B', 'B', 'D', 'D',
+ 'A', 'A', 'C', 'C', 'D', 'D', 'B', 'B',
+ 'A', 'A', 'B', 'B', 'D', 'D', 'C', 'C',
+ 'D', 'D', 'C', 'C', 'B', 'B', 'A', 'A',
+ };
+ // clang-format on
+
+ FAIL_IF(memcmp(expected, GET_PKT_DATA(r) + 20 + 8, sizeof(expected)) != 0);
+
+ DefragDestroy();
+ PASS;
+}
+
+static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[4];
+
+ /* Packet 1: off=16, mf=1 */
+ packets[0] = BuildIpv6TestPacketWithContent(
+ IPPROTO_ICMP, 6, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);
+
+ /* Packet 2: off=8, mf=1 */
+ packets[1] = BuildIpv6TestPacketWithContent(
+ IPPROTO_ICMP, 6, 8 >> 3, 1, (uint8_t *)"AACCBBDDAACCDDBB", 16);
+
+ /* Packet 3: off=0, mf=1: IP and ICMP header. */
+ packets[2] = BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 6, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);
+
+ /* Packet 4: off=8, mf=1 */
+ packets[3] =
+ BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 6, 32 >> 3, 0, (uint8_t *)"DDCCBBAA", 8);
+
+ Packet *r = Defrag(NULL, NULL, packets[0]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[1]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[2]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[3]);
+ FAIL_IF_NULL(r);
+
+ // clang-format off
+ const uint8_t expected[] = {
+ // AACCBBDD
+ // AACCDDBB
+ // AABBDDCC
+ // DDCCBBAA
+ 'A', 'A', 'C', 'C', 'B', 'B', 'D', 'D',
+ 'A', 'A', 'C', 'C', 'D', 'D', 'B', 'B',
+ 'A', 'A', 'B', 'B', 'D', 'D', 'C', 'C',
+ 'D', 'D', 'C', 'C', 'B', 'B', 'A', 'A',
+ };
+ // clang-format on
+
+ FAIL_IF(memcmp(expected, GET_PKT_DATA(r) + 40 + 8, sizeof(expected)) != 0);
+
+ DefragDestroy();
+ PASS;
+}
+
+/**
+ * #### Input
+ *
+ * | 96 (0) | 104 (8) | 112 (16) | 120 (24) |
+ * |----------|----------|----------|----------|
+ * | | EEEEEEEE | EEEEEEEE | EEEEEEEE |
+ * | MMMMMMMM | MMMMMMMM | MMMMMMMM | |
+ *
+ * #### Expected Output
+ *
+ * | MMMMMMMM | MMMMMMMM | MMMMMMMM | EEEEEEEE |
+ */
+static int DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[2];
+
+ packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 8 >> 3, 0, 'E', 24);
+ packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'M', 24);
+
+ Packet *r = Defrag(NULL, NULL, packets[0]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[1]);
+ FAIL_IF_NULL(r);
+
+ // clang-format off
+ const uint8_t expected[] = {
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E',
+ };
+ // clang-format on
+
+ if (memcmp(expected, GET_PKT_DATA(r) + 20, sizeof(expected)) != 0) {
+ printf("Expected:\n");
+ PrintRawDataFp(stdout, expected, sizeof(expected));
+ printf("Got:\n");
+ PrintRawDataFp(stdout, GET_PKT_DATA(r) + 20, GET_PKT_LEN(r) - 20);
+ FAIL;
+ }
+
+ PASS;
+}
+
+static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[2];
+
+ packets[0] = BuildIpv6TestPacket(IPPROTO_ICMP, 1, 8 >> 3, 0, 'E', 24);
+ packets[1] = BuildIpv6TestPacket(IPPROTO_ICMP, 1, 0, 1, 'M', 24);
+
+ Packet *r = Defrag(NULL, NULL, packets[0]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[1]);
+ FAIL_IF_NULL(r);
+
+ // clang-format off
+ const uint8_t expected[] = {
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E',
+ };
+ // clang-format on
+
+ if (memcmp(expected, GET_PKT_DATA(r) + 40, sizeof(expected)) != 0) {
+ printf("Expected:\n");
+ PrintRawDataFp(stdout, expected, sizeof(expected));
+ printf("Got:\n");
+ PrintRawDataFp(stdout, GET_PKT_DATA(r) + 40, GET_PKT_LEN(r) - 40);
+ FAIL;
+ }
+
+ PASS;
+}
+
#endif /* UNITTESTS */
void DefragRegisterTests(void)
UtRegisterTest("DefragInOrderSimpleTest", DefragInOrderSimpleTest);
UtRegisterTest("DefragReverseSimpleTest", DefragReverseSimpleTest);
UtRegisterTest("DefragSturgesNovakBsdTest", DefragSturgesNovakBsdTest);
- UtRegisterTest("DefragSturgesNovakLinuxIpv4Test",
- DefragSturgesNovakLinuxIpv4Test);
- UtRegisterTest("DefragSturgesNovakWindowsIpv4Test",
- DefragSturgesNovakWindowsIpv4Test);
- UtRegisterTest("DefragSturgesNovakSolarisTest",
- DefragSturgesNovakSolarisTest);
+ UtRegisterTest("DefragSturgesNovakLinuxIpv4Test", DefragSturgesNovakLinuxIpv4Test);
+ UtRegisterTest("DefragSturgesNovakWindowsIpv4Test", DefragSturgesNovakWindowsIpv4Test);
+ UtRegisterTest("DefragSturgesNovakSolarisTest", DefragSturgesNovakSolarisTest);
UtRegisterTest("DefragSturgesNovakFirstTest", DefragSturgesNovakFirstTest);
UtRegisterTest("DefragSturgesNovakLastTest", DefragSturgesNovakLastTest);
UtRegisterTest("DefragBsdFragmentAfterNoMfIpv4Test", DefragBsdFragmentAfterNoMfIpv4Test);
UtRegisterTest("DefragBsdFragmentAfterNoMfIpv6Test", DefragBsdFragmentAfterNoMfIpv6Test);
+ UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test",
+ DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test);
+ UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test",
+ DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test);
+ UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2",
+ DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2);
+ UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2",
+ DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2);
#endif /* UNITTESTS */
}