From f5b47f1a6e9048e72f1e3b0e0f7c03459e20ca66 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 10 Dec 2023 10:45:31 +0100 Subject: Merging upstream version 1.3.0. Signed-off-by: Daniel Baumann --- examples/pcap2tcpdns.lua | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100755 examples/pcap2tcpdns.lua (limited to 'examples/pcap2tcpdns.lua') diff --git a/examples/pcap2tcpdns.lua b/examples/pcap2tcpdns.lua new file mode 100755 index 0000000..6cb829a --- /dev/null +++ b/examples/pcap2tcpdns.lua @@ -0,0 +1,80 @@ +#!/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 pre‐ambule 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)) -- cgit v1.2.3