diff options
Diffstat (limited to 'util')
| -rw-r--r-- | util/wireshark/minetest.lua | 1285 |
1 files changed, 1285 insertions, 0 deletions
diff --git a/util/wireshark/minetest.lua b/util/wireshark/minetest.lua new file mode 100644 index 000000000..a7cd0c77c --- /dev/null +++ b/util/wireshark/minetest.lua @@ -0,0 +1,1285 @@ +-- minetest.lua +-- Packet dissector for the UDP-based Minetest protocol +-- Copy this to $HOME/.wireshark/plugins/ + + +-- +-- Minetest-c55 +-- 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. +-- + + +-- Table of Contents: +-- Part 1: Client command dissectors (TOSERVER_*) +-- Part 2: Server command dissectors (TOCLIENT_*) +-- Part 3: Wrapper protocol subdissectors +-- Part 4: Wrapper protocol main dissector +-- Part 5: Utility functions + + + + +-------------------------------------------- +-- Part 1 -- +-- Client command dissectors (TOSERVER_*) -- +-------------------------------------------- + +minetest_client_commands = {} +minetest_client_obsolete = {} + +-- TOSERVER_INIT + +do + local f_ser_fmt = ProtoField.uint8("minetest.client.init_ser_version", + "Maximum serialization format version", base.DEC) + local f_player_name = ProtoField.stringz("minetest.client.init_player_name", "Player Name") + local f_password = ProtoField.stringz("minetest.client.init_password", "Password") + local f_version = ProtoField.uint16("minetest.client.init_version", "Version", base.DEC) + + minetest_client_commands[0x10] = { + "INIT", -- Command name + 53, -- Minimum message length including code + { f_ser_fmt, -- List of fields [optional] + f_player_name, + f_password, + f_version }, + function(buffer, pinfo, tree, t) -- Dissector function [optional] + t:add(f_ser_fmt, buffer(2,1)) + t:add(f_player_name, buffer(3,20)) + t:add(f_password, buffer(23,28)) + t:add(f_version, buffer(51,2)) + end + } +end + +-- TOSERVER_INIT2 + +minetest_client_commands[0x11] = { "INIT2", 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 f_x = ProtoField.int32("minetest.client.playerpos_x", "Position X", base.DEC) + local f_y = ProtoField.int32("minetest.client.playerpos_y", "Position Y", base.DEC) + local f_z = ProtoField.int32("minetest.client.playerpos_z", "Position Z", base.DEC) + local f_speed_x = ProtoField.int32("minetest.client.playerpos_speed_x", "Speed X", base.DEC) + local f_speed_y = ProtoField.int32("minetest.client.playerpos_speed_y", "Speed Y", base.DEC) + local f_speed_z = ProtoField.int32("minetest.client.playerpos_speed_z", "Speed Z", base.DEC) + local f_pitch = ProtoField.int32("minetest.client.playerpos_pitch", "Pitch", base.DEC) + local f_yaw = ProtoField.int32("minetest.client.playerpos_yaw", "Yaw", 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 }, + 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)) + end + } +end + +-- TOSERVER_GOTBLOCKS + +do + local f_count = ProtoField.uint8("minetest.client.gotblocks_count", "Count", base.DEC) + local f_block = ProtoField.bytes("minetset.client.gotblocks_block", "Block", base.DEC) + 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 +-- TODO: Test this + +do + local f_count = ProtoField.uint8("minetest.client.deletedblocks_count", "Count", base.DEC) + local f_block = ProtoField.bytes("minetset.client.deletedblocks_block", "Block", base.DEC) + 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 +-- TODO: Test this + +do + local vs_button = { + [0] = "left", + [1] = "right" + } + + local f_button = ProtoField.uint8("minetest.client.click_object_button", "Button", base.DEC, vs_button) + local f_blockpos_x = ProtoField.int16("minetest.client.click_object_blockpos_x", "Block position X", base.DEC) + local f_blockpos_y = ProtoField.int16("minetest.client.click_object_blockpos_y", "Block position Y", base.DEC) + local f_blockpos_z = ProtoField.int16("minetest.client.click_object_blockpos_z", "Block position Z", base.DEC) + local f_id = ProtoField.int16("minetest.client.click_object_id", "ID", base.DEC) + local f_item = ProtoField.uint16("minetest.client.click_object_item", "Item", base.DEC) + + minetest_client_commands[0x27] = { + "CLICK_OBJECT", 13, + { f_button, f_blockpos_x, f_blockpos_y, f_blockpos_z, f_id, f_item }, + function(buffer, pinfo, tree, t) + t:add(f_button, buffer(2,1)) + t:add(f_blockpos_x, buffer(3,2)) + t:add(f_blockpos_y, buffer(5,2)) + t:add(f_blockpos_z, buffer(7,2)) + t:add(f_id, buffer(9,2)) + t:add(f_item, buffer(11,2)) + end + } +end + +-- TOSERVER_GROUND_ACTION + +do + local vs_action = { + [0] = "Start digging", + [1] = "Place block", + [2] = "Stop digging", + [3] = "Digging completed" + } + + local f_action = ProtoField.uint8("minetest.client.ground_action", "Action", base.DEC, vs_action) + local f_nodepos_undersurface_x = ProtoField.int16( + "minetest.client.ground_action_nodepos_undersurface_x", + "Node position (under surface) X") + local f_nodepos_undersurface_y = ProtoField.int16( + "minetest.client.ground_action_nodepos_undersurface_y", + "Node position (under surface) Y") + local f_nodepos_undersurface_z = ProtoField.int16( + "minetest.client.ground_action_nodepos_undersurface_z", + "Node position (under surface) Z") + local f_nodepos_abovesurface_x = ProtoField.int16( + "minetest.client.ground_action_nodepos_abovesurface_x", + "Node position (above surface) X") + local f_nodepos_abovesurface_y = ProtoField.int16( + "minetest.client.ground_action_nodepos_abovesurface_y", + "Node position (above surface) Y") + local f_nodepos_abovesurface_z = ProtoField.int16( + "minetest.client.ground_action_nodepos_abovesurface_z", + "Node position (above surface) Z") + local f_item = ProtoField.uint16("minetest.client.ground_action_item", "Item") + + minetest_client_commands[0x28] = { + "GROUND_ACTION", 17, + { f_action, + f_nodepos_undersurface_x, + f_nodepos_undersurface_y, + f_nodepos_undersurface_z, + f_nodepos_abovesurface_x, + f_nodepos_abovesurface_y, + f_nodepos_abovesurface_z, + f_item }, + function(buffer, pinfo, tree, t) + t:add(f_action, buffer(2,1)) + t:add(f_nodepos_undersurface_x, buffer(3,2)) + t:add(f_nodepos_undersurface_y, buffer(5,2)) + t:add(f_nodepos_undersurface_z, buffer(7,2)) + t:add(f_nodepos_abovesurface_x, buffer(9,2)) + t:add(f_nodepos_abovesurface_y, buffer(11,2)) + t:add(f_nodepos_abovesurface_z, buffer(13,2)) + t:add(f_item, buffer(15,2)) + end + } +end + +-- TOSERVER_RELEASE (obsolete) + +minetest_client_commands[0x29] = { "RELEASE", 2 } +minetest_client_obsolete[0x29] = true + +-- TOSERVER_SIGNTEXT (old signs) +-- TODO: Test this or mark obsolete + +do + local f_blockpos_x = ProtoField.int16("minetest.client.signtext_blockpos_x", "Block position X", base.DEC) + local f_blockpos_y = ProtoField.int16("minetest.client.signtext_blockpos_y", "Block position Y", base.DEC) + local f_blockpos_z = ProtoField.int16("minetest.client.signtext_blockpos_z", "Block position Z", base.DEC) + local f_id = ProtoField.int16("minetest.client.signtext_id", "ID", base.DEC) + local f_textlen = ProtoField.uint16("minetest.client.signtext_textlen", "Text length", base.DEC) + local f_text = ProtoField.string("minetest.client.signtext_text", "Text") + + minetest_client_commands[0x30] = { + "SIGNTEXT", 12, + { f_blockpos_x, f_blockpos_y, f_blockpos_z, f_id, f_textlen, f_text }, + function(buffer, pinfo, tree, t) + t:add(f_blockpos_x, buffer(2,2)) + t:add(f_blockpos_y, buffer(4,2)) + t:add(f_blockpos_z, buffer(6,2)) + t:add(f_id, buffer(8,2)) + t:add(f_textlen, buffer(10,2)) + local textlen = buffer(10,2):uint() + if minetest_check_length(buffer, 12 + textlen, t) then + t:add(f_text, buffer, buffer(12,textlen)) + end + end + } +end + +-- TOSERVER_INVENTORY_ACTION + + + minetest_client_commands[0x36] = { + "PASSWORD", 58, + { f_old_password, f_new_password }, + function(buffer, pinfo, tree, t) + t:add(f_old_password, buffer(2,28)) + t:add(f_new_password, buffer(30,28)) + end + } +end + +-- 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 + + + + +-------------------------------------------- +-- Part 2 -- +-- Server command dissectors (TOCLIENT_*) -- +-------------------------------------------- + +minetest_server_commands = {} +minetest_server_obsolete = {} + +-- TOCLIENT_INIT + +do + local f_version = ProtoField.uint8("minetest.server.init_version", "Deployed version", base.DEC) + local f_pos_x = ProtoField.int16("minetest.server.init_pos_x", "Position X", base.DEC) + local f_pos_y = ProtoField.int16("minetest.server.init_pos_y", "Position Y", base.DEC) + local f_pos_z = ProtoField.int16("minetest.server.init_pos_x", "Position Z", base.DEC) + local f_map_seed = ProtoField.uint64("minetest.server.init_map_seed", "Map seed", base.DEC) + + minetest_server_commands[0x10] = { + "INIT", 17, + { f_version, f_pos_x, f_pos_y, f_pos_z, f_map_seed }, + function(buffer, pinfo, tree, t) + t:add(f_version, buffer(2,1)) + t:add(f_pos_x, buffer(3,2)) + t:add(f_pos_y, buffer(5,2)) + t:add(f_pos_z, buffer(7,2)) + t:add(f_map_seed, buffer(9,8)) + end + } +end + +-- 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 + +do + local f_count = ProtoField.uint16("minetest.server.playerinfo_count", "Count", base.DEC) + local f_player = ProtoField.bytes("minetest.server.playerinfo_player", "Player", base.DEC) + local f_peer_id = ProtoField.uint16("minetest.server.playerinfo_peer_id", "Peer ID", base.DEC) + local f_name = ProtoField.string("minetest.server.playerinfo_name", "Name") + + minetest_server_commands[0x24] = { + "PLAYERINFO", 2, + { f_count, f_player, f_peer_id, f_name }, + function(buffer, pinfo, tree, t) + local count = 0 + local pos, index + for pos = 2, buffer:len() - 22, 22 do -- does lua have integer division? + count = count + 1 + end + t:add(f_count, count):set_generated() + t:set_len(2 + 22 * count) + pinfo.cols.info:append(" * " .. count) + for index = 0, count - 1 do + local pos = 2 + 22 * index + local t2 = t:add(f_player, buffer(pos, 22)) + t2:set_text("Player, ID: " .. buffer(pos, 2):uint() + .. ", Name: " .. buffer(pos + 2, 20):string()) + t2:add(f_peer_id, buffer(pos, 2)) + t2:add(f_name, buffer(pos + 2, 20)) + end + end + } +end + +-- 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_
VORBIS_LIBRARY - Only if building with sound; path to libvorbis.a/libvorbis.so/libvorbis.dll.a
XXF86VM_LIBRARY - Only on Linux; path to libXXf86vm.a/libXXf86vm.so
ZLIB_DLL - Only on Windows; path to zlib1.dll
ZLIB_INCLUDE_DIR - Directory that contains zlib.h
ZLIB_LIBRARY - Path to libz.a/libz.so/zlib.lib
### Compiling on Windows
### Requirements
- [Visual Studio 2015 or newer](https://visualstudio.microsoft.com)
- [CMake](https://cmake.org/download/)
- [vcpkg](https://github.com/Microsoft/vcpkg)
- [Git](https://git-scm.com/downloads)
### Compiling and installing the dependencies
It is highly recommended to use vcpkg as package manager.
#### a) Using vcpkg to install dependencies
After you successfully built vcpkg you can easily install the required libraries:
```powershell
vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit --triplet x64-windows
```
- `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store.
- `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound.
- `freetype` is optional, it allows true-type font rendering.
- `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter.
There are other optional libraries, but they are not tested if they can build and link correctly.
Use `--triplet` to specify the target triplet, e.g. `x64-windows` or `x86-windows`.
#### b) Compile the dependencies on your own
This is outdated and not recommended. Follow the instructions on https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build
### Compile Minetest
#### a) Using the vcpkg toolchain and CMake GUI
1. Start up the CMake GUI
2. Select **Browse Source...** and select DIR/minetest
3. Select **Browse Build...** and select DIR/minetest-build
4. Select **Configure**
5. Choose the right visual Studio version and target platform. It has to match the version of the installed dependencies
6. Choose **Specify toolchain file for cross-compiling**
7. Click **Next**
8. Select the vcpkg toolchain file e.g. `D:/vcpkg/scripts/buildsystems/vcpkg.cmake`
9. Click Finish
10. Wait until cmake have generated the cash file
11. If there are any errors, solve them and hit **Configure**
12. Click **Generate**
13. Click **Open Project**
14. Compile Minetest inside Visual studio.
#### b) Using the vcpkg toolchain and the commandline
Run the following script in PowerShell:
```powershell
cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=0 -DENABLE_CURSES=0
cmake --build . --config Release
```
Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct.
#### c) Using your own compiled libraries
**This is outdated and not recommended**
Follow the instructions on https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build
### Windows Installer using WiX Toolset
Requirements:
* [Visual Studio 2017](https://visualstudio.microsoft.com/)
* [WiX Toolset](https://wixtoolset.org/)
In the Visual Studio 2017 Installer select **Optional Features -> WiX Toolset**.
Build the binaries as described above, but make sure you unselect `RUN_IN_PLACE`.
Open the generated project file with Visual Studio. Right-click **Package** and choose **Generate**.
It may take some minutes to generate the installer.
Docker
------
We provide Minetest server Docker images using the GitLab mirror registry.
Images are built on each commit and available using the following tag scheme:
* `registry.gitlab.com/minetest/minetest/server:latest` (latest build)
* `registry.gitlab.com/minetest/minetest/server:<branch/tag>` (current branch or current tag)
* `registry.gitlab.com/minetest/minetest/server:<commit-id>` (current commit id)
If you want to test it on a Docker server you can easily run:
sudo docker run registry.gitlab.com/minetest/minetest/server:<docker tag>
If you want to use it in a production environment you should use volumes bound to the Docker host
to persist data and modify the configuration:
sudo docker create -v /home/minetest/data/:/var/lib/minetest/ -v /home/minetest/conf/:/etc/minetest/ registry.gitlab.com/minetest/minetest/server:master
Data will be written to `/home/minetest/data` on the host, and configuration will be read from `/home/minetest/conf/minetest.conf`.
**Note:** If you don't understand the previous commands please read the official Docker documentation before use.
You can also host your Minetest server inside a Kubernetes cluster. See our example implementation in [`misc/kubernetes.yml`](misc/kubernetes.yml).
Version scheme
--------------
We use `major.minor.patch` since 5.0.0-dev. Prior to that we used `0.major.minor`.
- Major is incremented when the release contains breaking changes, all other
numbers are set to 0.
- Minor is incremented when the release contains new non-breaking features,
patch is set to 0.
- Patch is incremented when the release only contains bugfixes and very
minor/trivial features considered necessary.
Since 5.0.0-dev and 0.4.17-dev, the dev notation refers to the next release,
i.e.: 5.0.0-dev is the development version leading to 5.0.0.
Prior to that we used `previous_version-dev`.
|
