1 /*
2
3 silcd.c
4
5 Author: Pekka Riikonen <priikone@silcnet.org>
6
7 Copyright (C) 1997 - 2005 Pekka Riikonen
8
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.
12
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.
17
18 */
19 /*
20 * Created: Wed Mar 19 00:17:12 1997
21 *
22 * This is the main program for the SILC daemon. This parses command
23 * line arguments and creates the server object.
24 */
25 /* $Id: silcd.c,v 1.60 2005/04/23 13:32:25 priikone Exp $ */
26
27 #include "serverincludes.h"
28 #include "server_internal.h"
29 #include "silcversion.h"
30
31 /* For now, we'll have this one server context global for this module. */
32 static SilcServer silcd;
33
34 static void silc_usage(void);
35
36 /* Long command line options */
37 static struct option long_opts[] =
38 {
39 { "config-file", 1, NULL, 'f' },
40 { "passphrase", 1, NULL, 'p' },
41 { "debug", 2, NULL, 'd' },
42 { "debug-level", 1, NULL, 'D' },
43 { "hexdump", 0, NULL, 'x' },
44 { "help", 0, NULL, 'h' },
45 { "foreground", 0, NULL, 'F' },
46 { "version", 0, NULL,'V' },
47
48 /* Key management options */
49 { "create-key-pair", 1, NULL, 'C' },
50 { "pkcs", 1, NULL, 10 },
51 { "bits", 1, NULL, 11 },
52 { "identifier", 1, NULL, 12 },
53
54 { NULL, 0, NULL, 0 }
55 };
56
57 /* Command line option variables */
58 static char *opt_keypath = NULL;
59 static char *opt_pkcs = "rsa";
60 static char *opt_identifier = NULL;
61 static int opt_bits = 2048;
62
63 /* Prints out the usage of silc client */
64
65 static void silc_usage(void)
66 {
67 printf(""
68 "Usage: silcd [options]\n"
69 "\n"
70 " Generic Options:\n"
71 " -f --config-file=FILE Alternate configuration file\n"
72 " -d --debug=string Enable debugging (Implies --foreground)\n"
73 " -D --debug-level=level Enable debugging (Implies --foreground)\n"
74 " -x --hexdump Enable hexdumps (Implies --debug)\n"
75 " -h --help Display this message\n"
76 " -F --foreground Dont fork\n"
77 " -V --version Display version\n"
78 "\n"
79 " Key Management Options:\n"
80 " -C, --create-key-pair=PATH Create new public key pair\n"
81 " --pkcs=PKCS Set the PKCS of the public key pair\n"
82 " --bits=VALUE Set length of the public key pair\n"
83 " --identifier=IDENTIFIER Public key identifier\n"
84 "\n"
85 " The public key identifier may be of the following format:\n"
86 "\n"
87 " UN=<username>, HN=<hostname or IP>, RN=<real name>, E=<email>,\n"
88 " O=<organization>, C=<country>\n"
89 "\n"
90 " The UN and HN must be provided, the others are optional. If the\n"
91 " --identifier option is not used an identifier will be created for\n"
92 " the public key automatically.\n"
93 "\n"
94 " Example identifier: \"UN=foobar, HN=foo.bar.com, RN=Foo T. Bar, \n"
95 " E=foo@bar.com, C=FI\"\n"
96 "\n");
97 exit(0);
98 }
99
100 /* Die if a *valid* pid file exists already */
101
102 static void silc_server_checkpid(SilcServer silcd)
103 {
104 if (silcd->config->server_info->pid_file) {
105 int oldpid;
106 char *buf;
107 SilcUInt32 buf_len;
108
109 SILC_LOG_DEBUG(("Checking for another silcd running"));
110 buf = silc_file_readfile(silcd->config->server_info->pid_file, &buf_len);
111 if (!buf)
112 return;
113 oldpid = atoi(buf);
114 silc_free(buf);
115 if (oldpid <= 0)
116 return;
117 kill(oldpid, SIGCHLD); /* this signal does nothing, check if alive */
118 if (errno != ESRCH) {
119 fprintf(stderr, "\nI detected another daemon running with the "
120 "same pid file.\n");
121 fprintf(stderr, "Please change the config file, or erase the %s\n",
122 silcd->config->server_info->pid_file);
123 exit(1);
124 }
125 }
126 }
127
128 /* Drop root privileges. If some system call fails, die. */
129
130 static void silc_server_drop_privs(SilcServer server)
131 {
132 /* Are we executing silcd as root or a regular user? */
133 if (geteuid()) {
134 SILC_LOG_DEBUG(("Server started as user"));
135 }
136 else {
137 struct passwd *pw;
138 struct group *gr;
139 char *user, *group;
140
141 SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
142
143 /* Get the values given for user and group in configuration file */
144 user = server->config->server_info->user;
145 group = server->config->server_info->group;
146
147 if (!user || !group) {
148 fprintf(stderr, "Error:"
149 "\tSILC server must not be run as root. For the security of your\n"
150 "\tsystem it is strongly suggested that you run SILC under dedicated\n"
151 "\tuser account. Modify the ServerInfo configuration section to run\n"
152 "\tthe server as non-root user.\n");
153 exit(1);
154 }
155
156 /* Check whether the user/group does not begin with a number */
157 if (isdigit(user[0]) || isdigit(group[0])) {
158 SILC_LOG_DEBUG(("User and/or group starts with a number"));
159 fprintf(stderr, "Invalid user and/or group information\n");
160 fprintf(stderr, "Please assign them as names, not numbers\n");
161 exit(1);
162 }
163
164 if (!(pw = getpwnam(user))) {
165 fprintf(stderr, "Error: No such user %s found.\n", user);
166 exit(1);
167 }
168 if (!(gr = getgrnam(group))) {
169 fprintf(stderr, "Error: No such group %s found.\n", group);
170 exit(1);
171 }
172
173 /* Check whether user and/or group is set to root. If yes, exit
174 immediately. Otherwise, setgid and setuid server to user.group */
175 if ((gr->gr_gid == 0) || (pw->pw_uid == 0)) {
176 fprintf(stderr, "Error:"
177 "\tSILC server must not be run as root. For the security of your\n"
178 "\tsystem it is strongly suggested that you run SILC under dedicated\n"
179 "\tuser account. Modify the ServerInfo configuration section to run\n"
180 "\tthe server as non-root user.\n");
181 exit(1);
182 }
183
184 SILC_LOG_DEBUG(("Changing to group %s (gid=%u)", group, gr->gr_gid));
185 if (setgid(gr->gr_gid) != 0) {
186 fprintf(stderr, "Error: Failed setgid() to %s (gid=%u). Exiting.\n",
187 group, gr->gr_gid);
188 exit(1);
189 }
190 #if defined HAVE_SETGROUPS && defined HAVE_INITGROUPS
191 SILC_LOG_DEBUG(("Removing supplementary groups"));
192 if (setgroups(0, NULL) != 0) {
193 fprintf(stderr, "Error: Failed setgroups() to NULL. Exiting.\n");
194 exit(1);
195 }
196 SILC_LOG_DEBUG(("Setting supplementary groups for user %s", user));
197 if (initgroups(user, gr->gr_gid) != 0) {
198 fprintf(stderr, "Error: Failed initgroups() for user %s (gid=%u). "
199 "Exiting.\n", user, gr->gr_gid);
200 exit(1);
201 }
202 #endif
203 SILC_LOG_DEBUG(("Changing to user %s (uid=%u)", user, pw->pw_uid));
204 if (setuid(pw->pw_uid) != 0) {
205 fprintf(stderr, "Error: Failed to setuid() to %s (gid=%u). Exiting.\n",
206 user, pw->pw_uid);
207 exit(1);
208 }
209 }
210 }
211
212 /* Fork server to background */
213
214 static void silc_server_daemonise(SilcServer server)
215 {
216 int i;
217
218 SILC_LOG_DEBUG(("Forking SILC server to background"));
219
220 if ((i = fork()) < 0) {
221 fprintf(stderr, "Error: fork() failed: %s\n", strerror(errno));
222 exit(1);
223 }
224
225 if (i) /* Kill the parent */
226 exit(0);
227
228 server->background = TRUE;
229 setsid();
230
231 /* XXX close stdin, stdout, stderr -- before this, check that all writes
232 to stderr are changed to SILC_SERVER_LOG_ERROR() */
233 }
234
235 static void signal_handler(int sig)
236 {
237 /* Mark the signal to be caller after this signal is over. */
238 silc_schedule_signal_call(silcd->schedule, sig);
239 }
240
241 SILC_TASK_CALLBACK(got_hup)
242 {
243 /* First, reset all log files (they might have been deleted) */
244 silc_log_reset_all();
245
246 /* Rehash the configuration file */
247 silc_server_rehash(silcd);
248 }
249
250 SILC_TASK_CALLBACK(stop_server)
251 {
252 /* Stop scheduler, the program will stop eventually after noticing
253 that the scheduler is down. */
254 silc_schedule_stop(silcd->schedule);
255 }
256
257 /* Dump server statistics into a file into /tmp directory */
258
259 SILC_TASK_CALLBACK(dump_stats)
260 {
261 FILE *fdd;
262 char filename[256];
263
264 memset(filename, 0, sizeof(filename));
265 snprintf(filename, sizeof(filename) - 1, "/tmp/silcd.%d.stats", getpid());
266 fdd = fopen(filename, "w+");
267 if (!fdd)
268 return;
269
270 #define STAT_OUTPUT(fmt, stat) fprintf(fdd, fmt "\n", (int)stat);
271
272 fprintf(fdd, "SILC Server %s Statistics\n\n", silcd->server_name);
273 fprintf(fdd, "Local Stats:\n");
274 STAT_OUTPUT(" My clients : %d", silcd->stat.my_clients);
275 STAT_OUTPUT(" My servers : %d", silcd->stat.my_servers);
276 STAT_OUTPUT(" My routers : %d", silcd->stat.my_routers);
277 STAT_OUTPUT(" My channels : %d", silcd->stat.my_channels);
278 STAT_OUTPUT(" My joined users : %d", silcd->stat.my_chanclients);
279 STAT_OUTPUT(" My aways : %d", silcd->stat.my_aways);
280 STAT_OUTPUT(" My detached clients : %d", silcd->stat.my_detached);
281 STAT_OUTPUT(" My server operators : %d", silcd->stat.my_server_ops);
282 STAT_OUTPUT(" My router operators : %d", silcd->stat.my_router_ops);
283 fprintf(fdd, "\nGlobal Stats:\n");
284 STAT_OUTPUT(" Cell clients : %d", silcd->stat.cell_clients);
285 STAT_OUTPUT(" Cell servers : %d", silcd->stat.cell_servers);
286 STAT_OUTPUT(" Cell channels : %d", silcd->stat.cell_channels);
287 STAT_OUTPUT(" Cell joined users : %d", silcd->stat.cell_chanclients);
288 STAT_OUTPUT(" All clients : %d", silcd->stat.clients);
289 STAT_OUTPUT(" All servers : %d", silcd->stat.servers);
290 STAT_OUTPUT(" All routers : %d", silcd->stat.routers);
291 STAT_OUTPUT(" All channels : %d", silcd->stat.channels);
292 STAT_OUTPUT(" All joined users : %d", silcd->stat.chanclients);
293 STAT_OUTPUT(" All aways : %d", silcd->stat.aways);
294 STAT_OUTPUT(" All detached clients : %d", silcd->stat.detached);
295 STAT_OUTPUT(" All server operators : %d", silcd->stat.server_ops);
296 STAT_OUTPUT(" All router operators : %d", silcd->stat.router_ops);
297 fprintf(fdd, "\nGeneral Stats:\n");
298 STAT_OUTPUT(" Connection attempts : %d", silcd->stat.conn_attempts);
299 STAT_OUTPUT(" Connection failures : %d", silcd->stat.conn_failures);
300 STAT_OUTPUT(" Authentication attempts : %d", silcd->stat.auth_attempts);
301 STAT_OUTPUT(" Authentication failures : %d", silcd->stat.auth_failures);
302 STAT_OUTPUT(" Packets sent : %d", silcd->stat.packets_sent);
303 STAT_OUTPUT(" Packets received : %d", silcd->stat.packets_received);
304 STAT_OUTPUT(" Commands sent : %d", silcd->stat.commands_sent);
305 STAT_OUTPUT(" Commands received : %d", silcd->stat.commands_received);
306 STAT_OUTPUT(" Connections : %d", silcd->stat.conn_num);
307
308 #undef STAT_OUTPUT
309
310 #ifdef SILC_DEBUG
311 /* Dump internal flags */
312 fprintf(fdd, "\nDumping internal flags\n");
313 fprintf(fdd, " server_type : %d\n", silcd->server_type);
314 fprintf(fdd, " standalone : %d\n", silcd->standalone);
315 fprintf(fdd, " listenning : %d\n", silcd->listenning);
316 fprintf(fdd, " background : %d\n", silcd->background);
317 fprintf(fdd, " backup_router : %d\n", silcd->backup_router);
318 fprintf(fdd, " backup_primary : %d\n", silcd->backup_primary);
319 fprintf(fdd, " backup_noswitch : %d\n", silcd->backup_noswitch);
320 fprintf(fdd, " backup_closed : %d\n", silcd->backup_closed);
321 fprintf(fdd, " wait_backup : %d\n", silcd->wait_backup);
322 if (silcd->router)
323 fprintf(fdd, " primary router : %s\n",
324 silcd->router->server_name ? silcd->router->server_name : "");
325
326 /* Dump socket connections */
327 {
328 int i;
329 SilcSocketConnection s;
330
331 fprintf(fdd, "\nDumping socket connections\n");
332 for (i = 0; i < silcd->config->param.connections_max; i++) {
333 s = silcd->sockets[i];
334 if (!s)
335 continue;
336 fprintf(fdd, " %d: host %s ip %s port %d type %d flags 0x%x\n",
337 s->sock, s->hostname ? s->hostname : "N/A",
338 s->ip ? s->ip : "N/A", s->port, s->type,
339 (unsigned int)s->flags);
340 }
341 }
342
343 /* Dump lists */
344 {
345 SilcIDCacheList list = NULL;
346 SilcIDCacheEntry id_cache = NULL;
347 SilcServerEntry server_entry;
348 SilcClientEntry client_entry;
349 SilcChannelEntry channel_entry;
350 int c;
351
352 fprintf(fdd, "\nDumping databases\n");
353
354 if (silc_idcache_get_all(silcd->local_list->servers, &list)) {
355 if (silc_idcache_list_first(list, &id_cache)) {
356 fprintf(fdd, "\nServers in local-list:\n");
357 c = 1;
358 while (id_cache) {
359 server_entry = (SilcServerEntry)id_cache->context;
360 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
361 server_entry->server_name ? server_entry->server_name :
362 "N/A", server_entry->id ?
363 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
364 server_entry->data.status);
365 if (!silc_idcache_list_next(list, &id_cache))
366 break;
367 c++;
368 }
369 }
370 silc_idcache_list_free(list);
371 }
372 if (silc_idcache_get_all(silcd->global_list->servers, &list)) {
373 if (silc_idcache_list_first(list, &id_cache)) {
374 fprintf(fdd, "\nServers in global-list:\n");
375 c = 1;
376 while (id_cache) {
377 server_entry = (SilcServerEntry)id_cache->context;
378 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
379 server_entry->server_name ? server_entry->server_name :
380 "N/A", server_entry->id ?
381 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
382 server_entry->data.status);
383 if (!silc_idcache_list_next(list, &id_cache))
384 break;
385 c++;
386 }
387 }
388 silc_idcache_list_free(list);
389 }
390 if (silc_idcache_get_all(silcd->local_list->clients, &list)) {
391 if (silc_idcache_list_first(list, &id_cache)) {
392 fprintf(fdd, "\nClients in local-list:\n");
393 c = 1;
394 while (id_cache) {
395 client_entry = (SilcClientEntry)id_cache->context;
396 server_entry = client_entry->router;
397 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
398 client_entry->nickname ? client_entry->nickname :
399 (unsigned char *)"N/A", client_entry->id ?
400 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
401 client_entry->data.status, server_entry ?
402 server_entry->server_name ? server_entry->server_name :
403 "N/A" : "local");
404 if (!silc_idcache_list_next(list, &id_cache))
405 break;
406 c++;
407 }
408 }
409 silc_idcache_list_free(list);
410 }
411 if (silc_idcache_get_all(silcd->global_list->clients, &list)) {
412 if (silc_idcache_list_first(list, &id_cache)) {
413 fprintf(fdd, "\nClients in global-list:\n");
414 c = 1;
415 while (id_cache) {
416 client_entry = (SilcClientEntry)id_cache->context;
417 server_entry = client_entry->router;
418 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
419 client_entry->nickname ? client_entry->nickname :
420 (unsigned char *)"N/A", client_entry->id ?
421 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
422 client_entry->data.status, server_entry ?
423 server_entry->server_name ? server_entry->server_name :
424 "N/A" : "local");
425 if (!silc_idcache_list_next(list, &id_cache))
426 break;
427 c++;
428 }
429 }
430 silc_idcache_list_free(list);
431 }
432 if (silc_idcache_get_all(silcd->local_list->channels, &list)) {
433 if (silc_idcache_list_first(list, &id_cache)) {
434 fprintf(fdd, "\nChannels in local-list:\n");
435 c = 1;
436 while (id_cache) {
437 channel_entry = (SilcChannelEntry)id_cache->context;
438 fprintf(fdd, " %d: name %s id %s\n", c,
439 channel_entry->channel_name ? channel_entry->channel_name :
440 "N/A", channel_entry->id ?
441 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
442 if (!silc_idcache_list_next(list, &id_cache))
443 break;
444 c++;
445 }
446 }
447 silc_idcache_list_free(list);
448 }
449 if (silc_idcache_get_all(silcd->global_list->channels, &list)) {
450 if (silc_idcache_list_first(list, &id_cache)) {
451 fprintf(fdd, "\nChannels in global-list:\n");
452 c = 1;
453 while (id_cache) {
454 channel_entry = (SilcChannelEntry)id_cache->context;
455 fprintf(fdd, " %d: name %s id %s\n", c,
456 channel_entry->channel_name ? channel_entry->channel_name :
457 "N/A", channel_entry->id ?
458 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
459 if (!silc_idcache_list_next(list, &id_cache))
460 break;
461 c++;
462 }
463 }
464 silc_idcache_list_free(list);
465 }
466 }
467 #endif
468
469 fflush(fdd);
470 fclose(fdd);
471 }
472
473 #ifdef SILC_DEBUG
474
475 typedef struct {
476 int level;
477 const char *string;
478 } DebugLevel;
479
480 static DebugLevel debug_levels[] = {
481 /* Very basic stuff from silcd/ */
482 { 3, "silcd\\.c,server\\.c" },
483
484 /* More stuff from silcd/ */
485 { 7, "silcd\\.c,server\\.c,command\\.c,server_backup\\.c,packet_send\\.c" },
486
487 /* All basic stuff from silcd/ */
488 { 10, "silc_server_*" },
489
490 /* All from silcd/ */
491 { 15, "*silcd*,*serverid*,silc_server_*,*idlist*" },
492
493 /* All from silcd/ and basic stuff from libs */
494 { 20, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,*silcske*" },
495
496 /* All from silcd/ and more stuff from libs */
497 { 25, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
498 "*silcpacket*,*ske*,*silcrng*" },
499
500 /* All from silcd/ and even more stuff from libs */
501 { 30, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
502 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*" },
503
504 /* All from silcd/ and even more stuff from libs + all from silccore */
505 { 35, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
506 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
507 "*silcid*,*argument*" },
508
509 /* All from silcd/, all from silccore, silccrypt and silcmath */
510 { 40, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
511 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
512 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*" },
513
514 /* All from silcd/, all from silccore, silccrypt and silcmath + stuff
515 from silcutil */
516 { 45, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
517 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
518 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
519 "*sockconn*" },
520
521 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
522 from silcutil */
523 { 50, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
524 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
525 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
526 "*sockconn*,*net*" },
527
528 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
529 from silcutil */
530 { 55, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
531 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
532 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
533 "*sockconn*,*net*,*log*,*config*" },
534
535 /* All */
536 { 90, "*" },
537
538 { -1, NULL },
539 };
540
541 static void silc_get_debug_level(int level)
542 {
543 int i;
544
545 if (level < 0)
546 return;
547
548 for (i = 0; debug_levels[i].string; i++)
549 if (level <= debug_levels[i].level) {
550 silc_log_set_debug_string(debug_levels[i].string);
551 break;
552 }
553 }
554 #endif /* SILC_DEBUG */
555
556 /* This function should not be called directly but through the appropriate
557 wrapper macro defined in server.h */
558
559 void silc_server_stderr(SilcLogType type, char *message)
560 {
561 if (silcd->background) {
562 char *p, *n = message;
563
564 /* remove newlines if we are going to output it to a log file */
565 for (p = n; *p; p++) {
566 if (*p != '\n') {
567 if (p != n)
568 *n = *p;
569 n++;
570 }
571 }
572 *n = 0;
573
574 /* the message is freed inside the logging function */
575 silc_log_output(type, message);
576 }
577 else {
578 fprintf(stderr, "%s\n", message);
579 silc_free(message);
580 }
581 }
582
583 int main(int argc, char **argv)
584 {
585 int ret, opt, option_index;
586 bool foreground = FALSE;
587 bool opt_create_keypair = FALSE;
588 char *silcd_config_file = NULL;
589 struct sigaction sa;
590
591 /* Parse command line arguments */
592 if (argc > 1) {
593 while ((opt = getopt_long(argc, argv, "f:p:d:D:xhFVC:",
594 long_opts, &option_index)) != EOF) {
595 switch(opt) {
596 case 'h':
597 silc_usage();
598 break;
599 case 'V':
600 printf("SILCd Secure Internet Live Conferencing daemon, "
601 "version %s (base: SILC Toolkit %s)\n",
602 silc_dist_version, silc_version);
603 printf("(c) 1997 - 2005 Pekka Riikonen "
604 "<priikone@silcnet.org>\n");
605 exit(0);
606 break;
607 case 'd':
608 #ifdef SILC_DEBUG
609 silc_debug = TRUE;
610 if (optarg)
611 silc_log_set_debug_string(optarg);
612 foreground = TRUE; /* implied */
613 silc_log_quick = TRUE; /* implied */
614 #else
615 fprintf(stderr,
616 "Run-time debugging is not enabled. To enable it recompile\n"
617 "the server with --enable-debug configuration option.\n");
618 #endif
619 break;
620 case 'D':
621 #ifdef SILC_DEBUG
622 silc_debug = TRUE;
623 if (optarg)
624 silc_get_debug_level(atoi(optarg));
625 foreground = TRUE; /* implied */
626 silc_log_quick = TRUE; /* implied */
627 #else
628 fprintf(stderr,
629 "Run-time debugging is not enabled. To enable it recompile\n"
630 "the server with --enable-debug configuration option.\n");
631 #endif
632 break;
633 case 'x':
634 #ifdef SILC_DEBUG
635 silc_debug_hexdump = TRUE;
636 silc_debug = TRUE; /* implied */
637 foreground = TRUE; /* implied */
638 silc_log_quick = TRUE; /* implied */
639 #else
640 fprintf(stderr,
641 "Run-time debugging is not enabled. To enable it recompile\n"
642 "the server with --enable-debug configuration option.\n");
643 #endif
644 break;
645 case 'f':
646 silcd_config_file = strdup(optarg);
647 break;
648 case 'F':
649 foreground = TRUE;
650 break;
651
652 /*
653 * Key management options
654 */
655 case 'C':
656 opt_create_keypair = TRUE;
657 if (optarg)
658 opt_keypath = strdup(optarg);
659 break;
660 case 10:
661 if (optarg)
662 opt_pkcs = strdup(optarg);
663 break;
664 case 11:
665 if (optarg)
666 opt_bits = atoi(optarg);
667 break;
668 case 12:
669 if (optarg)
670 opt_identifier = strdup(optarg);
671 break;
672
673 default:
674 silc_usage();
675 break;
676 }
677 }
678 }
679
680 if (opt_create_keypair == TRUE) {
681 /* Create new key pair and exit */
682 char pubfile[256], prvfile[256];
683
684 memset(pubfile, 0, sizeof(pubfile));
685 memset(prvfile, 0, sizeof(prvfile));
686 snprintf(pubfile, sizeof(pubfile) - 1, "%s/silcd.pub", opt_keypath);
687 snprintf(prvfile, sizeof(prvfile) - 1, "%s/silcd.prv", opt_keypath);
688
689 silc_cipher_register_default();
690 silc_pkcs_register_default();
691 silc_hash_register_default();
692 silc_hmac_register_default();
693 silc_create_key_pair(opt_pkcs, opt_bits, pubfile, prvfile,
694 opt_identifier, "", NULL, NULL, NULL, FALSE);
695 exit(0);
696 }
697
698 /* Default configuration file */
699 if (!silcd_config_file)
700 silcd_config_file = strdup(SILC_SERVER_CONFIG_FILE);
701
702 /* Create SILC Server object */
703 ret = silc_server_alloc(&silcd);
704 if (ret == FALSE)
705 goto fail;
706
707 /* Register default crypto stuff since we are going to need them
708 in the configuration file parsing phase */
709 silc_cipher_register_default();
710 silc_pkcs_register_default();
711 silc_hash_register_default();
712 silc_hmac_register_default();
713
714 /* Read configuration files */
715 silcd->config = silc_server_config_alloc(silcd_config_file);
716 if (silcd->config == NULL)
717 goto fail;
718 silcd->config_file = silcd_config_file;
719
720 /* Unregister the default crypto stuff so that configuration takes effect */
721 silc_cipher_unregister_all();
722 silc_pkcs_unregister_all();
723 silc_hash_unregister_all();
724 silc_hmac_unregister_all();
725
726 /* Check for another silcd running */
727 silc_server_checkpid(silcd);
728
729 /* Initialize the server */
730 if (silc_server_init(silcd) == FALSE)
731 goto fail;
732
733 /* Ignore some signals */
734 sa.sa_handler = SIG_IGN;
735 sa.sa_flags = 0;
736 sigemptyset(&sa.sa_mask);
737 #if defined(SIGPIPE)
738 sigaction(SIGPIPE, &sa, NULL); /* Ignore broken pipes */
739 #endif /* SIGPIPE*/
740 #if defined(SIGXFSZ)
741 sigaction(SIGXFSZ, &sa, NULL); /* Ignore file limit exceeds */
742 #endif /* SIGXFSZ */
743 #if defined(SIGXCPU)
744 sigaction(SIGXCPU, &sa, NULL); /* Ignore CPU time limit exceeds */
745 #endif /* SIGXCPU */
746
747 /* Handle specificly some other signals. */
748 sa.sa_handler = signal_handler;
749 sigaction(SIGHUP, &sa, NULL);
750 sigaction(SIGTERM, &sa, NULL);
751 sigaction(SIGINT, &sa, NULL);
752 sigaction(SIGUSR1, &sa, NULL);
753 silc_schedule_signal_register(silcd->schedule, SIGHUP, got_hup, NULL);
754 silc_schedule_signal_register(silcd->schedule, SIGTERM, stop_server, NULL);
755 silc_schedule_signal_register(silcd->schedule, SIGINT, stop_server, NULL);
756 silc_schedule_signal_register(silcd->schedule, SIGUSR1, dump_stats, NULL);
757
758 if (!foreground) {
759 /* Before running the server, fork to background. */
760 silc_server_daemonise(silcd);
761
762 /* If set, write pid to file */
763 if (silcd->config->server_info->pid_file) {
764 char buf[10], *pidfile = silcd->config->server_info->pid_file;
765 unlink(pidfile);
766 snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
767 silc_file_writefile(pidfile, buf, strlen(buf));
768 }
769 }
770
771 /* Drop root if we are not in debug mode, so you don't need to bother about
772 file writing permissions and so on */
773 if (!silc_debug)
774 silc_server_drop_privs(silcd);
775
776 /* Run the server. When this returns the server has been stopped
777 and we will exit. */
778 silc_server_run(silcd);
779
780 /* Stop the server and free it. */
781 silc_server_stop(silcd);
782 silc_server_config_destroy(silcd->config);
783 silc_server_free(silcd);
784
785 /* Flush the logging system */
786 silc_log_flush_all();
787
788 silc_free(silcd_config_file);
789 silc_free(opt_identifier);
790 silc_free(opt_keypath);
791 exit(0);
792
793 fail:
794 silc_free(silcd_config_file);
795 silc_free(opt_identifier);
796 silc_free(opt_keypath);
797 exit(1);
798 }
799
This page was automatically generated by the LXR engine.
Free-text search provided by Glimpse