updates.
authorPekka Riikonen <priikone@silcnet.org>
Fri, 3 May 2002 11:08:20 +0000 (11:08 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Fri, 3 May 2002 11:08:20 +0000 (11:08 +0000)
16 files changed:
CHANGES
TODO
apps/irssi/src/silc/core/silc-channels.c
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/packet_receive.c
apps/silcd/server.c
lib/silcclient/client.c
lib/silcclient/client_ftp.c
lib/silcclient/client_notify.c
lib/silcclient/client_resume.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/idlist.c
lib/silcclient/protocol.c
lib/silccore/silcstatus.h

diff --git a/CHANGES b/CHANGES
index 603b64b2aebd4dec7390ab4a92c2d3606e3c496b..1ff1a6c33bde2d9b500c088550bd3527f8d8f5a2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,25 @@
+Fri May  3 11:37:10 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed rekey protocol with PFS in the client library.
+         Affected file is lib/silcclient/protocol.c.
+
+       * Added support for list of errors in client library
+         command reply handling.  Affected file is
+         lib/silcclient/command_reply.c.
+
+       * Defined that the WHOIS and IDENTIFY commands can send
+         list of errors.  Updated the protocol specs.  Protocol
+         TODO #2.
+
+       * Added support for sending list of errors to WHOIS and
+         IDENTIFY commands in server.  Added support for receiving
+         list of errors in server.  Affected files are
+         silcd/command.c and silcd/command_reply.c.
+
+       * Fixed client info resolving on LEAVE command in client
+         library to not crash.  Affected file is 
+         lib/silcclient/client_notify.c.
+
 Thu May  2 08:45:11 CEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * Defined that the NICK command replies with thew changed
diff --git a/TODO b/TODO
index 66547e95bef16fa8703b4c143de4014708af860c..419f7b4518faa6ee88bb70d1c080f6bd7ac4c7b4 100644 (file)
--- a/TODO
+++ b/TODO
@@ -14,11 +14,6 @@ TODO/bugs In SILC Client Library
    set the key only if application wishes to set (accept the key) it
    (Do this to 1.0).
 
- o Additions to do after protocol version 1.1:
-
-       o Add support for list of errors in command replies.  Protocol
-         TODO entry 1.
-
 
 TODO/bugs In SILC Server
 ========================
@@ -33,13 +28,7 @@ TODO/bugs In SILC Server
    and router does not have founder on channel (founder is left or there's
    no founder on channel at all), the router will accept the server's
    founder mode change, even though it perhaps should not do that (Fix 
-   this to 0.9).
-
- o The router should check for validity of received notify packets from
-   routers (fix this to 0.9).  Following NOTIFYs needs to be verified:
-
-       o JOIN (check that joining is allowed)
-       o SIGNOFF (maybe should check that notifier owns the client)
+   this to 0.9) (Protocol TODO #17 relates).
 
  o Implement the SILC_CUMODE_QUIET user mode (Do this to 0.9.x).
 
index 9a11cb66095caed04fcb540325d899461378e5f5..6235e6f012912f0cd12f669eb195342a758305ba 100644 (file)
@@ -156,6 +156,7 @@ static void command_part(const char *data, SILC_SERVER_REC *server,
   signal_emit("message part", 5, server, chanrec->name,
              server->nick, userhost, "");
   
+  chanrec->left = TRUE;
   silc_command_exec(server, "LEAVE", chanrec->name);
   signal_stop();
   
index 9efae7374e4762f7f92ed47a60ba814c1a7d63af..0d222bd360af1463a468fb2f1ef2cafe70341521 100644 (file)
@@ -477,16 +477,18 @@ silc_server_command_pending_error_check(SilcServerCommandContext cmd,
 
 typedef struct {
   void *id;
+  SilcIdType id_type;
   SilcUInt32 index;
   SilcStatus error;
 } *ResolveError;
 
-#define ADD_ERROR(errptr, errptr_count, _id, _index, _status)          \
+#define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status)        \
 do {                                                                   \
   errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
   if (!errptr)                                                         \
     return FALSE;                                                      \
   errptr[errptr_count].id = _id;                                       \
+  errptr[errptr_count].id_type = _id_type;                             \
   errptr[errptr_count].index = _index;                                 \
   errptr[errptr_count].error = _status;                                        \
   errptr_count++;                                                      \
@@ -509,7 +511,7 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
   int i, k;
 
   /* If client ID is in the command it must be used instead of nickname */
-  tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+  tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
   if (!tmp) {
     /* No ID, get the nickname@server string and parse it. */
     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
@@ -524,7 +526,7 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
     /* Command includes ID, we must use that.  Take all ID's from the 
        command packet */
     for (k = 0, i = 0; i < argc; i++) {
-      tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
+      tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
       if (!tmp)
        continue;
       id = silc_id_payload_parse_id(tmp, len, NULL);
@@ -535,7 +537,7 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
        (*client_id_count)++;
        k++;
       } else {
-       ADD_ERROR((*error_client), (*error_client_count), NULL, i + 3,
+       ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
                  SILC_STATUS_ERR_BAD_CLIENT_ID);
       }
     }
@@ -543,11 +545,10 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
 
   /* Get the max count of reply messages allowed */
   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
-  if (tmp) {
+  if (tmp)
     SILC_GET32_MSB(*count, tmp);
-  } else {
+  else
     *count = 0;
-  }
 
   return TRUE;
 }
@@ -653,7 +654,7 @@ silc_server_command_whois_check(SilcServerCommandContext cmd,
                                               sizeof(**r->res_argv));
        memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
        r->res_argv_lens[r->res_argc] = idp->len;
-       r->res_argv_types[r->res_argc] = r->res_argc + 3;
+       r->res_argv_types[r->res_argc] = r->res_argc + 4;
        r->res_argc++;
        silc_buffer_free(idp);
 
@@ -834,7 +835,7 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
       umode_list = NULL;
     }
 
-    if (count && k - 1 == count)
+    if (status == SILC_STATUS_LIST_END)
       break;
     k++;
   }
@@ -870,7 +871,7 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
     silc_buffer_free(idp);
     idp = NULL;
       
-    if (count && k - 1 == count)
+    if (status == SILC_STATUS_LIST_END)
       break;
     k++;
   }
@@ -963,8 +964,8 @@ silc_server_command_whois_process(SilcServerCommandContext cmd)
          goto out;
        }
 
-       ADD_ERROR(error_client, error_client_count, client_id[i], 0,
-                 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+       ADD_ERROR(error_client, error_client_count, client_id[i], 
+                 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
       }
     }
   } else if (nick) {
@@ -1079,11 +1080,10 @@ silc_server_command_whowas_parse(SilcServerCommandContext cmd,
 
   /* Get the max count of reply messages allowed */
   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
-  if (tmp) {
+  if (tmp)
     SILC_GET32_MSB(*count, tmp);
-  } else {
+  else
     *count = 0;
-  }
 
   return TRUE;
 }
@@ -1160,13 +1160,10 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
 
   if (!valid_count) {
     /* No valid entries found at all, just send error */
-    unsigned char *tmp;
-    
     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-    if (tmp)
-      silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
-                                          SILC_STATUS_ERR_NO_SUCH_NICK, 0,
-                                          3, tmp, strlen(tmp));
+    silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
+                                        SILC_STATUS_ERR_NO_SUCH_NICK, 0,
+                                        3, tmp, tmp ? strlen(tmp) : 0);
     return;
   }
 
@@ -1184,8 +1181,6 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
       status = SILC_STATUS_LIST_END;
     if (count && k - 1 == count)
       status = SILC_STATUS_LIST_END;
-    if (count && k - 1 > count)
-      break;
 
     /* Send WHOWAS reply */
     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
@@ -1227,6 +1222,8 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
     silc_buffer_free(packet);
     silc_buffer_free(idp);
 
+    if (status == SILC_STATUS_LIST_END)
+      break;
     k++;
   }
 }
@@ -1382,7 +1379,9 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
                                   SilcUInt32 *servers_count,
                                   SilcChannelEntry **channels,
                                   SilcUInt32 *channels_count,
-                                  SilcUInt32 *count)
+                                  SilcUInt32 *count,
+                                  ResolveError *error_id,
+                                  SilcUInt32 *error_id_count)
 {
   SilcServer server = cmd->server;
   unsigned char *tmp;
@@ -1392,7 +1391,6 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
   bool check_global = FALSE;
   void *entry;
   int i;
-  bool error = FALSE;
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
     check_global = TRUE;
@@ -1513,26 +1511,19 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
        continue;
       
       idp = silc_id_payload_parse(tmp, len);
-      if (!idp) {
-       silc_free(*clients);
-       silc_free(*servers);
-       silc_free(*channels);
-       silc_server_command_send_status_reply(
-                                      cmd, SILC_COMMAND_IDENTIFY,
-                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
-       return 0;
-      }
+      if (!idp)
+       ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
+                 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
 
       id = silc_id_payload_get_id(idp);
-      
       switch (silc_id_payload_get_type(idp)) {
        
       case SILC_ID_CLIENT:
-       entry = (void *)silc_idlist_find_client_by_id(server->local_list, 
-                                                     id, TRUE, NULL);
+       entry = silc_idlist_find_client_by_id(server->local_list, 
+                                             id, TRUE, NULL);
        if (!entry && check_global)
-         entry = (void *)silc_idlist_find_client_by_id(server->global_list, 
-                                                       id, TRUE, NULL);
+         entry = silc_idlist_find_client_by_id(server->global_list, 
+                                               id, TRUE, NULL);
        if (entry) {
          *clients = silc_realloc(*clients, sizeof(**clients) * 
                                  (*clients_count + 1));
@@ -1547,24 +1538,22 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
            silc_free(*clients);
            silc_free(*servers);
            silc_free(*channels);
+           silc_free(*error_id);
            return -1;
-         } else {
-           silc_server_command_send_status_data(
-                                       cmd, SILC_COMMAND_IDENTIFY,
-                                       SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
-                                       0, 2, tmp, len);
-           error = TRUE;
          }
+
+         ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
+                   SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
        }
 
        break;
        
       case SILC_ID_SERVER:
-       entry = (void *)silc_idlist_find_server_by_id(server->local_list, 
-                                                     id, TRUE, NULL);
+       entry = silc_idlist_find_server_by_id(server->local_list, 
+                                             id, TRUE, NULL);
        if (!entry && check_global)
-         entry = (void *)silc_idlist_find_server_by_id(server->global_list, 
-                                                       id, TRUE, NULL);
+         entry = silc_idlist_find_server_by_id(server->global_list, 
+                                               id, TRUE, NULL);
        if (entry) {
          *servers = silc_realloc(*servers, sizeof(**servers) * 
                                  (*servers_count + 1));
@@ -1579,23 +1568,20 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
            silc_free(*clients);
            silc_free(*servers);
            silc_free(*channels);
+           silc_free(*error_id);
            return -1;
-         } else {
-           silc_server_command_send_status_data(
-                                        cmd, SILC_COMMAND_IDENTIFY,
-                                        SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
-                                        0, 2, tmp, len);
-           error = TRUE;
          }
+
+         ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
+                   SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
        }
        break;
        
       case SILC_ID_CHANNEL:
-       entry = (void *)silc_idlist_find_channel_by_id(server->local_list, 
-                                                      id, NULL);
+       entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
        if (!entry && check_global)
-         entry = (void *)silc_idlist_find_channel_by_id(server->global_list, 
-                                                        id, NULL);
+         entry = silc_idlist_find_channel_by_id(server->global_list, id,
+                                                NULL);
        if (entry) {
          *channels = silc_realloc(*channels, sizeof(**channels) * 
                                   (*channels_count + 1));
@@ -1610,14 +1596,12 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
            silc_free(*clients);
            silc_free(*servers);
            silc_free(*channels);
+           silc_free(*error_id);
            return -1;
-         } else {
-           silc_server_command_send_status_data(
-                                        cmd, SILC_COMMAND_IDENTIFY,
-                                        SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
-                                        0, 2, tmp, len);
-           error = TRUE;
          }
+
+         ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
+                   SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
        }
        break;
       }
@@ -1626,20 +1610,12 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
     }
   }
 
-  if (error) {
-    silc_free(*clients);
-    silc_free(*servers);
-    silc_free(*channels);
-    return FALSE;
-  }
-  
   /* Get the max count of reply messages allowed */
   tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
-  if (tmp) {
+  if (tmp)
     SILC_GET32_MSB(*count, tmp);
-  } else {
+  else
     *count = 0;
-  }
 
   return 1;
 }
@@ -1737,7 +1713,7 @@ silc_server_command_identify_check_client(SilcServerCommandContext cmd,
                                               sizeof(**r->res_argv));
        memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
        r->res_argv_lens[r->res_argc] = idp->len;
-       r->res_argv_types[r->res_argc] = r->res_argc + 3;
+       r->res_argv_types[r->res_argc] = r->res_argc + 4;
        r->res_argc++;
        silc_buffer_free(idp);
 
@@ -1793,46 +1769,46 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
                                        SilcUInt32 servers_count,
                                        SilcChannelEntry *channels,
                                        SilcUInt32 channels_count,
+                                       ResolveError errors,
+                                       SilcUInt32 errors_count,
                                        int count)
 {
   SilcServer server = cmd->server;
-  int i, k, len, valid_count;
+  int i, k, valid_count;
+  SilcUInt32 len;
   SilcBuffer packet, idp;
   SilcStatus status;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char nh[256], uh[256];
   SilcSocketConnection hsock;
+  unsigned char *tmp;
 
   status = SILC_STATUS_OK;
 
   if (clients) {
     SilcClientEntry entry;
+    valid_count = clients_count;
+
+    if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
+      /* Process only valid clients and ignore those that are not registered. 
+        This is checked with nickname only because when resolved client IDs
+        we check that they are registered earlier. */
+      valid_count = 0;
+      for (i = 0; i < clients_count; i++) {
+       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
+         valid_count++;
+       else
+         clients[i] = NULL;
+      }
 
-    /* Process only valid entries. */
-    valid_count = 0;
-    for (i = 0; i < clients_count; i++) {
-      if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
-       valid_count++;
-      else
-       clients[i] = NULL;
-    }
-
-    if (!valid_count) {
-      /* No valid entries found at all, just send error */
-      unsigned char *tmp;
-
-      tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-      if (tmp) {
+      if (!valid_count) {
+       /* No valid entries found at all, just send error */
+       tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
                                             SILC_STATUS_ERR_NO_SUCH_NICK, 0,
-                                            3, tmp, strlen(tmp));
-      } else {
-       tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
-       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
-                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
-                                            0, 2, tmp, len);
+                                            3, tmp, tmp ? strlen(tmp) : 0);
+       return;
       }
-      return;
     }
 
     /* Process all valid client entries and send command replies */
@@ -1848,7 +1824,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
       if (k >= 1)
        status = SILC_STATUS_LIST_ITEM;
       if (valid_count > 1 && k == valid_count - 1 
-         && !servers_count && !channels_count)
+         && !servers_count && !channels_count && !errors_count)
        status = SILC_STATUS_LIST_END;
       if (count && k - 1 == count)
        status = SILC_STATUS_LIST_END;
@@ -1898,9 +1874,8 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
       silc_buffer_free(packet);
       silc_buffer_free(idp);
       
-      if (count && k - 1 == count)
+      if (status == SILC_STATUS_LIST_END)
        break;
-
       k++;
     }
   }
@@ -1916,7 +1891,8 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
       
       if (k >= 1)
        status = SILC_STATUS_LIST_ITEM;
-      if (servers_count > 1 && k == servers_count - 1 && !channels_count)
+      if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
+         !errors_count)
        status = SILC_STATUS_LIST_END;
       if (count && k - 1 == count)
        status = SILC_STATUS_LIST_END;
@@ -1936,9 +1912,8 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
       silc_buffer_free(packet);
       silc_buffer_free(idp);
       
-      if (count && k - 1 == count)
+      if (status == SILC_STATUS_LIST_END)
        break;
-
       k++;
     }
   }
@@ -1954,7 +1929,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
       
       if (k >= 1)
        status = SILC_STATUS_LIST_ITEM;
-      if (channels_count > 1 && k == channels_count - 1)
+      if (channels_count > 1 && k == channels_count - 1 && !errors_count)
        status = SILC_STATUS_LIST_END;
       if (count && k - 1 == count)
        status = SILC_STATUS_LIST_END;
@@ -1974,9 +1949,46 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
       silc_buffer_free(packet);
       silc_buffer_free(idp);
       
-      if (count && k - 1 == count)
+      if (status == SILC_STATUS_LIST_END)
        break;
+      k++;
+    }
+  }
+
+  /* Send error replies */
+  if (errors) {
+    if (status == SILC_STATUS_OK && errors_count > 1)
+      status = SILC_STATUS_LIST_START;
 
+    idp = NULL;
+    for (i = 0, k = 0; i < errors_count; i++) {
+      if (errors[i].id) {
+       idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
+       tmp = idp->data;
+       len = idp->len;
+      } else {
+       tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
+      }
+      
+      if (k >= 1)
+       status = SILC_STATUS_LIST_ITEM;
+      if (errors_count > 1 && k == errors_count - 1)
+       status = SILC_STATUS_LIST_END;
+      if (count && k - 1 == count)
+       status = SILC_STATUS_LIST_END;
+      
+      /* Send error */
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+                                          (status == SILC_STATUS_OK ?
+                                           errors[i].error : status),
+                                          (status == SILC_STATUS_OK ?
+                                           0 : errors[i].error),
+                                          2, tmp, len);
+      silc_buffer_free(idp);
+      idp = NULL;
+      
+      if (status == SILC_STATUS_LIST_END)
+       break;
       k++;
     }
   }
@@ -1991,21 +2003,23 @@ silc_server_command_identify_process(SilcServerCommandContext cmd)
   SilcServerEntry *servers = NULL;
   SilcChannelEntry *channels = NULL;
   SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
+  SilcUInt32 errors_count = 0;
+  ResolveError errors = NULL;
 
   /* Parse the IDENTIFY request */
   ret = silc_server_command_identify_parse(cmd,
                                           &clients, &clients_count,
                                           &servers, &servers_count,
                                           &channels, &channels_count,
-                                          &count);
+                                          &count, &errors, &errors_count);
   if (ret < 1)
     return ret;
   ret = 0;
 
   /* Check that all mandatory fields are present and request those data
      from the server who owns the client if necessary. */
-  if (clients && !silc_server_command_identify_check_client(cmd, clients, 
-                                                           clients_count)) {
+  if (!silc_server_command_identify_check_client(cmd, clients, 
+                                                clients_count)) {
     ret = -1;
     goto out;
   }
@@ -2015,12 +2029,14 @@ silc_server_command_identify_process(SilcServerCommandContext cmd)
                                          clients, clients_count,
                                          servers, servers_count,
                                          channels, channels_count, 
+                                         errors, errors_count,
                                          count);
 
  out:
   silc_free(clients);
   silc_free(servers);
   silc_free(channels);
+  silc_free(errors);
   return ret;
 }
 
index eb56f929e90d11fe527305ce7052959e99593c8d..9b344cda9a157b17729b19fe2a7bce772b7dc4c7 100644 (file)
 #include "command_reply.h"
 
 /* All functions that call the COMMAND_CHECK_STATUS macros must have
-   out: goto label. */
-
-#define COMMAND_CHECK_STATUS                                   \
-do {                                                           \
-  SILC_LOG_DEBUG(("Start"));                                   \
-  if (!silc_command_get_status(cmd->payload, &status, &error)) \
-    goto out;                                                  \
+   out: and err: goto labels. */
+
+#define COMMAND_CHECK_STATUS                                           \
+do {                                                                   \
+  SILC_LOG_DEBUG(("Start"));                                           \
+  if (!silc_command_get_status(cmd->payload, &status, &error)) {       \
+    if (SILC_STATUS_IS_ERROR(status))                                  \
+      goto out;                                                                \
+    if (status == SILC_STATUS_LIST_END)                                        \
+      goto out;                                                                \
+    goto err;                                                          \
+  }                                                                    \
 } while(0)
 
 /* Server command reply list. Not all commands have reply function as
@@ -115,6 +120,37 @@ void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
   }
 }
 
+static void 
+silc_server_command_process_error(SilcServerCommandReplyContext cmd,
+                                 SilcStatus error)
+{
+  SilcServer server = cmd->server;
+
+  /* If we received notify for invalid ID we'll remove the ID if we
+     have it cached. */
+  if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
+      cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
+    SilcClientEntry client;
+    SilcUInt32 tmp_len;
+    unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+    if (tmp) {
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+      if (client_id) {
+       SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
+                       "the entry from cache"));
+       client = silc_idlist_find_client_by_id(server->global_list, 
+                                              client_id, FALSE, NULL);
+       if (client) {
+         silc_server_remove_from_channels(server, NULL, client, TRUE, 
+                                          NULL, TRUE);
+         silc_idlist_del_client(server->global_list, client);
+       }
+       silc_free(client_id);
+      }
+    }
+  }
+}
+
 /* Caches the received WHOIS information. */
 
 static char
@@ -253,7 +289,6 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
 SILC_SERVER_CMD_REPLY_FUNC(whois)
 {
   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
-  SilcServer server = cmd->server;
   SilcStatus status, error;
 
   COMMAND_CHECK_STATUS;
@@ -269,32 +304,14 @@ SILC_SERVER_CMD_REPLY_FUNC(whois)
   }
 
  out:
-  /* If we received notify for invalid ID we'll remove the ID if we
-     have it cached. */
-  if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
-      cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
-    SilcClientEntry client;
-    SilcUInt32 tmp_len;
-    unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-    if (tmp) {
-      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-      if (client_id) {
-       SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
-                       "the entry from cache"));
-       client = silc_idlist_find_client_by_id(server->global_list, 
-                                              client_id, FALSE, NULL);
-       if (client) {
-         silc_server_remove_from_channels(server, NULL, client, TRUE, 
-                                          NULL, TRUE);
-         silc_idlist_del_client(server->global_list, client);
-       }
-       silc_free(client_id);
-      }
-    }
-  }
-
+  silc_server_command_process_error(cmd, error);
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
   silc_server_command_reply_free(cmd);
+  return;
+
+ err:
+  silc_server_command_process_error(cmd, error);
+  silc_server_command_reply_free(cmd);
 }
 
 /* Caches the received WHOWAS information for a short period of time. */
@@ -406,6 +423,7 @@ SILC_SERVER_CMD_REPLY_FUNC(whowas)
 
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
+ err:
   silc_server_command_reply_free(cmd);
 }
 
@@ -614,7 +632,6 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
 SILC_SERVER_CMD_REPLY_FUNC(identify)
 {
   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
-  SilcServer server = cmd->server;
   SilcStatus status, error;
 
   COMMAND_CHECK_STATUS;
@@ -630,32 +647,14 @@ SILC_SERVER_CMD_REPLY_FUNC(identify)
   }
 
  out:
-  /* If we received notify for invalid ID we'll remove the ID if we
-     have it cached. */
-  if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
-      cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
-    SilcClientEntry client;
-    SilcUInt32 tmp_len;
-    unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-    if (tmp) {
-      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-      if (client_id) {
-       SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
-                       "the entry from cache"));
-       client = silc_idlist_find_client_by_id(server->global_list, 
-                                              client_id, FALSE, NULL);
-       if (client) {
-         silc_server_remove_from_channels(server, NULL, client, TRUE, 
-                                          NULL, TRUE);
-         silc_idlist_del_client(server->global_list, client);
-       }
-       silc_free(client_id);
-      }
-    }
-  }
-
+  silc_server_command_process_error(cmd, error);
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
   silc_server_command_reply_free(cmd);
+  return;
+
+ err:
+  silc_server_command_process_error(cmd, error);
+  silc_server_command_reply_free(cmd);
 }
 
 /* Received reply fro INFO command. Cache the server and its information */
@@ -712,6 +711,7 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
 
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
+ err:
   silc_server_command_reply_free(cmd);
 }
 
@@ -755,6 +755,7 @@ SILC_SERVER_CMD_REPLY_FUNC(motd)
 
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
+ err:
   silc_server_command_reply_free(cmd);
 
   if (entry)
@@ -958,6 +959,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
 
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
+ err:
   silc_free(client_id);
   silc_server_command_reply_free(cmd);
 
@@ -1005,6 +1007,8 @@ SILC_SERVER_CMD_REPLY_FUNC(stats)
 
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
+ err:
+  silc_server_command_reply_free(cmd);
 }
 
 SILC_SERVER_CMD_REPLY_FUNC(users)
@@ -1096,6 +1100,7 @@ SILC_SERVER_CMD_REPLY_FUNC(users)
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
   silc_free(channel_id);
+ err:
   silc_server_command_reply_free(cmd);
 }
 
@@ -1183,6 +1188,7 @@ SILC_SERVER_CMD_REPLY_FUNC(getkey)
   silc_free(server_id);
   if (public_key)
     silc_pkcs_public_key_free(public_key);
+ err:
   silc_server_command_reply_free(cmd);
 }
 
@@ -1260,6 +1266,7 @@ SILC_SERVER_CMD_REPLY_FUNC(list)
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
   silc_free(channel_id);
+ err:
   silc_server_command_reply_free(cmd);
 }
 
@@ -1272,5 +1279,6 @@ SILC_SERVER_CMD_REPLY_FUNC(watch)
 
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
+ err:
   silc_server_command_reply_free(cmd);
 }
index 080e9eb5c0afde9fa5985f46dfac2ec6b09232c5..20dd6210af285df4be1fdf46d33a2bbc79ad3c34 100644 (file)
@@ -2993,7 +2993,7 @@ void silc_server_resume_client(SilcServer server,
   unsigned char *id_string, *auth = NULL;
   SilcUInt16 id_len, auth_len = 0;
   int ret, nickfail = 0;
-  bool resolved, local, nick_change = FALSE;
+  bool resolved, local, nick_change = FALSE, resolve = FALSE;
   SilcChannelEntry channel;
   SilcHashTableList htl;
   SilcChannelClientEntry chl;
@@ -3060,10 +3060,15 @@ void silc_server_resume_client(SilcServer server,
       return;
     }
 
-    /* Check that the client is detached, and that we have other info too */
-    if (!(detached_client->mode & SILC_UMODE_DETACHED) ||
-       !silc_hash_table_count(detached_client->channels) ||
-       !detached_client->nickname) {
+    if (!(detached_client->mode & SILC_UMODE_DETACHED))
+      resolve = TRUE;
+    if (!silc_hash_table_count(detached_client->channels) &&
+       detached_client->router)
+      resolve = TRUE;
+    if (!detached_client->nickname)
+      resolve = TRUE;
+
+    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. */
@@ -3094,7 +3099,7 @@ void silc_server_resume_client(SilcServer server,
     /* Check that we have the public key of the client, if not then we must
        resolve it first. */
     if (!detached_client->data.public_key) {
-      if (server->standalone) {
+      if (server->server_type == SILC_SERVER && server->standalone) {
        silc_server_disconnect_remote(server, sock,
                                      SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
                                      "Resuming not possible");
index 6aaf3e553dd4a1495c45adf27b601641657a3d6a..6037be57522704dd83a81afe3122fa6092c13e3e 100644 (file)
@@ -4336,7 +4336,7 @@ SilcClientEntry silc_server_get_client_resolve(SilcServer server,
     idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
     buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS,
                                            server->cmd_ident, 1,
-                                           3, idp->data, idp->len);
+                                           4, idp->data, idp->len);
     silc_server_packet_send(server, client ? client->router->connection :
                            server->router->connection,
                            SILC_PACKET_COMMAND, 0,
index ac05ae50e943594545bc50f60a70029a9a185209..b05f81b680c3a887c39a947407525b3c9829e57c 100644 (file)
@@ -1498,7 +1498,7 @@ void silc_client_disconnected_by_server(SilcClient client,
 
   if (packet->len > 1 &&
       silc_utf8_valid(packet->data + 1, packet->len - 1))
-    message = silc_memdup(packet->data, packet->len);
+    message = silc_memdup(packet->data + 1, packet->len - 1);
 
   client->internal->ops->say(client, sock->user_data, 
                             SILC_CLIENT_MESSAGE_AUDIT, 
index 1f19f94567e106c4bfa5a39a9cdffba9be2cd3f4..d22d4e4ceefa85a5a90e590618ecc9880aec896c 100644 (file)
@@ -769,6 +769,7 @@ void silc_client_ftp_session_free(SilcClientFtpSession session)
 
   silc_free(session->hostname);
   silc_free(session->filepath);
+  silc_free(session->path);
   silc_free(session);
 }
 
index 7a2d83e5af7fe7b54b1485435d14a4d9dd30a6cc..b272e242d5e413bea56d30ed7c4d595da0365824 100644 (file)
@@ -892,6 +892,17 @@ void silc_client_notify_by_server(SilcClient client,
        silc_hash_table_del(channel->user_list, client_entry);
        silc_free(chu);
       }
+
+      if (!silc_hash_table_count(client_entry->channels)) {
+       SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
+       res->context = client;
+       res->sock = silc_socket_dup(conn->sock);
+       res->packet = silc_id_dup(client_entry->id, SILC_ID_CLIENT);
+       silc_schedule_task_add(client->schedule, 0,
+                              silc_client_notify_check_client, res,
+                              (5 + (silc_rng_get_rn16(client->rng) % 529)),
+                              0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+      }
     }
     break;
 
index 6cccf3c7cad34053f820a3c5f5e011fa0ebec803..e7d88301fd117df33e7dfc7dfd20d45ab1a536a6 100644 (file)
@@ -208,14 +208,14 @@ SILC_TASK_CALLBACK(silc_client_resume_call_completion)
   SilcClientResumeSession session = context;
   int i;
 
-  session->callback(session->client, session->conn, session->success,
-                   session->context);
-
   for (i = 0; i < session->cmd_idents_count; i++)
     silc_client_command_pending_del(session->conn, SILC_COMMAND_IDENTIFY, 
                                    session->cmd_idents[i]);
   silc_free(session->cmd_idents);
 
+  session->callback(session->client, session->conn, session->success,
+                   session->context);
+
   memset(session, 'F', sizeof(*session));
   silc_free(session);
 }
index 15af4c3801a92516b59bff6ccce560c2e09dac4d..9373396e1ee91cc8fd04a0ca12d5cf045d959772 100644 (file)
@@ -129,6 +129,9 @@ void silc_client_command_pending_del(SilcClientConnection conn,
 {
   SilcClientCommandPending *r;
 
+  if (!conn->pending_commands)
+    return;
+
   silc_dlist_start(conn->pending_commands);
   while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) {
     if (r->reply_cmd == reply_cmd && r->ident == ident) {
index ddb4b0d34ff8a8928818719b8d0b7c52cb9b0523..73d553cb9685e5cd5569637e667b0f1d1476ea6d 100644 (file)
 #define SAY cmd->client->internal->ops->say
 
 /* All functions that call the COMMAND_CHECK_STATUS macro must have 
-   out: goto label. */
+   out: and err: goto labels. out label should call the pending
+   command replies, and the err label just handle error condition. */
 
 #define COMMAND_CHECK_STATUS                                   \
 do {                                                           \
   SILC_LOG_DEBUG(("Start"));                                   \
   if (!silc_command_get_status(cmd->payload, NULL, NULL)) {    \
+    if (SILC_STATUS_IS_ERROR(cmd->status)) {                   \
+      /* Single error */                                       \
+      COMMAND_REPLY_ERROR;                                     \
+      goto out;                                                        \
+    }                                                          \
+    /* List of errors */                                       \
     COMMAND_REPLY_ERROR;                                       \
-    goto out;                                                  \
+    if (cmd->status == SILC_STATUS_LIST_END)                   \
+      goto out;                                                        \
+    goto err;                                                  \
+  }                                                            \
+} while(0)
+
+/* Same as COMMAND_CHECK_STATUS but doesn't call client operation */
+#define COMMAND_CHECK_STATUS_I                                 \
+do {                                                           \
+  SILC_LOG_DEBUG(("Start"));                                   \
+  if (!silc_command_get_status(cmd->payload, NULL, NULL)) {    \
+    if (SILC_STATUS_IS_ERROR(cmd->status))                     \
+      goto out;                                                        \
+    if (cmd->status == SILC_STATUS_LIST_END)                   \
+      goto out;                                                        \
+    goto err;                                                  \
   }                                                            \
 } while(0)
 
@@ -236,6 +258,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois)
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
 
+ err:
   /* If we received notify for invalid ID we'll remove the ID if we
      have it cached. */
   if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
@@ -312,6 +335,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
 
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
+ err:
   silc_client_command_reply_free(cmd);
 }
 
@@ -454,6 +478,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify)
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
 
+ err:
   /* If we received notify for invalid ID we'll remove the ID if we
      have it cached. */
   if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
@@ -599,6 +624,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(list)
  out:
   silc_free(channel_id);
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
+ err:
   silc_client_command_reply_free(cmd);
 }
 
@@ -1595,7 +1621,7 @@ silc_client_command_reply_users_save(SilcClientCommandReplyContext cmd,
                                    (res_argc + 1));
       res_argv[res_argc] = client_id_list.data;
       res_argv_lens[res_argc] = idp_len;
-      res_argv_types[res_argc] = res_argc + 3;
+      res_argv_types[res_argc] = res_argc + 4;
       res_argc++;
     } else {
       if (!silc_client_on_channel(channel, client_entry)) {
@@ -1793,10 +1819,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois_i)
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
 
-  SILC_LOG_DEBUG(("Start"));
-
-  if (cmd->error != SILC_STATUS_OK)
-    goto out;
+  COMMAND_CHECK_STATUS_I;
 
   /* Save WHOIS info */
   silc_client_command_reply_whois_save(cmd, cmd->status, FALSE);
@@ -1811,6 +1834,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois_i)
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
 
+ err:
   /* If we received notify for invalid ID we'll remove the ID if we
      have it cached. */
   if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
@@ -1844,10 +1868,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify_i)
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
 
-  SILC_LOG_DEBUG(("Start"));
-
-  if (cmd->error != SILC_STATUS_OK)
-    goto out;
+  COMMAND_CHECK_STATUS_I;
 
   /* Save IDENTIFY info */
   silc_client_command_reply_identify_save(cmd, cmd->status, FALSE);
@@ -1862,6 +1883,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify_i)
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
 
+ err:
   /* If we received notify for invalid ID we'll remove the ID if we
      have it cached. */
   if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
@@ -1900,10 +1922,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i)
   char *server_name, *server_info;
   SilcUInt32 len;
 
-  SILC_LOG_DEBUG(("Start"));
-
-  if (cmd->error != SILC_STATUS_OK)
-    goto out;
+  COMMAND_CHECK_STATUS_I;
 
   /* Get server ID */
   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
@@ -1935,6 +1954,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i)
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
   silc_free(server_id);
+ err:
   silc_client_command_reply_free(cmd);
 }
 
@@ -1964,10 +1984,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users_i)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
 
-  SILC_LOG_DEBUG(("Start"));
-
-  if (cmd->error != SILC_STATUS_OK)
-    goto out;
+  COMMAND_CHECK_STATUS_I;
 
   /* Save USERS info */
   if (silc_client_command_reply_users_save(
@@ -1979,6 +1996,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users_i)
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
 
+ err:
   /* Unregister this command reply */
   silc_client_command_unregister(cmd->client, SILC_COMMAND_USERS,
                                 NULL, silc_client_command_reply_users_i,
index 2d5a8c0cdb8f2fc780605d6252cdbc32b5a828e1..a7fd0f71f135fc007f037aed8a97b143531d1491 100644 (file)
@@ -558,7 +558,7 @@ void silc_client_get_client_by_id_resolve(SilcClient client,
   /* Send the command */
   idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
   silc_client_command_send(client, conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
-                          1, 3, idp->data, idp->len);
+                          1, 4, idp->data, idp->len);
   silc_buffer_free(idp);
 
   /* Add pending callback */
index 6ab25d6806b4d7a7fbb8050961be574bb91abc34..4e955a6efc4797e73cdfb9566146702098be40c4 100644 (file)
@@ -1079,7 +1079,10 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
 
     /* We received the REKEY_DONE packet and all packets after this is
        encrypted with the new key so set the decryption key to the new key */
-    silc_client_protocol_rekey_generate(client, ctx, FALSE);
+    if (ctx->pfs == TRUE)
+      silc_client_protocol_rekey_generate_pfs(client, ctx, FALSE);
+    else
+      silc_client_protocol_rekey_generate(client, ctx, FALSE);
 
     /* Protocol has ended, call the final callback */
     if (protocol->final_callback)
index dea64e94184d3e8d5a9555cc4976a2e781fd4b42..f619ea9ed5964cb54983d9f5c3658833e92d9f91 100644 (file)
@@ -101,4 +101,6 @@ typedef SilcUInt8 SilcStatus;
 #define SILC_STATUS_ERR_BAD_VERSION         53
 /***/
 
+#define SILC_STATUS_IS_ERROR(status) (status >= SILC_STATUS_ERR_NO_SUCH_NICK)
+
 #endif /* SILCSTATUS_H */