Various cleanup in error message output in config parsing code
[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\".", 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                               void **auth_data, SilcUInt32 *auth_data_len)
119 {
120   if (auth_meth == SILC_AUTH_PASSWORD) {
121     /* p is a plain text password */
122     if (auth_data && auth_data_len) {
123       if (!silc_utf8_valid(p, strlen(p))) {
124         *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
125                                                SILC_STRING_LANGUAGE);
126         *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
127         silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *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(("Error while parsing config file: "
141                                "Could not load public key file!"));
142         return FALSE;
143       }
144
145     /* The auth_data is a pointer to the hash table of public keys. */
146     if (auth_data) {
147       if (*auth_data == NULL)
148         *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
149                                            NULL, NULL,
150                                            my_free_public_key, NULL,
151                                            TRUE);
152       silc_hash_table_add(*auth_data, public_key, public_key);
153     }
154   } else
155     abort();
156
157   return TRUE;
158 }
159
160 /* Callbacks */
161
162 SILC_CONFIG_CALLBACK(fetch_generic)
163 {
164   SilcServerConfig config = (SilcServerConfig) context;
165   int got_errno = 0;
166
167   if (!strcmp(name, "module_path")) {
168     CONFIG_IS_DOUBLE(config->module_path);
169     config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
170   }
171   else if (!strcmp(name, "prefer_passphrase_auth")) {
172     config->prefer_passphrase_auth = *(bool *)val;
173   }
174   else if (!strcmp(name, "require_reverse_lookup")) {
175     config->require_reverse_lookup = *(bool *)val;
176   }
177   else if (!strcmp(name, "connections_max")) {
178     config->param.connections_max = (SilcUInt32) *(int *)val;
179   }
180   else if (!strcmp(name, "connections_max_per_host")) {
181     config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
182   }
183   else if (!strcmp(name, "keepalive_secs")) {
184     config->param.keepalive_secs = (SilcUInt32) *(int *)val;
185   }
186   else if (!strcmp(name, "reconnect_count")) {
187     config->param.reconnect_count = (SilcUInt32) *(int *)val;
188   }
189   else if (!strcmp(name, "reconnect_interval")) {
190     config->param.reconnect_interval = (SilcUInt32) *(int *)val;
191   }
192   else if (!strcmp(name, "reconnect_interval_max")) {
193     config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
194   }
195   else if (!strcmp(name, "reconnect_keep_trying")) {
196     config->param.reconnect_keep_trying = *(bool *)val;
197   }
198   else if (!strcmp(name, "key_exchange_rekey")) {
199     config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
200   }
201   else if (!strcmp(name, "key_exchange_pfs")) {
202     config->param.key_exchange_pfs = *(bool *)val;
203   }
204   else if (!strcmp(name, "channel_rekey_secs")) {
205     config->channel_rekey_secs = (SilcUInt32) *(int *)val;
206   }
207   else if (!strcmp(name, "key_exchange_timeout")) {
208     config->key_exchange_timeout = (SilcUInt32) *(int *)val;
209   }
210   else if (!strcmp(name, "conn_auth_timeout")) {
211     config->conn_auth_timeout = (SilcUInt32) *(int *)val;
212   }
213   else if (!strcmp(name, "version_protocol")) {
214     CONFIG_IS_DOUBLE(config->param.version_protocol);
215     config->param.version_protocol =
216       (*(char *)val ? strdup((char *) val) : NULL);
217   }
218   else if (!strcmp(name, "version_software")) {
219     CONFIG_IS_DOUBLE(config->param.version_software);
220     config->param.version_software =
221       (*(char *)val ? strdup((char *) val) : NULL);
222   }
223   else if (!strcmp(name, "version_software_vendor")) {
224     CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
225     config->param.version_software_vendor =
226       (*(char *)val ? strdup((char *) val) : NULL);
227   }
228   else if (!strcmp(name, "detach_disabled")) {
229     config->detach_disabled = *(bool *)val;
230   }
231   else if (!strcmp(name, "detach_timeout")) {
232     config->detach_timeout = (SilcUInt32) *(int *)val;
233   }
234   else
235     return SILC_CONFIG_EINTERNAL;
236
237   return SILC_CONFIG_OK;
238
239  got_err:
240   return got_errno;
241 }
242
243 SILC_CONFIG_CALLBACK(fetch_cipher)
244 {
245   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
246
247   SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
248                        type, name, context));
249   if (type == SILC_CONFIG_ARG_BLOCK) {
250     /* check the temporary struct's fields */
251     if (!tmp) /* discard empty sub-blocks */
252       return SILC_CONFIG_OK;
253     if (!tmp->name) {
254       got_errno = SILC_CONFIG_EMISSFIELDS;
255       goto got_err;
256     }
257
258     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
259     config->tmp = NULL;
260     return SILC_CONFIG_OK;
261   }
262   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
263
264   /* Identify and save this value */
265   if (!strcmp(name, "name")) {
266     CONFIG_IS_DOUBLE(tmp->name);
267     tmp->name = strdup((char *) val);
268   }
269   else if (!strcmp(name, "module")) {
270     CONFIG_IS_DOUBLE(tmp->module);
271     tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
272   }
273   else if (!strcmp(name, "keylength")) {
274     tmp->key_length = *(SilcUInt32 *)val;
275   }
276   else if (!strcmp(name, "blocklength")) {
277     tmp->block_length = *(SilcUInt32 *)val;
278   }
279   else
280     return SILC_CONFIG_EINTERNAL;
281   return SILC_CONFIG_OK;
282
283  got_err:
284   silc_free(tmp->name);
285   silc_free(tmp->module);
286   silc_free(tmp);
287   config->tmp = NULL;
288   return got_errno;
289 }
290
291 SILC_CONFIG_CALLBACK(fetch_hash)
292 {
293   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
294
295   SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
296                        type, name, context));
297   if (type == SILC_CONFIG_ARG_BLOCK) {
298     /* check the temporary struct's fields */
299     if (!tmp) /* discard empty sub-blocks */
300       return SILC_CONFIG_OK;
301     if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
302       got_errno = SILC_CONFIG_EMISSFIELDS;
303       goto got_err;
304     }
305
306     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
307     config->tmp = NULL;
308     return SILC_CONFIG_OK;
309   }
310   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
311
312   /* Identify and save this value */
313   if (!strcmp(name, "name")) {
314     CONFIG_IS_DOUBLE(tmp->name);
315     tmp->name = strdup((char *) val);
316   }
317   else if (!strcmp(name, "module")) {
318     CONFIG_IS_DOUBLE(tmp->module);
319     tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
320   }
321   else if (!strcmp(name, "blocklength")) {
322     tmp->block_length = *(int *)val;
323   }
324   else if (!strcmp(name, "digestlength")) {
325     tmp->digest_length = *(int *)val;
326   }
327   else
328     return SILC_CONFIG_EINTERNAL;
329   return SILC_CONFIG_OK;
330
331  got_err:
332   silc_free(tmp->name);
333   silc_free(tmp->module);
334   silc_free(tmp);
335   config->tmp = NULL;
336   return got_errno;
337 }
338
339 SILC_CONFIG_CALLBACK(fetch_hmac)
340 {
341   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
342
343   SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
344                        type, name, context));
345   if (type == SILC_CONFIG_ARG_BLOCK) {
346     /* check the temporary struct's fields */
347     if (!tmp) /* discard empty sub-blocks */
348       return SILC_CONFIG_OK;
349     if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
350       got_errno = SILC_CONFIG_EMISSFIELDS;
351       goto got_err;
352     }
353
354     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
355     config->tmp = NULL;
356     return SILC_CONFIG_OK;
357   }
358   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
359
360   /* Identify and save this value */
361   if (!strcmp(name, "name")) {
362     CONFIG_IS_DOUBLE(tmp->name);
363     tmp->name = strdup((char *) val);
364   }
365   else if (!strcmp(name, "hash")) {
366     CONFIG_IS_DOUBLE(tmp->hash);
367     tmp->hash = strdup((char *) val);
368   }
369   else if (!strcmp(name, "maclength")) {
370     tmp->mac_length = *(int *)val;
371   }
372   else
373     return SILC_CONFIG_EINTERNAL;
374   return SILC_CONFIG_OK;
375
376  got_err:
377   silc_free(tmp->name);
378   silc_free(tmp->hash);
379   silc_free(tmp);
380   config->tmp = NULL;
381   return got_errno;
382 }
383
384 SILC_CONFIG_CALLBACK(fetch_pkcs)
385 {
386   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
387
388   SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
389                        type, name, context));
390   if (type == SILC_CONFIG_ARG_BLOCK) {
391     /* check the temporary struct's fields */
392     if (!tmp) /* discard empty sub-blocks */
393       return SILC_CONFIG_OK;
394     if (!tmp->name) {
395       got_errno = SILC_CONFIG_EMISSFIELDS;
396       goto got_err;
397     }
398
399     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
400     config->tmp = NULL;
401     return SILC_CONFIG_OK;
402   }
403   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
404
405   /* Identify and save this value */
406   if (!strcmp(name, "name")) {
407     CONFIG_IS_DOUBLE(tmp->name);
408     tmp->name = strdup((char *) val);
409   }
410   else
411     return SILC_CONFIG_EINTERNAL;
412   return SILC_CONFIG_OK;
413
414  got_err:
415   silc_free(tmp->name);
416   silc_free(tmp);
417   config->tmp = NULL;
418   return got_errno;
419 }
420
421 SILC_CONFIG_CALLBACK(fetch_serverinfo)
422 {
423   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
424   SilcServerConfigServerInfo *server_info = config->server_info;
425
426   /* if there isn't the struct alloc it */
427   if (!server_info)
428     config->server_info = server_info = (SilcServerConfigServerInfo *)
429                 silc_calloc(1, sizeof(*server_info));
430
431   if (type == SILC_CONFIG_ARG_BLOCK) {
432     if (!strcmp(name, "primary")) {
433       CONFIG_IS_DOUBLE(server_info->primary);
434       if (!tmp)
435         return SILC_CONFIG_OK;
436       server_info->primary = tmp;
437       config->tmp = NULL;
438       return SILC_CONFIG_OK;
439     } else if (!strcmp(name, "secondary")) {
440       if (!tmp)
441         return SILC_CONFIG_OK;
442       SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
443       config->tmp = NULL;
444       return SILC_CONFIG_OK;
445     } else if (!server_info->public_key || !server_info->private_key) {
446       got_errno = SILC_CONFIG_EMISSFIELDS;
447       goto got_err;
448     }
449     return SILC_CONFIG_OK;
450   }
451   if (!strcmp(name, "hostname")) {
452     CONFIG_IS_DOUBLE(server_info->server_name);
453     server_info->server_name = strdup((char *) val);
454   }
455   else if (!strcmp(name, "ip")) {
456     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
457     CONFIG_IS_DOUBLE(tmp->server_ip);
458     tmp->server_ip = strdup((char *) val);
459   }
460   else if (!strcmp(name, "port")) {
461     int port = *(int *)val;
462     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
463     if ((port <= 0) || (port > 65535)) {
464       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
465                              "Invalid port number!"));
466       got_errno = SILC_CONFIG_EPRINTLINE;
467       goto got_err;
468     }
469     tmp->port = (SilcUInt16) port;
470   }
471   else if (!strcmp(name, "servertype")) {
472     CONFIG_IS_DOUBLE(server_info->server_type);
473     server_info->server_type = strdup((char *) val);
474   }
475   else if (!strcmp(name, "admin")) {
476     CONFIG_IS_DOUBLE(server_info->admin);
477     server_info->admin = strdup((char *) val);
478   }
479   else if (!strcmp(name, "adminemail")) {
480     CONFIG_IS_DOUBLE(server_info->email);
481     server_info->email = strdup((char *) val);
482   }
483   else if (!strcmp(name, "location")) {
484     CONFIG_IS_DOUBLE(server_info->location);
485     server_info->location = strdup((char *) val);
486   }
487   else if (!strcmp(name, "user")) {
488     CONFIG_IS_DOUBLE(server_info->user);
489     server_info->user = strdup((char *) val);
490   }
491   else if (!strcmp(name, "group")) {
492     CONFIG_IS_DOUBLE(server_info->group);
493     server_info->group = strdup((char *) val);
494   }
495   else if (!strcmp(name, "motdfile")) {
496     CONFIG_IS_DOUBLE(server_info->motd_file);
497     server_info->motd_file = strdup((char *) val);
498   }
499   else if (!strcmp(name, "pidfile")) {
500     CONFIG_IS_DOUBLE(server_info->pid_file);
501     server_info->pid_file = strdup((char *) val);
502   }
503   else if (!strcmp(name, "publickey")) {
504     char *file_tmp = (char *) val;
505
506     /* try to load specified file, if fail stop config parsing */
507     if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
508                                    SILC_PKCS_FILE_PEM))
509       if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
510                                      SILC_PKCS_FILE_BIN)) {
511         SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
512         return SILC_CONFIG_EPRINTLINE;
513       }
514   }
515   else if (!strcmp(name, "privatekey")) {
516     char *file_tmp = (char *) val;
517
518     /* try to load specified file, if fail stop config parsing */
519     if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
520                                     SILC_PKCS_FILE_BIN))
521       if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
522                                       SILC_PKCS_FILE_PEM)) {
523         SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
524         return SILC_CONFIG_EPRINTLINE;
525       }
526   }
527   else
528     return SILC_CONFIG_EINTERNAL;
529   return SILC_CONFIG_OK;
530
531  got_err:
532   silc_free(tmp);
533   silc_free(config->tmp);
534   config->tmp = NULL;
535   return got_errno;
536 }
537
538 SILC_CONFIG_CALLBACK(fetch_logging)
539 {
540   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
541
542   if (!strcmp(name, "timestamp")) {
543     config->logging_timestamp = *(bool *)val;
544   }
545   else if (!strcmp(name, "quicklogs")) {
546     config->logging_quick = *(bool *)val;
547   }
548   else if (!strcmp(name, "flushdelay")) {
549     int flushdelay = *(int *)val;
550     if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
551       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
552                             "Invalid flushdelay value, use quicklogs if you "
553                             "want real-time logging."));
554       return SILC_CONFIG_EPRINTLINE;
555     }
556     config->logging_flushdelay = (long) flushdelay;
557   }
558
559   /* The following istances happens only in Logging's sub-blocks, a match
560      for the sub-block name means that you should store the filename/maxsize
561      temporary struct to the proper logging channel.
562      If we get a match for "file" or "maxsize" this means that we are inside
563      a sub-sub-block and it is safe to alloc a new tmp. */
564 #define FETCH_LOGGING_CHAN(__chan__, __member__)                \
565   else if (!strcmp(name, __chan__)) {                           \
566     if (!tmp) return SILC_CONFIG_OK;                            \
567     if (!tmp->file) {                                           \
568       got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;        \
569     }                                                           \
570     config->__member__ = tmp;                                   \
571     config->tmp = NULL;                                         \
572   }
573   FETCH_LOGGING_CHAN("info", logging_info)
574   FETCH_LOGGING_CHAN("warnings", logging_warnings)
575   FETCH_LOGGING_CHAN("errors", logging_errors)
576   FETCH_LOGGING_CHAN("fatals", logging_fatals)
577 #undef FETCH_LOGGING_CHAN
578   else if (!strcmp(name, "file")) {
579     SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
580     CONFIG_IS_DOUBLE(tmp->file);
581     tmp->file = strdup((char *) val);
582   }
583   else if (!strcmp(name, "size")) {
584     if (!tmp) {
585       config->tmp = silc_calloc(1, sizeof(*tmp));
586       tmp = (SilcServerConfigLogging *) config->tmp;
587     }
588     tmp->maxsize = *(SilcUInt32 *) val;
589   }
590   else
591     return SILC_CONFIG_EINTERNAL;
592   return SILC_CONFIG_OK;
593
594  got_err:
595   silc_free(tmp->file);
596   silc_free(tmp);
597   config->tmp = NULL;
598   return got_errno;
599 }
600
601 SILC_CONFIG_CALLBACK(fetch_connparam)
602 {
603   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
604
605   SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
606                        type, name, context));
607   if (type == SILC_CONFIG_ARG_BLOCK) {
608     /* check the temporary struct's fields */
609     if (!tmp) /* discard empty sub-blocks */
610       return SILC_CONFIG_OK;
611     if (!tmp->name) {
612       got_errno = SILC_CONFIG_EMISSFIELDS;
613       goto got_err;
614     }
615     /* Set defaults */
616     my_set_param_defaults(tmp, &config->param);
617
618     SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
619     config->tmp = NULL;
620     return SILC_CONFIG_OK;
621   }
622   SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
623
624   if (!strcmp(name, "name")) {
625     CONFIG_IS_DOUBLE(tmp->name);
626     tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
627   }
628   else if (!strcmp(name, "connections_max")) {
629     tmp->connections_max = *(SilcUInt32 *)val;
630   }
631   else if (!strcmp(name, "connections_max_per_host")) {
632     tmp->connections_max_per_host = *(SilcUInt32 *)val;
633   }
634   else if (!strcmp(name, "keepalive_secs")) {
635     tmp->keepalive_secs = *(SilcUInt32 *)val;
636   }
637   else if (!strcmp(name, "reconnect_count")) {
638     tmp->reconnect_count = *(SilcUInt32 *)val;
639   }
640   else if (!strcmp(name, "reconnect_interval")) {
641     tmp->reconnect_interval = *(SilcUInt32 *)val;
642   }
643   else if (!strcmp(name, "reconnect_interval_max")) {
644     tmp->reconnect_interval_max = *(SilcUInt32 *)val;
645   }
646   else if (!strcmp(name, "reconnect_keep_trying")) {
647     tmp->reconnect_keep_trying = *(bool *)val;
648   }
649   else if (!strcmp(name, "key_exchange_rekey")) {
650     tmp->key_exchange_rekey = *(SilcUInt32 *)val;
651   }
652   else if (!strcmp(name, "key_exchange_pfs")) {
653     tmp->key_exchange_pfs = *(bool *)val;
654   }
655   else if (!strcmp(name, "version_protocol")) {
656     CONFIG_IS_DOUBLE(tmp->version_protocol);
657     tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
658   }
659   else if (!strcmp(name, "version_software")) {
660     CONFIG_IS_DOUBLE(tmp->version_software);
661     tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
662   }
663   else if (!strcmp(name, "version_software_vendor")) {
664     CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
665     tmp->version_software_vendor =
666       (*(char *)val ? strdup((char *) val) : NULL);
667   }
668   else if (!strcmp(name, "anonymous")) {
669     tmp->anonymous = *(bool *)val;
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,
708                            (void **)&tmp->passphrase,
709                            &tmp->passphrase_len)) {
710       got_errno = SILC_CONFIG_EPRINTLINE;
711       goto got_err;
712     }
713   }
714   else if (!strcmp(name, "publickey")) {
715     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
716                            (void **)&tmp->publickeys, NULL)) {
717       got_errno = SILC_CONFIG_EPRINTLINE;
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,
774                            (void **)&tmp->passphrase,
775                            &tmp->passphrase_len)) {
776       got_errno = SILC_CONFIG_EPRINTLINE;
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,
783                            (void **)&tmp->publickeys, NULL)) {
784       got_errno = SILC_CONFIG_EPRINTLINE;
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,
870                            (void **)&tmp->passphrase,
871                            &tmp->passphrase_len)) {
872       got_errno = SILC_CONFIG_EPRINTLINE;
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,
879                            (void **)&tmp->publickeys, NULL)) {
880       got_errno = SILC_CONFIG_EPRINTLINE;
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!"));
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,
942                            (void **)&tmp->passphrase,
943                            &tmp->passphrase_len)) {
944       got_errno = SILC_CONFIG_EPRINTLINE;
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,
951                            (void **)&tmp->publickeys, NULL)) {
952       got_errno = SILC_CONFIG_EPRINTLINE;
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!"));
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   { "timestamp",        SILC_CONFIG_ARG_TOGGLE, fetch_logging,  NULL },
1085   { "quicklogs",        SILC_CONFIG_ARG_TOGGLE, fetch_logging,  NULL },
1086   { "flushdelay",       SILC_CONFIG_ARG_INT,    fetch_logging,  NULL },
1087   { "info",             SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1088   { "warnings",         SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1089   { "errors",           SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1090   { "fatals",           SILC_CONFIG_ARG_BLOCK,  fetch_logging,  table_logging_c },
1091   { 0, 0, 0, 0 }
1092 };
1093
1094 static const SilcConfigTable table_connparam[] = {
1095   { "name",                    SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1096   { "require_reverse_lookup",  SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1097   { "connections_max",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1098   { "connections_max_per_host",SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1099   { "keepalive_secs",          SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1100   { "reconnect_count",         SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1101   { "reconnect_interval",      SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1102   { "reconnect_interval_max",  SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1103   { "reconnect_keep_trying",   SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1104   { "key_exchange_rekey",      SILC_CONFIG_ARG_INT,    fetch_connparam, NULL },
1105   { "key_exchange_pfs",        SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1106   { "version_protocol",        SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1107   { "version_software",        SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1108   { "version_software_vendor", SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
1109   { "anonymous",               SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1110   { 0, 0, 0, 0 }
1111 };
1112
1113 static const SilcConfigTable table_client[] = {
1114   { "host",             SILC_CONFIG_ARG_STRE,   fetch_client,   NULL },
1115   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1116   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1117   { "params",           SILC_CONFIG_ARG_STR,    fetch_client,   NULL },
1118   { 0, 0, 0, 0 }
1119 };
1120
1121 static const SilcConfigTable table_admin[] = {
1122   { "host",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1123   { "user",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1124   { "nick",             SILC_CONFIG_ARG_STRE,   fetch_admin,    NULL },
1125   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1126   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1127   { "port",             SILC_CONFIG_ARG_INT,    fetch_admin,    NULL },
1128   { "params",           SILC_CONFIG_ARG_STR,    fetch_admin,    NULL },
1129   { 0, 0, 0, 0 }
1130 };
1131
1132 static const SilcConfigTable table_deny[] = {
1133   { "host",             SILC_CONFIG_ARG_STRE,   fetch_deny,     NULL },
1134   { "reason",           SILC_CONFIG_ARG_STR,    fetch_deny,     NULL },
1135   { 0, 0, 0, 0 }
1136 };
1137
1138 static const SilcConfigTable table_serverconn[] = {
1139   { "host",             SILC_CONFIG_ARG_STRE,   fetch_server,   NULL },
1140   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1141   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1142   { "params",           SILC_CONFIG_ARG_STR,    fetch_server,   NULL },
1143   { "backup",           SILC_CONFIG_ARG_TOGGLE, fetch_server,   NULL },
1144   { 0, 0, 0, 0 }
1145 };
1146
1147 static const SilcConfigTable table_routerconn[] = {
1148   { "host",             SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
1149   { "port",             SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
1150   { "passphrase",       SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1151   { "publickey",        SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1152   { "params",           SILC_CONFIG_ARG_STR,    fetch_router,   NULL },
1153   { "initiator",        SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1154   { "backuphost",       SILC_CONFIG_ARG_STRE,   fetch_router,   NULL },
1155   { "backupport",       SILC_CONFIG_ARG_INT,    fetch_router,   NULL },
1156   { "backuplocal",      SILC_CONFIG_ARG_TOGGLE, fetch_router,   NULL },
1157   { 0, 0, 0, 0 }
1158 };
1159
1160 static const SilcConfigTable table_main[] = {
1161   { "general",          SILC_CONFIG_ARG_BLOCK,  NULL,          table_general },
1162   { "cipher",           SILC_CONFIG_ARG_BLOCK,  fetch_cipher,  table_cipher },
1163   { "hash",             SILC_CONFIG_ARG_BLOCK,  fetch_hash,    table_hash },
1164   { "hmac",             SILC_CONFIG_ARG_BLOCK,  fetch_hmac,    table_hmac },
1165   { "pkcs",             SILC_CONFIG_ARG_BLOCK,  fetch_pkcs,    table_pkcs },
1166   { "serverinfo",       SILC_CONFIG_ARG_BLOCK,  fetch_serverinfo, table_serverinfo },
1167   { "logging",          SILC_CONFIG_ARG_BLOCK,  NULL,          table_logging },
1168   { "connectionparams", SILC_CONFIG_ARG_BLOCK,  fetch_connparam, table_connparam },
1169   { "client",           SILC_CONFIG_ARG_BLOCK,  fetch_client,  table_client },
1170   { "admin",            SILC_CONFIG_ARG_BLOCK,  fetch_admin,   table_admin },
1171   { "deny",             SILC_CONFIG_ARG_BLOCK,  fetch_deny,    table_deny },
1172   { "serverconnection", SILC_CONFIG_ARG_BLOCK,  fetch_server,  table_serverconn },
1173   { "routerconnection", SILC_CONFIG_ARG_BLOCK,  fetch_router,  table_routerconn },
1174   { 0, 0, 0, 0 }
1175 };
1176
1177 /* Set default values to stuff that was not configured. */
1178
1179 static void silc_server_config_set_defaults(SilcServerConfig config)
1180 {
1181   my_set_param_defaults(&config->param, NULL);
1182
1183   config->channel_rekey_secs = (config->channel_rekey_secs ?
1184                                 config->channel_rekey_secs :
1185                                 SILC_SERVER_CHANNEL_REKEY);
1186   config->key_exchange_timeout = (config->key_exchange_timeout ?
1187                                   config->key_exchange_timeout :
1188                                   SILC_SERVER_SKE_TIMEOUT);
1189   config->conn_auth_timeout = (config->conn_auth_timeout ?
1190                                config->conn_auth_timeout :
1191                                SILC_SERVER_CONNAUTH_TIMEOUT);
1192 }
1193
1194 /* Allocates a new configuration object, opens configuration file and
1195    parses it. The parsed data is returned to the newly allocated
1196    configuration object. The SilcServerConfig must be freed by calling
1197    the silc_server_config_destroy function. */
1198
1199 SilcServerConfig silc_server_config_alloc(const char *filename)
1200 {
1201   SilcServerConfig config_new;
1202   SilcConfigEntity ent;
1203   SilcConfigFile *file;
1204   int ret;
1205   SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1206
1207   /* alloc a config object */
1208   config_new = silc_calloc(1, sizeof(*config_new));
1209   config_new->refcount = 1;
1210   if (!config_new)
1211     return NULL;
1212
1213   /* general config defaults */
1214   config_new->logging_timestamp = TRUE;
1215
1216   /* obtain a config file object */
1217   file = silc_config_open(filename);
1218   if (!file) {
1219     SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1220                            filename));
1221     return NULL;
1222   }
1223
1224   /* obtain a SilcConfig entity, we can use it to start the parsing */
1225   ent = silc_config_init(file);
1226
1227   /* load the known configuration options, give our empty object as context */
1228   silc_config_register_table(ent, table_main, (void *) config_new);
1229
1230   /* enter the main parsing loop.  When this returns, we have the parsing
1231    * result and the object filled (or partially, in case of errors). */
1232   ret = silc_config_main(ent);
1233   SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1234                   silc_config_strerror(ret)));
1235
1236   /* Check if the parser returned errors */
1237   if (ret) {
1238     /* handle this special error return which asks to quietly return */
1239     if (ret != SILC_CONFIG_ESILENT) {
1240       char *linebuf, *filename = silc_config_get_filename(file);
1241       SilcUInt32 line = silc_config_get_line(file);
1242       if (ret != SILC_CONFIG_EPRINTLINE)
1243         SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1244                                silc_config_strerror(ret)));
1245       linebuf = silc_config_read_line(file, line);
1246       SILC_SERVER_LOG_ERROR(("  file %s line %lu:  %s\n", filename,
1247                              line, linebuf));
1248       silc_free(linebuf);
1249     }
1250     silc_server_config_destroy(config_new);
1251     return NULL;
1252   }
1253
1254   /* close (destroy) the file object */
1255   silc_config_close(file);
1256
1257   /* If config_new is incomplete, abort the object and return NULL */
1258   if (!config_new->server_info) {
1259     SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1260                            "`server_info'"));
1261     silc_server_config_destroy(config_new);
1262     return NULL;
1263   }
1264
1265   /* Set default to configuration parameters */
1266   silc_server_config_set_defaults(config_new);
1267
1268   return config_new;
1269 }
1270
1271 /* Increments the reference counter of a config object */
1272
1273 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1274                             void *ref_ptr)
1275 {
1276   if (ref_ptr) {
1277     config->refcount++;
1278     ref->config = config;
1279     ref->ref_ptr = ref_ptr;
1280     SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1281                     config->refcount - 1, config->refcount));
1282   }
1283 }
1284
1285 /* Decrements the reference counter of a config object.  If the counter
1286    reaches 0, the config object is destroyed. */
1287
1288 void silc_server_config_unref(SilcServerConfigRef *ref)
1289 {
1290   if (ref->ref_ptr)
1291     silc_server_config_destroy(ref->config);
1292 }
1293
1294 /* Destroy a config object with all his children lists */
1295
1296 void silc_server_config_destroy(SilcServerConfig config)
1297 {
1298   void *tmp;
1299
1300   config->refcount--;
1301   SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1302                   config->refcount + 1, config->refcount));
1303   if (config->refcount > 0)
1304     return;
1305
1306   SILC_LOG_DEBUG(("Freeing config context"));
1307
1308   /* Destroy general config stuff */
1309   silc_free(config->module_path);
1310   silc_free(config->param.version_protocol);
1311   silc_free(config->param.version_software);
1312   silc_free(config->param.version_software_vendor);
1313
1314   /* Destroy Logging channels */
1315   if (config->logging_info)
1316     silc_free(config->logging_info->file);
1317   if (config->logging_warnings)
1318     silc_free(config->logging_warnings->file);
1319   if (config->logging_errors)
1320     silc_free(config->logging_errors->file);
1321   if (config->logging_fatals)
1322     silc_free(config->logging_fatals->file);
1323   silc_free(config->logging_info);
1324   silc_free(config->logging_warnings);
1325   silc_free(config->logging_errors);
1326   silc_free(config->logging_fatals);
1327
1328   /* Destroy the ServerInfo struct */
1329   if (config->server_info) {
1330     register SilcServerConfigServerInfo *si = config->server_info;
1331     silc_free(si->server_name);
1332     if (si->primary) {
1333       silc_free(si->primary->server_ip);
1334       silc_free(si->primary);
1335     }
1336     SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1337                                   si->secondary)
1338       silc_free(di->server_ip);
1339       silc_free(di);
1340     }
1341     silc_free(si->server_type);
1342     silc_free(si->location);
1343     silc_free(si->admin);
1344     silc_free(si->email);
1345     silc_free(si->user);
1346     silc_free(si->group);
1347     silc_free(si->motd_file);
1348     silc_free(si->pid_file);
1349     silc_pkcs_public_key_free(si->public_key);
1350     silc_pkcs_private_key_free(si->private_key);
1351     silc_free(si);
1352   }
1353
1354   /* Now let's destroy the lists */
1355
1356   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1357                                   config->cipher)
1358     silc_free(di->name);
1359     silc_free(di->module);
1360     silc_free(di);
1361   }
1362   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1363     silc_free(di->name);
1364     silc_free(di->module);
1365     silc_free(di);
1366   }
1367   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1368     silc_free(di->name);
1369     silc_free(di->hash);
1370     silc_free(di);
1371   }
1372   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1373     silc_free(di->name);
1374     silc_free(di);
1375   }
1376   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1377                                   config->conn_params)
1378     silc_free(di->name);
1379     silc_free(di->version_protocol);
1380     silc_free(di->version_software);
1381     silc_free(di->version_software_vendor);
1382     silc_free(di);
1383   }
1384   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1385     silc_free(di->host);
1386     CONFIG_FREE_AUTH(di);
1387     silc_free(di);
1388   }
1389   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1390     silc_free(di->host);
1391     silc_free(di->user);
1392     silc_free(di->nick);
1393     CONFIG_FREE_AUTH(di);
1394     silc_free(di);
1395   }
1396   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1397     silc_free(di->host);
1398     silc_free(di->reason);
1399     silc_free(di);
1400   }
1401   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1402                                   config->servers)
1403     silc_free(di->host);
1404     CONFIG_FREE_AUTH(di);
1405     silc_free(di);
1406   }
1407   SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1408                                   config->routers)
1409     silc_free(di->host);
1410     silc_free(di->backup_replace_ip);
1411     CONFIG_FREE_AUTH(di);
1412     silc_free(di);
1413   }
1414
1415   memset(config, 'F', sizeof(*config));
1416   silc_free(config);
1417 }
1418
1419 /* Registers configured ciphers. These can then be allocated by the
1420    server when needed. */
1421
1422 bool silc_server_config_register_ciphers(SilcServer server)
1423 {
1424   SilcServerConfig config = server->config;
1425   SilcServerConfigCipher *cipher = config->cipher;
1426   char *module_path = config->module_path;
1427
1428   SILC_LOG_DEBUG(("Registering configured ciphers"));
1429
1430   if (!cipher) /* any cipher in the config file? */
1431     return FALSE;
1432
1433   while (cipher) {
1434     /* if there isn't a module_path OR there isn't a module sim name try to
1435      * use buil-in functions */
1436     if (!module_path || !cipher->module) {
1437       int i;
1438       for (i = 0; silc_default_ciphers[i].name; i++)
1439         if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1440           silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1441           break;
1442         }
1443       if (!silc_cipher_is_supported(cipher->name)) {
1444         SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1445         silc_server_stop(server);
1446         exit(1);
1447       }
1448     } else {
1449 #ifdef SILC_SIM
1450       /* Load (try at least) the crypto SIM module */
1451       char buf[1023], *alg_name;
1452       SilcCipherObject cipher_obj;
1453       SilcSim sim;
1454
1455       memset(&cipher_obj, 0, sizeof(cipher_obj));
1456       cipher_obj.name = cipher->name;
1457       cipher_obj.block_len = cipher->block_length;
1458       cipher_obj.key_len = cipher->key_length * 8;
1459
1460       /* build the libname */
1461       snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1462                 cipher->module);
1463       sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1464
1465       alg_name = strdup(cipher->name);
1466       if (strchr(alg_name, '-'))
1467         *strchr(alg_name, '-') = '\0';
1468
1469       if (silc_sim_load(sim)) {
1470         cipher_obj.set_key =
1471           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1472                                                 SILC_CIPHER_SIM_SET_KEY));
1473         SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1474         cipher_obj.set_key_with_string =
1475           silc_sim_getsym(sim,
1476             silc_sim_symname(alg_name,
1477               SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1478         SILC_LOG_DEBUG(("set_key_with_string=%p",
1479           cipher_obj.set_key_with_string));
1480         cipher_obj.encrypt =
1481           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1482                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1483         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1484         cipher_obj.decrypt =
1485           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1486                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1487         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1488         cipher_obj.context_len =
1489           silc_sim_getsym(sim, silc_sim_symname(alg_name,
1490                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1491         SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1492
1493         /* Put the SIM to the list of all SIM's in server */
1494         silc_dlist_add(server->sim, sim);
1495
1496         silc_free(alg_name);
1497       } else {
1498         SILC_LOG_ERROR(("Error configuring ciphers"));
1499         silc_server_stop(server);
1500         exit(1);
1501       }
1502
1503       /* Register the cipher */
1504       silc_cipher_register(&cipher_obj);
1505 #else
1506       SILC_LOG_ERROR(("Dynamic module support not compiled, "
1507                         "can't load modules!"));
1508       silc_server_stop(server);
1509       exit(1);
1510 #endif
1511     }
1512     cipher = cipher->next;
1513   } /* while */
1514
1515   return TRUE;
1516 }
1517
1518 /* Registers configured hash functions. These can then be allocated by the
1519    server when needed. */
1520
1521 bool silc_server_config_register_hashfuncs(SilcServer server)
1522 {
1523   SilcServerConfig config = server->config;
1524   SilcServerConfigHash *hash = config->hash;
1525   char *module_path = config->module_path;
1526
1527   SILC_LOG_DEBUG(("Registering configured hash functions"));
1528
1529   if (!hash) /* any hash func in the config file? */
1530     return FALSE;
1531
1532   while (hash) {
1533     /* if there isn't a module_path OR there isn't a module sim name try to
1534      * use buil-in functions */
1535     if (!module_path || !hash->module) {
1536       int i;
1537       for (i = 0; silc_default_hash[i].name; i++)
1538         if (!strcmp(silc_default_hash[i].name, hash->name)) {
1539           silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1540           break;
1541         }
1542       if (!silc_hash_is_supported(hash->name)) {
1543         SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1544         silc_server_stop(server);
1545         exit(1);
1546       }
1547     } else {
1548 #ifdef SILC_SIM
1549       /* Load (try at least) the hash SIM module */
1550       SilcHashObject hash_obj;
1551       SilcSim sim;
1552
1553       memset(&hash_obj, 0, sizeof(hash_obj));
1554       hash_obj.name = hash->name;
1555       hash_obj.block_len = hash->block_length;
1556       hash_obj.hash_len = hash->digest_length;
1557
1558       sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1559
1560       if ((silc_sim_load(sim))) {
1561         hash_obj.init =
1562           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1563                                                 SILC_HASH_SIM_INIT));
1564         SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1565         hash_obj.update =
1566           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1567                                                 SILC_HASH_SIM_UPDATE));
1568         SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1569         hash_obj.final =
1570           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1571                                                 SILC_HASH_SIM_FINAL));
1572         SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1573         hash_obj.context_len =
1574           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1575                                                 SILC_HASH_SIM_CONTEXT_LEN));
1576         SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1577
1578         /* Put the SIM to the table of all SIM's in server */
1579         silc_dlist_add(server->sim, sim);
1580       } else {
1581         SILC_LOG_ERROR(("Error configuring hash functions"));
1582         silc_server_stop(server);
1583         exit(1);
1584       }
1585
1586       /* Register the hash function */
1587       silc_hash_register(&hash_obj);
1588 #else
1589       SILC_LOG_ERROR(("Dynamic module support not compiled, "
1590                         "can't load modules!"));
1591       silc_server_stop(server);
1592       exit(1);
1593 #endif
1594     }
1595     hash = hash->next;
1596   } /* while */
1597
1598   return TRUE;
1599 }
1600
1601 /* Registers configure HMACs. These can then be allocated by the server
1602    when needed. */
1603
1604 bool silc_server_config_register_hmacs(SilcServer server)
1605 {
1606   SilcServerConfig config = server->config;
1607   SilcServerConfigHmac *hmac = config->hmac;
1608
1609   SILC_LOG_DEBUG(("Registering configured HMACs"));
1610
1611   if (!hmac)
1612     return FALSE;
1613
1614   while (hmac) {
1615     SilcHmacObject hmac_obj;
1616     if (!silc_hash_is_supported(hmac->hash)) {
1617       SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1618       silc_server_stop(server);
1619       exit(1);
1620     }
1621
1622     /* Register the HMAC */
1623     memset(&hmac_obj, 0, sizeof(hmac_obj));
1624     hmac_obj.name = hmac->name;
1625     hmac_obj.len = hmac->mac_length;
1626     silc_hmac_register(&hmac_obj);
1627
1628     hmac = hmac->next;
1629   } /* while */
1630
1631   return TRUE;
1632 }
1633
1634 /* Registers configured PKCS's. */
1635
1636 bool silc_server_config_register_pkcs(SilcServer server)
1637 {
1638   SilcServerConfig config = server->config;
1639   SilcServerConfigPkcs *pkcs = config->pkcs;
1640
1641   SILC_LOG_DEBUG(("Registering configured PKCS"));
1642
1643   if (!pkcs)
1644     return FALSE;
1645
1646   while (pkcs) {
1647     int i;
1648     for (i = 0; silc_default_pkcs[i].name; i++)
1649       if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1650         silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1651         break;
1652       }
1653     if (!silc_pkcs_is_supported(pkcs->name)) {
1654       SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1655       silc_server_stop(server);
1656       exit(1);
1657     }
1658     pkcs = pkcs->next;
1659   } /* while */
1660
1661   return TRUE;
1662 }
1663
1664 /* Sets log files where log messages are saved by the server logger. */
1665
1666 void silc_server_config_setlogfiles(SilcServer server)
1667 {
1668   SilcServerConfig config = server->config;
1669   SilcServerConfigLogging *this;
1670
1671   SILC_LOG_DEBUG(("Setting configured log file names and options"));
1672
1673   silc_log_timestamp = config->logging_timestamp;
1674   silc_log_quick = config->logging_quick;
1675   silc_log_flushdelay = (config->logging_flushdelay ?
1676                          config->logging_flushdelay :
1677                          SILC_SERVER_LOG_FLUSH_DELAY);
1678
1679   if ((this = config->logging_fatals))
1680     silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1681                       server->schedule);
1682   if ((this = config->logging_errors))
1683     silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1684                       server->schedule);
1685   if ((this = config->logging_warnings))
1686     silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1687                       server->schedule);
1688   if ((this = config->logging_info))
1689     silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1690                       server->schedule);
1691 }
1692
1693 /* Returns client authentication information from configuration file by host
1694    (name or ip) */
1695
1696 SilcServerConfigClient *
1697 silc_server_config_find_client(SilcServer server, char *host)
1698 {
1699   SilcServerConfig config = server->config;
1700   SilcServerConfigClient *client;
1701
1702   if (!config || !host)
1703     return NULL;
1704
1705   for (client = config->clients; client; client = client->next) {
1706     if (client->host && !silc_string_compare(client->host, host))
1707       continue;
1708     break;
1709   }
1710
1711   /* if none matched, then client is already NULL */
1712   return client;
1713 }
1714
1715 /* Returns admin connection configuration by host, username and/or
1716    nickname. */
1717
1718 SilcServerConfigAdmin *
1719 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1720                               char *nick)
1721 {
1722   SilcServerConfig config = server->config;
1723   SilcServerConfigAdmin *admin;
1724
1725   /* make sure we have a value for the matching parameters */
1726   if (!host)
1727     host = "*";
1728   if (!user)
1729     user = "*";
1730   if (!nick)
1731     nick = "*";
1732
1733   for (admin = config->admins; admin; admin = admin->next) {
1734     if (admin->host && !silc_string_compare(admin->host, host))
1735       continue;
1736     if (admin->user && !silc_string_compare(admin->user, user))
1737       continue;
1738     if (admin->nick && !silc_string_compare(admin->nick, nick))
1739       continue;
1740     /* no checks failed -> this entry matches */
1741     break;
1742   }
1743
1744   /* if none matched, then admin is already NULL */
1745   return admin;
1746 }
1747
1748 /* Returns the denied connection configuration entry by host. */
1749
1750 SilcServerConfigDeny *
1751 silc_server_config_find_denied(SilcServer server, char *host)
1752 {
1753   SilcServerConfig config = server->config;
1754   SilcServerConfigDeny *deny;
1755
1756   /* make sure we have a value for the matching parameters */
1757   if (!config || !host)
1758     return NULL;
1759
1760   for (deny = config->denied; deny; deny = deny->next) {
1761     if (deny->host && !silc_string_compare(deny->host, host))
1762       continue;
1763     break;
1764   }
1765
1766   /* if none matched, then deny is already NULL */
1767   return deny;
1768 }
1769
1770 /* Returns server connection info from server configuartion by host
1771    (name or ip). */
1772
1773 SilcServerConfigServer *
1774 silc_server_config_find_server_conn(SilcServer server, char *host)
1775 {
1776   SilcServerConfig config = server->config;
1777   SilcServerConfigServer *serv = NULL;
1778
1779   if (!host)
1780     return NULL;
1781
1782   if (!config->servers)
1783     return NULL;
1784
1785   for (serv = config->servers; serv; serv = serv->next) {
1786     if (!silc_string_compare(serv->host, host))
1787       continue;
1788     break;
1789   }
1790
1791   return serv;
1792 }
1793
1794 /* Returns router connection info from server configuration by
1795    host (name or ip). */
1796
1797 SilcServerConfigRouter *
1798 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1799 {
1800   SilcServerConfig config = server->config;
1801   SilcServerConfigRouter *serv = NULL;
1802
1803   if (!host)
1804     return NULL;
1805
1806   if (!config->routers)
1807     return NULL;
1808
1809   for (serv = config->routers; serv; serv = serv->next) {
1810     if (!silc_string_compare(serv->host, host))
1811       continue;
1812     if (port && serv->port && serv->port != port)
1813       continue;
1814     break;
1815   }
1816
1817   return serv;
1818 }
1819
1820 /* Find backup router connection by host (name or ip) */
1821
1822 SilcServerConfigRouter *
1823 silc_server_config_find_backup_conn(SilcServer server, char *host)
1824 {
1825   SilcServerConfig config = server->config;
1826   SilcServerConfigRouter *serv = NULL;
1827
1828   if (!host)
1829     return NULL;
1830
1831   if (!config->routers)
1832     return NULL;
1833
1834   for (serv = config->routers; serv; serv = serv->next) {
1835     if (!serv->backup_router)
1836       continue;
1837     if (!silc_string_compare(serv->host, host))
1838       continue;
1839     break;
1840   }
1841
1842   return serv;
1843 }
1844
1845 /* Returns TRUE if configuration for a router connection that we are
1846    initiating exists. */
1847
1848 bool silc_server_config_is_primary_route(SilcServer server)
1849 {
1850   SilcServerConfig config = server->config;
1851   SilcServerConfigRouter *serv = NULL;
1852   int i;
1853   bool found = FALSE;
1854
1855   serv = config->routers;
1856   for (i = 0; serv; i++) {
1857     if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1858       found = TRUE;
1859       break;
1860     }
1861
1862     serv = serv->next;
1863   }
1864
1865   return found;
1866 }
1867
1868 /* Returns our primary connection configuration or NULL if we do not
1869    have primary router configured. */
1870
1871 SilcServerConfigRouter *
1872 silc_server_config_get_primary_router(SilcServer server)
1873 {
1874   SilcServerConfig config = server->config;
1875   SilcServerConfigRouter *serv = NULL;
1876   int i;
1877
1878   serv = config->routers;
1879   for (i = 0; serv; i++) {
1880     if (serv->initiator == TRUE && serv->backup_router == FALSE)
1881       return serv;
1882     serv = serv->next;
1883   }
1884
1885   return NULL;
1886 }
1887
1888 /* If we have backup router configured that is going to replace us this
1889    function returns it. */
1890
1891 SilcServerConfigRouter *
1892 silc_server_config_get_backup_router(SilcServer server)
1893 {
1894   SilcServerConfig config = server->config;
1895   SilcServerConfigRouter *serv = NULL;
1896   int i;
1897
1898   if (server->server_type != SILC_ROUTER)
1899     return NULL;
1900
1901   serv = config->routers;
1902   for (i = 0; serv; i++) {
1903     if (serv->initiator == FALSE && serv->backup_router == TRUE &&
1904         serv->backup_local == TRUE &&
1905         !strcmp(server->config->server_info->primary->server_ip,
1906                 serv->backup_replace_ip) &&
1907         server->config->server_info->primary->port ==
1908         serv->backup_replace_port)
1909       return serv;
1910     serv = serv->next;
1911   }
1912
1913   return NULL;
1914 }