for backup router.
Fixed version string parsing crash.
Fixed NICK_CHANGE notify crash in client library.
+Tue Jun 25 18:47:39 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Enable all local server connections before updating client
+ caches when we've become backup router. Otherwise, signoff
+ packets may not reach the clients. Affected files are
+ silcd/server.c and silcd/server_util.[ch].
+
+ * Fixed a bug in version string parsing which could crash
+ the program with specially formatted version string.
+ Bug reported and patch provided by Ville Räsänen. Affected
+ file lib/silcutil/silcutil.c.
+
+ * Handle the disconnection immediately when DISCONNECT
+ packet is received in server. Affected file silcd/server.c.
+
+ * Primary router now waits a short time (10 seconds) for
+ backup router connection before accepting any other
+ connection (except local). Affected file silcd/server.c,
+ serverconfig.[ch].
+
+ * Fixed a crash in client libary in NICK_CHANGE notify when
+ NICK_CHANGE arrived for client entry we are resolving
+ currently. Affected file lib/silcclient/client_notify.c.
+
+ * Call the sconn->callback completion even if error had
+ occurred. Start reconnecting always if connection to
+ primary router fails during backup router protocol.
+ Affected files silcd/server.c and server_backup.c.
+
Mon Jun 24 17:47:52 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
* Added functions silc_server_send_opers and
the core library, client and server. Maybe implementations of
RFC 2425 and RFC 2426 to make it complete.
+ o Add special handling in router and server for "connection timed out"
+ error. Be optimistic.
+
o Backup router related issues (Fix this to 0.9.x):
o Complete backup router support with standalone router
cell use it. When primary goes down, also those that are
not using it (are not connected locally) are signoffed.
+ o When primary goes down and removing clients of non-backup
+ aware server the SERVER_SIGNOFF includes the router's ID
+ not the server's ID, which it should include. The notify
+ is sent by backup.
+
o Testing
o Add a timeout to handling incoming JOIN commands. It should be
int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
{
- SILC_LOG_DEBUG(("Start"));
-
if (entry) {
/* Remove from cache */
if (!silc_idcache_del_by_context(id_list->servers, entry))
return FALSE;
+ SILC_LOG_DEBUG(("Deleting server %s", entry->server_name ?
+ entry->server_name : ""));
+
/* Free data */
silc_free(entry->server_name);
silc_free(entry->id);
return;
/* If entry is disabled do not sent anything. */
- if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED)
+ if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+ SILC_LOG_DEBUG(("Connection is disabled"));
return;
+ }
/* Get data used in the packet sending, keys and stuff */
switch(sock->type) {
idata = (SilcIDListData)sock->user_data;
/* If entry is disabled do not sent anything. */
- if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED)
+ if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+ SILC_LOG_DEBUG(("Connection is disabled"));
return;
+ }
SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
if (!server->sockets[i])
continue;
if (!SILC_IS_LISTENER(server->sockets[i])) {
+ SilcIDListData idata = server->sockets[i]->user_data;
+
+ if (idata)
+ idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
+
silc_schedule_task_del_by_context(server->schedule,
server->sockets[i]);
silc_server_disconnect_remote(server, server->sockets[i],
ptr->initiator ? "Initiator" : "Responder",
ptr->host, ptr->port));
+ if (server->server_type == SILC_ROUTER && ptr->backup_router &&
+ ptr->initiator == FALSE && !server->backup_router)
+ server->wait_backup = TRUE;
+
if (ptr->initiator) {
/* Check whether we are connected to this host already */
if (silc_server_num_sockets_by_remote(server,
SILC_TASK_PRI_NORMAL);
return;
}
+
+ /* Call completion to indicate error */
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+
silc_server_config_unref(&sconn->conn);
silc_free(sconn->remote_host);
silc_free(sconn->backup_replace_ip);
SILC_TASK_PRI_NORMAL);
return;
}
+
+ /* Call completion to indicate error */
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+
silc_server_config_unref(&sconn->conn);
silc_free(sconn->remote_host);
silc_free(sconn->backup_replace_ip);
SilcServer server = (SilcServer)ctx->server;
SilcServerConnection sconn = (SilcServerConnection)ctx->context;
SilcSocketConnection sock = ctx->sock;
- SilcServerEntry id_entry;
+ SilcServerEntry id_entry = NULL;
SilcBuffer packet;
SilcServerHBContext hb_context;
unsigned char *id_string;
sock->user_data = (void *)id_entry;
sock->type = SILC_SOCKET_TYPE_ROUTER;
idata = (SilcIDListData)sock->user_data;
- idata->status |= SILC_IDLIST_STATUS_REGISTERED;
+ idata->status |= (SILC_IDLIST_STATUS_REGISTERED |
+ SILC_IDLIST_STATUS_LOCAL);
conn = sconn->conn.ref_ptr;
param = &server->config->param;
sock->protocol = NULL;
+ out:
/* Call the completion callback to indicate that we've connected to
the router */
if (sconn->callback)
(*sconn->callback)(server, id_entry, sconn->callback_context);
- out:
/* Free the temporary connection data context */
if (sconn) {
silc_server_config_unref(&sconn->conn);
SILC_TASK_PRI_LOW);
}
+/* After this is called, server don't wait for backup router anymore */
+
+SILC_TASK_CALLBACK(silc_server_backup_router_wait)
+{
+ SilcServer server = context;
+ server->wait_backup = FALSE;
+}
+
/* Final part of accepting new connection. The connection has now
been authenticated and keys has been exchanged. We also know whether
this is client or server connection. */
goto out;
}
+ /* If we are primary router and we have backup router configured
+ but it has not connected to use yet, do not accept any other
+ connection. */
+ if (server->wait_backup && server->server_type == SILC_ROUTER &&
+ !server->backup_router) {
+ SilcServerConfigRouter *router;
+ router = silc_server_config_get_backup_router(server);
+ if (router && strcmp(server->config->server_info->primary->server_ip,
+ sock->ip) &&
+ silc_server_find_socket_by_host(server,
+ SILC_SOCKET_TYPE_SERVER,
+ router->backup_replace_ip, 0)) {
+ SILC_LOG_INFO(("Will not accept connections because we do "
+ "not have backup router connection established"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_PERM_DENIED,
+ "We do not have connection to backup "
+ "router established, try later");
+ silc_free(sock->user_data);
+ server->stat.auth_failures++;
+
+ /* From here on, wait 10 seconds for the backup router to appear. */
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_backup_router_wait,
+ (void *)server, 10, 0,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ goto out;
+ }
+ }
+
SILC_LOG_DEBUG(("Remote host is client"));
SILC_LOG_INFO(("Connection %s (%s) is client", sock->hostname,
sock->ip));
}
}
+ /* If we are primary router and we have backup router configured
+ but it has not connected to use yet, do not accept any other
+ connection. */
+ if (server->wait_backup && server->server_type == SILC_ROUTER &&
+ !server->backup_router && !backup_router) {
+ SilcServerConfigRouter *router;
+ router = silc_server_config_get_backup_router(server);
+ if (router && strcmp(server->config->server_info->primary->server_ip,
+ sock->ip) &&
+ silc_server_find_socket_by_host(server,
+ SILC_SOCKET_TYPE_SERVER,
+ router->backup_replace_ip, 0)) {
+ SILC_LOG_INFO(("Will not accept connections because we do "
+ "not have backup router connection established"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_PERM_DENIED,
+ "We do not have connection to backup "
+ "router established, try later");
+ silc_free(sock->user_data);
+ server->stat.auth_failures++;
+
+ /* From here on, wait 10 seconds for the backup router to appear. */
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_backup_router_wait,
+ (void *)server, 10, 0,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ goto out;
+ }
+ }
+
SILC_LOG_DEBUG(("Remote host is %s",
ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
"server" : (backup_router ?
ctx->conn_type = SILC_SOCKET_TYPE_SERVER;
new_server->server_type = SILC_BACKUP_ROUTER;
+ server->wait_backup = FALSE;
}
/* Statistics */
/* Check that the the current client ID is same as in the client's packet. */
if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
SilcClientEntry client = (SilcClientEntry)sock->user_data;
- if (client && client->id) {
+ if (client && client->id && packet->src_id) {
void *id = silc_id_str2id(packet->src_id, packet->src_id_len,
packet->src_id_type);
if (!id || !SILC_ID_CLIENT_COMPARE(client->id, id)) {
if (server->server_type == SILC_ROUTER) {
/* Route the packet if it is not destined to us. Other ID types but
server are handled separately after processing them. */
- if (!(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
+ if (packet->dst_id && !(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
packet->dst_id_type == SILC_ID_SERVER &&
sock->type != SILC_SOCKET_TYPE_CLIENT &&
memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
silc_get_status_message(status), status,
message ? message : ""));
silc_free(message);
+
+ /* Handle the disconnection from our end too */
+ if (sock->user_data && SILC_IS_LOCAL(sock->user_data))
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_close_connection(server, sock);
}
break;
SilcSocketConnection sock)
{
if (!server->sockets[sock->sock] && SILC_IS_DISCONNECTED(sock)) {
- silc_socket_free(sock);
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_close_connection_final,
+ (void *)sock, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
return;
}
server->router_connect = time(0);
server->backup_primary = TRUE;
} else {
- SILC_LOG_INFO(("We are now new router in this cell"));
+ SILC_LOG_INFO(("We are now new primary router in this cell"));
server->id_entry->router = NULL;
server->router = NULL;
server->standalone = TRUE;
/* Update the client entries of this server to the new backup
router. This also removes the clients that *really* was owned
by the primary router and went down with the router. */
+ silc_server_local_servers_toggle_enabled(server, TRUE);
silc_server_update_clients_by_server(server, user_data, backup_router,
TRUE, TRUE);
- silc_server_update_servers_by_server(server, user_data, backup_router,
- TRUE);
+ silc_server_update_servers_by_server(server, user_data, backup_router);
if (server->server_type == SILC_SERVER)
silc_server_update_channels_by_server(server, user_data,
backup_router);
(*channel_topics)[i] = NULL;
silc_server_announce_get_channel_topic(server, channel,
&(*channel_topics)[i]);
+ (*channel_users_modes_c)++;
i++;
if (!silc_idcache_list_next(list, &id_cache))
break;
}
-
- *channel_users_modes_c += i;
}
silc_idcache_list_free(list);
/* Callback function that is called after the key exchange and connection
authentication protocols has been completed with a remote router. The
- `server_entry' is the remote router entry. */
+ `server_entry' is the remote router entry or NULL on error. */
typedef void (*SilcServerConnectRouterCallback)(SilcServer server,
SilcServerEntry server_entry,
void *context);
#include "server_internal.h"
SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
+static void silc_server_backup_connect_primary(SilcServer server,
+ SilcServerEntry server_entry,
+ void *context);
/* Backup router */
typedef struct {
/* Connect to remote host */
server_ip = server->config->server_info->primary == NULL ? NULL :
- server->config->server_info->primary->server_ip;
+ server->config->server_info->primary->server_ip;
sock = silc_net_create_connection(server_ip, sconn->remote_port,
sconn->remote_host);
if (sock < 0) {
sconn->remote_port = port;
sconn->callback = callback;
sconn->callback_context = context;
+ sconn->no_reconnect = TRUE;
silc_schedule_task_add(server->schedule, 0,
silc_server_backup_connect_to_router,
sconn, 1, 0, SILC_TASK_TIMEOUT,
void *context)
{
SilcServerBackupProtocolContext proto_ctx;
- SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
+ SilcSocketConnection sock;
+ if (!server_entry) {
+ /* Try again */
+ SilcServerConfigRouter *primary;
+ primary = silc_server_config_get_primary_router(server);
+ if (primary)
+ silc_server_backup_reconnect(server,
+ primary->host, primary->port,
+ silc_server_backup_connected,
+ context);
+ return;
+ }
+
+ sock = (SilcSocketConnection)server_entry->connection;
proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
proto_ctx->server = server;
proto_ctx->sock = sock;
void *context)
{
SilcSocketConnection backup_router = (SilcSocketConnection)context;
- SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
- SilcIDListData idata = (SilcIDListData)server_entry;
- SilcServerBackupProtocolContext ctx =
- (SilcServerBackupProtocolContext)backup_router->protocol->context;
+ SilcServerBackupProtocolContext ctx;
+ SilcSocketConnection sock;
+ SilcIDListData idata;
SilcBuffer buffer;
+ if (!server_entry) {
+ /* Try again */
+ SilcServerConfigRouter *primary;
+ primary = silc_server_config_get_primary_router(server);
+ if (primary)
+ silc_server_backup_reconnect(server,
+ primary->host, primary->port,
+ silc_server_backup_connect_primary,
+ context);
+ return;
+ }
+
+ ctx = (SilcServerBackupProtocolContext)backup_router->protocol->context;
+ sock = (SilcSocketConnection)server_entry->connection;
+ idata = (SilcIDListData)server_entry;
+
SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
/* Send the CONNECTED packet back to the backup router. */
/* Switch announced informations to our primary router of using the
backup router. */
+ silc_server_local_servers_toggle_enabled(server, TRUE);
silc_server_update_servers_by_server(server, ctx->sock->user_data,
- server->router, TRUE);
+ server->router);
silc_server_update_clients_by_server(server, ctx->sock->user_data,
server->router, TRUE, FALSE);
if (server->server_type == SILC_SERVER)
SILC_LOG_INFO(("Switching back to primary router %s",
server->router->server_name));
-
- /* We cannot talk to backup router connection anymore, it's
- enabled again if primary goes down. */
- backup_router->data.status |= SILC_IDLIST_STATUS_DISABLED;
} else {
/* We are connected to new primary and now continue using it */
router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
/* Update the client entries of the backup router to the new
router */
- silc_server_update_servers_by_server(server, backup_router, router,
- FALSE);
+ silc_server_local_servers_toggle_enabled(server, FALSE);
+ silc_server_update_servers_by_server(server, backup_router, router);
silc_server_update_clients_by_server(server, NULL, router,
FALSE, FALSE);
if (server->server_type == SILC_SERVER)
server_entry = (SilcServerEntry)id_cache->context;
sock = (SilcSocketConnection)server_entry->connection;
+ /* XXXX */
+ if (!sock) {
+ SILC_LOG_DEBUG(("******** REMOVE THIS TEST, IT ALLOWS A BUG"));
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ continue;
+ }
+
if (sock->protocol == protocol) {
sock->protocol = NULL;
server_entry = (SilcServerEntry)id_cache->context;
sock = (SilcSocketConnection)server_entry->connection;
+ /* XXXX */
+ if (!sock) {
+ SILC_LOG_DEBUG(("******** REMOVE THIS TEST, IT ALLOWS A BUG"));
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ continue;
+ }
+
if (sock->protocol == protocol) {
sock->protocol = NULL;
unsigned int backup_router : 1; /* Set if this is backup router */
unsigned int backup_primary : 1; /* Set if we've switched our primary
router to a backup router. */
+ unsigned int wait_backup : 1; /* Set if we are waiting for backup
+ router to connect to us. */
SilcServerEntry router; /* Pointer to the primary router */
unsigned long router_connect; /* Time when router was connected */
#define SILC_BROADCAST(server) (server->server_type == SILC_ROUTER)
/* Return TRUE if entry is locally connected or local to us */
-#define SILC_IS_LOCAL(entry) \
- ((entry)->connection ? TRUE : \
- (entry)->data.status & SILC_IDLIST_STATUS_LOCAL ? TRUE : FALSE)
+#define SILC_IS_LOCAL(entry) \
+ (((SilcIDListData)entry)->status & SILC_IDLIST_STATUS_LOCAL)
/* Registers generic task for file descriptor for reading from network and
writing to network. As being generic task the actual task is allocated
SilcHashTable channels, clients;
int i;
+ if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
+ return FALSE;
+
SILC_LOG_DEBUG(("Start"));
/* Allocate the hash table that holds the channels that require
client->router =
silc_server_update_clients_by_real_server(server, from, client,
local, id_cache);
- if (!client->router)
- client->router = to;
+ if (!client->router) {
+ if (server->server_type == SILC_ROUTER)
+ client->router = from;
+ else
+ client->router = to;
+ }
} else {
client->router = to;
}
client->router = to;
}
+ if (client->router)
+ SILC_LOG_DEBUG(("Client changed to %s",
+ silc_id_render(client->router->id, SILC_ID_CLIENT)));
+
if (!silc_idcache_list_next(list, &id_cache))
break;
}
silc_server_update_clients_by_real_server(server, from, client,
local, id_cache);
if (!client->router)
- client->router = from; /* on local list put old from */
+ client->router = from;
} else {
client->router = to;
}
client->router = to;
}
+ if (client->router)
+ SILC_LOG_DEBUG(("Client changed to %s",
+ silc_id_render(client->router->id, SILC_ID_CLIENT)));
+
if (!silc_idcache_list_next(list, &id_cache))
break;
}
}
/* Updates servers that are from `from' to be originated from `to'. This
- will also update the server's connection to `to's connection. If
- `local_toggle_enabled' is TRUE then local server's connections are
- enabled, if FALSE they are disabled. */
+ will also update the server's connection to `to's connection. */
void silc_server_update_servers_by_server(SilcServer server,
SilcServerEntry from,
- SilcServerEntry to,
- bool local_toggle_enabled)
+ SilcServerEntry to)
{
SilcIDCacheList list = NULL;
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server_entry = NULL;
+ SILC_LOG_DEBUG(("Updating servers"));
+
if (silc_idcache_get_all(server->local_list->servers, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
server_entry = (SilcServerEntry)id_cache->context;
- if (SILC_IS_LOCAL(server_entry)) {
- if (server_entry != server->id_entry) {
- if (local_toggle_enabled)
- server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
- else
- server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
- }
-
- /* If entry is local to us, do not switch it to any oneelse,
- it is ours. */
+ /* If entry is local to us, do not switch it to any anyone else,
+ it is ours. */
+ if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+ server_entry == from) {
if (!silc_idcache_list_next(list, &id_cache))
break;
else
continue;
}
- if (server_entry->router == from) {
- SILC_LOG_DEBUG(("Updating server (local) %s",
- server_entry->server_name ?
- server_entry->server_name : ""));
- server_entry->router = to;
- server_entry->connection = to->connection;
+ /* If we are standalone router, any server that is not directly
+ connected to cannot exist anymore. If we are not standalone
+ we update it correctly. */
+ if (server->server_type == SILC_ROUTER && server->standalone) {
+ silc_server_backup_del(server, server_entry);
+ silc_server_backup_replaced_del(server, server_entry);
+ silc_idlist_del_data(server_entry);
+ silc_idlist_del_server(server->local_list, server_entry);
+ server->stat.servers--;
+ server->stat.cell_servers--;
+ } else {
+ /* XXX if we are not standalone, do a check from local config
+ whether this server is in our cell, but not connected to
+ us (in which case we must remove it). */
+
+ if (server_entry->router == from) {
+ SILC_LOG_DEBUG(("Updating server (local) %s",
+ server_entry->server_name ?
+ server_entry->server_name : ""));
+ server_entry->router = to;
+ server_entry->connection = to->connection;
+ }
}
if (!silc_idcache_list_next(list, &id_cache))
while (id_cache) {
server_entry = (SilcServerEntry)id_cache->context;
- if (SILC_IS_LOCAL(server_entry)) {
- if (server_entry != server->id_entry) {
- if (local_toggle_enabled)
- server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
- else
- server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
+ /* If entry is local to us, do not switch it to anyone else,
+ it is ours. */
+ if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+ server_entry == from) {
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ else
+ continue;
+ }
+
+ /* If we are standalone router, any server that is not directly
+ connected to cannot exist anymore. If we are not standalone
+ we update it correctly. */
+ if (server->server_type == SILC_ROUTER && server->standalone) {
+ silc_server_backup_del(server, server_entry);
+ silc_server_backup_replaced_del(server, server_entry);
+ silc_idlist_del_data(server_entry);
+ silc_idlist_del_server(server->global_list, server_entry);
+ server->stat.servers--;
+ server->stat.cell_servers--;
+ } else {
+ /* XXX if we are not standalone, do a check from local config
+ whether this server is in our cell, but not connected to
+ us (in which case we must remove it). */
+
+ if (server_entry->router == from) {
+ SILC_LOG_DEBUG(("Updating server (global) %s",
+ server_entry->server_name ?
+ server_entry->server_name : ""));
+ server_entry->router = to;
+ server_entry->connection = to->connection;
}
+ }
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ }
+ silc_idcache_list_free(list);
+ }
+}
- /* If entry is local to us, do not switch it to anyone else,
- it is ours. */
+
+/* Toggles the enabled/disabled status of local server connections. Packets
+ can be sent to the servers when `toggle_enabled' is TRUE and will be
+ dropped if `toggle_enabled' is FALSE, after this function is called. */
+
+void silc_server_local_servers_toggle_enabled(SilcServer server,
+ bool toggle_enabled)
+{
+ SilcIDCacheList list = NULL;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server_entry = NULL;
+
+ if (silc_idcache_get_all(server->local_list->servers, &list)) {
+ if (silc_idcache_list_first(list, &id_cache)) {
+ while (id_cache) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
if (!silc_idcache_list_next(list, &id_cache))
break;
else
continue;
}
- if (server_entry->router == from) {
- SILC_LOG_DEBUG(("Updating server (global) %s",
- server_entry->server_name ?
- server_entry->server_name : ""));
- server_entry->router = to;
- server_entry->connection = to->connection;
+ if (toggle_enabled)
+ server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+ else
+ server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ }
+ silc_idcache_list_free(list);
+ }
+
+ if (silc_idcache_get_all(server->global_list->servers, &list)) {
+ if (silc_idcache_list_first(list, &id_cache)) {
+ while (id_cache) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ else
+ continue;
}
+ if (toggle_enabled)
+ server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+ else
+ server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
+
if (!silc_idcache_list_next(list, &id_cache))
break;
}
silc_idcache_list_free(list);
}
}
-
/* Removes channels that are from `from. */
void silc_server_remove_channels_by_server(SilcServer server,
bool remove_from);
/* Updates servers that are from `from' to be originated from `to'. This
- will also update the server's connection to `to's connection. If
- `local_toggle_enabled' is TRUE then local server's connections are
- enabled, if FALSE they are disabled. */
-void silc_server_update_servers_by_server(SilcServer server,
+ will also update the server's connection to `to's connection. */
+void silc_server_update_servers_by_server(SilcServer server,
SilcServerEntry from,
- SilcServerEntry to,
- bool local_toggle_enabled);
+ SilcServerEntry to);
+
+/* Toggles the enabled/disabled status of local server connections. Packets
+ can be sent to the servers when `toggle_enabled' is TRUE and will be
+ dropped if `toggle_enabled' is FALSE, after this function is called. */
+void silc_server_local_servers_toggle_enabled(SilcServer server,
+ bool toggle_enabled);
/* Removes channels that are from `from. */
void silc_server_remove_channels_by_server(SilcServer server,
return NULL;
}
+
+/* If we have backup router configured that is going to replace us this
+ function returns it. */
+
+SilcServerConfigRouter *
+silc_server_config_get_backup_router(SilcServer server)
+{
+ SilcServerConfig config = server->config;
+ SilcServerConfigRouter *serv = NULL;
+ int i;
+
+ if (server->server_type != SILC_ROUTER)
+ return NULL;
+
+ serv = config->routers;
+ for (i = 0; serv; i++) {
+ if (serv->initiator == FALSE && serv->backup_router == TRUE &&
+ serv->backup_local == TRUE &&
+ !strcmp(server->config->server_info->primary->server_ip,
+ serv->backup_replace_ip) &&
+ server->config->server_info->primary->port ==
+ serv->backup_replace_port)
+ return serv;
+ serv = serv->next;
+ }
+
+ return NULL;
+}
bool silc_server_config_is_primary_route(SilcServer server);
SilcServerConfigRouter *
silc_server_config_get_primary_router(SilcServer server);
+SilcServerConfigRouter *
+silc_server_config_get_backup_router(SilcServer server);
#endif /* !SERVERCONFIG_H */
goto out;
silc_free(client_id);
+ /* Wait for resolving if necessary */
+ if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
+ SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
+ res->packet = silc_packet_context_dup(packet);
+ res->context = client;
+ res->sock = silc_socket_dup(conn->sock);
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ client_entry->resolve_cmd_ident,
+ silc_client_notify_by_server_pending, res);
+ goto out;
+ }
+
client_entry->valid = FALSE;
/* Get new Client ID */
void silc_config_close(SilcConfigFile *file)
{
if (file) {
- /* XXX FIXME: this check could probably be removed later */
- SilcUInt32 my_len = (SilcUInt32) (strchr(file->base, EOF) - file->base);
- SILC_CONFIG_DEBUG(("file=0x%x name=\"%s\" level=%d line=%lu",
- (SilcUInt32) file, file->filename, file->level,
- file->line));
- if (my_len != file->len) {
- fprintf(stderr,
- "FATAL ERROR: saved len and current len does not match!\n");
- abort();
- }
silc_free(file->filename);
memset(file->base, 'F', file->len);
silc_free(file->base);
/* Take protocol version */
maj = atoi(cp);
- cp = strchr(cp, '.');
- if (cp) {
- min = atoi(cp + 1);
- cp++;
- }
+ if (!strchr(cp, '.'))
+ return FALSE;
+ cp = strchr(cp, '.') + 1;
+ if (!cp || !(*cp))
+ return FALSE;
+ min = atoi(cp);
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
maj = 0;
min = 0;
- cp = strchr(cp, '-');
- if (!cp)
+ if (!strchr(cp, '-'))
+ return FALSE;
+ cp = strchr(cp, '-') + 1;
+ if (!cp || !(*cp))
return FALSE;
- maj = atoi(cp + 1);
- cp = strchr(cp, '.');
- if (cp)
- min = atoi(cp + 1);
+ maj = atoi(cp);
+ if (strchr(cp, '.')) {
+ cp = strchr(cp, '.') + 1;
+ if (cp && *cp)
+ min = atoi(cp);
+ }
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
/* Take vendor string */
- cp++;
- if (cp) {
- cp = strchr(cp, '.');
- if (cp && cp + 1 && vendor_version)
- *vendor_version = strdup(cp + 1);
+ if (strchr(cp, '.')) {
+ cp = strchr(cp, '.') + 1;
+ if (cp && *cp && vendor_version)
+ *vendor_version = strdup(cp);
}
return TRUE;