]>
git.ipfire.org Git - thirdparty/bird.git/blob - sysdep/unix/main.c
2 * BIRD Internet Routing Daemon -- Unix Entry Point
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
23 #include "nest/bird.h"
24 #include "lib/lists.h"
25 #include "lib/resource.h"
26 #include "lib/socket.h"
27 #include "lib/event.h"
28 #include "lib/string.h"
29 #include "nest/route.h"
30 #include "nest/protocol.h"
31 #include "nest/iface.h"
33 #include "nest/locks.h"
34 #include "conf/conf.h"
35 #include "filter/filter.h"
45 static int debug_flag
= 1;
47 static int debug_flag
= 0;
53 debug("INTERNAL STATE DUMP\n\n");
71 #ifdef CONFIG_RESTRICTED_PRIVILEGES
72 #include "lib/syspriv.h"
78 die("Cannot change user on this platform");
91 * Reading the Configuration
94 #ifdef PATH_IPROUTE_DIR
97 add_num_const(char *name
, int val
)
99 struct symbol
*s
= cf_find_symbol(name
);
100 s
->class = SYM_CONSTANT
| T_INT
;
101 s
->def
= cfg_allocz(sizeof(struct f_val
));
106 /* the code of read_iproute_table() is based on
107 rtnl_tab_initialize() from iproute2 package */
109 read_iproute_table(char *file
, char *prefix
, int max
)
111 char buf
[512], namebuf
[512];
116 strcpy(namebuf
, prefix
);
117 name
= namebuf
+ strlen(prefix
);
119 fp
= fopen(file
, "r");
123 while (fgets(buf
, sizeof(buf
), fp
))
127 while (*p
== ' ' || *p
== '\t')
130 if (*p
== '#' || *p
== '\n' || *p
== 0)
133 if (sscanf(p
, "0x%x %s\n", &val
, name
) != 2 &&
134 sscanf(p
, "0x%x %s #", &val
, name
) != 2 &&
135 sscanf(p
, "%d %s\n", &val
, name
) != 2 &&
136 sscanf(p
, "%d %s #", &val
, name
) != 2)
139 if (val
< 0 || val
> max
)
142 for(p
= name
; *p
; p
++)
143 if ((*p
< 'a' || *p
> 'z') && (*p
< '0' || *p
> '9') && (*p
!= '_'))
146 add_num_const(namebuf
, val
);
152 #endif // PATH_IPROUTE_DIR
155 static char *config_name
= PATH_CONFIG_FILE
;
158 cf_read(byte
*dest
, unsigned int len
, int fd
)
160 int l
= read(fd
, dest
, len
);
162 cf_error("Read error");
167 sysdep_preconfig(struct config
*c
)
169 init_list(&c
->logfiles
);
171 #ifdef PATH_IPROUTE_DIR
172 read_iproute_table(PATH_IPROUTE_DIR
"/rt_protos", "ipp_", 256);
173 read_iproute_table(PATH_IPROUTE_DIR
"/rt_realms", "ipr_", 256);
174 read_iproute_table(PATH_IPROUTE_DIR
"/rt_scopes", "ips_", 256);
175 read_iproute_table(PATH_IPROUTE_DIR
"/rt_tables", "ipt_", 256);
180 sysdep_commit(struct config
*new, struct config
*old UNUSED
)
182 log_switch(debug_flag
, &new->logfiles
, new->syslog_name
);
187 unix_read_config(struct config
**cp
, char *name
)
189 struct config
*conf
= config_alloc(name
);
193 conf
->file_fd
= open(name
, O_RDONLY
);
194 if (conf
->file_fd
< 0)
196 cf_read_hook
= cf_read
;
197 ret
= config_parse(conf
);
198 close(conf
->file_fd
);
202 static struct config
*
207 if (!unix_read_config(&conf
, config_name
))
210 die("%s, line %d: %s", conf
->err_file_name
, conf
->err_lino
, conf
->err_msg
);
212 die("Unable to open configuration file %s: %m", config_name
);
223 log(L_INFO
"Reconfiguration requested by SIGHUP");
224 if (!unix_read_config(&conf
, config_name
))
227 log(L_ERR
"%s, line %d: %s", conf
->err_file_name
, conf
->err_lino
, conf
->err_msg
);
229 log(L_ERR
"Unable to open configuration file %s: %m", config_name
);
233 config_commit(conf
, RECONFIG_HARD
, 0);
236 static struct config
*
237 cmd_read_config(char *name
)
244 cli_msg(-2, "Reading configuration from %s", name
);
245 if (!unix_read_config(&conf
, name
))
248 cli_msg(8002, "%s, line %d: %s", conf
->err_file_name
, conf
->err_lino
, conf
->err_msg
);
250 cli_msg(8002, "%s: %m", name
);
259 cmd_check_config(char *name
)
261 struct config
*conf
= cmd_read_config(name
);
265 cli_msg(20, "Configuration OK");
270 cmd_reconfig_msg(int r
)
274 case CONF_DONE
: cli_msg( 3, "Reconfigured"); break;
275 case CONF_PROGRESS
: cli_msg( 4, "Reconfiguration in progress"); break;
276 case CONF_QUEUED
: cli_msg( 5, "Reconfiguration already in progress, queueing new config"); break;
277 case CONF_UNQUEUED
: cli_msg(17, "Reconfiguration already in progress, removing queued config"); break;
278 case CONF_CONFIRM
: cli_msg(18, "Reconfiguration confirmed"); break;
279 case CONF_SHUTDOWN
: cli_msg( 6, "Reconfiguration ignored, shutting down"); break;
280 case CONF_NOTHING
: cli_msg(19, "Nothing to do"); break;
285 /* Hack for scheduled undo notification */
286 cli
*cmd_reconfig_stored_cli
;
289 cmd_reconfig_undo_notify(void)
291 if (cmd_reconfig_stored_cli
)
293 cli
*c
= cmd_reconfig_stored_cli
;
294 cli_printf(c
, CLI_ASYNC_CODE
, "Config timeout expired, starting undo");
295 cli_write_trigger(c
);
300 cmd_reconfig(char *name
, int type
, int timeout
)
302 if (cli_access_restricted())
305 struct config
*conf
= cmd_read_config(name
);
309 int r
= config_commit(conf
, type
, timeout
);
311 if ((r
>= 0) && (timeout
> 0))
313 cmd_reconfig_stored_cli
= this_cli
;
314 cli_msg(-22, "Undo scheduled in %d s", timeout
);
321 cmd_reconfig_confirm(void)
323 if (cli_access_restricted())
326 int r
= config_confirm();
331 cmd_reconfig_undo(void)
333 if (cli_access_restricted())
336 cli_msg(-21, "Undo requested");
338 int r
= config_undo();
343 * Command-Line Interface
347 static char *path_control_socket
= PATH_CONTROL_SOCKET
;
357 struct cli_out
*o
= c
->tx_pos
;
359 int len
= o
->wpos
- o
->outpos
;
363 if (sk_send(s
, len
) <= 0)
369 /* Everything is written */
375 cli_write_trigger(cli
*c
)
390 cli_get_command(cli
*c
)
393 byte
*t
= c
->rx_aux
? : s
->rbuf
;
394 byte
*tend
= s
->rpos
;
396 byte
*dend
= c
->rx_buf
+ CLI_RX_BUF_SIZE
- 2;
405 c
->rx_pos
= c
->rx_buf
;
408 return (d
< dend
) ? 1 : -1;
413 c
->rx_aux
= s
->rpos
= s
->rbuf
;
419 cli_rx(sock
*s
, int size UNUSED
)
426 cli_err(sock
*s
, int err
)
428 if (config
->cli_debug
)
431 log(L_INFO
"CLI connection dropped: %s", strerror(err
));
433 log(L_INFO
"CLI connection closed");
439 cli_connect(sock
*s
, int size UNUSED
)
443 if (config
->cli_debug
)
444 log(L_INFO
"CLI connect");
447 s
->err_hook
= cli_err
;
448 s
->data
= c
= cli_new(s
);
449 s
->pool
= c
->pool
; /* We need to have all the socket buffers allocated in the cli pool */
450 c
->rx_pos
= c
->rx_buf
;
457 cli_init_unix(uid_t use_uid
, gid_t use_gid
)
462 s
= cli_sk
= sk_new(cli_pool
);
463 s
->type
= SK_UNIX_PASSIVE
;
464 s
->rx_hook
= cli_connect
;
467 /* Return value intentionally ignored */
468 unlink(path_control_socket
);
470 if (sk_open_unix(s
, path_control_socket
) < 0)
471 die("Cannot create control socket %s: %m", path_control_socket
);
473 if (use_uid
|| use_gid
)
474 if (chown(path_control_socket
, use_uid
, use_gid
) < 0)
477 if (chmod(path_control_socket
, 0660) < 0)
485 static char *pid_file
;
494 pid_fd
= open(pid_file
, O_WRONLY
|O_CREAT
, 0664);
496 die("Cannot create PID file %s: %m", pid_file
);
508 /* We don't use PID file for uniqueness, so no need for locking */
510 pl
= bsnprintf(ps
, sizeof(ps
), "%ld\n", (long) getpid());
512 bug("PID buffer too small");
514 rv
= ftruncate(pid_fd
, 0);
518 rv
= write(pid_fd
, ps
, pl
);
526 unlink_pid_file(void)
540 if (cli_access_restricted())
543 cli_msg(7, "Shutdown requested");
550 DBG("Shutting down...\n");
555 sysdep_shutdown_done(void)
558 unlink(path_control_socket
);
559 log_msg(L_FATAL
"Shutdown completed");
568 handle_sighup(int sig UNUSED
)
570 DBG("Caught SIGHUP...\n");
571 async_config_flag
= 1;
575 handle_sigusr(int sig UNUSED
)
577 DBG("Caught SIGUSR...\n");
582 handle_sigterm(int sig UNUSED
)
584 DBG("Caught SIGTERM...\n");
585 async_shutdown_flag
= 1;
593 bzero(&sa
, sizeof(sa
));
594 sa
.sa_handler
= handle_sigusr
;
595 sa
.sa_flags
= SA_RESTART
;
596 sigaction(SIGUSR1
, &sa
, NULL
);
597 sa
.sa_handler
= handle_sighup
;
598 sa
.sa_flags
= SA_RESTART
;
599 sigaction(SIGHUP
, &sa
, NULL
);
600 sa
.sa_handler
= handle_sigterm
;
601 sa
.sa_flags
= SA_RESTART
;
602 sigaction(SIGTERM
, &sa
, NULL
);
603 signal(SIGPIPE
, SIG_IGN
);
607 * Parsing of command-line arguments
610 static char *opt_list
= "c:dD:ps:P:u:g:fR";
611 static int parse_and_exit
;
613 static char *use_user
;
614 static char *use_group
;
615 static int run_in_foreground
= 0;
620 fprintf(stderr
, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-P <pid-file>] [-u <user>] [-g <group>] [-f] [-R]\n", bird_name
);
625 get_bird_name(char *s
, char *def
)
639 get_uid(const char *s
)
649 rv
= strtol(s
, &endptr
, 10);
651 if (!errno
&& !*endptr
)
656 die("Cannot find user '%s'", s
);
662 get_gid(const char *s
)
672 rv
= strtol(s
, &endptr
, 10);
674 if (!errno
&& !*endptr
)
679 die("Cannot find group '%s'", s
);
685 parse_args(int argc
, char **argv
)
689 bird_name
= get_bird_name(argv
[0], "bird");
692 if (!strcmp(argv
[1], "--version"))
694 fprintf(stderr
, "BIRD version " BIRD_VERSION
"\n");
697 if (!strcmp(argv
[1], "--help"))
700 while ((c
= getopt(argc
, argv
, opt_list
)) >= 0)
704 config_name
= optarg
;
710 log_init_debug(optarg
);
717 path_control_socket
= optarg
;
729 run_in_foreground
= 1;
732 graceful_restart_recovery();
746 main(int argc
, char **argv
)
748 #ifdef HAVE_LIBDMALLOC
749 if (!getenv("DMALLOC_OPTIONS"))
750 dmalloc_debug(0x2f03d00);
753 parse_args(argc
, argv
);
756 log_switch(debug_flag
, NULL
, NULL
);
766 uid_t use_uid
= get_uid(use_user
);
767 gid_t use_gid
= get_gid(use_group
);
771 test_old_bird(path_control_socket
);
772 cli_init_unix(use_uid
, use_gid
);
785 proto_build(&proto_unix_kernel
);
786 proto_build(&proto_unix_iface
);
788 struct config
*conf
= read_config();
793 if (!(debug_flag
||run_in_foreground
))
802 if (open("/dev/null", O_RDWR
) < 0)
803 die("Cannot open /dev/null: %m");
814 config_commit(conf
, RECONFIG_HARD
, 0);
816 graceful_restart_init();
822 log(L_INFO
"Started");
823 DBG("Entering I/O loop.\n");
826 bug("I/O loop died");