diff options
author | Maria Matejka <mq@ucw.cz> | 2024-06-24 11:10:07 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2024-06-27 04:14:38 +0200 |
commit | f3b6661ddda9a9c2591444799ff88cd82621d06b (patch) | |
tree | ae4ac9154932587ffe1c8acc64effb9fb44806c1 | |
parent | a95fff37937171302167e670bd8b6e80d447cf65 (diff) |
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.
-rw-r--r-- | conf/conf.c | 1 | ||||
-rw-r--r-- | conf/confbase.Y | 1 | ||||
-rw-r--r-- | doc/bird.sgml | 29 | ||||
-rw-r--r-- | nest/cli.h | 4 | ||||
-rw-r--r-- | sysdep/unix/config.Y | 16 | ||||
-rw-r--r-- | sysdep/unix/io.c | 2 | ||||
-rw-r--r-- | sysdep/unix/main.c | 99 | ||||
-rw-r--r-- | sysdep/unix/unix.h | 2 |
8 files changed, 134 insertions, 20 deletions
diff --git a/conf/conf.c b/conf/conf.c index d98d421c..805fdbd4 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -552,6 +552,7 @@ order_shutdown(int gr) init_list(&c->tables); init_list(&c->mpls_domains); init_list(&c->symbols); + c->cli = (struct cli_config_list) {}; memset(c->def_tables, 0, sizeof(c->def_tables)); c->shutdown = 1; c->gr_down = gr; diff --git a/conf/confbase.Y b/conf/confbase.Y index cdbdf1ce..4bf70ccf 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -100,6 +100,7 @@ CF_DECLS mpls_label_stack *mls; const struct adata *bs; struct aggr_item_node *ai; + struct cli_config *cli; } %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT diff --git a/doc/bird.sgml b/doc/bird.sgml index 44543012..5acdf7c1 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1219,9 +1219,11 @@ protocol bgp { <chapt>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 -BIRD. Communication is done using a <file/bird.ctl/ UNIX domain socket (unless -changed with the <tt/-s/ option given to both the server and the client). The +BIRD. Communication is done using the appropriate UNIX domain socket. The commands can perform simple actions such as enabling/disabling of protocols, 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 @@ -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 Readline library (required for regular BIRD client) is not available. -<p>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. +<sect>Configuration +<label id="remote-control-configuration"> + +<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. -<p>Here is a brief list of supported functions: +<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> <tag><label id="cli-show-status">show status</tag> @@ -55,12 +55,16 @@ struct cli_config { #define TLIST_ITEM n #define TLIST_DEFINED_BEFORE #define TLIST_WANT_ADD_TAIL +#define TLIST_WANT_WALK TLIST_DEFAULT_NODE; const char *name; + struct config *config; uint uid, gid, mode; }; #include "lib/tlists.h" +void cli_config_listen(struct cli_config *, const char *); + extern pool *cli_pool; extern struct cli *this_cli; /* Used during parsing */ diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y index 24d1ae5d..665b0b09 100644 --- a/sysdep/unix/config.Y +++ b/sysdep/unix/config.Y @@ -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(DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, TIMEOUT, THREADS) +%type <cli> cli_opts %type <i> log_mask log_mask_list log_cat cfg_timeout %type <t> cfg_name %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 ; debug_unix: diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 5a0dde8e..ba2e1661 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -2431,7 +2431,7 @@ io_loop(void) } void -test_old_bird(char *path) +test_old_bird(const char *path) { int fd; struct sockaddr_un sa; diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index c712aee4..17f7edb5 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -29,6 +29,7 @@ #include "lib/socket.h" #include "lib/event.h" #include "lib/timer.h" +#include "lib/tlists.h" #include "lib/string.h" #include "nest/route.h" #include "nest/protocol.h" @@ -183,6 +184,8 @@ cf_read(byte *dest, uint len, int fd) return l; } +static void cli_preconfig(struct config *c); + void 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_tables", "ipt_", 0xffffffff); #endif + + cli_preconfig(c); } +static void cli_commit(struct config *new, struct config *old); + 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); + cli_commit(new, old); return 0; } @@ -395,13 +403,29 @@ cmd_reconfig_status(void) * 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; + +#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 { + TLIST_DEFAULT_NODE; sock *s; struct cli_config *config; } *main_control_socket = NULL; +#include "lib/tlists.h" + +static TLIST_LIST(cli_listener) cli_listeners; + static void cli_write(cli *c) { @@ -523,7 +547,7 @@ cli_connect(sock *s, uint size UNUSED) } 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); l->config = cf; @@ -557,29 +581,78 @@ cli_listener(struct cli_config *cf) return NULL; } + cli_listener_add_tail(&cli_listeners, 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 cli_init_unix(uid_t use_uid, gid_t use_gid) { 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 = (struct cli_config) { - .name = path_control_socket, - .uid = use_uid, - .gid = use_gid, - .mode = 0660, - }; + main_control_socket_config = &initial_control_socket_config; + main_control_socket_config->uid = use_uid; + main_control_socket_config->gid = use_gid; ASSERT_DIE(main_control_socket == NULL); - cli_init(); - main_control_socket = cli_listener(main_control_socket_config); + main_control_socket = cli_listen(main_control_socket_config); if (!main_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 @@ -658,7 +731,7 @@ void sysdep_shutdown_done(void) { unlink_pid_file(); - unlink(path_control_socket); + cli_deafen(main_control_socket); log_msg(L_FATAL "Shutdown completed"); exit(0); } diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h index 7c15e30d..33ece06c 100644 --- a/sysdep/unix/unix.h +++ b/sysdep/unix/unix.h @@ -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); void *rf_file(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); /* krt.c bits */ |