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