]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Additional CLI sockets can be now configured in the config file
authorMaria Matejka <mq@ucw.cz>
Mon, 24 Jun 2024 09:10:07 +0000 (11:10 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 27 Jun 2024 02:14:38 +0000 (04:14 +0200)
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.

conf/conf.c
conf/confbase.Y
doc/bird.sgml
nest/cli.h
sysdep/unix/config.Y
sysdep/unix/io.c
sysdep/unix/main.c
sysdep/unix/unix.h

index d98d421cddf0d7ee81bc30d7c0184b8f0fe8451f..805fdbd47401f4c5d4c466ccb346dc61866d49bb 100644 (file)
@@ -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;
index cdbdf1ce29e7bbc269401fc5e0211e88690cc86e..4bf70ccfa6d7da4e7500d70cf09df2d592f31219 100644 (file)
@@ -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
index 4454301210aab833d9142da5d7e2a5326b01217c..5acdf7c13fc428aa540dcdc6d415a9c450b8a435 100644 (file)
@@ -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>
index a9848a89dca1b9cb337e047bd8803e51f87b9f09..c20f9c476533b3128f762121c1a5b20691b8bb51 100644 (file)
@@ -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 */
 
index 24d1ae5d288e343350547f18e9b2637a02f6b878..665b0b0974ed15a8e4f5bbc40c2f0993e18a02ce 100644 (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(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:
index 5a0dde8e3b567febc64367f877755ab81a95a664..ba2e166149951bd1e206768c5fbacb3568b81af6 100644 (file)
@@ -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;
index c712aee482f5e084601bf1367f594e6a4a6e3e50..17f7edb567fbbcde1adecafe4273bdf038fe73fc 100644 (file)
@@ -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);
 }
index 7c15e30d46a29e67b9b5b3925d48c3603bf521c0..33ece06cd9b61027d39b832b308712bf7a8ce6d9 100644 (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);
 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 */