#include "util.h"
#include "conffile.h"
+#include "process.h"
-/* Command-line options (possibly config-file options too) */
+/* XXX should be from autoconf */
static char *configfile="/etc/secnet/secnet.conf";
bool_t just_check_config=False;
static char *userid=NULL;
static uid_t uid=0;
-static bool_t background=True;
+bool_t background=True;
static char *pidfile=NULL;
+bool_t require_root_privileges=False;
+string_t require_root_privileges_explanation=NULL;
+
+static pid_t secnet_pid;
+
+/* from log.c */
+extern uint32_t message_level;
+extern bool_t secnet_is_daemon;
+extern struct log_if *system_log;
+
+/* from process.c */
+extern void start_signal_handling(void);
/* Structures dealing with poll() call */
struct poll_interest {
break;
case 'v':
- message_level|=M_INFO|M_WARNING|M_ERROR|M_FATAL;
+ message_level|=M_INFO|M_NOTICE|M_WARNING|M_ERROR|M_SECURITY|
+ M_FATAL;
break;
- case 'n':
- background=False;
+ case 'w':
+ message_level&=(~M_WARNING);
break;
case 'd':
- message_level|=M_DEBUG_CONFIG|M_DEBUG_PHASE;
+ message_level|=M_DEBUG_CONFIG|M_DEBUG_PHASE|M_DEBUG;
break;
case 'f':
message_level=M_FATAL;
break;
+ case 'n':
+ background=False;
+ break;
+
case 'c':
if (optarg)
configfile=safe_strdup(optarg,"config_filename");
break;
default:
- Message(M_WARNING,"secnet: Unknown getopt code %c\n",c);
+ Message(M_ERROR,"secnet: Unknown getopt code %c\n",c);
}
}
if (argc-optind != 0) {
- Message(M_WARNING,"secnet: You gave extra command line parameters, "
+ Message(M_ERROR,"secnet: You gave extra command line parameters, "
"which were ignored.\n");
}
}
list_t *l;
item_t *site;
dict_t *system;
- struct log_if *log;
struct passwd *pw;
struct cloc loc;
int i;
if (!l) {
fatal("configuration does not include a system/log facility\n");
}
- log=init_log(l);
- log->log(log->st,LOG_DEBUG,"%s: logging started",version);
+ system_log=init_log(l);
/* Who are we supposed to run as? */
userid=dict_read_string(system,"userid",False,"system",loc);
/* Pidfile name */
pidfile=dict_read_string(system,"pidfile",False,"system",loc);
+ /* Check whether we need root privileges */
+ if (require_root_privileges && uid!=0) {
+ fatal("the following configured feature (\"%s\") requires "
+ "that secnet retain root privileges while running.\n",
+ require_root_privileges_explanation);
+ }
+
/* Go along site list, starting sites */
l=dict_lookup(config,"sites");
if (!l) {
- fatal("configuration did not define any remote sites\n");
- }
- i=0;
- while ((site=list_elem(l, i++))) {
- struct site_if *s;
- if (site->type!=t_closure) {
- cfgfatal(site->loc,"system","non-closure in site list");
- }
- if (site->data.closure->type!=CL_SITE) {
- cfgfatal(site->loc,"system","non-site closure in site list");
+ Message(M_WARNING,"secnet: configuration did not define any "
+ "remote sites\n");
+ } else {
+ i=0;
+ while ((site=list_elem(l, i++))) {
+ struct site_if *s;
+ if (site->type!=t_closure) {
+ cfgfatal(site->loc,"system","non-closure in site list");
+ }
+ if (site->data.closure->type!=CL_SITE) {
+ cfgfatal(site->loc,"system","non-site closure in site list");
+ }
+ s=site->data.closure->interface;
+ s->control(s->st,True);
}
- s=site->data.closure->interface;
- s->control(s->st,True);
}
}
fatal("run: couldn't alloca\n");
}
- while (!finished) {
+ Message(M_NOTICE,"%s [%d]: starting\n",version,secnet_pid);
+
+ do {
if (gettimeofday(&tv_now, NULL)!=0) {
fatal_perror("main loop: gettimeofday");
}
i->nfds=nfds;
}
do {
+ if (finished) break;
rv=poll(fds, idx, timeout);
if (rv<0) {
if (errno!=EINTR) {
}
}
} while (rv<0);
- }
+ } while (!finished);
}
static void droppriv(void)
add_hook(PHASE_SHUTDOWN,system_phase_hook,NULL);
- /* Background now, if we're supposed to: we may be unable to write the
- pidfile if we don't. */
- if (background) {
- printf("goto background\n");
- /* Open the pidfile before forking - that way the parent can tell
- whether it succeeds */
- if (pidfile) {
- pf=fopen(pidfile,"w");
- if (!pf) {
- fatal_perror("cannot open pidfile \"%s\"",pidfile);
- }
- } else {
- Message(M_WARNING,"secnet: no pidfile configured, but "
- "backgrounding anyway\n");
+ /* Open the pidfile for writing now: we may be unable to do so
+ once we drop privileges. */
+ if (pidfile) {
+ pf=fopen(pidfile,"w");
+ if (!pf) {
+ fatal_perror("cannot open pidfile \"%s\"",pidfile);
+ }
+ }
+ if (!background && pf) {
+ fprintf(pf,"%d\n",getpid());
+ fclose(pf);
+ }
+
+ /* Now drop privileges */
+ if (uid!=0) {
+ if (setuid(uid)!=0) {
+ fatal_perror("can't set uid to \"%s\"",userid);
}
+ }
+ if (background) {
p=fork();
if (p>0) {
if (pf) {
} else if (p==0) {
/* Child process - all done, just carry on */
if (pf) fclose(pf);
- printf("child\n");
+ secnet_is_daemon=True;
} else {
/* Error */
fatal_perror("cannot fork");
exit(1);
}
- } else {
- if (pidfile) {
- pf=fopen(pidfile,"w");
- if (!pf) {
- fatal_perror("cannot open pidfile \"%s\"",pidfile);
- }
- fprintf(pf,"%d\n",getpid());
- fclose(pf);
- }
}
+ secnet_pid=getpid();
+}
- /* Drop privilege now, if configured to do so */
- if (uid!=0) {
- if (setuid(uid)!=0) {
- fatal_perror("can't set uid to \"%s\"",userid);
- }
- }
+static signal_notify_fn finish,ignore_hup;
+static void finish(void *st, int signum)
+{
+ finished=True;
+ Message(M_NOTICE,"%s [%d]: received %s\n",version,secnet_pid,(string_t)st);
+}
+static void ignore_hup(void *st, int signum)
+{
+ Message(M_INFO,"%s [%d]: received SIGHUP\n",version,secnet_pid);
+ return;
}
int main(int argc, char **argv)
droppriv();
enter_phase(PHASE_RUN);
+ start_signal_handling();
+ request_signal_notification(SIGTERM,finish,"SIGTERM");
+ if (!background) request_signal_notification(SIGINT,finish,"SIGINT");
+ request_signal_notification(SIGHUP,ignore_hup,NULL);
run();
enter_phase(PHASE_SHUTDOWN);
+ Message(M_NOTICE,"%s [%d]: finished\n",version,secnet_pid);
return 0;
}
-