1package dns
2
3import "fmt"
4
5type Message struct {
6 Header Header
7 Questions []Question
8 Answers []RR
9}
10
11// Pack serializes the entire DNS message to wire format
12func (m *Message) Pack() ([]byte, error) {
13 var buf []byte
14
15 m.Header.QDCount = uint16(len(m.Questions))
16 m.Header.ANCount = uint16(len(m.Answers))
17 m.Header.NSCount = 0
18 m.Header.ARCount = 0
19
20 buf = append(buf, m.Header.Pack()...)
21
22 for _, q := range m.Questions {
23 buf = append(buf, q.Pack()...)
24 }
25
26 for _, rr := range m.Answers {
27 buf = append(buf, rr.Pack()...)
28 }
29
30 return buf, nil
31}
32
33// Unpack parses a raw DNS message from wire format
34func UnpackMessage(buf []byte) (*Message, error) {
35 if len(buf) < 12 {
36 return nil, fmt.Errorf("message too short: %d bytes", len(buf))
37 }
38
39 header, err := UnpackHeader(buf)
40 if err != nil {
41 return nil, err
42 }
43
44 msg := &Message{Header: *header}
45 offset := 12 // start after header
46
47 // Parse questions
48 for i := 0; i < int(header.QDCount); i++ {
49 q, consumed, err := UnpackQuestion(buf, offset)
50 if err != nil {
51 return nil, fmt.Errorf("question %d: %w", i, err)
52 }
53 msg.Questions = append(msg.Questions, *q)
54 offset += consumed
55 }
56
57 return msg, nil
58}