local pc = Proto("pictochat", "Nintendo DS PictoChat") pc.fields.unknown = ProtoField.bytes("pictochat.unknown", "Unknown") pc.fields.msg_type = ProtoField.uint16("pictochat.msg_type", "Frame type", base.DEC, { [0] = "Normal", -- Used for actual messages, ack packets [1] = "Announcement", -- TODO: send broadcast??? }) pc.fields.resend = ProtoField.uint16("pictochat.resend", "Resend", base.DEC, { [0] = "Resend", [2] = "Original", }) pc.fields.length = ProtoField.uint16("pictochat.length", "Message length") pc.fields.host = ProtoField.ether("pictochat.host", "Room host") pc.fields.src = ProtoField.ether("pictochat.src", "Source") pc.fields.dst = ProtoField.ether("pictochat.dst", "Destination") -- Content offset appears to be some kind of offset for indicating where to -- store the current frame's data in a larger buffer. Messages sent in multiple -- parts increment this value by 160 for each new original (pictochat.resend == -- 2) message. pc.fields.content_offset = ProtoField.uint16("pictochat.content_offset", "Content offset") -- This appears to be the actual message content (the drawing) sent as an array -- of 8x8 tiles. pc.fields.content = ProtoField.bytes("pictochat.content", "Content") pc.fields.sequence = ProtoField.uint16("pictochat.sequence", "Packet sequence") local nifi_length_field = Field.new("nifi.length") local pc_msg_type_field = Field.new("pictochat.msg_type") local pc_length_field = Field.new("pictochat.length") local pc_resend_field = Field.new("pictochat.resend") local pc_src_field = Field.new("pictochat.src") local pc_dst_field = Field.new("pictochat.dst") function pc.dissector(buffer, pinfo, tree) local header_length = nifi_length_field()() if header_length == 0 then return end buffer = buffer(0x18) -- skip the Ni-Fi header local pc_tree = tree:add(pc, buffer(), "PictoChat: " .. header_length .. " bytes") pc_tree:add_le(pc.fields.msg_type, buffer(0x00, 2)) pc_tree:add_le(pc.fields.resend, buffer(0x02, 2)) pc_tree:add(pc.fields.unknown, buffer(0x04, 6)) pc_tree:add_le(pc.fields.length, buffer(0x0a, 2)) pc_tree:add(pc.fields.unknown, buffer(0x0c, 2)) pc_tree:add(pc.fields.unknown, buffer(0x0e, 2)) pc_tree:add_le(pc.fields.dst, buffer(0x10, 6)) pc_tree:add_le(pc.fields.src, buffer(0x16, 6)) pc_tree:add_le(pc.fields.host, buffer(0x1c, 6)) pinfo.cols.protocol = pc.name pinfo.cols.src = tostring(pc_src_field()) pinfo.cols.dst = tostring(pc_dst_field()) pinfo.cols.info = pc_msg_type_field().display .. ", " .. pc_resend_field().display pc_tree:add_le(pc.fields.unknown, buffer(0x22, 2)) -- counting pc_tree:add_le(pc.fields.unknown, buffer(0x24, 2)) pc_tree:add_le(pc.fields.resend, buffer(0x26, 2)) pc_tree:add(pc.fields.unknown, buffer(0x28, 6)) pc_tree:add(pc.fields.unknown, buffer(0x2e, 4)) local msg_type = pc_msg_type_field()() if msg_type == 0 then -- type = Normal (TODO: this should be 'message = drawing') pc_tree:add_le(pc.fields.content_offset, buffer(0x32, 2)) pc_tree:add_le(pc.fields.unknown, buffer(0x34, 2)) local content_length = pc_length_field()() - 50 -- TODO: why 50? buffer = buffer(0x36) pc_tree:add(pc.fields.content, buffer(0, content_length)) buffer = buffer(content_length) pc_tree:add_le(pc.fields.sequence, buffer(0x00, 2)) pc_tree:add_le(pc.fields.resend, buffer(0x02, 2)) -- copy pc_tree:add(pc.fields.unknown, buffer(0x04, 2)) pc_tree:add(pc.fields.unknown, buffer(0x06, 2)) end end register_postdissector(pc)