1
0
Fork 0
dnsjit/examples/pcap2tcpdns.lua
Daniel Baumann 62c97c4e0a
Adding upstream version 1.3.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-09 08:34:55 +01:00

80 lines
2.3 KiB
Lua
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env dnsjit
-- Author: Petr Špaček (ISC)
-- Convert PCAP with IPv[46] & UDP payloads into TCP-stream binary format as
-- specified by RFC 1035 section "4.2.2. TCP usage". Each packet is preceded by
-- 2-byte preambule which specifies length of the following DNS packet in
-- network byte order, immediately followed by raw bytes of the packet.
--
-- This script does not do any filtering or input sanitation.
-- Outputs raw binary to stdout!
local bit = require("bit")
local ffi = require("ffi")
local input = require("dnsjit.input.pcap").new()
local layer = require("dnsjit.filter.layer").new()
local object = require("dnsjit.core.objects")
local log = require("dnsjit.core.log").new("extract-clients.lua")
local getopt = require("dnsjit.lib.getopt").new({
{ "r", "read", "-", "input file to read, use - for stdin", "?" },
})
local tmpbuf = ffi.new("uint8_t[?]", 2)
local function put_uint16_be(dst, offset, src)
dst[offset] = bit.rshift(bit.band(src, 0xff00), 8)
dst[offset + 1] = bit.band(src, 0xff)
end
log:enable("all")
-- Parse arguments
local args = {}
getopt:parse()
args.read = getopt:val("r")
-- Display help
if getopt:val("help") then
getopt:usage()
return
end
-- Set up input
if args.read ~= "" then
log:notice("using input PCAP "..args.read)
if input:open_offline(args.read) ~= 0 then
log:fatal("failed to open input PCAP "..args.read)
end
else
getopt:usage()
log:fatal("input must be specified, use -r")
end
layer:producer(input)
local produce, pctx = layer:produce()
-- set up output
io.stdout:setvbuf("full")
local obj, obj_pcap_in, obj_ip, obj_udp, obj_pl
local npacketsin = 0
while true do
obj = produce(pctx)
if obj == nil then break end
npacketsin = npacketsin + 1
obj_ip = obj:cast_to(object.IP)
if obj_ip == nil then
obj_ip = obj:cast_to(object.IP6)
end
obj_udp = obj:cast_to(object.UDP)
obj_pl = obj:cast_to(object.PAYLOAD)
obj_pcap_in = obj:cast_to(object.PCAP)
if obj_ip ~= nil and obj_udp ~= nil and obj_pl ~= nil and obj_pcap_in ~= nil then
-- UDP header length is 8 bytes and is included in the ulen field below.
-- RFC 1035 framing has just the DNS message size as two bytes (big-endian).
put_uint16_be(tmpbuf, 0, obj_udp.ulen - 8)
io.stdout:write(ffi.string(tmpbuf, 2))
io.stdout:write(ffi.string(obj_pl.payload, obj_pl.len))
end
end
log:info(string.format("processed %d packets", npacketsin))