1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
require "util"
local p = Proto("ieee", "IEEE802.11 frame header")
local dslmp = DissectorTable.new("dslmp") -- DS Local Multi-Player
-- based off <https://www.problemkaputt.de/gbatek.htm#dswifiieee80211frames>
p.fields.ctl = ProtoField.new("Frame control", "ieee.ctl", ftypes.BYTES)
p.fields.ctl_ver = ProtoField.uint16("ieee.ctl.ver", "Protocol version", base.DEC, {
[0] = "Current",
[1] = "Reserved",
[2] = "Reserved",
[3] = "Reserved",
}, bits(0, 2))
p.fields.ctl_type = ProtoField.uint16("ieee.ctl.type", "Type", base.DEC, {
[0] = "Management",
[1] = "Control",
[2] = "Data",
[3] = "Reserved",
}, bits(2, 2))
p.fields.ctl_subtype = ProtoField.uint16("ieee.ctl.subtype", "Subtype", base.DEC, nil, bits(4, 4))
p.fields.ctl_to_ds = ProtoField.bool("ieee.ctl.tods", "To DS", base.DEC, nil, bits(8))
p.fields.ctl_from_ds = ProtoField.bool("ieee.ctl.fromds", "From DS", base.DEC, nil, bits(9))
p.fields.ctl_fragment = ProtoField.bool("ieee.ctl.fragment", "More fragments", base.DEC, nil, bits(10))
p.fields.ctl_retry = ProtoField.bool("ieee.ctl.retry", "Retry", base.DEC, nil, bits(11))
p.fields.ctl_power = ProtoField.bool("ieee.ctl.power", "Power management", base.DEC, nil, bits(12))
p.fields.ctl_data = ProtoField.bool("ieee.ctl.data", "More data", base.DEC, nil, bits(13))
p.fields.ctl_wep = ProtoField.bool("ieee.ctl.wep", "WEP encrypt", base.DEC, nil, bits(14))
p.fields.ctl_order = ProtoField.bool("ieee.ctl.order", "Order", base.DEC, nil, bits(15))
p.fields.duration = ProtoField.uint16("ieee.duration", "Duration / ID", base.HEX, nil, 0xffff)
p.fields.addr1 = ProtoField.bytes("ieee.addr1", "Address 1", base.COLON)
p.fields.addr2 = ProtoField.bytes("ieee.addr2", "Address 2", base.COLON)
p.fields.addr3 = ProtoField.bytes("ieee.addr3", "Address 3", base.COLON)
p.fields.seq = ProtoField.uint16("ieee.seq", "Sequence control")
p.fields.seq_frag = ProtoField.uint16("ieee.seq.frag", "Fragment", base.DEC, nil, bits(0, 4))
p.fields.seq_num = ProtoField.uint16("ieee.seq.num", "Sequence number", base.DEC, nil, bits(4, 12))
p.fields.body = ProtoField.bytes("ieee.body", "Body")
p.fields.gameid = ProtoField.uint16("ieee.gameid", "Game ID", base.HEX, {
[GAMEID.PICTOCHAT] = "PictoChat",
[GAMEID.MARIOKART] = "Mario Kart DS",
})
p.fields.fcs = ProtoField.bytes("ieee.fcs", "FCS (hardware only)")
function p.dissector(buffer, pinfo, tree)
local buffer_len = buffer:len()
-- invalid
if buffer_len < 10 then return 0 end
-- pretty wireshark shit
pinfo.cols.protocol = p.name
-- The 0x18 here is so wireshark only highlights the header when clicking
-- this item in the dissection tree.
local subtree = tree:add(p, buffer(0x00, 0x18), p.description)
local ctl_tree = subtree:add_le(p.fields.ctl, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_ver, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_type, buffer(0x00, 2))
local ctl_type = buffer(0x00, 2):bitfield(14, 2)
ctl_tree:add_le(p.fields.ctl_subtype, buffer(0x00, 2))
local ctl_subtype = buffer(0x00, 2):bitfield(12, 4)
ctl_tree:add_le(p.fields.ctl_to_ds, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_from_ds, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_fragment, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_retry, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_power, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_data, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_wep, buffer(0x00, 2))
ctl_tree:add_le(p.fields.ctl_order, buffer(0x00, 2))
subtree:add_le(p.fields.duration, buffer(0x02, 2))
add_addr(subtree, p.fields.addr1, buffer(0x04, 6))
add_addr(subtree, p.fields.addr2, buffer(0x0a, 6))
add_addr(subtree, p.fields.addr3, buffer(0x10, 6))
local seq_tree = subtree:add_le(p.fields.seq, buffer(0x16, 2))
seq_tree:add_le(p.fields.seq_frag, buffer(0x16, 2))
seq_tree:add_le(p.fields.seq_num, buffer(0x16, 2))
buffer = buffer(0x18) -- seek forward
local fcs = true -- Frame Check Sequence (FCS) (hardware-generated CRC32)
if ctl_type == 0 then
fcs = false
end
local body_size = buffer:len()
if fcs == true then
body_size = body_size - 4
end
subtree:add(p.fields.body, buffer(0, body_size))
-- Type = 2 (Data frame) and Subtype = 2 (Data + CF-Poll)
if ctl_type == 2 and ctl_subtype == 2 then
subtree:add(p.fields.gameid, buffer(0, 2))
local gameid = buffer(0, 2):uint()
dslmp:try(gameid, buffer(0, body_size):tvb(), pinfo, tree)
end
if fcs == true then
buffer = buffer(body_size)
subtree:add(p.fields.fcs, buffer(0, 4))
end
return buffer_len
end
|