Skip to content

Instantly share code, notes, and snippets.

@birarda
Last active September 11, 2015 21:43
Show Gist options
  • Save birarda/85d9fa19cfdf9db2c4bd to your computer and use it in GitHub Desktop.
Save birarda/85d9fa19cfdf9db2c4bd to your computer and use it in GitHub Desktop.
High Fidelity Wireshark Dissector
-- require bit so we can look at the HFUDT bitfields
require ("bit")
-- create the HFUDT protocol
p_hfudt = Proto("hfudt", "HFUDT Protocol")
-- create fields shared between packets in HFUDT
local f_data = ProtoField.string("hfudt.data", "Data", FT_STRING)
-- create the fields for data packets in HFUDT
local f_length = ProtoField.uint16("hfudt.length", "Length", base.DEC)
local f_control_bit = ProtoField.uint8("hfudt.control", "Control Bit", base.DEC)
local f_reliable_bit = ProtoField.uint8("hfudt.reliable", "Reliability Bit", base.DEC)
local f_message_bit = ProtoField.uint8("hfudt.message", "Message Bit", base.DEC)
local f_sequence_number = ProtoField.uint32("hfudt.sequence_number", "Sequence Number", base.DEC)
local f_message_position = ProtoField.uint8("hfudt.message_position", "Message Position", base.DEC)
local f_message_number = ProtoField.uint32("hfudt.message_number", "Message Number", base.DEC)
local f_type = ProtoField.uint8("hfudt.type", "Type", base.DEC)
local f_version = ProtoField.uint8("hfudt.version", "Version", base.DEC)
-- create the fields for control packets in HFUDT
local f_control_type = ProtoField.uint16("hfudt.control_type", "Control Type", base.DEC)
local f_ack_sequence_number = ProtoField.uint32("hfudt.ack_sequence_number", "ACKed Sequence Number", base.DEC)
local f_control_sub_sequence = ProtoField.uint32("hfudt.control_sub_sequence", "Control Sub-Sequence Number", base.DEC)
p_hfudt.fields = {
f_length,
f_control_bit, f_reliable_bit, f_message_bit, f_sequence_number, f_type, f_version,
f_message_position, f_message_number,
f_control_type, f_control_sub_sequence, f_ack_sequence_number,
f_data
}
p_hfudt.prefs["udp_port"] = Pref.uint("UDP Port", 40102, "UDP Port for HFUDT Packets (udt::Socket bound port)")
local control_types = {
[0] = { "ACK", "Acknowledgement" },
[1] = { "ACK2", "Acknowledgement of acknowledgement" },
[2] = { "LightACK", "Light Acknowledgement" },
[3] = { "NAK", "Loss report (NAK)" },
[4] = { "TimeoutNAK", "Loss report re-transmission (TimeoutNAK)" },
[5] = { "Handshake", "Handshake" },
[6] = { "HandshakeACK", "Acknowledgement of Handshake" }
}
local message_positions = {
[0] = "ONLY",
[1] = "LAST",
[2] = "FIRST",
[3] = "MIDDLE"
}
function p_hfudt.dissector (buf, pinfo, root)
-- make sure this isn't a STUN packet - those don't follow HFUDT format
if pinfo.dst == Address.ip("stun.highfidelity.io") then return end
-- validate that the packet length is at least the minimum control packet size
if buf:len() < 4 then return end
-- create a subtree for HFUDT
subtree = root:add(p_hfudt, buf(0))
-- set the packet length
subtree:add(f_length, buf:len())
-- pull out the entire first word
local first_word = buf(0, 4):le_uint()
-- pull out the control bit and add it to the subtree
local control_bit = bit.rshift(first_word, 31)
subtree:add(f_control_bit, control_bit)
local data_length = 0
if control_bit == 1 then
-- dissect the control packet
pinfo.cols.protocol = p_hfudt.name .. " Control"
-- remove the control bit and shift to the right to get the type value
local shifted_type = bit.rshift(bit.lshift(first_word, 1), 17)
local type = subtree:add(f_control_type, shifted_type)
if control_types[shifted_type] ~= nil then
-- if we know this type then add the name
type:append_text(" (".. control_types[shifted_type][1] .. ")")
end
if shifted_type == 0 or shifted_type == 1 then
-- this has a sub-sequence number
local second_word = buf(4, 4):le_uint()
subtree:add(f_control_sub_sequence, bit.band(second_word, 1073741823))
local data_index = 8
if shifted_type == 0 then
-- if this is an ACK let's read out the sequence number
local sequence_number = buf(8, 4):le_uint()
subtree:add(f_ack_sequence_number, bit.band(sequence_number, 1073741823))
data_index = data_index + 4
end
data_length = buf:len() - data_index
-- set the data from whatever is left in the packet
subtree:add(f_data, buf(data_index, data_length))
elseif shifted_type == 2 then
-- this is a Light ACK let's read out the sequence number
local sequence_number = buf(4, 4):le_uint()
subtree:add(f_ack_sequence_number, bit.band(sequence_number, 1073741823))
data_length = buf:len() - 4
-- set the data from whatever is left in the packet
subtree:add(f_data, buf(4, data_length))
else
data_length = buf:len() - 4
-- no sub-sequence number, just read the data
subtree:add(f_data, buf(4, data_length))
end
else
-- dissect the data packet
pinfo.cols.protocol = p_hfudt.name
-- set the reliability bit
subtree:add(f_reliable_bit, bit.rshift(first_word, 30))
local message_bit = bit.band(0x01, bit.rshift(first_word, 29))
-- set the message bit
subtree:add(f_message_bit, message_bit)
-- read the sequence number
subtree:add(f_sequence_number, bit.band(first_word, 0x1FFFFFFF))
local payload_offset = 4
-- if the message bit is set, handle the second word
if message_bit == 1 then
payload_offset = 8
local second_word = buf(4, 4):le_uint()
-- read message position from upper 2 bits
local message_position = bit.rshift(second_word, 30)
local position = subtree:add(f_message_position, message_position)
if message_positions[message_position] ~= nil then
-- if we know this position then add the name
position:append_text(" (".. message_positions[message_position] .. ")")
end
-- read message number from lower 30 bits
subtree:add(f_message_number, bit.band(second_word, 0x3FFFFFFF))
end
-- read the type
subtree:add(f_type, buf(payload_offset, 1):le_uint())
-- read the version
subtree:add(f_version, buf(payload_offset + 1, 1):le_uint())
data_length = buf:len() - (payload_offset + 2)
-- pull the data that is the rest of the packet
subtree:add(f_data, buf(payload_offset + 2, data_length))
end
-- return the size of the header
return buf:len()
end
function p_hfudt.init()
local udp_dissector_table = DissectorTable.get("udp.port")
udp_dissector_table:add(p_hfudt.prefs["udp_port"], p_hfudt)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment