Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2008 Pekka Riikonen
+ Copyright (C) 1997 - 2009 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
SILC_LOG_DEBUG(("Verifying public key"));
- if (silc_pkcs_get_type(public_key) != SILC_SKE_PK_TYPE_SILC) {
+ if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) {
SILC_LOG_WARNING(("We don't support %s (%s) port %d public key type %d",
entry->hostname, entry->ip, entry->port,
silc_pkcs_get_type(public_key)));
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) {
- if (idata->sconn && idata->sconn->callback)
+ if (idata && idata->sconn && idata->sconn->callback)
(*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
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 &&
+ if (idata &&
+ 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;
}
- if (idata->sconn && idata->sconn->callback)
+ if (idata && idata->sconn && idata->sconn->callback)
(*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
silc_server_free_sock_user_data(server, stream, NULL);
}
SilcPacketStream stream = context;
SilcIDListData idata = silc_packet_get_context(stream);
- if (!idata)
+ if (!idata || !silc_packet_stream_is_valid(stream)) {
+ silc_packet_stream_unref(stream);
return;
+ }
if (server->router_conn && server->router_conn->sock == stream &&
!server->router && server->standalone) {
+ if (idata->sconn && idata->sconn->callback)
+ (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
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) {
+ 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_close_connection(server, stream);
+
+ /* Release our stream reference */
+ silc_packet_stream_unref(stream);
}
/* Packet engine callback to indicate error */
const char *ip;
SilcUInt16 port;
- SILC_LOG_DEBUG(("Packet error, sock %p", stream));
+ SILC_LOG_DEBUG(("Packet error %d, sock %p", error, stream));
if (!idata || !sock)
return;
if (!silc_packet_stream_is_valid(stream))
return;
+ /* We must take reference of the stream */
+ silc_packet_stream_ref(stream);
+
+ /* In case we get here many times, register only one timeout */
+ silc_schedule_task_del_by_all(server->schedule, 0,
+ silc_server_packet_error_timeout, stream);
+
+ /* Close connection with random timeout */
silc_schedule_task_add_timeout(server->schedule,
silc_server_packet_error_timeout, stream,
- silc_rng_get_byte(server->rng) % 5, 0);
+ silc_rng_get_byte(server->rng) % 10, 0);
}
/* Packet stream callbacks */
{
SilcPacketType type = packet->type;
SilcIDListData idata = silc_packet_get_context(sock);
+#ifdef SILC_DEBUG
+ const char *ip;
+ SilcUInt16 port;
+
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, NULL, &ip, &port);
+#endif /* SILC_DEBUG */
- SILC_LOG_DEBUG(("Received %s packet [flags %d]",
- silc_get_packet_name(type), packet->flags));
+ SILC_LOG_DEBUG(("Received %s packet [flags %d] from %s:%d",
+ silc_get_packet_name(type), packet->flags, ip, port));
/* Parse the packet type */
switch (type) {
case SILC_PACKET_KEY_AGREEMENT:
/*
- * Received heartbeat.
+ * Received key agreement.
*/
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
entry->data.conn_type = SILC_CONN_CLIENT;
/* Statistics */
+ SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
+ server->stat.clients + 1));
server->stat.my_clients++;
server->stat.clients++;
server->stat.cell_clients++;
SilcBool initiator = FALSE;
SilcBool backup_local = FALSE;
SilcBool backup_router = FALSE;
- char *backup_replace_ip = NULL;
- SilcUInt16 backup_replace_port = 0;
SilcServerConfigServer *srvconn = entry->sconfig.ref_ptr;
SilcServerConfigRouter *rconn = entry->rconfig.ref_ptr;
initiator = rconn->initiator;
backup_local = rconn->backup_local;
backup_router = rconn->backup_router;
- backup_replace_ip = rconn->backup_replace_ip;
- backup_replace_port = rconn->backup_replace_port;
}
}
/* Add connection to server->conns so that we know we have connection
to this peer. */
sconn = silc_calloc(1, sizeof(*sconn));
+ if (!sconn)
+ goto out;
sconn->server = server;
sconn->sock = sock;
sconn->remote_host = strdup(hostname);
param->qos_rate_limit, param->qos_bytes_limit,
param->qos_limit_sec, param->qos_limit_usec);
+ /* Perform heartbeat */
+ if (param->keepalive_secs) {
+ SILC_LOG_DEBUG(("Perform heartbeat every %d seconds",
+ param->keepalive_secs));
+ silc_schedule_task_add_timeout(server->schedule, silc_server_do_heartbeat,
+ sock, param->keepalive_secs, 0);
+ }
+
silc_server_config_unref(&entry->cconfig);
silc_server_config_unref(&entry->sconfig);
silc_server_config_unref(&entry->rconfig);
entry->op = silc_ske_responder(ske, packet_stream, ¶ms);
}
+/* Perform heartbeat */
+
+SILC_TASK_CALLBACK(silc_server_do_heartbeat)
+{
+ SilcServer server = app_context;
+ SilcPacketStream sock = context;
+ silc_server_send_heartbeat(server, sock);
+}
+
/********************************** Rekey ***********************************/
silc_packet_free(packet);
return;
}
+ if (idata->conn_type == SILC_CONN_UNKNOWN) {
+ silc_packet_free(packet);
+ return;
+ }
SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s], sock %p",
idata->sconn->remote_host, idata->sconn->remote_port,
if (!sock)
return;
- SILC_LOG_DEBUG(("Disconnecting remote host, sock %p", sock));
+ silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_rekey,
+ sock);
+ silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_heartbeat,
+ sock);
+
+ SILC_LOG_DEBUG(("Disconnecting remote host, sock %p, status %d", sock,
+ status));
va_start(ap, status);
cp = va_arg(ap, char *);
/* Local detached clients aren't counted. */
if (!client->local_detached)
server->stat.my_clients--;
+ SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
+ server->stat.clients - 1));
SILC_VERIFY(server->stat.clients > 0);
server->stat.clients--;
if (server->stat.cell_clients)
silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_rekey,
sock);
+ silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_heartbeat,
+ 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);
+ idata->sconn->op = 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);
+ ((SilcUnknownEntry)idata)->op = NULL;
}
}
if (server->server_type == SILC_ROUTER) {
if (!channel->rekey)
channel->rekey = silc_calloc(1, sizeof(*channel->rekey));
+ if (!channel->rekey) {
+ memset(channel->key, 0, channel->key_len / 8);
+ silc_free(channel->key);
+ silc_cipher_free(channel->send_key);
+ silc_cipher_free(channel->receive_key);
+ channel->send_key = channel->receive_key = NULL;
+ return FALSE;
+ }
channel->rekey->channel = channel;
channel->rekey->key_len = key_len;
if (channel->rekey->task)
silc_cipher_free(channel->send_key);
silc_cipher_free(channel->receive_key);
channel->send_key = channel->receive_key = NULL;
- return FALSE;
+ return NULL;
}
silc_hash_make(silc_hmac_get_hash(channel->hmac), tmp, tmp_len, hash);
silc_hmac_set_key(channel->hmac, hash,
if (server->server_type == SILC_ROUTER) {
if (!channel->rekey)
channel->rekey = silc_calloc(1, sizeof(*channel->rekey));
+ if (!channel->rekey) {
+ memset(channel->key, 0, channel->key_len / 8);
+ silc_free(channel->key);
+ silc_cipher_free(channel->send_key);
+ silc_cipher_free(channel->receive_key);
+ channel->send_key = channel->receive_key = NULL;
+ return NULL;
+ }
channel->rekey->channel = channel;
if (channel->rekey->task)
silc_schedule_task_del(server->schedule, channel->rekey->task);
}
client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+
+ SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
+ server->stat.clients + 1));
+ server->stat.clients++;
}
if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
- SILC_LOG_ERROR(("Attempting to add unregistered client to channel ",
+ SILC_LOG_ERROR(("Attempting to add unregistered client to channel "
"%s", channel->channel_name));
continue;
}
if (!silc_server_client_on_channel(client, channel, &chl)) {
/* Client was not on the channel, add it. */
chl = silc_calloc(1, sizeof(*chl));
+ if (!chl)
+ continue;
chl->client = client;
chl->mode = mode;
chl->channel = channel;
/* Add the client on the channel */
if (!silc_server_client_on_channel(client, channel, &chl)) {
chl = silc_calloc(1, sizeof(*chl));
+ if (!chl)
+ continue;
chl->client = client;
chl->mode = chumodes[i++];
chl->channel = channel;
buffer = silc_buffer_realloc(buffer,
(buffer ?
silc_buffer_truelen(buffer) + len : len));
+ if (!buffer)
+ return NULL;
silc_buffer_pull_tail(buffer, (buffer->end - buffer->data));
silc_buffer_format(buffer,
SILC_STR_UI_SHORT(name_len),
silc_buffer_realloc(*user_mode_list,
(*user_mode_list ?
silc_buffer_truelen((*user_mode_list)) + 4 : 4));
+ if (!(*user_mode_list))
+ return NULL;
silc_buffer_pull_tail(*user_mode_list, ((*user_mode_list)->end -
(*user_mode_list)->data));
SILC_PUT32_MSB(chl->mode, (*user_mode_list)->data);