Log file is not dupped internally anymore.
[silc.git] / apps / silcd / serverconfig.c
1 /*
2
3   serverconfig.c
4
5   Author: Johnny Mnemonic <johnny@themnemonic.org>
6
7   Copyright (C) 1997 - 2002 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; either version 2 of the License, or
12   (at your option) any later version.
13
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.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 #if 0
26 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
27 #else
28 #define SERVER_CONFIG_DEBUG(fmt)
29 #endif
30
31 /* auto-declare needed variables for the common list parsing */
32 #define SILC_SERVER_CONFIG_SECTION_INIT(__type__)                       \
33   SilcServerConfig config = (SilcServerConfig) context;                 \
34   __type__ *findtmp, *tmp = (__type__ *) config->tmp;                   \
35   int got_errno = 0
36
37 /* allocate the tmp field for fetching data */
38 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__)                           \
39   if (!tmp) {                                                           \
40     config->tmp = silc_calloc(1, sizeof(*findtmp));                     \
41     tmp = (__type__ *) config->tmp;                                     \
42   }
43
44 /* append the tmp field to the specified list */
45 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__)                     \
46   if (!__list__) {                                                      \
47     __list__ = tmp;                                                     \
48   } else {                                                              \
49     for (findtmp = __list__; findtmp->next; findtmp = findtmp->next);   \
50     findtmp->next = tmp;                                                \
51   }
52
53 /* loops all elements in a list and provides a di struct pointer of the
54  * specified type containing the current element */
55 #define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__)             \
56   for (tmp = (void *) __list__; tmp;) {                                 \
57     __type__ *di = (__type__ *) tmp;                                    \
58     tmp = (void *) di->next;
59
60 /* Set EDOUBLE error value and bail out if necessary */
61 #define CONFIG_IS_DOUBLE(__x__)                                         \
62   if ((__x__)) {                                                        \
63     got_errno = SILC_CONFIG_EDOUBLE;                                    \
64     goto got_err;                                                       \
65   }
66
67 /* Free the authentication fields in the specified struct
68  * Expands to two instructions */
69 #define CONFIG_FREE_AUTH(__section__)                   \
70   silc_free(__section__->passphrase);                   \
71   if (__section__->publickeys)                          \
72     silc_hash_table_free(__section__->publickeys);
73
74 static void my_free_public_key(void *key, void *context, void *user_data)
75 {
76   silc_pkcs_public_key_free(context);
77 }
78
79 /* Set default values to those parameters that have not been defined */
80 static void
81 my_set_param_defaults(SilcServerConfigConnParams *params,
82                       SilcServerConfigConnParams *defaults)
83 {
84 #define SET_PARAM_DEFAULT(p, d) params->p =                             \
85   (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
86
87   SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
88   SET_PARAM_DEFAULT(connections_max_per_host,
89                     SILC_SERVER_MAX_CONNECTIONS_SINGLE);
90   SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
91   SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
92   SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
93   SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
94   SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
95
96 #undef SET_PARAM_DEFAULT
97 }
98
99 /* Find connection parameters by the parameter block name. */
100 static SilcServerConfigConnParams *
101 my_find_param(SilcServerConfig config, const char *name)
102 {
103   SilcServerConfigConnParams *param;
104
105   for (param = config->conn_params; param; param = param->next) {
106     if (!strcasecmp(param->name, name))
107       return param;
108   }
109
110   SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
111                          "Cannot find Params \"%s\".\n", name));
112
113   return NULL;
114 }
115
116 /* parse an authdata according to its auth method */
117 static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
118                               SilcUInt32 line, void **auth_data,
119                               SilcUInt32 *auth_data_len)
120 {
121   if (auth_meth == SILC_AUTH_PASSWORD) {
122     /* p is a plain text password */
123     if (auth_data && auth_data_len) {
124       if (!silc_utf8_valid(p, strlen(p))) {
125         *auth_data_len = silc_utf8_encoded_len(p, strlen(p), 0);
126         *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
127         silc_utf8_encode(p, strlen(p), SILC_STRING_ASCII, *auth_data,
128                          *auth_data_len);
129       } else {
130         *auth_data = (void *) strdup(p);
131         *auth_data_len = (SilcUInt32) strlen(p);
132       }
133     }
134   } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
135     /* p is a public key file name */
136     SilcPublicKey public_key;
137
138     if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
139       if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
140         SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
141                                "%lu: Could not load public key file!\n",
142                                line));
143         return FALSE;
144       }
145
146     /* The auth_data is a pointer to the hash table of public keys. */
147     if (auth_data) {
148       if (*auth_data == NULL)
149         *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
150                                            NULL, NULL,
151                                            my_free_public_key, NULL,
152                                            TRUE);
153       silc_hash_table_add(*auth_data, public_key, public_key);
154     }
155   } else {
156     SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
157                            "Unknown authentication method.\n", line));
158     return FALSE;
159   }
160   return TRUE;
161 }
162
163 /* Callbacks */
164
165 SILC_CONFIG_CALLBACK(fetch_generic)
166 {
167   SilcServerConfig config = (SilcServerConfig) context;
168   int got_errno = 0;
169
170   if (!strcmp(name, "module_path")) {
171     CONFIG_IS_DOUBLE(config->module_path);
172     config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
173   }
174   else if (!strcmp(name, "prefer_passphrase_auth")) {
175     config->prefer_passphrase_auth = *(bool *)val;
176   }
177   else if (!strcmp(name, "require_reverse_lookup")) {
178     config->require_reverse_lookup = *(bool *)val;
179   }
180   else if (!strcmp(name, "connections_max")) {
181     config->param.connections_max = (SilcUInt32) *(int *)val;
182   }
183   else if (!strcmp(name, "connections_max_per_host")) {
184     config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
185   }
186   else if (!strcmp(name, "keepalive_secs")) {
187     config->param.keepalive_secs = (SilcUInt32) *(int *)val;
188   }
189   else if (!strcmp(name, "reconnect_count")) {
190     config->param.reconnect_count = (SilcUInt32) *(int *)val;
191   }
192   else if (!strcmp(name, "reconnect_interval")) {
193     config->param.reconnect_interval = (SilcUInt32) *(int *)val;
194   }
195   else if (!strcmp(name, "reconnect_interval_max")) {
196     config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
197   }
198   else if (!strcmp(name, "reconnect_keep_trying")) {
199     config->param.reconnect_keep_trying = *(bool *)val;
200   }
201   else if (!strcmp(name, "key_exchange_rekey")) {
202     config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
203   }
204   else if (!strcmp(name, "key_exchange_pfs")) {
205     config->param.key_exchange_pfs = *(bool *)val;
206   }
207   else if (!strcmp(name, "channel_rekey_secs")) {
208     config->channel_rekey_secs = (SilcUInt32) *(int *)val;
209   }
210   else if (!strcmp(name, "key_exchange_timeout")) {
211     config->key_exchange_timeout = (SilcUInt32) *(int *)val;
212   }
213   else if (!strcmp(name, "conn_auth_timeout")) {
214     config->conn_auth_timeout = (SilcUInt32) *(int *)val;
215   }
216   else if (!strcmp(name, "version_protocol")) {
217     CONFIG_IS_DOUBLE(config->param.version_protocol);
218     config->param.version_protocol =
219       (*(char *)val ? strdup((char *) val) : NULL);
220   }
221   else if (!strcmp(name, "version_software")) {
222     CONFIG_IS_DOUBLE(config->param.version_software);
223     config->param.version_software =
224       (*(char *)val ? strdup((char *) val) : NULL);
225   }
226   else if (!strcmp(name, "version_software_vendor")) {
227     CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
228     config->param.version_software_vendor =
229       (*(char *)val ? strdup((char *) val) : NULL);
230   }
231   else if (!strcmp(name, "detach_disabled")) {
232     config->detach_disabled = *(bool *)val;
233   }
234   else if (!strcmp(name, "detach_timeout")) {
235     config->detach_timeout = (SilcUInt32) *(int *)val;
236   }
237   else
238     return SILC_CONFIG_EINTERNAL;
239
240   return SILC_CONFIG_OK;
241
242  got_err:
243   return got_errno;
244 }
245
246 SILC_CONFIG_CALLBACK(fetch_cipher)
247 {
248   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
249
250   SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
251                        type, name, context));
252   if (type == SILC_CONFIG_ARG_BLOCK) {
253     /* check the temporary struct's fields */
254     if (!tmp) /* discard empty sub-blocks */
255       return SILC_CONFIG_OK;
256     if (!tmp->name) {
257       got_errno = SILC_CONFIG_EMISSFIELDS;
258       goto got_err;
259     }
260
261     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
262     config->tmp = NULL;
263     return SILC_CONFIG_OK;
264   }
265   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
266
267   /* Identify and save this value */
268   if (!strcmp(name, "name")) {
269     CONFIG_IS_DOUBLE(tmp->name);
270     tmp->name = strdup((char *) val);
271   }
272   else if (!strcmp(name, "module")) {
273     CONFIG_IS_DOUBLE(tmp->module);
274     tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
275   }
276   else if (!strcmp(name, "keylength")) {
277     tmp->key_length = *(SilcUInt32 *)val;
278   }
279   else if (!strcmp(name, "blocklength")) {
280     tmp->block_length = *(SilcUInt32 *)val;
281   }
282   else
283     return SILC_CONFIG_EINTERNAL;
284   return SILC_CONFIG_OK;
285
286  got_err:
287   silc_free(tmp->name);
288   silc_free(tmp->module);
289   silc_free(tmp);
290   config->tmp = NULL;
291   return got_errno;
292 }
293
294 SILC_CONFIG_CALLBACK(fetch_hash)
295 {
296   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
297
298   SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
299                        type, name, context));
300   if (type == SILC_CONFIG_ARG_BLOCK) {
301     /* check the temporary struct's fields */
302     if (!tmp) /* discard empty sub-blocks */
303       return SILC_CONFIG_OK;
304     if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
305       got_errno = SILC_CONFIG_EMISSFIELDS;
306       goto got_err;
307     }
308
309     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
310     config->tmp = NULL;
311     return SILC_CONFIG_OK;
312   }
313   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
314
315   /* Identify and save this value */
316   if (!strcmp(name, "name")) {
317     CONFIG_IS_DOUBLE(tmp->name);
318     tmp->name = strdup((char *) val);
319   }
320   else if (!strcmp(name, "module")) {
321     CONFIG_IS_DOUBLE(tmp->module);
322     tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
323   }
324   else if (!strcmp(name, "blocklength")) {
325     tmp->block_length = *(int *)val;
326   }
327   else if (!strcmp(name, "digestlength")) {
328     tmp->digest_length = *(int *)val;
329   }
330   else
331     return SILC_CONFIG_EINTERNAL;
332   return SILC_CONFIG_OK;
333
334  got_err:
335   silc_free(tmp->name);
336   silc_free(tmp->module);
337   silc_free(tmp);
338   config->tmp = NULL;
339   return got_errno;
340 }
341
342 SILC_CONFIG_CALLBACK(fetch_hmac)
343 {
344   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
345
346   SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
347                        type, name, context));
348   if (type == SILC_CONFIG_ARG_BLOCK) {
349     /* check the temporary struct's fields */
350     if (!tmp) /* discard empty sub-blocks */
351       return SILC_CONFIG_OK;
352     if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
353       got_errno = SILC_CONFIG_EMISSFIELDS;
354       goto got_err;
355     }
356
357     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
358     config->tmp = NULL;
359     return SILC_CONFIG_OK;
360   }
361   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
362
363   /* Identify and save this value */
364   if (!strcmp(name, "name")) {
365     CONFIG_IS_DOUBLE(tmp->name);
366     tmp->name = strdup((char *) val);
367   }
368   else if (!strcmp(name, "hash")) {
369     CONFIG_IS_DOUBLE(tmp->hash);
370     tmp->hash = strdup((char *) val);
371   }
372   else if (!strcmp(name, "maclength")) {
373     tmp->mac_length = *(int *)val;
374   }
375   else
376     return SILC_CONFIG_EINTERNAL;
377   return SILC_CONFIG_OK;
378
379  got_err:
380   silc_free(tmp->name);
381   silc_free(tmp->hash);
382   silc_free(tmp);
383   config->tmp = NULL;
384   return got_errno;
385 }
386
387 SILC_CONFIG_CALLBACK(fetch_pkcs)
388 {
389   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
390
391   SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
392                        type, name, context));
393   if (type == SILC_CONFIG_ARG_BLOCK) {
394     /* check the temporary struct's fields */
395     if (!tmp) /* discard empty sub-blocks */
396       return SILC_CONFIG_OK;
397     if (!tmp->name) {
398       got_errno = SILC_CONFIG_EMISSFIELDS;
399       goto got_err;
400     }
401
402     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
403     config->tmp = NULL;
404     return SILC_CONFIG_OK;
405   }
406   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
407
408   /* Identify and save this value */
409   if (!strcmp(name, "name")) {
410     CONFIG_IS_DOUBLE(tmp->name);
411     tmp->name = strdup((char *) val);
412   }
413   else
414     return SILC_CONFIG_EINTERNAL;
415   return SILC_CONFIG_OK;
416
417  got_err:
418   silc_free(tmp->name);
419   silc_free(tmp);
420   config->tmp = NULL;
421   return got_errno;
422 }
423
424 SILC_CONFIG_CALLBACK(fetch_serverinfo)
425 {
426   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
427   SilcServerConfigServerInfo *server_info = config->server_info;
428
429   /* if there isn't the struct alloc it */
430   if (!server_info)
431     config->server_info = server_info = (SilcServerConfigServerInfo *)
432                 silc_calloc(1, sizeof(*server_info));
433
434   if (type == SILC_CONFIG_ARG_BLOCK) {
435     if (!strcmp(name, "primary")) {
436       CONFIG_IS_DOUBLE(server_info->primary);
437       if (!tmp)
438         return SILC_CONFIG_OK;
439       server_info->primary = tmp;
440       config->tmp = NULL;
441       return SILC_CONFIG_OK;
442     } else if (!strcmp(name, "secondary")) {
443       if (!tmp)
444         return SILC_CONFIG_OK;
445       SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
446       config->tmp = NULL;
447       return SILC_CONFIG_OK;
448     } else if (!server_info->public_key || !server_info->private_key) {
449       got_errno = SILC_CONFIG_EMISSFIELDS;
450       goto got_err;
451     }
452     return SILC_CONFIG_OK;
453   }
454   if (!strcmp(name, "hostname")) {
455     CONFIG_IS_DOUBLE(server_info->server_name);
456     server_info->server_name = strdup((char *) val);
457   }
458   else if (!strcmp(name, "ip")) {
459     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
460     CONFIG_IS_DOUBLE(tmp->server_ip);
461     tmp->server_ip = strdup((char *) val);
462   }
463   else if (!strcmp(name, "port")) {
464     int port = *(int *)val;
465     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
466     if ((port <= 0) || (port > 65535)) {
467       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
468                              "Invalid port number!\n"));
469       got_errno = SILC_CONFIG_EPRINTLINE;
470       goto got_err;
471     }
472     tmp->port = (SilcUInt16) port;
473   }
474   else if (!strcmp(name, "servertype")) {
475     CONFIG_IS_DOUBLE(server_info->server_type);
476     server_info->server_type = strdup((char *) val);
477   }
478   else if (!strcmp(name, "admin")) {
479     CONFIG_IS_DOUBLE(server_info->admin);
480     server_info->admin = strdup((char *) val);
481   }
482   else if (!strcmp(name, "adminemail")) {
483     CONFIG_IS_DOUBLE(server_info->email);
484     server_info->email = strdup((char *) val);
485   }
486   else if (!strcmp(name, "location")) {
487     CONFIG_IS_DOUBLE(server_info->location);
488     server_info->location = strdup((char *) val);
489   }
490   else if (!strcmp(name, "user")) {
491     CONFIG_IS_DOUBLE(server_info->user);
492     server_info->user = strdup((char *) val);
493   }
494   else if (!strcmp(name, "group")) {
495     CONFIG_IS_DOUBLE(server_info->group);
496     server_info->group = strdup((char *) val);
497   }
498   else if (!strcmp(name, "motdfile")) {
499     CONFIG_IS_DOUBLE(server_info->motd_file);
500     server_info->motd_file = strdup((char *) val);
501   }
502   else if (!strcmp(name, "pidfile")) {
503     CONFIG_IS_DOUBLE(server_info->pid_file);
504     server_info->pid_file = strdup((char *) val);
505   }
506   else if (!strcmp(name, "publickey")) {
507     char *file_tmp = (char *) val;
508
509     /* try to load specified file, if fail stop config parsing */
510     if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
511                                    SILC_PKCS_FILE_PEM))
512       if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
513                                      SILC_PKCS_FILE_BIN)) {
514         SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
515         SILC_SERVER_LOG_ERROR(("   line %lu, file \"%s\"\n", line, file_tmp));
516         return SILC_CONFIG_ESILENT;
517       }
518   }
519   else if (!strcmp(name, "privatekey")) {
520     char *file_tmp = (char *) val;
521
522     /* try to load specified file, if fail stop config parsing */
523     if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
524                                     SILC_PKCS_FILE_BIN))
525       if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
526                                       SILC_PKCS_FILE_PEM)) {
527         SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
528         SILC_SERVER_LOG_ERROR(("   line %lu, file \"%s\"\n", line, file_tmp));
529         return SILC_CONFIG_ESILENT;
530       }
531   }
532   else
533     return SILC_CONFIG_EINTERNAL;
534   return SILC_CONFIG_OK;
535
536  got_err:
537   silc_free(tmp);
538   silc_free(config->tmp);
539   config->tmp = NULL;
540   return got_errno;
541 }
542
543 SILC_CONFIG_CALLBACK(fetch_logging)
544 {
545   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
546
547   if (!strcmp(name, "quicklogs")) {
548     config->logging_quick = *(bool *)val;
549   }
550   else if (!strcmp(name, "flushdelay")) {
551     int flushdelay = *(int *)val;
552     if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
553       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
554                             "Invalid flushdelay value, use quicklogs if you "
555                             "want real-time logging.\n"));
556       return SILC_CONFIG_EPRINTLINE;
557     }
558     config->logging_flushdelay = (long) flushdelay;
559   }
560
561   /* The following istances happens only in Logging's sub-blocks, a match
562      for the sub-block name means that you should store the filename/maxsize
563      temporary struct to the proper logging channel.
564      If we get a match for "file" or "maxsize" this means that we are inside
565      a sub-sub-block and it is safe to alloc a new tmp. */
566 #define FETCH_LOGGING_CHAN(__chan__, __member__)                \
567   else if (!strcmp(name, __chan__)) {                           \
568     if (!tmp) return SILC_CONFIG_OK;                            \
569     if (!tmp->file) {                                           \
570       got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;        \
571     }                                                           \
572     config->__member__ = tmp;                                   \
573     config->tmp = NULL;                                         \
574   }
575   FETCH_LOGGING_CHAN("info", logging_info)
576   FETCH_LOGGING_CHAN("warnings", logging_warnings)
577   FETCH_LOGGING_CHAN("errors", logging_errors)
578   FETCH_LOGGING_CHAN("fatals", logging_fatals)
579 #undef FETCH_LOGGING_CHAN
580   else if (!strcmp(name, "file")) {
581     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
582     CONFIG_IS_DOUBLE(tmp->file);
583     tmp->file = strdup((char *) val);
584   }
585   else if (!strcmp(name, "size")) {
586     if (!tmp) {
587       config->tmp = silc_calloc(1, sizeof(*tmp));
588       tmp = (SilcServerConfigLogging *) config->tmp;
589     }
590     tmp->maxsize = *(SilcUInt32 *) val;
591   }
592   else
593     return SILC_CONFIG_EINTERNAL;
594   return SILC_CONFIG_OK;
595
596  got_err:
597   silc_free(tmp->file);
598   silc_free(tmp);
599   config->tmp = NULL;
600   return got_errno;
601 }
602
603 SILC_CONFIG_CALLBACK(fetch_connparam)
604 {
605   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
606
607   SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
608                        type, name, context));
609   if (type == SILC_CONFIG_ARG_BLOCK) {
610     /* check the temporary struct's fields */
611     if (!tmp) /* discard empty sub-blocks */
612       return SILC_CONFIG_OK;
613     if (!tmp->name) {
614       got_errno = SILC_CONFIG_EMISSFIELDS;
615       goto got_err;
616     }
617     /* Set defaults */
618     my_set_param_defaults(tmp, &config->param);
619
620     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
621     config->tmp = NULL;
622     return SILC_CONFIG_OK;
623   }
624   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
625
626   if (!strcmp(name, "name")) {
627     CONFIG_IS_DOUBLE(tmp->name);
628     tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
629   }
630   else if (!strcmp(name, "connections_max")) {
631     tmp->connections_max = *(SilcUInt32 *)val;
632   }
633   else if (!strcmp(name, "connections_max_per_host")) {
634     tmp->connections_max_per_host = *(SilcUInt32 *)val;
635   }
636   else if (!strcmp(name, "keepalive_secs")) {
637     tmp->keepalive_secs = *(SilcUInt32 *)val;
638   }
639   else if (!strcmp(name, "reconnect_count")) {
640     tmp->reconnect_count = *(SilcUInt32 *)val;
641   }
642   else if (!strcmp(name, "reconnect_interval")) {
643     tmp->reconnect_interval = *(SilcUInt32 *)val;
644   }
645   else if (!strcmp(name, "reconnect_interval_max")) {
646     tmp->reconnect_interval_max = *(SilcUInt32 *)val;
647   }
648   else if (!strcmp(name, "reconnect_keep_trying")) {
649     tmp->reconnect_keep_trying = *(bool *)val;
650   }
651   else if (!strcmp(name, "key_exchange_rekey")) {
652     tmp->key_exchange_rekey = *(SilcUInt32 *)val;
653   }
654   else if (!strcmp(name, "key_exchange_pfs")) {
655     tmp->key_exchange_pfs = *(bool *)val;
656   }
657   else if (!strcmp(name, "version_protocol")) {
658     CONFIG_IS_DOUBLE(tmp->version_protocol);
659     tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
660   }
661   else if (!strcmp(name, "version_software")) {
662     CONFIG_IS_DOUBLE(tmp->version_software);
663     tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
664   }
665   else if (!strcmp(name, "version_software_vendor")) {
666     CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
667     tmp->version_software_vendor =
668       (*(char *)val ? strdup((char *) val) : NULL);
669   }
670   else
671     return SILC_CONFIG_EINTERNAL;
672
673   return SILC_CONFIG_OK;
674
675  got_err:
676   silc_free(tmp->name);
677   silc_free(tmp);
678   config->tmp = NULL;
679   return got_errno;
680 }
681
682 SILC_CONFIG_CALLBACK(fetch_client)
683 {
684   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
685
686   SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
687                        type, name, context));
688
689   /* Alloc before block checking, because empty sub-blocks are welcome here */
690   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
691
692   if (type == SILC_CONFIG_ARG_BLOCK) {
693     /* empty sub-blocks are welcome */
694     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
695     config->tmp = NULL;
696     return SILC_CONFIG_OK;
697   }
698
699   /* Identify and save this value */
700   if (!strcmp(name, "host")) {
701     CONFIG_IS_DOUBLE(tmp->host);
702     tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
703   }
704   else if (!strcmp(name, "passphrase")) {
705     CONFIG_IS_DOUBLE(tmp->passphrase);
706     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
707                            (void **)&tmp->passphrase,
708                            &tmp->passphrase_len)) {
709       got_errno = SILC_CONFIG_ESILENT;
710       goto got_err;
711     }
712   }
713   else if (!strcmp(name, "publickey")) {
714     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
715                            (void **)&tmp->publickeys, NULL)) {
716       got_errno = SILC_CONFIG_ESILENT;
717       goto got_err;
718     }
719   }
720   else if (!strcmp(name, "params")) {
721     CONFIG_IS_DOUBLE(tmp->param);
722     tmp->param = my_find_param(config, (char *) val);
723     if (!tmp->param) { /* error message already output */
724       got_errno = SILC_CONFIG_EPRINTLINE;
725       goto got_err;
726     }
727   }
728   else
729     return SILC_CONFIG_EINTERNAL;
730   return SILC_CONFIG_OK;
731
732  got_err:
733   silc_free(tmp->host);
734   CONFIG_FREE_AUTH(tmp);
735   silc_free(tmp);
736   config->tmp = NULL;
737   return got_errno;
738 }
739
740 SILC_CONFIG_CALLBACK(fetch_admin)
741 {
742   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
743
744   SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
745                        type, name, context));
746   if (type == SILC_CONFIG_ARG_BLOCK) {
747     /* check the temporary struct's fields */
748     if (!tmp) /* discard empty sub-blocks */
749       return SILC_CONFIG_OK;
750
751     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
752     config->tmp = NULL;
753     return SILC_CONFIG_OK;
754   }
755   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
756
757   /* Identify and save this value */
758   if (!strcmp(name, "host")) {
759     CONFIG_IS_DOUBLE(tmp->host);
760     tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
761   }
762   else if (!strcmp(name, "user")) {
763     CONFIG_IS_DOUBLE(tmp->user);
764     tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
765   }
766   else if (!strcmp(name, "nick")) {
767     CONFIG_IS_DOUBLE(tmp->nick);
768     tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
769   }
770   else if (!strcmp(name, "passphrase")) {
771     CONFIG_IS_DOUBLE(tmp->passphrase);
772     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
773                            (void **)&tmp->passphrase,
774                            &tmp->passphrase_len)) {
775       got_errno = SILC_CONFIG_ESILENT;
776       goto got_err;
777     }
778   }
779   else if (!strcmp(name, "publickey")) {
780     CONFIG_IS_DOUBLE(tmp->publickeys);
781     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
782                            (void **)&tmp->publickeys, NULL)) {
783       got_errno = SILC_CONFIG_ESILENT;
784       goto got_err;
785     }
786   }
787   else
788     return SILC_CONFIG_EINTERNAL;
789   return SILC_CONFIG_OK;
790
791  got_err:
792   silc_free(tmp->host);
793   silc_free(tmp->user);
794   silc_free(tmp->nick);
795   CONFIG_FREE_AUTH(tmp);
796   silc_free(tmp);
797   config->tmp = NULL;
798   return got_errno;
799 }
800
801 SILC_CONFIG_CALLBACK(fetch_deny)
802 {
803   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
804
805   SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
806                        type, name, context));
807   if (type == SILC_CONFIG_ARG_BLOCK) {
808     /* check the temporary struct's fields */
809     if (!tmp) /* discard empty sub-blocks */
810       return SILC_CONFIG_OK;
811     if (!tmp->reason) {
812       got_errno = SILC_CONFIG_EMISSFIELDS;
813       goto got_err;
814     }
815
816     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
817     config->tmp = NULL;
818     return SILC_CONFIG_OK;
819   }
820   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
821
822   /* Identify and save this value */
823   if (!strcmp(name, "host")) {
824     CONFIG_IS_DOUBLE(tmp->host);
825     tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
826   }
827   else if (!strcmp(name, "reason")) {
828     CONFIG_IS_DOUBLE(tmp->reason);
829     tmp->reason = strdup((char *) val);
830   }
831   else
832     return SILC_CONFIG_EINTERNAL;
833   return SILC_CONFIG_OK;
834
835  got_err:
836   silc_free(tmp->host);
837   silc_free(tmp->reason);
838   silc_free(tmp);
839   config->tmp = NULL;
840   return got_errno;
841 }
842
843 SILC_CONFIG_CALLBACK(fetch_server)
844 {
845   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
846
847   SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
848                        type, name, context));
849   if (type == SILC_CONFIG_ARG_BLOCK) {
850     /* check the temporary struct's fields */
851     if (!tmp) /* discard empty sub-blocks */
852       return SILC_CONFIG_OK;
853
854     /* the temporary struct is ok, append it to the list */
855     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
856     config->tmp = NULL;
857     return SILC_CONFIG_OK;
858   }
859   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
860
861   /* Identify and save this value */
862   if (!strcmp(name, "host")) {
863     CONFIG_IS_DOUBLE(tmp->host);
864     tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
865   }
866   else if (!strcmp(name, "passphrase")) {
867     CONFIG_IS_DOUBLE(tmp->passphrase);
868     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
869                            (void **)&tmp->passphrase,
870                            &tmp->passphrase_len)) {
871       got_errno = SILC_CONFIG_ESILENT;
872       goto got_err;
873     }
874   }
875   else if (!strcmp(name, "publickey")) {
876     CONFIG_IS_DOUBLE(tmp->publickeys);
877     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
878                            (void **)&tmp->publickeys, NULL)) {
879       got_errno = SILC_CONFIG_ESILENT;
880       goto got_err;
881     }
882   }
883   else if (!strcmp(name, "params")) {
884     CONFIG_IS_DOUBLE(tmp->param);
885     tmp->param = my_find_param(config, (char *) val);
886     if (!tmp->param) { /* error message already output */
887       got_errno = SILC_CONFIG_EPRINTLINE;
888       goto got_err;
889     }
890   }
891   else if (!strcmp(name, "backup")) {
892     tmp->backup_router = *(bool *)val;
893   }
894   else
895     return SILC_CONFIG_EINTERNAL;
896
897   return SILC_CONFIG_OK;
898
899  got_err:
900   silc_free(tmp->host);
901   CONFIG_FREE_AUTH(tmp);
902   silc_free(tmp);
903   config->tmp = NULL;
904   return got_errno;
905 }
906
907 SILC_CONFIG_CALLBACK(fetch_router)
908 {
909   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
910
911   SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
912                        type, name, context));
913   if (type == SILC_CONFIG_ARG_BLOCK) {
914     if (!tmp) /* discard empty sub-blocks */
915       return SILC_CONFIG_OK;
916
917     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
918     config->tmp = NULL;
919     return SILC_CONFIG_OK;
920   }
921   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
922
923   /* Identify and save this value */
924   if (!strcmp(name, "host")) {
925     CONFIG_IS_DOUBLE(tmp->host);
926     tmp->host = strdup((char *) val);
927   }
928   else if (!strcmp(name, "port")) {
929     int port = *(int *)val;
930     if ((port <= 0) || (port > 65535)) {
931       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
932                              "Invalid port number!\n"));
933       got_errno = SILC_CONFIG_EPRINTLINE;
934       goto got_err;
935     }
936     tmp->port = (SilcUInt16) port;
937   }
938   else if (!strcmp(name, "passphrase")) {
939     CONFIG_IS_DOUBLE(tmp->passphrase);
940     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
941                            (void **)&tmp->passphrase,
942                            &tmp->passphrase_len)) {
943       got_errno = SILC_CONFIG_ESILENT;
944       goto got_err;
945     }
946   }
947   else if (!strcmp(name, "publickey")) {
948     CONFIG_IS_DOUBLE(tmp->publickeys);
949     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
950                            (void **)&tmp->publickeys, NULL)) {
951       got_errno = SILC_CONFIG_ESILENT;
952       goto got_err;
953     }
954   }
955   else if (!strcmp(name, "params")) {
956     CONFIG_IS_DOUBLE(tmp->param);
957     tmp->param = my_find_param(config, (char *) val);
958     if (!tmp->param) { /* error message already output */
959       got_errno = SILC_CONFIG_EPRINTLINE;
960       goto got_err;
961     }
962   }
963   else if (!strcmp(name, "initiator")) {
964     tmp->initiator = *(bool *)val;
965   }
966   else if (!strcmp(name, "backuphost")) {
967     CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
968     tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
969                               strdup("*"));
970     tmp->backup_router = TRUE;
971   }
972   else if (!strcmp(name, "backupport")) {
973     int port = *(int *)val;
974     if ((port <= 0) || (port > 65535)) {
975       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
976                              "Invalid port number!\n"));
977       got_errno = SILC_CONFIG_EPRINTLINE;
978       goto got_err;
979     }
980     tmp->backup_replace_port = (SilcUInt16) port;
981   }
982   else if (!strcmp(name, "backuplocal")) {
983     tmp->backup_local = *(bool *)val;
984   }
985   else
986     return SILC_CONFIG_EINTERNAL;
987
988   return SILC_CONFIG_OK;
989
990  got_err:
991   silc_free(tmp->host);
992   silc_free(tmp->backup_replace_ip);
993   CONFIG_FREE_AUTH(tmp);
994   silc_free(tmp);
995   config->tmp = NULL;
996   return got_errno;
997 }
998
999 /* known config options tables */
1000 static const SilcConfigTable table_general[] = {
1001   { "module_path",              SILC_CONFIG_ARG_STRE,   fetch_generic,  NULL },
1002   { "prefer_passphrase_auth",   SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1003   { "require_reverse_lookup",   SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1004   { "connections_max",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1005   { "connections_max_per_host", SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1006   { "keepalive_secs",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1007   { "reconnect_count",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1008   { "reconnect_interval",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1009   { "reconnect_interval_max",   SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1010   { "reconnect_keep_trying",    SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1011   { "key_exchange_rekey",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1012   { "key_exchange_pfs",         SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1013   { "channel_rekey_secs",       SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1014   { "key_exchange_timeout",     SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1015   { "conn_auth_timeout",        SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1016   { "version_protocol",         SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1017   { "version_software",         SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1018   { "version_software_vendor",  SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
1019   { "detach_disabled",          SILC_CONFIG_ARG_TOGGLE, fetch_generic,  NULL },
1020   { "detach_timeout",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
1021   { 0, 0, 0, 0 }
1022 };
1023
1024 static const SilcConfigTable table_cipher[] = {
1025   { "name",             SILC_CONFIG_ARG_STR,    fetch_cipher,   NULL },
1026   { "module",           SILC_CONFIG_ARG_STRE,   fetch_cipher,   NULL },
1027   { "keylength",        SILC_CONFIG_ARG_INT,    fetch_cipher,   NULL },
1028   { "blocklength",      SILC_CONFIG_ARG_INT,    fetch_cipher,   NULL },
1029   { 0, 0, 0, 0 }
1030 };
1031
1032 static const SilcConfigTable table_hash[] = {
1033   { "name",             SILC_CONFIG_ARG_STR,    fetch_hash,     NULL },
1034   { "module",           SILC_CONFIG_ARG_STRE,   fetch_hash,     NULL },
1035   { "blocklength",      SILC_CONFIG_ARG_INT,    fetch_hash,     NULL },
1036   { "digestlength",     SILC_CONFIG_ARG_INT,    fetch_hash,     NULL },
1037   { 0, 0, 0, 0 }
1038 };
1039
1040 static const SilcConfigTable table_hmac[] = {
1041   { "name",             SILC_CONFIG_ARG_STR,    fetch_hmac,     NULL },
1042   { "hash",             SILC_CONFIG_ARG_STR,    fetch_hmac,     NULL },
1043   { "maclength",        SILC_CONFIG_ARG_INT,    fetch_hmac,     NULL },
1044   { 0, 0, 0, 0 }
1045 };
1046
1047 static const SilcConfigTable table_pkcs[] = {
1048   { "name",             SILC_CONFIG_ARG_STR,    fetch_pkcs,     NULL },
1049   { 0, 0, 0, 0 }
1050 };
1051
1052 static const SilcConfigTable table_serverinfo_c[] = {
1053   { "ip",               SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1054   { "port",             SILC_CONFIG_ARG_INT,    fetch_serverinfo, NULL},
1055   { 0, 0, 0, 0 }
1056 };
1057
1058 static const SilcConfigTable table_serverinfo[] = {
1059   { "hostname",         SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1060   { "primary",          SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo_c},
1061   { "secondary",        SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo_c},
1062   { "servertype",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1063   { "location",         SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1064   { "admin",            SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1065   { "adminemail",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1066   { "user",             SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1067   { "group",            SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1068   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1069   { "privatekey",       SILC_CONFIG_ARG_STR,    fetch_serverinfo, NULL},
1070   { "motdfile",         SILC_CONFIG_ARG_STRE,   fetch_serverinfo, NULL},
1071   { "pidfile",          SILC_CONFIG_ARG_STRE,   fetch_serverinfo, NULL},
1072   { 0, 0, 0, 0 }
1073 };
1074
1075 static const SilcConfigTable table_logging_c[] = {
1076   { "file",             SILC_CONFIG_ARG_STR,    fetch_logging,  NULL },
1077   { "size",             SILC_CONFIG_ARG_SIZE,   fetch_logging,  NULL },
1078 /*{ "quicklog",         SILC_CONFIG_ARG_NONE,   fetch_logging,  NULL }, */
1079   { 0, 0, 0, 0 }
1080 };
1081
1082 static const SilcConfigTable table_logging[] = {
1083   { "quicklogs",        SILC_CONFIG_ARG_TOGGLE, fetch_logging,  NULL },
1084   { "flushdelay",       SILC_CONFIG_ARG_INT,    fetch_logging,  NULL },
1085   { "info",             SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1086   { "warnings",         SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1087   { "errors",           SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1088   { "fatals",           SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1089   { 0, 0, 0, 0 }
1090 };
1091
1092 static const SilcConfigTable table_connparam[] = {
1093   { "name",                    SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1094   { "require_reverse_lookup",  SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1095   { "connections_max",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1096   { "connections_max_per_host",SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1097   { "keepalive_secs",          SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1098   { "reconnect_count",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1099   { "reconnect_interval",      SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1100   { "reconnect_interval_max",  SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1101   { "reconnect_keep_trying",   SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1102   { "key_exchange_rekey",      SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1103   { "key_exchange_pfs",        SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1104   { "version_protocol",        SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1105   { "version_software",        SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1106   { "version_software_vendor", SILC_CONFIG_ARG_STR,     fetch_connparam,        NULL },
1107   { 0, 0, 0, 0 }
1108 };
1109
1110 static const SilcConfigTable table_client[] = {
1111   { "host",             SILC_CONFIG_ARG_STRE,   fetch_client,   NULL },
1112   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1113   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1114   { "params",           SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1115   { 0, 0, 0, 0 }
1116 };
1117
1118 static const SilcConfigTable table_admin[] = {
1119   { "host",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1120   { "user",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1121   { "nick",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1122   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1123   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1124   { "port",             SILC_CONFIG_ARG_INT,    fetch_admin,    NULL },
1125   { "params",           SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1126   { 0, 0, 0, 0 }
1127 };
1128
1129 static const SilcConfigTable table_deny[] = {
1130   { "host",             SILC_CONFIG_ARG_STRE,   fetch_deny,     NULL },
1131   { "reason",           SILC_CONFIG_ARG_STR,    fetch_deny,     NULL },
1132   { 0, 0, 0, 0 }
1133 };
1134
1135 static const SilcConfigTable table_serverconn[] = {
1136   { "host",             SILC_CONFIG_ARG_STRE,   fetch_server,   NULL },
1137   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1138   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1139   { "params",           SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1140   { "backup",           SILC_CONFIG_ARG_TOGGLE, fetch_server,   NULL },
1141   { 0, 0, 0, 0 }
1142 };
1143
1144 static const SilcConfigTable table_routerconn[] = {
1145   { "host",             SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
1146   { "port",             SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
1147   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1148   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1149   { "params",           SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1150   { "initiator",        SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1151   { "backuphost",       SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
1152   { "backupport",       SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
1153   { "backuplocal",      SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1154   { 0, 0, 0, 0 }
1155 };
1156
1157 static const SilcConfigTable table_main[] = {
1158   { "general",          SILC_CONFIG_ARG_BLOCK,  NULL,          table_general },
1159   { "cipher",           SILC_CONFIG_ARG_BLOCK,  fetch_cipher,  table_cipher },
1160   { "hash",             SILC_CONFIG_ARG_BLOCK,  fetch_hash,    table_hash },
1161   { "hmac",             SILC_CONFIG_ARG_BLOCK,  fetch_hmac,    table_hmac },
1162   { "pkcs",             SILC_CONFIG_ARG_BLOCK,  fetch_pkcs,    table_pkcs },
1163   { "serverinfo",       SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo },
1164   { "logging",          SILC_CONFIG_ARG_BLOCK,  NULL,          table_logging },
1165   { "connectionparams", SILC_CONFIG_ARG_BLOCK,  fetch_connparam, table_connparam },
1166   { "client",           SILC_CONFIG_ARG_BLOCK,  fetch_client,  table_client },
1167   { "admin",            SILC_CONFIG_ARG_BLOCK,  fetch_admin,   table_admin },
1168   { "deny",             SILC_CONFIG_ARG_BLOCK,  fetch_deny,    table_deny },
1169   { "serverconnection", SILC_CONFIG_ARG_BLOCK,  fetch_server,  table_serverconn },
1170   { "routerconnection", SILC_CONFIG_ARG_BLOCK,  fetch_router,  table_routerconn },
1171   { 0, 0, 0, 0 }
1172 };
1173
1174 /* Set default values to stuff that was not configured. */
1175
1176 static void silc_server_config_set_defaults(SilcServerConfig config)
1177 {
1178   my_set_param_defaults(&config->param, NULL);
1179
1180   config->channel_rekey_secs = (config->channel_rekey_secs ?
1181                                 config->channel_rekey_secs :
1182                                 SILC_SERVER_CHANNEL_REKEY);
1183   config->key_exchange_timeout = (config->key_exchange_timeout ?
1184                                   config->key_exchange_timeout :
1185                                   SILC_SERVER_SKE_TIMEOUT);
1186   config->conn_auth_timeout = (config->conn_auth_timeout ?
1187                                config->conn_auth_timeout :
1188                                SILC_SERVER_CONNAUTH_TIMEOUT);
1189 }
1190
1191 /* Allocates a new configuration object, opens configuration file and
1192    parses it. The parsed data is returned to the newly allocated
1193    configuration object. The SilcServerConfig must be freed by calling
1194    the silc_server_config_destroy function. */
1195
1196 SilcServerConfig silc_server_config_alloc(const char *filename)
1197 {
1198   SilcServerConfig config_new;
1199   SilcConfigEntity ent;
1200   SilcConfigFile *file;
1201   int ret;
1202   SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1203
1204   /* alloc a config object */
1205   config_new = silc_calloc(1, sizeof(*config_new));
1206   config_new->refcount = 1;
1207   if (!config_new)
1208     return NULL;
1209
1210   /* obtain a config file object */
1211   file = silc_config_open(filename);
1212   if (!file) {
1213     SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1214                            filename));
1215     return NULL;
1216   }
1217
1218   /* obtain a SilcConfig entity, we can use it to start the parsing */
1219   ent = silc_config_init(file);
1220
1221   /* load the known configuration options, give our empty object as context */
1222   silc_config_register_table(ent, table_main, (void *) config_new);
1223
1224   /* enter the main parsing loop.  When this returns, we have the parsing
1225    * result and the object filled (or partially, in case of errors). */
1226   ret = silc_config_main(ent);
1227   SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1228                   silc_config_strerror(ret)));
1229
1230   /* Check if the parser returned errors */
1231   if (ret) {
1232     /* handle this special error return which asks to quietly return */
1233     if (ret != SILC_CONFIG_ESILENT) {
1234       char *linebuf, *filename = silc_config_get_filename(file);
1235       SilcUInt32 line = silc_config_get_line(file);
1236       if (ret != SILC_CONFIG_EPRINTLINE)
1237         SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1238                                silc_config_strerror(ret)));
1239       linebuf = silc_config_read_line(file, line);
1240       SILC_SERVER_LOG_ERROR(("  file %s line %lu:  %s\n\n", filename,
1241                              line, linebuf));
1242       silc_free(linebuf);
1243     }
1244     silc_server_config_destroy(config_new);
1245     return NULL;
1246   }
1247
1248   /* close (destroy) the file object */
1249   silc_config_close(file);
1250
1251   /* If config_new is incomplete, abort the object and return NULL */
1252   if (!config_new->server_info) {
1253     SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1254                            "`server_info'\n"));
1255     silc_server_config_destroy(config_new);
1256     return NULL;
1257   }
1258
1259   /* Set default to configuration parameters */
1260   silc_server_config_set_defaults(config_new);
1261
1262   return config_new;
1263 }
1264
1265 /* Increments the reference counter of a config object */
1266
1267 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1268                             void *ref_ptr)
1269 {
1270   if (ref_ptr) {
1271     config->refcount++;
1272     ref->config = config;
1273     ref->ref_ptr = ref_ptr;
1274     SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1275                     config->refcount - 1, config->refcount));
1276   }
1277 }
1278
1279 /* Decrements the reference counter of a config object.  If the counter
1280    reaches 0, the config object is destroyed. */
1281
1282 void silc_server_config_unref(SilcServerConfigRef *ref)
1283 {
1284   if (ref->ref_ptr)
1285     silc_server_config_destroy(ref->config);
1286 }
1287
1288 /* Destroy a config object with all his children lists */
1289
1290 void silc_server_config_destroy(SilcServerConfig config)
1291 {
1292   void *tmp;
1293
1294   config->refcount--;
1295   SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1296                   config->refcount + 1, config->refcount));
1297   if (config->refcount > 0)
1298     return;
1299
1300   SILC_LOG_DEBUG(("Freeing config context"));
1301
1302   /* Destroy general config stuff */
1303   silc_free(config->module_path);
1304   silc_free(config->param.version_protocol);
1305   silc_free(config->param.version_software);
1306   silc_free(config->param.version_software_vendor);
1307
1308   /* Destroy Logging channels */
1309   if (config->logging_info)
1310     silc_free(config->logging_info->file);
1311   if (config->logging_warnings)
1312     silc_free(config->logging_warnings->file);
1313   if (config->logging_errors)
1314     silc_free(config->logging_errors->file);
1315   if (config->logging_fatals)
1316     silc_free(config->logging_fatals->file);
1317   silc_free(config->logging_info);
1318   silc_free(config->logging_warnings);
1319   silc_free(config->logging_errors);
1320   silc_free(config->logging_fatals);
1321
1322   /* Destroy the ServerInfo struct */
1323   if (config->server_info) {
1324     register SilcServerConfigServerInfo *si = config->server_info;
1325     silc_free(si->server_name);
1326     if (si->primary) {
1327       silc_free(si->primary->server_ip);
1328       silc_free(si->primary);
1329     }
1330     SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1331                                   si->secondary)
1332       silc_free(di->server_ip);
1333       silc_free(di);
1334     }
1335     silc_free(si->server_type);
1336     silc_free(si->location);
1337     silc_free(si->admin);
1338     silc_free(si->email);
1339     silc_free(si->user);
1340     silc_free(si->group);
1341     silc_free(si->motd_file);
1342     silc_free(si->pid_file);
1343     silc_pkcs_public_key_free(si->public_key);
1344     silc_pkcs_private_key_free(si->private_key);
1345     silc_free(si);
1346   }
1347
1348   /* Now let's destroy the lists */
1349
1350   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1351                                   config->cipher)
1352     silc_free(di->name);
1353     silc_free(di->module);
1354     silc_free(di);
1355   }
1356   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1357     silc_free(di->name);
1358     silc_free(di->module);
1359     silc_free(di);
1360   }
1361   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1362     silc_free(di->name);
1363     silc_free(di->hash);
1364     silc_free(di);
1365   }
1366   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1367     silc_free(di->name);
1368     silc_free(di);
1369   }
1370   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1371                                   config->conn_params)
1372     silc_free(di->name);
1373     silc_free(di->version_protocol);
1374     silc_free(di->version_software);
1375     silc_free(di->version_software_vendor);
1376     silc_free(di);
1377   }
1378   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1379     silc_free(di->host);
1380     CONFIG_FREE_AUTH(di);
1381     silc_free(di);
1382   }
1383   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1384     silc_free(di->host);
1385     silc_free(di->user);
1386     silc_free(di->nick);
1387     CONFIG_FREE_AUTH(di);
1388     silc_free(di);
1389   }
1390   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1391     silc_free(di->host);
1392     silc_free(di->reason);
1393     silc_free(di);
1394   }
1395   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1396                                   config->servers)
1397     silc_free(di->host);
1398     CONFIG_FREE_AUTH(di);
1399     silc_free(di);
1400   }
1401   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1402                                   config->routers)
1403     silc_free(di->host);
1404     silc_free(di->backup_replace_ip);
1405     CONFIG_FREE_AUTH(di);
1406     silc_free(di);
1407   }
1408
1409   memset(config, 'F', sizeof(*config));
1410   silc_free(config);
1411 }
1412
1413 /* Registers configured ciphers. These can then be allocated by the
1414    server when needed. */
1415
1416 bool silc_server_config_register_ciphers(SilcServer server)
1417 {
1418   SilcServerConfig config = server->config;
1419   SilcServerConfigCipher *cipher = config->cipher;
1420   char *module_path = config->module_path;
1421
1422   SILC_LOG_DEBUG(("Registering configured ciphers"));
1423
1424   if (!cipher) /* any cipher in the config file? */
1425     return FALSE;
1426
1427   while (cipher) {
1428     /* if there isn't a module_path OR there isn't a module sim name try to
1429      * use buil-in functions */
1430     if (!module_path || !cipher->module) {
1431       int i;
1432       for (i = 0; silc_default_ciphers[i].name; i++)
1433         if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1434           silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1435           break;
1436         }
1437       if (!silc_cipher_is_supported(cipher->name)) {
1438         SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1439         silc_server_stop(server);
1440         exit(1);
1441       }
1442     } else {
1443 #ifdef SILC_SIM
1444       /* Load (try at least) the crypto SIM module */
1445       char buf[1023], *alg_name;
1446       SilcCipherObject cipher_obj;
1447       SilcSim sim;
1448
1449       memset(&cipher_obj, 0, sizeof(cipher_obj));
1450       cipher_obj.name = cipher->name;
1451       cipher_obj.block_len = cipher->block_length;
1452       cipher_obj.key_len = cipher->key_length * 8;
1453
1454       /* build the libname */
1455       snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1456                 cipher->module);
1457       sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1458
1459       alg_name = strdup(cipher->name);
1460       if (strchr(alg_name, '-'))
1461         *strchr(alg_name, '-') = '\0';
1462
1463       if (silc_sim_load(sim)) {
1464         cipher_obj.set_key =
1465           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1466                                                 SILC_CIPHER_SIM_SET_KEY));
1467         SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1468         cipher_obj.set_key_with_string =
1469           silc_sim_getsym(sim,
1470             silc_sim_symname(alg_name,
1471               SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1472         SILC_LOG_DEBUG(("set_key_with_string=%p",
1473           cipher_obj.set_key_with_string));
1474         cipher_obj.encrypt =
1475           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1476                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1477         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1478         cipher_obj.decrypt =
1479           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1480                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1481         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1482         cipher_obj.context_len =
1483           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1484                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1485         SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1486
1487         /* Put the SIM to the list of all SIM's in server */
1488         silc_dlist_add(server->sim, sim);
1489
1490         silc_free(alg_name);
1491       } else {
1492         SILC_LOG_ERROR(("Error configuring ciphers"));
1493         silc_server_stop(server);
1494         exit(1);
1495       }
1496
1497       /* Register the cipher */
1498       silc_cipher_register(&cipher_obj);
1499 #else
1500       SILC_LOG_ERROR(("Dynamic module support not compiled, "
1501                         "can't load modules!"));
1502       silc_server_stop(server);
1503       exit(1);
1504 #endif
1505     }
1506     cipher = cipher->next;
1507   } /* while */
1508
1509   return TRUE;
1510 }
1511
1512 /* Registers configured hash functions. These can then be allocated by the
1513    server when needed. */
1514
1515 bool silc_server_config_register_hashfuncs(SilcServer server)
1516 {
1517   SilcServerConfig config = server->config;
1518   SilcServerConfigHash *hash = config->hash;
1519   char *module_path = config->module_path;
1520
1521   SILC_LOG_DEBUG(("Registering configured hash functions"));
1522
1523   if (!hash) /* any hash func in the config file? */
1524     return FALSE;
1525
1526   while (hash) {
1527     /* if there isn't a module_path OR there isn't a module sim name try to
1528      * use buil-in functions */
1529     if (!module_path || !hash->module) {
1530       int i;
1531       for (i = 0; silc_default_hash[i].name; i++)
1532         if (!strcmp(silc_default_hash[i].name, hash->name)) {
1533           silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1534           break;
1535         }
1536       if (!silc_hash_is_supported(hash->name)) {
1537         SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1538         silc_server_stop(server);
1539         exit(1);
1540       }
1541     } else {
1542 #ifdef SILC_SIM
1543       /* Load (try at least) the hash SIM module */
1544       SilcHashObject hash_obj;
1545       SilcSim sim;
1546
1547       memset(&hash_obj, 0, sizeof(hash_obj));
1548       hash_obj.name = hash->name;
1549       hash_obj.block_len = hash->block_length;
1550       hash_obj.hash_len = hash->digest_length;
1551
1552       sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1553
1554       if ((silc_sim_load(sim))) {
1555         hash_obj.init =
1556           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1557                                                 SILC_HASH_SIM_INIT));
1558         SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1559         hash_obj.update =
1560           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1561                                                 SILC_HASH_SIM_UPDATE));
1562         SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1563         hash_obj.final =
1564           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1565                                                 SILC_HASH_SIM_FINAL));
1566         SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1567         hash_obj.context_len =
1568           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1569                                                 SILC_HASH_SIM_CONTEXT_LEN));
1570         SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1571
1572         /* Put the SIM to the table of all SIM's in server */
1573         silc_dlist_add(server->sim, sim);
1574       } else {
1575         SILC_LOG_ERROR(("Error configuring hash functions"));
1576         silc_server_stop(server);
1577         exit(1);
1578       }
1579
1580       /* Register the hash function */
1581       silc_hash_register(&hash_obj);
1582 #else
1583       SILC_LOG_ERROR(("Dynamic module support not compiled, "
1584                         "can't load modules!"));
1585       silc_server_stop(server);
1586       exit(1);
1587 #endif
1588     }
1589     hash = hash->next;
1590   } /* while */
1591
1592   return TRUE;
1593 }
1594
1595 /* Registers configure HMACs. These can then be allocated by the server
1596    when needed. */
1597
1598 bool silc_server_config_register_hmacs(SilcServer server)
1599 {
1600   SilcServerConfig config = server->config;
1601   SilcServerConfigHmac *hmac = config->hmac;
1602
1603   SILC_LOG_DEBUG(("Registering configured HMACs"));
1604
1605   if (!hmac)
1606     return FALSE;
1607
1608   while (hmac) {
1609     SilcHmacObject hmac_obj;
1610     if (!silc_hash_is_supported(hmac->hash)) {
1611       SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1612       silc_server_stop(server);
1613       exit(1);
1614     }
1615
1616     /* Register the HMAC */
1617     memset(&hmac_obj, 0, sizeof(hmac_obj));
1618     hmac_obj.name = hmac->name;
1619     hmac_obj.len = hmac->mac_length;
1620     silc_hmac_register(&hmac_obj);
1621
1622     hmac = hmac->next;
1623   } /* while */
1624
1625   return TRUE;
1626 }
1627
1628 /* Registers configured PKCS's. */
1629
1630 bool silc_server_config_register_pkcs(SilcServer server)
1631 {
1632   SilcServerConfig config = server->config;
1633   SilcServerConfigPkcs *pkcs = config->pkcs;
1634
1635   SILC_LOG_DEBUG(("Registering configured PKCS"));
1636
1637   if (!pkcs)
1638     return FALSE;
1639
1640   while (pkcs) {
1641     int i;
1642     for (i = 0; silc_default_pkcs[i].name; i++)
1643       if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1644         silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1645         break;
1646       }
1647     if (!silc_pkcs_is_supported(pkcs->name)) {
1648       SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1649       silc_server_stop(server);
1650       exit(1);
1651     }
1652     pkcs = pkcs->next;
1653   } /* while */
1654
1655   return TRUE;
1656 }
1657
1658 /* Sets log files where log messages are saved by the server logger. */
1659
1660 void silc_server_config_setlogfiles(SilcServer server)
1661 {
1662   SilcServerConfig config = server->config;
1663   SilcServerConfigLogging *this;
1664
1665   SILC_LOG_DEBUG(("Setting configured log file names and options"));
1666
1667   silc_log_quick = config->logging_quick;
1668   silc_log_flushdelay = (config->logging_flushdelay ?
1669                          config->logging_flushdelay :
1670                          SILC_SERVER_LOG_FLUSH_DELAY);
1671
1672   if ((this = config->logging_fatals))
1673     silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1674                       server->schedule);
1675   if ((this = config->logging_errors))
1676     silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1677                       server->schedule);
1678   if ((this = config->logging_warnings))
1679     silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1680                       server->schedule);
1681   if ((this = config->logging_info))
1682     silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1683                       server->schedule);
1684 }
1685
1686 /* Returns client authentication information from configuration file by host
1687    (name or ip) */
1688
1689 SilcServerConfigClient *
1690 silc_server_config_find_client(SilcServer server, char *host)
1691 {
1692   SilcServerConfig config = server->config;
1693   SilcServerConfigClient *client;
1694
1695   if (!config || !host)
1696     return NULL;
1697
1698   for (client = config->clients; client; client = client->next) {
1699     if (client->host && !silc_string_compare(client->host, host))
1700       continue;
1701     break;
1702   }
1703
1704   /* if none matched, then client is already NULL */
1705   return client;
1706 }
1707
1708 /* Returns admin connection configuration by host, username and/or
1709    nickname. */
1710
1711 SilcServerConfigAdmin *
1712 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1713                               char *nick)
1714 {
1715   SilcServerConfig config = server->config;
1716   SilcServerConfigAdmin *admin;
1717
1718   /* make sure we have a value for the matching parameters */
1719   if (!host)
1720     host = "*";
1721   if (!user)
1722     user = "*";
1723   if (!nick)
1724     nick = "*";
1725
1726   for (admin = config->admins; admin; admin = admin->next) {
1727     if (admin->host && !silc_string_compare(admin->host, host))
1728       continue;
1729     if (admin->user && !silc_string_compare(admin->user, user))
1730       continue;
1731     if (admin->nick && !silc_string_compare(admin->nick, nick))
1732       continue;
1733     /* no checks failed -> this entry matches */
1734     break;
1735   }
1736
1737   /* if none matched, then admin is already NULL */
1738   return admin;
1739 }
1740
1741 /* Returns the denied connection configuration entry by host. */
1742
1743 SilcServerConfigDeny *
1744 silc_server_config_find_denied(SilcServer server, char *host)
1745 {
1746   SilcServerConfig config = server->config;
1747   SilcServerConfigDeny *deny;
1748
1749   /* make sure we have a value for the matching parameters */
1750   if (!config || !host)
1751     return NULL;
1752
1753   for (deny = config->denied; deny; deny = deny->next) {
1754     if (deny->host && !silc_string_compare(deny->host, host))
1755       continue;
1756     break;
1757   }
1758
1759   /* if none matched, then deny is already NULL */
1760   return deny;
1761 }
1762
1763 /* Returns server connection info from server configuartion by host
1764    (name or ip). */
1765
1766 SilcServerConfigServer *
1767 silc_server_config_find_server_conn(SilcServer server, char *host)
1768 {
1769   SilcServerConfig config = server->config;
1770   SilcServerConfigServer *serv = NULL;
1771
1772   if (!host)
1773     return NULL;
1774
1775   if (!config->servers)
1776     return NULL;
1777
1778   for (serv = config->servers; serv; serv = serv->next) {
1779     if (!silc_string_compare(serv->host, host))
1780       continue;
1781     break;
1782   }
1783
1784   return serv;
1785 }
1786
1787 /* Returns router connection info from server configuration by
1788    host (name or ip). */
1789
1790 SilcServerConfigRouter *
1791 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1792 {
1793   SilcServerConfig config = server->config;
1794   SilcServerConfigRouter *serv = NULL;
1795
1796   if (!host)
1797     return NULL;
1798
1799   if (!config->routers)
1800     return NULL;
1801
1802   for (serv = config->routers; serv; serv = serv->next) {
1803     if (!silc_string_compare(serv->host, host))
1804       continue;
1805     if (port && serv->port && serv->port != port)
1806       continue;
1807     break;
1808   }
1809
1810   return serv;
1811 }
1812
1813 /* Returns TRUE if configuration for a router connection that we are
1814    initiating exists. */
1815
1816 bool silc_server_config_is_primary_route(SilcServer server)
1817 {
1818   SilcServerConfig config = server->config;
1819   SilcServerConfigRouter *serv = NULL;
1820   int i;
1821   bool found = FALSE;
1822
1823   serv = config->routers;
1824   for (i = 0; serv; i++) {
1825     if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1826       found = TRUE;
1827       break;
1828     }
1829
1830     serv = serv->next;
1831   }
1832
1833   return found;
1834 }
1835
1836 /* Returns our primary connection configuration or NULL if we do not
1837    have primary router configured. */
1838
1839 SilcServerConfigRouter *
1840 silc_server_config_get_primary_router(SilcServer server)
1841 {
1842   SilcServerConfig config = server->config;
1843   SilcServerConfigRouter *serv = NULL;
1844   int i;
1845
1846   serv = config->routers;
1847   for (i = 0; serv; i++) {
1848     if (serv->initiator == TRUE && serv->backup_router == FALSE)
1849       return serv;
1850     serv = serv->next;
1851   }
1852
1853   return NULL;
1854 }