<commit_before>package weavedns

import (
	"github.com/miekg/dns"
	"log"
	"net"
)

type MDNSServer struct {
	localAddrs []net.Addr
	sendconn   *net.UDPConn
	zone       *ZoneDb
}

func NewMDNSServer(zone *ZoneDb) (*MDNSServer, error) {
	//log.Println("minimalServer sending:", buf)
	// This is a bit of a kludge - per the RFC we should send responses from 5353, but that doesn't seem to work
	sendconn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
	if err != nil {
		return nil, err
	}
	retval := &MDNSServer{sendconn: sendconn, zone: zone}

	return retval, nil
}

func makeDNSReply(r *dns.Msg, name string, addr net.IP) *dns.Msg {
	m := new(dns.Msg)
	m.SetReply(r)
	hdr := dns.RR_Header{Name: name, Rrtype: dns.TypeA,
		Class: dns.ClassINET, Ttl: 3600}
	a := &dns.A{hdr, addr}
	m.Answer = append(m.Answer, a)
	return m
}

// Return true if testaddr is a UDP address with IP matching my local i/f
func (s *MDNSServer) addrIsLocal(testaddr net.Addr) bool {
	if udpaddr, ok := testaddr.(*net.UDPAddr); ok {
		for _, localaddr := range s.localAddrs {
			if ipnetlocal, ok := localaddr.(*net.IPNet); ok {
				if ipnetlocal.IP.Equal(udpaddr.IP) {
					return true
				}
			}
		}
	}
	return false
}

func (s *MDNSServer) Start(ifi *net.Interface) error {
	handleMDNS := func(w dns.ResponseWriter, r *dns.Msg) {
		// Ignore answers to other questions
		if len(r.Answer) == 0 && len(r.Question) > 0 {
			q := r.Question[0]
			ip, err := s.zone.MatchLocal(q.Name)
			if err == nil {
				m := makeDNSReply(r, q.Name, ip)
				s.SendResponse(m)
			} else if s.addrIsLocal(w.RemoteAddr()) {
				// ignore this - it's our own query received via multicast
			} else {
				log.Printf("Failed MDNS lookup for %s", q.Name)
			}
		}
	}

	conn, err := LinkLocalMulticastListener(ifi)
	if err != nil {
		return err
	}
	s.localAddrs, err = ifi.Addrs()
	if err != nil {
		return err
	}

	go dns.ActivateAndServe(nil, conn, dns.HandlerFunc(handleMDNS))

	return err
}

func (s *MDNSServer) SendResponse(m *dns.Msg) error {
	buf, err := m.Pack()
	if err != nil {
		return err
	}
	_, err = s.sendconn.WriteTo(buf, ipv4Addr)
	return err
}
<commit_msg>Don't crash on nil (default) interface<commit_after>package weavedns

import (
	"github.com/miekg/dns"
	"log"
	"net"
)

type MDNSServer struct {
	localAddrs []net.Addr
	sendconn   *net.UDPConn
	zone       *ZoneDb
}

func NewMDNSServer(zone *ZoneDb) (*MDNSServer, error) {
	//log.Println("minimalServer sending:", buf)
	// This is a bit of a kludge - per the RFC we should send responses from 5353, but that doesn't seem to work
	sendconn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
	if err != nil {
		return nil, err
	}
	retval := &MDNSServer{sendconn: sendconn, zone: zone}

	return retval, nil
}

func makeDNSReply(r *dns.Msg, name string, addr net.IP) *dns.Msg {
	m := new(dns.Msg)
	m.SetReply(r)
	hdr := dns.RR_Header{Name: name, Rrtype: dns.TypeA,
		Class: dns.ClassINET, Ttl: 3600}
	a := &dns.A{hdr, addr}
	m.Answer = append(m.Answer, a)
	return m
}

// Return true if testaddr is a UDP address with IP matching my local i/f
func (s *MDNSServer) addrIsLocal(testaddr net.Addr) bool {
	if udpaddr, ok := testaddr.(*net.UDPAddr); ok {
		for _, localaddr := range s.localAddrs {
			if ipnetlocal, ok := localaddr.(*net.IPNet); ok {
				if ipnetlocal.IP.Equal(udpaddr.IP) {
					return true
				}
			}
		}
	}
	return false
}

func (s *MDNSServer) Start(ifi *net.Interface) error {
	handleMDNS := func(w dns.ResponseWriter, r *dns.Msg) {
		// Ignore answers to other questions
		if len(r.Answer) == 0 && len(r.Question) > 0 {
			q := r.Question[0]
			ip, err := s.zone.MatchLocal(q.Name)
			if err == nil {
				m := makeDNSReply(r, q.Name, ip)
				s.SendResponse(m)
			} else if s.addrIsLocal(w.RemoteAddr()) {
				// ignore this - it's our own query received via multicast
			} else {
				log.Printf("Failed MDNS lookup for %s", q.Name)
			}
		}
	}

	conn, err := LinkLocalMulticastListener(ifi)
	if err != nil {
		return err
	}
	if ifi == nil {
		s.localAddrs, err = net.InterfaceAddrs()
	} else {
		s.localAddrs, err = ifi.Addrs()
	}
	if err != nil {
		return err
	}

	go dns.ActivateAndServe(nil, conn, dns.HandlerFunc(handleMDNS))

	return err
}

func (s *MDNSServer) SendResponse(m *dns.Msg) error {
	buf, err := m.Pack()
	if err != nil {
		return err
	}
	_, err = s.sendconn.WriteTo(buf, ipv4Addr)
	return err
}

{'fraction_non_alphanumeric': 0.14175199089874857, 'fraction_numerical': 0.006825938566552901, 'mean_word_length': 3.3225172074729596, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7519039', 'n_tokens_mistral': 1904, 'n_tokens_neox': 1748, 'n_words': 468}