updates.
[silc.git] / apps / silcd / packet_send.c
index c42daec9404c9e25f8d1fdb239c350b3c6278772..d2e19b7410a4f6ccf00e7e4d11dc5ec59c586f4a 100644 (file)
@@ -140,8 +140,10 @@ void silc_server_packet_send_dest(SilcServer server,
   SilcIDListData idata = (SilcIDListData)sock->user_data;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
+  uint32 sequence = 0;
   unsigned char *dst_id_data = NULL;
   uint32 dst_id_len = 0;
+  int block_len = 0;
 
   /* If disconnecting, ignore the data */
   if (SILC_IS_DISCONNECTING(sock))
@@ -158,6 +160,13 @@ void silc_server_packet_send_dest(SilcServer server,
     dst_id_len = silc_id_get_len(dst_id, dst_id_type);
   }
 
+  if (idata) {
+    cipher = idata->send_key;
+    hmac = idata->hmac_send;
+    sequence = idata->psn_send++;
+    block_len = silc_cipher_get_block_len(cipher);
+  }
+
   /* Set the packet context pointers */
   packetdata.type = type;
   packetdata.flags = flags;
@@ -169,7 +178,7 @@ void silc_server_packet_send_dest(SilcServer server,
   packetdata.dst_id_type = dst_id_type;
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packetdata.src_id_len + dst_id_len;
-  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
+  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
 
   /* Prepare outgoing data buffer for packet sending */
   silc_packet_send_prepare(sock, 
@@ -188,17 +197,13 @@ void silc_server_packet_send_dest(SilcServer server,
     silc_buffer_put(sock->outbuf, data, data_len);
 
   /* Create the outgoing packet */
-  silc_packet_assemble(&packetdata);
-
-  if (idata) {
-    cipher = idata->send_key;
-    hmac = idata->hmac_send;
-  }
+  silc_packet_assemble(&packetdata, cipher);
 
   /* Encrypt the packet */
-  silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
+  silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, sock->outbuf->len);
 
-  SILC_LOG_HEXDUMP(("Outgoing packet, len %d", sock->outbuf->len),
+  SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, 
+                   sock->outbuf->len),
                   sock->outbuf->data, sock->outbuf->len);
 
   /* Now actually send the packet */
@@ -234,10 +239,12 @@ void silc_server_packet_send_srcdest(SilcServer server,
   SilcIDListData idata;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
+  uint32 sequence = 0;
   unsigned char *dst_id_data = NULL;
   uint32 dst_id_len = 0;
   unsigned char *src_id_data = NULL;
   uint32 src_id_len = 0;
+  int block_len = 0;
 
   SILC_LOG_DEBUG(("Sending packet, type %d", type));
 
@@ -254,6 +261,13 @@ void silc_server_packet_send_srcdest(SilcServer server,
     src_id_len = silc_id_get_len(src_id, src_id_type);
   }
 
+  if (idata) {
+    cipher = idata->send_key;
+    hmac = idata->hmac_send;
+    sequence = idata->psn_send++;
+    block_len = silc_cipher_get_block_len(cipher);
+  }
+
   /* Set the packet context pointers */
   packetdata.type = type;
   packetdata.flags = flags;
@@ -265,7 +279,7 @@ void silc_server_packet_send_srcdest(SilcServer server,
   packetdata.dst_id_type = dst_id_type;
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packetdata.src_id_len + dst_id_len;
-  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
+  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
 
   /* Prepare outgoing data buffer for packet sending */
   silc_packet_send_prepare(sock, 
@@ -284,17 +298,13 @@ void silc_server_packet_send_srcdest(SilcServer server,
     silc_buffer_put(sock->outbuf, data, data_len);
 
   /* Create the outgoing packet */
-  silc_packet_assemble(&packetdata);
-
-  if (idata) {
-    cipher = idata->send_key;
-    hmac = idata->hmac_send;
-  }
+  silc_packet_assemble(&packetdata, cipher);
 
   /* Encrypt the packet */
-  silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
+  silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, sock->outbuf->len);
 
-  SILC_LOG_HEXDUMP(("Outgoing packet, len %d", sock->outbuf->len),
+  SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, 
+                   sock->outbuf->len),
                   sock->outbuf->data, sock->outbuf->len);
 
   /* Now actually send the packet */
@@ -330,10 +340,11 @@ void silc_server_packet_broadcast(SilcServer server,
     silc_buffer_push(buffer, buffer->data - buffer->head);
     silc_packet_send_prepare(sock, 0, 0, buffer->len); 
     silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
-    silc_packet_encrypt(idata->send_key, idata->hmac_send, 
+    silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
                        sock->outbuf, sock->outbuf->len);
 
-    SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len),
+    SILC_LOG_HEXDUMP(("Broadcasted packet (%d), len %d", idata->psn_send - 1,
+                     sock->outbuf->len),
                     sock->outbuf->data, sock->outbuf->len);
 
     /* Now actually send the packet */
@@ -364,10 +375,11 @@ void silc_server_packet_route(SilcServer server,
   silc_buffer_push(buffer, buffer->data - buffer->head);
   silc_packet_send_prepare(sock, 0, 0, buffer->len); 
   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
-  silc_packet_encrypt(idata->send_key, idata->hmac_send, 
+  silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
                      sock->outbuf, sock->outbuf->len);
 
-  SILC_LOG_HEXDUMP(("Routed packet, len %d", sock->outbuf->len),
+  SILC_LOG_HEXDUMP(("Routed packet (%d), len %d", idata->psn_send - 1, 
+                   sock->outbuf->len),
                   sock->outbuf->data, sock->outbuf->len);
 
   /* Now actually send the packet */
@@ -385,14 +397,24 @@ silc_server_packet_send_to_channel_real(SilcServer server,
                                        SilcPacketContext *packet,
                                        SilcCipher cipher,
                                        SilcHmac hmac,
+                                       uint32 sequence,
                                        unsigned char *data,
                                        uint32 data_len,
-                                       int channel_message,
+                                       bool channel_message,
                                        bool force_send)
 {
+  int block_len;
   packet->truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packet->src_id_len + packet->dst_id_len;
 
+  block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
+  if (channel_message)
+    packet->padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
+                                        packet->src_id_len +
+                                        packet->dst_id_len), block_len);
+  else
+    packet->padlen = SILC_PACKET_PADLEN(packet->truelen, block_len);
+
   /* Prepare outgoing data buffer for packet sending */
   silc_packet_send_prepare(sock, 
                           SILC_PACKET_HEADER_LEN +
@@ -407,15 +429,17 @@ silc_server_packet_send_to_channel_real(SilcServer server,
      is encrypted with normal session key shared with the client, unless
      the `channel_message' is TRUE. */
   silc_buffer_put(sock->outbuf, data, data_len);
-  silc_packet_assemble(packet);
+  silc_packet_assemble(packet, cipher);
   if (channel_message)
-    silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
-                       packet->src_id_len + packet->dst_id_len +
-                       packet->padlen);
+    silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, 
+                       SILC_PACKET_HEADER_LEN + packet->src_id_len + 
+                       packet->dst_id_len + packet->padlen);
   else
-    silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
+    silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, 
+                       sock->outbuf->len);
     
-  SILC_LOG_HEXDUMP(("Channel packet, len %d", sock->outbuf->len),
+  SILC_LOG_HEXDUMP(("Channel packet (%d), len %d", sequence, 
+                   sock->outbuf->len),
                   sock->outbuf->data, sock->outbuf->len);
 
   /* Now actually send the packet */
@@ -448,6 +472,8 @@ void silc_server_packet_send_to_channel(SilcServer server,
   SilcHashTableList htl;
   SilcIDListData idata;
   uint32 routed_count = 0;
+  bool gone = FALSE;
+  int k;
 
   /* This doesn't send channel message packets */
   assert(type != SILC_PACKET_CHANNEL_MESSAGE);
@@ -463,9 +489,6 @@ void silc_server_packet_send_to_channel(SilcServer server,
   packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
   packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
   packetdata.dst_id_type = SILC_ID_CHANNEL;
-  packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
-    packetdata.src_id_len + packetdata.dst_id_len;
-  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
 
   /* If there are global users in the channel we will send the message
      first to our router for further routing. */
@@ -484,22 +507,27 @@ void silc_server_packet_send_to_channel(SilcServer server,
       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
                                              idata->send_key, 
                                              idata->hmac_send, 
+                                             idata->psn_send++,
                                              data, data_len, FALSE, 
                                              force_send);
     }
   }
 
+  routed = silc_calloc(silc_hash_table_count(channel->user_list), 
+                      sizeof(*routed));
+
   /* Send the message to clients on the channel's client list. */
   silc_hash_table_list(channel->user_list, &htl);
   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     client = chl->client;
+    if (!client)
+      continue;
 
     /* If client has router set it is not locally connected client and
        we will route the message to the router set in the client. Though,
        send locally connected server in all cases. */
-    if (server->server_type == SILC_ROUTER && client && client->router && 
+    if (server->server_type == SILC_ROUTER && client->router && 
        ((!route && client->router->router == server->id_entry) || route)) {
-      int k;
 
       /* Check if we have sent the packet to this route already */
       for (k = 0; k < routed_count; k++)
@@ -515,47 +543,48 @@ void silc_server_packet_send_to_channel(SilcServer server,
       if (sender && sock == sender)
        continue;
 
+      /* Route only once to router */
+      if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+       if (gone)
+         continue;
+       gone = TRUE;
+      }
+
       /* Send the packet */
       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
                                              idata->send_key, 
                                              idata->hmac_send, 
+                                             idata->psn_send++,
                                              data, data_len, FALSE, 
                                              force_send);
 
-      /* We want to make sure that the packet is routed to same router
-        only once. Mark this route as sent route. */
-      k = routed_count;
-      routed = silc_realloc(routed, sizeof(*routed) * (k + 1));
-      routed[k] = client->router;
-      routed_count++;
-
+      /* Mark this route routed already */
+      routed[routed_count++] = client->router;
       continue;
     }
 
-    if (client && client->router)
+    if (client->router)
       continue;
 
     /* Send to locally connected client */
-    if (client) {
-
-      /* Get data used in packet header encryption, keys and stuff. */
-      sock = (SilcSocketConnection)client->connection;
-      idata = (SilcIDListData)client;
 
-      if (sender && sock == sender)
-       continue;
+    /* Get data used in packet header encryption, keys and stuff. */
+    sock = (SilcSocketConnection)client->connection;
+    idata = (SilcIDListData)client;
+    
+    if (sender && sock == sender)
+      continue;
 
-      /* Send the packet */
-      silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                             idata->send_key, 
-                                             idata->hmac_send, 
-                                             data, data_len, FALSE
-                                             force_send);
-    }
+    /* Send the packet */
+    silc_server_packet_send_to_channel_real(server, sock, &packetdata,
+                                           idata->send_key, 
+                                           idata->hmac_send, 
+                                           idata->psn_send++
+                                           data, data_len, FALSE, 
+                                           force_send);
   }
 
-  if (routed_count)
-    silc_free(routed);
+  silc_free(routed);
   silc_free(packetdata.src_id);
   silc_free(packetdata.dst_id);
 }
@@ -639,6 +668,8 @@ void silc_server_packet_relay_to_channel(SilcServer server,
   uint32 routed_count = 0;
   SilcIDListData idata;
   SilcHashTableList htl;
+  bool gone = FALSE;
+  int k;
 
   SILC_LOG_DEBUG(("Relaying packet to channel"));
 
@@ -660,17 +691,12 @@ void silc_server_packet_relay_to_channel(SilcServer server,
   packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
   packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
   packetdata.dst_id_type = SILC_ID_CHANNEL;
-  packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
-                                         packetdata.src_id_len +
-                                         packetdata.dst_id_len));
 
   /* If there are global users in the channel we will send the message
      first to our router for further routing. */
   if (server->server_type != SILC_ROUTER && !server->standalone &&
       channel->global_users) {
-    SilcServerEntry router;
-
-    router = server->router;
+    SilcServerEntry router = server->router;
 
     /* Check that the sender is not our router. */
     if (sender_sock != (SilcSocketConnection)router->connection) {
@@ -684,148 +710,163 @@ void silc_server_packet_relay_to_channel(SilcServer server,
       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
                                              idata->send_key, 
                                              idata->hmac_send, 
+                                             idata->psn_send++, 
                                              data, data_len, TRUE, 
                                              force_send);
     }
   }
 
+  routed = silc_calloc(silc_hash_table_count(channel->user_list), 
+                      sizeof(*routed));
+
+  /* Mark that to the route the original sender if from is not routed */
+  if (sender_type == SILC_ID_CLIENT) {
+    client = (SilcClientEntry)sender_entry;
+    if (client->router) {
+      routed[routed_count++] = client->router;
+      SILC_LOG_DEBUG(("************* router %s", 
+                     silc_id_render(client->router->id, SILC_ID_SERVER)));
+    }
+  }
+
   /* Send the message to clients on the channel's client list. */
   silc_hash_table_list(channel->user_list, &htl);
   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     client = chl->client;
+    if (!client)
+      continue;
+
+    /* Do not send to the sender */
+    if (!found && client == sender_entry) {
+      found = TRUE;
+      continue;
+    }
 
-    if (client) {
+    /* If the client has set router it means that it is not locally
+       connected client and we will route the packet further. */
+    if (server->server_type == SILC_ROUTER && client->router) {
 
-      /* If sender is one on the channel do not send it the packet. */
-      if (!found && sender_type == SILC_ID_CLIENT &&
-         SILC_ID_CLIENT_COMPARE(client->id, sender)) {
+      /* Sender maybe server as well so we want to make sure that
+        we won't send the message to the server it came from. */
+      if (!found && SILC_ID_SERVER_COMPARE(client->router->id, sender)) {
        found = TRUE;
+       routed[routed_count++] = client->router;
        continue;
       }
 
-      /* If the client has set router it means that it is not locally
-        connected client and we will route the packet further. */
-      if (server->server_type == SILC_ROUTER && client->router) {
-       int k;
+      /* Check if we have sent the packet to this route already */
+      for (k = 0; k < routed_count; k++)
+       if (routed[k] == client->router)
+         break;
+      if (k < routed_count)
+       continue;
+       
+      /* Get data used in packet header encryption, keys and stuff. */
+      sock = (SilcSocketConnection)client->router->connection;
+      idata = (SilcIDListData)client->router;
+
+      /* Do not send to the sender. Check first whether the true
+        sender's router is same as this client's router. Also check
+        if the sender socket is the same as this client's router
+        socket. */
+      if (sender_entry &&
+         ((SilcClientEntry)sender_entry)->router == client->router)
+       continue;
+      if (sender_sock && sock == sender_sock)
+       continue;
 
-       /* Sender maybe server as well so we want to make sure that
-          we won't send the message to the server it came from. */
-       if (!found && SILC_ID_SERVER_COMPARE(client->router->id, sender)) {
-         found = TRUE;
-         continue;
-       }
+      SILC_LOG_DEBUG(("Relaying packet to client ID(%s) %s (%s)", 
+                     silc_id_render(client->id, SILC_ID_CLIENT),
+                     sock->hostname, sock->ip));
 
-       /* Check if we have sent the packet to this route already */
-       for (k = 0; k < routed_count; k++)
-         if (routed[k] == client->router)
-           break;
-       if (k < routed_count)
-         continue;
+      /* Mark this route routed already. */
+      routed[routed_count++] = client->router;
        
-       /* Get data used in packet header encryption, keys and stuff. */
-       sock = (SilcSocketConnection)client->router->connection;
-       idata = (SilcIDListData)client->router;
-
-       /* Do not send to the sender. Check first whether the true
-          sender's router is same as this client's router. Also check
-          if the sender socket is the same as this client's router
-          socket. */
-       if (sender_entry && 
-           ((SilcClientEntry)sender_entry)->router == client->router)
-         continue;
-       if (sender_sock && sock == sender_sock)
+      /* If the remote connection is router then we'll decrypt the
+        channel message and re-encrypt it with the session key shared
+        between us and the remote router. This is done because the
+        channel keys are cell specific and we have different channel
+        key than the remote router has. */
+      if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+       if (gone)
          continue;
 
-       SILC_LOG_DEBUG(("Relaying packet to client ID(%s) %s (%s)", 
-                       silc_id_render(client->id, SILC_ID_CLIENT),
-                       sock->hostname, sock->ip));
+       SILC_LOG_DEBUG(("Remote is router, encrypt with session key"));
+       gone = TRUE;
 
-       /* We want to make sure that the packet is routed to same router
-          only once. Mark this route as sent route. */
-       k = routed_count;
-       routed = silc_realloc(routed, sizeof(*routed) * (k + 1));
-       routed[k] = client->router;
-       routed_count++;
-       
-       /* If the remote connection is router then we'll decrypt the
-          channel message and re-encrypt it with the session key shared
-          between us and the remote router. This is done because the
-          channel keys are cell specific and we have different channel
-          key than the remote router has. */
-       if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
-         SILC_LOG_DEBUG(("Remote is router, encrypt with session key"));
-
-         /* If private key mode is not set then decrypt the packet
-            and re-encrypt it */
-         if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
-           unsigned char *tmp = silc_calloc(data_len, sizeof(*data));
-           memcpy(tmp, data, data_len);
-
-           /* Decrypt the channel message (we don't check the MAC) */
-           if (channel->channel_key &&
-               !silc_channel_message_payload_decrypt(tmp, data_len, 
-                                                     channel->channel_key,
-                                                     NULL)) {
-             memset(tmp, 0, data_len);
-             silc_free(tmp);
-             continue;
-           }
-
-           /* Now re-encrypt and send it to the router */
-           silc_server_packet_send_srcdest(server, sock, 
-                                           SILC_PACKET_CHANNEL_MESSAGE, 0,
-                                           sender, sender_type,
-                                           channel->id, SILC_ID_CHANNEL,
-                                           tmp, data_len, force_send);
-           
-           /* Free the copy of the channel message */
+       /* If private key mode is not set then decrypt the packet
+          and re-encrypt it */
+       if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+         unsigned char *tmp = silc_calloc(data_len, sizeof(*data));
+         memcpy(tmp, data, data_len);
+
+         /* Decrypt the channel message (we don't check the MAC) */
+         if (channel->channel_key &&
+             !silc_channel_message_payload_decrypt(tmp, data_len, 
+                                                   channel->channel_key,
+                                                   NULL)) {
            memset(tmp, 0, data_len);
            silc_free(tmp);
-         } else {
-           /* Private key mode is set, we don't have the channel key, so
-              just re-encrypt the entire packet and send it to the router. */
-           silc_server_packet_send_srcdest(server, sock, 
-                                           SILC_PACKET_CHANNEL_MESSAGE, 0,
-                                           sender, sender_type,
-                                           channel->id, SILC_ID_CHANNEL,
-                                           data, data_len, force_send);
+           continue;
          }
-         continue;
-       }
-
-       /* Send the packet (to normal server) */
-       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                               idata->send_key, 
-                                               idata->hmac_send, 
-                                               data, data_len, TRUE, 
-                                               force_send);
 
+         /* Now re-encrypt and send it to the router */
+         silc_server_packet_send_srcdest(server, sock, 
+                                         SILC_PACKET_CHANNEL_MESSAGE, 0,
+                                         sender, sender_type,
+                                         channel->id, SILC_ID_CHANNEL,
+                                         tmp, data_len, force_send);
+
+         /* Free the copy of the channel message */
+         memset(tmp, 0, data_len);
+         silc_free(tmp);
+       } else {
+         /* Private key mode is set, we don't have the channel key, so
+            just re-encrypt the entire packet and send it to the router. */
+         silc_server_packet_send_srcdest(server, sock, 
+                                         SILC_PACKET_CHANNEL_MESSAGE, 0,
+                                         sender, sender_type,
+                                         channel->id, SILC_ID_CHANNEL,
+                                         data, data_len, force_send);
+       }
        continue;
       }
 
-      if (client && client->router)
-       continue;
-
-      /* Get data used in packet header encryption, keys and stuff. */
-      sock = (SilcSocketConnection)client->connection;
-      idata = (SilcIDListData)client;
-
-      if (sender_sock && sock == sender_sock)
-       continue;
-
-      SILC_LOG_DEBUG(("Sending packet to client ID(%s) %s (%s)", 
-                     silc_id_render(client->id, SILC_ID_CLIENT),
-                     sock->hostname, sock->ip));
-
-      /* Send the packet */
+      /* Send the packet (to normal server) */
       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
                                              idata->send_key, 
                                              idata->hmac_send, 
+                                             idata->psn_send++, 
                                              data, data_len, TRUE, 
                                              force_send);
+
+      continue;
     }
+
+    if (client->router)
+      continue;
+
+    /* Get data used in packet header encryption, keys and stuff. */
+    sock = (SilcSocketConnection)client->connection;
+    idata = (SilcIDListData)client;
+
+    if (sender_sock && sock == sender_sock)
+      continue;
+
+    SILC_LOG_DEBUG(("Sending packet to client ID(%s) %s (%s)", 
+                   silc_id_render(client->id, SILC_ID_CLIENT),
+                   sock->hostname, sock->ip));
+
+    /* Send the packet */
+    silc_server_packet_send_to_channel_real(server, sock, &packetdata,
+                                           idata->send_key, 
+                                           idata->hmac_send, 
+                                           idata->psn_send++, 
+                                           data, data_len, TRUE, 
+                                           force_send);
   }
 
+  silc_free(routed);
   silc_free(packetdata.src_id);
   silc_free(packetdata.dst_id);
 }
@@ -875,6 +916,7 @@ void silc_server_send_private_message(SilcServer server,
                                      SilcSocketConnection dst_sock,
                                      SilcCipher cipher,
                                      SilcHmac hmac,
+                                     uint32 sequence,
                                      SilcPacketContext *packet)
 {
   SilcBuffer buffer = packet->buffer;
@@ -886,10 +928,10 @@ void silc_server_send_private_message(SilcServer server,
                     + packet->dst_id_len + packet->padlen);
     silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
     silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
-    
+
     /* Re-encrypt packet */
-    silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, buffer->len);
-    
+    silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, buffer->len);
+
     /* Send the packet */
     silc_server_packet_send_real(server, dst_sock, FALSE);
 
@@ -901,7 +943,7 @@ void silc_server_send_private_message(SilcServer server,
     silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
 
     /* Encrypt header */
-    silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, 
+    silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, 
                        SILC_PACKET_HEADER_LEN + packet->src_id_len + 
                        packet->dst_id_len + packet->padlen);
 
@@ -920,7 +962,7 @@ void silc_server_send_motd(SilcServer server,
   if (server->config && server->config->motd && 
       server->config->motd->motd_file) {
 
-    motd = silc_file_read(server->config->motd->motd_file, &motd_len);
+    motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
     if (!motd)
       return;
 
@@ -956,7 +998,7 @@ void silc_server_send_error(SilcServer server,
 
 void silc_server_send_notify(SilcServer server,
                             SilcSocketConnection sock,
-                            int broadcast,
+                            bool broadcast,
                             SilcNotifyType type,
                             uint32 argc, ...)
 {
@@ -986,7 +1028,7 @@ void silc_server_send_notify(SilcServer server,
 
 void silc_server_send_notify_args(SilcServer server,
                                  SilcSocketConnection sock,
-                                 int broadcast,
+                                 bool broadcast,
                                  SilcNotifyType type,
                                  uint32 argc,
                                  SilcBuffer args)
@@ -1005,7 +1047,7 @@ void silc_server_send_notify_args(SilcServer server,
 
 void silc_server_send_notify_channel_change(SilcServer server,
                                            SilcSocketConnection sock,
-                                           int broadcast,
+                                           bool broadcast,
                                            SilcChannelID *old_id,
                                            SilcChannelID *new_id)
 {
@@ -1026,7 +1068,7 @@ void silc_server_send_notify_channel_change(SilcServer server,
 
 void silc_server_send_notify_nick_change(SilcServer server,
                                         SilcSocketConnection sock,
-                                        int broadcast,
+                                        bool broadcast,
                                         SilcClientID *old_id,
                                         SilcClientID *new_id)
 {
@@ -1047,7 +1089,7 @@ void silc_server_send_notify_nick_change(SilcServer server,
 
 void silc_server_send_notify_join(SilcServer server,
                                  SilcSocketConnection sock,
-                                 int broadcast,
+                                 bool broadcast,
                                  SilcChannelEntry channel,
                                  SilcClientID *client_id)
 {
@@ -1067,7 +1109,7 @@ void silc_server_send_notify_join(SilcServer server,
 
 void silc_server_send_notify_leave(SilcServer server,
                                   SilcSocketConnection sock,
-                                  int broadcast,
+                                  bool broadcast,
                                   SilcChannelEntry channel,
                                   SilcClientID *client_id)
 {
@@ -1086,7 +1128,7 @@ void silc_server_send_notify_leave(SilcServer server,
 
 void silc_server_send_notify_cmode(SilcServer server,
                                   SilcSocketConnection sock,
-                                  int broadcast,
+                                  bool broadcast,
                                   SilcChannelEntry channel,
                                   uint32 mode_mask,
                                   void *id, SilcIdType id_type,
@@ -1113,7 +1155,7 @@ void silc_server_send_notify_cmode(SilcServer server,
 
 void silc_server_send_notify_cumode(SilcServer server,
                                    SilcSocketConnection sock,
-                                   int broadcast,
+                                   bool broadcast,
                                    SilcChannelEntry channel,
                                    uint32 mode_mask,
                                    void *id, SilcIdType id_type,
@@ -1143,7 +1185,7 @@ void silc_server_send_notify_cumode(SilcServer server,
 
 void silc_server_send_notify_signoff(SilcServer server,
                                     SilcSocketConnection sock,
-                                    int broadcast,
+                                    bool broadcast,
                                     SilcClientID *client_id,
                                     char *message)
 {
@@ -1164,7 +1206,7 @@ void silc_server_send_notify_signoff(SilcServer server,
 
 void silc_server_send_notify_topic_set(SilcServer server,
                                       SilcSocketConnection sock,
-                                      int broadcast,
+                                      bool broadcast,
                                       SilcChannelEntry channel,
                                       SilcClientID *client_id,
                                       char *topic)
@@ -1173,7 +1215,7 @@ void silc_server_send_notify_topic_set(SilcServer server,
 
   idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
   silc_server_send_notify(server, sock, broadcast,
-                         SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+                         SILC_NOTIFY_TYPE_TOPIC_SET,
                          topic ? 2 : 1, 
                          idp->data, idp->len, 
                          topic, topic ? strlen(topic) : 0);
@@ -1187,7 +1229,7 @@ void silc_server_send_notify_topic_set(SilcServer server,
 
 void silc_server_send_notify_kicked(SilcServer server,
                                    SilcSocketConnection sock,
-                                   int broadcast,
+                                   bool broadcast,
                                    SilcChannelEntry channel,
                                    SilcClientID *client_id,
                                    char *comment)
@@ -1208,7 +1250,7 @@ void silc_server_send_notify_kicked(SilcServer server,
 
 void silc_server_send_notify_killed(SilcServer server,
                                    SilcSocketConnection sock,
-                                   int broadcast,
+                                   bool broadcast,
                                    SilcClientID *client_id,
                                    char *comment)
 {
@@ -1228,7 +1270,7 @@ void silc_server_send_notify_killed(SilcServer server,
 
 void silc_server_send_notify_umode(SilcServer server,
                                   SilcSocketConnection sock,
-                                  int broadcast,
+                                  bool broadcast,
                                   SilcClientID *client_id,
                                   uint32 mode_mask)
 {
@@ -1251,7 +1293,7 @@ void silc_server_send_notify_umode(SilcServer server,
 
 void silc_server_send_notify_ban(SilcServer server,
                                 SilcSocketConnection sock,
-                                int broadcast,
+                                bool broadcast,
                                 SilcChannelEntry channel,
                                 char *add, char *del)
 {
@@ -1273,7 +1315,7 @@ void silc_server_send_notify_ban(SilcServer server,
 
 void silc_server_send_notify_invite(SilcServer server,
                                    SilcSocketConnection sock,
-                                   int broadcast,
+                                   bool broadcast,
                                    SilcChannelEntry channel,
                                    SilcClientID *client_id,
                                    char *add, char *del)
@@ -1297,7 +1339,7 @@ void silc_server_send_notify_invite(SilcServer server,
 
 void silc_server_send_notify_dest(SilcServer server,
                                  SilcSocketConnection sock,
-                                 int broadcast,
+                                 bool broadcast,
                                  void *dest_id,
                                  SilcIdType dest_id_type,
                                  SilcNotifyType type,
@@ -1309,7 +1351,8 @@ void silc_server_send_notify_dest(SilcServer server,
   va_start(ap, argc);
 
   packet = silc_notify_payload_encode(type, argc, ap);
-  silc_server_packet_send_dest(server, sock, SILC_PACKET_NOTIFY, 0, 
+  silc_server_packet_send_dest(server, sock, SILC_PACKET_NOTIFY, 
+                              broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
                               dest_id, dest_id_type,
                               packet->data, packet->len, FALSE);
   silc_buffer_free(packet);
@@ -1424,18 +1467,24 @@ void silc_server_send_notify_on_channels(SilcServer server,
        /* Get data used in packet header encryption, keys and stuff. */
        sock = (SilcSocketConnection)c->router->connection;
        idata = (SilcIDListData)c->router;
-       
+
+       {
+         SILC_LOG_DEBUG(("*****************"));
+         SILC_LOG_DEBUG(("client->router->id %s",
+                         silc_id_render(c->router->id, SILC_ID_SERVER)));
+         SILC_LOG_DEBUG(("client->router->connection->user_data->id %s",
+                         silc_id_render(((SilcServerEntry)sock->user_data)->id, SILC_ID_SERVER)));
+       }
+
        packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER);
        packetdata.dst_id_len = silc_id_get_len(c->router->id, SILC_ID_SERVER);
        packetdata.dst_id_type = SILC_ID_SERVER;
-       packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
-         packetdata.src_id_len + packetdata.dst_id_len;
-       packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
 
        /* Send the packet */
        silc_server_packet_send_to_channel_real(server, sock, &packetdata,
                                                idata->send_key, 
                                                idata->hmac_send, 
+                                               idata->psn_send++, 
                                                data, data_len, FALSE, 
                                                force_send);
        
@@ -1443,11 +1492,8 @@ void silc_server_send_notify_on_channels(SilcServer server,
 
        /* We want to make sure that the packet is routed to same router
           only once. Mark this route as sent route. */
-       k = routed_count;
-       routed = silc_realloc(routed, sizeof(*routed) * (k + 1));
-       routed[k] = c->router;
-       routed_count++;
-
+       routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
+       routed[routed_count++] = c->router;
        continue;
       }
 
@@ -1464,14 +1510,12 @@ void silc_server_send_notify_on_channels(SilcServer server,
        packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
        packetdata.dst_id_len = silc_id_get_len(c->id, SILC_ID_CLIENT);
        packetdata.dst_id_type = SILC_ID_CLIENT;
-       packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
-         packetdata.src_id_len + packetdata.dst_id_len;
-       packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
 
        /* Send the packet */
        silc_server_packet_send_to_channel_real(server, sock, &packetdata,
                                                idata->send_key, 
                                                idata->hmac_send, 
+                                               idata->psn_send++, 
                                                data, data_len, FALSE, 
                                                force_send);
 
@@ -1480,16 +1524,13 @@ void silc_server_send_notify_on_channels(SilcServer server,
        /* Make sure that we send the notify only once per client. */
        sent_clients = silc_realloc(sent_clients, sizeof(*sent_clients) * 
                                    (sent_clients_count + 1));
-       sent_clients[sent_clients_count] = c;
-       sent_clients_count++;
+       sent_clients[sent_clients_count++] = c;
       }
     }
   }
 
-  if (routed_count)
-    silc_free(routed);
-  if (sent_clients_count)
-    silc_free(sent_clients);
+  silc_free(routed);
+  silc_free(sent_clients);
   silc_free(packetdata.src_id);
   va_end(ap);
 }
@@ -1502,7 +1543,7 @@ void silc_server_send_notify_on_channels(SilcServer server,
 
 void silc_server_send_new_id(SilcServer server,
                             SilcSocketConnection sock,
-                            int broadcast,
+                            bool broadcast,
                             void *id, SilcIdType id_type, 
                             uint32 id_len)
 {
@@ -1532,7 +1573,7 @@ void silc_server_send_new_id(SilcServer server,
 
 void silc_server_send_new_channel(SilcServer server,
                                  SilcSocketConnection sock,
-                                 int broadcast,
+                                 bool broadcast,
                                  char *channel_name,
                                  void *channel_id, 
                                  uint32 channel_id_len,
@@ -1642,6 +1683,7 @@ void silc_server_relay_packet(SilcServer server,
                              SilcSocketConnection dst_sock,
                              SilcCipher cipher,
                              SilcHmac hmac,
+                             uint32 sequence,
                              SilcPacketContext *packet,
                              bool force_send)
 {
@@ -1652,7 +1694,8 @@ void silc_server_relay_packet(SilcServer server,
   silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len);
   
   /* Re-encrypt packet */
-  silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len);
+  silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, 
+                     packet->buffer->len);
   
   /* Send the packet */
   silc_server_packet_send_real(server, dst_sock, force_send);