From 64c1f96f805eba0a9c9757af85c3a953eab798cc Mon Sep 17 00:00:00 2001 From: bol-van Date: Thu, 5 Feb 2026 14:32:36 +0300 Subject: [PATCH] nfqws2: time convert functions --- docs/changes.txt | 1 + docs/manual.en.md | 29 ++++++++++++++ docs/manual.md | 31 ++++++++++++++- lua/zapret-tests.lua | 29 +++++++++++++- nfq2/lua.c | 92 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 178 insertions(+), 4 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 3a09fd9..ee5bb56 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -225,3 +225,4 @@ v0.8.1 0.9.2 nfqws2: bt and utp_bt protocol detectors +nfqws2: localtime,gmtime,timelocal,timegm luacalls diff --git a/docs/manual.en.md b/docs/manual.en.md index 61489e5..92ff9dc 100644 --- a/docs/manual.en.md +++ b/docs/manual.en.md @@ -76,6 +76,7 @@ - [clock\_gettime](#clock_gettime) - [getpid](#getpid) - [stat](#stat) + - [time](#time) - [Packet handling options](#packet-handling-options) - [standard reconstruct](#standard-reconstruct) - [standard rawsend](#standard-rawsend) @@ -1993,6 +1994,34 @@ If successful returns the following table : In case of error returns 3 values : nil, error string, error number (errno). +#### time + +``` +function localtime(unixtime) +function gmtime(unixtime) +function timelocal(tm) +function timegm(tm) +``` + +localtime and gmtime return dissected unixtime similar to C "struct tm". timelocal and timegm are reverse functions. + +| Поле | Тип | Описание | +| :------- | :----- | :---------- | +| sec* | number | second | +| min* | number | minute | +| hour* | number | hour | +| mon* | number | month starting from 0 | +| mday* | number | day of month starting from 1 | +| year* | number | full year, not from 1900 | +| wday | number | day of week. 0 = sunday | +| yday | number | day of year starting from 0 | +| isdst* | number | not zero if summer time in effect | +| zone | string | time zone | +| str | number | formatted string: "dd.mm.yyyy hh:mi:ss" | + +Fields marked with "*" are required for reverse translation. + + ### Packet handling options The following functions use standard sets of options: `rawsend` and `reconstruct`. diff --git a/docs/manual.md b/docs/manual.md index bbd3f32..4c39631 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -38,7 +38,7 @@ - [Структура track](#структура-track) - [Особенности обработки icmp](#особенности-обработки-icmp) - [Особенности обработки raw ip](#особенности-обработки-raw-ip) -- [C интерфейс nfqws2](#c-интерфейс-nfqws2) +- [С интерфейс nfqws2](#с-интерфейс-nfqws2) - [Базовые константы](#базовые-константы) - [Стандартные блобы](#стандартные-блобы) - [Переменные окружения](#переменные-окружения) @@ -73,6 +73,7 @@ - [clock\_gettime](#clock_gettime) - [getpid](#getpid) - [stat](#stat) + - [time](#time) - [Опции по работе с пакетами](#опции-по-работе-с-пакетами) - [standard reconstruct](#standard-reconstruct) - [standard rawsend](#standard-rawsend) @@ -150,7 +151,7 @@ - [rawsend\_dissect\_segmented](#rawsend_dissect_segmented) - [rawsend\_payload\_segmented](#rawsend_payload_segmented) - [Стандартные фильтры direction и payload](#стандартные-фильтры-direction-и-payload) - - [Работа с многопакетными пейлоадами](#работа-с-многопакетными-пейлоадами) + - [Работа с многопакетными пейлоадам](#работа-с-многопакетными-пейлоадам) - [Оркестрация](#оркестрация) - [instance\_cutoff\_shim](#instance_cutoff_shim) - [cutoff\_shim\_check](#cutoff_shim_check) @@ -2139,6 +2140,32 @@ function stat(filename) В случае неудачи возвращает 3 значения : nil, строка ошибки, код ошибки errno. +#### time + +``` +function localtime(unixtime) +function gmtime(unixtime) +function timelocal(tm) +function timegm(tm) +``` + +Функции localtime и gmtime возвращают таблицу, аналогичную struct tm в C. timelocal и timegm - обратные функции. + +| Поле | Тип | Описание | +| :------- | :----- | :---------- | +| sec* | number | секунды | +| min* | number | минуты | +| hour* | number | часы | +| mon* | number | месяц, начиная с 0 | +| mday* | number | день месяца | +| year* | number | год - полный, не с 1900 года | +| wday | number | день недели. 0 - воскресенье, 6 - суббота | +| yday | number | номер дня в году, начиная с 0 | +| isdst* | number | не 0, если включен переход на летнее/зимнее время | +| zone | string | часовой пояс (timezone) | +| str | number | отформатированная строка dd.mm.yyyy hh:mi:ss | + +Поля, помеченные `*`, нужны для обратного перевода. Остальные не учитываются. ### Опции по работе с пакетами diff --git a/lua/zapret-tests.lua b/lua/zapret-tests.lua index ae00a75..7a0404b 100644 --- a/lua/zapret-tests.lua +++ b/lua/zapret-tests.lua @@ -14,7 +14,7 @@ end function test_all(...) test_run({ - test_crypto, test_bin, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve, + test_crypto, test_bin, test_time, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve, test_get_source_ip, test_ifaddrs, test_rawsend},...) end @@ -415,6 +415,33 @@ function test_bin(...) test_run({test_ub, test_bit, test_swap, test_ux},...) end +function test_time(...) + print("* time") + + local unixtime=os.time() + local tm = localtime(unixtime); + print() + print("now: "..tm.str.." "..tm.zone.." = "..unixtime) + local tm = gmtime(unixtime); + print("gmt: "..tm.str.." "..tm.zone.." = "..unixtime) + print() + for i=1,20 do + unixtime = math.random(0,10000000000); + tm = localtime(unixtime); + local t = timelocal(tm) + print("timelocal: "..tm.str.." "..tm.zone.." = "..t) + print( t==unixtime and "LOCALTIME OK" or "LOCALTIME FAILED" ) + test_assert(t==unixtime) + + unixtime = math.random(0,10000000000); + tm = gmtime(unixtime); + t = timegm(tm) + print("timegm: "..tm.str.." "..tm.zone.." = "..t) + print( t==unixtime and "GMTIME OK" or "GMTIME FAILED" ) + test_assert(t==unixtime) + end +end + function test_gzip() print("* gzip") diff --git a/nfq2/lua.c b/nfq2/lua.c index 9bc4d71..e8e41b2 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -3614,6 +3614,90 @@ static int luacall_stat(lua_State *L) return 1; } +static void lua_xtime(lua_State *L, struct tm *(*timefunc)(const time_t *,struct tm *)) +{ + struct tm t; + + time_t unixtime = (time_t)luaL_checklint(L,1); + if (!timefunc(&unixtime, &t)) + { + lua_pushnil(L); + } + else + { + lua_createtable(L, 0, 11); + lua_pushf_int(L,"sec", t.tm_sec); + lua_pushf_int(L,"min", t.tm_min); + lua_pushf_int(L,"hour", t.tm_hour); + lua_pushf_int(L,"mday", t.tm_mday); + lua_pushf_int(L,"mon", t.tm_mon); + lua_pushf_int(L,"year", t.tm_year+1900); + lua_pushf_int(L,"wday", t.tm_wday); + lua_pushf_int(L,"yday", t.tm_yday); + lua_pushf_int(L,"isdst", t.tm_isdst); + lua_pushf_str(L,"zone", t.tm_zone); + + char s[24]; + snprintf(s,sizeof(s),"%02d.%02d.%04d %02d:%02d:%02d", t.tm_mday, t.tm_mon + 1, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec); + lua_pushf_str(L,"str", s); + } +} +static int luacall_localtime(lua_State *L) +{ + // localtime(unixtime) + lua_check_argc(L,"localtime",1); + lua_xtime(L, localtime_r); + return 1; +} +static int luacall_gmtime(lua_State *L) +{ + // gmtime(unixtime) + lua_check_argc(L,"gmtime",1); + lua_xtime(L, gmtime_r); + return 1; +} +#define TIMEX_VAL(v) \ + lua_getfield(L,1,#v); \ + if (lua_type(L,-1)!=LUA_TNUMBER) luaL_error(L,"invalid tm." #v); \ + t.tm_##v = lua_tointeger(L,-1); \ + lua_pop(L,1); +static void lua_timex(lua_State *L, time_t (*timefunc)(struct tm *)) +{ + if (lua_type(L,1)!=LUA_TTABLE) luaL_error(L,"invalid tm structure"); + + struct tm t; + TIMEX_VAL(sec) + TIMEX_VAL(min) + TIMEX_VAL(hour) + TIMEX_VAL(mday) + TIMEX_VAL(mon) + TIMEX_VAL(year) + t.tm_year-=1900; + TIMEX_VAL(isdst) + + time_t unixtime = timefunc(&t); + if (unixtime==(time_t)-1) + { + lua_pushnil(L); + } + else + lua_pushlint(L,unixtime); +} +static int luacall_timelocal(lua_State *L) +{ + // timelocal(tm) + lua_check_argc(L,"timelocal",1); + lua_timex(L, timelocal); + return 1; +} +static int luacall_timegm(lua_State *L) +{ + // timegm(tm) + lua_check_argc(L,"timegm",1); + lua_timex(L, timegm); + return 1; +} + // ---------------------------------------- void lua_cleanup(lua_State *L) @@ -4258,7 +4342,13 @@ static void lua_init_functions(void) {"gzip_deflate",luacall_gzip_deflate}, // stat() - file size, mod time - {"stat",luacall_stat} + {"stat",luacall_stat}, + + // time + {"localtime",luacall_localtime}, + {"gmtime",luacall_gmtime}, + {"timelocal",luacall_timelocal}, + {"timegm",luacall_timegm} }; for(int i=0;i<(sizeof(lfunc)/sizeof(*lfunc));i++) lua_register(params.L,lfunc[i].name,lfunc[i].f);