1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
/*
* src/rcon.c
* (c) 2020 Jonas Gunz <himself@jonasgunz.de>
* License: MIT
*/
/*
* 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^2 Two null bytes
*
* sizeof int: 4B
* Little Endian
*
* LOGIN 3
* LOGINFAIL -1
* COMMAND 2
* RESPONSE 0
*/
#include "rcon.h"
static char* rcon_errors[] = {
"No Error.",
"Undefined Error.",
"Login Denied.",
"Buffer size incorrect.",
"Malformed packet recieved."
};
static int rcon_write_int ( char* _buffer, int _len, int32_t _data ) {
if ( _len < 4 )
return -1;
for (int i = 0; i < 4; i++)
_buffer[i] = (char)(_data >> (i*8));
return 4;
}
static int rcon_read_int ( char* _buffer, int _len, int32_t* _out ) {
if ( _len < 4 )
return -1;
*_out = 0;
for (int i = 0; i < 4; i++)
*_out |= (int32_t)((int32_t)_buffer[i] << (i*8));
return 4;
}
int rcon_parse_packet ( rcon_packet_t* _packet, char* _buffer, uint32_t _len ) {
if ( _len < 14 )
return -1;
int32_t bytecount = 0;
bytecount += rcon_read_int ( _buffer + bytecount, _len - bytecount, &_packet->length );
bytecount += rcon_read_int ( _buffer + bytecount, _len - bytecount, &_packet->id );
bytecount += rcon_read_int ( _buffer + bytecount, _len - bytecount, &_packet->type );
int32_t payload_len = _len - bytecount - 2;
_packet->payload_len = payload_len;
_packet->payload = malloc(payload_len);
memcpy ( _packet->payload, _buffer + bytecount, payload_len );
bytecount += payload_len;
bytecount += 2; // padding
//TODO check validity
return bytecount;
}
int rcon_construct_packet ( char* _buffer, uint32_t _len, rcon_packet_t* _packet ) {
if ( _len < RCON_SEND_PKGSIZE )
return -1; // Payload does not fit.
int32_t bytecount = 0;
_packet->length = _packet->payload_len + 10;
bytecount += rcon_write_int ( _buffer + bytecount, _len - bytecount, _packet->length );
bytecount += rcon_write_int ( _buffer + bytecount, _len - bytecount, _packet->id );
bytecount += rcon_write_int ( _buffer + bytecount, _len - bytecount, _packet->type );
memcpy ( _buffer + bytecount, _packet->payload, _packet->payload_len );
bytecount += _packet->payload_len;
memcpy ( _buffer + bytecount, "\0\0", 2);
bytecount += 2;
return bytecount;
}
char* rcon_strerror ( int _errno ) {
return _errno > 4 ? rcon_errors[1] : rcon_errors[_errno];
}
|