void silc_server_free(SilcServer server)
{
- if (server) {
+ if (!server)
+ return;
+
#ifdef SILC_SIM
+ {
SilcSim sim;
-
+
while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
silc_dlist_del(server->sim, sim);
silc_sim_free(sim);
}
silc_dlist_uninit(server->sim);
+ }
#endif
- silc_server_config_unref(&server->config_ref);
- if (server->rng)
- silc_rng_free(server->rng);
- if (server->pkcs)
- silc_pkcs_free(server->pkcs);
- if (server->public_key)
- silc_pkcs_public_key_free(server->public_key);
- if (server->private_key)
- silc_pkcs_private_key_free(server->private_key);
- if (server->pending_commands)
- silc_dlist_uninit(server->pending_commands);
- if (server->id_entry)
- silc_idlist_del_server(server->local_list, server->id_entry);
-
- 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->clients);
- silc_idcache_free(server->global_list->servers);
- silc_idcache_free(server->global_list->channels);
- silc_hash_table_free(server->watcher_list);
-
- silc_free(server->sockets);
- silc_free(server);
- }
+ silc_server_config_unref(&server->config_ref);
+ if (server->rng)
+ silc_rng_free(server->rng);
+ if (server->pkcs)
+ silc_pkcs_free(server->pkcs);
+ if (server->public_key)
+ silc_pkcs_public_key_free(server->public_key);
+ if (server->private_key)
+ silc_pkcs_private_key_free(server->private_key);
+ if (server->pending_commands)
+ silc_dlist_uninit(server->pending_commands);
+ if (server->id_entry)
+ silc_idlist_del_server(server->local_list, server->id_entry);
+
+ 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->clients);
+ silc_idcache_free(server->global_list->servers);
+ silc_idcache_free(server->global_list->channels);
+ silc_hash_table_free(server->watcher_list);
+
+ 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_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);
}
-/* Opens a listening port.
- XXX This function will become more general and will support multiple
- listening ports */
+/* Creates a new server listener. */
-static bool silc_server_listen(SilcServer server, int *sock)
+static bool silc_server_listen(SilcServer server, const char *server_ip,
+ SilcUInt16 port, int *sock)
{
-
- *sock = silc_net_create_server(server->config->server_info->port,
- server->config->server_info->server_ip);
+ *sock = silc_net_create_server(port, server_ip);
if (*sock < 0) {
SILC_LOG_ERROR(("Could not create server listener: %s on %hu",
- server->config->server_info->server_ip,
- server->config->server_info->port));
+ server_ip, port));
return FALSE;
}
return TRUE;
}
+/* Adds a secondary listener. */
+
+bool silc_server_init_secondary(SilcServer server)
+{
+ int sock = 0, sock_list[server->config->param.connections_max];
+ SilcSocketConnection newsocket = NULL;
+ SilcServerConfigServerInfoInterface *interface;
+
+ 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_SOCKET_TYPE_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);
+ }
+
+ return TRUE;
+
+ err:
+ do silc_net_close_server(sock_list[sock--]); while (sock >= 0);
+ return FALSE;
+}
+
/* Initializes the entire SILC server. This is called always before running
the server. This is called only once at the initialization of the program.
This binds the server to its listenning port. After this function returns
goto err;
/* Create a listening server */
- if (!silc_server_listen(server, &sock))
+ if (!silc_server_listen(server,
+ server->config->server_info->primary == NULL ? NULL :
+ server->config->server_info->primary->server_ip,
+ server->config->server_info->primary == NULL ? 0 :
+ server->config->server_info->primary->port,
+ &sock))
goto err;
/* Set socket to non-blocking mode */
is sent as argument for fast referencing in the future. */
silc_socket_alloc(sock, SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
server->sockets[sock] = newsocket;
+ SILC_SET_LISTENER(newsocket);
/* Perform name and address lookups to resolve the listenning address
and port. */
server->id = id;
server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER);
- server->id_type = SILC_ID_SERVER;
server->server_name = server->config->server_info->server_name;
server->config->server_info->server_name = NULL;
(void *)server, 0, 0,
SILC_TASK_FD,
SILC_TASK_PRI_NORMAL);
+
+ if (silc_server_init_secondary(server) == FALSE)
+ goto err;
+
server->listenning = TRUE;
/* If server connections has been configured then we must be router as
and removes the expired cache entries. */
/* Clients local list */
- purge = silc_calloc(1, sizeof(*purge));
+ server->purge_i = purge = silc_calloc(1, sizeof(*purge));
purge->cache = server->local_list->clients;
purge->schedule = server->schedule;
purge->timeout = 600;
SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
/* Clients global list */
- purge = silc_calloc(1, sizeof(*purge));
+ server->purge_g = purge = silc_calloc(1, sizeof(*purge));
purge->cache = server->global_list->clients;
purge->schedule = server->schedule;
purge->timeout = 300;
server, 10, 0, SILC_TASK_TIMEOUT,
SILC_TASK_PRI_LOW);
+ if (server->server_type == SILC_ROUTER)
+ server->stat.routers++;
+
SILC_LOG_DEBUG(("Server initialized"));
/* We are done here, return succesfully */
SILC_LOG_DEBUG(("Stopping server"));
if (server->schedule) {
+ int i;
+
+ /* Close all connections */
+ for (i = 0; i < server->config->param.connections_max; i++) {
+ if (!server->sockets[i])
+ continue;
+ if (!SILC_IS_LISTENER(server->sockets[i])) {
+ silc_schedule_task_del_by_context(server->schedule,
+ server->sockets[i]);
+ silc_server_disconnect_remote(server, server->sockets[i],
+ SILC_STATUS_OK,
+ "Server is shutting down");
+ } else {
+ silc_socket_free(server->sockets[i]);
+ server->sockets[i] = NULL;
+ }
+ }
+
+ /* We are not connected to network anymore */
+ server->standalone = TRUE;
+
silc_schedule_stop(server->schedule);
silc_schedule_uninit(server->schedule);
server->schedule = NULL;
+
+ silc_free(server->sockets);
+ server->sockets = NULL;
}
silc_server_protocols_unregister();
/* Cancel any possible retry timeouts */
silc_schedule_task_del_by_callback(server->schedule,
- silc_server_connect_router);
+ silc_server_connect_to_router_retry);
/* Set socket options */
silc_net_set_socket_nonblock(sock);
return;
}
+ SILC_LOG_DEBUG(("Retrying connecting to a router in %d seconds",
+ sconn->retry_timeout));
+
/* We will lookup a fresh pointer later */
silc_server_config_unref(&sconn->conn);
silc_server_config_ref(&sconn->conn, server->config, (void *)rconn);
/* Connect to remote host */
- sock = silc_net_create_connection(server->config->server_info->server_ip,
- sconn->remote_port,
- sconn->remote_host);
+ sock = silc_net_create_connection(
+ (!server->config->server_info->primary ? NULL :
+ server->config->server_info->primary->server_ip),
+ sconn->remote_port, sconn->remote_host);
if (sock < 0) {
SILC_LOG_ERROR(("Could not connect to router %s:%d",
sconn->remote_host, sconn->remote_port));
/* If we are router then announce our possible servers. */
if (server->server_type == SILC_ROUTER)
silc_server_announce_servers(server, FALSE, 0,
- server->router->connection);
+ SILC_PRIMARY_ROUTE(server));
/* Announce our clients and channels to the router */
- silc_server_announce_clients(server, 0, server->router->connection);
- silc_server_announce_channels(server, 0, server->router->connection);
+ 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 */
silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
void *context)
{
- SilcServer server = (SilcServer)context;
- SilcServerKEInternalContext *proto_ctx;
+ SilcServerKEInternalContext *proto_ctx =
+ (SilcServerKEInternalContext *)context;
+ SilcServer server = (SilcServer)proto_ctx->server;
SilcServerConfigClient *cconfig = NULL;
SilcServerConfigServer *sconfig = NULL;
SilcServerConfigRouter *rconfig = NULL;
SilcServerConfigDeny *deny;
int port;
- SILC_LOG_DEBUG(("Start"));
+ context = (void *)server;
/* Check whether we could resolve both IP and FQDN. */
if (!sock->ip || (!strcmp(sock->ip, sock->hostname) &&
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
"Unknown host or IP");
+ silc_free(proto_ctx);
return;
}
SILC_LOG_INFO(("Incoming connection %s (%s)", sock->hostname,
sock->ip));
- port = server->sockets[server->sock]->port; /* Listenning port */
+ /* Listenning port */
+ if (!server->sockets[(SilcUInt32)proto_ctx->context]) {
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_RESOURCE_LIMIT,
+ "Connection refused");
+ server->stat.conn_failures++;
+ silc_free(proto_ctx);
+ return;
+ }
+ port = server->sockets[(SilcUInt32)proto_ctx->context]->port;
/* Check whether this connection is denied to connect to us. */
deny = silc_server_config_find_denied(server, sock->ip);
/* The connection is denied */
SILC_LOG_INFO(("Connection %s (%s) is denied",
sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock,
+ silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BANNED_FROM_SERVER,
deny->reason);
server->stat.conn_failures++;
+ silc_free(proto_ctx);
return;
}
sconfig = silc_server_config_find_server_conn(server, sock->hostname);
if (server->server_type == SILC_ROUTER) {
if (!(rconfig = silc_server_config_find_router_conn(server,
- sock->ip, port)))
+ sock->ip, sock->port)))
rconfig = silc_server_config_find_router_conn(server, sock->hostname,
sock->port);
}
SILC_LOG_INFO(("Connection %s (%s) is not allowed", sock->hostname,
sock->ip));
silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_BANNED_FROM_SERVER);
+ SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL);
server->stat.conn_failures++;
+ silc_free(proto_ctx);
return;
}
/* The connection is allowed */
- /* Allocate internal context for key exchange protocol. This is
+ /* Set internal context for key exchange protocol. This is
sent as context for the protocol. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->server = context;
proto_ctx->sock = sock;
proto_ctx->rng = server->rng;
proto_ctx->responder = TRUE;
initiator of the protocol thus we will wait for initiation from
there before we start the protocol. */
server->stat.auth_attempts++;
+ SILC_LOG_DEBUG(("Starting key exchange protocol"));
silc_protocol_alloc(SILC_PROTOCOL_SERVER_KEY_EXCHANGE,
&sock->protocol, proto_ctx,
silc_server_accept_new_connection_second);
proto_ctx->timeout_task =
silc_schedule_task_add(server->schedule, sock->sock,
silc_server_timeout_remote,
- context, server->config->key_exchange_timeout, 0,
+ (void *)server,
+ server->config->key_exchange_timeout, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_LOW);
}
{
SilcServer server = (SilcServer)context;
SilcSocketConnection newsocket;
+ SilcServerKEInternalContext *proto_ctx;
int sock;
SILC_LOG_DEBUG(("Accepting new connection"));
server->stat.conn_attempts++;
- sock = silc_net_accept_connection(server->sock);
+ sock = silc_net_accept_connection(fd);
if (sock < 0) {
SILC_LOG_ERROR(("Could not accept new connection: %s", strerror(errno)));
server->stat.conn_failures++;
/* Perform asynchronous host lookup. This will lookup the IP and the
FQDN of the remote connection. After the lookup is done the connection
is accepted further. */
+ proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
+ proto_ctx->server = server;
+ proto_ctx->context = (void *)fd;
silc_socket_host_lookup(newsocket, TRUE,
- silc_server_accept_new_connection_lookup, context,
- server->schedule);
+ silc_server_accept_new_connection_lookup,
+ (void *)proto_ctx, server->schedule);
}
/* Second part of accepting new connection. Key exchange protocol has been
if ((protocol->state == SILC_PROTOCOL_STATE_ERROR) ||
(protocol->state == SILC_PROTOCOL_STATE_FAILURE)) {
/* Error occured during protocol */
+ SILC_LOG_DEBUG(("Error key exchange protocol"));
silc_protocol_free(protocol);
sock->protocol = NULL;
silc_ske_free_key_material(ctx->keymat);
ctx->ske->prop->hmac,
ctx->ske->prop->group,
ctx->responder)) {
+ SILC_LOG_ERROR(("Error setting key material in use"));
silc_protocol_free(protocol);
sock->protocol = NULL;
silc_ske_free_key_material(ctx->keymat);
but we won't start it yet. We will be receiving party of this
protocol thus we will wait that connecting party will make
their first move. */
+ SILC_LOG_DEBUG(("Starting connection authentication protocol"));
silc_protocol_alloc(SILC_PROTOCOL_SERVER_CONNECTION_AUTH,
&sock->protocol, proto_ctx,
silc_server_accept_new_connection_final);
void *id_entry;
SilcUInt32 hearbeat_timeout = server->config->param.keepalive_secs;
- SILC_LOG_DEBUG(("Start"));
-
if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
/* Error occured during protocol */
+ SILC_LOG_DEBUG(("Error during authentication protocol"));
silc_protocol_free(protocol);
sock->protocol = NULL;
if (ctx->packet)
server->stat.auth_failures++;
goto out;
}
+ entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
/* Statistics */
server->stat.my_clients++;
server->stat.auth_failures++;
goto out;
}
+ entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
/* Statistics */
- if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER)
+ if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) {
server->stat.my_servers++;
- else
+ } else {
server->stat.my_routers++;
+ server->stat.routers++;
+ }
server->stat.servers++;
id_entry = (void *)new_server;
/* Check whether this connection is to be our primary router connection
if we do not already have the primary route. */
- if (server->standalone && ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) {
+ if (!backup_router &&
+ server->standalone && ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) {
if (silc_server_config_is_primary_route(server) && !initiator)
break;
SilcUInt32 sequence = 0;
int ret;
- if (!sock)
+ if (!sock) {
+ SILC_LOG_DEBUG(("Unknown socket connection"));
return;
-
- SILC_LOG_DEBUG(("Processing packet"));
+ }
/* Packet sending */
if (type == SILC_TASK_WRITE) {
/* Do not send data to disconnected connection */
- if (SILC_IS_DISCONNECTED(sock))
+ if (SILC_IS_DISCONNECTED(sock)) {
+ SILC_LOG_DEBUG(("Disconnected socket connection, cannot send"));
return;
+ }
server->stat.packets_sent++;
return;
}
- server->stat.packets_received++;
-
/* Get keys and stuff from ID entry */
idata = (SilcIDListData)sock->user_data;
if (idata) {
SilcIDListData idata = (SilcIDListData)sock->user_data;
int ret;
- SILC_LOG_DEBUG(("Start"));
+ server->stat.packets_received++;
/* Parse the packet */
if (parse_ctx->normal)
goto out;
}
- if (ret == SILC_PACKET_NONE)
+ 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_SOCKET_TYPE_CLIENT) {
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);
/* Parse the incoming packet type */
silc_server_packet_parse_type(server, sock, packet);
- if (server->server_type == SILC_ROUTER) {
- /* Broadcast packet if it is marked as broadcast packet and it is
- originated from router and we are router. */
- if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
- packet->flags & SILC_PACKET_FLAG_BROADCAST &&
- !server->standalone) {
- /* Broadcast to our primary route */
- silc_server_packet_broadcast(server, server->router->connection, packet);
-
- /* If we have backup routers then we need to feed all broadcast
- data to those servers. */
- silc_server_backup_broadcast(server, sock, packet);
- }
+ /* 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_SOCKET_TYPE_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, sock, packet);
}
out:
SilcPacketType type = packet->type;
SilcIDListData idata = (SilcIDListData)sock->user_data;
- SILC_LOG_DEBUG(("Parsing packet type %d", type));
+ SILC_LOG_DEBUG(("Received %s packet [flags %d]",
+ silc_get_packet_name(type), packet->flags));
/* Parse the packet type */
switch (type) {
SilcStatus status;
char *message = NULL;
- SILC_LOG_DEBUG(("Disconnect packet"));
-
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
if (packet->buffer->len < 1)
status = (SilcStatus)packet->buffer->data[0];
if (packet->buffer->len > 1 &&
silc_utf8_valid(packet->buffer->data + 1, packet->buffer->len - 1))
- message = silc_memdup(packet->buffer->data, packet->buffer->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,
* one protocol for connection executing at once hence this
* success message is for whatever protocol is executing currently.
*/
- SILC_LOG_DEBUG(("Success packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
if (sock->protocol)
* one protocol for connection executing at once hence this
* failure message is for whatever protocol is executing currently.
*/
- SILC_LOG_DEBUG(("Failure packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
if (sock->protocol) {
break;
case SILC_PACKET_REJECT:
- SILC_LOG_DEBUG(("Reject packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
return;
* Received notify packet. Server can receive notify packets from
* router. Server then relays the notify messages to clients if needed.
*/
- SILC_LOG_DEBUG(("Notify packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
silc_server_notify_list(server, sock, packet);
else
* (although probably most common ones) thus they are handled
* specially.
*/
- SILC_LOG_DEBUG(("Channel Message packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
idata->last_receive = time(NULL);
* locally connected clients on the particular channel. Router
* never receives this channel and thus is ignored.
*/
- SILC_LOG_DEBUG(("Channel Key packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_channel_key(server, sock, packet);
* Recived command. Processes the command request and allocates the
* command context and calls the command.
*/
- SILC_LOG_DEBUG(("Command packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_command_process(server, sock, packet);
* may be reply to command sent by us or reply to command sent by client
* that we've routed further.
*/
- SILC_LOG_DEBUG(("Command Reply packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_command_reply(server, sock, packet);
* Received private message packet. The packet is coming from either
* client or server.
*/
- SILC_LOG_DEBUG(("Private Message packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
idata->last_receive = time(NULL);
* Key Exchange protocol packets
*/
case SILC_PACKET_KEY_EXCHANGE:
- SILC_LOG_DEBUG(("KE packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
break;
case SILC_PACKET_KEY_EXCHANGE_1:
- SILC_LOG_DEBUG(("KE 1 packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
break;
case SILC_PACKET_KEY_EXCHANGE_2:
- SILC_LOG_DEBUG(("KE 2 packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
* authentication method for the connection. This packet maybe received
* at any time.
*/
- SILC_LOG_DEBUG(("Connection authentication request packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_connection_auth_request(server, sock, packet);
case SILC_PACKET_CONNECTION_AUTH:
/* Start of the authentication protocol. We receive here the
authentication data and will verify it. */
- SILC_LOG_DEBUG(("Connection auth packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
* to distribute information about new registered entities in the
* SILC network.
*/
- SILC_LOG_DEBUG(("New ID packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
silc_server_new_id_list(server, sock, packet);
else
* we will use to create initial client ID. After creating new
* ID we will send it to the client.
*/
- SILC_LOG_DEBUG(("New Client packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_new_client(server, sock, packet);
* information that we may save. This is received after server has
* connected to us.
*/
- SILC_LOG_DEBUG(("New Server packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_new_server(server, sock, packet);
* Received new channel packet. Information about new channel in the
* network are distributed using this packet.
*/
- SILC_LOG_DEBUG(("New Channel packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
silc_server_new_channel_list(server, sock, packet);
else
/*
* Received heartbeat.
*/
- SILC_LOG_DEBUG(("Heartbeat packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
break;
/*
* Received heartbeat.
*/
- SILC_LOG_DEBUG(("Key agreement packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_key_agreement(server, sock, packet);
* Received re-key packet. The sender wants to regenerate the session
* keys.
*/
- SILC_LOG_DEBUG(("Re-key packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_rekey(server, sock, packet);
/*
* The re-key is done.
*/
- SILC_LOG_DEBUG(("Re-key done packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
case SILC_PACKET_FTP:
/* FTP packet */
- SILC_LOG_DEBUG(("FTP packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_ftp(server, sock, packet);
case SILC_PACKET_RESUME_CLIENT:
/* Resume client */
- SILC_LOG_DEBUG(("Resume Client packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_resume_client(server, sock, packet);
case SILC_PACKET_RESUME_ROUTER:
/* Resume router packet received. This packet is received for backup
router resuming protocol. */
- SILC_LOG_DEBUG(("Resume router packet"));
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
silc_server_backup_resume_router(server, sock, packet);
SILC_LOG_ERROR(("Incorrect packet type %d, packet dropped", type));
break;
}
-
}
/* Creates connection to a remote router. */
void silc_server_close_connection(SilcServer server,
SilcSocketConnection sock)
{
- if (!server->sockets[sock->sock])
+ if (!server->sockets[sock->sock] && SILC_IS_DISCONNECTED(sock)) {
+ silc_socket_free(sock);
return;
+ }
SILC_LOG_INFO(("Closing connection %s:%d [%s]", sock->hostname,
sock->port,
/* If any protocol is active cancel its execution. It will call
the final callback which will finalize the disconnection. */
if (sock->protocol) {
+ 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);
{
FreeClientInternal i = silc_calloc(1, sizeof(*i));
+ SILC_LOG_DEBUG(("Freeing client data"));
+
+#if 1
+ if (!client->router && !client->connection &&
+ !(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
+ SILC_LOG_ERROR(("****** freeing data for already unregistered client -s"));
+ SILC_LOG_ERROR(("****** Contact Pekka"));
+ SILC_LOG_ERROR(("****** freeing data for already unregistered client -e"));
+ return;
+ }
+#endif
+
/* If there is pending outgoing data for the client then purge it
to the network before removing the client entry. */
silc_server_packet_queue_purge(server, sock);
SILC_NOTIFY_TYPE_SIGNOFF);
/* Send SIGNOFF notify to routers. */
- if (notify && !server->standalone && server->router)
- silc_server_send_notify_signoff(server, server->router->connection,
- server->server_type == SILC_SERVER ?
- FALSE : TRUE, client->id, signoff);
-
- /* Remove client from all channels */
if (notify)
- silc_server_remove_from_channels(server, NULL, client,
- TRUE, (char *)signoff, TRUE);
- else
- silc_server_remove_from_channels(server, NULL, client,
- FALSE, NULL, FALSE);
-
- /* Remove this client from watcher list if it is */
- silc_server_del_from_watcher_list(server, client);
+ silc_server_send_notify_signoff(server, SILC_PRIMARY_ROUTE(server),
+ SILC_BROADCAST(server), client->id,
+ signoff);
}
+ /* Remove client from all channels */
+ if (notify)
+ silc_server_remove_from_channels(server, NULL, client,
+ TRUE, (char *)signoff, TRUE);
+ else
+ silc_server_remove_from_channels(server, NULL, client,
+ FALSE, NULL, FALSE);
+
+ /* Remove this client from watcher list if it is */
+ silc_server_del_from_watcher_list(server, client);
+
/* Update statistics */
server->stat.my_clients--;
server->stat.clients--;
SilcSocketConnection sock,
const char *signoff_message)
{
- SILC_LOG_DEBUG(("Start"));
-
switch (sock->type) {
case SILC_SOCKET_TYPE_CLIENT:
{
SilcServerEntry user_data = (SilcServerEntry)sock->user_data;
SilcServerEntry backup_router = NULL;
+ SILC_LOG_DEBUG(("Freeing server data"));
+
if (user_data->id)
backup_router = silc_server_backup_get(server, user_data->id);
backup_router->server_name));
SILC_LOG_DEBUG(("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
+ if (server->id_entry != backup_router) {
+#endif /* BACKUP_SINGLE_ROUTER */
+ server->id_entry->router = backup_router;
+ server->router = backup_router;
+ server->router_connect = time(0);
+ server->backup_primary = TRUE;
+#ifdef BACKUP_SINGLE_ROUTER
+ } else {
+ server->id_entry->router = NULL;
+ server->router = NULL;
+ server->standalone = TRUE;
+ }
+#endif /* BACKUP_SINGLE_ROUTER */
+
if (server->server_type == SILC_BACKUP_ROUTER) {
server->server_type = SILC_ROUTER;
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);
- server->stat.my_servers--;
+ if (sock->type == SILC_SOCKET_TYPE_SERVER) {
+ server->stat.my_servers--;
+ } else {
+ server->stat.my_routers--;
+ server->stat.routers--;
+ }
server->stat.servers--;
if (server->server_type == SILC_ROUTER)
server->stat.cell_servers--;
{
SilcUnknownEntry user_data = (SilcUnknownEntry)sock->user_data;
+ SILC_LOG_DEBUG(("Freeing unknown connection data"));
+
silc_idlist_del_data(user_data);
silc_free(user_data);
break;
/* If any protocol is active cancel its execution */
if (sock->protocol) {
+ 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);
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcHashTableList htl;
- SilcBuffer clidp;
-
- SILC_LOG_DEBUG(("Start"));
+ SilcBuffer clidp = NULL;
- if (!client || !client->id)
+ if (!client)
return;
- clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- if (!clidp)
+ SILC_LOG_DEBUG(("Removing client from joined channels"));
+
+ if (notify && !client->id)
notify = FALSE;
+ if (notify) {
+ clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ if (!clidp)
+ notify = FALSE;
+ }
+
/* Remove the client from all channels. The client is removed from
the channels' user list. */
silc_hash_table_list(client->channels, &htl);
channel->global_users = FALSE;
silc_free(chl);
- server->stat.my_chanclients--;
+
+ /* Update statistics */
+ if (SILC_IS_LOCAL(client))
+ server->stat.my_chanclients--;
+ if (server->server_type == SILC_ROUTER) {
+ server->stat.cell_chanclients--;
+ server->stat.chanclients--;
+ }
/* If there is not at least one local user on the channel then we don't
need the channel entry anymore, we can remove it safely, unless the
}
silc_hash_table_list_reset(&htl);
- silc_buffer_free(clidp);
+ if (clidp)
+ silc_buffer_free(clidp);
}
/* Removes client from one channel. This is used for example when client
channel->global_users = FALSE;
silc_free(chl);
- server->stat.my_chanclients--;
+
+ /* Update statistics */
+ if (SILC_IS_LOCAL(client))
+ server->stat.my_chanclients--;
+ if (server->server_type == SILC_ROUTER) {
+ server->stat.cell_chanclients--;
+ server->stat.chanclients--;
+ }
clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
if (!clidp)
SilcCipher key;
SilcHmac newhmac;
- SILC_LOG_DEBUG(("Creating new channel"));
+ SILC_LOG_DEBUG(("Creating new channel %s", channel_name));
if (!cipher)
cipher = SILC_DEFAULT_CIPHER;
/* Notify other routers about the new channel. We send the packet
to our primary route. */
- if (broadcast && server->standalone == FALSE)
- silc_server_send_new_channel(server, server->router->connection, TRUE,
+ if (broadcast)
+ silc_server_send_new_channel(server, SILC_PRIMARY_ROUTE(server), TRUE,
channel_name, entry->id,
silc_id_get_len(entry->id, SILC_ID_CHANNEL),
entry->mode);
- server->stat.my_channels++;
+ /* Distribute to backup routers */
+ if (broadcast && server->server_type == SILC_ROUTER) {
+ SilcBuffer packet;
+ unsigned char *cid;
+ SilcUInt32 name_len = strlen(channel_name);
+ SilcUInt32 channel_id_len = silc_id_get_len(entry->id, SILC_ID_CHANNEL);
+ cid = silc_id_id2str(entry->id, SILC_ID_CHANNEL);
+
+ packet = silc_channel_payload_encode(channel_name, name_len,
+ cid, channel_id_len, entry->mode);
+ silc_server_backup_send(server, NULL, SILC_PACKET_NEW_CHANNEL, 0,
+ packet->data, packet->len, FALSE, TRUE);
+ silc_free(cid);
+ silc_buffer_free(packet);
+ }
- if (server->server_type == SILC_ROUTER)
+ server->stat.my_channels++;
+ if (server->server_type == SILC_ROUTER) {
+ server->stat.channels++;
+ server->stat.cell_channels++;
entry->users_resolved = TRUE;
+ }
return entry;
}
SilcCipher key;
SilcHmac newhmac;
- SILC_LOG_DEBUG(("Creating new channel"));
+ SILC_LOG_DEBUG(("Creating new channel %s", channel_name));
if (!cipher)
cipher = SILC_DEFAULT_CIPHER;
/* Notify other routers about the new channel. We send the packet
to our primary route. */
- if (broadcast && server->standalone == FALSE)
- silc_server_send_new_channel(server, server->router->connection, TRUE,
+ if (broadcast)
+ silc_server_send_new_channel(server, SILC_PRIMARY_ROUTE(server), TRUE,
channel_name, entry->id,
silc_id_get_len(entry->id, SILC_ID_CHANNEL),
entry->mode);
- server->stat.my_channels++;
+ /* Distribute to backup routers */
+ if (broadcast && server->server_type == SILC_ROUTER) {
+ SilcBuffer packet;
+ unsigned char *cid;
+ SilcUInt32 name_len = strlen(channel_name);
+ SilcUInt32 channel_id_len = silc_id_get_len(entry->id, SILC_ID_CHANNEL);
+ cid = silc_id_id2str(entry->id, SILC_ID_CHANNEL);
+
+ packet = silc_channel_payload_encode(channel_name, name_len,
+ cid, channel_id_len, entry->mode);
+ silc_server_backup_send(server, NULL, SILC_PACKET_NEW_CHANNEL, 0,
+ packet->data, packet->len, FALSE, TRUE);
+ silc_free(cid);
+ silc_buffer_free(packet);
+ }
- if (server->server_type == SILC_ROUTER)
+ server->stat.my_channels++;
+ if (server->server_type == SILC_ROUTER) {
+ server->stat.channels++;
+ server->stat.cell_channels++;
entry->users_resolved = TRUE;
+ }
return entry;
}
SilcUInt32 tmp_len;
char *cipher;
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Saving new channel key"));
/* Decode channel key payload */
payload = silc_channel_key_payload_parse(key_payload->data,
{
SilcChannelClientEntry chl;
SilcHashTableList htl;
- SilcBuffer chidp, clidp;
+ SilcBuffer chidp, clidp, csidp;
SilcBuffer tmp;
int len;
unsigned char mode[4], *fkey = NULL;
SILC_LOG_DEBUG(("Start"));
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
+ csidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
/* CMODE notify */
- clidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
SILC_PUT32_MSB(channel->mode, mode);
hmac = channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : NULL;
if (channel->founder_key)
fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
tmp =
silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CMODE_CHANGE,
- 6, clidp->data, clidp->len,
+ 6, csidp->data, csidp->len,
mode, sizeof(mode),
NULL, 0,
hmac, hmac ? strlen(hmac) : 0,
silc_buffer_put(*channel_modes, tmp->data, tmp->len);
silc_buffer_pull(*channel_modes, len);
silc_buffer_free(tmp);
- silc_buffer_free(clidp);
silc_free(fkey);
+ fkey = NULL;
+ fkey_len = 0;
/* Now find all users on the channel */
silc_hash_table_list(channel->user_list, &htl);
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && channel->founder_key)
fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CUMODE_CHANGE,
- 4, clidp->data, clidp->len,
- mode, 4,
+ 4, csidp->data, csidp->len,
+ mode, sizeof(mode),
clidp->data, clidp->len,
fkey, fkey_len);
len = tmp->len;
silc_buffer_pull(*channel_users_modes, len);
silc_buffer_free(tmp);
silc_free(fkey);
+ fkey = NULL;
+ fkey_len = 0;
silc_buffer_free(clidp);
}
silc_hash_table_list_reset(&htl);
silc_buffer_free(chidp);
+ silc_buffer_free(csidp);
}
/* Returns assembled packets for all channels and users on those channels
silc_buffer_free(channels);
}
+ if (channel_users) {
+ silc_buffer_push(channel_users, channel_users->data - channel_users->head);
+ SILC_LOG_HEXDUMP(("channel users"), channel_users->data,
+ channel_users->len);
+
+ /* Send the packet */
+ silc_server_packet_send(server, remote,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel_users->data, channel_users->len,
+ FALSE);
+
+ silc_buffer_free(channel_users);
+ }
+
if (channel_modes) {
int i;
silc_free(channel_modes);
}
- if (channel_users) {
- silc_buffer_push(channel_users, channel_users->data - channel_users->head);
- SILC_LOG_HEXDUMP(("channel users"), channel_users->data,
- channel_users->len);
-
- /* Send the packet */
- silc_server_packet_send(server, remote,
- SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- channel_users->data, channel_users->len,
- FALSE);
-
- silc_buffer_free(channel_users);
- }
-
if (channel_users_modes) {
int i;
/* Assembles user list and users mode list from the `channel'. */
-void silc_server_get_users_on_channel(SilcServer server,
+bool silc_server_get_users_on_channel(SilcServer server,
SilcChannelEntry channel,
SilcBuffer *user_list,
SilcBuffer *mode_list,
SilcBuffer idp;
SilcUInt32 list_count = 0, len = 0;
+ if (!silc_hash_table_count(channel->user_list))
+ return FALSE;
+
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl))
len += (silc_id_get_len(chl->client->id, SILC_ID_CLIENT) + 4);
*user_list = client_id_list;
*mode_list = client_mode_list;
*user_count = list_count;
+ return TRUE;
}
/* Saves users and their modes to the `channel'. */
silc_free(id);
if (idata)
*idata = (SilcIDListData)server->router;
- return server->router->connection;
+ return SILC_PRIMARY_ROUTE(server);
}
/* We are router and we will perform route lookup for the destination
server->cmd_ident, 1,
4, idp->data, idp->len);
silc_server_packet_send(server, client ? client->router->connection :
- server->router->connection,
+ SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, 0,
buffer->data, buffer->len, FALSE);
silc_buffer_free(idp);
packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
++server->cmd_ident, 1,
1, idp->data, idp->len);
- silc_server_packet_send(server, server->router->connection,
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_COMMAND, 0, packet->data,
packet->len, FALSE);
silc_buffer_free(packet);