package libnetwork

import (
	"context"
	"errors"
	"fmt"
	"math/rand"
	"net"
	"net/netip"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/containerd/log"
	"github.com/docker/docker/libnetwork/internal/netiputil"
	"github.com/docker/docker/libnetwork/types"
	"github.com/miekg/dns"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/codes"
	"go.opentelemetry.io/otel/trace"
	"golang.org/x/sync/semaphore"
	"golang.org/x/time/rate"
)

// DNSBackend represents a backend DNS resolver used for DNS name
// resolution. All the queries to the resolver are forwarded to the
// backend resolver.
type DNSBackend interface {
	// ResolveName resolves a service name to an IPv4 or IPv6 address by searching
	// the networks the sandbox is connected to. For IPv6 queries, second return
	// value will be true if the name exists in docker domain but doesn't have an
	// IPv6 address. Such queries shouldn't be forwarded to external nameservers.
	ResolveName(ctx context.Context, name string, iplen int) ([]net.IP, bool)
	// ResolveIP returns the service name for the passed in IP. IP is in reverse dotted
	// notation; the format used for DNS PTR records
	ResolveIP(ctx context.Context, name string) string
	// ResolveService returns all the backend details about the containers or hosts
	// backing a service. Its purpose is to satisfy an SRV query
	ResolveService(ctx context.Context, name string) ([]*net.SRV, []net.IP)
	// ExecFunc allows a function to be executed in the context of the backend
	// on behalf of the resolver.
	ExecFunc(f func()) error
	// NdotsSet queries the backends ndots dns option settings
	NdotsSet() bool
	// HandleQueryResp passes the name & IP from a response to the backend. backend
	// can use it to maintain any required state about the resolution
	HandleQueryResp(name string, ip net.IP)
}

const (
	dnsPort       = "53"
	ptrIPv4domain = ".in-addr.arpa."
	ptrIPv6domain = ".ip6.arpa."
	respTTL       = 600
	maxExtDNS     = 3 // max number of external servers to try
	extIOTimeout  = 4 * time.Second
	maxConcurrent = 1024
	logInterval   = 2 * time.Second
)

type extDNSEntry struct {
	IPStr        string
	port         uint16 // for testing
	HostLoopback bool
}

func (e extDNSEntry) String() string {
	if e.HostLoopback {
		return "host(" + e.IPStr + ")"
	}
	return e.IPStr
}

// Resolver is the embedded DNS server in Docker. It operates by listening on
// the container's loopback interface for DNS queries.
type Resolver struct {
	backend       DNSBackend
	extDNSList    [maxExtDNS]extDNSEntry // Ext servers to use when there's no entry in ipToExtDNS.
	ipToExtDNS    addrToExtDNSMap        // DNS query source IP -> ext servers.
	server        *dns.Server
	conn          *net.UDPConn
	tcpServer     *dns.Server
	tcpListen     *net.TCPListener
	err           error
	listenAddress netip.Addr
	proxyDNS      atomic.Bool
	startCh       chan struct{}
	logger        *log.Entry

	fwdSem      *semaphore.Weighted // Limit the number of concurrent external DNS requests in-flight
	logInterval rate.Sometimes      // Rate-limit logging about hitting the fwdSem limit
}

// NewResolver creates a new instance of the Resolver
func NewResolver(address string, proxyDNS bool, backend DNSBackend) *Resolver {
	r := &Resolver{
		backend:     backend,
		err:         fmt.Errorf("setup not done yet"),
		startCh:     make(chan struct{}, 1),
		fwdSem:      semaphore.NewWeighted(maxConcurrent),
		logInterval: rate.Sometimes{Interval: logInterval},
	}
	r.listenAddress, _ = netip.ParseAddr(address)
	r.proxyDNS.Store(proxyDNS)

	return r
}

type addrToExtDNSMap struct {
	mu   sync.Mutex
	eMap map[netip.Addr][maxExtDNS]extDNSEntry
}

func (am *addrToExtDNSMap) get(addr netip.Addr) ([maxExtDNS]extDNSEntry, bool) {
	am.mu.Lock()
	defer am.mu.Unlock()
	entries, ok := am.eMap[addr]
	return entries, ok
}

func (am *addrToExtDNSMap) set(addr netip.Addr, entries []extDNSEntry) {
	var e [maxExtDNS]extDNSEntry
	copy(e[:], entries)
	am.mu.Lock()
	defer am.mu.Unlock()
	if len(entries) > 0 {
		if am.eMap == nil {
			am.eMap = map[netip.Addr][maxExtDNS]extDNSEntry{}
		}
		am.eMap[addr] = e
	} else {
		delete(am.eMap, addr)
	}
}

func (r *Resolver) log(ctx context.Context) *log.Entry {
	if r.logger == nil {
		return log.G(ctx)
	}
	return r.logger
}

// SetupFunc returns the setup function that should be run in the container's
// network namespace.
func (r *Resolver) SetupFunc(port uint16) func() {
	return func() {
		var err error

		// DNS operates primarily on UDP
		r.conn, err = net.ListenUDP("udp", net.UDPAddrFromAddrPort(
			netip.AddrPortFrom(r.listenAddress, port)),
		)
		if err != nil {
			r.err = fmt.Errorf("error in opening name server socket %v", err)
			return
		}

		// Listen on a TCP as well
		r.tcpListen, err = net.ListenTCP("tcp", net.TCPAddrFromAddrPort(
			netip.AddrPortFrom(r.listenAddress, port)),
		)
		if err != nil {
			r.err = fmt.Errorf("error in opening name TCP server socket %v", err)
			return
		}
		r.err = nil
	}
}

// Start starts the name server for the container.
func (r *Resolver) Start() error {
	r.startCh <- struct{}{}
	defer func() { <-r.startCh }()

	// make sure the resolver has been setup before starting
	if r.err != nil {
		return r.err
	}

	if err := r.setupIPTable(); err != nil {
		return fmt.Errorf("setting up IP table rules failed: %v", err)
	}

	s := &dns.Server{Handler: dns.HandlerFunc(r.serveDNS), PacketConn: r.conn}
	r.server = s
	go func() {
		if err := s.ActivateAndServe(); err != nil {
			r.log(context.TODO()).WithError(err).Error("[resolver] failed to start PacketConn DNS server")
		}
	}()

	tcpServer := &dns.Server{Handler: dns.HandlerFunc(r.serveDNS), Listener: r.tcpListen}
	r.tcpServer = tcpServer
	go func() {
		if err := tcpServer.ActivateAndServe(); err != nil {
			r.log(context.TODO()).WithError(err).Error("[resolver] failed to start TCP DNS server")
		}
	}()
	return nil
}

// Stop stops the name server for the container. A stopped resolver can be
// reused after running the SetupFunc again.
func (r *Resolver) Stop() {
	r.startCh <- struct{}{}
	defer func() { <-r.startCh }()

	if r.server != nil {
		r.server.Shutdown() //nolint:errcheck
	}
	if r.tcpServer != nil {
		r.tcpServer.Shutdown() //nolint:errcheck
	}
	r.conn = nil
	r.tcpServer = nil
	r.err = fmt.Errorf("setup not done yet")
	r.fwdSem = semaphore.NewWeighted(maxConcurrent)
}

// SetExtServers configures the external nameservers the resolver should use
// when forwarding queries, unless SetExtServersForSrc has configured servers
// for the DNS client making the request.
func (r *Resolver) SetExtServers(extDNS []extDNSEntry) {
	copy(r.extDNSList[:], r.filterExtServers(extDNS))
}

// SetForwardingPolicy re-configures the embedded DNS resolver to either enable or disable forwarding DNS queries to
// external servers.
func (r *Resolver) SetForwardingPolicy(policy bool) {
	r.proxyDNS.Store(policy)
}

// SetExtServersForSrc configures the external nameservers the resolver should
// use when forwarding queries from srcAddr. If set, these servers will be used
// in preference to servers set by SetExtServers. Supplying a nil or empty extDNS
// deletes nameservers for srcAddr.
func (r *Resolver) SetExtServersForSrc(srcAddr netip.Addr, extDNS []extDNSEntry) error {
	r.ipToExtDNS.set(srcAddr, r.filterExtServers(extDNS))
	return nil
}

// NameServer returns the IP of the DNS resolver for the containers.
func (r *Resolver) NameServer() netip.Addr {
	return r.listenAddress
}

// ResolverOptions returns resolv.conf options that should be set.
func (r *Resolver) ResolverOptions() []string {
	return []string{"ndots:0"}
}

// filterExtServers removes the resolver's own address from extDNS if present,
// and returns the result.
func (r *Resolver) filterExtServers(extDNS []extDNSEntry) []extDNSEntry {
	result := make([]extDNSEntry, 0, len(extDNS))
	for _, e := range extDNS {
		if !e.HostLoopback {
			if ra, _ := netip.ParseAddr(e.IPStr); ra == r.listenAddress {
				log.G(context.TODO()).Infof("[resolver] not using own address (%s) as an external DNS server",
					r.listenAddress)
				continue
			}
		}
		result = append(result, e)
	}
	return result
}

//nolint:gosec // The RNG is not used in a security-sensitive context.
var (
	shuffleRNG   = rand.New(rand.NewSource(time.Now().Unix()))
	shuffleRNGMu sync.Mutex
)

func shuffleAddr(addr []net.IP) []net.IP {
	shuffleRNGMu.Lock()
	defer shuffleRNGMu.Unlock()
	for i := len(addr) - 1; i > 0; i-- {
		r := shuffleRNG.Intn(i + 1) //nolint:gosec // gosec complains about the use of rand here. It should be fine.
		addr[i], addr[r] = addr[r], addr[i]
	}
	return addr
}

func createRespMsg(query *dns.Msg) *dns.Msg {
	resp := &dns.Msg{}
	resp.SetReply(query)
	resp.RecursionAvailable = true

	return resp
}

func (r *Resolver) handleMXQuery(ctx context.Context, query *dns.Msg) (*dns.Msg, error) {
	name := query.Question[0].Name
	addrv4, _ := r.backend.ResolveName(ctx, name, types.IPv4)
	addrv6, _ := r.backend.ResolveName(ctx, name, types.IPv6)

	if addrv4 == nil && addrv6 == nil {
		return nil, nil
	}

	// We were able to resolve the name. Respond with an empty list with
	// RcodeSuccess/NOERROR so that email clients can treat it as "implicit MX"
	// [RFC 5321 Section-5.1] and issue a Type A/AAAA query for the name.

	resp := createRespMsg(query)
	return resp, nil
}

func (r *Resolver) handleIPQuery(ctx context.Context, query *dns.Msg, ipType int) (*dns.Msg, error) {
	var (
		addr     []net.IP
		ipv6Miss bool
		name     = query.Question[0].Name
	)
	addr, ipv6Miss = r.backend.ResolveName(ctx, name, ipType)

	if addr == nil && ipv6Miss {
		// Send a reply without any Answer sections
		r.log(ctx).Debugf("[resolver] lookup name %s present without IPv6 address", name)
		resp := createRespMsg(query)
		return resp, nil
	}
	if addr == nil {
		return nil, nil
	}

	r.log(ctx).Debugf("[resolver] lookup for %s: IP %v", name, addr)

	resp := createRespMsg(query)
	if len(addr) > 1 {
		addr = shuffleAddr(addr)
	}
	if ipType == types.IPv4 {
		for _, ip := range addr {
			resp.Answer = append(resp.Answer, &dns.A{
				Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL},
				A:   ip,
			})
		}
	} else {
		for _, ip := range addr {
			resp.Answer = append(resp.Answer, &dns.AAAA{
				Hdr:  dns.RR_Header{Name: name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: respTTL},
				AAAA: ip,
			})
		}
	}
	return resp, nil
}

func (r *Resolver) handlePTRQuery(ctx context.Context, query *dns.Msg) (*dns.Msg, error) {
	ptr := query.Question[0].Name
	name, after, found := strings.Cut(ptr, ptrIPv4domain)
	if !found || after != "" {
		name, after, found = strings.Cut(ptr, ptrIPv6domain)
	}
	if !found || after != "" {
		// Not a known IPv4 or IPv6 PTR domain.
		// Maybe the external DNS servers know what to do with the query?
		return nil, nil
	}

	host := r.backend.ResolveIP(ctx, name)
	if host == "" {
		return nil, nil
	}

	r.log(ctx).Debugf("[resolver] lookup for IP %s: name %s", name, host)
	fqdn := dns.Fqdn(host)

	resp := createRespMsg(query)
	resp.Answer = append(resp.Answer, &dns.PTR{
		Hdr: dns.RR_Header{Name: ptr, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: respTTL},
		Ptr: fqdn,
	})
	return resp, nil
}

func (r *Resolver) handleSRVQuery(ctx context.Context, query *dns.Msg) (*dns.Msg, error) {
	svc := query.Question[0].Name
	srv, ip := r.backend.ResolveService(ctx, svc)

	if len(srv) == 0 {
		return nil, nil
	}
	if len(srv) != len(ip) {
		return nil, fmt.Errorf("invalid reply for SRV query %s", svc)
	}

	resp := createRespMsg(query)

	for i, r := range srv {
		resp.Answer = append(resp.Answer, &dns.SRV{
			Hdr:    dns.RR_Header{Name: svc, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: respTTL},
			Port:   r.Port,
			Target: r.Target,
		})
		resp.Extra = append(resp.Extra, &dns.A{
			Hdr: dns.RR_Header{Name: r.Target, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL},
			A:   ip[i],
		})
	}
	return resp, nil
}

func (r *Resolver) serveDNS(w dns.ResponseWriter, query *dns.Msg) {
	var (
		resp *dns.Msg
		err  error
	)

	if query == nil || len(query.Question) == 0 {
		return
	}

	queryName := query.Question[0].Name
	queryType := query.Question[0].Qtype

	ctx, span := otel.Tracer("").Start(context.Background(), "resolver.serveDNS", trace.WithAttributes(
		attribute.String("libnet.resolver.query.name", queryName),
		attribute.String("libnet.resolver.query.type", dns.TypeToString[queryType]),
	))
	defer span.End()

	switch queryType {
	case dns.TypeA:
		resp, err = r.handleIPQuery(ctx, query, types.IPv4)
	case dns.TypeAAAA:
		resp, err = r.handleIPQuery(ctx, query, types.IPv6)
	case dns.TypeMX:
		resp, err = r.handleMXQuery(ctx, query)
	case dns.TypePTR:
		resp, err = r.handlePTRQuery(ctx, query)
	case dns.TypeSRV:
		resp, err = r.handleSRVQuery(ctx, query)
	default:
		r.log(ctx).Debugf("[resolver] query type %s is not supported by the embedded DNS and will be forwarded to external DNS", dns.TypeToString[queryType])
	}

	reply := func(msg *dns.Msg) {
		if err = w.WriteMsg(msg); err != nil {
			r.log(ctx).WithError(err).Error("[resolver] failed to write response")
			span.RecordError(err)
			span.SetStatus(codes.Error, "WriteMsg failed")
			// Make a best-effort attempt to send a failure response to the
			// client so it doesn't have to wait for a timeout if the failure
			// has to do with the content of msg rather than the connection.
			if msg.Rcode != dns.RcodeServerFailure {
				if err := w.WriteMsg(new(dns.Msg).SetRcode(query, dns.RcodeServerFailure)); err != nil {
					r.log(ctx).WithError(err).Error("[resolver] writing ServFail response also failed")
					span.RecordError(err)
				}
			}
		}
	}

	if err != nil {
		r.log(ctx).WithError(err).Errorf("[resolver] failed to handle query: %s (%s)", queryName, dns.TypeToString[queryType])
		reply(new(dns.Msg).SetRcode(query, dns.RcodeServerFailure))
		return
	}

	if resp != nil {
		// We are the authoritative DNS server for this request so it's
		// on us to truncate the response message to the size limit
		// negotiated by the client.
		maxSize := dns.MinMsgSize
		if w.LocalAddr().Network() == "tcp" {
			maxSize = dns.MaxMsgSize
		} else {
			if optRR := query.IsEdns0(); optRR != nil {
				if udpsize := int(optRR.UDPSize()); udpsize > maxSize {
					maxSize = udpsize
				}
			}
		}
		resp.Truncate(maxSize)
		span.AddEvent("found local record", trace.WithAttributes(
			attribute.String("libnet.resolver.resp", resp.String()),
		))
		reply(resp)
		return
	}

	// If the user sets ndots > 0 explicitly and the query is
	// in the root domain don't forward it out. We will return
	// failure and let the client retry with the search domain
	// attached.
	if (queryType == dns.TypeA || queryType == dns.TypeAAAA) && r.backend.NdotsSet() &&
		!strings.Contains(strings.TrimSuffix(queryName, "."), ".") {
		resp = createRespMsg(query)
	} else {
		resp = r.forwardExtDNS(ctx, w.LocalAddr().Network(), w.RemoteAddr(), query)
	}

	if resp == nil {
		// We were unable to get an answer from any of the upstream DNS
		// servers or the backend doesn't support proxying DNS requests.
		resp = new(dns.Msg).SetRcode(query, dns.RcodeServerFailure)
	}
	reply(resp)
}

const defaultPort = "53"

func (r *Resolver) dialExtDNS(proto string, server extDNSEntry) (net.Conn, error) {
	port := defaultPort
	if server.port != 0 {
		port = strconv.FormatUint(uint64(server.port), 10)
	}
	addr := net.JoinHostPort(server.IPStr, port)

	if server.HostLoopback {
		return net.DialTimeout(proto, addr, extIOTimeout)
	}

	var (
		extConn net.Conn
		dialErr error
	)
	err := r.backend.ExecFunc(func() {
		extConn, dialErr = net.DialTimeout(proto, addr, extIOTimeout)
	})
	if err != nil {
		return nil, err
	}
	if dialErr != nil {
		return nil, dialErr
	}

	return extConn, nil
}

func (r *Resolver) forwardExtDNS(ctx context.Context, proto string, remoteAddr net.Addr, query *dns.Msg) *dns.Msg {
	ctx, span := otel.Tracer("").Start(ctx, "resolver.forwardExtDNS")
	defer span.End()

	proxyDNS := r.proxyDNS.Load()
	for _, extDNS := range r.extDNS(netiputil.AddrPortFromNet(remoteAddr)) {
		if extDNS.IPStr == "" {
			break
		}
		// If proxyDNS is false, do not forward the request from the host's namespace
		// (don't access an external DNS server from an internal network). But, it is
		// safe to make the request from the container's network namespace - it'll fail
		// if the DNS server is not accessible, but the server may be on-net.
		if !proxyDNS && extDNS.HostLoopback {
			continue
		}

		// limits the number of outstanding concurrent queries.
		ctx, cancel := context.WithTimeout(ctx, extIOTimeout)
		err := r.fwdSem.Acquire(ctx, 1)
		cancel()

		if err != nil {
			if errors.Is(err, context.DeadlineExceeded) {
				r.logInterval.Do(func() {
					r.log(ctx).Errorf("[resolver] more than %v concurrent queries", maxConcurrent)
				})
			}
			return new(dns.Msg).SetRcode(query, dns.RcodeRefused)
		}
		resp := func() *dns.Msg {
			defer r.fwdSem.Release(1)
			return r.exchange(ctx, proto, extDNS, query)
		}()
		if resp == nil {
			continue
		}

		switch resp.Rcode {
		case dns.RcodeServerFailure, dns.RcodeRefused:
			// Server returned FAILURE: continue with the next external DNS server
			// Server returned REFUSED: this can be a transitional status, so continue with the next external DNS server
			r.log(ctx).Debugf("[resolver] external DNS %s:%s returned failure:\n%s", proto, extDNS.IPStr, resp)
			continue
		}
		answers := 0
		for _, rr := range resp.Answer {
			h := rr.Header()
			switch h.Rrtype {
			case dns.TypeA:
				answers++
				ip := rr.(*dns.A).A
				r.log(ctx).Debugf("[resolver] received A record %q for %q from %s:%s", ip, h.Name, proto, extDNS.IPStr)
				r.backend.HandleQueryResp(h.Name, ip)
			case dns.TypeAAAA:
				answers++
				ip := rr.(*dns.AAAA).AAAA
				r.log(ctx).Debugf("[resolver] received AAAA record %q for %q from %s:%s", ip, h.Name, proto, extDNS.IPStr)
				r.backend.HandleQueryResp(h.Name, ip)
			}
		}
		if len(resp.Answer) == 0 {
			r.log(ctx).Debugf("[resolver] external DNS %s:%s returned response with no answers:\n%s", proto, extDNS.IPStr, resp)
		}
		resp.Compress = true
		span.AddEvent("response from upstream server")
		return resp
	}

	span.AddEvent("no response from upstream servers")
	return nil
}

func (r *Resolver) extDNS(remoteAddr netip.AddrPort) []extDNSEntry {
	if res, ok := r.ipToExtDNS.get(remoteAddr.Addr()); ok {
		return res[:]
	}
	return r.extDNSList[:]
}

func (r *Resolver) exchange(ctx context.Context, proto string, extDNS extDNSEntry, query *dns.Msg) *dns.Msg {
	ctx, span := otel.Tracer("").Start(ctx, "resolver.exchange", trace.WithAttributes(
		attribute.String("libnet.resolver.upstream.proto", proto),
		attribute.String("libnet.resolver.upstream.address", extDNS.IPStr),
		attribute.Bool("libnet.resolver.upstream.host-loopback", extDNS.HostLoopback)))
	defer span.End()

	extConn, err := r.dialExtDNS(proto, extDNS)
	if err != nil {
		r.log(ctx).WithError(err).Warn("[resolver] connect failed")
		span.RecordError(err)
		span.SetStatus(codes.Error, "dialExtDNS failed")
		return nil
	}
	defer extConn.Close()

	logger := r.log(ctx).WithFields(log.Fields{
		"dns-server":  extConn.RemoteAddr().Network() + ":" + extConn.RemoteAddr().String(),
		"client-addr": extConn.LocalAddr().Network() + ":" + extConn.LocalAddr().String(),
		"question":    query.Question[0].String(),
	})
	logger.Debug("[resolver] forwarding query")

	resp, _, err := (&dns.Client{
		Timeout: extIOTimeout,
		// Following the robustness principle, make a best-effort
		// attempt to receive oversized response messages without
		// truncating them on our end to forward verbatim to the client.
		// Some DNS servers (e.g. Mikrotik RouterOS) don't support
		// EDNS(0) and may send replies over UDP longer than 512 bytes
		// regardless of what size limit, if any, was advertised in the
		// query message. Note that ExchangeWithConn will override this
		// value if it detects an EDNS OPT record in query so only
		// oversized replies to non-EDNS queries will benefit.
		UDPSize: dns.MaxMsgSize,
	}).ExchangeWithConn(query, &dns.Conn{Conn: extConn})
	if err != nil {
		logger.WithError(err).Error("[resolver] failed to query external DNS server")
		span.RecordError(err)
		span.SetStatus(codes.Error, "ExchangeWithConn failed")
		return nil
	}

	if resp == nil {
		// Should be impossible, so make noise if it happens anyway.
		logger.Error("[resolver] external DNS returned empty response")
		span.SetStatus(codes.Error, "External DNS returned empty response")
	}
	return resp
}
