Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005, 2007 Pekka Riikonen
+ Copyright (C) 1997 - 2008 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
#include "serverincludes.h"
#include "server_internal.h"
-/************************* Types and definitions ***************************/
+/************************* Types and definitions ****************************/
SILC_TASK_CALLBACK(silc_server_get_stats);
SILC_TASK_CALLBACK(silc_server_connect_router);
+SILC_TASK_CALLBACK(silc_server_connect_to_router_retry);
SILC_TASK_CALLBACK(silc_server_do_rekey);
+SILC_TASK_CALLBACK(silc_server_purge_expired_clients);
static void silc_server_accept_new_connection(SilcNetStatus status,
SilcStream stream,
void *context);
SilcServer server = callback_context;
SilcIDListData idata = stream_context;
+ if (!idata)
+ return FALSE;
+
/* Packets we do not handle */
switch (packet->type) {
case SILC_PACKET_HEARTBEAT:
!(idata->status & SILC_IDLIST_STATUS_REGISTERED)) &&
packet->type != SILC_PACKET_NEW_CLIENT &&
packet->type != SILC_PACKET_NEW_SERVER &&
+ packet->type != SILC_PACKET_RESUME_CLIENT &&
packet->type != SILC_PACKET_CONNECTION_AUTH_REQUEST &&
packet->type != SILC_PACKET_DISCONNECT)
return FALSE;
- /* NEW_CLIENT and NEW_SERVER are accepted only without source ID
- and for unregistered connection. */
+ /* NEW_CLIENT and NEW_SERVER are accepted only without source ID and
+ for unregistered connection. */
if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT ||
packet->type == SILC_PACKET_NEW_SERVER) &&
(idata->status & SILC_IDLIST_STATUS_REGISTERED))
return FALSE;
+ /* Ignore packets from disabled connection */
+ if (idata->status & SILC_IDLIST_STATUS_DISABLED &&
+ packet->type != SILC_PACKET_HEARTBEAT &&
+ packet->type != SILC_PACKET_RESUME_ROUTER &&
+ packet->type != SILC_PACKET_REKEY)
+ return FALSE;
+
+ /* Check that the the current client ID is same as in the client's packet. */
+ if (idata->conn_type == SILC_CONN_CLIENT) {
+ SilcClientEntry client = (SilcClientEntry)silc_packet_get_context(stream);
+ SilcClientID client_id;
+
+ if (client->id && packet->src_id &&
+ silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type, &client_id, sizeof(client_id))) {
+ if (!SILC_ID_CLIENT_COMPARE(client->id, &client_id)) {
+ SILC_LOG_DEBUG(("Packet source is not same as sender, packet %s",
+ silc_get_packet_name(packet->type)));
+ return FALSE;
+ }
+ }
+ }
+
+ 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->dst_id &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
+ packet->dst_id_type == SILC_ID_SERVER &&
+ idata->conn_type != SILC_CONN_CLIENT &&
+ memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
+ SilcPacketStream conn;
+ SilcServerID server_id;
+
+ silc_id_str2id(packet->dst_id, packet->dst_id_len, packet->dst_id_type,
+ &server_id, sizeof(server_id));
+
+ conn = silc_server_route_get(server, &server_id, SILC_ID_SERVER);
+ if (!conn) {
+ SILC_LOG_WARNING(("Packet to unknown server ID %s, dropped (no route)",
+ silc_id_render(&server_id, SILC_ID_SERVER)));
+ return FALSE;
+ }
+
+ silc_server_packet_route(server, conn, packet);
+ silc_packet_free(packet);
+ return TRUE;
+ }
+ }
+
+ /* Broadcast packet if it is marked as broadcast packet and it is
+ originated from router and we are router. */
+ if (server->server_type == SILC_ROUTER &&
+ idata->conn_type == SILC_CONN_ROUTER &&
+ packet->flags & SILC_PACKET_FLAG_BROADCAST) {
+ /* Broadcast to our primary route */
+ silc_server_packet_broadcast(server, SILC_PRIMARY_ROUTE(server), packet);
+
+ /* If we have backup routers then we need to feed all broadcast
+ data to those servers. */
+ silc_server_backup_broadcast(server, stream, packet);
+ }
+
/* Process packet */
silc_server_packet_parse_type(server, stream, packet);
void *callback_context,
void *stream_context)
{
- SILC_LOG_DEBUG(("End of stream received"));
+ SilcServer server = callback_context;
+ SilcIDListData idata = silc_packet_get_context(stream);
+
+ SILC_LOG_DEBUG(("End of stream received, sock %p", stream));
+
+ if (!idata)
+ return;
+
+ if (server->router_conn && server->router_conn->sock == stream &&
+ !server->router && server->standalone) {
+ silc_server_create_connections(server);
+ silc_server_free_sock_user_data(server, stream, NULL);
+ } else {
+ /* If backup disconnected then mark that resuming will not be allowed */
+ if (server->server_type == SILC_ROUTER && !server->backup_router &&
+ idata->conn_type == SILC_CONN_SERVER) {
+ SilcServerEntry server_entry = (SilcServerEntry)idata;
+ if (server_entry->server_type == SILC_BACKUP_ROUTER)
+ server->backup_closed = TRUE;
+ }
+
+ silc_server_free_sock_user_data(server, stream, NULL);
+ }
+
+ silc_server_close_connection(server, stream);
+}
+
+SILC_TASK_CALLBACK(silc_server_packet_error_timeout)
+{
+ SilcServer server = app_context;
+ SilcPacketStream stream = context;
+ SilcIDListData idata = silc_packet_get_context(stream);
+
+ if (!idata)
+ return;
+
+ if (server->router_conn && server->router_conn->sock == stream &&
+ !server->router && server->standalone) {
+ silc_server_create_connections(server);
+ } else {
+ /* If backup disconnected then mark that resuming will not be allowed */
+ if (server->server_type == SILC_ROUTER && !server->backup_router &&
+ idata->conn_type == SILC_CONN_SERVER) {
+ SilcServerEntry server_entry = (SilcServerEntry)idata;
+ if (server_entry->server_type == SILC_BACKUP_ROUTER)
+ server->backup_closed = TRUE;
+ }
+
+ silc_server_free_sock_user_data(server, stream, NULL);
+ }
+
+ silc_server_close_connection(server, stream);
}
/* Packet engine callback to indicate error */
void *callback_context,
void *stream_context)
{
+ SilcServer server = callback_context;
+ SilcIDListData idata = silc_packet_get_context(stream);
+ SilcStream sock = silc_packet_stream_get_stream(stream);
+ const char *ip;
+ SilcUInt16 port;
+
+ SILC_LOG_DEBUG(("Packet error, sock %p", stream));
+
+ if (!idata || !sock)
+ return;
+ if (!silc_socket_stream_get_info(sock, NULL, NULL, &ip, &port))
+ return;
+
+ SILC_LOG_ERROR(("Connection %s:%d [%s]: %s", ip, port,
+ SILC_CONNTYPE_STRING(idata->conn_type),
+ silc_packet_error_string(error)));
+
+ if (!silc_packet_stream_is_valid(stream))
+ return;
+
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_packet_error_timeout,
+ stream, 0, 0);
}
/* Packet stream callbacks */
{
SilcStatus status;
char *message = NULL;
+ const char *hostname, *ip;
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
status = (SilcStatus)packet->buffer.data[0];
if (silc_buffer_len(&packet->buffer) > 1 &&
- silc_utf8_valid(packet->buffer.data + 1, silc_buffer_len(&packet->buffer) - 1))
+ silc_utf8_valid(packet->buffer.data + 1,
+ silc_buffer_len(&packet->buffer) - 1))
message = silc_memdup(packet->buffer.data + 1,
silc_buffer_len(&packet->buffer) - 1);
-#if 0
- SILC_LOG_INFO(("Disconnected by %s (%s): %s (%d) %s",
- sock->ip, sock->hostname,
+ if (!silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL))
+ break;
+
+ SILC_LOG_INFO(("Disconnected by %s (%s): %s (%d) %s", ip, hostname,
silc_get_status_message(status), status,
message ? message : ""));
-#endif
+
silc_free(message);
/* Do not switch to backup in case of error */
server->backup_noswitch = (status == SILC_STATUS_OK ? FALSE : TRUE);
/* If backup disconnected then mark that resuming will not be allowed */
-#if 0
if (server->server_type == SILC_ROUTER && !server->backup_router &&
- sock->type == SILC_CONN_SERVER && sock->user_data) {
- SilcServerEntry server_entry = sock->user_data;
+ idata->conn_type == SILC_CONN_SERVER) {
+ SilcServerEntry server_entry = (SilcServerEntry)idata;
if (server_entry->server_type == SILC_BACKUP_ROUTER)
server->backup_closed = TRUE;
}
/* Handle the disconnection from our end too */
- if (sock->user_data && SILC_IS_LOCAL(sock->user_data))
+ if (SILC_IS_LOCAL(idata))
silc_server_free_sock_user_data(server, sock, NULL);
- SILC_SET_DISCONNECTING(sock);
silc_server_close_connection(server, sock);
server->backup_noswitch = FALSE;
-#endif
}
break;
router resuming protocol. */
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
-#if 0
silc_server_backup_resume_router(server, sock, packet);
-#endif
break;
default:
server->conns = silc_dlist_init();
if (!server->conns)
return FALSE;
+ server->expired_clients = silc_dlist_init();
+ if (!server->expired_clients)
+ return FALSE;
*new_server = server;
{
SilcList list;
SilcIDCacheEntry cache;
+ SilcIDListData idata;
+
+ SILC_LOG_DEBUG(("Free server %p", server));
if (!server)
return;
silc_server_backup_free(server);
silc_server_config_unref(&server->config_ref);
- if (server->pk_hash)
- silc_hash_table_free(server->pk_hash);
if (server->rng)
silc_rng_free(server->rng);
if (server->public_key)
silc_pkcs_private_key_free(server->private_key);
if (server->pending_commands)
silc_dlist_uninit(server->pending_commands);
- if (server->id_entry)
+ if (server->id_entry) {
+ if (server->id_entry->data.sconn)
+ silc_schedule_task_del_by_context(server->schedule,
+ server->id_entry->data.sconn->sock);
silc_idlist_del_server(server->local_list, server->id_entry);
+ }
/* Delete all channels */
if (silc_idcache_get_all(server->local_list->channels, &list)) {
/* Delete all clients */
if (silc_idcache_get_all(server->local_list->clients, &list)) {
silc_list_start(list);
- while ((cache = silc_list_get(list)))
+ while ((cache = silc_list_get(list))) {
+ silc_schedule_task_del_by_context(server->schedule, cache->context);
silc_idlist_del_client(server->local_list, cache->context);
+ }
}
if (silc_idcache_get_all(server->global_list->clients, &list)) {
silc_list_start(list);
- while ((cache = silc_list_get(list)))
+ while ((cache = silc_list_get(list))) {
+ silc_schedule_task_del_by_context(server->schedule, cache->context);
silc_idlist_del_client(server->global_list, cache->context);
+ }
}
/* Delete all servers */
if (silc_idcache_get_all(server->local_list->servers, &list)) {
silc_list_start(list);
- while ((cache = silc_list_get(list)))
+ while ((cache = silc_list_get(list))) {
+ idata = (SilcIDListData)cache->context;
+ if (idata->sconn)
+ silc_schedule_task_del_by_context(server->schedule,
+ idata->sconn->sock);
silc_idlist_del_server(server->local_list, cache->context);
+ }
}
if (silc_idcache_get_all(server->global_list->servers, &list)) {
- while ((cache = silc_list_get(list)))
+ while ((cache = silc_list_get(list))) {
+ idata = (SilcIDListData)cache->context;
+ if (idata->sconn)
+ silc_schedule_task_del_by_context(server->schedule,
+ idata->sconn->sock);
silc_idlist_del_server(server->global_list, cache->context);
+ }
}
+ silc_schedule_task_del_by_context(server->schedule, server);
+ silc_schedule_uninit(server->schedule);
+ server->schedule = NULL;
+
silc_idcache_free(server->local_list->clients);
silc_idcache_free(server->local_list->servers);
silc_idcache_free(server->local_list->channels);
silc_idcache_free(server->global_list->channels);
silc_hash_table_free(server->watcher_list);
silc_hash_table_free(server->watcher_list_pk);
-
silc_hash_free(server->md5hash);
silc_hash_free(server->sha1hash);
- silc_hmac_unregister_all();
- silc_hash_unregister_all();
- silc_cipher_unregister_all();
- silc_pkcs_unregister_all();
+
+ silc_dlist_uninit(server->listeners);
+ silc_dlist_uninit(server->conns);
+ silc_dlist_uninit(server->expired_clients);
+ silc_skr_free(server->repository);
+ silc_packet_engine_stop(server->packet_engine);
silc_free(server->local_list);
silc_free(server->global_list);
silc_free(server->server_name);
- silc_free(server->id_string);
- silc_free(server->purge_i);
- silc_free(server->purge_g);
silc_free(server);
+
+ silc_hmac_unregister_all();
+ silc_hash_unregister_all();
+ silc_cipher_unregister_all();
+ silc_pkcs_unregister_all();
}
/* Creates a new server listener. */
SilcBool silc_server_init_secondary(SilcServer server)
{
- return TRUE;
-#if 0
- int sock = 0;
- SilcPacketStream newsocket = NULL;
SilcServerConfigServerInfoInterface *interface;
+ SilcNetListener listener;
for (interface = server->config->server_info->secondary; interface;
- interface = interface->next, sock++) {
-
- if (!silc_server_listen(server,
- interface->server_ip, interface->port, &sock_list[sock]))
- goto err;
-
- /* Set socket to non-blocking mode */
- silc_net_set_socket_nonblock(sock_list[sock]);
-
- /* Add ourselves also to the socket table. The entry allocated above
- is sent as argument for fast referencing in the future. */
- silc_socket_alloc(sock_list[sock],
- SILC_CONN_SERVER, NULL, &newsocket);
- server->sockets[sock_list[sock]] = newsocket;
- SILC_SET_LISTENER(newsocket);
-
- /* Perform name and address lookups to resolve the listenning address
- and port. */
- if (!silc_net_check_local_by_sock(sock_list[sock], &newsocket->hostname,
- &newsocket->ip)) {
- if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
- !newsocket->ip) {
- SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
- newsocket->hostname ? newsocket->hostname :
- newsocket->ip ? newsocket->ip : ""));
- server->stat.conn_failures++;
- goto err;
- }
- if (!newsocket->hostname)
- newsocket->hostname = strdup(newsocket->ip);
- }
- newsocket->port = silc_net_get_local_port(sock);
-
- newsocket->user_data = (void *)server->id_entry;
- silc_schedule_task_add(server->schedule, sock_list[sock],
- silc_server_accept_new_connection,
- (void *)server, 0, 0,
- SILC_TASK_FD,
- SILC_TASK_PRI_NORMAL);
+ interface = interface->next) {
+ listener = silc_server_listen(server, interface->server_ip,
+ interface->port);
+ if (!listener)
+ return FALSE;
+ silc_dlist_add(server->listeners, listener);
}
return TRUE;
-
- err:
- do silc_net_close_server(sock_list[sock--]); while (sock >= 0);
-#endif /* 0 */
- return FALSE;
}
/* Initializes the entire SILC server. This is called always before running
{
SilcServerID *id;
SilcServerEntry id_entry;
- SilcIDListPurge purge;
SilcNetListener listener;
SilcUInt16 *port;
char **ip;
silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
server);
server->local_list->servers =
- silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL);
+ silc_idcache_alloc(0, SILC_ID_SERVER, silc_idlist_server_destructor,
+ server);
server->local_list->channels =
- silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL);
+ silc_idcache_alloc(0, SILC_ID_CHANNEL, silc_idlist_channel_destructor,
+ NULL);
/* These are allocated for normal server as well as these hold some
global information that the server has fetched from its router. For
silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
server);
server->global_list->servers =
- silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL);
+ silc_idcache_alloc(0, SILC_ID_SERVER, silc_idlist_server_destructor,
+ server);
server->global_list->channels =
- silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL);
+ silc_idcache_alloc(0, SILC_ID_CHANNEL, silc_idlist_channel_destructor,
+ NULL);
/* Init watcher lists */
server->watcher_list =
if (!server->watcher_list_pk)
goto err;
- /* Init public key list */
- server->pk_hash =
- silc_hash_table_alloc(0, silc_hash_public_key, NULL,
- silc_hash_public_key_compare, NULL,
- NULL, NULL, TRUE);
-
- if (!server->pk_hash)
- goto err;
-
/* Create TCP listener */
listener = silc_server_listen(
server,
server->config->server_info->primary->port);
if (!listener)
goto err;
-
silc_dlist_add(server->listeners, listener);
/* Create a Server ID for the server. */
port = silc_net_listener_get_port(listener, NULL);
ip = silc_net_listener_get_ip(listener, NULL);
- silc_id_create_server_id(ip[0], port[0], server->rng, &id);
+ silc_id_create_server_id(server->config->server_info->primary->public_ip ?
+ server->config->server_info->primary->public_ip :
+ ip[0], port[0], server->rng, &id);
if (!id)
goto err;
server->id = id;
server->server_name = server->config->server_info->server_name;
server->config->server_info->server_name = NULL;
+ silc_id_id2str(server->id, SILC_ID_SERVER, server->id_string,
+ sizeof(server->id_string), &server->id_string_len);
/* Add ourselves to the server list. We don't have a router yet
beacuse we haven't established a route yet. It will be done later.
the ID list. */
id_entry =
silc_idlist_add_server(server->local_list, strdup(server->server_name),
- server->server_type, server->id, NULL, NULL);
+ server->server_type,
+ silc_id_dup(server->id, SILC_ID_SERVER),
+ NULL, NULL);
if (!id_entry) {
SILC_LOG_ERROR(("Could not add local server to cache"));
goto err;
}
id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+ id_entry->data.conn_type = (server->server_type == SILC_SERVER ?
+ SILC_CONN_SERVER : SILC_CONN_ROUTER);
server->id_entry = id_entry;
/* Create secondary TCP listeners */
if (silc_server_init_secondary(server) == FALSE)
goto err;
- /* Create connections to configured routers. */
- silc_server_create_connections(server);
-
server->listenning = TRUE;
- /* Allocate the entire socket list that is used in server. Eventually
- all connections will have entry in this table (it is a table of
- pointers to the actual object that is allocated individually
- later). */
- server->sockets = silc_calloc(server->config->param.connections_max,
- sizeof(*server->sockets));
- if (!server->sockets)
- goto err;
+ /* Create connections to configured routers. */
+ silc_server_create_connections(server);
/* If server connections has been configured then we must be router as
normal server cannot have server connections, only router connections. */
}
}
- /* Register the ID Cache purge task. This periodically purges the ID cache
- and removes the expired cache entries. */
-
- /* Clients local list */
- server->purge_i = purge = silc_calloc(1, sizeof(*purge));
- purge->cache = server->local_list->clients;
- purge->timeout = 600;
- silc_schedule_task_add_timeout(server->schedule, silc_idlist_purge,
- (void *)purge, purge->timeout, 0);
-
- /* Clients global list */
- server->purge_g = purge = silc_calloc(1, sizeof(*purge));
- purge->cache = server->global_list->clients;
- purge->timeout = 300;
- silc_schedule_task_add_timeout(server->schedule, silc_idlist_purge,
- (void *)purge, purge->timeout, 0);
+ if (server->server_type != SILC_ROUTER) {
+ server->stat.servers = 1;
+ server->stat.cell_servers = 1;
+ } else {
+ server->stat.routers = 1;
+ }
/* If we are normal server we'll retrieve network statisticial information
once in a while from the router. */
silc_schedule_task_add_timeout(server->schedule, silc_server_get_stats,
server, 10, 0);
- if (server->server_type == SILC_ROUTER)
- server->stat.routers++;
-
/* Start packet engine */
server->packet_engine =
silc_packet_engine_start(server->rng, server->server_type == SILC_ROUTER,
if (!server->packet_engine)
goto err;
+ /* Register client entry expiration timeout */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_purge_expired_clients, server,
+ 120, 0);
+
+ /* Initialize HTTP server */
+ silc_server_http_init(server);
+
SILC_LOG_DEBUG(("Server initialized"));
/* We are done here, return succesfully */
return FALSE;
}
-#if 0
/* Task callback to close a socket connection after rehash */
SILC_TASK_CALLBACK(silc_server_rehash_close_connection)
{
- SilcServer server = context;
- SilcPacketStream sock = server->sockets[fd];
+ SilcServer server = app_context;
+ SilcPacketStream sock = context;
+ SilcIDListData idata = silc_packet_get_context(sock);
+ const char *hostname;
+ SilcUInt16 port;
- if (!sock)
- return;
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, NULL, &port);
SILC_LOG_INFO(("Connection %s:%d [%s] is unconfigured",
- sock->hostname, sock->port,
- (sock->type == SILC_CONN_UNKNOWN ? "Unknown" :
- sock->type == SILC_CONN_CLIENT ? "Client" :
- sock->type == SILC_CONN_SERVER ? "Server" :
- "Router")));
+ hostname, port, SILC_CONNTYPE_STRING(idata->conn_type)));
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);
+ silc_server_free_sock_user_data(server, sock, NULL);
}
-#endif /* 0 */
/* 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
SilcBool silc_server_rehash(SilcServer server)
{
-#if 0
SilcServerConfig newconfig;
SILC_LOG_INFO(("Rehashing server"));
return FALSE;
}
- /* Reinit scheduler if necessary */
- if (newconfig->param.connections_max > server->config->param.connections_max)
- if (!silc_schedule_reinit(server->schedule,
- newconfig->param.connections_max))
- return FALSE;
-
/* Fix the server_name field */
if (strcmp(server->server_name, newconfig->server_info->server_name)) {
silc_free(server->server_name);
/* Update the idcache list with a fresh pointer */
silc_free(server->id_entry->server_name);
server->id_entry->server_name = strdup(server->server_name);
- if (!silc_idcache_del_by_context(server->local_list->servers,
- server->id_entry))
- return FALSE;
- if (!silc_idcache_add(server->local_list->servers,
- strdup(server->id_entry->server_name),
- server->id_entry->id, server->id_entry, 0, NULL))
- return FALSE;
+ silc_idcache_update_by_context(server->local_list->servers,
+ server->id_entry, NULL,
+ strdup(server->id_entry->server_name),
+ TRUE);
}
/* Set logging */
server->private_key = newconfig->server_info->private_key;
newconfig->server_info->public_key = NULL;
newconfig->server_info->private_key = NULL;
-
- /* Allocate PKCS context for local public and private keys */
- silc_pkcs_free(server->pkcs);
- if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs))
- return FALSE;
- silc_pkcs_public_key_set(server->pkcs, server->public_key);
- silc_pkcs_private_key_set(server->pkcs, server->private_key);
}
/* Check for unconfigured server and router connections and close
SilcPacketStream sock;
sock = silc_server_find_socket_by_host(server, SILC_CONN_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 (sock)
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_rehash_close_connection,
+ sock, 0, 1);
}
}
}
SilcPacketStream sock;
sock = silc_server_find_socket_by_host(server, SILC_CONN_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);
+ if (sock)
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_rehash_close_connection,
+ sock, 0, 1);
}
}
}
sock = silc_server_find_socket_by_host(server, SILC_CONN_CLIENT,
ptr->host, 0);
if (sock)
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rehash_close_connection,
- server, 0, 1, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_rehash_close_connection,
+ sock, 0, 1);
}
}
}
#endif /* SILC_DEBUG */
SILC_LOG_DEBUG(("Server rehashed"));
-#endif /* 0 */
return TRUE;
}
{
SilcDList list;
SilcPacketStream ps;
+ SilcNetListener listener;
SILC_LOG_INFO(("SILC Server shutting down"));
while ((ps = silc_dlist_get(list))) {
SilcIDListData idata = silc_packet_get_context(ps);
+ if (!silc_packet_stream_is_valid(ps))
+ continue;
+
if (idata)
idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
silc_server_free_sock_user_data(server, ps,
"Server is shutting down");
}
- silc_dlist_uninit(list);
+ silc_packet_engine_free_streams_list(list);
}
/* We are not connected to network anymore */
server->standalone = TRUE;
+ silc_dlist_start(server->listeners);
+ while ((listener = silc_dlist_get(server->listeners)))
+ silc_net_close_listener(listener);
+
+ silc_server_http_uninit(server);
+
+ /* Cancel any possible retry timeouts */
+ silc_schedule_task_del_by_callback(server->schedule,
+ silc_server_connect_router);
+ silc_schedule_task_del_by_callback(server->schedule,
+ silc_server_connect_to_router_retry);
+ silc_schedule_task_del_by_callback(server->schedule,
+ silc_server_connect_to_router);
+
silc_schedule_stop(server->schedule);
- silc_schedule_uninit(server->schedule);
- server->schedule = NULL;
SILC_LOG_DEBUG(("Server stopped"));
}
-#if 0
-/* Parses whole packet, received earlier. */
+/* Purge expired client entries from the server */
-SILC_TASK_CALLBACK(silc_server_packet_parse_real)
+SILC_TASK_CALLBACK(silc_server_purge_expired_clients)
{
- SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
- SilcServer server = (SilcServer)parse_ctx->context;
- SilcPacketStream sock = parse_ctx->sock;
- SilcPacket *packet = parse_ctx->packet;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
- int ret;
-
- if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
- SILC_LOG_DEBUG(("Connection is disconnected"));
- goto out;
- }
-
- server->stat.packets_received++;
-
- /* Parse the packet */
- if (parse_ctx->normal)
- ret = silc_packet_parse(packet, idata ? idata->receive_key : NULL);
- else
- ret = silc_packet_parse_special(packet, idata ? idata->receive_key : NULL);
-
- /* If entry is disabled ignore what we got. */
- if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
- ret != SILC_PACKET_HEARTBEAT && ret != SILC_PACKET_RESUME_ROUTER &&
- ret != SILC_PACKET_REKEY && ret != SILC_PACKET_REKEY_DONE &&
- ret != SILC_PACKET_KEY_EXCHANGE_1 && ret != SILC_PACKET_KEY_EXCHANGE_2) {
- SILC_LOG_DEBUG(("Connection is disabled (packet %s dropped)",
- silc_get_packet_name(ret)));
- goto out;
- }
-
- if (ret == SILC_PACKET_NONE) {
- SILC_LOG_DEBUG(("Error parsing packet"));
- goto out;
- }
-
- /* Check that the the current client ID is same as in the client's packet. */
- if (sock->type == SILC_CONN_CLIENT) {
- SilcClientEntry client = (SilcClientEntry)sock->user_data;
- 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)) {
- silc_free(id);
- SILC_LOG_DEBUG(("Packet source is not same as sender"));
- goto out;
- }
- silc_free(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->dst_id && !(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
- packet->dst_id_type == SILC_ID_SERVER &&
- sock->type != SILC_CONN_CLIENT &&
- memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
- SilcPacketStream conn;
-
- /* Route the packet to fastest route for the destination ID */
- void *id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!id)
- goto out;
+ SilcServer server = context;
+ SilcClientEntry client;
+ SilcIDList id_list;
+ SilcUInt64 curtime = silc_time();
- conn = silc_server_route_get(server, id, packet->dst_id_type);
- if (!conn) {
- SILC_LOG_WARNING(("Packet to unknown server ID %s, dropped (no route)",
- silc_id_render(id, SILC_ID_SERVER)));
- goto out;
- }
+ SILC_LOG_DEBUG(("Expire timeout"));
- silc_server_packet_route(server, conn, packet);
- silc_free(id);
- goto out;
- }
- }
+ silc_dlist_start(server->expired_clients);
+ while ((client = silc_dlist_get(server->expired_clients))) {
+ if (client->data.status & SILC_IDLIST_STATUS_REGISTERED)
+ continue;
- /* Parse the incoming packet type */
- silc_server_packet_parse_type(server, sock, packet);
+ /* For unregistered clients the created timestamp is actually
+ unregistered timestamp. Make sure client remains in history
+ at least 500 seconds. */
+ if (curtime - client->data.created < 500)
+ continue;
- /* Broadcast packet if it is marked as broadcast packet and it is
- originated from router and we are router. */
- if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_CONN_ROUTER &&
- packet->flags & SILC_PACKET_FLAG_BROADCAST) {
- /* Broadcast to our primary route */
- silc_server_packet_broadcast(server, SILC_PRIMARY_ROUTE(server), packet);
+ id_list = (client->data.status & SILC_IDLIST_STATUS_LOCAL ?
+ server->local_list : server->global_list);
- /* If we have backup routers then we need to feed all broadcast
- data to those servers. */
- silc_server_backup_broadcast(server, sock, packet);
+ silc_idlist_del_data(client);
+ silc_idlist_del_client(id_list, client);
+ silc_dlist_del(server->expired_clients, client);
}
- out:
- silc_packet_context_free(packet);
- silc_free(parse_ctx);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_purge_expired_clients, server,
+ 120, 0);
}
-#endif /* 0 */
/******************************* Connecting *********************************/
/* Free connection context */
-static void silc_server_connection_free(SilcServerConnection sconn)
+void silc_server_connection_free(SilcServerConnection sconn)
{
+ SILC_LOG_DEBUG(("Free connection %p", sconn));
silc_dlist_del(sconn->server->conns, sconn);
silc_server_config_unref(&sconn->conn);
silc_free(sconn->remote_host);
void silc_server_create_connection(SilcServer server,
SilcBool reconnect,
+ SilcBool dynamic,
const char *remote_host, SilcUInt32 port,
SilcServerConnectCallback callback,
void *context)
sconn->no_reconnect = reconnect == FALSE;
sconn->callback = callback;
sconn->callback_context = context;
+ sconn->no_conf = dynamic;
+ sconn->server = server;
+
+ SILC_LOG_DEBUG(("Created connection %p", sconn));
silc_schedule_task_add_timeout(server->schedule, silc_server_connect_router,
sconn, 0, 0);
SilcServerConfigServer *conn;
SilcServerConfigConnParams *param;
SilcIDListData idata;
- SilcServerEntry id_entry;
+ SilcServerEntry id_entry = NULL;
unsigned char id[32];
SilcUInt32 id_len;
SilcID remote_id;
+ const char *ip;
+
+ SILC_LOG_DEBUG(("Connection %p authentication completed, entry %p",
+ sconn, entry));
- SILC_LOG_DEBUG(("Connection authentication completed"));
+ entry->op = NULL;
if (success == FALSE) {
/* Authentication failed */
silc_server_disconnect_remote(server, sconn->sock,
SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_free_sock_user_data(server, sconn->sock, NULL);
+ silc_server_connection_free(sconn);
return;
}
+ /* XXX For now remote is router always */
+ entry->data.conn_type = SILC_CONN_ROUTER;
+
SILC_LOG_INFO(("Connected to %s %s",
SILC_CONNTYPE_STRING(entry->data.conn_type),
sconn->remote_host));
if (!id_entry) {
silc_server_disconnect_remote(server, sconn->sock,
SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_free_sock_user_data(server, sconn->sock, NULL);
silc_server_connection_free(sconn);
silc_free(entry);
return;
}
+ /* Statistics */
+ server->stat.my_servers++;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.servers++;
+ SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers));
+
silc_idlist_add_data(id_entry, (SilcIDListData)entry);
break;
SILC_STR_END)) {
silc_server_disconnect_remote(server, sconn->sock,
SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_free_sock_user_data(server, sconn->sock, NULL);
silc_server_connection_free(sconn);
silc_free(entry);
return;
as NULL since it's local to us. */
id_entry = silc_idlist_add_server(server->global_list,
strdup(sconn->remote_host),
- SILC_ROUTER, &remote_id.u.server_id,
+ SILC_ROUTER,
+ silc_id_dup(&remote_id.u.server_id,
+ SILC_ID_SERVER),
NULL, sconn->sock);
if (!id_entry) {
silc_server_disconnect_remote(server, sconn->sock,
SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_free_sock_user_data(server, sconn->sock, NULL);
silc_server_connection_free(sconn);
silc_free(entry);
return;
/* Registered */
silc_idlist_add_data(id_entry, (SilcIDListData)entry);
- idata = (SilcIDListData)entry;
+ idata = (SilcIDListData)id_entry;
idata->status |= (SILC_IDLIST_STATUS_REGISTERED |
SILC_IDLIST_STATUS_LOCAL);
+ idata->sconn = sconn;
+
+ /* Statistics */
+ server->stat.my_routers++;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.routers++;
+ SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers));
if (!sconn->backup) {
/* Mark this router our primary router if we're still standalone */
silc_server_announce_channels(server, 0, SILC_PRIMARY_ROUTE(server));
}
-#if 0
/* 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,
+ if (server->server_type == SILC_BACKUP_ROUTER) {
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sconn->
+ sock),
+ NULL, NULL, &ip, NULL);
+ silc_server_backup_add(server, server->id_entry, ip,
sconn->remote_port, TRUE);
+ }
+#if 0
+ } else {
+ /* We already have primary router. Disconnect this connection */
+ SILC_LOG_DEBUG(("We already have primary router, disconnect"));
+ silc_idlist_del_server(server->global_list, id_entry);
+ silc_server_disconnect_remote(server, sconn->sock,
+ SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_connection_free(sconn);
+ silc_free(entry);
+ return;
#endif /* 0 */
}
} else {
default:
silc_server_disconnect_remote(server, sconn->sock,
SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_free_sock_user_data(server, sconn->sock, NULL);
silc_server_connection_free(sconn);
silc_free(entry);
return;
}
+ SILC_LOG_DEBUG(("Connection established, sock %p", sconn->sock));
+
conn = sconn->conn.ref_ptr;
param = &server->config->param;
if (conn && conn->param)
silc_schedule_task_add_timeout(server->schedule, silc_server_do_rekey,
sconn->sock, sconn->rekey_timeout, 0);
-#if 0
- /* Perform keepalive. */
- silc_socket_set_heartbeat(sock, param->keepalive_secs, server,
- silc_server_perform_heartbeat,
- server->schedule);
+ /* Set the entry as packet stream context */
+ silc_packet_set_context(sconn->sock, id_entry);
- out:
/* Call the completion callback to indicate that we've connected to
the router */
if (sconn && sconn->callback)
(*sconn->callback)(server, id_entry, sconn->callback_context);
- /* Free the temporary connection data context */
- if (sconn) {
- silc_server_config_unref(&sconn->conn);
- silc_free(sconn->remote_host);
- silc_free(sconn->backup_replace_ip);
- silc_free(sconn);
- }
if (sconn == server->router_conn)
server->router_conn = NULL;
-#endif /* 0 */
silc_free(entry);
}
SilcSKERekeyMaterial rekey,
void *context)
{
- SilcServerConnection sconn = context;
- SilcUnknownEntry entry = silc_packet_get_context(sconn->sock);
+ SilcPacketStream sock = context;
+ SilcUnknownEntry entry = silc_packet_get_context(sock);
+ SilcServerConnection sconn = silc_ske_get_context(ske);
SilcServer server = entry->server;
SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
SilcAuthMethod auth_meth = SILC_AUTH_NONE;
SilcHmac hmac_send, hmac_receive;
SilcHash hash;
+ SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry));
+
+ entry->op = NULL;
+
if (status != SILC_SKE_STATUS_OK) {
/* SKE failed */
SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
silc_ske_free(ske);
silc_server_disconnect_remote(server, sconn->sock,
SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_free_sock_user_data(server, sconn->sock, NULL);
silc_server_connection_free(sconn);
return;
}
silc_ske_free(ske);
silc_server_disconnect_remote(server, sconn->sock,
SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_free_sock_user_data(server, sconn->sock, NULL);
silc_server_connection_free(sconn);
return;
}
silc_ske_free(ske);
silc_server_disconnect_remote(server, sconn->sock,
SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
+ silc_server_free_sock_user_data(server, sconn->sock, NULL);
silc_server_connection_free(sconn);
return;
}
}
}
+ entry->data.rekey = rekey;
+
/* Start connection authentication */
- silc_connauth_initiator(connauth, server->server_type == SILC_ROUTER ?
- SILC_CONN_ROUTER : SILC_CONN_SERVER, auth_meth,
- auth_data, auth_data_len,
- silc_server_ke_auth_compl, sconn);
+ entry->op =
+ silc_connauth_initiator(connauth, server->server_type == SILC_SERVER ?
+ SILC_CONN_SERVER : SILC_CONN_ROUTER, auth_meth,
+ auth_data, auth_data_len,
+ silc_server_ke_auth_compl, sconn);
}
/* Function that is called when the network connection to a router has
if (!sconn->sock) {
SILC_LOG_ERROR(("Cannot connect: cannot create packet stream"));
silc_stream_destroy(sconn->stream);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
silc_server_connection_free(sconn);
return;
}
if (!silc_packet_set_ids(sconn->sock, SILC_ID_SERVER, server->id,
0, NULL)) {
silc_packet_stream_destroy(sconn->sock);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
silc_server_connection_free(sconn);
return;
}
entry->server = server;
silc_packet_set_context(sconn->sock, entry);
+ SILC_LOG_DEBUG(("Created unknown connection %p", entry));
+
/* Set Key Exchange flags from configuration, but fall back to global
settings too. */
memset(¶ms, 0, sizeof(params));
params.flags |= SILC_SKE_SP_FLAG_PFS;
/* Start SILC Key Exchange protocol */
- SILC_LOG_DEBUG(("Starting key exchange protocol"));
+ SILC_LOG_DEBUG(("Starting key exchange protocol, connection %p", sconn));
ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
- server->public_key, server->private_key, sconn->sock);
+ server->public_key, server->private_key, sconn);
if (!ske) {
silc_free(entry);
silc_packet_stream_destroy(sconn->sock);
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
silc_server_connection_free(sconn);
return;
}
/* Start key exchange protocol */
params.version = silc_version_string;
params.timeout_secs = server->config->key_exchange_timeout;
- silc_ske_initiator(ske, sconn->sock, ¶ms, NULL);
+ entry->op = silc_ske_initiator(ske, sconn->sock, ¶ms, NULL);
}
/* Timeout callback that will be called to retry connecting to remote
if ((sconn->retry_count > param->reconnect_count) &&
!param->reconnect_keep_trying) {
SILC_LOG_ERROR(("Could not connect, giving up"));
+
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
silc_server_connection_free(sconn);
return;
}
switch (status) {
case SILC_NET_OK:
- SILC_LOG_DEBUG(("Connection to %s:%d established",
+ SILC_LOG_DEBUG(("Connection %p to %s:%d established", sconn,
sconn->remote_host, sconn->remote_port));
/* Continue with key exchange protocol */
SILC_LOG_ERROR(("Could not connect to %s:%d: %s",
sconn->remote_host, sconn->remote_port,
silc_net_get_error_string(status)));
+
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
silc_server_connection_free(sconn);
break;
silc_schedule_task_add_timeout(sconn->server->schedule,
silc_server_connect_to_router_retry,
sconn, 1, 0);
+ silc_dlist_del(server->conns, sconn);
} else {
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
silc_server_connection_free(sconn);
}
break;
/* Don't connect if we are shutting down. */
if (server->server_shutdown) {
+ if (sconn->callback)
+ (*sconn->callback)(server, NULL, sconn->callback_context);
silc_server_connection_free(sconn);
return;
}
(sconn->backup ? "backup router" : "router"),
sconn->remote_host, sconn->remote_port));
- if (!server->no_conf) {
+ if (!sconn->no_conf) {
/* Find connection configuration */
rconn = silc_server_config_find_router_conn(server, sconn->remote_host,
sconn->remote_port);
"normal server" : server->server_type == SILC_ROUTER ?
"router" : "backup router/normal server")));
- /* XXX */
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. */
return;
}
+ /* Cancel any possible retry timeouts */
+ silc_schedule_task_del_by_callback(server->schedule,
+ silc_server_connect_router);
+ silc_schedule_task_del_by_callback(server->schedule,
+ silc_server_connect_to_router_retry);
+
/* Create the connections to all our routes */
for (ptr = server->config->routers; ptr; ptr = ptr->next) {
if (!ptr->initiator)
continue;
+ if (ptr->dynamic_connection)
+ continue;
/* Check whether we are connecting or connected to this host already */
if (silc_server_num_sockets_by_remote(server,
silc_net_is_ip(ptr->host) ?
ptr->host : NULL,
silc_net_is_ip(ptr->host) ?
- NULL : ptr->host, ptr->port)) {
+ NULL : ptr->host, ptr->port,
+ SILC_CONN_ROUTER)) {
SILC_LOG_DEBUG(("We are already connected to %s:%d",
ptr->host, ptr->port));
if (!sock)
continue;
server->backup_noswitch = TRUE;
-#if 0
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
silc_server_disconnect_remote(server, sock, 0, NULL);
-#endif /* 0 */
server->backup_noswitch = FALSE;
SILC_LOG_DEBUG(("Reconnecting to primary router"));
} else {
sconn = silc_calloc(1, sizeof(*sconn));
if (!sconn)
continue;
+ sconn->server = server;
sconn->remote_host = strdup(ptr->host);
sconn->remote_port = ptr->port;
sconn->backup = ptr->backup_router;
sconn->backup_replace_port = ptr->backup_replace_port;
}
- /* XXX */
+ SILC_LOG_DEBUG(("Created connection %p", sconn));
+
if (!server->router_conn && !sconn->backup)
server->router_conn = sconn;
if (cconfig->publickeys)
*repository = server->repository;
- entry->data.conn_type = conn_type;
+ if (cconfig->publickeys) {
+ if (server->config->prefer_passphrase_auth) {
+ *repository = NULL;
+ } else {
+ *passphrase = NULL;
+ *passphrase_len = 0;
+ }
+ }
+
+ entry->conn_type = conn_type;
return TRUE;
}
/* Remote end is server */
if (conn_type == SILC_CONN_SERVER) {
- SilcServerConfigServer *sconfig = entry->sconfig.ref_ptr;
+ SilcServerConfigServer *sconfig;
+
+ /* If we are normal server, don't accept the connection */
+ if (server->server_type == SILC_SERVER)
+ return FALSE;
+
+ sconfig = entry->sconfig.ref_ptr;
if (!sconfig)
return FALSE;
if (sconfig->publickeys)
*repository = server->repository;
- entry->data.conn_type = conn_type;
+ if (sconfig->publickeys) {
+ if (server->config->prefer_passphrase_auth) {
+ *repository = NULL;
+ } else {
+ *passphrase = NULL;
+ *passphrase_len = 0;
+ }
+ }
+
+ entry->conn_type = conn_type;
return TRUE;
}
if (rconfig->publickeys)
*repository = server->repository;
- entry->data.conn_type = conn_type;
+ if (rconfig->publickeys) {
+ if (server->config->prefer_passphrase_auth) {
+ *repository = NULL;
+ } else {
+ *passphrase = NULL;
+ *passphrase_len = 0;
+ }
+ }
+
+ entry->conn_type = conn_type;
return TRUE;
}
SilcUnknownEntry entry = silc_packet_get_context(sock);
SilcIDListData idata = (SilcIDListData)entry;
SilcServer server = entry->server;
- SilcServerConfigConnParams *param;
+ SilcServerConfigConnParams *param = &server->config->param;
SilcServerConnection sconn;
void *id_entry;
- const char *hostname;
+ const char *hostname, *ip;
SilcUInt16 port;
+ entry->op = NULL;
silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
- NULL, &hostname, NULL, &port);
+ NULL, &hostname, &ip, &port);
if (success == FALSE) {
/* Authentication failed */
server->stat.auth_failures++;
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
SILC_LOG_DEBUG(("Checking whether connection is allowed"));
- switch (entry->data.conn_type) {
+ switch (entry->conn_type) {
case SILC_CONN_CLIENT:
{
SilcClientEntry client;
SilcServerConfigClient *conn = entry->cconfig.ref_ptr;
/* Verify whether this connection is after all allowed to connect */
- if (!silc_server_connection_allowed(server, sock, entry->data.conn_type,
+ if (!silc_server_connection_allowed(server, sock, entry->conn_type,
&server->config->param,
conn->param,
silc_connauth_get_ske(connauth))) {
SILC_STATUS_ERR_PERM_DENIED,
"We do not have connection to backup "
"router established, try later");
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_server_free_sock_user_data(server, sock, NULL);
server->stat.auth_failures++;
/* From here on, wait 20 seconds for the backup router to appear. */
server->stat.auth_failures++;
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
+ entry->data.conn_type = SILC_CONN_CLIENT;
/* Statistics */
server->stat.my_clients++;
}
/* Add public key to repository */
+ SILC_LOG_DEBUG(("Add client public key to repository"));
if (!silc_server_get_public_key_by_client(server, client, NULL))
silc_skr_add_public_key_simple(server->repository,
entry->data.public_key,
- SILC_SKR_USAGE_IDENTIFICATION, client);
+ SILC_SKR_USAGE_IDENTIFICATION, client,
+ NULL);
id_entry = (void *)client;
break;
SilcBool backup_router = FALSE;
char *backup_replace_ip = NULL;
SilcUInt16 backup_replace_port = 0;
- SilcServerConfigServer *sconn = entry->sconfig.ref_ptr;
+ SilcServerConfigServer *srvconn = entry->sconfig.ref_ptr;
SilcServerConfigRouter *rconn = entry->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 &&
- entry->data.conn_type == SILC_CONN_SERVER &&
+ entry->conn_type == SILC_CONN_SERVER &&
!SILC_PRIMARY_ROUTE(server)) {
SILC_LOG_INFO(("Will not accept server connection because we do "
"not have primary router connection established"));
SILC_STATUS_ERR_PERM_DENIED,
"We do not have connection to primary "
"router established, try later");
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_server_free_sock_user_data(server, sock, NULL);
server->stat.auth_failures++;
goto out;
}
- if (entry->data.conn_type == SILC_CONN_ROUTER) {
+ if (entry->conn_type == SILC_CONN_ROUTER) {
/* Verify whether this connection is after all allowed to connect */
if (!silc_server_connection_allowed(server, sock,
- entry->data.conn_type,
+ entry->conn_type,
&server->config->param,
rconn ? rconn->param : NULL,
silc_connauth_get_ske(connauth))) {
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
server->stat.auth_failures++;
goto out;
}
}
}
- if (entry->data.conn_type == SILC_CONN_SERVER) {
+ if (entry->conn_type == SILC_CONN_SERVER) {
/* Verify whether this connection is after all allowed to connect */
if (!silc_server_connection_allowed(server, sock,
- entry->data.conn_type,
+ entry->conn_type,
&server->config->param,
- sconn ? sconn->param : NULL,
+ srvconn ? srvconn->param : NULL,
silc_connauth_get_ske(connauth))) {
server->stat.auth_failures++;
goto out;
}
- if (sconn) {
- if (sconn->param) {
- param = sconn->param;
+ if (srvconn) {
+ if (srvconn->param) {
+ param = srvconn->param;
if (!param->keepalive_secs)
param->keepalive_secs = server->config->param.keepalive_secs;
}
}
- backup_router = sconn->backup_router;
+ backup_router = srvconn->backup_router;
}
}
/* 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 0
if (server->wait_backup && server->server_type == SILC_ROUTER &&
!server->backup_router && !backup_router) {
SilcServerConfigRouter *router;
SILC_STATUS_ERR_PERM_DENIED,
"We do not have connection to backup "
"router established, try later");
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_server_free_sock_user_data(server, sock, NULL);
server->stat.auth_failures++;
/* From here on, wait 20 seconds for the backup router to appear. */
goto out;
}
}
-#endif /* 0 */
SILC_LOG_DEBUG(("Remote host is %s",
- entry->data.conn_type == SILC_CONN_SERVER ?
+ entry->conn_type == SILC_CONN_SERVER ?
"server" : (backup_router ?
"backup router" : "router")));
SILC_LOG_INFO(("Connection %s (%s) is %s", entry->hostname,
- entry->ip, entry->data.conn_type == SILC_CONN_SERVER ?
+ entry->ip, entry->conn_type == SILC_CONN_SERVER ?
"server" : (backup_router ?
"backup router" : "router")));
server. We mark ourselves as router for this server if we really
are router. */
new_server =
- silc_idlist_add_server((entry->data.conn_type == SILC_CONN_SERVER ?
+ silc_idlist_add_server((entry->conn_type == SILC_CONN_SERVER ?
server->local_list : (backup_router ?
server->local_list :
server->global_list)),
NULL,
- (entry->data.conn_type == SILC_CONN_SERVER ?
+ (entry->conn_type == SILC_CONN_SERVER ?
SILC_SERVER : SILC_ROUTER),
NULL,
- (entry->data.conn_type == SILC_CONN_SERVER ?
+ (entry->conn_type == SILC_CONN_SERVER ?
server->id_entry : (backup_router ?
server->id_entry : NULL)),
sock);
SILC_LOG_ERROR(("Could not add new server to cache"));
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_server_free_sock_user_data(server, sock, NULL);
server->stat.auth_failures++;
goto out;
}
entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
+ entry->data.conn_type = entry->conn_type;
id_entry = (void *)new_server;
if (entry->data.conn_type == SILC_CONN_SERVER) {
server->stat.my_servers++;
server->stat.servers++;
+ SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers));
} else {
server->stat.my_routers++;
server->stat.routers++;
+ SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers));
}
/* Check whether this connection is to be our primary router connection
sconn->remote_port = port;
silc_dlist_add(server->conns, sconn);
idata->sconn = sconn;
+ idata->last_receive = time(NULL);
/* Add the common data structure to the ID entry. */
silc_idlist_add_data(id_entry, (SilcIDListData)entry);
silc_packet_set_context(sock, id_entry);
/* Connection has been fully established now. Everything is ok. */
- SILC_LOG_DEBUG(("New connection authenticated"));
-
-
-#if 0
- /* Perform keepalive. */
- if (param->keepalive_secs)
- silc_socket_set_heartbeat(sock, param->keepalive_secs, server,
- silc_server_perform_heartbeat,
- server->schedule);
+ SILC_LOG_DEBUG(("New connection %p authenticated", sconn));
/* Perform Quality of Service */
if (param->qos)
- silc_socket_set_qos(sock, param->qos_rate_limit, param->qos_bytes_limit,
- param->qos_limit_sec, param->qos_limit_usec,
- server->schedule);
-#endif
+ silc_socket_stream_set_qos(silc_packet_stream_get_stream(sock),
+ param->qos_rate_limit, param->qos_bytes_limit,
+ param->qos_limit_sec, param->qos_limit_usec);
silc_server_config_unref(&entry->cconfig);
silc_server_config_unref(&entry->sconfig);
SilcCipher send_key, receive_key;
SilcHmac hmac_send, hmac_receive;
SilcHash hash;
+ unsigned char *pk;
+ SilcUInt32 pk_len;
+
+ entry->op = NULL;
if (status != SILC_SKE_STATUS_OK) {
/* SKE failed */
silc_ske_free(ske);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_server_free_sock_user_data(server, sock, NULL);
return;
}
silc_ske_free(ske);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+ silc_server_free_sock_user_data(server, sock, NULL);
return;
}
silc_packet_set_keys(sock, send_key, receive_key, hmac_send,
idata->rekey = rekey;
idata->public_key = silc_pkcs_public_key_copy(prop->public_key);
+ pk = silc_pkcs_public_key_encode(idata->public_key, &pk_len);
+ silc_hash_make(server->sha1hash, pk, pk_len, idata->fingerprint);
+
+ silc_hash_alloc(silc_hash_get_name(prop->hash), &idata->hash);
SILC_LOG_DEBUG(("Starting connection authentication"));
server->stat.auth_attempts++;
silc_ske_free(ske);
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ silc_server_config_unref(&entry->cconfig);
+ silc_server_config_unref(&entry->sconfig);
+ silc_server_config_unref(&entry->rconfig);
+ silc_server_free_sock_user_data(server, sock, NULL);
return;
}
/* Start connection authentication */
- silc_connauth_responder(connauth, silc_server_accept_get_auth,
- silc_server_accept_auth_compl, sock);
+ entry->op =
+ silc_connauth_responder(connauth, silc_server_accept_get_auth,
+ silc_server_accept_auth_compl, sock);
}
/* Accept new TCP connection */
/* Check for maximum allowed connections */
server->stat.conn_attempts++;
-#if 0
- if (silc_server_num_connections(server) >
+ if (silc_dlist_count(server->conns) >
server->config->param.connections_max) {
SILC_LOG_ERROR(("Refusing connection, server is full"));
server->stat.conn_failures++;
silc_stream_destroy(stream);
return;
}
-#endif
/* Get hostname, IP and port */
if (!silc_socket_stream_get_info(stream, NULL, (const char **)&hostname,
}
server->stat.conn_num++;
+ SILC_LOG_DEBUG(("Created packet stream %p", packet_stream));
+
/* Set source ID to packet stream */
if (!silc_packet_set_ids(packet_stream, SILC_ID_SERVER, server->id,
0, NULL)) {
silc_server_disconnect_remote(server, packet_stream,
SILC_STATUS_ERR_BANNED_FROM_SERVER,
deny->reason);
+ silc_server_free_sock_user_data(server, packet_stream, NULL);
return;
}
server->stat.conn_failures++;
silc_server_disconnect_remote(server, packet_stream,
SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL);
+ silc_server_free_sock_user_data(server, packet_stream, NULL);
return;
}
server->stat.conn_failures++;
silc_server_disconnect_remote(server, packet_stream,
SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ silc_server_free_sock_user_data(server, packet_stream, NULL);
return;
}
entry->hostname = hostname;
entry->ip = ip;
entry->port = port;
entry->server = server;
+ entry->data.conn_type = SILC_CONN_UNKNOWN;
silc_packet_set_context(packet_stream, entry);
+ SILC_LOG_DEBUG(("Created unknown connection %p", entry));
+
silc_server_config_ref(&entry->cconfig, server->config, cconfig);
silc_server_config_ref(&entry->sconfig, server->config, sconfig);
silc_server_config_ref(&entry->rconfig, server->config, rconfig);
server->stat.conn_failures++;
silc_server_disconnect_remote(server, packet_stream,
SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+ silc_server_free_sock_user_data(server, packet_stream, NULL);
return;
}
silc_ske_set_callbacks(ske, silc_server_verify_key,
/* Start key exchange protocol */
params.version = silc_version_string;
params.timeout_secs = server->config->key_exchange_timeout;
- silc_ske_responder(ske, packet_stream, ¶ms);
+ entry->op = silc_ske_responder(ske, packet_stream, ¶ms);
}
SilcIDListData idata = silc_packet_get_context(sock);
SilcSKE ske;
+ SILC_LOG_DEBUG(("Perform rekey, sock %p", sock));
+
/* Do not execute rekey with disabled connections */
if (idata->status & SILC_IDLIST_STATUS_DISABLED)
return;
SILC_CONNTYPE_STRING(idata->conn_type)));
/* Allocate SKE */
- ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
- server->public_key, server->private_key, sock);
+ ske = silc_ske_alloc(server->rng, server->schedule, NULL,
+ server->public_key, NULL, sock);
if (!ske)
return;
SilcIDListData idata = silc_packet_get_context(sock);
SilcSKE ske;
- SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]",
+ SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s], sock %p",
idata->sconn->remote_host, idata->sconn->remote_port,
- SILC_CONNTYPE_STRING(idata->conn_type)));
+ SILC_CONNTYPE_STRING(idata->conn_type), sock));
/* Allocate SKE */
- ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
- server->public_key, server->private_key, sock);
+ ske = silc_ske_alloc(server->rng, server->schedule, NULL,
+ server->public_key, NULL, sock);
if (!ske) {
silc_packet_free(packet);
return;
SILC_TASK_CALLBACK(silc_server_close_connection_final)
{
- silc_packet_stream_destroy(context);
+ silc_packet_stream_unref(context);
}
/* Closes connection to socket connection */
const char *hostname;
SilcUInt16 port;
-#if 0
- /* If any protocol is active cancel its execution. It will call
- the final callback which will finalize the disconnection. */
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type != SILC_PROTOCOL_SERVER_BACKUP) {
- SILC_LOG_DEBUG(("Cancelling protocol, calling final callback"));
- silc_protocol_cancel(sock->protocol, server->schedule);
- sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute_final(sock->protocol, server->schedule);
- sock->protocol = NULL;
+ if (!silc_packet_stream_is_valid(sock))
return;
- }
-#endif
memset(tmp, 0, sizeof(tmp));
// silc_socket_get_error(sock, tmp, sizeof(tmp));
silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
NULL, &hostname, NULL, &port);
SILC_LOG_INFO(("Closing connection %s:%d [%s] %s", hostname, port,
- SILC_CONNTYPE_STRING(idata->conn_type),
+ idata ? SILC_CONNTYPE_STRING(idata->conn_type) : "",
tmp[0] ? tmp : ""));
// silc_socket_set_qos(sock, 0, 0, 0, 0, NULL);
+ if (idata && idata->sconn) {
+ silc_server_connection_free(idata->sconn);
+ idata->sconn = NULL;
+ }
+
+ /* Take a reference and then destroy the stream. The last reference
+ is released later in a timeout callback. */
+ silc_packet_stream_ref(sock);
+ silc_packet_stream_destroy(sock);
+
/* Close connection with timeout */
server->stat.conn_num--;
+ silc_schedule_task_del_by_all(server->schedule, 0,
+ silc_server_close_connection_final, sock);
silc_schedule_task_add_timeout(server->schedule,
silc_server_close_connection_final,
sock, 0, 1);
if (!sock)
return;
- SILC_LOG_DEBUG(("Disconnecting remote host"));
+ SILC_LOG_DEBUG(("Disconnecting remote host, sock %p", sock));
va_start(ap, status);
cp = va_arg(ap, char *);
silc_server_close_connection(server, sock);
}
-SILC_TASK_CALLBACK(silc_server_free_client_data_timeout)
-{
- SilcClientEntry client = context;
-
- assert(!silc_hash_table_count(client->channels));
-
- silc_idlist_del_data(client);
- // silc_idcache_purge_by_context(server->local_list->clients, client);
-}
-
/* Frees client data and notifies about client's signoff. */
void silc_server_free_client_data(SilcServer server,
int notify,
const char *signoff)
{
- SILC_LOG_DEBUG(("Freeing client data"));
+ SILC_LOG_DEBUG(("Freeing client %p data", client));
if (client->id) {
/* Check if anyone is watching this nickname */
/* Remove this client from watcher list if it is */
silc_server_del_from_watcher_list(server, client);
- /* Remove this client from the public key hash list */
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key, client);
+ /* Remove client's public key from repository, this will free it too. */
+ if (client->data.public_key) {
+ silc_skr_del_public_key(server->repository, client->data.public_key,
+ client);
+ client->data.public_key = NULL;
+ }
/* Update statistics */
server->stat.my_clients--;
SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
silc_schedule_task_del_by_context(server->schedule, client);
+ if (client->data.sconn) {
+ silc_server_connection_free(client->data.sconn);
+ client->data.sconn = NULL;
+ }
+
/* We will not delete the client entry right away. We will take it
into history (for WHOWAS command) for 5 minutes, unless we're
shutting down server. */
if (!server->server_shutdown) {
- silc_schedule_task_add_timeout(server->schedule,
- silc_server_free_client_data_timeout,
- client, 600, 0);
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
- client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
client->mode = 0;
client->router = NULL;
client->connection = NULL;
+ client->data.created = silc_time();
+ silc_dlist_add(server->expired_clients, client);
} else {
/* Delete directly since we're shutting down server */
+ SILC_LOG_DEBUG(("Delete client directly"));
silc_idlist_del_data(client);
silc_idlist_del_client(server->local_list, client);
}
const char *signoff_message)
{
SilcIDListData idata = silc_packet_get_context(sock);
+ const char *ip;
+ SilcUInt16 port;
+
+ SILC_LOG_DEBUG(("Start, sock %p", sock));
if (!idata)
return;
+ silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_rekey,
+ sock);
+
+ /* Cancel active protocols */
+ if (idata) {
+ if (idata->sconn && idata->sconn->op) {
+ SILC_LOG_DEBUG(("Abort active protocol"));
+ silc_async_abort(idata->sconn->op, NULL, NULL);
+ }
+ if (idata->conn_type == SILC_CONN_UNKNOWN &&
+ ((SilcUnknownEntry)idata)->op) {
+ SILC_LOG_DEBUG(("Abort active protocol"));
+ silc_async_abort(((SilcUnknownEntry)idata)->op, NULL, NULL);
+ }
+ }
+
switch (idata->conn_type) {
case SILC_CONN_CLIENT:
{
SilcClientEntry client_entry = (SilcClientEntry)idata;
silc_server_free_client_data(server, sock, client_entry, TRUE,
signoff_message);
+ silc_packet_set_context(sock, NULL);
break;
}
SilcServerEntry user_data = (SilcServerEntry)idata;
SilcServerEntry backup_router = NULL;
- SILC_LOG_DEBUG(("Freeing server data"));
+ SILC_LOG_DEBUG(("Freeing server %p data", user_data));
if (user_data->id)
backup_router = silc_server_backup_get(server, user_data->id);
if (server->server_shutdown || server->backup_noswitch)
backup_router = NULL;
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, NULL, &ip, &port);
+
/* If this was our primary router connection then we're lost to
the outside world. */
if (server->router == user_data) {
/* We stop here to take a breath */
sleep(2);
-#if 0
if (server->backup_router) {
server->server_type = SILC_ROUTER;
/* We'll need to constantly try to reconnect to the primary
router so that we'll see when it comes back online. */
- silc_server_backup_reconnect(server, sock->ip, sock->port,
+ silc_server_create_connection(server, FALSE, FALSE, ip, port,
silc_server_backup_connected,
NULL);
}
-#endif /* 0 */
/* Mark this connection as replaced */
silc_server_backup_replaced_add(server, user_data->id,
}
server->backup_noswitch = FALSE;
- /* Free the server entry */
- silc_server_backup_del(server, user_data);
- silc_server_backup_replaced_del(server, user_data);
- silc_idlist_del_data(user_data);
- if (!silc_idlist_del_server(server->local_list, user_data))
- silc_idlist_del_server(server->global_list, user_data);
+ if (idata->sconn)
+ silc_server_connection_free(idata->sconn);
+
+ /* Statistics */
if (idata->conn_type == SILC_CONN_SERVER) {
server->stat.my_servers--;
server->stat.servers--;
- } else {
+ SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers));
+ } else if (idata->conn_type == SILC_CONN_ROUTER) {
server->stat.my_routers--;
server->stat.routers--;
+ SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers));
}
if (server->server_type == SILC_ROUTER)
server->stat.cell_servers--;
+ /* Free the server entry */
+ silc_server_backup_del(server, user_data);
+ silc_server_backup_replaced_del(server, user_data);
+ silc_idlist_del_data(user_data);
+ if (!silc_idlist_del_server(server->local_list, user_data))
+ silc_idlist_del_server(server->global_list, user_data);
+
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. */
silc_server_announce_channels(server, time(0) - 300,
backup_router->connection);
}
+
+ silc_packet_set_context(sock, NULL);
break;
}
{
SilcUnknownEntry entry = (SilcUnknownEntry)idata;
- SILC_LOG_DEBUG(("Freeing unknown connection data"));
+ SILC_LOG_DEBUG(("Freeing unknown connection data %p", entry));
+ if (idata->sconn) {
+ silc_server_connection_free(idata->sconn);
+ idata->sconn = NULL;
+ }
silc_idlist_del_data(idata);
silc_free(entry);
+ silc_packet_set_context(sock, NULL);
break;
}
}
return TRUE;
}
-#if 0
-/* Timeout callback. This is called if connection is idle or for some
- other reason is not responding within some period of time. This
- disconnects the remote end. */
-
-SILC_TASK_CALLBACK(silc_server_timeout_remote)
-{
- SilcServer server = (SilcServer)context;
- SilcPacketStream sock = server->sockets[fd];
-
- SILC_LOG_DEBUG(("Start"));
-
- if (!sock)
- return;
-
- SILC_LOG_ERROR(("No response from %s (%s), Connection timeout",
- sock->hostname, sock->ip));
-
- /* If we have protocol active we must assure that we call the protocol's
- final callback so that all the memory is freed. */
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type != SILC_PROTOCOL_SERVER_BACKUP) {
- protocol = sock->protocol->protocol->type;
- silc_protocol_cancel(sock->protocol, server->schedule);
- sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute_final(sock->protocol, server->schedule);
- sock->protocol = NULL;
- return;
- }
-
- silc_server_disconnect_remote(server, sock,
- protocol ==
- SILC_PROTOCOL_SERVER_CONNECTION_AUTH ?
- SILC_STATUS_ERR_AUTH_FAILED :
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED,
- "Connection timeout");
-
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
-}
-#endif /* 0 */
-
/* Creates new channel. Sends NEW_CHANNEL packet to primary route. This
function may be used only by router. In real SILC network all channels
are created by routers thus this function is never used by normal
if (!client->connection && !client->router)
continue;
+ SILC_LOG_DEBUG(("Announce Client ID %s",
+ silc_id_render(client->id, SILC_ID_CLIENT)));
+
idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
*clients = silc_buffer_realloc(*clients,
{
SilcBuffer list, idp, idp2, tmp2;
SilcUInt32 type;
+ void *ptype;
SilcHashTableList htl;
const unsigned char a[1] = { 0x03 };
type = silc_hash_table_count(channel->invite_list);
SILC_PUT16_MSB(type, list->data);
silc_hash_table_list(channel->invite_list, &htl);
- while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
- list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
- type);
+ while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2))
+ list = silc_argument_payload_encode_one(list, tmp2->data,
+ silc_buffer_len(tmp2),
+ SILC_PTR_TO_32(ptype));
silc_hash_table_list_reset(&htl);
idp2 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
type = silc_hash_table_count(channel->ban_list);
SILC_PUT16_MSB(type, list->data);
silc_hash_table_list(channel->ban_list, &htl);
- while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
- list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
- type);
+ while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2))
+ list = silc_argument_payload_encode_one(list, tmp2->data,
+ silc_buffer_len(tmp2),
+ SILC_PTR_TO_32(ptype));
silc_hash_table_list_reset(&htl);
*ban =
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
clidp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
+ SILC_LOG_DEBUG(("JOIN Client %s", silc_id_render(chl->client->id,
+ SILC_ID_CLIENT)));
+
/* JOIN Notify */
tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_JOIN, 2,
clidp->data,
else
announce = TRUE;
+ SILC_LOG_DEBUG(("Announce Channel ID %s",
+ silc_id_render(channel->id, SILC_ID_CHANNEL)));
+
silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &id_len);
name_len = strlen(channel->channel_name);
/* Assembles user list and users mode list from the `channel'. */
SilcBool silc_server_get_users_on_channel(SilcServer server,
- SilcChannelEntry channel,
- SilcBuffer *user_list,
- SilcBuffer *mode_list,
- SilcUInt32 *user_count)
+ SilcChannelEntry channel,
+ SilcBuffer *user_list,
+ SilcBuffer *mode_list,
+ SilcUInt32 *user_count)
{
SilcChannelClientEntry chl;
SilcHashTableList htl;
SILC_LOG_DEBUG(("Retrieving stats from router"));
server->stat.commands_sent++;
idp = silc_id_payload_encode(server->router->id, SILC_ID_SERVER);
- packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
- ++server->cmd_ident, 1,
- 1, idp->data,
- silc_buffer_len(idp));
- silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
- SILC_PACKET_COMMAND, 0, packet->data,
- silc_buffer_len(packet));
- silc_buffer_free(packet);
- silc_buffer_free(idp);
+ if (idp) {
+ packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
+ ++server->cmd_ident, 1,
+ 1, idp->data,
+ silc_buffer_len(idp));
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ SILC_PACKET_COMMAND, 0, packet->data,
+ silc_buffer_len(packet));
+ silc_buffer_free(packet);
+ silc_buffer_free(idp);
+ }
}
silc_schedule_task_add_timeout(server->schedule, silc_server_get_stats,