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