op-packages/luci-app-packet-capture/root/usr/libexec/packet_capture
github-actions[bot] 971b549a31 🌈 Sync 2026-07-25 08:33:42
2026-07-25 08:33:42 +08:00

116 lines
2.4 KiB
Lua
Executable File

#!/usr/bin/env lua
local ubus = require "ubus"
local fs = require "nixio.fs"
local conn = ubus.connect()
if not conn then
error("Failed to connect to ubus")
return
end
local args = "-n"
local duration = ""
local workdir = "/var/run/packet_capture"
local filterfile = workdir .. "/tcpdump_filter"
local pcapbase = workdir .. "/capture.pcap"
local outputfile = "/tmp/capture.pcap"
local function validate_args(value)
if type(value) ~= "string" or value == "" then
return false
end
local tokens = {}
for token in value:gmatch("%S+") do
tokens[#tokens + 1] = token
end
local i = 1
while i <= #tokens do
local token = tokens[i]
if token == "-n" or token == "-e" then
i = i + 1
elseif token == "-i" then
if not tokens[i + 1] or not tokens[i + 1]:match("^[%w_.:-]+$") then return false end
i = i + 2
elseif token == "-c" then
if not tokens[i + 1] or not tokens[i + 1]:match("^%d+$") then return false end
i = i + 2
elseif token == "-W" then
if tokens[i + 1] ~= "2" then return false end
i = i + 2
elseif token == "-C" then
if not tokens[i + 1] or not tokens[i + 1]:match("^%d+$") then return false end
i = i + 2
elseif token == "-w" then
if tokens[i + 1] ~= pcapbase then return false end
i = i + 2
elseif token == "-z" then
if tokens[i + 1] ~= "/usr/libexec/packet_capture_stop" then return false end
i = i + 2
elseif token == "-F" then
if tokens[i + 1] ~= filterfile then return false end
i = i + 2
else
return false
end
end
return true
end
if arg[1] ~= nil then
args = arg[1]
if not validate_args(args) then
error("Invalid tcpdump arguments")
end
if arg[2] ~= nil and arg[2] ~= "" then
duration = arg[2]
if not duration:match("^%d+$") then
error("Invalid duration")
end
end
end
local filter = fs.stat(filterfile)
if filter then
args = args .. " -F " .. filterfile
end
local ubus_objects = {
tcpdump = {
}
}
conn:add( ubus_objects )
os.execute("sleep 1")
local command = "tcpdump -l " .. args .. " 2>&1"
if duration ~= "" then
command = "timeout " .. duration .. " " .. command
end
local pipe = io.popen(command)
for line in pipe:lines() do
local params = {
data = line
}
conn:notify(ubus_objects.tcpdump.__ubusobj, "tcpdump.data", params)
end
local pcap = fs.stat(pcapbase .. "0")
if pcap then
fs.move(pcapbase .. "0", outputfile)
fs.remove(pcapbase .. "1")
end
if filter then
fs.remove(filterfile)
end
conn:close()
pipe:close()
fs.remove("/var/run/packet_capture.pid")