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