mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-16 14:58:17 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f91c069a8b | ||
|
|
6961c013c5 | ||
|
|
e5736b5fdd | ||
|
|
efa675468d | ||
|
|
1073f03802 | ||
|
|
9125cb0205 | ||
|
|
9d5435f977 | ||
|
|
f17ab4c91e | ||
|
|
97aa261e14 | ||
|
|
813fece07a | ||
|
|
2a7b44b1d0 | ||
|
|
28e719d825 | ||
|
|
18725f6442 | ||
|
|
20b20fbb90 | ||
|
|
967b53b628 | ||
|
|
9cebc5cc37 | ||
|
|
0dc29c9c35 | ||
|
|
fd1eac2ef1 | ||
|
|
0c2abab6a9 | ||
|
|
efd8acb8de | ||
|
|
a147ebef61 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -108,7 +108,7 @@ jobs:
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
export STAGING_DIR=$RUNNER_TEMP
|
||||
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]]; then
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]]; then
|
||||
# use classic lua
|
||||
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
|
||||
@@ -47,5 +47,17 @@ v0.4
|
||||
* nfqws2: profile templates
|
||||
* nfqws2: remove stun_binding_req, replace to stun. no more message type details
|
||||
* nfqws2: proper conntack position for replayed packets
|
||||
* nfqws2: execution_plan, execution_plan_cancel
|
||||
* blockcheck2: fix broken dns cache
|
||||
* nfqws2: LUA_COMPAT_VER tracking
|
||||
|
||||
v0.5
|
||||
|
||||
* nfqws2: u8add,u16add,u24add,u32add luacalls
|
||||
* nfqws2: abandon any arithmetics beyond 32bit (because lua 5.1 does not support 64 bit integers, store everything as double)
|
||||
* nfqws2: fix issues with 32-bit lua_Integer in lua<5.3 on 32-bit platforms
|
||||
* nfqws2: instance_cutoff luacall just warns and do nothing if ctx is nil
|
||||
* actions: build nfqws2 x86 binary with LUA 5.4, not with luajit
|
||||
* zapret-lib: http_reply, url and nld dissectors
|
||||
* zapret-lib: instance_cutoff_shim
|
||||
* zapret-auto: circular orchestrator
|
||||
|
||||
@@ -41,7 +41,7 @@ PIDDIR=/var/run
|
||||
|
||||
USEROPT="--user=$WS_USER"
|
||||
NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}"
|
||||
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua"
|
||||
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua --lua-init=@$ZAPRET_BASE/lua/zapret-auto.lua"
|
||||
NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT"
|
||||
|
||||
run_daemon()
|
||||
|
||||
@@ -72,7 +72,7 @@ DESYNC_MARK_POSTNAT=${DESYNC_MARK_POSTNAT:-0x20000000}
|
||||
|
||||
QNUM=${QNUM:-300}
|
||||
NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}"
|
||||
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua"
|
||||
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua --lua-init=@$ZAPRET_BASE/lua/zapret-auto.lua"
|
||||
NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT"
|
||||
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ end
|
||||
-- standard args : direction
|
||||
function http_domcase(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -139,7 +139,7 @@ end
|
||||
-- arg : spell=<str> . spelling of the "Host" header. must be exactly 4 chars long
|
||||
function http_hostcase(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -164,7 +164,7 @@ end
|
||||
-- standard args : direction
|
||||
function http_methodeol(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -221,10 +221,10 @@ function synack_split(ctx, desync)
|
||||
error("synack_split: bad mode '"..mode.."'")
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx) -- mission complete
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -238,10 +238,10 @@ function synack(ctx, desync)
|
||||
DLOG("synack: sending")
|
||||
rawsend_dissect_ipfrag(dis, desync_opts(desync))
|
||||
else
|
||||
instance_cutoff(ctx) -- mission complete
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -256,10 +256,10 @@ function wsize(ctx, desync)
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx) -- mission complete
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -270,7 +270,7 @@ end
|
||||
-- arg : forced_cutoff=<list> - comma separated list of payloads that trigger forced wssize cutoff. by default - any non-empty payload
|
||||
function wssize(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
local verdict = VERDICT_PASS
|
||||
@@ -281,7 +281,7 @@ function wssize(ctx, desync)
|
||||
end
|
||||
if #desync.dis.payload>0 and (not desync.arg.forced_cutoff or in_list(desync.arg.forced_cutoff, desync.l7payload)) then
|
||||
DLOG("wssize: forced cutoff")
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
return verdict
|
||||
@@ -290,7 +290,7 @@ end
|
||||
-- nfqws1 : "--dpi-desync=syndata"
|
||||
-- standard args : fooling, rawsend, reconstruct, ipfrag
|
||||
-- arg : blob=<blob> - fake payload. must fit to single packet. no segmentation possible. default - 16 zero bytes.
|
||||
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>,dupsid,padencap
|
||||
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>
|
||||
function syndata(ctx, desync)
|
||||
if desync.dis.tcp then
|
||||
if bitand(desync.dis.tcp.th_flags, TH_SYN + TH_ACK)==TH_SYN then
|
||||
@@ -305,10 +305,10 @@ function syndata(ctx, desync)
|
||||
return VERDICT_DROP
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx) -- mission complete
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -317,7 +317,7 @@ end
|
||||
-- arg : rstack - send RST,ACK instead of RST
|
||||
function rst(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -371,7 +371,7 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multisplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -425,7 +425,7 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multidisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -491,7 +491,7 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function hostfakesplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -604,7 +604,7 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakedsplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -697,7 +697,7 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakeddisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -797,7 +797,7 @@ end
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
function tcpseg(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -841,7 +841,7 @@ end
|
||||
-- arg : pattern_offset=N . offset in the pattern. 0 by default
|
||||
function udplen(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -877,7 +877,7 @@ end
|
||||
-- arg : dn=N - message starts from "dN". 2 by default
|
||||
function dht_dn(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
|
||||
230
lua/zapret-auto.lua
Normal file
230
lua/zapret-auto.lua
Normal file
@@ -0,0 +1,230 @@
|
||||
-- arg: reqhost - require hostname, do not work with ip
|
||||
function automate_host_record(desync)
|
||||
local key
|
||||
if desync.arg.reqhost then
|
||||
key = desync.track and desync.track.hostname
|
||||
else
|
||||
key = host_or_ip(desync)
|
||||
end
|
||||
if not key then
|
||||
DLOG("automate: host record key unavailable")
|
||||
return nil
|
||||
end
|
||||
DLOG("automate: host record key '"..key.."'")
|
||||
if not autostate then
|
||||
autostate = {}
|
||||
end
|
||||
if not autostate[key] then
|
||||
autostate[key] = {}
|
||||
end
|
||||
return autostate[key]
|
||||
end
|
||||
function automate_conn_record(desync)
|
||||
if not desync.track.lua_state.automate then
|
||||
desync.track.lua_state.automate = {}
|
||||
end
|
||||
return desync.track.lua_state.automate
|
||||
end
|
||||
|
||||
-- counts failure, optionally (if crec is given) prevents dup failure counts in a single connection
|
||||
-- if 'maxtime' between failures is exceeded then failure count is reset
|
||||
-- return true if threshold ('fails') is reached
|
||||
-- hres is host record. host or ip bound table
|
||||
-- cres is connection record. connection bound table
|
||||
function automate_failure_counter(hrec, crec, fails, maxtime)
|
||||
if crec and crec.failure then
|
||||
DLOG("automate: duplicate failure in the same connection. not counted")
|
||||
else
|
||||
if crec then crec.failure = true end
|
||||
local tnow=os.time()
|
||||
if not hrec.failure_time_last then
|
||||
hrec.failure_time_last = tnow
|
||||
end
|
||||
if not hrec.failure_counter then
|
||||
hrec.failure_counter = 0
|
||||
elseif tnow>(hrec.failure_time_last + maxtime) then
|
||||
DLOG("automate: failure counter reset because last failure was "..(tnow - hrec.failure_time_last).." seconds ago")
|
||||
hrec.failure_counter = 0
|
||||
end
|
||||
hrec.failure_counter = hrec.failure_counter + 1
|
||||
hrec.failure_time_last = tnow
|
||||
if b_debug then DLOG("automate: failure counter "..hrec.failure_counter..(fails and ('/'..fails) or '')) end
|
||||
if fails and hrec.failure_counter>=fails then
|
||||
hrec.failure_counter = nil -- reset counter
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- location is url compatible with Location: header
|
||||
-- hostname is original hostname
|
||||
function is_dpi_redirect(hostname, location)
|
||||
local ds = dissect_url(location)
|
||||
if ds.domain then
|
||||
local sld1 = dissect_nld(hostname,2)
|
||||
local sld2 = dissect_nld(ds.domain,2)
|
||||
return sld2 and sld1~=sld2
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- circularily change strategy numbers when failure count reaches threshold ('fails')
|
||||
-- detected failures: incoming RST, incoming http redirection, outgoing retransmissions
|
||||
-- this orchestrator requires redirection of incoming traffic to cache RST and http replies !
|
||||
-- each orchestrated instance must have strategy=N arg, where N starts from 1 and increment without gaps
|
||||
-- if 'final' arg is present in an orchestrated instance it stops rotation
|
||||
-- arg: fails=N - failture count threshold. default is 3
|
||||
-- arg: retrans=N - retrans count threshold. default is 3
|
||||
-- arg: seq=<rseq> - if packet is beyond this relative sequence number treat this connection as successful. default is 64K
|
||||
-- arg: rst=<rseq> - maximum relative sequence number to treat incoming RST as DPI reset. default is 1
|
||||
-- arg: time=<sec> - if last failure happened earlier than `maxtime` seconds ago - reset failure counter. default is 60.
|
||||
-- arg: reqhost - pass with no tampering if hostname is unavailable
|
||||
-- test case: nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s1 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
function circular(ctx, desync)
|
||||
local function count_strategies(hrec, plan)
|
||||
if not hrec.ctstrategy then
|
||||
local uniq={}
|
||||
local n=0
|
||||
for i,instance in pairs(plan) do
|
||||
if instance.arg.strategy then
|
||||
n = tonumber(instance.arg.strategy)
|
||||
if not n or n<1 then
|
||||
error("circular: strategy number '"..tostring(instance.arg.strategy).."' is invalid")
|
||||
end
|
||||
uniq[tonumber(instance.arg.strategy)] = true
|
||||
if instance.arg.final then
|
||||
hrec.final = n
|
||||
end
|
||||
end
|
||||
end
|
||||
n=0
|
||||
for i,v in pairs(uniq) do
|
||||
n=n+1
|
||||
end
|
||||
if n~=#uniq then
|
||||
error("circular: strategies numbers must start from 1 and increment. gaps are not allowed.")
|
||||
end
|
||||
hrec.ctstrategy = n
|
||||
end
|
||||
end
|
||||
|
||||
-- take over orchestration. prevent further instance execution in case of error
|
||||
execution_plan_cancel(ctx)
|
||||
|
||||
if not desync.dis.tcp then
|
||||
DLOG("circular: this orchestrator is tcp only")
|
||||
instance_cutoff(ctx)
|
||||
return
|
||||
end
|
||||
if not desync.track then
|
||||
DLOG_ERR("circular: conntrack is missing but required")
|
||||
return
|
||||
end
|
||||
|
||||
local plan = execution_plan(ctx)
|
||||
if #plan==0 then
|
||||
DLOG("circular: need some desync instances or useless")
|
||||
return
|
||||
end
|
||||
|
||||
local hrec = automate_host_record(desync)
|
||||
if not hrec then
|
||||
DLOG("circular: passing with no tampering")
|
||||
return
|
||||
end
|
||||
|
||||
count_strategies(hrec, plan)
|
||||
if hrec.ctstrategy==0 then
|
||||
error("circular: add strategy=N tag argument to each following instance ! N must start from 1 and increment")
|
||||
end
|
||||
|
||||
local rstseq = tonumber(desync.arg.rst) or 1
|
||||
local maxseq = tonumber(desync.arg.seq) or 0x10000
|
||||
local fails = tonumber(desync.arg.fails) or 3
|
||||
local retrans = tonumber(desync.arg.retrans) or 3
|
||||
local maxtime = tonumber(desync.arg.time) or 60
|
||||
local crec = automate_conn_record(desync)
|
||||
local pos = bitand(desync.track.tcp.seq - desync.track.tcp.seq0,0xFFFFFFFF)
|
||||
local trigger = false
|
||||
|
||||
if not hrec.nstrategy then
|
||||
DLOG("circular: start from strategy 1")
|
||||
hrec.nstrategy = 1
|
||||
end
|
||||
|
||||
if not crec.nocheck then
|
||||
local seq = pos_get(desync,'s')
|
||||
if seq>maxseq then
|
||||
DLOG("circular: s"..seq.." is beyond s"..maxseq..". treating connection as successful")
|
||||
crec.nocheck = true
|
||||
end
|
||||
end
|
||||
|
||||
local verdict = VERDICT_PASS
|
||||
if not crec.nocheck and hrec.final~=hrec.nstrategy then
|
||||
if desync.outgoing then
|
||||
if #desync.dis.payload>0 and (crec.retrans or 0)<retrans then
|
||||
if not crec.uppos then crec.uppos=0 end
|
||||
if desync.track.tcp.pos_orig<=crec.uppos then
|
||||
crec.retrans = crec.retrans and (crec.retrans+1) or 1
|
||||
DLOG("circular: retransmission "..crec.retrans.."/"..retrans)
|
||||
trigger = crec.retrans>=retrans
|
||||
end
|
||||
if desync.track.tcp.pos_orig>crec.uppos then
|
||||
crec.uppos=desync.track.tcp.pos_orig
|
||||
end
|
||||
end
|
||||
else
|
||||
if bitand(desync.dis.tcp.th_flags, TH_RST)~=0 then
|
||||
local seq=u32add(desync.track.tcp.ack, -desync.track.tcp.ack0)
|
||||
trigger = seq<=rstseq
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("circular: incoming RST s"..seq.." in range s"..rstseq)
|
||||
else
|
||||
DLOG("circular: not counting incoming RST s"..seq.." beyond s"..rstseq)
|
||||
end
|
||||
end
|
||||
elseif desync.l7payload=="http_reply" and desync.track.hostname then
|
||||
local hdis = http_dissect_reply(desync.dis.payload)
|
||||
if hdis and (hdis.code==302 or hdis.code==307) and hdis.headers.location and hdis.headers.location then
|
||||
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers.location.value)
|
||||
if trigger and b_debug then
|
||||
DLOG("circular: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if trigger then
|
||||
if automate_failure_counter(hrec, crec, fails, maxtime) then
|
||||
-- circular strategy change
|
||||
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
|
||||
DLOG("circular: rotate strategy to "..hrec.nstrategy)
|
||||
if hrec.nstrategy == hrec.final then
|
||||
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DLOG("circular: current strategy "..hrec.nstrategy)
|
||||
local dcopy = desync_copy(desync)
|
||||
for i=1,#plan do
|
||||
if plan[i].arg.strategy and tonumber(plan[i].arg.strategy)==hrec.nstrategy then
|
||||
apply_execution_plan(dcopy, plan[i])
|
||||
if cutoff_shim_check(dcopy) then
|
||||
DLOG("circular: not calling '"..dcopy.func_instance.."' because of voluntary cutoff")
|
||||
elseif not payload_match_filter(dcopy.l7payload, plan[i].payload_filter) then
|
||||
DLOG("circular: not calling '"..dcopy.func_instance.."' because payload '"..dcopy.l7payload.."' does not match filter '"..plan[i].payload_filter.."'")
|
||||
elseif not pos_check_range(dcopy, plan[i].range) then
|
||||
DLOG("circular: not calling '"..dcopy.func_instance.."' because pos "..pos_str(dcopy,plan[i].range.from).." "..pos_str(dcopy,plan[i].range.to).." is out of range '"..pos_range_str(plan[i].range).."'")
|
||||
else
|
||||
DLOG("circular: calling '"..dcopy.func_instance.."'")
|
||||
verdict = verdict_aggregate(verdict,_G[plan[i].func](nil, dcopy))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return verdict
|
||||
end
|
||||
@@ -61,6 +61,46 @@ function posdebug(ctx,desync)
|
||||
DLOG(s)
|
||||
end
|
||||
|
||||
-- this shim is needed then function is orchestrated. ctx services not available
|
||||
-- have to emulate cutoff in LUA using connection persistent table track.lua_state
|
||||
function instance_cutoff_shim(ctx, desync, dir)
|
||||
if ctx then
|
||||
instance_cutoff(ctx, dir)
|
||||
elseif not desync.track then
|
||||
DLOG("instance_cutoff_shim: cannot cutoff '"..desync.func_instance.."' because conntrack is absent")
|
||||
else
|
||||
if not desync.track.lua_state.cutoff_shim then
|
||||
desync.track.lua_state.cutoff_shim = {}
|
||||
end
|
||||
if not desync.track.lua_state.cutoff_shim[desync.func_instance] then
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance] = {}
|
||||
end
|
||||
if type(dir)=="nil" then
|
||||
-- cutoff both directions by default
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance][true] = true
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance][false] = true
|
||||
else
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance][dir] = true
|
||||
end
|
||||
if b_debug then DLOG("instance_cutoff_shim: cutoff '"..desync.func_instance.."' in="..tostring(type(dir)=="nil" and true or not dir).." out="..tostring(type(dir)=="nil" or dir)) end
|
||||
end
|
||||
end
|
||||
function cutoff_shim_check(desync)
|
||||
if not desync.track then
|
||||
DLOG("cutoff_shim_check: cannot check '"..desync.func_instance.."' cutoff because conntrack is absent")
|
||||
return false
|
||||
else
|
||||
local b=desync.track.lua_state.cutoff_shim and
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance] and
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance][desync.outgoing]
|
||||
if b and b_debug then
|
||||
DLOG("cutoff_shim_check: '"..desync.func_instance.."' "..(desync.outgoing and "out" or "in").." cutoff")
|
||||
end
|
||||
return b
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- applies # and $ prefixes. #var means var length, %var means var value
|
||||
function apply_arg_prefix(arg)
|
||||
for a,v in pairs(arg) do
|
||||
@@ -85,20 +125,49 @@ function apply_execution_plan(desync, plan)
|
||||
desync.arg = deepcopy(plan.arg)
|
||||
apply_arg_prefix(desync.arg)
|
||||
end
|
||||
-- produce resulting verdict from 2 verdicts
|
||||
function verdict_aggregate(v1, v2)
|
||||
local v
|
||||
v1 = v1 or VERDICT_PASS
|
||||
v2 = v2 or VERDICT_PASS
|
||||
if v1==VERDICT_DROP or v2==VERDICT_DROP then
|
||||
v=VERDICT_DROP
|
||||
elseif v1==VERDICT_MODIFY or v2==VERDICT_MODIFY then
|
||||
v=VERDICT_MODIFY
|
||||
else
|
||||
v=VERDICT_PASS
|
||||
end
|
||||
return v
|
||||
end
|
||||
-- redo what whould be done without orchestration
|
||||
function replay_execution_plan(desync, plan)
|
||||
local verdict = VERDICT_PASS
|
||||
for i=1,#plan do
|
||||
if not payload_match_filter(desync.l7payload, plan[i].payload_filter) then
|
||||
if cutoff_shim_check(desync) then
|
||||
DLOG("orchestrator: not calling '"..desync.func_instance.."' because of voluntary cutoff")
|
||||
elseif not payload_match_filter(desync.l7payload, plan[i].payload_filter) then
|
||||
DLOG("orchestrator: not calling '"..desync.func_instance.."' because payload '"..desync.l7payload.."' does not match filter '"..plan[i].payload_filter.."'")
|
||||
elseif not pos_check_range(desync, plan[i].range) then
|
||||
DLOG("orchestrator: not calling '"..desync.func_instance.."' because pos "..pos_str(desync,plan[i].range.from).." "..pos_str(desync,plan[i].range.to).." is out of range '"..pos_range_str(plan[i].range).."'")
|
||||
else
|
||||
apply_execution_plan(desync, plan[i])
|
||||
DLOG("orchestrator: executing '"..desync.func_instance.."'")
|
||||
_G[plan[i].func](ctx, desync)
|
||||
DLOG("orchestrator: calling '"..desync.func_instance.."'")
|
||||
verdict = verdict_aggregate(verdict,_G[plan[i].func](nil, desync))
|
||||
end
|
||||
end
|
||||
return verdict
|
||||
end
|
||||
|
||||
-- copy desync preserving lua_state
|
||||
function desync_copy(desync)
|
||||
local dcopy = deepcopy(desync)
|
||||
if desync.track then
|
||||
-- preserve lua state
|
||||
dcopy.track.lua_state = desync.track.lua_state
|
||||
end
|
||||
return dcopy
|
||||
end
|
||||
|
||||
-- this function demonstrates how to stop execution of upcoming desync instances and take over their job
|
||||
-- this can be used, for example, for orchestrating conditional processing without modifying of desync functions code
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-desync=desync_orchestrator_example --lua-desync=pass --lua-desync=pass
|
||||
@@ -106,9 +175,9 @@ function desync_orchestrator_example(ctx, desync)
|
||||
local plan = execution_plan(ctx)
|
||||
if #plan>0 then
|
||||
DLOG("orchestrator: taking over upcoming desync instances")
|
||||
local desync_copy = deepcopy(desync)
|
||||
local dcopy = desync_copy(desync)
|
||||
execution_plan_cancel(ctx)
|
||||
replay_execution_plan(desync_copy, plan)
|
||||
return replay_execution_plan(dcopy, plan)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -126,7 +195,7 @@ function pos_get(desync, mode)
|
||||
elseif mode=='b' then
|
||||
return desync.outgoing and desync.track.pbcounter_orig or desync.track.pbcounter_reply
|
||||
elseif mode=='s' and desync.track.tcp then
|
||||
return desync.outgoing and (desync.track.tcp.seq - desync.track.tcp.seq0) or (desync.track.tcp.ack - desync.track.tcp.ack0)
|
||||
return desync.outgoing and u32add(desync.track.tcp.seq, -desync.track.tcp.seq0) or u32add(desync.track.tcp.ack, -desync.track.tcp.ack0)
|
||||
end
|
||||
end
|
||||
return 0
|
||||
@@ -241,7 +310,7 @@ function var_debug(v)
|
||||
local function dbg(v,level)
|
||||
if type(v)=="table" then
|
||||
for key, value in pairs(v) do
|
||||
DLOG(string.rep(" ",2*level).."."..key)
|
||||
DLOG(string.rep(" ",2*level).."."..tostring(key))
|
||||
dbg(v[key],level+1)
|
||||
end
|
||||
elseif type(v)=="string" then
|
||||
@@ -429,6 +498,75 @@ function http_dissect_req(http)
|
||||
local uri = string.sub(req,pos,pnext-1)
|
||||
return { method = method, uri = uri, headers = http_dissect_headers(http,hdrpos) }
|
||||
end
|
||||
function http_dissect_reply(http)
|
||||
if not http then return nil; end
|
||||
local s, pos, code
|
||||
s = string.sub(http,1,8)
|
||||
if s~="HTTP/1.1" and s~="HTTP/1.0" then return nil end
|
||||
pos = string.find(http,"[ \t\r\n]",10)
|
||||
code = tonumber(string.sub(http,10,pos-1))
|
||||
if not code then return nil end
|
||||
pos = find_next_line(http,pos)
|
||||
return { code = code, headers = http_dissect_headers(http,pos) }
|
||||
end
|
||||
function dissect_url(url)
|
||||
local p1,pb,pstart,pend
|
||||
local proto, creds, domain, port, uri
|
||||
p1 = string.find(url,"[^ \t]")
|
||||
if not p1 then return nil end
|
||||
pb = p1
|
||||
pstart,pend = string.find(url,"[a-z]+://",p1)
|
||||
if pend then
|
||||
proto = string.sub(url,pstart,pend-3)
|
||||
p1 = pend+1
|
||||
end
|
||||
pstart,pend = string.find(url,"[@/]",p1)
|
||||
if pend and string.sub(url,pstart,pend)=='@' then
|
||||
creds = string.sub(url,p1,pend-1)
|
||||
p1 = pend+1
|
||||
end
|
||||
pstart,pend = string.find(url,"/",p1,true)
|
||||
if pend then
|
||||
if pend==pb then
|
||||
uri = string.sub(url,pb)
|
||||
else
|
||||
uri = string.sub(url,pend)
|
||||
domain = string.sub(url,p1,pend-1)
|
||||
end
|
||||
else
|
||||
if proto then
|
||||
domain = string.sub(url,p1)
|
||||
else
|
||||
uri = string.sub(url,p1)
|
||||
end
|
||||
end
|
||||
if domain then
|
||||
pstart,pend = string.find(domain,':',1,true)
|
||||
if pend then
|
||||
port = string.sub(domain, pend+1)
|
||||
domain = string.sub(domain, 1, pstart-1)
|
||||
end
|
||||
end
|
||||
return { proto = proto, creds = creds, domain = domain, port = port, uri=uri }
|
||||
end
|
||||
function dissect_nld(domain, level)
|
||||
if domain then
|
||||
local n=1
|
||||
for pos=#domain,1,-1 do
|
||||
if string.sub(domain,pos,pos)=='.' then
|
||||
if n==level then
|
||||
return string.sub(domain, pos+1)
|
||||
end
|
||||
n=n+1
|
||||
end
|
||||
end
|
||||
if n==level then
|
||||
return domain
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
-- convert comma separated list of tcp flags to tcp.th_flags bit field
|
||||
function parse_tcp_flags(s)
|
||||
@@ -641,10 +779,10 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
if not dis then dis = desync.dis end
|
||||
if dis.tcp then
|
||||
if tonumber(fooling_options.tcp_seq) then
|
||||
dis.tcp.th_seq = dis.tcp.th_seq + fooling_options.tcp_seq
|
||||
dis.tcp.th_seq = u32add(dis.tcp.th_seq, fooling_options.tcp_seq)
|
||||
end
|
||||
if tonumber(fooling_options.tcp_ack) then
|
||||
dis.tcp.th_ack = dis.tcp.th_ack + fooling_options.tcp_ack
|
||||
dis.tcp.th_ack = u32add(dis.tcp.th_ack, fooling_options.tcp_ack)
|
||||
end
|
||||
if fooling_options.tcp_flags_unset then
|
||||
dis.tcp.th_flags = bitand(dis.tcp.th_flags, bitnot(parse_tcp_flags(fooling_options.tcp_flags_unset)))
|
||||
@@ -655,7 +793,7 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
if tonumber(fooling_options.tcp_ts) then
|
||||
local idx = find_tcp_option(dis.tcp.options,TCP_KIND_TS)
|
||||
if idx and (dis.tcp.options[idx].data and #dis.tcp.options[idx].data or 0)==8 then
|
||||
dis.tcp.options[idx].data = bu32(u32(dis.tcp.options[idx].data)+fooling_options.tcp_ts)..string.sub(dis.tcp.options[idx].data,5)
|
||||
dis.tcp.options[idx].data = bu32(u32add(u32(dis.tcp.options[idx].data),fooling_options.tcp_ts))..string.sub(dis.tcp.options[idx].data,5)
|
||||
else
|
||||
DLOG("apply_fooling: timestamp tcp option not present or invalid")
|
||||
end
|
||||
@@ -872,7 +1010,6 @@ end
|
||||
-- send dissect with tcp segmentation based on mss value. appply specified rawsend options.
|
||||
function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
local discopy = deepcopy(dis)
|
||||
apply_ip_id(desync, discopy, options and options.ipid)
|
||||
apply_fooling(desync, discopy, options and options.fooling)
|
||||
|
||||
if dis.tcp then
|
||||
@@ -888,6 +1025,7 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
len = #payload - pos + 1
|
||||
if len > max_data then len = max_data end
|
||||
discopy.payload = string.sub(payload,pos,pos+len-1)
|
||||
apply_ip_id(desync, discopy, options and options.ipid)
|
||||
if not rawsend_dissect_ipfrag(discopy, options) then
|
||||
-- stop if failed
|
||||
return false
|
||||
@@ -898,6 +1036,7 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
return true
|
||||
end
|
||||
end
|
||||
apply_ip_id(desync, discopy, options and options.ipid)
|
||||
-- no reason to segment
|
||||
return rawsend_dissect_ipfrag(discopy, options)
|
||||
end
|
||||
@@ -924,10 +1063,10 @@ function direction_cutoff_opposite(ctx, desync, def)
|
||||
local dir = desync.arg.dir or def or "out"
|
||||
if dir=="out" then
|
||||
-- cutoff in
|
||||
instance_cutoff(ctx, false)
|
||||
instance_cutoff_shim(ctx, desync, false)
|
||||
elseif dir=="in" then
|
||||
-- cutoff out
|
||||
instance_cutoff(ctx, true)
|
||||
instance_cutoff_shim(ctx, desync, true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1015,6 +1154,14 @@ function genhost(len, template)
|
||||
end
|
||||
end
|
||||
|
||||
-- return hostname if present or ip address in text form otherwise
|
||||
function host_or_ip(desync)
|
||||
if desync.track and desync.track.hostname then
|
||||
return desync.track.hostname
|
||||
end
|
||||
return desync.target.ip and ntop(desync.target.ip) or desync.target.ip6 and ntop(desync.target.ip6)
|
||||
end
|
||||
|
||||
function is_absolute_path(path)
|
||||
if string.sub(path,1,1)=='/' then return true end
|
||||
local un = uname()
|
||||
@@ -1163,3 +1310,16 @@ function ipfrag2(dis, ipfrag_options)
|
||||
|
||||
return {dis1,dis2}
|
||||
end
|
||||
|
||||
|
||||
-- location is url compatible with Location: header
|
||||
-- hostname is original hostname
|
||||
function is_dpi_redirect(hostname, location)
|
||||
local ds = dissect_url(location)
|
||||
if ds.domain then
|
||||
local sld1 = dissect_nld(hostname,2)
|
||||
local sld2 = dissect_nld(ds.domain,2)
|
||||
return sld2 and sld1~=sld2
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -264,8 +264,8 @@ end
|
||||
function test_bit()
|
||||
local v, v2, v3, v4, b1, b2, pow
|
||||
|
||||
v = math.random(0,0xFFFFFFFFFFFF)
|
||||
b1 = math.random(1,15)
|
||||
v = math.random(0,0xFFFFFFFF)
|
||||
b1 = math.random(1,16)
|
||||
|
||||
v2 = bitrshift(v, b1)
|
||||
pow = 2^b1
|
||||
@@ -275,17 +275,17 @@ function test_bit()
|
||||
|
||||
v2 = bitlshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = v * pow
|
||||
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u = 0x%X", v,b1,v2, v,pow,v3))
|
||||
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)
|
||||
|
||||
v2 = math.random(0,0xFFFFFFFFFFFF)
|
||||
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)
|
||||
|
||||
b2 = b1 + math.random(1,31)
|
||||
b2 = b1 + math.random(1,15)
|
||||
v2 = bitget(v, b1, b2)
|
||||
pow = 2^(b2-b1+1) - 1
|
||||
v3 = bitand(bitrshift(v,b1), pow)
|
||||
@@ -299,8 +299,32 @@ function test_bit()
|
||||
test_assert(v2==v3)
|
||||
end
|
||||
|
||||
function test_ux()
|
||||
local v1, v2, v3, usum, sum
|
||||
for k,test in pairs({
|
||||
{ add=u8add, fname="u8add", max = 0xFF },
|
||||
{ add=u16add, fname="u16add", max = 0xFFFF },
|
||||
{ add=u24add, fname="u24add", max = 0xFFFFFF },
|
||||
{ add=u32add, fname="u32add", max = 0xFFFFFFFF }
|
||||
}) do
|
||||
io.write(test.fname.." : ")
|
||||
for i=1,1000 do
|
||||
v1=math.random(-test.max,test.max)
|
||||
v2=math.random(-test.max,test.max)
|
||||
v3=math.random(-test.max,test.max)
|
||||
usum = test.add(v1,v2,v3)
|
||||
sum = bitand((v1+v2+v3)%(test.max+1),test.max)
|
||||
if sum~=usum then
|
||||
print("FAIL")
|
||||
end
|
||||
test_assert(sum==usum)
|
||||
end
|
||||
print("OK")
|
||||
end
|
||||
end
|
||||
|
||||
function test_bin(...)
|
||||
test_run({test_ub, test_bit},...)
|
||||
test_run({test_ub, test_bit, test_ux},...)
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -647,7 +647,9 @@ static uint8_t desync(
|
||||
t_ctrack *ctrack,
|
||||
const t_ctrack_position *pos,
|
||||
t_l7payload l7payload,
|
||||
t_l7proto l7proto,
|
||||
const struct dissect *dis,
|
||||
const struct in_addr *sdp4, const struct in6_addr *sdp6, uint16_t sdport,
|
||||
uint8_t *mod_pkt, size_t *len_mod_pkt,
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset, const uint8_t *rdata_payload, size_t rlen_payload,
|
||||
const uint8_t *data_decrypt, size_t len_decrypt)
|
||||
@@ -677,6 +679,9 @@ static uint8_t desync(
|
||||
}
|
||||
if (!pos) pos = &ctrack->pos;
|
||||
}
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
if (LIST_FIRST(&dp->lua_desync))
|
||||
{
|
||||
b_cutoff_all = b_unwanted_payload = true;
|
||||
@@ -732,7 +737,13 @@ static uint8_t desync(
|
||||
lua_pushf_bool("outgoing", !bIncoming);
|
||||
lua_pushf_str("ifin", (ifin && *ifin) ? ifin : NULL);
|
||||
lua_pushf_str("ifout", (ifout && *ifout) ? ifout : NULL);
|
||||
lua_pushf_int("fwmark", fwmark);
|
||||
lua_pushf_lint("fwmark", fwmark);
|
||||
lua_pushf_table("target");
|
||||
lua_getfield(params.L,-1,"target");
|
||||
if (sdport) lua_pushf_int("port",sdport);
|
||||
if (sdp4) lua_pushf_lstr("ip",(const char*)sdp4,sizeof(*sdp4));
|
||||
if (sdp6) lua_pushf_lstr("ip6",(const char*)sdp6,sizeof(*sdp6));
|
||||
lua_pop(params.L,1);
|
||||
lua_pushf_bool("replay", !!replay_piece_count);
|
||||
if (replay_piece_count)
|
||||
{
|
||||
@@ -741,10 +752,11 @@ static uint8_t desync(
|
||||
lua_pushf_bool("replay_piece_last", (replay_piece+1)>=replay_piece_count);
|
||||
}
|
||||
lua_pushf_str("l7payload", l7payload_str(l7payload));
|
||||
lua_pushf_str("l7proto", l7proto_str(l7proto));
|
||||
lua_pushf_int("reasm_offset", reasm_offset);
|
||||
lua_pushf_raw("reasm_data", rdata_payload, rlen_payload);
|
||||
lua_pushf_raw("decrypt_data", data_decrypt, len_decrypt);
|
||||
if (ctrack) lua_pushf_reg("instance_cutoff", ctrack->lua_instance_cutoff);
|
||||
//if (ctrack) lua_pushf_reg("instance_cutoff", ctrack->lua_instance_cutoff);
|
||||
if (dis->tcp)
|
||||
{
|
||||
// recommended mss value for generated packets
|
||||
@@ -864,6 +876,7 @@ static uint8_t desync(
|
||||
DLOG("no lua functions in this profile\n");
|
||||
ex:
|
||||
luaL_unref(params.L, LUA_REGISTRYINDEX, ref_arg);
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return verdict;
|
||||
err:
|
||||
DLOG_ERR("desync ERROR. passing packet unmodified.\n");
|
||||
@@ -1354,7 +1367,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2));
|
||||
DLOG("dpi desync src=%s dst=%s track_direction=%s fixed_direction=%s connection_proto=%s payload_type=%s\n", s1, s2, bReverse ? "in" : "out", bReverseFixed ? "in" : "out", l7proto_str(l7proto), l7payload_str(l7payload));
|
||||
}
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, pos, l7payload, dis, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, rdata_payload, rlen_payload, NULL, 0);
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, pos, l7payload, l7proto, dis, sdip4, sdip6, sdport, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, rdata_payload, rlen_payload, NULL, 0);
|
||||
|
||||
pass:
|
||||
return (!bReverseFixed && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
||||
@@ -1810,7 +1823,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2));
|
||||
DLOG("dpi desync src=%s dst=%s track_direction=%s fixed_direction=%s connection_proto=%s payload_type=%s\n", s1, s2, bReverse ? "in" : "out", bReverseFixed ? "in" : "out", l7proto_str(l7proto), l7payload_str(l7payload));
|
||||
}
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, pos, l7payload, dis, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, NULL, 0, data_decrypt, len_decrypt);
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, pos, l7payload, l7proto, dis, sdip4, sdip6, sdport, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, NULL, 0, data_decrypt, len_decrypt);
|
||||
|
||||
pass:
|
||||
return (!bReverse && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
||||
|
||||
280
nfq2/lua.c
280
nfq2/lua.c
@@ -68,72 +68,100 @@ static int luacall_DLOG_CONDUP(lua_State *L)
|
||||
static int luacall_bitlshift(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitlshift",2);
|
||||
lua_pushinteger(L,luaL_checkinteger(L,1) << luaL_checkinteger(L,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));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitrshift(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitrshift",2);
|
||||
lua_pushinteger(L,((LUA_UNSIGNED)luaL_checkinteger(L,1)) >> luaL_checkinteger(L,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));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitand(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"bitand",2,100);
|
||||
int argc = lua_gettop(L);
|
||||
lua_Integer v=luaL_checkinteger(L,1);
|
||||
for(int i=2;i<=argc;i++) v&=luaL_checkinteger(L,i);
|
||||
lua_pushinteger(L,v);
|
||||
int64_t v;
|
||||
uint32_t sum=0xFFFFFFFF;
|
||||
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;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitor(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"bitor",2,100);
|
||||
lua_check_argc_range(L,"bitor",1,100);
|
||||
int argc = lua_gettop(L);
|
||||
lua_Integer v=0;
|
||||
for(int i=1;i<=argc;i++) v|=luaL_checkinteger(L,i);
|
||||
lua_pushinteger(L,v);
|
||||
int64_t v;
|
||||
uint32_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;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitnot(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot",1);
|
||||
lua_pushinteger(L,~luaL_checkinteger(L,1));
|
||||
lua_pushlint(L,~(uint32_t)luaL_checklint(L,1));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitxor(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"bitxor",2,100);
|
||||
lua_check_argc_range(L,"bitxor",1,100);
|
||||
int argc = lua_gettop(L);
|
||||
lua_Integer v=0;
|
||||
for(int i=1;i<=argc;i++) v^=luaL_checkinteger(L,i);
|
||||
lua_pushinteger(L,v);
|
||||
int64_t v;
|
||||
uint32_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;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitget(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitget",3);
|
||||
|
||||
LUA_UNSIGNED what = (LUA_UNSIGNED)luaL_checkinteger(L,1);
|
||||
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;
|
||||
lua_Integer from = luaL_checkinteger(L,2);
|
||||
lua_Integer to = luaL_checkinteger(L,3);
|
||||
if (from>to || from>63 || to>63)
|
||||
if (from>to || from>31 || to>31)
|
||||
luaL_error(L, "bit range invalid");
|
||||
|
||||
what = (what >> from) & ~((lua_Integer)-1 << (to-from+1));
|
||||
|
||||
lua_pushinteger(L,what);
|
||||
lua_pushlint(L,what);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitset(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitset",4);
|
||||
|
||||
LUA_UNSIGNED what = (LUA_UNSIGNED)luaL_checkinteger(L,1);
|
||||
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;
|
||||
lua_Integer from = luaL_checkinteger(L,2);
|
||||
lua_Integer to = luaL_checkinteger(L,3);
|
||||
LUA_UNSIGNED set = (LUA_UNSIGNED)luaL_checkinteger(L,4);
|
||||
if (from>to || from>63 || to>63)
|
||||
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)
|
||||
luaL_error(L, "bit range invalid");
|
||||
|
||||
lua_Integer mask = ~((lua_Integer)-1 << (to-from+1));
|
||||
@@ -141,7 +169,7 @@ static int luacall_bitset(lua_State *L)
|
||||
mask <<= from;
|
||||
what = what & ~mask | set;
|
||||
|
||||
lua_pushinteger(L,what);
|
||||
lua_pushlint(L,what);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -198,15 +226,15 @@ static int luacall_u32(lua_State *L)
|
||||
offset = (argc>=2 && lua_type(L,2)!=LUA_TNIL) ? luaL_checkinteger(L,2)-1 : 0;
|
||||
if (offset<0 || (offset+4)>l) luaL_error(L, "out of range");
|
||||
|
||||
lua_pushinteger(L,pntoh32(p+offset));
|
||||
lua_pushlint(L,pntoh32(p+offset));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_swap16(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"swap16",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i>0xFFFF || i<-(lua_Integer)0xFFFF) luaL_error(L, "out of range");
|
||||
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));
|
||||
@@ -216,17 +244,52 @@ static int luacall_swap32(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"swap32",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i>0xFFFFFFFF || i<-(lua_Integer)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
int64_t i =(int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFFFFFFFF || i<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint32_t u = (uint32_t)i;
|
||||
lua_pushinteger(L,__builtin_bswap32(u));
|
||||
lua_pushlint(L,__builtin_bswap32(u));
|
||||
return 1;
|
||||
}
|
||||
static int lua_uxadd(lua_State *L, uint32_t max)
|
||||
{
|
||||
int64_t v;
|
||||
uint32_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;
|
||||
}
|
||||
lua_pushlint(L, sum & max);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_u8add(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"u8add",1,100);
|
||||
return lua_uxadd(L, 0xFF);
|
||||
}
|
||||
static int luacall_u16add(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"u16add",1,100);
|
||||
return lua_uxadd(L, 0xFFFF);
|
||||
}
|
||||
static int luacall_u24add(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"u24add",1,100);
|
||||
return lua_uxadd(L, 0xFFFFFF);
|
||||
}
|
||||
static int luacall_u32add(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"u32add",1,100);
|
||||
return lua_uxadd(L, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static int luacall_bu8(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bu8",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
int64_t i = (int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFF || i<-(lua_Integer)0xFF) luaL_error(L, "out of range");
|
||||
uint8_t v=(uint8_t)i;
|
||||
lua_pushlstring(L,(char*)&v,1);
|
||||
@@ -236,7 +299,7 @@ static int luacall_bu16(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bu16",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
int64_t i = (int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFFFF || i<-(lua_Integer)0xFFFF) luaL_error(L, "out of range");
|
||||
uint8_t v[2];
|
||||
phton16(v,(uint16_t)i);
|
||||
@@ -247,7 +310,7 @@ static int luacall_bu24(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bu24",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
int64_t i = (int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFFFFFF || i<-(lua_Integer)0xFFFFFF) luaL_error(L, "out of range");
|
||||
uint8_t v[3];
|
||||
phton24(v,(uint32_t)i);
|
||||
@@ -258,8 +321,8 @@ static int luacall_bu32(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bu32",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i>0xFFFFFFFF || i<-(lua_Integer)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
int64_t i = (int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFFFFFFFF || i<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint8_t v[4];
|
||||
phton32(v,(uint32_t)i);
|
||||
lua_pushlstring(L,(char*)v,4);
|
||||
@@ -269,10 +332,10 @@ static int luacall_bu32(lua_State *L)
|
||||
static int luacall_divint(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"divint",2);
|
||||
lua_Integer v1=luaL_checkinteger(L,1);
|
||||
lua_Integer v2=luaL_checkinteger(L,2);
|
||||
int64_t v1=(int64_t)luaL_checklint(L,1);
|
||||
int64_t v2=(int64_t)luaL_checklint(L,2);
|
||||
if (v2)
|
||||
lua_pushinteger(L,v1/v2);
|
||||
lua_pushlint(L,v1/v2);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
@@ -622,15 +685,15 @@ static int luacall_clock_gettime(lua_State *L)
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushinteger(L, ts.tv_sec);
|
||||
lua_pushlint(L, ts.tv_sec);
|
||||
lua_pushinteger(L, ts.tv_nsec);
|
||||
}
|
||||
LUA_STACK_GUARD_RETURN(L,2)
|
||||
}
|
||||
static int luacall_instance_cutoff(lua_State *L)
|
||||
{
|
||||
// out : func_name.profile_number[0]
|
||||
// in : func_name.profile_number[1]
|
||||
// out : instance_name.profile_number[0]
|
||||
// in : instance_name.profile_number[1]
|
||||
|
||||
lua_check_argc_range(L,"instance_cutoff",1,2);
|
||||
|
||||
@@ -638,45 +701,51 @@ static int luacall_instance_cutoff(lua_State *L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "instance_cutoff expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
bool bIn,bOut;
|
||||
if (argc>=2 && lua_type(L,2)!=LUA_TNIL)
|
||||
{
|
||||
luaL_checktype(L,2,LUA_TBOOLEAN);
|
||||
bOut = lua_toboolean(L,2);
|
||||
bIn = !bOut;
|
||||
}
|
||||
if (lua_isnil(L,1))
|
||||
// this can happen in orchestrated function. they do not have their own ctx and they cant cutoff
|
||||
DLOG("instance cutoff not possible because missing ctx\n");
|
||||
else
|
||||
bIn = bOut = true;
|
||||
|
||||
if (ctx->ctrack)
|
||||
{
|
||||
DLOG("instance cutoff for '%s' in=%u out=%u\n",ctx->instance,bIn,bOut);
|
||||
lua_rawgeti(L,LUA_REGISTRYINDEX,ctx->ctrack->lua_instance_cutoff);
|
||||
lua_getfield(L,-1,ctx->instance);
|
||||
if (!lua_istable(L,-1))
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "instance_cutoff expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
bool bIn,bOut;
|
||||
if (argc>=2 && lua_type(L,2)!=LUA_TNIL)
|
||||
{
|
||||
lua_pop(L,1);
|
||||
lua_pushf_table(ctx->instance);
|
||||
luaL_checktype(L,2,LUA_TBOOLEAN);
|
||||
bOut = lua_toboolean(L,2);
|
||||
bIn = !bOut;
|
||||
}
|
||||
else
|
||||
bIn = bOut = true;
|
||||
|
||||
if (ctx->ctrack)
|
||||
{
|
||||
DLOG("instance cutoff for '%s' in=%u out=%u\n",ctx->instance,bIn,bOut);
|
||||
lua_rawgeti(L,LUA_REGISTRYINDEX,ctx->ctrack->lua_instance_cutoff);
|
||||
lua_getfield(L,-1,ctx->instance);
|
||||
}
|
||||
lua_rawgeti(L,-1,ctx->dp->n);
|
||||
if (!lua_istable(L,-1))
|
||||
{
|
||||
lua_pop(L,1);
|
||||
lua_pushi_table(ctx->dp->n);
|
||||
if (!lua_istable(L,-1))
|
||||
{
|
||||
lua_pop(L,1);
|
||||
lua_pushf_table(ctx->instance);
|
||||
lua_getfield(L,-1,ctx->instance);
|
||||
}
|
||||
lua_rawgeti(L,-1,ctx->dp->n);
|
||||
if (!lua_istable(L,-1))
|
||||
{
|
||||
lua_pop(L,1);
|
||||
lua_pushi_table(ctx->dp->n);
|
||||
lua_rawgeti(L,-1,ctx->dp->n);
|
||||
}
|
||||
if (bOut) lua_pushi_bool(0,true);
|
||||
if (bIn) lua_pushi_bool(1,true);
|
||||
lua_pop(L,3);
|
||||
}
|
||||
if (bOut) lua_pushi_bool(0,true);
|
||||
if (bIn) lua_pushi_bool(1,true);
|
||||
lua_pop(L,3);
|
||||
else
|
||||
DLOG("instance cutoff requested for '%s' in=%u out=%u but not possible without conntrack\n",ctx->instance,bIn,bOut);
|
||||
}
|
||||
else
|
||||
DLOG("instance cutoff requested for '%s' in=%u out=%u but not possible without conntrack\n",ctx->instance,bIn,bOut);
|
||||
|
||||
LUA_STACK_GUARD_RETURN(L,0)
|
||||
}
|
||||
@@ -839,13 +908,25 @@ void lua_pushi_nil(lua_Integer idx)
|
||||
void lua_pushf_int(const char *field, lua_Integer v)
|
||||
{
|
||||
lua_pushstring(params.L, field);
|
||||
lua_pushinteger(params.L, v);
|
||||
lua_pushlint(params.L, v);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushi_int(lua_Integer idx, lua_Integer v)
|
||||
{
|
||||
lua_pushinteger(params.L, idx);
|
||||
lua_pushinteger(params.L, v);
|
||||
lua_pushlint(params.L, v);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushf_lint(const char *field, int64_t v)
|
||||
{
|
||||
lua_pushstring(params.L, field);
|
||||
lua_pushlint(params.L, v);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushi_lint(lua_Integer idx, int64_t v)
|
||||
{
|
||||
lua_pushinteger(params.L, idx);
|
||||
lua_pushlint(params.L, v);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushf_bool(const char *field, bool b)
|
||||
@@ -872,6 +953,18 @@ void lua_pushi_str(lua_Integer idx, const char *str)
|
||||
lua_pushstring(params.L, str); // pushes nil if str==NULL
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushf_lstr(const char *field, const char *str, size_t size)
|
||||
{
|
||||
lua_pushstring(params.L, field);
|
||||
lua_pushlstring(params.L, str, size);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_pushi_lstr(lua_Integer idx, const char *str, size_t size)
|
||||
{
|
||||
lua_pushinteger(params.L, idx);
|
||||
lua_pushlstring(params.L, str, size);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
void lua_push_raw(const void *v, size_t l)
|
||||
{
|
||||
if (v)
|
||||
@@ -990,8 +1083,8 @@ void lua_pushf_tcphdr(const struct tcphdr *tcp, size_t len)
|
||||
lua_createtable(params.L, 0, 11);
|
||||
lua_pushf_int("th_sport",ntohs(tcp->th_sport));
|
||||
lua_pushf_int("th_dport",ntohs(tcp->th_dport));
|
||||
lua_pushf_int("th_seq",ntohl(tcp->th_seq));
|
||||
lua_pushf_int("th_ack",ntohl(tcp->th_ack));
|
||||
lua_pushf_lint("th_seq",ntohl(tcp->th_seq));
|
||||
lua_pushf_lint("th_ack",ntohl(tcp->th_ack));
|
||||
lua_pushf_int("th_x2",tcp->th_x2);
|
||||
lua_pushf_int("th_off",tcp->th_off);
|
||||
lua_pushf_int("th_flags",tcp->th_flags);
|
||||
@@ -1126,8 +1219,8 @@ void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len)
|
||||
if (ip6)
|
||||
{
|
||||
lua_createtable(params.L, 0, 7);
|
||||
lua_pushf_int("ip6_flow",ntohl(ip6->ip6_ctlun.ip6_un1.ip6_un1_flow));
|
||||
lua_pushf_int("ip6_plen",ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen));
|
||||
lua_pushf_lint("ip6_flow",ntohl(ip6->ip6_ctlun.ip6_un1.ip6_un1_flow));
|
||||
lua_pushf_lint("ip6_plen",ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen));
|
||||
lua_pushf_int("ip6_nxt",ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt);
|
||||
lua_pushf_int("ip6_hlim",ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim);
|
||||
lua_pushf_raw("ip6_src",&ip6->ip6_src,sizeof(struct in6_addr));
|
||||
@@ -1178,12 +1271,12 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
{
|
||||
lua_createtable(params.L, 0, 13 + (ctrack->ipproto == IPPROTO_TCP));
|
||||
|
||||
lua_pushf_int("pcounter_orig", pos->pcounter_orig);
|
||||
lua_pushf_int("pdcounter_orig", pos->pdcounter_orig);
|
||||
lua_pushf_int("pbcounter_orig", pos->pbcounter_orig);
|
||||
lua_pushf_int("pcounter_reply", pos->pcounter_reply);
|
||||
lua_pushf_int("pdcounter_reply", pos->pdcounter_reply);
|
||||
lua_pushf_int("pbcounter_reply", pos->pbcounter_reply);
|
||||
lua_pushf_lint("pcounter_orig", pos->pcounter_orig);
|
||||
lua_pushf_lint("pdcounter_orig", pos->pdcounter_orig);
|
||||
lua_pushf_lint("pbcounter_orig", pos->pbcounter_orig);
|
||||
lua_pushf_lint("pcounter_reply", pos->pcounter_reply);
|
||||
lua_pushf_lint("pdcounter_reply", pos->pdcounter_reply);
|
||||
lua_pushf_lint("pbcounter_reply", pos->pbcounter_reply);
|
||||
if (ctrack->incoming_ttl)
|
||||
lua_pushf_int("incoming_ttl", ctrack->incoming_ttl);
|
||||
else
|
||||
@@ -1199,10 +1292,10 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
{
|
||||
lua_pushliteral(params.L, "tcp");
|
||||
lua_createtable(params.L, 0, 14);
|
||||
lua_pushf_int("seq0", pos->seq0);
|
||||
lua_pushf_int("seq", pos->seq_last);
|
||||
lua_pushf_int("ack0", pos->ack0);
|
||||
lua_pushf_int("ack", pos->ack_last);
|
||||
lua_pushf_lint("seq0", pos->seq0);
|
||||
lua_pushf_lint("seq", pos->seq_last);
|
||||
lua_pushf_lint("ack0", pos->ack0);
|
||||
lua_pushf_lint("ack", pos->ack_last);
|
||||
lua_pushf_int("pos_orig", pos->pos_orig - pos->seq0);
|
||||
lua_pushf_int("winsize_orig", pos->winsize_orig);
|
||||
lua_pushf_int("winsize_orig_calc", pos->winsize_orig_calc);
|
||||
@@ -1272,7 +1365,7 @@ void lua_pushf_pos(const char *name, const struct packet_pos *pos)
|
||||
lua_getfield(params.L,-1,name);
|
||||
*smode=pos->mode;
|
||||
lua_pushf_str("mode",smode);
|
||||
lua_pushf_int("pos",pos->pos);
|
||||
lua_pushf_lint("pos",pos->pos);
|
||||
lua_pop(params.L,1);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
@@ -1406,7 +1499,7 @@ bool lua_reconstruct_ip6hdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t l
|
||||
idx = lua_absindex(params.L, idx);
|
||||
|
||||
lua_getfield(params.L,idx,"ip6_flow");
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(lua_type(params.L,-1)==LUA_TNUMBER ? (uint32_t)lua_tointeger(params.L,-1) : 0x60000000);
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(lua_type(params.L,-1)==LUA_TNUMBER ? (uint32_t)lua_tolint(params.L,-1) : 0x60000000);
|
||||
lua_pop(params.L, 1);
|
||||
|
||||
lua_getfield(params.L,idx,"ip6_plen");
|
||||
@@ -1666,12 +1759,12 @@ bool lua_reconstruct_tcphdr(int idx, struct tcphdr *tcp, size_t *len)
|
||||
|
||||
lua_getfield(params.L,idx,"th_seq");
|
||||
if (lua_type(params.L,-1)!=LUA_TNUMBER) goto err;
|
||||
tcp->th_seq = htonl((uint32_t)lua_tointeger(params.L,-1));
|
||||
tcp->th_seq = htonl((uint32_t)lua_tolint(params.L,-1));
|
||||
lua_pop(params.L, 1);
|
||||
|
||||
lua_getfield(params.L,idx,"th_ack");
|
||||
if (lua_type(params.L,-1)!=LUA_TNUMBER) goto err;
|
||||
tcp->th_ack = htonl((uint32_t)lua_tointeger(params.L,-1));
|
||||
tcp->th_ack = htonl((uint32_t)lua_tolint(params.L,-1));
|
||||
lua_pop(params.L, 1);
|
||||
|
||||
lua_getfield(params.L,idx,"th_x2");
|
||||
@@ -2146,7 +2239,7 @@ static void lua_rawsend_extract_options(lua_State *L, int idx, int *repeats, uin
|
||||
if (fwmark)
|
||||
{
|
||||
lua_getfield(L,idx,"fwmark");
|
||||
*fwmark=(uint32_t)lua_tointeger(L,-1) | params.desync_fwmark;
|
||||
*fwmark=(uint32_t)lua_tolint(L,-1) | params.desync_fwmark;
|
||||
lua_pop(L,1);
|
||||
}
|
||||
if (ifout)
|
||||
@@ -2948,6 +3041,11 @@ static void lua_init_functions(void)
|
||||
{"u16",luacall_u16},
|
||||
{"u24",luacall_u24},
|
||||
{"u32",luacall_u32},
|
||||
// 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},
|
||||
// convert number to blob (string) - big endian
|
||||
{"bu8",luacall_bu8},
|
||||
{"bu16",luacall_bu16},
|
||||
|
||||
15
nfq2/lua.h
15
nfq2/lua.h
@@ -22,6 +22,17 @@
|
||||
#define LUA_UNSIGNED uint64_t
|
||||
#endif
|
||||
|
||||
// in old lua integer is 32 bit on 32 bit platforms and 64 bit on 64 bit platforms
|
||||
#if LUA_VERSION_NUM < 503 && __SIZEOF_POINTER__==4
|
||||
#define lua_pushlint lua_pushnumber
|
||||
#define lua_tolint lua_tonumber
|
||||
#define luaL_checklint luaL_checknumber
|
||||
#else
|
||||
#define lua_pushlint lua_pushinteger
|
||||
#define luaL_checklint luaL_checkinteger
|
||||
#define lua_tolint lua_tointeger
|
||||
#endif
|
||||
|
||||
// pushing and not popping inside luacall cause memory leak
|
||||
#define LUA_STACK_GUARD_ENTER(L) int _lsg=lua_gettop(L);
|
||||
#define LUA_STACK_GUARD_LEAVE(L,N) if ((_lsg+N)!=lua_gettop(L)) luaL_error(L,"stack guard failure");
|
||||
@@ -51,8 +62,12 @@ void lua_pushf_bool(const char *field, bool b);
|
||||
void lua_pushi_bool(lua_Integer idx, bool b);
|
||||
void lua_pushf_str(const char *field, const char *str);
|
||||
void lua_pushi_str(lua_Integer idx, const char *str);
|
||||
void lua_pushf_lstr(const char *field, const char *str, size_t len);
|
||||
void lua_pushi_lstr(lua_Integer idx, const char *str, size_t len);
|
||||
void lua_pushf_int(const char *field, lua_Integer v);
|
||||
void lua_pushi_int(lua_Integer idx, lua_Integer v);
|
||||
void lua_pushf_lint(const char *field, int64_t v);
|
||||
void lua_pushi_lint(lua_Integer idx, int64_t v);
|
||||
void lua_push_raw(const void *v, size_t l);
|
||||
void lua_pushf_raw(const char *field, const void *v, size_t l);
|
||||
void lua_pushi_raw(lua_Integer idx, const void *v, size_t l);
|
||||
|
||||
@@ -1283,8 +1283,10 @@ static bool wf_make_filter(
|
||||
|
||||
if (bHaveTCP)
|
||||
{
|
||||
if (dp_list_have_autohostlist(¶ms.desync_profiles))
|
||||
snprintf(wf + strlen(wf), len - strlen(wf), " or\n " DIVERT_HTTP_REDIRECT);
|
||||
// may be required by orchestrators - always redirect
|
||||
// if (dp_list_have_autohostlist(¶ms.desync_profiles))
|
||||
|
||||
snprintf(wf + strlen(wf), len - strlen(wf), " or\n " DIVERT_HTTP_REDIRECT);
|
||||
}
|
||||
|
||||
if (!LIST_EMPTY(wf_raw_part))
|
||||
|
||||
Reference in New Issue
Block a user