X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fserverconfig.c;h=911caff0dde735085b13ccc4fa628097740cbe6e;hp=0d217e7c3e39f7c22d9feaf46d94a4b56d887492;hb=382d15d447b7a95390decfa783836ae4fe255b3d;hpb=b087cbcdbc1d2c76b73f4a7b426fc54103abd27e diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index 0d217e7c..911caff0 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -4,7 +4,7 @@ Author: Johnny Mnemonic - Copyright (C) 1997 - 2002 Johnny Mnemonic + Copyright (C) 1997 - 2002 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #include "serverincludes.h" #include "server_internal.h" +#include #if 0 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt) @@ -34,6 +35,13 @@ __type__ *findtmp, *tmp = (__type__ *) config->tmp; \ int got_errno = 0 +/* allocate the tmp field for fetching data */ +#define SILC_SERVER_CONFIG_ALLOCTMP(__type__) \ + if (!tmp) { \ + config->tmp = silc_calloc(1, sizeof(*findtmp)); \ + tmp = (__type__ *) config->tmp; \ + } + /* append the tmp field to the specified list */ #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \ if (!__list__) { \ @@ -78,20 +86,24 @@ my_set_param_defaults(SilcServerConfigConnParams *params, (params->p ? params->p : (defaults && defaults->p ? defaults->p : d)) SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS); - SET_PARAM_DEFAULT(connections_max_per_host, + SET_PARAM_DEFAULT(connections_max_per_host, SILC_SERVER_MAX_CONNECTIONS_SINGLE); SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE); SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT); SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN); SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX); SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY); + SET_PARAM_DEFAULT(qos_rate_limit, SILC_SERVER_QOS_RATE_LIMIT); + SET_PARAM_DEFAULT(qos_bytes_limit, SILC_SERVER_QOS_BYTES_LIMIT); + SET_PARAM_DEFAULT(qos_limit_sec, SILC_SERVER_QOS_LIMIT_SEC); + SET_PARAM_DEFAULT(qos_limit_usec, SILC_SERVER_QOS_LIMIT_USEC); #undef SET_PARAM_DEFAULT } /* Find connection parameters by the parameter block name. */ static SilcServerConfigConnParams * -my_find_param(SilcServerConfig config, const char *name, SilcUInt32 line) +my_find_param(SilcServerConfig config, const char *name) { SilcServerConfigConnParams *param; @@ -100,34 +112,52 @@ my_find_param(SilcServerConfig config, const char *name, SilcUInt32 line) return param; } - SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: " - "Cannot find Param \"%s\".\n", line, name)); + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Cannot find Params \"%s\".", name)); return NULL; } /* parse an authdata according to its auth method */ -static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, - SilcUInt32 line, void **auth_data, - SilcUInt32 *auth_data_len) +static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p, + void **auth_data, SilcUInt32 *auth_data_len) { if (auth_meth == SILC_AUTH_PASSWORD) { /* p is a plain text password */ - if (auth_data) - *auth_data = (void *) strdup(p); - if (auth_data_len) - *auth_data_len = (SilcUInt32) strlen(p); + if (auth_data && auth_data_len) { + if (!silc_utf8_valid(p, strlen(p))) { + *auth_data_len = silc_utf8_encoded_len(p, strlen(p), + SILC_STRING_LANGUAGE); + *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char)); + silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *auth_data, + *auth_data_len); + } else { + *auth_data = (void *) strdup(p); + *auth_data_len = (SilcUInt32) strlen(p); + } + } } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) { /* p is a public key file name */ SilcPublicKey public_key; + SilcPublicKey cached_key; if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM)) if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) { - SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: " - "Could not load public key file!\n", line)); + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Could not load public key file!")); return FALSE; } + if (*auth_data && + silc_hash_table_find_ext(*auth_data, public_key, (void **)&cached_key, + NULL, silc_hash_public_key, NULL, + silc_hash_public_key_compare, NULL)) { + silc_pkcs_public_key_free(public_key); + SILC_SERVER_LOG_WARNING(("Warning: public key file \"%s\" already " + "configured, ignoring this key", p)); + return TRUE; /* non fatal error */ + } + /* The auth_data is a pointer to the hash table of public keys. */ if (auth_data) { if (*auth_data == NULL) @@ -137,11 +167,50 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, TRUE); silc_hash_table_add(*auth_data, public_key, public_key); } - } else { - SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: " - "Unknown authentication method.\n", line)); + } else + abort(); + + return TRUE; +} + +static bool my_parse_publickeydir(const char *dirname, void **auth_data) +{ + int total = 0; + struct dirent *get_file; + DIR *dp; + + if (!(dp = opendir(dirname))) { + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Could not open directory \"%s\"", dirname)); return FALSE; } + + /* errors are not considered fatal */ + while ((get_file = readdir(dp))) { + const char *filename = get_file->d_name; + char buf[1024]; + int dirname_len = strlen(dirname), filename_len = strlen(filename); + struct stat check_file; + + /* Ignore "." and "..", and take files only with ".pub" suffix. */ + if (!strcmp(filename, ".") || !strcmp(filename, "..") || + (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub")) + continue; + + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname, + (dirname[dirname_len - 1] == '/' ? "" : "/"), filename); + + if (stat(buf, &check_file) < 0) { + SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf, + strerror(errno))); + } else if (S_ISREG(check_file.st_mode)) { + my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL); + total++; + } + } + + SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname)); return TRUE; } @@ -200,19 +269,40 @@ SILC_CONFIG_CALLBACK(fetch_generic) } else if (!strcmp(name, "version_protocol")) { CONFIG_IS_DOUBLE(config->param.version_protocol); - config->param.version_protocol = + config->param.version_protocol = (*(char *)val ? strdup((char *) val) : NULL); } else if (!strcmp(name, "version_software")) { CONFIG_IS_DOUBLE(config->param.version_software); - config->param.version_software = + config->param.version_software = (*(char *)val ? strdup((char *) val) : NULL); } else if (!strcmp(name, "version_software_vendor")) { CONFIG_IS_DOUBLE(config->param.version_software_vendor);; - config->param.version_software_vendor = + config->param.version_software_vendor = (*(char *)val ? strdup((char *) val) : NULL); } + else if (!strcmp(name, "detach_disabled")) { + config->detach_disabled = *(bool *)val; + } + else if (!strcmp(name, "detach_timeout")) { + config->detach_timeout = (SilcUInt32) *(int *)val; + } + else if (!strcmp(name, "qos")) { + config->param.qos = *(bool *)val; + } + else if (!strcmp(name, "qos_rate_limit")) { + config->param.qos_rate_limit = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_bytes_limit")) { + config->param.qos_bytes_limit = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_limit_sec")) { + config->param.qos_limit_sec = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_limit_usec")) { + config->param.qos_limit_usec = *(SilcUInt32 *)val; + } else return SILC_CONFIG_EINTERNAL; @@ -230,22 +320,18 @@ SILC_CONFIG_CALLBACK(fetch_cipher) type, name, context)); if (type == SILC_CONFIG_ARG_BLOCK) { /* check the temporary struct's fields */ - if (!tmp) /* empty sub-block? */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; if (!tmp->name) { got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; } - /* the temporary struct is ok, append it to the list */ + SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher); config->tmp = NULL; return SILC_CONFIG_OK; } - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigCipher *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher); /* Identify and save this value */ if (!strcmp(name, "name")) { @@ -282,23 +368,18 @@ SILC_CONFIG_CALLBACK(fetch_hash) type, name, context)); if (type == SILC_CONFIG_ARG_BLOCK) { /* check the temporary struct's fields */ - if (!tmp) /* empty sub-block? */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) { got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; } - /* the temporary struct in tmp is ok */ + SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash); config->tmp = NULL; return SILC_CONFIG_OK; } - - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigHash *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash); /* Identify and save this value */ if (!strcmp(name, "name")) { @@ -335,22 +416,18 @@ SILC_CONFIG_CALLBACK(fetch_hmac) type, name, context)); if (type == SILC_CONFIG_ARG_BLOCK) { /* check the temporary struct's fields */ - if (!tmp) /* empty sub-block? */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) { got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; } - /* the temporary struct is ok, append it to the list */ + SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac); config->tmp = NULL; return SILC_CONFIG_OK; } - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigHmac *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac); /* Identify and save this value */ if (!strcmp(name, "name")) { @@ -384,22 +461,18 @@ SILC_CONFIG_CALLBACK(fetch_pkcs) type, name, context)); if (type == SILC_CONFIG_ARG_BLOCK) { /* check the temporary struct's fields */ - if (!tmp) /* empty sub-block? */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; if (!tmp->name) { got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; } - /* the temporary struct is ok, append it to the list */ + SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs); config->tmp = NULL; return SILC_CONFIG_OK; } - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigPkcs *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs); /* Identify and save this value */ if (!strcmp(name, "name")) { @@ -419,9 +492,8 @@ SILC_CONFIG_CALLBACK(fetch_pkcs) SILC_CONFIG_CALLBACK(fetch_serverinfo) { - SilcServerConfig config = (SilcServerConfig) context; + SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface); SilcServerConfigServerInfo *server_info = config->server_info; - int got_errno = 0; /* if there isn't the struct alloc it */ if (!server_info) @@ -429,8 +501,20 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo) silc_calloc(1, sizeof(*server_info)); if (type == SILC_CONFIG_ARG_BLOCK) { - /* check for mandatory inputs */ - if (!server_info->public_key || !server_info->private_key) { + if (!strcmp(name, "primary")) { + CONFIG_IS_DOUBLE(server_info->primary); + if (!tmp) + return SILC_CONFIG_OK; + server_info->primary = tmp; + config->tmp = NULL; + return SILC_CONFIG_OK; + } else if (!strcmp(name, "secondary")) { + if (!tmp) + return SILC_CONFIG_OK; + SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary); + config->tmp = NULL; + return SILC_CONFIG_OK; + } else if (!server_info->public_key || !server_info->private_key) { got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; } @@ -441,16 +525,20 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo) server_info->server_name = strdup((char *) val); } else if (!strcmp(name, "ip")) { - CONFIG_IS_DOUBLE(server_info->server_ip); - server_info->server_ip = strdup((char *) val); + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface); + CONFIG_IS_DOUBLE(tmp->server_ip); + tmp->server_ip = strdup((char *) val); } else if (!strcmp(name, "port")) { int port = *(int *)val; + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface); if ((port <= 0) || (port > 65535)) { - SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line)); - return SILC_CONFIG_ESILENT; + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Invalid port number!")); + got_errno = SILC_CONFIG_EPRINTLINE; + goto got_err; } - server_info->port = (SilcUInt16) port; + tmp->port = (SilcUInt16) port; } else if (!strcmp(name, "servertype")) { CONFIG_IS_DOUBLE(server_info->server_type); @@ -486,28 +574,28 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo) } else if (!strcmp(name, "publickey")) { char *file_tmp = (char *) val; + CONFIG_IS_DOUBLE(server_info->public_key); /* try to load specified file, if fail stop config parsing */ if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key, SILC_PKCS_FILE_PEM)) if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key, SILC_PKCS_FILE_BIN)) { - SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n")); - SILC_SERVER_LOG_ERROR((" line %lu: file \"%s\"\n", line, file_tmp)); - return SILC_CONFIG_ESILENT; + SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.")); + return SILC_CONFIG_EPRINTLINE; } } else if (!strcmp(name, "privatekey")) { char *file_tmp = (char *) val; + CONFIG_IS_DOUBLE(server_info->private_key); /* try to load specified file, if fail stop config parsing */ if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key, - SILC_PKCS_FILE_BIN)) + "", 0, SILC_PKCS_FILE_BIN)) if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key, - SILC_PKCS_FILE_PEM)) { - SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n")); - SILC_SERVER_LOG_ERROR((" line %lu: file \"%s\"\n", line, file_tmp)); - return SILC_CONFIG_ESILENT; + "", 0, SILC_PKCS_FILE_PEM)) { + SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.")); + return SILC_CONFIG_EPRINTLINE; } } else @@ -515,28 +603,38 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo) return SILC_CONFIG_OK; got_err: + silc_free(tmp); + silc_free(config->tmp); + config->tmp = NULL; return got_errno; } SILC_CONFIG_CALLBACK(fetch_logging) { - SilcServerConfig config = (SilcServerConfig) context; - SilcServerConfigLogging *tmp = - (SilcServerConfigLogging *) config->tmp; - int got_errno; + SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging); - if (!strcmp(name, "quicklogs")) { + if (!strcmp(name, "timestamp")) { + config->logging_timestamp = *(bool *)val; + } + else if (!strcmp(name, "quicklogs")) { config->logging_quick = *(bool *)val; } else if (!strcmp(name, "flushdelay")) { int flushdelay = *(int *)val; if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */ - SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid flushdelay value, use " - "quicklogs if you want real-time logging.\n", line)); - return SILC_CONFIG_ESILENT; + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Invalid flushdelay value, use quicklogs if you " + "want real-time logging.")); + return SILC_CONFIG_EPRINTLINE; } config->logging_flushdelay = (long) flushdelay; } + + /* The following istances happens only in Logging's sub-blocks, a match + for the sub-block name means that you should store the filename/maxsize + temporary struct to the proper logging channel. + If we get a match for "file" or "maxsize" this means that we are inside + a sub-sub-block and it is safe to alloc a new tmp. */ #define FETCH_LOGGING_CHAN(__chan__, __member__) \ else if (!strcmp(name, __chan__)) { \ if (!tmp) return SILC_CONFIG_OK; \ @@ -552,13 +650,8 @@ SILC_CONFIG_CALLBACK(fetch_logging) FETCH_LOGGING_CHAN("fatals", logging_fatals) #undef FETCH_LOGGING_CHAN else if (!strcmp(name, "file")) { - if (!tmp) { /* FIXME: what the fuck is this? */ - config->tmp = silc_calloc(1, sizeof(*tmp)); - tmp = (SilcServerConfigLogging *) config->tmp; - } - if (tmp->file) { - got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging); + CONFIG_IS_DOUBLE(tmp->file); tmp->file = strdup((char *) val); } else if (!strcmp(name, "size")) { @@ -583,18 +676,16 @@ SILC_CONFIG_CALLBACK(fetch_connparam) { SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams); - SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)", + SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)", type, name, context)); - if (type == SILC_CONFIG_ARG_BLOCK) { - if (!tmp) + /* check the temporary struct's fields */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; - if (!tmp->name) { got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; } - /* Set defaults */ my_set_param_defaults(tmp, &config->param); @@ -602,12 +693,7 @@ SILC_CONFIG_CALLBACK(fetch_connparam) config->tmp = NULL; return SILC_CONFIG_OK; } - - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigConnParams *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams); if (!strcmp(name, "name")) { CONFIG_IS_DOUBLE(tmp->name); @@ -650,9 +736,27 @@ SILC_CONFIG_CALLBACK(fetch_connparam) } else if (!strcmp(name, "version_software_vendor")) { CONFIG_IS_DOUBLE(tmp->version_software_vendor);; - tmp->version_software_vendor = + tmp->version_software_vendor = (*(char *)val ? strdup((char *) val) : NULL); } + else if (!strcmp(name, "anonymous")) { + tmp->anonymous = *(bool *)val; + } + else if (!strcmp(name, "qos")) { + tmp->qos = *(bool *)val; + } + else if (!strcmp(name, "qos_rate_limit")) { + tmp->qos_rate_limit = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_bytes_limit")) { + tmp->qos_bytes_limit = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_limit_sec")) { + tmp->qos_limit_sec = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_limit_usec")) { + tmp->qos_limit_usec = *(SilcUInt32 *)val; + } else return SILC_CONFIG_EINTERNAL; @@ -672,14 +776,11 @@ SILC_CONFIG_CALLBACK(fetch_client) SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)", type, name, context)); - /* alloc tmp before block checking (empty sub-blocks are welcome here) */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigClient *) config->tmp; - } + /* Alloc before block checking, because empty sub-blocks are welcome here */ + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient); if (type == SILC_CONFIG_ARG_BLOCK) { - /* closing the block */ + /* empty sub-blocks are welcome */ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients); config->tmp = NULL; return SILC_CONFIG_OK; @@ -692,25 +793,31 @@ SILC_CONFIG_CALLBACK(fetch_client) } else if (!strcmp(name, "passphrase")) { CONFIG_IS_DOUBLE(tmp->passphrase); - if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, (void **)&tmp->passphrase, &tmp->passphrase_len)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "publickey")) { - if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, (void **)&tmp->publickeys, NULL)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; + goto got_err; + } + } + else if (!strcmp(name, "publickeydir")) { + if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) { + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "params")) { CONFIG_IS_DOUBLE(tmp->param); - tmp->param = my_find_param(config, (char *) val, line); - if (!tmp->param) { /* error already output */ - got_errno = SILC_CONFIG_ESILENT; + tmp->param = my_find_param(config, (char *) val); + if (!tmp->param) { /* error message already output */ + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } @@ -732,22 +839,16 @@ SILC_CONFIG_CALLBACK(fetch_admin) SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)", type, name, context)); - if (type == SILC_CONFIG_ARG_BLOCK) { /* check the temporary struct's fields */ - if (!tmp) /* empty sub-block? */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins); config->tmp = NULL; return SILC_CONFIG_OK; } - - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigAdmin *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin); /* Identify and save this value */ if (!strcmp(name, "host")) { @@ -764,18 +865,23 @@ SILC_CONFIG_CALLBACK(fetch_admin) } else if (!strcmp(name, "passphrase")) { CONFIG_IS_DOUBLE(tmp->passphrase); - if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, (void **)&tmp->passphrase, &tmp->passphrase_len)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "publickey")) { - CONFIG_IS_DOUBLE(tmp->publickeys); - if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, (void **)&tmp->publickeys, NULL)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; + goto got_err; + } + } + else if (!strcmp(name, "publickeydir")) { + if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) { + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } @@ -801,21 +907,18 @@ SILC_CONFIG_CALLBACK(fetch_deny) type, name, context)); if (type == SILC_CONFIG_ARG_BLOCK) { /* check the temporary struct's fields */ - if (!tmp) /* empty sub-block? */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; if (!tmp->reason) { got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; } + SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied); config->tmp = NULL; return SILC_CONFIG_OK; } - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigDeny *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny); /* Identify and save this value */ if (!strcmp(name, "host")) { @@ -844,10 +947,9 @@ SILC_CONFIG_CALLBACK(fetch_server) SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)", type, name, context)); - if (type == SILC_CONFIG_ARG_BLOCK) { /* check the temporary struct's fields */ - if (!tmp) /* empty sub-block? */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; /* the temporary struct is ok, append it to the list */ @@ -855,12 +957,7 @@ SILC_CONFIG_CALLBACK(fetch_server) config->tmp = NULL; return SILC_CONFIG_OK; } - - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigServer *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer); /* Identify and save this value */ if (!strcmp(name, "host")) { @@ -869,30 +966,26 @@ SILC_CONFIG_CALLBACK(fetch_server) } else if (!strcmp(name, "passphrase")) { CONFIG_IS_DOUBLE(tmp->passphrase); - if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, (void **)&tmp->passphrase, &tmp->passphrase_len)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "publickey")) { CONFIG_IS_DOUBLE(tmp->publickeys); - if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, (void **)&tmp->publickeys, NULL)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } - else if (!strcmp(name, "versionid")) { - CONFIG_IS_DOUBLE(tmp->version); - tmp->version = strdup((char *) val); - } else if (!strcmp(name, "params")) { CONFIG_IS_DOUBLE(tmp->param); - tmp->param = my_find_param(config, (char *) val, line); - if (!tmp->param) { /* error already output */ - got_errno = SILC_CONFIG_ESILENT; + tmp->param = my_find_param(config, (char *) val); + if (!tmp->param) { /* error message already output */ + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } @@ -906,7 +999,6 @@ SILC_CONFIG_CALLBACK(fetch_server) got_err: silc_free(tmp->host); - silc_free(tmp->version); CONFIG_FREE_AUTH(tmp); silc_free(tmp); config->tmp = NULL; @@ -919,22 +1011,15 @@ SILC_CONFIG_CALLBACK(fetch_router) SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)", type, name, context)); - if (type == SILC_CONFIG_ARG_BLOCK) { - if (!tmp) /* empty sub-block? */ + if (!tmp) /* discard empty sub-blocks */ return SILC_CONFIG_OK; - /* the temporary struct is ok, append it to the list */ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers); config->tmp = NULL; return SILC_CONFIG_OK; } - - /* if there isn't a temporary struct alloc one */ - if (!tmp) { - config->tmp = silc_calloc(1, sizeof(*findtmp)); - tmp = (SilcServerConfigRouter *) config->tmp; - } + SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter); /* Identify and save this value */ if (!strcmp(name, "host")) { @@ -944,37 +1029,35 @@ SILC_CONFIG_CALLBACK(fetch_router) else if (!strcmp(name, "port")) { int port = *(int *)val; if ((port <= 0) || (port > 65535)) { - SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line)); - return SILC_CONFIG_ESILENT; + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Invalid port number!")); + got_errno = SILC_CONFIG_EPRINTLINE; + goto got_err; } tmp->port = (SilcUInt16) port; } else if (!strcmp(name, "passphrase")) { CONFIG_IS_DOUBLE(tmp->passphrase); - if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, (void **)&tmp->passphrase, &tmp->passphrase_len)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "publickey")) { CONFIG_IS_DOUBLE(tmp->publickeys); - if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, (void **)&tmp->publickeys, NULL)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } - else if (!strcmp(name, "versionid")) { - CONFIG_IS_DOUBLE(tmp->version); - tmp->version = strdup((char *) val); - } else if (!strcmp(name, "params")) { CONFIG_IS_DOUBLE(tmp->param); - tmp->param = my_find_param(config, (char *) val, line); - if (!tmp->param) { /* error already output */ - got_errno = SILC_CONFIG_ESILENT; + tmp->param = my_find_param(config, (char *) val); + if (!tmp->param) { /* error message already output */ + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } @@ -985,12 +1068,15 @@ SILC_CONFIG_CALLBACK(fetch_router) CONFIG_IS_DOUBLE(tmp->backup_replace_ip); tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) : strdup("*")); + tmp->backup_router = TRUE; } else if (!strcmp(name, "backupport")) { int port = *(int *)val; if ((port <= 0) || (port > 65535)) { - SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line)); - return SILC_CONFIG_ESILENT; + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Invalid port number!")); + got_errno = SILC_CONFIG_EPRINTLINE; + goto got_err; } tmp->backup_replace_port = (SilcUInt16) port; } @@ -1004,7 +1090,6 @@ SILC_CONFIG_CALLBACK(fetch_router) got_err: silc_free(tmp->host); - silc_free(tmp->version); silc_free(tmp->backup_replace_ip); CONFIG_FREE_AUTH(tmp); silc_free(tmp); @@ -1029,9 +1114,16 @@ static const SilcConfigTable table_general[] = { { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, - { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL }, - { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL }, - { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL }, + { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL }, + { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL }, + { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL }, + { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL }, + { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL }, + { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, { 0, 0, 0, 0 } }; @@ -1063,10 +1155,16 @@ static const SilcConfigTable table_pkcs[] = { { 0, 0, 0, 0 } }; -static const SilcConfigTable table_serverinfo[] = { - { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL}, +static const SilcConfigTable table_serverinfo_c[] = { { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL}, { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL}, + { 0, 0, 0, 0 } +}; + +static const SilcConfigTable table_serverinfo[] = { + { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL}, + { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c}, + { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c}, { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL}, { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL}, { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL}, @@ -1088,6 +1186,7 @@ static const SilcConfigTable table_logging_c[] = { }; static const SilcConfigTable table_logging[] = { + { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL }, { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL }, { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL }, { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c }, @@ -1112,6 +1211,12 @@ static const SilcConfigTable table_connparam[] = { { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL }, { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL }, { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL }, + { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL }, + { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL }, + { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, { 0, 0, 0, 0 } }; @@ -1119,6 +1224,7 @@ static const SilcConfigTable table_client[] = { { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL }, { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL }, { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL }, + { "publickeydir", SILC_CONFIG_ARG_STR, fetch_client, NULL }, { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL }, { 0, 0, 0, 0 } }; @@ -1129,6 +1235,7 @@ static const SilcConfigTable table_admin[] = { { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL }, { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL }, { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL }, + { "publickeydir", SILC_CONFIG_ARG_STR, fetch_admin, NULL }, { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL }, { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL }, { 0, 0, 0, 0 } @@ -1144,7 +1251,6 @@ static const SilcConfigTable table_serverconn[] = { { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL }, { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL }, { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL }, - { "versionid", SILC_CONFIG_ARG_STR, fetch_server, NULL }, { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL }, { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL }, { 0, 0, 0, 0 } @@ -1155,7 +1261,6 @@ static const SilcConfigTable table_routerconn[] = { { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL }, { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL }, { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL }, - { "versionid", SILC_CONFIG_ARG_STR, fetch_router, NULL }, { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL }, { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL }, { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL }, @@ -1165,11 +1270,11 @@ static const SilcConfigTable table_routerconn[] = { }; static const SilcConfigTable table_main[] = { - { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general }, { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher }, { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash }, { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac }, { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs }, + { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general }, { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo }, { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging }, { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam }, @@ -1198,6 +1303,82 @@ static void silc_server_config_set_defaults(SilcServerConfig config) SILC_SERVER_CONNAUTH_TIMEOUT); } +/* Check for correctness of the configuration */ + +static bool silc_server_config_check(SilcServerConfig config) +{ + bool ret = TRUE; + SilcServerConfigServer *s; + SilcServerConfigRouter *r; + bool b = FALSE; + + /* ServerConfig is mandatory */ + if (!config->server_info) { + SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `ServerInfo'")); + ret = FALSE; + } + + /* RouterConnection sanity checks */ + + if (config->routers && config->routers->backup_router == TRUE && + !config->servers) { + SILC_SERVER_LOG_ERROR(( + "\nError: First RouterConnection block must be primary router " + "connection. You have marked it incorrectly as backup router.")); + ret = FALSE; + } + if (config->routers && config->routers->initiator == FALSE && + config->routers->backup_router == FALSE) { + SILC_SERVER_LOG_ERROR(( + "\nError: First RouterConnection block must be primary router " + "connection and it must be marked as Initiator.")); + ret = FALSE; + } + if (config->routers && config->routers->backup_router == TRUE && + !config->servers && !config->routers->next) { + SILC_SERVER_LOG_ERROR(( + "\nError: You have configured backup router but not primary router. " + "If backup router is configured also primary router must be " + "configured.")); + ret = FALSE; + } + + /* Backup router sanity checks */ + + for (r = config->routers; r; r = r->next) { + if (r->backup_router && !strcmp(r->host, r->backup_replace_ip)) { + SILC_SERVER_LOG_ERROR(( + "\nError: Backup router connection incorrectly configured to use " + "primary and backup router as same host `%s'. They must not be " + "same host.", r->host)); + ret = FALSE; + } + } + + /* ServerConnection sanity checks */ + + for (s = config->servers; s; s = s->next) { + if (s->backup_router) { + b = TRUE; + break; + } + } + if (b) { + for (s = config->servers; s; s = s->next) { + if (!s->backup_router) { + SILC_SERVER_LOG_ERROR(( + "\nError: Your server is backup router but not all ServerConnection " + "blocks were marked as backup connections. They all must be " + "marked as backup connections.")); + ret = FALSE; + break; + } + } + } + + return ret; +} + /* Allocates a new configuration object, opens configuration file and parses it. The parsed data is returned to the newly allocated configuration object. The SilcServerConfig must be freed by calling @@ -1216,10 +1397,14 @@ SilcServerConfig silc_server_config_alloc(const char *filename) if (!config_new) return NULL; + /* general config defaults */ + config_new->refcount = 1; + config_new->logging_timestamp = TRUE; + /* obtain a config file object */ file = silc_config_open(filename); if (!file) { - SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n", + SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'", filename)); return NULL; } @@ -1242,12 +1427,15 @@ SilcServerConfig silc_server_config_alloc(const char *filename) if (ret != SILC_CONFIG_ESILENT) { char *linebuf, *filename = silc_config_get_filename(file); SilcUInt32 line = silc_config_get_line(file); - SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n", - silc_config_strerror(ret))); + if (ret != SILC_CONFIG_EPRINTLINE) + SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.", + silc_config_strerror(ret))); linebuf = silc_config_read_line(file, line); - SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename, - line, linebuf)); - silc_free(linebuf); + if (linebuf) { + SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename, + line, linebuf)); + silc_free(linebuf); + } } silc_server_config_destroy(config_new); return NULL; @@ -1256,16 +1444,12 @@ SilcServerConfig silc_server_config_alloc(const char *filename) /* close (destroy) the file object */ silc_config_close(file); - /* If config_new is incomplete, abort the object and return NULL */ - if (!config_new->server_info) { - SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block " - "`server_info'\n")); + /* Check the configuration */ + if (!silc_server_config_check(config_new)) { silc_server_config_destroy(config_new); return NULL; } - /* XXX are there any other mandatory sections in the config file? */ - /* Set default to configuration parameters */ silc_server_config_set_defaults(config_new); @@ -1281,7 +1465,7 @@ void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config, config->refcount++; ref->config = config; ref->ref_ptr = ref_ptr; - SILC_LOG_DEBUG(("Referencing config [%p] refcnt %hu->%hu", config, + SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config, config->refcount - 1, config->refcount)); } } @@ -1291,16 +1475,8 @@ void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config, void silc_server_config_unref(SilcServerConfigRef *ref) { - SilcServerConfig config = ref->config; - - if (ref->ref_ptr) { - config->refcount--; - SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config, - config->refcount + 1, config->refcount)); - if (!config->refcount) - silc_server_config_destroy(config); - ref->ref_ptr = NULL; - } + if (ref->ref_ptr) + silc_server_config_destroy(ref->config); } /* Destroy a config object with all his children lists */ @@ -1309,9 +1485,19 @@ void silc_server_config_destroy(SilcServerConfig config) { void *tmp; + config->refcount--; + SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config, + config->refcount + 1, config->refcount)); + if (config->refcount > 0) + return; + SILC_LOG_DEBUG(("Freeing config context")); + /* Destroy general config stuff */ silc_free(config->module_path); + silc_free(config->param.version_protocol); + silc_free(config->param.version_software); + silc_free(config->param.version_software_vendor); /* Destroy Logging channels */ if (config->logging_info) @@ -1322,12 +1508,24 @@ void silc_server_config_destroy(SilcServerConfig config) silc_free(config->logging_errors->file); if (config->logging_fatals) silc_free(config->logging_fatals->file); + silc_free(config->logging_info); + silc_free(config->logging_warnings); + silc_free(config->logging_errors); + silc_free(config->logging_fatals); /* Destroy the ServerInfo struct */ if (config->server_info) { register SilcServerConfigServerInfo *si = config->server_info; silc_free(si->server_name); - silc_free(si->server_ip); + if (si->primary) { + silc_free(si->primary->server_ip); + silc_free(si->primary); + } + SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface, + si->secondary) + silc_free(di->server_ip); + silc_free(di); + } silc_free(si->server_type); silc_free(si->location); silc_free(si->admin); @@ -1338,6 +1536,7 @@ void silc_server_config_destroy(SilcServerConfig config) silc_free(si->pid_file); silc_pkcs_public_key_free(si->public_key); silc_pkcs_private_key_free(si->private_key); + silc_free(si); } /* Now let's destroy the lists */ @@ -1362,8 +1561,15 @@ void silc_server_config_destroy(SilcServerConfig config) silc_free(di->name); silc_free(di); } - SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, - config->clients) + SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams, + config->conn_params) + silc_free(di->name); + silc_free(di->version_protocol); + silc_free(di->version_software); + silc_free(di->version_software_vendor); + silc_free(di); + } + SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients) silc_free(di->host); CONFIG_FREE_AUTH(di); silc_free(di); @@ -1383,14 +1589,12 @@ void silc_server_config_destroy(SilcServerConfig config) SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer, config->servers) silc_free(di->host); - silc_free(di->version); CONFIG_FREE_AUTH(di); silc_free(di); } SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter, config->routers) silc_free(di->host); - silc_free(di->version); silc_free(di->backup_replace_ip); CONFIG_FREE_AUTH(di); silc_free(di); @@ -1456,7 +1660,7 @@ bool silc_server_config_register_ciphers(SilcServer server) SILC_CIPHER_SIM_SET_KEY)); SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key)); cipher_obj.set_key_with_string = - silc_sim_getsym(sim, + silc_sim_getsym(sim, silc_sim_symname(alg_name, SILC_CIPHER_SIM_SET_KEY_WITH_STRING)); SILC_LOG_DEBUG(("set_key_with_string=%p", @@ -1480,6 +1684,7 @@ bool silc_server_config_register_ciphers(SilcServer server) silc_free(alg_name); } else { SILC_LOG_ERROR(("Error configuring ciphers")); + silc_sim_free(sim); silc_server_stop(server); exit(1); } @@ -1563,6 +1768,7 @@ bool silc_server_config_register_hashfuncs(SilcServer server) silc_dlist_add(server->sim, sim); } else { SILC_LOG_ERROR(("Error configuring hash functions")); + silc_sim_free(sim); silc_server_stop(server); exit(1); } @@ -1654,8 +1860,9 @@ void silc_server_config_setlogfiles(SilcServer server) SILC_LOG_DEBUG(("Setting configured log file names and options")); + silc_log_timestamp = config->logging_timestamp; silc_log_quick = config->logging_quick; - silc_log_flushdelay = (config->logging_flushdelay ? + silc_log_flushdelay = (config->logging_flushdelay ? config->logging_flushdelay : SILC_SERVER_LOG_FLUSH_DELAY); @@ -1699,7 +1906,7 @@ silc_server_config_find_client(SilcServer server, char *host) nickname. */ SilcServerConfigAdmin * -silc_server_config_find_admin(SilcServer server, char *host, char *user, +silc_server_config_find_admin(SilcServer server, char *host, char *user, char *nick) { SilcServerConfig config = server->config; @@ -1800,6 +2007,31 @@ silc_server_config_find_router_conn(SilcServer server, char *host, int port) return serv; } +/* Find backup router connection by host (name or ip) */ + +SilcServerConfigRouter * +silc_server_config_find_backup_conn(SilcServer server, char *host) +{ + SilcServerConfig config = server->config; + SilcServerConfigRouter *serv = NULL; + + if (!host) + return NULL; + + if (!config->routers) + return NULL; + + for (serv = config->routers; serv; serv = serv->next) { + if (!serv->backup_router) + continue; + if (!silc_string_compare(serv->host, host)) + continue; + break; + } + + return serv; +} + /* Returns TRUE if configuration for a router connection that we are initiating exists. */ @@ -1842,3 +2074,31 @@ silc_server_config_get_primary_router(SilcServer server) return NULL; } + +/* If we have backup router configured that is going to replace us this + function returns it. */ + +SilcServerConfigRouter * +silc_server_config_get_backup_router(SilcServer server) +{ + SilcServerConfig config = server->config; + SilcServerConfigRouter *serv = NULL; + int i; + + if (server->server_type != SILC_ROUTER) + return NULL; + + serv = config->routers; + for (i = 0; serv; i++) { + if (serv->initiator == FALSE && serv->backup_router == TRUE && + serv->backup_local == TRUE && + !strcmp(server->config->server_info->primary->server_ip, + serv->backup_replace_ip) && + server->config->server_info->primary->port == + serv->backup_replace_port) + return serv; + serv = serv->next; + } + + return NULL; +}