all repos

scratch @ a00759d867bab8c32d08a2388ef49e4b4c3ff603

⭐ me doing recreational ~~drugs~~ programming

scratch/dns-server/lookup.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
dns: ch5, 1 month ago
1
package main
2
3
import (
4
	"bytes"
5
	"fmt"
6
	"net"
7
)
8
9
func Lookup(qname string, qtype QueryType, server string) (Packet, error) {
10
	conn, _ := net.Dial("udp", server)
11
	defer conn.Close()
12
13
	p := Packet{}
14
	p.Header.ID = 6666
15
	p.Header.RecursionDesired = true
16
	p.Questions = append(p.Questions, Question{
17
		Name:  qname,
18
		Type:  qtype,
19
		Class: 1, // IN
20
	})
21
22
	buf := &bytes.Buffer{}
23
	if err := p.Write(buf); err != nil {
24
		return Packet{}, fmt.Errorf("failed to write packet: %v", err)
25
	}
26
27
	if _, err := conn.Write(buf.Bytes()); err != nil {
28
		fmt.Printf("failed to write to connection: %v", err)
29
	}
30
31
	res := make([]byte, 512)
32
	n, err := conn.Read(res)
33
	if err != nil {
34
		fmt.Printf("failed to read from connection: %v", err)
35
	}
36
37
	return ParsePacket(res[:n])
38
}
39
40
func RecursiveLookup(qname string, qtype QueryType) (Packet, error) {
41
	ns := "198.41.0.4" // For now we're always starting with *a.root-servers.net*.
42
	for {
43
		fmt.Printf("attempting lookup of %v %s with ns %s\n", qtype, qname, ns)
44
45
		response, err := Lookup(qname, qtype, ns+":53")
46
		if err != nil {
47
			return Packet{}, err
48
		}
49
50
		if len(response.Answers) > 0 && response.Header.Rescode == NOERROR {
51
			return response, nil
52
		}
53
54
		if response.Header.Rescode == NXDOMAIN {
55
			return response, nil
56
		}
57
58
		if newNS, ok := response.GetResolvedNS(qname); ok {
59
			ns = newNS.String()
60
			continue
61
		}
62
63
		newNSName, ok := response.GetUnresolvedNS(qname)
64
		if !ok {
65
			return response, nil
66
		}
67
68
		recursive, err := RecursiveLookup(newNSName, AType)
69
		if err != nil {
70
			return response, nil
71
		}
72
73
		if ip, ok := recursive.GetRandomA(); ok {
74
			ns = ip.String()
75
		} else {
76
			return response, nil
77
		}
78
	}
79
}