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