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