Last active
July 6, 2024 20:13
-
-
Save sauerbraten/9237ded67c88985c1520d6820a8ab476 to your computer and use it in GitHub Desktop.
ENet Wireshark dissector. Place in ~/.local/lib/wireshark/plugins/.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Enet 1.3 Protocol Dissector For Wireshark | |
-- | |
-- Cameron Gutman ([email protected]) | |
-- fixes by Alexander Willing ([email protected]) | |
-- 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