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