5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2014 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 = 4096;
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);
312 /* Dump internal flags */
313 fprintf(fdd, "\nDumping internal flags\n");
314 fprintf(fdd, " server_type : %d\n", silcd->server_type);
315 fprintf(fdd, " standalone : %d\n", silcd->standalone);
316 fprintf(fdd, " listenning : %d\n", silcd->listenning);
317 fprintf(fdd, " background : %d\n", silcd->background);
318 fprintf(fdd, " backup_router : %d\n", silcd->backup_router);
319 fprintf(fdd, " backup_primary : %d\n", silcd->backup_primary);
320 fprintf(fdd, " backup_noswitch : %d\n", silcd->backup_noswitch);
321 fprintf(fdd, " backup_closed : %d\n", silcd->backup_closed);
322 fprintf(fdd, " wait_backup : %d\n", silcd->wait_backup);
324 fprintf(fdd, " primary router : %s\n",
325 silcd->router->server_name ? silcd->router->server_name : "");
327 /* Dump connections */
330 SilcDList conns = silc_packet_engine_get_streams(silcd->packet_engine);
332 fprintf(fdd, "\nDumping connections\n");
333 silc_dlist_start(conns);
334 while ((s = silc_dlist_get(conns))) {
335 const char *hostname, *ip;
338 SilcIDListData idata = silc_packet_get_context(s);
339 if (!silc_socket_stream_get_info(silc_packet_stream_get_stream(s),
340 &sock, &hostname, &ip, &port))
342 fprintf(fdd, " %d: host %s ip %s port %d type %d idata %p\n",
343 sock, hostname ? hostname : "N/A",
344 ip ? ip : "N/A", port, idata ? idata->conn_type : 0, idata);
346 silc_dlist_uninit(conns);
352 SilcIDCacheEntry id_cache = NULL;
353 SilcServerEntry server_entry;
354 SilcClientEntry client_entry;
355 SilcChannelEntry channel_entry;
358 fprintf(fdd, "\nDumping databases\n");
360 if (silc_idcache_get_all(silcd->local_list->servers, &list)) {
362 fprintf(fdd, "\nServers in local-list:\n");
363 silc_list_start(list);
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 idata %p\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, server_entry);
374 if (silc_idcache_get_all(silcd->global_list->servers, &list)) {
375 fprintf(fdd, "\nServers in global-list:\n");
377 silc_list_start(list);
378 while ((id_cache = silc_list_get(list))) {
379 server_entry = (SilcServerEntry)id_cache->context;
380 fprintf(fdd, " %d: name %s id %s status 0x%x idata %p\n", c,
381 server_entry->server_name ? server_entry->server_name :
382 "N/A", server_entry->id ?
383 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
384 server_entry->data.status, server_entry);
388 if (silc_idcache_get_all(silcd->local_list->clients, &list)) {
389 fprintf(fdd, "\nClients in local-list:\n");
391 silc_list_start(list);
392 while ((id_cache = silc_list_get(list))) {
393 client_entry = (SilcClientEntry)id_cache->context;
394 server_entry = client_entry->router;
395 fprintf(fdd, " %d: name %s id %s status 0x%x from %s idata %p\n", c,
396 client_entry->nickname ? client_entry->nickname :
397 (unsigned char *)"N/A", client_entry->id ?
398 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
399 client_entry->data.status, server_entry ?
400 server_entry->server_name ? server_entry->server_name :
401 "N/A" : "local", client_entry);
405 if (silc_idcache_get_all(silcd->global_list->clients, &list)) {
406 fprintf(fdd, "\nClients in global-list:\n");
408 silc_list_start(list);
409 while ((id_cache = silc_list_get(list))) {
410 client_entry = (SilcClientEntry)id_cache->context;
411 server_entry = client_entry->router;
412 fprintf(fdd, " %d: name %s id %s status 0x%x from %s idata %p\n", c,
413 client_entry->nickname ? client_entry->nickname :
414 (unsigned char *)"N/A", client_entry->id ?
415 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
416 client_entry->data.status, server_entry ?
417 server_entry->server_name ? server_entry->server_name :
418 "N/A" : "local", client_entry);
422 if (silc_idcache_get_all(silcd->local_list->channels, &list)) {
423 fprintf(fdd, "\nChannels in local-list:\n");
425 silc_list_start(list);
426 while ((id_cache = silc_list_get(list))) {
427 channel_entry = (SilcChannelEntry)id_cache->context;
428 fprintf(fdd, " %d: name %s id %s\n", c,
429 channel_entry->channel_name ? channel_entry->channel_name :
430 "N/A", channel_entry->id ?
431 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
435 if (silc_idcache_get_all(silcd->global_list->channels, &list)) {
436 fprintf(fdd, "\nChannels in global-list:\n");
438 silc_list_start(list);
439 while ((id_cache = silc_list_get(list))) {
440 channel_entry = (SilcChannelEntry)id_cache->context;
441 fprintf(fdd, " %d: name %s id %s\n", c,
442 channel_entry->channel_name ? channel_entry->channel_name :
443 "N/A", channel_entry->id ?
444 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
461 static DebugLevel debug_levels[] = {
462 /* Very basic stuff from silcd/ */
463 { 3, "silcd\\.c,server\\.c" },
465 /* More stuff from silcd/ */
466 { 7, "silcd\\.c,server\\.c,command\\.c,server_backup\\.c,packet_send\\.c" },
468 /* All basic stuff from silcd/ */
469 { 10, "silc_server_*,*silc_id_create_*,*idlist*,*skr*" },
471 /* All from silcd/ */
472 { 15, "*silcd*,*serverid*,silc_server_*,*idlist*,*skr*" },
474 /* All from silcd/ and basic stuff from libs */
475 { 20, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*silcske*,"
478 /* All from silcd/ and more stuff from libs */
479 { 25, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
480 "*silcpacket*,*ske*,*silcrng*,*skr*" },
482 /* All from silcd/ and even more stuff from libs */
483 { 30, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
484 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*" },
486 /* All from silcd/ and even more stuff from libs + all from silccore */
487 { 35, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
488 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
489 "*silcid*,*argument*" },
491 /* All from silcd/, all from silccore, silccrypt and silcmath */
492 { 40, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
493 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
494 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*" },
496 /* All from silcd/, all from silccore, silccrypt and silcmath + stuff
498 { 45, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
499 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
500 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
503 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
505 { 50, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
506 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
507 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
508 "*sockconn*,*net*" },
510 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
512 { 55, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*skr*"
513 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
514 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
515 "*sockconn*,*net*,*log*,*config*" },
523 static void silc_get_debug_level(int level)
530 for (i = 0; debug_levels[i].string; i++)
531 if (level <= debug_levels[i].level) {
532 silc_log_set_debug_string(debug_levels[i].string);
536 #endif /* SILC_DEBUG */
538 /* This function should not be called directly but through the appropriate
539 wrapper macro defined in server.h */
541 void silc_server_stderr(SilcLogType type, char *message)
543 if (silcd->background) {
544 char *p, *n = message;
546 /* remove newlines if we are going to output it to a log file */
547 for (p = n; *p; p++) {
556 /* the message is freed inside the logging function */
557 silc_log_output(type, message);
560 fprintf(stderr, "%s\n", message);
566 #define NUM_DEBUGS 3000
567 static char debugs[NUM_DEBUGS][128];
568 static int cur_debug = 0;
570 SilcBool silc_server_debug_callback(char *file, char *function, int line,
571 char *message, void *context)
573 SilcTimeStruct curtime;
575 /* Save the message to ring buffer */
576 silc_time_value(0, &curtime);
577 silc_snprintf(debugs[cur_debug % NUM_DEBUGS], sizeof(debugs[0]),
578 "%02d:%02d:%02d %s:%d: %s", curtime.hour,
579 curtime.minute, curtime.second, function, line,
585 #endif /* SILC_DEBUG */
587 int main(int argc, char **argv)
589 int ret, opt, option_index;
590 SilcBool foreground = FALSE;
591 SilcBool opt_create_keypair = FALSE;
592 char *silcd_config_file = NULL;
596 silc_log_set_debug_callbacks(silc_server_debug_callback, NULL, NULL, NULL);
597 #endif /* SILC_DEBUG */
599 /* Parse command line arguments */
601 #ifdef HAVE_GETOPT_LONG
602 while ((opt = getopt_long(argc, argv, "f:p:d:D:xhFVC:",
603 long_opts, &option_index)) != EOF) {
605 while ((opt = getopt(argc, argv, "f:p:d:D:xhFVC:")) != EOF) {
606 #endif /* HAVE_GETOPT_LONG */
612 printf("SILCd Secure Internet Live Conferencing daemon, "
613 "version %s (base: SILC Toolkit %s)\n",
614 silc_dist_version, silc_version);
615 printf("(c) 1997 - 2007 Pekka Riikonen "
616 "<priikone@silcnet.org>\n");
621 silc_log_debug(TRUE);
622 silc_log_quick(TRUE);
624 silc_log_set_debug_string(optarg);
625 foreground = 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_log_debug(TRUE);
635 silc_log_quick(TRUE);
637 silc_get_debug_level(atoi(optarg));
638 foreground = TRUE; /* implied */
641 "Run-time debugging is not enabled. To enable it recompile\n"
642 "the server with --enable-debug configuration option.\n");
647 silc_log_debug(TRUE);
648 silc_log_debug_hexdump(TRUE);
649 silc_log_quick(TRUE);
650 foreground = TRUE; /* implied */
653 "Run-time debugging is not enabled. To enable it recompile\n"
654 "the server with --enable-debug configuration option.\n");
658 silcd_config_file = strdup(optarg);
665 * Key management options
668 opt_create_keypair = TRUE;
670 opt_keypath = strdup(optarg);
674 opt_pkcs = strdup(optarg);
678 opt_bits = atoi(optarg);
682 opt_identifier = strdup(optarg);
692 if (opt_create_keypair == TRUE) {
693 /* Create new key pair and exit */
694 char pubfile[256], prvfile[256];
696 memset(pubfile, 0, sizeof(pubfile));
697 memset(prvfile, 0, sizeof(prvfile));
698 snprintf(pubfile, sizeof(pubfile) - 1, "%s/silcd.pub", opt_keypath);
699 snprintf(prvfile, sizeof(prvfile) - 1, "%s/silcd.prv", opt_keypath);
701 silc_cipher_register_default();
702 silc_pkcs_register_default();
703 silc_hash_register_default();
704 silc_hmac_register_default();
708 "warning: You have specified key length under 4096 bits. It is "
709 "recommended to use at least 4096 bits.\n");
711 if (!silc_create_key_pair(opt_pkcs, opt_bits, pubfile, prvfile,
712 opt_identifier, "", NULL, NULL, FALSE))
717 /* Default configuration file */
718 if (!silcd_config_file)
719 silcd_config_file = strdup(SILC_SERVER_CONFIG_FILE);
721 /* Create SILC Server object */
722 ret = silc_server_alloc(&silcd);
726 /* Register default crypto stuff since we are going to need them
727 in the configuration file parsing phase */
728 silc_cipher_register_default();
729 silc_pkcs_register_default();
730 silc_hash_register_default();
731 silc_hmac_register_default();
733 /* Read configuration files */
734 silcd->config = silc_server_config_alloc(silcd_config_file, silcd);
735 if (silcd->config == NULL)
737 silcd->config_file = silcd_config_file;
739 /* Unregister the default crypto stuff so that configuration takes effect */
740 silc_cipher_unregister_all();
741 /* silc_pkcs_unregister_all(); MUST NOT do this anymore; SilcPublicKey
742 parsed from config file references pointers so we cannot unregister */
743 silc_hash_unregister_all();
744 silc_hmac_unregister_all();
746 /* Check for another silcd running */
747 silc_server_checkpid(silcd);
749 /* Initialize the server */
750 if (silc_server_init(silcd) == FALSE)
753 /* Ignore some signals */
754 sa.sa_handler = SIG_IGN;
756 sigemptyset(&sa.sa_mask);
758 sigaction(SIGPIPE, &sa, NULL); /* Ignore broken pipes */
761 sigaction(SIGXFSZ, &sa, NULL); /* Ignore file limit exceeds */
764 sigaction(SIGXCPU, &sa, NULL); /* Ignore CPU time limit exceeds */
767 /* Handle specificly some other signals. */
768 silc_schedule_task_add_signal(silcd->schedule, SIGHUP, got_hup, NULL);
769 silc_schedule_task_add_signal(silcd->schedule, SIGTERM, stop_server, NULL);
770 silc_schedule_task_add_signal(silcd->schedule, SIGINT, stop_server, NULL);
771 silc_schedule_task_add_signal(silcd->schedule, SIGUSR1, dump_stats, NULL);
774 /* Before running the server, fork to background. */
775 silc_server_daemonise(silcd);
777 /* If set, write pid to file */
778 if (silcd->config->server_info->pid_file) {
779 char buf[10], *pidfile = silcd->config->server_info->pid_file;
781 snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
782 silc_file_writefile(pidfile, buf, strlen(buf));
786 silc_server_drop_privs(silcd);
788 /* Run the server. When this returns the server has been stopped
790 silc_server_run(silcd);
793 silc_server_config_destroy(silcd->config);
794 silc_server_free(silcd);
796 /* Flush the logging system */
797 silc_log_flush_all();
799 silc_free(silcd_config_file);
800 silc_free(opt_identifier);
801 silc_free(opt_keypath);
805 silc_free(silcd_config_file);
806 silc_free(opt_identifier);
807 silc_free(opt_keypath);