From d1a489a196763361e46524d641e66901e7abcc01 Mon Sep 17 00:00:00 2001 From: bol-van Date: Sun, 28 Dec 2025 12:32:01 +0300 Subject: [PATCH] nfqws2: support 48-bit arithmetics --- docs/changes.txt | 1 + lua/zapret-tests.lua | 72 +++++++++++++---------- nfq2/helpers.c | 23 ++++++++ nfq2/helpers.h | 5 ++ nfq2/lua.c | 136 +++++++++++++++++++++++++++++++++---------- nfq2/nfqws.h | 2 +- 6 files changed, 175 insertions(+), 64 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index caed444..91c5c28 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -137,3 +137,4 @@ v0.7.6 v0.7.7 * init.d: 50-dht4all NFQWS_OPT_DHT_PKT_OUT +* nfqws2: support 48-bit arithmetics diff --git a/lua/zapret-tests.lua b/lua/zapret-tests.lua index e38a002..ff1a6de 100644 --- a/lua/zapret-tests.lua +++ b/lua/zapret-tests.lua @@ -1,6 +1,8 @@ -- nfqws2 C functions tests -- to run : --lua-init=@zapret-lib.lua --lua-init=@zapret-tests.lua --lua-init="test_all()" +math.randomseed(bitxor(getpid(),gettid(),clock_gettime())) + function test_assert(b) assert(b, "test failed") end @@ -251,12 +253,12 @@ function test_aes_ctr() end function test_ub() - for k,f in pairs({{u8,bu8,0xFF,8}, {u16,bu16,0xFFFF,16}, {u24,bu24,0xFFFFFF,24}, {u32,bu32,0xFFFFFFFF,32}}) do + for k,f in pairs({{u8,bu8,0xFF,8}, {u16,bu16,0xFFFF,16}, {u24,bu24,0xFFFFFF,24}, {u32,bu32,0xFFFFFFFF,32}, {u48,bu48,0xFFFFFFFFFFFF,48}}) do local v = math.random(0,f[3]) local pos = math.random(1,20) local s = brandom(pos-1)..f[2](v)..brandom(20) local v2 = f[1](s,pos) - print("u"..tostring(f[4]).." pos="..tostring(pos).." "..tostring(v).." "..tostring(v2)) + print(string.format("u%u pos=%u %016X %016X",f[4],pos,v,v2)) test_assert(v==v2) end end @@ -264,39 +266,44 @@ end function test_bit() local v, v2, v3, v4, b1, b2, pow - v = math.random(0,0xFFFFFFFF) - b1 = math.random(1,16) + for i=1,100 do + v = math.random(0,0xFFFFFFFFFFFF) + b1 = math.random(1,16) - v2 = bitrshift(v, b1) - pow = 2^b1 - v3 = divint(v, pow) - print(string.format("rshift(0x%X,%u) = 0x%X 0x%X/%u = 0x%X", v,b1,v2, v,pow,v3)) - test_assert(v2==v3) + v2 = bitrshift(v, b1) + pow = 2^b1 + v3 = divint(v, pow) + print(string.format("rshift(0x%X,%u) = 0x%X 0x%X/%u = 0x%X", v,b1,v2, v,pow,v3)) + test_assert(v2==v3) - v2 = bitlshift(v, b1) - pow = 2^b1 - v3 = (v * pow) % 0x100000000 - print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x10000000 = 0x%X", v,b1,v2, v,pow,v3)) - test_assert(v2==v3) + v = math.random(0,0xFFFFFFFFF) + b1 = math.random(1,12) + v2 = bitlshift(v, b1) + pow = 2^b1 + v3 = (v * pow) % 0x1000000000000 + print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x100000000000 = 0x%X", v,b1,v2, v,pow,v3)) + test_assert(v2==v3) - v2 = math.random(0,0xFFFFFFFF) - v3 = bitxor(v, v2) - v4 = bitor(v, v2) - bitand(v, v2) - print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4)) - test_assert(v3==v4) + v2 = math.random(0,0xFFFFFFFFFFFF) + v3 = bitxor(v, v2) + v4 = bitor(v, v2) - bitand(v, v2) + print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4)) + test_assert(v3==v4) - b2 = b1 + math.random(1,15) - v2 = bitget(v, b1, b2) - pow = 2^(b2-b1+1) - 1 - v3 = bitand(bitrshift(v,b1), pow) - print(string.format("bitget(0x%X,%u,%u) = 0x%X bitand/bitrshift/pow = 0x%X", v, b1, b2, v2, v3)) - test_assert(v2==v3) + b1 = math.random(1,31) + b2 = b1 + math.random(1,16) + v2 = bitget(v, b1, b2) + pow = 2^(b2-b1+1) - 1 + v3 = bitand(bitrshift(v,b1), pow) + print(string.format("bitget(0x%X,%u,%u) = 0x%X bitand/bitrshift/pow = 0x%X", v, b1, b2, v2, v3)) + test_assert(v2==v3) - v4 = math.random(0,pow) - v2 = bitset(v, b1, b2, v4) - v3 = bitor(bitlshift(v4, b1), bitand(v, bitnot(bitlshift(pow, b1)))) - print(string.format("bitset(0x%X,%u,%u,0x%X) = 0x%X bitand/bitnot/bitlshift/pow = 0x%X", v, b1, b2, v4, v2, v3)) - test_assert(v2==v3) + v4 = math.random(0,pow) + v2 = bitset(v, b1, b2, v4) + v3 = bitor(bitlshift(v4, b1), bitand(v, bitnot(bitlshift(pow, b1)))) + print(string.format("bitset(0x%X,%u,%u,0x%X) = 0x%X bitand/bitnot/bitlshift/pow = 0x%X", v, b1, b2, v4, v2, v3)) + test_assert(v2==v3) + end end function test_ux() @@ -305,7 +312,8 @@ function test_ux() { add=u8add, fname="u8add", max = 0xFF }, { add=u16add, fname="u16add", max = 0xFFFF }, { add=u24add, fname="u24add", max = 0xFFFFFF }, - { add=u32add, fname="u32add", max = 0xFFFFFFFF } + { add=u32add, fname="u32add", max = 0xFFFFFFFF }, + { add=u48add, fname="u48add", max = 0xFFFFFFFFFFFF } }) do io.write(test.fname.." : ") for i=1,1000 do @@ -315,7 +323,7 @@ function test_ux() usum = test.add(v1,v2,v3) sum = bitand((v1+v2+v3)%(test.max+1),test.max) if sum~=usum then - print("FAIL") + print(string.format("FAIL: 0x%012X + 0x%012X + 0x%012X = 0x%012X 0x%012X",v1,v2,v3,usum,sum)) end test_assert(sum==usum) end diff --git a/nfq2/helpers.c b/nfq2/helpers.c index f98b97a..ea78514 100644 --- a/nfq2/helpers.c +++ b/nfq2/helpers.c @@ -367,6 +367,19 @@ void phton32(uint8_t *p, uint32_t v) p[2] = (uint8_t)(v>>8); p[3] = (uint8_t)v; } +uint64_t pntoh48(const uint8_t *p) +{ + return ((uint64_t)p[0] << 40) | ((uint64_t)p[1] << 32) | ((uint64_t)p[2] << 24) | ((uint64_t)p[3] << 16) | ((uint64_t)p[4] << 8) | p[5]; +} +void phton48(uint8_t *p, uint64_t v) +{ + p[0] = (uint8_t)(v>>40); + p[1] = (uint8_t)(v>>32); + p[2] = (uint8_t)(v>>24); + p[3] = (uint8_t)(v>>16); + p[4] = (uint8_t)(v>>8); + p[5] = (uint8_t)v; +} uint64_t pntoh64(const uint8_t *p) { return ((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) | ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32) | ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) | ((uint64_t)p[6] << 8) | p[7]; @@ -383,6 +396,16 @@ void phton64(uint8_t *p, uint64_t v) p[7] = (uint8_t)v; } +uint16_t swap16(uint16_t u) +{ + // __builtin_bswap16 is absent in ancient lexra gcc 4.6 + return (u>>8) | ((u&0xFF)<<8); +} +uint64_t swap48(uint64_t u) +{ + return ((u & 0xFF0000000000) >> 40) | ((u & 0xFF00000000) >> 24) | ((u & 0xFF000000) >> 8) | ((u & 0xFF0000) << 8) | ((u & 0xFF00) << 24) | ((u & 0xFF) << 40); +} + #define INVALID_HEX_DIGIT ((uint8_t)-1) static inline uint8_t parse_hex_digit(char c) diff --git a/nfq2/helpers.h b/nfq2/helpers.h index df65d27..109bc8f 100644 --- a/nfq2/helpers.h +++ b/nfq2/helpers.h @@ -61,9 +61,14 @@ uint32_t pntoh24(const uint8_t *p); void phton24(uint8_t *p, uint32_t v); uint32_t pntoh32(const uint8_t *p); void phton32(uint8_t *p, uint32_t v); +uint64_t pntoh48(const uint8_t *p); +void phton48(uint8_t *p, uint64_t v); uint64_t pntoh64(const uint8_t *p); void phton64(uint8_t *p, uint64_t v); +uint16_t swap16(uint16_t u); +uint64_t swap48(uint64_t u); + bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size); char hex_digit(uint8_t v); diff --git a/nfq2/lua.c b/nfq2/lua.c index d8232ac..64120b4 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -70,16 +70,16 @@ static int luacall_bitlshift(lua_State *L) { lua_check_argc(L,"bitlshift",2); int64_t v=(int64_t)luaL_checklint(L,1); - if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range"); - lua_pushlint(L,((uint32_t)v) << luaL_checkinteger(L,2)); + if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + lua_pushlint(L,(((uint64_t)v) << luaL_checkinteger(L,2)) & 0xFFFFFFFFFFFF); return 1; } static int luacall_bitrshift(lua_State *L) { lua_check_argc(L,"bitrshift",2); int64_t v=(int64_t)luaL_checklint(L,1); - if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range"); - lua_pushlint(L,((uint32_t)v) >> luaL_checkinteger(L,2)); + if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + lua_pushlint(L,((uint64_t)v) >> luaL_checkinteger(L,2)); return 1; } static int luacall_bitand(lua_State *L) @@ -87,12 +87,12 @@ static int luacall_bitand(lua_State *L) lua_check_argc_range(L,"bitand",2,100); int argc = lua_gettop(L); int64_t v; - uint32_t sum=0xFFFFFFFF; + uint64_t sum=0xFFFFFFFFFFFF; for(int i=1;i<=argc;i++) { v=(int64_t)luaL_checklint(L,i); - if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range"); - sum&=(uint32_t)v; + if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + sum&=(uint64_t)v; } lua_pushlint(L,sum); return 1; @@ -102,33 +102,60 @@ static int luacall_bitor(lua_State *L) lua_check_argc_range(L,"bitor",1,100); int argc = lua_gettop(L); int64_t v; - uint32_t sum=0; + uint64_t sum=0; for(int i=1;i<=argc;i++) { v=(int64_t)luaL_checklint(L,i); - if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range"); - sum|=(uint32_t)v; + if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + sum|=(uint64_t)v; } lua_pushlint(L,sum); return 1; } -static int luacall_bitnot(lua_State *L) +static int lua_bitnotx(lua_State *L, int64_t max) { lua_check_argc(L,"bitnot",1); - lua_pushlint(L,~(uint32_t)luaL_checklint(L,1)); + int64_t v=(int64_t)luaL_checklint(L,1); + if (v>max || v<-max) luaL_error(L, "out of range"); + lua_pushlint(L,~(uint64_t)v & max); return 1; } +static int luacall_bitnot8(lua_State *L) +{ + lua_check_argc(L,"bitnot8",1); + return lua_bitnotx(L, 0xFF); +} +static int luacall_bitnot16(lua_State *L) +{ + lua_check_argc(L,"bitnot16",1); + return lua_bitnotx(L, 0xFFFF); +} +static int luacall_bitnot24(lua_State *L) +{ + lua_check_argc(L,"bitnot24",1); + return lua_bitnotx(L, 0xFFFFFF); +} +static int luacall_bitnot32(lua_State *L) +{ + lua_check_argc(L,"bitnot32",1); + return lua_bitnotx(L, 0xFFFFFFFF); +} +static int luacall_bitnot48(lua_State *L) +{ + lua_check_argc(L,"bitnot48",1); + return lua_bitnotx(L, 0xFFFFFFFFFFFF); +} static int luacall_bitxor(lua_State *L) { lua_check_argc_range(L,"bitxor",1,100); int argc = lua_gettop(L); int64_t v; - uint32_t sum=0; + uint64_t sum=0; for(int i=1;i<=argc;i++) { v=(int64_t)luaL_checklint(L,i); - if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range"); - sum^=(uint32_t)v; + if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + sum^=(uint64_t)v; } lua_pushlint(L,sum); return 1; @@ -138,11 +165,11 @@ static int luacall_bitget(lua_State *L) lua_check_argc(L,"bitget",3); int64_t iwhat = (int64_t)luaL_checklint(L,1); - if (iwhat>0xFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range"); - uint32_t what = (uint32_t)iwhat; + if (iwhat>0xFFFFFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + uint64_t what = (uint64_t)iwhat; lua_Integer from = luaL_checkinteger(L,2); lua_Integer to = luaL_checkinteger(L,3); - if (from>to || from>31 || to>31) + if (from>to || from>47 || to>47) luaL_error(L, "bit range invalid"); what = (what >> from) & ~((lua_Integer)-1 << (to-from+1)); @@ -155,14 +182,14 @@ static int luacall_bitset(lua_State *L) lua_check_argc(L,"bitset",4); int64_t iwhat = (int64_t)luaL_checklint(L,1); - if (iwhat>0xFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range"); - uint32_t what = (uint32_t)iwhat; + if (iwhat>0xFFFFFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + uint64_t what = (uint64_t)iwhat; lua_Integer from = luaL_checkinteger(L,2); lua_Integer to = luaL_checkinteger(L,3); int64_t iset = (int64_t)luaL_checklint(L,4); - if (iset>0xFFFFFFFF || iset<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range"); - uint32_t set = (uint32_t)iset; - if (from>to || from>31 || to>31) + if (iset>0xFFFFFFFFFFFF || iset<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + uint64_t set = (uint64_t)iset; + if (from>to || from>47 || to>47) luaL_error(L, "bit range invalid"); lua_Integer mask = ~((lua_Integer)-1 << (to-from+1)); @@ -230,6 +257,20 @@ static int luacall_u32(lua_State *L) lua_pushlint(L,pntoh32(p+offset)); return 1; } +static int luacall_u48(lua_State *L) +{ + lua_check_argc_range(L,"u48",1,2); + + int argc=lua_gettop(L); + size_t l; + lua_Integer offset; + const uint8_t *p = (uint8_t*)luaL_checklstring(L,1,&l); + offset = (argc>=2 && lua_type(L,2)!=LUA_TNIL) ? luaL_checkinteger(L,2)-1 : 0; + if (offset<0 || (offset+6)>l) luaL_error(L, "out of range"); + + lua_pushlint(L,pntoh48(p+offset)); + return 1; +} static int luacall_swap16(lua_State *L) { lua_check_argc(L,"swap16",1); @@ -237,8 +278,7 @@ static int luacall_swap16(lua_State *L) int64_t i = (int64_t)luaL_checklint(L,1); if (i>0xFFFF || i<-(int64_t)0xFFFF) luaL_error(L, "out of range"); uint16_t u = (uint16_t)i; - // __builtin_bswap16 is absent in ancient lexra gcc 4.6 - lua_pushinteger(L,(u>>8) | ((u&0xFF)<<8)); + lua_pushinteger(L,swap16(u)); return 1; } static int luacall_swap32(lua_State *L) @@ -251,16 +291,26 @@ static int luacall_swap32(lua_State *L) lua_pushlint(L,__builtin_bswap32(u)); return 1; } -static int lua_uxadd(lua_State *L, uint32_t max) +static int luacall_swap48(lua_State *L) +{ + lua_check_argc(L,"swap48",1); + + int64_t i =(int64_t)luaL_checklint(L,1); + if (i>0xFFFFFFFFFFFF || i<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + uint64_t u = (uint64_t)i; + lua_pushlint(L, swap48(u)); + return 1; +} +static int lua_uxadd(lua_State *L, int64_t max) { int64_t v; - uint32_t sum=0; + uint64_t sum=0; int argc = lua_gettop(L); for(int i=1;i<=argc;i++) { v = (int64_t)luaL_checklint(L,i); - if (v>max || v<-(int64_t)max) luaL_error(L, "out of range"); - sum+=(uint32_t)v; + if (v>max || v<-max) luaL_error(L, "out of range"); + sum+=(uint64_t)v; } lua_pushlint(L, sum & max); return 1; @@ -285,6 +335,11 @@ static int luacall_u32add(lua_State *L) lua_check_argc_range(L,"u32add",1,100); return lua_uxadd(L, 0xFFFFFFFF); } +static int luacall_u48add(lua_State *L) +{ + lua_check_argc_range(L,"u48add",1,100); + return lua_uxadd(L, 0xFFFFFFFFFFFF); +} static int luacall_bu8(lua_State *L) { @@ -329,6 +384,17 @@ static int luacall_bu32(lua_State *L) lua_pushlstring(L,(char*)v,4); return 1; } +static int luacall_bu48(lua_State *L) +{ + lua_check_argc(L,"bu48",1); + + int64_t i = (int64_t)luaL_checklint(L,1); + if (i>0xFFFFFFFFFFFF || i<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range"); + uint8_t v[4]; + phton48(v,(uint64_t)i); + lua_pushlstring(L,(char*)v,6); + return 1; +} static int luacall_divint(lua_State *L) { @@ -3090,10 +3156,14 @@ static void lua_init_functions(void) {"bitand",luacall_bitand}, {"bitor",luacall_bitor}, {"bitxor",luacall_bitxor}, - {"bitxor",luacall_bitxor}, {"bitget",luacall_bitget}, {"bitset",luacall_bitset}, - {"bitnot",luacall_bitnot}, + {"bitnot",luacall_bitnot48}, + {"bitnot8",luacall_bitnot8}, + {"bitnot16",luacall_bitnot16}, + {"bitnot24",luacall_bitnot24}, + {"bitnot32",luacall_bitnot32}, + {"bitnot48",luacall_bitnot48}, // WARNING : lua 5.1 and luajit does not correctly implement integers. they seem to be stored as float which can't hold 64-bit. // convert part of the blob (string) to number @@ -3101,19 +3171,23 @@ static void lua_init_functions(void) {"u16",luacall_u16}, {"u24",luacall_u24}, {"u32",luacall_u32}, + {"u48",luacall_u48}, // add any number of arguments as they would be unsigned int of specific size {"u8add",luacall_u8add}, {"u16add",luacall_u16add}, {"u24add",luacall_u24add}, {"u32add",luacall_u32add}, + {"u48add",luacall_u48add}, // convert number to blob (string) - big endian {"bu8",luacall_bu8}, {"bu16",luacall_bu16}, {"bu24",luacall_bu24}, {"bu32",luacall_bu32}, + {"bu48",luacall_bu48}, // swap byte order {"swap16",luacall_swap16}, {"swap32",luacall_swap32}, + {"swap48",luacall_swap48}, // integer division {"divint",luacall_divint}, diff --git a/nfq2/nfqws.h b/nfq2/nfqws.h index ab4fc8b..bcb0d65 100644 --- a/nfq2/nfqws.h +++ b/nfq2/nfqws.h @@ -12,4 +12,4 @@ extern bool bQuit; int main(int argc, char *argv[]); // when something changes that can break LUA compatibility this version should be increased -#define LUA_COMPAT_VER 3 +#define LUA_COMPAT_VER 4