-- b-CAP.lua -- -- a basic Wireshark's LUA dissector for Binary Controller Access Protocol -- see README for installation and usage -- -- Copyright (C) 2014 DENSO WAVE INCORPORATED -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- b-CAP definition bCAP_proto = Proto("b-cap", "b-CAP", "Binary Controller Access Protocol") -- function: main function bCAP_proto.dissector(buffer, pinfo, tree) pinfo.cols.protocol = "b-CAP" local subtree = tree:add(bCAP_proto, buffer(), "b-CAP Packet") if buffer(0, 1):uint() ~= 1 or buffer(buffer:len() - 1, 1):uint() ~= 4 then subtree:add(buffer(), "Error: Message length is too long") return end -- pinfo.port_type -> tcp: 2, udp: 3 (maybe) if buffer(buffer:len() - 2, 1):uint() == 1 then subtree:add(buffer(), "Error: This message compressed by ZIP") return end subtree:add(buffer(1, 4), "Message length: " .. buffer(1, 4):le_uint()) subtree:add(buffer(5, 2), "Serial number: " .. buffer(5, 2):le_uint()) subtree:add(buffer(7, 2), "Version or Retry: " .. buffer(7, 2):le_uint()) subtree:add(buffer(9, 4), "Function ID or Return code: " .. buffer(9, 4):le_int()) local num = buffer(13, 2):le_uint() subtree:add(buffer(13, 2), "Number of Args: " .. num) -- tvb -> Variant array tvb2VariantArray(subtree, buffer, 15, num, true) end -- load table of udp.port udp_table = DissectorTable.get("udp.port") udp_table:add(5007, bCAP_proto) -- load table of tcp.port tcp_table = DissectorTable.get("tcp.port") tcp_table:add(5007, bCAP_proto) -- function: tvb -> Variant arrray function tvb2VariantArray(tree, buffer, offset, num, first) local tmp = offset for i = 0, (num - 1) do local subtree if first then subtree = tree:add(buffer(offset, buffer(offset, 4):le_int() + 4), "Arg" .. i) offset = offset + 4 else subtree = tree:add("Arg" .. i) end -- Data type local type = buffer(offset, 2):le_int() subtree:add(buffer(offset, 2), "Data type: " .. DataType2String(type)) offset = offset + 2 -- The number of arrays local ary = buffer(offset, 4):le_uint() subtree:add(buffer(offset, 4), "The number of arrays: " .. ary) offset = offset + 4 -- Variant offset = offset + tvb2Variant(subtree, buffer, offset, type, ary) end return offset - tmp end -- function: tvb -> Variant function tvb2Variant(tree, buffer, offset, type, ary) local tmp = offset local str if type >= 0x2000 then type = type - 0x2000 if type == 17 then -- UI1 | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 1):le_uint() else str = str .. ", " .. buffer(offset + i, 1):le_uint() end end tree:add(buffer(offset, ary), "Data: " .. str) offset = offset + ary elseif type == 2 then -- I2 | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 2):le_uint() else str = str .. ", " .. buffer(offset + 2 * i, 2):le_int() end end tree:add(buffer(offset, 2 * ary), "Data: " .. str) offset = offset + 2 * ary elseif type == 18 then -- UI2 | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 2):le_uint() else str = str .. ", " .. buffer(offset + 2 * i, 2):le_uint() end end tree:add(buffer(offset, 2 * ary), "Data: " .. str) offset = offset + 2 * ary elseif type == 3 then -- I4 | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 4):le_uint() else str = str .. ", " .. buffer(offset + 4 * i, 4):le_int() end end tree:add(buffer(offset, 4 * ary), "Data: " .. str) offset = offset + 4 * ary elseif type == 19 then -- UI4 | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 4):le_uint() else str = str .. ", " .. buffer(offset + 4 * i, 4):le_uint() end end tree:add(buffer(offset, 4 * ary), "Data: " .. str) offset = offset + 4 * ary elseif type == 4 then -- R4 | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 4):le_float() else str = str .. ", " .. buffer(offset + 4 * i, 4):le_float() end end tree:add(buffer(offset, 4 * ary), "Data: " .. str) offset = offset + 4 * ary elseif type == 5 then -- R8 | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 8):le_float() else str = str .. ", " .. buffer(offset + 8 * i, 8):le_float() end end tree:add(buffer(offset, 8 * ary), "Data: " .. str) offset = offset + 8 * ary elseif type == 6 then -- CY | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 8):le_int64() else str = str .. ", " .. buffer(offset + 8 * i, 8):le_int64() end end tree:add(buffer(offset, 8 * ary), "Data: " .. str) offset = offset + 8 * ary elseif type == 7 then -- DATE | ARRAY for i = 0, (ary - 1) do if i == 0 then str = buffer(offset, 8):le_float() else str = str .. ", " .. buffer(offset + 8 * i, 8):le_float() end end tree:add(buffer(offset, 8 * ary), "Data: " .. str) offset = offset + 8 * ary elseif type == 11 then -- BOOL | ARRAY for i = 0, (ary - 1) do if i == 0 then if buffer(offset, 2):le_int() == 0 then str = "False" else str = "True" end else if buffer(offset + 2 * i, 2):le_int() == 0 then str = str .. ", False" else str = str .. ", True" end end end tree:add(buffer(offset, 2 * ary), "Data: " .. str) offset = offset + 2 * ary elseif type == 8 then -- BSTR | ARRAY local len, mem mem = offset for i = 0, (ary - 1) do len = buffer(offset, 4):le_uint() if i == 0 then if len > 0 then str = buffer(offset + 4, len):le_ustring() else str = "" end else str = str .. ", " if len > 0 then str = str .. buffer(offset + 4, len):le_ustring() end end offset = offset + 4 + len end tree:add(buffer(mem, offset - mem), "Data: " .. str) elseif type == 12 then -- VARIANT | ARRAY local len = tvb2VariantArray(tree, buffer, offset, ary, false) offset = offset + len end else if type == 10 then -- ERROR str = buffer(offset, 4):le_int() tree:add(buffer(offset, 4), "Data: " .. str) offset = offset + 4 elseif type == 17 then -- UI1 str = buffer(offset, 1):le_uint() tree:add(buffer(offset, 1), "Data: " .. str) offset = offset + 1 elseif type == 2 then -- I2 str = buffer(offset, 2):le_int() tree:add(buffer(offset, 2), "Data: " .. str) offset = offset + 2 elseif type == 18 then -- UI2 str = buffer(offset, 2):le_uint() tree:add(buffer(offset, 2), "Data: " .. str) offset = offset + 2 elseif type == 3 then -- I4 str = buffer(offset, 4):le_int() tree:add(buffer(offset, 4), "Data: " .. str) offset = offset + 4 elseif type == 19 then -- UI4 str = buffer(offset, 4):le_uint() tree:add(buffer(offset, 4), "Data: " .. str) offset = offset + 4 elseif type == 4 then -- R4 str = buffer(offset, 4):le_float() tree:add(buffer(offset, 4), "Data: " .. str) offset = offset + 4 elseif type == 5 then -- R8 str = buffer(offset, 8):le_float() tree:add(buffer(offset, 8), "Data: " .. str) offset = offset + 8 elseif type == 6 then -- CY str = buffer(offset, 8):le_int64() tree:add(buffer(offset, 8), "Data: " .. str) offset = offset + 8 elseif type == 7 then -- DATE str = buffer(offset, 8):le_float() tree:add(buffer(offset, 8), "Data: " .. str) offset = offset + 8 elseif type == 11 then -- BOOL if buffer(offset, 2):le_int() == 0 then str = "False" else str = "True" end tree:add(buffer(offset, 2), "Data: " .. str) offset = offset + 2 elseif type == 8 then -- BSTR local len = buffer(offset, 4):le_uint() if len > 0 then str = buffer(offset + 4, len):le_ustring() else str = "" end tree:add(buffer(offset, 4 + len), "Data: " .. str) offset = offset + 4 + len end end return offset - tmp end -- Data type string function DataType2String(type) local strReturn = "" if type >= 0x2000 then strReturn = "VT_ARRAY | " type = type - 0x2000 end if type == 0 then strReturn = strReturn .. "VT_EMPTY" elseif type == 1 then strReturn = strReturn .. "VT_NULL" elseif type == 10 then strReturn = strReturn .. "VT_ERROR" elseif type == 17 then strReturn = strReturn .. "VT_UI1" elseif type == 2 then strReturn = strReturn .. "VT_I2" elseif type == 18 then strReturn = strReturn .. "VT_UI2" elseif type == 3 then strReturn = strReturn .. "VT_I4" elseif type == 19 then strReturn = strReturn .. "VT_UI4" elseif type == 4 then strReturn = strReturn .. "VT_R4" elseif type == 5 then strReturn = strReturn .. "VT_R8" elseif type == 6 then strReturn = strReturn .. "VT_CY" elseif type == 7 then strReturn = strReturn .. "VT_DATE" elseif type == 11 then strReturn = strReturn .. "VT_BOOL" elseif type == 8 then strReturn = strReturn .. "VT_BSTR" elseif type == 12 then strReturn = strReturn .. "VT_VARIANT" end return strReturn end