serverconfig.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#include "serverincludes.h"
#include "server_internal.h"
+#include <dirent.h>
-/* XXX
- All possible configuration sections for SILC server.
-
- <Cipher>
-
- Format:
-
- +<Cipher name>:<SIM path>
-
- <PKCS>
-
- Format:
-
- +<PKCS name>:<key length>
-
- <HashFunction>
-
- Format:
-
- +<Hash function name>:<SIM path>
-
- <ServerInfo>
-
- This section is used to set the server informations.
-
- Format:
-
- +<Server DNS name>:<Server IP>:<Geographic location>:<Port>
-
- <AdminInfo>
-
- This section is used to set the server's administrative information.
-
- Format:
-
- +<Location>:<Server type>:<Admin's name>:<Admin's email address>
-
- <ListenPort>
-
- This section is used to set ports the server is listenning.
-
- Format:
-
- +<Local IP/UNIX socket path>:<Remote IP>:<Port>
-
- <Logging>
-
- This section is used to set various logging files, their paths
- and maximum sizes. All the other directives except those defined
- below are ignored in this section. Log files are purged after they
- reach the maximum set byte size.
-
- Format:
-
- +infologfile:<path>:<max byte size>
- +errorlogfile:<path>:<max byte size>
-
- <ConnectionClass>
-
- This section is used to define connection classes. These can be
- used to optimize the server and the connections.
-
- Format:
-
- +<Class number>:<Ping freq>:<Connect freq>:<Max links>
-
- <ClientAuth>
-
- This section is used to define client authentications.
-
- Format:
-
- +<Remote address or name>:<auth method>:<password/cert/key/???>:<Port>:<Class>
-
- <AdminAuth>
-
- This section is used to define the server's administration
- authentications.
-
- Format:
-
- +<Hostname>:<auth method>:<password/cert/key/???>:<Nickname hash>:<Class>
-
- <ServerConnection>
-
- This section is used to define the server connections to this
- server/router. Only routers can have normal server connections.
- Normal servers leave this section epmty. The remote server cannot be
- older than specified Version ID.
-
- Format:
-
- +<Remote address or name>:<auth method>:<password/key/???>:<Port>:<Version ID>:<Class>
-
- <RouterConnection>
-
- This section is used to define the router connections to this
- server/router. Both normal server and router can have router
- connections. Normal server usually has only one connection while
- a router can have multiple. The remote server cannot be older than
- specified Version ID.
-
- Format:
-
- +<Remote address or name>:<auth method>:<password/key/???>:
- <Port>:<Version ID>:<Class>:<Initiator>
-
- <DenyConnection>
-
- This section is used to deny specific connections to your server. This
- can be used to deny both clients and servers.
-
- Format:
-
- +<Remote address or name or nickname>:<Time interval>:<Comment>:<Port>
-
- <RedirectClient>
+#if 0
+#define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
+#else
+#define SERVER_CONFIG_DEBUG(fmt)
+#endif
- This section is used to set the alternate servers that clients will be
- redirected to when our server is full.
+/* auto-declare needed variables for the common list parsing */
+#define SILC_SERVER_CONFIG_SECTION_INIT(__type__) \
+ SilcServerConfig config = (SilcServerConfig) context; \
+ __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; \
+ }
- Format:
+/* append the tmp field to the specified list */
+#define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
+ if (!__list__) { \
+ __list__ = tmp; \
+ } else { \
+ for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
+ findtmp->next = tmp; \
+ }
- +<Remote address or name>:<Port>
+/* loops all elements in a list and provides a di struct pointer of the
+ * specified type containing the current element */
+#define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__) \
+ for (tmp = (void *) __list__; tmp;) { \
+ __type__ *di = (__type__ *) tmp; \
+ tmp = (void *) di->next;
+
+/* Set EDOUBLE error value and bail out if necessary */
+#define CONFIG_IS_DOUBLE(__x__) \
+ if ((__x__)) { \
+ got_errno = SILC_CONFIG_EDOUBLE; \
+ goto got_err; \
+ }
-*/
-SilcConfigServerSection silc_config_server_sections[] = {
- { "[Cipher]",
- SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER, 4 },
- { "[PKCS]",
- SILC_CONFIG_SERVER_SECTION_TYPE_PKCS, 2 },
- { "[HashFunction]",
- SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION, 4 },
- { "[ServerInfo]",
- SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO, 4 },
- { "[AdminInfo]",
- SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO, 4 },
- { "[ListenPort]",
- SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT, 3 },
- { "[Logging]",
- SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING, 3 },
- { "[ConnectionClass]",
- SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS, 4 },
- { "[ClientConnection]",
- SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION, 5 },
- { "[ServerConnection]",
- SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION, 6 },
- { "[RouterConnection]",
- SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION, 7 },
- { "[AdminConnection]",
- SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION, 5 },
- { "[DenyConnection]",
- SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION, 4 },
- { "[RedirectClient]",
- SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT, 2 },
- { "[motd]",
- SILC_CONFIG_SERVER_SECTION_TYPE_MOTD, 1 },
-
- { NULL, SILC_CONFIG_SERVER_SECTION_TYPE_NONE, 0 }
-};
+/* Free the authentication fields in the specified struct
+ * Expands to two instructions */
+#define CONFIG_FREE_AUTH(__section__) \
+ silc_free(__section__->passphrase); \
+ if (__section__->publickeys) \
+ silc_hash_table_free(__section__->publickeys);
-/* Allocates a new configuration object, opens configuration file and
- parses the file. The parsed data is returned to the newly allocated
- configuration object. */
+static void my_free_public_key(void *key, void *context, void *user_data)
+{
+ silc_pkcs_public_key_free(context);
+}
-SilcConfigServer silc_config_server_alloc(char *filename)
+/* Set default values to those parameters that have not been defined */
+static void
+my_set_param_defaults(SilcServerConfigConnParams *params,
+ SilcServerConfigConnParams *defaults)
{
- SilcConfigServer new;
- SilcBuffer buffer;
- SilcConfigServerParse config_parse;
+#define SET_PARAM_DEFAULT(p, d) params->p = \
+ (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,
+ 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);
+ SET_PARAM_DEFAULT(chlimit, SILC_SERVER_CH_JOIN_LIMIT);
+
+#undef SET_PARAM_DEFAULT
+}
- SILC_LOG_DEBUG(("Allocating new configuration object"));
+/* Find connection parameters by the parameter block name. */
+static SilcServerConfigConnParams *
+my_find_param(SilcServerConfig config, const char *name)
+{
+ SilcServerConfigConnParams *param;
- new = silc_calloc(1, sizeof(*new));
- if (!new) {
- fprintf(stderr, "Could not allocate new configuration object");
- return NULL;
+ for (param = config->conn_params; param; param = param->next) {
+ if (!strcasecmp(param->name, name))
+ return param;
}
- new->filename = filename;
-
- /* Open configuration file and parse it */
- config_parse = NULL;
- buffer = NULL;
- silc_config_open(filename, &buffer);
- if (!buffer)
- goto fail;
- if ((silc_config_server_parse(new, buffer, &config_parse)) == FALSE)
- goto fail;
- if ((silc_config_server_parse_lines(new, config_parse)) == FALSE)
- goto fail;
-
- silc_free(buffer);
-
- return new;
+ SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+ "Cannot find Params \"%s\".", name));
- fail:
- silc_free(new);
return NULL;
}
-/* Free's a configuration object. */
-
-void silc_config_server_free(SilcConfigServer config)
-{
- if (config) {
- silc_free(config->filename);
- silc_free(config->server_info);
- silc_free(config->admin_info);
- silc_free(config->listen_port);
- silc_free(config->conn_class);
- silc_free(config->clients);
- silc_free(config->admins);
- silc_free(config->servers);
- silc_free(config->routers);
- silc_free(config->denied);
- silc_free(config->redirect);
- silc_free(config->motd);
- silc_free(config);
- }
-}
-
-/* Parses the the buffer and returns the parsed lines into return_config
- argument. The return_config argument doesn't have to be initialized
- before calling this. It will be initialized during the parsing. The
- buffer sent as argument can be safely free'd after this function has
- succesfully returned. */
-
-int silc_config_server_parse(SilcConfigServer config, SilcBuffer buffer,
- SilcConfigServerParse *return_config)
+/* parse an authdata according to its auth method */
+static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
+ void **auth_data, SilcUInt32 *auth_data_len)
{
- int i, begin;
- unsigned int linenum;
- char line[1024], *cp;
- SilcConfigServerSection *cptr = NULL;
- SilcConfigServerParse parse = *return_config, first = NULL;
-
- SILC_LOG_DEBUG(("Parsing configuration file"));
-
- begin = 0;
- linenum = 0;
- while((begin = silc_gets(line, sizeof(line),
- buffer->data, buffer->len, begin)) != EOF) {
- cp = line;
- linenum++;
-
- /* Check for bad line */
- if (silc_check_line(cp))
- continue;
-
- /* Remove tabs and whitespaces from the line */
- if (strchr(cp, '\t')) {
- i = 0;
- while(strchr(cp + i, '\t')) {
- *strchr(cp + i, '\t') = ' ';
- i++;
- }
- }
- for (i = 0; i < strlen(cp); i++) {
- if (cp[i] != ' ') {
- if (i)
- cp++;
- break;
+ if (auth_meth == SILC_AUTH_PASSWORD) {
+ /* p is a plain text password */
+ 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_LOCALE);
+ *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
+ silc_utf8_encode(p, strlen(p), SILC_STRING_LOCALE, *auth_data,
+ *auth_data_len);
+ } else {
+ *auth_data = (void *) strdup(p);
+ *auth_data_len = (SilcUInt32) strlen(p);
}
- cp++;
}
-
- /* Parse line */
- switch(cp[0]) {
- case '[':
- /*
- * Start of a section
- */
-
- /* Remove new line sign */
- if (strchr(cp, '\n'))
- *strchr(cp, '\n') = '\0';
-
- /* Check for matching sections */
- for (cptr = silc_config_server_sections; cptr->section; cptr++)
- if (!strncasecmp(cp, cptr->section, strlen(cptr->section)))
- break;
-
- if (!cptr->section) {
- fprintf(stderr, "%s:%d: Unknown section `%s'\n",
- config->filename, linenum, cp);
+ } 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(("Error while parsing config file: "
+ "Could not load public key file!"));
return FALSE;
}
- break;
- default:
- /*
- * Start of a configuration line
- */
-
- if (cptr->type != SILC_CONFIG_SERVER_SECTION_TYPE_NONE) {
-
- if (strchr(cp, '\n'))
- *strchr(cp, '\n') = ':';
-
- if (parse == NULL) {
- parse = silc_calloc(1, sizeof(*parse));
- parse->line = NULL;
- parse->section = NULL;
- parse->next = NULL;
- parse->prev = NULL;
- } else {
- if (parse->next == NULL) {
- parse->next = silc_calloc(1, sizeof(*parse->next));
- parse->next->line = NULL;
- parse->next->section = NULL;
- parse->next->next = NULL;
- parse->next->prev = parse;
- parse = parse->next;
- }
- }
-
- if (first == NULL)
- first = parse;
-
- /* Add the line to parsing structure for further parsing. */
- if (parse) {
- parse->section = cptr;
- parse->line = silc_buffer_alloc(strlen(cp) + 1);
- parse->linenum = linenum;
- silc_buffer_pull_tail(parse->line, strlen(cp));
- silc_buffer_put(parse->line, cp, strlen(cp));
- }
- }
- break;
+ 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 */
}
- }
-
- /* Set the return_config argument to its first value so that further
- parsing can be started from the first line. */
- *return_config = first;
+
+ /* The auth_data is a pointer to the hash table of public keys. */
+ if (auth_data) {
+ if (*auth_data == NULL)
+ *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
+ NULL, NULL,
+ my_free_public_key, NULL,
+ TRUE);
+ SILC_LOG_DEBUG(("Adding public key '%s' to authentication cache",
+ public_key->identifier));
+ silc_hash_table_add(*auth_data, public_key, public_key);
+ }
+ } else
+ abort();
return TRUE;
}
-/* Parses the lines earlier read from configuration file. The config object
- must not be initialized, it will be initialized in this function. The
- parse_config argument is uninitialized automatically during this
- function. */
-
-int silc_config_server_parse_lines(SilcConfigServer config,
- SilcConfigServerParse parse_config)
+static bool my_parse_publickeydir(const char *dirname, void **auth_data)
{
- int ret, check = FALSE;
- unsigned int checkmask;
- char *tmp;
- SilcConfigServerParse pc = parse_config;
- SilcBuffer line;
-
- SILC_LOG_DEBUG(("Parsing configuration lines"));
-
- if (!config)
+ 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;
-
- checkmask = 0;
- while(pc) {
- check = FALSE;
- line = pc->line;
-
- /* Get number of tokens in line */
- ret = silc_config_check_num_token(line);
- if (ret != pc->section->maxfields) {
- /* Bad line */
- fprintf(stderr, "%s:%d: Missing tokens, %d tokens (should be %d)\n",
- config->filename, pc->linenum, ret,
- pc->section->maxfields);
- break;
- }
+ }
- /* Parse the line */
- switch(pc->section->type) {
- case SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER:
+ /* 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;
- SILC_SERVER_CONFIG_LIST_ALLOC(config->cipher);
+ /* Ignore "." and "..", and take files only with ".pub" suffix. */
+ if (!strcmp(filename, ".") || !strcmp(filename, "..") ||
+ (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub"))
+ continue;
- /* Get cipher name */
- ret = silc_config_get_token(line, &config->cipher->alg_name);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: Cipher name not defined\n",
- config->filename, pc->linenum);
- break;
- }
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname,
+ (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
- /* Get module name */
- config->cipher->sim_name = NULL;
- ret = silc_config_get_token(line, &config->cipher->sim_name);
- if (ret < 0)
- break;
+ 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++;
+ }
+ }
- /* Get block length */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: Cipher block length not defined\n",
- config->filename, pc->linenum);
- break;
- }
- config->cipher->block_len = atoi(tmp);
- silc_free(tmp);
+ SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
+ return TRUE;
+}
- /* Get key length */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: Cipher key length not defined\n",
- config->filename, pc->linenum);
- break;
- }
- config->cipher->key_len = atoi(tmp);
- silc_free(tmp);
+/* Callbacks */
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+SILC_CONFIG_CALLBACK(fetch_generic)
+{
+ SilcServerConfig config = (SilcServerConfig) context;
+ int got_errno = 0;
- case SILC_CONFIG_SERVER_SECTION_TYPE_PKCS:
+ if (!strcmp(name, "module_path")) {
+ CONFIG_IS_DOUBLE(config->module_path);
+ config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "prefer_passphrase_auth")) {
+ config->prefer_passphrase_auth = *(bool *)val;
+ }
+ else if (!strcmp(name, "require_reverse_lookup")) {
+ config->require_reverse_lookup = *(bool *)val;
+ }
+ else if (!strcmp(name, "connections_max")) {
+ config->param.connections_max = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "connections_max_per_host")) {
+ config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "keepalive_secs")) {
+ config->param.keepalive_secs = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "reconnect_count")) {
+ config->param.reconnect_count = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "reconnect_interval")) {
+ config->param.reconnect_interval = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "reconnect_interval_max")) {
+ config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "reconnect_keep_trying")) {
+ config->param.reconnect_keep_trying = *(bool *)val;
+ }
+ else if (!strcmp(name, "key_exchange_rekey")) {
+ config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "key_exchange_pfs")) {
+ config->param.key_exchange_pfs = *(bool *)val;
+ }
+ else if (!strcmp(name, "channel_rekey_secs")) {
+ config->channel_rekey_secs = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "key_exchange_timeout")) {
+ config->key_exchange_timeout = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "conn_auth_timeout")) {
+ config->conn_auth_timeout = (SilcUInt32) *(int *)val;
+ }
+ else if (!strcmp(name, "version_protocol")) {
+ CONFIG_IS_DOUBLE(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 =
+ (*(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 =
+ (*(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 if (!strcmp(name, "channel_join_limit")) {
+ config->param.chlimit = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "debug_string")) {
+ CONFIG_IS_DOUBLE(config->debug_string);
+ config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
- SILC_SERVER_CONFIG_LIST_ALLOC(config->pkcs);
+ return SILC_CONFIG_OK;
- /* Get PKCS name */
- ret = silc_config_get_token(line, &config->pkcs->alg_name);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: PKCS name not defined\n",
- config->filename, pc->linenum);
- break;
- }
+ got_err:
+ return got_errno;
+}
- /* Get key length */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: PKCS key length not defined\n",
- config->filename, pc->linenum);
- break;
- }
- config->pkcs->key_len = atoi(tmp);
- silc_free(tmp);
+SILC_CONFIG_CALLBACK(fetch_cipher)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
+
+ SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
+ type, name, context));
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ /* 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;
+ }
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
- case SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION:
+ /* Identify and save this value */
+ if (!strcmp(name, "name")) {
+ CONFIG_IS_DOUBLE(tmp->name);
+ tmp->name = strdup((char *) val);
+ }
+ else if (!strcmp(name, "module")) {
+ CONFIG_IS_DOUBLE(tmp->module);
+ tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "keylength")) {
+ tmp->key_length = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "blocklength")) {
+ tmp->block_length = *(SilcUInt32 *)val;
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->name);
+ silc_free(tmp->module);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- SILC_SERVER_CONFIG_LIST_ALLOC(config->hash_func);
+SILC_CONFIG_CALLBACK(fetch_hash)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
+
+ SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
+ type, name, context));
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ /* check the temporary struct's fields */
+ 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;
+ }
- /* Get Hash function name */
- ret = silc_config_get_token(line, &config->hash_func->alg_name);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: Hash function name not defined\n",
- config->filename, pc->linenum);
- break;
- }
-
- /* Get Hash function module name */
- config->hash_func->sim_name = NULL;
- ret = silc_config_get_token(line, &config->hash_func->sim_name);
- if (ret < 0)
- break;
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
- /* Get block length */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: Hash function block length not defined\n",
- config->filename, pc->linenum);
- break;
- }
- config->hash_func->block_len = atoi(tmp);
- silc_free(tmp);
+ /* Identify and save this value */
+ if (!strcmp(name, "name")) {
+ CONFIG_IS_DOUBLE(tmp->name);
+ tmp->name = strdup((char *) val);
+ }
+ else if (!strcmp(name, "module")) {
+ CONFIG_IS_DOUBLE(tmp->module);
+ tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "blocklength")) {
+ tmp->block_length = *(int *)val;
+ }
+ else if (!strcmp(name, "digestlength")) {
+ tmp->digest_length = *(int *)val;
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->name);
+ silc_free(tmp->module);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- /* Get hash length */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: Hash function hash length not defined\n",
- config->filename, pc->linenum);
- break;
- }
- config->hash_func->key_len = atoi(tmp);
- silc_free(tmp);
+SILC_CONFIG_CALLBACK(fetch_hmac)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
+
+ SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
+ type, name, context));
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ /* check the temporary struct's fields */
+ 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;
+ }
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
- case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO:
+ /* Identify and save this value */
+ if (!strcmp(name, "name")) {
+ CONFIG_IS_DOUBLE(tmp->name);
+ tmp->name = strdup((char *) val);
+ }
+ else if (!strcmp(name, "hash")) {
+ CONFIG_IS_DOUBLE(tmp->hash);
+ tmp->hash = strdup((char *) val);
+ }
+ else if (!strcmp(name, "maclength")) {
+ tmp->mac_length = *(int *)val;
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->name);
+ silc_free(tmp->hash);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- if (!config->server_info)
- config->server_info = silc_calloc(1, sizeof(*config->server_info));
+SILC_CONFIG_CALLBACK(fetch_pkcs)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
+
+ SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
+ type, name, context));
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ /* 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;
+ }
- /* Get server name */
- ret = silc_config_get_token(line, &config->server_info->server_name);
- if (ret < 0)
- break;
- if (ret == 0) {
- /* Server name not defined */
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
- }
-
- /* Get server IP */
- ret = silc_config_get_token(line, &config->server_info->server_ip);
- if (ret < 0)
- break;
- if (ret == 0) {
- /* Server IP not defined */
+ /* Identify and save this value */
+ if (!strcmp(name, "name")) {
+ CONFIG_IS_DOUBLE(tmp->name);
+ tmp->name = strdup((char *) val);
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->name);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
+SILC_CONFIG_CALLBACK(fetch_serverinfo)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
+ SilcServerConfigServerInfo *server_info = config->server_info;
+
+ SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
+ type, name, context));
+
+ /* If there isn't the main struct alloc it */
+ if (!server_info)
+ config->server_info = server_info = (SilcServerConfigServerInfo *)
+ silc_calloc(1, sizeof(*server_info));
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!strcmp(name, "primary")) {
+ if (server_info->primary) {
+ SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+ "Double primary specification."));
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
}
+ CONFIG_IS_DOUBLE(server_info->primary);
- /* Get server location */
- ret = silc_config_get_token(line, &config->server_info->location);
- if (ret < 0)
- break;
-
- /* Get server port */
- /* XXX: Need port here??? */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- /* Port not defined */
-
+ /* now check the temporary struct, don't accept empty block and
+ make sure all fields are there */
+ if (!tmp || !tmp->server_ip || !tmp->port) {
+ got_errno = SILC_CONFIG_EMISSFIELDS;
+ goto got_err;
}
- config->server_info->port = atoi(tmp);
- silc_free(tmp);
-
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
-
- case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO:
-
- if (!config->admin_info)
- config->admin_info = silc_calloc(1, sizeof(*config->admin_info));
-
- /* Get location */
- ret = silc_config_get_token(line, &config->admin_info->location);
- if (ret < 0)
- break;
-
- /* Get server type */
- ret = silc_config_get_token(line, &config->admin_info->server_type);
- if (ret < 0)
- break;
-
- /* Get admins name */
- ret = silc_config_get_token(line, &config->admin_info->admin_name);
- if (ret < 0)
- break;
-
- /* Get admins email address */
- ret = silc_config_get_token(line, &config->admin_info->admin_email);
- if (ret < 0)
- break;
-
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
-
- case SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT:
-
- SILC_SERVER_CONFIG_LIST_ALLOC(config->listen_port);
-
- /* Get host */
- ret = silc_config_get_token(line, &config->listen_port->host);
- if (ret < 0)
- break;
-
- /* Get remote IP */
- ret = silc_config_get_token(line, &config->listen_port->remote_ip);
- if (ret < 0)
- break;
-
- /* Get port */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- /* Any port */
- config->listen_port->port = 0;
- } else {
- config->listen_port->port = atoi(tmp);
- silc_free(tmp);
+ server_info->primary = tmp;
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ } else if (!strcmp(name, "secondary")) {
+ if (!tmp)
+ return SILC_CONFIG_OK;
+ if (!tmp || !tmp->server_ip || !tmp->port) {
+ got_errno = SILC_CONFIG_EMISSFIELDS;
+ goto got_err;
}
-
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
-
- case SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS:
-
- SILC_SERVER_CONFIG_LIST_ALLOC(config->conn_class);
-
- /* Get class number */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- /* Class number not defined */
-
+ 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;
+ }
+ return SILC_CONFIG_OK;
+ }
+ if (!strcmp(name, "hostname")) {
+ CONFIG_IS_DOUBLE(server_info->server_name);
+ server_info->server_name = strdup((char *) val);
+ }
+ else if (!strcmp(name, "ip")) {
+ 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 while parsing config file: "
+ "Invalid port number!"));
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ tmp->port = (SilcUInt16) port;
+ }
+ else if (!strcmp(name, "servertype")) {
+ CONFIG_IS_DOUBLE(server_info->server_type);
+ server_info->server_type = strdup((char *) val);
+ }
+ else if (!strcmp(name, "admin")) {
+ CONFIG_IS_DOUBLE(server_info->admin);
+ server_info->admin = strdup((char *) val);
+ }
+ else if (!strcmp(name, "adminemail")) {
+ CONFIG_IS_DOUBLE(server_info->email);
+ server_info->email = strdup((char *) val);
+ }
+ else if (!strcmp(name, "location")) {
+ CONFIG_IS_DOUBLE(server_info->location);
+ server_info->location = strdup((char *) val);
+ }
+ else if (!strcmp(name, "user")) {
+ CONFIG_IS_DOUBLE(server_info->user);
+ server_info->user = strdup((char *) val);
+ }
+ else if (!strcmp(name, "group")) {
+ CONFIG_IS_DOUBLE(server_info->group);
+ server_info->group = strdup((char *) val);
+ }
+ else if (!strcmp(name, "motdfile")) {
+ CONFIG_IS_DOUBLE(server_info->motd_file);
+ server_info->motd_file = strdup((char *) val);
+ }
+ else if (!strcmp(name, "pidfile")) {
+ CONFIG_IS_DOUBLE(server_info->pid_file);
+ server_info->pid_file = strdup((char *) val);
+ }
+ 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."));
+ return SILC_CONFIG_EPRINTLINE;
}
- config->conn_class->class = atoi(tmp);
- silc_free(tmp);
-
- /* Get ping frequency */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- config->conn_class->ping_freq = atoi(tmp);
- silc_free(tmp);
-
- /* Get connect frequency */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- config->conn_class->connect_freq = atoi(tmp);
- silc_free(tmp);
+ }
+ else if (!strcmp(name, "privatekey")) {
+ struct stat st;
+ char *file_tmp = (char *) val;
+ CONFIG_IS_DOUBLE(server_info->private_key);
+
+ /* Check the private key file permissions. */
+ if ((stat(file_tmp, &st)) != -1) {
+ if ((st.st_mode & 0777) != 0600) {
+ SILC_SERVER_LOG_ERROR(("Wrong permissions in private key "
+ "file \"%s\". The permissions must be "
+ "0600.", file_tmp));
+ return SILC_CONFIG_ESILENT;
+ }
+ }
- /* Get max links */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- config->conn_class->max_links = atoi(tmp);
- silc_free(tmp);
+ /* Try to load specified file, if fail stop config parsing */
+ if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
+ "", 0, SILC_PKCS_FILE_BIN))
+ if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
+ "", 0, SILC_PKCS_FILE_PEM)) {
+ SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
+ return SILC_CONFIG_EPRINTLINE;
+ }
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ /* Here we need to check if tmp exists because this function handles
+ * misc data (multiple fields and single-only fields) */
+ if (tmp) {
+ silc_free(tmp->server_ip);
+ silc_free(tmp);
+ config->tmp = NULL;
+ }
+ return got_errno;
+}
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+SILC_CONFIG_CALLBACK(fetch_logging)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
- case SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING:
+ 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 while parsing config file: "
+ "Invalid flushdelay value, use quicklogs if you "
+ "want real-time logging."));
+ return SILC_CONFIG_EPRINTLINE;
+ }
+ config->logging_flushdelay = (long) flushdelay;
+ }
- SILC_SERVER_CONFIG_LIST_ALLOC(config->logging);
+ /* 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; \
+ if (!tmp->file) { \
+ got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
+ } \
+ config->__member__ = tmp; \
+ config->tmp = NULL; \
+ }
+ FETCH_LOGGING_CHAN("info", logging_info)
+ FETCH_LOGGING_CHAN("warnings", logging_warnings)
+ FETCH_LOGGING_CHAN("errors", logging_errors)
+ FETCH_LOGGING_CHAN("fatals", logging_fatals)
+#undef FETCH_LOGGING_CHAN
+ else if (!strcmp(name, "file")) {
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
+ CONFIG_IS_DOUBLE(tmp->file);
+ tmp->file = strdup((char *) val);
+ }
+ else if (!strcmp(name, "size")) {
+ if (!tmp) {
+ config->tmp = silc_calloc(1, sizeof(*tmp));
+ tmp = (SilcServerConfigLogging *) config->tmp;
+ }
+ tmp->maxsize = *(SilcUInt32 *) val;
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->file);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- /* Get log section type and check it */
- ret = silc_config_get_token(line, &config->logging->logtype);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: Log file section not defined\n",
- config->filename, pc->linenum);
- break;
- }
- if (strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_INFO)
- && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_WARNING)
- && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_ERROR)
- && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
- fprintf(stderr, "%s:%d: Unknown log file section '%s'\n",
- config->filename, pc->linenum, config->logging->logtype);
- break;
- }
+SILC_CONFIG_CALLBACK(fetch_connparam)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
+
+ SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
+ type, name, context));
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ /* 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);
- /* Get log filename */
- ret = silc_config_get_token(line, &config->logging->filename);
- if (ret < 0)
- break;
- if (ret == 0) {
- fprintf(stderr, "%s:%d: Log file name not defined\n",
- config->filename, pc->linenum);
- break;
- }
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ if (!tmp) {
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
+ tmp->reconnect_keep_trying = TRUE;
+ }
- /* Get max byte size */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- config->logging->maxsize = atoi(tmp);
- silc_free(tmp);
- }
+ if (!strcmp(name, "name")) {
+ CONFIG_IS_DOUBLE(tmp->name);
+ tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "connections_max")) {
+ tmp->connections_max = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "connections_max_per_host")) {
+ tmp->connections_max_per_host = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "keepalive_secs")) {
+ tmp->keepalive_secs = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "reconnect_count")) {
+ tmp->reconnect_count = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "reconnect_interval")) {
+ tmp->reconnect_interval = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "reconnect_interval_max")) {
+ tmp->reconnect_interval_max = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "reconnect_keep_trying")) {
+ tmp->reconnect_keep_trying = *(bool *)val;
+ }
+ else if (!strcmp(name, "key_exchange_rekey")) {
+ tmp->key_exchange_rekey = *(SilcUInt32 *)val;
+ }
+ else if (!strcmp(name, "key_exchange_pfs")) {
+ tmp->key_exchange_pfs = *(bool *)val;
+ }
+ else if (!strcmp(name, "version_protocol")) {
+ CONFIG_IS_DOUBLE(tmp->version_protocol);
+ tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "version_software")) {
+ CONFIG_IS_DOUBLE(tmp->version_software);
+ tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "version_software_vendor")) {
+ CONFIG_IS_DOUBLE(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;
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+ return SILC_CONFIG_OK;
- case SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION:
+ got_err:
+ silc_free(tmp->name);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- SILC_SERVER_CONFIG_LIST_ALLOC(config->clients);
+SILC_CONFIG_CALLBACK(fetch_client)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
- /* Get host */
- ret = silc_config_get_token(line, &config->clients->host);
- if (ret < 0)
- break;
- if (ret == 0)
- /* Any host */
- config->clients->host = strdup("*");
+ SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
+ type, name, context));
- /* Get authentication method */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
- strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
- fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
- config->filename, pc->linenum, tmp);
- break;
- }
+ /* Alloc before block checking, because empty sub-blocks are welcome here */
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
- if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
- config->clients->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ /* empty sub-blocks are welcome */
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
- if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
- config->clients->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+ /* Identify and save this value */
+ if (!strcmp(name, "host")) {
+ CONFIG_IS_DOUBLE(tmp->host);
+ tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "passphrase")) {
+ CONFIG_IS_DOUBLE(tmp->passphrase);
+ if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
+ (void *)&tmp->passphrase,
+ &tmp->passphrase_len)) {
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ }
+ else if (!strcmp(name, "publickey")) {
+ if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
+ (void *)&tmp->publickeys, NULL)) {
+ 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);
+ if (!tmp->param) { /* error message already output */
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->host);
+ CONFIG_FREE_AUTH(tmp);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- silc_free(tmp);
- }
+SILC_CONFIG_CALLBACK(fetch_admin)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
+
+ 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) /* discard empty sub-blocks */
+ return SILC_CONFIG_OK;
+
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
- /* Get authentication data */
- ret = silc_config_get_token(line, &config->clients->auth_data);
- if (ret < 0)
- break;
- if (ret == 0)
- /* Any host */
- config->clients->host = strdup("*");
+ /* Identify and save this value */
+ if (!strcmp(name, "host")) {
+ CONFIG_IS_DOUBLE(tmp->host);
+ tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "user")) {
+ CONFIG_IS_DOUBLE(tmp->user);
+ tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "nick")) {
+ CONFIG_IS_DOUBLE(tmp->nick);
+ tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "passphrase")) {
+ CONFIG_IS_DOUBLE(tmp->passphrase);
+ if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
+ (void *)&tmp->passphrase,
+ &tmp->passphrase_len)) {
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ }
+ else if (!strcmp(name, "publickey")) {
+ if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
+ (void *)&tmp->publickeys, NULL)) {
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->host);
+ silc_free(tmp->user);
+ silc_free(tmp->nick);
+ CONFIG_FREE_AUTH(tmp);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- /* Get port */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret == 0) {
- config->clients->port = atoi(tmp);
- silc_free(tmp);
- }
+SILC_CONFIG_CALLBACK(fetch_deny)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
+
+ SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
+ type, name, context));
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ /* check the temporary struct's fields */
+ if (!tmp) /* discard empty sub-blocks */
+ return SILC_CONFIG_OK;
+ if (!tmp->reason) {
+ got_errno = SILC_CONFIG_EMISSFIELDS;
+ goto got_err;
+ }
- /* Get class number */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- config->clients->class = atoi(tmp);
- silc_free(tmp);
- }
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+ /* Identify and save this value */
+ if (!strcmp(name, "host")) {
+ CONFIG_IS_DOUBLE(tmp->host);
+ tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
+ }
+ else if (!strcmp(name, "reason")) {
+ CONFIG_IS_DOUBLE(tmp->reason);
+ tmp->reason = strdup((char *) val);
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->host);
+ silc_free(tmp->reason);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION:
+SILC_CONFIG_CALLBACK(fetch_server)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
+
+ 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) /* discard empty sub-blocks */
+ return SILC_CONFIG_OK;
+ if (!tmp->host) {
+ got_errno = SILC_CONFIG_EMISSFIELDS;
+ goto got_err;
+ }
- SILC_SERVER_CONFIG_LIST_ALLOC(config->servers);
+ /* the temporary struct is ok, append it to the list */
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
- /* Get host */
- ret = silc_config_get_token(line, &config->servers->host);
- if (ret < 0)
- break;
- if (ret == 0)
- /* Any host */
- config->servers->host = strdup("*");
+ /* Identify and save this value */
+ if (!strcmp(name, "host")) {
+ CONFIG_IS_DOUBLE(tmp->host);
+ tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
+ }
+ else if (!strcmp(name, "passphrase")) {
+ CONFIG_IS_DOUBLE(tmp->passphrase);
+ if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
+ (void *)&tmp->passphrase,
+ &tmp->passphrase_len)) {
+ 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,
+ (void *)&tmp->publickeys, NULL)) {
+ 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);
+ if (!tmp->param) { /* error message already output */
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ }
+ else if (!strcmp(name, "backup")) {
+ tmp->backup_router = *(bool *)val;
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
- /* Get authentication method */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
- strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
- fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
- config->filename, pc->linenum, tmp);
- break;
- }
+ return SILC_CONFIG_OK;
- if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
- config->servers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+ got_err:
+ silc_free(tmp->host);
+ CONFIG_FREE_AUTH(tmp);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
- config->servers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+SILC_CONFIG_CALLBACK(fetch_router)
+{
+ SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
+
+ SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
+ type, name, context));
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!tmp) /* discard empty sub-blocks */
+ return SILC_CONFIG_OK;
+ if (!tmp->host) {
+ got_errno = SILC_CONFIG_EMISSFIELDS;
+ goto got_err;
+ }
- silc_free(tmp);
- }
+ SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
+ config->tmp = NULL;
+ return SILC_CONFIG_OK;
+ }
+ SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
- /* Get authentication data */
- ret = silc_config_get_token(line, &config->servers->auth_data);
- if (ret < 0)
- break;
+ /* Identify and save this value */
+ if (!strcmp(name, "host")) {
+ CONFIG_IS_DOUBLE(tmp->host);
+ tmp->host = strdup((char *) val);
+ }
+ else if (!strcmp(name, "port")) {
+ int port = *(int *)val;
+ if ((port <= 0) || (port > 65535)) {
+ 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,
+ (void *)&tmp->passphrase,
+ &tmp->passphrase_len)) {
+ 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,
+ (void *)&tmp->publickeys, NULL)) {
+ 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);
+ if (!tmp->param) { /* error message already output */
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ }
+ else if (!strcmp(name, "initiator")) {
+ tmp->initiator = *(bool *)val;
+ }
+ else if (!strcmp(name, "backuphost")) {
+ 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 while parsing config file: "
+ "Invalid port number!"));
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ tmp->backup_replace_port = (SilcUInt16) port;
+ }
+ else if (!strcmp(name, "backuplocal")) {
+ tmp->backup_local = *(bool *)val;
+ }
+ else
+ return SILC_CONFIG_EINTERNAL;
+
+ return SILC_CONFIG_OK;
+
+ got_err:
+ silc_free(tmp->host);
+ silc_free(tmp->backup_replace_ip);
+ CONFIG_FREE_AUTH(tmp);
+ silc_free(tmp);
+ config->tmp = NULL;
+ return got_errno;
+}
- /* Get port */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- config->servers->port = atoi(tmp);
- silc_free(tmp);
- }
+/* known config options tables */
+static const SilcConfigTable table_general[] = {
+ { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
+ { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
+ { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
+ { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
+ { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
+ { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
+ { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
+ { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
+ { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
+ { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
+ { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
+ { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
+ { "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 },
+ { "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 },
+ { "channel_join_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
+ { "debug_string", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
+ { 0, 0, 0, 0 }
+};
- /* Get version */
- ret = silc_config_get_token(line, &config->servers->version);
- if (ret < 0)
- break;
+static const SilcConfigTable table_cipher[] = {
+ { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
+ { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
+ { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
+ { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
+ { 0, 0, 0, 0 }
+};
- /* Get class number */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- config->servers->class = atoi(tmp);
- silc_free(tmp);
- }
+static const SilcConfigTable table_hash[] = {
+ { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
+ { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
+ { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
+ { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
+ { 0, 0, 0, 0 }
+};
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+static const SilcConfigTable table_hmac[] = {
+ { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
+ { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
+ { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
+ { 0, 0, 0, 0 }
+};
- case SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION:
+static const SilcConfigTable table_pkcs[] = {
+ { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
+ { 0, 0, 0, 0 }
+};
- SILC_SERVER_CONFIG_LIST_ALLOC(config->routers);
+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 }
+};
- /* Get host */
- ret = silc_config_get_token(line, &config->routers->host);
- if (ret < 0)
- break;
- // if (ret == 0)
- ///* Any host */
- // config->routers->host = strdup("*");
+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},
+ { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
+ { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
+ { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
+ { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
+ { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
+ { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
+ { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
+ { 0, 0, 0, 0 }
+};
- /* Get authentication method */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
- strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
- fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
- config->filename, pc->linenum, tmp);
- break;
- }
+static const SilcConfigTable table_logging_c[] = {
+ { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
+ { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
+/*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
+ { 0, 0, 0, 0 }
+};
- if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
- config->routers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+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 },
+ { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
+ { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
+ { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
+ { 0, 0, 0, 0 }
+};
- if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
- config->routers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+static const SilcConfigTable table_connparam[] = {
+ { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
+ { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
+ { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
+ { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
+ { "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_connparam, NULL },
+ { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
+ { 0, 0, 0, 0 }
+};
- silc_free(tmp);
- }
+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 }
+};
- /* Get authentication data */
- ret = silc_config_get_token(line, &config->routers->auth_data);
- if (ret < 0)
- break;
+static const SilcConfigTable table_admin[] = {
+ { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
+ { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
+ { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
+ { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
+ { "publickey", 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 }
+};
- /* Get port */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- config->routers->port = atoi(tmp);
- silc_free(tmp);
- }
+static const SilcConfigTable table_deny[] = {
+ { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
+ { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
+ { 0, 0, 0, 0 }
+};
- /* Get version */
- ret = silc_config_get_token(line, &config->routers->version);
- if (ret < 0)
- break;
+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 },
+ { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
+ { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
+ { 0, 0, 0, 0 }
+};
- /* Get class number */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- config->routers->class = atoi(tmp);
- silc_free(tmp);
- }
+static const SilcConfigTable table_routerconn[] = {
+ { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
+ { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
+ { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
+ { "publickey", 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 },
+ { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
+ { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
+ { 0, 0, 0, 0 }
+};
- /* Get whether we are initiator or not */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- config->routers->initiator = atoi(tmp);
- if (config->routers->initiator != 0)
- config->routers->initiator = TRUE;
- silc_free(tmp);
- }
+static const SilcConfigTable table_main[] = {
+ { "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 },
+ { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
+ { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
+ { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
+ { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
+ { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
+ { 0, 0, 0, 0 }
+};
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+/* Set default values to stuff that was not configured. */
- case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION:
+static void silc_server_config_set_defaults(SilcServerConfig config)
+{
+ my_set_param_defaults(&config->param, NULL);
+
+ config->channel_rekey_secs = (config->channel_rekey_secs ?
+ config->channel_rekey_secs :
+ SILC_SERVER_CHANNEL_REKEY);
+ config->key_exchange_timeout = (config->key_exchange_timeout ?
+ config->key_exchange_timeout :
+ SILC_SERVER_SKE_TIMEOUT);
+ config->conn_auth_timeout = (config->conn_auth_timeout ?
+ config->conn_auth_timeout :
+ SILC_SERVER_CONNAUTH_TIMEOUT);
+}
- SILC_SERVER_CONFIG_LIST_ALLOC(config->admins);
+/* Check for correctness of the configuration */
- /* Get host */
- ret = silc_config_get_token(line, &config->admins->host);
- if (ret < 0)
- break;
- if (ret == 0)
- /* Any host */
- config->admins->host = strdup("*");
+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;
+ }
- /* Get authentication method */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
- strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
- fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
- config->filename, pc->linenum, tmp);
- break;
- }
+ /* RouterConnection sanity checks */
- if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
- config->admins->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+ 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 0
+ 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;
+ }
+#endif
+ 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;
+ }
- if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
- config->admins->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+ /* Backup router sanity checks */
- silc_free(tmp);
- }
+ 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;
+ }
- /* Get authentication data */
- ret = silc_config_get_token(line, &config->admins->auth_data);
- if (ret < 0)
- break;
+ if (r->initiator == FALSE && r->port != 0) {
+ SILC_SERVER_LOG_WARNING(("\nWarning: Initiator is FALSE and Port is "
+ "specified. Ignoring Port value."));
+ r->port = 0;
+ }
+ }
- /* Get nickname */
- ret = silc_config_get_token(line, &config->admins->nickname);
- if (ret < 0)
- break;
+ /* ServerConnection sanity checks */
- /* Get class number */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
+ 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;
- if (ret) {
- config->admins->class = atoi(tmp);
- silc_free(tmp);
}
+ }
+ }
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+ return ret;
+}
- case SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION:
- /* Not implemented yet */
- check = TRUE;
- break;
+/* 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
+ the silc_server_config_destroy function. */
- case SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT:
- /* Not implemented yet */
- check = TRUE;
- break;
+SilcServerConfig silc_server_config_alloc(const char *filename)
+{
+ SilcServerConfig config_new;
+ SilcConfigEntity ent;
+ SilcConfigFile *file;
+ int ret;
+ SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
+
+ /* alloc a config object */
+ config_new = silc_calloc(1, sizeof(*config_new));
+ if (!config_new)
+ return NULL;
- case SILC_CONFIG_SERVER_SECTION_TYPE_MOTD:
+ /* general config defaults */
+ config_new->refcount = 1;
+ config_new->logging_timestamp = TRUE;
+ config_new->param.reconnect_keep_trying = TRUE;
- if (!config->motd)
- config->motd = silc_calloc(1, sizeof(*config->motd));
+ /* obtain a config file object */
+ file = silc_config_open(filename);
+ if (!file) {
+ SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
+ filename));
+ return NULL;
+ }
- /* Get motd file */
- ret = silc_config_get_token(line, &config->motd->motd_file);
- if (ret < 0)
- break;
+ /* obtain a SilcConfig entity, we can use it to start the parsing */
+ ent = silc_config_init(file);
+
+ /* load the known configuration options, give our empty object as context */
+ silc_config_register_table(ent, table_main, (void *) config_new);
+
+ /* enter the main parsing loop. When this returns, we have the parsing
+ * result and the object filled (or partially, in case of errors). */
+ ret = silc_config_main(ent);
+ SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
+ silc_config_strerror(ret)));
+
+ /* Check if the parser returned errors */
+ if (ret) {
+ /* handle this special error return which asks to quietly return */
+ if (ret != SILC_CONFIG_ESILENT) {
+ char *linebuf, *filename = silc_config_get_filename(file);
+ SilcUInt32 line = silc_config_get_line(file);
+ 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);
+ if (linebuf) {
+ SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
+ line, linebuf));
+ silc_free(linebuf);
+ }
+ }
+ silc_server_config_destroy(config_new);
+ silc_config_close(file);
+ return NULL;
+ }
- check = TRUE;
- checkmask |= (1L << pc->section->type);
- break;
+ /* close (destroy) the file object */
+ silc_config_close(file);
- case SILC_CONFIG_SERVER_SECTION_TYPE_NONE:
- default:
- /* Error */
- break;
- }
+ /* Check the configuration */
+ if (!silc_server_config_check(config_new)) {
+ silc_server_config_destroy(config_new);
+ return NULL;
+ }
- /* Check for error */
- if (check == FALSE) {
- /* Line could not be parsed */
- fprintf(stderr, "%s:%d: Parse error\n", config->filename, pc->linenum);
- break;
- }
+ /* Set default to configuration parameters */
+ silc_server_config_set_defaults(config_new);
- pc = pc->next;
- /* XXXX */
- // silc_free(pc->prev);
- // pc->prev = NULL;
- }
-
- if (check == FALSE)
- return FALSE;;
-
- /* Check that all mandatory sections really were found. If not, the server
- cannot function and we return error. */
- ret = silc_config_server_check_sections(checkmask);
- if (ret == FALSE) {
- /* XXX */
-
- }
-
- /* Before returning all the lists in the config object must be set
- to their first values (the last value is first here). */
- while (config->cipher && config->cipher->prev)
- config->cipher = config->cipher->prev;
- while (config->pkcs && config->pkcs->prev)
- config->pkcs = config->pkcs->prev;
- while (config->hash_func && config->hash_func->prev)
- config->hash_func = config->hash_func->prev;
- while (config->listen_port && config->listen_port->prev)
- config->listen_port = config->listen_port->prev;
- while (config->logging && config->logging->prev)
- config->logging = config->logging->prev;
- while (config->conn_class && config->conn_class->prev)
- config->conn_class = config->conn_class->prev;
- while (config->clients && config->clients->prev)
- config->clients = config->clients->prev;
- while (config->servers && config->servers->prev)
- config->servers = config->servers->prev;
- while (config->routers && config->routers->prev)
- config->routers = config->routers->prev;
-
- SILC_LOG_DEBUG(("Done"));
-
- return TRUE;
+ return config_new;
}
-/* This function checks that the mask sent as argument includes all the
- sections that are mandatory in SILC server. */
+/* Increments the reference counter of a config object */
-int silc_config_server_check_sections(unsigned int checkmask)
+void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
+ void *ref_ptr)
{
- if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO))) {
-
- return FALSE;
- }
- if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO))) {
-
- return FALSE;
- }
- if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT))) {
-
- return FALSE;
- }
- if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
-
- return FALSE;
- }
- if (!(checkmask
- & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION))) {
-
- return FALSE;
- }
- if (!(checkmask
- & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION))) {
-
- return FALSE;
+ if (ref_ptr) {
+ config->refcount++;
+ ref->config = config;
+ ref->ref_ptr = ref_ptr;
+ SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
+ config->refcount - 1, config->refcount));
}
+}
- return TRUE;
+/* Decrements the reference counter of a config object. If the counter
+ reaches 0, the config object is destroyed. */
+
+void silc_server_config_unref(SilcServerConfigRef *ref)
+{
+ if (ref->ref_ptr)
+ silc_server_config_destroy(ref->config);
}
-/* Sets log files where log messages is saved by the server. */
+/* Destroy a config object with all his children lists */
-void silc_config_server_setlogfiles(SilcConfigServer config)
+void silc_server_config_destroy(SilcServerConfig config)
{
- SilcConfigServerSectionLogging *log;
- char *info, *warning, *error, *fatal;
- unsigned int info_size, warning_size, error_size, fatal_size;
-
- SILC_LOG_DEBUG(("Setting configured log file names"));
-
- /* Set default files before checking configuration */
- info = SILC_LOG_FILE_INFO;
- warning = SILC_LOG_FILE_WARNING;
- error = SILC_LOG_FILE_ERROR;
- fatal = SILC_LOG_FILE_FATAL;
- info_size = 0;
- warning_size = 0;
- error_size = 0;
- fatal_size = 0;
-
- log = config->logging;
- while(log) {
- if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO)) {
- info = log->filename;
- info_size = log->maxsize;
- }
- if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING)) {
- warning = log->filename;
- warning_size = log->maxsize;
+ 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->debug_string);
+ 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)
+ silc_free(config->logging_info->file);
+ if (config->logging_warnings)
+ silc_free(config->logging_warnings->file);
+ if (config->logging_errors)
+ 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);
+ if (si->primary) {
+ silc_free(si->primary->server_ip);
+ silc_free(si->primary);
}
- if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR)) {
- error = log->filename;
- error_size = log->maxsize;
- }
- if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
- fatal = log->filename;
- fatal_size = log->maxsize;
+ 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);
+ silc_free(si->email);
+ silc_free(si->user);
+ silc_free(si->group);
+ silc_free(si->motd_file);
+ silc_free(si->pid_file);
+ silc_pkcs_public_key_free(si->public_key);
+ silc_pkcs_private_key_free(si->private_key);
+ silc_free(si);
+ }
- log = log->next;
+ /* Now let's destroy the lists */
+
+ SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
+ config->cipher)
+ silc_free(di->name);
+ silc_free(di->module);
+ silc_free(di);
+ }
+ SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
+ silc_free(di->name);
+ silc_free(di->module);
+ silc_free(di);
+ }
+ SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
+ silc_free(di->name);
+ silc_free(di->hash);
+ silc_free(di);
+ }
+ SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
+ silc_free(di->name);
+ silc_free(di);
+ }
+ 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);
+ }
+ SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
+ silc_free(di->host);
+ silc_free(di->user);
+ silc_free(di->nick);
+ CONFIG_FREE_AUTH(di);
+ silc_free(di);
+ }
+ SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
+ silc_free(di->host);
+ silc_free(di->reason);
+ silc_free(di);
+ }
+ SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
+ config->servers)
+ silc_free(di->host);
+ CONFIG_FREE_AUTH(di);
+ silc_free(di);
+ }
+ SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
+ config->routers)
+ silc_free(di->host);
+ silc_free(di->backup_replace_ip);
+ CONFIG_FREE_AUTH(di);
+ silc_free(di);
}
- silc_log_set_files(info, info_size, warning, warning_size,
- error, error_size, fatal, fatal_size);
+ memset(config, 'F', sizeof(*config));
+ silc_free(config);
}
/* Registers configured ciphers. These can then be allocated by the
server when needed. */
-void silc_config_server_register_ciphers(SilcConfigServer config)
+bool silc_server_config_register_ciphers(SilcServer server)
{
- SilcConfigServerSectionAlg *alg;
- SilcServer server = (SilcServer)config->server;
+ SilcServerConfig config = server->config;
+ SilcServerConfigCipher *cipher = config->cipher;
+ char *module_path = config->module_path;
SILC_LOG_DEBUG(("Registering configured ciphers"));
- alg = config->cipher;
- while(alg) {
-
- if (!alg->sim_name) {
- /* Crypto module is supposed to be built in. Nothing to be done
- here except to test that the cipher really is built in. */
- SilcCipher tmp = NULL;
+ if (!cipher) /* any cipher in the config file? */
+ return FALSE;
- if (silc_cipher_alloc(alg->alg_name, &tmp) == FALSE) {
- SILC_LOG_ERROR(("Unsupported cipher `%s'", alg->alg_name));
+ while (cipher) {
+ /* if there isn't a module_path OR there isn't a module sim name try to
+ * use buil-in functions */
+ if (!module_path || !cipher->module) {
+ int i;
+ for (i = 0; silc_default_ciphers[i].name; i++)
+ if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
+ silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
+ break;
+ }
+ if (!silc_cipher_is_supported(cipher->name)) {
+ SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
silc_server_stop(server);
exit(1);
}
- silc_cipher_free(tmp);
-
-#ifdef SILC_SIM
} else {
+#ifdef SILC_SIM
/* Load (try at least) the crypto SIM module */
- SilcCipherObject cipher;
- SilcSimContext *sim;
-
- memset(&cipher, 0, sizeof(cipher));
- cipher.name = alg->alg_name;
- cipher.block_len = alg->block_len;
- cipher.key_len = alg->key_len * 8;
-
- sim = silc_sim_alloc();
- sim->type = SILC_SIM_CIPHER;
- sim->libname = alg->sim_name;
-
- if ((silc_sim_load(sim))) {
- cipher.set_key =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ char buf[1023], *alg_name;
+ SilcCipherObject cipher_obj;
+ SilcSim sim;
+
+ memset(&cipher_obj, 0, sizeof(cipher_obj));
+ cipher_obj.name = cipher->name;
+ cipher_obj.block_len = cipher->block_length;
+ cipher_obj.key_len = cipher->key_length * 8;
+
+ /* build the libname */
+ snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
+ cipher->module);
+ sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
+
+ alg_name = strdup(cipher->name);
+ if (strchr(alg_name, '-'))
+ *strchr(alg_name, '-') = '\0';
+
+ if (silc_sim_load(sim)) {
+ cipher_obj.set_key =
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_SET_KEY));
- SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
- cipher.set_key_with_string =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
- SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
- SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
- cipher.encrypt =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
+ cipher_obj.set_key_with_string =
+ silc_sim_getsym(sim,
+ silc_sim_symname(alg_name,
+ SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
+ SILC_LOG_DEBUG(("set_key_with_string=%p",
+ cipher_obj.set_key_with_string));
+ cipher_obj.encrypt =
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_ENCRYPT_CBC));
- SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
- cipher.decrypt =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
+ cipher_obj.decrypt =
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_DECRYPT_CBC));
- SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
- cipher.context_len =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
+ cipher_obj.context_len =
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_CONTEXT_LEN));
- SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
+ SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
/* Put the SIM to the list of all SIM's in server */
silc_dlist_add(server->sim, sim);
+
+ silc_free(alg_name);
} else {
SILC_LOG_ERROR(("Error configuring ciphers"));
+ silc_sim_free(sim);
silc_server_stop(server);
exit(1);
}
/* Register the cipher */
- silc_cipher_register(&cipher);
-#endif
- }
-
- alg = alg->next;
- }
-}
-
-/* Registers configured PKCS's. */
-/* XXX: This really doesn't do anything now since we have statically
- registered our PKCS's. This should be implemented when PKCS works
- as SIM's. This checks now only that the PKCS user requested is
- really out there. */
-
-void silc_config_server_register_pkcs(SilcConfigServer config)
-{
- SilcConfigServerSectionAlg *alg = config->pkcs;
- SilcServer server = (SilcServer)config->server;
- SilcPKCS tmp = NULL;
-
- SILC_LOG_DEBUG(("Registering configured PKCS"));
-
- while(alg) {
-
- if (silc_pkcs_alloc(alg->alg_name, &tmp) == FALSE) {
- SILC_LOG_ERROR(("Unsupported PKCS `%s'", alg->alg_name));
+ silc_cipher_register(&cipher_obj);
+#else
+ SILC_LOG_ERROR(("Dynamic module support not compiled, "
+ "can't load modules!"));
silc_server_stop(server);
exit(1);
+#endif
}
- silc_free(tmp);
+ cipher = cipher->next;
+ } /* while */
- alg = alg->next;
- }
+ return TRUE;
}
/* Registers configured hash functions. These can then be allocated by the
server when needed. */
-void silc_config_server_register_hashfuncs(SilcConfigServer config)
+bool silc_server_config_register_hashfuncs(SilcServer server)
{
- SilcConfigServerSectionAlg *alg;
- SilcServer server = (SilcServer)config->server;
+ SilcServerConfig config = server->config;
+ SilcServerConfigHash *hash = config->hash;
+ char *module_path = config->module_path;
SILC_LOG_DEBUG(("Registering configured hash functions"));
- alg = config->hash_func;
- while(alg) {
-
- if (!alg->sim_name) {
- /* Hash module is supposed to be built in. Nothing to be done
- here except to test that the hash function really is built in. */
- SilcHash tmp = NULL;
+ if (!hash) /* any hash func in the config file? */
+ return FALSE;
- if (silc_hash_alloc(alg->alg_name, &tmp) == FALSE) {
- SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->alg_name));
+ while (hash) {
+ /* if there isn't a module_path OR there isn't a module sim name try to
+ * use buil-in functions */
+ if (!module_path || !hash->module) {
+ int i;
+ for (i = 0; silc_default_hash[i].name; i++)
+ if (!strcmp(silc_default_hash[i].name, hash->name)) {
+ silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
+ break;
+ }
+ if (!silc_hash_is_supported(hash->name)) {
+ SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
silc_server_stop(server);
exit(1);
}
- silc_free(tmp);
-
-#ifdef SILC_SIM
} else {
+#ifdef SILC_SIM
/* Load (try at least) the hash SIM module */
- SilcHashObject hash;
- SilcSimContext *sim;
+ SilcHashObject hash_obj;
+ SilcSim sim;
- memset(&hash, 0, sizeof(hash));
- hash.name = alg->alg_name;
- hash.block_len = alg->block_len;
- hash.hash_len = alg->key_len;
+ memset(&hash_obj, 0, sizeof(hash_obj));
+ hash_obj.name = hash->name;
+ hash_obj.block_len = hash->block_length;
+ hash_obj.hash_len = hash->digest_length;
- sim = silc_sim_alloc();
- sim->type = SILC_SIM_HASH;
- sim->libname = alg->sim_name;
+ sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
if ((silc_sim_load(sim))) {
- hash.init =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ hash_obj.init =
+ silc_sim_getsym(sim, silc_sim_symname(hash->name,
SILC_HASH_SIM_INIT));
- SILC_LOG_DEBUG(("init=%p", hash.init));
- hash.update =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ SILC_LOG_DEBUG(("init=%p", hash_obj.init));
+ hash_obj.update =
+ silc_sim_getsym(sim, silc_sim_symname(hash->name,
SILC_HASH_SIM_UPDATE));
- SILC_LOG_DEBUG(("update=%p", hash.update));
- hash.final =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ SILC_LOG_DEBUG(("update=%p", hash_obj.update));
+ hash_obj.final =
+ silc_sim_getsym(sim, silc_sim_symname(hash->name,
SILC_HASH_SIM_FINAL));
- SILC_LOG_DEBUG(("final=%p", hash.final));
- hash.context_len =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ SILC_LOG_DEBUG(("final=%p", hash_obj.final));
+ hash_obj.context_len =
+ silc_sim_getsym(sim, silc_sim_symname(hash->name,
SILC_HASH_SIM_CONTEXT_LEN));
- SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
+ SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
/* Put the SIM to the table of all SIM's in 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);
}
- /* Register the cipher */
- silc_hash_register(&hash);
+ /* Register the hash function */
+ silc_hash_register(&hash_obj);
+#else
+ SILC_LOG_ERROR(("Dynamic module support not compiled, "
+ "can't load modules!"));
+ silc_server_stop(server);
+ exit(1);
#endif
}
+ hash = hash->next;
+ } /* while */
- alg = alg->next;
- }
+ return TRUE;
}
-/* Returns client authentication information from server configuration
- by host (name or ip). */
+/* Registers configure HMACs. These can then be allocated by the server
+ when needed. */
-SilcConfigServerSectionClientConnection *
-silc_config_server_find_client_conn(SilcConfigServer config,
- char *host, int port)
+bool silc_server_config_register_hmacs(SilcServer server)
{
- int i;
- SilcConfigServerSectionClientConnection *client = NULL;
+ SilcServerConfig config = server->config;
+ SilcServerConfigHmac *hmac = config->hmac;
- if (!host)
- return NULL;
+ SILC_LOG_DEBUG(("Registering configured HMACs"));
+
+ if (!hmac)
+ return FALSE;
+
+ while (hmac) {
+ SilcHmacObject hmac_obj;
+ if (!silc_hash_is_supported(hmac->hash)) {
+ SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
+ silc_server_stop(server);
+ exit(1);
+ }
+
+ /* Register the HMAC */
+ memset(&hmac_obj, 0, sizeof(hmac_obj));
+ hmac_obj.name = hmac->name;
+ hmac_obj.len = hmac->mac_length;
+ silc_hmac_register(&hmac_obj);
+
+ hmac = hmac->next;
+ } /* while */
+
+ return TRUE;
+}
+
+/* Registers configured PKCS's. */
+
+bool silc_server_config_register_pkcs(SilcServer server)
+{
+ SilcServerConfig config = server->config;
+ SilcServerConfigPkcs *pkcs = config->pkcs;
+
+ SILC_LOG_DEBUG(("Registering configured PKCS"));
+
+ if (!pkcs)
+ return FALSE;
+
+ while (pkcs) {
+ int i;
+ for (i = 0; silc_default_pkcs[i].name; i++)
+ if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
+ silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
+ break;
+ }
+ if (!silc_pkcs_is_supported(pkcs->name)) {
+ SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
+ silc_server_stop(server);
+ exit(1);
+ }
+ pkcs = pkcs->next;
+ } /* while */
+
+ return TRUE;
+}
+
+/* Sets log files where log messages are saved by the server logger. */
+
+void silc_server_config_setlogfiles(SilcServer server)
+{
+ SilcServerConfig config = server->config;
+ SilcServerConfigLogging *this;
+
+ 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 ?
+ config->logging_flushdelay :
+ SILC_SERVER_LOG_FLUSH_DELAY);
+
+ if ((this = config->logging_fatals))
+ silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
+ server->schedule);
+ if ((this = config->logging_errors))
+ silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
+ server->schedule);
+ if ((this = config->logging_warnings))
+ silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
+ server->schedule);
+ if ((this = config->logging_info))
+ silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
+ server->schedule);
+}
+
+/* Returns client authentication information from configuration file by host
+ (name or ip) */
+
+SilcServerConfigClient *
+silc_server_config_find_client(SilcServer server, char *host)
+{
+ SilcServerConfig config = server->config;
+ SilcServerConfigClient *client;
- if (!config->clients)
+ if (!config || !host)
return NULL;
- client = config->clients;
+ for (client = config->clients; client; client = client->next) {
+ if (client->host && !silc_string_compare(client->host, host))
+ continue;
+ break;
+ }
- for (i = 0; client; i++) {
- if (silc_string_compare(client->host, host))
- break;
- client = client->next;
+ /* if none matched, then client is already NULL */
+ return client;
+}
+
+/* Returns admin connection configuration by host, username and/or
+ nickname. */
+
+SilcServerConfigAdmin *
+silc_server_config_find_admin(SilcServer server, char *host, char *user,
+ char *nick)
+{
+ SilcServerConfig config = server->config;
+ SilcServerConfigAdmin *admin;
+
+ /* make sure we have a value for the matching parameters */
+ if (!host)
+ host = "*";
+ if (!user)
+ user = "*";
+ if (!nick)
+ nick = "*";
+
+ for (admin = config->admins; admin; admin = admin->next) {
+ if (admin->host && !silc_string_compare(admin->host, host))
+ continue;
+ if (admin->user && !silc_string_compare(admin->user, user))
+ continue;
+ if (admin->nick && !silc_string_compare(admin->nick, nick))
+ continue;
+ /* no checks failed -> this entry matches */
+ break;
}
- if (!client)
+ /* if none matched, then admin is already NULL */
+ return admin;
+}
+
+/* Returns the denied connection configuration entry by host. */
+
+SilcServerConfigDeny *
+silc_server_config_find_denied(SilcServer server, char *host)
+{
+ SilcServerConfig config = server->config;
+ SilcServerConfigDeny *deny;
+
+ /* make sure we have a value for the matching parameters */
+ if (!config || !host)
return NULL;
- return client;
+ for (deny = config->denied; deny; deny = deny->next) {
+ if (deny->host && !silc_string_compare(deny->host, host))
+ continue;
+ break;
+ }
+
+ /* if none matched, then deny is already NULL */
+ return deny;
}
-/* Returns server connection info from server configuartion by host
+/* Returns server connection info from server configuartion by host
(name or ip). */
-SilcConfigServerSectionServerConnection *
-silc_config_server_find_server_conn(SilcConfigServer config,
- char *host, int port)
+SilcServerConfigServer *
+silc_server_config_find_server_conn(SilcServer server, char *host)
{
- int i;
- SilcConfigServerSectionServerConnection *serv = NULL;
+ SilcServerConfig config = server->config;
+ SilcServerConfigServer *serv = NULL;
if (!host)
return NULL;
if (!config->servers)
return NULL;
- serv = config->servers;
- for (i = 0; serv; i++) {
- if (silc_string_compare(serv->host, host))
- break;
- serv = serv->next;
+ for (serv = config->servers; serv; serv = serv->next) {
+ if (!silc_string_compare(serv->host, host))
+ continue;
+ break;
}
- if (!serv)
- return NULL;
-
return serv;
}
-/* Returns router connection info from server configuartion by
+/* Returns router connection info from server configuration by
host (name or ip). */
-SilcConfigServerSectionServerConnection *
-silc_config_server_find_router_conn(SilcConfigServer config,
- char *host, int port)
+SilcServerConfigRouter *
+silc_server_config_find_router_conn(SilcServer server, char *host, int port)
{
- int i;
- SilcConfigServerSectionServerConnection *serv = NULL;
+ SilcServerConfig config = server->config;
+ SilcServerConfigRouter *serv = NULL;
if (!host)
return NULL;
if (!config->routers)
return NULL;
- serv = config->routers;
- for (i = 0; serv; i++) {
- if (silc_string_compare(serv->host, host))
- break;
- serv = serv->next;
+ for (serv = config->routers; serv; serv = serv->next) {
+ if (!silc_string_compare(serv->host, host))
+ continue;
+ if (port && serv->port && serv->port != port)
+ continue;
+ break;
}
- if (!serv)
+ 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;
}
-/* Prints out example configuration file with default built in
- configuration values. */
+/* Returns TRUE if configuration for a router connection that we are
+ initiating exists. */
-void silc_config_server_print()
+bool silc_server_config_is_primary_route(SilcServer server)
{
- char *buf;
-
- buf = "\
-#\n\
-# Automatically generated example SILCd configuration file with default\n\
-# built in values. Use this as a guide to configure your SILCd configuration\n\
-# file for your system. For detailed description of different configuration\n\
-# sections refer to silcd(8) manual page.\n\
-#\n";
- /*
-#<Cipher>
-#+blowfish
-#+twofish
-#+rc5
-#+rc6
-#+3des
+ SilcServerConfig config = server->config;
+ SilcServerConfigRouter *serv = NULL;
+ int i;
+ bool found = FALSE;
-#<HashFunction>
-#+md5
-#+sha1
+ serv = config->routers;
+ for (i = 0; serv; i++) {
+ if (serv->initiator == TRUE && serv->backup_router == FALSE) {
+ found = TRUE;
+ break;
+ }
-<ServerInfo>
-+lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:1333
+ serv = serv->next;
+ }
-<AdminInfo>
-+Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
+ return found;
+}
-<ListenPort>
-+10.2.1.6:10.2.1.6:1333
+/* Returns our primary connection configuration or NULL if we do not
+ have primary router configured. */
-<Logging>
-+infologfile:silcd.log:10000
-#+warninglogfile:/var/log/silcd_warning.log:10000
-#+errorlogfile:ERROR.log:10000
-#+fatallogfile:/var/log/silcd_error.log:
+SilcServerConfigRouter *
+silc_server_config_get_primary_router(SilcServer server)
+{
+ SilcServerConfig config = server->config;
+ SilcServerConfigRouter *serv = NULL;
+ int i;
-<ConnectionClass>
- +1:100:100:100
- +2:200:300:400
+ serv = config->routers;
+ for (i = 0; serv; i++) {
+ if (serv->initiator == TRUE && serv->backup_router == FALSE)
+ return serv;
+ serv = serv->next;
+ }
-<ClientAuth>
-+10.2.1.199:priikone:333:1
+ return NULL;
+}
-<AdminAuth>
-+10.2.1.199:priikone:priikone:1
+/* If we have backup router configured that is going to replace us this
+ function returns it. */
-<ServerConnection>
+SilcServerConfigRouter *
+silc_server_config_get_backup_router(SilcServer server)
+{
+ SilcServerConfig config = server->config;
+ SilcServerConfigRouter *serv = NULL;
+ int i;
-<RouterConnection>
+ if (server->server_type != SILC_ROUTER)
+ return NULL;
-<DenyConnection>
-<RedirectClient>
- */
+ 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;
+ }
- fprintf(stdout, "%s\n", buf);
+ return NULL;
}