@@ -3,6 +3,7 @@ package layers
33import (
44 "encoding/binary"
55 "fmt"
6+ "net/netip"
67 "strings"
78 "unsafe"
89)
@@ -147,13 +148,13 @@ func bytesToStr(myBytes []byte) string {
147148 return unsafe .String (unsafe .SliceData (myBytes ), len (myBytes ))
148149}
149150
150- func extractDomain ( data [] byte , tail []byte ) (string , []byte ) {
151+ func ( d * DNSMessage ) extractDomain ( tail []byte ) (string , []byte ) {
151152 var domainName string
152153 for {
153154 blen := tail [0 ]
154155 if blen >> 6 == 0b11 {
155156 offset := binary .BigEndian .Uint16 (tail [0 :2 ])& (1 << 14 - 1 ) - headerSizeDNS
156- part , _ := extractDomain (data , data [offset :])
157+ part , _ := d . extractDomain (d . payload [offset :])
157158 domainName += part
158159 tail = tail [2 :]
159160 break
@@ -167,76 +168,162 @@ func extractDomain(data []byte, tail []byte) (string, []byte) {
167168
168169 tail = tail [blen :]
169170 }
170- return domainName , tail
171+ return strings .TrimRight (domainName , "." ), tail
172+ }
173+
174+ func (d * DNSMessage ) parseRData (typ uint16 , tail []byte , rdl int ) (string , string , []byte ) {
175+ var rdata string
176+ var typname string
177+ switch typ {
178+ case 1 :
179+ typname = "A"
180+ addr , _ := netip .AddrFromSlice (tail [0 :rdl ])
181+ rdata = fmt .Sprintf ("Address: %s" , addr )
182+ case 2 :
183+ typname = "NS"
184+ domain , _ := d .extractDomain (tail )
185+ rdata = fmt .Sprintf ("%s: %s" , typname , domain )
186+ case 5 :
187+ typname = "CNAME"
188+ domain , _ := d .extractDomain (tail )
189+ rdata = fmt .Sprintf ("%s: %s" , typname , domain )
190+ case 6 :
191+ typname = "SOA"
192+ var (
193+ primary string
194+ mailbox string
195+ )
196+ ttail := tail
197+ primary , ttail = d .extractDomain (ttail )
198+ mailbox , ttail = d .extractDomain (ttail )
199+ serial := binary .BigEndian .Uint32 (ttail [0 :4 ])
200+ refresh := binary .BigEndian .Uint32 (ttail [4 :8 ])
201+ retry := binary .BigEndian .Uint32 (ttail [8 :12 ])
202+ expire := binary .BigEndian .Uint32 (ttail [12 :16 ])
203+ min := binary .BigEndian .Uint32 (ttail [16 :20 ])
204+ rdata = fmt .Sprintf (`Primary name server: %s
205+ - Responsible authority's mailbox: %s
206+ - Serial number: %d
207+ - Refresh interval: %d
208+ - Retry interval: %d
209+ - Expire limit: %d
210+ - Minimum TTL: %d
211+ ` , primary , mailbox , serial , refresh , retry , expire , min )
212+ case 15 :
213+ typname = "MX"
214+ preference := binary .BigEndian .Uint16 (tail [0 :2 ])
215+ domain , _ := d .extractDomain (tail [2 :rdl ])
216+ rdata = fmt .Sprintf ("%s: preference %d %s" , typname , preference , domain )
217+ case 16 :
218+ typname = "TXT"
219+ rdata = fmt .Sprintf ("%s: %s" , typname , tail [:rdl ])
220+ case 28 :
221+ typname = "AAAA"
222+ addr , _ := netip .AddrFromSlice (tail [0 :rdl ])
223+ rdata = fmt .Sprintf ("Address: %s" , addr )
224+ case 41 :
225+ typname = "OPT"
226+ default :
227+ rdata = fmt .Sprintf ("Unknown: %d bytes" , rdl )
228+ }
229+ return typname , rdata , tail [rdl :]
230+ }
231+
232+ func (d * DNSMessage ) parseQuery (tail []byte ) (string , []byte ) {
233+ var domain string
234+ domain , tail = d .extractDomain (tail )
235+ typ := binary .BigEndian .Uint16 (tail [0 :2 ])
236+ class := binary .BigEndian .Uint16 (tail [2 :4 ])
237+ tail = tail [4 :]
238+ // TODO: add type and class description https://en.wikipedia.org/wiki/List_of_DNS_record_types
239+ return fmt .Sprintf (` - %s:
240+ - Name: %s
241+ - Type: (%d)
242+ - Class: %d
243+ ` , domain , domain , typ , class ), tail
244+ }
245+
246+ func (d * DNSMessage ) parseRR (tail []byte ) (string , []byte ) {
247+ var domain string
248+ domain , tail = d .extractDomain (tail )
249+ typ := binary .BigEndian .Uint16 (tail [0 :2 ])
250+ class := binary .BigEndian .Uint16 (tail [2 :4 ])
251+ ttl := binary .BigEndian .Uint32 (tail [4 :8 ])
252+ rdl := int (binary .BigEndian .Uint16 (tail [8 :10 ]))
253+ var (
254+ typename string
255+ rdata string
256+ )
257+ typename , rdata , tail = d .parseRData (typ , tail [10 :], rdl )
258+ return fmt .Sprintf (` - %s:
259+ - Name: %s
260+ - Type: %s (%d)
261+ - Class: %d
262+ - TTL: %d
263+ - Data Length: %d
264+ - %s
265+ ` , domain , domain , typename , typ , class , ttl , rdl , rdata ), tail
266+ }
267+
268+ func (d * DNSMessage ) parseRoot (tail []byte ) (string , []byte ) {
269+ domain := "Root"
270+ tail = tail [1 :]
271+ typ := binary .BigEndian .Uint16 (tail [0 :2 ])
272+ ups := binary .BigEndian .Uint16 (tail [2 :4 ])
273+ hb := tail [4 ]
274+ ednsv := tail [5 ]
275+ zres := binary .BigEndian .Uint16 (tail [6 :8 ])
276+ rdl := int (binary .BigEndian .Uint16 (tail [8 :10 ]))
277+ var typename string
278+ typename , _ , tail = d .parseRData (typ , tail [10 :], rdl )
279+ return fmt .Sprintf (` - %s:
280+ - Name: %s
281+ - Type: %s (%d)
282+ - UDP payload size: %d
283+ - Higher bits in extended RCODE: %#02x
284+ - EDNS0 version: %d
285+ - Z: %d
286+ - Data Length: %d
287+ ` , domain , domain , typename , typ , ups , hb , ednsv , zres , rdl ), tail
171288}
172289
173290func (d * DNSMessage ) rrecords () string {
174- var sb strings.Builder
175- tail := d .payload
291+ var (
292+ sb strings.Builder
293+ rec string
294+ tail = d .payload
295+ )
176296 if d .Questions > 0 {
177297 sb .WriteString ("- Queries:\n " )
178298 for range d .Questions {
179- var domain string
180- domain , tail = extractDomain (d .payload , tail )
181- typ := binary .BigEndian .Uint16 (tail [0 :2 ])
182- class := binary .BigEndian .Uint16 (tail [2 :4 ])
183- tail = tail [4 :]
184- // TODO: add type and class description https://en.wikipedia.org/wiki/List_of_DNS_record_types
185- sb .WriteString (fmt .Sprintf (" %s: type %d class %d\n " , domain , typ , class ))
299+ rec , tail = d .parseQuery (tail )
300+ sb .WriteString (rec )
186301 }
187302 }
188303 if d .AnswerRRs > 0 {
189304 sb .WriteString ("- Answers:\n " )
190305 for range d .AnswerRRs {
191- var domain string
192- domain , tail = extractDomain (d .payload , tail )
193- typ := binary .BigEndian .Uint16 (tail [0 :2 ])
194- class := binary .BigEndian .Uint16 (tail [2 :4 ])
195- ttl := binary .BigEndian .Uint32 (tail [4 :8 ])
196- rdl := int (binary .BigEndian .Uint16 (tail [8 :10 ]))
197- //rdata := d.payload[offset : offset+rdl]
198- tail = tail [10 + rdl :]
199- sb .WriteString (fmt .Sprintf (" %s: type %d class %d ttl %08x rdl %04x\n " , domain , typ , class , ttl , rdl ))
306+ rec , tail = d .parseRR (tail )
307+ sb .WriteString (rec )
200308 }
201309 }
202310 if d .AuthorityRRs > 0 {
203311 sb .WriteString ("- Authoritative nameservers:\n " )
204312 for range d .AuthorityRRs {
205- var domain string
206- domain , tail = extractDomain (d .payload , tail )
207- typ := binary .BigEndian .Uint16 (tail [0 :2 ])
208- class := binary .BigEndian .Uint16 (tail [2 :4 ])
209- ttl := binary .BigEndian .Uint32 (tail [4 :8 ])
210- rdl := int (binary .BigEndian .Uint16 (tail [8 :10 ]))
211- //rdata := d.payload[offset : offset+rdl]
212- tail = tail [10 + rdl :]
213- sb .WriteString (fmt .Sprintf (" %s: type %d class %d ttl %d rdl %d\n " , domain , typ , class , ttl , rdl ))
313+ rec , tail = d .parseRR (tail )
314+ sb .WriteString (rec )
214315 }
215316 }
216317 if d .AdditionalRRs > 0 {
217318 sb .WriteString ("- Additional records:\n " )
218319 for range d .AdditionalRRs {
219320 if tail [0 ] != 0 {
220- var domain string
221- domain , tail = extractDomain (d .payload , tail )
222- typ := binary .BigEndian .Uint16 (tail [0 :2 ])
223- class := binary .BigEndian .Uint16 (tail [2 :4 ])
224- ttl := binary .BigEndian .Uint32 (tail [4 :8 ])
225- rdl := int (binary .BigEndian .Uint16 (tail [8 :10 ]))
226- //rdata := d.payload[offset : offset+rdl]
227- tail = tail [10 + rdl :]
228- sb .WriteString (fmt .Sprintf (" %s: type %d class %d ttl %d rdl %d\n " , domain , typ , class , ttl , rdl ))
321+ rec , tail = d .parseRR (tail )
322+ sb .WriteString (rec )
229323 } else {
230- tail = tail [1 :]
231- typ := binary .BigEndian .Uint16 (tail [0 :2 ])
232- ups := binary .BigEndian .Uint16 (tail [2 :4 ])
233- t1 := tail [4 ]
234- zres := binary .BigEndian .Uint16 (tail [5 :7 ])
235- rdl := int (binary .BigEndian .Uint16 (tail [7 :9 ]))
236- tail = tail [9 + rdl :]
237- sb .WriteString (fmt .Sprintf (" Root: type %d UDP payload size %d t1 %d zres %d rdl %d\n " , typ , ups , t1 , zres , rdl ))
324+ rec , tail = d .parseRoot (tail )
325+ sb .WriteString (rec )
238326 }
239-
240327 }
241328 }
242329 return sb .String ()
0 commit comments