More disconnection crash fixes.
[runtime.git] / apps / silcd / server.c
index 9f68e5b8f4fd869ea3f6ff407652e432b4ea4a52..5b88aa2819317a602529758c28d1df301daa3bc3 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2007 Pekka Riikonen
+  Copyright (C) 1997 - 2008 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
@@ -108,11 +108,10 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine,
       packet->type != SILC_PACKET_DISCONNECT)
     return FALSE;
 
-  /* NEW_CLIENT, NEW_SERVER and RESUME_CLIENT are accepted only without
-     source ID and for unregistered connection. */
+  /* NEW_CLIENT and NEW_SERVER are accepted only without source ID and
+     for unregistered connection. */
   if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT ||
-                        packet->type == SILC_PACKET_NEW_SERVER ||
-                        packet->type == SILC_PACKET_RESUME_CLIENT) &&
+                        packet->type == SILC_PACKET_NEW_SERVER) &&
       (idata->status & SILC_IDLIST_STATUS_REGISTERED))
     return FALSE;
 
@@ -195,7 +194,7 @@ static void silc_server_packet_eos(SilcPacketEngine engine,
   SilcServer server = callback_context;
   SilcIDListData idata = silc_packet_get_context(stream);
 
-  SILC_LOG_DEBUG(("End of stream received"));
+  SILC_LOG_DEBUG(("End of stream received, sock %p", stream));
 
   if (!idata)
     return;
@@ -203,6 +202,7 @@ static void silc_server_packet_eos(SilcPacketEngine engine,
   if (server->router_conn && server->router_conn->sock == stream &&
       !server->router && server->standalone) {
     silc_server_create_connections(server);
+    silc_server_free_sock_user_data(server, stream, NULL);
   } else {
     /* If backup disconnected then mark that resuming will not be allowed */
      if (server->server_type == SILC_ROUTER && !server->backup_router &&
@@ -259,6 +259,8 @@ static void silc_server_packet_error(SilcPacketEngine engine,
   const char *ip;
   SilcUInt16 port;
 
+  SILC_LOG_DEBUG(("Packet error, sock %p", stream));
+
   if (!idata || !sock)
     return;
 
@@ -269,6 +271,9 @@ static void silc_server_packet_error(SilcPacketEngine engine,
                  SILC_CONNTYPE_STRING(idata->conn_type),
                  silc_packet_error_string(error)));
 
+  if (!silc_packet_stream_is_valid(stream))
+    return;
+
   silc_schedule_task_add_timeout(server->schedule,
                                 silc_server_packet_error_timeout,
                                 stream, 0, 0);
@@ -1287,6 +1292,8 @@ SILC_TASK_CALLBACK(silc_server_purge_expired_clients)
 
 void silc_server_connection_free(SilcServerConnection sconn)
 {
+  if (!sconn)
+    return;
   SILC_LOG_DEBUG(("Free connection %p", sconn));
   silc_dlist_del(sconn->server->conns, sconn);
   silc_server_config_unref(&sconn->conn);
@@ -1342,9 +1349,10 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
   SilcID remote_id;
   const char *ip;
 
-  SILC_LOG_DEBUG(("Connection authentication completed"));
+  SILC_LOG_DEBUG(("Connection %p authentication completed, entry %p",
+                 sconn, entry));
 
-  sconn->op = NULL;
+  entry->op = NULL;
 
   if (success == FALSE) {
     /* Authentication failed */
@@ -1354,7 +1362,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                  SILC_STATUS_ERR_AUTH_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
-    silc_server_connection_free(sconn);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     return;
   }
 
@@ -1380,8 +1388,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                    SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-      silc_server_connection_free(sconn);
-      silc_free(entry);
+      silc_server_free_sock_user_data(server, sconn->sock, NULL);
       return;
     }
 
@@ -1410,8 +1417,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                    SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-      silc_server_connection_free(sconn);
-      silc_free(entry);
+      silc_server_free_sock_user_data(server, sconn->sock, NULL);
       return;
     }
 
@@ -1449,8 +1455,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                    SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-      silc_server_connection_free(sconn);
-      silc_free(entry);
+      silc_server_free_sock_user_data(server, sconn->sock, NULL);
       return;
     }
 
@@ -1513,8 +1518,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                      SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        if (sconn->callback)
          (*sconn->callback)(server, NULL, sconn->callback_context);
-       silc_server_connection_free(sconn);
-       silc_free(entry);
+       silc_server_free_sock_user_data(server, sconn->sock, NULL);
        return;
 #endif /* 0 */
       }
@@ -1532,8 +1536,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                  SILC_STATUS_ERR_AUTH_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
-    silc_server_connection_free(sconn);
-    silc_free(entry);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     return;
   }
 
@@ -1573,7 +1576,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
 {
   SilcPacketStream sock = context;
   SilcUnknownEntry entry = silc_packet_get_context(sock);
-  SilcServerConnection sconn = silc_ske_get_context(ske);
+  SilcServerConnection sconn = entry->data.sconn;
   SilcServer server = entry->server;
   SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
   SilcAuthMethod auth_meth = SILC_AUTH_NONE;
@@ -1584,7 +1587,9 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
   SilcHmac hmac_send, hmac_receive;
   SilcHash hash;
 
-  sconn->op = NULL;
+  SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry));
+
+  entry->op = NULL;
 
   if (status != SILC_SKE_STATUS_OK) {
     /* SKE failed */
@@ -1597,7 +1602,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
-    silc_server_connection_free(sconn);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     return;
   }
 
@@ -1615,7 +1620,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
-    silc_server_connection_free(sconn);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     return;
   }
   silc_packet_set_keys(sconn->sock, send_key, receive_key, hmac_send,
@@ -1634,7 +1639,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
-    silc_server_connection_free(sconn);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     return;
   }
 
@@ -1658,7 +1663,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
   entry->data.rekey = rekey;
 
   /* Start connection authentication */
-  sconn->op =
+  entry->op =
     silc_connauth_initiator(connauth, server->server_type == SILC_SERVER ?
                            SILC_CONN_SERVER : SILC_CONN_ROUTER, auth_meth,
                            auth_data, auth_data_len,
@@ -1711,8 +1716,11 @@ void silc_server_start_key_exchange(SilcServerConnection sconn)
     return;
   }
   entry->server = server;
+  entry->data.sconn = sconn;
   silc_packet_set_context(sconn->sock, entry);
 
+  SILC_LOG_DEBUG(("Created unknown connection %p", entry));
+
   /* Set Key Exchange flags from configuration, but fall back to global
      settings too. */
   memset(&params, 0, sizeof(params));
@@ -1721,7 +1729,7 @@ void silc_server_start_key_exchange(SilcServerConnection sconn)
     params.flags |= SILC_SKE_SP_FLAG_PFS;
 
   /* Start SILC Key Exchange protocol */
-  SILC_LOG_DEBUG(("Starting key exchange protocol"));
+  SILC_LOG_DEBUG(("Starting key exchange protocol, connection %p", sconn));
   ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
                       server->public_key, server->private_key, sconn);
   if (!ske) {
@@ -1738,7 +1746,7 @@ void silc_server_start_key_exchange(SilcServerConnection sconn)
   /* Start key exchange protocol */
   params.version = silc_version_string;
   params.timeout_secs = server->config->key_exchange_timeout;
-  sconn->op = silc_ske_initiator(ske, sconn->sock, &params, NULL);
+  entry->op = silc_ske_initiator(ske, sconn->sock, &params, NULL);
 }
 
 /* Timeout callback that will be called to retry connecting to remote
@@ -1805,7 +1813,7 @@ static void silc_server_connection_established(SilcNetStatus status,
 
   switch (status) {
   case SILC_NET_OK:
-    SILC_LOG_DEBUG(("Connection to %s:%d established",
+    SILC_LOG_DEBUG(("Connection %p to %s:%d established", sconn,
                    sconn->remote_host, sconn->remote_port));
 
     /* Continue with key exchange protocol */
@@ -2142,6 +2150,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
     server->stat.auth_failures++;
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+    silc_server_config_unref(&entry->cconfig);
+    silc_server_config_unref(&entry->sconfig);
+    silc_server_config_unref(&entry->rconfig);
+    silc_server_free_sock_user_data(server, sock, NULL);
     goto out;
   }
 
@@ -2180,6 +2192,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
                                        SILC_STATUS_ERR_PERM_DENIED,
                                        "We do not have connection to backup "
                                        "router established, try later");
+         silc_server_config_unref(&entry->cconfig);
+         silc_server_config_unref(&entry->sconfig);
+         silc_server_config_unref(&entry->rconfig);
+         silc_server_free_sock_user_data(server, sock, NULL);
          server->stat.auth_failures++;
 
          /* From here on, wait 20 seconds for the backup router to appear. */
@@ -2204,6 +2220,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
        server->stat.auth_failures++;
        silc_server_disconnect_remote(server, sock,
                                      SILC_STATUS_ERR_AUTH_FAILED, NULL);
+       silc_server_config_unref(&entry->cconfig);
+       silc_server_config_unref(&entry->sconfig);
+       silc_server_config_unref(&entry->rconfig);
+       silc_server_free_sock_user_data(server, sock, NULL);
        goto out;
       }
       entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
@@ -2270,6 +2290,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
                                      SILC_STATUS_ERR_PERM_DENIED,
                                      "We do not have connection to primary "
                                      "router established, try later");
+       silc_server_config_unref(&entry->cconfig);
+       silc_server_config_unref(&entry->sconfig);
+       silc_server_config_unref(&entry->rconfig);
+       silc_server_free_sock_user_data(server, sock, NULL);
        server->stat.auth_failures++;
        goto out;
       }
@@ -2281,6 +2305,9 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
                                            &server->config->param,
                                            rconn ? rconn->param : NULL,
                                            silc_connauth_get_ske(connauth))) {
+         silc_server_config_unref(&entry->cconfig);
+         silc_server_config_unref(&entry->sconfig);
+         silc_server_config_unref(&entry->rconfig);
          server->stat.auth_failures++;
          goto out;
        }
@@ -2357,6 +2384,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
                                        SILC_STATUS_ERR_PERM_DENIED,
                                        "We do not have connection to backup "
                                        "router established, try later");
+         silc_server_config_unref(&entry->cconfig);
+         silc_server_config_unref(&entry->sconfig);
+         silc_server_config_unref(&entry->rconfig);
+         silc_server_free_sock_user_data(server, sock, NULL);
          server->stat.auth_failures++;
 
          /* From here on, wait 20 seconds for the backup router to appear. */
@@ -2397,6 +2428,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
        SILC_LOG_ERROR(("Could not add new server to cache"));
        silc_server_disconnect_remote(server, sock,
                                      SILC_STATUS_ERR_AUTH_FAILED, NULL);
+       silc_server_config_unref(&entry->cconfig);
+       silc_server_config_unref(&entry->sconfig);
+       silc_server_config_unref(&entry->rconfig);
+       silc_server_free_sock_user_data(server, sock, NULL);
        server->stat.auth_failures++;
        goto out;
       }
@@ -2520,6 +2555,10 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
     silc_ske_free(ske);
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+    silc_server_config_unref(&entry->cconfig);
+    silc_server_config_unref(&entry->sconfig);
+    silc_server_config_unref(&entry->rconfig);
+    silc_server_free_sock_user_data(server, sock, NULL);
     return;
   }
 
@@ -2532,6 +2571,7 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
     silc_ske_free(ske);
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+    silc_server_free_sock_user_data(server, sock, NULL);
     return;
   }
   silc_packet_set_keys(sock, send_key, receive_key, hmac_send,
@@ -2554,6 +2594,10 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
     silc_ske_free(ske);
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+    silc_server_config_unref(&entry->cconfig);
+    silc_server_config_unref(&entry->sconfig);
+    silc_server_config_unref(&entry->rconfig);
+    silc_server_free_sock_user_data(server, sock, NULL);
     return;
   }
 
@@ -2613,6 +2657,8 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
   }
   server->stat.conn_num++;
 
+  SILC_LOG_DEBUG(("Created packet stream %p", packet_stream));
+
   /* Set source ID to packet stream */
   if (!silc_packet_set_ids(packet_stream, SILC_ID_SERVER, server->id,
                           0, NULL)) {
@@ -2632,6 +2678,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
     silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_BANNED_FROM_SERVER,
                                  deny->reason);
+    silc_server_free_sock_user_data(server, packet_stream, NULL);
     return;
   }
 
@@ -2650,6 +2697,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
     server->stat.conn_failures++;
     silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL);
+    silc_server_free_sock_user_data(server, packet_stream, NULL);
     return;
   }
 
@@ -2659,6 +2707,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
     server->stat.conn_failures++;
     silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+    silc_server_free_sock_user_data(server, packet_stream, NULL);
     return;
   }
   entry->hostname = hostname;
@@ -2668,6 +2717,8 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
   entry->data.conn_type = SILC_CONN_UNKNOWN;
   silc_packet_set_context(packet_stream, entry);
 
+  SILC_LOG_DEBUG(("Created unknown connection %p", entry));
+
   silc_server_config_ref(&entry->cconfig, server->config, cconfig);
   silc_server_config_ref(&entry->sconfig, server->config, sconfig);
   silc_server_config_ref(&entry->rconfig, server->config, rconfig);
@@ -2694,6 +2745,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
     server->stat.conn_failures++;
     silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+    silc_server_free_sock_user_data(server, packet_stream, NULL);
     return;
   }
   silc_ske_set_callbacks(ske, silc_server_verify_key,
@@ -2816,9 +2868,9 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock,
   SilcIDListData idata = silc_packet_get_context(sock);
   SilcSKE ske;
 
-  SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]",
+  SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s], sock %p",
                  idata->sconn->remote_host, idata->sconn->remote_port,
-                 SILC_CONNTYPE_STRING(idata->conn_type)));
+                 SILC_CONNTYPE_STRING(idata->conn_type), sock));
 
   /* Allocate SKE */
   ske = silc_ske_alloc(server->rng, server->schedule, NULL,
@@ -2843,7 +2895,7 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock,
 
 SILC_TASK_CALLBACK(silc_server_close_connection_final)
 {
-  silc_packet_stream_destroy(context);
+  silc_packet_stream_unref(context);
 }
 
 /* Closes connection to socket connection */
@@ -2856,6 +2908,9 @@ void silc_server_close_connection(SilcServer server,
   const char *hostname;
   SilcUInt16 port;
 
+  if (!silc_packet_stream_is_valid(sock))
+    return;
+
   memset(tmp, 0, sizeof(tmp));
   //  silc_socket_get_error(sock, tmp, sizeof(tmp));
   silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
@@ -2871,6 +2926,11 @@ void silc_server_close_connection(SilcServer server,
     idata->sconn = NULL;
   }
 
+  /* Take a reference and then destroy the stream.  The last reference
+     is released later in a timeout callback. */
+  silc_packet_stream_ref(sock);
+  silc_packet_stream_destroy(sock);
+
   /* Close connection with timeout */
   server->stat.conn_num--;
   silc_schedule_task_del_by_all(server->schedule, 0,
@@ -2894,7 +2954,7 @@ void silc_server_disconnect_remote(SilcServer server,
   if (!sock)
     return;
 
-  SILC_LOG_DEBUG(("Disconnecting remote host"));
+  SILC_LOG_DEBUG(("Disconnecting remote host, sock %p", sock));
 
   va_start(ap, status);
   cp = va_arg(ap, char *);
@@ -2962,8 +3022,10 @@ void silc_server_free_client_data(SilcServer server,
   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
   silc_schedule_task_del_by_context(server->schedule, client);
 
-  if (client->data.sconn)
+  if (client->data.sconn) {
     silc_server_connection_free(client->data.sconn);
+    client->data.sconn = NULL;
+  }
 
   /* We will not delete the client entry right away. We will take it
      into history (for WHOWAS command) for 5 minutes, unless we're
@@ -2991,16 +3053,21 @@ void silc_server_free_sock_user_data(SilcServer server,
                                     SilcPacketStream sock,
                                     const char *signoff_message)
 {
-  SilcIDListData idata = silc_packet_get_context(sock);
+  SilcIDListData idata;
   const char *ip;
   SilcUInt16 port;
 
-  SILC_LOG_DEBUG(("Start"));
+  if (!sock)
+    return;
 
+  SILC_LOG_DEBUG(("Start, sock %p", sock));
+
+  idata = silc_packet_get_context(sock);
   if (!idata)
     return;
 
-  silc_schedule_task_del_by_context(server->schedule, sock);
+  silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_rekey,
+                               sock);
 
   /* Cancel active protocols */
   if (idata) {
@@ -3183,8 +3250,10 @@ void silc_server_free_sock_user_data(SilcServer server,
       }
       server->backup_noswitch = FALSE;
 
-      if (idata->sconn)
+      if (idata->sconn) {
        silc_server_connection_free(idata->sconn);
+       idata->sconn = NULL;
+      }
 
       /* Statistics */
       if (idata->conn_type == SILC_CONN_SERVER) {
@@ -3228,10 +3297,12 @@ void silc_server_free_sock_user_data(SilcServer server,
     {
       SilcUnknownEntry entry = (SilcUnknownEntry)idata;
 
-      SILC_LOG_DEBUG(("Freeing unknown connection data"));
+      SILC_LOG_DEBUG(("Freeing unknown connection data %p", entry));
 
-      if (idata->sconn)
+      if (idata->sconn) {
        silc_server_connection_free(idata->sconn);
+       idata->sconn = NULL;
+      }
       silc_idlist_del_data(idata);
       silc_free(entry);
       silc_packet_set_context(sock, NULL);
@@ -4122,6 +4193,7 @@ void silc_server_announce_get_inviteban(SilcServer server,
 {
   SilcBuffer list, idp, idp2, tmp2;
   SilcUInt32 type;
+  void *ptype;
   SilcHashTableList htl;
   const unsigned char a[1] = { 0x03 };
 
@@ -4133,9 +4205,10 @@ void silc_server_announce_get_inviteban(SilcServer server,
     type = silc_hash_table_count(channel->invite_list);
     SILC_PUT16_MSB(type, list->data);
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
-      list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
-                                              type);
+    while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2))
+      list = silc_argument_payload_encode_one(list, tmp2->data,
+                                             silc_buffer_len(tmp2),
+                                             SILC_PTR_TO_32(ptype));
     silc_hash_table_list_reset(&htl);
 
     idp2 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
@@ -4157,9 +4230,10 @@ void silc_server_announce_get_inviteban(SilcServer server,
     type = silc_hash_table_count(channel->ban_list);
     SILC_PUT16_MSB(type, list->data);
     silc_hash_table_list(channel->ban_list, &htl);
-    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
-      list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
-                                              type);
+    while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2))
+      list = silc_argument_payload_encode_one(list, tmp2->data,
+                                             silc_buffer_len(tmp2),
+                                             SILC_PTR_TO_32(ptype));
     silc_hash_table_list_reset(&htl);
 
     *ban =