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 int 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 if (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_AUTH |
871 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
872 got_errno = SILC_CONFIG_EPRINTLINE;
875 tmp->publickeys = TRUE;
877 else if (!strcmp(name, "publickeydir")) {
878 if (my_parse_publickeydir((char *) val,
879 (void *)&config->server->repository,
880 SILC_SKR_USAGE_AUTH |
881 SILC_SKR_USAGE_KEY_AGREEMENT) < 0) {
882 got_errno = SILC_CONFIG_EPRINTLINE;
885 tmp->publickeys = TRUE;
887 else if (!strcmp(name, "params")) {
888 CONFIG_IS_DOUBLE(tmp->param);
889 tmp->param = my_find_param(config, (char *) val);
890 if (!tmp->param) { /* error message already output */
891 got_errno = SILC_CONFIG_EPRINTLINE;
896 return SILC_CONFIG_EINTERNAL;
897 return SILC_CONFIG_OK;
900 silc_free(tmp->host);
901 CONFIG_FREE_AUTH(tmp);
907 SILC_CONFIG_CALLBACK(fetch_admin)
909 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
911 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
912 type, name, context));
913 if (type == SILC_CONFIG_ARG_BLOCK) {
914 /* check the temporary struct's fields */
915 if (!tmp) /* discard empty sub-blocks */
916 return SILC_CONFIG_OK;
918 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
920 return SILC_CONFIG_OK;
922 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
924 /* Identify and save this value */
925 if (!strcmp(name, "host")) {
926 CONFIG_IS_DOUBLE(tmp->host);
927 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
929 else if (!strcmp(name, "user")) {
930 CONFIG_IS_DOUBLE(tmp->user);
931 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
933 else if (!strcmp(name, "nick")) {
934 CONFIG_IS_DOUBLE(tmp->nick);
935 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
937 else if (!strcmp(name, "passphrase")) {
938 CONFIG_IS_DOUBLE(tmp->passphrase);
939 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
940 (void *)&tmp->passphrase,
941 &tmp->passphrase_len, 0, NULL)) {
942 got_errno = SILC_CONFIG_EPRINTLINE;
946 else if (!strcmp(name, "publickey")) {
947 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
948 (void *)&config->server->repository, NULL,
949 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, tmp)) {
950 got_errno = SILC_CONFIG_EPRINTLINE;
953 tmp->publickeys = TRUE;
956 return SILC_CONFIG_EINTERNAL;
957 return SILC_CONFIG_OK;
960 silc_free(tmp->host);
961 silc_free(tmp->user);
962 silc_free(tmp->nick);
963 CONFIG_FREE_AUTH(tmp);
969 SILC_CONFIG_CALLBACK(fetch_deny)
971 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
973 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
974 type, name, context));
975 if (type == SILC_CONFIG_ARG_BLOCK) {
976 /* check the temporary struct's fields */
977 if (!tmp) /* discard empty sub-blocks */
978 return SILC_CONFIG_OK;
980 got_errno = SILC_CONFIG_EMISSFIELDS;
984 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
986 return SILC_CONFIG_OK;
988 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
990 /* Identify and save this value */
991 if (!strcmp(name, "host")) {
992 CONFIG_IS_DOUBLE(tmp->host);
993 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
995 else if (!strcmp(name, "reason")) {
996 CONFIG_IS_DOUBLE(tmp->reason);
997 tmp->reason = strdup((char *) val);
1000 return SILC_CONFIG_EINTERNAL;
1001 return SILC_CONFIG_OK;
1004 silc_free(tmp->host);
1005 silc_free(tmp->reason);
1011 SILC_CONFIG_CALLBACK(fetch_server)
1013 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
1015 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
1016 type, name, context));
1017 if (type == SILC_CONFIG_ARG_BLOCK) {
1018 /* check the temporary struct's fields */
1019 if (!tmp) /* discard empty sub-blocks */
1020 return SILC_CONFIG_OK;
1022 got_errno = SILC_CONFIG_EMISSFIELDS;
1026 /* the temporary struct is ok, append it to the list */
1027 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
1029 return SILC_CONFIG_OK;
1031 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
1033 /* Identify and save this value */
1034 if (!strcmp(name, "host")) {
1035 CONFIG_IS_DOUBLE(tmp->host);
1036 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
1038 else if (!strcmp(name, "passphrase")) {
1039 CONFIG_IS_DOUBLE(tmp->passphrase);
1040 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1041 (void *)&tmp->passphrase,
1042 &tmp->passphrase_len, 0, NULL)) {
1043 got_errno = SILC_CONFIG_EPRINTLINE;
1047 else if (!strcmp(name, "publickey")) {
1048 CONFIG_IS_DOUBLE(tmp->publickeys);
1049 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1050 (void *)&config->server->repository, NULL,
1051 SILC_SKR_USAGE_AUTH |
1052 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1053 got_errno = SILC_CONFIG_EPRINTLINE;
1056 tmp->publickeys = TRUE;
1058 else if (!strcmp(name, "params")) {
1059 CONFIG_IS_DOUBLE(tmp->param);
1060 tmp->param = my_find_param(config, (char *) val);
1061 if (!tmp->param) { /* error message already output */
1062 got_errno = SILC_CONFIG_EPRINTLINE;
1066 else if (!strcmp(name, "backup")) {
1067 tmp->backup_router = *(SilcBool *)val;
1070 return SILC_CONFIG_EINTERNAL;
1072 return SILC_CONFIG_OK;
1075 silc_free(tmp->host);
1076 CONFIG_FREE_AUTH(tmp);
1082 SILC_CONFIG_CALLBACK(fetch_router)
1084 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1086 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1087 type, name, context));
1088 if (type == SILC_CONFIG_ARG_BLOCK) {
1089 if (!tmp) /* discard empty sub-blocks */
1090 return SILC_CONFIG_OK;
1092 got_errno = SILC_CONFIG_EMISSFIELDS;
1096 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
1098 return SILC_CONFIG_OK;
1100 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
1102 /* Identify and save this value */
1103 if (!strcmp(name, "host")) {
1104 CONFIG_IS_DOUBLE(tmp->host);
1105 tmp->host = strdup((char *) val);
1107 else if (!strcmp(name, "port")) {
1108 int port = *(int *)val;
1109 if ((port <= 0) || (port > 65535)) {
1110 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1111 "Invalid port number!"));
1112 got_errno = SILC_CONFIG_EPRINTLINE;
1115 tmp->port = (SilcUInt16) port;
1117 else if (!strcmp(name, "passphrase")) {
1118 CONFIG_IS_DOUBLE(tmp->passphrase);
1119 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1120 (void *)&tmp->passphrase,
1121 &tmp->passphrase_len, 0, NULL)) {
1122 got_errno = SILC_CONFIG_EPRINTLINE;
1126 else if (!strcmp(name, "publickey")) {
1127 CONFIG_IS_DOUBLE(tmp->publickeys);
1128 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1129 (void *)&config->server->repository, NULL,
1130 SILC_SKR_USAGE_AUTH |
1131 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1132 got_errno = SILC_CONFIG_EPRINTLINE;
1135 tmp->publickeys = TRUE;
1137 else if (!strcmp(name, "params")) {
1138 CONFIG_IS_DOUBLE(tmp->param);
1139 tmp->param = my_find_param(config, (char *) val);
1140 if (!tmp->param) { /* error message already output */
1141 got_errno = SILC_CONFIG_EPRINTLINE;
1145 else if (!strcmp(name, "initiator")) {
1146 tmp->initiator = *(SilcBool *)val;
1148 else if (!strcmp(name, "backuphost")) {
1149 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
1150 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1152 tmp->backup_router = TRUE;
1154 else if (!strcmp(name, "backupport")) {
1155 int port = *(int *)val;
1156 if ((port <= 0) || (port > 65535)) {
1157 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1158 "Invalid port number!"));
1159 got_errno = SILC_CONFIG_EPRINTLINE;
1162 tmp->backup_replace_port = (SilcUInt16) port;
1164 else if (!strcmp(name, "backuplocal")) {
1165 tmp->backup_local = *(SilcBool *)val;
1167 else if (!strcmp(name, "dynamic_connection")) {
1168 tmp->dynamic_connection = *(SilcBool *)val;
1171 return SILC_CONFIG_EINTERNAL;
1173 return SILC_CONFIG_OK;
1176 silc_free(tmp->host);
1177 silc_free(tmp->backup_replace_ip);
1178 CONFIG_FREE_AUTH(tmp);
1184 /* known config options tables */
1185 static const SilcConfigTable table_general[] = {
1186 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1187 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1188 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1189 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1190 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1191 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1192 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1193 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1194 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1195 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1196 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1197 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1198 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1199 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1200 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1201 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1202 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1203 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1204 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1205 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1206 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1207 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1208 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1209 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1210 { "channel_join_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1211 { "debug_string", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1212 { "http_server", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1213 { "http_server_ip", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1214 { "http_server_port", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1215 { "dynamic_server", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1216 { "local_channels", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1220 static const SilcConfigTable table_cipher[] = {
1221 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1222 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1223 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1227 static const SilcConfigTable table_hash[] = {
1228 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1229 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1230 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1234 static const SilcConfigTable table_hmac[] = {
1235 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1236 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1237 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1241 static const SilcConfigTable table_pkcs[] = {
1242 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1246 static const SilcConfigTable table_serverinfo_c[] = {
1247 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1248 { "public_ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1249 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1253 static const SilcConfigTable table_serverinfo[] = {
1254 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1255 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1256 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1257 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1258 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1259 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1260 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1261 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1262 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1263 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1264 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1265 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1266 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1270 static const SilcConfigTable table_logging_c[] = {
1271 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1272 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1273 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1277 static const SilcConfigTable table_logging[] = {
1278 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1279 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1280 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1281 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1282 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1283 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1284 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1288 static const SilcConfigTable table_connparam[] = {
1289 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1290 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1291 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1292 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1293 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1294 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1295 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1296 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1297 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1298 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1299 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1300 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1301 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1302 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1303 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1304 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1305 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1306 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1307 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1308 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1312 static const SilcConfigTable table_client[] = {
1313 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1314 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1315 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1316 { "publickeydir", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1317 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1321 static const SilcConfigTable table_admin[] = {
1322 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1323 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1324 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1325 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1326 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1327 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1328 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1332 static const SilcConfigTable table_deny[] = {
1333 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1334 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1338 static const SilcConfigTable table_serverconn[] = {
1339 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1340 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1341 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1342 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1343 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1347 static const SilcConfigTable table_routerconn[] = {
1348 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1349 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1350 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1351 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1352 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1353 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1354 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1355 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1356 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1357 { "dynamic_connection", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1361 static const SilcConfigTable table_main[] = {
1362 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1363 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1364 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1365 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1366 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1367 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1368 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1369 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1370 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1371 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1372 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1373 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1374 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1378 /* Set default values to stuff that was not configured. */
1380 static void silc_server_config_set_defaults(SilcServerConfig config)
1382 my_set_param_defaults(&config->param, NULL);
1384 config->channel_rekey_secs = (config->channel_rekey_secs ?
1385 config->channel_rekey_secs :
1386 SILC_SERVER_CHANNEL_REKEY);
1387 config->key_exchange_timeout = (config->key_exchange_timeout ?
1388 config->key_exchange_timeout :
1389 SILC_SERVER_SKE_TIMEOUT);
1390 config->conn_auth_timeout = (config->conn_auth_timeout ?
1391 config->conn_auth_timeout :
1392 SILC_SERVER_CONNAUTH_TIMEOUT);
1395 /* Check for correctness of the configuration */
1397 static SilcBool silc_server_config_check(SilcServerConfig config)
1399 SilcBool ret = TRUE;
1400 SilcServerConfigServer *s;
1401 SilcServerConfigRouter *r;
1404 /* ServerConfig is mandatory */
1405 if (!config->server_info) {
1406 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `ServerInfo'"));
1410 if (!config->server_info->public_key ||
1411 !config->server_info->private_key) {
1412 SILC_SERVER_LOG_ERROR(("\nError: Server keypair is missing"));
1416 if (!config->server_info->primary) {
1417 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `Primary' "
1418 "in `ServerInfo'"));
1422 if (!config->server_info->primary->server_ip) {
1423 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory field `Ip' "
1424 "in `Primary' in `ServerInfo'"));
1428 /* RouterConnection sanity checks */
1430 if (config->routers && config->routers->backup_router == TRUE &&
1432 SILC_SERVER_LOG_ERROR((
1433 "\nError: First RouterConnection block must be primary router "
1434 "connection. You have marked it incorrectly as backup router."));
1437 if (config->routers && config->routers->backup_router == TRUE &&
1438 !config->servers && !config->routers->next) {
1439 SILC_SERVER_LOG_ERROR((
1440 "\nError: You have configured backup router but not primary router. "
1441 "If backup router is configured also primary router must be "
1446 /* Backup router sanity checks */
1448 for (r = config->routers; r; r = r->next) {
1449 if (r->backup_router && !strcmp(r->host, r->backup_replace_ip)) {
1450 SILC_SERVER_LOG_ERROR((
1451 "\nError: Backup router connection incorrectly configured to use "
1452 "primary and backup router as same host `%s'. They must not be "
1453 "same host.", r->host));
1457 if (r->initiator == FALSE && r->port != 0) {
1458 SILC_SERVER_LOG_WARNING(("\nWarning: Initiator is FALSE and Port is "
1459 "specified. Ignoring Port value."));
1464 /* ServerConnection sanity checks */
1466 for (s = config->servers; s; s = s->next) {
1467 if (s->backup_router) {
1473 for (s = config->servers; s; s = s->next) {
1474 if (!s->backup_router) {
1475 SILC_SERVER_LOG_ERROR((
1476 "\nError: Your server is backup router but not all ServerConnection "
1477 "blocks were marked as backup connections. They all must be "
1478 "marked as backup connections."));
1488 /* Allocates a new configuration object, opens configuration file and
1489 parses it. The parsed data is returned to the newly allocated
1490 configuration object. The SilcServerConfig must be freed by calling
1491 the silc_server_config_destroy function. */
1493 SilcServerConfig silc_server_config_alloc(const char *filename,
1496 SilcServerConfig config_new;
1497 SilcConfigEntity ent;
1498 SilcConfigFile *file;
1500 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1502 /* alloc a config object */
1503 config_new = silc_calloc(1, sizeof(*config_new));
1507 /* general config defaults */
1508 config_new->refcount = 1;
1509 config_new->logging_timestamp = TRUE;
1510 config_new->param.reconnect_keep_trying = TRUE;
1511 config_new->server = server;
1513 /* obtain a config file object */
1514 file = silc_config_open(filename);
1516 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1521 /* obtain a SilcConfig entity, we can use it to start the parsing */
1522 ent = silc_config_init(file);
1524 /* load the known configuration options, give our empty object as context */
1525 silc_config_register_table(ent, table_main, (void *) config_new);
1527 /* enter the main parsing loop. When this returns, we have the parsing
1528 * result and the object filled (or partially, in case of errors). */
1529 ret = silc_config_main(ent);
1530 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1531 silc_config_strerror(ret)));
1533 /* Check if the parser returned errors */
1535 /* handle this special error return which asks to quietly return */
1536 if (ret != SILC_CONFIG_ESILENT) {
1537 char *linebuf, *filename = silc_config_get_filename(file);
1538 SilcUInt32 line = silc_config_get_line(file);
1539 if (ret != SILC_CONFIG_EPRINTLINE)
1540 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1541 silc_config_strerror(ret)));
1542 linebuf = silc_config_read_line(file, line);
1544 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1549 silc_server_config_destroy(config_new);
1550 silc_config_close(file);
1554 /* close (destroy) the file object */
1555 silc_config_close(file);
1557 /* Check the configuration */
1558 if (!silc_server_config_check(config_new)) {
1559 silc_server_config_destroy(config_new);
1563 /* Set default to configuration parameters */
1564 silc_server_config_set_defaults(config_new);
1569 /* Increments the reference counter of a config object */
1571 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1576 ref->config = config;
1577 ref->ref_ptr = ref_ptr;
1578 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1579 config->refcount - 1, config->refcount));
1583 /* Decrements the reference counter of a config object. If the counter
1584 reaches 0, the config object is destroyed. */
1586 void silc_server_config_unref(SilcServerConfigRef *ref)
1589 silc_server_config_destroy(ref->config);
1592 /* Destroy a config object with all his children lists */
1594 void silc_server_config_destroy(SilcServerConfig config)
1599 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1600 config->refcount + 1, config->refcount));
1601 if (config->refcount > 0)
1604 SILC_LOG_DEBUG(("Freeing config context"));
1606 /* Destroy general config stuff */
1607 silc_free(config->debug_string);
1608 silc_free(config->param.version_protocol);
1609 silc_free(config->param.version_software);
1610 silc_free(config->param.version_software_vendor);
1611 silc_free(config->httpd_ip);
1613 /* Destroy Logging channels */
1614 if (config->logging_info)
1615 silc_free(config->logging_info->file);
1616 if (config->logging_warnings)
1617 silc_free(config->logging_warnings->file);
1618 if (config->logging_errors)
1619 silc_free(config->logging_errors->file);
1620 if (config->logging_fatals)
1621 silc_free(config->logging_fatals->file);
1622 silc_free(config->logging_info);
1623 silc_free(config->logging_warnings);
1624 silc_free(config->logging_errors);
1625 silc_free(config->logging_fatals);
1627 /* Destroy the ServerInfo struct */
1628 if (config->server_info) {
1629 register SilcServerConfigServerInfo *si = config->server_info;
1630 silc_free(si->server_name);
1632 silc_free(si->primary->server_ip);
1633 silc_free(si->primary);
1635 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1637 silc_free(di->server_ip);
1640 silc_free(si->server_type);
1641 silc_free(si->location);
1642 silc_free(si->admin);
1643 silc_free(si->email);
1644 silc_free(si->user);
1645 silc_free(si->group);
1646 silc_free(si->motd_file);
1647 silc_free(si->pid_file);
1649 silc_pkcs_public_key_free(si->public_key);
1650 if (si->private_key)
1651 silc_pkcs_private_key_free(si->private_key);
1655 /* Now let's destroy the lists */
1657 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1659 silc_free(di->name);
1662 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1663 silc_free(di->name);
1666 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1667 silc_free(di->name);
1668 silc_free(di->hash);
1671 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1672 silc_free(di->name);
1675 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1676 config->conn_params)
1677 silc_free(di->name);
1678 silc_free(di->version_protocol);
1679 silc_free(di->version_software);
1680 silc_free(di->version_software_vendor);
1683 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1684 silc_free(di->host);
1685 CONFIG_FREE_AUTH(di);
1688 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1689 silc_free(di->host);
1690 silc_free(di->user);
1691 silc_free(di->nick);
1692 CONFIG_FREE_AUTH(di);
1695 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1696 silc_free(di->host);
1697 silc_free(di->reason);
1700 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1702 silc_free(di->host);
1703 CONFIG_FREE_AUTH(di);
1706 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1708 silc_free(di->host);
1709 silc_free(di->backup_replace_ip);
1710 CONFIG_FREE_AUTH(di);
1714 memset(config, 'F', sizeof(*config));
1718 /* Registers configured ciphers. These can then be allocated by the
1719 server when needed. */
1721 SilcBool silc_server_config_register_ciphers(SilcServer server)
1723 SilcServerConfig config = server->config;
1724 SilcServerConfigCipher *cipher = config->cipher;
1725 char *module_path = config->module_path;
1727 SILC_LOG_DEBUG(("Registering configured ciphers"));
1729 if (!cipher) /* any cipher in the config file? */
1733 /* if there isn't a module_path OR there isn't a module sim name try to
1734 * use buil-in functions */
1735 if (!module_path || !cipher->module) {
1737 for (i = 0; silc_default_ciphers[i].name; i++)
1738 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1739 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1742 if (!silc_cipher_is_supported(cipher->name)) {
1743 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1744 silc_server_stop(server);
1748 cipher = cipher->next;
1754 /* Registers configured hash functions. These can then be allocated by the
1755 server when needed. */
1757 SilcBool silc_server_config_register_hashfuncs(SilcServer server)
1759 SilcServerConfig config = server->config;
1760 SilcServerConfigHash *hash = config->hash;
1761 char *module_path = config->module_path;
1763 SILC_LOG_DEBUG(("Registering configured hash functions"));
1765 if (!hash) /* any hash func in the config file? */
1769 /* if there isn't a module_path OR there isn't a module sim name try to
1770 * use buil-in functions */
1771 if (!module_path || !hash->module) {
1773 for (i = 0; silc_default_hash[i].name; i++)
1774 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1775 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1778 if (!silc_hash_is_supported(hash->name)) {
1779 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1780 silc_server_stop(server);
1790 /* Registers configure HMACs. These can then be allocated by the server
1793 SilcBool silc_server_config_register_hmacs(SilcServer server)
1795 SilcServerConfig config = server->config;
1796 SilcServerConfigHmac *hmac = config->hmac;
1798 SILC_LOG_DEBUG(("Registering configured HMACs"));
1804 SilcHmacObject hmac_obj;
1805 if (!silc_hash_is_supported(hmac->hash)) {
1806 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1807 silc_server_stop(server);
1811 /* Register the HMAC */
1812 memset(&hmac_obj, 0, sizeof(hmac_obj));
1813 hmac_obj.name = hmac->name;
1814 hmac_obj.len = hmac->mac_length;
1815 silc_hmac_register(&hmac_obj);
1823 /* Registers configured PKCS's. */
1825 SilcBool silc_server_config_register_pkcs(SilcServer server)
1830 /* Sets log files where log messages are saved by the server logger. */
1832 void silc_server_config_setlogfiles(SilcServer server)
1834 SilcServerConfig config = server->config;
1835 SilcServerConfigLogging *this;
1837 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1839 silc_log_timestamp(config->logging_timestamp);
1840 silc_log_quick(config->logging_quick);
1841 silc_log_flushdelay(config->logging_flushdelay ?
1842 config->logging_flushdelay :
1843 SILC_SERVER_LOG_FLUSH_DELAY);
1845 if ((this = config->logging_fatals))
1846 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1848 if ((this = config->logging_errors))
1849 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1851 if ((this = config->logging_warnings))
1852 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1854 if ((this = config->logging_info))
1855 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1859 /* Returns client authentication information from configuration file by host
1862 SilcServerConfigClient *
1863 silc_server_config_find_client(SilcServer server, char *host)
1865 SilcServerConfig config = server->config;
1866 SilcServerConfigClient *client;
1868 if (!config || !host)
1871 for (client = config->clients; client; client = client->next) {
1872 if (client->host && !silc_string_compare(client->host, host))
1877 /* if none matched, then client is already NULL */
1881 /* Returns admin connection configuration by host, username and/or
1884 SilcServerConfigAdmin *
1885 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1888 SilcServerConfig config = server->config;
1889 SilcServerConfigAdmin *admin;
1891 /* make sure we have a value for the matching parameters */
1899 for (admin = config->admins; admin; admin = admin->next) {
1900 if (admin->host && !silc_string_compare(admin->host, host))
1902 if (admin->user && !silc_string_compare(admin->user, user))
1904 if (admin->nick && !silc_string_compare(admin->nick, nick))
1906 /* no checks failed -> this entry matches */
1910 /* if none matched, then admin is already NULL */
1914 /* Returns the denied connection configuration entry by host. */
1916 SilcServerConfigDeny *
1917 silc_server_config_find_denied(SilcServer server, char *host)
1919 SilcServerConfig config = server->config;
1920 SilcServerConfigDeny *deny;
1922 /* make sure we have a value for the matching parameters */
1923 if (!config || !host)
1926 for (deny = config->denied; deny; deny = deny->next) {
1927 if (deny->host && !silc_string_compare(deny->host, host))
1932 /* if none matched, then deny is already NULL */
1936 /* Returns server connection info from server configuartion by host
1939 SilcServerConfigServer *
1940 silc_server_config_find_server_conn(SilcServer server, char *host)
1942 SilcServerConfig config = server->config;
1943 SilcServerConfigServer *serv = NULL;
1948 if (!config->servers)
1951 for (serv = config->servers; serv; serv = serv->next) {
1952 if (!silc_string_compare(serv->host, host))
1960 /* Returns router connection info from server configuration by
1961 host (name or ip). */
1963 SilcServerConfigRouter *
1964 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1966 SilcServerConfig config = server->config;
1967 SilcServerConfigRouter *serv = NULL;
1972 if (!config->routers)
1975 for (serv = config->routers; serv; serv = serv->next) {
1976 if (!silc_string_compare(serv->host, host))
1978 if (port && serv->port && serv->port != port)
1986 /* Find backup router connection by host (name or ip) */
1988 SilcServerConfigRouter *
1989 silc_server_config_find_backup_conn(SilcServer server, char *host)
1991 SilcServerConfig config = server->config;
1992 SilcServerConfigRouter *serv = NULL;
1997 if (!config->routers)
2000 for (serv = config->routers; serv; serv = serv->next) {
2001 if (!serv->backup_router)
2003 if (!silc_string_compare(serv->host, host))
2011 /* Returns TRUE if configuration for a router connection that we are
2012 initiating exists. */
2014 SilcBool silc_server_config_is_primary_route(SilcServer server)
2016 SilcServerConfig config = server->config;
2017 SilcServerConfigRouter *serv = NULL;
2019 SilcBool found = FALSE;
2021 serv = config->routers;
2022 for (i = 0; serv; i++) {
2023 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
2034 /* Returns our primary connection configuration or NULL if we do not
2035 have primary router configured. */
2037 SilcServerConfigRouter *
2038 silc_server_config_get_primary_router(SilcServer server)
2040 SilcServerConfig config = server->config;
2041 SilcServerConfigRouter *serv = NULL;
2044 serv = config->routers;
2045 for (i = 0; serv; i++) {
2046 if (serv->initiator == TRUE && serv->backup_router == FALSE)
2054 /* If we have backup router configured that is going to replace us this
2055 function returns it. */
2057 SilcServerConfigRouter *
2058 silc_server_config_get_backup_router(SilcServer server)
2060 SilcServerConfig config = server->config;
2061 SilcServerConfigRouter *serv = NULL;
2064 if (server->server_type != SILC_ROUTER)
2067 serv = config->routers;
2068 for (i = 0; serv; i++) {
2069 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
2070 serv->backup_local == TRUE &&
2071 !strcmp(server->config->server_info->primary->server_ip,
2072 serv->backup_replace_ip) &&
2073 server->config->server_info->primary->port ==
2074 serv->backup_replace_port)