all repos

scratch @ 77539dbab7c4667298a1184973b0ad6c0819c0bb

⭐ me doing recreational ~~drugs~~ programming

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

1
package main
2
3
import (
4
	"bytes"
5
	"encoding/binary"
6
	"fmt"
7
	"strings"
8
)
9
10
type Record struct {
11
	Name  string
12
	Type  uint16
13
	Class uint16
14
	TTL   uint32
15
	Data  string
16
}
17
18
func ReadRecord(r *bytes.Reader, packet []byte) (Record, error) {
19
	name, err := readName(r, packet)
20
	if err != nil {
21
		return Record{}, err
22
	}
23
24
	var rtype, class, rdlen uint16
25
	var ttl uint32
26
	_ = binary.Read(r, binary.BigEndian, &rtype)
27
	_ = binary.Read(r, binary.BigEndian, &class)
28
	_ = binary.Read(r, binary.BigEndian, &ttl)
29
	_ = binary.Read(r, binary.BigEndian, &rdlen)
30
31
	var data string
32
	switch rtype {
33
	case 1: // A
34
		var ip [4]byte
35
		_, _ = r.Read(ip[:])
36
		data = fmt.Sprintf("%d.%d.%d.%d",
37
			ip[0], ip[1], ip[2], ip[3])
38
39
	default:
40
		buf := make([]byte, rdlen)
41
		_, _ = r.Read(buf)
42
		data = fmt.Sprintf("%x", buf)
43
	}
44
45
	return Record{
46
		Name:  name,
47
		Type:  rtype,
48
		Class: class,
49
		TTL:   ttl,
50
		Data:  data,
51
	}, nil
52
}
53
54
func readName(r *bytes.Reader, packet []byte) (string, error) {
55
	var labels []string
56
	for {
57
		length, err := r.ReadByte()
58
		if err != nil {
59
			return "", err
60
		}
61
		if length == 0 {
62
			break
63
		}
64
		// pointer: top two bits set (0xC0)
65
		if length&0xC0 == 0xC0 {
66
			low, err := r.ReadByte()
67
			if err != nil {
68
				return "", err
69
			}
70
			offset := int(uint16(length&0x3F)<<8 | uint16(low))
71
			sub := bytes.NewReader(packet[offset:])
72
			name, err := readName(sub, packet)
73
			if err != nil {
74
				return "", err
75
			}
76
			labels = append(labels, name)
77
			break // pointer always ends the name
78
		}
79
		buf := make([]byte, length)
80
		if _, err := r.Read(buf); err != nil {
81
			return "", err
82
		}
83
		labels = append(labels, string(buf))
84
	}
85
	return strings.Join(labels, "."), nil
86
}