aboutsummaryrefslogtreecommitdiff
path: root/middleware/dnstap/msg/msg.go
diff options
context:
space:
mode:
Diffstat (limited to 'middleware/dnstap/msg/msg.go')
-rw-r--r--middleware/dnstap/msg/msg.go89
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,
+ }
+}