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