5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2003 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
21 * Created: Wed Mar 19 00:17:12 1997
23 * This is the main program for the SILC daemon. This parses command
24 * line arguments and creates the server object.
28 #include "serverincludes.h"
29 #include "server_internal.h"
30 #include "silcversion.h"
32 /* For now, we'll have this one server context global for this module. */
33 static SilcServer silcd;
35 static void silc_usage(void);
37 /* Long command line options */
38 static struct option long_opts[] =
40 { "config-file", 1, NULL, 'f' },
41 { "passphrase", 1, NULL, 'p' },
42 { "debug", 2, NULL, 'd' },
43 { "debug-level", 1, NULL, 'D' },
44 { "hexdump", 0, NULL, 'x' },
45 { "help", 0, NULL, 'h' },
46 { "foreground", 0, NULL, 'F' },
47 { "version", 0, NULL,'V' },
49 /* Key management options */
50 { "create-key-pair", 1, NULL, 'C' },
51 { "pkcs", 1, NULL, 10 },
52 { "bits", 1, NULL, 11 },
53 { "identifier", 1, NULL, 12 },
58 /* Command line option variables */
59 static char *opt_keypath = NULL;
60 static char *opt_pkcs = "rsa";
61 static char *opt_identifier = NULL;
62 static int opt_bits = 2048;
64 /* Prints out the usage of silc client */
66 static void silc_usage(void)
69 "Usage: silcd [options]\n"
72 " -f --config-file=FILE Alternate configuration file\n"
73 " -d --debug=string Enable debugging (Implies --foreground)\n"
74 " -D --debug-level=level Enable debugging (Implies --foreground)\n"
75 " -x --hexdump Enable hexdumps (Implies --debug)\n"
76 " -h --help Display this message\n"
77 " -F --foreground Dont fork\n"
78 " -V --version Display version\n"
80 " Key Management Options:\n"
81 " -C, --create-key-pair=PATH Create new public key pair\n"
82 " --pkcs=PKCS Set the PKCS of the public key pair\n"
83 " --bits=VALUE Set length of the public key pair\n"
84 " --identifier=IDENTIFIER Public key identifier\n"
86 " The public key identifier may be of the following format:\n"
88 " UN=<username>, HN=<hostname or IP>, RN=<real name>, E=<email>,\n"
89 " O=<organization>, C=<country>\n"
91 " The UN and HN must be provided, the others are optional. If the\n"
92 " --identifier option is not used an identifier will be created for\n"
93 " the public key automatically.\n"
95 " Example identifier: \"UN=foobar, HN=foo.bar.com, RN=Foo T. Bar, \n"
96 " E=foo@bar.com, C=FI\"\n"
101 /* Die if a *valid* pid file exists already */
103 static void silc_server_checkpid(SilcServer silcd)
105 if (silcd->config->server_info->pid_file) {
110 SILC_LOG_DEBUG(("Checking for another silcd running"));
111 buf = silc_file_readfile(silcd->config->server_info->pid_file, &buf_len);
118 kill(oldpid, SIGCHLD); /* this signal does nothing, check if alive */
119 if (errno != ESRCH) {
120 fprintf(stderr, "\nI detected another daemon running with the "
122 fprintf(stderr, "Please change the config file, or erase the %s\n",
123 silcd->config->server_info->pid_file);
129 /* Drop root privileges. If some system call fails, die. */
131 static void silc_server_drop_privs(SilcServer server)
133 /* Are we executing silcd as root or a regular user? */
135 SILC_LOG_DEBUG(("Server started as user"));
142 SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
144 /* Get the values given for user and group in configuration file */
145 user = server->config->server_info->user;
146 group = server->config->server_info->group;
148 if (!user || !group) {
149 fprintf(stderr, "Error:"
150 "\tSILC server must not be run as root. For the security of your\n"
151 "\tsystem it is strongly suggested that you run SILC under dedicated\n"
152 "\tuser account. Modify the ServerInfo configuration section to run\n"
153 "\tthe server as non-root user.\n");
157 /* Check whether the user/group does not begin with a number */
158 if (isdigit(user[0]) || isdigit(group[0])) {
159 SILC_LOG_DEBUG(("User and/or group starts with a number"));
160 fprintf(stderr, "Invalid user and/or group information\n");
161 fprintf(stderr, "Please assign them as names, not numbers\n");
165 if (!(pw = getpwnam(user))) {
166 fprintf(stderr, "Error: No such user %s found.\n", user);
169 if (!(gr = getgrnam(group))) {
170 fprintf(stderr, "Error: No such group %s found.\n", group);
174 /* Check whether user and/or group is set to root. If yes, exit
175 immediately. Otherwise, setgid and setuid server to user.group */
176 if ((gr->gr_gid == 0) || (pw->pw_uid == 0)) {
177 fprintf(stderr, "Error:"
178 "\tSILC server must not be run as root. For the security of your\n"
179 "\tsystem it is strongly suggested that you run SILC under dedicated\n"
180 "\tuser account. Modify the ServerInfo configuration section to run\n"
181 "\tthe server as non-root user.\n");
185 SILC_LOG_DEBUG(("Changing to group %s (gid=%u)", group, gr->gr_gid));
186 if (setgid(gr->gr_gid) != 0) {
187 fprintf(stderr, "Error: Failed setgid() to %s (gid=%u). Exiting.\n",
191 #if defined HAVE_SETGROUPS && defined HAVE_INITGROUPS
192 SILC_LOG_DEBUG(("Removing supplementary groups"));
193 if (setgroups(0, NULL) != 0) {
194 fprintf(stderr, "Error: Failed setgroups() to NULL. Exiting.\n");
197 SILC_LOG_DEBUG(("Setting supplementary groups for user %s", user));
198 if (initgroups(user, gr->gr_gid) != 0) {
199 fprintf(stderr, "Error: Failed initgroups() for user %s (gid=%u). "
200 "Exiting.\n", user, gr->gr_gid);
204 SILC_LOG_DEBUG(("Changing to user %s (uid=%u)", user, pw->pw_uid));
205 if (setuid(pw->pw_uid) != 0) {
206 fprintf(stderr, "Error: Failed to setuid() to %s (gid=%u). Exiting.\n",
213 /* Fork server to background */
215 static void silc_server_daemonise(SilcServer server)
219 SILC_LOG_DEBUG(("Forking SILC server to background"));
221 if ((i = fork()) < 0) {
222 fprintf(stderr, "Error: fork() failed: %s\n", strerror(errno));
226 if (i) /* Kill the parent */
229 server->background = TRUE;
232 /* XXX close stdin, stdout, stderr -- before this, check that all writes
233 to stderr are changed to SILC_SERVER_LOG_ERROR() */
236 static void signal_handler(int sig)
238 /* Mark the signal to be caller after this signal is over. */
239 silc_schedule_signal_call(silcd->schedule, sig);
242 SILC_TASK_CALLBACK(got_hup)
244 /* First, reset all log files (they might have been deleted) */
245 silc_log_reset_all();
247 /* Rehash the configuration file */
248 silc_server_rehash(silcd);
251 SILC_TASK_CALLBACK(stop_server)
253 /* Stop scheduler, the program will stop eventually after noticing
254 that the scheduler is down. */
255 silc_schedule_stop(silcd->schedule);
258 /* Dump server statistics into a file into /tmp directory */
260 SILC_TASK_CALLBACK(dump_stats)
265 memset(filename, 0, sizeof(filename));
266 snprintf(filename, sizeof(filename) - 1, "/tmp/silcd.%d.stats", getpid());
267 fdd = fopen(filename, "w+");
271 #define STAT_OUTPUT(fmt, stat) fprintf(fdd, fmt "\n", (int)stat);
273 fprintf(fdd, "SILC Server %s Statistics\n\n", silcd->server_name);
274 fprintf(fdd, "Local Stats:\n");
275 STAT_OUTPUT(" My clients : %d", silcd->stat.my_clients);
276 STAT_OUTPUT(" My servers : %d", silcd->stat.my_servers);
277 STAT_OUTPUT(" My routers : %d", silcd->stat.my_routers);
278 STAT_OUTPUT(" My channels : %d", silcd->stat.my_channels);
279 STAT_OUTPUT(" My joined users : %d", silcd->stat.my_chanclients);
280 STAT_OUTPUT(" My aways : %d", silcd->stat.my_aways);
281 STAT_OUTPUT(" My detached clients : %d", silcd->stat.my_detached);
282 STAT_OUTPUT(" My server operators : %d", silcd->stat.my_server_ops);
283 STAT_OUTPUT(" My router operators : %d", silcd->stat.my_router_ops);
284 fprintf(fdd, "\nGlobal Stats:\n");
285 STAT_OUTPUT(" Cell clients : %d", silcd->stat.cell_clients);
286 STAT_OUTPUT(" Cell servers : %d", silcd->stat.cell_servers);
287 STAT_OUTPUT(" Cell channels : %d", silcd->stat.cell_channels);
288 STAT_OUTPUT(" Cell joined users : %d", silcd->stat.cell_chanclients);
289 STAT_OUTPUT(" All clients : %d", silcd->stat.clients);
290 STAT_OUTPUT(" All servers : %d", silcd->stat.servers);
291 STAT_OUTPUT(" All routers : %d", silcd->stat.routers);
292 STAT_OUTPUT(" All channels : %d", silcd->stat.channels);
293 STAT_OUTPUT(" All joined users : %d", silcd->stat.chanclients);
294 STAT_OUTPUT(" All aways : %d", silcd->stat.aways);
295 STAT_OUTPUT(" All detached clients : %d", silcd->stat.detached);
296 STAT_OUTPUT(" All server operators : %d", silcd->stat.server_ops);
297 STAT_OUTPUT(" All router operators : %d", silcd->stat.router_ops);
298 fprintf(fdd, "\nGeneral Stats:\n");
299 STAT_OUTPUT(" Connection attempts : %d", silcd->stat.conn_attempts);
300 STAT_OUTPUT(" Connection failures : %d", silcd->stat.conn_failures);
301 STAT_OUTPUT(" Authentication attempts : %d", silcd->stat.auth_attempts);
302 STAT_OUTPUT(" Authentication failures : %d", silcd->stat.auth_failures);
303 STAT_OUTPUT(" Packets sent : %d", silcd->stat.packets_sent);
304 STAT_OUTPUT(" Packets received : %d", silcd->stat.packets_received);
305 STAT_OUTPUT(" Connections : %d", silcd->stat.conn_num);
310 /* Dump internal flags */
311 fprintf(fdd, "\nDumping internal flags\n");
312 fprintf(fdd, " server_type : %d\n", silcd->server_type);
313 fprintf(fdd, " standalone : %d\n", silcd->standalone);
314 fprintf(fdd, " listenning : %d\n", silcd->listenning);
315 fprintf(fdd, " background : %d\n", silcd->background);
316 fprintf(fdd, " backup_router : %d\n", silcd->backup_router);
317 fprintf(fdd, " backup_primary : %d\n", silcd->backup_primary);
318 fprintf(fdd, " backup_noswitch : %d\n", silcd->backup_noswitch);
319 fprintf(fdd, " backup_closed : %d\n", silcd->backup_closed);
320 fprintf(fdd, " wait_backup : %d\n", silcd->wait_backup);
322 fprintf(fdd, " primary router : %s\n",
323 silcd->router->server_name ? silcd->router->server_name : "");
325 /* Dump socket connections */
328 SilcSocketConnection s;
330 fprintf(fdd, "\nDumping socket connections\n");
331 for (i = 0; i < silcd->config->param.connections_max; i++) {
332 s = silcd->sockets[i];
335 fprintf(fdd, " %d: host %s ip %s port %d type %d flags 0x%x\n",
336 s->sock, s->hostname ? s->hostname : "N/A",
337 s->ip ? s->ip : "N/A", s->port, s->type,
338 (unsigned int)s->flags);
344 SilcIDCacheList list = NULL;
345 SilcIDCacheEntry id_cache = NULL;
346 SilcServerEntry server_entry;
347 SilcClientEntry client_entry;
348 SilcChannelEntry channel_entry;
351 fprintf(fdd, "\nDumping databases\n");
353 if (silc_idcache_get_all(silcd->local_list->servers, &list)) {
354 if (silc_idcache_list_first(list, &id_cache)) {
355 fprintf(fdd, "\nServers in local-list:\n");
358 server_entry = (SilcServerEntry)id_cache->context;
359 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
360 server_entry->server_name ? server_entry->server_name :
361 "N/A", server_entry->id ?
362 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
363 server_entry->data.status);
364 if (!silc_idcache_list_next(list, &id_cache))
369 silc_idcache_list_free(list);
371 if (silc_idcache_get_all(silcd->global_list->servers, &list)) {
372 if (silc_idcache_list_first(list, &id_cache)) {
373 fprintf(fdd, "\nServers in global-list:\n");
376 server_entry = (SilcServerEntry)id_cache->context;
377 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
378 server_entry->server_name ? server_entry->server_name :
379 "N/A", server_entry->id ?
380 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
381 server_entry->data.status);
382 if (!silc_idcache_list_next(list, &id_cache))
387 silc_idcache_list_free(list);
389 if (silc_idcache_get_all(silcd->local_list->clients, &list)) {
390 if (silc_idcache_list_first(list, &id_cache)) {
391 fprintf(fdd, "\nClients in local-list:\n");
394 client_entry = (SilcClientEntry)id_cache->context;
395 server_entry = client_entry->router;
396 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
397 client_entry->nickname ? client_entry->nickname :
398 (unsigned char *)"N/A", client_entry->id ?
399 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
400 client_entry->data.status, server_entry ?
401 server_entry->server_name ? server_entry->server_name :
403 if (!silc_idcache_list_next(list, &id_cache))
408 silc_idcache_list_free(list);
410 if (silc_idcache_get_all(silcd->global_list->clients, &list)) {
411 if (silc_idcache_list_first(list, &id_cache)) {
412 fprintf(fdd, "\nClients in global-list:\n");
415 client_entry = (SilcClientEntry)id_cache->context;
416 server_entry = client_entry->router;
417 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
418 client_entry->nickname ? client_entry->nickname :
419 (unsigned char *)"N/A", client_entry->id ?
420 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
421 client_entry->data.status, server_entry ?
422 server_entry->server_name ? server_entry->server_name :
424 if (!silc_idcache_list_next(list, &id_cache))
429 silc_idcache_list_free(list);
431 if (silc_idcache_get_all(silcd->local_list->channels, &list)) {
432 if (silc_idcache_list_first(list, &id_cache)) {
433 fprintf(fdd, "\nChannels in local-list:\n");
436 channel_entry = (SilcChannelEntry)id_cache->context;
437 fprintf(fdd, " %d: name %s id %s\n", c,
438 channel_entry->channel_name ? channel_entry->channel_name :
439 "N/A", channel_entry->id ?
440 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
441 if (!silc_idcache_list_next(list, &id_cache))
446 silc_idcache_list_free(list);
448 if (silc_idcache_get_all(silcd->global_list->channels, &list)) {
449 if (silc_idcache_list_first(list, &id_cache)) {
450 fprintf(fdd, "\nChannels in global-list:\n");
453 channel_entry = (SilcChannelEntry)id_cache->context;
454 fprintf(fdd, " %d: name %s id %s\n", c,
455 channel_entry->channel_name ? channel_entry->channel_name :
456 "N/A", channel_entry->id ?
457 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
458 if (!silc_idcache_list_next(list, &id_cache))
463 silc_idcache_list_free(list);
479 static DebugLevel debug_levels[] = {
480 /* Very basic stuff from silcd/ */
481 { 3, "silcd\\.c,server\\.c" },
483 /* More stuff from silcd/ */
484 { 7, "silcd\\.c,server\\.c,command\\.c,server_backup\\.c,packet_send\\.c" },
486 /* All basic stuff from silcd/ */
487 { 10, "silc_server_*" },
489 /* All from silcd/ */
490 { 15, "*silcd*,*serverid*,silc_server_*,*idlist*" },
492 /* All from silcd/ and basic stuff from libs */
493 { 20, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,*silcske*" },
495 /* All from silcd/ and more stuff from libs */
496 { 25, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
497 "*silcpacket*,*ske*,*silcrng*" },
499 /* All from silcd/ and even more stuff from libs */
500 { 30, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
501 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*" },
503 /* All from silcd/ and even more stuff from libs + all from silccore */
504 { 35, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
505 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
506 "*silcid*,*argument*" },
508 /* All from silcd/, all from silccore, silccrypt and silcmath */
509 { 40, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
510 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
511 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*" },
513 /* All from silcd/, all from silccore, silccrypt and silcmath + stuff
515 { 45, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
516 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
517 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
520 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
522 { 50, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
523 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
524 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
525 "*sockconn*,*net*" },
527 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
529 { 55, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
530 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
531 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
532 "*sockconn*,*net*,*log*,*config*" },
540 static void silc_get_debug_level(int level)
547 for (i = 0; debug_levels[i].string; i++)
548 if (level <= debug_levels[i].level) {
549 silc_log_set_debug_string(debug_levels[i].string);
553 #endif /* SILC_DEBUG */
555 /* This function should not be called directly but through the appropriate
556 wrapper macro defined in server.h */
558 void silc_server_stderr(SilcLogType type, char *message)
560 if (silcd->background) {
561 char *p, *n = message;
563 /* remove newlines if we are going to output it to a log file */
564 for (p = n; *p; p++) {
573 /* the message is freed inside the logging function */
574 silc_log_output(type, message);
577 fprintf(stderr, "%s\n", message);
582 int main(int argc, char **argv)
584 int ret, opt, option_index;
585 bool foreground = FALSE;
586 bool opt_create_keypair = FALSE;
587 char *silcd_config_file = NULL;
590 /* Parse command line arguments */
592 while ((opt = getopt_long(argc, argv, "f:p:d:D:xhFVC:",
593 long_opts, &option_index)) != EOF) {
599 printf("SILCd Secure Internet Live Conferencing daemon, "
600 "version %s (base: SILC Toolkit %s)\n",
601 silc_dist_version, silc_version);
602 printf("(c) 1997 - 2005 Pekka Riikonen "
603 "<priikone@silcnet.org>\n");
610 silc_log_set_debug_string(optarg);
611 foreground = TRUE; /* implied */
612 silc_log_quick = TRUE; /* implied */
615 "Run-time debugging is not enabled. To enable it recompile\n"
616 "the server with --enable-debug configuration option.\n");
623 silc_get_debug_level(atoi(optarg));
624 foreground = TRUE; /* implied */
625 silc_log_quick = TRUE; /* implied */
628 "Run-time debugging is not enabled. To enable it recompile\n"
629 "the server with --enable-debug configuration option.\n");
634 silc_debug_hexdump = TRUE;
635 silc_debug = TRUE; /* implied */
636 foreground = TRUE; /* implied */
637 silc_log_quick = TRUE; /* implied */
640 "Run-time debugging is not enabled. To enable it recompile\n"
641 "the server with --enable-debug configuration option.\n");
645 silcd_config_file = strdup(optarg);
652 * Key management options
655 opt_create_keypair = TRUE;
657 opt_keypath = strdup(optarg);
661 opt_pkcs = strdup(optarg);
665 opt_bits = atoi(optarg);
669 opt_identifier = strdup(optarg);
679 if (opt_create_keypair == TRUE) {
680 /* Create new key pair and exit */
681 char pubfile[256], prvfile[256];
683 memset(pubfile, 0, sizeof(pubfile));
684 memset(prvfile, 0, sizeof(prvfile));
685 snprintf(pubfile, sizeof(pubfile) - 1, "%s/silcd.pub", opt_keypath);
686 snprintf(prvfile, sizeof(prvfile) - 1, "%s/silcd.prv", opt_keypath);
688 silc_cipher_register_default();
689 silc_pkcs_register_default();
690 silc_hash_register_default();
691 silc_hmac_register_default();
692 silc_create_key_pair(opt_pkcs, opt_bits, pubfile, prvfile,
693 opt_identifier, "", NULL, NULL, NULL, FALSE);
697 /* Default configuration file */
698 if (!silcd_config_file)
699 silcd_config_file = strdup(SILC_SERVER_CONFIG_FILE);
701 /* Create SILC Server object */
702 ret = silc_server_alloc(&silcd);
706 /* Register default crypto stuff since we are going to need them
707 in the configuration file parsing phase */
708 silc_cipher_register_default();
709 silc_pkcs_register_default();
710 silc_hash_register_default();
711 silc_hmac_register_default();
713 /* Read configuration files */
714 silcd->config = silc_server_config_alloc(silcd_config_file);
715 if (silcd->config == NULL)
717 silcd->config_file = silcd_config_file;
719 /* Unregister the default crypto stuff so that configuration takes effect */
720 silc_cipher_unregister_all();
721 silc_pkcs_unregister_all();
722 silc_hash_unregister_all();
723 silc_hmac_unregister_all();
725 /* Check for another silcd running */
726 silc_server_checkpid(silcd);
728 /* Initialize the server */
729 if (silc_server_init(silcd) == FALSE)
732 /* Ignore some signals */
733 sa.sa_handler = SIG_IGN;
735 sigemptyset(&sa.sa_mask);
737 sigaction(SIGPIPE, &sa, NULL); /* Ignore broken pipes */
740 sigaction(SIGXFSZ, &sa, NULL); /* Ignore file limit exceeds */
743 sigaction(SIGXCPU, &sa, NULL); /* Ignore CPU time limit exceeds */
746 /* Handle specificly some other signals. */
747 sa.sa_handler = signal_handler;
748 sigaction(SIGHUP, &sa, NULL);
749 sigaction(SIGTERM, &sa, NULL);
750 sigaction(SIGINT, &sa, NULL);
751 sigaction(SIGUSR1, &sa, NULL);
752 silc_schedule_signal_register(silcd->schedule, SIGHUP, got_hup, NULL);
753 silc_schedule_signal_register(silcd->schedule, SIGTERM, stop_server, NULL);
754 silc_schedule_signal_register(silcd->schedule, SIGINT, stop_server, NULL);
755 silc_schedule_signal_register(silcd->schedule, SIGUSR1, dump_stats, NULL);
758 /* Before running the server, fork to background. */
759 silc_server_daemonise(silcd);
761 /* If set, write pid to file */
762 if (silcd->config->server_info->pid_file) {
763 char buf[10], *pidfile = silcd->config->server_info->pid_file;
765 snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
766 silc_file_writefile(pidfile, buf, strlen(buf));
770 /* Drop root if we are not in debug mode, so you don't need to bother about
771 file writing permissions and so on */
773 silc_server_drop_privs(silcd);
775 /* Run the server. When this returns the server has been stopped
777 silc_server_run(silcd);
779 /* Stop the server and free it. */
780 silc_server_stop(silcd);
781 silc_server_config_destroy(silcd->config);
782 silc_server_free(silcd);
784 /* Flush the logging system */
785 silc_log_flush_all();
787 silc_free(silcd_config_file);
788 silc_free(opt_identifier);
789 silc_free(opt_keypath);
793 silc_free(silcd_config_file);
794 silc_free(opt_identifier);
795 silc_free(opt_keypath);