mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00

This commit introduces the Frontend Interface which can be used by front-end management clients like Netconf server, Restconf Server and CLI to interact with new FRR Management daemon (MGMTd) to access and sometimes modify FRR management data. This commit includes the following functionalities in the changeset: 1. Add new Frontend server for clients connect to. 2. Add a C-based Frontend client library which can be used by Frontend clients to communicate with MGMTd via the Frontend interface. 3. Maintain a frontend adapter for each connection from an appropriate Frontend client to facilitate client requests and track one or more client sessions across it. 4. Define the protobuf message format for messages to be exchanged between MGMTd Frontend module and the Frontend client. 5. This changeset also introduces an instance of MGMT Frontend client embedded within the lib/vty module that can be leveraged by any FRR daemon to connect to MGMTd's Frontend interface. The same has been integrated with and initialized within the MGMTd daemon's process context to implement a bunch of 'set-config', 'commit-apply', 'get-config' and 'get-data' commands via VTYSH Co-authored-by: Pushpasis Sarkar <pushpasis@gmail.com> Co-authored-by: Abhinay Ramesh <rabhinay@vmware.com> Co-authored-by: Ujwal P <ujwalp@vmware.com> Signed-off-by: Yash Ranjan <ranjany@vmware.com>
161 lines
4 KiB
C
161 lines
4 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* MGMTD Frontend Server
|
|
*
|
|
* Copyright (C) 2021 Vmware, Inc.
|
|
* Pushpasis Sarkar <spushpasis@vmware.com>
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
#include "network.h"
|
|
#include "libfrr.h"
|
|
#include "mgmtd/mgmt.h"
|
|
#include "mgmtd/mgmt_fe_server.h"
|
|
#include "mgmtd/mgmt_fe_adapter.h"
|
|
|
|
#ifdef REDIRECT_DEBUG_TO_STDERR
|
|
#define MGMTD_FE_SRVR_DBG(fmt, ...) \
|
|
fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
|
|
#define MGMTD_FE_SRVR_ERR(fmt, ...) \
|
|
fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
|
|
#else /* REDIRECT_DEBUG_TO_STDERR */
|
|
#define MGMTD_FE_SRVR_DBG(fmt, ...) \
|
|
do { \
|
|
if (mgmt_debug_fe) \
|
|
zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
|
|
} while (0)
|
|
#define MGMTD_FE_SRVR_ERR(fmt, ...) \
|
|
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
|
|
#endif /* REDIRECT_DEBUG_TO_STDERR */
|
|
|
|
static int mgmt_fe_listen_fd;
|
|
static struct thread_master *mgmt_fe_listen_tm;
|
|
static struct thread *mgmt_fe_listen_ev;
|
|
static void mgmt_fe_server_register_event(enum mgmt_fe_event event);
|
|
|
|
static void mgmt_fe_conn_accept(struct thread *thread)
|
|
{
|
|
int client_conn_fd;
|
|
union sockunion su;
|
|
|
|
if (mgmt_fe_listen_fd < 0)
|
|
return;
|
|
|
|
/* We continue hearing server listen socket. */
|
|
mgmt_fe_server_register_event(MGMTD_FE_SERVER);
|
|
|
|
memset(&su, 0, sizeof(union sockunion));
|
|
|
|
/* We can handle IPv4 or IPv6 socket. */
|
|
client_conn_fd = sockunion_accept(mgmt_fe_listen_fd, &su);
|
|
if (client_conn_fd < 0) {
|
|
MGMTD_FE_SRVR_ERR(
|
|
"Failed to accept MGMTD Frontend client connection : %s",
|
|
safe_strerror(errno));
|
|
return;
|
|
}
|
|
set_nonblocking(client_conn_fd);
|
|
set_cloexec(client_conn_fd);
|
|
|
|
MGMTD_FE_SRVR_DBG("Got a new MGMTD Frontend connection");
|
|
|
|
mgmt_fe_create_adapter(client_conn_fd, &su);
|
|
}
|
|
|
|
static void mgmt_fe_server_register_event(enum mgmt_fe_event event)
|
|
{
|
|
if (event == MGMTD_FE_SERVER) {
|
|
thread_add_read(mgmt_fe_listen_tm, mgmt_fe_conn_accept,
|
|
NULL, mgmt_fe_listen_fd,
|
|
&mgmt_fe_listen_ev);
|
|
assert(mgmt_fe_listen_ev);
|
|
} else {
|
|
assert(!"mgmt_fe_server_post_event() called incorrectly");
|
|
}
|
|
}
|
|
|
|
static void mgmt_fe_server_start(const char *hostname)
|
|
{
|
|
int ret;
|
|
int sock;
|
|
struct sockaddr_un addr;
|
|
mode_t old_mask;
|
|
|
|
/* Set umask */
|
|
old_mask = umask(0077);
|
|
|
|
sock = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
|
|
if (sock < 0) {
|
|
MGMTD_FE_SRVR_ERR("Failed to create server socket: %s",
|
|
safe_strerror(errno));
|
|
goto mgmt_fe_server_start_failed;
|
|
}
|
|
|
|
addr.sun_family = AF_UNIX,
|
|
strlcpy(addr.sun_path, MGMTD_FE_SERVER_PATH, sizeof(addr.sun_path));
|
|
unlink(addr.sun_path);
|
|
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
|
|
if (ret < 0) {
|
|
MGMTD_FE_SRVR_ERR(
|
|
"Failed to bind server socket to '%s'. Err: %s",
|
|
addr.sun_path, safe_strerror(errno));
|
|
goto mgmt_fe_server_start_failed;
|
|
}
|
|
|
|
ret = listen(sock, MGMTD_FE_MAX_CONN);
|
|
if (ret < 0) {
|
|
MGMTD_FE_SRVR_ERR("Failed to listen on server socket: %s",
|
|
safe_strerror(errno));
|
|
goto mgmt_fe_server_start_failed;
|
|
}
|
|
|
|
/* Restore umask */
|
|
umask(old_mask);
|
|
|
|
mgmt_fe_listen_fd = sock;
|
|
mgmt_fe_server_register_event(MGMTD_FE_SERVER);
|
|
|
|
MGMTD_FE_SRVR_DBG("Started MGMTD Frontend Server!");
|
|
return;
|
|
|
|
mgmt_fe_server_start_failed:
|
|
if (sock)
|
|
close(sock);
|
|
|
|
mgmt_fe_listen_fd = -1;
|
|
exit(-1);
|
|
}
|
|
|
|
int mgmt_fe_server_init(struct thread_master *master)
|
|
{
|
|
if (mgmt_fe_listen_tm) {
|
|
MGMTD_FE_SRVR_DBG("MGMTD Frontend Server already running!");
|
|
return 0;
|
|
}
|
|
|
|
mgmt_fe_listen_tm = master;
|
|
|
|
mgmt_fe_server_start("localhost");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mgmt_fe_server_destroy(void)
|
|
{
|
|
if (mgmt_fe_listen_tm) {
|
|
MGMTD_FE_SRVR_DBG("Closing MGMTD Frontend Server!");
|
|
|
|
if (mgmt_fe_listen_ev) {
|
|
THREAD_OFF(mgmt_fe_listen_ev);
|
|
mgmt_fe_listen_ev = NULL;
|
|
}
|
|
|
|
if (mgmt_fe_listen_fd >= 0) {
|
|
close(mgmt_fe_listen_fd);
|
|
mgmt_fe_listen_fd = -1;
|
|
}
|
|
|
|
mgmt_fe_listen_tm = NULL;
|
|
}
|
|
}
|