adding zephyr-im master branch
This commit is contained in:
233
contrib/zephyr-dissector.lua
Normal file
233
contrib/zephyr-dissector.lua
Normal file
@ -0,0 +1,233 @@
|
||||
-- Wireshark dissector for Zephyr
|
||||
-- Place in ~/.local/lib/wireshark/plugins/2.6/
|
||||
|
||||
zephyr_protocol = Proto("Zephyr", "Zephyr IM Protocol")
|
||||
|
||||
local kind_names = {
|
||||
[0] = "UNSAFE",
|
||||
[1] = "UNACKED",
|
||||
[2] = "ACKED",
|
||||
[3] = "HMACK",
|
||||
[4] = "HMCTL",
|
||||
[5] = "SERVACK",
|
||||
[6] = "SERVNAK",
|
||||
[7] = "CLIENTACK",
|
||||
[8] = "STAT"
|
||||
}
|
||||
zephyr_protocol.fields.version = ProtoField.stringz("zephyr.version", "Version")
|
||||
zephyr_protocol.fields.numfields = ProtoField.uint32("zephyr.fields", "Field Count")
|
||||
zephyr_protocol.fields.z_kind = ProtoField.uint32("zephyr.z_kind", "Kind", base.DEC, kind_names)
|
||||
zephyr_protocol.fields.z_uid = ProtoField.stringz("zephyr.z_uid", "UID")
|
||||
zephyr_protocol.fields.z_uid_addr = ProtoField.ipv4("zephyr.z_uid.zuid_addr", "Address")
|
||||
zephyr_protocol.fields.z_uid_tv = ProtoField.absolute_time("zephyr.z_uid.tv", "Time")
|
||||
zephyr_protocol.fields.z_port = ProtoField.uint16("zephyr.z_port", "Port")
|
||||
zephyr_protocol.fields.z_auth = ProtoField.uint32("zephyr.z_auth", "Auth")
|
||||
zephyr_protocol.fields.z_authent_len = ProtoField.uint32("zephyr.z_authent_len", "Authenticator Length")
|
||||
zephyr_protocol.fields.z_ascii_authent = ProtoField.stringz("zephyr.z_ascii_authent", "Authenticator")
|
||||
zephyr_protocol.fields.z_class = ProtoField.stringz("zephyr.z_class", "Class")
|
||||
zephyr_protocol.fields.z_class_inst = ProtoField.stringz("zephyr.z_class_inst", "Instance")
|
||||
zephyr_protocol.fields.z_opcode = ProtoField.stringz("zephyr.z_opcode", "Opcode")
|
||||
zephyr_protocol.fields.z_sender = ProtoField.stringz("zephyr.z_sender", "Sender")
|
||||
zephyr_protocol.fields.z_recipient = ProtoField.stringz("zephyr.z_recipient", "Recipient")
|
||||
zephyr_protocol.fields.z_default_format = ProtoField.stringz("zephyr.z_default_format", "Default Format")
|
||||
zephyr_protocol.fields.z_ascii_checksum = ProtoField.stringz("zephyr.z_ascii_checksum", "ASCII Checksum")
|
||||
zephyr_protocol.fields.z_checksum = ProtoField.uint32("zephyr.z_checksum", "Checksum")
|
||||
zephyr_protocol.fields.z_multinotice = ProtoField.stringz("zephyr.z_multinotice", "Multinotice")
|
||||
zephyr_protocol.fields.z_multiuid = ProtoField.stringz("zephyr.z_multiuid", "MultiUID")
|
||||
zephyr_protocol.fields.z_multiuid_addr = ProtoField.ipv4("zephyr.z_multiuid.zuid_addr", "Address")
|
||||
zephyr_protocol.fields.z_multiuid_tv = ProtoField.absolute_time("zephyr.z_multiuid.tv", "Time")
|
||||
zephyr_protocol.fields.z_sender_sockaddr = ProtoField.ipv4("zephyr.z_sender_sockaddr", "Sender sockaddr")
|
||||
zephyr_protocol.fields.z_charset = ProtoField.uint16("zephyr.z_charset", "Character Set")
|
||||
zephyr_protocol.fields.z_message = ProtoField.string("zephyr.z_message", "Message")
|
||||
zephyr_protocol.fields.z_message_len = ProtoField.uint32("zephyr.z_message_len", "Message Length")
|
||||
|
||||
function parse_ascii(range)
|
||||
local v = range(2):string()
|
||||
return tonumber(string.match(v, "[0-9A-F]+"), 16)
|
||||
end
|
||||
|
||||
function parse_ascii_ip(range)
|
||||
local ip = "" .. tonumber(range(2, 2):string(), 16) .. "." .. tonumber(range(4, 2):string(), 16) .. "." .. tonumber(range(6, 2):string(), 16) .. "." .. tonumber(range(8, 2):string(), 16)
|
||||
return Address.ip(ip)
|
||||
end
|
||||
|
||||
function parse_zcode_ip(range)
|
||||
local bytes = {}
|
||||
local str = range(1,range:len()-2):bytes()
|
||||
local i = 0
|
||||
while i < str:len() do
|
||||
local byte = str:get_index(i)
|
||||
info(i .. ": " .. byte)
|
||||
if (byte == 0xFF) then
|
||||
if (str:get_index(i+1) == 0xF0) then
|
||||
table.insert(bytes, 0)
|
||||
elseif (str:get_index(i+1) == 0xF1) then
|
||||
table.insert(bytes, 0xFF)
|
||||
end
|
||||
i = i + 2
|
||||
else
|
||||
table.insert(bytes, byte)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
info(bytes[1])
|
||||
info(table.concat(bytes, "."))
|
||||
return Address.ip(table.concat(bytes, "."))
|
||||
end
|
||||
|
||||
function parse_ascii_tv(range)
|
||||
info(range:string())
|
||||
local seconds = parse_ascii(range)
|
||||
local microseconds = parse_ascii(range(11))
|
||||
return NSTime.new(seconds, microseconds*1000)
|
||||
end
|
||||
|
||||
function zephyr_protocol.dissector(buffer, pinfo, tree)
|
||||
length = buffer:len()
|
||||
if length == 0 then return end
|
||||
|
||||
pinfo.cols.protocol = zephyr_protocol.name
|
||||
|
||||
local subtree = tree:add(zephyr_protocol, buffer(), "Zephyr")
|
||||
|
||||
local range = buffer()
|
||||
local length = range:strsize()
|
||||
local v = range:stringz()
|
||||
subtree:add(zephyr_protocol.fields.version, range)
|
||||
|
||||
if v == "ZEPH0.2" then
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
local numfields = parse_ascii(range)
|
||||
subtree:add(zephyr_protocol.fields.numfields, range, numfields)
|
||||
numfields = numfields - 2
|
||||
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
local kind = parse_ascii(range)
|
||||
subtree:add(zephyr_protocol.fields.z_kind, range, kind)
|
||||
numfields = numfields - 1
|
||||
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
local z_uid = subtree:add(zephyr_protocol.fields.z_uid, range)
|
||||
|
||||
local addr = parse_ascii_ip(range)
|
||||
local tv = parse_ascii_tv(range(11))
|
||||
z_uid:add(zephyr_protocol.fields.z_uid_addr, range(0, 11), addr)
|
||||
z_uid:add(zephyr_protocol.fields.z_uid_tv, range(11), tv)
|
||||
z_uid:set_text("UID: " .. tostring(addr) .. " " .. tostring(tv))
|
||||
|
||||
numfields = numfields - 1
|
||||
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
subtree:add(zephyr_protocol.fields.z_port, range, parse_ascii(range))
|
||||
numfields = numfields - 1
|
||||
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
subtree:add(zephyr_protocol.fields.z_auth, range, parse_ascii(range))
|
||||
numfields = numfields - 1
|
||||
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
local authent_length = parse_ascii(range)
|
||||
subtree:add(zephyr_protocol.fields.z_authent_len, range, authent_length)
|
||||
numfields = numfields - 1
|
||||
|
||||
function add(field)
|
||||
range = buffer(range:offset()+range:len())
|
||||
subtree:add(field, range)
|
||||
numfields = numfields - 1
|
||||
end
|
||||
|
||||
add(zephyr_protocol.fields.z_ascii_authent)
|
||||
add(zephyr_protocol.fields.z_class)
|
||||
local class = range:stringz()
|
||||
add(zephyr_protocol.fields.z_class_inst)
|
||||
local instance = range:stringz()
|
||||
add(zephyr_protocol.fields.z_opcode)
|
||||
local opcode = range:stringz()
|
||||
add(zephyr_protocol.fields.z_sender)
|
||||
add(zephyr_protocol.fields.z_recipient)
|
||||
add(zephyr_protocol.fields.z_default_format)
|
||||
|
||||
if (numfields > 0) then
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
subtree:add(zephyr_protocol.fields.z_ascii_checksum, range)
|
||||
local status, value = pcall(function() return parse_ascii(range) end)
|
||||
if status then
|
||||
subtree:add(zephyr_protocol.fields.z_checksum, range, value)
|
||||
end
|
||||
numfields = numfields - 1
|
||||
-- TODO: validate checksum and flag if wrong
|
||||
end
|
||||
|
||||
if (numfields > 0) then
|
||||
range = buffer(range:offset()+range:len())
|
||||
subtree:add(zephyr_protocol.fields.z_multinotice, range)
|
||||
numfields = numfields - 1
|
||||
end
|
||||
|
||||
if (numfields > 0) then
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
local z_multiuid = subtree:add(zephyr_protocol.fields.z_multiuid, range)
|
||||
|
||||
local addr = parse_ascii_ip(range)
|
||||
local tv = parse_ascii_tv(range(11))
|
||||
z_multiuid:add(zephyr_protocol.fields.z_multiuid_addr, range(0, 11), addr)
|
||||
z_multiuid:add(zephyr_protocol.fields.z_multiuid_tv, range(11), tv)
|
||||
z_multiuid:set_text("MultiUID: " .. tostring(addr) .. " " .. tostring(tv))
|
||||
numfields = numfields - 1
|
||||
-- else z_multiuid = z_uid
|
||||
end
|
||||
|
||||
if (numfields > 0) then
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
if (range:string():byte(1) == 90) then
|
||||
-- TODO: parse Zcode address for real
|
||||
subtree:add(zephyr_protocol.fields.z_sender_sockaddr, range, parse_zcode_ip(range)):append_text(" (Zcode)")
|
||||
else
|
||||
subtree:add(zephyr_protocol.fields.z_sender_sockaddr, range, parse_ascii_ip(range)):append_text(" (NetASCII)")
|
||||
end
|
||||
numfields = numfields - 1
|
||||
end
|
||||
|
||||
if (numfields > 0) then
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
subtree:add(zephyr_protocol.fields.z_charset, range, parse_ascii(range))
|
||||
numfields = numfields - 1
|
||||
end
|
||||
|
||||
if (numfields > 0) then
|
||||
local otherfields = subtree:add("Other Fields")
|
||||
for i = 1,numfields do
|
||||
range = buffer(range:offset()+range:len())
|
||||
range = range(0, range:strsize())
|
||||
otherfields:add(range)
|
||||
numfields = numfields - 1
|
||||
end
|
||||
end
|
||||
|
||||
range = buffer(range:offset()+range:len())
|
||||
if (range:len() > 0) then
|
||||
subtree:add(zephyr_protocol.fields.z_message_len, range:len())
|
||||
subtree:add(zephyr_protocol.fields.z_message, range)
|
||||
end
|
||||
local info = kind_names[kind] .. " " .. class .. " " .. instance .. " " .. opcode
|
||||
pinfo.columns.info = info
|
||||
subtree.text = "Zephyr, " .. info
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local udp_port = DissectorTable.get("udp.port")
|
||||
udp_port:add(2102, zephyr_protocol)
|
||||
udp_port:add(2103, zephyr_protocol)
|
||||
udp_port:add(2104, zephyr_protocol)
|
Reference in New Issue
Block a user