Backup router related fixes.
[silc.git] / apps / silcd / packet_send.c
index a1d4bc873b7620e2fb3372396f843d5a9ffbbd68..40d303e621b84e7c1626a4210268bd0c18a1ce41 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2002 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
@@ -444,6 +444,9 @@ void silc_server_packet_send_clients(SilcServer server,
 
     /* Send to locally connected client */
     sock = (SilcSocketConnection)client->connection;
+    if (!sock)
+      continue;
+
     silc_server_packet_send_dest(server, sock, type, flags,
                                 client->id, SILC_ID_CLIENT,
                                 data, data_len, force_send);
@@ -680,15 +683,16 @@ silc_server_packet_relay_to_channel_encrypt(SilcServer server,
       channel->channel_key) {
     SilcUInt32 mac_len = silc_hmac_len(channel->hmac);
     SilcUInt32 iv_len = silc_cipher_get_block_len(channel->channel_key);
+    unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
 
     if (data_len <= mac_len + iv_len) {
       SILC_LOG_WARNING(("Corrupted channel message, cannot relay it"));
       return FALSE;
     }
 
-    memcpy(channel->iv, data + (data_len - iv_len), iv_len);
+    memcpy(iv, data + (data_len - iv_len), iv_len);
     silc_channel_message_payload_encrypt(data, data_len - iv_len - mac_len,
-                                        data_len, channel->iv, iv_len,
+                                        data_len, iv, iv_len,
                                         channel->channel_key, channel->hmac);
   }
 
@@ -718,7 +722,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
   SilcPacketContext packetdata;
   SilcClientEntry client = NULL;
   SilcServerEntry *routed = NULL;
-  SilcChannelClientEntry chl;
+  SilcChannelClientEntry chl, chl_sender;
   SilcUInt32 routed_count = 0;
   SilcIDListData idata;
   SilcHashTableList htl;
@@ -727,6 +731,9 @@ void silc_server_packet_relay_to_channel(SilcServer server,
 
   SILC_LOG_DEBUG(("Relaying packet to channel"));
 
+  if (!silc_server_client_on_channel(sender_entry, channel, &chl_sender))
+    return;
+
   /* This encrypts the packet, if needed. It will be encrypted if
      it came from the router thus it needs to be encrypted with the
      channel key. If the channel key does not exist, then we know we
@@ -784,6 +791,17 @@ void silc_server_packet_relay_to_channel(SilcServer server,
     if (!client || client == sender_entry)
       continue;
 
+    /* Check whether message sending is blocked */
+    if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
+      continue;
+    if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS &&
+       !(chl_sender->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+       !(chl_sender->mode & SILC_CHANNEL_UMODE_CHANFO))
+      continue;
+    if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS &&
+       sender_entry->mode & SILC_UMODE_ROBOT)
+      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) {
@@ -1093,7 +1111,8 @@ void silc_server_send_notify_nick_change(SilcServer server,
                                         SilcSocketConnection sock,
                                         bool broadcast,
                                         SilcClientID *old_id,
-                                        SilcClientID *new_id)
+                                        SilcClientID *new_id,
+                                        const char *nickname)
 {
   SilcBuffer idp1, idp2;
 
@@ -1102,7 +1121,8 @@ void silc_server_send_notify_nick_change(SilcServer server,
 
   silc_server_send_notify(server, sock, broadcast, 
                          SILC_NOTIFY_TYPE_NICK_CHANGE,
-                         2, idp1->data, idp1->len, idp2->data, idp2->len);
+                         3, idp1->data, idp1->len, idp2->data, idp2->len,
+                         nickname, nickname ? strlen(nickname) : 0);
   silc_buffer_free(idp1);
   silc_buffer_free(idp2);
 }
@@ -1155,27 +1175,33 @@ void silc_server_send_notify_cmode(SilcServer server,
                                   SilcChannelEntry channel,
                                   SilcUInt32 mode_mask,
                                   void *id, SilcIdType id_type,
-                                  char *cipher, char *hmac,
-                                  char *passphrase)
+                                  const char *cipher, const char *hmac,
+                                  const char *passphrase,
+                                  SilcPublicKey founder_key)
 {
   SilcBuffer idp;
-  unsigned char mode[4];
+  unsigned char mode[4], *key = NULL;
+  SilcUInt32 key_len = 0;
 
   idp = silc_id_payload_encode((void *)id, id_type);
   SILC_PUT32_MSB(mode_mask, mode);
+  if (founder_key)
+    key = silc_pkcs_public_key_encode(founder_key, &key_len);
 
   silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
                               SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_CMODE_CHANGE,
-                              5, idp->data, idp->len,
+                              6, idp->data, idp->len,
                               mode, 4,
                               cipher, cipher ? strlen(cipher) : 0,
                               hmac, hmac ? strlen(hmac) : 0,
                               passphrase, passphrase ? 
-                              strlen(passphrase) : 0);
+                              strlen(passphrase) : 0,
+                              key, key_len);
+  silc_free(key);
   silc_buffer_free(idp);
 }
 
-/* Sends CUMODE_CHANGE notify type. This tells that `client_id' changed the
+/* Sends CUMODE_CHANGE notify type. This tells that `id' changed the
    `target' client's mode on `channel'. The notify packet is always
    destined to the channel. */
 
@@ -1185,21 +1211,27 @@ void silc_server_send_notify_cumode(SilcServer server,
                                    SilcChannelEntry channel,
                                    SilcUInt32 mode_mask,
                                    void *id, SilcIdType id_type,
-                                   SilcClientID *target)
+                                   SilcClientID *target,
+                                   SilcPublicKey founder_key)
 {
   SilcBuffer idp1, idp2;
-  unsigned char mode[4];
+  unsigned char mode[4], *key = NULL;
+  SilcUInt32 key_len = 0;
 
   idp1 = silc_id_payload_encode((void *)id, id_type);
   idp2 = silc_id_payload_encode((void *)target, SILC_ID_CLIENT);
   SILC_PUT32_MSB(mode_mask, mode);
+  if (founder_key)
+    key = silc_pkcs_public_key_encode(founder_key, &key_len);
 
   silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
                               SILC_ID_CHANNEL, 
-                              SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3
+                              SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4
                               idp1->data, idp1->len,
                               mode, 4,
-                              idp2->data, idp2->len);
+                              idp2->data, idp2->len,
+                              key, key_len);
+  silc_free(key);
   silc_buffer_free(idp1);
   silc_buffer_free(idp2);
 }
@@ -1284,16 +1316,21 @@ void silc_server_send_notify_killed(SilcServer server,
                                    SilcSocketConnection sock,
                                    bool broadcast,
                                    SilcClientID *client_id,
-                                   char *comment)
+                                   const char *comment,
+                                   void *killer, SilcIdType killer_type)
 {
-  SilcBuffer idp;
+  SilcBuffer idp1;
+  SilcBuffer idp2;
 
-  idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  idp1 = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+  idp2 = silc_id_payload_encode(killer, killer_type);
   silc_server_send_notify_dest(server, sock, broadcast, (void *)client_id,
                               SILC_ID_CLIENT, SILC_NOTIFY_TYPE_KILLED,
-                              comment ? 2 : 1, idp->data, idp->len,
-                              comment, comment ? strlen(comment) : 0);
-  silc_buffer_free(idp);
+                              3, idp1->data, idp1->len,
+                              comment, comment ? strlen(comment) : 0,
+                              idp2->data, idp2->len);
+  silc_buffer_free(idp1);
+  silc_buffer_free(idp2);
 }
 
 /* Sends UMODE_CHANGE notify type. This tells that `client_id' client's
@@ -1367,6 +1404,32 @@ void silc_server_send_notify_invite(SilcServer server,
   silc_buffer_free(idp2);
 }
 
+/* Sends WATCH notify type. This tells that the `client' was watched and
+   its status in the network has changed. */
+
+void silc_server_send_notify_watch(SilcServer server,
+                                  SilcSocketConnection sock,
+                                  SilcClientEntry watcher,
+                                  SilcClientEntry client,
+                                  const char *nickname,
+                                  SilcNotifyType type)
+{
+  SilcBuffer idp;
+  unsigned char mode[4], n[2];
+
+  idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+  SILC_PUT16_MSB(type, n);
+  SILC_PUT32_MSB(client->mode, mode);
+  silc_server_send_notify_dest(server, sock, FALSE, watcher->id,
+                              SILC_ID_CLIENT, SILC_NOTIFY_TYPE_WATCH,
+                              4, idp->data, idp->len,
+                              nickname, nickname ? strlen(nickname) : 0,
+                              mode, sizeof(mode), 
+                              type != SILC_NOTIFY_TYPE_NONE ?
+                              n : NULL, sizeof(n));
+  silc_buffer_free(idp);
+}
+
 /* Sends notify message destined to specific entity. */
 
 void silc_server_send_notify_dest(SilcServer server,
@@ -1593,14 +1656,6 @@ void silc_server_send_new_id(SilcServer server,
   silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID, 
                          broadcast ? SILC_PACKET_FLAG_BROADCAST : 0, 
                          idp->data, idp->len, FALSE);
-
-  /* Send to backup routers if this is being broadcasted to primary
-     router. */
-  if (server->router && server->router->connection &&
-      sock == server->router->connection && broadcast)
-    silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
-                           idp->data, idp->len, FALSE, TRUE);
-
   silc_buffer_free(idp);
 }
 
@@ -1634,14 +1689,6 @@ void silc_server_send_new_channel(SilcServer server,
                          broadcast ? SILC_PACKET_FLAG_BROADCAST : 0, 
                          packet->data, packet->len, FALSE);
 
-  /* Send to backup routers if this is being broadcasted to primary
-     router. */
-  if (server->server_type == SILC_ROUTER &&
-      server->router && server->router->connection &&
-      sock == server->router->connection && broadcast)
-    silc_server_backup_send(server, NULL, SILC_PACKET_NEW_CHANNEL, 0,
-                           packet->data, packet->len, FALSE, TRUE);
-
   silc_free(cid);
   silc_buffer_free(packet);
 }
@@ -1712,7 +1759,8 @@ void silc_server_send_command(SilcServer server,
 void silc_server_send_command_reply(SilcServer server, 
                                    SilcSocketConnection sock,
                                    SilcCommand command, 
-                                   SilcCommandStatus status,
+                                   SilcStatus status,
+                                   SilcStatus error,
                                    SilcUInt16 ident,
                                    SilcUInt32 argc, ...)
 {
@@ -1721,8 +1769,8 @@ void silc_server_send_command_reply(SilcServer server,
 
   va_start(ap, argc);
 
-  packet = silc_command_reply_payload_encode_vap(command, status, ident, 
-                                                argc, ap);
+  packet = silc_command_reply_payload_encode_vap(command, status, error,
+                                                ident, argc, ap);
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
                          packet->data, packet->len, TRUE);
   silc_buffer_free(packet);
@@ -1737,7 +1785,8 @@ void silc_server_send_dest_command_reply(SilcServer server,
                                         void *dst_id,
                                         SilcIdType dst_id_type,
                                         SilcCommand command, 
-                                        SilcCommandStatus status,
+                                        SilcStatus status,
+                                        SilcStatus error,
                                         SilcUInt16 ident,
                                         SilcUInt32 argc, ...)
 {
@@ -1746,8 +1795,8 @@ void silc_server_send_dest_command_reply(SilcServer server,
 
   va_start(ap, argc);
 
-  packet = silc_command_reply_payload_encode_vap(command, status, ident, 
-                                                argc, ap);
+  packet = silc_command_reply_payload_encode_vap(command, status, error,
+                                                ident, argc, ap);
   silc_server_packet_send_dest(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
                               dst_id, dst_id_type, packet->data, 
                               packet->len, TRUE);