12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415 |
- -- minetest.lua
- -- Packet dissector for the UDP-based Minetest protocol
- -- Copy this to $HOME/.wireshark/plugins/
- --
- -- Minetest
- -- Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
- --
- -- 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 2 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, write to the Free Software Foundation, Inc.,
- -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- --
- -- Wireshark documentation:
- -- https://web.archive.org/web/20170711121726/https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Proto.html
- -- https://web.archive.org/web/20170711121844/https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Tree.html
- -- https://web.archive.org/web/20170711121917/https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Tvb.html
- -- Table of Contents:
- -- Part 1: Utility functions
- -- Part 2: Client command dissectors (TOSERVER_*)
- -- Part 3: Server command dissectors (TOCLIENT_*)
- -- Part 4: Wrapper protocol subdissectors
- -- Part 5: Wrapper protocol main dissector
- -- Part 6: Utility functions part 2
- -----------------------
- -- Part 1 --
- -- Utility functions --
- -----------------------
- -- Creates two ProtoFields to hold a length and variable-length text content
- -- lentype must be either "uint16" or "uint32"
- function minetest_field_helper(lentype, name, abbr)
- local f_textlen = ProtoField[lentype](name .. "len", abbr .. " (length)", base.DEC)
- local f_text = ProtoField.string(name, abbr)
- return f_textlen, f_text
- end
- --------------------------------------------
- -- Part 2 --
- -- Client command dissectors (TOSERVER_*) --
- --------------------------------------------
- minetest_client_commands = {}
- minetest_client_obsolete = {}
- -- TOSERVER_INIT
- do
- local abbr = "minetest.client.init_"
- local f_ser_fmt = ProtoField.uint8(abbr.."ser_version",
- "Maximum serialization format version", base.DEC)
- local f_comp_modes = ProtoField.uint16(abbr.."compression",
- "Supported compression modes", base.DEC, { [0] = "No compression" })
- local f_proto_min = ProtoField.uint16(abbr.."proto_min", "Minimum protocol version", base.DEC)
- local f_proto_max = ProtoField.uint16(abbr.."_proto_max", "Maximum protocol version", base.DEC)
- local f_player_namelen, f_player_name =
- minetest_field_helper("uint16", abbr.."player_name", "Player Name")
- minetest_client_commands[0x02] = {
- "INIT", -- Command name
- 11, -- Minimum message length including code
- { f_ser_fmt, -- List of fields [optional]
- f_comp_modes,
- f_proto_min,
- f_proto_max,
- f_player_namelen,
- f_player_name },
- function(buffer, pinfo, tree, t) -- Dissector function [optional]
- t:add(f_ser_fmt, buffer(2,1))
- t:add(f_comp_modes, buffer(3,2))
- t:add(f_proto_min, buffer(5,2))
- t:add(f_proto_max, buffer(7,2))
- minetest_decode_helper_ascii(buffer, t, "uint16", 9, f_player_namelen, f_player_name)
- end
- }
- end
- -- TOSERVER_INIT_LEGACY (obsolete)
- minetest_client_commands[0x10] = { "INIT_LEGACY", 53 }
- minetest_client_obsolete[0x10] = true
- -- TOSERVER_INIT2
- do
- local f_langlen, f_lang =
- minetest_field_helper("uint16", "minetest.client.init2_language", "Language Code")
- minetest_client_commands[0x11] = {
- "INIT2",
- 2,
- { f_langlen,
- f_lang },
- function(buffer, pinfo, tree, t)
- minetest_decode_helper_ascii(buffer, t, "uint16", 2, f_langlen, f_lang)
- end
- }
- end
- -- TOSERVER_MODCHANNEL_JOIN
- minetest_client_commands[0x17] = { "MODCHANNEL_JOIN", 2 }
- -- TOSERVER_MODCHANNEL_LEAVE
- minetest_client_commands[0x18] = { "MODCHANNEL_LEAVE", 2 }
- -- TOSERVER_MODCHANNEL_MSG
- minetest_client_commands[0x19] = { "MODCHANNEL_MSG", 2 }
- -- TOSERVER_GETBLOCK (obsolete)
- minetest_client_commands[0x20] = { "GETBLOCK", 2 }
- minetest_client_obsolete[0x20] = true
- -- TOSERVER_ADDNODE (obsolete)
- minetest_client_commands[0x21] = { "ADDNODE", 2 }
- minetest_client_obsolete[0x21] = true
- -- TOSERVER_REMOVENODE (obsolete)
- minetest_client_commands[0x22] = { "REMOVENODE", 2 }
- minetest_client_obsolete[0x22] = true
- -- TOSERVER_PLAYERPOS
- do
- local abbr = "minetest.client.playerpos_"
- local f_x = ProtoField.int32(abbr.."x", "Position X", base.DEC)
- local f_y = ProtoField.int32(abbr.."y", "Position Y", base.DEC)
- local f_z = ProtoField.int32(abbr.."z", "Position Z", base.DEC)
- local f_speed_x = ProtoField.int32(abbr.."speed_x", "Speed X", base.DEC)
- local f_speed_y = ProtoField.int32(abbr.."speed_y", "Speed Y", base.DEC)
- local f_speed_z = ProtoField.int32(abbr.."speed_z", "Speed Z", base.DEC)
- local f_pitch = ProtoField.int32(abbr.."pitch", "Pitch", base.DEC)
- local f_yaw = ProtoField.int32(abbr.."yaw", "Yaw", base.DEC)
- local f_key_pressed = ProtoField.bytes(abbr.."key_pressed", "Pressed keys")
- local f_fov = ProtoField.uint8(abbr.."fov", "FOV", base.DEC)
- local f_wanted_range = ProtoField.uint8(abbr.."wanted_range", "Requested view range", base.DEC)
- minetest_client_commands[0x23] = {
- "PLAYERPOS", 34,
- { f_x, f_y, f_z, f_speed_x, f_speed_y, f_speed_z, f_pitch, f_yaw,
- f_key_pressed, f_fov, f_wanted_range },
- function(buffer, pinfo, tree, t)
- t:add(f_x, buffer(2,4))
- t:add(f_y, buffer(6,4))
- t:add(f_z, buffer(10,4))
- t:add(f_speed_x, buffer(14,4))
- t:add(f_speed_y, buffer(18,4))
- t:add(f_speed_z, buffer(22,4))
- t:add(f_pitch, buffer(26,4))
- t:add(f_yaw, buffer(30,4))
- t:add(f_key_pressed, buffer(34,4))
- t:add(f_fov, buffer(38,1))
- t:add(f_wanted_range, buffer(39,1))
- end
- }
- end
- -- TOSERVER_GOTBLOCKS
- do
- local f_count = ProtoField.uint8("minetest.client.gotblocks_count", "Count", base.DEC)
- local f_block = ProtoField.bytes("minetest.client.gotblocks_block", "Block", base.NONE)
- local f_x = ProtoField.int16("minetest.client.gotblocks_x", "Block position X", base.DEC)
- local f_y = ProtoField.int16("minetest.client.gotblocks_y", "Block position Y", base.DEC)
- local f_z = ProtoField.int16("minetest.client.gotblocks_z", "Block position Z", base.DEC)
- minetest_client_commands[0x24] = {
- "GOTBLOCKS", 3,
- { f_count, f_block, f_x, f_y, f_z },
- function(buffer, pinfo, tree, t)
- t:add(f_count, buffer(2,1))
- local count = buffer(2,1):uint()
- if minetest_check_length(buffer, 3 + 6*count, t) then
- pinfo.cols.info:append(" * " .. count)
- local index
- for index = 0, count - 1 do
- local pos = 3 + 6*index
- local t2 = t:add(f_block, buffer(pos, 6))
- t2:set_text("Block, X: " .. buffer(pos, 2):int()
- .. ", Y: " .. buffer(pos + 2, 2):int()
- .. ", Z: " .. buffer(pos + 4, 2):int())
- t2:add(f_x, buffer(pos, 2))
- t2:add(f_y, buffer(pos + 2, 2))
- t2:add(f_z, buffer(pos + 4, 2))
- end
- end
- end
- }
- end
- -- TOSERVER_DELETEDBLOCKS
- do
- local f_count = ProtoField.uint8("minetest.client.deletedblocks_count", "Count", base.DEC)
- local f_block = ProtoField.bytes("minetest.client.deletedblocks_block", "Block", base.NONE)
- local f_x = ProtoField.int16("minetest.client.deletedblocks_x", "Block position X", base.DEC)
- local f_y = ProtoField.int16("minetest.client.deletedblocks_y", "Block position Y", base.DEC)
- local f_z = ProtoField.int16("minetest.client.deletedblocks_z", "Block position Z", base.DEC)
- minetest_client_commands[0x25] = {
- "DELETEDBLOCKS", 3,
- { f_count, f_block, f_x, f_y, f_z },
- function(buffer, pinfo, tree, t)
- t:add(f_count, buffer(2,1))
- local count = buffer(2,1):uint()
- if minetest_check_length(buffer, 3 + 6*count, t) then
- pinfo.cols.info:append(" * " .. count)
- local index
- for index = 0, count - 1 do
- local pos = 3 + 6*index
- local t2 = t:add(f_block, buffer(pos, 6))
- t2:set_text("Block, X: " .. buffer(pos, 2):int()
- .. ", Y: " .. buffer(pos + 2, 2):int()
- .. ", Z: " .. buffer(pos + 4, 2):int())
- t2:add(f_x, buffer(pos, 2))
- t2:add(f_y, buffer(pos + 2, 2))
- t2:add(f_z, buffer(pos + 4, 2))
- end
- end
- end
- }
- end
- -- TOSERVER_ADDNODE_FROM_INVENTORY (obsolete)
- minetest_client_commands[0x26] = { "ADDNODE_FROM_INVENTORY", 2 }
- minetest_client_obsolete[0x26] = true
- -- TOSERVER_CLICK_OBJECT (obsolete)
- minetest_client_commands[0x27] = { "CLICK_OBJECT", 2 }
- minetest_client_obsolete[0x27] = true
- -- TOSERVER_GROUND_ACTION (obsolete)
- minetest_client_commands[0x28] = { "GROUND_ACTION", 2 }
- minetest_client_obsolete[0x28] = true
- -- TOSERVER_RELEASE (obsolete)
- minetest_client_commands[0x29] = { "RELEASE", 2 }
- minetest_client_obsolete[0x29] = true
- -- TOSERVER_SIGNTEXT (obsolete)
- minetest_client_commands[0x30] = { "SIGNTEXT", 2 }
- minetest_client_obsolete[0x30] = true
- -- TOSERVER_INVENTORY_ACTION
- do
- local f_action = ProtoField.string("minetest.client.inventory_action", "Action")
- minetest_client_commands[0x31] = {
- "INVENTORY_ACTION", 2,
- { f_action },
- function(buffer, pinfo, tree, t)
- t:add(f_action, buffer(2, buffer:len() - 2))
- end
- }
- end
- -- TOSERVER_CHAT_MESSAGE
- do
- local f_length = ProtoField.uint16("minetest.client.chat_message_length", "Length", base.DEC)
- local f_message = ProtoField.string("minetest.client.chat_message", "Message")
- minetest_client_commands[0x32] = {
- "CHAT_MESSAGE", 4,
- { f_length, f_message },
- function(buffer, pinfo, tree, t)
- t:add(f_length, buffer(2,2))
- local textlen = buffer(2,2):uint()
- if minetest_check_length(buffer, 4 + textlen*2, t) then
- t:add(f_message, buffer(4, textlen*2), buffer(4, textlen*2):ustring())
- end
- end
- }
- end
- -- TOSERVER_SIGNNODETEXT (obsolete)
- minetest_client_commands[0x33] = { "SIGNNODETEXT", 2 }
- minetest_client_obsolete[0x33] = true
- -- TOSERVER_CLICK_ACTIVEOBJECT (obsolete)
- minetest_client_commands[0x34] = { "CLICK_ACTIVEOBJECT", 2 }
- minetest_client_obsolete[0x34] = true
- -- TOSERVER_DAMAGE
- do
- local f_amount = ProtoField.uint8("minetest.client.damage_amount", "Amount", base.DEC)
- minetest_client_commands[0x35] = {
- "DAMAGE", 3,
- { f_amount },
- function(buffer, pinfo, tree, t)
- t:add(f_amount, buffer(2,1))
- end
- }
- end
- -- TOSERVER_PASSWORD (obsolete)
- minetest_client_commands[0x36] = { "CLICK_ACTIVEOBJECT", 2 }
- minetest_client_obsolete[0x36] = true
- -- TOSERVER_PLAYERITEM
- do
- local f_item = ProtoField.uint16("minetest.client.playeritem_item", "Wielded item")
- minetest_client_commands[0x37] = {
- "PLAYERITEM", 4,
- { f_item },
- function(buffer, pinfo, tree, t)
- t:add(f_item, buffer(2,2))
- end
- }
- end
- -- TOSERVER_RESPAWN
- minetest_client_commands[0x38] = { "RESPAWN", 2 }
- -- TOSERVER_INTERACT
- do
- local abbr = "minetest.client.interact_"
- local vs_action = {
- [0] = "Start digging",
- [1] = "Stop digging",
- [2] = "Digging completed",
- [3] = "Place block or item",
- [4] = "Use item",
- [5] = "Activate held item",
- }
- local vs_pointed_type = {
- [0] = "Nothing",
- [1] = "Node",
- [2] = "Object",
- }
- local f_action = ProtoField.uint8(abbr.."action", "Action", base.DEC, vs_action)
- local f_item = ProtoField.uint16(abbr.."item", "Item Index", base.DEC)
- local f_plen = ProtoField.uint32(abbr.."plen", "Length of pointed thing", base.DEC)
- local f_pointed_version = ProtoField.uint8(abbr.."pointed_version",
- "Pointed Thing Version", base.DEC)
- local f_pointed_type = ProtoField.uint8(abbr.."pointed_version",
- "Pointed Thing Type", base.DEC, vs_pointed_type)
- local f_pointed_under_x = ProtoField.int16(abbr.."pointed_under_x",
- "Node position (under surface) X")
- local f_pointed_under_y = ProtoField.int16(abbr.."pointed_under_y",
- "Node position (under surface) Y")
- local f_pointed_under_z = ProtoField.int16(abbr.."pointed_under_z",
- "Node position (under surface) Z")
- local f_pointed_above_x = ProtoField.int16(abbr.."pointed_above_x",
- "Node position (above surface) X")
- local f_pointed_above_y = ProtoField.int16(abbr.."pointed_above_y",
- "Node position (above surface) Y")
- local f_pointed_above_z = ProtoField.int16(abbr.."pointed_above_z",
- "Node position (above surface) Z")
- local f_pointed_object_id = ProtoField.int16(abbr.."pointed_object_id",
- "Object ID")
- -- mising: additional playerpos data just like in TOSERVER_PLAYERPOS
- minetest_client_commands[0x39] = {
- "INTERACT", 11,
- { f_action,
- f_item,
- f_plen,
- f_pointed_version,
- f_pointed_type,
- f_pointed_under_x,
- f_pointed_under_y,
- f_pointed_under_z,
- f_pointed_above_x,
- f_pointed_above_y,
- f_pointed_above_z,
- f_pointed_object_id },
- function(buffer, pinfo, tree, t)
- t:add(f_action, buffer(2,1))
- t:add(f_item, buffer(3,2))
- t:add(f_plen, buffer(5,4))
- local plen = buffer(5,4):uint()
- if minetest_check_length(buffer, 9 + plen, t) then
- t:add(f_pointed_version, buffer(9,1))
- t:add(f_pointed_type, buffer(10,1))
- local ptype = buffer(10,1):uint()
- if ptype == 1 then -- Node
- t:add(f_pointed_under_x, buffer(11,2))
- t:add(f_pointed_under_y, buffer(13,2))
- t:add(f_pointed_under_z, buffer(15,2))
- t:add(f_pointed_above_x, buffer(17,2))
- t:add(f_pointed_above_x, buffer(19,2))
- t:add(f_pointed_above_x, buffer(21,2))
- elseif ptype == 2 then -- Object
- t:add(f_pointed_object_id, buffer(11,2))
- end
- end
- end
- }
- end
- -- ...
- minetest_client_commands[0x3a] = { "REMOVED_SOUNDS", 2 }
- minetest_client_commands[0x3b] = { "NODEMETA_FIELDS", 2 }
- minetest_client_commands[0x3c] = { "INVENTORY_FIELDS", 2 }
- minetest_client_commands[0x40] = { "REQUEST_MEDIA", 2 }
- minetest_client_commands[0x41] = { "RECEIVED_MEDIA", 2 }
- -- TOSERVER_BREATH (obsolete)
- minetest_client_commands[0x42] = { "BREATH", 2 }
- minetest_client_obsolete[0x42] = true
- -- TOSERVER_CLIENT_READY
- do
- local abbr = "minetest.client.client_ready_"
- local f_major = ProtoField.uint8(abbr.."major","Version Major")
- local f_minor = ProtoField.uint8(abbr.."minor","Version Minor")
- local f_patch = ProtoField.uint8(abbr.."patch","Version Patch")
- local f_reserved = ProtoField.uint8(abbr.."reserved","Reserved")
- local f_versionlen, f_version =
- minetest_field_helper("uint16", abbr.."version", "Full Version String")
- local f_formspec_ver = ProtoField.uint16(abbr.."formspec_version",
- "Formspec API version")
- minetest_client_commands[0x43] = {
- "CLIENT_READY",
- 8,
- { f_major, f_minor, f_patch, f_reserved, f_versionlen,
- f_version, f_formspec_ver },
- function(buffer, pinfo, tree, t)
- t:add(f_major, buffer(2,1))
- t:add(f_minor, buffer(3,1))
- t:add(f_patch, buffer(4,1))
- t:add(f_reserved, buffer(5,1))
- local off = minetest_decode_helper_ascii(buffer, t, "uint16", 6,
- f_versionlen, f_version)
- if off and minetest_check_length(buffer, off + 2, t) then
- t:add(f_formspec_ver, buffer(off,2))
- end
- end
- }
- end
- -- ...
- minetest_client_commands[0x50] = { "FIRST_SRP", 2 }
- minetest_client_commands[0x51] = { "SRP_BYTES_A", 2 }
- minetest_client_commands[0x52] = { "SRP_BYTES_M", 2 }
- --------------------------------------------
- -- Part 3 --
- -- Server command dissectors (TOCLIENT_*) --
- --------------------------------------------
- minetest_server_commands = {}
- minetest_server_obsolete = {}
- -- TOCLIENT_HELLO
- do
- local abbr = "minetest.server.hello_"
- local f_ser_fmt = ProtoField.uint8(abbr.."ser_version",
- "Deployed serialization format version", base.DEC)
- local f_comp_mode = ProtoField.uint16(abbr.."compression",
- "Deployed compression mode", base.DEC, { [0] = "No compression" })
- local f_proto = ProtoField.uint16(abbr.."proto",
- "Deployed protocol version", base.DEC)
- local f_auth_methods = ProtoField.bytes(abbr.."auth_modes",
- "Supported authentication modes")
- local f_legacy_namelen, f_legacy_name = minetest_field_helper("uint16",
- abbr.."legacy_name", "Legacy player name for hashing")
- minetest_server_commands[0x02] = {
- "HELLO",
- 13,
- { f_ser_fmt, f_comp_mode, f_proto, f_auth_methods,
- f_legacy_namelen, f_legacy_name },
- function(buffer, pinfo, tree, t)
- t:add(f_ser_fmt, buffer(2,1))
- t:add(f_comp_mode, buffer(3,2))
- t:add(f_proto, buffer(5,2))
- t:add(f_auth_methods, buffer(7,4))
- minetest_decode_helper_ascii(buffer, t, "uint16", 11, f_legacy_namelen, f_legacy_name)
- end
- }
- end
- -- TOCLIENT_AUTH_ACCEPT
- do
- local abbr = "minetest.server.auth_accept_"
- local f_player_x = ProtoField.float(abbr.."player_x", "Player position X")
- local f_player_y = ProtoField.float(abbr.."player_y", "Player position Y")
- local f_player_z = ProtoField.float(abbr.."player_z", "Player position Z")
- local f_map_seed = ProtoField.uint64(abbr.."map_seed", "Map seed")
- local f_send_interval = ProtoField.float(abbr.."send_interval",
- "Recommended send interval")
- local f_sudo_auth_methods = ProtoField.bytes(abbr.."sudo_auth_methods",
- "Supported auth methods for sudo mode")
- minetest_server_commands[0x03] = {
- "AUTH_ACCEPT",
- 30,
- { f_player_x, f_player_y, f_player_z, f_map_seed,
- f_send_interval, f_sudo_auth_methods },
- function(buffer, pinfo, tree, t)
- t:add(f_player_x, buffer(2,4))
- t:add(f_player_y, buffer(6,4))
- t:add(f_player_z, buffer(10,4))
- t:add(f_map_seed, buffer(14,8))
- t:add(f_send_interval, buffer(22,4))
- t:add(f_sudo_auth_methods, buffer(26,4))
- end
- }
- end
- -- ...
- minetest_server_commands[0x04] = {"ACCEPT_SUDO_MODE", 2}
- minetest_server_commands[0x05] = {"DENY_SUDO_MODE", 2}
- minetest_server_commands[0x0A] = {"ACCESS_DENIED", 2}
- -- TOCLIENT_INIT (obsolete)
- minetest_server_commands[0x10] = { "INIT", 2 }
- minetest_server_obsolete[0x10] = true
- -- TOCLIENT_BLOCKDATA
- do
- local f_x = ProtoField.int16("minetest.server.blockdata_x", "Block position X", base.DEC)
- local f_y = ProtoField.int16("minetest.server.blockdata_y", "Block position Y", base.DEC)
- local f_z = ProtoField.int16("minetest.server.blockdata_z", "Block position Z", base.DEC)
- local f_data = ProtoField.bytes("minetest.server.blockdata_block", "Serialized MapBlock")
- minetest_server_commands[0x20] = {
- "BLOCKDATA", 8,
- { f_x, f_y, f_z, f_data },
- function(buffer, pinfo, tree, t)
- t:add(f_x, buffer(2,2))
- t:add(f_y, buffer(4,2))
- t:add(f_z, buffer(6,2))
- t:add(f_data, buffer(8, buffer:len() - 8))
- end
- }
- end
- -- TOCLIENT_ADDNODE
- do
- local f_x = ProtoField.int16("minetest.server.addnode_x", "Position X", base.DEC)
- local f_y = ProtoField.int16("minetest.server.addnode_y", "Position Y", base.DEC)
- local f_z = ProtoField.int16("minetest.server.addnode_z", "Position Z", base.DEC)
- local f_data = ProtoField.bytes("minetest.server.addnode_node", "Serialized MapNode")
- minetest_server_commands[0x21] = {
- "ADDNODE", 8,
- { f_x, f_y, f_z, f_data },
- function(buffer, pinfo, tree, t)
- t:add(f_x, buffer(2,2))
- t:add(f_y, buffer(4,2))
- t:add(f_z, buffer(6,2))
- t:add(f_data, buffer(8, buffer:len() - 8))
- end
- }
- end
- -- TOCLIENT_REMOVENODE
- do
- local f_x = ProtoField.int16("minetest.server.removenode_x", "Position X", base.DEC)
- local f_y = ProtoField.int16("minetest.server.removenode_y", "Position Y", base.DEC)
- local f_z = ProtoField.int16("minetest.server.removenode_z", "Position Z", base.DEC)
- minetest_server_commands[0x22] = {
- "REMOVENODE", 8,
- { f_x, f_y, f_z },
- function(buffer, pinfo, tree, t)
- t:add(f_x, buffer(2,2))
- t:add(f_y, buffer(4,2))
- t:add(f_z, buffer(6,2))
- end
- }
- end
- -- TOCLIENT_PLAYERPOS (obsolete)
- minetest_server_commands[0x23] = { "PLAYERPOS", 2 }
- minetest_server_obsolete[0x23] = true
- -- TOCLIENT_PLAYERINFO (obsolete)
- minetest_server_commands[0x24] = { "PLAYERINFO", 2 }
- minetest_server_obsolete[0x24] = true
- -- TOCLIENT_OPT_BLOCK_NOT_FOUND (obsolete)
- minetest_server_commands[0x25] = { "OPT_BLOCK_NOT_FOUND", 2 }
- minetest_server_obsolete[0x25] = true
- -- TOCLIENT_SECTORMETA (obsolete)
- minetest_server_commands[0x26] = { "SECTORMETA", 2 }
- minetest_server_obsolete[0x26] = true
- -- TOCLIENT_INVENTORY
- do
- local f_inventory = ProtoField.string("minetest.server.inventory", "Inventory")
- minetest_server_commands[0x27] = {
- "INVENTORY", 2,
- { f_inventory },
- function(buffer, pinfo, tree, t)
- t:add(f_inventory, buffer(2, buffer:len() - 2))
- end
- }
- end
- -- TOCLIENT_OBJECTDATA (obsolete)
- minetest_server_commands[0x28] = { "OBJECTDATA", 2 }
- minetest_server_obsolete[0x28] = true
- -- TOCLIENT_TIME_OF_DAY
- do
- local f_time = ProtoField.uint16("minetest.server.time_of_day", "Time", base.DEC)
- local f_time_speed = ProtoField.float("minetest.server.time_speed", "Time Speed", base.DEC)
- minetest_server_commands[0x29] = {
- "TIME_OF_DAY", 4,
- { f_time, f_time_speed },
- function(buffer, pinfo, tree, t)
- t:add(f_time, buffer(2,2))
- t:add(f_time_speed, buffer(4,4))
- end
- }
- end
- -- TOCLIENT_CSM_RESTRICTION_FLAGS
- minetest_server_commands[0x2a] = { "CSM_RESTRICTION_FLAGS", 2 }
- -- TOCLIENT_PLAYER_SPEED
- minetest_server_commands[0x2b] = { "PLAYER_SPEED", 2 }
- -- TOCLIENT_CHAT_MESSAGE
- do
- local abbr = "minetest.server.chat_message_"
- local vs_type = {
- [0] = "Raw",
- [1] = "Normal",
- [2] = "Announce",
- [3] = "System",
- }
- local f_version = ProtoField.uint8(abbr.."version", "Version")
- local f_type = ProtoField.uint8(abbr.."type", "Message Type", base.DEC, vs_type)
- local f_senderlen, f_sender = minetest_field_helper("uint16", abbr.."sender",
- "Message sender")
- local f_messagelen, f_message = minetest_field_helper("uint16", abbr:sub(1,-2),
- "Message")
- minetest_server_commands[0x2f] = {
- "CHAT_MESSAGE", 8,
- { f_version, f_type, f_senderlen, f_sender,
- f_messagelen, f_message },
- function(buffer, pinfo, tree, t)
- t:add(f_version, buffer(2,1))
- t:add(f_type, buffer(3,1))
- local off = 4
- off = minetest_decode_helper_utf16(buffer, t, "uint16", off, f_senderlen, f_sender)
- if off then
- off = minetest_decode_helper_utf16(buffer, t, "uint16", off, f_messagelen, f_message)
- end
- end
- }
- end
- -- TOCLIENT_CHAT_MESSAGE_OLD (obsolete)
- minetest_server_commands[0x30] = { "CHAT_MESSAGE_OLD", 2 }
- minetest_server_obsolete[0x30] = true
- -- TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD
- do
- local f_removed_count = ProtoField.uint16(
- "minetest.server.active_object_remove_add_removed_count",
- "Count of removed objects", base.DEC)
- local f_removed = ProtoField.bytes(
- "minetest.server.active_object_remove_add_removed",
- "Removed object")
- local f_removed_id = ProtoField.uint16(
- "minetest.server.active_object_remove_add_removed_id",
- "ID", base.DEC)
- local f_added_count = ProtoField.uint16(
- "minetest.server.active_object_remove_add_added_count",
- "Count of added objects", base.DEC)
- local f_added = ProtoField.bytes(
- "minetest.server.active_object_remove_add_added",
- "Added object")
- local f_added_id = ProtoField.uint16(
- "minetest.server.active_object_remove_add_added_id",
- "ID", base.DEC)
- local f_added_type = ProtoField.uint8(
- "minetest.server.active_object_remove_add_added_type",
- "Type", base.DEC)
- local f_added_init_length = ProtoField.uint32(
- "minetest.server.active_object_remove_add_added_init_length",
- "Initialization data length", base.DEC)
- local f_added_init_data = ProtoField.bytes(
- "minetest.server.active_object_remove_add_added_init_data",
- "Initialization data")
- minetest_server_commands[0x31] = {
- "ACTIVE_OBJECT_REMOVE_ADD", 6,
- { f_removed_count, f_removed, f_removed_id,
- f_added_count, f_added, f_added_id,
- f_added_type, f_added_init_length, f_added_init_data },
- function(buffer, pinfo, tree, t)
- local t2, index, pos
- local removed_count_pos = 2
- local removed_count = buffer(removed_count_pos, 2):uint()
- t:add(f_removed_count, buffer(removed_count_pos, 2))
- local added_count_pos = removed_count_pos + 2 + 2 * removed_count
- if not minetest_check_length(buffer, added_count_pos + 2, t) then
- return
- end
- -- Loop through removed active objects
- for index = 0, removed_count - 1 do
- pos = removed_count_pos + 2 + 2 * index
- t2 = t:add(f_removed, buffer(pos, 2))
- t2:set_text("Removed object, ID = " .. buffer(pos, 2):uint())
- t2:add(f_removed_id, buffer(pos, 2))
- end
- local added_count = buffer(added_count_pos, 2):uint()
- t:add(f_added_count, buffer(added_count_pos, 2))
- -- Loop through added active objects
- pos = added_count_pos + 2
- for index = 0, added_count - 1 do
- if not minetest_check_length(buffer, pos + 7, t) then
- return
- end
- local init_length = buffer(pos + 3, 4):uint()
- if not minetest_check_length(buffer, pos + 7 + init_length, t) then
- return
- end
- t2 = t:add(f_added, buffer(pos, 7 + init_length))
- t2:set_text("Added object, ID = " .. buffer(pos, 2):uint())
- t2:add(f_added_id, buffer(pos, 2))
- t2:add(f_added_type, buffer(pos + 2, 1))
- t2:add(f_added_init_length, buffer(pos + 3, 4))
- t2:add(f_added_init_data, buffer(pos + 7, init_length))
- pos = pos + 7 + init_length
- end
- pinfo.cols.info:append(" * " .. (removed_count + added_count))
- end
- }
- end
- -- TOCLIENT_ACTIVE_OBJECT_MESSAGES
- do
- local f_object_count = ProtoField.uint16(
- "minetest.server.active_object_messages_object_count",
- "Count of objects", base.DEC)
- local f_object = ProtoField.bytes(
- "minetest.server.active_object_messages_object",
- "Object")
- local f_object_id = ProtoField.uint16(
- "minetest.server.active_object_messages_id",
- "ID", base.DEC)
- local f_message_length = ProtoField.uint16(
- "minetest.server.active_object_messages_message_length",
- "Message length", base.DEC)
- local f_message = ProtoField.bytes(
- "minetest.server.active_object_messages_message",
- "Message")
- minetest_server_commands[0x32] = {
- "ACTIVE_OBJECT_MESSAGES", 2,
- { f_object_count, f_object, f_object_id, f_message_length, f_message },
- function(buffer, pinfo, tree, t)
- local t2, count, pos, message_length
- count = 0
- pos = 2
- while pos < buffer:len() do
- if not minetest_check_length(buffer, pos + 4, t) then
- return
- end
- message_length = buffer(pos + 2, 2):uint()
- if not minetest_check_length(buffer, pos + 4 + message_length, t) then
- return
- end
- count = count + 1
- pos = pos + 4 + message_length
- end
- pinfo.cols.info:append(" * " .. count)
- t:add(f_object_count, count):set_generated()
- pos = 2
- while pos < buffer:len() do
- message_length = buffer(pos + 2, 2):uint()
- t2 = t:add(f_object, buffer(pos, 4 + message_length))
- t2:set_text("Object, ID = " .. buffer(pos, 2):uint())
- t2:add(f_object_id, buffer(pos, 2))
- t2:add(f_message_length, buffer(pos + 2, 2))
- t2:add(f_message, buffer(pos + 4, message_length))
- pos = pos + 4 + message_length
- end
- end
- }
- end
- -- TOCLIENT_HP
- do
- local f_hp = ProtoField.uint16("minetest.server.hp", "Health points", base.DEC)
- minetest_server_commands[0x33] = {
- "HP", 4,
- { f_hp },
- function(buffer, pinfo, tree, t)
- t:add(f_hp, buffer(2,2))
- end
- }
- end
- -- TOCLIENT_MOVE_PLAYER
- do
- local abbr = "minetest.server.move_player_"
- local f_x = ProtoField.float(abbr.."x", "Position X")
- local f_y = ProtoField.float(abbr.."y", "Position Y")
- local f_z = ProtoField.float(abbr.."z", "Position Z")
- local f_pitch = ProtoField.float(abbr.."_pitch", "Pitch")
- local f_yaw = ProtoField.float(abbr.."yaw", "Yaw")
- minetest_server_commands[0x34] = {
- "MOVE_PLAYER", 22,
- { f_x, f_y, f_z, f_pitch, f_yaw, f_garbage },
- function(buffer, pinfo, tree, t)
- t:add(f_x, buffer(2, 4))
- t:add(f_y, buffer(6, 4))
- t:add(f_z, buffer(10, 4))
- t:add(f_pitch, buffer(14, 4))
- t:add(f_yaw, buffer(18, 4))
- end
- }
- end
- -- TOCLIENT_ACCESS_DENIED_LEGACY
- do
- local f_reason_length = ProtoField.uint16("minetest.server.access_denied_reason_length", "Reason length", base.DEC)
- local f_reason = ProtoField.string("minetest.server.access_denied_reason", "Reason")
- minetest_server_commands[0x35] = {
- "ACCESS_DENIED_LEGACY", 4,
- { f_reason_length, f_reason },
- function(buffer, pinfo, tree, t)
- t:add(f_reason_length, buffer(2,2))
- local reason_length = buffer(2,2):uint()
- if minetest_check_length(buffer, 4 + reason_length * 2, t) then
- t:add(f_reason, minetest_convert_utf16(buffer(4, reason_length * 2), "Converted reason message"))
- end
- end
- }
- end
- -- TOCLIENT_FOV
- minetest_server_commands[0x36] = { "FOV", 2 }
- -- TOCLIENT_DEATHSCREEN
- do
- local f_set_camera_point_target = ProtoField.bool(
- "minetest.server.deathscreen_set_camera_point_target",
- "Set camera point target")
- local f_camera_point_target_x = ProtoField.int32(
- "minetest.server.deathscreen_camera_point_target_x",
- "Camera point target X", base.DEC)
- local f_camera_point_target_y = ProtoField.int32(
- "minetest.server.deathscreen_camera_point_target_y",
- "Camera point target Y", base.DEC)
- local f_camera_point_target_z = ProtoField.int32(
- "minetest.server.deathscreen_camera_point_target_z",
- "Camera point target Z", base.DEC)
- minetest_server_commands[0x37] = {
- "DEATHSCREEN", 15,
- { f_set_camera_point_target, f_camera_point_target_x,
- f_camera_point_target_y, f_camera_point_target_z},
- function(buffer, pinfo, tree, t)
- t:add(f_set_camera_point_target, buffer(2,1))
- t:add(f_camera_point_target_x, buffer(3,4))
- t:add(f_camera_point_target_y, buffer(7,4))
- t:add(f_camera_point_target_z, buffer(11,4))
- end
- }
- end
- -- TOCLIENT_MEDIA
- minetest_server_commands[0x38] = {"MEDIA", 2}
- -- TOCLIENT_TOOLDEF (obsolete)
- minetest_server_commands[0x39] = {"TOOLDEF", 2}
- minetest_server_obsolete[0x39] = true
- -- TOCLIENT_NODEDEF
- minetest_server_commands[0x3a] = {"NODEDEF", 2}
- -- TOCLIENT_CRAFTITEMDEF (obsolete)
- minetest_server_commands[0x3b] = {"CRAFTITEMDEF", 2}
- minetest_server_obsolete[0x3b] = true
- -- ...
- minetest_server_commands[0x3c] = {"ANNOUNCE_MEDIA", 2}
- minetest_server_commands[0x3d] = {"ITEMDEF", 2}
- minetest_server_commands[0x3f] = {"PLAY_SOUND", 2}
- minetest_server_commands[0x40] = {"STOP_SOUND", 2}
- minetest_server_commands[0x41] = {"PRIVILEGES", 2}
- minetest_server_commands[0x42] = {"INVENTORY_FORMSPEC", 2}
- minetest_server_commands[0x43] = {"DETACHED_INVENTORY", 2}
- minetest_server_commands[0x44] = {"SHOW_FORMSPEC", 2}
- minetest_server_commands[0x45] = {"MOVEMENT", 2}
- minetest_server_commands[0x46] = {"SPAWN_PARTICLE", 2}
- minetest_server_commands[0x47] = {"ADD_PARTICLE_SPAWNER", 2}
- -- TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY (obsolete)
- minetest_server_commands[0x48] = {"DELETE_PARTICLESPAWNER_LEGACY", 2}
- minetest_server_obsolete[0x48] = true
- -- ...
- minetest_server_commands[0x49] = {"HUDADD", 2}
- minetest_server_commands[0x4a] = {"HUDRM", 2}
- minetest_server_commands[0x4b] = {"HUDCHANGE", 2}
- minetest_server_commands[0x4c] = {"HUD_SET_FLAGS", 2}
- minetest_server_commands[0x4d] = {"HUD_SET_PARAM", 2}
- minetest_server_commands[0x4e] = {"BREATH", 2}
- minetest_server_commands[0x4f] = {"SET_SKY", 2}
- minetest_server_commands[0x50] = {"OVERRIDE_DAY_NIGHT_RATIO", 2}
- minetest_server_commands[0x51] = {"LOCAL_PLAYER_ANIMATIONS", 2}
- minetest_server_commands[0x52] = {"EYE_OFFSET", 2}
- minetest_server_commands[0x53] = {"DELETE_PARTICLESPAWNER", 2}
- minetest_server_commands[0x54] = {"CLOUD_PARAMS", 2}
- minetest_server_commands[0x55] = {"FADE_SOUND", 2}
- -- TOCLIENT_UPDATE_PLAYER_LIST
- do
- local abbr = "minetest.server.update_player_list_"
- local vs_type = {
- [0] = "Init",
- [1] = "Add",
- [2] = "Remove",
- }
- local f_type = ProtoField.uint8(abbr.."type", "Type", base.DEC, vs_type)
- local f_count = ProtoField.uint16(abbr.."count", "Number of players", base.DEC)
- local f_name = ProtoField.string(abbr.."name", "Name")
- minetest_server_commands[0x56] = {
- "UPDATE_PLAYER_LIST",
- 5,
- { f_type, f_count, f_name },
- function(buffer, pinfo, tree, t)
- t:add(f_type, buffer(2,1))
- t:add(f_count, buffer(3,2))
- local count = buffer(3,2):uint()
- local off = 5
- for i = 1, count do
- if not minetest_check_length(buffer, off + 2, t) then
- return
- end
- off = minetest_decode_helper_ascii(buffer, t, "uint16", off, nil, f_name)
- if not off then
- return
- end
- end
- end
- }
- end
- -- ...
- minetest_server_commands[0x57] = {"MODCHANNEL_MSG", 2}
- minetest_server_commands[0x58] = {"MODCHANNEL_SIGNAL", 2}
- minetest_server_commands[0x59] = {"NODEMETA_CHANGED", 2}
- minetest_server_commands[0x5a] = {"SET_SUN", 2}
- minetest_server_commands[0x5b] = {"SET_MOON", 2}
- minetest_server_commands[0x5c] = {"SET_STARS", 2}
- minetest_server_commands[0x60] = {"SRP_BYTES_S_B", 2}
- minetest_server_commands[0x61] = {"FORMSPEC_PREPEND", 2}
- ------------------------------------
- -- Part 4 --
- -- Wrapper protocol subdissectors --
- ------------------------------------
- -- minetest.control dissector
- do
- local p_control = Proto("minetest.control", "Minetest Control")
- local vs_control_type = {
- [0] = "Ack",
- [1] = "Set Peer ID",
- [2] = "Ping",
- [3] = "Disco"
- }
- local f_control_type = ProtoField.uint8("minetest.control.type", "Control Type", base.DEC, vs_control_type)
- local f_control_ack = ProtoField.uint16("minetest.control.ack", "ACK sequence number", base.DEC)
- local f_control_peerid = ProtoField.uint8("minetest.control.peerid", "New peer ID", base.DEC)
- p_control.fields = { f_control_type, f_control_ack, f_control_peerid }
- local data_dissector = Dissector.get("data")
- function p_control.dissector(buffer, pinfo, tree)
- local t = tree:add(p_control, buffer(0,1))
- t:add(f_control_type, buffer(0,1))
- pinfo.cols.info = "Control message"
- local pos = 1
- if buffer(0,1):uint() == 0 then
- pos = 3
- t:set_len(3)
- t:add(f_control_ack, buffer(1,2))
- pinfo.cols.info = "Ack " .. buffer(1,2):uint()
- elseif buffer(0,1):uint() == 1 then
- pos = 3
- t:set_len(3)
- t:add(f_control_peerid, buffer(1,2))
- pinfo.cols.info = "Set peer ID " .. buffer(1,2):uint()
- elseif buffer(0,1):uint() == 2 then
- pinfo.cols.info = "Ping"
- elseif buffer(0,1):uint() == 3 then
- pinfo.cols.info = "Disco"
- end
- data_dissector:call(buffer(pos):tvb(), pinfo, tree)
- end
- end
- -- minetest.client dissector
- -- minetest.server dissector
- -- Defines the minetest.client or minetest.server Proto. These two protocols
- -- are created by the same function because they are so similar.
- -- Parameter: proto: the Proto object
- -- Parameter: this_peer: "Client" or "Server"
- -- Parameter: other_peer: "Server" or "Client"
- -- Parameter: commands: table of command information, built above
- -- Parameter: obsolete: table of obsolete commands, built above
- function minetest_define_client_or_server_proto(is_client)
- -- Differences between minetest.client and minetest.server
- local proto_name, this_peer, other_peer, empty_message_info
- local commands, obsolete
- if is_client then
- proto_name = "minetest.client"
- this_peer = "Client"
- other_peer = "Server"
- empty_message_info = "Empty message / Connect"
- commands = minetest_client_commands -- defined in Part 2
- obsolete = minetest_client_obsolete -- defined in Part 2
- else
- proto_name = "minetest.server"
- this_peer = "Server"
- other_peer = "Client"
- empty_message_info = "Empty message"
- commands = minetest_server_commands -- defined in Part 3
- obsolete = minetest_server_obsolete -- defined in Part 3
- end
- -- Create the protocol object.
- local proto = Proto(proto_name, "Minetest " .. this_peer .. " to " .. other_peer)
- -- Create a table vs_command that maps command codes to command names.
- local vs_command = {}
- local code, command_info
- for code, command_info in pairs(commands) do
- local command_name = command_info[1]
- vs_command[code] = "TO" .. other_peer:upper() .. "_" .. command_name
- end
- -- Field definitions
- local f_command = ProtoField.uint16(proto_name .. ".command", "Command", base.HEX, vs_command)
- local f_empty = ProtoField.bool(proto_name .. ".empty", "Is empty", BASE_NONE)
- proto.fields = { f_command, f_empty }
- -- Add command-specific fields to the protocol
- for code, command_info in pairs(commands) do
- local command_fields = command_info[3]
- if command_fields ~= nil then
- for index, field in ipairs(command_fields) do
- assert(field ~= nil)
- table.insert(proto.fields, field)
- end
- end
- end
- -- minetest.client or minetest.server dissector function
- function proto.dissector(buffer, pinfo, tree)
- local t = tree:add(proto, buffer)
- pinfo.cols.info = this_peer
- if buffer:len() == 0 then
- -- Empty message.
- t:add(f_empty, 1):set_generated()
- pinfo.cols.info:append(": " .. empty_message_info)
- elseif minetest_check_length(buffer, 2, t) then
- -- Get the command code.
- t:add(f_command, buffer(0,2))
- local code = buffer(0,2):uint()
- local command_info = commands[code]
- if command_info == nil then
- -- Error: Unknown command.
- pinfo.cols.info:append(": Unknown command")
- t:add_expert_info(PI_UNDECODED, PI_WARN, "Unknown " .. this_peer .. " to " .. other_peer .. " command")
- else
- -- Process a known command
- local command_name = command_info[1]
- local command_min_length = command_info[2]
- local command_fields = command_info[3]
- local command_dissector = command_info[4]
- if minetest_check_length(buffer, command_min_length, t) then
- pinfo.cols.info:append(": " .. command_name)
- if command_dissector ~= nil then
- command_dissector(buffer, pinfo, tree, t)
- end
- end
- if obsolete[code] then
- t:add_expert_info(PI_REQUEST_CODE, PI_WARN, "Obsolete command.")
- end
- end
- end
- end
- end
- minetest_define_client_or_server_proto(true) -- minetest.client
- minetest_define_client_or_server_proto(false) -- minetest.server
- -- minetest.split dissector
- do
- local p_split = Proto("minetest.split", "Minetest Split Message")
- local f_split_seq = ProtoField.uint16("minetest.split.seq", "Sequence number", base.DEC)
- local f_split_chunkcount = ProtoField.uint16("minetest.split.chunkcount", "Chunk count", base.DEC)
- local f_split_chunknum = ProtoField.uint16("minetest.split.chunknum", "Chunk number", base.DEC)
- local f_split_data = ProtoField.bytes("minetest.split.data", "Split message data")
- p_split.fields = { f_split_seq, f_split_chunkcount, f_split_chunknum, f_split_data }
- function p_split.dissector(buffer, pinfo, tree)
- local t = tree:add(p_split, buffer(0,6))
- t:add(f_split_seq, buffer(0,2))
- t:add(f_split_chunkcount, buffer(2,2))
- t:add(f_split_chunknum, buffer(4,2))
- t:add(f_split_data, buffer(6))
- pinfo.cols.info:append(" " .. buffer(0,2):uint() .. " chunk " .. buffer(4,2):uint() .. "/" .. buffer(2,2):uint())
- end
- end
- -------------------------------------
- -- Part 5 --
- -- Wrapper protocol main dissector --
- -------------------------------------
- -- minetest dissector
- do
- local p_minetest = Proto("minetest", "Minetest")
- local minetest_id = 0x4f457403
- local vs_id = {
- [minetest_id] = "Valid"
- }
- local vs_peer = {
- [0] = "Inexistent",
- [1] = "Server"
- }
- local vs_type = {
- [0] = "Control",
- [1] = "Original",
- [2] = "Split",
- [3] = "Reliable"
- }
- local f_id = ProtoField.uint32("minetest.id", "ID", base.HEX, vs_id)
- local f_peer = ProtoField.uint16("minetest.peer", "Peer", base.DEC, vs_peer)
- local f_channel = ProtoField.uint8("minetest.channel", "Channel", base.DEC)
- local f_type = ProtoField.uint8("minetest.type", "Type", base.DEC, vs_type)
- local f_seq = ProtoField.uint16("minetest.seq", "Sequence number", base.DEC)
- local f_subtype = ProtoField.uint8("minetest.subtype", "Subtype", base.DEC, vs_type)
- p_minetest.fields = { f_id, f_peer, f_channel, f_type, f_seq, f_subtype }
- local data_dissector = Dissector.get("data")
- local control_dissector = Dissector.get("minetest.control")
- local client_dissector = Dissector.get("minetest.client")
- local server_dissector = Dissector.get("minetest.server")
- local split_dissector = Dissector.get("minetest.split")
- function p_minetest.dissector(buffer, pinfo, tree)
- -- Add Minetest tree item and verify the ID
- local t = tree:add(p_minetest, buffer(0,8))
- t:add(f_id, buffer(0,4))
- if buffer(0,4):uint() ~= minetest_id then
- t:add_expert_info(PI_UNDECODED, PI_WARN, "Invalid ID, this is not a Minetest packet")
- return
- end
- -- ID is valid, so replace packet's shown protocol
- pinfo.cols.protocol = "Minetest"
- pinfo.cols.info = "Minetest"
- -- Set the other header fields
- t:add(f_peer, buffer(4,2))
- t:add(f_channel, buffer(6,1))
- t:add(f_type, buffer(7,1))
- t:set_text("Minetest, Peer: " .. buffer(4,2):uint() .. ", Channel: " .. buffer(6,1):uint())
- local reliability_info
- if buffer(7,1):uint() == 3 then
- -- Reliable message
- reliability_info = "Seq=" .. buffer(8,2):uint()
- t:set_len(11)
- t:add(f_seq, buffer(8,2))
- t:add(f_subtype, buffer(10,1))
- pos = 10
- else
- -- Unreliable message
- reliability_info = "Unrel"
- pos = 7
- end
- if buffer(pos,1):uint() == 0 then
- -- Control message, possibly reliable
- control_dissector:call(buffer(pos+1):tvb(), pinfo, tree)
- elseif buffer(pos,1):uint() == 1 then
- -- Original message, possibly reliable
- if buffer(4,2):uint() == 1 then
- server_dissector:call(buffer(pos+1):tvb(), pinfo, tree)
- else
- client_dissector:call(buffer(pos+1):tvb(), pinfo, tree)
- end
- elseif buffer(pos,1):uint() == 2 then
- -- Split message, possibly reliable
- if buffer(4,2):uint() == 1 then
- pinfo.cols.info = "Server: Split message"
- else
- pinfo.cols.info = "Client: Split message"
- end
- split_dissector:call(buffer(pos+1):tvb(), pinfo, tree)
- elseif buffer(pos,1):uint() == 3 then
- -- Doubly reliable message??
- t:add_expert_info(PI_MALFORMED, PI_ERROR, "Reliable message wrapped in reliable message")
- else
- data_dissector:call(buffer(pos+1):tvb(), pinfo, tree)
- end
- pinfo.cols.info:append(" (" .. reliability_info .. ")")
- end
- -- FIXME Is there a way to let the dissector table check if the first payload bytes are 0x4f457403?
- DissectorTable.get("udp.port"):add(30000, p_minetest)
- DissectorTable.get("udp.port"):add(30001, p_minetest)
- end
- ------------------------------
- -- Part 6 --
- -- Utility functions part 2 --
- ------------------------------
- -- Checks if a (sub-)Tvb is long enough to be further dissected.
- -- If it is long enough, sets the dissector tree item length to min_len
- -- and returns true. If it is not long enough, adds expert info to the
- -- dissector tree and returns false.
- -- Parameter: tvb: the Tvb
- -- Parameter: min_len: required minimum length
- -- Parameter: t: dissector tree item
- -- Returns: true if tvb:len() >= min_len, false otherwise
- function minetest_check_length(tvb, min_len, t)
- if tvb:len() >= min_len then
- t:set_len(min_len)
- return true
- -- TODO: check if other parts of
- -- the dissector could benefit from reported_length_remaining
- elseif tvb:reported_length_remaining() >= min_len then
- t:add_expert_info(PI_UNDECODED, PI_INFO, "Only part of this packet was captured, unable to decode.")
- return false
- else
- t:add_expert_info(PI_MALFORMED, PI_ERROR, "Message is too short")
- return false
- end
- end
- -- Decodes a variable-length string as ASCII text
- -- t_textlen, t_text should be the ProtoFields created by minetest_field_helper
- -- alternatively t_text can be a ProtoField.string and t_textlen can be nil
- -- lentype must be the type of the length field (as passed to minetest_field_helper)
- -- returns nil if length check failed
- function minetest_decode_helper_ascii(tvb, t, lentype, offset, f_textlen, f_text)
- local n = ({uint16 = 2, uint32 = 4})[lentype]
- assert(n)
- if f_textlen then
- t:add(f_textlen, tvb(offset, n))
- end
- local textlen = tvb(offset, n):uint()
- if minetest_check_length(tvb, offset + n + textlen, t) then
- t:add(f_text, tvb(offset + n, textlen))
- return offset + n + textlen
- end
- end
- -- Decodes a variable-length string as UTF-16 text
- -- (see minetest_decode_helper_ascii)
- function minetest_decode_helper_utf16(tvb, t, lentype, offset, f_textlen, f_text)
- local n = ({uint16 = 2, uint32 = 4})[lentype]
- assert(n)
- if f_textlen then
- t:add(f_textlen, tvb(offset, n))
- end
- local textlen = tvb(offset, n):uint() * 2
- if minetest_check_length(tvb, offset + n + textlen, t) then
- t:add(f_text, tvb(offset + n, textlen), tvb(offset + n, textlen):ustring())
- return offset + n + textlen
- end
- end
|