Do not process packets for disconnected sockets.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 12 Oct 2003 17:51:20 +0000 (17:51 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 12 Oct 2003 17:51:20 +0000 (17:51 +0000)
lib/silccore/silcidcache.c
lib/silccore/silcpacket.c

index 3d6904e74421b00d962d69e55466f92c9240fa0a..fb284c22237fc333807f9a90b56e4deb264e6d67 100644 (file)
@@ -10,7 +10,7 @@
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
-  
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -26,7 +26,7 @@
 static void silc_idcache_destructor(void *key, void *context,
                                    void *user_context);
 static SilcIDCacheList silc_idcache_list_alloc();
-static void silc_idcache_list_add(SilcIDCacheList list, 
+static void silc_idcache_list_add(SilcIDCacheList list,
                                  SilcIDCacheEntry cache);
 
 /*
@@ -70,9 +70,9 @@ struct SilcIDCacheStruct {
   SilcIdType type;
 };
 
-/* 
+/*
    ID Cache list.
-   
+
    This is returned when searching the cache. Enumeration functions are
    provided to traverse the list; actually this is used as table not as
    list. :)
@@ -94,7 +94,7 @@ struct SilcIDCacheListStruct {
 };
 
 /* Allocates new ID cache object. The initial amount of allocated entries
-   can be sent as argument. If `count' is 0 the system uses default values. 
+   can be sent as argument. If `count' is 0 the system uses default values.
    The `id_type' defines the types of the ID's that will be saved to the
    cache. */
 
@@ -153,7 +153,7 @@ void silc_idcache_free(SilcIDCache cache)
    If the `expire' is TRUE the entry expires in default time and if FALSE
    the entry never expires from the cache. */
 
-bool silc_idcache_add(SilcIDCache cache, char *name, void *id, 
+bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
                      void *context, int expire, SilcIDCacheEntry *ret)
 {
   SilcIDCacheEntry c;
@@ -210,8 +210,10 @@ bool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry old)
     ret = silc_hash_table_del(cache->context_table, old->context);
   if (old->id)
     ret = silc_hash_table_del(cache->id_table, old->id);
-  else
+  else {
     silc_idcache_destructor(NULL, old, NULL);
+    ret = TRUE;
+  }
 
   return ret;
 }
@@ -232,9 +234,9 @@ bool silc_idcache_del_by_id(SilcIDCache cache, void *id)
    functions are NULL then default values are used. */
 
 bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
-                               SilcHashFunction hash, 
+                               SilcHashFunction hash,
                                void *hash_context,
-                               SilcHashCompare compare, 
+                               SilcHashCompare compare,
                                void *compare_context)
 {
   SilcIDCacheEntry c;
@@ -243,7 +245,7 @@ bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
   SILC_LOG_DEBUG(("Deleting cache entry"));
 
   if (!silc_hash_table_find_ext(cache->id_table, id, NULL, (void *)&c,
-                               hash, hash_context, compare, 
+                               hash, hash_context, compare,
                                compare_context))
     return FALSE;
 
@@ -277,8 +279,10 @@ bool silc_idcache_del_by_context(SilcIDCache cache, void *context)
     ret = silc_hash_table_del(cache->context_table, c->context);
   if (c->id)
     ret = silc_hash_table_del_by_context(cache->id_table, c->id, c);
-  else
+  else {
     silc_idcache_destructor(NULL, c, NULL);
+    ret = TRUE;
+  }
 
   return ret;
 }
@@ -322,7 +326,7 @@ static void silc_idcache_purge_foreach(void *key, void *context,
     if (c->id)
       ret =
        silc_hash_table_del_by_context_ext(cache->id_table, c->id, c,
-                                          NULL, NULL, NULL, NULL, 
+                                          NULL, NULL, NULL, NULL,
                                           silc_idcache_destructor_dummy,
                                           NULL);
     if (ret == TRUE) {
@@ -352,7 +356,7 @@ bool silc_idcache_purge_by_context(SilcIDCache cache, void *context)
   SilcIDCacheEntry c;
   bool ret = FALSE;
 
-  if (!silc_hash_table_find(cache->context_table, context, NULL, 
+  if (!silc_hash_table_find(cache->context_table, context, NULL,
                            (void *)&c))
     return FALSE;
 
@@ -364,7 +368,7 @@ bool silc_idcache_purge_by_context(SilcIDCache cache, void *context)
   if (c->id)
     ret =
       silc_hash_table_del_by_context_ext(cache->id_table, c->id, c,
-                                        NULL, NULL, NULL, NULL, 
+                                        NULL, NULL, NULL, NULL,
                                         silc_idcache_destructor_dummy, NULL);
   if (ret == TRUE) {
     /* Call the destructor */
@@ -416,7 +420,7 @@ bool silc_idcache_get_all(SilcIDCache cache, SilcIDCacheList *ret)
 
 /* Find ID Cache entry by ID. May return multiple entries. */
 
-bool silc_idcache_find_by_id(SilcIDCache cache, void *id, 
+bool silc_idcache_find_by_id(SilcIDCache cache, void *id,
                             SilcIDCacheList *ret)
 {
   SilcIDCacheList list;
@@ -445,21 +449,21 @@ bool silc_idcache_find_by_id(SilcIDCache cache, void *id,
    If `hash' is NULL then the default hash funtion is used and if `compare'
    is NULL default comparison function is used. */
 
-bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id, 
-                                    SilcHashFunction hash, 
+bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id,
+                                    SilcHashFunction hash,
                                     void *hash_context,
-                                    SilcHashCompare compare, 
+                                    SilcHashCompare compare,
                                     void *compare_context,
                                     SilcIDCacheEntry *ret)
 {
   return silc_hash_table_find_ext(cache->id_table, id, NULL, (void *)ret,
-                                 hash, hash_context, compare, 
+                                 hash, hash_context, compare,
                                  compare_context);
 }
 
 /* Find one specific ID entry. */
 
-bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id, 
+bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
                                 SilcIDCacheEntry *ret)
 {
   return silc_hash_table_find(cache->id_table, id, NULL, (void *)ret);
@@ -467,10 +471,10 @@ bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
 
 /* Finds cache entry by context. */
 
-bool silc_idcache_find_by_context(SilcIDCache cache, void *context, 
+bool silc_idcache_find_by_context(SilcIDCache cache, void *context,
                                  SilcIDCacheEntry *ret)
 {
-  return silc_hash_table_find(cache->context_table, context, NULL, 
+  return silc_hash_table_find(cache->context_table, context, NULL,
                              (void *)ret);
 }
 
@@ -488,7 +492,7 @@ bool silc_idcache_find_by_name(SilcIDCache cache, char *name,
   if (!ret)
     return TRUE;
 
-  silc_hash_table_find_foreach(cache->name_table, name, 
+  silc_hash_table_find_foreach(cache->name_table, name,
                               silc_idcache_get_all_foreach, list);
 
   if (silc_idcache_list_count(list) == 0) {
@@ -555,7 +559,7 @@ static void silc_idcache_list_add(SilcIDCacheList list, SilcIDCacheEntry cache)
     int k;
 
     i = list->cache_dyn_count;
-    list->cache_dyn = silc_realloc(list->cache_dyn, 
+    list->cache_dyn = silc_realloc(list->cache_dyn,
                                   sizeof(*list->cache_dyn) * (i + 5));
     if (!list->cache_dyn)
       return;
@@ -585,7 +589,7 @@ bool silc_idcache_list_first(SilcIDCacheList list, SilcIDCacheEntry *ret)
 
   if (!list->cache[list->pos])
     return FALSE;
-  
+
   if (ret)
     *ret = list->cache[list->pos];
 
@@ -609,17 +613,17 @@ bool silc_idcache_list_next(SilcIDCacheList list, SilcIDCacheEntry *ret)
 
   if (!list->dyn && !list->cache[list->pos])
     return FALSE;
-  
+
   if (list->dyn && !list->cache_dyn[list->pos])
     return FALSE;
-  
+
   if (ret) {
     if (!list->dyn)
       *ret = list->cache[list->pos];
     else
       *ret = list->cache_dyn[list->pos];
   }
-  
+
   return TRUE;
 }
 
index 00c4b5e9ab4d6077688d5f02325537994ce470a2..167d7d17a61fcae170a8cf4b8171344b9d6a447a 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcpacket.c 
+  silcpacket.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2003 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
@@ -40,7 +40,7 @@
 int silc_packet_send(SilcSocketConnection sock, bool force_send)
 {
   SILC_LOG_DEBUG(("Sending packet to %s:%d [%s]", sock->hostname,
-                 sock->port,  
+                 sock->port,
                  (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
                   sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
                   sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
@@ -56,21 +56,21 @@ int silc_packet_send(SilcSocketConnection sock, bool force_send)
     ret = silc_socket_write(sock);
 
     if (ret == -1) {
-      SILC_LOG_ERROR(("Error sending packet, dropped: %s", 
+      SILC_LOG_ERROR(("Error sending packet, dropped: %s",
                       strerror(errno)));
     }
     if (ret != -2)
       return ret;
 
     SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
-  }  
+  }
 
   SILC_LOG_DEBUG(("Packet in queue"));
 
   return -2;
 }
 
-/* Encrypts a packet. This also creates HMAC of the packet before 
+/* Encrypts a packet. This also creates HMAC of the packet before
    encryption and adds the HMAC at the end of the buffer. This assumes
    that there is enough free space at the end of the buffer to add the
    computed HMAC. This is the normal way of encrypting packets, if some
@@ -83,7 +83,7 @@ void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, SilcUInt32 sequence,
 
   /* Encrypt the data area of the packet. */
   if (cipher) {
-    SILC_LOG_DEBUG(("Encrypting packet (%d), cipher %s, len %d", 
+    SILC_LOG_DEBUG(("Encrypting packet (%d), cipher %s, len %d",
                    sequence, silc_cipher_get_name(cipher), len));
     silc_cipher_encrypt(cipher, buffer->data, buffer->data, len, NULL);
   }
@@ -114,8 +114,8 @@ bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng,
                          SilcSocketConnection sock,
                          const unsigned char *data, SilcUInt32 data_len,
                          const SilcBuffer assembled_packet)
-{ 
-  unsigned char tmppad[SILC_PACKET_MAX_PADLEN];   
+{
+  unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
   unsigned int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
   int i, ret;
 
@@ -130,7 +130,7 @@ bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng,
   if (!packet->truelen) {
     data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
                                   packet->src_id_len + packet->dst_id_len);
-    packet->truelen = data_len + SILC_PACKET_HEADER_LEN + 
+    packet->truelen = data_len + SILC_PACKET_HEADER_LEN +
       packet->src_id_len + packet->dst_id_len;
   }
 
@@ -201,7 +201,7 @@ bool silc_packet_send_prepare(SilcSocketConnection sock,
                              SilcUInt32 data_len,
                              SilcHmac hmac,
                              const SilcBuffer packet)
-{ 
+{
   SilcUInt32 totlen;
   unsigned char *oldptr;
   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
@@ -251,8 +251,8 @@ bool silc_packet_send_prepare(SilcSocketConnection sock,
 
 ******************************************************************************/
 
-static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac, 
-                              SilcUInt32 sequence, SilcBuffer buffer, 
+static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
+                              SilcUInt32 sequence, SilcBuffer buffer,
                               bool normal);
 static bool silc_packet_check_mac(SilcHmac hmac,
                                  const unsigned char *data,
@@ -272,7 +272,7 @@ int silc_packet_receive(SilcSocketConnection sock)
   int ret;
 
   SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
-                 sock->port, 
+                 sock->port,
                  (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
                   sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
                   sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
@@ -289,8 +289,8 @@ int silc_packet_receive(SilcSocketConnection sock)
    If more than one packet was received this calls the parser multiple
    times.  The parser callback will get context SilcPacketParserContext
    that includes the packet and the `parser_context' sent to this
-   function. 
-   
+   function.
+
    The `local_is_router' indicates whether the caller is router server
    in which case the receiving process of a certain packet types may
    be special.  Normal server and client must set it to FALSE.  The
@@ -313,7 +313,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
 
   /* Do not process for disconnected connection */
-  if (SILC_IS_DISCONNECTED(sock))
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
     return TRUE;
 
   if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
@@ -394,7 +394,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
       if (header[3] == SILC_PACKET_PRIVATE_MESSAGE &&
          (header[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
        parse_ctx->normal = FALSE;
-      else if (header[3] != SILC_PACKET_CHANNEL_MESSAGE || 
+      else if (header[3] != SILC_PACKET_CHANNEL_MESSAGE ||
               (header[3] == SILC_PACKET_CHANNEL_MESSAGE &&
                sock->type == SILC_SOCKET_TYPE_ROUTER))
        parse_ctx->normal = TRUE;
@@ -417,11 +417,11 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
                    paddedlen - block_len);
     if (cipher) {
       silc_cipher_set_iv(cipher, iv);
-      ret = silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
-                               parse_ctx->packet->buffer, 
+      ret = silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
+                               parse_ctx->packet->buffer,
                                parse_ctx->normal);
       if (ret < 0) {
-       SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]", 
+       SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]",
                          sock->hostname, sock->port,
                          silc_get_packet_name(parse_ctx->packet->type),
                          (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
@@ -437,7 +437,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     silc_buffer_push(parse_ctx->packet->buffer, block_len);
 
     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d",
-                     parse_ctx->packet->buffer->len), 
+                     parse_ctx->packet->buffer->len),
                     parse_ctx->packet->buffer->data,
                     parse_ctx->packet->buffer->len);
 
@@ -447,6 +447,13 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
 
     /* Call the parser */
     cont = (*parser)(parse_ctx, parser_context);
+
+    /* See if socket disconnected while parsing the packet */
+    if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+      SILC_LOG_DEBUG(("Abandoning packet processing, socket disconnected"));
+      cont = FALSE;
+    }
+
     memset(tmp, 0, sizeof(tmp));
   }
 
@@ -470,7 +477,7 @@ static bool silc_packet_check_mac(SilcHmac hmac,
   if (hmac) {
     unsigned char mac[32], psn[4];
     SilcUInt32 mac_len;
-    
+
     SILC_LOG_DEBUG(("Verifying MAC"));
 
     /* Compute HMAC of packet */
@@ -485,10 +492,10 @@ static bool silc_packet_check_mac(SilcHmac hmac,
       SILC_LOG_ERROR(("MAC failed"));
       return FALSE;
     }
-    
+
     SILC_LOG_DEBUG(("MAC is Ok"));
   }
-  
+
   return TRUE;
 }
 
@@ -496,7 +503,7 @@ static bool silc_packet_check_mac(SilcHmac hmac,
    Return 0 when packet is normal and 1 when it it special, -1 on error. */
 
 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
-                              SilcUInt32 sequence, SilcBuffer buffer, 
+                              SilcUInt32 sequence, SilcBuffer buffer,
                               bool normal)
 {
   /* If the packet type is not any special type lets decrypt rest
@@ -524,7 +531,7 @@ static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
       /* padding length + src id len + dst id len + header length - 16
         bytes already decrypted, gives the rest of the encrypted packet */
       silc_buffer_push(buffer, block_len);
-      len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] + 
+      len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
              (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
             block_len);
       silc_buffer_pull(buffer, block_len);
@@ -546,9 +553,9 @@ static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
 }
 
 /* Parses the packet. This is called when a whole packet is ready to be
-   parsed. The buffer sent must be already decrypted before calling this 
-   function. The len argument must be the true length of the packet. This 
-   function returns the type of the packet. The data section of the 
+   parsed. The buffer sent must be already decrypted before calling this
+   function. The len argument must be the true length of the packet. This
+   function returns the type of the packet. The data section of the
    buffer is parsed, not head or tail sections. */
 
 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
@@ -567,7 +574,7 @@ SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
   }
 
   /* Parse the buffer. This parses the SILC header of the packet. */
-  len = silc_buffer_unformat(buffer, 
+  len = silc_buffer_unformat(buffer,
                             SILC_STR_UI_SHORT(&ctx->truelen),
                             SILC_STR_UI_CHAR(&ctx->flags),
                             SILC_STR_UI_CHAR(&ctx->type),
@@ -588,7 +595,7 @@ SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
   }
 
   silc_buffer_pull(buffer, len);
-  ret = silc_buffer_unformat(buffer, 
+  ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
                                                        src_id_len),
                             SILC_STR_UI_CHAR(&dst_id_type),
@@ -613,7 +620,7 @@ SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
 
   silc_buffer_push(buffer, len);
 
-  SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
+  SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
                   ctx->buffer->data, ctx->buffer->len);
 
   /* Pull SILC header and padding from packet */
@@ -648,7 +655,7 @@ SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
   }
 
   /* Parse the buffer. This parses the SILC header of the packet. */
-  len = silc_buffer_unformat(buffer, 
+  len = silc_buffer_unformat(buffer,
                             SILC_STR_UI_SHORT(&ctx->truelen),
                             SILC_STR_UI_CHAR(&ctx->flags),
                             SILC_STR_UI_CHAR(&ctx->type),
@@ -671,7 +678,7 @@ SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
   }
 
   silc_buffer_pull(buffer, len);
-  ret = silc_buffer_unformat(buffer, 
+  ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
                                                        src_id_len),
                             SILC_STR_UI_CHAR(&dst_id_type),
@@ -698,7 +705,7 @@ SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
 
   silc_buffer_push(buffer, len);
 
-  SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
+  SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
                   ctx->buffer->data, ctx->buffer->len);
 
   /* Pull SILC header and padding from packet */