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