summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Hopps <chopps@labn.net>2024-06-11 11:08:49 +0200
committerChristian Hopps <chopps@labn.net>2024-06-11 16:37:31 +0200
commit3dad09b228e3c4a4ffa6da260fadda6762a77c58 (patch)
tree75c36cc0a1b7f8b5c5e65e005758543454ad37ee
parenttests: switch test to new fe_client notify selector syntax (diff)
downloadfrr-3dad09b228e3c4a4ffa6da260fadda6762a77c58.tar.xz
frr-3dad09b228e3c4a4ffa6da260fadda6762a77c58.zip
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 <chopps@labn.net>
-rw-r--r--lib/mgmt_msg_native.c27
-rw-r--r--lib/mgmt_msg_native.h45
-rw-r--r--mgmtd/mgmt_fe_adapter.c124
3 files changed, 195 insertions, 1 deletions
diff --git a/lib/mgmt_msg_native.c b/lib/mgmt_msg_native.c
index d0a0b7218..b85c7d1b6 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 e61346e6e..76a52658c 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 a076dc72f..5f53c928a 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) {