all repos

scratch @ a00759d

⭐ me doing recreational ~~drugs~~ programming
3 files changed, 87 insertions(+), 5 deletions(-)
dns: ch5
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-04-19 12:31:39 +0300
Authored at: 2026-04-18 20:36:59 +0300
Change ID: pwqmqmyqlzttszzwzkyllxxnonvtpskz
Parent: c33ca6e
M dns-server/lookup.go
···
        6
        6
         	"net"

      
        7
        7
         )

      
        8
        8
         

      
        9
        
        -const server = "8.8.8.8:53"

      
        10
        
        -

      
        11
        
        -func Lookup(qname string, qtype QueryType) (Packet, error) {

      
        
        9
        +func Lookup(qname string, qtype QueryType, server string) (Packet, error) {

      
        12
        10
         	conn, _ := net.Dial("udp", server)

      
        13
        11
         	defer conn.Close()

      
        14
        12
         

      ···
        38
        36
         

      
        39
        37
         	return ParsePacket(res[:n])

      
        40
        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
        +}

      
M dns-server/packet.go
···
        1
        1
         package main

      
        2
        2
         

      
        3
        
        -import "bytes"

      
        
        3
        +import (

      
        
        4
        +	"bytes"

      
        
        5
        +	"net"

      
        
        6
        +	"strings"

      
        
        7
        +)

      
        4
        8
         

      
        5
        9
         type Packet struct {

      
        6
        10
         	Header      Header

      ···
        81
        85
         

      
        82
        86
         	return nil

      
        83
        87
         }

      
        
        88
        +

      
        
        89
        +func (p Packet) GetRandomA() (net.IP, bool) {

      
        
        90
        +	for _, r := range p.Answers {

      
        
        91
        +		if r.Type == AType {

      
        
        92
        +			return net.ParseIP(r.Data), true

      
        
        93
        +		}

      
        
        94
        +	}

      
        
        95
        +	return nil, false

      
        
        96
        +}

      
        
        97
        +

      
        
        98
        +func (p Packet) GetResolvedNS(qname string) (net.IP, bool) {

      
        
        99
        +	for _, ns := range p.getNS(qname) {

      
        
        100
        +		host := ns[1]

      
        
        101
        +		for _, r := range p.Resources {

      
        
        102
        +			if r.Type == AType && r.Name == host {

      
        
        103
        +				return net.ParseIP(r.Data), true

      
        
        104
        +			}

      
        
        105
        +		}

      
        
        106
        +	}

      
        
        107
        +	return nil, false

      
        
        108
        +}

      
        
        109
        +

      
        
        110
        +func (p Packet) GetUnresolvedNS(qname string) (string, bool) {

      
        
        111
        +	ns := p.getNS(qname)

      
        
        112
        +	if len(ns) == 0 {

      
        
        113
        +		return "", false

      
        
        114
        +	}

      
        
        115
        +	return ns[0][1], true

      
        
        116
        +}

      
        
        117
        +

      
        
        118
        +func (p Packet) getNS(qname string) [][2]string {

      
        
        119
        +	var res [][2]string

      
        
        120
        +	for _, r := range p.Authorities {

      
        
        121
        +		if r.Type == NSType && strings.HasPrefix(qname, r.Name) {

      
        
        122
        +			res = append(res, [2]string{r.Name, r.Data})

      
        
        123
        +		}

      
        
        124
        +	}

      
        
        125
        +	return res

      
        
        126
        +}

      
M dns-server/server.go
···
        33
        33
         		q := request.Questions[0]

      
        34
        34
         		fmt.Printf("Received query: %+v\n", q)

      
        35
        35
         

      
        36
        
        -		res, rerr := Lookup(q.Name, q.Type)

      
        
        36
        +		res, rerr := RecursiveLookup(q.Name, q.Type)

      
        37
        37
         		if rerr != nil {

      
        38
        38
         			response.Header.Rescode = SERVFAIL

      
        39
        39
         		} else {