From 183d9fe2d3a82778e110490a74425776743e74b4 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Mon, 19 Mar 2001 15:19:06 +0000 Subject: [PATCH] Added KILL command. --- CHANGES | 47 +++- TODO | 12 - apps/silc/client_ops.c | 19 ++ apps/silcd/command.c | 62 +++-- apps/silcd/packet_receive.c | 424 ++++++++------------------------- apps/silcd/packet_send.c | 74 ++---- apps/silcd/packet_send.h | 23 +- apps/silcd/server.c | 105 +++++++- apps/silcd/server.h | 8 +- apps/silcd/testi2.conf | 25 +- lib/silcclient/client_notify.c | 49 +++- lib/silcclient/command.c | 116 ++++++++- lib/silcclient/command_reply.c | 25 ++ lib/silccore/silcsockconn.h | 2 +- 14 files changed, 521 insertions(+), 470 deletions(-) diff --git a/CHANGES b/CHANGES index 65971497..47a58caf 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,48 @@ +Mon Mar 19 16:13:07 EET 2001 Pekka Riikonen + + * Added silc_server_get_client_route to resolve the route to + the client indicated by the client ID. Affected file is + silcd/server.[ch]. + + * Added silc_server_relay_packet as general function to relay + packet to arbitrary destination. This deprecates functions + like _send_private_message_key, _relay_notify etc. Affected + file is silcd/packet_send.[ch]. + + Removed silc_server_send_key_agreement, + silc_server_send_private_message_key and + silc_server_packet_relay_notify functions from the file + silcd/packet_send.[ch]. + + * Updated TODO. + + * Implemented the SILC_NOTIFY_TYPE_KILLED notify handling in the + server. Affected file silcd/packet_receive.[ch]. + + * Implemented the KILL command to the client. Implemented the + SILC_NOTIFY_TYPE_KILLED notify handling in the client library. + Affected files lib/silcclient/command[_reply].c and + lib/silcclient/client_notify.c. Implemented the KILL notify + printing in the user inteface. + + * Fixed a lot silc_parse_nick memory leaks from the client + library in the file lib/silcclient/command.c. + + * Changed the silc_server_send_notify_on_channels's `sender' + argument from SilcSocketConnection to SilcClientEntry to + check the sender as entry and not as connection object and not + to send to the client provided as argument. The affected file + is silcd/packet_send.[ch]. + + * The notify packets that are destined directly to the client used + to not to be processed by the server. Now changed that and the + server processes all notify packets. After relaying the packet + to the client the notify packet is processed in the server. + + * The silc_server_free_client_data now checks whether there is + pending outgoing traffic for the client and purges the data to + the network before removing the client entry. + Sun Mar 18 21:02:47 EET 2001 Pekka Riikonen * Added SILC_NOTIFY_TYPE_KILLED notify type. It is sent when @@ -16,7 +61,7 @@ Sun Mar 18 21:02:47 EET 2001 Pekka Riikonen whereto relay the notify. Affected file is silcd/packet_receive.[ch]. - * Implemented KILL command to the server. + * Implemented the KILL command to the server. * Updated TODO. diff --git a/TODO b/TODO index 133d751a..8001456e 100644 --- a/TODO +++ b/TODO @@ -100,18 +100,6 @@ TODO In SILC Client Library TODO In SILC Server =================== - o Functions such as silc_server_private_message, - silc_server_private_message_key and - silc_server_packet_process_relay_notify can be optimized. I don't think - we need such a big lookups to lookup the router to the destination, - it is already provided in the client entry. - - o silc_server_send_key_agreement and silc_server_send_private_message_key - are one and same function (also silc_server_send_private_message is - almost same function). These should be unified to one generic named - function and use that (silc_server_packet_relay_notify is also - same function). - o Packet processing can be made faster. All packet function in the packet_receive.c has same prototypes. Instead of calling those from huge switch() make a table of callback functions that can be called diff --git a/apps/silc/client_ops.c b/apps/silc/client_ops.c index edb17478..f2096c66 100644 --- a/apps/silc/client_ops.c +++ b/apps/silc/client_ops.c @@ -250,6 +250,25 @@ void silc_notify(SilcClient client, SilcClientConnection conn, } break; + case SILC_NOTIFY_TYPE_KILLED: + client_entry = va_arg(vp, SilcClientEntry); + tmp = va_arg(vp, char *); + channel_entry = va_arg(vp, SilcChannelEntry); + + if (client_entry == conn->local_entry) { + snprintf(message, sizeof(message), + "You have been killed from the SILC Network %s%s%s", + tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : ""); + } else { + snprintf(message, sizeof(message), + "%s%s%s has been killed from the SILC Network %s%s%s", + client_entry->nickname, + client_entry->server ? "@" : "", + client_entry->server ? client_entry->server : "", + tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : ""); + } + break; + default: break; } diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 4133e7ce..0cded085 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -1965,7 +1965,7 @@ SILC_TASK_CALLBACK(silc_server_command_quit_cb) /* Free all client specific data, such as client entry and entires on channels this client may be on. */ silc_server_free_client_data(q->server, q->sock, q->sock->user_data, - q->signoff); + TRUE, q->signoff); q->sock->user_data = NULL; /* Close the connection on our side */ @@ -2021,16 +2021,19 @@ SILC_SERVER_CMD_FUNC(kill) SilcClientEntry remote_client; SilcClientID *client_id; unsigned char *tmp, *comment; - unsigned int tmp_len; - SilcBuffer idp; + unsigned int tmp_len, tmp_len2; SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2); if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; - if (server->server_type != SILC_ROUTER) + /* KILL command works only on router */ + if (server->server_type != SILC_ROUTER) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, + SILC_STATUS_ERR_NO_ROUTER_PRIV); goto out; + } /* Check whether client has the permissions. */ if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) { @@ -2067,27 +2070,32 @@ SILC_SERVER_CMD_FUNC(kill) } /* Get comment */ - comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); + comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2); + if (tmp_len2 > 128) + comment = NULL; /* Send reply to the sender */ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, SILC_STATUS_OK); + /* Send the KILL notify packets. First send it to the channel, then + to our primary router and then directly to the client who is being + killed right now. */ + /* Send KILLED notify to the channels. It is not sent to the client as it will be sent differently destined directly to the client and not to the channel. */ - idp = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT); - silc_server_send_notify_on_channels(server, remote_client->connection, + silc_server_send_notify_on_channels(server, remote_client, remote_client, SILC_NOTIFY_TYPE_KILLED, comment ? 2 : 1, - idp->data, idp->len, - comment, comment ? strlen(comment) : 0); - silc_buffer_free(idp); + tmp, tmp_len, + comment, comment ? tmp_len2 : 0); - /* Remove the client from all channels. This generates new keys to the - channels as well. */ - silc_server_remove_from_channels(server, NULL, remote_client, FALSE, - NULL, TRUE); + /* Send KILLED notify to primary route */ + if (!server->standalone) + silc_server_send_notify_killed(server, server->router->connection, TRUE, + remote_client->id, SILC_ID_CLIENT_LEN, + comment); /* Send KILLED notify to the client directly */ silc_server_send_notify_killed(server, remote_client->connection ? @@ -2096,13 +2104,23 @@ SILC_SERVER_CMD_FUNC(kill) remote_client->id, SILC_ID_CLIENT_LEN, comment); - /* Send KILLED notify to primary route */ - if (!server->standalone) - silc_server_send_notify_killed(server, server->router->connection, - server->server_type == SILC_ROUTER ? - TRUE : FALSE, - remote_client->id, SILC_ID_CLIENT_LEN, - comment); + /* Remove the client from all channels. This generates new keys to the + channels as well. */ + silc_server_remove_from_channels(server, NULL, remote_client, FALSE, + NULL, TRUE); + + /* Remove the client entry, If it is locally connected then we will also + disconnect the client here */ + if (remote_client->data.registered && remote_client->connection) { + /* Remove locally conneted client */ + SilcSocketConnection sock = remote_client->connection; + silc_server_free_client_data(server, sock, remote_client, FALSE, NULL); + silc_server_close_connection(server, sock); + } else { + /* Remove remote client */ + if (!silc_idlist_del_client(server->global_list, remote_client)) + silc_idlist_del_client(server->local_list, remote_client); + } out: silc_server_command_free(cmd); @@ -3873,7 +3891,7 @@ SILC_SERVER_CMD_FUNC(users) /* Send reply */ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS, - SILC_STATUS_OK, 0, 4, + SILC_STATUS_OK, ident, 4, 2, channel_id, channel_id_len, 3, lc, 4, 4, client_id_list->data, diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 83e19b8e..2a40208b 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -27,99 +27,6 @@ extern char *server_version; -/* Check whereto relay the received notify packet that was destined - to a client. */ - -static void -silc_server_packet_process_relay_notify(SilcServer server, - SilcSocketConnection sock, - SilcPacketContext *packet) -{ - SilcClientID *id; - SilcServerEntry router; - SilcSocketConnection dst_sock; - SilcClientEntry client; - SilcIDListData idata; - - SILC_LOG_DEBUG(("Start")); - - /* Decode destination Client ID */ - id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT); - if (!id) { - SILC_LOG_ERROR(("Could not decode destination Client ID, dropped")); - return; - } - - /* If the destination belongs to our server we don't have to route - the packet anywhere but to send it to the local destination. */ - client = silc_idlist_find_client_by_id(server->local_list, id, NULL); - if (client) { - /* It exists, now deliver the packet to the destination */ - dst_sock = (SilcSocketConnection)client->connection; - - /* If we are router and the client has router then the client is in - our cell but not directly connected to us. */ - if (server->server_type == SILC_ROUTER && client->router) { - /* We are of course in this case the client's router thus the real - "router" of the client is the server who owns the client. Thus - we will send the packet to that server. */ - router = (SilcServerEntry)client->router; - idata = (SilcIDListData)router; - silc_server_packet_relay_notify(server, router->connection, - idata->send_key, - idata->hmac, - packet); - silc_free(id); - return; - } - - /* Seems that client really is directly connected to us */ - idata = (SilcIDListData)client; - silc_server_packet_relay_notify(server, dst_sock, - idata->send_key, - idata->hmac, packet); - silc_free(id); - return; - } - - /* Destination belongs to someone not in this server. If we are normal - server our action is to send the packet to our router. */ - if (server->server_type == SILC_SERVER && !server->standalone) { - router = server->router; - - /* Send to primary route */ - if (router) { - dst_sock = (SilcSocketConnection)router->connection; - idata = (SilcIDListData)router; - silc_server_packet_relay_notify(server, dst_sock, - idata->send_key, - idata->hmac, packet); - } - silc_free(id); - return; - } - - /* We are router and we will perform route lookup for the destination - and send the packet to fastest route. */ - if (server->server_type == SILC_ROUTER && !server->standalone) { - /* Check first that the ID is valid */ - client = silc_idlist_find_client_by_id(server->global_list, id, NULL); - if (client) { - dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT); - router = (SilcServerEntry)dst_sock->user_data; - idata = (SilcIDListData)router; - - /* Get fastest route and send packet. */ - if (router) - silc_server_packet_relay_notify(server, dst_sock, - idata->send_key, - idata->hmac, packet); - silc_free(id); - return; - } - } -} - /* Received notify packet. Server can receive notify packets from router. Server then relays the notify messages to clients if needed. */ @@ -145,11 +52,22 @@ void silc_server_notify(SilcServer server, packet->src_id_type != SILC_ID_SERVER) return; - /* If the packet is destined directly to a client, then we don't - process the packet at all but just relay it to the client. */ - if (packet->dst_id_type == SILC_ID_CLIENT) { - silc_server_packet_process_relay_notify(server, sock, packet); + if (!packet->dst_id) return; + + /* If the packet is destined directly to a client then relay the packet + before processing it. */ + if (packet->dst_id_type == SILC_ID_CLIENT) { + SilcIDListData idata; + SilcSocketConnection dst_sock; + + /* Get the route to the client */ + dst_sock = silc_server_get_client_route(server, packet->dst_id, + packet->dst_id_len, &idata); + if (dst_sock) + /* Relay the packet */ + silc_server_relay_packet(server, dst_sock, idata->send_key, + idata->hmac, packet, TRUE); } /* If we are router and this packet is not already broadcast packet @@ -639,13 +557,65 @@ void silc_server_notify(SilcServer server, break; case SILC_NOTIFY_TYPE_KILLED: - /* - * Distribute the notify to local clients on channels - */ + { + /* + * Distribute the notify to local clients on channels + */ + unsigned char *id; + unsigned int id_len; - SILC_LOG_DEBUG(("KILLED notify")); + SILC_LOG_DEBUG(("KILLED notify")); - break; + /* Get client ID */ + id = silc_argument_get_arg_type(args, 1, &id_len); + if (!id) + goto out; + client_id = silc_id_payload_parse_id(id, id_len); + if (!client_id) + goto out; + + /* If the the client is not in local list we check global list */ + client = silc_idlist_find_client_by_id(server->local_list, + client_id, NULL); + if (!client) { + client = silc_idlist_find_client_by_id(server->global_list, + client_id, NULL); + if (!client) { + silc_free(client_id); + goto out; + } + } + silc_free(client_id); + + /* If the client is one of ours, then close the connection to the + client now. This removes the client from all channels as well. */ + if (packet->dst_id_type == SILC_ID_CLIENT && client->data.registered && + client->connection) { + sock = client->connection; + silc_server_free_client_data(server, NULL, client, FALSE, NULL); + silc_server_close_connection(server, sock); + break; + } + + /* Get comment */ + tmp = silc_argument_get_arg_type(args, 2, &tmp_len); + if (tmp_len > 128) + tmp = NULL; + + /* Send the notify to local clients on the channels except to the + client who is killed. */ + silc_server_send_notify_on_channels(server, client, client, + SILC_NOTIFY_TYPE_KILLED, + tmp ? 2 : 1, + id, id_len, + tmp, tmp_len); + + /* Remove the client from all channels */ + silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, + FALSE); + + break; + } /* Ignore rest of the notify types for now */ case SILC_NOTIFY_TYPE_NONE: @@ -722,10 +692,7 @@ void silc_server_private_message(SilcServer server, SilcSocketConnection sock, SilcPacketContext *packet) { - SilcClientID *id; - SilcServerEntry router; SilcSocketConnection dst_sock; - SilcClientEntry client; SilcIDListData idata; SILC_LOG_DEBUG(("Start")); @@ -737,82 +704,15 @@ void silc_server_private_message(SilcServer server, if (!packet->dst_id) return; - /* Decode destination Client ID */ - id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT); - if (!id) { - SILC_LOG_ERROR(("Could not decode destination Client ID, dropped")); + /* Get the route to the client */ + dst_sock = silc_server_get_client_route(server, packet->dst_id, + packet->dst_id_len, &idata); + if (!dst_sock) return; - } - - /* If the destination belongs to our server we don't have to route - the message anywhere but to send it to the local destination. */ - client = silc_idlist_find_client_by_id(server->local_list, id, NULL); - if (client) { - /* It exists, now deliver the message to the destination */ - dst_sock = (SilcSocketConnection)client->connection; - - /* If we are router and the client has router then the client is in - our cell but not directly connected to us. */ - if (server->server_type == SILC_ROUTER && client->router) { - /* We are of course in this case the client's router thus the real - "router" of the client is the server who owns the client. Thus - we will send the packet to that server. */ - router = (SilcServerEntry)client->router; - idata = (SilcIDListData)router; - - silc_server_send_private_message(server, router->connection, - idata->send_key, - idata->hmac, - packet); - silc_free(id); - return; - } - - /* Seems that client really is directly connected to us */ - idata = (SilcIDListData)client; - silc_server_send_private_message(server, dst_sock, - idata->send_key, - idata->hmac, packet); - silc_free(id); - return; - } - /* Destination belongs to someone not in this server. If we are normal - server our action is to send the packet to our router. */ - if (server->server_type == SILC_SERVER && !server->standalone) { - router = server->router; - - /* Send to primary route */ - if (router) { - dst_sock = (SilcSocketConnection)router->connection; - idata = (SilcIDListData)router; - silc_server_send_private_message(server, dst_sock, - idata->send_key, - idata->hmac, packet); - } - silc_free(id); - return; - } - - /* We are router and we will perform route lookup for the destination - and send the message to fastest route. */ - if (server->server_type == SILC_ROUTER && !server->standalone) { - /* Check first that the ID is valid */ - client = silc_idlist_find_client_by_id(server->global_list, id, NULL); - if (client) { - dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT); - router = (SilcServerEntry)dst_sock->user_data; - idata = (SilcIDListData)router; - - /* Get fastest route and send packet. */ - if (router) - silc_server_send_private_message(server, dst_sock, - idata->send_key, - idata->hmac, packet); - silc_free(id); - return; - } - } + /* Send the private message */ + silc_server_send_private_message(server, dst_sock, idata->send_key, + idata->hmac, packet); } /* Received private message key packet.. This packet is never for us. It is to @@ -824,10 +724,7 @@ void silc_server_private_message_key(SilcServer server, SilcSocketConnection sock, SilcPacketContext *packet) { - SilcClientID *id; - SilcServerEntry router; SilcSocketConnection dst_sock; - SilcClientEntry client; SilcIDListData idata; SILC_LOG_DEBUG(("Start")); @@ -839,81 +736,15 @@ void silc_server_private_message_key(SilcServer server, if (!packet->dst_id) return; - /* Decode destination Client ID */ - id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT); - if (!id) { - SILC_LOG_ERROR(("Could not decode destination Client ID, dropped")); + /* Get the route to the client */ + dst_sock = silc_server_get_client_route(server, packet->dst_id, + packet->dst_id_len, &idata); + if (!dst_sock) return; - } - - /* If the destination belongs to our server we don't have to route - the message anywhere but to send it to the local destination. */ - client = silc_idlist_find_client_by_id(server->local_list, id, NULL); - if (client) { - /* It exists, now deliver the message to the destination */ - dst_sock = (SilcSocketConnection)client->connection; - /* If we are router and the client has router then the client is in - our cell but not directly connected to us. */ - if (server->server_type == SILC_ROUTER && client->router) { - /* We are of course in this case the client's router thus the real - "router" of the client is the server who owns the client. Thus - we will send the packet to that server. */ - router = (SilcServerEntry)client->router; - idata = (SilcIDListData)router; - silc_server_send_private_message_key(server, router->connection, - idata->send_key, - idata->hmac, - packet); - silc_free(id); - return; - } - - /* Seems that client really is directly connected to us */ - idata = (SilcIDListData)client; - silc_server_send_private_message_key(server, dst_sock, - idata->send_key, - idata->hmac, packet); - silc_free(id); - return; - } - - /* Destination belongs to someone not in this server. If we are normal - server our action is to send the packet to our router. */ - if (server->server_type == SILC_SERVER && !server->standalone) { - router = server->router; - - /* Send to primary route */ - if (router) { - dst_sock = (SilcSocketConnection)router->connection; - idata = (SilcIDListData)router; - silc_server_send_private_message_key(server, dst_sock, - idata->send_key, - idata->hmac, packet); - } - silc_free(id); - return; - } - - /* We are router and we will perform route lookup for the destination - and send the packet to fastest route. */ - if (server->server_type == SILC_ROUTER && !server->standalone) { - /* Check first that the ID is valid */ - client = silc_idlist_find_client_by_id(server->global_list, id, NULL); - if (client) { - dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT); - router = (SilcServerEntry)dst_sock->user_data; - idata = (SilcIDListData)router; - - /* Get fastest route and send packet. */ - if (router) - silc_server_send_private_message_key(server, dst_sock, - idata->send_key, - idata->hmac, packet); - silc_free(id); - return; - } - } + /* Relay the packet */ + silc_server_relay_packet(server, dst_sock, idata->send_key, + idata->hmac, packet, FALSE); } /* Processes incoming command reply packet. The command reply packet may @@ -1771,10 +1602,7 @@ void silc_server_key_agreement(SilcServer server, SilcSocketConnection sock, SilcPacketContext *packet) { - SilcClientID *id; - SilcServerEntry router; SilcSocketConnection dst_sock; - SilcClientEntry client; SilcIDListData idata; SILC_LOG_DEBUG(("Start")); @@ -1786,79 +1614,13 @@ void silc_server_key_agreement(SilcServer server, if (!packet->dst_id) return; - /* Decode destination Client ID */ - id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT); - if (!id) { - SILC_LOG_ERROR(("Could not decode destination Client ID, dropped")); - return; - } - - /* If the destination belongs to our server we don't have to route - the packet anywhere but to send it to the local destination. */ - client = silc_idlist_find_client_by_id(server->local_list, id, NULL); - if (client) { - /* It exists, now deliver the packet to the destination */ - dst_sock = (SilcSocketConnection)client->connection; - - /* If we are router and the client has router then the client is in - our cell but not directly connected to us. */ - if (server->server_type == SILC_ROUTER && client->router) { - /* We are of course in this case the client's router thus the real - "router" of the client is the server who owns the client. Thus - we will send the packet to that server. */ - router = (SilcServerEntry)client->router; - idata = (SilcIDListData)router; - silc_server_send_key_agreement(server, router->connection, - idata->send_key, - idata->hmac, - packet); - silc_free(id); - return; - } - - /* Seems that client really is directly connected to us */ - idata = (SilcIDListData)client; - silc_server_send_key_agreement(server, dst_sock, - idata->send_key, - idata->hmac, packet); - silc_free(id); - return; - } - - /* Destination belongs to someone not in this server. If we are normal - server our action is to send the packet to our router. */ - if (server->server_type == SILC_SERVER && !server->standalone) { - router = server->router; - - /* Send to primary route */ - if (router) { - dst_sock = (SilcSocketConnection)router->connection; - idata = (SilcIDListData)router; - silc_server_send_key_agreement(server, dst_sock, - idata->send_key, - idata->hmac, packet); - } - silc_free(id); + /* Get the route to the client */ + dst_sock = silc_server_get_client_route(server, packet->dst_id, + packet->dst_id_len, &idata); + if (!dst_sock) return; - } - /* We are router and we will perform route lookup for the destination - and send the packet to fastest route. */ - if (server->server_type == SILC_ROUTER && !server->standalone) { - /* Check first that the ID is valid */ - client = silc_idlist_find_client_by_id(server->global_list, id, NULL); - if (client) { - dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT); - router = (SilcServerEntry)dst_sock->user_data; - idata = (SilcIDListData)router; - - /* Get fastest route and send packet. */ - if (router) - silc_server_send_key_agreement(server, dst_sock, - idata->send_key, - idata->hmac, packet); - silc_free(id); - return; - } - } + /* Relay the packet */ + silc_server_relay_packet(server, dst_sock, idata->send_key, + idata->hmac, packet, FALSE); } diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index 1fbb0e59..4476c4df 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -1149,14 +1149,15 @@ void silc_server_send_notify_to_channel(SilcServer server, silc_buffer_free(packet); } -/* Send notify message to all clients the client has joined. It is quaranteed +/* Send notify message to all channels the client has joined. It is quaranteed that the message is sent only once to a client (ie. if a client is joined on two same channel it will receive only one notify message). Also, this sends only to local clients (locally connected if we are server, and to - local servers if we are router). */ + local servers if we are router). If `sender' is provided the packet is + not sent to that client at all. */ void silc_server_send_notify_on_channels(SilcServer server, - SilcSocketConnection sender, + SilcClientEntry sender, SilcClientEntry client, SilcNotifyType type, unsigned int argc, ...) @@ -1204,6 +1205,9 @@ void silc_server_send_notify_on_channels(SilcServer server, while ((chl2 = silc_list_get(channel->user_list)) != SILC_LIST_END) { c = chl2->client; + if (sender && c == sender) + continue; + /* Check if we have sent the packet to this client already */ for (k = 0; k < sent_clients_count; k++) if (sent_clients[k] == c) @@ -1226,9 +1230,6 @@ void silc_server_send_notify_on_channels(SilcServer server, sock = (SilcSocketConnection)c->router->connection; idata = (SilcIDListData)c->router; - if (sender && sock == sender) - continue; - packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER); packetdata.dst_id_len = SILC_ID_SERVER_LEN; packetdata.dst_id_type = SILC_ID_SERVER; @@ -1264,9 +1265,6 @@ void silc_server_send_notify_on_channels(SilcServer server, sock = (SilcSocketConnection)c->connection; idata = (SilcIDListData)c; - if (sender && sock == sender) - continue; - packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT); packetdata.dst_id_len = SILC_ID_CLIENT_LEN; packetdata.dst_id_type = SILC_ID_CLIENT; @@ -1426,38 +1424,19 @@ void silc_server_send_heartbeat(SilcServer server, NULL, 0, FALSE); } -/* Routine used to send (relay, route) key agreement packets to some - destination. */ +/* Generic function to relay packet we've received. This is used to relay + packets to a client but generally can be used to other purposes as well. */ -void silc_server_send_key_agreement(SilcServer server, - SilcSocketConnection dst_sock, - SilcCipher cipher, - SilcHmac hmac, - SilcPacketContext *packet) +void silc_server_relay_packet(SilcServer server, + SilcSocketConnection dst_sock, + SilcCipher cipher, + SilcHmac hmac, + SilcPacketContext *packet, + int force_send) { silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len + packet->dst_id_len + packet->padlen); - silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len); - silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len); - - /* Re-encrypt packet */ - silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len); - - /* Send the packet */ - silc_server_packet_send_real(server, dst_sock, FALSE); -} - -/* Routine used to send (relay, route) private message key packets to some - destination. */ -void silc_server_send_private_message_key(SilcServer server, - SilcSocketConnection dst_sock, - SilcCipher cipher, - SilcHmac hmac, - SilcPacketContext *packet) -{ - silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len - + packet->dst_id_len + packet->padlen); silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len); silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len); @@ -1465,27 +1444,8 @@ void silc_server_send_private_message_key(SilcServer server, silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len); /* Send the packet */ - silc_server_packet_send_real(server, dst_sock, FALSE); -} + silc_server_packet_send_real(server, dst_sock, force_send); -/* Routine used to relay notify packets to a client. The notify packets - may be destined directly to a client and this routine is used to do - that. */ - -void silc_server_packet_relay_notify(SilcServer server, - SilcSocketConnection dst_sock, - SilcCipher cipher, - SilcHmac hmac, - SilcPacketContext *packet) -{ - silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len + silc_buffer_pull(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len + packet->dst_id_len + packet->padlen); - silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len); - silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len); - - /* Re-encrypt packet */ - silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len); - - /* Send the packet */ - silc_server_packet_send_real(server, dst_sock, FALSE); } diff --git a/apps/silcd/packet_send.h b/apps/silcd/packet_send.h index 08bb1e62..49520c84 100644 --- a/apps/silcd/packet_send.h +++ b/apps/silcd/packet_send.h @@ -182,7 +182,7 @@ void silc_server_send_notify_to_channel(SilcServer server, SilcNotifyType type, unsigned int argc, ...); void silc_server_send_notify_on_channels(SilcServer server, - SilcSocketConnection sender, + SilcClientEntry sender, SilcClientEntry client, SilcNotifyType type, unsigned int argc, ...); @@ -207,20 +207,11 @@ void silc_server_send_command(SilcServer server, unsigned int argc, ...); void silc_server_send_heartbeat(SilcServer server, SilcSocketConnection sock); -void silc_server_send_key_agreement(SilcServer server, - SilcSocketConnection dst_sock, - SilcCipher cipher, - SilcHmac hmac, - SilcPacketContext *packet); -void silc_server_send_private_message_key(SilcServer server, - SilcSocketConnection dst_sock, - SilcCipher cipher, - SilcHmac hmac, - SilcPacketContext *packet); -void silc_server_packet_relay_notify(SilcServer server, - SilcSocketConnection dst_sock, - SilcCipher cipher, - SilcHmac hmac, - SilcPacketContext *packet); +void silc_server_relay_packet(SilcServer server, + SilcSocketConnection dst_sock, + SilcCipher cipher, + SilcHmac hmac, + SilcPacketContext *packet, + int force_send); #endif diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 1487ee0f..34f7326f 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -1293,7 +1293,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process) server->stat.packets_sent++; if (sock->outbuf->data - sock->outbuf->head) - silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head); + silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head); ret = silc_server_packet_send_real(server, sock, TRUE); @@ -1973,19 +1973,41 @@ SILC_TASK_CALLBACK(silc_server_free_client_data_timeout) void silc_server_free_client_data(SilcServer server, SilcSocketConnection sock, - SilcClientEntry client, char *signoff) + SilcClientEntry client, + int notify, + char *signoff) { FreeClientInternal i = silc_calloc(1, sizeof(*i)); + /* If there is pending outgoing data for the client then purge it + to the network before removing the client entry. */ + if (SILC_IS_OUTBUF_PENDING(sock) && (SILC_IS_DISCONNECTED(sock) == FALSE)) { + server->stat.packets_sent++; + + if (sock->outbuf->data - sock->outbuf->head) + silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head); + + silc_server_packet_send_real(server, sock, TRUE); + + SILC_SET_CONNECTION_FOR_INPUT(sock->sock); + SILC_UNSET_OUTBUF_PENDING(sock); + silc_buffer_clear(sock->outbuf); + } + /* Send SIGNOFF notify to routers. */ - if (!server->standalone && server->router) + if (notify && !server->standalone && server->router) silc_server_send_notify_signoff(server, server->router->connection, server->server_type == SILC_SERVER ? FALSE : TRUE, client->id, SILC_ID_CLIENT_LEN, signoff); /* Remove client from all channels */ - silc_server_remove_from_channels(server, sock, client, TRUE, signoff, TRUE); + if (notify) + silc_server_remove_from_channels(server, NULL, client, + TRUE, signoff, TRUE); + else + silc_server_remove_from_channels(server, NULL, client, + FALSE, NULL, FALSE); /* We will not delete the client entry right away. We will take it into history (for WHOWAS command) for 5 minutes */ @@ -2017,7 +2039,7 @@ void silc_server_free_sock_user_data(SilcServer server, case SILC_SOCKET_TYPE_CLIENT: { SilcClientEntry user_data = (SilcClientEntry)sock->user_data; - silc_server_free_client_data(server, sock, user_data, NULL); + silc_server_free_client_data(server, sock, user_data, TRUE, NULL); break; } case SILC_SOCKET_TYPE_SERVER: @@ -3079,3 +3101,76 @@ void silc_server_save_users_on_channel(SilcServer server, } } } + +/* Lookups route to the client indicated by `id' client ID. The connection + object and internal data object is returned. Returns NULL if route + could not be found to the client. */ + +SilcSocketConnection silc_server_get_client_route(SilcServer server, + unsigned char *id_data, + unsigned int id_len, + SilcIDListData *idata) +{ + SilcClientID *id; + SilcClientEntry client; + + SILC_LOG_DEBUG(("Start")); + + /* Decode destination Client ID */ + id = silc_id_str2id(id_data, id_len, SILC_ID_CLIENT); + if (!id) { + SILC_LOG_ERROR(("Could not decode destination Client ID, dropped")); + return NULL; + } + + /* If the destination belongs to our server we don't have to route + the packet anywhere but to send it to the local destination. */ + client = silc_idlist_find_client_by_id(server->local_list, id, NULL); + if (client) { + silc_free(id); + + if (client && client->data.registered == FALSE) + return NULL; + + /* If we are router and the client has router then the client is in + our cell but not directly connected to us. */ + if (server->server_type == SILC_ROUTER && client->router) { + /* We are of course in this case the client's router thus the real + "router" of the client is the server who owns the client. Thus + we will send the packet to that server. */ + *idata = (SilcIDListData)client->router; + return client->router->connection; + } + + /* Seems that client really is directly connected to us */ + *idata = (SilcIDListData)client; + return client->connection; + } + + /* Destination belongs to someone not in this server. If we are normal + server our action is to send the packet to our router. */ + if (server->server_type == SILC_SERVER && !server->standalone) { + silc_free(id); + *idata = (SilcIDListData)server->router; + return server->router->connection; + } + + /* We are router and we will perform route lookup for the destination + and send the packet to fastest route. */ + if (server->server_type == SILC_ROUTER && !server->standalone) { + /* Check first that the ID is valid */ + client = silc_idlist_find_client_by_id(server->global_list, id, NULL); + if (client) { + SilcSocketConnection dst_sock; + + dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT); + + silc_free(id); + *idata = (SilcIDListData)dst_sock->user_data; + return dst_sock; + } + } + + silc_free(id); + return NULL; +} diff --git a/apps/silcd/server.h b/apps/silcd/server.h index e25f6f11..28a87518 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -96,7 +96,9 @@ void silc_server_close_connection(SilcServer server, SilcSocketConnection sock); void silc_server_free_client_data(SilcServer server, SilcSocketConnection sock, - SilcClientEntry client, char *signoff); + SilcClientEntry client, + int notify, + char *signoff); void silc_server_free_sock_user_data(SilcServer server, SilcSocketConnection sock); int silc_server_channel_has_global(SilcChannelEntry channel); @@ -155,5 +157,9 @@ void silc_server_save_users_on_channel(SilcServer server, SilcBuffer user_list, SilcBuffer mode_list, unsigned int user_count); +SilcSocketConnection silc_server_get_client_route(SilcServer server, + unsigned char *id_data, + unsigned int id_len, + SilcIDListData *idata); #endif diff --git a/apps/silcd/testi2.conf b/apps/silcd/testi2.conf index 964d073e..e584862b 100644 --- a/apps/silcd/testi2.conf +++ b/apps/silcd/testi2.conf @@ -1,23 +1,17 @@ [Cipher] -aes-256-cbc:../lib/silcsim/modules/aes.sim.so:32:16 -aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16 -aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16 -twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16 -twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16 -twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16 -mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16 -mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16 -mars-128-cbc:../lib/silcsim/modules/mars.sim.so:16:16 +rc6:../lib/silcsim/modules/rc6.sim.so:16:16 +twofish:../lib/silcsim/modules/twofish.sim.so:16:16 +mars:../lib/silcsim/modules/mars.sim.so:16:16 none:../lib/silcsim/modules/none.sim.so:0:0 -[Hash] +[Hash] md5::64:16 sha1::64:20 [hmac] hmac-sha1-96:sha1:12 hmac-md5-96:md5:12 -hmac-sha1:sha1:20 +hmac-sha1:sha1:20 hmac-md5:md5:16 #[PKCS] @@ -31,10 +25,10 @@ nobody:nobody Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi [ServerInfo] -lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334 +lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334 [ListenPort] -212.146.42.253:212.146.42.253:1334 +10.2.1.7:10.2.1.7:1334 [Logging] infologfile:silcd2.log:10000 @@ -53,12 +47,13 @@ errorlogfile:silcd2.log:10000 :::1336:1 [AdminConnection] +*:silc:silc:passwd:testi [ServerConnection] -212.146.42.253:passwd:priikone:1336:1:1 +10.2.1.7:passwd:priikone:1333:1:1 [RouterConnection] -212.146.42.253:passwd:priikone:1335:1:1:0 +10.2.1.7:passwd:priikone:1334:1:1:0 [DenyConnection] [RedirectClient] diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index e398d96c..d1668cae 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -410,6 +410,7 @@ void silc_client_notify_by_server(SilcClient client, silc_cipher_free(client_entry->send_key); if (client_entry->receive_key) silc_cipher_free(client_entry->receive_key); + silc_free(client_entry); break; case SILC_NOTIFY_TYPE_CMODE_CHANGE: @@ -597,8 +598,7 @@ void silc_client_notify_by_server(SilcClient client, goto out; /* Find Client entry */ - client_entry = - silc_client_get_client_by_id(client, conn, client_id); + client_entry = silc_client_get_client_by_id(client, conn, client_id); if (!client_entry) goto out; @@ -634,6 +634,51 @@ void silc_client_notify_by_server(SilcClient client, silc_free(channel); } break; + + case SILC_NOTIFY_TYPE_KILLED: + /* + * A client (maybe me) was killed from the network. + */ + + /* Get Client ID */ + tmp = silc_argument_get_arg_type(args, 1, &tmp_len); + if (!tmp) + goto out; + + client_id = silc_id_payload_parse_id(tmp, tmp_len); + if (!client_id) + goto out; + + /* Find Client entry */ + client_entry = silc_client_get_client_by_id(client, conn, client_id); + if (!client_entry) + goto out; + + /* Get comment */ + tmp = silc_argument_get_arg_type(args, 2, &tmp_len); + + /* Notify application. The channel entry is sent last as this notify + is for channel but application don't know it from the arguments + sent by server. */ + client->ops->notify(client, conn, type, client_entry, tmp); + + if (client_entry != conn->local_entry) { + silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, + client_entry->id); + if (client_entry->nickname) + silc_free(client_entry->nickname); + if (client_entry->server) + silc_free(client_entry->server); + if (client_entry->id) + silc_free(client_entry->id); + if (client_entry->send_key) + silc_cipher_free(client_entry->send_key); + if (client_entry->receive_key) + silc_cipher_free(client_entry->receive_key); + silc_free(client_entry); + } + + break; default: break; diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 4b3214b4..f6dca333 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -54,7 +54,7 @@ SilcClientCommand silc_command_list[] = SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 3), SILC_CLIENT_CMD(shutdown, SHUTDOWN, "SHUTDOWN", SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 1), - SILC_CLIENT_CMD(silcoper, SILCOPER, "SILOPER", + SILC_CLIENT_CMD(silcoper, SILCOPER, "SILCOPER", SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER, 3), SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", SILC_CF_LAG | SILC_CF_REG, 2), SILC_CLIENT_CMD(users, USERS, "USERS", SILC_CF_LAG | SILC_CF_REG, 2), @@ -334,7 +334,7 @@ SILC_CLIENT_CMD_FUNC(identify) buffer = silc_command_payload_encode(SILC_COMMAND_IDENTIFY, cmd->argc - 1, ++cmd->argv, ++cmd->argv_lens, ++cmd->argv_types, - 0); + ++conn->cmd_ident); silc_client_packet_send(cmd->client, cmd->conn->sock, SILC_PACKET_COMMAND, NULL, 0, NULL, NULL, buffer->data, buffer->len, TRUE); @@ -528,7 +528,7 @@ SILC_CLIENT_CMD_FUNC(invite) /* Client entry not found, it was requested thus mark this to be pending command. */ - silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0, + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident, silc_client_command_destructor, silc_client_command_invite, silc_client_command_dup(cmd)); @@ -564,6 +564,10 @@ SILC_CLIENT_CMD_FUNC(invite) COMMAND; out: + if (nickname) + silc_free(nickname); + if (server) + silc_free(server); silc_client_command_free(cmd); } @@ -625,8 +629,96 @@ SILC_CLIENT_CMD_FUNC(quit) silc_client_command_free(cmd); } +/* Command KILL. Router operator can use this command to remove an client + fromthe SILC Network. */ + SILC_CLIENT_CMD_FUNC(kill) { + SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClientConnection conn = cmd->conn; + SilcBuffer buffer, idp; + SilcClientEntry target; + unsigned int num = 0; + char *nickname = NULL, *server = NULL; + + if (!cmd->conn) { + SILC_NOT_CONNECTED(cmd->client, cmd->conn); + COMMAND_ERROR; + goto out; + } + + if (cmd->argc < 2) { + cmd->client->ops->say(cmd->client, conn, + "Usage: /KILL []"); + COMMAND_ERROR; + goto out; + } + + /* Parse the typed nickname. */ + if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) { + cmd->client->ops->say(cmd->client, conn, "Bad nickname"); + COMMAND_ERROR; + goto out; + } + + /* Get the target client */ + target = silc_idlist_get_client(cmd->client, conn, nickname, + server, num, TRUE); + if (!target) { + silc_free(nickname); + if (server) + silc_free(server); + + /* Client entry not found, it was requested thus mark this to be + pending command. */ + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, + conn->cmd_ident, + silc_client_command_destructor, + silc_client_command_kill, + silc_client_command_dup(cmd)); + cmd->pending = 1; + return; + } + + /* Send the KILL command to the server */ + idp = silc_id_payload_encode(target->id, SILC_ID_CLIENT); + if (cmd->argc == 2) + buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 0, 1, + 1, idp->data, idp->len); + else + buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 0, 2, + 1, idp->data, idp->len, + 2, cmd->argv[2], + strlen(cmd->argv[2])); + silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, + 0, NULL, NULL, buffer->data, buffer->len, TRUE); + silc_buffer_free(buffer); + silc_buffer_free(idp); + + /* Notify application */ + COMMAND; + + /* Remove the client entry to be killed */ + silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, + target->id); + if (target->nickname) + silc_free(target->nickname); + if (target->server) + silc_free(target->server); + if (target->id) + silc_free(target->id); + if (target->send_key) + silc_cipher_free(target->send_key); + if (target->receive_key) + silc_cipher_free(target->receive_key); + silc_free(target); + + out: + if (nickname) + silc_free(nickname); + if (server) + silc_free(server); + silc_client_command_free(cmd); } /* Command INFO. Request information about specific server. If specific @@ -1091,7 +1183,8 @@ SILC_CLIENT_CMD_FUNC(cumode) if (!client_entry) { /* Client entry not found, it was requested thus mark this to be pending command. */ - silc_client_command_pending(conn, SILC_COMMAND_CUMODE, 0, + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, + conn->cmd_ident, silc_client_command_destructor, silc_client_command_cumode, silc_client_command_dup(cmd)); @@ -1165,6 +1258,10 @@ SILC_CLIENT_CMD_FUNC(cumode) COMMAND; out: + if (nickname) + silc_free(nickname); + if (server) + silc_free(server); silc_client_command_free(cmd); } @@ -1190,7 +1287,7 @@ SILC_CLIENT_CMD_FUNC(kick) if (cmd->argc < 3) { cmd->client->ops->say(cmd->client, conn, - "Usage: /KICK []"); + "Usage: /KICK []"); COMMAND_ERROR; goto out; } @@ -1261,6 +1358,10 @@ SILC_CLIENT_CMD_FUNC(kick) COMMAND; out: + if (nickname) + silc_free(nickname); + if (server) + silc_free(server); silc_client_command_free(cmd); } @@ -1642,7 +1743,8 @@ SILC_CLIENT_CMD_FUNC(users) if (!cmd->pending) { /* Send USERS command to the server */ idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL); - buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1, + buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, + ++conn->cmd_ident, 1, 1, idp->data, idp->len); silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 0, NULL, NULL, buffer->data, @@ -1653,7 +1755,7 @@ SILC_CLIENT_CMD_FUNC(users) /* Register pending callback which will recall this command callback with same context and reprocesses the command. When reprocessing we actually display the information on the screen. */ - silc_client_command_pending(conn, SILC_COMMAND_USERS, 0, + silc_client_command_pending(conn, SILC_COMMAND_USERS, conn->cmd_ident, silc_client_command_destructor, silc_client_command_users, silc_client_command_dup(cmd)); diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index a9833571..a2e3e1c4 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -673,9 +673,34 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INVITE); silc_client_command_reply_free(cmd); } + +/* Received reply to the KILL command. */ SILC_CLIENT_CMD_REPLY_FUNC(kill) { + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + SilcCommandStatus status; + unsigned char *tmp; + + tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); + SILC_GET16_MSB(status, tmp); + if (status != SILC_STATUS_OK) { + cmd->client->ops->say(cmd->client, conn, + "%s", silc_client_command_status_message(status)); + COMMAND_REPLY_ERROR; + goto out; + } + + /* Notify application */ + COMMAND_REPLY((ARGS)); + + /* Execute any pending command callbacks */ + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE); + + out: + SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CLOSE); + silc_client_command_reply_free(cmd); } /* Received reply to INFO command. We receive the server ID and some diff --git a/lib/silccore/silcsockconn.h b/lib/silccore/silcsockconn.h index 8a7967eb..b54f1218 100644 --- a/lib/silccore/silcsockconn.h +++ b/lib/silccore/silcsockconn.h @@ -144,7 +144,7 @@ struct SilcSocketConnectionHB { /* Generic manipulation of flags */ #define SF_SET(x, f) (x)->flags |= (1L << (f)) #define SF_UNSET(x, f) (x)->flags &= ~(1L << (f)) -#define SF_IS(x, f) (x)->flags & (1L << (f)) +#define SF_IS(x, f) ((x)->flags & (1L << (f))) /* Setting/Unsetting flags */ #define SILC_SET_OUTBUF_PENDING(x) SF_SET((x), SILC_SF_OUTBUF_PENDING) -- 2.43.0