summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--minecctl/rcon-commands.c34
-rw-r--r--minecproxy/server-rcon.c36
-rw-r--r--shared/rcon-protocol.c29
-rw-r--r--shared/rcon-protocol.h16
4 files changed, 62 insertions, 53 deletions
diff --git a/minecctl/rcon-commands.c b/minecctl/rcon-commands.c
index dfe8647..be18bba 100644
--- a/minecctl/rcon-commands.c
+++ b/minecctl/rcon-commands.c
@@ -69,10 +69,11 @@ static void read_packet(int sfd, char *buf, size_t len, int32_t *id,
}
static void send_msg(int sfd, char *buf, size_t len, enum rcon_packet_type type,
- const char *msg, enum rcon_packet_type *rtype,
+ const char *msg, int32_t *rtype,
const char **reply)
{
static uint32_t rcon_packet_id = 1;
+ const char *error;
size_t plen;
int32_t id;
@@ -84,25 +85,17 @@ static void send_msg(int sfd, char *buf, size_t len, enum rcon_packet_type type,
read_packet(sfd, buf, len, &id, rtype, reply);
- /* FIXME: this should be shared */
- if (type == RCON_PACKET_LOGIN) {
- if (*rtype != RCON_PACKET_LOGIN_OK)
- die("Invalid reply id");
-
- if (id == RCON_PACKET_LOGIN_FAIL)
- *rtype = RCON_PACKET_LOGIN_FAIL;
- else if (id != rcon_packet_id)
- die("Invalid reply id");
- } else {
- if (id != rcon_packet_id)
- die("Invalid reply");
- }
+ /* FIXME: Shouldn't die */
+ if (!rcon_protocol_verify_response(rcon_packet_id, id, type,
+ *rtype, &error))
+ die("Invalid response: %s", error);
rcon_packet_id++;
}
static int rcon_login(struct cfg *cfg, struct server *server)
{
+ const char *error;
char buf[4096];
int32_t rtype;
const char *reply;
@@ -135,15 +128,12 @@ static int rcon_login(struct cfg *cfg, struct server *server)
explicit_bzero(buf, sizeof(buf));
free_password(&server->scfg.rcon_password);
- if (rtype == RCON_PACKET_LOGIN_OK)
- verbose("%s: login ok", server->name);
- else if (rtype == RCON_PACKET_LOGIN_FAIL) {
- info("%s: login failure, invalid password?", server->name);
+ if (!rcon_protocol_verify_response(1, 1, RCON_PACKET_LOGIN,
+ rtype, &error)) {
+ error("%s: invalid response - %s", server->name, error);
goto error;
- } else {
- error("%s: invalid return code: %" PRIi32, server->name, rtype);
- goto error;
- }
+ } else
+ verbose("%s: login ok", server->name);
return fd;
diff --git a/minecproxy/server-rcon.c b/minecproxy/server-rcon.c
index 1f3acfa..4c9da48 100644
--- a/minecproxy/server-rcon.c
+++ b/minecproxy/server-rcon.c
@@ -55,7 +55,7 @@ static void rcon_stop_reply(struct uring_task *task, int res)
struct server *server = container_of(task, struct server, rcon_task);
int32_t id;
int32_t type;
- const char *msg;
+ const char *msg, *error;
assert_return(task);
assert_task_alive(DBG_RCON, task);
@@ -63,19 +63,13 @@ static void rcon_stop_reply(struct uring_task *task, int res)
if (!rcon_check_reply(task, res, &id, &type, &msg))
return;
- if (id != 2) {
- error("rcon(%s): stop cmd failed, reply id (%" PRIi32 ")",
- server->name, id);
- goto out;
- } else if (type != RCON_PACKET_RESPONSE) {
- error("rcon(%s): stop cmd failed, reply type (%" PRIi32 ")",
- server->name, type);
- goto out;
- }
-
- verbose("rcon(%s): stop command sent, reply: %s", server->name, msg);
+ if (!rcon_protocol_verify_response(2, id, RCON_PACKET_COMMAND, type,
+ &error))
+ error("rcon(%s): stop cmd failed - %s", server->name, error);
+ else
+ verbose("rcon(%s): stop command sent, reply: %s",
+ server->name, msg);
-out:
uring_task_close_fd(task);
}
@@ -102,7 +96,7 @@ static void rcon_login_reply(struct uring_task *task, int res)
struct server *server = container_of(task, struct server, rcon_task);
int32_t id;
int32_t type;
- const char *msg;
+ const char *msg, *error;
assert_return(task);
assert_task_alive(DBG_RCON, task);
@@ -110,17 +104,9 @@ static void rcon_login_reply(struct uring_task *task, int res)
if (!rcon_check_reply(task, res, &id, &type, &msg))
return;
- if (id != 1) {
- error("rcon(%s): login failed, reply id (%" PRIi32 ")",
- server->name, id);
- goto error;
- } else if (type == RCON_PACKET_LOGIN_FAIL) {
- error("rcon(%s): login failed, incorrect password",
- server->name);
- goto error;
- } else if (type != RCON_PACKET_LOGIN_OK) {
- error("rcon(%s): login failed, reply type (%" PRIi32 ")",
- server->name, type);
+ if (!rcon_protocol_verify_response(1, id, RCON_PACKET_LOGIN, type,
+ &error)) {
+ error("rcon(%s): login failed - %s", server->name, error);
goto error;
}
diff --git a/shared/rcon-protocol.c b/shared/rcon-protocol.c
index 0cf73fc..1941662 100644
--- a/shared/rcon-protocol.c
+++ b/shared/rcon-protocol.c
@@ -75,6 +75,35 @@ static void write_end(char **pos, size_t *len)
*len += RCON_END_LEN;
}
+bool rcon_protocol_verify_response(int32_t id_sent, int32_t id_recv,
+ enum rcon_packet_type t_sent,
+ enum rcon_packet_type t_recv,
+ const char **error)
+{
+ if (t_sent == RCON_PACKET_LOGIN) {
+ if (t_recv != RCON_PACKET_LOGIN_RESPONSE) {
+ *error = "invalid reply id";
+ return false;
+ } else if (id_recv == RCON_PACKET_LOGIN_FAIL_ID) {
+ *error = "login failure";
+ return false;
+ } else if (id_recv != id_sent) {
+ *error = "invalid reply id";
+ return false;
+ }
+ } else {
+ if (t_recv != RCON_PACKET_RESPONSE) {
+ *error = "invalid reply type";
+ return false;
+ } else if (id_recv != id_sent) {
+ *error = "invalid reply id";
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool rcon_protocol_create_packet(char *buf, size_t len, size_t *rlen,
int32_t reqid, enum rcon_packet_type type,
const char *msg)
diff --git a/shared/rcon-protocol.h b/shared/rcon-protocol.h
index b3aea98..593a43f 100644
--- a/shared/rcon-protocol.h
+++ b/shared/rcon-protocol.h
@@ -4,14 +4,13 @@
#include <stdbool.h>
#include <stdint.h>
-/* FIXME: FAIL is an id, not type, LOGIN_OK should be LOGIN_RESPONSE */
/* clang-format off */
+#define RCON_PACKET_LOGIN_FAIL_ID -1
enum rcon_packet_type {
- RCON_PACKET_LOGIN = 3,
- RCON_PACKET_LOGIN_OK = 2,
- RCON_PACKET_LOGIN_FAIL = -1,
- RCON_PACKET_COMMAND = 2,
- RCON_PACKET_RESPONSE = 0,
+ RCON_PACKET_LOGIN = 3,
+ RCON_PACKET_LOGIN_RESPONSE = 2,
+ RCON_PACKET_COMMAND = 2,
+ RCON_PACKET_RESPONSE = 0,
};
/* clang-format on */
@@ -30,6 +29,11 @@ static inline size_t rcon_protocol_packet_len(size_t msglen)
return (RCON_PKT_MIN_LEN + msglen);
}
+bool rcon_protocol_verify_response(int32_t id_sent, int32_t id_recv,
+ enum rcon_packet_type t_sent,
+ enum rcon_packet_type t_recv,
+ const char **error);
+
bool rcon_protocol_create_packet(char *buf, size_t len, size_t *rlen,
int32_t reqid, enum rcon_packet_type type,
const char *msg);