| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | // Package msg helps to build a dnstap Message. | 
					
						
							|  |  |  | package msg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tap "github.com/dnstap/golang-dnstap" | 
					
						
							|  |  |  | 	"github.com/miekg/dns" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | // Builder helps to build Data by being aware of the dnstap plugin configuration. | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | // 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 | 
					
						
							|  |  |  | 	Port        uint32 | 
					
						
							|  |  |  | 	TimeSec     uint64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | // HostPort decodes into Data any string returned by dnsutil.ParseHostPortOrFile. | 
					
						
							|  |  |  | func (d *Data) HostPort(addr string) error { | 
					
						
							|  |  |  | 	ip, port, err := net.SplitHostPort(addr) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	p, err := strconv.ParseUint(port, 10, 32) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	d.Port = uint32(p) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ip := net.ParseIP(ip); ip != nil { | 
					
						
							|  |  |  | 		d.Address = []byte(ip) | 
					
						
							|  |  |  | 		if ip := ip.To4(); ip != nil { | 
					
						
							|  |  |  | 			d.SocketFam = tap.SocketFamily_INET | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			d.SocketFam = tap.SocketFamily_INET6 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-01 10:21:05 -07:00
										 |  |  | 	return errors.New("not an ip address") | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RemoteAddr parses the information about the remote address into Data. | 
					
						
							|  |  |  | func (d *Data) RemoteAddr(remote net.Addr) error { | 
					
						
							|  |  |  | 	switch addr := remote.(type) { | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | // Pack encodes the DNS message into Data. | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | func (d *Data) Pack(m *dns.Msg) error { | 
					
						
							|  |  |  | 	packed, err := m.Pack() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	d.Packed = packed | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | // ToClientResponse transforms Data into a client response message. | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | func (d *Data) ToClientResponse() *tap.Message { | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 	t := tap.Message_CLIENT_RESPONSE | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 	return &tap.Message{ | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 		Type:            &t, | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 		SocketFamily:    &d.SocketFam, | 
					
						
							|  |  |  | 		SocketProtocol:  &d.SocketProto, | 
					
						
							|  |  |  | 		ResponseTimeSec: &d.TimeSec, | 
					
						
							|  |  |  | 		ResponseMessage: d.Packed, | 
					
						
							|  |  |  | 		QueryAddress:    d.Address, | 
					
						
							|  |  |  | 		QueryPort:       &d.Port, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | // ToClientQuery transforms Data into a client query message. | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | func (d *Data) ToClientQuery() *tap.Message { | 
					
						
							| 
									
										
										
										
											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, | 
					
						
							| 
									
										
										
										
											2017-07-24 23:12:50 +02:00
										 |  |  | 		SocketFamily:   &d.SocketFam, | 
					
						
							|  |  |  | 		SocketProtocol: &d.SocketProto, | 
					
						
							|  |  |  | 		QueryTimeSec:   &d.TimeSec, | 
					
						
							|  |  |  | 		QueryMessage:   d.Packed, | 
					
						
							|  |  |  | 		QueryAddress:   d.Address, | 
					
						
							|  |  |  | 		QueryPort:      &d.Port, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ToOutsideQuery transforms the data into a forwarder or resolver query message. | 
					
						
							|  |  |  | func (d *Data) ToOutsideQuery(t tap.Message_Type) *tap.Message { | 
					
						
							|  |  |  | 	return &tap.Message{ | 
					
						
							|  |  |  | 		Type:            &t, | 
					
						
							|  |  |  | 		SocketFamily:    &d.SocketFam, | 
					
						
							|  |  |  | 		SocketProtocol:  &d.SocketProto, | 
					
						
							|  |  |  | 		QueryTimeSec:    &d.TimeSec, | 
					
						
							|  |  |  | 		QueryMessage:    d.Packed, | 
					
						
							|  |  |  | 		ResponseAddress: d.Address, | 
					
						
							|  |  |  | 		ResponsePort:    &d.Port, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ToOutsideResponse transforms the data into a forwarder or resolver response message. | 
					
						
							|  |  |  | func (d *Data) ToOutsideResponse(t tap.Message_Type) *tap.Message { | 
					
						
							|  |  |  | 	return &tap.Message{ | 
					
						
							|  |  |  | 		Type:            &t, | 
					
						
							|  |  |  | 		SocketFamily:    &d.SocketFam, | 
					
						
							|  |  |  | 		SocketProtocol:  &d.SocketProto, | 
					
						
							|  |  |  | 		ResponseTimeSec: &d.TimeSec, | 
					
						
							|  |  |  | 		ResponseMessage: d.Packed, | 
					
						
							|  |  |  | 		ResponseAddress: d.Address, | 
					
						
							|  |  |  | 		ResponsePort:    &d.Port, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |