summaryrefslogtreecommitdiff
path: root/lib9p/9p.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/9p.c')
-rw-r--r--lib9p/9p.c97
1 files changed, 73 insertions, 24 deletions
diff --git a/lib9p/9p.c b/lib9p/9p.c
index a3d81d0..ecb75fd 100644
--- a/lib9p/9p.c
+++ b/lib9p/9p.c
@@ -1,6 +1,6 @@
/* lib9p/9p.c - Base 9P protocol utilities for both clients and servers
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -9,6 +9,9 @@
#include <stdio.h> /* for vsnprintf() */
#include <string.h> /* for strncpy() */
+#define LOG_NAME 9P
+#include <libmisc/log.h> /* for const_byte_str() */
+
#include <lib9p/9p.h>
#include "internal.h"
@@ -69,12 +72,16 @@ const char *lib9p_msg_type_str(struct lib9p_ctx *ctx, enum lib9p_msg_type typ) {
#pragma GCC diagnostic ignored "-Wtype-limits"
assert(0 <= typ && typ <= 0xFF);
#pragma GCC diagnostic pop
- return _lib9p_versions[ctx->version].msgs[typ].name;
+ return _lib9p_table_msg_name[ctx->version][typ] ?: const_byte_str(typ);
}
/* main message functions *****************************************************/
-ssize_t lib9p_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
+static
+ssize_t _lib9p_validate(uint8_t xxx_low_typ_bit,
+ const char *xxx_errmsg,
+ const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0x80],
+ struct lib9p_ctx *ctx, uint8_t *net_bytes) {
/* Inspect the first 5 bytes ourselves. */
struct _validate_ctx subctx = {
.ctx = ctx,
@@ -87,13 +94,16 @@ ssize_t lib9p_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
if (subctx.net_size < 5)
return lib9p_error(ctx, LINUX_EBADMSG, "message is impossibly short");
uint8_t typ = net_bytes[4];
- struct _table_msg table = _lib9p_versions[ctx->version].msgs[typ];
- if (!table.validate)
+ if (typ % 2 != xxx_low_typ_bit)
+ return lib9p_errorf(ctx, LINUX_EOPNOTSUPP, "%s: message_type=%s", xxx_errmsg,
+ lib9p_msg_type_str(ctx, typ));
+ struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
+ if (!tentry.validate)
return lib9p_errorf(ctx, LINUX_EOPNOTSUPP, "unknown message type: %s (protocol_version=%s)",
lib9p_msg_type_str(ctx, typ), lib9p_version_str(ctx->version));
- /* Now use the message-type-specific table to process the whole thing. */
- if (table.validate(&subctx))
+ /* Now use the message-type-specific tentry to process the whole thing. */
+ if (tentry.validate(&subctx))
return -1;
assert(subctx.net_offset <= subctx.net_size);
if (subctx.net_offset < subctx.net_size)
@@ -102,13 +112,25 @@ ssize_t lib9p_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
/* Return. */
ssize_t ret;
- if (__builtin_add_overflow(table.basesize, subctx.host_extra, &ret))
+ if (__builtin_add_overflow(tentry.basesize, subctx.host_extra, &ret))
return lib9p_error(ctx, LINUX_EMSGSIZE, "unmarshalled payload overflows SSIZE_MAX");
return ret;
}
-void lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
- enum lib9p_msg_type *ret_typ, void *ret_body) {
+ssize_t lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
+ return _lib9p_validate(0, "expected a T-message but got an R-message", _lib9p_table_Tmsg_recv,
+ ctx, net_bytes);
+}
+
+ssize_t lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
+ return _lib9p_validate(1, "expected an R-message but got a T-message", _lib9p_table_Rmsg_recv,
+ ctx, net_bytes);
+}
+
+static
+void _lib9p_unmarshal(const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0x80],
+ struct lib9p_ctx *ctx, uint8_t *net_bytes,
+ enum lib9p_msg_type *ret_typ, void *ret_body) {
struct _unmarshal_ctx subctx = {
.ctx = ctx,
.net_bytes = net_bytes,
@@ -116,27 +138,54 @@ void lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
.net_offset = 0,
};
- *ret_typ = net_bytes[4];
- struct _table_msg table = _lib9p_versions[ctx->version].msgs[*ret_typ];
- subctx.extra = ret_body + table.basesize;
- table.unmarshal(&subctx, ret_body);
+ enum lib9p_msg_type typ = net_bytes[4];
+ *ret_typ = typ;
+ struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
+ subctx.extra = ret_body + tentry.basesize;
+ tentry.unmarshal(&subctx, ret_body);
+}
+
+void lib9p_Tmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
+ enum lib9p_msg_type *ret_typ, void *ret_body) {
+ _lib9p_unmarshal(_lib9p_table_Tmsg_recv,
+ ctx, net_bytes, ret_typ, ret_body);
}
-bool lib9p_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
- uint8_t *ret_bytes) {
+void lib9p_Rmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
+ enum lib9p_msg_type *ret_typ, void *ret_body) {
+ _lib9p_unmarshal(_lib9p_table_Rmsg_recv,
+ ctx, net_bytes, ret_typ, ret_body);
+}
+
+static
+bool _lib9p_marshal(const struct _lib9p_send_tentry xxx_table[LIB9P_VER_NUM][0x80],
+ struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
+ uint8_t *ret_bytes) {
struct _marshal_ctx subctx = {
.ctx = ctx,
.net_bytes = ret_bytes,
.net_offset = 0,
};
- struct _table_msg table = _lib9p_versions[ctx->version].msgs[typ];
- return table.marshal(&subctx, body);
+ struct _lib9p_send_tentry tentry = xxx_table[ctx->version][typ/2];
+ return tentry.marshal(&subctx, body);
+}
+
+bool lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
+ uint8_t *ret_bytes) {
+ assert(typ % 2 == 0);
+ return _lib9p_marshal(_lib9p_table_Tmsg_send, ctx, typ, body, ret_bytes);
+}
+
+bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
+ uint8_t *ret_bytes) {
+ assert(typ % 2 == 1);
+ return _lib9p_marshal(_lib9p_table_Rmsg_send, ctx, typ, body, ret_bytes);
}
/* `struct lib9p_stat` helpers ************************************************/
-bool lib9p_validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes,
+bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes,
uint32_t *ret_net_size, ssize_t *ret_host_size) {
struct _validate_ctx subctx = {
.ctx = ctx,
@@ -146,7 +195,7 @@ bool lib9p_validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_
.net_offset = 0,
.host_extra = 0,
};
- if (_lib9p_validate_stat(&subctx))
+ if (_lib9p_stat_validate(&subctx))
return true;
if (ret_net_size)
*ret_net_size = subctx.net_offset;
@@ -156,7 +205,7 @@ bool lib9p_validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_
return false;
}
-uint32_t lib9p_unmarshal_stat(struct lib9p_ctx *ctx, uint8_t *net_bytes,
+uint32_t lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
struct lib9p_stat *ret_obj, void *ret_extra) {
struct _unmarshal_ctx subctx = {
.ctx = ctx,
@@ -165,11 +214,11 @@ uint32_t lib9p_unmarshal_stat(struct lib9p_ctx *ctx, uint8_t *net_bytes,
.extra = ret_extra,
};
- _lib9p_unmarshal_stat(&subctx, ret_obj);
+ _lib9p_stat_unmarshal(&subctx, ret_obj);
return subctx.net_offset;
}
-uint32_t lib9p_marshal_stat(struct lib9p_ctx *ctx, uint32_t max_net_size, struct lib9p_stat *obj,
+uint32_t lib9p_stat_marshal(struct lib9p_ctx *ctx, uint32_t max_net_size, struct lib9p_stat *obj,
uint8_t *ret_bytes) {
struct lib9p_ctx _ctx = *ctx;
_ctx.max_msg_size = max_net_size;
@@ -178,7 +227,7 @@ uint32_t lib9p_marshal_stat(struct lib9p_ctx *ctx, uint32_t max_net_size, struct
.net_bytes = ret_bytes,
.net_offset = 0,
};
- if (_lib9p_marshal_stat(&subctx, obj))
+ if (_lib9p_stat_marshal(&subctx, obj))
return 0;
return subctx.net_offset;
}