2021-09-28 12:42:01 +02:00
|
|
|
package netxlite
|
2021-02-02 12:05:47 +01:00
|
|
|
|
2022-01-03 13:53:23 +01:00
|
|
|
import (
|
|
|
|
"github.com/miekg/dns"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/model"
|
|
|
|
)
|
2021-02-02 12:05:47 +01:00
|
|
|
|
2021-09-28 10:47:59 +02:00
|
|
|
// DNSDecoderMiekg uses github.com/miekg/dns to implement the Decoder.
|
|
|
|
type DNSDecoderMiekg struct{}
|
2021-02-02 12:05:47 +01:00
|
|
|
|
2021-09-28 10:47:59 +02:00
|
|
|
func (d *DNSDecoderMiekg) parseReply(data []byte) (*dns.Msg, error) {
|
2021-02-02 12:05:47 +01:00
|
|
|
reply := new(dns.Msg)
|
|
|
|
if err := reply.Unpack(data); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// TODO(bassosimone): map more errors to net.DNSError names
|
2021-09-27 16:48:46 +02:00
|
|
|
// TODO(bassosimone): add support for lame referral.
|
2021-02-02 12:05:47 +01:00
|
|
|
switch reply.Rcode {
|
|
|
|
case dns.RcodeSuccess:
|
2021-09-27 16:48:46 +02:00
|
|
|
return reply, nil
|
2021-02-02 12:05:47 +01:00
|
|
|
case dns.RcodeNameError:
|
2021-09-28 12:42:01 +02:00
|
|
|
return nil, ErrOODNSNoSuchHost
|
2021-09-27 16:48:46 +02:00
|
|
|
case dns.RcodeRefused:
|
2021-09-28 12:42:01 +02:00
|
|
|
return nil, ErrOODNSRefused
|
2021-02-02 12:05:47 +01:00
|
|
|
default:
|
2021-09-28 12:42:01 +02:00
|
|
|
return nil, ErrOODNSMisbehaving
|
2021-09-27 16:48:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-03 13:53:23 +01:00
|
|
|
func (d *DNSDecoderMiekg) DecodeHTTPS(data []byte) (*model.HTTPSSvc, error) {
|
2021-09-27 23:09:41 +02:00
|
|
|
reply, err := d.parseReply(data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-01-03 13:53:23 +01:00
|
|
|
out := &model.HTTPSSvc{}
|
2021-09-27 23:09:41 +02:00
|
|
|
for _, answer := range reply.Answer {
|
|
|
|
switch avalue := answer.(type) {
|
|
|
|
case *dns.HTTPS:
|
|
|
|
for _, v := range avalue.Value {
|
|
|
|
switch extv := v.(type) {
|
|
|
|
case *dns.SVCBAlpn:
|
|
|
|
out.ALPN = extv.Alpn
|
|
|
|
case *dns.SVCBIPv4Hint:
|
|
|
|
for _, ip := range extv.Hint {
|
|
|
|
out.IPv4 = append(out.IPv4, ip.String())
|
|
|
|
}
|
|
|
|
case *dns.SVCBIPv6Hint:
|
|
|
|
for _, ip := range extv.Hint {
|
|
|
|
out.IPv6 = append(out.IPv6, ip.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(out.ALPN) <= 0 {
|
2021-09-28 12:42:01 +02:00
|
|
|
return nil, ErrOODNSNoAnswer
|
2021-09-27 23:09:41 +02:00
|
|
|
}
|
|
|
|
return out, nil
|
|
|
|
}
|
|
|
|
|
2021-09-28 10:47:59 +02:00
|
|
|
func (d *DNSDecoderMiekg) DecodeLookupHost(qtype uint16, data []byte) ([]string, error) {
|
2021-09-27 16:48:46 +02:00
|
|
|
reply, err := d.parseReply(data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
var addrs []string
|
|
|
|
for _, answer := range reply.Answer {
|
|
|
|
switch qtype {
|
|
|
|
case dns.TypeA:
|
|
|
|
if rra, ok := answer.(*dns.A); ok {
|
|
|
|
ip := rra.A
|
|
|
|
addrs = append(addrs, ip.String())
|
|
|
|
}
|
|
|
|
case dns.TypeAAAA:
|
|
|
|
if rra, ok := answer.(*dns.AAAA); ok {
|
|
|
|
ip := rra.AAAA
|
|
|
|
addrs = append(addrs, ip.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(addrs) <= 0 {
|
2021-09-28 12:42:01 +02:00
|
|
|
return nil, ErrOODNSNoAnswer
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
return addrs, nil
|
|
|
|
}
|
|
|
|
|
2022-01-03 13:53:23 +01:00
|
|
|
var _ model.DNSDecoder = &DNSDecoderMiekg{}
|