a go dns packet parser
at v0.0.1 3.5 kB view raw
1package magna 2 3import ( 4 "fmt" 5 "math/rand" 6) 7 8// Decode decodes a DNS packet. 9func (m *Message) Decode(buf []byte) (err error) { 10 offset, err := m.Header.Decode(buf, 0) 11 if err != nil { 12 return fmt.Errorf("failed to decode message header: %w", err) 13 } 14 15 m.Question = make([]Question, 0, m.Header.QDCount) 16 for i := range m.Header.QDCount { 17 var question Question 18 offset, err = question.Decode(buf, offset) 19 if err != nil { 20 return fmt.Errorf("failed to decode question #%d: %w", i+1, err) 21 } 22 23 m.Question = append(m.Question, question) 24 } 25 26 m.Answer = make([]ResourceRecord, 0, m.Header.ANCount) 27 for i := range m.Header.ANCount { 28 var rr ResourceRecord 29 offset, err = rr.Decode(buf, offset) 30 if err != nil { 31 return fmt.Errorf("failed to decode answer record #%d: %w", i+1, err) 32 } 33 34 m.Answer = append(m.Answer, rr) 35 } 36 37 m.Authority = make([]ResourceRecord, 0, m.Header.NSCount) 38 for i := range m.Header.NSCount { 39 var rr ResourceRecord 40 offset, err = rr.Decode(buf, offset) 41 if err != nil { 42 return fmt.Errorf("failed to decode authority record #%d: %w", i+1, err) 43 } 44 45 m.Authority = append(m.Authority, rr) 46 } 47 48 m.Additional = make([]ResourceRecord, 0, m.Header.ARCount) 49 for i := range m.Header.ARCount { 50 var rr ResourceRecord 51 offset, err = rr.Decode(buf, offset) 52 if err != nil { 53 return fmt.Errorf("failed to decode additional record #%d: %w", i+1, err) 54 } 55 56 m.Additional = append(m.Additional, rr) 57 } 58 59 return nil 60} 61 62// Encode encodes a message to a DNS packet. 63// TODO: set truncation bit if over 512 and udp is protocol 64func (m *Message) Encode() ([]byte, error) { 65 m.offsets = make(map[string]uint16) 66 bytes := make([]byte, 0, 512) 67 68 headerBytes := m.Header.Encode() 69 bytes = append(bytes, headerBytes...) 70 71 var err error 72 73 for i, question := range m.Question { 74 bytes, err = question.Encode(bytes, &m.offsets) 75 if err != nil { 76 return nil, fmt.Errorf("failed to encode question #%d (%s): %w", i+1, question.QName, err) 77 } 78 } 79 80 for i, answer := range m.Answer { 81 bytes, err = answer.Encode(bytes, &m.offsets) 82 if err != nil { 83 return nil, fmt.Errorf("failed to encode answer record #%d (%s): %w", i+1, answer.Name, err) 84 } 85 } 86 87 for i, authority := range m.Authority { 88 bytes, err = authority.Encode(bytes, &m.offsets) 89 if err != nil { 90 return nil, fmt.Errorf("failed to encode authority record #%d (%s): %w", i+1, authority.Name, err) 91 } 92 } 93 94 for i, additional := range m.Additional { 95 bytes, err = additional.Encode(bytes, &m.offsets) 96 if err != nil { 97 return nil, fmt.Errorf("failed to encode additional record #%d (%s): %w", i+1, additional.Name, err) 98 } 99 } 100 101 return bytes, nil 102} 103 104func CreateRequest(op OPCode, rd bool) *Message { 105 return &Message{ 106 Header: Header{ 107 ID: uint16(rand.Intn(65534) + 1), 108 QR: false, 109 OPCode: op, 110 AA: false, 111 TC: false, 112 RD: rd, 113 RA: false, 114 Z: 0, 115 RCode: NOERROR, 116 QDCount: 0, 117 ARCount: 0, 118 NSCount: 0, 119 ANCount: 0, 120 }, 121 Question: make([]Question, 0), 122 Answer: make([]ResourceRecord, 0), 123 Additional: make([]ResourceRecord, 0), 124 Authority: make([]ResourceRecord, 0), 125 } 126} 127 128func (m *Message) CreateReply(req *Message) *Message { 129 m.Header.ID = req.Header.ID 130 m.Header.QR = true 131 m.Header.OPCode = req.Header.OPCode 132 133 return m 134} 135 136func (m *Message) AddQuestion(q Question) *Message { 137 m.Header.QDCount += 1 138 m.Question = append(m.Question, q) 139 140 return m 141} 142 143func (m *Message) SetRCode(rc RCode) *Message { 144 m.Header.RCode = rc 145 146 return m 147}