Skip to content

Commit

Permalink
Clients, responses and objects
Browse files Browse the repository at this point in the history
- `README`/`examples/readme.lua`: Update example to use `filter.coro`
- `examples/dumpdns-qr.lua`: Use `core.objects`, `filter.coro` and local variables
- `examples/dumpdns.lua`: Use `core.objects`, `filter.coro` and `core.object.dns:print()`
- `examples/filter_rcode.lua`: Use `core.objects` and `filter.coro`
- `examples/playqr.lua`: Add example of replaying DNS queries and showing the original response vs received response
- `examples/replay.lua`:
  - Add `-t` to use `output.tcpcli`
  - Add `-u` to use `output.udpcli`
  - Use `core.object.dns:print()`
- `core.compat`: Add documentation
- `core.object`:
  - Add `core.object.payload`
  - `core_object_copy()`: Disable copying of `core.object.udp`
- `core.object.dns`:
  - Issue DNS-OARC#39: Parse `core.object.payload` instead of `core.object.udp`
  - Add `rr_reset()` to reset the walking of resource records
  - Add `print()` to print the DNS message
- `core.object.ip`:
  - Remove payload attributes in favor of `core.object.payload`
  - Add `source()` and `destination()` to get a string representation of the IP addresses
- `core.object.ip6`:
  - Remove payload attributes in favor of `core.object.payload`
  - Add `source(pretty)` and `destination(pretty)` to get a string representation of the IP addresses, if `pretty` is true then return easier to read addresses (RFC 5952)
- `core.object.payload`: Add new object to hold the payload of any other object with the option to have padding
- `core.object.tcp`: Remove payload attributes in favor of `core.object.payload`
- `core.object.udp`: Remove payload attributes in favor of `core.object.payload`
- `core.objects`: Add new module to easier `require()` all objects
- `filter.coro`: Handle error on resume
- `filter.layer`: Use `core.object.payload` for all payloads
- `core.output.tcpcli`:
  - Use `core.object.payload` on receive instead of `core.object.tcp` or `core.object.udp`
  - Issue DNS-OARC#47: Add producer to receive responses
  - Use non-blocking mode as default
- `core.output.udpcli`:
  - Use `core.object.payload` on receive instead of `core.object.tcp` or `core.object.udp`
  - Issue DNS-OARC#46: Add producer to receive responses
  - Use non-blocking mode as default
  • Loading branch information
jelu committed May 10, 2018
1 parent 163de2c commit 78fe01a
Show file tree
Hide file tree
Showing 45 changed files with 1,044 additions and 317 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ Shebang-style:
Following example display the DNS ID found in queries.

```lua
require("dnsjit.core.objects")
local input = require("dnsjit.input.pcapthread").new()
local output = require("dnsjit.filter.lua").new()
local output = require("dnsjit.filter.coro").new()

output:func(function(filter, object)
local packet = object:cast()
local dns = require("dnsjit.core.object.dns").new(packet)
if dns:parse() == 0 then
local dns = require("dnsjit.core.object.dns").new(object)
if dns and dns:parse() == 0 then
print(dns.id)
end
end)
Expand Down
12 changes: 6 additions & 6 deletions examples/dumpdns-qr.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ if pcap == nil then
return
end

require("dnsjit.core.object")
require("dnsjit.core.object.packet")
require("dnsjit.core.objects")

c = require("dnsjit.filter.coro").new()
queries = {}
responses = {}
local c = require("dnsjit.filter.coro").new()
local queries = {}
local responses = {}
c:func(function(c,o)
local dns = require("dnsjit.core.object.dns").new(o)
local pkt = o:cast()
Expand Down Expand Up @@ -41,12 +40,13 @@ c:func(function(c,o)
end
end)

i = require("dnsjit.input.pcapthread").new()
local i = require("dnsjit.input.pcapthread").new()
i:receiver(c)
i:open_offline(pcap)
i:run()

print("src", "dst", "id", "rcode", "qname", "qtype")
local q, r
for _, q in pairs(queries) do
for _, r in pairs(responses) do
if q.id == r.id and q.sport == r.dport and q.dport == r.sport and q.src == r.dst and q.dst == r.src then
Expand Down
65 changes: 7 additions & 58 deletions examples/dumpdns.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,68 +6,17 @@ if pcap == nil then
return
end

require("dnsjit.core.objects")

local input = require("dnsjit.input.pcapthread").new()
local output = require("dnsjit.filter.lua").new()
local output = require("dnsjit.filter.coro").new()

output:func(function(filter, obj)
require("dnsjit.core.object.packet")
local pkt = obj:cast()
local dns
if pkt:type() == "packet" then
dns = require("dnsjit.core.object.dns").new(obj)
if dns:parse() ~= 0 then
return
end
elseif pkt:type() == "dns" then
dns = pkt
if dns:parse() ~= 0 then
return
end
pkt = dns:prev()
while pkt ~= nil do
if pkt:type() == "packet" then
pkt = pkt:cast()
break
end
pkt = pkt:prev()
end
if pkt == nil then
return
end
else
return
end

print(pkt:src()..":"..pkt.sport.." -> "..pkt:dst()..":"..pkt.dport)

print(" id:", dns.id)
local n = dns.questions
while n > 0 and dns:rr_next() == 0 do
if dns:rr_ok() == 1 then
print(" qd:", dns:rr_class(), dns:rr_type(), dns:rr_label())
end
n = n - 1
end
n = dns.answers
while n > 0 and dns:rr_next() == 0 do
if dns:rr_ok() == 1 then
print(" an:", dns:rr_class(), dns:rr_type(), dns:rr_ttl(), dns:rr_label())
end
n = n - 1
end
n = dns.authorities
while n > 0 and dns:rr_next() == 0 do
if dns:rr_ok() == 1 then
print(" ns:", dns:rr_class(), dns:rr_type(), dns:rr_ttl(), dns:rr_label())
end
n = n - 1
end
n = dns.additionals
while n > 0 and dns:rr_next() == 0 do
if dns:rr_ok() == 1 then
print(" ar:", dns:rr_class(), dns:rr_type(), dns:rr_ttl(), dns:rr_label())
end
n = n - 1
local dns = require("dnsjit.core.object.dns").new(obj)
if pkt and dns and dns:parse() == 0 then
print(pkt:src()..":"..pkt.sport.." -> "..pkt:dst()..":"..pkt.dport)
dns:print()
end
end)

Expand Down
40 changes: 7 additions & 33 deletions examples/filter_rcode.lua
Original file line number Diff line number Diff line change
@@ -1,47 +1,21 @@
#!/usr/bin/env dnsjit
local pcap = arg[2]
local rcode = arg[3]
local rcode = tonumber(arg[3])

if pcap == nil or rcode == nil then
print("usage: "..arg[1].." <pcap> <rcode>")
return
end

require("dnsjit.core.objects")

local input = require("dnsjit.input.pcapthread").new()
local output = require("dnsjit.filter.lua").new()
local output = require("dnsjit.filter.coro").new()

output:push(tonumber(rcode))
output:func(function(filter, obj, args)
require("dnsjit.core.object.packet")
output:func(function(filter, obj)
local pkt = obj:cast()
local rcode = unpack(args, 0)
local dns
if pkt:type() == "packet" then
dns = require("dnsjit.core.object.dns").new(obj)
if dns:parse() ~= 0 then
return
end
elseif pkt:type() == "dns" then
dns = pkt
if dns:parse() ~= 0 then
return
end
pkt = dns:prev()
while pkt ~= nil do
if pkt:type() == "packet" then
pkt = pkt:cast()
break
end
pkt = pkt:prev()
end
if pkt == nil then
return
end
else
return
end

if dns.have_rcode == 1 and dns.rcode == rcode then
local dns = require("dnsjit.core.object.dns").new(obj)
if pkt and dns and dns:parse() == 0 and dns.have_rcode == 1 and dns.rcode == rcode then
print(dns.id, pkt:src().." -> "..pkt:dst())
end
end)
Expand Down
120 changes: 120 additions & 0 deletions examples/playqr.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env dnsjit
local ffi = require("ffi")
local getopt = require("dnsjit.lib.getopt").new({
})
local pcap, host, port = unpack(getopt:parse())

if pcap == nil or host == nil or port == nil then
print("usage: "..arg[1].." <pcap> <host> <port>")
return
end

local object = require("dnsjit.core.objects")

function tohex(p, l)
local o, n = "", 0
for n = 0, l do
o = o .. string.format("%02x", p[n])
end
return o
end

local input = require("dnsjit.input.mmpcap").new()
input:open(pcap)
local layer = require("dnsjit.filter.layer").new()
layer:producer(input)

local udpcli, tcpcli
local udprecv, udpctx, tcprecv, tcpctx
local udpprod, tcpprod

local prod, pctx = layer:produce()
local queries = {}
local clipayload = ffi.new("core_object_payload_t")
clipayload.obj_type = object.CORE_OBJECT_PAYLOAD
local cliobject = ffi.cast("core_object_t*", clipayload)

print("id", "query", "original response")
print("", "", "received response")

while true do
local obj = prod(pctx)
if obj == nil then
break
end
local dns = require("dnsjit.core.object.dns").new(obj)
if dns and dns:parse() == 0 then
local ip, proto, payload = obj, obj, obj:cast()
while ip ~= nil and ip:type() ~= "ip" and ip:type() ~= "ip6" do
ip = ip.obj_prev
end
while proto ~= nil and proto:type() ~= "udp" and proto:type() ~= "tcp" do
proto = proto.obj_prev
end
if ip ~= nil and proto ~= nil then
ip = ip:cast()
proto = proto:cast()
if dns.qr == 0 then
local k = string.format("%s %d %s %d", ip:source(), proto.sport, ip:destination(), proto.dport)
local q = {
id = dns.id,
proto = proto:type(),
payload = ffi.new("uint8_t[?]", payload.len),
len = tonumber(payload.len)
}
ffi.copy(q.payload, payload.payload, payload.len)
queries[k] = q
else
local k = string.format("%s %d %s %d", ip:destination(), proto.dport, ip:source(), proto.sport)
local q = queries[k]
if q then
queries[k] = nil
clipayload.payload = q.payload
clipayload.len = q.len

local responses, response = {}, nil
if q.proto == "udp" then
if not udpcli then
udpcli = require("dnsjit.output.udpcli").new()
udpcli:connect(host, port)
udprecv, udpctx = udpcli:receive()
udpprod, _ = udpcli:produce()
end
udprecv(udpctx, cliobject)
while response == nil do
response = udpprod(udpctx)
end
while response ~= nil do
table.insert(responses, response)
response = udpprod(udpctx)
end
elseif q.proto == "tcp" then
if not tcpcli then
tcpcli = require("dnsjit.output.tcpcli").new()
tcpcli:connect(host, port)
tcprecv, tcpctx = tcpcli:receive()
tcpprod, _ = tcpcli:produce()
end
tcprecv(tcpctx, cliobject)
while response == nil do
response = tcpprod(tcpctx)
end
while response ~= nil do
table.insert(responses, response)
response = tcpprod(tcpctx)
end
end

print(dns.id, tohex(q.payload, q.len), tohex(payload.payload, tonumber(payload.len)))
for _, response in pairs(responses) do
local dns = require("dnsjit.core.object.dns").new(response)
if dns and dns:parse() == 0 and dns.id == q.id then
response = response:cast()
print("", "", tohex(response.payload, tonumber(response.len)))
end
end
end
end
end
end
end
8 changes: 4 additions & 4 deletions examples/readme.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/usr/bin/env dnsjit
require("dnsjit.core.objects")
local input = require("dnsjit.input.pcapthread").new()
local output = require("dnsjit.filter.lua").new()
local output = require("dnsjit.filter.coro").new()

output:func(function(filter, object)
local packet = object:cast()
local dns = require("dnsjit.core.object.dns").new(packet)
if dns:parse() == 0 then
local dns = require("dnsjit.core.object.dns").new(object)
if dns and dns:parse() == 0 then
print(dns.id)
end
end)
Expand Down
Loading

0 comments on commit 78fe01a

Please sign in to comment.