X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fcommand.c;h=d8d105c535a76a72de9518fe9c1853fe17c48765;hp=f2211f50877cbdaa3be76a01f8e367227a5a54c5;hb=55401f49c984e35e652eb590bdcefa07387ddd44;hpb=0a6ebeedacee8f43f604cddbf7dc6bc113c6515e diff --git a/apps/silcd/command.c b/apps/silcd/command.c index f2211f50..d8d105c5 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1051,7 +1051,8 @@ SILC_SERVER_CMD_FUNC(invite) SilcBuffer list, tmp2; SilcBufferStruct alist; unsigned char *tmp, *atype = NULL; - SilcUInt32 len, type, len2; + SilcUInt32 len, len2, ttype; + void *type; SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload); SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4); @@ -1163,7 +1164,7 @@ SILC_SERVER_CMD_FUNC(invite) tmp = silc_argument_get_arg_type(cmd->args, 2, &len); silc_hash_table_list(channel->invite_list, &htl); while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) { - if (type == 3 && !memcmp(tmp2->data, tmp, len)) { + if (SILC_PTR_TO_32(type) == 3 && !memcmp(tmp2->data, tmp, len)) { tmp = NULL; break; } @@ -1252,7 +1253,8 @@ SILC_SERVER_CMD_FUNC(invite) silc_hash_table_list(channel->invite_list, &htl); while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) list = silc_argument_payload_encode_one(list, tmp2->data, - silc_buffer_len(tmp2), type); + silc_buffer_len(tmp2), + SILC_PTR_TO_32(type)); silc_hash_table_list_reset(&htl); } @@ -1287,21 +1289,21 @@ SILC_SERVER_CMD_FUNC(invite) /* Send invite list back only if the list was modified, or no arguments was given. */ - type = 0; + ttype = 0; argc = silc_argument_get_arg_num(cmd->args); if (argc == 1) - type = 1; + ttype = 1; if (silc_argument_get_arg_type(cmd->args, 3, &len)) - type = 1; + ttype = 1; /* Send command reply */ tmp = silc_argument_get_arg_type(cmd->args, 1, &len); silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INVITE, SILC_STATUS_OK, 0, ident, 2, 2, tmp, len, - 3, type && list ? + 3, ttype && list ? list->data : NULL, - type && list ? silc_buffer_len(list) : 0); + ttype && list ? silc_buffer_len(list) : 0); silc_buffer_free(list); out: @@ -1470,13 +1472,19 @@ SILC_SERVER_CMD_FUNC(kill) /* Do normal signoff for the destination client */ sock = remote_client->connection; + + if (sock) + silc_packet_stream_ref(sock); + silc_server_remove_from_channels(server, NULL, remote_client, TRUE, (char *)"Killed", TRUE, TRUE); - silc_server_free_client_data(server, NULL, remote_client, TRUE, - comment ? comment : - (unsigned char *)"Killed"); - if (sock) + silc_server_free_sock_user_data(server, sock, comment ? comment : + (unsigned char *)"Killed"); + if (sock) { + silc_packet_set_context(sock, NULL); silc_server_close_connection(server, sock); + silc_packet_stream_unref(sock); + } } else { /* Router operator killing */ @@ -1828,6 +1836,7 @@ static void silc_server_command_join_channel(SilcServer server, SilcBuffer user_list, mode_list, invite_list, ban_list; SilcUInt16 ident = silc_command_get_ident(cmd->payload); char check[512], check2[512]; + void *plen; SilcBool founder = FALSE; SilcBool resolve; SilcBuffer fkey = NULL, chpklist = NULL; @@ -2144,10 +2153,11 @@ static void silc_server_command_join_channel(SilcServer server, SILC_STR_END); silc_hash_table_list(channel->invite_list, &htl); - while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply)) + while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply)) invite_list = silc_argument_payload_encode_one(invite_list, reply->data, - silc_buffer_len(reply), tmp_len); + silc_buffer_len(reply), + SILC_PTR_TO_32(plen)); silc_hash_table_list_reset(&htl); } @@ -2163,10 +2173,11 @@ static void silc_server_command_join_channel(SilcServer server, SILC_STR_END); silc_hash_table_list(channel->ban_list, &htl); - while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply)) + while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply)) ban_list = silc_argument_payload_encode_one(ban_list, reply->data, - silc_buffer_len(reply), tmp_len); + silc_buffer_len(reply), + SILC_PTR_TO_32(plen)); silc_hash_table_list_reset(&htl); } @@ -2294,36 +2305,37 @@ static void silc_server_command_join_channel(SilcServer server, /* Server side of command JOIN. Joins client into requested channel. If the channel does not exist it will be created. */ -/* Ways of creating channel with dynamic connections: - - 1. If channels are not local (no local_channels in silcd.conf) then - /join silc, will create connection to default router if it is - specified in the silcd.conf. If it isn't, it creates local channel. - - 2. If channels are not local then /join silc@silcnet.org, will create - connection to default if it is specified in the silcd.conf and if it - isn't or join fails it creates connection to silcnet.org and sends - the JOIN command to that server/router. +void silc_server_command_join_connected(SilcServer server, + SilcServerEntry server_entry, + void *context) +{ + SilcServerCommandContext cmd = (SilcServerCommandContext)context; - 3. If channels are local (local_channels set in silcd.conf) then - /join silc, will create local channel. No connections are created - to anywhere. + if (!server_entry) { + SilcUInt32 tmp_len; + unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); + char serv[256 + 1]; - 4. If channels are local then /join silc@silcnet.org will create - connection to default router if it is specified in the silcd.conf and - if it isn't, or join fails it creates connection to silcnet.org and - send the JOIN command to that server/router. + SILC_LOG_DEBUG(("Connecting to router failed")); + silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv)); - 5. If we create connection to a remote that already has a channel that - we also have as a local channel, should we merge those channels? - Should I announce my local channels when I connect to router? Should - I keep local channels local, unless I say /join localch@silcnet.org - in which case the local channel 'localch' becomes global? + if (serv[0]) { + silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_NO_SUCH_SERVER, 0, + 2, serv, strlen(serv)); + } else { + silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0, + 2, tmp, tmp_len); + } + silc_server_command_free(cmd); + return; + } - 6. After we have connection established to router, depending on the - local_channels setting /join silc will join locally or globally. - /join silc@silcnet.org would always join globally. -*/ + /* Reprocess command */ + SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router")); + silc_server_command_join(cmd, NULL); +} SILC_SERVER_CMD_FUNC(join) { @@ -2357,10 +2369,52 @@ SILC_SERVER_CMD_FUNC(join) } /* Parse server name from the channel name */ - silc_parse_userfqdn(channel_name, parsed, sizeof(parsed), serv, + silc_parse_userfqdn(tmp, parsed, sizeof(parsed), serv, sizeof(serv)); channel_name = parsed; + if (server->config->dynamic_server) { + /* If server name is not specified but local channels is FALSE then the + channel will be global, based on our router name. */ + if (!serv[0] && !server->config->local_channels) { + if (!server->standalone) { + silc_snprintf(serv, sizeof(serv), server->router->server_name); + } else { + SilcServerConfigRouter *router; + router = silc_server_config_get_primary_router(server); + if (router) { + /* Create connection to primary router */ + SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d", + router->host, router->port)); + silc_server_create_connection(server, FALSE, TRUE, + router->host, router->port, + silc_server_command_join_connected, + cmd); + return; + } + } + } + + /* If server name is ours, ignore it. */ + if (serv[0] && silc_utf8_strcasecmp(serv, server->server_name)) + memset(serv, 0, sizeof(serv)); + + /* Create connection */ + if (serv[0] && server->standalone) { + SilcServerConfigRouter *router; + router = silc_server_config_get_primary_router(server); + if (router) { + /* Create connection to primary router */ + SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d", + router->host, router->port)); + silc_server_create_connection(server, FALSE, TRUE, + router->host, router->port, + silc_server_command_join_connected, cmd); + return; + } + } + } + /* Check for valid channel name. This is cached, the original is saved in the channel context. */ channel_namec = silc_channel_name_check(channel_name, strlen(channel_name), @@ -2422,10 +2476,22 @@ SILC_SERVER_CMD_FUNC(join) channel = silc_server_create_new_channel(server, server->id, cipher, hmac, channel_name, TRUE); if (!channel) { - silc_server_command_send_status_data( - cmd, SILC_COMMAND_JOIN, - SILC_STATUS_ERR_UNKNOWN_ALGORITHM, - 0, 2, cipher, strlen(cipher)); + if (cipher) { + silc_server_command_send_status_data( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_UNKNOWN_ALGORITHM, + 0, 2, cipher, strlen(cipher)); + } else if (hmac) { + silc_server_command_send_status_data( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_UNKNOWN_ALGORITHM, + 0, 2, hmac, strlen(hmac)); + } else { + silc_server_command_send_status_reply( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_RESOURCE_LIMIT, + 0); + } goto out; } @@ -2481,10 +2547,22 @@ SILC_SERVER_CMD_FUNC(join) channel = silc_server_create_new_channel(server, server->id, cipher, hmac, channel_name, TRUE); if (!channel) { - silc_server_command_send_status_data( - cmd, SILC_COMMAND_JOIN, - SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0, - 2, cipher, strlen(cipher)); + if (cipher) { + silc_server_command_send_status_data( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_UNKNOWN_ALGORITHM, + 0, 2, cipher, strlen(cipher)); + } else if (hmac) { + silc_server_command_send_status_data( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_UNKNOWN_ALGORITHM, + 0, 2, hmac, strlen(hmac)); + } else { + silc_server_command_send_status_reply( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_RESOURCE_LIMIT, + 0); + } goto out; } @@ -2514,10 +2592,22 @@ SILC_SERVER_CMD_FUNC(join) channel = silc_server_create_new_channel(server, server->id, cipher, hmac, channel_name, TRUE); if (!channel) { - silc_server_command_send_status_data( - cmd, SILC_COMMAND_JOIN, - SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0, - 2, cipher, strlen(cipher)); + if (cipher) { + silc_server_command_send_status_data( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_UNKNOWN_ALGORITHM, + 0, 2, cipher, strlen(cipher)); + } else if (hmac) { + silc_server_command_send_status_data( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_UNKNOWN_ALGORITHM, + 0, 2, hmac, strlen(hmac)); + } else { + silc_server_command_send_status_reply( + cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_RESOURCE_LIMIT, + 0); + } goto out; } @@ -4291,8 +4381,10 @@ SILC_SERVER_CMD_FUNC(watch) pk = silc_argument_get_next_arg(pkargs, &type, &pk_len); while (pk) { - if (!silc_public_key_payload_decode(pk, pk_len, &public_key)) + if (!silc_public_key_payload_decode(pk, pk_len, &public_key)) { + pk = silc_argument_get_next_arg(pkargs, &type, &pk_len); continue; + } if (type == 0x03) type = 0x00; @@ -4421,7 +4513,7 @@ SILC_SERVER_CMD_FUNC(silcoper) username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128, &tmp_len); if (!username) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER, + silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER, SILC_STATUS_ERR_BAD_USERNAME, 0); goto out; @@ -4470,7 +4562,7 @@ SILC_SERVER_CMD_FUNC(silcoper) } if (!result) { /* Authentication failed */ - silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER, + silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER, SILC_STATUS_ERR_AUTH_FAILED, 0); goto out; } @@ -4519,7 +4611,7 @@ SILC_SERVER_CMD_FUNC(ban) SilcUInt32 id_len, len, len2; SilcArgumentPayload args; SilcHashTableList htl; - SilcUInt32 type; + void *type; SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload); SilcBufferStruct blist; @@ -4628,7 +4720,8 @@ SILC_SERVER_CMD_FUNC(ban) silc_hash_table_list(channel->ban_list, &htl); while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) list = silc_argument_payload_encode_one(list, tmp2->data, - silc_buffer_len(tmp2), type); + silc_buffer_len(tmp2), + SILC_PTR_TO_32(type)); silc_hash_table_list_reset(&htl); }