From d9303149cb989e7af96b3964cf34018f295ba312 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 01:02:13 +0000 Subject: Initial commit --- util/run_tests | 192 +++++++++++++++++++++++++++++ util/snowcast-dissector/README.md | 68 ++++++++++ util/snowcast-dissector/cs168_snowcast.lua | 107 ++++++++++++++++ util/snowcast-dissector/install.sh | 14 +++ util/tester/arm64/control_tester | Bin 0 -> 6742776 bytes util/tester/arm64/server_tester | Bin 0 -> 6808312 bytes util/tester/control_tester | Bin 0 -> 7031352 bytes util/tester/data/short_file | Bin 0 -> 20480 bytes util/tester/data/test.txt | 12 ++ util/tester/server_tester | Bin 0 -> 7055960 bytes util/update_from_stencil | 18 +++ 11 files changed, 411 insertions(+) create mode 100755 util/run_tests create mode 100644 util/snowcast-dissector/README.md create mode 100644 util/snowcast-dissector/cs168_snowcast.lua create mode 100755 util/snowcast-dissector/install.sh create mode 100755 util/tester/arm64/control_tester create mode 100755 util/tester/arm64/server_tester create mode 100755 util/tester/control_tester create mode 100644 util/tester/data/short_file create mode 100644 util/tester/data/test.txt create mode 100755 util/tester/server_tester create mode 100755 util/update_from_stencil (limited to 'util') diff --git a/util/run_tests b/util/run_tests new file mode 100755 index 0000000..4dbdf4b --- /dev/null +++ b/util/run_tests @@ -0,0 +1,192 @@ +#!/bin/bash +set -euo pipefail + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +TESTER_DIR=${SCRIPT_DIR}/tester +DATA_DIR=${TESTER_DIR}/data +MP3_DIR=${SCRIPT_DIR}/../mp3 + +# Set automatically +arch="`uname -m`" +platform= + +verbose=true +fail_fast=false +bin_dir=$(realpath ${SCRIPT_DIR}/..) + +__check_platform() +{ + if test -z "$platform" -a \( "$arch" = "arm64" -o "$arch" = "aarch64" \); then + platform=linux/arm64 + elif test -z "$platform"; then + platform=linux/amd64 + fi +} + +do_help() { + cat <&2 + exit 1 + fi + ;; + -x|--x86-64) + shift + platform=linux/amd64 + ;; + --bin-dir) + bin_dir="$2" + shift + shift + ;; + --help) + shift + do_help + exit 0 + ;; + *) + POSITIONAL+=("$1") + shift + esac + done + set -- "${POSITIONAL[@]}" + + __check_platform + + # Default subcommand + if [[ $# == 0 ]]; then + do_all + exit 0 + fi + + # Subcommands + case $1 in + help) + do_help + exit 0 + ;; + server) + shift + do_server $@ + ;; + control) + shift + do_control $@ + ;; + milestone) + shift + do_milestone $@ + ;; + all) + shift + do_all $@ + ;; + *) + echo "Unrecognized command $1" + exit 1 + ;; + esac +} + +main $@ diff --git a/util/snowcast-dissector/README.md b/util/snowcast-dissector/README.md new file mode 100644 index 0000000..a62522e --- /dev/null +++ b/util/snowcast-dissector/README.md @@ -0,0 +1,68 @@ +# CS1680 Snowcast Dissector + +THis directory contains a dissector (also known as a decoder) for the Snowcast +protocol implementation for CS168. + +## Installation Instructions + +The dissector is provided as a Lua script in this directory. For security +reasons, Wireshark does not run Lua scripts when run as root--therefore, you +must ensure that you are using Wireshark as your local user, not with root or +sudo. To run wireshark as a standard user, make sure your user is added to the +`wireshark` group. If you are using the provided VM, the the vagrant user is +already in the wireshark group. However, if you are running Wireshark on your +own system, you will need to configure this yourself. + +Once you have Wireshark running as your user. Add the dissector to Wireshark, +by copying the script into your plugins directory. + +To do this: + + 1. Run wireshark as your user (**not with root or sudo**). + 2. Open Wireshark's Help menu and select "About Wireshark". + 3. In the folders tab, find the entry "Personal Lua Plugins". For example: + `~/.config/wireshark/plugins` + 4. Copy the script to this directory (if it doesn't exist, create it) and + restart wireshark + 5. Open the "About Wireshark" window again and look in the Plugins tab. You + should now see cs168_rip.lua in the list of plugins. + +## Using the dissector + +_To make sure your dissector is working, please run the Snowcast reference +binaries_ + +Wireshark will automatically invoke the Snowcast dissector when it encounters a +TCP packets on port 1680. This means that if you start the Snowcast server on +port 1680, TCP packets on port 1680 will automatically be decoded as Snowcast +commands and replies. + +To use the Snowcast dissector with other port numbers we can instruct wireshark +to interpret TCP packets on a given port as Snowcast commands and responses. +We can tell wireshark to do this using Wireshark's "User-Specified Decodes" +feature: + +1. Run your binaries and to start capturing packets. You should be capturing + packets on the loopback interface. +2. Find a TCP packet related to this assignment and select it. These packets + will have a destination and source port number. One of these port numbers + should be the port number you selected when starting up the Snowcast server. +3. Right click on the TCP packet and select "Decode As..." +4. Double click "(none)" under "current" and select CS168SNOWCAST. + +Wireshark should no update and decode the TCP packets with your specified port +number as Snowcast commands and replies. + +If you do not see Snowcast commands and replies, check your "Decode As..." rule +from step 4. If you still do not see Snowcast commands and replies, make sure +that the plugin is loaded in the help menu. + +### Disclaimer + +The steps listed above will invoke the decoder only on a single TCP port. You +should repeat the steps above each time you change TCP ports + +## Feedback + +If you have questions or encounter any issues with the decoder, please post on +EdStem or see the course staff for help. diff --git a/util/snowcast-dissector/cs168_snowcast.lua b/util/snowcast-dissector/cs168_snowcast.lua new file mode 100644 index 0000000..5389035 --- /dev/null +++ b/util/snowcast-dissector/cs168_snowcast.lua @@ -0,0 +1,107 @@ +-- CS168 Snowcast Protocol Dissector + +snowcast_protocol = Proto("CS168Snowcast", "CS168 Snowcast Protocol") + +message = ProtoField.uint8("cs168snowcast.messsage_type", "messageType", base.DEC) + +-- HELLO fields +udp_port = ProtoField.uint16("cs168snowcast.udp_port", "udpPort", base.DEC) +-- SET_STATION fields +station_number = ProtoField.uint16("cs168snowcast.station_number", "stationNumber", base.DEC) +-- WELCOME fields +num_stations = ProtoField.uint16("cs168snowcast.num_stations", "numStations", base.DEC) +-- ANNOUNCE fields +song_name_size = ProtoField.uint8("cs168snowcast.song_name_size", "songnameSize", base.DEC) +song_name = ProtoField.string("cs168snowcast.song_name", "songname") +-- INVALID_COMMAND fields +reply_string_size = ProtoField.uint8("cs168snowcast.reply_string_size", "replyStringSize", base.DEC) +reply_string = ProtoField.string("cs168snowcast.reply_string", "replyString") + +snowcast_protocol.fields = { + message, + udp_port, + station_number, + num_stations, + song_name_size, + song_name, + reply_string_size, + reply_string +} + +function snowcast_protocol.dissector(buffer, pinfo, tree) + length = buffer:len() + if length == 0 then return end + + pinfo.cols.protocol = snowcast_protocol.name + + local subtree = tree:add(snowcast_protocol, buffer(), "Snowcast Protocol Data") + + local packet_len = buffer:reported_length_remaining() + + local message_num = buffer(0, 1):uint() + local message_name = get_message_name(message_num) + + -- Add command ID and name + subtree:add(message, buffer(0, 1)):append_text(" (" .. message_name .. ") ") + + -- Clear any existing info in the info column so the TCP stuff info isn't in the way + pinfo.cols.info = "" + + pinfo.cols.info:append("Snowcast " .. message_name) + + if message_num == 0 then + -- Handling HELLO command + local udpPort = buffer(1, 2):uint() + subtree:add(udp_port, buffer(1, 2)) + pinfo.cols.info:append(" (UDP Port: " .. udpPort .. ") ") + elseif message_num == 1 then + -- Handling SET_STATION command + local stationNumber = buffer(1, 2):uint() + subtree:add(station_number, buffer(1, 2)) + pinfo.cols.info:append(" (Station Number: " .. stationNumber .. ") ") + elseif message_num == 2 then + -- Handling WELCOME reply + local numStations = buffer(1, 2):uint() + subtree:add(num_stations, buffer(1, 2)) + pinfo.cols.info:append(" (Station Number: " .. numStations .. ") ") + elseif message_num == 3 then + -- Handling ANNOUNCE reply + local songnameSize = buffer(1, 1):uint() + subtree:add(reply_string_size, buffer(1, 1)) + + local songname = buffer(2, songnameSize):string() + subtree:add(reply_string, buffer(2, songnameSize)) + + pinfo.cols.info:append(" (Song Name [" .. songnameSize .. " bytes]: " .. songname .. ") ") + elseif message_num == 4 then + -- Handling INVALID_COMMAND reply + local replyStringSize = buffer(1, 1):uint() + subtree:add(reply_string_size, buffer(1, 1)) + + local replyString = buffer(2, replyStringSize):string() + subtree:add(reply_string, buffer(2, replyStringSize)) + + pinfo.cols.info:append(" (Reply String [" .. replyStringSize .. " bytes]: " .. replyString .. ") ") + end +end + +function get_message_name(message_num) + local message_name = "UNNOWN" + + if message_num == 0 then + message_name = "HELLO" + elseif message_num == 1 then + message_name = "SET_STATION" + elseif message_num == 2 then + message_name = "WELCOME REPLY" + elseif message_num == 3 then + message_name = "ANNOUNCE REPLY" + elseif message_num == 4 then + message_name = "INVALID_COMMAND REPLY" + end + + return message_name +end + +local tcp_port = DissectorTable.get("tcp.port") +tcp_port:add(16800, snowcast_protocol) diff --git a/util/snowcast-dissector/install.sh b/util/snowcast-dissector/install.sh new file mode 100755 index 0000000..efd2341 --- /dev/null +++ b/util/snowcast-dissector/install.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -euo pipefail + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +TARGET=~/.config/wireshark/plugins + +main() { + mkdir -pv ${TARGET} + install -v -m644 ${SCRIPT_DIR}/cs168_snowcast.lua ${TARGET} +} + +main $@ diff --git a/util/tester/arm64/control_tester b/util/tester/arm64/control_tester new file mode 100755 index 0000000..5eebce7 Binary files /dev/null and b/util/tester/arm64/control_tester differ diff --git a/util/tester/arm64/server_tester b/util/tester/arm64/server_tester new file mode 100755 index 0000000..6694cfe Binary files /dev/null and b/util/tester/arm64/server_tester differ diff --git a/util/tester/control_tester b/util/tester/control_tester new file mode 100755 index 0000000..942e960 Binary files /dev/null and b/util/tester/control_tester differ diff --git a/util/tester/data/short_file b/util/tester/data/short_file new file mode 100644 index 0000000..cc198a1 Binary files /dev/null and b/util/tester/data/short_file differ diff --git a/util/tester/data/test.txt b/util/tester/data/test.txt new file mode 100644 index 0000000..e4f841e --- /dev/null +++ b/util/tester/data/test.txt @@ -0,0 +1,12 @@ +1234567 +1234567 +1234567 +1234567 +1234567 +1234567 +1234567 +1234567 +1234567 +1234567 +1234567 +1234567 \ No newline at end of file diff --git a/util/tester/server_tester b/util/tester/server_tester new file mode 100755 index 0000000..13063ec Binary files /dev/null and b/util/tester/server_tester differ diff --git a/util/update_from_stencil b/util/update_from_stencil new file mode 100755 index 0000000..6385b67 --- /dev/null +++ b/util/update_from_stencil @@ -0,0 +1,18 @@ +#!/bin/bash + +set -euo pipefail + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +REPO_DIR=$(realpath ${SCRIPT_DIR}/..) + +STENCIL_REPO=http://github.com/brown-csci1680/snowcast-template + +main() { + git remote rm stencil || true + git remote add stencil $STENCIL_REPO + + git pull stencil main +} + + +main $@ -- cgit v1.2.3-70-g09d2