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