/* check if the 'check' timestamp is not before the creation ts.
* This can happen due to the async nature of the host timeout
* code that also calls this code from a management thread. */
- if (((uint32_t)tv->tv_sec < tmp->tv_sec1) || (tv->tv_sec - tmp->tv_sec1) <= tmp->seconds) {
+ struct timeval entry = TimevalWithSeconds(&tmp->tv1, (time_t)tmp->seconds);
+ if (TimevalEarlier(tv, &entry)) {
prev = tmp;
tmp = tmp->next;
continue;
* \retval int 1 if threshold reached for this entry
*
*/
-static int IsThresholdReached(DetectThresholdEntry* lookup_tsh, const DetectThresholdData *td, uint32_t packet_time)
+static int IsThresholdReached(DetectThresholdEntry* lookup_tsh, const DetectThresholdData *td, struct timeval packet_time)
{
int ret = 0;
/* Check if we have a timeout enabled, if so,
* we still matching (and enabling the new_action) */
if (lookup_tsh->tv_timeout != 0) {
- if ((packet_time - lookup_tsh->tv_timeout) > td->timeout) {
+ if ((packet_time.tv_sec - lookup_tsh->tv_timeout) > td->timeout) {
/* Ok, we are done, timeout reached */
lookup_tsh->tv_timeout = 0;
}
}
else {
/* Update the matching state with the timeout interval */
- if ((packet_time - lookup_tsh->tv_sec1) < td->seconds) {
+ struct timeval entry = TimevalWithSeconds(&lookup_tsh->tv1, (time_t)td->seconds);
+ if (TimevalEarlier(&packet_time, &entry)) {
lookup_tsh->current_count++;
if (lookup_tsh->current_count > td->count) {
/* Then we must enable the new action by setting a
* timeout */
- lookup_tsh->tv_timeout = packet_time;
+ lookup_tsh->tv_timeout = packet_time.tv_sec;
ret = 1;
}
- }
- else {
- lookup_tsh->tv_sec1 = packet_time;
+ } else {
+ lookup_tsh->tv1 = packet_time;
lookup_tsh->current_count = 1;
}
} /* else - if (lookup_tsh->tv_timeout != 0) */
return ret;
}
-static void AddEntryToHostStorage(Host *h, DetectThresholdEntry *e, uint32_t packet_time)
+static void AddEntryToHostStorage(Host *h, DetectThresholdEntry *e, struct timeval packet_time)
{
if (h && e) {
e->current_count = 1;
- e->tv_sec1 = packet_time;
+ e->tv1 = packet_time;
e->tv_timeout = 0;
e->next = HostGetStorageById(h, host_threshold_id);
HostSetStorageById(h, host_threshold_id, e);
}
}
-static void AddEntryToIPPairStorage(IPPair *pair, DetectThresholdEntry *e, uint32_t packet_time)
+static void AddEntryToIPPairStorage(IPPair *pair, DetectThresholdEntry *e, struct timeval packet_time)
{
if (pair && e) {
e->current_count = 1;
- e->tv_sec1 = packet_time;
+ e->tv1 = packet_time;
e->tv_timeout = 0;
e->next = IPPairGetStorageById(pair, ippair_threshold_id);
IPPairSetStorageById(pair, ippair_threshold_id, e);
{
SCLogDebug("rate_filter");
ret = 1;
- if (lookup_tsh && IsThresholdReached(lookup_tsh, td, p->ts.tv_sec)) {
+ if (lookup_tsh && IsThresholdReached(lookup_tsh, td, p->ts)) {
RateFilterSetAction(p, pa, td->new_action);
} else if (!lookup_tsh) {
DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, sid, gid);
- AddEntryToIPPairStorage(pair, e, p->ts.tv_sec);
+ AddEntryToIPPairStorage(pair, e, p->ts);
}
break;
}
SCLogDebug("limit");
if (lookup_tsh != NULL) {
- if ((p->ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) {
+ struct timeval entry = TimevalWithSeconds(&lookup_tsh->tv1, (time_t)td->seconds);
+ if (TimevalEarlier(&p->ts, &entry)) {
lookup_tsh->current_count++;
if (lookup_tsh->current_count <= td->count) {
} else {
ret = 2;
}
- } else {
- lookup_tsh->tv_sec1 = p->ts.tv_sec;
+ } else {
+ lookup_tsh->tv1 = p->ts;
lookup_tsh->current_count = 1;
ret = 1;
break;
}
- e->tv_sec1 = p->ts.tv_sec;
+ e->tv1 = p->ts;
e->current_count = 1;
ret = 1;
SCLogDebug("threshold");
if (lookup_tsh != NULL) {
- if ((p->ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) {
+ struct timeval entry = TimevalWithSeconds(&lookup_tsh->tv1, (time_t)td->seconds);
+ if (TimevalEarlier(&p->ts, &entry)) {
lookup_tsh->current_count++;
if (lookup_tsh->current_count >= td->count) {
lookup_tsh->current_count = 0;
}
} else {
- lookup_tsh->tv_sec1 = p->ts.tv_sec;
+ lookup_tsh->tv1 = p->ts;
lookup_tsh->current_count = 1;
}
} else {
}
e->current_count = 1;
- e->tv_sec1 = p->ts.tv_sec;
+ e->tv1 = p->ts;
e->next = HostGetStorageById(h, host_threshold_id);
HostSetStorageById(h, host_threshold_id, e);
SCLogDebug("both");
if (lookup_tsh != NULL) {
- if ((p->ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) {
+ struct timeval entry = TimevalWithSeconds(&lookup_tsh->tv1, (time_t)td->seconds);
+ if (TimevalEarlier(&p->ts, &entry)) {
/* within time limit */
lookup_tsh->current_count++;
}
} else {
/* expired, so reset */
- lookup_tsh->tv_sec1 = p->ts.tv_sec;
+ lookup_tsh->tv1 = p->ts;
lookup_tsh->current_count = 1;
/* if we have a limit of 1, this is a match */
}
e->current_count = 1;
- e->tv_sec1 = p->ts.tv_sec;
+ e->tv1 = p->ts;
e->next = HostGetStorageById(h, host_threshold_id);
HostSetStorageById(h, host_threshold_id, e);
SCLogDebug("detection_filter");
if (lookup_tsh != NULL) {
- long double time_diff = ((p->ts.tv_sec + p->ts.tv_usec/1000000.0) -
- (lookup_tsh->tv_sec1 + lookup_tsh->tv_usec1/1000000.0));
-
- if (time_diff < td->seconds) {
+ struct timeval entry = TimevalWithSeconds(&lookup_tsh->tv1, (time_t)td->seconds);
+ if (TimevalEarlier(&p->ts, &entry)) {
/* within timeout */
lookup_tsh->current_count++;
}
} else {
/* expired, reset */
-
- lookup_tsh->tv_sec1 = p->ts.tv_sec;
- lookup_tsh->tv_usec1 = p->ts.tv_usec;
+ lookup_tsh->tv1 = p->ts;
lookup_tsh->current_count = 1;
}
} else {
}
e->current_count = 1;
- e->tv_sec1 = p->ts.tv_sec;
- e->tv_usec1 = p->ts.tv_usec;
+ e->tv1 = p->ts;
e->next = HostGetStorageById(h, host_threshold_id);
HostSetStorageById(h, host_threshold_id, e);
{
SCLogDebug("rate_filter");
ret = 1;
- if (lookup_tsh && IsThresholdReached(lookup_tsh, td, p->ts.tv_sec)) {
+ if (lookup_tsh && IsThresholdReached(lookup_tsh, td, p->ts)) {
RateFilterSetAction(p, pa, td->new_action);
} else if (!lookup_tsh) {
DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, sid, gid);
- AddEntryToHostStorage(h, e, p->ts.tv_sec);
+ AddEntryToHostStorage(h, e, p->ts);
}
break;
}
case TYPE_RATE:
{
ret = 1;
- if (lookup_tsh && IsThresholdReached(lookup_tsh, td, p->ts.tv_sec)) {
+ if (lookup_tsh && IsThresholdReached(lookup_tsh, td, p->ts)) {
RateFilterSetAction(p, pa, td->new_action);
}
else if (!lookup_tsh) {
DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, s->id, s->gid);
if (e != NULL) {
e->current_count = 1;
- e->tv_sec1 = p->ts.tv_sec;
+ e->tv1 = p->ts;
e->tv_timeout = 0;
de_ctx->ths_ctx.th_entry[s->num] = e;
/** \brief intialize a 'struct timespec' from a 'struct timeval'. */
#define FROM_TIMEVAL(timev) { .tv_sec = (timev).tv_sec, .tv_nsec = (timev).tv_usec * 1000 }
-/** \brief compare two 'struct timeval' and return the difference in seconds */
-#define TIMEVAL_DIFF_SEC(tv_new, tv_old) \
- (uint64_t)((((uint64_t)(tv_new).tv_sec * 1000000 + (tv_new).tv_usec) - \
- ((uint64_t)(tv_old).tv_sec * 1000000 + (tv_old).tv_usec)) / \
- 1000000)
+static inline struct timeval TimevalWithSeconds(const struct timeval *ts, const time_t sec_add)
+{
+#ifdef timeradd
+ struct timeval add = { .tv_sec = sec_add, .tv_usec = 0 };
+ struct timeval result;
+ timeradd(ts, &add, &result);
+ return result;
+#else
+ const time_t sec = ts->tv_sec + sec_add;
+ struct timeval result = { .tv_sec = sec, .tv_usec = ts->tv_usec };
+ return result;
+#endif
+}
/** \brief compare two 'struct timeval' and return if the first is earlier than the second */
-#define TIMEVAL_EARLIER(tv_first, tv_second) \
- (((tv_first).tv_sec < (tv_second).tv_sec) || \
- ((tv_first).tv_sec == (tv_second).tv_sec && (tv_first).tv_usec < (tv_second).tv_usec))
+static inline bool TimevalEarlier(struct timeval *first, struct timeval *second)
+{
+ /* from man timercmp on Linux: "Some systems (but not Linux/glibc), have a broken timercmp()
+ * implementation, in which CMP of >=, <=, and == do not work; portable applications can instead
+ * use ... !timercmp(..., >) */
+ return !timercmp(first, second, >);
+}
#ifndef timeradd
#define timeradd(a, b, r) \