summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-09 03:19:22 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-13 13:00:58 -0600
commit2eb287e707ed7efb8b77cb0fc9a90d7e24d06bc3 (patch)
tree03dd68b85cb6faf245b2422cc111dc6894bffe95
parent2a9d1f54758988ce23fbd1e9da4f0ad28c0edcbf (diff)
lib9p: srv: Implement p9p version negotiation
I've spent enough time thinking about how I would implement this that I should just get it out of my head and into the code.
-rw-r--r--lib9p/idl/2003-9P2000.p9p.9p2
-rw-r--r--lib9p/include/lib9p/srv.h11
-rw-r--r--lib9p/srv.c26
3 files changed, 38 insertions, 1 deletions
diff --git a/lib9p/idl/2003-9P2000.p9p.9p b/lib9p/idl/2003-9P2000.p9p.9p
index 3f6a524..1d1c307 100644
--- a/lib9p/idl/2003-9P2000.p9p.9p
+++ b/lib9p/idl/2003-9P2000.p9p.9p
@@ -27,7 +27,7 @@ from ./2002-9P2000.9p import *
# e.g. you replace syscall:`open()` with lib9pclient:`fsopen()`).
#
# "Unfortunately", programs in plan9port must deal both with 9P files
-# and native "Unix" files; and need to turn an 9P FID into a native
+# and native "Unix" files; and need to turn a 9P FID into a native
# file descriptor. To do this, the `9pserve` program and lib9pclient
# add an extension call to 9P2000: Topenfd/Ropenfd/fsopenfd().
#
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h
index 7109179..bb5efb9 100644
--- a/lib9p/include/lib9p/srv.h
+++ b/lib9p/include/lib9p/srv.h
@@ -145,11 +145,22 @@ LO_INTERFACE(lib9p_srv_dio);
CR_RPC_DECLARE(_lib9p_srv_reqch, struct lib9p_srv_ctx *, bool);
+#if CONFIG_9P_ENABLE_9P2000_p9p
+#define net_stream_conn_unix_LO_IFACE \
+ LO_NEST(net_stream_conn) \
+ /** Returns 0 on success, -errno on error. */ \
+ LO_FUNC(int, send_unix_fd, int fd)
+LO_INTERFACE(net_stream_conn_unix);
+#endif
+
struct lib9p_srv {
/* Things you provide */
void /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */
lo_interface lib9p_srv_file (*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename);
void (*msglog )(struct lib9p_srv_ctx *, enum lib9p_msg_type, void *hostmsg); /* optional */
+#if CONFIG_9P_ENABLE_9P2000_p9p
+ lo_interface net_stream_conn_unix (*type_assert_unix)(lo_interface net_stream_conn); /* optional */
+#endif
/* For internal use */
BEGIN_PRIVATE(LIB9P_SRV_H);
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 50e5dae..0a33e03 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -599,6 +599,9 @@ _HANDLER_PROTO(clunk);
_HANDLER_PROTO(remove);
_HANDLER_PROTO(stat);
_HANDLER_PROTO(wstat);
+#if CONFIG_9P_ENABLE_9P2000_p9p
+_HANDLER_PROTO(openfd);
+#endif
#if CONFIG_9P_ENABLE_9P2000_e
_HANDLER_PROTO(session);
_HANDLER_PROTO(sread);
@@ -621,6 +624,9 @@ static tmessage_handler tmessage_handlers[0x100] = {
[LIB9P_TYP_Tremove] = (tmessage_handler)handle_Tremove,
[LIB9P_TYP_Tstat] = (tmessage_handler)handle_Tstat,
[LIB9P_TYP_Twstat] = (tmessage_handler)handle_Twstat,
+#if CONFIG_9P_ENABLE_9P2000_p9p
+ [LIB9P_TYP_Topenfd] = (tmessage_handler)handle_Topenfd,
+#endif
#if CONFIG_9P_ENABLE_9P2000_e
[LIB9P_TYP_Tsession] = (tmessage_handler)handle_Tsession,
[LIB9P_TYP_Tsread] = (tmessage_handler)handle_Tsread,
@@ -688,6 +694,11 @@ static void handle_Tversion(struct srv_req *ctx,
'0' <= req->version.utf8[5] && req->version.utf8[5] <= '9' &&
(req->version.len == 6 || req->version.utf8[6] == '.')) {
version = LIB9P_VER_9P2000;
+#if CONFIG_9P_ENABLE_9P2000_p9p
+ struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv;
+ if (srv->type_assert_unix && !LO_IS_NULL(srv->type_assert_unix(ctx->parent_sess->parent_conn->fd)))
+ version = LIB9P_VER_9P2000_p9p;
+#endif
#if CONFIG_9P_ENABLE_9P2000_u
if (lib9p_str_eq(lib9p_str_sliceleft(req->version, 6), lib9p_str(".u")))
version = LIB9P_VER_9P2000_u;
@@ -707,6 +718,10 @@ static void handle_Tversion(struct srv_req *ctx,
}
resp->version = lib9p_str((char *)lib9p_version_str(version)); /* cast to discard "const" qualifier */
+#if CONFIG_9P_ENABLE_9P2000_p9p
+ if (version == LIB9P_VER_9P2000_p9p)
+ resp->version = lib9p_str("9P2000");
+#endif
resp->max_msg_size = (CONFIG_9P_SRV_MAX_MSG_SIZE < req->max_msg_size)
? CONFIG_9P_SRV_MAX_MSG_SIZE
: req->max_msg_size;
@@ -1223,6 +1238,17 @@ static void handle_Twstat(struct srv_req *ctx,
LINUX_EOPNOTSUPP, "wstat not (yet?) implemented");
}
+#if CONFIG_9P_ENABLE_9P2000_p9p
+static void handle_Topenfd(struct srv_req *ctx,
+ struct lib9p_msg_Topenfd *req,
+ struct lib9p_msg_Ropenfd *resp) {
+ srv_handler_common(ctx, req, resp);
+
+ lib9p_error(&ctx->basectx,
+ LINUX_EOPNOTSUPP, "openfd not (yet?) implemented");
+}
+#endif
+
#if CONFIG_9P_ENABLE_9P2000_e
static void handle_Tsession(struct srv_req *ctx,
struct lib9p_msg_Tsession *req,