197 lines
4.4 KiB
Go
197 lines
4.4 KiB
Go
package dnsProxy
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"net"
|
|
"strings"
|
|
)
|
|
|
|
type ResourceRecord interface {
|
|
EncodeResource() []byte
|
|
}
|
|
|
|
type ResourceRecordHeader struct {
|
|
Name Name
|
|
Type uint16
|
|
Class uint16
|
|
TTL uint32
|
|
}
|
|
|
|
func (q ResourceRecordHeader) EncodeHeader() []byte {
|
|
buf := bytes.NewBuffer([]byte{})
|
|
buf.Write(q.Name.Encode())
|
|
buf.Write(binary.BigEndian.AppendUint16([]byte{}, q.Type))
|
|
buf.Write(binary.BigEndian.AppendUint16([]byte{}, q.Class))
|
|
buf.Write(binary.BigEndian.AppendUint32([]byte{}, q.TTL))
|
|
return buf.Bytes()
|
|
}
|
|
|
|
type Name struct {
|
|
Parts []string
|
|
}
|
|
|
|
func (n Name) String() string {
|
|
return strings.Join(n.Parts, ".")
|
|
}
|
|
|
|
func (n Name) Encode() []byte {
|
|
buf := bytes.NewBuffer([]byte{})
|
|
for _, part := range n.Parts {
|
|
partLen := byte(len(part)) & 0x3F
|
|
buf.WriteByte(partLen)
|
|
buf.Write([]byte(part)[0:partLen])
|
|
}
|
|
buf.WriteByte(0)
|
|
return buf.Bytes()
|
|
}
|
|
|
|
type Flags struct {
|
|
QR uint8
|
|
Opcode uint8
|
|
AA uint8
|
|
TC uint8
|
|
RD uint8
|
|
RA uint8
|
|
Z1 uint8
|
|
Z2 uint8
|
|
Z3 uint8
|
|
RCode uint8
|
|
}
|
|
|
|
func (f Flags) Encode() []byte {
|
|
return []byte{
|
|
f.QR&0x1<<7 + f.Opcode&0xF<<3 + f.AA&0x1<<2 + f.TC&0x1<<1 + f.RD&0x1<<0,
|
|
f.RA&0x1<<7 + f.Z1&0x1<<6 + f.Z2&0x1<<5 + f.Z3&0x1<<4 + f.RCode&0xF<<0,
|
|
}
|
|
}
|
|
|
|
type Question struct {
|
|
QName Name
|
|
QType uint16
|
|
QClass uint16
|
|
}
|
|
|
|
func (q Question) EncodeQuestion() []byte {
|
|
buf := bytes.NewBuffer([]byte{})
|
|
buf.Write(q.QName.Encode())
|
|
buf.Write(binary.BigEndian.AppendUint16([]byte{}, q.QType))
|
|
buf.Write(binary.BigEndian.AppendUint16([]byte{}, q.QClass))
|
|
return buf.Bytes()
|
|
}
|
|
|
|
type Address struct {
|
|
ResourceRecordHeader
|
|
Address net.IP
|
|
}
|
|
|
|
func (a Address) EncodeResource() []byte {
|
|
rr := bytes.NewBuffer([]byte{})
|
|
rr.Write(a.ResourceRecordHeader.EncodeHeader())
|
|
rr.Write([]byte{0x00, 0x04})
|
|
rr.Write(a.Address[:])
|
|
return rr.Bytes()
|
|
}
|
|
|
|
type NameServer struct {
|
|
ResourceRecordHeader
|
|
NSDName Name
|
|
}
|
|
|
|
func (a NameServer) EncodeResource() []byte {
|
|
rdataBytes := a.NSDName.Encode()
|
|
rr := bytes.NewBuffer([]byte{})
|
|
rr.Write(a.ResourceRecordHeader.EncodeHeader())
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, uint16(len(rdataBytes))))
|
|
rr.Write(rdataBytes)
|
|
return rr.Bytes()
|
|
}
|
|
|
|
type CName struct {
|
|
ResourceRecordHeader
|
|
CName Name
|
|
}
|
|
|
|
func (a CName) EncodeResource() []byte {
|
|
rdataBytes := a.CName.Encode()
|
|
rr := bytes.NewBuffer([]byte{})
|
|
rr.Write(a.ResourceRecordHeader.EncodeHeader())
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, uint16(len(rdataBytes))))
|
|
rr.Write(rdataBytes)
|
|
return rr.Bytes()
|
|
}
|
|
|
|
type Authority struct {
|
|
ResourceRecordHeader
|
|
MName Name
|
|
RName Name
|
|
Serial uint32
|
|
Refresh uint32
|
|
Retry uint32
|
|
Expire uint32
|
|
Minimum uint32
|
|
}
|
|
|
|
func (a Authority) EncodeResource() []byte {
|
|
rdata := bytes.NewBuffer([]byte{})
|
|
rdata.Write(a.MName.Encode())
|
|
rdata.Write(a.RName.Encode())
|
|
rdata.Write(binary.BigEndian.AppendUint32([]byte{}, a.Serial))
|
|
rdata.Write(binary.BigEndian.AppendUint32([]byte{}, a.Refresh))
|
|
rdata.Write(binary.BigEndian.AppendUint32([]byte{}, a.Retry))
|
|
rdata.Write(binary.BigEndian.AppendUint32([]byte{}, a.Expire))
|
|
rdata.Write(binary.BigEndian.AppendUint32([]byte{}, a.Minimum))
|
|
rdataBytes := rdata.Bytes()
|
|
|
|
rr := bytes.NewBuffer([]byte{})
|
|
rr.Write(a.ResourceRecordHeader.EncodeHeader())
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, uint16(len(rdataBytes))))
|
|
rr.Write(rdataBytes)
|
|
return rr.Bytes()
|
|
}
|
|
|
|
type Unknown struct {
|
|
ResourceRecordHeader
|
|
Data []byte
|
|
}
|
|
|
|
func (u Unknown) EncodeResource() []byte {
|
|
rr := bytes.NewBuffer([]byte{})
|
|
rr.Write(u.ResourceRecordHeader.EncodeHeader())
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, uint16(len(u.Data))))
|
|
rr.Write(u.Data)
|
|
return rr.Bytes()
|
|
}
|
|
|
|
type Message struct {
|
|
ID uint16
|
|
Flags Flags
|
|
QD []Question
|
|
AN []ResourceRecord
|
|
NS []ResourceRecord
|
|
AR []ResourceRecord
|
|
}
|
|
|
|
func (m Message) Encode() []byte {
|
|
rr := bytes.NewBuffer([]byte{})
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, m.ID))
|
|
rr.Write(m.Flags.Encode())
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, uint16(len(m.QD))))
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, uint16(len(m.AN))))
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, uint16(len(m.NS))))
|
|
rr.Write(binary.BigEndian.AppendUint16([]byte{}, uint16(len(m.AR))))
|
|
for _, q := range m.QD {
|
|
rr.Write(q.EncodeQuestion())
|
|
}
|
|
for _, a := range m.AN {
|
|
rr.Write(a.EncodeResource())
|
|
}
|
|
for _, ns := range m.NS {
|
|
rr.Write(ns.EncodeResource())
|
|
}
|
|
for _, a := range m.AR {
|
|
rr.Write(a.EncodeResource())
|
|
}
|
|
return rr.Bytes()
|
|
}
|