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