Skip to content

Instantly share code, notes, and snippets.

@Croydon
Forked from sauerbraten/enet.lua
Created December 16, 2022 17:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Croydon/ec302cb89a7fed3e122c4328aacf6b91 to your computer and use it in GitHub Desktop.
Save Croydon/ec302cb89a7fed3e122c4328aacf6b91 to your computer and use it in GitHub Desktop.
ENet Wireshark dissector. Place in ~/.local/lib/wireshark/plugins/.
-- Enet 1.3 Protocol Dissector For Wireshark
--
-- Cameron Gutman (aicommander@gmail.com)
-- fixes by Alexander Willing (willing.alexander@gmail.com)
-- Licensed under GPLv3
--
-- ENetProtocolHeader
enet_header_hassenttime = ProtoField.bool("enet.header.has_senttime", "Has Sent Time")
enet_header_compressed = ProtoField.bool("enet.header.is_compressed", "Compressed")
enet_header_sessionid = ProtoField.uint8("enet.header.sessionid", "Session ID", base.DEC)
enet_header_peerid = ProtoField.uint16("enet.header.peerid", "Peer ID", base.DEC)
enet_header_senttime = ProtoField.uint16("enet.header.senttime", "Sent Time", base.DEC)
-- intermediate field for commands
enet_command = ProtoField.protocol("enet.command", "ENet Command")
p_enet_header = Proto("enet", "ENet Header")
p_enet_header.fields = {
enet_header_hassenttime,
enet_header_compressed,
enet_header_sessionid,
enet_header_peerid,
enet_header_senttime,
enet_command,
}
function p_enet_header.dissector(buf, pkt, root)
pkt.cols.protocol = p_enet_header.name
local i = 0
-- Read the protocol header
peeridbuf = buf(i, 2)
i = i + 2
peerid = peeridbuf:uint()
has_senttime = bit.band(peerid, 0x8000) > 0
compressed = bit.band(peerid, 0x4000) > 0
sessionid = bit.rshift(bit.band(peerid, 0x300), 12)
peerid = bit.band(peerid, 0xFFF)
header_len = 2
if has_senttime then
header_len = 4
end
header = root:add(p_enet_header, buf(0, header_len))
header:add(enet_header_hassenttime, peeridbuf, has_senttime)
header:add(enet_header_compressed, peeridbuf, compressed)
header:add(enet_header_sessionid, peeridbuf, sessionid)
header:add(enet_header_peerid, peeridbuf, peerid)
if has_senttime then
header:add(enet_header_senttime, buf(i, 2), buf(i, 2):uint())
i = i + 2
end
dissector = Dissector.get("enet_command")
while i < buf:len() do
cmd = root:add(enet_command, buf(i))
n = dissector(buf(i):tvb(), pkt, cmd)
if n < 0 then
print("error")
return
end
cmd:set_len(n)
i = i + n
end
return i
end
command2string = {
[0] = "NONE",
[1] = "ACKNOWLEDGE",
[2] = "CONNECT",
[3] = "VERIFY_CONNECT",
[4] = "DISCONNECT",
[5] = "PING",
[6] = "SEND_RELIABLE",
[7] = "SEND_UNRELIABLE",
[8] = "SEND_FRAGMENT",
[9] = "SEND_UNSEQUENCED",
[10] = "BANDWIDTH_LIMIT",
[11] = "THROTTLE_CONFIGURE",
[99] = "UNKNOWN COMMAND (THIS IS AN ERROR)",
}
-- ENetProtocolCommandHeader
enet_cmdheader_ackrequested = ProtoField.bool("enet.command.ack_requested", "Acknowledgement Requested")
enet_cmdheader_unsequenced = ProtoField.bool("enet.command.unsequenced", "Unsequenced")
enet_cmdheader_command = ProtoField.uint8("enet.command.commandnum", "Command", base.DEC, command2string)
enet_cmdheader_channelid = ProtoField.int8("enet.command.channelid", "Channel ID", base.DEC)
enet_cmdheader_relseqnum = ProtoField.uint16("enet.command.relseqnum", "Reliable Sequence Number", base.DEC)
-- ENetProtocolAcknowledge
enet_ack_recvrelseqnum = ProtoField.uint16("enet.command.ack.recvrelseqnum", "Received Reliable Sequence Number", base.DEC)
enet_ack_recvsenttime = ProtoField.uint16("enet.command.ack.recvsenttime", "Received Sent Time", base.DEC)
-- ENetProtocolConnect
enet_connect_outgoingpeerid = ProtoField.uint16("enet.command.conn.outgoingpeerid", "Outgoing Peer ID", base.DEC)
enet_connect_incomingsessionid = ProtoField.uint8("enet.command.conn.incomingsessionid", "Incoming Session ID", base.DEC)
enet_connect_outgoingsessionid = ProtoField.uint8("enet.command.conn.outgoingsessionid", "Outgoing Session ID", base.DEC)
enet_connect_mtu = ProtoField.uint32("enet.command.conn.mtu", "MTU", base.DEC)
enet_connect_windowsize = ProtoField.uint32("enet.command.conn.windowsize", "Window Size", base.DEC)
enet_connect_channelcount = ProtoField.uint32("enet.command.conn.channelcount", "Channel Count", base.DEC)
enet_connect_incomingbandwidth = ProtoField.uint32("enet.command.conn.incomingbandwidth", "Incoming Bandwidth", base.DEC)
enet_connect_outgoingbandwidth = ProtoField.uint32("enet.command.conn.outgoingbandwidth", "Outgoing Bandwidth", base.DEC)
enet_connect_packetthrottleinterval = ProtoField.uint32("enet.command.conn.packetthrottleinterval", "Packet Throttle Interval", base.HEX)
enet_connect_packetthrottleaccel = ProtoField.uint32("enet.command.conn.packetthrottleaccel", "Packet Throttle Acceleration", base.HEX)
enet_connect_packetthrottledecel = ProtoField.uint32("enet.command.conn.packetthrottledecel", "Packet Throttle Deceleration", base.HEX)
enet_connect_connectid = ProtoField.uint32("enet.command.conn.connectid", "Connect ID", base.DEC)
enet_connect_data = ProtoField.uint32("enet.command.conn.data", "Data", base.HEX)
-- ENetProtocolVerifyConnect
enet_verifyconnect_outgoingpeerid = ProtoField.uint16("enet.command.connverify.outgoingpeerid", "Outgoing Peer ID", base.DEC)
enet_verifyconnect_incomingsessionid = ProtoField.uint8("enet.command.connverify.incomingsessionid", "Incoming Session ID", base.DEC)
enet_verifyconnect_outgoingsessionid = ProtoField.uint8("enet.command.connverify.outgoingsessionid", "Outgoing Session ID", base.DEC)
enet_verifyconnect_mtu = ProtoField.uint32("enet.command.connverify.mtu", "MTU", base.DEC)
enet_verifyconnect_windowsize = ProtoField.uint32("enet.command.connverify.windowsize", "Window Size", base.DEC)
enet_verifyconnect_channelcount = ProtoField.uint32("enet.command.connverify.channelcount", "Channel Count", base.DEC)
enet_verifyconnect_incomingbandwidth = ProtoField.uint32("enet.command.connverify.incomingbandwidth", "Incoming Bandwidth", base.DEC)
enet_verifyconnect_outgoingbandwidth = ProtoField.uint32("enet.command.connverify.outgoingbandwidth", "Outgoing Bandwidth", base.DEC)
enet_verifyconnect_packetthrottleinterval = ProtoField.uint32("enet.command.connverify.packetthrottleinterval", "Packet Throttle Interval", base.HEX)
enet_verifyconnect_packetthrottleaccel = ProtoField.uint32("enet.command.connverify.packetthrottleaccel", "Packet Throttle Acceleration", base.HEX)
enet_verifyconnect_packetthrottledecel = ProtoField.uint32("enet.command.connverify.packetthrottledecel", "Packet Throttle Deceleration", base.HEX)
enet_verifyconnect_connectid = ProtoField.uint32("enet.command.connverify.connectid", "Connect ID", base.DEC)
-- ENetProtocolBandwidthLimit
enet_bwlimit_incomingbandwidth = ProtoField.uint32("enet.command.bwlimit.incomingbandwidth", "Incoming Bandwidth", base.DEC)
enet_bwlimit_outgoingbandwidth = ProtoField.uint32("enet.command.bwlimit.outgoingbandwidth", "Outgoing Bandwidth", base.DEC)
-- ENetProtocolThrottleConfigure
enet_throttle_packetthrottleinterval = ProtoField.uint32("enet.command.throttle.packetthrottleinterval", "Packet Throttle Interval", base.HEX)
enet_throttle_packetthrottleaccel = ProtoField.uint32("enet.command.throttle.packetthrottleaccel", "Packet Throttle Acceleration", base.HEX)
enet_throttle_packetthrottledecel = ProtoField.uint32("enet.command.throttle.packetthrottledecel", "Packet Throttle Deceleration", base.HEX)
-- ENetProtocolDisconnect
enet_disconn_data = ProtoField.uint32("enet.command.disconn.data", "Data", base.HEX)
-- ENetProtocolSendReliable
enet_sendrel_datalen = ProtoField.uint16("enet.command.sendrel.datalen", "Data Length", base.DEC)
enet_sendrel_data = ProtoField.bytes("enet.command.sendrel.data", "Data")
-- ENetProtocolSendUnreliable
enet_sendunrel_unrelseqnum = ProtoField.uint16("enet.command.sendunrel.unrelseqnum", "Unreliable Sequence Number", base.DEC)
enet_sendunrel_datalen = ProtoField.uint16("enet.command.sendunrel.datalen", "Data Length", base.DEC)
enet_sendunrel_data = ProtoField.bytes("enet.command.sendunrel.data", "Data")
-- ENetProtocolSendUnsequenced
enet_sendunseq_unseqgroup = ProtoField.uint16("enet.sendunseq.unseqgroup", "Unsequenced Group", base.DEC)
enet_sendunseq_datalen = ProtoField.uint16("enet.sendunseq.datalen", "Data Length", base.DEC)
enet_sendunseq_data = ProtoField.bytes("enet.sendunseq.data", "Data")
-- ENetProtocolSendFragment
enet_sendfrag_startseqnum = ProtoField.uint16("enet.sendfrag.startseqnum", "Start Sequence Number", base.DEC)
enet_sendfrag_datalen = ProtoField.uint16("enet.sendfrag.datalen", "Data Length", base.DEC)
enet_sendfrag_fragcount = ProtoField.uint32("enet.sendfrag.fragcount", "Fragment Count", base.DEC)
enet_sendfrag_fragnum = ProtoField.uint32("enet.sendfrag.fragnum", "Fragment Number", base.DEC)
enet_sendfrag_totallen = ProtoField.uint32("enet.sendfrag.totallen", "Total Length", base.DEC)
enet_sendfrag_fragoff = ProtoField.uint32("enet.sendfrag.fragoff", "Fragment Offset", base.DEC)
enet_sendfrag_data = ProtoField.bytes("enet.sendfrag.data", "Data")
p_enet_cmd = Proto("enet_command", "ENet Command")
p_enet_cmd.fields = {
enet_cmdheader_ackrequested,
enet_cmdheader_unsequenced,
enet_cmdheader_command,
enet_cmdheader_channelid,
enet_cmdheader_relseqnum,
enet_ack,
enet_ack_recvrelseqnum,
enet_ack_recvsenttime,
enet_connect,
enet_connect_outgoingpeerid,
enet_connect_incomingsessionid,
enet_connect_outgoingsessionid,
enet_connect_mtu,
enet_connect_windowsize,
enet_connect_channelcount,
enet_connect_incomingbandwidth,
enet_connect_outgoingbandwidth,
enet_connect_packetthrottleinterval,
enet_connect_packetthrottleaccel,
enet_connect_packetthrottledecel,
enet_connect_connectid,
enet_connect_data,
enet_verifyconnect,
enet_verifyconnect_outgoingpeerid,
enet_verifyconnect_incomingsessionid,
enet_verifyconnect_outgoingsessionid,
enet_verifyconnect_mtu,
enet_verifyconnect_windowsize,
enet_verifyconnect_channelcount,
enet_verifyconnect_incomingbandwidth,
enet_verifyconnect_outgoingbandwidth,
enet_verifyconnect_packetthrottleinterval,
enet_verifyconnect_packetthrottleaccel,
enet_verifyconnect_packetthrottledecel,
enet_verifyconnect_connectid,
enet_bwlimit,
enet_bwlimit_incomingbandwidth,
enet_bwlimit_outgoingbandwidth,
enet_throttle,
enet_throttle_packetthrottleinterval,
enet_throttle_packetthrottleaccel,
enet_throttle_packetthrottledecel,
enet_disconn,
enet_disconn_data,
enet_ping,
enet_sendrel,
enet_sendrel_datalen,
enet_sendrel_data,
enet_sendunrel,
enet_sendunrel_unrelseqnum,
enet_sendunrel_datalen,
enet_sendunrel_data,
enet_sendunseq,
enet_sendunseq_unseqgroup,
enet_sendunseq_datalen,
enet_sendunseq_data,
enet_sendfrag,
enet_sendfrag_startseqnum,
enet_sendfrag_datalen,
enet_sendfrag_fragcount,
enet_sendfrag_fragnum,
enet_sendfrag_totallen,
enet_sendfrag_fragoff,
enet_sendfrag_data
}
function p_enet_cmd.dissector(buf, pkt, cmd)
local i = 0
-- Read the command header
commandnumbuf = buf(i, 1)
i = i + 1
commandnum = commandnumbuf:uint()
ack_requested = bit.band(commandnum, 0x80)
cmd:add(enet_cmdheader_ackrequested, commandnumbuf, ack_requested)
unsequenced = bit.band(commandnum, 0x40)
cmd:add(enet_cmdheader_unsequenced, commandnumbuf, unsequenced)
commandnum = bit.band(commandnum, 0x0F)
cmd:add(enet_cmdheader_command, commandnumbuf, commandnum)
cmd:add(enet_cmdheader_channelid, buf(i, 1), buf(i, 1):int())
i = i + 1
cmd:add(enet_cmdheader_relseqnum, buf(i, 2), buf(i, 2):uint())
i = i + 2
if commandnum == 1 then
-- ENetProtocolAcknowledge
cmd:add(enet_ack_recvrelseqnum, buf(i, 2), buf(i, 2):uint())
i = i + 2
cmd:add(enet_ack_recvsenttime, buf(i, 2), buf(i, 2):uint())
i = i + 2
elseif commandnum == 2 then
-- ENetProtocolConnect
cmd:add(enet_connect_outgoingpeerid, buf(i, 2), buf(i, 2):uint())
i = i + 2
cmd:add(enet_connect_incomingsessionid, buf(i, 1), buf(i, 1):uint())
i = i + 1
cmd:add(enet_connect_outgoingsessionid, buf(i, 1), buf(i, 1):uint())
i = i + 1
cmd:add(enet_connect_mtu, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_windowsize, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_channelcount, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_incomingbandwidth, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_outgoingbandwidth, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_packetthrottleinterval, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_packetthrottleaccel, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_packetthrottledecel, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_connectid, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_connect_data, buf(i, 4), buf(i, 4):uint())
i = i + 4
elseif commandnum == 3 then
-- ENetProtocolVerifyConnect
cmd:add(enet_verifyconnect_outgoingpeerid, buf(i, 2), buf(i, 2):uint())
i = i + 2
cmd:add(enet_verifyconnect_incomingsessionid, buf(i, 1), buf(i, 1):uint())
i = i + 1
cmd:add(enet_verifyconnect_outgoingsessionid, buf(i, 1), buf(i, 1):uint())
i = i + 1
cmd:add(enet_verifyconnect_mtu, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_verifyconnect_windowsize, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_verifyconnect_channelcount, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_verifyconnect_incomingbandwidth, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_verifyconnect_outgoingbandwidth, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_verifyconnect_packetthrottleinterval, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_verifyconnect_packetthrottleaccel, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_verifyconnect_packetthrottledecel, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_verifyconnect_connectid, buf(i, 4), buf(i, 4):uint())
i = i + 4
elseif commandnum == 4 then
-- ENetProtocolDisconnect
cmd:add(enet_disconn_data, buf(i, 4), buf(i, 4):uint())
elseif commandnum == 5 then
-- ENetProtocolPing
elseif commandnum == 6 then
-- ENetProtocolSendReliable
datalen = buf(i, 2):uint()
cmd:add(enet_sendrel_datalen, buf(i, 2), buf(i, 2):uint())
i = i + 2
cmd:add(enet_sendrel_data, buf(i, datalen))
i = i + datalen
elseif commandnum == 7 then
-- ENetProtocolSendUnreliable
cmd:add(enet_sendunrel_unrelseqnum, buf(i, 2), buf(i, 2):uint())
i = i + 2
datalen = buf(i, 2):uint()
cmd:add(enet_sendunrel_datalen, buf(i, 2), buf(i, 2):uint())
i = i + 2
cmd:add(enet_sendunrel_data, buf(i, datalen))
i = i + datalen
elseif commandnum == 8 or commandnum == 12 then
-- ENetProtocolSendFragment
cmd:add(enet_sendfrag_startseqnum, buf(i, 2), buf(i, 2):uint())
i = i + 2
datalen = buf(i, 2):uint()
cmd:add(enet_sendfrag_datalen, buf(i, 2), buf(i, 2):uint())
i = i + 2
cmd:add(enet_sendfrag_fragcount, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_sendfrag_fragnum, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_sendfrag_totallen, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_sendfrag_fragoff, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_sendfrag_data, buf(i, datalen))
i = i + datalen
elseif commandnum == 9 then
-- ENetProtocolSendUnsequenced
cmd:add(enet_sendunseq_unseqgroup, buf(i, 2), buf(i, 2):uint())
i = i + 2
datalen = buf(i, 2):uint()
cmd:add(enet_sendunseq_datalen, buf(i, 2), buf(i, 2):uint())
i = i + 2
cmd:add(enet_sendunseq_data, buf(i, datalen))
i = i + datalen
elseif commandnum == 10 then
-- ENetProtocolBandwidthLimit
cmd:add(enet_bwlimit_incomingbandwidth, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_bwlimit_outgoingbandwidth, buf(i, 4), buf(i, 4):uint())
i = i + 4
elseif commandnum == 11 then
-- ENetProtocolThrottleConfigure
cmd:add(enet_throttle_packetthrottleinterval, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_throttle_packetthrottleaccel, buf(i, 4), buf(i, 4):uint())
i = i + 4
cmd:add(enet_throttle_packetthrottledecel, buf(i, 4), buf(i, 4):uint())
i = i + 4
else
print("unexpected command number " .. commandnum)
return -1
end
return i
end
-- FIXME: A better way to get ourselves in the UDP dissector list?
local udp_dissector_table = DissectorTable.get("udp.port")
udp_dissector_table:add(0, p_enet_header)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment