Check that outgoing purge is successful.
Use rekey period as rekey protocol timeout.
+Thu Oct 30 20:23:40 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Check that packet queue purging was successful. Affected
+ files lib/silcclient/client.c and silcd/packet_send.c. Related
+ to MAC failed errors.
+
+ * Do not clear the inbuf even if it is empty if QoS was applied
+ to it. Otherwise the QoS data is cleared and MAC failed error
+ will occur. Affected file lib/silccore/silcpacket.c.
+
+ * Use the rekey period time as rekey protocol timeout value.
+ If the rekey does not succeed during the rekey period there's
+ something very wrong, and we most likely end up with wrong keys,
+ do graceful reconnect then. Affected file silcd/server.c.
+
+ * Take reference of the socket in the parser context, as it's
+ possible to have the parsers in queue after the socket is
+ disconnected and this may cause crash. Affected files are
+ lib/silccore/silcpacket.c, lib/silcclient/client.c and
+ silcd/server.c.
+
Thu Oct 30 17:01:01 EET 2003 Pekka Riikonen <priikone@silcnet.org>
* Fixed KICK command reply sending, it sent to replies.
* Finish the silc-mime.pl script. It now supports MIME type
guessing using magic files, signing data messages, executing
- MIME handlers in background. Affected files
+ MIME handlers in background. Affected files
irssi/scripts/silc-mime.pl and irssi/docs/help/in/mmsg.in
* Changed MIME signal handler to make things easier for the perl
Fri Oct 24 21:24:12 CEST 2003 Jochen Eisinger <jochen@penguin-breeder.org>
- * Fixed race condition between silc_client_init and
+ * Fixed race condition between silc_client_init and
my_silc_scheduler. Affected file irssi/src/silc/core/silc-core.c
Fri Oct 24 16:43:40 EEST 2003 Pekka Riikonen <priikone@silcnet.org>
* Modified the MIME parsing to allow \n and \r\n as delimiters.
Affected files lib/silcutil/silcstrutil.c
-
+
* Cleaned up the escape/unescape functions for correctness and
speed. Affected file irssi/src/silc/core/client_ops.c
* Removed handling for data messages with Content-Type: text/*,
moved parsing of MIME headers to the signal handler, added
- support for signing and verifying data messages. Affected
+ support for signing and verifying data messages. Affected
files are irssi/docs/signals.txt, irssi/src/silc/core/client_ops.c,
irssi/src/silc/core/silc-{servers,channels}.c
* Added a perl script for handling data messages based on
- information read from Mailcap files. New file
+ information read from Mailcap files. New file
irssi/scripts/silc-mime.pl
-
+
Mon Oct 20 16:08:22 EEST 2003 Pekka Riikonen <priikone@silcnet.org>
* Added new SILC_MESSAGE_FLAG_ACK that can be used to
int ret;
/* If disconnecting, ignore the data */
- if (SILC_IS_DISCONNECTING(sock))
+ if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
return -1;
/* Send the packet */
idata = (SilcIDListData)sock->user_data;
/* If disconnecting, ignore the data */
- if (SILC_IS_DISCONNECTING(sock))
+ if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
return;
/* If entry is disabled do not sent anything. Allow hearbeat and
int block_len = 0;
/* If disconnecting, ignore the data */
- if (!sock || SILC_IS_DISCONNECTING(sock))
+ if (!sock || SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
return;
idata = (SilcIDListData)sock->user_data;
}
/* Purge the outgoing packet queue to the network if there is data. This
- function can be used to empty the packet queue. It is guaranteed that
- after this function returns the outgoing data queue is empty. */
+ function can be used to empty the packet queue. */
void silc_server_packet_queue_purge(SilcServer server,
SilcSocketConnection sock)
{
if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
!(SILC_IS_DISCONNECTING(sock)) && !(SILC_IS_DISCONNECTED(sock))) {
+ int ret;
+
SILC_LOG_DEBUG(("Purging outgoing queue"));
+
server->stat.packets_sent++;
- silc_packet_send(sock, TRUE);
+ ret = silc_packet_send(sock, TRUE);
+ if (ret == -2) {
+ if (sock->outbuf && sock->outbuf->len > 0) {
+ /* Couldn't send all data, put the queue back up, we'll send
+ rest later. */
+ SILC_SET_CONNECTION_FOR_OUTPUT(server->schedule, sock->sock);
+ SILC_SET_OUTBUF_PENDING(sock);
+ return;
+ }
+ }
+
+ /* Purged all data */
SILC_UNSET_OUTBUF_PENDING(sock);
SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
silc_buffer_clear(sock->outbuf);
*/
/* Send the REKEY_DONE to indicate we will take new keys into use */
+ silc_server_packet_queue_purge(server, ctx->sock);
silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
0, NULL, 0, FALSE);
/* Send the REKEY_DONE to indicate we will take new keys into use
now. */
+ silc_server_packet_queue_purge(server, ctx->sock);
silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
0, NULL, 0, FALSE);
/* Send the REKEY_DONE to indicate we will take new keys into use
now. */
+ silc_server_packet_queue_purge(server, ctx->sock);
silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
0, NULL, 0, FALSE);
key to the new key since all packets after this packet must
encrypted with the new key. */
silc_server_protocol_rekey_generate_pfs(server, ctx, TRUE);
+ silc_server_packet_queue_purge(server, ctx->sock);
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
silc_server_protocol_rekey_generate_pfs(server, ctx, FALSE);
else
silc_server_protocol_rekey_generate(server, ctx, FALSE);
+ silc_server_packet_queue_purge(server, ctx->sock);
/* Assure that after calling final callback there cannot be pending
executions for this protocol anymore. This just unregisters any
/* Do not send data to disconnected connection */
if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
SILC_LOG_DEBUG(("Disconnected socket connection, cannot send"));
+ SILC_SET_CONNECTION_FOR_INPUT(server->schedule, fd);
+ SILC_UNSET_OUTBUF_PENDING(sock);
+ silc_buffer_clear(sock->outbuf);
return;
}
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 */
out:
silc_packet_context_free(packet);
+ silc_socket_free(parse_ctx->sock);
silc_free(parse_ctx);
}
SilcIDListData idata = (SilcIDListData)sock->user_data;
bool ret;
+ if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+ SILC_LOG_DEBUG(("Connection is disconnected"));
+ silc_socket_free(parser_context->sock);
+ silc_free(parser_context);
+ return FALSE;
+ }
+
if (idata)
idata->psn_receive = parser_context->packet->sequence + 1;
if (sock->protocol && sock->protocol->protocol &&
(sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
+ silc_socket_dup(sock);
silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
parser_context);
+ if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+ SILC_LOG_DEBUG(("Connection is disconnected"));
+ silc_socket_free(sock);
+ return FALSE;
+ }
+ silc_socket_free(sock);
+
/* Reprocess data since we'll return FALSE here. This is because
the idata->receive_key might have become valid in the last packet
and we want to call this processor with valid cipher. */
silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
parser_context);
break;
- default:
- return TRUE;
}
return TRUE;
silc_ske_free(ctx->ske);
silc_socket_free(sock);
silc_free(ctx);
+
+ /* Disconnect since we failed to rekey, the keys are probably wrong. */
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+
+ /* Reconnect */
+ if (sock->type != SILC_SOCKET_TYPE_CLIENT)
+ silc_server_create_connections(server);
}
/* A timeout callback for the re-key. We will be the initiator of the
silc_schedule_task_add(server->schedule, sock->sock,
silc_server_rekey_timeout,
proto_ctx,
- server->config->key_exchange_timeout, 0,
+ (idata->rekey->timeout >
+ server->config->key_exchange_timeout ?
+ idata->rekey->timeout :
+ server->config->key_exchange_timeout * 4), 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_LOW);
if (ret == SILC_PACKET_NONE) {
silc_packet_context_free(packet);
+ silc_socket_free(parser_context->sock);
silc_free(parser_context);
return FALSE;
}
/* Parse the incoming packet type */
silc_client_packet_parse_type(client, sock, packet);
- silc_packet_context_free(packet);
- silc_free(parser_context);
/* Reprocess the buffer since we'll return FALSE. This is because
the `conn->internal->receive_key' might have become valid by processing
silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
silc_client_packet_parse, client);
+ silc_packet_context_free(packet);
+ silc_socket_free(parser_context->sock);
+ silc_free(parser_context);
+
return FALSE;
}
/* Parse the incoming packet type */
silc_client_packet_parse_type(client, sock, packet);
silc_packet_context_free(packet);
+ silc_socket_free(parser_context->sock);
silc_free(parser_context);
return TRUE;
}
SilcSocketConnection sock)
{
if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
- (SILC_IS_DISCONNECTED(sock) == FALSE)) {
- silc_packet_send(sock, TRUE);
+ !(SILC_IS_DISCONNECTED(sock))) {
+ int ret;
+
+ ret = silc_packet_send(sock, TRUE);
+ if (ret == -2) {
+ if (sock->outbuf && sock->outbuf->len > 0) {
+ /* Couldn't send all data, put the queue back up, we'll send
+ rest later. */
+ SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
+ SILC_SET_OUTBUF_PENDING(sock);
+ return;
+ }
+ }
+
+ /* Purged all data */
SILC_UNSET_OUTBUF_PENDING(sock);
SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
silc_buffer_clear(sock->outbuf);
*/
/* Send the REKEY_DONE to indicate we will take new keys into use */
+ silc_client_packet_queue_purge(client, ctx->sock);
silc_client_packet_send(client, ctx->sock,
SILC_PACKET_REKEY_DONE,
NULL, 0, NULL, NULL, NULL, 0, FALSE);
/* Send the REKEY_DONE to indicate we will take new keys into use
now. */
+ silc_client_packet_queue_purge(client, ctx->sock);
silc_client_packet_send(client, ctx->sock,
SILC_PACKET_REKEY_DONE,
NULL, 0, NULL, NULL, NULL, 0, FALSE);
/* Send the REKEY_DONE to indicate we will take new keys into use
now. */
+ silc_client_packet_queue_purge(client, ctx->sock);
silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
NULL, 0, NULL, NULL, NULL, 0, FALSE);
key to the new key since all packets after this packet must
encrypted with the new key. */
silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
+ silc_client_packet_queue_purge(client, ctx->sock);
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
silc_client_protocol_rekey_generate_pfs(client, ctx, FALSE);
else
silc_client_protocol_rekey_generate(client, ctx, FALSE);
+ silc_client_packet_queue_purge(client, ctx->sock);
/* Protocol has ended, call the final callback */
if (protocol->final_callback)
parse_ctx->packet->type = (SilcPacketType)header[3];
parse_ctx->packet->padlen = (SilcUInt8)header[4];
parse_ctx->packet->sequence = sequence++;
- parse_ctx->sock = sock;
+ parse_ctx->sock = silc_socket_dup(sock);
parse_ctx->context = parser_context;
/* Check whether this is normal or special packet */
memset(tmp, 0, sizeof(tmp));
}
+ /* Don't clear buffer if pending data is in the buffer */
if (cont == FALSE && sock->inbuf->len > 0)
return TRUE;
+ /* Don't clear buffer if QoS data exists in the buffer */
+ if (sock->qos && sock->qos->data_len > 0)
+ return TRUE;
+
SILC_LOG_DEBUG(("Clearing inbound buffer"));
silc_buffer_clear(sock->inbuf);
return TRUE;
/* Compare the MAC's */
if (memcmp(packet_mac, mac, mac_len)) {
SILC_LOG_ERROR(("MAC failed"));
+#if 1
+ abort();
+#endif
return FALSE;
}