main
c8b91bc ยท 4 months ago 7 commits
 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}