0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

Additional CLI sockets can be now configured in the config file

If the user has such a need, they may configure additional sockets
in the config file. This may work for e.g. some advanced access control.
This commit is contained in:
Maria Matejka 2024-06-24 11:10:07 +02:00
parent 9639f88bb1
commit 5b53fe36e7
8 changed files with 134 additions and 20 deletions

View File

@ -552,6 +552,7 @@ order_shutdown(int gr)
init_list(&c->tables); init_list(&c->tables);
init_list(&c->mpls_domains); init_list(&c->mpls_domains);
init_list(&c->symbols); init_list(&c->symbols);
c->cli = (struct cli_config_list) {};
memset(c->def_tables, 0, sizeof(c->def_tables)); memset(c->def_tables, 0, sizeof(c->def_tables));
c->shutdown = 1; c->shutdown = 1;
c->gr_down = gr; c->gr_down = gr;

View File

@ -100,6 +100,7 @@ CF_DECLS
mpls_label_stack *mls; mpls_label_stack *mls;
const struct adata *bs; const struct adata *bs;
struct aggr_item_node *ai; struct aggr_item_node *ai;
struct cli_config *cli;
} }
%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT

View File

@ -1219,9 +1219,11 @@ protocol bgp {
<chapt>Remote control <chapt>Remote control
<label id="remote-control"> <label id="remote-control">
<sect>Overview
<label id="remote-control-overview">
<p>You can use the command-line client <file>birdc</file> to talk with a running <p>You can use the command-line client <file>birdc</file> to talk with a running
BIRD. Communication is done using a <file/bird.ctl/ UNIX domain socket (unless BIRD. Communication is done using the appropriate UNIX domain socket. The
changed with the <tt/-s/ option given to both the server and the client). The
commands can perform simple actions such as enabling/disabling of protocols, commands can perform simple actions such as enabling/disabling of protocols,
telling BIRD to show various information, telling it to show routing table telling BIRD to show various information, telling it to show routing table
filtered by filter, or asking BIRD to reconfigure. Press <tt/?/ at any time to filtered by filter, or asking BIRD to reconfigure. Press <tt/?/ at any time to
@ -1237,10 +1239,27 @@ does not support command line editing and history and has minimal dependencies.
This is useful for running BIRD in resource constrained environments, where This is useful for running BIRD in resource constrained environments, where
Readline library (required for regular BIRD client) is not available. Readline library (required for regular BIRD client) is not available.
<p>Many commands have the <m/name/ of the protocol instance as an argument. <sect>Configuration
This argument can be omitted if there exists only a single instance. <label id="remote-control-configuration">
<p>Here is a brief list of supported functions: <p>By default, BIRD opens <file/bird.ctl/ UNIX domain socket and the CLI tool
connects to it. If changed on the command line by the <tt/-s/ option,
BIRD or the CLI tool connects there instead.
<p>It's also possible to configure additional remote control sockets in the
configuration file by <cf/cli "name";/ and you can open how many
sockets you wish. There are no checks whether the user configured the same
socket multiple times and BIRD may behave weirdly if this happens. On shutdown,
the additional sockets get removed immediately and only the main socket stays
until the very end.
<sect>Usage
<label id="remote-control-usage">
<p>Here is a brief list of supported functions.
<p>Note: Many commands have the <m/name/ of the protocol instance as an argument.
This argument can be omitted if there exists only a single instance.
<descrip> <descrip>
<tag><label id="cli-show-status">show status</tag> <tag><label id="cli-show-status">show status</tag>

View File

@ -55,12 +55,16 @@ struct cli_config {
#define TLIST_ITEM n #define TLIST_ITEM n
#define TLIST_DEFINED_BEFORE #define TLIST_DEFINED_BEFORE
#define TLIST_WANT_ADD_TAIL #define TLIST_WANT_ADD_TAIL
#define TLIST_WANT_WALK
TLIST_DEFAULT_NODE; TLIST_DEFAULT_NODE;
const char *name; const char *name;
struct config *config;
uint uid, gid, mode; uint uid, gid, mode;
}; };
#include "lib/tlists.h" #include "lib/tlists.h"
void cli_config_listen(struct cli_config *, const char *);
extern pool *cli_pool; extern pool *cli_pool;
extern struct cli *this_cli; /* Used during parsing */ extern struct cli *this_cli; /* Used during parsing */

View File

@ -21,6 +21,7 @@ CF_KEYWORDS(LOG, SYSLOG, NAME, STDERR, UDP, PORT, CLI)
CF_KEYWORDS(ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG) CF_KEYWORDS(ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG)
CF_KEYWORDS(DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, TIMEOUT, THREADS) CF_KEYWORDS(DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, TIMEOUT, THREADS)
%type <cli> cli_opts
%type <i> log_mask log_mask_list log_cat cfg_timeout %type <i> log_mask log_mask_list log_cat cfg_timeout
%type <t> cfg_name %type <t> cfg_name
%type <tf> timeformat_which %type <tf> timeformat_which
@ -123,6 +124,21 @@ mrtdump_base:
} }
; ;
conf: cli ;
cli: CLI text cli_opts {
$3->name = $2;
cli_config_add_tail(&new_config->cli, $3);
} ;
cli_opts: ';' {
$$ = cfg_alloc(sizeof *$$);
*$$ = (typeof (*$$)) {
.config = new_config,
.mode = 0660,
};
};
conf: debug_unix ; conf: debug_unix ;
debug_unix: debug_unix:

View File

@ -2427,7 +2427,7 @@ io_loop(void)
} }
void void
test_old_bird(char *path) test_old_bird(const char *path)
{ {
int fd; int fd;
struct sockaddr_un sa; struct sockaddr_un sa;

View File

@ -29,6 +29,7 @@
#include "lib/socket.h" #include "lib/socket.h"
#include "lib/event.h" #include "lib/event.h"
#include "lib/timer.h" #include "lib/timer.h"
#include "lib/tlists.h"
#include "lib/string.h" #include "lib/string.h"
#include "nest/route.h" #include "nest/route.h"
#include "nest/protocol.h" #include "nest/protocol.h"
@ -183,6 +184,8 @@ cf_read(byte *dest, uint len, int fd)
return l; return l;
} }
static void cli_preconfig(struct config *c);
void void
sysdep_preconfig(struct config *c) sysdep_preconfig(struct config *c)
{ {
@ -197,12 +200,17 @@ sysdep_preconfig(struct config *c)
read_iproute_table(c, PATH_IPROUTE_DIR "/rt_scopes", "ips_", 255); read_iproute_table(c, PATH_IPROUTE_DIR "/rt_scopes", "ips_", 255);
read_iproute_table(c, PATH_IPROUTE_DIR "/rt_tables", "ipt_", 0xffffffff); read_iproute_table(c, PATH_IPROUTE_DIR "/rt_tables", "ipt_", 0xffffffff);
#endif #endif
cli_preconfig(c);
} }
static void cli_commit(struct config *new, struct config *old);
int int
sysdep_commit(struct config *new, struct config *old UNUSED) sysdep_commit(struct config *new, struct config *old)
{ {
log_switch(0, &new->logfiles, new->syslog_name); log_switch(0, &new->logfiles, new->syslog_name);
cli_commit(new, old);
return 0; return 0;
} }
@ -395,13 +403,29 @@ cmd_reconfig_status(void)
* Command-Line Interface * Command-Line Interface
*/ */
static char *path_control_socket = PATH_CONTROL_SOCKET; static struct cli_config initial_control_socket_config = {
.name = PATH_CONTROL_SOCKET,
.mode = 0660,
};
#define path_control_socket initial_control_socket_config.name
static struct cli_config *main_control_socket_config = NULL; static struct cli_config *main_control_socket_config = NULL;
#define TLIST_PREFIX cli_listener
#define TLIST_TYPE struct cli_listener
#define TLIST_ITEM n
#define TLIST_WANT_ADD_TAIL
#define TLIST_WANT_WALK
static struct cli_listener { static struct cli_listener {
TLIST_DEFAULT_NODE;
sock *s; sock *s;
struct cli_config *config; struct cli_config *config;
} *main_control_socket = NULL; } *main_control_socket = NULL;
#include "lib/tlists.h"
static TLIST_LIST(cli_listener) cli_listeners;
static void static void
cli_write(cli *c) cli_write(cli *c)
{ {
@ -523,7 +547,7 @@ cli_connect(sock *s, uint size UNUSED)
} }
static struct cli_listener * static struct cli_listener *
cli_listener(struct cli_config *cf) cli_listen(struct cli_config *cf)
{ {
struct cli_listener *l = mb_allocz(cli_pool, sizeof *l); struct cli_listener *l = mb_allocz(cli_pool, sizeof *l);
l->config = cf; l->config = cf;
@ -557,29 +581,78 @@ cli_listener(struct cli_config *cf)
return NULL; return NULL;
} }
cli_listener_add_tail(&cli_listeners, l);
return l; return l;
} }
static void
cli_deafen(struct cli_listener *l)
{
rfree(l->s);
unlink(l->config->name);
cli_listener_rem_node(&cli_listeners, l);
mb_free(l);
}
static void static void
cli_init_unix(uid_t use_uid, gid_t use_gid) cli_init_unix(uid_t use_uid, gid_t use_gid)
{ {
ASSERT_DIE(main_control_socket_config == NULL); ASSERT_DIE(main_control_socket_config == NULL);
cli_init();
main_control_socket_config = mb_alloc(&root_pool, sizeof *main_control_socket_config); main_control_socket_config = &initial_control_socket_config;
*main_control_socket_config = (struct cli_config) { main_control_socket_config->uid = use_uid;
.name = path_control_socket, main_control_socket_config->gid = use_gid;
.uid = use_uid,
.gid = use_gid,
.mode = 0660,
};
ASSERT_DIE(main_control_socket == NULL); ASSERT_DIE(main_control_socket == NULL);
cli_init(); main_control_socket = cli_listen(main_control_socket_config);
main_control_socket = cli_listener(main_control_socket_config);
if (!main_control_socket) if (!main_control_socket)
die("Won't run without control socket"); die("Won't run without control socket");
} }
static void
cli_preconfig(struct config *c)
{
struct cli_config *ccf = mb_alloc(cli_pool, sizeof *ccf);
memcpy(ccf, main_control_socket_config, sizeof *ccf);
ccf->n = (struct cli_config_node) {};
ccf->config = c;
cli_config_add_tail(&c->cli, ccf);
}
static void
cli_commit(struct config *new, struct config *old)
{
if (new->shutdown)
{
/* Keep the main CLI throughout the shutdown */
initial_control_socket_config.config = new;
main_control_socket->config = &initial_control_socket_config;
}
WALK_TLIST(cli_config, c, &new->cli)
{
_Bool seen = 0;
WALK_TLIST(cli_listener, l, &cli_listeners)
if (l->config->config != new)
if (!strcmp(l->config->name, c->name))
{
ASSERT_DIE(l->config->config == old);
l->config = c;
seen = 1;
break;
}
if (!seen)
cli_listen(c);
}
WALK_TLIST_DELSAFE(cli_listener, l, &cli_listeners)
if (l->config->config != new)
cli_deafen(l);
}
/* /*
* PID file * PID file
@ -658,7 +731,7 @@ void
sysdep_shutdown_done(void) sysdep_shutdown_done(void)
{ {
unlink_pid_file(); unlink_pid_file();
unlink(path_control_socket); cli_deafen(main_control_socket);
log_msg(L_FATAL "Shutdown completed"); log_msg(L_FATAL "Shutdown completed");
exit(0); exit(0);
} }

View File

@ -112,7 +112,7 @@ struct rfile *rf_open(struct pool *, const char *name, const char *mode);
struct rfile *rf_fdopen(pool *p, int fd, const char *mode); struct rfile *rf_fdopen(pool *p, int fd, const char *mode);
void *rf_file(struct rfile *f); void *rf_file(struct rfile *f);
int rf_fileno(struct rfile *f); int rf_fileno(struct rfile *f);
void test_old_bird(char *path); void test_old_bird(const char *path);
ip_addr resolve_hostname(const char *host, int type, const char **err_msg); ip_addr resolve_hostname(const char *host, int type, const char **err_msg);
/* krt.c bits */ /* krt.c bits */