local p = Proto("nifi", "Ni-Fi header") local dt = DissectorTable.new("nifi") p.fields.frame_type = ProtoField.uint16("nifi.type", "Frame type", base.DEC, { [0] = "Normal", -- Used for actual messages, ack packets [1] = "Announcement", -- TODO: send broadcast??? }) p.fields.original = ProtoField.bool("nifi.original", "Original") -- only 0 or 2 p.fields.gameid = ProtoField.uint16("nifi.gid", "Game ID", base.HEX, { [0xfffd] = "PictoChat (CMD)", [0x7dcb] = "PictoChat (ACK)", [0x5a5a] = "Mario Kart DS (CMD)", [0x7c02] = "Mario Kart DS (ACK)", }) p.fields.magic = ProtoField.bytes("nifi.magic", "Magic") p.fields.length = ProtoField.uint16("nifi.len", "Remaining message length") local melon_type_enum_field = Field.new("melon.type.enum") function p.init() -- register nifi as a subdissector for melon DissectorTable.get("melon"):add(0, p) end function p.dissector(buffer, pinfo, tree) local header_size = 12 local subtree = tree:add(p, buffer(0, header_size), string.format("%s: %d bytes", p.description, header_size)) subtree:add_le(p.fields.frame_type, buffer(0x00, 2)) subtree:add_le(p.fields.original, buffer(0x02, 2)) local original = buffer(0x02, 2):le_uint() > 0 local melon_type = melon_type_enum_field()() local gameid_buf = buffer(0x04, 4) local gameid = 0 if melon_type == 1 then -- CMD gameid_buf = gameid_buf(2, 2) elseif melon_type == 3 then -- ACK gameid_buf = gameid_buf(0, 2) end gameid = gameid_buf():le_uint() subtree:add_le(p.fields.gameid, gameid_buf) subtree:add_le(p.fields.magic, buffer(0x08, 2)) -- const 0x1401 subtree:add_le(p.fields.length, buffer(0x0a, 2)) local length = buffer(0x0a, 2):le_uint() -- pretty wireshark shit pinfo.cols.protocol = p.name pinfo.cols.info = string.format("GID %04x %s, %s", gameid, pinfo.cols.info, (original and "Original" or "Resend")) -- try to call subdissector for gameid dt:try(gameid, buffer(header_size, length):tvb(), pinfo, tree) return header_size end