159 lines
3.7 KiB
Go
159 lines
3.7 KiB
Go
package msg
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"strconv"
|
|
"time"
|
|
|
|
tap "github.com/dnstap/golang-dnstap"
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
// Builder helps to build a Dnstap message.
|
|
type Builder struct {
|
|
Packed []byte
|
|
SocketProto tap.SocketProtocol
|
|
SocketFam tap.SocketFamily
|
|
Address net.IP
|
|
Port uint32
|
|
TimeSec uint64
|
|
TimeNsec uint32
|
|
|
|
err error
|
|
}
|
|
|
|
// New returns a new Builder
|
|
func New() *Builder {
|
|
return &Builder{}
|
|
}
|
|
|
|
// Addr adds the remote address to the message.
|
|
func (b *Builder) Addr(remote net.Addr) *Builder {
|
|
if b.err != nil {
|
|
return b
|
|
}
|
|
|
|
switch addr := remote.(type) {
|
|
case *net.TCPAddr:
|
|
b.Address = addr.IP
|
|
b.Port = uint32(addr.Port)
|
|
b.SocketProto = tap.SocketProtocol_TCP
|
|
case *net.UDPAddr:
|
|
b.Address = addr.IP
|
|
b.Port = uint32(addr.Port)
|
|
b.SocketProto = tap.SocketProtocol_UDP
|
|
default:
|
|
b.err = errors.New("unknown remote address type")
|
|
return b
|
|
}
|
|
|
|
if b.Address.To4() != nil {
|
|
b.SocketFam = tap.SocketFamily_INET
|
|
} else {
|
|
b.SocketFam = tap.SocketFamily_INET6
|
|
}
|
|
return b
|
|
}
|
|
|
|
// Msg adds the raw DNS message to the dnstap message.
|
|
func (b *Builder) Msg(m *dns.Msg) *Builder {
|
|
if b.err != nil {
|
|
return b
|
|
}
|
|
|
|
b.Packed, b.err = m.Pack()
|
|
return b
|
|
}
|
|
|
|
// HostPort adds the remote address as encoded by dnsutil.ParseHostPortOrFile to the message.
|
|
func (b *Builder) HostPort(addr string) *Builder {
|
|
ip, port, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
b.err = err
|
|
return b
|
|
}
|
|
p, err := strconv.ParseUint(port, 10, 32)
|
|
if err != nil {
|
|
b.err = err
|
|
return b
|
|
}
|
|
b.Port = uint32(p)
|
|
|
|
if ip := net.ParseIP(ip); ip != nil {
|
|
b.Address = []byte(ip)
|
|
if ip := ip.To4(); ip != nil {
|
|
b.SocketFam = tap.SocketFamily_INET
|
|
} else {
|
|
b.SocketFam = tap.SocketFamily_INET6
|
|
}
|
|
return b
|
|
}
|
|
b.err = errors.New("not an ip address")
|
|
return b
|
|
}
|
|
|
|
// Time adds the timestamp to the message.
|
|
func (b *Builder) Time(ts time.Time) *Builder {
|
|
b.TimeSec = uint64(ts.Unix())
|
|
b.TimeNsec = uint32(ts.Nanosecond())
|
|
return b
|
|
}
|
|
|
|
// ToClientResponse transforms Data into a client response message.
|
|
func (b *Builder) ToClientResponse() (*tap.Message, error) {
|
|
t := tap.Message_CLIENT_RESPONSE
|
|
return &tap.Message{
|
|
Type: &t,
|
|
SocketFamily: &b.SocketFam,
|
|
SocketProtocol: &b.SocketProto,
|
|
ResponseTimeSec: &b.TimeSec,
|
|
ResponseTimeNsec: &b.TimeNsec,
|
|
ResponseMessage: b.Packed,
|
|
QueryAddress: b.Address,
|
|
QueryPort: &b.Port,
|
|
}, b.err
|
|
}
|
|
|
|
// ToClientQuery transforms Data into a client query message.
|
|
func (b *Builder) ToClientQuery() (*tap.Message, error) {
|
|
t := tap.Message_CLIENT_QUERY
|
|
return &tap.Message{
|
|
Type: &t,
|
|
SocketFamily: &b.SocketFam,
|
|
SocketProtocol: &b.SocketProto,
|
|
QueryTimeSec: &b.TimeSec,
|
|
QueryTimeNsec: &b.TimeNsec,
|
|
QueryMessage: b.Packed,
|
|
QueryAddress: b.Address,
|
|
QueryPort: &b.Port,
|
|
}, b.err
|
|
}
|
|
|
|
// ToOutsideQuery transforms the data into a forwarder or resolver query message.
|
|
func (b *Builder) ToOutsideQuery(t tap.Message_Type) (*tap.Message, error) {
|
|
return &tap.Message{
|
|
Type: &t,
|
|
SocketFamily: &b.SocketFam,
|
|
SocketProtocol: &b.SocketProto,
|
|
QueryTimeSec: &b.TimeSec,
|
|
QueryTimeNsec: &b.TimeNsec,
|
|
QueryMessage: b.Packed,
|
|
ResponseAddress: b.Address,
|
|
ResponsePort: &b.Port,
|
|
}, b.err
|
|
}
|
|
|
|
// ToOutsideResponse transforms the data into a forwarder or resolver response message.
|
|
func (b *Builder) ToOutsideResponse(t tap.Message_Type) (*tap.Message, error) {
|
|
return &tap.Message{
|
|
Type: &t,
|
|
SocketFamily: &b.SocketFam,
|
|
SocketProtocol: &b.SocketProto,
|
|
ResponseTimeSec: &b.TimeSec,
|
|
ResponseTimeNsec: &b.TimeNsec,
|
|
ResponseMessage: b.Packed,
|
|
ResponseAddress: b.Address,
|
|
ResponsePort: &b.Port,
|
|
}, b.err
|
|
}
|