Protocol version 1.2 integrations
[silc.git] / apps / silcd / packet_receive.c
index 525ada9d0d9d57112830a826989048cf698b0467..b715828dd5e4cb34ac46d9351ac22634d7929fe3 100644 (file)
@@ -131,6 +131,9 @@ void silc_server_notify(SilcServer server,
      */
     SILC_LOG_DEBUG(("JOIN notify"));
 
+    if (channel_id)
+      silc_free(channel_id);
+
     /* Get Channel ID */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
     if (!tmp)
@@ -303,6 +306,7 @@ void silc_server_notify(SilcServer server,
       }
     }
     silc_free(client_id);
+    silc_free(channel_id);
 
     /* Check if on channel */
     if (!silc_server_client_on_channel(client, channel, NULL))
@@ -546,8 +550,8 @@ void silc_server_notify(SilcServer server,
          goto out;
        }
       }
-      silc_free(client_id);
     }
+    silc_free(client_id);
 
     if (!channel_id) {
       channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
@@ -608,7 +612,8 @@ void silc_server_notify(SilcServer server,
        if (channel->founder_key)
          silc_pkcs_public_key_free(channel->founder_key);
        channel->founder_key = NULL;
-       silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+       silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+                                           &channel->founder_key);
       }
 
       break;
@@ -714,7 +719,7 @@ void silc_server_notify(SilcServer server,
       if (channel->founder_key)
        silc_pkcs_public_key_free(channel->founder_key);
       channel->founder_key = NULL;
-      silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+      silc_pkcs_public_key_payload_decode(tmp, tmp_len, &channel->founder_key);
 
       if (!channel->founder_key || 
          (client && client->data.public_key && 
@@ -798,8 +803,8 @@ void silc_server_notify(SilcServer server,
            goto out;
          }
        }
-       silc_free(client_id);
       }
+      silc_free(client_id);
 
       if (!channel_id) {
        channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
@@ -934,8 +939,8 @@ void silc_server_notify(SilcServer server,
        if (channel->founder_key) {
          /* Get public key that must be present in notify */
          tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
-         if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len,
-                                                  &founder_key)) {
+         if (!tmp || !silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+                                                          &founder_key)) {
            chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
            silc_server_force_cumode_change(server, sock, channel, chl, mode);
            notify_sent = TRUE;
@@ -1230,6 +1235,12 @@ void silc_server_notify(SilcServer server,
     if (!server_id)
       goto out;
 
+    /* If the ID is mine, this notify is not allowed. */
+    if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
+      SILC_LOG_DEBUG(("Ignoring my own ID for SERVER_SIGNOFF"));
+      break;
+    }
+
     /* Get server entry */
     server_entry = silc_idlist_find_server_by_id(server->global_list, 
                                                 server_id, TRUE, NULL);
@@ -1305,7 +1316,7 @@ void silc_server_notify(SilcServer server,
     silc_free(server_id);
 
     /* Sending SERVER_SIGNOFF is not right way to signoff local connection */
-    if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry)
+    if (SILC_IS_LOCAL(server_entry))
       break;
 
     /* Remove all servers that are originated from this server, and
@@ -1894,11 +1905,6 @@ void silc_server_command_reply(SilcServer server,
 
   SILC_LOG_DEBUG(("Start"));
 
-  /* Source must be server or router */
-  if (packet->src_id_type != SILC_ID_SERVER &&
-      sock->type != SILC_SOCKET_TYPE_ROUTER)
-    return;
-
   if (packet->dst_id_type == SILC_ID_CHANNEL)
     return;
 
@@ -2088,7 +2094,7 @@ void silc_server_channel_key(SilcServer server,
   SilcChannelEntry channel;
 
   if (packet->src_id_type != SILC_ID_SERVER ||
-      (server->server_type == SILC_ROUTER &&
+      (server->server_type == SILC_ROUTER && !server->backup_router &&
        sock->type == SILC_SOCKET_TYPE_ROUTER))
     return;
 
@@ -2313,7 +2319,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   idata->status |= SILC_IDLIST_STATUS_REGISTERED;
   client->nickname = nickname;
   client->username = username;
-  client->userinfo = realname ? realname : strdup(" ");
+  client->userinfo = realname ? realname : strdup(username);
   client->id = client_id;
   id_len = silc_id_get_len(client_id, SILC_ID_CLIENT);
 
@@ -2855,9 +2861,10 @@ void silc_server_new_channel(SilcServer server,
   char *channel_name;
   SilcUInt32 name_len;
   unsigned char *id;
-  SilcUInt32 id_len;
+  SilcUInt32 id_len, cipher_len;
   SilcServerEntry server_entry;
   SilcChannelEntry channel;
+  const char *cipher;
 
   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
       packet->src_id_type != SILC_ID_SERVER ||
@@ -2903,8 +2910,11 @@ void silc_server_new_channel(SilcServer server,
       channel = 
        silc_idlist_add_channel(server->global_list, strdup(channel_name), 
                                0, channel_id, sock->user_data, NULL, NULL, 0);
-      if (!channel)
+      if (!channel) {
+       silc_channel_payload_free(payload);
+       silc_free(channel_id);
        return;
+      }
       channel->disabled = TRUE;    /* Disabled until someone JOINs */
 
       server->stat.channels++;
@@ -2943,6 +2953,7 @@ void silc_server_new_channel(SilcServer server,
        if (silc_id_create_channel_id(server, server->id, server->rng, &tmp)) {
          silc_server_send_notify_channel_change(server, sock, FALSE, 
                                                 channel_id, tmp);
+         silc_channel_payload_free(payload);
          silc_free(channel_id);
          silc_free(tmp);
        }
@@ -2974,15 +2985,16 @@ void silc_server_new_channel(SilcServer server,
       /* Send the new channel key to the server */
       id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
       id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+      cipher = silc_cipher_get_name(channel->channel_key);
+      cipher_len = strlen(cipher);
       chk = silc_channel_key_payload_encode(id_len, id,
-                                           strlen(channel->channel_key->
-                                                  cipher->name),
-                                           channel->channel_key->cipher->name,
+                                           cipher_len, cipher,
                                            channel->key_len / 8, 
                                            channel->key);
       silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
                              chk->data, chk->len, FALSE);
       silc_buffer_free(chk);
+      silc_free(id);
     } else {
       /* The channel exist by that name, check whether the ID's match.
         If they don't then we'll force the server to use the ID we have.
@@ -2997,6 +3009,8 @@ void silc_server_new_channel(SilcServer server,
        SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
        silc_server_send_notify_channel_change(server, sock, FALSE, 
                                               channel_id, channel->id);
+       silc_channel_payload_free(payload);
+       silc_free(channel_id);
 
        /* Wait that server re-announces this channel */
        return;
@@ -3024,8 +3038,11 @@ void silc_server_new_channel(SilcServer server,
       if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
 
        if (silc_hash_table_count(channel->user_list)) {
-         if (!silc_server_create_channel_key(server, channel, 0))
+         if (!silc_server_create_channel_key(server, channel, 0)) {
+           silc_channel_payload_free(payload);
+           silc_free(channel_id);
            return;
+         }
 
          /* Send to the channel */
          silc_server_send_channel_key(server, sock, channel, FALSE);
@@ -3034,11 +3051,10 @@ void silc_server_new_channel(SilcServer server,
        /* Send to the server */
        id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
        id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+       cipher = silc_cipher_get_name(channel->channel_key);
+       cipher_len = strlen(cipher);
        chk = silc_channel_key_payload_encode(id_len, id,
-                                             strlen(channel->channel_key->
-                                                    cipher->name),
-                                             channel->channel_key->
-                                             cipher->name,
+                                             cipher_len, cipher,
                                              channel->key_len / 8, 
                                              channel->key);
        silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
@@ -3049,10 +3065,6 @@ void silc_server_new_channel(SilcServer server,
 
       silc_free(channel_id);
 
-      /* Update statistics */
-      server->stat.channels++;
-      server->stat.cell_channels++;
-
       /* Since the channel is coming from server and we also know about it
         then send the JOIN notify to the server so that it see's our
         users on the channel "joining" the channel. */
@@ -3385,6 +3397,8 @@ SILC_SERVER_CMD_FUNC(resume_resolve)
        silc_server_free_sock_user_data(server, sock, NULL);
       goto out;
     }
+
+    client->data.status |= SILC_IDLIST_STATUS_RESUME_RES;
   }
 
   /* Reprocess the packet */
@@ -3419,6 +3433,7 @@ void silc_server_resume_client(SilcServer server,
   SilcHashTableList htl;
   SilcChannelClientEntry chl;
   SilcServerResumeResolve r;
+  const char *cipher;
 
   ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI16_NSTRING(&id_string, &id_len),
@@ -3455,8 +3470,8 @@ void silc_server_resume_client(SilcServer server,
     idata = (SilcIDListData)client;
 
     /* Get entry to the client, and resolve it if we don't have it. */
-    detached_client = silc_server_get_client_resolve(server, client_id, FALSE,
-                                                    &resolved);
+    detached_client = silc_server_query_client(server, client_id, FALSE,
+                                              &resolved);
     if (!detached_client) {
       if (resolved) {
        /* The client info is being resolved. Reprocess this packet after
@@ -3492,13 +3507,15 @@ void silc_server_resume_client(SilcServer server,
       resolve = TRUE;
     if (!detached_client->nickname)
       resolve = TRUE;
+    if (detached_client->data.status & SILC_IDLIST_STATUS_RESUME_RES)
+      resolve = FALSE;
 
     if (resolve) {
       if (server->server_type == SILC_SERVER && !server->standalone) {
        /* The client info is being resolved. Reprocess this packet after
           receiving the reply to the query. */
        SILC_LOG_DEBUG(("Resolving client info"));
-       silc_server_get_client_resolve(server, client_id, TRUE, NULL);
+       silc_server_query_client(server, client_id, TRUE, NULL);
        r = silc_calloc(1, sizeof(*r));
        if (!r)
          return;
@@ -3611,6 +3628,7 @@ void silc_server_resume_client(SilcServer server,
     silc_idlist_add_data(detached_client, idata);
     detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
     detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
+    detached_client->data.status &= ~SILC_IDLIST_STATUS_RESUME_RES;
     detached_client->mode &= ~SILC_UMODE_DETACHED;
     server->stat.my_detached--;
 
@@ -3626,6 +3644,8 @@ void silc_server_resume_client(SilcServer server,
     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_RESUME_CLIENT, 0, 
                            buf->data, buf->len, TRUE);
+    silc_server_backup_send(server, NULL, SILC_PACKET_RESUME_CLIENT, 0,
+                           buf->data, buf->len, TRUE, TRUE);
 
     /* As router we must deliver this packet directly to the original
        server whom this client was earlier. */
@@ -3648,6 +3668,8 @@ void silc_server_resume_client(SilcServer server,
     if (!silc_idlist_del_client(server->local_list, client))
       silc_idlist_del_client(server->global_list, client);
     client = detached_client;
+    silc_free(client->servername);
+    client->servername = strdup(server->server_name);
 
     /* If the ID is not based in our ID then change it */
     if (!SILC_ID_COMPARE(client->id, server->id, server->id->ip.data_len)) {
@@ -3744,13 +3766,12 @@ void silc_server_resume_client(SilcServer server,
       }
 
       id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+      cipher = silc_cipher_get_name(channel->channel_key);
       keyp = 
        silc_channel_key_payload_encode(silc_id_get_len(channel->id,
                                                        SILC_ID_CHANNEL), 
                                        id_string,
-                                       strlen(channel->channel_key->
-                                              cipher->name),
-                                       channel->channel_key->cipher->name,
+                                       strlen(cipher), cipher,
                                        channel->key_len / 8, channel->key);
       silc_free(id_string);
 
@@ -3862,11 +3883,11 @@ void silc_server_resume_client(SilcServer server,
     /* Get server entry */
     server_entry = silc_idlist_find_server_by_id(server->global_list, 
                                                 server_id, TRUE, NULL);
-    local = TRUE;
+    local = FALSE;
     if (!server_entry) {
       server_entry = silc_idlist_find_server_by_id(server->local_list, 
                                                   server_id, TRUE, NULL);
-      local = FALSE;
+      local = TRUE;
       if (!server_entry) {
        silc_free(server_id);
        silc_free(client_id);