main
c8b91bc ยท 4 months ago 7 commits
 1package dns
 2
 3import (
 4	"encoding/binary"
 5	"fmt"
 6)
 7
 8// Record types per RFC 1035 + RFC 3596
 9const (
10	TypeA     = 1
11	TypeNS    = 2
12	TypeCNAME = 5
13	TypeMX    = 15
14	TypeTXT   = 16
15	TypeAAAA  = 28 // RFC 3596
16
17	ClassIN = 1 // Internet class
18)
19
20type Question struct {
21	Name  string
22	Type  uint16
23	Class uint16
24}
25
26// Pack serializes a question to wire format
27func (q *Question) Pack() []byte {
28	var buf []byte
29	buf = append(buf, PackDomain(q.Name)...)
30	buf = append(buf, 0, 0) // Type
31	buf = append(buf, 0, 0) // Class
32	binary.BigEndian.PutUint16(buf[len(buf)-4:], q.Type)
33	binary.BigEndian.PutUint16(buf[len(buf)-2:], q.Class)
34	return buf
35}
36
37// UnpackQuestion parses a question from wire format at offset
38func UnpackQuestion(buf []byte, offset int) (*Question, int, error) {
39	name, consumed, err := UnpackDomain(buf, offset)
40	if err != nil {
41		return nil, 0, fmt.Errorf("question name: %w", err)
42	}
43	offset += consumed
44
45	if offset+4 > len(buf) {
46		return nil, 0, fmt.Errorf("question too short for type/class")
47	}
48
49	qtype := binary.BigEndian.Uint16(buf[offset : offset+2])
50	qclass := binary.BigEndian.Uint16(buf[offset+2 : offset+4])
51
52	return &Question{
53		Name:  name,
54		Type:  qtype,
55		Class: qclass,
56	}, consumed + 4, nil
57}