798 lines
21 KiB
Lua
798 lines
21 KiB
Lua
|
-- Copyright (c) 2018-2021, OARC, Inc.
|
||
|
-- All rights reserved.
|
||
|
--
|
||
|
-- This file is part of dnsjit.
|
||
|
--
|
||
|
-- dnsjit is free software: you can redistribute it and/or modify
|
||
|
-- it under the terms of the GNU General Public License as published by
|
||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||
|
-- (at your option) any later version.
|
||
|
--
|
||
|
-- dnsjit is distributed in the hope that it will be useful,
|
||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
-- GNU General Public License for more details.
|
||
|
--
|
||
|
-- You should have received a copy of the GNU General Public License
|
||
|
-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
-- dnsjit.core.object.dns
|
||
|
-- Container of a DNS message
|
||
|
-- .SS Parse DNS header and check if query or response
|
||
|
-- local dns = require("dnsjit.core.object.dns").new(payload)
|
||
|
-- if dns:parse_header() == 0 then
|
||
|
-- if dns.qr == 0 then
|
||
|
-- print(dns.id, dns.opcode_tostring(dns.opcode))
|
||
|
-- else
|
||
|
-- print(dns.id, dns.rcode_tostring(dns.rcode))
|
||
|
-- end
|
||
|
-- end
|
||
|
-- .SS Print a DNS payload
|
||
|
-- local dns = require("dnsjit.core.object.dns").new(payload)
|
||
|
-- dns:print()
|
||
|
-- .SS Parse a DNS payload
|
||
|
-- local dns = require("dnsjit.core.object.dns").new(payload)
|
||
|
-- local qs, q_labels, rrs, rr_labels = dns:parse()
|
||
|
-- if qs and q_labels then
|
||
|
-- ...
|
||
|
-- if rrs and rr_labels then
|
||
|
-- ...
|
||
|
-- end
|
||
|
-- end
|
||
|
--
|
||
|
-- The object that describes a DNS message.
|
||
|
-- .SS Attributes
|
||
|
-- .TP
|
||
|
-- includes_dnslen
|
||
|
-- If non-zero then this indicates that the DNS length is included in the
|
||
|
-- payload (for example if the transport is TCP) and will affect parsing of it.
|
||
|
-- .TP
|
||
|
-- have_dnslen
|
||
|
-- Set if the dnslen was included in the payload and could be read.
|
||
|
-- .TP
|
||
|
-- have_id
|
||
|
-- Set if there is a DNS ID.
|
||
|
-- .TP
|
||
|
-- have_qr
|
||
|
-- Set if there is a QR flag.
|
||
|
-- .TP
|
||
|
-- have_opcode
|
||
|
-- Set if there is an OPCODE.
|
||
|
-- .TP
|
||
|
-- have_aa
|
||
|
-- Set if there is a AA flag.
|
||
|
-- .TP
|
||
|
-- have_tc
|
||
|
-- Set if there is a TC flag.
|
||
|
-- .TP
|
||
|
-- have_rd
|
||
|
-- Set if there is a RD flag.
|
||
|
-- .TP
|
||
|
-- have_ra
|
||
|
-- Set if there is a RA flag.
|
||
|
-- .TP
|
||
|
-- have_z
|
||
|
-- Set if there is a Z flag.
|
||
|
-- .TP
|
||
|
-- have_ad
|
||
|
-- Set if there is a AD flag.
|
||
|
-- .TP
|
||
|
-- have_cd
|
||
|
-- Set if there is a CD flag.
|
||
|
-- .TP
|
||
|
-- have_rcode
|
||
|
-- Set if there is a RCODE.
|
||
|
-- .TP
|
||
|
-- have_qdcount
|
||
|
-- Set if there is an QDCOUNT.
|
||
|
-- .TP
|
||
|
-- have_ancount
|
||
|
-- Set if there is an ANCOUNT.
|
||
|
-- .TP
|
||
|
-- have_nscount
|
||
|
-- Set if there is a NSCOUNT.
|
||
|
-- .TP
|
||
|
-- have_arcount
|
||
|
-- Set if there is an ARCOUNT.
|
||
|
-- .TP
|
||
|
-- dnslen
|
||
|
-- The DNS length found in the payload.
|
||
|
-- .TP
|
||
|
-- id
|
||
|
-- The DNS ID.
|
||
|
-- .TP
|
||
|
-- qr
|
||
|
-- The QR flag.
|
||
|
-- .TP
|
||
|
-- opcode
|
||
|
-- The OPCODE.
|
||
|
-- .TP
|
||
|
-- aa
|
||
|
-- The AA flag.
|
||
|
-- .TP
|
||
|
-- tc
|
||
|
-- The TC flag.
|
||
|
-- .TP
|
||
|
-- rd
|
||
|
-- The RD flag.
|
||
|
-- .TP
|
||
|
-- ra
|
||
|
-- The RA flag.
|
||
|
-- .TP
|
||
|
-- z
|
||
|
-- The Z flag.
|
||
|
-- .TP
|
||
|
-- ad
|
||
|
-- The AD flag.
|
||
|
-- .TP
|
||
|
-- cd
|
||
|
-- The CD flag.
|
||
|
-- .TP
|
||
|
-- rcode
|
||
|
-- The RCODE.
|
||
|
-- .TP
|
||
|
-- qdcount
|
||
|
-- The QDCOUNT.
|
||
|
-- .TP
|
||
|
-- ancount
|
||
|
-- The ANCOUNT.
|
||
|
-- .TP
|
||
|
-- nscount
|
||
|
-- The NSCOUNT.
|
||
|
-- .TP
|
||
|
-- arcount
|
||
|
-- The ARCOUNT.
|
||
|
-- .SS Constants
|
||
|
-- The following tables exists for DNS parameters, taken from
|
||
|
-- .I https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
|
||
|
-- on the 2016-12-09.
|
||
|
-- .LP
|
||
|
-- .IR CLASS ,
|
||
|
-- .IR CLASS_STR ,
|
||
|
-- .IR TYPE ,
|
||
|
-- .IR TYPE_STR ,
|
||
|
-- .IR OPCODE ,
|
||
|
-- .IR OPCODE_STR ,
|
||
|
-- .IR RCODE ,
|
||
|
-- .IR RCODE_STR ,
|
||
|
-- .IR AFSDB ,
|
||
|
-- .IR AFSDB_STR ,
|
||
|
-- .IR DHCID ,
|
||
|
-- .IR DHCID_STR ,
|
||
|
-- .IR ENDS0 ,
|
||
|
-- .IR ENDS0_STR
|
||
|
-- .LP
|
||
|
-- The
|
||
|
-- .I *_STR
|
||
|
-- tables can be used to get a textual representation of the numbers, see also
|
||
|
-- .IR class_tostring() ,
|
||
|
-- .IR type_tostring() ,
|
||
|
-- .IR opcode_tostring() ,
|
||
|
-- .IR rcode_tostring() ,
|
||
|
-- .IR afsdb_tostring() ,
|
||
|
-- .I dhcid_tostring()
|
||
|
-- and
|
||
|
-- .IR edns0_tostring() .
|
||
|
module(...,package.seeall)
|
||
|
|
||
|
require("dnsjit.core.object.dns_h")
|
||
|
local label = require("dnsjit.core.object.dns.label")
|
||
|
local Q = require("dnsjit.core.object.dns.q")
|
||
|
local RR = require("dnsjit.core.object.dns.rr")
|
||
|
local ffi = require("ffi")
|
||
|
local C = ffi.C
|
||
|
|
||
|
local t_name = "core_object_dns_t"
|
||
|
local core_object_dns_t
|
||
|
local Dns = {
|
||
|
CLASS = {
|
||
|
IN = 1,
|
||
|
CH = 3,
|
||
|
HS = 4,
|
||
|
NONE = 254,
|
||
|
ANY = 255,
|
||
|
},
|
||
|
TYPE = {
|
||
|
A = 1,
|
||
|
NS = 2,
|
||
|
MD = 3,
|
||
|
MF = 4,
|
||
|
CNAME = 5,
|
||
|
SOA = 6,
|
||
|
MB = 7,
|
||
|
MG = 8,
|
||
|
MR = 9,
|
||
|
NULL = 10,
|
||
|
WKS = 11,
|
||
|
PTR = 12,
|
||
|
HINFO = 13,
|
||
|
MINFO = 14,
|
||
|
MX = 15,
|
||
|
TXT = 16,
|
||
|
RP = 17,
|
||
|
AFSDB = 18,
|
||
|
X25 = 19,
|
||
|
ISDN = 20,
|
||
|
RT = 21,
|
||
|
NSAP = 22,
|
||
|
NSAP_PTR = 23,
|
||
|
SIG = 24,
|
||
|
KEY = 25,
|
||
|
PX = 26,
|
||
|
GPOS = 27,
|
||
|
AAAA = 28,
|
||
|
LOC = 29,
|
||
|
NXT = 30,
|
||
|
EID = 31,
|
||
|
NIMLOC = 32,
|
||
|
SRV = 33,
|
||
|
ATMA = 34,
|
||
|
NAPTR = 35,
|
||
|
KX = 36,
|
||
|
CERT = 37,
|
||
|
A6 = 38,
|
||
|
DNAME = 39,
|
||
|
SINK = 40,
|
||
|
OPT = 41,
|
||
|
APL = 42,
|
||
|
DS = 43,
|
||
|
SSHFP = 44,
|
||
|
IPSECKEY = 45,
|
||
|
RRSIG = 46,
|
||
|
NSEC = 47,
|
||
|
DNSKEY = 48,
|
||
|
DHCID = 49,
|
||
|
NSEC3 = 50,
|
||
|
NSEC3PARAM = 51,
|
||
|
TLSA = 52,
|
||
|
SMIMEA = 53,
|
||
|
HIP = 55,
|
||
|
NINFO = 56,
|
||
|
RKEY = 57,
|
||
|
TALINK = 58,
|
||
|
CDS = 59,
|
||
|
CDNSKEY = 60,
|
||
|
OPENPGPKEY = 61,
|
||
|
CSYNC = 62,
|
||
|
SPF = 99,
|
||
|
UINFO = 100,
|
||
|
UID = 101,
|
||
|
GID = 102,
|
||
|
UNSPEC = 103,
|
||
|
NID = 104,
|
||
|
L32 = 105,
|
||
|
L64 = 106,
|
||
|
LP = 107,
|
||
|
EUI48 = 108,
|
||
|
EUI64 = 109,
|
||
|
TKEY = 249,
|
||
|
TSIG = 250,
|
||
|
IXFR = 251,
|
||
|
AXFR = 252,
|
||
|
MAILB = 253,
|
||
|
MAILA = 254,
|
||
|
ANY = 255,
|
||
|
URI = 256,
|
||
|
CAA = 257,
|
||
|
AVC = 258,
|
||
|
TA = 32768,
|
||
|
DLV = 32769,
|
||
|
},
|
||
|
OPCODE = {
|
||
|
QUERY = 0,
|
||
|
IQUERY = 1,
|
||
|
STATUS = 2,
|
||
|
NOTIFY = 4,
|
||
|
UPDATE = 5,
|
||
|
},
|
||
|
RCODE = {
|
||
|
NOERROR = 0,
|
||
|
FORMERR = 1,
|
||
|
SERVFAIL = 2,
|
||
|
NXDOMAIN = 3,
|
||
|
NOTIMP = 4,
|
||
|
REFUSED = 5,
|
||
|
YXDOMAIN = 6,
|
||
|
YXRRSET = 7,
|
||
|
NXRRSET = 8,
|
||
|
NOTAUTH = 9,
|
||
|
NOTZONE = 10,
|
||
|
BADVERS = 16,
|
||
|
BADSIG = 16,
|
||
|
BADKEY = 17,
|
||
|
BADTIME = 18,
|
||
|
BADMODE = 19,
|
||
|
BADNAME = 20,
|
||
|
BADALG = 21,
|
||
|
BADTRUNC = 22,
|
||
|
BADCOOKIE = 23,
|
||
|
},
|
||
|
AFSDB = {
|
||
|
SUBTYPE_AFS3LOCSRV = 1,
|
||
|
SUBTYPE_DCENCA_ROOT = 2,
|
||
|
},
|
||
|
DHCID = {
|
||
|
TYPE_1OCTET = 0,
|
||
|
TYPE_DATAOCTET = 1,
|
||
|
TYPE_CLIENT_DUID = 2,
|
||
|
},
|
||
|
EDNS0 = {
|
||
|
OPT_LLQ = 1,
|
||
|
OPT_UL = 2,
|
||
|
OPT_NSID = 3,
|
||
|
OPT_DAU = 5,
|
||
|
OPT_DHU = 6,
|
||
|
OPT_N3U = 7,
|
||
|
OPT_CLIENT_SUBNET = 8,
|
||
|
OPT_EXPIRE = 9,
|
||
|
OPT_COOKIE = 10,
|
||
|
OPT_TCP_KEEPALIVE = 11,
|
||
|
OPT_PADDING = 12,
|
||
|
OPT_CHAIN = 13,
|
||
|
OPT_DEVICEID = 26946,
|
||
|
},
|
||
|
}
|
||
|
local _CLASS = {}
|
||
|
_CLASS[Dns.CLASS.IN] = "IN"
|
||
|
_CLASS[Dns.CLASS.CH] = "CH"
|
||
|
_CLASS[Dns.CLASS.HS] = "HS"
|
||
|
_CLASS[Dns.CLASS.NONE] = "NONE"
|
||
|
_CLASS[Dns.CLASS.ANY] = "ANY"
|
||
|
local _TYPE = {}
|
||
|
_TYPE[Dns.TYPE.A] = "A"
|
||
|
_TYPE[Dns.TYPE.NS] = "NS"
|
||
|
_TYPE[Dns.TYPE.MD] = "MD"
|
||
|
_TYPE[Dns.TYPE.MF] = "MF"
|
||
|
_TYPE[Dns.TYPE.CNAME] = "CNAME"
|
||
|
_TYPE[Dns.TYPE.SOA] = "SOA"
|
||
|
_TYPE[Dns.TYPE.MB] = "MB"
|
||
|
_TYPE[Dns.TYPE.MG] = "MG"
|
||
|
_TYPE[Dns.TYPE.MR] = "MR"
|
||
|
_TYPE[Dns.TYPE.NULL] = "NULL"
|
||
|
_TYPE[Dns.TYPE.WKS] = "WKS"
|
||
|
_TYPE[Dns.TYPE.PTR] = "PTR"
|
||
|
_TYPE[Dns.TYPE.HINFO] = "HINFO"
|
||
|
_TYPE[Dns.TYPE.MINFO] = "MINFO"
|
||
|
_TYPE[Dns.TYPE.MX] = "MX"
|
||
|
_TYPE[Dns.TYPE.TXT] = "TXT"
|
||
|
_TYPE[Dns.TYPE.RP] = "RP"
|
||
|
_TYPE[Dns.TYPE.AFSDB] = "AFSDB"
|
||
|
_TYPE[Dns.TYPE.X25] = "X25"
|
||
|
_TYPE[Dns.TYPE.ISDN] = "ISDN"
|
||
|
_TYPE[Dns.TYPE.RT] = "RT"
|
||
|
_TYPE[Dns.TYPE.NSAP] = "NSAP"
|
||
|
_TYPE[Dns.TYPE.NSAP_PTR] = "NSAP_PTR"
|
||
|
_TYPE[Dns.TYPE.SIG] = "SIG"
|
||
|
_TYPE[Dns.TYPE.KEY] = "KEY"
|
||
|
_TYPE[Dns.TYPE.PX] = "PX"
|
||
|
_TYPE[Dns.TYPE.GPOS] = "GPOS"
|
||
|
_TYPE[Dns.TYPE.AAAA] = "AAAA"
|
||
|
_TYPE[Dns.TYPE.LOC] = "LOC"
|
||
|
_TYPE[Dns.TYPE.NXT] = "NXT"
|
||
|
_TYPE[Dns.TYPE.EID] = "EID"
|
||
|
_TYPE[Dns.TYPE.NIMLOC] = "NIMLOC"
|
||
|
_TYPE[Dns.TYPE.SRV] = "SRV"
|
||
|
_TYPE[Dns.TYPE.ATMA] = "ATMA"
|
||
|
_TYPE[Dns.TYPE.NAPTR] = "NAPTR"
|
||
|
_TYPE[Dns.TYPE.KX] = "KX"
|
||
|
_TYPE[Dns.TYPE.CERT] = "CERT"
|
||
|
_TYPE[Dns.TYPE.A6] = "A6"
|
||
|
_TYPE[Dns.TYPE.DNAME] = "DNAME"
|
||
|
_TYPE[Dns.TYPE.SINK] = "SINK"
|
||
|
_TYPE[Dns.TYPE.OPT] = "OPT"
|
||
|
_TYPE[Dns.TYPE.APL] = "APL"
|
||
|
_TYPE[Dns.TYPE.DS] = "DS"
|
||
|
_TYPE[Dns.TYPE.SSHFP] = "SSHFP"
|
||
|
_TYPE[Dns.TYPE.IPSECKEY] = "IPSECKEY"
|
||
|
_TYPE[Dns.TYPE.RRSIG] = "RRSIG"
|
||
|
_TYPE[Dns.TYPE.NSEC] = "NSEC"
|
||
|
_TYPE[Dns.TYPE.DNSKEY] = "DNSKEY"
|
||
|
_TYPE[Dns.TYPE.DHCID] = "DHCID"
|
||
|
_TYPE[Dns.TYPE.NSEC3] = "NSEC3"
|
||
|
_TYPE[Dns.TYPE.NSEC3PARAM] = "NSEC3PARAM"
|
||
|
_TYPE[Dns.TYPE.TLSA] = "TLSA"
|
||
|
_TYPE[Dns.TYPE.SMIMEA] = "SMIMEA"
|
||
|
_TYPE[Dns.TYPE.HIP] = "HIP"
|
||
|
_TYPE[Dns.TYPE.NINFO] = "NINFO"
|
||
|
_TYPE[Dns.TYPE.RKEY] = "RKEY"
|
||
|
_TYPE[Dns.TYPE.TALINK] = "TALINK"
|
||
|
_TYPE[Dns.TYPE.CDS] = "CDS"
|
||
|
_TYPE[Dns.TYPE.CDNSKEY] = "CDNSKEY"
|
||
|
_TYPE[Dns.TYPE.OPENPGPKEY] = "OPENPGPKEY"
|
||
|
_TYPE[Dns.TYPE.CSYNC] = "CSYNC"
|
||
|
_TYPE[Dns.TYPE.SPF] = "SPF"
|
||
|
_TYPE[Dns.TYPE.UINFO] = "UINFO"
|
||
|
_TYPE[Dns.TYPE.UID] = "UID"
|
||
|
_TYPE[Dns.TYPE.GID] = "GID"
|
||
|
_TYPE[Dns.TYPE.UNSPEC] = "UNSPEC"
|
||
|
_TYPE[Dns.TYPE.NID] = "NID"
|
||
|
_TYPE[Dns.TYPE.L32] = "L32"
|
||
|
_TYPE[Dns.TYPE.L64] = "L64"
|
||
|
_TYPE[Dns.TYPE.LP] = "LP"
|
||
|
_TYPE[Dns.TYPE.EUI48] = "EUI48"
|
||
|
_TYPE[Dns.TYPE.EUI64] = "EUI64"
|
||
|
_TYPE[Dns.TYPE.TKEY] = "TKEY"
|
||
|
_TYPE[Dns.TYPE.TSIG] = "TSIG"
|
||
|
_TYPE[Dns.TYPE.IXFR] = "IXFR"
|
||
|
_TYPE[Dns.TYPE.AXFR] = "AXFR"
|
||
|
_TYPE[Dns.TYPE.MAILB] = "MAILB"
|
||
|
_TYPE[Dns.TYPE.MAILA] = "MAILA"
|
||
|
_TYPE[Dns.TYPE.ANY] = "ANY"
|
||
|
_TYPE[Dns.TYPE.URI] = "URI"
|
||
|
_TYPE[Dns.TYPE.CAA] = "CAA"
|
||
|
_TYPE[Dns.TYPE.AVC] = "AVC"
|
||
|
_TYPE[Dns.TYPE.TA] = "TA"
|
||
|
_TYPE[Dns.TYPE.DLV] = "DLV"
|
||
|
local _OPCODE = {}
|
||
|
_OPCODE[Dns.OPCODE.QUERY] = "QUERY"
|
||
|
_OPCODE[Dns.OPCODE.IQUERY] = "IQUERY"
|
||
|
_OPCODE[Dns.OPCODE.STATUS] = "STATUS"
|
||
|
_OPCODE[Dns.OPCODE.NOTIFY] = "NOTIFY"
|
||
|
_OPCODE[Dns.OPCODE.UPDATE] = "UPDATE"
|
||
|
local _RCODE = {}
|
||
|
_RCODE[Dns.RCODE.NOERROR] = "NOERROR"
|
||
|
_RCODE[Dns.RCODE.FORMERR] = "FORMERR"
|
||
|
_RCODE[Dns.RCODE.SERVFAIL] = "SERVFAIL"
|
||
|
_RCODE[Dns.RCODE.NXDOMAIN] = "NXDOMAIN"
|
||
|
_RCODE[Dns.RCODE.NOTIMP] = "NOTIMP"
|
||
|
_RCODE[Dns.RCODE.REFUSED] = "REFUSED"
|
||
|
_RCODE[Dns.RCODE.YXDOMAIN] = "YXDOMAIN"
|
||
|
_RCODE[Dns.RCODE.YXRRSET] = "YXRRSET"
|
||
|
_RCODE[Dns.RCODE.NXRRSET] = "NXRRSET"
|
||
|
_RCODE[Dns.RCODE.NOTAUTH] = "NOTAUTH"
|
||
|
_RCODE[Dns.RCODE.NOTZONE] = "NOTZONE"
|
||
|
_RCODE[Dns.RCODE.BADVERS] = "BADVERS"
|
||
|
_RCODE[Dns.RCODE.BADSIG] = "BADSIG"
|
||
|
_RCODE[Dns.RCODE.BADKEY] = "BADKEY"
|
||
|
_RCODE[Dns.RCODE.BADTIME] = "BADTIME"
|
||
|
_RCODE[Dns.RCODE.BADMODE] = "BADMODE"
|
||
|
_RCODE[Dns.RCODE.BADNAME] = "BADNAME"
|
||
|
_RCODE[Dns.RCODE.BADALG] = "BADALG"
|
||
|
_RCODE[Dns.RCODE.BADTRUNC] = "BADTRUNC"
|
||
|
_RCODE[Dns.RCODE.BADCOOKIE] = "BADCOOKIE"
|
||
|
local _AFSDB = {}
|
||
|
_AFSDB[Dns.AFSDB.SUBTYPE_AFS3LOCSRV] = "SUBTYPE_AFS3LOCSRV"
|
||
|
_AFSDB[Dns.AFSDB.SUBTYPE_DCENCA_ROOT] = "SUBTYPE_DCENCA_ROOT"
|
||
|
local _DHCID = {}
|
||
|
_DHCID[Dns.DHCID.TYPE_1OCTET] = "TYPE_1OCTET"
|
||
|
_DHCID[Dns.DHCID.TYPE_DATAOCTET] = "TYPE_DATAOCTET"
|
||
|
_DHCID[Dns.DHCID.TYPE_CLIENT_DUID] = "TYPE_CLIENT_DUID"
|
||
|
local _EDNS0 = {}
|
||
|
_EDNS0[Dns.EDNS0.OPT_LLQ] = "OPT_LLQ"
|
||
|
_EDNS0[Dns.EDNS0.OPT_UL] = "OPT_UL"
|
||
|
_EDNS0[Dns.EDNS0.OPT_NSID] = "OPT_NSID"
|
||
|
_EDNS0[Dns.EDNS0.OPT_DAU] = "OPT_DAU"
|
||
|
_EDNS0[Dns.EDNS0.OPT_DHU] = "OPT_DHU"
|
||
|
_EDNS0[Dns.EDNS0.OPT_N3U] = "OPT_N3U"
|
||
|
_EDNS0[Dns.EDNS0.OPT_CLIENT_SUBNET] = "OPT_CLIENT_SUBNET"
|
||
|
_EDNS0[Dns.EDNS0.OPT_EXPIRE] = "OPT_EXPIRE"
|
||
|
_EDNS0[Dns.EDNS0.OPT_COOKIE] = "OPT_COOKIE"
|
||
|
_EDNS0[Dns.EDNS0.OPT_TCP_KEEPALIVE] = "OPT_TCP_KEEPALIVE"
|
||
|
_EDNS0[Dns.EDNS0.OPT_PADDING] = "OPT_PADDING"
|
||
|
_EDNS0[Dns.EDNS0.OPT_CHAIN] = "OPT_CHAIN"
|
||
|
_EDNS0[Dns.EDNS0.OPT_DEVICEID] = "OPT_DEVICEID"
|
||
|
Dns.CLASS_STR = _CLASS
|
||
|
Dns.TYPE_STR = _TYPE
|
||
|
Dns.OPCODE_STR = _OPCODE
|
||
|
Dns.RCODE_STR = _RCODE
|
||
|
Dns.AFSDB_STR = _AFSDB
|
||
|
Dns.DHCID_STR = _DHCID
|
||
|
Dns.EDNS0_STR = _EDNS0
|
||
|
|
||
|
-- Create a new DNS object, optionally on-top of another object.
|
||
|
function Dns.new(obj)
|
||
|
local self = C.core_object_dns_new()
|
||
|
self.obj_prev = obj
|
||
|
ffi.gc(self, C.core_object_dns_free)
|
||
|
return self
|
||
|
end
|
||
|
|
||
|
-- Return the textual type of the object.
|
||
|
function Dns:type()
|
||
|
return "dns"
|
||
|
end
|
||
|
|
||
|
-- Return the previous object.
|
||
|
function Dns:prev()
|
||
|
return self.obj_prev
|
||
|
end
|
||
|
|
||
|
-- Cast the object to the underlining object module and return it.
|
||
|
function Dns:cast()
|
||
|
return self
|
||
|
end
|
||
|
|
||
|
-- Cast the object to the generic object module and return it.
|
||
|
function Dns:uncast()
|
||
|
return ffi.cast("core_object_t*", self)
|
||
|
end
|
||
|
|
||
|
-- Make a copy of the object and return it.
|
||
|
function Dns:copy()
|
||
|
return C.core_object_dns_copy(self)
|
||
|
end
|
||
|
|
||
|
-- Free the object, should only be used on copies or otherwise allocated.
|
||
|
function Dns:free()
|
||
|
C.core_object_dns_free(self)
|
||
|
end
|
||
|
|
||
|
-- Return the Log object to control logging of this module.
|
||
|
function Dns:log()
|
||
|
return C.core_object_dns_log()
|
||
|
end
|
||
|
|
||
|
-- Begin parsing the underlaying object, first the header is parsed then
|
||
|
-- optionally continue calling
|
||
|
-- .IR parse_q ()
|
||
|
-- for the number of questions (see
|
||
|
-- .IR qdcount ).
|
||
|
-- After that continue calling
|
||
|
-- .IR parse_rr ()
|
||
|
-- for the number of answers, authorities and additionals resource records
|
||
|
-- (see
|
||
|
-- .IR ancount ", "
|
||
|
-- .I nscount
|
||
|
-- and
|
||
|
-- .IR arcount ).
|
||
|
-- Returns 0 on success or negative integer on error which can be for
|
||
|
-- malformed or truncated DNS (-2) or if more space for labels is needed (-3).
|
||
|
function Dns:parse_header()
|
||
|
return C.core_object_dns_parse_header(self)
|
||
|
end
|
||
|
|
||
|
-- Parse the next resource record as a question.
|
||
|
-- Returns 0 on success or negative integer on error which can be for
|
||
|
-- malformed or truncated DNS (-2) or if more space for labels is needed (-3).
|
||
|
function Dns:parse_q(q, labels, num_labels)
|
||
|
return C.core_object_dns_parse_q(self, q, labels, num_labels)
|
||
|
end
|
||
|
|
||
|
-- Parse the next resource record.
|
||
|
-- Returns 0 on success or negative integer on error which can be for
|
||
|
-- malformed or truncated DNS (-2) or if more space for labels is needed (-3).
|
||
|
function Dns:parse_rr(rr, labels, num_labels)
|
||
|
return C.core_object_dns_parse_rr(self, rr, labels, num_labels)
|
||
|
end
|
||
|
|
||
|
-- Begin parsing the underlaying object using
|
||
|
-- .IR parse_header "(), "
|
||
|
-- .IR parse_q ()
|
||
|
-- and
|
||
|
-- .IR parse_rr ().
|
||
|
-- The optional
|
||
|
-- .I num_labels
|
||
|
-- can be used to set a specific number of labels used for each question
|
||
|
-- and resource record (default 16).
|
||
|
-- Returns result code, an array of questions, an array of question labels,
|
||
|
-- an array of resource records and an array of resource records labels.
|
||
|
-- Result code is 0 on success or negative integer on error which can be for
|
||
|
-- malformed or truncated DNS (-2) or if more space for labels is needed (-3).
|
||
|
function Dns:parse(num_labels)
|
||
|
local qs, qls, rrs, rrls = {}, {}, {}, {}
|
||
|
if num_labels == nil then
|
||
|
num_labels = 16
|
||
|
end
|
||
|
|
||
|
ret = self:parse_header()
|
||
|
if ret ~= 0 then
|
||
|
return ret, qs, qls, rrs, rrls
|
||
|
end
|
||
|
for n = 1, self.qdcount do
|
||
|
local labels = label.new(num_labels)
|
||
|
local q = Q.new()
|
||
|
local ret = C.core_object_dns_parse_q(self, q, labels, num_labels)
|
||
|
|
||
|
if ret ~= 0 then
|
||
|
return ret, qs, qls, rrs, rrls
|
||
|
end
|
||
|
table.insert(qs, q)
|
||
|
table.insert(qls, labels)
|
||
|
end
|
||
|
for n = 1, self.ancount do
|
||
|
local labels = label.new(num_labels)
|
||
|
local rr = RR.new()
|
||
|
local ret = C.core_object_dns_parse_rr(self, rr, labels, num_labels)
|
||
|
|
||
|
if ret ~= 0 then
|
||
|
return ret, qs, qls, rrs, rrls
|
||
|
end
|
||
|
table.insert(rrs, rr)
|
||
|
table.insert(rrls, labels)
|
||
|
end
|
||
|
for n = 1, self.nscount do
|
||
|
local labels = label.new(num_labels)
|
||
|
local rr = RR.new()
|
||
|
local ret = C.core_object_dns_parse_rr(self, rr, labels, num_labels)
|
||
|
|
||
|
if ret ~= 0 then
|
||
|
return ret, qs, qls, rrs, rrls
|
||
|
end
|
||
|
table.insert(rrs, rr)
|
||
|
table.insert(rrls, labels)
|
||
|
end
|
||
|
for n = 1, self.arcount do
|
||
|
local labels = label.new(num_labels)
|
||
|
local rr = RR.new()
|
||
|
local ret = C.core_object_dns_parse_rr(self, rr, labels, num_labels)
|
||
|
|
||
|
if ret ~= 0 then
|
||
|
return ret, qs, qls, rrs, rrls
|
||
|
end
|
||
|
table.insert(rrs, rr)
|
||
|
table.insert(rrls, labels)
|
||
|
end
|
||
|
|
||
|
return 0, qs, qls, rrs, rrls
|
||
|
end
|
||
|
|
||
|
-- Begin parsing the underlaying object using
|
||
|
-- .IR parse_header "(), "
|
||
|
-- .IR parse_q ()
|
||
|
-- and
|
||
|
-- .IR parse_rr (),
|
||
|
-- and print it's content.
|
||
|
-- The optional
|
||
|
-- .I num_labels
|
||
|
-- can be used to set a specific number of labels used for each question
|
||
|
-- and resource record (default 16).
|
||
|
function Dns:print(num_labels)
|
||
|
if num_labels == nil then
|
||
|
num_labels = 16
|
||
|
end
|
||
|
local labels = label.new(num_labels)
|
||
|
local q = Q.new()
|
||
|
local rr = RR.new()
|
||
|
|
||
|
if self:parse_header() ~= 0 then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local flags = {}
|
||
|
if self.have_aa and self.aa == 1 then
|
||
|
table.insert(flags, "AA")
|
||
|
end
|
||
|
if self.have_tc and self.tc == 1 then
|
||
|
table.insert(flags, "TC")
|
||
|
end
|
||
|
if self.have_rd and self.rd == 1 then
|
||
|
table.insert(flags, "RD")
|
||
|
end
|
||
|
if self.have_ra and self.ra == 1 then
|
||
|
table.insert(flags, "RA")
|
||
|
end
|
||
|
if self.have_z and self.z == 1 then
|
||
|
table.insert(flags, "Z")
|
||
|
end
|
||
|
if self.have_ad and self.ad == 1 then
|
||
|
table.insert(flags, "AD")
|
||
|
end
|
||
|
if self.have_cd and self.cd == 1 then
|
||
|
table.insert(flags, "CD")
|
||
|
end
|
||
|
|
||
|
print("id:", self.id)
|
||
|
print("", "qr:", self.qr)
|
||
|
print("", "opcode:", Dns.opcode_tostring(self.opcode))
|
||
|
print("", "flags:", table.concat(flags, " "))
|
||
|
print("", "rcode:", Dns.rcode_tostring(self.rcode))
|
||
|
print("", "qdcount:", self.qdcount)
|
||
|
print("", "ancount:", self.ancount)
|
||
|
print("", "nscount:", self.nscount)
|
||
|
print("", "arcount:", self.arcount)
|
||
|
|
||
|
if self.qdcount > 0 then
|
||
|
print("questions:", "class", "type", "labels")
|
||
|
for n = 1, self.qdcount do
|
||
|
if C.core_object_dns_parse_q(self, q, labels, num_labels) ~= 0 then
|
||
|
return
|
||
|
end
|
||
|
print("", Dns.class_tostring(q.class), Dns.type_tostring(q.type), label.tooffstr(self, labels, num_labels))
|
||
|
end
|
||
|
end
|
||
|
if self.ancount > 0 then
|
||
|
print("answers:", "class", "type", "ttl", "labels", "RR labels")
|
||
|
for n = 1, self.ancount do
|
||
|
if C.core_object_dns_parse_rr(self, rr, labels, num_labels) ~= 0 then
|
||
|
return
|
||
|
end
|
||
|
if rr.rdata_labels == 0 then
|
||
|
print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels))
|
||
|
else
|
||
|
print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels), label.tooffstr(self, labels, rr.rdata_labels, rr.labels))
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
if self.nscount > 0 then
|
||
|
print("authorities:", "class", "type", "ttl", "labels", "RR labels")
|
||
|
for n = 1, self.nscount do
|
||
|
if C.core_object_dns_parse_rr(self, rr, labels, num_labels) ~= 0 then
|
||
|
return
|
||
|
end
|
||
|
if rr.rdata_labels == 0 then
|
||
|
print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels))
|
||
|
else
|
||
|
print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels), label.tooffstr(self, labels, rr.rdata_labels, rr.labels))
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
if self.arcount > 0 then
|
||
|
print("additionals:", "class", "type", "ttl", "labels", "RR labels")
|
||
|
for n = 1, self.arcount do
|
||
|
if C.core_object_dns_parse_rr(self, rr, labels, num_labels) ~= 0 then
|
||
|
return
|
||
|
end
|
||
|
if rr.rdata_labels == 0 then
|
||
|
print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels))
|
||
|
else
|
||
|
print("", Dns.class_tostring(rr.class), Dns.type_tostring(rr.type), rr.ttl, label.tooffstr(self, labels, rr.labels), label.tooffstr(self, labels, rr.rdata_labels, rr.labels))
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Return the textual name for a class.
|
||
|
function Dns.class_tostring(class)
|
||
|
if Dns.CLASS_STR[class] == nil then
|
||
|
return "UNKNOWN("..class..")"
|
||
|
end
|
||
|
return Dns.CLASS_STR[class]
|
||
|
end
|
||
|
|
||
|
-- Return the textual name for a type.
|
||
|
function Dns.type_tostring(type)
|
||
|
if Dns.TYPE_STR[type] == nil then
|
||
|
return "UNKNOWN("..type..")"
|
||
|
end
|
||
|
return Dns.TYPE_STR[type]
|
||
|
end
|
||
|
|
||
|
-- Return the textual name for an opcode.
|
||
|
function Dns.opcode_tostring(opcode)
|
||
|
if Dns.OPCODE_STR[opcode] == nil then
|
||
|
return "UNKNOWN("..opcode..")"
|
||
|
end
|
||
|
return Dns.OPCODE_STR[opcode]
|
||
|
end
|
||
|
|
||
|
-- Return the textual name for a rcode.
|
||
|
function Dns.rcode_tostring(rcode)
|
||
|
if Dns.RCODE_STR[rcode] == nil then
|
||
|
return "UNKNOWN("..rcode..")"
|
||
|
end
|
||
|
return Dns.RCODE_STR[rcode]
|
||
|
end
|
||
|
|
||
|
-- Return the textual name for an afsdb subtype.
|
||
|
function Dns.afsdb_tostring(afsdb)
|
||
|
if Dns.AFSDB_STR[afsdb] == nil then
|
||
|
return "UNKNOWN("..afsdb..")"
|
||
|
end
|
||
|
return Dns.AFSDB_STR[afsdb]
|
||
|
end
|
||
|
|
||
|
-- Return the textual name for a dhcid type.
|
||
|
function Dns.dhcid_tostring(dhcid)
|
||
|
if Dns.DHCID_STR[dhcid] == nil then
|
||
|
return "UNKNOWN("..dhcid..")"
|
||
|
end
|
||
|
return Dns.DHCID_STR[dhcid]
|
||
|
end
|
||
|
|
||
|
-- Return the textual name for an EDNS0 OPT record.
|
||
|
function Dns.edns0_tostring(edns0)
|
||
|
if Dns.EDNS0_STR[edns0] == nil then
|
||
|
return "UNKNOWN("..edns0..")"
|
||
|
end
|
||
|
return Dns.EDNS0_STR[edns0]
|
||
|
end
|
||
|
|
||
|
core_object_dns_t = ffi.metatype(t_name, { __index = Dns })
|
||
|
|
||
|
-- dnsjit.core.object (3),
|
||
|
-- dnsjit.core.object.payload (3),
|
||
|
-- dnsjit.core.object.dns.label (3),
|
||
|
-- dnsjit.core.object.dns.q (3),
|
||
|
-- dnsjit.core.object.dns.rr (3)
|
||
|
return Dns
|