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;
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);
164 silc_skr_find_set_context(find, key_context ? key_context : (void *)usage);
165 silc_skr_find(skr, NULL, find, my_find_callback, &status);
166 if (status == SILC_SKR_ALREADY_EXIST) {
167 silc_pkcs_public_key_free(public_key);
168 SILC_SERVER_LOG_WARNING(("Warning: public key file \"%s\" already "
169 "configured, ignoring this key", p));
170 return TRUE; /* non fatal error */
173 /* Add the public key to repository */
174 if (silc_skr_add_public_key(skr, public_key, usage,
175 key_context ? key_context : (void *)usage,
176 NULL) != SILC_SKR_OK) {
177 SILC_SERVER_LOG_ERROR(("Error while adding public key \"%s\"", p));
185 static SilcBool my_parse_publickeydir(const char *dirname, void **auth_data,
186 SilcSKRKeyUsage usage)
189 struct dirent *get_file;
192 if (!(dp = opendir(dirname))) {
193 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
194 "Could not open directory \"%s\"", dirname));
198 /* errors are not considered fatal */
199 while ((get_file = readdir(dp))) {
200 const char *filename = get_file->d_name;
202 int dirname_len = strlen(dirname), filename_len = strlen(filename);
203 struct stat check_file;
205 /* Ignore "." and "..", and take files only with ".pub" suffix. */
206 if (!strcmp(filename, ".") || !strcmp(filename, "..") ||
207 (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub"))
210 memset(buf, 0, sizeof(buf));
211 snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname,
212 (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
214 if (stat(buf, &check_file) < 0) {
215 SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
217 } else if (S_ISREG(check_file.st_mode)) {
218 my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL,
224 SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
230 SILC_CONFIG_CALLBACK(fetch_generic)
232 SilcServerConfig config = (SilcServerConfig) context;
235 if (!strcmp(name, "module_path")) {
236 CONFIG_IS_DOUBLE(config->module_path);
237 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
239 else if (!strcmp(name, "prefer_passphrase_auth")) {
240 config->prefer_passphrase_auth = *(SilcBool *)val;
242 else if (!strcmp(name, "require_reverse_lookup")) {
243 config->require_reverse_lookup = *(SilcBool *)val;
245 else if (!strcmp(name, "connections_max")) {
246 config->param.connections_max = (SilcUInt32) *(int *)val;
248 else if (!strcmp(name, "connections_max_per_host")) {
249 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
251 else if (!strcmp(name, "keepalive_secs")) {
252 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
254 else if (!strcmp(name, "reconnect_count")) {
255 config->param.reconnect_count = (SilcUInt32) *(int *)val;
257 else if (!strcmp(name, "reconnect_interval")) {
258 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
260 else if (!strcmp(name, "reconnect_interval_max")) {
261 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
263 else if (!strcmp(name, "reconnect_keep_trying")) {
264 config->param.reconnect_keep_trying = *(SilcBool *)val;
266 else if (!strcmp(name, "key_exchange_rekey")) {
267 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
269 else if (!strcmp(name, "key_exchange_pfs")) {
270 config->param.key_exchange_pfs = *(SilcBool *)val;
272 else if (!strcmp(name, "channel_rekey_secs")) {
273 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
275 else if (!strcmp(name, "key_exchange_timeout")) {
276 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
278 else if (!strcmp(name, "conn_auth_timeout")) {
279 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
281 else if (!strcmp(name, "version_protocol")) {
282 CONFIG_IS_DOUBLE(config->param.version_protocol);
283 config->param.version_protocol =
284 (*(char *)val ? strdup((char *) val) : NULL);
286 else if (!strcmp(name, "version_software")) {
287 CONFIG_IS_DOUBLE(config->param.version_software);
288 config->param.version_software =
289 (*(char *)val ? strdup((char *) val) : NULL);
291 else if (!strcmp(name, "version_software_vendor")) {
292 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
293 config->param.version_software_vendor =
294 (*(char *)val ? strdup((char *) val) : NULL);
296 else if (!strcmp(name, "detach_disabled")) {
297 config->detach_disabled = *(SilcBool *)val;
299 else if (!strcmp(name, "detach_timeout")) {
300 config->detach_timeout = (SilcUInt32) *(int *)val;
302 else if (!strcmp(name, "qos")) {
303 config->param.qos = *(SilcBool *)val;
305 else if (!strcmp(name, "qos_rate_limit")) {
306 config->param.qos_rate_limit = *(SilcUInt32 *)val;
308 else if (!strcmp(name, "qos_bytes_limit")) {
309 config->param.qos_bytes_limit = *(SilcUInt32 *)val;
311 else if (!strcmp(name, "qos_limit_sec")) {
312 config->param.qos_limit_sec = *(SilcUInt32 *)val;
314 else if (!strcmp(name, "qos_limit_usec")) {
315 config->param.qos_limit_usec = *(SilcUInt32 *)val;
317 else if (!strcmp(name, "channel_join_limit")) {
318 config->param.chlimit = *(SilcUInt32 *)val;
320 else if (!strcmp(name, "debug_string")) {
321 CONFIG_IS_DOUBLE(config->debug_string);
322 config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
324 else if (!strcmp(name, "http_server")) {
325 config->httpd = *(SilcBool *)val;
327 else if (!strcmp(name, "http_server_ip")) {
328 CONFIG_IS_DOUBLE(config->httpd_ip);
329 config->httpd_ip = (*(char *)val ? strdup((char *) val) : NULL);
331 else if (!strcmp(name, "http_server_port")) {
332 int port = *(int *)val;
333 if ((port <= 0) || (port > 65535)) {
334 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
335 "Invalid port number!"));
336 got_errno = SILC_CONFIG_EPRINTLINE;
339 config->httpd_port = (SilcUInt16)port;
342 return SILC_CONFIG_EINTERNAL;
344 return SILC_CONFIG_OK;
350 SILC_CONFIG_CALLBACK(fetch_cipher)
352 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
354 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
355 type, name, context));
356 if (type == SILC_CONFIG_ARG_BLOCK) {
357 /* check the temporary struct's fields */
358 if (!tmp) /* discard empty sub-blocks */
359 return SILC_CONFIG_OK;
361 got_errno = SILC_CONFIG_EMISSFIELDS;
365 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
367 return SILC_CONFIG_OK;
369 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
371 /* Identify and save this value */
372 if (!strcmp(name, "name")) {
373 CONFIG_IS_DOUBLE(tmp->name);
374 tmp->name = strdup((char *) val);
376 else if (!strcmp(name, "module")) {
377 CONFIG_IS_DOUBLE(tmp->module);
378 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
380 else if (!strcmp(name, "keylength")) {
381 tmp->key_length = *(SilcUInt32 *)val;
383 else if (!strcmp(name, "blocklength")) {
384 tmp->block_length = *(SilcUInt32 *)val;
387 return SILC_CONFIG_EINTERNAL;
388 return SILC_CONFIG_OK;
391 silc_free(tmp->name);
392 silc_free(tmp->module);
398 SILC_CONFIG_CALLBACK(fetch_hash)
400 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
402 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
403 type, name, context));
404 if (type == SILC_CONFIG_ARG_BLOCK) {
405 /* check the temporary struct's fields */
406 if (!tmp) /* discard empty sub-blocks */
407 return SILC_CONFIG_OK;
408 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
409 got_errno = SILC_CONFIG_EMISSFIELDS;
413 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
415 return SILC_CONFIG_OK;
417 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
419 /* Identify and save this value */
420 if (!strcmp(name, "name")) {
421 CONFIG_IS_DOUBLE(tmp->name);
422 tmp->name = strdup((char *) val);
424 else if (!strcmp(name, "module")) {
425 CONFIG_IS_DOUBLE(tmp->module);
426 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
428 else if (!strcmp(name, "blocklength")) {
429 tmp->block_length = *(int *)val;
431 else if (!strcmp(name, "digestlength")) {
432 tmp->digest_length = *(int *)val;
435 return SILC_CONFIG_EINTERNAL;
436 return SILC_CONFIG_OK;
439 silc_free(tmp->name);
440 silc_free(tmp->module);
446 SILC_CONFIG_CALLBACK(fetch_hmac)
448 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
450 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
451 type, name, context));
452 if (type == SILC_CONFIG_ARG_BLOCK) {
453 /* check the temporary struct's fields */
454 if (!tmp) /* discard empty sub-blocks */
455 return SILC_CONFIG_OK;
456 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
457 got_errno = SILC_CONFIG_EMISSFIELDS;
461 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
463 return SILC_CONFIG_OK;
465 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
467 /* Identify and save this value */
468 if (!strcmp(name, "name")) {
469 CONFIG_IS_DOUBLE(tmp->name);
470 tmp->name = strdup((char *) val);
472 else if (!strcmp(name, "hash")) {
473 CONFIG_IS_DOUBLE(tmp->hash);
474 tmp->hash = strdup((char *) val);
476 else if (!strcmp(name, "maclength")) {
477 tmp->mac_length = *(int *)val;
480 return SILC_CONFIG_EINTERNAL;
481 return SILC_CONFIG_OK;
484 silc_free(tmp->name);
485 silc_free(tmp->hash);
491 SILC_CONFIG_CALLBACK(fetch_pkcs)
493 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
495 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
496 type, name, context));
497 if (type == SILC_CONFIG_ARG_BLOCK) {
498 /* Check the temporary struct's fields */
499 if (!tmp) /* discard empty sub-blocks */
500 return SILC_CONFIG_OK;
502 got_errno = SILC_CONFIG_EMISSFIELDS;
506 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
508 return SILC_CONFIG_OK;
510 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
512 /* Identify and save this value */
513 if (!strcmp(name, "name")) {
514 CONFIG_IS_DOUBLE(tmp->name);
515 tmp->name = strdup((char *) val);
518 return SILC_CONFIG_EINTERNAL;
519 return SILC_CONFIG_OK;
522 silc_free(tmp->name);
528 SILC_CONFIG_CALLBACK(fetch_serverinfo)
530 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
531 SilcServerConfigServerInfo *server_info = config->server_info;
533 SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
534 type, name, context));
536 /* If there isn't the main struct alloc it */
538 config->server_info = server_info = (SilcServerConfigServerInfo *)
539 silc_calloc(1, sizeof(*server_info));
541 if (type == SILC_CONFIG_ARG_BLOCK) {
542 if (!strcmp(name, "primary")) {
543 if (server_info->primary) {
544 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
545 "Double primary specification."));
546 got_errno = SILC_CONFIG_EPRINTLINE;
549 CONFIG_IS_DOUBLE(server_info->primary);
551 /* now check the temporary struct, don't accept empty block and
552 make sure all fields are there */
553 if (!tmp || !tmp->server_ip || !tmp->port) {
554 got_errno = SILC_CONFIG_EMISSFIELDS;
557 server_info->primary = tmp;
559 return SILC_CONFIG_OK;
560 } else if (!strcmp(name, "secondary")) {
562 return SILC_CONFIG_OK;
563 if (!tmp || !tmp->server_ip || !tmp->port) {
564 got_errno = SILC_CONFIG_EMISSFIELDS;
567 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
569 return SILC_CONFIG_OK;
570 } else if (!server_info->public_key || !server_info->private_key) {
571 got_errno = SILC_CONFIG_EMISSFIELDS;
574 return SILC_CONFIG_OK;
576 if (!strcmp(name, "hostname")) {
577 CONFIG_IS_DOUBLE(server_info->server_name);
578 server_info->server_name = strdup((char *) val);
580 else if (!strcmp(name, "ip")) {
581 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
582 CONFIG_IS_DOUBLE(tmp->server_ip);
583 tmp->server_ip = strdup((char *) val);
585 else if (!strcmp(name, "port")) {
586 int port = *(int *)val;
587 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
588 if ((port <= 0) || (port > 65535)) {
589 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
590 "Invalid port number!"));
591 got_errno = SILC_CONFIG_EPRINTLINE;
594 tmp->port = (SilcUInt16) port;
596 else if (!strcmp(name, "servertype")) {
597 CONFIG_IS_DOUBLE(server_info->server_type);
598 server_info->server_type = strdup((char *) val);
600 else if (!strcmp(name, "admin")) {
601 CONFIG_IS_DOUBLE(server_info->admin);
602 server_info->admin = strdup((char *) val);
604 else if (!strcmp(name, "adminemail")) {
605 CONFIG_IS_DOUBLE(server_info->email);
606 server_info->email = strdup((char *) val);
608 else if (!strcmp(name, "location")) {
609 CONFIG_IS_DOUBLE(server_info->location);
610 server_info->location = strdup((char *) val);
612 else if (!strcmp(name, "user")) {
613 CONFIG_IS_DOUBLE(server_info->user);
614 server_info->user = strdup((char *) val);
616 else if (!strcmp(name, "group")) {
617 CONFIG_IS_DOUBLE(server_info->group);
618 server_info->group = strdup((char *) val);
620 else if (!strcmp(name, "motdfile")) {
621 CONFIG_IS_DOUBLE(server_info->motd_file);
622 server_info->motd_file = strdup((char *) val);
624 else if (!strcmp(name, "pidfile")) {
625 CONFIG_IS_DOUBLE(server_info->pid_file);
626 server_info->pid_file = strdup((char *) val);
628 else if (!strcmp(name, "publickey")) {
629 char *file_tmp = (char *) val;
630 CONFIG_IS_DOUBLE(server_info->public_key);
632 /* Try to load specified file, if fail stop config parsing */
633 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key)) {
634 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
635 return SILC_CONFIG_EPRINTLINE;
638 else if (!strcmp(name, "privatekey")) {
640 char *file_tmp = (char *) val;
641 CONFIG_IS_DOUBLE(server_info->private_key);
643 /* Check the private key file permissions. */
644 if ((stat(file_tmp, &st)) != -1) {
645 if ((st.st_mode & 0777) != 0600) {
646 SILC_SERVER_LOG_ERROR(("Wrong permissions in private key "
647 "file \"%s\". The permissions must be "
649 return SILC_CONFIG_ESILENT;
653 /* Try to load specified file, if fail stop config parsing */
654 if (!silc_pkcs_load_private_key(file_tmp, "", 0,
655 &server_info->private_key)) {
656 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
657 return SILC_CONFIG_EPRINTLINE;
661 return SILC_CONFIG_EINTERNAL;
662 return SILC_CONFIG_OK;
665 /* Here we need to check if tmp exists because this function handles
666 * misc data (multiple fields and single-only fields) */
668 silc_free(tmp->server_ip);
675 SILC_CONFIG_CALLBACK(fetch_logging)
677 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
679 if (!strcmp(name, "timestamp")) {
680 config->logging_timestamp = *(SilcBool *)val;
682 else if (!strcmp(name, "quicklogs")) {
683 config->logging_quick = *(SilcBool *)val;
685 else if (!strcmp(name, "flushdelay")) {
686 int flushdelay = *(int *)val;
687 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
688 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
689 "Invalid flushdelay value, use quicklogs if you "
690 "want real-time logging."));
691 return SILC_CONFIG_EPRINTLINE;
693 config->logging_flushdelay = (long) flushdelay;
696 /* The following istances happens only in Logging's sub-blocks, a match
697 for the sub-block name means that you should store the filename/maxsize
698 temporary struct to the proper logging channel.
699 If we get a match for "file" or "maxsize" this means that we are inside
700 a sub-sub-block and it is safe to alloc a new tmp. */
701 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
702 else if (!strcmp(name, __chan__)) { \
703 if (!tmp) return SILC_CONFIG_OK; \
705 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
707 config->__member__ = tmp; \
708 config->tmp = NULL; \
710 FETCH_LOGGING_CHAN("info", logging_info)
711 FETCH_LOGGING_CHAN("warnings", logging_warnings)
712 FETCH_LOGGING_CHAN("errors", logging_errors)
713 FETCH_LOGGING_CHAN("fatals", logging_fatals)
714 #undef FETCH_LOGGING_CHAN
715 else if (!strcmp(name, "file")) {
716 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
717 CONFIG_IS_DOUBLE(tmp->file);
718 tmp->file = strdup((char *) val);
720 else if (!strcmp(name, "size")) {
722 config->tmp = silc_calloc(1, sizeof(*tmp));
723 tmp = (SilcServerConfigLogging *) config->tmp;
725 tmp->maxsize = *(SilcUInt32 *) val;
728 return SILC_CONFIG_EINTERNAL;
729 return SILC_CONFIG_OK;
732 silc_free(tmp->file);
738 SILC_CONFIG_CALLBACK(fetch_connparam)
740 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
742 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
743 type, name, context));
744 if (type == SILC_CONFIG_ARG_BLOCK) {
745 /* check the temporary struct's fields */
746 if (!tmp) /* discard empty sub-blocks */
747 return SILC_CONFIG_OK;
749 got_errno = SILC_CONFIG_EMISSFIELDS;
753 my_set_param_defaults(tmp, &config->param);
755 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
757 return SILC_CONFIG_OK;
760 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
761 tmp->reconnect_keep_trying = TRUE;
764 if (!strcmp(name, "name")) {
765 CONFIG_IS_DOUBLE(tmp->name);
766 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
768 else if (!strcmp(name, "connections_max")) {
769 tmp->connections_max = *(SilcUInt32 *)val;
771 else if (!strcmp(name, "connections_max_per_host")) {
772 tmp->connections_max_per_host = *(SilcUInt32 *)val;
774 else if (!strcmp(name, "keepalive_secs")) {
775 tmp->keepalive_secs = *(SilcUInt32 *)val;
777 else if (!strcmp(name, "reconnect_count")) {
778 tmp->reconnect_count = *(SilcUInt32 *)val;
780 else if (!strcmp(name, "reconnect_interval")) {
781 tmp->reconnect_interval = *(SilcUInt32 *)val;
783 else if (!strcmp(name, "reconnect_interval_max")) {
784 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
786 else if (!strcmp(name, "reconnect_keep_trying")) {
787 tmp->reconnect_keep_trying = *(SilcBool *)val;
789 else if (!strcmp(name, "key_exchange_rekey")) {
790 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
792 else if (!strcmp(name, "key_exchange_pfs")) {
793 tmp->key_exchange_pfs = *(SilcBool *)val;
795 else if (!strcmp(name, "version_protocol")) {
796 CONFIG_IS_DOUBLE(tmp->version_protocol);
797 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
799 else if (!strcmp(name, "version_software")) {
800 CONFIG_IS_DOUBLE(tmp->version_software);
801 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
803 else if (!strcmp(name, "version_software_vendor")) {
804 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
805 tmp->version_software_vendor =
806 (*(char *)val ? strdup((char *) val) : NULL);
808 else if (!strcmp(name, "anonymous")) {
809 tmp->anonymous = *(SilcBool *)val;
811 else if (!strcmp(name, "qos")) {
812 tmp->qos = *(SilcBool *)val;
814 else if (!strcmp(name, "qos_rate_limit")) {
815 tmp->qos_rate_limit = *(SilcUInt32 *)val;
817 else if (!strcmp(name, "qos_bytes_limit")) {
818 tmp->qos_bytes_limit = *(SilcUInt32 *)val;
820 else if (!strcmp(name, "qos_limit_sec")) {
821 tmp->qos_limit_sec = *(SilcUInt32 *)val;
823 else if (!strcmp(name, "qos_limit_usec")) {
824 tmp->qos_limit_usec = *(SilcUInt32 *)val;
827 return SILC_CONFIG_EINTERNAL;
829 return SILC_CONFIG_OK;
832 silc_free(tmp->name);
838 SILC_CONFIG_CALLBACK(fetch_client)
840 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
842 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
843 type, name, context));
845 /* Alloc before block checking, because empty sub-blocks are welcome here */
846 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
848 if (type == SILC_CONFIG_ARG_BLOCK) {
849 /* empty sub-blocks are welcome */
850 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
852 return SILC_CONFIG_OK;
855 /* Identify and save this value */
856 if (!strcmp(name, "host")) {
857 CONFIG_IS_DOUBLE(tmp->host);
858 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
860 else if (!strcmp(name, "passphrase")) {
861 CONFIG_IS_DOUBLE(tmp->passphrase);
862 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
863 (void *)&tmp->passphrase,
864 &tmp->passphrase_len, 0, NULL)) {
865 got_errno = SILC_CONFIG_EPRINTLINE;
869 else if (!strcmp(name, "publickey")) {
870 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
871 (void *)&config->server->repository, NULL,
872 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
873 got_errno = SILC_CONFIG_EPRINTLINE;
877 else if (!strcmp(name, "publickeydir")) {
878 if (!my_parse_publickeydir((char *) val,
879 (void *)&config->server->repository,
880 SILC_SKR_USAGE_KEY_AGREEMENT)) {
881 got_errno = SILC_CONFIG_EPRINTLINE;
885 else if (!strcmp(name, "params")) {
886 CONFIG_IS_DOUBLE(tmp->param);
887 tmp->param = my_find_param(config, (char *) val);
888 if (!tmp->param) { /* error message already output */
889 got_errno = SILC_CONFIG_EPRINTLINE;
894 return SILC_CONFIG_EINTERNAL;
895 return SILC_CONFIG_OK;
898 silc_free(tmp->host);
899 CONFIG_FREE_AUTH(tmp);
905 SILC_CONFIG_CALLBACK(fetch_admin)
907 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
909 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
910 type, name, context));
911 if (type == SILC_CONFIG_ARG_BLOCK) {
912 /* check the temporary struct's fields */
913 if (!tmp) /* discard empty sub-blocks */
914 return SILC_CONFIG_OK;
916 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
918 return SILC_CONFIG_OK;
920 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
922 /* Identify and save this value */
923 if (!strcmp(name, "host")) {
924 CONFIG_IS_DOUBLE(tmp->host);
925 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
927 else if (!strcmp(name, "user")) {
928 CONFIG_IS_DOUBLE(tmp->user);
929 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
931 else if (!strcmp(name, "nick")) {
932 CONFIG_IS_DOUBLE(tmp->nick);
933 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
935 else if (!strcmp(name, "passphrase")) {
936 CONFIG_IS_DOUBLE(tmp->passphrase);
937 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
938 (void *)&tmp->passphrase,
939 &tmp->passphrase_len, 0, NULL)) {
940 got_errno = SILC_CONFIG_EPRINTLINE;
944 else if (!strcmp(name, "publickey")) {
945 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
946 (void *)&config->server->repository, NULL,
947 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, tmp)) {
948 got_errno = SILC_CONFIG_EPRINTLINE;
953 return SILC_CONFIG_EINTERNAL;
954 return SILC_CONFIG_OK;
957 silc_free(tmp->host);
958 silc_free(tmp->user);
959 silc_free(tmp->nick);
960 CONFIG_FREE_AUTH(tmp);
966 SILC_CONFIG_CALLBACK(fetch_deny)
968 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
970 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
971 type, name, context));
972 if (type == SILC_CONFIG_ARG_BLOCK) {
973 /* check the temporary struct's fields */
974 if (!tmp) /* discard empty sub-blocks */
975 return SILC_CONFIG_OK;
977 got_errno = SILC_CONFIG_EMISSFIELDS;
981 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
983 return SILC_CONFIG_OK;
985 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
987 /* Identify and save this value */
988 if (!strcmp(name, "host")) {
989 CONFIG_IS_DOUBLE(tmp->host);
990 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
992 else if (!strcmp(name, "reason")) {
993 CONFIG_IS_DOUBLE(tmp->reason);
994 tmp->reason = strdup((char *) val);
997 return SILC_CONFIG_EINTERNAL;
998 return SILC_CONFIG_OK;
1001 silc_free(tmp->host);
1002 silc_free(tmp->reason);
1008 SILC_CONFIG_CALLBACK(fetch_server)
1010 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
1012 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
1013 type, name, context));
1014 if (type == SILC_CONFIG_ARG_BLOCK) {
1015 /* check the temporary struct's fields */
1016 if (!tmp) /* discard empty sub-blocks */
1017 return SILC_CONFIG_OK;
1019 got_errno = SILC_CONFIG_EMISSFIELDS;
1023 /* the temporary struct is ok, append it to the list */
1024 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
1026 return SILC_CONFIG_OK;
1028 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
1030 /* Identify and save this value */
1031 if (!strcmp(name, "host")) {
1032 CONFIG_IS_DOUBLE(tmp->host);
1033 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
1035 else if (!strcmp(name, "passphrase")) {
1036 CONFIG_IS_DOUBLE(tmp->passphrase);
1037 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1038 (void *)&tmp->passphrase,
1039 &tmp->passphrase_len, 0, NULL)) {
1040 got_errno = SILC_CONFIG_EPRINTLINE;
1044 else if (!strcmp(name, "publickey")) {
1045 CONFIG_IS_DOUBLE(tmp->publickeys);
1046 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1047 (void *)&config->server->repository, NULL,
1048 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1049 got_errno = SILC_CONFIG_EPRINTLINE;
1053 else if (!strcmp(name, "params")) {
1054 CONFIG_IS_DOUBLE(tmp->param);
1055 tmp->param = my_find_param(config, (char *) val);
1056 if (!tmp->param) { /* error message already output */
1057 got_errno = SILC_CONFIG_EPRINTLINE;
1061 else if (!strcmp(name, "backup")) {
1062 tmp->backup_router = *(SilcBool *)val;
1065 return SILC_CONFIG_EINTERNAL;
1067 return SILC_CONFIG_OK;
1070 silc_free(tmp->host);
1071 CONFIG_FREE_AUTH(tmp);
1077 SILC_CONFIG_CALLBACK(fetch_router)
1079 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1081 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1082 type, name, context));
1083 if (type == SILC_CONFIG_ARG_BLOCK) {
1084 if (!tmp) /* discard empty sub-blocks */
1085 return SILC_CONFIG_OK;
1087 got_errno = SILC_CONFIG_EMISSFIELDS;
1091 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
1093 return SILC_CONFIG_OK;
1095 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
1097 /* Identify and save this value */
1098 if (!strcmp(name, "host")) {
1099 CONFIG_IS_DOUBLE(tmp->host);
1100 tmp->host = strdup((char *) val);
1102 else if (!strcmp(name, "port")) {
1103 int port = *(int *)val;
1104 if ((port <= 0) || (port > 65535)) {
1105 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1106 "Invalid port number!"));
1107 got_errno = SILC_CONFIG_EPRINTLINE;
1110 tmp->port = (SilcUInt16) port;
1112 else if (!strcmp(name, "passphrase")) {
1113 CONFIG_IS_DOUBLE(tmp->passphrase);
1114 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1115 (void *)&tmp->passphrase,
1116 &tmp->passphrase_len, 0, NULL)) {
1117 got_errno = SILC_CONFIG_EPRINTLINE;
1121 else if (!strcmp(name, "publickey")) {
1122 CONFIG_IS_DOUBLE(tmp->publickeys);
1123 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1124 (void *)&config->server->repository, NULL,
1125 SILC_SKR_USAGE_KEY_AGREEMENT, NULL)) {
1126 got_errno = SILC_CONFIG_EPRINTLINE;
1130 else if (!strcmp(name, "params")) {
1131 CONFIG_IS_DOUBLE(tmp->param);
1132 tmp->param = my_find_param(config, (char *) val);
1133 if (!tmp->param) { /* error message already output */
1134 got_errno = SILC_CONFIG_EPRINTLINE;
1138 else if (!strcmp(name, "initiator")) {
1139 tmp->initiator = *(SilcBool *)val;
1141 else if (!strcmp(name, "backuphost")) {
1142 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
1143 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1145 tmp->backup_router = TRUE;
1147 else if (!strcmp(name, "backupport")) {
1148 int port = *(int *)val;
1149 if ((port <= 0) || (port > 65535)) {
1150 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1151 "Invalid port number!"));
1152 got_errno = SILC_CONFIG_EPRINTLINE;
1155 tmp->backup_replace_port = (SilcUInt16) port;
1157 else if (!strcmp(name, "backuplocal")) {
1158 tmp->backup_local = *(SilcBool *)val;
1161 return SILC_CONFIG_EINTERNAL;
1163 return SILC_CONFIG_OK;
1166 silc_free(tmp->host);
1167 silc_free(tmp->backup_replace_ip);
1168 CONFIG_FREE_AUTH(tmp);
1174 /* known config options tables */
1175 static const SilcConfigTable table_general[] = {
1176 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
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 },
1209 static const SilcConfigTable table_cipher[] = {
1210 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1211 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1212 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1213 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1217 static const SilcConfigTable table_hash[] = {
1218 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1219 { "module", SILC_CONFIG_ARG_STRE, 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 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1243 static const SilcConfigTable table_serverinfo[] = {
1244 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1245 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1246 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1247 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1248 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1249 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1250 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1251 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1252 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1253 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1254 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1255 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1256 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1260 static const SilcConfigTable table_logging_c[] = {
1261 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1262 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1263 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1267 static const SilcConfigTable table_logging[] = {
1268 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1269 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1270 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1271 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1272 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1273 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1274 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1278 static const SilcConfigTable table_connparam[] = {
1279 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1280 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1281 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1282 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1283 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1284 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1285 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1286 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1287 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1288 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1289 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1290 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1291 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1292 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1293 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1294 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1295 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1296 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1297 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1298 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1302 static const SilcConfigTable table_client[] = {
1303 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1304 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1305 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1306 { "publickeydir", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1307 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1311 static const SilcConfigTable table_admin[] = {
1312 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1313 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1314 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1315 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1316 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1317 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1318 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1322 static const SilcConfigTable table_deny[] = {
1323 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1324 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1328 static const SilcConfigTable table_serverconn[] = {
1329 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1330 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1331 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1332 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1333 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1337 static const SilcConfigTable table_routerconn[] = {
1338 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1339 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1340 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1341 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1342 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1343 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1344 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1345 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1346 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1350 static const SilcConfigTable table_main[] = {
1351 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1352 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1353 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1354 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1355 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1356 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1357 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1358 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1359 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1360 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1361 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1362 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1363 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1367 /* Set default values to stuff that was not configured. */
1369 static void silc_server_config_set_defaults(SilcServerConfig config)
1371 my_set_param_defaults(&config->param, NULL);
1373 config->channel_rekey_secs = (config->channel_rekey_secs ?
1374 config->channel_rekey_secs :
1375 SILC_SERVER_CHANNEL_REKEY);
1376 config->key_exchange_timeout = (config->key_exchange_timeout ?
1377 config->key_exchange_timeout :
1378 SILC_SERVER_SKE_TIMEOUT);
1379 config->conn_auth_timeout = (config->conn_auth_timeout ?
1380 config->conn_auth_timeout :
1381 SILC_SERVER_CONNAUTH_TIMEOUT);
1384 /* Check for correctness of the configuration */
1386 static SilcBool silc_server_config_check(SilcServerConfig config)
1388 SilcBool ret = TRUE;
1389 SilcServerConfigServer *s;
1390 SilcServerConfigRouter *r;
1393 /* ServerConfig is mandatory */
1394 if (!config->server_info) {
1395 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `ServerInfo'"));
1399 /* RouterConnection sanity checks */
1401 if (config->routers && config->routers->backup_router == TRUE &&
1403 SILC_SERVER_LOG_ERROR((
1404 "\nError: First RouterConnection block must be primary router "
1405 "connection. You have marked it incorrectly as backup router."));
1409 if (config->routers && config->routers->initiator == FALSE &&
1410 config->routers->backup_router == FALSE) {
1411 SILC_SERVER_LOG_ERROR((
1412 "\nError: First RouterConnection block must be primary router "
1413 "connection and it must be marked as Initiator."));
1417 if (config->routers && config->routers->backup_router == TRUE &&
1418 !config->servers && !config->routers->next) {
1419 SILC_SERVER_LOG_ERROR((
1420 "\nError: You have configured backup router but not primary router. "
1421 "If backup router is configured also primary router must be "
1426 /* Backup router sanity checks */
1428 for (r = config->routers; r; r = r->next) {
1429 if (r->backup_router && !strcmp(r->host, r->backup_replace_ip)) {
1430 SILC_SERVER_LOG_ERROR((
1431 "\nError: Backup router connection incorrectly configured to use "
1432 "primary and backup router as same host `%s'. They must not be "
1433 "same host.", r->host));
1437 if (r->initiator == FALSE && r->port != 0) {
1438 SILC_SERVER_LOG_WARNING(("\nWarning: Initiator is FALSE and Port is "
1439 "specified. Ignoring Port value."));
1444 /* ServerConnection sanity checks */
1446 for (s = config->servers; s; s = s->next) {
1447 if (s->backup_router) {
1453 for (s = config->servers; s; s = s->next) {
1454 if (!s->backup_router) {
1455 SILC_SERVER_LOG_ERROR((
1456 "\nError: Your server is backup router but not all ServerConnection "
1457 "blocks were marked as backup connections. They all must be "
1458 "marked as backup connections."));
1468 /* Allocates a new configuration object, opens configuration file and
1469 parses it. The parsed data is returned to the newly allocated
1470 configuration object. The SilcServerConfig must be freed by calling
1471 the silc_server_config_destroy function. */
1473 SilcServerConfig silc_server_config_alloc(const char *filename,
1476 SilcServerConfig config_new;
1477 SilcConfigEntity ent;
1478 SilcConfigFile *file;
1480 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1482 /* alloc a config object */
1483 config_new = silc_calloc(1, sizeof(*config_new));
1487 /* general config defaults */
1488 config_new->refcount = 1;
1489 config_new->logging_timestamp = TRUE;
1490 config_new->param.reconnect_keep_trying = TRUE;
1491 config_new->server = server;
1493 /* obtain a config file object */
1494 file = silc_config_open(filename);
1496 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1501 /* obtain a SilcConfig entity, we can use it to start the parsing */
1502 ent = silc_config_init(file);
1504 /* load the known configuration options, give our empty object as context */
1505 silc_config_register_table(ent, table_main, (void *) config_new);
1507 /* enter the main parsing loop. When this returns, we have the parsing
1508 * result and the object filled (or partially, in case of errors). */
1509 ret = silc_config_main(ent);
1510 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1511 silc_config_strerror(ret)));
1513 /* Check if the parser returned errors */
1515 /* handle this special error return which asks to quietly return */
1516 if (ret != SILC_CONFIG_ESILENT) {
1517 char *linebuf, *filename = silc_config_get_filename(file);
1518 SilcUInt32 line = silc_config_get_line(file);
1519 if (ret != SILC_CONFIG_EPRINTLINE)
1520 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1521 silc_config_strerror(ret)));
1522 linebuf = silc_config_read_line(file, line);
1524 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1529 silc_server_config_destroy(config_new);
1530 silc_config_close(file);
1534 /* close (destroy) the file object */
1535 silc_config_close(file);
1537 /* Check the configuration */
1538 if (!silc_server_config_check(config_new)) {
1539 silc_server_config_destroy(config_new);
1543 /* Set default to configuration parameters */
1544 silc_server_config_set_defaults(config_new);
1549 /* Increments the reference counter of a config object */
1551 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1556 ref->config = config;
1557 ref->ref_ptr = ref_ptr;
1558 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1559 config->refcount - 1, config->refcount));
1563 /* Decrements the reference counter of a config object. If the counter
1564 reaches 0, the config object is destroyed. */
1566 void silc_server_config_unref(SilcServerConfigRef *ref)
1569 silc_server_config_destroy(ref->config);
1572 /* Destroy a config object with all his children lists */
1574 void silc_server_config_destroy(SilcServerConfig config)
1579 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1580 config->refcount + 1, config->refcount));
1581 if (config->refcount > 0)
1584 SILC_LOG_DEBUG(("Freeing config context"));
1586 /* Destroy general config stuff */
1587 silc_free(config->module_path);
1588 silc_free(config->debug_string);
1589 silc_free(config->param.version_protocol);
1590 silc_free(config->param.version_software);
1591 silc_free(config->param.version_software_vendor);
1592 silc_free(config->httpd_ip);
1594 /* Destroy Logging channels */
1595 if (config->logging_info)
1596 silc_free(config->logging_info->file);
1597 if (config->logging_warnings)
1598 silc_free(config->logging_warnings->file);
1599 if (config->logging_errors)
1600 silc_free(config->logging_errors->file);
1601 if (config->logging_fatals)
1602 silc_free(config->logging_fatals->file);
1603 silc_free(config->logging_info);
1604 silc_free(config->logging_warnings);
1605 silc_free(config->logging_errors);
1606 silc_free(config->logging_fatals);
1608 /* Destroy the ServerInfo struct */
1609 if (config->server_info) {
1610 register SilcServerConfigServerInfo *si = config->server_info;
1611 silc_free(si->server_name);
1613 silc_free(si->primary->server_ip);
1614 silc_free(si->primary);
1616 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1618 silc_free(di->server_ip);
1621 silc_free(si->server_type);
1622 silc_free(si->location);
1623 silc_free(si->admin);
1624 silc_free(si->email);
1625 silc_free(si->user);
1626 silc_free(si->group);
1627 silc_free(si->motd_file);
1628 silc_free(si->pid_file);
1630 silc_pkcs_public_key_free(si->public_key);
1631 if (si->private_key)
1632 silc_pkcs_private_key_free(si->private_key);
1636 /* Now let's destroy the lists */
1638 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1640 silc_free(di->name);
1641 silc_free(di->module);
1644 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1645 silc_free(di->name);
1646 silc_free(di->module);
1649 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1650 silc_free(di->name);
1651 silc_free(di->hash);
1654 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1655 silc_free(di->name);
1658 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1659 config->conn_params)
1660 silc_free(di->name);
1661 silc_free(di->version_protocol);
1662 silc_free(di->version_software);
1663 silc_free(di->version_software_vendor);
1666 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1667 silc_free(di->host);
1668 CONFIG_FREE_AUTH(di);
1671 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1672 silc_free(di->host);
1673 silc_free(di->user);
1674 silc_free(di->nick);
1675 CONFIG_FREE_AUTH(di);
1678 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1679 silc_free(di->host);
1680 silc_free(di->reason);
1683 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1685 silc_free(di->host);
1686 CONFIG_FREE_AUTH(di);
1689 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1691 silc_free(di->host);
1692 silc_free(di->backup_replace_ip);
1693 CONFIG_FREE_AUTH(di);
1697 memset(config, 'F', sizeof(*config));
1701 /* Registers configured ciphers. These can then be allocated by the
1702 server when needed. */
1704 SilcBool silc_server_config_register_ciphers(SilcServer server)
1706 SilcServerConfig config = server->config;
1707 SilcServerConfigCipher *cipher = config->cipher;
1708 char *module_path = config->module_path;
1710 SILC_LOG_DEBUG(("Registering configured ciphers"));
1712 if (!cipher) /* any cipher in the config file? */
1716 /* if there isn't a module_path OR there isn't a module sim name try to
1717 * use buil-in functions */
1718 if (!module_path || !cipher->module) {
1720 for (i = 0; silc_default_ciphers[i].name; i++)
1721 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1722 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1725 if (!silc_cipher_is_supported(cipher->name)) {
1726 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1727 silc_server_stop(server);
1731 cipher = cipher->next;
1737 /* Registers configured hash functions. These can then be allocated by the
1738 server when needed. */
1740 SilcBool silc_server_config_register_hashfuncs(SilcServer server)
1742 SilcServerConfig config = server->config;
1743 SilcServerConfigHash *hash = config->hash;
1744 char *module_path = config->module_path;
1746 SILC_LOG_DEBUG(("Registering configured hash functions"));
1748 if (!hash) /* any hash func in the config file? */
1752 /* if there isn't a module_path OR there isn't a module sim name try to
1753 * use buil-in functions */
1754 if (!module_path || !hash->module) {
1756 for (i = 0; silc_default_hash[i].name; i++)
1757 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1758 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1761 if (!silc_hash_is_supported(hash->name)) {
1762 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1763 silc_server_stop(server);
1773 /* Registers configure HMACs. These can then be allocated by the server
1776 SilcBool silc_server_config_register_hmacs(SilcServer server)
1778 SilcServerConfig config = server->config;
1779 SilcServerConfigHmac *hmac = config->hmac;
1781 SILC_LOG_DEBUG(("Registering configured HMACs"));
1787 SilcHmacObject hmac_obj;
1788 if (!silc_hash_is_supported(hmac->hash)) {
1789 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1790 silc_server_stop(server);
1794 /* Register the HMAC */
1795 memset(&hmac_obj, 0, sizeof(hmac_obj));
1796 hmac_obj.name = hmac->name;
1797 hmac_obj.len = hmac->mac_length;
1798 silc_hmac_register(&hmac_obj);
1806 /* Registers configured PKCS's. */
1808 SilcBool silc_server_config_register_pkcs(SilcServer server)
1813 /* Sets log files where log messages are saved by the server logger. */
1815 void silc_server_config_setlogfiles(SilcServer server)
1817 SilcServerConfig config = server->config;
1818 SilcServerConfigLogging *this;
1820 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1822 silc_log_timestamp(config->logging_timestamp);
1823 silc_log_quick(config->logging_quick);
1824 silc_log_flushdelay(config->logging_flushdelay ?
1825 config->logging_flushdelay :
1826 SILC_SERVER_LOG_FLUSH_DELAY);
1828 if ((this = config->logging_fatals))
1829 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1831 if ((this = config->logging_errors))
1832 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1834 if ((this = config->logging_warnings))
1835 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1837 if ((this = config->logging_info))
1838 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1842 /* Returns client authentication information from configuration file by host
1845 SilcServerConfigClient *
1846 silc_server_config_find_client(SilcServer server, char *host)
1848 SilcServerConfig config = server->config;
1849 SilcServerConfigClient *client;
1851 if (!config || !host)
1854 for (client = config->clients; client; client = client->next) {
1855 if (client->host && !silc_string_compare(client->host, host))
1860 /* if none matched, then client is already NULL */
1864 /* Returns admin connection configuration by host, username and/or
1867 SilcServerConfigAdmin *
1868 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1871 SilcServerConfig config = server->config;
1872 SilcServerConfigAdmin *admin;
1874 /* make sure we have a value for the matching parameters */
1882 for (admin = config->admins; admin; admin = admin->next) {
1883 if (admin->host && !silc_string_compare(admin->host, host))
1885 if (admin->user && !silc_string_compare(admin->user, user))
1887 if (admin->nick && !silc_string_compare(admin->nick, nick))
1889 /* no checks failed -> this entry matches */
1893 /* if none matched, then admin is already NULL */
1897 /* Returns the denied connection configuration entry by host. */
1899 SilcServerConfigDeny *
1900 silc_server_config_find_denied(SilcServer server, char *host)
1902 SilcServerConfig config = server->config;
1903 SilcServerConfigDeny *deny;
1905 /* make sure we have a value for the matching parameters */
1906 if (!config || !host)
1909 for (deny = config->denied; deny; deny = deny->next) {
1910 if (deny->host && !silc_string_compare(deny->host, host))
1915 /* if none matched, then deny is already NULL */
1919 /* Returns server connection info from server configuartion by host
1922 SilcServerConfigServer *
1923 silc_server_config_find_server_conn(SilcServer server, char *host)
1925 SilcServerConfig config = server->config;
1926 SilcServerConfigServer *serv = NULL;
1931 if (!config->servers)
1934 for (serv = config->servers; serv; serv = serv->next) {
1935 if (!silc_string_compare(serv->host, host))
1943 /* Returns router connection info from server configuration by
1944 host (name or ip). */
1946 SilcServerConfigRouter *
1947 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1949 SilcServerConfig config = server->config;
1950 SilcServerConfigRouter *serv = NULL;
1955 if (!config->routers)
1958 for (serv = config->routers; serv; serv = serv->next) {
1959 if (!silc_string_compare(serv->host, host))
1961 if (port && serv->port && serv->port != port)
1969 /* Find backup router connection by host (name or ip) */
1971 SilcServerConfigRouter *
1972 silc_server_config_find_backup_conn(SilcServer server, char *host)
1974 SilcServerConfig config = server->config;
1975 SilcServerConfigRouter *serv = NULL;
1980 if (!config->routers)
1983 for (serv = config->routers; serv; serv = serv->next) {
1984 if (!serv->backup_router)
1986 if (!silc_string_compare(serv->host, host))
1994 /* Returns TRUE if configuration for a router connection that we are
1995 initiating exists. */
1997 SilcBool silc_server_config_is_primary_route(SilcServer server)
1999 SilcServerConfig config = server->config;
2000 SilcServerConfigRouter *serv = NULL;
2002 SilcBool found = FALSE;
2004 serv = config->routers;
2005 for (i = 0; serv; i++) {
2006 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
2017 /* Returns our primary connection configuration or NULL if we do not
2018 have primary router configured. */
2020 SilcServerConfigRouter *
2021 silc_server_config_get_primary_router(SilcServer server)
2023 SilcServerConfig config = server->config;
2024 SilcServerConfigRouter *serv = NULL;
2027 serv = config->routers;
2028 for (i = 0; serv; i++) {
2029 if (serv->initiator == TRUE && serv->backup_router == FALSE)
2037 /* If we have backup router configured that is going to replace us this
2038 function returns it. */
2040 SilcServerConfigRouter *
2041 silc_server_config_get_backup_router(SilcServer server)
2043 SilcServerConfig config = server->config;
2044 SilcServerConfigRouter *serv = NULL;
2047 if (server->server_type != SILC_ROUTER)
2050 serv = config->routers;
2051 for (i = 0; serv; i++) {
2052 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
2053 serv->backup_local == TRUE &&
2054 !strcmp(server->config->server_info->primary->server_ip,
2055 serv->backup_replace_ip) &&
2056 server->config->server_info->primary->port ==
2057 serv->backup_replace_port)