From: Pekka Riikonen Date: Mon, 10 Jul 2000 05:42:59 +0000 (+0000) Subject: Removed command packet processing from server.c and added it to X-Git-Tag: SILC.0.1~464 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=058eb4018305c0a584cef77420f1f3cf3a777f7d Removed command packet processing from server.c and added it to command.c. Implemented INFO command. Added support for testing that connections are registered before executing commands. --- diff --git a/apps/silcd/command.c b/apps/silcd/command.c index c3c58c3b..d5661fe2 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -20,6 +20,12 @@ /* * $Id$ * $Log$ + * Revision 1.8 2000/07/10 05:42:59 priikone + * Removed command packet processing from server.c and added it to + * command.c. + * Implemented INFO command. Added support for testing that + * connections are registered before executing commands. + * * Revision 1.7 2000/07/07 06:55:24 priikone * Do not allow client to join twice on same channel. * @@ -48,6 +54,23 @@ #include "serverincludes.h" #include "server_internal.h" +static int silc_server_is_registered(SilcServer server, + SilcSocketConnection sock, + SilcServerCommandContext cmd, + SilcCommand command); +static void +silc_server_command_send_status_reply(SilcServerCommandContext cmd, + SilcCommand command, + SilcCommandStatus status); +static void +silc_server_command_send_status_data(SilcServerCommandContext cmd, + SilcCommand command, + SilcCommandStatus status, + unsigned int arg_type, + unsigned char *arg, + unsigned int arg_len); +static void silc_server_command_free(SilcServerCommandContext cmd); + /* Server command list. */ SilcServerCommand silc_command_list[] = { @@ -86,6 +109,89 @@ SilcServerCommand silc_command_list[] = /* List of pending commands. */ SilcServerCommandPending *silc_command_pending = NULL; +/* Returns TRUE if the connection is registered. Unregistered connections + usually cannot send commands hence the check. */ + +static int silc_server_is_registered(SilcServer server, + SilcSocketConnection sock, + SilcServerCommandContext cmd, + SilcCommand command) +{ + switch(sock->type) { + case SILC_SOCKET_TYPE_CLIENT: + { + SilcClientList *client = (SilcClientList *)sock->user_data; + if (client->registered) + return TRUE; + break; + } + case SILC_SOCKET_TYPE_SERVER: + case SILC_SOCKET_TYPE_ROUTER: + { + SilcServerList *serv = (SilcServerList *)sock->user_data; + if (serv->registered) + return TRUE; + break; + } + default: + break; + } + + silc_server_command_send_status_reply(cmd, command, + SILC_STATUS_ERR_NOT_REGISTERED); + silc_server_command_free(cmd); + return FALSE; +} + +/* Processes received command packet. */ + +void silc_server_command_process(SilcServer server, + SilcSocketConnection sock, + SilcPacketContext *packet) +{ + SilcServerCommandContext ctx; + SilcServerCommand *cmd; + + /* Allocate command context. This must be free'd by the + command routine receiving it. */ + ctx = silc_calloc(1, sizeof(*ctx)); + ctx->server = server; + ctx->sock = sock; + ctx->packet = packet; /* Save original packet */ + + /* Parse the command payload in the packet */ + ctx->payload = silc_command_parse_payload(packet->buffer); + if (!ctx->payload) { + SILC_LOG_ERROR(("Bad command payload, packet dropped")); + silc_buffer_free(packet->buffer); + silc_free(ctx); + return; + } + + /* Execute command. If this fails the packet is dropped. */ + for (cmd = silc_command_list; cmd->cb; cmd++) + if (cmd->cmd == silc_command_get(ctx->payload)) { + + if (!(cmd->flags & SILC_CF_REG)) { + cmd->cb(ctx); + break; + } + + if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) { + cmd->cb(ctx); + break; + } + } + + if (cmd == NULL) { + SILC_LOG_ERROR(("Unknown command, packet dropped")); + silc_free(ctx); + return; + } + + silc_buffer_free(packet->buffer); +} + /* Add new pending command to the list of pending commands. Currently pending commands are executed from command replies, thus we can execute any command after receiving some specific command reply. @@ -665,11 +771,6 @@ SILC_SERVER_CMD_FUNC(invite) sender of this command must be at least channel operator. */ /* XXX */ - /* Check whether the requested client is already on the channel. */ - /* XXX if we are normal server we don't know about global clients on - the channel thus we must request it (NAMES command), check from - local cache as well. */ - /* Find the connection data for the destination. If it is local we will send it directly otherwise we will send it to router for routing. */ dest = silc_idlist_find_client_by_id(server->local_list->clients, dest_id); @@ -678,6 +779,16 @@ SILC_SERVER_CMD_FUNC(invite) else dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT); + /* Check whether the requested client is already on the channel. */ + /* XXX if we are normal server we don't know about global clients on + the channel thus we must request it (NAMES command), check from + local cache as well. */ + if (silc_server_client_on_channel(dest, channel)) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, + SILC_STATUS_ERR_USER_ON_CHANNEL); + goto out; + } + /* Send notify to the client that is invited to the channel */ silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT, "%s invites you to channel %s", @@ -729,8 +840,75 @@ SILC_SERVER_CMD_FUNC(kill) { } +/* Server side of command INFO. This sends information about us to + the client. If client requested specific server we will send the + command to that server. */ + SILC_SERVER_CMD_FUNC(info) { + SilcServerCommandContext cmd = (SilcServerCommandContext)context; + SilcServer server = cmd->server; + SilcBuffer packet; + unsigned int argc; + unsigned char *id_string; + char info_string[256], *dest_server; + + argc = silc_command_get_arg_num(cmd->payload); + if (argc < 1) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); + goto out; + } + if (argc > 1) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO, + SILC_STATUS_ERR_TOO_MANY_PARAMS); + goto out; + } + + /* Get server name */ + dest_server = silc_command_get_arg_type(cmd->payload, 1, NULL); + if (!dest_server) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO, + SILC_STATUS_ERR_NO_SUCH_SERVER); + goto out; + } + + if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) { + /* Send our reply */ + memset(info_string, 0, sizeof(info_string)); + snprintf(info_string, sizeof(info_string), "%s %s %s <%s>", + server->config->admin_info->location, + server->config->admin_info->server_type, + server->config->admin_info->admin_name, + server->config->admin_info->admin_email); + + id_string = silc_id_id2str(server->id, SILC_ID_SERVER); + + packet = + silc_command_encode_reply_payload_va(SILC_COMMAND_INFO, + SILC_STATUS_OK, 2, + 2, id_string, SILC_ID_SERVER_LEN, + 3, info_string, + strlen(info_string)); + silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, + packet->data, packet->len, FALSE); + + silc_free(id_string); + silc_buffer_free(packet); + } else { + /* Send this command to the requested server */ + + if (server->server_type == SILC_SERVER && !server->standalone) { + + } + + if (server->server_type == SILC_ROUTER) { + + } + } + + out: + silc_server_command_free(cmd); } SILC_SERVER_CMD_FUNC(connect) diff --git a/apps/silcd/command.h b/apps/silcd/command.h index d7ed4944..d5c96e9b 100644 --- a/apps/silcd/command.h +++ b/apps/silcd/command.h @@ -82,24 +82,6 @@ extern SilcServerCommandPending *silc_command_pending; #define SILC_SERVER_CMD_FUNC(func) \ void silc_server_command_##func(void *context) -/* Macro used to execute commands */ -#define SILC_SERVER_COMMAND_EXEC(ctx) \ -do { \ - SilcServerCommand *cmd; \ - \ - for (cmd = silc_command_list; cmd->cb; cmd++) \ - if (cmd->cmd == silc_command_get(ctx->payload)) { \ - cmd->cb(ctx); \ - break; \ - } \ - \ - if (cmd == NULL) { \ - SILC_LOG_ERROR(("Unknown command, packet dropped")); \ - silc_free(ctx); \ - return; \ - } \ -} while(0) - /* Checks for pending commands */ #define SILC_SERVER_COMMAND_CHECK_PENDING(ctx) \ do { \ @@ -128,6 +110,9 @@ do { \ } while(0) /* Prototypes */ +void silc_server_command_process(SilcServer server, + SilcSocketConnection sock, + SilcPacketContext *packet); void silc_server_command_pending(SilcCommand reply_cmd, SilcCommandCb callback, void *context); diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index 36ccb033..c958e26a 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -84,6 +84,9 @@ struct SilcServerListStruct { int server_type; SilcServerID *id; + /* TRUE when server is registered to server */ + int registered; + /* Pointer to the router */ struct SilcServerListStruct *router; @@ -201,6 +204,9 @@ struct SilcClientListStruct { SilcClientID *id; int mode; + /* TRUE when client is registered to server */ + int registered; + /* Pointer to the router */ SilcServerList *router; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 05953586..c0836ec7 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -25,6 +25,12 @@ /* * $Id$ * $Log$ + * Revision 1.7 2000/07/10 05:43:00 priikone + * Removed command packet processing from server.c and added it to + * command.c. + * Implemented INFO command. Added support for testing that + * connections are registered before executing commands. + * * Revision 1.6 2000/07/07 06:55:59 priikone * Added SILC style public key support and made server to use * it at all time. @@ -135,10 +141,9 @@ void silc_server_free(SilcServer server) int silc_server_init(SilcServer server) { - int *sock = NULL, sock_count, i; + int *sock = NULL, sock_count = 0, i; SilcServerID *id; SilcServerList *id_entry; - SilcHashObject hash; SILC_LOG_DEBUG(("Initializing server")); assert(server); @@ -200,16 +205,20 @@ int silc_server_init(SilcServer server) silc_pkcs_private_key_alloc("rsa", private_key, prv_len); /* XXX Save keys */ - silc_pkcs_save_public_key("pubkey.pub", server->public_key); - silc_pkcs_save_private_key("privkey.prv", server->private_key, NULL); + silc_pkcs_save_public_key("pubkey.pub", server->public_key, + SILC_PKCS_FILE_PEM); + silc_pkcs_save_private_key("privkey.prv", server->private_key, NULL, + SILC_PKCS_FILE_BIN); memset(public_key, 0, pk_len); memset(private_key, 0, prv_len); silc_free(public_key); silc_free(private_key); } else { - silc_pkcs_load_public_key("pubkey.pub", &server->public_key); - silc_pkcs_load_private_key("privkey.prv", &server->private_key); + silc_pkcs_load_public_key("pubkey.pub", &server->public_key, + SILC_PKCS_FILE_PEM); + silc_pkcs_load_private_key("privkey.prv", &server->private_key, + SILC_PKCS_FILE_BIN); } } @@ -1663,37 +1672,11 @@ void silc_server_packet_parse_type(SilcServer server, * Command packets */ case SILC_PACKET_COMMAND: - { - /* - * Recived command. Allocate command context and execute the command. - */ - SilcServerCommandContext ctx; - - SILC_LOG_DEBUG(("Command packet")); - - /* Router cannot send command packet */ - if (sock->type == SILC_SOCKET_TYPE_ROUTER) - break; - - /* Allocate command context. This must be free'd by the - command routine receiving it. */ - ctx = silc_calloc(1, sizeof(*ctx)); - ctx->server = server; - ctx->sock = sock; - ctx->packet = packet; /* Save original packet */ - - /* Parse the command payload in the packet */ - ctx->payload = silc_command_parse_payload(buffer); - if (!ctx->payload) { - SILC_LOG_ERROR(("Bad command payload, packet dropped")); - silc_free(ctx); - return; - } - - /* Execute command. If this fails the packet is dropped. */ - SILC_SERVER_COMMAND_EXEC(ctx); - silc_buffer_free(buffer); - } + /* + * Recived command. Allocate command context and execute the command. + */ + SILC_LOG_DEBUG(("Command packet")); + silc_server_command_process(server, sock, packet); break; case SILC_PACKET_COMMAND_REPLY: @@ -3705,6 +3688,7 @@ SilcClientList *silc_server_new_client(SilcServer server, /* Set the pointers to the client list and create new client ID */ id_entry = (SilcClientList *)sock->user_data; + id_entry->registered = TRUE; id_entry->nickname = strdup(username); id_entry->username = username; id_entry->userinfo = realname; @@ -3795,6 +3779,7 @@ SilcServerList *silc_server_new_server(SilcServer server, /* Save ID and name */ id_entry = (SilcServerList *)sock->user_data; + id_entry->registered = TRUE; id_entry->id = silc_id_str2id(id_string, SILC_ID_SERVER); id_entry->server_name = server_name;