a go dns packet parser
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 := m.Header.Encode() 62 63 for _, question := range m.Question { 64 bytes = question.Encode(bytes, &m.offsets) 65 } 66 67 for _, answer := range m.Answer { 68 bytes = answer.Encode(bytes, &m.offsets) 69 } 70 71 for _, authority := range m.Authority { 72 bytes = authority.Encode(bytes, &m.offsets) 73 } 74 75 for _, additional := range m.Additional { 76 bytes = additional.Encode(bytes, &m.offsets) 77 } 78 79 return bytes 80} 81 82func CreateRequest(op OPCode, rd bool) *Message { 83 return &Message{ 84 Header: Header{ 85 ID: uint16(rand.Intn(65534) + 1), 86 QR: false, 87 OPCode: op, 88 AA: false, 89 TC: false, 90 RD: rd, 91 RA: false, 92 Z: 0, 93 RCode: NOERROR, 94 QDCount: 0, 95 ARCount: 0, 96 NSCount: 0, 97 ANCount: 0, 98 }, 99 Question: make([]Question, 0), 100 Answer: make([]ResourceRecord, 0), 101 Additional: make([]ResourceRecord, 0), 102 Authority: make([]ResourceRecord, 0), 103 } 104} 105 106func (m *Message) CreateReply(req *Message) *Message { 107 m.Header.ID = req.Header.ID 108 m.Header.QR = true 109 m.Header.OPCode = req.Header.OPCode 110 111 return m 112} 113 114func (m *Message) AddQuestion(q Question) *Message { 115 m.Header.QDCount += 1 116 m.Question = append(m.Question, q) 117 118 return m 119} 120 121func (m *Message) SetRCode(rc RCode) *Message { 122 m.Header.RCode = rc 123 124 return m 125}