5 Author: Giovanni Giacobbi <giovanni@giacobbi.net>
7 Copyright (C) 1997 - 2007 Pekka Riikonen
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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
26 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
28 #define SERVER_CONFIG_DEBUG(fmt)
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; \
37 /* allocate the tmp field for fetching data */
38 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__) \
40 config->tmp = silc_calloc(1, sizeof(*findtmp)); \
41 tmp = (__type__ *) config->tmp; \
44 /* append the tmp field to the specified list */
45 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
49 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
50 findtmp->next = tmp; \
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;
60 /* Set EDOUBLE error value and bail out if necessary */
61 #define CONFIG_IS_DOUBLE(__x__) \
63 got_errno = SILC_CONFIG_EDOUBLE; \
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);
72 /* Set default values to those parameters that have not been defined */
74 my_set_param_defaults(SilcServerConfigConnParams *params,
75 SilcServerConfigConnParams *defaults)
77 #define SET_PARAM_DEFAULT(p, d) params->p = \
78 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
80 SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
81 SET_PARAM_DEFAULT(connections_max_per_host,
82 SILC_SERVER_MAX_CONNECTIONS_SINGLE);
83 SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
84 SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
85 SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
86 SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
87 SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
88 SET_PARAM_DEFAULT(qos_rate_limit, SILC_SERVER_QOS_RATE_LIMIT);
89 SET_PARAM_DEFAULT(qos_bytes_limit, SILC_SERVER_QOS_BYTES_LIMIT);
90 SET_PARAM_DEFAULT(qos_limit_sec, SILC_SERVER_QOS_LIMIT_SEC);
91 SET_PARAM_DEFAULT(qos_limit_usec, SILC_SERVER_QOS_LIMIT_USEC);
92 SET_PARAM_DEFAULT(chlimit, SILC_SERVER_CH_JOIN_LIMIT);
94 #undef SET_PARAM_DEFAULT
97 /* Find connection parameters by the parameter block name. */
98 static SilcServerConfigConnParams *
99 my_find_param(SilcServerConfig config, const char *name)
101 SilcServerConfigConnParams *param;
103 for (param = config->conn_params; param; param = param->next) {
104 if (!strcasecmp(param->name, name))
108 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
109 "Cannot find Params \"%s\".", name));
114 /* SKR find callbcak */
116 static void my_find_callback(SilcSKR skr, SilcSKRFind find,
117 SilcSKRStatus status, SilcDList keys,
120 SilcSKRStatus *s = context;
124 silc_dlist_uninit(keys);
126 silc_skr_find_free(find);
129 /* parse an authdata according to its auth method */
130 static SilcBool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
131 void **auth_data, SilcUInt32 *auth_data_len,
132 SilcSKRKeyUsage usage, void *key_context)
134 if (auth_meth == SILC_AUTH_PASSWORD) {
135 /* p is a plain text password */
136 if (auth_data && auth_data_len) {
137 if (!silc_utf8_valid(p, strlen(p))) {
138 *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
140 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
141 silc_utf8_encode(p, strlen(p), SILC_STRING_LOCALE, *auth_data,
144 *auth_data = (void *) strdup(p);
145 *auth_data_len = (SilcUInt32) strlen(p);
148 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
149 /* p is a public key file name */
150 SilcPublicKey public_key;
151 SilcSKR skr = *auth_data;
153 SilcSKRStatus status = SILC_SKR_NOT_FOUND;
155 if (!silc_pkcs_load_public_key(p, &public_key)) {
156 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
157 "Could not load public key file!"));
161 find = silc_skr_find_alloc();
162 silc_skr_find_set_public_key(find, public_key);
163 silc_skr_find_set_usage(find, usage);
165 silc_skr_find_set_context(find, SILC_32_TO_PTR(usage));
166 silc_skr_find(skr, NULL, find, my_find_callback, &status);
167 if (status == SILC_SKR_OK) {
168 /* Already added, ignore error */
169 silc_pkcs_public_key_free(public_key);
173 /* Add the public key to repository */
174 status = silc_skr_add_public_key(skr, public_key, usage,
175 key_context ? key_context :
176 (void *)usage, NULL);
177 if (status != SILC_SKR_OK) {
178 SILC_SERVER_LOG_ERROR(("Error while adding public key \"%s\"", p));
186 static SilcBool my_parse_publickeydir(const char *dirname, void **auth_data,
187 SilcSKRKeyUsage usage)
190 struct dirent *get_file;
193 if (!(dp = opendir(dirname))) {
194 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
195 "Could not open directory \"%s\"", dirname));
199 /* errors are not considered fatal */
200 while ((get_file = readdir(dp))) {
201 const char *filename = get_file->d_name;
203 int dirname_len = strlen(dirname), filename_len = strlen(filename);
204 struct stat check_file;
206 /* Ignore "." and "..", and take files only with ".pub" suffix. */
207 if (!strcmp(filename, ".") || !strcmp(filename, "..") ||
208 (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub"))
211 memset(buf, 0, sizeof(buf));
212 snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname,
213 (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
215 if (stat(buf, &check_file) < 0) {
216 SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
218 } else if (S_ISREG(check_file.st_mode)) {
219 my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL,
225 SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
231 SILC_CONFIG_CALLBACK(fetch_generic)
233 SilcServerConfig config = (SilcServerConfig) context;
236 if (!strcmp(name, "prefer_passphrase_auth")) {
237 config->prefer_passphrase_auth = *(SilcBool *)val;
239 else if (!strcmp(name, "require_reverse_lookup")) {
240 config->require_reverse_lookup = *(SilcBool *)val;
242 else if (!strcmp(name, "connections_max")) {
243 config->param.connections_max = (SilcUInt32) *(int *)val;
245 else if (!strcmp(name, "connections_max_per_host")) {
246 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
248 else if (!strcmp(name, "keepalive_secs")) {
249 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
251 else if (!strcmp(name, "reconnect_count")) {
252 config->param.reconnect_count = (SilcUInt32) *(int *)val;
254 else if (!strcmp(name, "reconnect_interval")) {
255 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
257 else if (!strcmp(name, "reconnect_interval_max")) {
258 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
260 else if (!strcmp(name, "reconnect_keep_trying")) {
261 config->param.reconnect_keep_trying = *(SilcBool *)val;
263 else if (!strcmp(name, "key_exchange_rekey")) {
264 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
266 else if (!strcmp(name, "key_exchange_pfs")) {
267 config->param.key_exchange_pfs = *(SilcBool *)val;
269 else if (!strcmp(name, "channel_rekey_secs")) {
270 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
272 else if (!strcmp(name, "key_exchange_timeout")) {
273 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
275 else if (!strcmp(name, "conn_auth_timeout")) {
276 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
278 else if (!strcmp(name, "version_protocol")) {
279 CONFIG_IS_DOUBLE(config->param.version_protocol);
280 config->param.version_protocol =
281 (*(char *)val ? strdup((char *) val) : NULL);
283 else if (!strcmp(name, "version_software")) {
284 CONFIG_IS_DOUBLE(config->param.version_software);
285 config->param.version_software =
286 (*(char *)val ? strdup((char *) val) : NULL);
288 else if (!strcmp(name, "version_software_vendor")) {
289 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
290 config->param.version_software_vendor =
291 (*(char *)val ? strdup((char *) val) : NULL);
293 else if (!strcmp(name, "detach_disabled")) {
294 config->detach_disabled = *(SilcBool *)val;
296 else if (!strcmp(name, "detach_timeout")) {
297 config->detach_timeout = (SilcUInt32) *(int *)val;
299 else if (!strcmp(name, "qos")) {
300 config->param.qos = *(SilcBool *)val;
302 else if (!strcmp(name, "qos_rate_limit")) {
303 config->param.qos_rate_limit = *(SilcUInt32 *)val;
305 else if (!strcmp(name, "qos_bytes_limit")) {
306 config->param.qos_bytes_limit = *(SilcUInt32 *)val;
308 else if (!strcmp(name, "qos_limit_sec")) {
309 config->param.qos_limit_sec = *(SilcUInt32 *)val;
311 else if (!strcmp(name, "qos_limit_usec")) {
312 config->param.qos_limit_usec = *(SilcUInt32 *)val;
314 else if (!strcmp(name, "channel_join_limit")) {
315 config->param.chlimit = *(SilcUInt32 *)val;
317 else if (!strcmp(name, "debug_string")) {
318 CONFIG_IS_DOUBLE(config->debug_string);
319 config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
321 else if (!strcmp(name, "http_server")) {
322 config->httpd = *(SilcBool *)val;
324 else if (!strcmp(name, "http_server_ip")) {
325 CONFIG_IS_DOUBLE(config->httpd_ip);
326 config->httpd_ip = (*(char *)val ? strdup((char *) val) : NULL);
328 else if (!strcmp(name, "http_server_port")) {
329 int port = *(int *)val;
330 if ((port <= 0) || (port > 65535)) {
331 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
332 "Invalid port number!"));
333 got_errno = SILC_CONFIG_EPRINTLINE;
336 config->httpd_port = (SilcUInt16)port;
338 else if (!strcmp(name, "dynamic_server")) {
339 config->dynamic_server = *(SilcBool *)val;
341 else if (!strcmp(name, "local_channels")) {
342 config->local_channels = *(SilcBool *)val;
345 return SILC_CONFIG_EINTERNAL;
347 return SILC_CONFIG_OK;
353 SILC_CONFIG_CALLBACK(fetch_cipher)
355 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
357 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
358 type, name, context));
359 if (type == SILC_CONFIG_ARG_BLOCK) {
360 /* check the temporary struct's fields */
361 if (!tmp) /* discard empty sub-blocks */
362 return SILC_CONFIG_OK;
364 got_errno = SILC_CONFIG_EMISSFIELDS;
368 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
370 return SILC_CONFIG_OK;
372 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
374 /* Identify and save this value */
375 if (!strcmp(name, "name")) {
376 CONFIG_IS_DOUBLE(tmp->name);
377 tmp->name = strdup((char *) val);
379 else if (!strcmp(name, "keylength")) {
380 tmp->key_length = *(SilcUInt32 *)val;
382 else if (!strcmp(name, "blocklength")) {
383 tmp->block_length = *(SilcUInt32 *)val;
386 return SILC_CONFIG_EINTERNAL;
387 return SILC_CONFIG_OK;
390 silc_free(tmp->name);
396 SILC_CONFIG_CALLBACK(fetch_hash)
398 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
400 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
401 type, name, context));
402 if (type == SILC_CONFIG_ARG_BLOCK) {
403 /* check the temporary struct's fields */
404 if (!tmp) /* discard empty sub-blocks */
405 return SILC_CONFIG_OK;
406 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
407 got_errno = SILC_CONFIG_EMISSFIELDS;
411 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
413 return SILC_CONFIG_OK;
415 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
417 /* Identify and save this value */
418 if (!strcmp(name, "name")) {
419 CONFIG_IS_DOUBLE(tmp->name);
420 tmp->name = strdup((char *) val);
422 else if (!strcmp(name, "blocklength")) {
423 tmp->block_length = *(int *)val;
425 else if (!strcmp(name, "digestlength")) {
426 tmp->digest_length = *(int *)val;
429 return SILC_CONFIG_EINTERNAL;
430 return SILC_CONFIG_OK;
433 silc_free(tmp->name);
439 SILC_CONFIG_CALLBACK(fetch_hmac)
441 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
443 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
444 type, name, context));
445 if (type == SILC_CONFIG_ARG_BLOCK) {
446 /* check the temporary struct's fields */
447 if (!tmp) /* discard empty sub-blocks */
448 return SILC_CONFIG_OK;
449 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
450 got_errno = SILC_CONFIG_EMISSFIELDS;
454 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
456 return SILC_CONFIG_OK;
458 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
460 /* Identify and save this value */
461 if (!strcmp(name, "name")) {
462 CONFIG_IS_DOUBLE(tmp->name);
463 tmp->name = strdup((char *) val);
465 else if (!strcmp(name, "hash")) {
466 CONFIG_IS_DOUBLE(tmp->hash);
467 tmp->hash = strdup((char *) val);
469 else if (!strcmp(name, "maclength")) {
470 tmp->mac_length = *(int *)val;
473 return SILC_CONFIG_EINTERNAL;
474 return SILC_CONFIG_OK;
477 silc_free(tmp->name);
478 silc_free(tmp->hash);
484 SILC_CONFIG_CALLBACK(fetch_pkcs)
486 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
488 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
489 type, name, context));
490 if (type == SILC_CONFIG_ARG_BLOCK) {
491 /* Check the temporary struct's fields */
492 if (!tmp) /* discard empty sub-blocks */
493 return SILC_CONFIG_OK;
495 got_errno = SILC_CONFIG_EMISSFIELDS;
499 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
501 return SILC_CONFIG_OK;
503 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
505 /* Identify and save this value */
506 if (!strcmp(name, "name")) {
507 CONFIG_IS_DOUBLE(tmp->name);
508 tmp->name = strdup((char *) val);
511 return SILC_CONFIG_EINTERNAL;
512 return SILC_CONFIG_OK;
515 silc_free(tmp->name);
521 SILC_CONFIG_CALLBACK(fetch_serverinfo)
523 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
524 SilcServerConfigServerInfo *server_info = config->server_info;
526 SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
527 type, name, context));
529 /* If there isn't the main struct alloc it */
531 config->server_info = server_info = (SilcServerConfigServerInfo *)
532 silc_calloc(1, sizeof(*server_info));
534 if (type == SILC_CONFIG_ARG_BLOCK) {
535 if (!strcmp(name, "primary")) {
536 if (server_info->primary) {
537 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
538 "Double primary specification."));
539 got_errno = SILC_CONFIG_EPRINTLINE;
542 CONFIG_IS_DOUBLE(server_info->primary);
544 /* now check the temporary struct, don't accept empty block and
545 make sure all fields are there */
546 if (!tmp || !tmp->server_ip || !tmp->port) {
547 got_errno = SILC_CONFIG_EMISSFIELDS;
550 server_info->primary = tmp;
552 return SILC_CONFIG_OK;
553 } else if (!strcmp(name, "secondary")) {
555 return SILC_CONFIG_OK;
556 if (!tmp || !tmp->server_ip || !tmp->port) {
557 got_errno = SILC_CONFIG_EMISSFIELDS;
560 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
562 return SILC_CONFIG_OK;
563 } else if (!server_info->public_key || !server_info->private_key) {
564 got_errno = SILC_CONFIG_EMISSFIELDS;
567 return SILC_CONFIG_OK;
569 if (!strcmp(name, "hostname")) {
570 CONFIG_IS_DOUBLE(server_info->server_name);
571 server_info->server_name = strdup((char *) val);
573 else if (!strcmp(name, "ip")) {
574 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
575 CONFIG_IS_DOUBLE(tmp->server_ip);
576 tmp->server_ip = strdup((char *) val);
578 else if (!strcmp(name, "public_ip")) {
579 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
580 CONFIG_IS_DOUBLE(tmp->public_ip);
581 tmp->public_ip = strdup((char *) val);
583 else if (!strcmp(name, "port")) {
584 int port = *(int *)val;
585 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
586 if ((port <= 0) || (port > 65535)) {
587 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
588 "Invalid port number!"));
589 got_errno = SILC_CONFIG_EPRINTLINE;
592 tmp->port = (SilcUInt16) port;
594 else if (!strcmp(name, "servertype")) {
595 CONFIG_IS_DOUBLE(server_info->server_type);
596 server_info->server_type = strdup((char *) val);
598 else if (!strcmp(name, "admin")) {
599 CONFIG_IS_DOUBLE(server_info->admin);
600 server_info->admin = strdup((char *) val);
602 else if (!strcmp(name, "adminemail")) {
603 CONFIG_IS_DOUBLE(server_info->email);
604 server_info->email = strdup((char *) val);
606 else if (!strcmp(name, "location")) {
607 CONFIG_IS_DOUBLE(server_info->location);
608 server_info->location = strdup((char *) val);
610 else if (!strcmp(name, "user")) {
611 CONFIG_IS_DOUBLE(server_info->user);
612 server_info->user = strdup((char *) val);
614 else if (!strcmp(name, "group")) {
615 CONFIG_IS_DOUBLE(server_info->group);
616 server_info->group = strdup((char *) val);
618 else if (!strcmp(name, "motdfile")) {
619 CONFIG_IS_DOUBLE(server_info->motd_file);
620 server_info->motd_file = strdup((char *) val);
622 else if (!strcmp(name, "pidfile")) {
623 CONFIG_IS_DOUBLE(server_info->pid_file);
624 server_info->pid_file = strdup((char *) val);
626 else if (!strcmp(name, "publickey")) {
627 char *file_tmp = (char *) val;
628 CONFIG_IS_DOUBLE(server_info->public_key);
630 /* Try to load specified file, if fail stop config parsing */
631 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key)) {
632 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
633 return SILC_CONFIG_EPRINTLINE;
636 else if (!strcmp(name, "privatekey")) {
638 char *file_tmp = (char *) val;
639 CONFIG_IS_DOUBLE(server_info->private_key);
641 /* Check the private key file permissions. */
642 if ((stat(file_tmp, &st)) != -1) {
643 if ((st.st_mode & 0777) != 0600) {
644 SILC_SERVER_LOG_ERROR(("Wrong permissions in private key "
645 "file \"%s\". The permissions must be "
647 return SILC_CONFIG_ESILENT;
651 /* Try to load specified file, if fail stop config parsing */
652 if (!silc_pkcs_load_private_key(file_tmp, "", 0,
653 &server_info->private_key)) {
654 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
655 return SILC_CONFIG_EPRINTLINE;
659 return SILC_CONFIG_EINTERNAL;
660 return SILC_CONFIG_OK;
663 /* Here we need to check if tmp exists because this function handles
664 * misc data (multiple fields and single-only fields) */
666 silc_free(tmp->server_ip);
673 SILC_CONFIG_CALLBACK(fetch_logging)
675 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
677 if (!strcmp(name, "timestamp")) {
678 config->logging_timestamp = *(SilcBool *)val;
680 else if (!strcmp(name, "quicklogs")) {
681 config->logging_quick = *(SilcBool *)val;
683 else if (!strcmp(name, "flushdelay")) {
684 int flushdelay = *(int *)val;
685 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
686 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
687 "Invalid flushdelay value, use quicklogs if you "
688 "want real-time logging."));
689 return SILC_CONFIG_EPRINTLINE;
691 config->logging_flushdelay = (long) flushdelay;
694 /* The following istances happens only in Logging's sub-blocks, a match
695 for the sub-block name means that you should store the filename/maxsize
696 temporary struct to the proper logging channel.
697 If we get a match for "file" or "maxsize" this means that we are inside
698 a sub-sub-block and it is safe to alloc a new tmp. */
699 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
700 else if (!strcmp(name, __chan__)) { \
701 if (!tmp) return SILC_CONFIG_OK; \
703 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
705 config->__member__ = tmp; \
706 config->tmp = NULL; \
708 FETCH_LOGGING_CHAN("info", logging_info)
709 FETCH_LOGGING_CHAN("warnings", logging_warnings)
710 FETCH_LOGGING_CHAN("errors", logging_errors)
711 FETCH_LOGGING_CHAN("fatals", logging_fatals)
712 #undef FETCH_LOGGING_CHAN
713 else if (!strcmp(name, "file")) {
714 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
715 CONFIG_IS_DOUBLE(tmp->file);
716 tmp->file = strdup((char *) val);
718 else if (!strcmp(name, "size")) {
720 config->tmp = silc_calloc(1, sizeof(*tmp));
721 tmp = (SilcServerConfigLogging *) config->tmp;
723 tmp->maxsize = *(SilcUInt32 *) val;
726 return SILC_CONFIG_EINTERNAL;
727 return SILC_CONFIG_OK;
730 silc_free(tmp->file);
736 SILC_CONFIG_CALLBACK(fetch_connparam)
738 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
740 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
741 type, name, context));
742 if (type == SILC_CONFIG_ARG_BLOCK) {
743 /* check the temporary struct's fields */
744 if (!tmp) /* discard empty sub-blocks */
745 return SILC_CONFIG_OK;
747 got_errno = SILC_CONFIG_EMISSFIELDS;
751 my_set_param_defaults(tmp, &config->param);
753 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
755 return SILC_CONFIG_OK;
758 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
759 tmp->reconnect_keep_trying = TRUE;
762 if (!strcmp(name, "name")) {
763 CONFIG_IS_DOUBLE(tmp->name);
764 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
766 else if (!strcmp(name, "connections_max")) {
767 tmp->connections_max = *(SilcUInt32 *)val;
769 else if (!strcmp(name, "connections_max_per_host")) {
770 tmp->connections_max_per_host = *(SilcUInt32 *)val;
772 else if (!strcmp(name, "keepalive_secs")) {
773 tmp->keepalive_secs = *(SilcUInt32 *)val;
775 else if (!strcmp(name, "reconnect_count")) {
776 tmp->reconnect_count = *(SilcUInt32 *)val;
778 else if (!strcmp(name, "reconnect_interval")) {
779 tmp->reconnect_interval = *(SilcUInt32 *)val;
781 else if (!strcmp(name, "reconnect_interval_max")) {
782 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
784 else if (!strcmp(name, "reconnect_keep_trying")) {
785 tmp->reconnect_keep_trying = *(SilcBool *)val;
787 else if (!strcmp(name, "key_exchange_rekey")) {
788 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
790 else if (!strcmp(name, "key_exchange_pfs")) {
791 tmp->key_exchange_pfs = *(SilcBool *)val;
793 else if (!strcmp(name, "version_protocol")) {
794 CONFIG_IS_DOUBLE(tmp->version_protocol);
795 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
797 else if (!strcmp(name, "version_software")) {
798 CONFIG_IS_DOUBLE(tmp->version_software);
799 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
801 else if (!strcmp(name, "version_software_vendor")) {
802 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
803 tmp->version_software_vendor =
804 (*(char *)val ? strdup((char *) val) : NULL);
806 else if (!strcmp(name, "anonymous")) {
807 tmp->anonymous = *(SilcBool *)val;
809 else if (!strcmp(name, "qos")) {
810 tmp->qos = *(SilcBool *)val;
812 else if (!strcmp(name, "qos_rate_limit")) {
813 tmp->qos_rate_limit = *(SilcUInt32 *)val;
815 else if (!strcmp(name, "qos_bytes_limit")) {
816 tmp->qos_bytes_limit = *(SilcUInt32 *)val;
818 else if (!strcmp(name, "qos_limit_sec")) {
819 tmp->qos_limit_sec = *(SilcUInt32 *)val;
821 else if (!strcmp(name, "qos_limit_usec")) {
822 tmp->qos_limit_usec = *(SilcUInt32 *)val;
825 return SILC_CONFIG_EINTERNAL;
827 return SILC_CONFIG_OK;
830 silc_free(tmp->name);
836 SILC_CONFIG_CALLBACK(fetch_client)
838 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
840 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
841 type, name, context));
843 /* Alloc before block checking, because empty sub-blocks are welcome here */
844 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
846 if (type == SILC_CONFIG_ARG_BLOCK) {
847 /* empty sub-blocks are welcome */
848 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
850 return SILC_CONFIG_OK;
853 /* Identify and save this value */
854 if (!strcmp(name, "host")) {
855 CONFIG_IS_DOUBLE(tmp->host);
856 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
858 else if (!strcmp(name, "passphrase")) {
859 CONFIG_IS_DOUBLE(tmp->passphrase);
860 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
861 (void *)&tmp->passphrase,
862 &tmp->passphrase_len, 0, NULL)) {
863 got_errno = SILC_CONFIG_EPRINTLINE;
867 else if (!strcmp(name, "publickey")) {
868 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
869 (void *)&config->server->repository, NULL,
870 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
871 got_errno = SILC_CONFIG_EPRINTLINE;
875 else if (!strcmp(name, "publickeydir")) {
876 if (!my_parse_publickeydir((char *) val,
877 (void *)&config->server->repository,
878 SILC_SKR_USAGE_KEY_AGREEMENT)) {
879 got_errno = SILC_CONFIG_EPRINTLINE;
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;
892 return SILC_CONFIG_EINTERNAL;
893 return SILC_CONFIG_OK;
896 silc_free(tmp->host);
897 CONFIG_FREE_AUTH(tmp);
903 SILC_CONFIG_CALLBACK(fetch_admin)
905 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
907 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
908 type, name, context));
909 if (type == SILC_CONFIG_ARG_BLOCK) {
910 /* check the temporary struct's fields */
911 if (!tmp) /* discard empty sub-blocks */
912 return SILC_CONFIG_OK;
914 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
916 return SILC_CONFIG_OK;
918 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
920 /* Identify and save this value */
921 if (!strcmp(name, "host")) {
922 CONFIG_IS_DOUBLE(tmp->host);
923 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
925 else if (!strcmp(name, "user")) {
926 CONFIG_IS_DOUBLE(tmp->user);
927 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
929 else if (!strcmp(name, "nick")) {
930 CONFIG_IS_DOUBLE(tmp->nick);
931 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
933 else if (!strcmp(name, "passphrase")) {
934 CONFIG_IS_DOUBLE(tmp->passphrase);
935 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
936 (void *)&tmp->passphrase,
937 &tmp->passphrase_len, 0, NULL)) {
938 got_errno = SILC_CONFIG_EPRINTLINE;
942 else if (!strcmp(name, "publickey")) {
943 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
944 (void *)&config->server->repository, NULL,
945 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, tmp)) {
946 got_errno = SILC_CONFIG_EPRINTLINE;
951 return SILC_CONFIG_EINTERNAL;
952 return SILC_CONFIG_OK;
955 silc_free(tmp->host);
956 silc_free(tmp->user);
957 silc_free(tmp->nick);
958 CONFIG_FREE_AUTH(tmp);
964 SILC_CONFIG_CALLBACK(fetch_deny)
966 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
968 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
969 type, name, context));
970 if (type == SILC_CONFIG_ARG_BLOCK) {
971 /* check the temporary struct's fields */
972 if (!tmp) /* discard empty sub-blocks */
973 return SILC_CONFIG_OK;
975 got_errno = SILC_CONFIG_EMISSFIELDS;
979 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
981 return SILC_CONFIG_OK;
983 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
985 /* Identify and save this value */
986 if (!strcmp(name, "host")) {
987 CONFIG_IS_DOUBLE(tmp->host);
988 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
990 else if (!strcmp(name, "reason")) {
991 CONFIG_IS_DOUBLE(tmp->reason);
992 tmp->reason = strdup((char *) val);
995 return SILC_CONFIG_EINTERNAL;
996 return SILC_CONFIG_OK;
999 silc_free(tmp->host);
1000 silc_free(tmp->reason);
1006 SILC_CONFIG_CALLBACK(fetch_server)
1008 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
1010 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
1011 type, name, context));
1012 if (type == SILC_CONFIG_ARG_BLOCK) {
1013 /* check the temporary struct's fields */
1014 if (!tmp) /* discard empty sub-blocks */
1015 return SILC_CONFIG_OK;
1017 got_errno = SILC_CONFIG_EMISSFIELDS;
1021 /* the temporary struct is ok, append it to the list */
1022 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
1024 return SILC_CONFIG_OK;
1026 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
1028 /* Identify and save this value */
1029 if (!strcmp(name, "host")) {
1030 CONFIG_IS_DOUBLE(tmp->host);
1031 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
1033 else if (!strcmp(name, "passphrase")) {
1034 CONFIG_IS_DOUBLE(tmp->passphrase);
1035 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1036 (void *)&tmp->passphrase,
1037 &tmp->passphrase_len, 0, NULL)) {
1038 got_errno = SILC_CONFIG_EPRINTLINE;
1042 else if (!strcmp(name, "publickey")) {
1043 CONFIG_IS_DOUBLE(tmp->publickeys);
1044 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1045 (void *)&config->server->repository, NULL,
1046 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1047 got_errno = SILC_CONFIG_EPRINTLINE;
1051 else if (!strcmp(name, "params")) {
1052 CONFIG_IS_DOUBLE(tmp->param);
1053 tmp->param = my_find_param(config, (char *) val);
1054 if (!tmp->param) { /* error message already output */
1055 got_errno = SILC_CONFIG_EPRINTLINE;
1059 else if (!strcmp(name, "backup")) {
1060 tmp->backup_router = *(SilcBool *)val;
1063 return SILC_CONFIG_EINTERNAL;
1065 return SILC_CONFIG_OK;
1068 silc_free(tmp->host);
1069 CONFIG_FREE_AUTH(tmp);
1075 SILC_CONFIG_CALLBACK(fetch_router)
1077 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1079 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1080 type, name, context));
1081 if (type == SILC_CONFIG_ARG_BLOCK) {
1082 if (!tmp) /* discard empty sub-blocks */
1083 return SILC_CONFIG_OK;
1085 got_errno = SILC_CONFIG_EMISSFIELDS;
1089 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
1091 return SILC_CONFIG_OK;
1093 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
1095 /* Identify and save this value */
1096 if (!strcmp(name, "host")) {
1097 CONFIG_IS_DOUBLE(tmp->host);
1098 tmp->host = strdup((char *) val);
1100 else if (!strcmp(name, "port")) {
1101 int port = *(int *)val;
1102 if ((port <= 0) || (port > 65535)) {
1103 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1104 "Invalid port number!"));
1105 got_errno = SILC_CONFIG_EPRINTLINE;
1108 tmp->port = (SilcUInt16) port;
1110 else if (!strcmp(name, "passphrase")) {
1111 CONFIG_IS_DOUBLE(tmp->passphrase);
1112 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1113 (void *)&tmp->passphrase,
1114 &tmp->passphrase_len, 0, NULL)) {
1115 got_errno = SILC_CONFIG_EPRINTLINE;
1119 else if (!strcmp(name, "publickey")) {
1120 CONFIG_IS_DOUBLE(tmp->publickeys);
1121 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1122 (void *)&config->server->repository, NULL,
1123 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1124 got_errno = SILC_CONFIG_EPRINTLINE;
1128 else if (!strcmp(name, "params")) {
1129 CONFIG_IS_DOUBLE(tmp->param);
1130 tmp->param = my_find_param(config, (char *) val);
1131 if (!tmp->param) { /* error message already output */
1132 got_errno = SILC_CONFIG_EPRINTLINE;
1136 else if (!strcmp(name, "initiator")) {
1137 tmp->initiator = *(SilcBool *)val;
1139 else if (!strcmp(name, "backuphost")) {
1140 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
1141 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1143 tmp->backup_router = TRUE;
1145 else if (!strcmp(name, "backupport")) {
1146 int port = *(int *)val;
1147 if ((port <= 0) || (port > 65535)) {
1148 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1149 "Invalid port number!"));
1150 got_errno = SILC_CONFIG_EPRINTLINE;
1153 tmp->backup_replace_port = (SilcUInt16) port;
1155 else if (!strcmp(name, "backuplocal")) {
1156 tmp->backup_local = *(SilcBool *)val;
1158 else if (!strcmp(name, "dynamic_connection")) {
1159 tmp->dynamic_connection = *(SilcBool *)val;
1162 return SILC_CONFIG_EINTERNAL;
1164 return SILC_CONFIG_OK;
1167 silc_free(tmp->host);
1168 silc_free(tmp->backup_replace_ip);
1169 CONFIG_FREE_AUTH(tmp);
1175 /* known config options tables */
1176 static const SilcConfigTable table_general[] = {
1177 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1178 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1179 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1180 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1181 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1182 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1183 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1184 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1185 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1186 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1187 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1188 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1189 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1190 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1191 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1192 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1193 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1194 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1195 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1196 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1197 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1198 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1199 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1200 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1201 { "channel_join_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1202 { "debug_string", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1203 { "http_server", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1204 { "http_server_ip", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1205 { "http_server_port", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1206 { "dynamic_server", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1207 { "local_channels", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1211 static const SilcConfigTable table_cipher[] = {
1212 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1213 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1214 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1218 static const SilcConfigTable table_hash[] = {
1219 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1220 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1221 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1225 static const SilcConfigTable table_hmac[] = {
1226 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1227 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1228 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1232 static const SilcConfigTable table_pkcs[] = {
1233 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1237 static const SilcConfigTable table_serverinfo_c[] = {
1238 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1239 { "public_ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1240 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1244 static const SilcConfigTable table_serverinfo[] = {
1245 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1246 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1247 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1248 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1249 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1250 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1251 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1252 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1253 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1254 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1255 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1256 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1257 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1261 static const SilcConfigTable table_logging_c[] = {
1262 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1263 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1264 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1268 static const SilcConfigTable table_logging[] = {
1269 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1270 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1271 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1272 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1273 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1274 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1275 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1279 static const SilcConfigTable table_connparam[] = {
1280 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1281 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1282 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1283 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1284 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1285 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1286 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1287 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1288 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1289 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1290 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1291 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1292 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1293 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1294 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1295 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1296 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1297 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1298 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1299 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1303 static const SilcConfigTable table_client[] = {
1304 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1305 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1306 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1307 { "publickeydir", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1308 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1312 static const SilcConfigTable table_admin[] = {
1313 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1314 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1315 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1316 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1317 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1318 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1319 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1323 static const SilcConfigTable table_deny[] = {
1324 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1325 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1329 static const SilcConfigTable table_serverconn[] = {
1330 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1331 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1332 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1333 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1334 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1338 static const SilcConfigTable table_routerconn[] = {
1339 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1340 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1341 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1342 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1343 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1344 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1345 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1346 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1347 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1348 { "dynamic_connection", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1352 static const SilcConfigTable table_main[] = {
1353 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1354 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1355 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1356 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1357 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1358 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1359 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1360 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1361 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1362 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1363 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1364 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1365 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1369 /* Set default values to stuff that was not configured. */
1371 static void silc_server_config_set_defaults(SilcServerConfig config)
1373 my_set_param_defaults(&config->param, NULL);
1375 config->channel_rekey_secs = (config->channel_rekey_secs ?
1376 config->channel_rekey_secs :
1377 SILC_SERVER_CHANNEL_REKEY);
1378 config->key_exchange_timeout = (config->key_exchange_timeout ?
1379 config->key_exchange_timeout :
1380 SILC_SERVER_SKE_TIMEOUT);
1381 config->conn_auth_timeout = (config->conn_auth_timeout ?
1382 config->conn_auth_timeout :
1383 SILC_SERVER_CONNAUTH_TIMEOUT);
1386 /* Check for correctness of the configuration */
1388 static SilcBool silc_server_config_check(SilcServerConfig config)
1390 SilcBool ret = TRUE;
1391 SilcServerConfigServer *s;
1392 SilcServerConfigRouter *r;
1395 /* ServerConfig is mandatory */
1396 if (!config->server_info) {
1397 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `ServerInfo'"));
1401 if (!config->server_info->public_key ||
1402 !config->server_info->private_key) {
1403 SILC_SERVER_LOG_ERROR(("\nError: Server keypair is missing"));
1407 if (!config->server_info->primary) {
1408 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `Primary' "
1409 "in `ServerInfo'"));
1413 if (!config->server_info->primary->server_ip) {
1414 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory field `Ip' "
1415 "in `Primary' in `ServerInfo'"));
1419 /* RouterConnection sanity checks */
1421 if (config->routers && config->routers->backup_router == TRUE &&
1423 SILC_SERVER_LOG_ERROR((
1424 "\nError: First RouterConnection block must be primary router "
1425 "connection. You have marked it incorrectly as backup router."));
1428 if (config->routers && config->routers->backup_router == TRUE &&
1429 !config->servers && !config->routers->next) {
1430 SILC_SERVER_LOG_ERROR((
1431 "\nError: You have configured backup router but not primary router. "
1432 "If backup router is configured also primary router must be "
1437 /* Backup router sanity checks */
1439 for (r = config->routers; r; r = r->next) {
1440 if (r->backup_router && !strcmp(r->host, r->backup_replace_ip)) {
1441 SILC_SERVER_LOG_ERROR((
1442 "\nError: Backup router connection incorrectly configured to use "
1443 "primary and backup router as same host `%s'. They must not be "
1444 "same host.", r->host));
1448 if (r->initiator == FALSE && r->port != 0) {
1449 SILC_SERVER_LOG_WARNING(("\nWarning: Initiator is FALSE and Port is "
1450 "specified. Ignoring Port value."));
1455 /* ServerConnection sanity checks */
1457 for (s = config->servers; s; s = s->next) {
1458 if (s->backup_router) {
1464 for (s = config->servers; s; s = s->next) {
1465 if (!s->backup_router) {
1466 SILC_SERVER_LOG_ERROR((
1467 "\nError: Your server is backup router but not all ServerConnection "
1468 "blocks were marked as backup connections. They all must be "
1469 "marked as backup connections."));
1479 /* Allocates a new configuration object, opens configuration file and
1480 parses it. The parsed data is returned to the newly allocated
1481 configuration object. The SilcServerConfig must be freed by calling
1482 the silc_server_config_destroy function. */
1484 SilcServerConfig silc_server_config_alloc(const char *filename,
1487 SilcServerConfig config_new;
1488 SilcConfigEntity ent;
1489 SilcConfigFile *file;
1491 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1493 /* alloc a config object */
1494 config_new = silc_calloc(1, sizeof(*config_new));
1498 /* general config defaults */
1499 config_new->refcount = 1;
1500 config_new->logging_timestamp = TRUE;
1501 config_new->param.reconnect_keep_trying = TRUE;
1502 config_new->server = server;
1504 /* obtain a config file object */
1505 file = silc_config_open(filename);
1507 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1512 /* obtain a SilcConfig entity, we can use it to start the parsing */
1513 ent = silc_config_init(file);
1515 /* load the known configuration options, give our empty object as context */
1516 silc_config_register_table(ent, table_main, (void *) config_new);
1518 /* enter the main parsing loop. When this returns, we have the parsing
1519 * result and the object filled (or partially, in case of errors). */
1520 ret = silc_config_main(ent);
1521 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1522 silc_config_strerror(ret)));
1524 /* Check if the parser returned errors */
1526 /* handle this special error return which asks to quietly return */
1527 if (ret != SILC_CONFIG_ESILENT) {
1528 char *linebuf, *filename = silc_config_get_filename(file);
1529 SilcUInt32 line = silc_config_get_line(file);
1530 if (ret != SILC_CONFIG_EPRINTLINE)
1531 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1532 silc_config_strerror(ret)));
1533 linebuf = silc_config_read_line(file, line);
1535 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1540 silc_server_config_destroy(config_new);
1541 silc_config_close(file);
1545 /* close (destroy) the file object */
1546 silc_config_close(file);
1548 /* Check the configuration */
1549 if (!silc_server_config_check(config_new)) {
1550 silc_server_config_destroy(config_new);
1554 /* Set default to configuration parameters */
1555 silc_server_config_set_defaults(config_new);
1560 /* Increments the reference counter of a config object */
1562 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1567 ref->config = config;
1568 ref->ref_ptr = ref_ptr;
1569 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1570 config->refcount - 1, config->refcount));
1574 /* Decrements the reference counter of a config object. If the counter
1575 reaches 0, the config object is destroyed. */
1577 void silc_server_config_unref(SilcServerConfigRef *ref)
1580 silc_server_config_destroy(ref->config);
1583 /* Destroy a config object with all his children lists */
1585 void silc_server_config_destroy(SilcServerConfig config)
1590 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1591 config->refcount + 1, config->refcount));
1592 if (config->refcount > 0)
1595 SILC_LOG_DEBUG(("Freeing config context"));
1597 /* Destroy general config stuff */
1598 silc_free(config->debug_string);
1599 silc_free(config->param.version_protocol);
1600 silc_free(config->param.version_software);
1601 silc_free(config->param.version_software_vendor);
1602 silc_free(config->httpd_ip);
1604 /* Destroy Logging channels */
1605 if (config->logging_info)
1606 silc_free(config->logging_info->file);
1607 if (config->logging_warnings)
1608 silc_free(config->logging_warnings->file);
1609 if (config->logging_errors)
1610 silc_free(config->logging_errors->file);
1611 if (config->logging_fatals)
1612 silc_free(config->logging_fatals->file);
1613 silc_free(config->logging_info);
1614 silc_free(config->logging_warnings);
1615 silc_free(config->logging_errors);
1616 silc_free(config->logging_fatals);
1618 /* Destroy the ServerInfo struct */
1619 if (config->server_info) {
1620 register SilcServerConfigServerInfo *si = config->server_info;
1621 silc_free(si->server_name);
1623 silc_free(si->primary->server_ip);
1624 silc_free(si->primary);
1626 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1628 silc_free(di->server_ip);
1631 silc_free(si->server_type);
1632 silc_free(si->location);
1633 silc_free(si->admin);
1634 silc_free(si->email);
1635 silc_free(si->user);
1636 silc_free(si->group);
1637 silc_free(si->motd_file);
1638 silc_free(si->pid_file);
1640 silc_pkcs_public_key_free(si->public_key);
1641 if (si->private_key)
1642 silc_pkcs_private_key_free(si->private_key);
1646 /* Now let's destroy the lists */
1648 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1650 silc_free(di->name);
1653 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1654 silc_free(di->name);
1657 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1658 silc_free(di->name);
1659 silc_free(di->hash);
1662 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1663 silc_free(di->name);
1666 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1667 config->conn_params)
1668 silc_free(di->name);
1669 silc_free(di->version_protocol);
1670 silc_free(di->version_software);
1671 silc_free(di->version_software_vendor);
1674 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1675 silc_free(di->host);
1676 CONFIG_FREE_AUTH(di);
1679 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1680 silc_free(di->host);
1681 silc_free(di->user);
1682 silc_free(di->nick);
1683 CONFIG_FREE_AUTH(di);
1686 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1687 silc_free(di->host);
1688 silc_free(di->reason);
1691 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1693 silc_free(di->host);
1694 CONFIG_FREE_AUTH(di);
1697 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1699 silc_free(di->host);
1700 silc_free(di->backup_replace_ip);
1701 CONFIG_FREE_AUTH(di);
1705 memset(config, 'F', sizeof(*config));
1709 /* Registers configured ciphers. These can then be allocated by the
1710 server when needed. */
1712 SilcBool silc_server_config_register_ciphers(SilcServer server)
1714 SilcServerConfig config = server->config;
1715 SilcServerConfigCipher *cipher = config->cipher;
1716 char *module_path = config->module_path;
1718 SILC_LOG_DEBUG(("Registering configured ciphers"));
1720 if (!cipher) /* any cipher in the config file? */
1724 /* if there isn't a module_path OR there isn't a module sim name try to
1725 * use buil-in functions */
1726 if (!module_path || !cipher->module) {
1728 for (i = 0; silc_default_ciphers[i].name; i++)
1729 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1730 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1733 if (!silc_cipher_is_supported(cipher->name)) {
1734 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1735 silc_server_stop(server);
1739 cipher = cipher->next;
1745 /* Registers configured hash functions. These can then be allocated by the
1746 server when needed. */
1748 SilcBool silc_server_config_register_hashfuncs(SilcServer server)
1750 SilcServerConfig config = server->config;
1751 SilcServerConfigHash *hash = config->hash;
1752 char *module_path = config->module_path;
1754 SILC_LOG_DEBUG(("Registering configured hash functions"));
1756 if (!hash) /* any hash func in the config file? */
1760 /* if there isn't a module_path OR there isn't a module sim name try to
1761 * use buil-in functions */
1762 if (!module_path || !hash->module) {
1764 for (i = 0; silc_default_hash[i].name; i++)
1765 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1766 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1769 if (!silc_hash_is_supported(hash->name)) {
1770 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1771 silc_server_stop(server);
1781 /* Registers configure HMACs. These can then be allocated by the server
1784 SilcBool silc_server_config_register_hmacs(SilcServer server)
1786 SilcServerConfig config = server->config;
1787 SilcServerConfigHmac *hmac = config->hmac;
1789 SILC_LOG_DEBUG(("Registering configured HMACs"));
1795 SilcHmacObject hmac_obj;
1796 if (!silc_hash_is_supported(hmac->hash)) {
1797 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1798 silc_server_stop(server);
1802 /* Register the HMAC */
1803 memset(&hmac_obj, 0, sizeof(hmac_obj));
1804 hmac_obj.name = hmac->name;
1805 hmac_obj.len = hmac->mac_length;
1806 silc_hmac_register(&hmac_obj);
1814 /* Registers configured PKCS's. */
1816 SilcBool silc_server_config_register_pkcs(SilcServer server)
1821 /* Sets log files where log messages are saved by the server logger. */
1823 void silc_server_config_setlogfiles(SilcServer server)
1825 SilcServerConfig config = server->config;
1826 SilcServerConfigLogging *this;
1828 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1830 silc_log_timestamp(config->logging_timestamp);
1831 silc_log_quick(config->logging_quick);
1832 silc_log_flushdelay(config->logging_flushdelay ?
1833 config->logging_flushdelay :
1834 SILC_SERVER_LOG_FLUSH_DELAY);
1836 if ((this = config->logging_fatals))
1837 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1839 if ((this = config->logging_errors))
1840 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1842 if ((this = config->logging_warnings))
1843 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1845 if ((this = config->logging_info))
1846 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1850 /* Returns client authentication information from configuration file by host
1853 SilcServerConfigClient *
1854 silc_server_config_find_client(SilcServer server, char *host)
1856 SilcServerConfig config = server->config;
1857 SilcServerConfigClient *client;
1859 if (!config || !host)
1862 for (client = config->clients; client; client = client->next) {
1863 if (client->host && !silc_string_compare(client->host, host))
1868 /* if none matched, then client is already NULL */
1872 /* Returns admin connection configuration by host, username and/or
1875 SilcServerConfigAdmin *
1876 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1879 SilcServerConfig config = server->config;
1880 SilcServerConfigAdmin *admin;
1882 /* make sure we have a value for the matching parameters */
1890 for (admin = config->admins; admin; admin = admin->next) {
1891 if (admin->host && !silc_string_compare(admin->host, host))
1893 if (admin->user && !silc_string_compare(admin->user, user))
1895 if (admin->nick && !silc_string_compare(admin->nick, nick))
1897 /* no checks failed -> this entry matches */
1901 /* if none matched, then admin is already NULL */
1905 /* Returns the denied connection configuration entry by host. */
1907 SilcServerConfigDeny *
1908 silc_server_config_find_denied(SilcServer server, char *host)
1910 SilcServerConfig config = server->config;
1911 SilcServerConfigDeny *deny;
1913 /* make sure we have a value for the matching parameters */
1914 if (!config || !host)
1917 for (deny = config->denied; deny; deny = deny->next) {
1918 if (deny->host && !silc_string_compare(deny->host, host))
1923 /* if none matched, then deny is already NULL */
1927 /* Returns server connection info from server configuartion by host
1930 SilcServerConfigServer *
1931 silc_server_config_find_server_conn(SilcServer server, char *host)
1933 SilcServerConfig config = server->config;
1934 SilcServerConfigServer *serv = NULL;
1939 if (!config->servers)
1942 for (serv = config->servers; serv; serv = serv->next) {
1943 if (!silc_string_compare(serv->host, host))
1951 /* Returns router connection info from server configuration by
1952 host (name or ip). */
1954 SilcServerConfigRouter *
1955 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1957 SilcServerConfig config = server->config;
1958 SilcServerConfigRouter *serv = NULL;
1963 if (!config->routers)
1966 for (serv = config->routers; serv; serv = serv->next) {
1967 if (!silc_string_compare(serv->host, host))
1969 if (port && serv->port && serv->port != port)
1977 /* Find backup router connection by host (name or ip) */
1979 SilcServerConfigRouter *
1980 silc_server_config_find_backup_conn(SilcServer server, char *host)
1982 SilcServerConfig config = server->config;
1983 SilcServerConfigRouter *serv = NULL;
1988 if (!config->routers)
1991 for (serv = config->routers; serv; serv = serv->next) {
1992 if (!serv->backup_router)
1994 if (!silc_string_compare(serv->host, host))
2002 /* Returns TRUE if configuration for a router connection that we are
2003 initiating exists. */
2005 SilcBool silc_server_config_is_primary_route(SilcServer server)
2007 SilcServerConfig config = server->config;
2008 SilcServerConfigRouter *serv = NULL;
2010 SilcBool found = FALSE;
2012 serv = config->routers;
2013 for (i = 0; serv; i++) {
2014 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
2025 /* Returns our primary connection configuration or NULL if we do not
2026 have primary router configured. */
2028 SilcServerConfigRouter *
2029 silc_server_config_get_primary_router(SilcServer server)
2031 SilcServerConfig config = server->config;
2032 SilcServerConfigRouter *serv = NULL;
2035 serv = config->routers;
2036 for (i = 0; serv; i++) {
2037 if (serv->initiator == TRUE && serv->backup_router == FALSE)
2045 /* If we have backup router configured that is going to replace us this
2046 function returns it. */
2048 SilcServerConfigRouter *
2049 silc_server_config_get_backup_router(SilcServer server)
2051 SilcServerConfig config = server->config;
2052 SilcServerConfigRouter *serv = NULL;
2055 if (server->server_type != SILC_ROUTER)
2058 serv = config->routers;
2059 for (i = 0; serv; i++) {
2060 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
2061 serv->backup_local == TRUE &&
2062 !strcmp(server->config->server_info->primary->server_ip,
2063 serv->backup_replace_ip) &&
2064 server->config->server_info->primary->port ==
2065 serv->backup_replace_port)