(* In the following post, all IP's, Ports and Passwords have been changed. Sorry about the formatting of this post, the editor doesn't seem to like new lines.)
Question: How do I store integers as signed 32bit little endian?
Background: Im attempting to use RCon to connect to a minecraft server in bash. So far the server shows the connection is being received but I can't get the packet formatted correctly. I can connect to the server using mcrcon and see the packets in wireshark but when I attempt using my bash script, the packet length, requestid and type values look wrong.
The following is some of my sources, trouble shooting data and my code which may help in answering the question.
Source: https://wiki.vg/RCON
Implementation of: https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
Server console:
[22:24:09 WARN]: Can't keep up! Is the server overloaded? Running 3190ms or 63 ticks behind
[22:24:23 INFO]: Rcon connection from: /164.256.8.10
[22:24:34 WARN]: Can't keep up! Is the server overloaded? Running 9961ms or 199 ticks behind
[22:24:55 WARN]: Can't keep up! Is the server overloaded? Running 2006ms or 40 ticks behind
[22:25:12 INFO]: Rcon connection from: /164.256.8.10
.
Code:
#!/bin/bash
# Length int Length of remainder of packet
# Request ID int Client-generated ID
# Type int 3 for login, 2 to run a command, 0 for a multi-packet response
# Payload byte[] ASCII text
# 2-byte pad byte, byte Two null bytes
# Connection details
RCON_HEADER=$(echo -e "\xff\xff\xff\xff")
HOST="192.168.0.173"
PORT=12345
LENGTH=0 # Length of packet
REQUESTID=$RANDOM
PASSWORD="$1"
RES=0
COM=2
AUTH=3
NULL="\0"
COMMAND=${@:2}
echo "command: $COMMAND"
## Packet Format as per docs
#Packet Size in Bytes
#Request ID any int
#Type as above
#Body null terminated ascii string
#Empty string null terminated
build_packet()
{
local TYPE="$1";
$([ "$TYPE" == "$AUTH" ]) && local BODY="$PASSWORD" || local BODY=$COMMAND;
local DATA="$REQUESTID$TYPE$BODY";
local LENGTH=${#DATA};
local PACKET="$LENGTH$DATA";
echo $PACKET;
}
send()
{
#local PACKET="$1"
echo "sending: $PACKET"
printf "$PACKET%s\0%s\0" >&5 &
}
read ()
{
LENGTH="$1"
RETURN=`dd bs=$1 count=1 <&5 2> /dev/null`
}
echo "trying to open socket"
# try to connect
if ! exec 5<> /dev/tcp/$HOST/$PORT; then
echo "`basename $0`: unable to connect to $HOST:$PORT"
exit 1
fi
echo "socket is open"
PACKET=$(build_packet $AUTH $PASSWORD);
echo "Command: $COMMAND"
echo "Packet: $PACKET"
send $PACKET
read 7
echo "RETURN: $RETURN"
PACKET=$(build_packet $COM $COMMAND);
echo "Command: $COMMAND"
echo "Packet: $PACKET"
send $PACKET
read 7
echo "RETURN: $RETURN"
.
Referenced Code: https://blog.chris007.de/using-bash-for-network-socket-operation/