73a38bfde43bba4a89a656b8cd95d75622496d76
[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_sim_free(sim);
1544         silc_server_stop(server);
1545         exit(1);
1546       }
1547
1548       /* Register the cipher */
1549       silc_cipher_register(&cipher_obj);
1550 #else
1551       SILC_LOG_ERROR(("Dynamic module support not compiled, "
1552                         "can't load modules!"));
1553       silc_server_stop(server);
1554       exit(1);
1555 #endif
1556     }
1557     cipher = cipher->next;
1558   } /* while */
1559
1560   return TRUE;
1561 }
1562
1563 /* Registers configured hash functions. These can then be allocated by the
1564    server when needed. */
1565
1566 bool silc_server_config_register_hashfuncs(SilcServer server)
1567 {
1568   SilcServerConfig config = server->config;
1569   SilcServerConfigHash *hash = config->hash;
1570   char *module_path = config->module_path;
1571
1572   SILC_LOG_DEBUG(("Registering configured hash functions"));
1573
1574   if (!hash) /* any hash func in the config file? */
1575     return FALSE;
1576
1577   while (hash) {
1578     /* if there isn't a module_path OR there isn't a module sim name try to
1579      * use buil-in functions */
1580     if (!module_path || !hash->module) {
1581       int i;
1582       for (i = 0; silc_default_hash[i].name; i++)
1583         if (!strcmp(silc_default_hash[i].name, hash->name)) {
1584           silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1585           break;
1586         }
1587       if (!silc_hash_is_supported(hash->name)) {
1588         SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1589         silc_server_stop(server);
1590         exit(1);
1591       }
1592     } else {
1593 #ifdef SILC_SIM
1594       /* Load (try at least) the hash SIM module */
1595       SilcHashObject hash_obj;
1596       SilcSim sim;
1597
1598       memset(&hash_obj, 0, sizeof(hash_obj));
1599       hash_obj.name = hash->name;
1600       hash_obj.block_len = hash->block_length;
1601       hash_obj.hash_len = hash->digest_length;
1602
1603       sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1604
1605       if ((silc_sim_load(sim))) {
1606         hash_obj.init =
1607           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1608                                                 SILC_HASH_SIM_INIT));
1609         SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1610         hash_obj.update =
1611           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1612                                                 SILC_HASH_SIM_UPDATE));
1613         SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1614         hash_obj.final =
1615           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1616                                                 SILC_HASH_SIM_FINAL));
1617         SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1618         hash_obj.context_len =
1619           silc_sim_getsym(sim, silc_sim_symname(hash->name,
1620                                                 SILC_HASH_SIM_CONTEXT_LEN));
1621         SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1622
1623         /* Put the SIM to the table of all SIM's in server */
1624         silc_dlist_add(server->sim, sim);
1625       } else {
1626         SILC_LOG_ERROR(("Error configuring hash functions"));
1627         silc_sim_free(sim);
1628         silc_server_stop(server);
1629         exit(1);
1630       }
1631
1632       /* Register the hash function */
1633       silc_hash_register(&hash_obj);
1634 #else
1635       SILC_LOG_ERROR(("Dynamic module support not compiled, "
1636                         "can't load modules!"));
1637       silc_server_stop(server);
1638       exit(1);
1639 #endif
1640     }
1641     hash = hash->next;
1642   } /* while */
1643
1644   return TRUE;
1645 }
1646
1647 /* Registers configure HMACs. These can then be allocated by the server
1648    when needed. */
1649
1650 bool silc_server_config_register_hmacs(SilcServer server)
1651 {
1652   SilcServerConfig config = server->config;
1653   SilcServerConfigHmac *hmac = config->hmac;
1654
1655   SILC_LOG_DEBUG(("Registering configured HMACs"));
1656
1657   if (!hmac)
1658     return FALSE;
1659
1660   while (hmac) {
1661     SilcHmacObject hmac_obj;
1662     if (!silc_hash_is_supported(hmac->hash)) {
1663       SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1664       silc_server_stop(server);
1665       exit(1);
1666     }
1667
1668     /* Register the HMAC */
1669     memset(&hmac_obj, 0, sizeof(hmac_obj));
1670     hmac_obj.name = hmac->name;
1671     hmac_obj.len = hmac->mac_length;
1672     silc_hmac_register(&hmac_obj);
1673
1674     hmac = hmac->next;
1675   } /* while */
1676
1677   return TRUE;
1678 }
1679
1680 /* Registers configured PKCS's. */
1681
1682 bool silc_server_config_register_pkcs(SilcServer server)
1683 {
1684   SilcServerConfig config = server->config;
1685   SilcServerConfigPkcs *pkcs = config->pkcs;
1686
1687   SILC_LOG_DEBUG(("Registering configured PKCS"));
1688
1689   if (!pkcs)
1690     return FALSE;
1691
1692   while (pkcs) {
1693     int i;
1694     for (i = 0; silc_default_pkcs[i].name; i++)
1695       if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1696         silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1697         break;
1698       }
1699     if (!silc_pkcs_is_supported(pkcs->name)) {
1700       SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1701       silc_server_stop(server);
1702       exit(1);
1703     }
1704     pkcs = pkcs->next;
1705   } /* while */
1706
1707   return TRUE;
1708 }
1709
1710 /* Sets log files where log messages are saved by the server logger. */
1711
1712 void silc_server_config_setlogfiles(SilcServer server)
1713 {
1714   SilcServerConfig config = server->config;
1715   SilcServerConfigLogging *this;
1716
1717   SILC_LOG_DEBUG(("Setting configured log file names and options"));
1718
1719   silc_log_timestamp = config->logging_timestamp;
1720   silc_log_quick = config->logging_quick;
1721   silc_log_flushdelay = (config->logging_flushdelay ?
1722                          config->logging_flushdelay :
1723                          SILC_SERVER_LOG_FLUSH_DELAY);
1724
1725   if ((this = config->logging_fatals))
1726     silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1727                       server->schedule);
1728   if ((this = config->logging_errors))
1729     silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1730                       server->schedule);
1731   if ((this = config->logging_warnings))
1732     silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1733                       server->schedule);
1734   if ((this = config->logging_info))
1735     silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1736                       server->schedule);
1737 }
1738
1739 /* Returns client authentication information from configuration file by host
1740    (name or ip) */
1741
1742 SilcServerConfigClient *
1743 silc_server_config_find_client(SilcServer server, char *host)
1744 {
1745   SilcServerConfig config = server->config;
1746   SilcServerConfigClient *client;
1747
1748   if (!config || !host)
1749     return NULL;
1750
1751   for (client = config->clients; client; client = client->next) {
1752     if (client->host && !silc_string_compare(client->host, host))
1753       continue;
1754     break;
1755   }
1756
1757   /* if none matched, then client is already NULL */
1758   return client;
1759 }
1760
1761 /* Returns admin connection configuration by host, username and/or
1762    nickname. */
1763
1764 SilcServerConfigAdmin *
1765 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1766                               char *nick)
1767 {
1768   SilcServerConfig config = server->config;
1769   SilcServerConfigAdmin *admin;
1770
1771   /* make sure we have a value for the matching parameters */
1772   if (!host)
1773     host = "*";
1774   if (!user)
1775     user = "*";
1776   if (!nick)
1777     nick = "*";
1778
1779   for (admin = config->admins; admin; admin = admin->next) {
1780     if (admin->host && !silc_string_compare(admin->host, host))
1781       continue;
1782     if (admin->user && !silc_string_compare(admin->user, user))
1783       continue;
1784     if (admin->nick && !silc_string_compare(admin->nick, nick))
1785       continue;
1786     /* no checks failed -> this entry matches */
1787     break;
1788   }
1789
1790   /* if none matched, then admin is already NULL */
1791   return admin;
1792 }
1793
1794 /* Returns the denied connection configuration entry by host. */
1795
1796 SilcServerConfigDeny *
1797 silc_server_config_find_denied(SilcServer server, char *host)
1798 {
1799   SilcServerConfig config = server->config;
1800   SilcServerConfigDeny *deny;
1801
1802   /* make sure we have a value for the matching parameters */
1803   if (!config || !host)
1804     return NULL;
1805
1806   for (deny = config->denied; deny; deny = deny->next) {
1807     if (deny->host && !silc_string_compare(deny->host, host))
1808       continue;
1809     break;
1810   }
1811
1812   /* if none matched, then deny is already NULL */
1813   return deny;
1814 }
1815
1816 /* Returns server connection info from server configuartion by host
1817    (name or ip). */
1818
1819 SilcServerConfigServer *
1820 silc_server_config_find_server_conn(SilcServer server, char *host)
1821 {
1822   SilcServerConfig config = server->config;
1823   SilcServerConfigServer *serv = NULL;
1824
1825   if (!host)
1826     return NULL;
1827
1828   if (!config->servers)
1829     return NULL;
1830
1831   for (serv = config->servers; serv; serv = serv->next) {
1832     if (!silc_string_compare(serv->host, host))
1833       continue;
1834     break;
1835   }
1836
1837   return serv;
1838 }
1839
1840 /* Returns router connection info from server configuration by
1841    host (name or ip). */
1842
1843 SilcServerConfigRouter *
1844 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1845 {
1846   SilcServerConfig config = server->config;
1847   SilcServerConfigRouter *serv = NULL;
1848
1849   if (!host)
1850     return NULL;
1851
1852   if (!config->routers)
1853     return NULL;
1854
1855   for (serv = config->routers; serv; serv = serv->next) {
1856     if (!silc_string_compare(serv->host, host))
1857       continue;
1858     if (port && serv->port && serv->port != port)
1859       continue;
1860     break;
1861   }
1862
1863   return serv;
1864 }
1865
1866 /* Find backup router connection by host (name or ip) */
1867
1868 SilcServerConfigRouter *
1869 silc_server_config_find_backup_conn(SilcServer server, char *host)
1870 {
1871   SilcServerConfig config = server->config;
1872   SilcServerConfigRouter *serv = NULL;
1873
1874   if (!host)
1875     return NULL;
1876
1877   if (!config->routers)
1878     return NULL;
1879
1880   for (serv = config->routers; serv; serv = serv->next) {
1881     if (!serv->backup_router)
1882       continue;
1883     if (!silc_string_compare(serv->host, host))
1884       continue;
1885     break;
1886   }
1887
1888   return serv;
1889 }
1890
1891 /* Returns TRUE if configuration for a router connection that we are
1892    initiating exists. */
1893
1894 bool silc_server_config_is_primary_route(SilcServer server)
1895 {
1896   SilcServerConfig config = server->config;
1897   SilcServerConfigRouter *serv = NULL;
1898   int i;
1899   bool found = FALSE;
1900
1901   serv = config->routers;
1902   for (i = 0; serv; i++) {
1903     if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1904       found = TRUE;
1905       break;
1906     }
1907
1908     serv = serv->next;
1909   }
1910
1911   return found;
1912 }
1913
1914 /* Returns our primary connection configuration or NULL if we do not
1915    have primary router configured. */
1916
1917 SilcServerConfigRouter *
1918 silc_server_config_get_primary_router(SilcServer server)
1919 {
1920   SilcServerConfig config = server->config;
1921   SilcServerConfigRouter *serv = NULL;
1922   int i;
1923
1924   serv = config->routers;
1925   for (i = 0; serv; i++) {
1926     if (serv->initiator == TRUE && serv->backup_router == FALSE)
1927       return serv;
1928     serv = serv->next;
1929   }
1930
1931   return NULL;
1932 }
1933
1934 /* If we have backup router configured that is going to replace us this
1935    function returns it. */
1936
1937 SilcServerConfigRouter *
1938 silc_server_config_get_backup_router(SilcServer server)
1939 {
1940   SilcServerConfig config = server->config;
1941   SilcServerConfigRouter *serv = NULL;
1942   int i;
1943
1944   if (server->server_type != SILC_ROUTER)
1945     return NULL;
1946
1947   serv = config->routers;
1948   for (i = 0; serv; i++) {
1949     if (serv->initiator == FALSE && serv->backup_router == TRUE &&
1950         serv->backup_local == TRUE &&
1951         !strcmp(server->config->server_info->primary->server_ip,
1952                 serv->backup_replace_ip) &&
1953         server->config->server_info->primary->port ==
1954         serv->backup_replace_port)
1955       return serv;
1956     serv = serv->next;
1957   }
1958
1959   return NULL;
1960 }