From 9cca2bb4ed4a0f11e8250c49799f555e8dfacd45 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sat, 29 Jun 2002 18:07:28 +0000 Subject: [PATCH] Memory leak fixes. --- apps/silcd/command.c | 12 ++++--- apps/silcd/command_reply.c | 1 + apps/silcd/packet_receive.c | 16 ++++++--- apps/silcd/server.c | 64 +++++++++++++++++++++++++++--------- apps/silcd/server_internal.h | 4 +++ apps/silcd/server_util.c | 26 +++++++++++---- lib/silcclient/command.c | 1 + lib/silccore/silcid.h | 3 +- 8 files changed, 95 insertions(+), 32 deletions(-) diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 6d0dcd8e..65b41e2d 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -368,6 +368,7 @@ void silc_server_command_pending_del(SilcServer server, while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) { if (r->reply_cmd == reply_cmd && r->ident == ident) { silc_dlist_del(server->pending_commands, r); + silc_free(r); break; } } @@ -1617,6 +1618,7 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd, break; } + silc_id_payload_free(idp); silc_free(id); } } @@ -4289,6 +4291,8 @@ SILC_SERVER_CMD_FUNC(cmode) silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, SILC_STATUS_ERR_AUTH_FAILED, 0); + silc_pkcs_public_key_free(channel->founder_key); + channel->founder_key = NULL; goto out; } } @@ -4927,7 +4931,7 @@ SILC_SERVER_CMD_FUNC(oper) client->mode |= SILC_UMODE_SERVER_OPERATOR; /* Update statistics */ - if (client->connection) + if (SILC_IS_LOCAL(client)) server->stat.my_server_ops++; if (server->server_type == SILC_ROUTER) server->stat.server_ops++; @@ -5018,8 +5022,8 @@ SILC_SERVER_CMD_FUNC(detach) /* Remove operator privileges, since the client may resume in some other server which to it does not have operator privileges. */ - client->mode &= ~(SILC_UMODE_SERVER_OPERATOR | - SILC_UMODE_ROUTER_OPERATOR); + SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); + SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); /* Send the user mode notify to notify that client is detached */ client->mode |= SILC_UMODE_DETACHED; @@ -5318,7 +5322,7 @@ SILC_SERVER_CMD_FUNC(silcoper) client->mode |= SILC_UMODE_ROUTER_OPERATOR; /* Update statistics */ - if (client->connection) + if (SILC_IS_LOCAL(client)) server->stat.my_router_ops++; if (server->server_type == SILC_ROUTER) server->stat.router_ops++; diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index 74e3d45e..76a30b89 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -143,6 +143,7 @@ silc_server_command_process_error(SilcServerCommandReplyContext cmd, if (client) { silc_server_remove_from_channels(server, NULL, client, TRUE, NULL, TRUE); + silc_idlist_del_data(client); silc_idlist_del_client(server->global_list, client); } silc_free(client_id); diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index fd45c463..2068c18b 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -173,8 +173,10 @@ void silc_server_notify(SilcServer server, NULL); if (!client) { /* If router did not find the client the it is bogus */ - if (server->server_type != SILC_SERVER) + if (server->server_type != SILC_SERVER) { + silc_free(client_id); goto out; + } client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL, @@ -189,6 +191,7 @@ void silc_server_notify(SilcServer server, client->data.status |= SILC_IDLIST_STATUS_REGISTERED; } } + silc_free(client_id); /* Do not process the notify if the client is not registered */ if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) @@ -233,7 +236,6 @@ void silc_server_notify(SilcServer server, silc_hash_table_add(channel->user_list, client, chl); silc_hash_table_add(client->channels, channel, chl); - silc_free(client_id); channel->user_count++; channel->disabled = FALSE; @@ -422,6 +424,7 @@ void silc_server_notify(SilcServer server, goto out; } } + silc_free(channel_id); if (channel->topic && !strcmp(channel->topic, tmp)) { SILC_LOG_DEBUG(("Topic is already set and same")); @@ -448,7 +451,6 @@ void silc_server_notify(SilcServer server, silc_server_packet_send_to_channel(server, NULL, channel, packet->type, FALSE, packet->buffer->data, packet->buffer->len, FALSE); - silc_free(channel_id); break; case SILC_NOTIFY_TYPE_NICK_CHANGE: @@ -475,8 +477,10 @@ void silc_server_notify(SilcServer server, if (!id2) goto out; client_id2 = silc_id_payload_parse_id(id2, tmp_len, NULL); - if (!client_id2) + if (!client_id2) { + silc_free(client_id); goto out; + } SILC_LOG_DEBUG(("Old Client ID id(%s)", silc_id_render(client_id, SILC_ID_CLIENT))); @@ -1284,6 +1288,7 @@ void silc_server_notify(SilcServer server, silc_server_del_from_watcher_list(server, client); /* Remove the client */ + silc_idlist_del_data(client); silc_idlist_del_client(local ? server->local_list : server->global_list, client); } @@ -1578,6 +1583,8 @@ void silc_server_notify(SilcServer server, server->stat.detached--; } } + SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR); + SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR); /* Change the mode */ client->mode = mode; @@ -1684,6 +1691,7 @@ void silc_server_notify(SilcServer server, if (client) { silc_server_remove_from_channels(server, NULL, client, TRUE, NULL, TRUE); + silc_idlist_del_data(client); silc_idlist_del_client(server->global_list, client); } silc_free(client_id); diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 83bb1254..cde4d750 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -675,7 +675,8 @@ void silc_server_stop(SilcServer server) if (!server->sockets[i]) continue; if (!SILC_IS_LISTENER(server->sockets[i])) { - SilcIDListData idata = server->sockets[i]->user_data; + SilcSocketConnection sock = server->sockets[i]; + SilcIDListData idata = sock->user_data; if (idata) idata->status &= ~SILC_IDLIST_STATUS_DISABLED; @@ -685,6 +686,10 @@ void silc_server_stop(SilcServer server) silc_server_disconnect_remote(server, server->sockets[i], SILC_STATUS_OK, "Server is shutting down"); + if (sock->user_data) + silc_server_free_sock_user_data(server, sock, + "Server is shutting down"); + silc_socket_free(sock); } else { silc_socket_free(server->sockets[i]); server->sockets[i] = NULL; @@ -798,6 +803,15 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry) SilcServerConfigConnParams *param = (conn->param ? conn->param : &server->config->param); + /* Don't retry if we are shutting down. */ + if (server->server_shutdown) { + silc_server_config_unref(&sconn->conn); + silc_free(sconn->remote_host); + silc_free(sconn->backup_replace_ip); + silc_free(sconn); + return; + } + SILC_LOG_INFO(("Retrying connecting to a router")); /* Calculate next timeout */ @@ -844,6 +858,14 @@ SILC_TASK_CALLBACK(silc_server_connect_router) SilcServerConfigRouter *rconn; int sock; + /* Don't connect if we are shutting down. */ + if (server->server_shutdown) { + silc_free(sconn->remote_host); + silc_free(sconn->backup_replace_ip); + silc_free(sconn); + return; + } + SILC_LOG_INFO(("Connecting to the %s %s on port %d", (sconn->backup ? "backup router" : "router"), sconn->remote_host, sconn->remote_port)); @@ -895,6 +917,10 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) SilcServerConnection sconn; SilcServerConfigRouter *ptr; + /* Don't connect if we are shutting down. */ + if (server->server_shutdown) + return; + SILC_LOG_DEBUG(("We are %s", (server->server_type == SILC_SERVER ? "normal server" : server->server_type == SILC_ROUTER ? @@ -1311,7 +1337,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final) out: /* Call the completion callback to indicate that we've connected to the router */ - if (sconn->callback) + if (sconn && sconn->callback) (*sconn->callback)(server, id_entry, sconn->callback_context); /* Free the temporary connection data context */ @@ -2891,8 +2917,6 @@ void silc_server_free_client_data(SilcServer server, int notify, const char *signoff) { - FreeClientInternal i = silc_calloc(1, sizeof(*i)); - SILC_LOG_DEBUG(("Freeing client data")); #if 1 @@ -2943,18 +2967,26 @@ void silc_server_free_client_data(SilcServer server, silc_schedule_task_del_by_context(server->schedule, client); /* We will not delete the client entry right away. We will take it - into history (for WHOWAS command) for 5 minutes */ - i->server = server; - i->client = client; - silc_schedule_task_add(server->schedule, 0, - silc_server_free_client_data_timeout, - (void *)i, 300, 0, - SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); - client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; - client->data.status &= ~SILC_IDLIST_STATUS_LOCAL; - client->mode = 0; - client->router = NULL; - client->connection = NULL; + into history (for WHOWAS command) for 5 minutes, unless we're + shutting down server. */ + if (!server->server_shutdown) { + FreeClientInternal i = silc_calloc(1, sizeof(*i)); + i->server = server; + i->client = client; + silc_schedule_task_add(server->schedule, 0, + silc_server_free_client_data_timeout, + (void *)i, 300, 0, + SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); + client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; + client->data.status &= ~SILC_IDLIST_STATUS_LOCAL; + client->mode = 0; + client->router = NULL; + client->connection = NULL; + } else { + /* Delete directly since we're shutting down server */ + silc_idlist_del_data(client); + silc_idlist_del_client(server->local_list, client); + } } /* Frees user_data pointer from socket connection object. This also sends diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index 74babfaa..35eb1d89 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -49,6 +49,10 @@ typedef struct { SilcUInt32 detached; /* All clients detached */ SilcUInt32 server_ops; /* All server operators */ SilcUInt32 router_ops; /* All router operators */ + /* More to add + SilcUInt32 secret_channels; + SilcUInt32 private_channels; + */ /* General */ SilcUInt32 conn_attempts; /* Connection attempts */ diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index 4e1b2cb8..74fbc40c 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -218,6 +218,7 @@ bool silc_server_remove_clients_by_server(SilcServer server, client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF; } else { + silc_idlist_del_data(client); silc_idlist_del_client(server->local_list, client); } @@ -277,6 +278,7 @@ bool silc_server_remove_clients_by_server(SilcServer server, client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF; } else { + silc_idlist_del_data(client); silc_idlist_del_client(server->global_list, client); } @@ -287,6 +289,21 @@ bool silc_server_remove_clients_by_server(SilcServer server, silc_idcache_list_free(list); } + /* Return now if we are shutting down */ + if (server->server_shutdown) { + silc_hash_table_free(channels); + + if (server_signoff) { + for (i = 0; i < argc; i++) + silc_free(argv[i]); + silc_free(argv); + silc_free(argv_lens); + silc_free(argv_types); + silc_hash_table_free(clients); + } + return TRUE; + } + /* Send the SERVER_SIGNOFF notify */ if (server_signoff) { SilcBuffer args, not; @@ -325,12 +342,6 @@ bool silc_server_remove_clients_by_server(SilcServer server, silc_hash_table_free(clients); } - /* Return now if we are shutting down */ - if (server->server_shutdown) { - silc_hash_table_free(channels); - return TRUE; - } - /* We must now re-generate the channel key for all channels that had this server's client(s) on the channel. As they left the channel we must re-generate the channel key. */ @@ -926,7 +937,7 @@ bool silc_server_channel_delete(SilcServer server, SilcHashTableList htl; bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH); - if (delchan) { + if (delchan || server->server_shutdown) { /* Update statistics */ if (server->server_type == SILC_ROUTER) server->stat.chanclients -= channel->user_count; @@ -1518,6 +1529,7 @@ void silc_server_kill_client(SilcServer server, } /* Remove remote client */ + silc_idlist_del_data(remote_client); if (!silc_idlist_del_client(server->global_list, remote_client)) { /* Remove this client from watcher list if it is */ silc_server_del_from_watcher_list(server, remote_client); diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 6b198691..167d7878 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -126,6 +126,7 @@ void silc_client_command_pending_del(SilcClientConnection conn, while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) { if (r->reply_cmd == reply_cmd && r->ident == ident) { silc_dlist_del(conn->pending_commands, r); + silc_free(r); break; } } diff --git a/lib/silccore/silcid.h b/lib/silccore/silcid.h index 5b890813..855d5470 100644 --- a/lib/silccore/silcid.h +++ b/lib/silccore/silcid.h @@ -113,7 +113,8 @@ typedef struct SilcArgumentPayloadStruct *SilcArgumentPayload; * DESCRIPTION * * Parses buffer and return ID payload into payload structure. The - * `buffer' is raw payload buffer. + * `buffer' is raw payload buffer. The caller must free the returned + * payload. * ***/ SilcIDPayload silc_id_payload_parse(const unsigned char *payload, -- 2.24.0