96 lines
2.2 KiB
Nim
96 lines
2.2 KiB
Nim
|
from std/strutils import join
|
||
|
import utils
|
||
|
|
||
|
type
|
||
|
Opcode* = enum
|
||
|
QUERY = 0, IQUERY = 1, STATUS = 2
|
||
|
|
||
|
type
|
||
|
Rcode* = enum
|
||
|
NO_ERROR = 0, FORMAT_ERROR = 1, SERVER_FAULURE = 2, NAME_ERROR = 3,
|
||
|
NOT_IMPLEMENTED = 4, REFUSED = 5
|
||
|
|
||
|
type
|
||
|
DnsHeader* = object
|
||
|
id*: uint16
|
||
|
qr*: bool
|
||
|
opcode*: Opcode
|
||
|
aa*: bool
|
||
|
tc*: bool
|
||
|
rd*: bool
|
||
|
ra*: bool
|
||
|
z*: uint8
|
||
|
rcode*: Rcode
|
||
|
qdcount*: uint16
|
||
|
ancount*: uint16
|
||
|
nscount*: uint16
|
||
|
arcount*: uint16
|
||
|
|
||
|
proc parseHeader*(data: string): DnsHeader =
|
||
|
assert len(data) >= 12
|
||
|
|
||
|
return DnsHeader(
|
||
|
id: toUInt16(data[1], data[0]),
|
||
|
qr: sliceBit(data[2], 0),
|
||
|
opcode: Opcode((toUint8(data[2]) shr 3) and 0b00001111),
|
||
|
aa: sliceBit(data[2], 5),
|
||
|
tc: sliceBit(data[2], 6),
|
||
|
rd: sliceBit(data[2], 7),
|
||
|
ra: sliceBit(data[3], 0),
|
||
|
z: (toUint8(data[3]) shr 4) and 0b00000111,
|
||
|
rcode: Rcode(toUint8(data[3]) and 0b00001111),
|
||
|
qdcount: toUint16(data[5], data[4]),
|
||
|
ancount: toUint16(data[7], data[6]),
|
||
|
nscount: toUint16(data[9], data[8]),
|
||
|
arcount: toUint16(data[11], data[10])
|
||
|
)
|
||
|
|
||
|
type
|
||
|
DnsType* = enum
|
||
|
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, AXFR = 252, MAILB = 253, MAILA = 254, ANY = 255
|
||
|
|
||
|
type
|
||
|
DnsClass* = enum
|
||
|
IN = 1, CS = 2, CH = 3, HS = 4
|
||
|
|
||
|
type
|
||
|
DnsQuestion* = object
|
||
|
qname*: string
|
||
|
qtype*: DnsType
|
||
|
qclass*: DnsClass
|
||
|
|
||
|
proc parseQuestion*(data: string): (DnsQuestion, uint16) =
|
||
|
var qname: seq[string] = @[]
|
||
|
var len = toUint8(data[0])
|
||
|
var offset: uint16 = 1
|
||
|
|
||
|
while len > 0:
|
||
|
qname.add(data[offset .. offset + len - 1])
|
||
|
|
||
|
offset += len + 1
|
||
|
len = toUint8(data[offset - 1])
|
||
|
|
||
|
return (DnsQuestion(
|
||
|
qname: qname.join("."),
|
||
|
qtype: DnsType(toUint16(data[offset + 1], data[offset])),
|
||
|
qclass: DnsClass(toUint16(data[offset + 3], data[offset + 2]))
|
||
|
), offset + 4)
|
||
|
|
||
|
type
|
||
|
DnsRecord* = object
|
||
|
name*: string
|
||
|
rtype*: DnsType
|
||
|
class*: DnsClass
|
||
|
ttl*: uint32
|
||
|
rdlength*: uint16
|
||
|
rdata: string
|
||
|
|
||
|
type
|
||
|
DnsMessage* = object
|
||
|
header*: DnsHeader
|
||
|
questions*: seq[DnsQuestion]
|
||
|
answer*: seq[DnsRecord]
|
||
|
authroity*: seq[DnsRecord]
|
||
|
additional*: seq[DnsRecord]
|