mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
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>
This commit is contained in:
parent
56ce19891b
commit
3dad09b228
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue