| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | package msg
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							|  |  |  | 	"errors"
 | 
					
						
							|  |  |  | 	"net"
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 	"strconv"
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 	"time"
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tap "github.com/dnstap/golang-dnstap"
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns"
 | 
					
						
							|  |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | // Builder helps to build a Dnstap message.
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | type Builder struct {
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	Packed      []byte
 | 
					
						
							|  |  |  | 	SocketProto tap.SocketProtocol
 | 
					
						
							|  |  |  | 	SocketFam   tap.SocketFamily
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 	Address     net.IP
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	Port        uint32
 | 
					
						
							|  |  |  | 	TimeSec     uint64
 | 
					
						
							| 
									
										
										
										
											2018-03-02 15:50:31 +03:00
										 |  |  | 	TimeNsec    uint32
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err error
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | // New returns a new Builder
 | 
					
						
							|  |  |  | func New() *Builder {
 | 
					
						
							|  |  |  | 	return &Builder{}
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | // Addr adds the remote address to the message.
 | 
					
						
							|  |  |  | func (b *Builder) Addr(remote net.Addr) *Builder {
 | 
					
						
							|  |  |  | 	if b.err != nil {
 | 
					
						
							|  |  |  | 		return b
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch addr := remote.(type) {
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	case *net.TCPAddr:
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		b.Address = addr.IP
 | 
					
						
							|  |  |  | 		b.Port = uint32(addr.Port)
 | 
					
						
							|  |  |  | 		b.SocketProto = tap.SocketProtocol_TCP
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	case *net.UDPAddr:
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		b.Address = addr.IP
 | 
					
						
							|  |  |  | 		b.Port = uint32(addr.Port)
 | 
					
						
							|  |  |  | 		b.SocketProto = tap.SocketProtocol_UDP
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	default:
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		b.err = errors.New("unknown remote address type")
 | 
					
						
							|  |  |  | 		return b
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 	if b.Address.To4() != nil {
 | 
					
						
							|  |  |  | 		b.SocketFam = tap.SocketFamily_INET
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	} else {
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		b.SocketFam = tap.SocketFamily_INET6
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 	return b
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | // 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
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | // 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)
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	if err != nil {
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		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
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 	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())
 | 
					
						
							| 
									
										
										
										
											2018-03-02 15:50:31 +03:00
										 |  |  | 	b.TimeNsec = uint32(ts.Nanosecond())
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 	return b
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | // ToClientResponse transforms Data into a client response message.
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | func (b *Builder) ToClientResponse() (*tap.Message, error) {
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 	t := tap.Message_CLIENT_RESPONSE
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	return &tap.Message{
 | 
					
						
							| 
									
										
										
										
											2018-03-02 15:50:31 +03:00
										 |  |  | 		Type:             &t,
 | 
					
						
							|  |  |  | 		SocketFamily:     &b.SocketFam,
 | 
					
						
							|  |  |  | 		SocketProtocol:   &b.SocketProto,
 | 
					
						
							|  |  |  | 		ResponseTimeSec:  &b.TimeSec,
 | 
					
						
							|  |  |  | 		ResponseTimeNsec: &b.TimeNsec,
 | 
					
						
							|  |  |  | 		ResponseMessage:  b.Packed,
 | 
					
						
							|  |  |  | 		QueryAddress:     b.Address,
 | 
					
						
							|  |  |  | 		QueryPort:        &b.Port,
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 	}, b.err
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | // ToClientQuery transforms Data into a client query message.
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | func (b *Builder) ToClientQuery() (*tap.Message, error) {
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 	t := tap.Message_CLIENT_QUERY
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	return &tap.Message{
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 		Type:           &t,
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		SocketFamily:   &b.SocketFam,
 | 
					
						
							|  |  |  | 		SocketProtocol: &b.SocketProto,
 | 
					
						
							|  |  |  | 		QueryTimeSec:   &b.TimeSec,
 | 
					
						
							| 
									
										
										
										
											2018-03-02 15:50:31 +03:00
										 |  |  | 		QueryTimeNsec:  &b.TimeNsec,
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		QueryMessage:   b.Packed,
 | 
					
						
							|  |  |  | 		QueryAddress:   b.Address,
 | 
					
						
							|  |  |  | 		QueryPort:      &b.Port,
 | 
					
						
							|  |  |  | 	}, b.err
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ToOutsideQuery transforms the data into a forwarder or resolver query message.
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | func (b *Builder) ToOutsideQuery(t tap.Message_Type) (*tap.Message, error) {
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 	return &tap.Message{
 | 
					
						
							|  |  |  | 		Type:            &t,
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		SocketFamily:    &b.SocketFam,
 | 
					
						
							|  |  |  | 		SocketProtocol:  &b.SocketProto,
 | 
					
						
							|  |  |  | 		QueryTimeSec:    &b.TimeSec,
 | 
					
						
							| 
									
										
										
										
											2018-03-02 15:50:31 +03:00
										 |  |  | 		QueryTimeNsec:   &b.TimeNsec,
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 		QueryMessage:    b.Packed,
 | 
					
						
							|  |  |  | 		ResponseAddress: b.Address,
 | 
					
						
							|  |  |  | 		ResponsePort:    &b.Port,
 | 
					
						
							|  |  |  | 	}, b.err
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ToOutsideResponse transforms the data into a forwarder or resolver response message.
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | func (b *Builder) ToOutsideResponse(t tap.Message_Type) (*tap.Message, error) {
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 	return &tap.Message{
 | 
					
						
							| 
									
										
										
										
											2018-03-02 15:50:31 +03:00
										 |  |  | 		Type:             &t,
 | 
					
						
							|  |  |  | 		SocketFamily:     &b.SocketFam,
 | 
					
						
							|  |  |  | 		SocketProtocol:   &b.SocketProto,
 | 
					
						
							|  |  |  | 		ResponseTimeSec:  &b.TimeSec,
 | 
					
						
							|  |  |  | 		ResponseTimeNsec: &b.TimeNsec,
 | 
					
						
							|  |  |  | 		ResponseMessage:  b.Packed,
 | 
					
						
							|  |  |  | 		ResponseAddress:  b.Address,
 | 
					
						
							|  |  |  | 		ResponsePort:     &b.Port,
 | 
					
						
							| 
									
										
										
										
											2018-03-01 03:19:01 +01:00
										 |  |  | 	}, b.err
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | }
 |