5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 * Created: Wed Mar 19 00:17:12 1997
22 * This is the main program for the SILC daemon. This parses command
23 * line arguments and creates the server object.
27 #include "serverincludes.h"
28 #include "server_internal.h"
29 #include "silcversion.h"
31 /* For now, we'll have this one server context global for this module. */
32 static SilcServer silcd;
34 static void silc_usage(void);
36 #ifdef HAVE_GETOPT_LONG
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 },
57 #endif /* HAVE_GETOPT_LONG */
59 /* Command line option variables */
60 static char *opt_keypath = NULL;
61 static char *opt_pkcs = "rsa";
62 static char *opt_identifier = NULL;
63 static int opt_bits = 2048;
65 /* Prints out the usage of silc client */
67 static void silc_usage(void)
70 "Usage: silcd [options]\n"
73 " -f --config-file=FILE Alternate configuration file\n"
74 " -d --debug=string Enable debugging (Implies --foreground)\n"
75 " -D --debug-level=level Enable debugging (Implies --foreground)\n"
76 " -x --hexdump Enable hexdumps (Implies --debug)\n"
77 " -h --help Display this message\n"
78 " -F --foreground Dont fork\n"
79 " -V --version Display version\n"
81 " Key Management Options:\n"
82 " -C, --create-key-pair=PATH Create new public key pair\n"
83 " --pkcs=PKCS Set the PKCS of the public key pair\n"
84 " --bits=VALUE Set length of the public key pair\n"
85 " --identifier=IDENTIFIER Public key identifier\n"
87 " The public key identifier may be of the following format:\n"
89 " UN=<username>, HN=<hostname or IP>, RN=<real name>, E=<email>,\n"
90 " O=<organization>, C=<country>\n"
92 " The UN and HN must be provided, the others are optional. If the\n"
93 " --identifier option is not used an identifier will be created for\n"
94 " the public key automatically.\n"
96 " Example identifier: \"UN=foobar, HN=foo.bar.com, RN=Foo T. Bar, \n"
97 " E=foo@bar.com, C=FI\"\n"
102 /* Die if a *valid* pid file exists already */
104 static void silc_server_checkpid(SilcServer silcd)
106 if (silcd->config->server_info->pid_file) {
111 SILC_LOG_DEBUG(("Checking for another silcd running"));
112 buf = silc_file_readfile(silcd->config->server_info->pid_file, &buf_len);
119 kill(oldpid, SIGCHLD); /* this signal does nothing, check if alive */
120 if (errno != ESRCH) {
121 fprintf(stderr, "\nI detected another daemon running with the "
123 fprintf(stderr, "Please change the config file, or erase the %s\n",
124 silcd->config->server_info->pid_file);
130 /* Drop root privileges. If some system call fails, die. */
132 static void silc_server_drop_privs(SilcServer server)
134 /* Are we executing silcd as root or a regular user? */
136 SILC_LOG_DEBUG(("Server started as user"));
143 SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
145 /* Get the values given for user and group in configuration file */
146 user = server->config->server_info->user;
147 group = server->config->server_info->group;
149 if (!user || !group) {
150 fprintf(stderr, "Error:"
151 "\tSILC server must not be run as root. For the security of your\n"
152 "\tsystem it is strongly suggested that you run SILC under dedicated\n"
153 "\tuser account. Modify the ServerInfo configuration section to run\n"
154 "\tthe server as non-root user.\n");
158 /* Check whether the user/group does not begin with a number */
159 if (isdigit(user[0]) || isdigit(group[0])) {
160 SILC_LOG_DEBUG(("User and/or group starts with a number"));
161 fprintf(stderr, "Invalid user and/or group information\n");
162 fprintf(stderr, "Please assign them as names, not numbers\n");
166 if (!(pw = getpwnam(user))) {
167 fprintf(stderr, "Error: No such user %s found.\n", user);
170 if (!(gr = getgrnam(group))) {
171 fprintf(stderr, "Error: No such group %s found.\n", group);
175 /* Check whether user and/or group is set to root. If yes, exit
176 immediately. Otherwise, setgid and setuid server to user.group */
177 if ((gr->gr_gid == 0) || (pw->pw_uid == 0)) {
178 fprintf(stderr, "Error:"
179 "\tSILC server must not be run as root. For the security of your\n"
180 "\tsystem it is strongly suggested that you run SILC under dedicated\n"
181 "\tuser account. Modify the ServerInfo configuration section to run\n"
182 "\tthe server as non-root user.\n");
186 SILC_LOG_DEBUG(("Changing to group %s (gid=%u)", group, gr->gr_gid));
187 if (setgid(gr->gr_gid) != 0) {
188 fprintf(stderr, "Error: Failed setgid() to %s (gid=%u). Exiting.\n",
192 #if defined HAVE_SETGROUPS && defined HAVE_INITGROUPS
193 SILC_LOG_DEBUG(("Removing supplementary groups"));
194 if (setgroups(0, NULL) != 0) {
195 fprintf(stderr, "Error: Failed setgroups() to NULL. Exiting.\n");
198 SILC_LOG_DEBUG(("Setting supplementary groups for user %s", user));
199 if (initgroups(user, gr->gr_gid) != 0) {
200 fprintf(stderr, "Error: Failed initgroups() for user %s (gid=%u). "
201 "Exiting.\n", user, gr->gr_gid);
205 SILC_LOG_DEBUG(("Changing to user %s (uid=%u)", user, pw->pw_uid));
206 if (setuid(pw->pw_uid) != 0) {
207 fprintf(stderr, "Error: Failed to setuid() to %s (gid=%u). Exiting.\n",
214 /* Fork server to background */
216 static void silc_server_daemonise(SilcServer server)
220 SILC_LOG_DEBUG(("Forking SILC server to background"));
222 if ((i = fork()) < 0) {
223 fprintf(stderr, "Error: fork() failed: %s\n", strerror(errno));
227 if (i) /* Kill the parent */
230 server->background = TRUE;
233 /* XXX close stdin, stdout, stderr -- before this, check that all writes
234 to stderr are changed to SILC_SERVER_LOG_ERROR() */
237 SILC_TASK_CALLBACK(got_hup)
239 /* First, reset all log files (they might have been deleted) */
240 silc_log_reset_all();
242 /* Rehash the configuration file */
243 silc_server_rehash(silcd);
246 SILC_TASK_CALLBACK(stop_server)
248 silc_server_stop(silcd);
251 /* Dump server statistics into a file into /tmp directory */
253 SILC_TASK_CALLBACK(dump_stats)
259 memset(filename, 0, sizeof(filename));
260 snprintf(filename, sizeof(filename) - 1, "/tmp/silcd.%d.stats-XXXXXX", getpid());
261 fild = mkstemp(filename);
265 fdd = fdopen(fild, "w");
272 #define STAT_OUTPUT(fmt, stat) fprintf(fdd, fmt "\n", (int)stat);
274 fprintf(fdd, "SILC Server %s Statistics\n\n", silcd->server_name);
275 fprintf(fdd, "Local Stats:\n");
276 STAT_OUTPUT(" My clients : %d", silcd->stat.my_clients);
277 STAT_OUTPUT(" My servers : %d", silcd->stat.my_servers);
278 STAT_OUTPUT(" My routers : %d", silcd->stat.my_routers);
279 STAT_OUTPUT(" My channels : %d", silcd->stat.my_channels);
280 STAT_OUTPUT(" My joined users : %d", silcd->stat.my_chanclients);
281 STAT_OUTPUT(" My aways : %d", silcd->stat.my_aways);
282 STAT_OUTPUT(" My detached clients : %d", silcd->stat.my_detached);
283 STAT_OUTPUT(" My server operators : %d", silcd->stat.my_server_ops);
284 STAT_OUTPUT(" My router operators : %d", silcd->stat.my_router_ops);
285 fprintf(fdd, "\nGlobal Stats:\n");
286 STAT_OUTPUT(" Cell clients : %d", silcd->stat.cell_clients);
287 STAT_OUTPUT(" Cell servers : %d", silcd->stat.cell_servers);
288 STAT_OUTPUT(" Cell channels : %d", silcd->stat.cell_channels);
289 STAT_OUTPUT(" Cell joined users : %d", silcd->stat.cell_chanclients);
290 STAT_OUTPUT(" All clients : %d", silcd->stat.clients);
291 STAT_OUTPUT(" All servers : %d", silcd->stat.servers);
292 STAT_OUTPUT(" All routers : %d", silcd->stat.routers);
293 STAT_OUTPUT(" All channels : %d", silcd->stat.channels);
294 STAT_OUTPUT(" All joined users : %d", silcd->stat.chanclients);
295 STAT_OUTPUT(" All aways : %d", silcd->stat.aways);
296 STAT_OUTPUT(" All detached clients : %d", silcd->stat.detached);
297 STAT_OUTPUT(" All server operators : %d", silcd->stat.server_ops);
298 STAT_OUTPUT(" All router operators : %d", silcd->stat.router_ops);
299 fprintf(fdd, "\nGeneral Stats:\n");
300 STAT_OUTPUT(" Connection attempts : %d", silcd->stat.conn_attempts);
301 STAT_OUTPUT(" Connection failures : %d", silcd->stat.conn_failures);
302 STAT_OUTPUT(" Authentication attempts : %d", silcd->stat.auth_attempts);
303 STAT_OUTPUT(" Authentication failures : %d", silcd->stat.auth_failures);
304 STAT_OUTPUT(" Packets sent : %d", silcd->stat.packets_sent);
305 STAT_OUTPUT(" Packets received : %d", silcd->stat.packets_received);
306 STAT_OUTPUT(" Commands sent : %d", silcd->stat.commands_sent);
307 STAT_OUTPUT(" Commands received : %d", silcd->stat.commands_received);
308 STAT_OUTPUT(" Connections : %d", silcd->stat.conn_num);
313 /* Dump internal flags */
314 fprintf(fdd, "\nDumping internal flags\n");
315 fprintf(fdd, " server_type : %d\n", silcd->server_type);
316 fprintf(fdd, " standalone : %d\n", silcd->standalone);
317 fprintf(fdd, " listenning : %d\n", silcd->listenning);
318 fprintf(fdd, " background : %d\n", silcd->background);
319 fprintf(fdd, " backup_router : %d\n", silcd->backup_router);
320 fprintf(fdd, " backup_primary : %d\n", silcd->backup_primary);
321 fprintf(fdd, " backup_noswitch : %d\n", silcd->backup_noswitch);
322 fprintf(fdd, " backup_closed : %d\n", silcd->backup_closed);
323 fprintf(fdd, " wait_backup : %d\n", silcd->wait_backup);
325 fprintf(fdd, " primary router : %s\n",
326 silcd->router->server_name ? silcd->router->server_name : "");
328 /* Dump connections */
331 SilcDList conns = silc_packet_engine_get_streams(silcd->packet_engine);
333 fprintf(fdd, "\nDumping connections\n");
334 silc_dlist_start(conns);
335 while ((s = silc_dlist_get(conns))) {
336 const char *hostname, *ip;
339 SilcIDListData idata = silc_packet_get_context(s);
340 if (!silc_socket_stream_get_info(silc_packet_stream_get_stream(s),
341 &sock, &hostname, &ip, &port))
343 fprintf(fdd, " %d: host %s ip %s port %d type %d\n",
344 sock, hostname ? hostname : "N/A",
345 ip ? ip : "N/A", port, idata ? idata->conn_type : 0);
347 silc_dlist_uninit(conns);
353 SilcIDCacheEntry id_cache = NULL;
354 SilcServerEntry server_entry;
355 SilcClientEntry client_entry;
356 SilcChannelEntry channel_entry;
359 fprintf(fdd, "\nDumping databases\n");
361 if (silc_idcache_get_all(silcd->local_list->servers, &list)) {
363 fprintf(fdd, "\nServers in local-list:\n");
364 while ((id_cache = silc_list_get(list))) {
365 server_entry = (SilcServerEntry)id_cache->context;
366 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
367 server_entry->server_name ? server_entry->server_name :
368 "N/A", server_entry->id ?
369 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
370 server_entry->data.status);
374 if (silc_idcache_get_all(silcd->global_list->servers, &list)) {
375 fprintf(fdd, "\nServers in global-list:\n");
377 while ((id_cache = silc_list_get(list))) {
378 server_entry = (SilcServerEntry)id_cache->context;
379 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
380 server_entry->server_name ? server_entry->server_name :
381 "N/A", server_entry->id ?
382 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
383 server_entry->data.status);
387 if (silc_idcache_get_all(silcd->local_list->clients, &list)) {
388 fprintf(fdd, "\nClients in local-list:\n");
390 while ((id_cache = silc_list_get(list))) {
391 client_entry = (SilcClientEntry)id_cache->context;
392 server_entry = client_entry->router;
393 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
394 client_entry->nickname ? client_entry->nickname :
395 (unsigned char *)"N/A", client_entry->id ?
396 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
397 client_entry->data.status, server_entry ?
398 server_entry->server_name ? server_entry->server_name :
403 if (silc_idcache_get_all(silcd->global_list->clients, &list)) {
404 fprintf(fdd, "\nClients in global-list:\n");
406 while ((id_cache = silc_list_get(list))) {
407 client_entry = (SilcClientEntry)id_cache->context;
408 server_entry = client_entry->router;
409 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
410 client_entry->nickname ? client_entry->nickname :
411 (unsigned char *)"N/A", client_entry->id ?
412 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
413 client_entry->data.status, server_entry ?
414 server_entry->server_name ? server_entry->server_name :
419 if (silc_idcache_get_all(silcd->local_list->channels, &list)) {
420 fprintf(fdd, "\nChannels in local-list:\n");
422 while ((id_cache = silc_list_get(list))) {
423 channel_entry = (SilcChannelEntry)id_cache->context;
424 fprintf(fdd, " %d: name %s id %s\n", c,
425 channel_entry->channel_name ? channel_entry->channel_name :
426 "N/A", channel_entry->id ?
427 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
431 if (silc_idcache_get_all(silcd->global_list->channels, &list)) {
432 fprintf(fdd, "\nChannels in global-list:\n");
434 while ((id_cache = silc_list_get(list))) {
435 channel_entry = (SilcChannelEntry)id_cache->context;
436 fprintf(fdd, " %d: name %s id %s\n", c,
437 channel_entry->channel_name ? channel_entry->channel_name :
438 "N/A", channel_entry->id ?
439 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
457 static DebugLevel debug_levels[] = {
458 /* Very basic stuff from silcd/ */
459 { 3, "silcd\\.c,server\\.c" },
461 /* More stuff from silcd/ */
462 { 7, "silcd\\.c,server\\.c,command\\.c,server_backup\\.c,packet_send\\.c" },
464 /* All basic stuff from silcd/ */
465 { 10, "silc_server_*,*silc_id_create_*,*idlist*,*skr*" },
467 /* All from silcd/ */
468 { 15, "*silcd*,*serverid*,silc_server_*,*idlist*,*skr*" },
470 /* All from silcd/ and basic stuff from libs */
471 { 20, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*silcske*,"
474 /* All from silcd/ and more stuff from libs */
475 { 25, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
476 "*silcpacket*,*ske*,*silcrng*,*skr*" },
478 /* All from silcd/ and even more stuff from libs */
479 { 30, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
480 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*" },
482 /* All from silcd/ and even more stuff from libs + all from silccore */
483 { 35, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
484 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
485 "*silcid*,*argument*" },
487 /* All from silcd/, all from silccore, silccrypt and silcmath */
488 { 40, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
489 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
490 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*" },
492 /* All from silcd/, all from silccore, silccrypt and silcmath + stuff
494 { 45, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
495 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
496 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
499 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
501 { 50, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
502 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
503 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
504 "*sockconn*,*net*" },
506 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
508 { 55, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
509 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
510 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
511 "*sockconn*,*net*,*log*,*config*" },
519 static void silc_get_debug_level(int level)
526 for (i = 0; debug_levels[i].string; i++)
527 if (level <= debug_levels[i].level) {
528 silc_log_set_debug_string(debug_levels[i].string);
532 #endif /* SILC_DEBUG */
534 /* This function should not be called directly but through the appropriate
535 wrapper macro defined in server.h */
537 void silc_server_stderr(SilcLogType type, char *message)
539 if (silcd->background) {
540 char *p, *n = message;
542 /* remove newlines if we are going to output it to a log file */
543 for (p = n; *p; p++) {
552 /* the message is freed inside the logging function */
553 silc_log_output(type, message);
556 fprintf(stderr, "%s\n", message);
562 #define NUM_DEBUGS 3000
563 static char debugs[NUM_DEBUGS][128];
564 static int cur_debug = 0;
566 SilcBool silc_server_debug_callback(char *file, char *function, int line,
567 char *message, void *context)
569 SilcTimeStruct curtime;
571 /* Save the message to ring buffer */
572 silc_time_value(0, &curtime);
573 silc_snprintf(debugs[cur_debug % NUM_DEBUGS], sizeof(debugs[0]),
574 "%02d:%02d:%02d %s:%d: %s", curtime.hour,
575 curtime.minute, curtime.second, function, line,
581 #endif /* SILC_DEBUG */
583 int main(int argc, char **argv)
585 int ret, opt, option_index;
586 SilcBool foreground = FALSE;
587 SilcBool opt_create_keypair = FALSE;
588 char *silcd_config_file = NULL;
592 silc_log_set_debug_callbacks(silc_server_debug_callback, NULL, NULL, NULL);
593 #endif /* SILC_DEBUG */
595 /* Parse command line arguments */
597 #ifdef HAVE_GETOPT_LONG
598 while ((opt = getopt_long(argc, argv, "f:p:d:D:xhFVC:",
599 long_opts, &option_index)) != EOF) {
601 while ((opt = getopt(argc, argv, "f:p:d:D:xhFVC:")) != EOF) {
602 #endif /* HAVE_GETOPT_LONG */
608 printf("SILCd Secure Internet Live Conferencing daemon, "
609 "version %s (base: SILC Toolkit %s)\n",
610 silc_dist_version, silc_version);
611 printf("(c) 1997 - 2007 Pekka Riikonen "
612 "<priikone@silcnet.org>\n");
617 silc_log_debug(TRUE);
618 silc_log_quick(TRUE);
620 silc_log_set_debug_string(optarg);
621 foreground = TRUE; /* implied */
624 "Run-time debugging is not enabled. To enable it recompile\n"
625 "the server with --enable-debug configuration option.\n");
630 silc_log_debug(TRUE);
631 silc_log_quick(TRUE);
633 silc_get_debug_level(atoi(optarg));
634 foreground = TRUE; /* implied */
637 "Run-time debugging is not enabled. To enable it recompile\n"
638 "the server with --enable-debug configuration option.\n");
643 silc_log_debug(TRUE);
644 silc_log_debug_hexdump(TRUE);
645 silc_log_quick(TRUE);
646 foreground = TRUE; /* implied */
649 "Run-time debugging is not enabled. To enable it recompile\n"
650 "the server with --enable-debug configuration option.\n");
654 silcd_config_file = strdup(optarg);
661 * Key management options
664 opt_create_keypair = TRUE;
666 opt_keypath = strdup(optarg);
670 opt_pkcs = strdup(optarg);
674 opt_bits = atoi(optarg);
678 opt_identifier = strdup(optarg);
688 if (opt_create_keypair == TRUE) {
689 /* Create new key pair and exit */
690 char pubfile[256], prvfile[256];
692 memset(pubfile, 0, sizeof(pubfile));
693 memset(prvfile, 0, sizeof(prvfile));
694 snprintf(pubfile, sizeof(pubfile) - 1, "%s/silcd.pub", opt_keypath);
695 snprintf(prvfile, sizeof(prvfile) - 1, "%s/silcd.prv", opt_keypath);
697 silc_cipher_register_default();
698 silc_pkcs_register_default();
699 silc_hash_register_default();
700 silc_hmac_register_default();
701 if (!silc_create_key_pair(opt_pkcs, opt_bits, pubfile, prvfile,
702 opt_identifier, "", NULL, NULL, FALSE))
707 /* Default configuration file */
708 if (!silcd_config_file)
709 silcd_config_file = strdup(SILC_SERVER_CONFIG_FILE);
711 /* Create SILC Server object */
712 ret = silc_server_alloc(&silcd);
716 /* Register default crypto stuff since we are going to need them
717 in the configuration file parsing phase */
718 silc_cipher_register_default();
719 silc_pkcs_register_default();
720 silc_hash_register_default();
721 silc_hmac_register_default();
723 /* Read configuration files */
724 silcd->config = silc_server_config_alloc(silcd_config_file, silcd);
725 if (silcd->config == NULL)
727 silcd->config_file = silcd_config_file;
729 /* Unregister the default crypto stuff so that configuration takes effect */
730 silc_cipher_unregister_all();
731 /* silc_pkcs_unregister_all(); MUST NOT do this anymore; SilcPublicKey
732 parsed from config file references pointers so we cannot unregister */
733 silc_hash_unregister_all();
734 silc_hmac_unregister_all();
736 /* Check for another silcd running */
737 silc_server_checkpid(silcd);
739 /* Initialize the server */
740 if (silc_server_init(silcd) == FALSE)
743 /* Ignore some signals */
744 sa.sa_handler = SIG_IGN;
746 sigemptyset(&sa.sa_mask);
748 sigaction(SIGPIPE, &sa, NULL); /* Ignore broken pipes */
751 sigaction(SIGXFSZ, &sa, NULL); /* Ignore file limit exceeds */
754 sigaction(SIGXCPU, &sa, NULL); /* Ignore CPU time limit exceeds */
757 /* Handle specificly some other signals. */
758 silc_schedule_task_add_signal(silcd->schedule, SIGHUP, got_hup, NULL);
759 silc_schedule_task_add_signal(silcd->schedule, SIGTERM, stop_server, NULL);
760 silc_schedule_task_add_signal(silcd->schedule, SIGINT, stop_server, NULL);
761 silc_schedule_task_add_signal(silcd->schedule, SIGUSR1, dump_stats, NULL);
764 /* Before running the server, fork to background. */
765 silc_server_daemonise(silcd);
767 /* If set, write pid to file */
768 if (silcd->config->server_info->pid_file) {
769 char buf[10], *pidfile = silcd->config->server_info->pid_file;
771 snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
772 silc_file_writefile(pidfile, buf, strlen(buf));
776 silc_server_drop_privs(silcd);
778 /* Run the server. When this returns the server has been stopped
780 silc_server_run(silcd);
783 silc_server_config_destroy(silcd->config);
784 silc_server_free(silcd);
786 /* Flush the logging system */
787 silc_log_flush_all();
789 silc_free(silcd_config_file);
790 silc_free(opt_identifier);
791 silc_free(opt_keypath);
795 silc_free(silcd_config_file);
796 silc_free(opt_identifier);
797 silc_free(opt_keypath);