From e8c2b7b9cabcf221862e7d91a1a7a1e0d6f02dd8 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Mon, 17 Dec 2001 19:14:55 +0000 Subject: [PATCH] updates. --- CHANGES | 30 +++++++++ TODO | 88 ++++++++++++++++----------- apps/irssi/src/silc/core/client_ops.c | 3 +- apps/irssi/src/silc/core/silc-core.c | 8 ++- apps/silcd/command.c | 18 +++++- apps/silcd/command.h | 2 +- apps/silcd/server.c | 15 ++++- apps/silcd/server_internal.h | 2 + lib/silcclient/client_notify.c | 37 +++++++---- lib/silcclient/command.c | 6 +- lib/silcclient/idlist.c | 4 ++ lib/silccore/silcchannel.c | 2 +- lib/silccore/silccommand.c | 40 ++++++------ 13 files changed, 176 insertions(+), 79 deletions(-) diff --git a/CHANGES b/CHANGES index b449fa48..d284fe5e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,33 @@ +Mon Dec 17 18:24:27 EET 2001 Pekka Riikonen + + * Fixed JOIN command parsing not to crash. Affected file + lib/silcclient/command.c. + + * Fied the NICK_CHANGE notify to add the new client entry + even it is resolved. This removes an <[unknown]> nick + thingy bug in the client. Affected file is + lib/silcclient/client_notify.c. + + * Do not try to allocate 0 bytes (efence does not like it) + in lib/silccore/silccomand.c when encoding payload. + + * Do not take IRCNICK as nickname in Irssi SILC client since + it is not possible to set nickname before hand connecting + the server (TODO has an entry about adding auto-nicking + support). + + * Changed the silc_server_command_pending to check whether + there already exists an pending entry with the specified + command, command identifier and pending callback. This is + to fix IDENTIFY and WHOIS related crashes that may register + multiple pending commands with same identifier. Affected + file silcd/command.c. + + * Fixed the server to reconnect to the router even if it + was already reconnecting and EOF was received. This to + fix a possibility that the server wouldn't ever try to + auto-reconnect to the router. Affected file silcd/server.c. + Sat Dec 15 20:31:50 EET 2001 Pekka Riikonen * Fixed the server's password authentication to use the diff --git a/TODO b/TODO index 757b9c12..a4d0dbb3 100644 --- a/TODO +++ b/TODO @@ -17,6 +17,10 @@ TODO/bugs in Irssi SILC client cipher, hash, hmac and pkcs configuration to the Irssi SILC's config file. + o Add auto-nick support to Irssi, so that the user specified nickname + would be sent to the server immediately (automatically) after the + client is connected to the server. + o Add PERL scripting support from Irssi CVS. o Extend the /HELP command to support sub commands or something. So @@ -35,17 +39,18 @@ TODO/bugs In SILC Client Library behaviour and maybe should be removed. The changer should always get the one it wants and not have the formatted nickname. + o Additions to do after protocol version 1.1: -TODO/bugs In SILC Server -======================== + o Fix the NICK_CHANGE notify handling not to create new entry + for the changed client, but take the nickname from the notify + (removes need for resolving as well). Protocol TODO entry 3. - o It is possible that IDENTIFy's check_client will register two pending - callbacks for same ident, which must not happen. Check same for WHOIS - as well. + o Add support for list of errors in command replies. Protocol + TODO entry 1. - o If auto-reconnecting to router and EOF is received during the - connecting phase the server will not try to auto-reconnect anymore - after that. Fix to auto-reconnect. + +TODO/bugs In SILC Server +======================== o Backup router related issues @@ -93,34 +98,45 @@ TODO/bugs In SILC Libraries TODO in SILC Protocol ===================== - o Add "request parameters" or similar to the WHOIS command, which can - be used to request various parameters (something not returned by - standard WHOIS command) about clients (info that could be fetched - even from clients). Additional specification (or appendix) should - be done to define the payload and the parameters. It could be used - to make the WHOIS command support various search conditions as well. - This would be the way to extend the WHOIS command to support various - new features without always making the command incompatible to previous - version. To be included in protocol version 1.1. - - o Re-define the Status Payload: it is now 16 bits, split it into two - 8 bits fields. First field includes status types from 0 - 9 and - 10 - n *if* it is not an list of errors. If it is list of errors then - the first field includes 1, 2 and/or 3, and the second field includes - the error status 10 - n. This way it is possible to send multiple - errors (list of errors) and we have a way to tell the receiver that - there will be other errors as well. The second field is used only - if there is list of errors. If normal status, or normal (single) - error status the second field is set to zero, and must be ignored. - Hence, the status works same way as now except for list of errors. - To be included in protocol version 1.1. - - o Define that WHOIS and IDENTIFY commands must send list of errors - if multiple Client ID (or Channel ID and Server ID for IDENTIFY) was - requested and was not found. Each unfound entry must cause an error - command reply to the sender. Also define that errors must be sent - *after* sending successfully found entries (this way receiver may - ignore them). To be included in protocol version 1.1. +Current protocol version is 1.0. However, it is far from being perfect, +and needs to include additional features. Following protocol TODO entries +describe new stuff to be added to protocol versions 1.x. + + 1. Re-define the Status Payload: it is now 16 bits, split it into two + 8 bits fields. First field includes status types from 0 - 9 and + 10 - n *if* it is not an list of errors. If it is list of errors then + the first field includes 1, 2 and/or 3, and the second field includes + the error status 10 - n. This way it is possible to send multiple + errors (list of errors) and we have a way to tell the receiver that + there will be other errors as well. The second field is used only + if there is list of errors. If normal status, or normal (single) + error status the second field is set to zero, and must be ignored. + Hence, the status works same way as now except for list of errors. + To be included in protocol version 1.1. + + 2. Define that WHOIS and IDENTIFY commands must send list of errors + if multiple Client ID (or Channel ID and Server ID for IDENTIFY) was + requested and was not found. Each unfound entry must cause an error + command reply to the sender. Also define that errors must be sent + *after* sending successfully found entries (this way receiver may + ignore them). To be included in protocol version 1.1. + + 3. Define the NICK_CHANGE notify to send the changed nickname as a new + third argument. This will make the NICK_CHANGE notify handling easier + in the receiver's end (client primarily) since it removes the + requirement that receiver must resolve (using IDENTIFY or WHOIS) the + new Client ID received in the notify (because of the new nickname is + unknown). To be included in protocol version 1.1. + + 4. Add "request parameters" or similar to the WHOIS command, which can + be used to request various parameters (something not returned by + standard WHOIS command) about clients (info that could be fetched + even from clients). Additional specification (or appendix) should + be done to define the payload and the parameters. It could be used + to make the WHOIS command support various search conditions as well. + This would be the way to extend the WHOIS command to support various + new features without always making the command incompatible to previous + version. To be included in protocol version 1.1. TODO After 1.0 diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index f6dac8ae..5fadb888 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -93,7 +93,8 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, nick = silc_nicklist_find(chanrec, sender); if (!nick) { - /* We didn't find client but it clearly exists, add it. */ + /* We didn't find client but it clearly exists, add it. It must be + found on the channel->clients list. */ SilcChannelUser chu; silc_list_start(channel->clients); diff --git a/apps/irssi/src/silc/core/silc-core.c b/apps/irssi/src/silc/core/silc-core.c index 3dddc6e4..f5ea52a3 100644 --- a/apps/irssi/src/silc/core/silc-core.c +++ b/apps/irssi/src/silc/core/silc-core.c @@ -120,13 +120,15 @@ static void silc_init_userinfo(void) user_name = settings_get_str("user_name"); } - + /* nick */ + /* Actually take SILCUSER or IRCUSER since nickname cannot be set + beforehand in SILC (XXX auto-nicking support should be added to Irssi). */ nick = settings_get_str("nick"); if (nick == NULL || *nick == '\0') { - str = g_getenv("SILCNICK"); + str = g_getenv("SILCUSER"); if (!str) - str = g_getenv("IRCNICK"); + str = g_getenv("IRCUSER"); settings_set_str("nick", str != NULL ? str : user_name); nick = settings_get_str("nick"); diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 38d7a74e..6ed2dc5e 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -297,9 +297,11 @@ silc_server_command_dup(SilcServerCommandContext ctx) with `context' when reply has been received. It can be SILC_COMMAND_NONE to match any command with the `ident'. If `ident' is non-zero the `callback' will be executed when received reply with command - identifier `ident'. */ + identifier `ident'. If there already exists pending command for the + specified command, ident, callback and context this function has no + effect. */ -void silc_server_command_pending(SilcServer server, +bool silc_server_command_pending(SilcServer server, SilcCommand reply_cmd, uint16 ident, SilcServerPendingDestructor destructor, @@ -308,6 +310,16 @@ void silc_server_command_pending(SilcServer server, { SilcServerCommandPending *reply; + /* Check whether identical pending already exists for same command, + ident, callback and callback context. If it does then it would be + error to register it again. */ + silc_dlist_start(server->pending_commands); + while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) { + if (reply->reply_cmd == reply_cmd && reply->ident == ident && + reply->callback == callback && reply->context == context) + return FALSE; + } + reply = silc_calloc(1, sizeof(*reply)); reply->reply_cmd = reply_cmd; reply->ident = ident; @@ -315,6 +327,8 @@ void silc_server_command_pending(SilcServer server, reply->callback = callback; reply->destructor = destructor; silc_dlist_add(server->pending_commands, reply); + + return TRUE; } /* Deletes pending command by reply command type. */ diff --git a/apps/silcd/command.h b/apps/silcd/command.h index da7a3ea7..b842e7ee 100644 --- a/apps/silcd/command.h +++ b/apps/silcd/command.h @@ -122,7 +122,7 @@ SilcServerCommandContext silc_server_command_alloc(); void silc_server_command_free(SilcServerCommandContext ctx); SilcServerCommandContext silc_server_command_dup(SilcServerCommandContext ctx); -void silc_server_command_pending(SilcServer server, +bool silc_server_command_pending(SilcServer server, SilcCommand reply_cmd, uint16 ident, SilcServerPendingDestructor destructor, diff --git a/apps/silcd/server.c b/apps/silcd/server.c index f90aca67..d6a4d4e2 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -689,6 +689,9 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) sconn->backup_replace_port = ptr->backup_replace_port; } + if (!server->router_conn && !sconn->backup) + server->router_conn = sconn; + silc_schedule_task_add(server->schedule, fd, silc_server_connect_router, (void *)sconn, 0, 1, SILC_TASK_TIMEOUT, @@ -988,6 +991,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final) silc_free(sconn->backup_replace_ip); silc_free(sconn); } + if (sconn == server->router_conn) + server->router_conn = NULL; /* Free the protocol object */ if (sock->protocol == protocol) @@ -1556,6 +1561,14 @@ SILC_TASK_CALLBACK(silc_server_packet_process) if (sock->user_data) silc_server_free_sock_user_data(server, sock); + else if (server->router_conn && server->router_conn->sock == sock && + !server->router && server->standalone) + silc_schedule_task_add(server->schedule, 0, + silc_server_connect_to_router, + server, 1, 0, + SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); + silc_server_close_connection(server, sock); return; } @@ -2365,7 +2378,7 @@ void silc_server_free_sock_user_data(SilcServer server, /* Check whether we have a backup router connection */ if (!backup_router || backup_router == user_data) { silc_schedule_task_add(server->schedule, 0, - silc_server_connect_to_router, + silc_server_connect_to_router, server, 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index a40adec6..8001cf38 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -80,6 +80,8 @@ struct SilcServerStruct { bool backup_router; /* TRUE if this is backup router */ bool backup_primary; /* TRUE if we've switched our primary router to a backup router. */ + SilcServerConnection router_conn; /* non-NULL when connecting to the + primary router, and NULL otherwise. */ /* Current command identifier, 0 not used */ uint16 cmd_ident; diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index 49c315c5..8b3663b9 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -41,6 +41,8 @@ static void silc_client_notify_by_server_pending(void *context, void *context2) SilcClientCommandReplyContext reply = (SilcClientCommandReplyContext)context2; + SILC_LOG_DEBUG(("Start")); + if (reply) { SilcCommandStatus status; unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL); @@ -472,26 +474,37 @@ void silc_client_notify_by_server(SilcClient client, /* Find Client entry and if not found resolve it */ client_entry2 = silc_client_get_client_by_id(client, conn, client_id); if (!client_entry2) { + /* Resolve the entry information */ silc_client_notify_by_server_resolve(client, conn, packet, client_id); - goto out; + + /* Add the new entry even though we resolved it. This is because we + want to replace the old entry with the new entry here right now. */ + client_entry2 = + silc_client_add_client(client, conn, NULL, NULL, NULL, + silc_id_dup(client_id, SILC_ID_CLIENT), + client_entry->mode); + + /* Replace old ID entry with new one on all channels. */ + silc_client_replace_from_channels(client, conn, client_entry, + client_entry2); } else { if (client_entry2 != conn->local_entry) silc_client_nickname_format(client, conn, client_entry2); - } - /* Remove the old from cache */ - silc_idcache_del_by_context(conn->client_cache, client_entry); + /* Remove the old from cache */ + silc_idcache_del_by_context(conn->client_cache, client_entry); - /* Replace old ID entry with new one on all channels. */ - silc_client_replace_from_channels(client, conn, client_entry, - client_entry2); + /* Replace old ID entry with new one on all channels. */ + silc_client_replace_from_channels(client, conn, client_entry, + client_entry2); - /* Notify application */ - client->internal->ops->notify(client, conn, type, - client_entry, client_entry2); + /* Notify application */ + client->internal->ops->notify(client, conn, type, + client_entry, client_entry2); - /* Free data */ - silc_client_del_client_entry(client, conn, client_entry); + /* Free data */ + silc_client_del_client_entry(client, conn, client_entry); + } break; case SILC_NOTIFY_TYPE_CMODE_CHANGE: diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index da743a42..37ea4d6f 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -997,13 +997,13 @@ SILC_CLIENT_CMD_FUNC(join) name = cmd->argv[1]; for (i = 2; i < cmd->argc; i++) { - if (!strcasecmp(cmd->argv[i], "-cipher") && cmd->argc >= i + 1) { + if (!strcasecmp(cmd->argv[i], "-cipher") && cmd->argc > i + 1) { cipher = cmd->argv[i + 1]; i++; - } else if (!strcasecmp(cmd->argv[i], "-hmac") && cmd->argc >= i + 1) { + } else if (!strcasecmp(cmd->argv[i], "-hmac") && cmd->argc > i + 1) { hmac = cmd->argv[i + 1]; i++; - } else if (!strcasecmp(cmd->argv[i], "-founder") && cmd->argc >= i + 1) { + } else if (!strcasecmp(cmd->argv[i], "-founder") && cmd->argc > i + 1) { if (!strcasecmp(cmd->argv[i + 1], "-pubkey")) { auth = silc_auth_public_key_auth_generate(cmd->client->public_key, cmd->client->private_key, diff --git a/lib/silcclient/idlist.c b/lib/silcclient/idlist.c index 2c520d14..d56421c2 100644 --- a/lib/silcclient/idlist.c +++ b/lib/silcclient/idlist.c @@ -747,6 +747,8 @@ SilcChannelEntry silc_client_get_channel(SilcClient client, entry = (SilcChannelEntry)id_cache->context; + SILC_LOG_DEBUG(("Found")); + return entry; } @@ -769,6 +771,8 @@ SilcChannelEntry silc_client_get_channel_by_id(SilcClient client, entry = (SilcChannelEntry)id_cache->context; + SILC_LOG_DEBUG(("Found")); + return entry; } diff --git a/lib/silccore/silcchannel.c b/lib/silccore/silcchannel.c index def0d53b..79419968 100644 --- a/lib/silccore/silcchannel.c +++ b/lib/silccore/silcchannel.c @@ -429,7 +429,7 @@ unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload, /* Return MAC. The caller knows the length of the MAC */ -unsigned char *silc_channel_mesage_get_mac(SilcChannelMessagePayload payload) +unsigned char *silc_channel_message_get_mac(SilcChannelMessagePayload payload) { return payload->mac; } diff --git a/lib/silccore/silccommand.c b/lib/silccore/silccommand.c index e1c2fc2b..0d64787d 100644 --- a/lib/silccore/silccommand.c +++ b/lib/silccore/silccommand.c @@ -207,31 +207,33 @@ SilcBuffer silc_command_payload_encode_vap(SilcCommand cmd, uint16 ident, uint32 argc, va_list ap) { - unsigned char **argv; + unsigned char **argv = NULL; uint32 *argv_lens = NULL, *argv_types = NULL; unsigned char *x; uint32 x_len; uint32 x_type; SilcBuffer buffer; - int i, k; - - argv = silc_calloc(argc, sizeof(unsigned char *)); - argv_lens = silc_calloc(argc, sizeof(uint32)); - argv_types = silc_calloc(argc, sizeof(uint32)); - - for (i = 0, k = 0; i < argc; i++) { - x_type = va_arg(ap, uint32); - x = va_arg(ap, unsigned char *); - x_len = va_arg(ap, uint32); + int i, k = 0; - if (!x_type || !x || !x_len) - continue; - - argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char)); - memcpy(argv[k], x, x_len); - argv_lens[k] = x_len; - argv_types[k] = x_type; - k++; + if (argc) { + argv = silc_calloc(argc, sizeof(unsigned char *)); + argv_lens = silc_calloc(argc, sizeof(uint32)); + argv_types = silc_calloc(argc, sizeof(uint32)); + + for (i = 0, k = 0; i < argc; i++) { + x_type = va_arg(ap, uint32); + x = va_arg(ap, unsigned char *); + x_len = va_arg(ap, uint32); + + if (!x_type || !x || !x_len) + continue; + + argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char)); + memcpy(argv[k], x, x_len); + argv_lens[k] = x_len; + argv_types[k] = x_type; + k++; + } } buffer = silc_command_payload_encode(cmd, k, argv, argv_lens, -- 2.24.0