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