summaryrefslogtreecommitdiff
path: root/sysdep/unix
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/unix')
-rw-r--r--sysdep/unix/config.Y33
-rw-r--r--sysdep/unix/io.c5
-rw-r--r--sysdep/unix/krt.c2
-rw-r--r--sysdep/unix/main.c113
-rw-r--r--sysdep/unix/timer.h1
-rw-r--r--sysdep/unix/unix.h7
6 files changed, 128 insertions, 33 deletions
diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y
index 844f53df..7bade918 100644
--- a/sysdep/unix/config.Y
+++ b/sysdep/unix/config.Y
@@ -14,9 +14,9 @@ CF_HDR
CF_DECLS
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
-CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, BASE, NAME)
+CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, BASE, NAME, CONFIRM, UNDO, CHECK, TIMEOUT)
-%type <i> log_mask log_mask_list log_cat
+%type <i> log_mask log_mask_list log_cat cfg_timeout
%type <g> log_file
%type <t> cfg_name
%type <tf> timeformat_which
@@ -104,13 +104,26 @@ timeformat_base:
/* Unix specific commands */
-CF_CLI_HELP(CONFIGURE, [soft] [\"<file>\"], [[Reload configuration]])
+CF_CLI_HELP(CONFIGURE, ..., [[Reload configuration]])
-CF_CLI(CONFIGURE, cfg_name, [\"<file>\"], [[Reload configuration]])
-{ cmd_reconfig($2, RECONFIG_HARD); } ;
+CF_CLI(CONFIGURE, cfg_name cfg_timeout, [\"<file>\"] [timeout [<sec>]], [[Reload configuration]])
+{ cmd_reconfig($2, RECONFIG_HARD, $3); } ;
-CF_CLI(CONFIGURE SOFT, cfg_name, [\"<file>\"], [[Reload configuration and ignore changes in filters]])
-{ cmd_reconfig($3, RECONFIG_SOFT); } ;
+CF_CLI(CONFIGURE SOFT, cfg_name cfg_timeout, [\"<file>\"] [timeout [<sec>]], [[Reload configuration and ignore changes in filters]])
+{ cmd_reconfig($3, RECONFIG_SOFT, $4); } ;
+
+/* Hack to get input completion for 'timeout' */
+CF_CLI_CMD(CONFIGURE TIMEOUT, [<sec>], [[Reload configuration with undo timeout]])
+CF_CLI_CMD(CONFIGURE SOFT TIMEOUT, [<sec>], [[Reload configuration with undo timeout]])
+
+CF_CLI(CONFIGURE CONFIRM,,, [[Confirm last configuration change - deactivate undo timeout]])
+{ cmd_reconfig_confirm(); } ;
+
+CF_CLI(CONFIGURE UNDO,,, [[Undo last configuration change]])
+{ cmd_reconfig_undo(); } ;
+
+CF_CLI(CONFIGURE CHECK, cfg_name, [\"<file>\"], [[Parse configuration and check its validity]])
+{ cmd_check_config($3); } ;
CF_CLI(DOWN,,, [[Shut the daemon down]])
{ cmd_shutdown(); } ;
@@ -120,6 +133,12 @@ cfg_name:
| TEXT
;
+cfg_timeout:
+ /* empty */ { $$ = 0; }
+ | TIMEOUT { $$ = UNIX_DEFAULT_CONFIGURE_TIMEOUT; }
+ | TIMEOUT expr { $$ = $2; }
+ ;
+
CF_CODE
CF_END
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index f91b5278..80914afe 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -121,7 +121,7 @@ static list near_timers, far_timers;
static bird_clock_t first_far_timer = TIME_INFINITY;
/* now must be different from 0, because 0 is a special value in timer->expires */
-bird_clock_t now = 1, now_real;
+bird_clock_t now = 1, now_real, boot_time;
static void
update_times_plain(void)
@@ -1530,6 +1530,7 @@ io_init(void)
krt_io_init();
init_times();
update_times();
+ boot_time = now;
srandom((int) now_real);
}
@@ -1557,7 +1558,7 @@ io_loop(void)
tm_shot();
continue;
}
- timo.tv_sec = events ? 0 : tout - now;
+ timo.tv_sec = events ? 0 : MIN(tout - now, 3);
timo.tv_usec = 0;
if (sock_recalc_fdsets_p)
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 6c0e5e91..3761ace6 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -900,7 +900,7 @@ krt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
{
struct krt_proto *p = (struct krt_proto *) P;
- if (shutting_down)
+ if (config->shutdown)
return;
if (!(net->n.flags & KRF_INSTALLED))
old = NULL;
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index f0344a8f..23040e54 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -210,7 +210,7 @@ read_config(void)
else
die("Unable to open configuration file %s: %m", config_name);
}
- config_commit(conf, RECONFIG_HARD);
+ config_commit(conf, RECONFIG_HARD, 0);
}
void
@@ -228,19 +228,17 @@ async_config(void)
config_free(conf);
}
else
- config_commit(conf, RECONFIG_HARD);
+ config_commit(conf, RECONFIG_HARD, 0);
}
-void
-cmd_reconfig(char *name, int type)
+static struct config *
+cmd_read_config(char *name)
{
struct config *conf;
- if (cli_access_restricted())
- return;
-
if (!name)
name = config_name;
+
cli_msg(-2, "Reading configuration from %s", name);
if (!unix_read_config(&conf, name))
{
@@ -249,24 +247,94 @@ cmd_reconfig(char *name, int type)
else
cli_msg(8002, "%s: %m", name);
config_free(conf);
+ conf = NULL;
}
- else
+
+ return conf;
+}
+
+void
+cmd_check_config(char *name)
+{
+ struct config *conf = cmd_read_config(name);
+ if (!conf)
+ return;
+
+ cli_msg(20, "Configuration OK");
+ config_free(conf);
+}
+
+static void
+cmd_reconfig_msg(int r)
+{
+ switch (r)
{
- switch (config_commit(conf, type))
- {
- case CONF_DONE:
- cli_msg(3, "Reconfigured.");
- break;
- case CONF_PROGRESS:
- cli_msg(4, "Reconfiguration in progress.");
- break;
- case CONF_SHUTDOWN:
- cli_msg(6, "Reconfiguration ignored, shutting down.");
- break;
- default:
- cli_msg(5, "Reconfiguration already in progress, queueing new config");
- }
+ case CONF_DONE: cli_msg( 3, "Reconfigured"); break;
+ case CONF_PROGRESS: cli_msg( 4, "Reconfiguration in progress"); break;
+ case CONF_QUEUED: cli_msg( 5, "Reconfiguration already in progress, queueing new config"); break;
+ case CONF_UNQUEUED: cli_msg(17, "Reconfiguration already in progress, removing queued config"); break;
+ case CONF_CONFIRM: cli_msg(18, "Reconfiguration confirmed"); break;
+ case CONF_SHUTDOWN: cli_msg( 6, "Reconfiguration ignored, shutting down"); break;
+ case CONF_NOTHING: cli_msg(19, "Nothing to do"); break;
+ default: break;
+ }
+}
+
+/* Hack for scheduled undo notification */
+cli *cmd_reconfig_stored_cli;
+
+void
+cmd_reconfig_undo_notify(void)
+{
+ if (cmd_reconfig_stored_cli)
+ {
+ cli *c = cmd_reconfig_stored_cli;
+ cli_printf(c, CLI_ASYNC_CODE, "Config timeout expired, starting undo");
+ cli_write_trigger(c);
+ }
+}
+
+void
+cmd_reconfig(char *name, int type, int timeout)
+{
+ if (cli_access_restricted())
+ return;
+
+ struct config *conf = cmd_read_config(name);
+ if (!conf)
+ return;
+
+ int r = config_commit(conf, type, timeout);
+
+ if ((r >= 0) && (timeout > 0))
+ {
+ cmd_reconfig_stored_cli = this_cli;
+ cli_msg(-22, "Undo scheduled in %d s", timeout);
}
+
+ cmd_reconfig_msg(r);
+}
+
+void
+cmd_reconfig_confirm(void)
+{
+ if (cli_access_restricted())
+ return;
+
+ int r = config_confirm();
+ cmd_reconfig_msg(r);
+}
+
+void
+cmd_reconfig_undo(void)
+{
+ if (cli_access_restricted())
+ return;
+
+ cli_msg(-21, "Undo requested");
+
+ int r = config_undo();
+ cmd_reconfig_msg(r);
}
/*
@@ -623,6 +691,7 @@ main(int argc, char **argv)
rt_init();
if_init();
roa_init();
+ config_init();
uid_t use_uid = get_uid(use_user);
gid_t use_gid = get_gid(use_group);
diff --git a/sysdep/unix/timer.h b/sysdep/unix/timer.h
index a788ae27..17450322 100644
--- a/sysdep/unix/timer.h
+++ b/sysdep/unix/timer.h
@@ -32,6 +32,7 @@ void tm_dump_all(void);
extern bird_clock_t now; /* Relative, monotonic time in seconds */
extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */
+extern bird_clock_t boot_time;
static inline bird_clock_t
tm_remains(timer *t)
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index 3e85c85c..1fc26db2 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -19,9 +19,14 @@ extern char *bird_name;
void async_config(void);
void async_dump(void);
void async_shutdown(void);
-void cmd_reconfig(char *name, int type);
+void cmd_check_config(char *name);
+void cmd_reconfig(char *name, int type, int timeout);
+void cmd_reconfig_confirm(void);
+void cmd_reconfig_undo(void);
void cmd_shutdown(void);
+#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
+
/* io.c */
volatile int async_config_flag;