From 3dad09b228e3c4a4ffa6da260fadda6762a77c58 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Tue, 11 Jun 2024 05:08:49 -0400 Subject: [PATCH] mgmtd: add native session-req (create/delete) messages This addition allows for a limited native-message-only front-end interaction. Signed-off-by: Christian Hopps --- lib/mgmt_msg_native.c | 27 +++++++++ lib/mgmt_msg_native.h | 45 ++++++++++++++- mgmtd/mgmt_fe_adapter.c | 124 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 1 deletion(-) diff --git a/lib/mgmt_msg_native.c b/lib/mgmt_msg_native.c index d0a0b72189ba..b85c7d1b6182 100644 --- a/lib/mgmt_msg_native.c +++ b/lib/mgmt_msg_native.c @@ -19,6 +19,33 @@ DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT, "native edit msg"); DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT_REPLY, "native edit reply msg"); DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_RPC, "native RPC msg"); DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_RPC_REPLY, "native RPC reply msg"); +DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_SESSION_REQ, "native session-req msg"); +DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_SESSION_REPLY, "native session-reply msg"); + + +size_t mgmt_msg_min_sizes[] = { + [MGMT_MSG_CODE_ERROR] = sizeof(struct mgmt_msg_error), + [MGMT_MSG_CODE_GET_TREE] = sizeof(struct mgmt_msg_get_tree), + [MGMT_MSG_CODE_TREE_DATA] = sizeof(struct mgmt_msg_tree_data), + [MGMT_MSG_CODE_GET_DATA] = sizeof(struct mgmt_msg_get_data), + [MGMT_MSG_CODE_NOTIFY] = sizeof(struct mgmt_msg_notify_data), + [MGMT_MSG_CODE_EDIT] = sizeof(struct mgmt_msg_edit), + [MGMT_MSG_CODE_EDIT_REPLY] = sizeof(struct mgmt_msg_edit_reply), + [MGMT_MSG_CODE_RPC] = sizeof(struct mgmt_msg_rpc), + [MGMT_MSG_CODE_RPC_REPLY] = sizeof(struct mgmt_msg_rpc_reply), + [MGMT_MSG_CODE_NOTIFY_SELECT] = sizeof(struct mgmt_msg_notify_select), + [MGMT_MSG_CODE_SESSION_REQ] = sizeof(struct mgmt_msg_session_req), + [MGMT_MSG_CODE_SESSION_REPLY] = sizeof(struct mgmt_msg_session_reply), +}; +size_t nmgmt_msg_min_sizes = sizeof(mgmt_msg_min_sizes) / + sizeof(*mgmt_msg_min_sizes); + +size_t mgmt_msg_get_min_size(uint code) +{ + if (code >= nmgmt_msg_min_sizes) + return 0; + return mgmt_msg_min_sizes[code]; +} int vmgmt_msg_native_send_error(struct msg_conn *conn, uint64_t sess_or_txn_id, uint64_t req_id, bool short_circuit_ok, diff --git a/lib/mgmt_msg_native.h b/lib/mgmt_msg_native.h index e61346e6e5d5..76a52658cdee 100644 --- a/lib/mgmt_msg_native.h +++ b/lib/mgmt_msg_native.h @@ -163,6 +163,8 @@ DECLARE_MTYPE(MSG_NATIVE_EDIT); DECLARE_MTYPE(MSG_NATIVE_EDIT_REPLY); DECLARE_MTYPE(MSG_NATIVE_RPC); DECLARE_MTYPE(MSG_NATIVE_RPC_REPLY); +DECLARE_MTYPE(MSG_NATIVE_SESSION_REQ); +DECLARE_MTYPE(MSG_NATIVE_SESSION_REPLY); /* * Native message codes @@ -177,6 +179,8 @@ DECLARE_MTYPE(MSG_NATIVE_RPC_REPLY); #define MGMT_MSG_CODE_RPC 7 /* Public API */ #define MGMT_MSG_CODE_RPC_REPLY 8 /* Public API */ #define MGMT_MSG_CODE_NOTIFY_SELECT 9 /* Public API */ +#define MGMT_MSG_CODE_SESSION_REQ 10 /* Public API */ +#define MGMT_MSG_CODE_SESSION_REPLY 11 /* Public API */ /* * Datastores @@ -434,7 +438,7 @@ _Static_assert(sizeof(struct mgmt_msg_rpc_reply) == * to the front-end client. * * @selectors: the xpath prefixes to selectors notifications through. - * @repalce: if true replace existing selectors with `selectors`. + * @replace: if true replace existing selectors with `selectors`. */ struct mgmt_msg_notify_select { struct mgmt_msg_header; @@ -448,12 +452,51 @@ _Static_assert(sizeof(struct mgmt_msg_notify_select) == offsetof(struct mgmt_msg_notify_select, selectors), "Size mismatch"); +/** + * struct mgmt_msg_session_req - Create or delete a front-end session. + * + * @refer_id: Zero for create, otherwise the session-id to delete. + * @req_id: For create will use as client-id. + * @client_name: For first session request the client name, otherwise empty. + */ +struct mgmt_msg_session_req { + struct mgmt_msg_header; + uint8_t resv2[8]; /* bug in compiler produces error w/o this */ + + alignas(8) char client_name[]; +}; + +_Static_assert(sizeof(struct mgmt_msg_session_req) == + offsetof(struct mgmt_msg_session_req, client_name), + "Size mismatch"); + +/** + * struct mgmt_msg_session_reply - Reply to session request message. + * + * @created: true if this is a reply to a create request, otherwise 0. + * @refer_id: The session-id for the action (create or delete) just taken. + */ +struct mgmt_msg_session_reply { + struct mgmt_msg_header; + uint8_t created; + uint8_t resv2[7]; +}; + /* * Validate that the message ends in a NUL terminating byte */ #define MGMT_MSG_VALIDATE_NUL_TERM(msgp, len) \ ((len) >= sizeof(*msgp) + 1 && ((char *)msgp)[(len)-1] == 0) +/** + * mgmt_msg_get_min_size() - Get minimum message size given the type + * @code: The type of the message (MGMT_MSG_CODE_*) + * + * Return: + * The minimum size of a message of the given type or 0 if the message + * code is unknown. + */ +size_t mgmt_msg_get_min_size(uint code); /** * Send a native message error to the other end of the connection. diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c index a076dc72f96b..5f53c928a47e 100644 --- a/mgmtd/mgmt_fe_adapter.c +++ b/mgmtd/mgmt_fe_adapter.c @@ -490,6 +490,26 @@ static int fe_adapter_send_get_reply(struct mgmt_fe_session_ctx *session, return fe_adapter_send_msg(session->adapter, &fe_msg, false); } +static int fe_adapter_conn_send_error(struct msg_conn *conn, + uint64_t session_id, uint64_t req_id, + bool short_circuit_ok, int16_t error, + const char *errfmt, ...) PRINTFRR(6, 7); +static int fe_adapter_conn_send_error(struct msg_conn *conn, uint64_t session_id, + uint64_t req_id, bool short_circuit_ok, + int16_t error, const char *errfmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, errfmt); + + ret = vmgmt_msg_native_send_error(conn, session_id, req_id, + short_circuit_ok, error, errfmt, ap); + va_end(ap); + + return ret; +} + static int fe_adapter_send_error(struct mgmt_fe_session_ctx *session, uint64_t req_id, bool short_circuit_ok, int16_t error, const char *errfmt, ...) @@ -1170,6 +1190,88 @@ static int fe_adapter_send_edit_reply(struct mgmt_fe_session_ctx *session, return ret; } +static int +fe_adapter_native_send_session_reply(struct mgmt_fe_client_adapter *adapter, + uint64_t req_id, uint64_t session_id, + bool created) +{ + struct mgmt_msg_session_reply *msg; + int ret; + + msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_session_reply, 0, + MTYPE_MSG_NATIVE_SESSION_REPLY); + msg->refer_id = session_id; + msg->req_id = req_id; + msg->code = MGMT_MSG_CODE_SESSION_REPLY; + msg->created = created; + + __dbg("Sending session-reply from adapter %s to session-id %" PRIu64 + " req-id %" PRIu64 " len %u", + adapter->name, session_id, req_id, + mgmt_msg_native_get_msg_len(msg)); + + ret = fe_adapter_send_native_msg(adapter, msg, + mgmt_msg_native_get_msg_len(msg), + false); + mgmt_msg_native_free_msg(msg); + + return ret; +} + +/** + * fe_adapter_handle_session_req() - Handle a session-req message from a FE client. + * @msg_raw: the message data. + * @msg_len: the length of the message data. + */ +static void fe_adapter_handle_session_req(struct mgmt_fe_client_adapter *adapter, + void *__msg, size_t msg_len) +{ + struct mgmt_msg_session_req *msg = __msg; + struct mgmt_fe_session_ctx *session; + uint64_t client_id; + + __dbg("Got session-req creating: %u for refer-id %" PRIu64 " from '%s'", + msg->refer_id == 0, msg->refer_id, adapter->name); + + if (msg->refer_id) { + uint64_t session_id = msg->refer_id; + + session = mgmt_session_id2ctx(session_id); + if (!session) { + fe_adapter_conn_send_error( + adapter->conn, session_id, msg->req_id, false, + -EINVAL, + "No session to delete for session-id: %" PRIu64, + session_id); + return; + } + fe_adapter_native_send_session_reply(adapter, msg->req_id, + session_id, false); + mgmt_fe_cleanup_session(&session); + return; + } + + client_id = msg->req_id; + + /* See if we have a client name to register */ + if (msg_len > sizeof(*msg)) { + if (!MGMT_MSG_VALIDATE_NUL_TERM(msg, msg_len)) { + fe_adapter_conn_send_error( + adapter->conn, client_id, msg->req_id, false, + -EINVAL, + "Corrupt session-req message rcvd from client-id: %" PRIu64, + client_id); + return; + } + __dbg("Set client-name to '%s'", msg->client_name); + strlcpy(adapter->name, msg->client_name, sizeof(adapter->name)); + } + + session = mgmt_fe_create_session(adapter, client_id); + fe_adapter_native_send_session_reply(adapter, client_id, + session->session_id, true); +} + /** * fe_adapter_handle_get_data() - Handle a get-tree message from a FE client. * @session: the client session. @@ -1529,6 +1631,28 @@ static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter, size_t msg_len) { struct mgmt_fe_session_ctx *session; + size_t min_size = mgmt_msg_get_min_size(msg->code); + + if (msg_len < min_size) { + if (!min_size) + __log_err("adapter %s: recv msg refer-id %" PRIu64 + " unknown message type %u", + adapter->name, msg->refer_id, msg->code); + else + __log_err("adapter %s: recv msg refer-id %" PRIu64 + " short (%zu<%zu) msg for type %u", + adapter->name, msg->refer_id, msg_len, + min_size, msg->code); + return; + } + + if (msg->code == MGMT_MSG_CODE_SESSION_REQ) { + __dbg("adapter %s: session-id %" PRIu64 + " received SESSION_REQ message", + adapter->name, msg->refer_id); + fe_adapter_handle_session_req(adapter, msg, msg_len); + return; + } session = mgmt_session_id2ctx(msg->refer_id); if (!session) {