-/* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
- Copyright (C) 2005-2010, Thorvald Natvig <thorvald@natvig.com>
+/* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#ifdef _POSIX_PRIORITY_SCHEDULING
+#if (_POSIX_PRIORITY_SCHEDULING > 0)
+#define POSIX_PRIORITY_SCHEDULING
#include <sched.h>
#endif
+#endif
#include "server.h"
#include "ssl.h"
#include "channel.h"
#include "client.h"
#include "conf.h"
#include "version.h"
+#include "config.h"
+#include "sharedmemory.h"
+#include "ban.h"
char system_string[64], version_string[64];
int bindport;
+int bindport6;
char *bindaddr;
+char *bindaddr6;
void lockfile(const char *pidfile)
{
* unmodified if we cannot lock it.
*/
lfp = open(pidfile, O_WRONLY|O_CREAT, 0640);
-
+
if (lfp < 0)
Log_fatal("Cannot open PID-file %s for writing", pidfile);
}
snprintf(str,16,"%d\n", getpid());
- write(lfp, str, strlen(str)); /* record pid to lockfile */
+ (void)write(lfp, str, strlen(str)); /* record pid to lockfile */
Log_info("PID-file: %s", pidfile);
/* If uMurmur ever starts to fork()+exec(), we don't want it to
if (setuid(pwd->pw_uid))
Log_fatal("setuid() failed: %s", strerror(errno));
-
+
if (!grp)
grp = getgrgid(gid);
if (!grp)
Log_fatal("getgrgid() failed: %s", strerror(errno));
-
+
Log_info("Switch to user '%s' group '%s'", pwd->pw_name, grp->gr_name);
}
void signal_handler(int sig)
{
switch(sig) {
- case SIGHUP:
- /* XXX - do stuff? */
- Log_info("HUP signal");
- break;
- case SIGTERM:
- Log_info("TERM signal. Shutting down.");
- Server_shutdown();
- break;
+ case SIGHUP:
+ Log_info("HUP signal received.");
+ Log_reset();
+ break;
+ case SIGTERM:
+ Log_info("TERM signal. Shutting down.");
+ Server_shutdown();
+ break;
}
}
void daemonize()
{
int i;
-
+
if (getppid() == 1)
return; /* already a daemon */
i = fork();
}
if ( i > 0)
exit(0); /* parent exits */
-
+
/* child (daemon) continues */
setsid(); /* obtain a new process group */
for (i = getdtablesize(); i >= 0; --i)
close(i); /* close all descriptors */
-
+
+#ifdef USE_GNUTLS
+ gnutls_global_init();
+#endif
+
i = open("/dev/null",O_RDWR);
- dup(i);
- dup(i);
-
+ (void)dup(i);
+ (void)dup(i);
+
umask(027); /* set newly created file permissions */
- chdir("/");
-
+ (void)chdir("/");
+
}
-#ifdef _POSIX_PRIORITY_SCHEDULING
+#ifdef POSIX_PRIORITY_SCHEDULING
void setscheduler()
{
int rc;
void printhelp()
{
- printf("uMurmur version %s. Mumble protocol %d.%d.%d\n", UMURMUR_VERSION, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
- printf("Usage: umurmurd [-d] [-p <pidfile>] [-c <conf file>] [-h]\n");
- printf(" -d - Do not daemonize\n");
- printf(" -p <pidfile> - Write PID to this file\n");
- printf(" -c <conf file> - Specify configuration file\n");
-#ifdef _POSIX_PRIORITY_SCHEDULING
+ printf("uMurmur version %s ('%s'). Mumble protocol %d.%d.%d\n", UMURMUR_VERSION,
+ UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
+ printf("Usage: umurmurd [-d] [-r] [-h] [-p <pidfile>] [-t] [-c <conf file>] [-a <addr>] [-b <port>]\n");
+ printf(" -d - Do not daemonize - run in foreground.\n");
+#ifdef POSIX_PRIORITY_SCHEDULING
printf(" -r - Run with realtime priority\n");
#endif
+ printf(" -p <pidfile> - Write PID to this file\n");
+ printf(" -c <conf file> - Specify configuration file (default %s)\n", DEFAULT_CONFIG);
+ printf(" -t - Test config. Error message to stderr + non-zero exit code on error\n");
printf(" -a <address> - Bind to IP address\n");
+ printf(" -A <address> - Bind to IPv6 address\n");
printf(" -b <port> - Bind to port\n");
+ printf(" -B <port> - Bind to port (IPv6)\n");
printf(" -h - Print this help\n");
exit(0);
}
int main(int argc, char **argv)
{
bool_t nodaemon = false;
-#ifdef _POSIX_PRIORITY_SCHEDULING
+#ifdef POSIX_PRIORITY_SCHEDULING
bool_t realtime = false;
#endif
+ bool_t testconfig = false;
char *conffile = NULL, *pidfile = NULL;
int c;
struct utsname utsbuf;
-
+
/* Arguments */
-#ifdef _POSIX_PRIORITY_SCHEDULING
- while ((c = getopt(argc, argv, "drp:c:a:b:h")) != EOF) {
+#ifdef POSIX_PRIORITY_SCHEDULING
+ while ((c = getopt(argc, argv, "drp:c:a:A:b:B:ht")) != EOF) {
#else
- while ((c = getopt(argc, argv, "dp:c:a:b:h")) != EOF) {
+ while ((c = getopt(argc, argv, "dp:c:a:A:b:B:ht")) != EOF) {
#endif
- switch(c) {
- case 'c':
- conffile = optarg;
- break;
- case 'p':
- pidfile = optarg;
- break;
- case 'a':
- bindaddr = optarg;
- break;
- case 'b':
- bindport = atoi(optarg);
- break;
- case 'd':
- nodaemon = true;
- break;
- case 'h':
- printhelp();
- break;
-#ifdef _POSIX_PRIORITY_SCHEDULING
- case 'r':
- realtime = true;
- break;
+ switch(c) {
+ case 'c':
+ conffile = optarg;
+ break;
+ case 'p':
+ pidfile = optarg;
+ break;
+ case 'a':
+ bindaddr = optarg;
+ break;
+ case 'A':
+ bindaddr6 = optarg;
+ break;
+ case 'b':
+ bindport = atoi(optarg);
+ break;
+ case 'B':
+ bindport6 = atoi(optarg);
+ break;
+ case 'd':
+ nodaemon = true;
+ break;
+ case 'h':
+ printhelp();
+ break;
+ case 't':
+ testconfig = true;
+ break;
+#ifdef POSIX_PRIORITY_SCHEDULING
+ case 'r':
+ realtime = true;
+ break;
#endif
- default:
- fprintf(stderr, "Unrecognized option\n");
- printhelp();
- break;
+ default:
+ fprintf(stderr, "Unrecognized option\n");
+ printhelp();
+ break;
+ }
}
- }
- /* Logging to terminal if not daemonizing, otherwise to syslog.
- * Need to initialize logging before calling Conf_init()
- */
- if (!nodaemon)
- Log_init(false);
- else
- Log_init(true);
-
- /* Initialize the config subsystem early;
- * switch_user() will need to read some config variables.
- */
- Conf_init(conffile);
+ if (testconfig) {
+ if (!Conf_ok(conffile))
+ exit(1);
+ else
+ exit(0);
+ }
- if (!nodaemon) {
- daemonize();
- if (pidfile != NULL)
- lockfile(pidfile);
+ /* Initialize the config subsystem early;
+ * switch_user() will need to read some config variables as well as logging.
+ */
+ Conf_init(conffile);
+
+ /* Logging to terminal if not daemonizing, otherwise to syslog or log file.
+ */
+ if (!nodaemon) {
+ daemonize();
+ Log_init(false);
+ if (pidfile != NULL)
+ lockfile(pidfile);
+
+#ifdef POSIX_PRIORITY_SCHEDULING
+ /* Set the scheduling policy, has to be called after daemonizing
+ * but before we drop privileges */
+ if (realtime)
+ setscheduler();
+#endif
- switch_user();
- }
+ switch_user();
- signal(SIGCHLD, SIG_IGN); /* ignore child */
- signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
- signal(SIGPIPE, SIG_IGN);
- signal(SIGHUP, signal_handler); /* catch hangup signal */
- signal(SIGTERM, signal_handler); /* catch kill signal */
-
- /* Build system string */
- if (uname(&utsbuf) == 0) {
- snprintf(system_string, 64, "%s %s", utsbuf.sysname, utsbuf.machine);
- snprintf(version_string, 64, "%s", utsbuf.release);
- }
- else {
- snprintf(system_string, 64, "unknown unknown");
- snprintf(version_string, 64, "unknown");
- }
-
- /* Initializing */
- SSLi_init();
- Chan_init();
- Client_init();
+ /* Reopen log file. If user switch results in access denied, we catch
+ * it early.
+ */
+ Log_reset();
+ }
+ else Log_init(true);
+
+#ifdef POSIX_PRIORITY_SCHEDULING
+ /* We still want to set scheduling policy if nodaemon is specified,
+ * but if we are daemonizing setscheduler() will be called above */
+ if (nodaemon) {
+ if (realtime)
+ setscheduler();
+ }
+#endif
-#ifdef _POSIX_PRIORITY_SCHEDULING
- if (realtime)
- setscheduler();
+ signal(SIGCHLD, SIG_IGN); /* ignore child */
+ signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGHUP, signal_handler); /* catch hangup signal */
+ signal(SIGTERM, signal_handler); /* catch kill signal */
+
+ /* Build system string */
+ if (uname(&utsbuf) == 0) {
+ snprintf(system_string, 64, "%s %s", utsbuf.sysname, utsbuf.machine);
+ snprintf(version_string, 64, "%s", utsbuf.release);
+ }
+ else {
+ snprintf(system_string, 64, "unknown unknown");
+ snprintf(version_string, 64, "unknown");
+ }
+
+ /* Initializing */
+ SSLi_init();
+ Chan_init();
+ Client_init();
+ Ban_init();
+
+#ifdef USE_SHAREDMEMORY_API
+ Sharedmemory_init( bindport, bindport6 );
#endif
-
- Server_run();
-
- SSLi_deinit();
- Chan_free();
- Log_free();
- Conf_deinit();
-
- if (pidfile != NULL)
- unlink(pidfile);
-
- return 0;
-}
+
+ Server_run();
+
+#ifdef USE_SHAREDMEMORY_API
+ Sharedmemory_deinit();
+#endif
+
+ Ban_deinit();
+ SSLi_deinit();
+ Chan_free();
+ Log_free();
+ Conf_deinit();
+
+ if (pidfile != NULL)
+ unlink(pidfile);
+
+ return 0;
+ }