Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005, 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
else
silc_schedule_task_add_timeout(server->schedule,
silc_server_command_process_timeout,
- timeout, 0, 1);
+ timeout, 0, 0);
return;
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
- silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd);
+ silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd, NULL);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
- silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd);
+ silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd, NULL);
silc_server_command_free(cmd);
}
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
- silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd);
+ silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd, NULL);
silc_server_command_free(cmd);
}
/* Truncate over long nicks */
if (nick_len > 128) {
- nick[128] = '\0';
nick_len = 128;
+ nick[nick_len - 1] = '\0';
}
/* Check for valid nickname string. This is cached, original is saved
oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- /* Remove old cache entry */
- silc_idcache_del_by_context(server->local_list->clients, client, NULL);
-
- silc_free(client->id);
- client->id = new_id;
-
+ /* Update client entry */
+ silc_idcache_update_by_context(server->local_list->clients, client,
+ new_id, nickc, TRUE);
+ silc_free(new_id);
silc_free(client->nickname);
client->nickname = strdup(nick);
- /* Update client cache */
- silc_idcache_add(server->local_list->clients, nickc,
- client->id, (void *)client);
-
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Send NICK_CHANGE notify to the client's channels */
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcID id;
+ SilcChannelID *channel_id = NULL;
SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
SilcUInt32 lch_count = 0, gch_count = 0;
}
/* Get Channel ID */
- if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- goto out;
- }
+ if (silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL))
+ channel_id = SILC_ID_GET_ID(id);
/* Get the channels from local list */
- lchannels = silc_idlist_get_channels(server->local_list, SILC_ID_GET_ID(id),
+ lchannels = silc_idlist_get_channels(server->local_list, channel_id,
&lch_count);
/* Get the channels from global list */
- gchannels = silc_idlist_get_channels(server->global_list, SILC_ID_GET_ID(id),
+ gchannels = silc_idlist_get_channels(server->global_list, channel_id,
&gch_count);
/* Send the reply */
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);
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;
}
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);
}
/* 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:
if (client) {
/* Free all client specific data, such as client entry and entires
on channels this client may be on. */
- silc_server_free_client_data(server, q->sock, client,
- TRUE, q->signoff);
- silc_packet_set_context(q->sock, NULL);
+ silc_server_free_sock_user_data(server, q->sock, q->signoff);
+ silc_server_close_connection(server, q->sock);
}
silc_packet_stream_unref(q->sock);
comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
if (comment && tmp_len2 > 128) {
tmp_len2 = 128;
- comment[127] = '\0';
+ comment[tmp_len2 - 1] = '\0';
}
/* If authentication data is provided then verify that killing is
/* 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 */
goto out;
}
+ SILC_LOG_DEBUG(("id %s", silc_id_render(SILC_ID_GET_ID(id),
+ id.type)));
+
/* The ID must be ours */
if (!SILC_ID_SERVER_COMPARE(server->id, SILC_ID_GET_ID(id))) {
tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
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;
if (!channel)
return;
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
/* Get the client entry */
if (idata->conn_type == SILC_CONN_CLIENT) {
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);
}
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);
}
/* Server side of command JOIN. Joins client into requested channel. If
the channel does not exist it will be created. */
+void silc_server_command_join_connected(SilcServer server,
+ SilcServerEntry server_entry,
+ void *context)
+{
+ SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+
+ if (!server_entry) {
+ SilcUInt32 tmp_len;
+ unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+ char serv[256 + 1];
+
+ SILC_LOG_DEBUG(("Connecting to router failed"));
+ silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv));
+
+ 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;
+ }
+
+ /* Reprocess command */
+ SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router"));
+ silc_server_command_join(cmd, NULL);
+}
+
SILC_SERVER_CMD_FUNC(join)
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
unsigned char *auth, *cauth;
SilcUInt32 tmp_len, auth_len, cauth_len;
char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
+ char parsed[256 + 1], serv[256 + 1];
SilcChannelEntry channel;
SilcUInt32 umode = 0;
SilcBool created = FALSE, create_key = TRUE;
/* Truncate over long channel names */
if (tmp_len > 256) {
- tmp[tmp_len - 1] = '\0';
tmp_len = 256;
+ tmp[tmp_len - 1] = '\0';
+ }
+
+ /* Parse server name from the channel name */
+ 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;
+ }
+ }
}
- channel_name = tmp;
/* Check for valid channel name. This is cached, the original is saved
in the channel context. */
- channel_namec = silc_channel_name_check(tmp, tmp_len, SILC_STRING_UTF8, 256,
- NULL);
+ channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
+ SILC_STRING_UTF8, 256, NULL);
if (!channel_namec) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BAD_CHANNEL, 0);
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;
}
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;
}
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;
}
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
- silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
+ NULL, &hostname, &ip, NULL);
/* Get the username */
username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
}
if (add_nick && add_nick_len > 128) {
- add_nick[128] = '\0';
add_nick_len = 128;
+ add_nick[add_nick_len - 1] = '\0';
}
if (del_nick && del_nick_len > 128) {
- del_nick[128] = '\0';
del_nick_len = 128;
+ del_nick[del_nick_len - 1] = '\0';
}
/* Add new nickname to be watched in our cell */
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;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
- silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
+ NULL, &hostname, &ip, NULL);
if (server->server_type != SILC_ROUTER) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_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;
}
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;
}
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;
SILC_STR_END);
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);
+ list = silc_argument_payload_encode_one(list, tmp2->data,
+ silc_buffer_len(tmp2),
+ SILC_PTR_TO_32(type));
silc_hash_table_list_reset(&htl);
}
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+
/* Send BAN notify type to local servers (but not clients) and to
network. */
if (atype && tmp && len2) {
if (server->server_type == SILC_ROUTER)
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
SILC_NOTIFY_TYPE_BAN, 3,
- id, id_len,
+ tmp_id, id_len,
atype, 1,
tmp ? blist.data : NULL,
tmp ? silc_buffer_len(&blist) : 0);
/* Send the reply back to the client */
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
SILC_STATUS_OK, 0, ident, 2,
- 2, id, id_len,
+ 2, tmp_id, id_len,
3, list ? list->data : NULL,
list ? silc_buffer_len(list) : 0);
silc_buffer_free(list);
SILC_GET32_MSB(port, tmp);
/* Create the connection. It is done with timeout and is async. */
- silc_server_create_connection(server, FALSE, host, port, NULL, NULL);
+ silc_server_create_connection(server, FALSE, FALSE, host, port, NULL, NULL);
/* Send reply to the sender */
silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,