diff options
Diffstat (limited to 'middleware/dnstap/msg/msg.go')
-rw-r--r-- | middleware/dnstap/msg/msg.go | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/middleware/dnstap/msg/msg.go b/middleware/dnstap/msg/msg.go new file mode 100644 index 000000000..97c7ec7cc --- /dev/null +++ b/middleware/dnstap/msg/msg.go @@ -0,0 +1,89 @@ +// Package msg helps to build a dnstap Message. +package msg + +import ( + "errors" + "net" + "time" + + "github.com/coredns/coredns/request" + + tap "github.com/dnstap/golang-dnstap" + "github.com/miekg/dns" +) + +// Data helps to build a dnstap Message. +// It can be transformed into the actual Message using this package. +type Data struct { + Type tap.Message_Type + Packed []byte + SocketProto tap.SocketProtocol + SocketFam tap.SocketFamily + Address []byte + Port uint32 + TimeSec uint64 +} + +func (d *Data) FromRequest(r request.Request) error { + switch addr := r.W.RemoteAddr().(type) { + case *net.TCPAddr: + d.Address = addr.IP + d.Port = uint32(addr.Port) + d.SocketProto = tap.SocketProtocol_TCP + case *net.UDPAddr: + d.Address = addr.IP + d.Port = uint32(addr.Port) + d.SocketProto = tap.SocketProtocol_UDP + default: + return errors.New("unknown remote address type") + } + + if a := net.IP(d.Address); a.To4() != nil { + d.SocketFam = tap.SocketFamily_INET + } else { + d.SocketFam = tap.SocketFamily_INET6 + } + + return nil +} + +func (d *Data) Pack(m *dns.Msg) error { + packed, err := m.Pack() + if err != nil { + return err + } + d.Packed = packed + return nil +} + +func (d *Data) Epoch() { + d.TimeSec = uint64(time.Now().Unix()) +} + +// Transform the data into a client response message. +func (d *Data) ToClientResponse() *tap.Message { + d.Type = tap.Message_CLIENT_RESPONSE + return &tap.Message{ + Type: &d.Type, + SocketFamily: &d.SocketFam, + SocketProtocol: &d.SocketProto, + ResponseTimeSec: &d.TimeSec, + ResponseMessage: d.Packed, + QueryAddress: d.Address, + QueryPort: &d.Port, + } +} + +// Transform the data into a client query message. +func (d *Data) ToClientQuery() *tap.Message { + d.Type = tap.Message_CLIENT_QUERY + return &tap.Message{ + Type: &d.Type, + SocketFamily: &d.SocketFam, + SocketProtocol: &d.SocketProto, + QueryTimeSec: &d.TimeSec, + QueryMessage: d.Packed, + QueryAddress: d.Address, + QueryPort: &d.Port, + } +} |