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}