suricata
util-time.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2020 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 * \author Ken Steele <suricata@tilera.com>
23 *
24 * Time keeping for offline (non-live) packet handling (pcap files).
25 * And time string generation for alerts.
26 */
27
28/* Real time vs offline time
29 *
30 * When we run on live traffic, time handling is simple. Packets have a
31 * timestamp set by the capture method. Management threads can simply
32 * use 'gettimeofday' to know the current time. There should never be
33 * any serious gap between the two.
34 *
35 * In offline mode, things are dramatically different. Here we try to keep
36 * the time from the pcap, which means that if the packets are in 2011 the
37 * log output should also reflect this. Multiple issues:
38 * 1. merged pcaps might have huge time jumps or time going backward
39 * 2. slowly recorded pcaps may be processed much faster than their 'realtime'
40 * 3. management threads need a concept of what the 'current' time is for
41 * enforcing timeouts
42 * 4. due to (1) individual threads may have very different views on what
43 * the current time is. E.g. T1 processed packet 1 with TS X, while T2
44 * at the very same time processes packet 2 with TS X+100000s.
45 *
46 * In offline mode we keep the timestamp per thread. If a management thread
47 * needs current time, it will get the minimum of the threads' values. This
48 * is to avoid the problem that T2s time value might already trigger a flow
49 * timeout as the flow lastts + 100000s is almost certainly meaning the flow
50 * would be considered timed out.
51 */
52
53#ifdef OS_WIN32
54/* for MinGW we need to set _POSIX_C_SOURCE before including
55 * sys/time.h. */
56#ifndef _POSIX_C_SOURCE
57#define _POSIX_C_SOURCE 200809L
58#endif
59#endif
60
61#include "suricata-common.h"
62#include "suricata.h"
63#include "detect.h"
64#include "threads.h"
65#include "tm-threads.h"
66#include "util-debug.h"
67#include "util-time.h"
68
69#ifdef UNITTESTS
70static struct timeval current_time = { 0, 0 };
71#endif
72//static SCMutex current_time_mutex = SCMUTEX_INITIALIZER;
73static SCSpinlock current_time_spinlock;
74static bool live_time_tracking = true;
75
76struct tm *SCLocalTime(time_t timep, struct tm *result);
77struct tm *SCUtcTime(time_t timep, struct tm *result);
78
79void TimeInit(void)
80{
81 SCSpinInit(&current_time_spinlock, 0);
82
83 /* Initialize Time Zone settings. */
84 tzset();
85}
86
87void TimeDeinit(void)
88{
89 SCSpinDestroy(&current_time_spinlock);
90}
91
93{
94 if (live_time_tracking)
95 return true;
97}
98
100{
101 live_time_tracking = true;
102 SCLogDebug("live time mode enabled");
103}
104
106{
107 live_time_tracking = false;
108 SCLogDebug("offline time mode enabled");
109}
110
112{
113 return live_time_tracking;
114}
115
116void TimeSetByThread(const int thread_id, SCTime_t tv)
117{
118 if (live_time_tracking)
119 return;
120
122}
123
124#ifdef UNITTESTS
126{
127 if (live_time_tracking)
128 return;
129
130 SCSpinLock(&current_time_spinlock);
131 SCTIME_TO_TIMEVAL(&current_time, ts);
132
133 SCLogDebug("time set to %" PRIuMAX " sec, %" PRIuMAX " usec",
134 (uintmax_t)current_time.tv_sec, (uintmax_t)current_time.tv_usec);
135
136 SCSpinUnlock(&current_time_spinlock);
137}
138
139/** \brief set the time to "gettimeofday" meant for testing */
141{
142 struct timeval tv;
143 memset(&tv, 0x00, sizeof(tv));
144
145 gettimeofday(&tv, NULL);
146
148 TimeSet(ts);
149}
150#endif
151
153{
154 struct timeval tv = { 0 };
155 if (live_time_tracking) {
156 gettimeofday(&tv, NULL);
157 } else {
158#ifdef UNITTESTS
160 SCSpinLock(&current_time_spinlock);
161 tv.tv_sec = current_time.tv_sec;
162 tv.tv_usec = current_time.tv_usec;
163 SCSpinUnlock(&current_time_spinlock);
164 } else {
165#endif
167#ifdef UNITTESTS
168 }
169#endif
170 }
171
172 SCLogDebug("time we got is %" PRIuMAX " sec, %" PRIuMAX " usec", (uintmax_t)tv.tv_sec,
173 (uintmax_t)tv.tv_usec);
174 return SCTIME_FROM_TIMEVAL(&tv);
175}
176
177#ifdef UNITTESTS
178/** \brief increment the time in the engine
179 * \param tv_sec seconds to increment the time with */
180void TimeSetIncrementTime(uint32_t tv_sec)
181{
182 SCTime_t ts = TimeGet();
183
184 ts = SCTIME_ADD_SECS(ts, tv_sec);
185
186 TimeSet(ts);
187}
188#endif
189
190#ifdef OS_WIN32
191/** \internal
192 * \brief wrapper around strftime on Windows to provide output
193 * compatible with posix %z
194 */
195static inline void WinStrftime(const SCTime_t ts, const struct tm *t, char *str, size_t size)
196{
197 char time_fmt[64] = { 0 };
198 char tz[6] = { 0 };
199 const long int tzdiff = -_timezone;
200 const int h = abs(_timezone) / 3600 + _daylight;
201 const int m = (abs(_timezone) % 3600) / 60;
202 snprintf(tz, sizeof(tz), "%c%02d%02d", tzdiff < 0 ? '-' : '+', h, m);
203 strftime(time_fmt, sizeof(time_fmt), "%Y-%m-%dT%H:%M:%S.%%06u", t);
204 snprintf(str, size, time_fmt, SCTIME_USECS(ts));
205 strlcat(str, tz, size); // append our timezone
206}
207#endif
208
209void CreateIsoTimeString(const SCTime_t ts, char *str, size_t size)
210{
211 time_t time = SCTIME_SECS(ts);
212 struct tm local_tm;
213 memset(&local_tm, 0, sizeof(local_tm));
214 struct tm *t = (struct tm*)SCLocalTime(time, &local_tm);
215
216 if (likely(t != NULL)) {
217#ifdef OS_WIN32
218 WinStrftime(ts, t, str, size);
219#else
220 char time_fmt[64] = { 0 };
221 int64_t usec = SCTIME_USECS(ts);
222 strftime(time_fmt, sizeof(time_fmt), "%Y-%m-%dT%H:%M:%S.%%06" PRIi64 "%z", t);
223 snprintf(str, size, time_fmt, usec);
224#endif
225 } else {
226 snprintf(str, size, "ts-error");
227 }
228}
229
230void CreateUtcIsoTimeString(const SCTime_t ts, char *str, size_t size)
231{
232 time_t time = SCTIME_SECS(ts);
233 struct tm local_tm;
234 memset(&local_tm, 0, sizeof(local_tm));
235 struct tm *t = (struct tm*)SCUtcTime(time, &local_tm);
236
237 if (likely(t != NULL)) {
238 char time_fmt[64] = { 0 };
239 strftime(time_fmt, sizeof(time_fmt), "%Y-%m-%dT%H:%M:%S", t);
240 snprintf(str, size, time_fmt, SCTIME_USECS(ts));
241 } else {
242 snprintf(str, size, "ts-error");
243 }
244}
245
246void CreateFormattedTimeString (const struct tm *t, const char *fmt, char *str, size_t size)
247{
248 if (likely(t != NULL)) {
249 strftime(str, size, fmt, t);
250 } else {
251 snprintf(str, size, "ts-error");
252 }
253}
254
255struct tm *SCUtcTime(time_t timep, struct tm *result)
256{
257 return gmtime_r(&timep, result);
258}
259
260/*
261 * Time Caching code
262 */
263
264#ifndef TLS
265/* OpenBSD does not support thread_local, so don't use time caching on BSD
266 */
267struct tm *SCLocalTime(time_t timep, struct tm *result)
268{
269 return localtime_r(&timep, result);
270}
271
272void CreateTimeString(const SCTime_t ts, char *str, size_t size)
273{
274 time_t time = SCTIME_SECS(ts);
275 struct tm local_tm;
276 struct tm *t = (struct tm*)SCLocalTime(time, &local_tm);
277
278 if (likely(t != NULL)) {
279 snprintf(str, size, "%02d/%02d/%02d-%02d:%02d:%02d.%06u", t->tm_mon + 1, t->tm_mday,
280 t->tm_year + 1900, t->tm_hour, t->tm_min, t->tm_sec, (uint32_t)SCTIME_USECS(ts));
281 } else {
282 snprintf(str, size, "ts-error");
283 }
284}
285
286#else
287
288/* On systems supporting thread_local, use Per-thread values for caching
289 * in CreateTimeString */
290
291/* The maximum possible length of the time string.
292 * "%02d/%02d/%02d-%02d:%02d:%02d.%06u"
293 * Or "01/01/2013-15:42:21.123456", which is 26, so round up to 32. */
294#define MAX_LOCAL_TIME_STRING 32
295
296static thread_local int mru_time_slot; /* Most recently used cached value */
297static thread_local time_t last_local_time[2];
298static thread_local short int cached_local_time_len[2];
299static thread_local char cached_local_time[2][MAX_LOCAL_TIME_STRING];
300
301/* Per-thread values for caching SCLocalTime() These cached values are
302 * independent from the CreateTimeString cached values. */
303static thread_local int mru_tm_slot; /* Most recently used local tm */
304static thread_local time_t cached_minute_start[2];
305static thread_local struct tm cached_local_tm[2];
306
307/** \brief Convert time_t into Year, month, day, hour and minutes.
308 * \param timep Time in seconds since defined date.
309 * \param result The structure into which the broken down time it put.
310 *
311 * To convert a time in seconds into year, month, day, hours, minutes
312 * and seconds, call localtime_r(), which uses the current time zone
313 * to compute these values. Note, glibc's localtime_r() acquires a lock
314 * each time it is called, which limits parallelism. To call
315 * localtime_r() less often, the values returned are cached for the
316 * current and previous minute and then seconds are adjusted to
317 * compute the returned result. This is valid as long as the
318 * difference between the start of the current minute and the current
319 * time is less than 60 seconds. Once the minute value changes, all
320 * the other values could change.
321 *
322 * Two values are cached to prevent thrashing when changing from one
323 * minute to the next. The two cached minutes are independent and are
324 * not required to be M and M+1. If more than two minutes are
325 * requested, the least-recently-used cached value is updated more
326 * often, the results are still correct, but performance will be closer
327 * to previous performance.
328 */
329struct tm *SCLocalTime(time_t timep, struct tm *result)
330{
331 /* Only get a new local time when the time crosses into a new
332 * minute. */
333 int mru = mru_tm_slot;
334 int lru = 1 - mru;
335 int mru_seconds = timep - cached_minute_start[mru];
336 int lru_seconds = timep - cached_minute_start[lru];
337 int new_seconds;
338 if (cached_minute_start[mru]==0 && cached_minute_start[lru]==0) {
339 localtime_r(&timep, &cached_local_tm[lru]);
340 /* Subtract seconds to get back to the start of the minute. */
341 new_seconds = cached_local_tm[lru].tm_sec;
342 cached_minute_start[lru] = timep - new_seconds;
343 mru = lru;
344 mru_tm_slot = mru;
345 } else if (lru_seconds > 0 && (mru_seconds >= 0 && mru_seconds <= 59)) {
346 /* Use most-recently cached time, adjusting the seconds. */
347 new_seconds = mru_seconds;
348 } else if (mru_seconds > 0 && (lru_seconds >= 0 && lru_seconds <= 59)) {
349 /* Use least-recently cached time, update to most recently used. */
350 new_seconds = lru_seconds;
351 mru = lru;
352 mru_tm_slot = mru;
353 } else {
354 /* Update least-recent cached time. */
355 if (localtime_r(&timep, &cached_local_tm[lru]) == NULL)
356 return NULL;
357 /* Subtract seconds to get back to the start of the minute. */
358 new_seconds = cached_local_tm[lru].tm_sec;
359 cached_minute_start[lru] = timep - new_seconds;
360 mru = lru;
361 mru_tm_slot = mru;
362 }
363 memcpy(result, &cached_local_tm[mru], sizeof(struct tm));
364 result->tm_sec = new_seconds;
365
366 return result;
367}
368
369/* Update the cached time string in cache index N, for the current minute. */
370static int UpdateCachedTime(int n, time_t time)
371{
372 struct tm local_tm;
373 struct tm *t = (struct tm *)SCLocalTime(time, &local_tm);
374 int cached_len = snprintf(cached_local_time[n], MAX_LOCAL_TIME_STRING,
375 "%02d/%02d/%02d-%02d:%02d:",
376 t->tm_mon + 1, t->tm_mday, t->tm_year + 1900,
377 t->tm_hour, t->tm_min);
378 cached_local_time_len[n] = cached_len;
379 /* Store the time of the beginning of the minute. */
380 last_local_time[n] = time - t->tm_sec;
381 mru_time_slot = n;
382
383 return t->tm_sec;
384}
385
386/** \brief Return a formatted string for the provided time.
387 *
388 * Cache the Month/Day/Year - Hours:Min part of the time string for
389 * the current minute. Copy that result into the return string and
390 * then only print the seconds for each call.
391 */
392void CreateTimeString(const SCTime_t ts, char *str, size_t size)
393{
394 time_t time = SCTIME_SECS(ts);
395 int seconds;
396
397 /* Only get a new local time when the time crosses into a new
398 * minute */
399 int mru = mru_time_slot;
400 int lru = 1 - mru;
401 int mru_seconds = time - last_local_time[mru];
402 int lru_seconds = time - last_local_time[lru];
403 if (last_local_time[mru]==0 && last_local_time[lru]==0) {
404 /* First time here, update both caches */
405 UpdateCachedTime(mru, time);
406 seconds = UpdateCachedTime(lru, time);
407 } else if (mru_seconds >= 0 && mru_seconds <= 59) {
408 /* Use most-recently cached time. */
409 seconds = mru_seconds;
410 } else if (lru_seconds >= 0 && lru_seconds <= 59) {
411 /* Use least-recently cached time. Change this slot to Most-recent */
412 seconds = lru_seconds;
413 mru_time_slot = lru;
414 } else {
415 /* Update least-recent cached time. Lock accessing local time
416 * function because it keeps any internal non-spin lock. */
417 seconds = UpdateCachedTime(lru, time);
418 }
419
420 /* Copy the string up to the current minute then print the seconds
421 into the return string buffer. */
422 char *cached_str = cached_local_time[mru_time_slot];
423 int cached_len = cached_local_time_len[mru_time_slot];
424 if (cached_len >= (int)size)
425 cached_len = size;
426 memcpy(str, cached_str, cached_len);
427 snprintf(str + cached_len, size - cached_len, "%02d.%06u", seconds, (uint32_t)SCTIME_USECS(ts));
428}
429
430#endif /* defined(__OpenBSD__) */
431
432/**
433 * \brief Convert broken-down time to seconds since Unix epoch.
434 *
435 * This function is based on: http://www.catb.org/esr/time-programming
436 * (released to the public domain).
437 *
438 * \param tp Pointer to broken-down time.
439 *
440 * \retval Seconds since Unix epoch.
441 */
442time_t SCMkTimeUtc (struct tm *tp)
443{
444 time_t result;
445 long year;
446#define MONTHSPERYEAR 12
447 static const int mdays[MONTHSPERYEAR] =
448 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
449
450 year = 1900 + tp->tm_year + tp->tm_mon / MONTHSPERYEAR;
451 result = (year - 1970) * 365 + mdays[tp->tm_mon % MONTHSPERYEAR];
452 result += (year - 1968) / 4;
453 result -= (year - 1900) / 100;
454 result += (year - 1600) / 400;
455 if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) &&
456 (tp->tm_mon % MONTHSPERYEAR) < 2)
457 result--;
458 result += tp->tm_mday - 1;
459 result *= 24;
460 result += tp->tm_hour;
461 result *= 60;
462 result += tp->tm_min;
463 result *= 60;
464 result += tp->tm_sec;
465#ifndef OS_WIN32
466 if (tp->tm_gmtoff)
467 result -= tp->tm_gmtoff;
468#endif
469 return result;
470}
471
472/**
473 * \brief Parse a date string based on specified patterns.
474 *
475 * This function is based on GNU C library getdate.
476 *
477 * \param string Date string to parse.
478 * \param patterns String array containing patterns.
479 * \param num_patterns Number of patterns to check.
480 * \param tp Pointer to broken-down time.
481 *
482 * \retval 0 on success.
483 * \retval 1 on failure.
484 */
485int SCStringPatternToTime (char *string, const char **patterns, int num_patterns,
486 struct tm *tp)
487{
488 char *result = NULL;
489 int i = 0;
490
491 /* Do the pattern matching */
492 for (i = 0; i < num_patterns; i++)
493 {
494 if (patterns[i] == NULL)
495 continue;
496
497 tp->tm_hour = tp->tm_min = tp->tm_sec = 0;
498 tp->tm_year = tp->tm_mon = tp->tm_mday = tp->tm_wday = INT_MIN;
499 tp->tm_isdst = -1;
500#ifndef OS_WIN32
501 tp->tm_gmtoff = 0;
502 tp->tm_zone = NULL;
503#endif
504 result = strptime(string, patterns[i], tp);
505
506 if (result && *result == '\0')
507 break;
508 }
509
510 /* Return if no patterns matched */
511 if (result == NULL || *result != '\0')
512 return 1;
513
514 /* Return if no date is given */
515 if (tp->tm_year == INT_MIN && tp->tm_mon == INT_MIN &&
516 tp->tm_mday == INT_MIN)
517 return 1;
518
519 /* The first of the month is assumed, if only year and
520 month is given */
521 if (tp->tm_year != INT_MIN && tp->tm_mon != INT_MIN &&
522 tp->tm_mday <= 0)
523 tp->tm_mday = 1;
524
525 return 0;
526}
527
528/**
529 * \brief Convert epoch time to string pattern.
530 *
531 * This function converts epoch time to a string based on a pattern.
532 *
533 * \param epoch Epoch time.
534 * \param pattern String pattern.
535 * \param str Formated string.
536 * \param size Size of allocated string.
537 *
538 * \retval 0 on success.
539 * \retval 1 on failure.
540 */
541int SCTimeToStringPattern (time_t epoch, const char *pattern, char *str, size_t size)
542{
543 struct tm tm;
544 memset(&tm, 0, sizeof(tm));
545 struct tm *tp = (struct tm *)SCLocalTime(epoch, &tm);
546 char buffer[PATH_MAX] = { 0 };
547
548 if (unlikely(tp == NULL)) {
549 return 1;
550 }
551
552 size_t r = strftime(buffer, sizeof(buffer), pattern, tp);
553 if (r == 0) {
554 return 1;
555 }
556
557 strlcpy(str, buffer, size);
558
559 return 0;
560}
561
562/**
563 * \brief Parse string containing time size (1m, 1h, etc).
564 *
565 * \param str String to parse.
566 *
567 * \retval size on success.
568 * \retval 0 on failure.
569 */
570uint64_t SCParseTimeSizeString (const char *str)
571{
572 uint64_t size = 0;
573 uint64_t modifier = 1;
574 char last = str[strlen(str)-1];
575
576 switch (last)
577 {
578 case '0' ... '9':
579 break;
580 /* seconds */
581 case 's':
582 break;
583 /* minutes */
584 case 'm':
585 modifier = 60;
586 break;
587 /* hours */
588 case 'h':
589 modifier = 60 * 60;
590 break;
591 /* days */
592 case 'd':
593 modifier = 60 * 60 * 24;
594 break;
595 /* weeks */
596 case 'w':
597 modifier = 60 * 60 * 24 * 7;
598 break;
599 /* invalid */
600 default:
601 return 0;
602 }
603
604 errno = 0;
605 size = strtoumax(str, NULL, 10);
606 if (errno) {
607 return 0;
608 }
609
610 return (size * modifier);
611}
612
613/**
614 * \brief Get seconds until a time unit changes.
615 *
616 * \param str String containing time type (minute, hour, etc).
617 * \param epoch Epoch time.
618 *
619 * \retval seconds.
620 */
621uint64_t SCGetSecondsUntil (const char *str, time_t epoch)
622{
623 uint64_t seconds = 0;
624 struct tm tm;
625 memset(&tm, 0, sizeof(tm));
626 struct tm *tp = (struct tm *)SCLocalTime(epoch, &tm);
627
628 if (strcmp(str, "minute") == 0)
629 seconds = 60 - tp->tm_sec;
630 else if (strcmp(str, "hour") == 0)
631 seconds = (60 * (60 - tp->tm_min)) + (60 - tp->tm_sec);
632 else if (strcmp(str, "day") == 0)
633 seconds = (3600 * (24 - tp->tm_hour)) + (60 * (60 - tp->tm_min)) +
634 (60 - tp->tm_sec);
635
636 return seconds;
637}
638
639uint64_t SCTimespecAsEpochMillis(const struct timespec* ts)
640{
641 return ts->tv_sec * 1000L + ts->tv_nsec / 1000000L;
642}
643
644uint64_t TimeDifferenceMicros(struct timeval t0, struct timeval t1)
645{
646 return (uint64_t)(t1.tv_sec - t0.tv_sec) * 1000000L + (t1.tv_usec - t1.tv_usec);
647}
SCMutex m
Definition flow-hash.h:6
ThreadVars * tv
uint64_t ts
size_t strlcat(char *, const char *src, size_t siz)
char * strptime(const char *__restrict, const char *__restrict, struct tm *__restrict)
#define str(s)
size_t strlcpy(char *dst, const char *src, size_t siz)
int RunmodeIsUnittests(void)
Definition suricata.c:270
#define SCSpinlock
#define SCSpinInit
#define SCSpinUnlock
#define SCSpinDestroy
#define SCSpinLock
bool TmThreadsTimeSubsysIsReady(void)
void TmThreadsSetThreadTimestamp(const int id, const SCTime_t ts)
void TmThreadsGetMinimalTimestamp(struct timeval *ts)
#define SCLogDebug(...)
Definition util-debug.h:275
#define likely(expr)
#define unlikely(expr)
uint64_t TimeDifferenceMicros(struct timeval t0, struct timeval t1)
Definition util-time.c:644
void TimeInit(void)
Definition util-time.c:79
void TimeSetToCurrentTime(void)
set the time to "gettimeofday" meant for testing
Definition util-time.c:140
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition util-time.c:267
void CreateTimeString(const SCTime_t ts, char *str, size_t size)
Definition util-time.c:272
void TimeSet(SCTime_t ts)
Definition util-time.c:125
#define MONTHSPERYEAR
uint64_t SCTimespecAsEpochMillis(const struct timespec *ts)
Definition util-time.c:639
bool TimeModeIsLive(void)
Definition util-time.c:111
void TimeModeSetLive(void)
Definition util-time.c:99
bool TimeModeIsReady(void)
Definition util-time.c:92
void CreateFormattedTimeString(const struct tm *t, const char *fmt, char *str, size_t size)
Definition util-time.c:246
uint64_t SCParseTimeSizeString(const char *str)
Parse string containing time size (1m, 1h, etc).
Definition util-time.c:570
void TimeSetByThread(const int thread_id, SCTime_t tv)
Definition util-time.c:116
int SCStringPatternToTime(char *string, const char **patterns, int num_patterns, struct tm *tp)
Parse a date string based on specified patterns.
Definition util-time.c:485
int SCTimeToStringPattern(time_t epoch, const char *pattern, char *str, size_t size)
Convert epoch time to string pattern.
Definition util-time.c:541
void CreateUtcIsoTimeString(const SCTime_t ts, char *str, size_t size)
Definition util-time.c:230
void CreateIsoTimeString(const SCTime_t ts, char *str, size_t size)
Definition util-time.c:209
time_t SCMkTimeUtc(struct tm *tp)
Convert broken-down time to seconds since Unix epoch.
Definition util-time.c:442
void TimeDeinit(void)
Definition util-time.c:87
SCTime_t TimeGet(void)
Definition util-time.c:152
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
Definition util-time.c:180
void TimeModeSetOffline(void)
Definition util-time.c:105
struct tm * SCUtcTime(time_t timep, struct tm *result)
Definition util-time.c:255
uint64_t SCGetSecondsUntil(const char *str, time_t epoch)
Get seconds until a time unit changes.
Definition util-time.c:621
#define SCTIME_TO_TIMEVAL(tv, t)
Definition util-time.h:97
#define SCTIME_SECS(t)
Definition util-time.h:57
#define SCTIME_ADD_SECS(ts, s)
Definition util-time.h:64
#define SCTIME_USECS(t)
Definition util-time.h:56
#define SCTIME_FROM_TIMEVAL(tv)
Definition util-time.h:79