require "util" local bit = require "bit" local p = Proto("ieee", "IEEE802.11 frame header") local dslmp = DissectorTable.new("dslmp") -- DS Local Multi-Player -- based off 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.ether("ieee.addr1", "Address 1") p.fields.addr2 = ProtoField.ether("ieee.addr2", "Address 2") p.fields.addr3 = ProtoField.ether("ieee.addr3", "Address 3") 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 = bit.rshift(bit.band(buffer(0x00, 2):le_uint(), bits(2, 2)), 2) ctl_tree:add_le(p.fields.ctl_subtype, buffer(0x00, 2)) local ctl_subtype = bit.rshift(bit.band(buffer(0x00, 2):le_uint(), bits(4, 4)), 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)) subtree:add(p.fields.addr1, buffer(0x04, 6)) subtree:add(p.fields.addr2, buffer(0x0a, 6)) subtree:add(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