#include "server_internal.h"
/* Static prototypes */
+SILC_TASK_CALLBACK(silc_server_rehash_close_connection);
SILC_TASK_CALLBACK(silc_server_connect_to_router_retry);
SILC_TASK_CALLBACK(silc_server_connect_router);
SILC_TASK_CALLBACK(silc_server_connect_to_router);
return FALSE;
}
+/* Task callback to close a socket connection after rehash */
+
+SILC_TASK_CALLBACK(silc_server_rehash_close_connection)
+{
+ SilcServer server = context;
+ SilcSocketConnection sock = server->sockets[fd];
+
+ if (!sock)
+ return;
+
+ SILC_LOG_INFO(("Closing connection %s:%d [%s]: connection is unconfigured",
+ sock->hostname, sock->port,
+ (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
+ sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
+ sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
+ "Router")));
+ silc_schedule_task_del_by_context(server->schedule, sock);
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_BANNED_FROM_SERVER,
+ "This connection is removed from "
+ "configuration");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+}
+
/* This function basically reads the config file again and switches the config
object pointed by the server object. After that, we have to fix various
things such as the server_name and the listening ports.
silc_pkcs_private_key_set(server->pkcs, server->private_key);
}
+ /* Check for unconfigured server and router connections and close
+ connections that were unconfigured. */
+
+ if (server->config->routers) {
+ SilcServerConfigRouter *ptr;
+ SilcServerConfigRouter *newptr;
+ bool found;
+
+ for (ptr = server->config->routers; ptr; ptr = ptr->next) {
+ found = FALSE;
+
+ /* Check whether new config has this one too */
+ for (newptr = newconfig->routers; newptr; newptr = newptr->next) {
+ if (!strcmp(newptr->host, ptr->host) && newptr->port == ptr->port &&
+ newptr->initiator == ptr->initiator) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* Remove this connection */
+ SilcSocketConnection sock;
+ sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
+ ptr->host, ptr->port);
+ if (sock && !SILC_IS_LISTENER(sock))
+ silc_schedule_task_add(server->schedule, sock->sock,
+ silc_server_rehash_close_connection,
+ server, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
+ }
+ }
+
+ if (server->config->servers) {
+ SilcServerConfigServer *ptr;
+ SilcServerConfigServer *newptr;
+ bool found;
+
+ for (ptr = server->config->servers; ptr; ptr = ptr->next) {
+ found = FALSE;
+
+ /* Check whether new config has this one too */
+ for (newptr = newconfig->servers; newptr; newptr = newptr->next) {
+ if (!strcmp(newptr->host, ptr->host)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* Remove this connection */
+ SilcSocketConnection sock;
+ sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_SERVER,
+ ptr->host, 0);
+ if (sock && !SILC_IS_LISTENER(sock))
+ silc_schedule_task_add(server->schedule, sock->sock,
+ silc_server_rehash_close_connection,
+ server, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
+ }
+ }
+
/* Go through all configured routers after rehash */
silc_schedule_task_add(server->schedule, 0,
silc_server_connect_to_router,
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],
SilcServerConnection sconn;
SilcServerConfigRouter *ptr;
- SILC_LOG_DEBUG(("Connecting to router(s)"));
-
- if (server->server_type == SILC_SERVER) {
- SILC_LOG_DEBUG(("We are normal server"));
- } else if (server->server_type == SILC_ROUTER) {
- SILC_LOG_DEBUG(("We are router"));
- } else {
- SILC_LOG_DEBUG(("We are backup router/normal server"));
- }
+ SILC_LOG_DEBUG(("We are %s",
+ (server->server_type == SILC_SERVER ?
+ "normal server" : server->server_type == SILC_ROUTER ?
+ "router" : "backup router/normal server")));
if (!server->config->routers) {
/* There wasn't a configured router, we will continue but we don't
have a connection to outside world. We will be standalone server. */
- SILC_LOG_DEBUG(("No router(s), server will be standalone"));
+ SILC_LOG_DEBUG(("No router(s), we are standalone"));
server->standalone = TRUE;
return;
}
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_ske_free(ctx->ske);
silc_free(ctx->dest_id);
silc_free(ctx);
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+
+ /* Try reconnecting if configuration wants it */
+ if (!sconn->no_reconnect) {
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_connect_to_router_retry,
+ sconn, 0, 1, SILC_TASK_TIMEOUT,
+ 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_free(sconn);
return;
}
silc_ske_free(ctx->ske);
silc_free(ctx->dest_id);
silc_free(ctx);
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+
+ /* Try reconnecting if configuration wants it */
+ if (!sconn->no_reconnect) {
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_connect_to_router_retry,
+ sconn, 0, 1, SILC_TASK_TIMEOUT,
+ 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_free(sconn);
return;
}
silc_ske_free_key_material(ctx->keymat);
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;
silc_free(ctx->dest_id);
silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED,
NULL);
+
+ /* Try reconnecting if configuration wants it */
+ if (!sconn->no_reconnect) {
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_connect_to_router_retry,
+ sconn, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ goto out2;
+ }
+
goto out;
}
SILC_LOG_DEBUG(("New server id(%s)",
silc_id_render(ctx->dest_id, SILC_ID_SERVER)));
- /* Add the connected router to global server list */
+ /* Add the connected router to global server list. Router is sent
+ as NULL since it's local to us. */
id_entry = silc_idlist_add_server(server->global_list,
strdup(sock->hostname),
SILC_ROUTER, ctx->dest_id, NULL, sock);
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;
server->router = id_entry;
server->standalone = FALSE;
- /* If we are router then announce our possible servers. */
+ /* If we are router then announce our possible servers. Backup
+ router announces also global servers. */
if (server->server_type == SILC_ROUTER)
- silc_server_announce_servers(server, FALSE, 0,
- SILC_PRIMARY_ROUTE(server));
+ silc_server_announce_servers(server,
+ server->backup_router ? TRUE : FALSE,
+ 0, SILC_PRIMARY_ROUTE(server));
/* Announce our clients and channels to the router */
silc_server_announce_clients(server, 0, SILC_PRIMARY_ROUTE(server));
silc_server_announce_channels(server, 0, SILC_PRIMARY_ROUTE(server));
-#ifdef BACKUP_SINGLE_ROUTER
/* If we are backup router then this primary router is whom we are
backing up. */
if (server->server_type == SILC_BACKUP_ROUTER)
silc_server_backup_add(server, server->id_entry, sock->ip, 0, TRUE);
-#endif /* BACKUP_SINGLE_ROUTER */
}
} else {
/* Add this server to be our backup router */
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);
if (sconn == server->router_conn)
server->router_conn = NULL;
+ out2:
/* Free the protocol object */
if (sock->protocol == protocol)
sock->protocol = NULL;
SILC_TASK_PRI_LOW);
}
+/* After this is called, server don't wait for backup router anymore.
+ This gets called automatically even after we have backup router
+ connection established. */
+
+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));
SilcServerConfigServer *sconn = ctx->sconfig.ref_ptr;
SilcServerConfigRouter *rconn = ctx->rconfig.ref_ptr;
+ /* If we are backup router and this is incoming server connection
+ and we do not have connection to primary router, do not allow
+ the connection. */
+ if (server->server_type == SILC_BACKUP_ROUTER &&
+ ctx->conn_type == SILC_SOCKET_TYPE_SERVER &&
+ !SILC_PRIMARY_ROUTE(server)) {
+ SILC_LOG_INFO(("Will not accept server connection because we do "
+ "not have primary router connection established"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_PERM_DENIED,
+ "We do not have connection to primary "
+ "router established, try later");
+ silc_free(sock->user_data);
+ server->stat.auth_failures++;
+ goto out;
+ }
+
if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) {
/* Verify whether this connection is after all allowed to connect */
if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
&server->config->param,
rconn ? rconn->param : NULL,
ctx->ske)) {
+ silc_free(sock->user_data);
server->stat.auth_failures++;
goto out;
}
&server->config->param,
sconn ? sconn->param : NULL,
ctx->ske)) {
+ silc_free(sock->user_data);
server->stat.auth_failures++;
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 && !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 ?
}
entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
- /* Statistics */
- if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) {
- server->stat.my_servers++;
- } else {
- server->stat.my_routers++;
- server->stat.routers++;
- }
- server->stat.servers++;
-
id_entry = (void *)new_server;
/* If the incoming connection is router and marked as backup router
new_server->server_type = SILC_BACKUP_ROUTER;
}
+ /* Statistics */
+ if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) {
+ server->stat.my_servers++;
+ } else {
+ server->stat.my_routers++;
+ server->stat.routers++;
+ }
+ server->stat.servers++;
+
/* Check whether this connection is to be our primary router connection
if we do not already have the primary route. */
if (!backup_router &&
/* 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)) {
message = silc_memdup(packet->buffer->data + 1,
packet->buffer->len - 1);
- SILC_LOG_ERROR(("Disconnected by %s (%s): %s (%d) %s",
- sock->ip, sock->hostname,
- silc_get_status_message(status), status,
- message ? message : ""));
+ SILC_LOG_INFO(("Disconnected by %s (%s): %s (%d) %s",
+ sock->ip, sock->hostname,
+ 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;
SILC_TASK_CALLBACK(silc_server_close_connection_final)
{
- silc_socket_free((SilcSocketConnection)context);
+ silc_socket_free(context);
}
/* Closes connection to socket connection */
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->standalone = TRUE;
backup_router = NULL;
} else {
- SILC_LOG_INFO(("New primary router is backup router %s",
- backup_router->server_name));
- SILC_LOG_DEBUG(("New primary router is backup router %s",
- backup_router->server_name));
-#ifdef BACKUP_SINGLE_ROUTER
if (server->id_entry != backup_router) {
-#endif /* BACKUP_SINGLE_ROUTER */
+ SILC_LOG_INFO(("New primary router is backup router %s",
+ backup_router->server_name));
server->id_entry->router = backup_router;
server->router = backup_router;
server->router_connect = time(0);
server->backup_primary = TRUE;
-#ifdef BACKUP_SINGLE_ROUTER
} else {
+ SILC_LOG_INFO(("We are now new primary router in this cell"));
server->id_entry->router = NULL;
server->router = NULL;
server->standalone = TRUE;
+
+ /* We stop here to take a breath */
+ sleep(2);
}
-#endif /* BACKUP_SINGLE_ROUTER */
if (server->server_type == SILC_BACKUP_ROUTER) {
server->server_type = SILC_ROUTER;
}
if (!backup_router) {
- /* Free all client entries that this server owns as they will
- become invalid now as well. */
- if (user_data->id)
- silc_server_remove_clients_by_server(server, user_data, TRUE);
+ /* Remove all servers that are originated from this server, and
+ remove the clients of those servers too. */
+ silc_server_remove_servers_by_server(server, user_data, TRUE);
+
+ /* Remove the clients that this server owns as they will become
+ invalid now too. */
+ silc_server_remove_clients_by_server(server, user_data,
+ user_data, TRUE);
+
+ /* Remove channels owned by this server */
if (server->server_type == SILC_SERVER)
silc_server_remove_channels_by_server(server, user_data);
} else {
+ /* Enable local server connections that may be disabled */
+ silc_server_local_servers_toggle_enabled(server, 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_update_clients_by_server(server, user_data, backup_router,
- TRUE, TRUE);
+ router. If we are the backup router we also resolve the real
+ servers for the clients. After updating is over this also
+ removes the clients that this server explicitly owns. */
+ silc_server_update_clients_by_server(server, user_data,
+ backup_router, TRUE);
+
+ /* If we are router and just lost our primary router (now standlaone)
+ we remove everything that was behind it, since we don't know
+ any better. */
+ if (server->server_type == SILC_ROUTER && server->standalone)
+ /* Remove all servers that are originated from this server, and
+ remove the clients of those servers too. */
+ silc_server_remove_servers_by_server(server, user_data, TRUE);
+
+ /* Finally remove the clients that are explicitly owned by this
+ server. They go down with the server. */
+ silc_server_remove_clients_by_server(server, user_data,
+ user_data, TRUE);
+
+ /* Update our server cache to use the new backup router too. */
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);
+
+ /* Send notify about primary router going down to local operators */
+ if (server->backup_router)
+ SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
+ SILC_NOTIFY_TYPE_NONE,
+ ("%s switched to backup router %s "
+ "(we are primary router now)",
+ server->server_name, server->server_name));
+ else
+ SILC_SERVER_SEND_OPERS(server, FALSE, TRUE,
+ SILC_NOTIFY_TYPE_NONE,
+ ("%s switched to backup router %s",
+ server->server_name,
+ server->router->server_name));
}
/* Free the server entry */
if (server->server_type == SILC_ROUTER)
server->stat.cell_servers--;
- if (backup_router) {
+ if (backup_router && backup_router != server->id_entry) {
/* Announce all of our stuff that was created about 5 minutes ago.
The backup router knows all the other stuff already. */
if (server->server_type == SILC_ROUTER)
unsigned char channel_key[32], hash[32];
SilcUInt32 len;
- SILC_LOG_DEBUG(("Generating channel key"));
-
if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
SILC_LOG_DEBUG(("Channel has private keys, will not generate new key"));
return TRUE;
}
+ SILC_LOG_DEBUG(("Generating channel %s key", channel->channel_name));
+
if (!channel->channel_key)
if (!silc_cipher_alloc(SILC_DEFAULT_CIPHER, &channel->channel_key)) {
channel->channel_key = NULL;
SilcUInt32 tmp_len;
char *cipher;
- SILC_LOG_DEBUG(("Saving new channel key"));
-
/* Decode channel key payload */
payload = silc_channel_key_payload_parse(key_payload->data,
key_payload->len);
}
}
+ SILC_LOG_DEBUG(("Saving new channel %s key", channel->channel_name));
+
tmp = silc_channel_key_get_key(payload, &tmp_len);
if (!tmp) {
channel = NULL;
silc_buffer_pull(*clients, idp->len);
SILC_PUT32_MSB(client->mode, mode);
- tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_UMODE_CHANGE,
- 2, idp->data, idp->len,
- mode, 4);
+ tmp =
+ silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_UMODE_CHANGE,
+ 2, idp->data, idp->len,
+ mode, 4);
*umodes = silc_buffer_realloc(*umodes,
(*umodes ?
(*umodes)->truelen + tmp->len :
silc_buffer_pull(*channels, len);
}
- /* Channel user modes */
- *channel_users_modes = silc_realloc(*channel_users_modes,
- sizeof(**channel_users_modes) *
- (i + 1));
- (*channel_users_modes)[i] = NULL;
- *channel_modes = silc_realloc(*channel_modes,
- sizeof(**channel_modes) * (i + 1));
- (*channel_modes)[i] = NULL;
- *channel_ids = silc_realloc(*channel_ids,
- sizeof(**channel_ids) * (i + 1));
- (*channel_ids)[i] = NULL;
- silc_server_announce_get_channel_users(server, channel,
- &(*channel_modes)[i],
- channel_users,
- &(*channel_users_modes)[i]);
- (*channel_ids)[i] = channel->id;
-
- /* Channel's topic */
- *channel_topics = silc_realloc(*channel_topics,
- sizeof(**channel_topics) * (i + 1));
- (*channel_topics)[i] = NULL;
- silc_server_announce_get_channel_topic(server, channel,
- &(*channel_topics)[i]);
- i++;
+ if (creation_time && channel->updated < creation_time)
+ announce = FALSE;
+ else
+ announce = TRUE;
+
+ if (announce) {
+ /* Channel user modes */
+ *channel_users_modes = silc_realloc(*channel_users_modes,
+ sizeof(**channel_users_modes) *
+ (i + 1));
+ (*channel_users_modes)[i] = NULL;
+ *channel_modes = silc_realloc(*channel_modes,
+ sizeof(**channel_modes) * (i + 1));
+ (*channel_modes)[i] = NULL;
+ *channel_ids = silc_realloc(*channel_ids,
+ sizeof(**channel_ids) * (i + 1));
+ (*channel_ids)[i] = NULL;
+ silc_server_announce_get_channel_users(server, channel,
+ &(*channel_modes)[i],
+ channel_users,
+ &(*channel_users_modes)[i]);
+ (*channel_ids)[i] = channel->id;
+
+ /* Channel's topic */
+ *channel_topics = silc_realloc(*channel_topics,
+ sizeof(**channel_topics) * (i + 1));
+ (*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);
SilcProtocol protocol;
SilcServerRekeyInternalContext *proto_ctx;
- SILC_LOG_DEBUG(("Start"));
-
/* Allocate internal protocol context. This is sent as context
to the protocol. */
proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
/* Run the protocol */
silc_protocol_execute(protocol, server->schedule, 0, 0);
+ SILC_LOG_DEBUG(("Rekey protocol completed"));
+
/* Re-register re-key timeout */
silc_schedule_task_add(server->schedule, sock->sock,
silc_server_rekey_callback,