@@ -9,18 +9,96 @@ import (
99
1010const headerSizeDNS = 12
1111
12+ type DNSFlags struct {
13+ Raw uint16
14+ QR uint8 // Indicates if the message is a query (0) or a reply (1).
15+ QRDesc string // Query (0) or Reply (1)
16+ OPCode uint8 // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5
17+ OPCodeDesc string
18+ AA uint8 // Authoritative Answer, in a response, indicates if the DNS server is authoritative for the queried hostname.
19+ TC uint8 // TrunCation, indicates that this message was truncated due to excessive length.
20+ RD uint8 // Recursion Desired, indicates if the client means a recursive query.
21+ RA uint8 // Recursion Available, in a response, indicates if the replying DNS server supports recursion.
22+ Z uint8 // Zero, reserved for future use.
23+ AU uint8 // Indicates if answer/authority portion was authenticated by the server.
24+ NA uint8 // Indicates if non-authenticated data is accepatable.
25+ RCode uint8 // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
26+ RCodeDesc string
27+ }
28+
29+ func (df * DNSFlags ) String () string {
30+ var flags string
31+ switch df .QR {
32+ case 0 :
33+ flags = fmt .Sprintf (` - Response: Message is a %s (%d)
34+ - Opcode: %s (%d)
35+ - Truncated: %d
36+ - Recursion desired: %d
37+ - Reserved: %d
38+ - Non-authenticated data: %d` , df .QRDesc , df .QR , df .OPCodeDesc , df .OPCode , df .TC , df .RD , df .Z , df .NA )
39+ case 1 :
40+ flags = fmt .Sprintf (` - Response: Message is a %s (%d)
41+ - Opcode: %s (%d)
42+ - Authoritative: %d
43+ - Truncated: %d
44+ - Recursion desired: %d
45+ - Recursion available: %d
46+ - Reserved: %d
47+ - Answer authenticated: %d
48+ - Non-authenticated data: %d
49+ - Reply code: %s (%d)` ,
50+ df .QRDesc ,
51+ df .QR ,
52+ df .OPCodeDesc ,
53+ df .OPCode ,
54+ df .AA ,
55+ df .TC ,
56+ df .RD ,
57+ df .RA ,
58+ df .Z ,
59+ df .AU ,
60+ df .NA ,
61+ df .RCodeDesc ,
62+ df .RCode )
63+ }
64+ return flags
65+ }
66+
67+ func newDNSFlags (flags uint16 ) * DNSFlags {
68+ qr := uint8 (flags >> 15 )
69+ opcode := uint8 ((flags >> 11 ) & 15 )
70+ rcode := uint8 (flags & 15 )
71+ return & DNSFlags {
72+ Raw : flags ,
73+ QR : qr ,
74+ QRDesc : qrdesc (qr ),
75+ OPCode : opcode ,
76+ OPCodeDesc : opcdesc (opcode ),
77+ AA : uint8 ((flags >> 10 ) & 1 ),
78+ TC : uint8 ((flags >> 9 ) & 1 ),
79+ RD : uint8 ((flags >> 8 ) & 1 ),
80+ RA : uint8 ((flags >> 7 ) & 1 ),
81+ Z : uint8 ((flags >> 6 ) & 1 ),
82+ AU : uint8 ((flags >> 5 ) & 1 ),
83+ NA : uint8 ((flags >> 4 ) & 1 ),
84+ RCode : rcode ,
85+ RCodeDesc : rcdesc (rcode ),
86+ }
87+ }
88+
1289type DNSMessage struct {
13- TransactionID uint16 // Used for matching response to queries.
14- Flags uint16 // Flags specify the requested operation and a response code.
15- Questions uint16 // Count of entries in the queries section.
16- AnswerRRs uint16 // Count of entries in the answers section.
17- AuthorityRRs uint16 // Count of entries in the authority section.
18- AdditionalRRs uint16 // Count of entries in the additional section.
90+ TransactionID uint16 // Used for matching response to queries.
91+ Flags * DNSFlags // Flags specify the requested operation and a response code.
92+ Questions uint16 // Count of entries in the queries section.
93+ AnswerRRs uint16 // Count of entries in the answers section.
94+ AuthorityRRs uint16 // Count of entries in the authority section.
95+ AdditionalRRs uint16 // Count of entries in the additional section.
1996 payload []byte
2097}
2198
2299func (d * DNSMessage ) String () string {
23- return fmt .Sprintf (`%s- Transaction ID: %#04x
100+ return fmt .Sprintf (`%s
101+ - Transaction ID: %#04x
24102- Flags: %#04x
25103%s
26104- Questions: %d
@@ -30,8 +108,8 @@ func (d *DNSMessage) String() string {
30108%s` ,
31109 d .Summary (),
32110 d .TransactionID ,
111+ d .Flags .Raw ,
33112 d .Flags ,
34- d .flags (),
35113 d .Questions ,
36114 d .AnswerRRs ,
37115 d .AuthorityRRs ,
@@ -41,7 +119,7 @@ func (d *DNSMessage) String() string {
41119}
42120
43121func (d * DNSMessage ) Summary () string {
44- return fmt .Sprint ("DNS Message:" )
122+ return fmt .Sprintf ("DNS Message: %s %s %#04x" , d . Flags . OPCodeDesc , d . Flags . QRDesc , d . TransactionID )
45123}
46124
47125// Parse parses the given byte data into a DNSMessage struct.
@@ -50,7 +128,7 @@ func (d *DNSMessage) Parse(data []byte) error {
50128 return fmt .Errorf ("minimum header size for DNS is %d bytes, got %d bytes" , headerSizeDNS , len (data ))
51129 }
52130 d .TransactionID = binary .BigEndian .Uint16 (data [0 :2 ])
53- d .Flags = binary .BigEndian .Uint16 (data [2 :4 ])
131+ d .Flags = newDNSFlags ( binary .BigEndian .Uint16 (data [2 :4 ]) )
54132 d .Questions = binary .BigEndian .Uint16 (data [4 :6 ])
55133 d .AnswerRRs = binary .BigEndian .Uint16 (data [6 :8 ])
56134 d .AuthorityRRs = binary .BigEndian .Uint16 (data [8 :10 ])
@@ -63,106 +141,87 @@ func (d *DNSMessage) NextLayer() (string, []byte) {
63141 return "" , nil
64142}
65143
66- func (d * DNSMessage ) flags () string {
67- var flags string
68- opcode := (d .Flags >> 11 ) & 15
69- // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5
70- var opcodes string
144+ func qrdesc (qr uint8 ) string {
145+ var qrdesc string
146+ switch qr {
147+ case 0 :
148+ qrdesc = "query"
149+ case 1 :
150+ qrdesc = "reply"
151+ }
152+ return qrdesc
153+ }
154+
155+ // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5
156+ func opcdesc (opcode uint8 ) string {
157+ var opcdesc string
71158 switch opcode {
72159 case 0 :
73- opcodes = "Standard query"
160+ opcdesc = "Standard query"
74161 case 1 :
75- opcodes = "Inverse query"
162+ opcdesc = "Inverse query"
76163 case 2 :
77- opcodes = "Server status request"
164+ opcdesc = "Server status request"
78165 case 4 :
79- opcodes = "Notify"
166+ opcdesc = "Notify"
80167 case 5 :
81- opcodes = "Update"
168+ opcdesc = "Update"
82169 case 6 :
83- opcodes = "Stateful operation"
170+ opcdesc = "Stateful operation"
84171 default :
85- opcodes = "Unknown"
172+ opcdesc = "Unknown"
86173 }
87- tc := ( d . Flags >> 9 ) & 1
88- rd := ( d . Flags >> 8 ) & 1
89- z := ( d . Flags >> 6 ) & 1
90- na := ( d . Flags >> 4 ) & 1
91- qr := d . Flags >> 15
92- var qrs string
93- switch qr {
174+ return opcdesc
175+ }
176+
177+ // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
178+ func rcdesc ( rcode uint8 ) string {
179+ var rcdesc string
180+ switch rcode {
94181 case 0 :
95- qrs = "query"
96- flags = fmt .Sprintf (` - Response: Message is a %s (%d)
97- - Opcode: %s (%d)
98- - Truncated: %d
99- - Recursion desired: %d
100- - Reserved: %d
101- - Non-authenticated data: %d` , qrs , qr , opcodes , opcode , tc , rd , z , na )
182+ rcdesc = "No error"
102183 case 1 :
103- qrs = "reply"
104- a := (d .Flags >> 10 ) & 1
105- ra := (d .Flags >> 7 ) & 1
106- aa := (d .Flags >> 5 ) & 1
107- rcode := d .Flags & 15
108- // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
109- var rcodes string
110- switch rcode {
111- case 0 :
112- rcodes = "No error"
113- case 1 :
114- rcodes = "Format error"
115- case 2 :
116- rcodes = "Server failed to complete the DNS request"
117- case 3 :
118- rcodes = "Domain name does not exist"
119- case 4 :
120- rcodes = "Function not implemented"
121- case 5 :
122- rcodes = "The server refused to answer for the query"
123- case 6 :
124- rcodes = "Name that should not exist, does exist"
125- case 7 :
126- rcodes = "RRset that should not exist, does exist"
127- case 8 :
128- rcodes = "Server not authoritative for the zone"
129- case 9 :
130- rcodes = "Server Not Authoritative for zone"
131- case 10 :
132- rcodes = "Name not contained in zone"
133- case 11 :
134- rcodes = "DSO-TYPE Not Implemented"
135- case 16 :
136- rcodes = "Bad OPT Version/TSIG Signature Failure"
137- case 17 :
138- rcodes = "Key not recognizede"
139- case 18 :
140- rcodes = "Signature out of time window"
141- case 19 :
142- rcodes = "Bad TKEY Mode"
143- case 20 :
144- rcodes = "Duplicate key name"
145- case 21 :
146- rcodes = "Algorithm not supported"
147- case 22 :
148- rcodes = "Bad Truncation"
149- case 23 :
150- rcodes = "Bad/missing Server Cookie"
151- default :
152- rcodes = "Unknown"
153- }
154- flags = fmt .Sprintf (` - Response: Message is a %s (%d)
155- - Opcode: %s (%d)
156- - Authoritative: %d
157- - Truncated: %d
158- - Recursion desired: %d
159- - Recursion available: %d
160- - Reserved: %d
161- - Answer authenticated: %d
162- - Non-authenticated data: %d
163- - Reply code: %s (%d)` , qrs , qr , opcodes , opcode , a , tc , rd , ra , z , aa , na , rcodes , rcode )
184+ rcdesc = "Format error"
185+ case 2 :
186+ rcdesc = "Server failed to complete the DNS request"
187+ case 3 :
188+ rcdesc = "Domain name does not exist"
189+ case 4 :
190+ rcdesc = "Function not implemented"
191+ case 5 :
192+ rcdesc = "The server refused to answer for the query"
193+ case 6 :
194+ rcdesc = "Name that should not exist, does exist"
195+ case 7 :
196+ rcdesc = "RRset that should not exist, does exist"
197+ case 8 :
198+ rcdesc = "Server not authoritative for the zone"
199+ case 9 :
200+ rcdesc = "Server Not Authoritative for zone"
201+ case 10 :
202+ rcdesc = "Name not contained in zone"
203+ case 11 :
204+ rcdesc = "DSO-TYPE Not Implemented"
205+ case 16 :
206+ rcdesc = "Bad OPT Version/TSIG Signature Failure"
207+ case 17 :
208+ rcdesc = "Key not recognizede"
209+ case 18 :
210+ rcdesc = "Signature out of time window"
211+ case 19 :
212+ rcdesc = "Bad TKEY Mode"
213+ case 20 :
214+ rcdesc = "Duplicate key name"
215+ case 21 :
216+ rcdesc = "Algorithm not supported"
217+ case 22 :
218+ rcdesc = "Bad Truncation"
219+ case 23 :
220+ rcdesc = "Bad/missing Server Cookie"
221+ default :
222+ rcdesc = "Unknown"
164223 }
165- return flags
224+ return rcdesc
166225}
167226
168227// https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
0 commit comments