Bug #82 ยป 0001-Issue-82-fragment-counters.patch
src/decode-ipv4.c | ||
---|---|---|
/* If a fragment, pass off for re-assembly. */
|
||
if (IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1) {
|
||
Packet *rp = Defrag(tv, NULL, p);
|
||
Packet *rp = Defrag(tv, dtv, NULL, p);
|
||
if (rp != NULL) {
|
||
/* Got re-assembled packet, re-run through decoder. */
|
||
DecodeIPV4(tv, dtv, rp, rp->pkt, rp->pktlen, pq);
|
src/decode-ipv6.c | ||
---|---|---|
/* Pass to defragger if a fragment. */
|
||
if (IPV6_EXTHDR_ISSET_FH(p)) {
|
||
Packet *rp = Defrag(tv, NULL, p);
|
||
Packet *rp = Defrag(tv, dtv, NULL, p);
|
||
if (rp != NULL) {
|
||
DecodeIPV6(tv, dtv, rp, rp->pkt, rp->pktlen, pq);
|
||
PacketEnqueue(pq, rp);
|
src/decode.c | ||
---|---|---|
dtv->counter_max_pkt_size = SCPerfTVRegisterMaxCounter("decoder.max_pkt_size", tv,
|
||
SC_PERF_TYPE_UINT64, "NULL");
|
||
dtv->counter_defrag_fragments = SCPerfTVRegisterCounter("defrag.fragments",
|
||
tv, SC_PERF_TYPE_UINT64, "NULL");
|
||
dtv->counter_defrag_reassembled =
|
||
SCPerfTVRegisterCounter("defrag.reassembled", tv, SC_PERF_TYPE_UINT64,
|
||
"NULL");
|
||
dtv->counter_defrag_timeouts = SCPerfTVRegisterCounter("defrag.timeouts",
|
||
tv, SC_PERF_TYPE_UINT64, "NULL");
|
||
tv->sc_perf_pca = SCPerfGetAllCountersArray(&tv->sc_perf_pctx);
|
||
SCPerfAddToClubbedTMTable(tv->name, &tv->sc_perf_pctx);
|
||
src/decode.h | ||
---|---|---|
uint16_t counter_pppoe;
|
||
uint16_t counter_avg_pkt_size;
|
||
uint16_t counter_max_pkt_size;
|
||
/** frag stats - defrag runs in the context of the decoder. */
|
||
uint16_t counter_defrag_fragments;
|
||
uint16_t counter_defrag_reassembled;
|
||
uint16_t counter_defrag_timeouts;
|
||
} DecodeThreadVars;
|
||
/* clear key vars so we don't need to call the expensive
|
src/defrag.c | ||
---|---|---|
* \todo Allocate packet buffers from a pool.
|
||
*/
|
||
static Packet *
|
||
DefragInsertFrag(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker,
|
||
Packet *p)
|
||
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc,
|
||
DefragTracker *tracker, Packet *p)
|
||
{
|
||
Packet *r = NULL;
|
||
int ltrim = 0;
|
||
... | ... | |
else if (tracker->af == AF_INET6)
|
||
r = Defrag6Reassemble(tv, dc, tracker, p);
|
||
}
|
||
if (r != NULL && tv != NULL && dtv != NULL) {
|
||
SCPerfCounterIncr(dtv->counter_defrag_reassembled, tv->sc_perf_pca);
|
||
}
|
||
done:
|
||
SCMutexUnlock(&tracker->lock);
|
||
... | ... | |
* \param p Packet that triggered this timeout run, used for timestamp.
|
||
*/
|
||
static void
|
||
DefragTimeoutTracker(DefragContext *dc, Packet *p)
|
||
DefragTimeoutTracker(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc,
|
||
Packet *p)
|
||
{
|
||
struct timeval tv = p->ts;
|
||
struct timeval now = p->ts;
|
||
HashListTableBucket *next = HashListTableGetListHead(dc->frag_table);
|
||
DefragTracker *tracker;
|
||
while (next != NULL) {
|
||
tracker = HashListTableGetListData(next);
|
||
if (timercmp(&tracker->timeout, &tv, <)) {
|
||
if (timercmp(&tracker->timeout, &now, <)) {
|
||
/* Tracker has timeout out. */
|
||
HashListTableRemove(dc->frag_table, tracker, sizeof(tracker));
|
||
DefragTrackerReset(tracker);
|
||
PoolReturn(dc->tracker_pool, tracker);
|
||
if (tv != NULL && dtv != NULL) {
|
||
SCPerfCounterIncr(dtv->counter_defrag_timeouts,
|
||
tv->sc_perf_pca);
|
||
}
|
||
return;
|
||
}
|
||
... | ... | |
}
|
||
static DefragTracker *
|
||
DefragGetTracker(DefragContext *dc, DefragTracker *lookup_key, Packet *p)
|
||
DefragGetTracker(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc,
|
||
DefragTracker *lookup_key, Packet *p)
|
||
{
|
||
DefragTracker *tracker;
|
||
... | ... | |
tracker = PoolGet(dc->tracker_pool);
|
||
if (tracker == NULL) {
|
||
/* Timeout trackers and try again. */
|
||
DefragTimeoutTracker(dc, p);
|
||
DefragTimeoutTracker(tv, dtv, dc, p);
|
||
tracker = PoolGet(dc->tracker_pool);
|
||
}
|
||
SCMutexUnlock(&dc->tracker_pool_lock);
|
||
... | ... | |
* NULL is returned.
|
||
*/
|
||
Packet *
|
||
Defrag(ThreadVars *tv, DefragContext *dc, Packet *p)
|
||
Defrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, Packet *p)
|
||
{
|
||
uint16_t frag_offset;
|
||
uint8_t more_frags;
|
||
... | ... | |
return NULL;
|
||
}
|
||
if (tv != NULL && dtv != NULL) {
|
||
SCPerfCounterIncr(dtv->counter_defrag_fragments, tv->sc_perf_pca);
|
||
}
|
||
/* Create a lookup key. */
|
||
lookup.af = af;
|
||
lookup.id = id;
|
||
lookup.src_addr = p->src;
|
||
lookup.dst_addr = p->dst;
|
||
tracker = DefragGetTracker(dc, &lookup, p);
|
||
tracker = DefragGetTracker(tv, dtv, dc, &lookup, p);
|
||
if (tracker == NULL)
|
||
return NULL;
|
||
return DefragInsertFrag(tv, dc, tracker, p);
|
||
return DefragInsertFrag(tv, dtv, dc, tracker, p);
|
||
}
|
||
void
|
||
... | ... | |
if (p3 == NULL)
|
||
goto end;
|
||
if (Defrag(NULL, dc, p1) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p1) != NULL)
|
||
goto end;
|
||
if (Defrag(NULL, dc, p2) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p2) != NULL)
|
||
goto end;
|
||
reassembled = Defrag(NULL, dc, p3);
|
||
reassembled = Defrag(NULL, NULL, dc, p3);
|
||
if (reassembled == NULL)
|
||
goto end;
|
||
... | ... | |
if (p3 == NULL)
|
||
goto end;
|
||
if (Defrag(NULL, dc, p3) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p3) != NULL)
|
||
goto end;
|
||
if (Defrag(NULL, dc, p2) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p2) != NULL)
|
||
goto end;
|
||
reassembled = Defrag(NULL, dc, p1);
|
||
reassembled = Defrag(NULL, NULL, dc, p1);
|
||
if (reassembled == NULL)
|
||
goto end;
|
||
... | ... | |
if (p3 == NULL)
|
||
goto end;
|
||
if (Defrag(NULL, dc, p1) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p1) != NULL)
|
||
goto end;
|
||
if (Defrag(NULL, dc, p2) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p2) != NULL)
|
||
goto end;
|
||
reassembled = Defrag(NULL, dc, p3);
|
||
reassembled = Defrag(NULL, NULL, dc, p3);
|
||
if (reassembled == NULL)
|
||
goto end;
|
||
... | ... | |
if (p3 == NULL)
|
||
goto end;
|
||
if (Defrag(NULL, dc, p3) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p3) != NULL)
|
||
goto end;
|
||
if (Defrag(NULL, dc, p2) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p2) != NULL)
|
||
goto end;
|
||
reassembled = Defrag(NULL, dc, p1);
|
||
reassembled = Defrag(NULL, NULL, dc, p1);
|
||
if (reassembled == NULL)
|
||
goto end;
|
||
... | ... | |
/* Send all but the last. */
|
||
for (i = 0; i < 16; i++) {
|
||
Packet *tp = Defrag(NULL, dc, packets[i]);
|
||
Packet *tp = Defrag(NULL, NULL, dc, packets[i]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
... | ... | |
}
|
||
/* And now the last one. */
|
||
Packet *reassembled = Defrag(NULL, dc, packets[16]);
|
||
Packet *reassembled = Defrag(NULL, NULL, dc, packets[16]);
|
||
if (reassembled == NULL)
|
||
goto end;
|
||
... | ... | |
/* Send all but the last. */
|
||
Packet *tp;
|
||
tp = Defrag(NULL, dc, packets[0]);
|
||
tp = Defrag(NULL, NULL, dc, packets[0]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[1]);
|
||
tp = Defrag(NULL, NULL, dc, packets[1]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[2]);
|
||
tp = Defrag(NULL, NULL, dc, packets[2]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[3]);
|
||
tp = Defrag(NULL, NULL, dc, packets[3]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[4]);
|
||
tp = Defrag(NULL, NULL, dc, packets[4]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[5]);
|
||
tp = Defrag(NULL, NULL, dc, packets[5]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[6]);
|
||
tp = Defrag(NULL, NULL, dc, packets[6]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[7]);
|
||
tp = Defrag(NULL, NULL, dc, packets[7]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[8]);
|
||
tp = Defrag(NULL, NULL, dc, packets[8]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[9]);
|
||
tp = Defrag(NULL, NULL, dc, packets[9]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[10]);
|
||
tp = Defrag(NULL, NULL, dc, packets[10]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[11]);
|
||
tp = Defrag(NULL, NULL, dc, packets[11]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[12]);
|
||
tp = Defrag(NULL, NULL, dc, packets[12]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[13]);
|
||
tp = Defrag(NULL, NULL, dc, packets[13]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[14]);
|
||
tp = Defrag(NULL, NULL, dc, packets[14]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
tp = Defrag(NULL, dc, packets[15]);
|
||
tp = Defrag(NULL, NULL, dc, packets[15]);
|
||
if (tp != NULL) {
|
||
free(tp);
|
||
goto end;
|
||
}
|
||
/* And now the last one. */
|
||
Packet *reassembled = Defrag(NULL, dc, packets[16]);
|
||
Packet *reassembled = Defrag(NULL, NULL, dc, packets[16]);
|
||
if (reassembled == NULL)
|
||
goto end;
|
||
if (memcmp(reassembled->pkt + 40, expected, expected_len) != 0)
|
||
... | ... | |
if (p == NULL)
|
||
goto end;
|
||
Packet *tp = Defrag(NULL, dc, p);
|
||
Packet *tp = Defrag(NULL, NULL, dc, p);
|
||
free(p);
|
||
... | ... | |
goto end;
|
||
p->ts.tv_sec += dc->timeout;
|
||
Packet *tp = Defrag(NULL, dc, p);
|
||
Packet *tp = Defrag(NULL, NULL, dc, p);
|
||
free(p);
|
||
... | ... | |
goto end;
|
||
/* We do not expect a packet returned. */
|
||
if (Defrag(NULL, dc, p) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p) != NULL)
|
||
goto end;
|
||
/* The fragment should have been ignored so no fragments should
|
||
... | ... | |
goto end;
|
||
/* We do not expect a packet returned. */
|
||
if (Defrag(NULL, dc, p) != NULL)
|
||
if (Defrag(NULL, NULL, dc, p) != NULL)
|
||
goto end;
|
||
/* The fragment should have been ignored so no fragments should have
|
src/defrag.h | ||
---|---|---|
typedef struct _DefragContext DefragContext;
|
||
void DefragInit(void);
|
||
Packet *Defrag(ThreadVars *, DefragContext *, Packet *);
|
||
Packet *Defrag(ThreadVars *, DecodeThreadVars *, DefragContext *, Packet *);
|
||
void DefragRegisterTests(void);
|
||
#endif /* __DEFRAG_H__ */
|