mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-30 17:53:21 -04:00 
			
		
		
		
	Easier way to dnstap? (#1496)
* Easier way to dnstap? * Remove unnecessary function parameter from Tapper * golint * golint 2 * Proxy dnstap tests * README.md & doc * net.IP * Proxy test was incorrect * Small changes * Update README.md * Was not reporting dnstap errors + test * Wasn't working at all, now it's ok * Thanks Travis
This commit is contained in:
		| @@ -1,157 +1,153 @@ | ||||
| // Package msg helps to build a dnstap Message. | ||||
| package msg | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
|  | ||||
| 	tap "github.com/dnstap/golang-dnstap" | ||||
| 	"github.com/miekg/dns" | ||||
| ) | ||||
|  | ||||
| // Builder helps to build Data by being aware of the dnstap plugin configuration. | ||||
| // Builder helps to build a Dnstap message. | ||||
| type Builder struct { | ||||
| 	Full bool | ||||
| 	Data | ||||
| } | ||||
|  | ||||
| // AddrMsg parses the info of net.Addr and dns.Msg. | ||||
| func (b *Builder) AddrMsg(a net.Addr, m *dns.Msg) (err error) { | ||||
| 	err = b.RemoteAddr(a) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return b.Msg(m) | ||||
| } | ||||
|  | ||||
| // Msg parses the info of dns.Msg. | ||||
| func (b *Builder) Msg(m *dns.Msg) (err error) { | ||||
| 	if b.Full { | ||||
| 		err = b.Pack(m) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // Data helps to build a dnstap Message. | ||||
| // It can be transformed into the actual Message using this package. | ||||
| type Data struct { | ||||
| 	Packed      []byte | ||||
| 	SocketProto tap.SocketProtocol | ||||
| 	SocketFam   tap.SocketFamily | ||||
| 	Address     []byte | ||||
| 	Address     net.IP | ||||
| 	Port        uint32 | ||||
| 	TimeSec     uint64 | ||||
|  | ||||
| 	err error | ||||
| } | ||||
|  | ||||
| // HostPort decodes into Data any string returned by dnsutil.ParseHostPortOrFile. | ||||
| func (d *Data) HostPort(addr string) 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 { | ||||
| 		return err | ||||
| 		b.err = err | ||||
| 		return b | ||||
| 	} | ||||
| 	p, err := strconv.ParseUint(port, 10, 32) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		b.err = err | ||||
| 		return b | ||||
| 	} | ||||
| 	d.Port = uint32(p) | ||||
| 	b.Port = uint32(p) | ||||
|  | ||||
| 	if ip := net.ParseIP(ip); ip != nil { | ||||
| 		d.Address = []byte(ip) | ||||
| 		b.Address = []byte(ip) | ||||
| 		if ip := ip.To4(); ip != nil { | ||||
| 			d.SocketFam = tap.SocketFamily_INET | ||||
| 			b.SocketFam = tap.SocketFamily_INET | ||||
| 		} else { | ||||
| 			d.SocketFam = tap.SocketFamily_INET6 | ||||
| 			b.SocketFam = tap.SocketFamily_INET6 | ||||
| 		} | ||||
| 		return nil | ||||
| 		return b | ||||
| 	} | ||||
| 	return errors.New("not an ip address") | ||||
| 	b.err = errors.New("not an ip address") | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // RemoteAddr parses the information about the remote address into Data. | ||||
| func (d *Data) RemoteAddr(remote net.Addr) error { | ||||
| 	switch addr := remote.(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 | ||||
| } | ||||
|  | ||||
| // Pack encodes the DNS message into Data. | ||||
| func (d *Data) Pack(m *dns.Msg) error { | ||||
| 	packed, err := m.Pack() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	d.Packed = packed | ||||
| 	return nil | ||||
| // Time adds the timestamp to the message. | ||||
| func (b *Builder) Time(ts time.Time) *Builder { | ||||
| 	b.TimeSec = uint64(ts.Unix()) | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // ToClientResponse transforms Data into a client response message. | ||||
| func (d *Data) ToClientResponse() *tap.Message { | ||||
| func (b *Builder) ToClientResponse() (*tap.Message, error) { | ||||
| 	t := tap.Message_CLIENT_RESPONSE | ||||
| 	return &tap.Message{ | ||||
| 		Type:            &t, | ||||
| 		SocketFamily:    &d.SocketFam, | ||||
| 		SocketProtocol:  &d.SocketProto, | ||||
| 		ResponseTimeSec: &d.TimeSec, | ||||
| 		ResponseMessage: d.Packed, | ||||
| 		QueryAddress:    d.Address, | ||||
| 		QueryPort:       &d.Port, | ||||
| 	} | ||||
| 		SocketFamily:    &b.SocketFam, | ||||
| 		SocketProtocol:  &b.SocketProto, | ||||
| 		ResponseTimeSec: &b.TimeSec, | ||||
| 		ResponseMessage: b.Packed, | ||||
| 		QueryAddress:    b.Address, | ||||
| 		QueryPort:       &b.Port, | ||||
| 	}, b.err | ||||
| } | ||||
|  | ||||
| // ToClientQuery transforms Data into a client query message. | ||||
| func (d *Data) ToClientQuery() *tap.Message { | ||||
| func (b *Builder) ToClientQuery() (*tap.Message, error) { | ||||
| 	t := tap.Message_CLIENT_QUERY | ||||
| 	return &tap.Message{ | ||||
| 		Type:           &t, | ||||
| 		SocketFamily:   &d.SocketFam, | ||||
| 		SocketProtocol: &d.SocketProto, | ||||
| 		QueryTimeSec:   &d.TimeSec, | ||||
| 		QueryMessage:   d.Packed, | ||||
| 		QueryAddress:   d.Address, | ||||
| 		QueryPort:      &d.Port, | ||||
| 	} | ||||
| 		SocketFamily:   &b.SocketFam, | ||||
| 		SocketProtocol: &b.SocketProto, | ||||
| 		QueryTimeSec:   &b.TimeSec, | ||||
| 		QueryMessage:   b.Packed, | ||||
| 		QueryAddress:   b.Address, | ||||
| 		QueryPort:      &b.Port, | ||||
| 	}, b.err | ||||
| } | ||||
|  | ||||
| // ToOutsideQuery transforms the data into a forwarder or resolver query message. | ||||
| func (d *Data) ToOutsideQuery(t tap.Message_Type) *tap.Message { | ||||
| func (b *Builder) ToOutsideQuery(t tap.Message_Type) (*tap.Message, error) { | ||||
| 	return &tap.Message{ | ||||
| 		Type:            &t, | ||||
| 		SocketFamily:    &d.SocketFam, | ||||
| 		SocketProtocol:  &d.SocketProto, | ||||
| 		QueryTimeSec:    &d.TimeSec, | ||||
| 		QueryMessage:    d.Packed, | ||||
| 		ResponseAddress: d.Address, | ||||
| 		ResponsePort:    &d.Port, | ||||
| 	} | ||||
| 		SocketFamily:    &b.SocketFam, | ||||
| 		SocketProtocol:  &b.SocketProto, | ||||
| 		QueryTimeSec:    &b.TimeSec, | ||||
| 		QueryMessage:    b.Packed, | ||||
| 		ResponseAddress: b.Address, | ||||
| 		ResponsePort:    &b.Port, | ||||
| 	}, b.err | ||||
| } | ||||
|  | ||||
| // ToOutsideResponse transforms the data into a forwarder or resolver response message. | ||||
| func (d *Data) ToOutsideResponse(t tap.Message_Type) *tap.Message { | ||||
| func (b *Builder) ToOutsideResponse(t tap.Message_Type) (*tap.Message, error) { | ||||
| 	return &tap.Message{ | ||||
| 		Type:            &t, | ||||
| 		SocketFamily:    &d.SocketFam, | ||||
| 		SocketProtocol:  &d.SocketProto, | ||||
| 		ResponseTimeSec: &d.TimeSec, | ||||
| 		ResponseMessage: d.Packed, | ||||
| 		ResponseAddress: d.Address, | ||||
| 		ResponsePort:    &d.Port, | ||||
| 	} | ||||
| 		SocketFamily:    &b.SocketFam, | ||||
| 		SocketProtocol:  &b.SocketProto, | ||||
| 		ResponseTimeSec: &b.TimeSec, | ||||
| 		ResponseMessage: b.Packed, | ||||
| 		ResponseAddress: b.Address, | ||||
| 		ResponsePort:    &b.Port, | ||||
| 	}, b.err | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user