Skip to content

Commit 761b859

Browse files
author
shadowy-pycoder
committed
Added parsing of HTTP messages, refactored DNS flags, made non verbose mode look better
1 parent e4f8b89 commit 761b859

File tree

10 files changed

+259
-127
lines changed

10 files changed

+259
-127
lines changed

layers/dns.go

Lines changed: 157 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,96 @@ import (
99

1010
const 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+
1289
type 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

2299
func (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

43121
func (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

layers/ethernet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (ef *EthernetFrame) String() string {
3535
}
3636

3737
func (ef *EthernetFrame) Summary() string {
38-
return fmt.Sprintf("Ethernet Frame: Src: %s Dst: %s", ef.SrcMAC, ef.DstMAC)
38+
return fmt.Sprintf("Ethernet Frame: Src MAC: %s -> Dst MAC: %s", ef.SrcMAC, ef.DstMAC)
3939
}
4040

4141
// Parse parses the given byte data into an Ethernet frame.

layers/ftp.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,39 @@
11
package layers
22

3-
import "fmt"
3+
import (
4+
"bytes"
5+
"fmt"
6+
)
47

58
type FTPMessage struct {
6-
payload string
9+
summary []byte
10+
data []byte
711
}
812

913
func (f *FTPMessage) String() string {
1014
return fmt.Sprintf(`%s
11-
%s`, f.Summary(), f.payload)
15+
%s
16+
`, f.Summary(), f.data)
1217
}
1318

1419
func (f *FTPMessage) Summary() string {
15-
return fmt.Sprint("FTP Message:")
20+
return fmt.Sprintf("FTP Message: %s", f.summary)
1621
}
1722

1823
func (f *FTPMessage) Parse(data []byte) error {
19-
f.payload = bytesToStr(data)
24+
sp := bytes.Split(data, lf)
25+
lsp := len(sp)
26+
switch {
27+
case lsp > 2:
28+
f.summary = bytes.Join(sp[:2], bspace)
29+
sp[0] = joinBytes(dash, sp[0])
30+
f.data = bytes.TrimSuffix(bytes.TrimSuffix(bytes.Join(sp, lfd), dash), lf)
31+
case lsp > 1:
32+
f.summary = sp[0]
33+
sp[0] = joinBytes(dash, sp[0])
34+
f.data = bytes.TrimSuffix(bytes.TrimSuffix(bytes.Join(sp, lfd), dash), lf)
35+
default:
36+
}
2037
return nil
2138
}
2239

0 commit comments

Comments
 (0)