Various fixes for package de/serialization #9
@@ -1,6 +1,6 @@
|
||||
CC = cc
|
||||
|
||||
CFLAGS = -std=c17
|
||||
CFLAGS = -std=gnu23
|
||||
CFLAGS_WARNINGS = -Wall -Wextra
|
||||
CFLAGS_RELEASE = -O2 -fstack-protector-strong -fpie -s
|
||||
CFLAGS_DEBUG = -O0 -ggdb -DDEBUG -fsanitize=address -static-libasan
|
||||
|
||||
+34
-20
@@ -1,3 +1,4 @@
|
||||
#include <endian.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -17,12 +18,22 @@ const char *LOCALHOST = "127.0.0.1";
|
||||
#define SERVERDATA_RESPONSE_VALUE 0
|
||||
|
||||
typedef struct {
|
||||
// size of the remainder of the packet
|
||||
int32_t size;
|
||||
// packet id (client sets, server echoes, -1 on auth failure)
|
||||
int32_t id;
|
||||
// packet type (see the SERVERDATA_* constants)
|
||||
int32_t type;
|
||||
// null-terminated command string (for auth and exec) or response string (from server)
|
||||
char body[4096];
|
||||
// yet another null byte after the body (required by protocol)
|
||||
uint8_t _padding;
|
||||
} rcon_packet_t;
|
||||
|
||||
// Minimum and maximum values for the `size` field of a valid packet.
|
||||
#define MIN_SIZE (sizeof(int32_t) * 2 + 2)
|
||||
#define MAX_SIZE (sizeof(rcon_packet_t) - sizeof(int32_t))
|
||||
|
||||
int read_env_int(const char *var) {
|
||||
const char* port_str = getenv(var);
|
||||
if (port_str == NULL) {
|
||||
@@ -72,34 +83,27 @@ int rcon_connect(int port) {
|
||||
}
|
||||
|
||||
void send_packet(int sockfd, int32_t id, int32_t type, const char *body) {
|
||||
int body_len = strlen(body);
|
||||
int32_t size = 10 + body_len;
|
||||
size_t body_len = strlen(body);
|
||||
|
||||
size_t packet_size = sizeof(int32_t) + size;
|
||||
size_t packet_size = sizeof(int32_t) * 3 + body_len + 2;
|
||||
unsigned char *packet = malloc(packet_size);
|
||||
if (!packet) {
|
||||
perror("malloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
packet[0] = size & 0xFF;
|
||||
packet[1] = (size >> 8) & 0xFF;
|
||||
packet[2] = (size >> 16) & 0xFF;
|
||||
packet[3] = (size >> 24) & 0xFF;
|
||||
int32_t size = htole32(packet_size - sizeof(int32_t));
|
||||
memcpy(packet, &size, sizeof(int32_t));
|
||||
|
||||
packet[4] = id & 0xFF;
|
||||
packet[5] = (id >> 8) & 0xFF;
|
||||
packet[6] = (id >> 16) & 0xFF;
|
||||
packet[7] = (id >> 24) & 0xFF;
|
||||
int32_t id_ = htole32(id);
|
||||
memcpy(packet + 4, &id_, sizeof(int32_t));
|
||||
|
||||
packet[8] = type & 0xFF;
|
||||
packet[9] = (type >> 8) & 0xFF;
|
||||
packet[10] = (type >> 16) & 0xFF;
|
||||
packet[11] = (type >> 24) & 0xFF;
|
||||
int32_t type_ = htole32(type);
|
||||
memcpy(packet + 8, &type_, sizeof(int32_t));
|
||||
|
||||
memcpy(packet + 12, body, body_len);
|
||||
packet[12 + body_len] = 0;
|
||||
packet[12 + body_len + 1] = 0;
|
||||
packet[3 * sizeof(int32_t) + body_len] = 0;
|
||||
packet[3 * sizeof(int32_t) + body_len + 1] = 0;
|
||||
|
||||
ssize_t sent = send(sockfd, packet, packet_size, 0);
|
||||
if (sent < 0) {
|
||||
@@ -123,8 +127,9 @@ int recv_packet(int sockfd, rcon_packet_t *packet) {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
packet->size = le32toh(packet->size);
|
||||
|
||||
if (packet->size < 10 || packet->size > 4110) {
|
||||
if (packet->size < (int32_t)MIN_SIZE || packet->size > (int32_t)MAX_SIZE) {
|
||||
fprintf(stderr, "invalid packet size: %d\n", packet->size);
|
||||
return -1;
|
||||
}
|
||||
@@ -134,22 +139,31 @@ int recv_packet(int sockfd, rcon_packet_t *packet) {
|
||||
perror("recv id failed");
|
||||
return -1;
|
||||
}
|
||||
packet->id = le32toh(packet->id);
|
||||
|
||||
bytes = recv(sockfd, &packet->type, sizeof(int32_t), MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv type failed");
|
||||
return -1;
|
||||
}
|
||||
packet->type = le32toh(packet->type);
|
||||
|
||||
int body_size = packet->size - 10;
|
||||
int body_size = packet->size - sizeof(int32_t) * 2 - 2;
|
||||
if (body_size > 0 && body_size < (int)sizeof(packet->body)) {
|
||||
bytes = recv(sockfd, packet->body, body_size + 2, MSG_WAITALL);
|
||||
bytes = recv(sockfd, packet->body, body_size, MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv body failed");
|
||||
return -1;
|
||||
}
|
||||
packet->body[body_size] = '\0';
|
||||
|
||||
bytes = recv(sockfd, &packet->_padding, 1, MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv padding failed");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
packet->size = sizeof(int32_t) * 2 + 2;
|
||||
packet->body[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user