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