silc_buffer_free(buffer);
}
+/******************************************************************************
+
+ WHOIS Functions
+
+******************************************************************************/
+
static int
silc_server_command_whois_parse(SilcServerCommandContext cmd,
SilcClientID **client_id,
if (!entry->nickname || !entry->username || !entry->userinfo) {
SilcBuffer tmpbuf;
+ unsigned short old_ident;
+ old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
- /* Send WHOIS command to fastest route for the client ID */
- silc_server_packet_send(server,
- silc_server_route_get(server, entry->id,
- SILC_ID_CLIENT),
+ /* Send WHOIS command */
+ silc_server_packet_send(server, entry->router->connection,
SILC_PACKET_COMMAND, cmd->packet->flags,
tmpbuf->data, tmpbuf->len, TRUE);
silc_server_command_whois, (void *)cmd);
cmd->pending = TRUE;
+ silc_command_set_ident(cmd->payload, old_ident);
+
silc_buffer_free(tmpbuf);
return FALSE;
}
SilcBuffer packet, idp;
SilcClientEntry entry;
SilcCommandStatus status;
+ unsigned short ident = silc_command_get_ident(cmd->payload);
status = SILC_STATUS_OK;
if (clients_count > 1)
tmp = silc_argument_get_first_arg(cmd->args, NULL);
/* XXX */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
+ {
char nh[256], uh[256];
unsigned char idle[4];
SilcSocketConnection hsock;
memset(nh, 0, sizeof(nh));
strncat(nh, entry->nickname, strlen(entry->nickname));
- strncat(nh, "@", 1);
- len = entry->router ? strlen(entry->router->server_name) :
- strlen(server->server_name);
- strncat(nh, entry->router ? entry->router->server_name :
- server->server_name, len);
+ if (!strchr(entry->nickname, '@')) {
+ strncat(nh, "@", 1);
+ len = entry->router ? strlen(entry->router->server_name) :
+ strlen(server->server_name);
+ strncat(nh, entry->router ? entry->router->server_name :
+ server->server_name, len);
+ }
strncat(uh, entry->username, strlen(entry->username));
- strncat(uh, "@", 1);
- hsock = (SilcSocketConnection)entry->connection;
- len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
- strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
+ if (!strchr(entry->username, '@')) {
+ strncat(uh, "@", 1);
+ hsock = (SilcSocketConnection)entry->connection;
+ len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
+ strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
+ }
SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
if (entry->userinfo)
packet =
silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, 0, 5,
+ status, ident, 5,
2, idp->data, idp->len,
3, nh, strlen(nh),
4, uh, strlen(uh),
else
packet =
silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, 0, 4,
+ status, ident, 4,
2, idp->data, idp->len,
3, nh, strlen(nh),
4, uh, strlen(uh),
7, idle, 4);
-
- } else {
- /* XXX */
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, 0, 3,
- 2, idp->data, idp->len,
- 3, entry->nickname,
- strlen(entry->nickname),
- 4, tmp, strlen(tmp)); /* XXX */
}
+
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
0, packet->data, packet->len, FALSE);
if (server->server_type == SILC_SERVER &&
!cmd->pending && !server->standalone) {
SilcBuffer tmpbuf;
+ unsigned short old_ident;
+ old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
silc_server_command_whois, (void *)cmd);
cmd->pending = TRUE;
+ silc_command_set_ident(cmd->payload, old_ident);
+
silc_buffer_free(tmpbuf);
ret = -1;
goto out;
/* Get all clients matching that ID or nickname from local list */
if (client_id) {
- entry = silc_idlist_find_client_by_id(server->local_list, client_id);
+ entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
if (entry) {
clients = silc_calloc(1, sizeof(*clients));
clients[0] = entry;
&clients_count);
}
- /* If we are router we will check our global list as well. */
- if (!clients && server->server_type == SILC_ROUTER) {
+ /* Check global list as well */
+ if (!clients) {
if (client_id) {
- entry = silc_idlist_find_client_by_id(server->global_list, client_id);
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
if (entry) {
clients = silc_calloc(1, sizeof(*clients));
clients[0] = entry;
send reply to the requesting server. */
if (client_id) {
- entry = silc_idlist_find_client_by_id(server->local_list, client_id);
+ entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
if (entry) {
clients = silc_calloc(1, sizeof(*clients));
clients[0] = entry;
clients = silc_idlist_get_clients_by_nickname(server->local_list,
nick, server_name,
&clients_count);
+ if (!clients)
+ clients = silc_idlist_get_clients_by_hash(server->local_list,
+ nick, server->md5hash,
+ &clients_count);
}
/* If we are router we will check our global list as well. */
if (!clients && server->server_type == SILC_ROUTER) {
if (client_id) {
- entry = silc_idlist_find_client_by_id(server->global_list, client_id);
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
if (entry) {
clients = silc_calloc(1, sizeof(*clients));
clients[0] = entry;
clients = silc_idlist_get_clients_by_nickname(server->global_list,
nick, server_name,
&clients_count);
+ if (!clients)
+ clients = silc_idlist_get_clients_by_hash(server->global_list,
+ nick, server->md5hash,
+ &clients_count);
}
}
{
}
-SILC_SERVER_CMD_FUNC(identify)
-{
- SilcServerCommandContext cmd = (SilcServerCommandContext)context;
- SilcServer server = cmd->server;
- char *tmp, *nick = NULL, *server_name = NULL;
- unsigned int argc, count = 0, len;
- int use_id = FALSE;
- SilcClientID *client_id = NULL;
- SilcClientEntry entry;
- SilcBuffer packet, idp;
+/******************************************************************************
- SILC_LOG_DEBUG(("Start"));
+ IDENTIFY Functions
- argc = silc_argument_get_arg_num(cmd->args);
- if (argc < 1) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
- }
- if (argc > 3) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_TOO_MANY_PARAMS);
- goto out;
- }
+******************************************************************************/
+
+static int
+silc_server_command_identify_parse(SilcServerCommandContext cmd,
+ SilcClientID **client_id,
+ char **nickname,
+ char **server_name,
+ int *count)
+{
+ unsigned char *tmp;
+ unsigned int len;
+ unsigned int argc = silc_argument_get_arg_num(cmd->args);
/* If client ID is in the command it must be used instead of nickname */
tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
if (!tmp) {
-
- /* Get the nickname@server string and parse it. */
+ /* No ID, get the nickname@server string and parse it. */
tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
if (tmp) {
if (strchr(tmp, '@')) {
len = strcspn(tmp, "@");
- nick = silc_calloc(len + 1, sizeof(char));
- memcpy(nick, tmp, len);
- server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
- memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
+ *nickname = silc_calloc(len + 1, sizeof(char));
+ memcpy(*nickname, tmp, len);
+ *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
+ memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
} else {
- nick = strdup(tmp);
+ *nickname = strdup(tmp);
}
} else {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
+ return FALSE;
}
} else {
/* Command includes ID, use that */
- client_id = silc_id_payload_parse_id(tmp, len);
- use_id = TRUE;
+ *client_id = silc_id_payload_parse_id(tmp, len);
}
/* Get the max count of reply messages allowed */
if (!tmp) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_TOO_MANY_PARAMS);
- goto out;
+ if (*nickname)
+ silc_free(*nickname);
+ if (*server_name)
+ silc_free(*server_name);
+
+ return FALSE;
}
- count = atoi(tmp);
+ *count = atoi(tmp);
}
- /* Find client */
- if (!use_id) {
- entry = silc_idlist_find_client_by_nickname(server->local_list,
- nick, NULL);
- if (!entry)
- entry = silc_idlist_find_client_by_hash(server->global_list,
- nick, server->md5hash);
- } else {
- entry = silc_idlist_find_client_by_id(server->local_list, client_id);
- }
+ return TRUE;
+}
- /* If client was not found and if we are normal server and are connected
- to a router we will make global query from the router. */
- if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
- !cmd->pending) {
- SilcBuffer buffer = cmd->packet->buffer;
-
- SILC_LOG_DEBUG(("Requesting identify from router"));
+static void
+silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
+ SilcClientEntry *clients,
+ unsigned int clients_count)
+{
+ SilcServer server = cmd->server;
+ char *tmp;
+ int i, count = 0, len;
+ SilcBuffer packet, idp;
+ SilcClientEntry entry;
+ SilcCommandStatus status;
+ unsigned short ident = silc_command_get_ident(cmd->payload);
+
+ status = SILC_STATUS_OK;
+ if (clients_count > 1)
+ status = SILC_STATUS_LIST_START;
+
+ for (i = 0; i < clients_count; i++) {
+ entry = clients[i];
+
+ if (count && i - 1 == count)
+ break;
+
+ if (clients_count > 2)
+ status = SILC_STATUS_LIST_ITEM;
+
+ if (clients_count > 1 && i == clients_count - 1)
+ status = SILC_STATUS_LIST_END;
+
+ /* Send IDENTIFY reply */
+ idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
+ tmp = silc_argument_get_first_arg(cmd->args, NULL);
+ /* XXX */
+ {
+ char nh[256], uh[256];
+ SilcSocketConnection hsock;
+
+ memset(uh, 0, sizeof(uh));
+ memset(nh, 0, sizeof(nh));
+
+ strncat(nh, entry->nickname, strlen(entry->nickname));
+ if (!strchr(entry->nickname, '@')) {
+ strncat(nh, "@", 1);
+ len = entry->router ? strlen(entry->router->server_name) :
+ strlen(server->server_name);
+ strncat(nh, entry->router ? entry->router->server_name :
+ server->server_name, len);
+ }
+
+ if (!entry->username) {
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_OK, ident, 2,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh));
+ } else {
+ strncat(uh, entry->username, strlen(entry->username));
+ if (!strchr(entry->username, '@')) {
+ strncat(uh, "@", 1);
+ hsock = (SilcSocketConnection)entry->connection;
+ len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
+ strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
+ }
+
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_OK, ident, 3,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh),
+ 4, uh, strlen(uh));
+ }
+
+ silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
+ 0, packet->data, packet->len, FALSE);
+
+ silc_buffer_free(packet);
+ silc_buffer_free(idp);
+ }
+ }
+}
+
+static int
+silc_server_command_identify_from_client(SilcServerCommandContext cmd)
+{
+ SilcServer server = cmd->server;
+ char *nick = NULL, *server_name = NULL;
+ int count = 0, clients_count;
+ SilcClientID *client_id = NULL;
+ SilcClientEntry *clients = NULL, entry;
+ int ret = 0;
+
+ /* Parse the IDENTIFY request */
+ if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
+ &server_name, &count))
+ return 0;
+
+ /* Protocol dictates that we must always send the received IDENTIFY request
+ to our router if we are normal server, so let's do it now unless we
+ are standalone. We will not send any replies to the client until we
+ have received reply from the router. */
+ if (server->server_type == SILC_SERVER &&
+ !cmd->pending && !server->standalone) {
+ SilcBuffer tmpbuf;
+ unsigned short old_ident;
+
+ old_ident = silc_command_get_ident(cmd->payload);
+ silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
/* Send IDENTIFY command to our router */
- silc_buffer_push(buffer, buffer->data - buffer->head);
- silc_server_packet_forward(server, (SilcSocketConnection)
- server->router->connection,
- buffer->data, buffer->len, TRUE);
- return;
+ silc_server_packet_send(server, (SilcSocketConnection)
+ server->router->connection,
+ SILC_PACKET_COMMAND, cmd->packet->flags,
+ tmpbuf->data, tmpbuf->len, TRUE);
+
+ /* Reprocess this packet after received reply from router */
+ silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
+ silc_command_get_ident(cmd->payload),
+ silc_server_command_identify, (void *)cmd);
+ cmd->pending = TRUE;
+
+ silc_command_set_ident(cmd->payload, old_ident);
+
+ silc_buffer_free(tmpbuf);
+ ret = -1;
+ goto out;
}
- /* If we are router we have checked our local list by nickname and our
- global list by hash so far. It is possible that the client is still not
- found and we'll check it from local list by hash. */
- if (!entry && server->server_type == SILC_ROUTER)
- entry = silc_idlist_find_client_by_hash(server->local_list,
- nick, server->md5hash);
+ /* We are ready to process the command request. Let's search for the
+ requested client and send reply to the requesting client. */
- if (!entry) {
- /* The client definitely does not exist */
+ /* Get all clients matching that ID or nickname from local list */
+ if (client_id) {
+ entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
+ if (entry) {
+ clients = silc_calloc(1, sizeof(*clients));
+ clients[0] = entry;
+ clients_count = 1;
+ }
+ } else {
+ clients = silc_idlist_get_clients_by_nickname(server->local_list,
+ nick, server_name,
+ &clients_count);
+ }
+
+ /* Check global list as well */
+ if (!clients) {
+ if (client_id) {
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
+ if (entry) {
+ clients = silc_calloc(1, sizeof(*clients));
+ clients[0] = entry;
+ clients_count = 1;
+ }
+ } else {
+ clients = silc_idlist_get_clients_by_nickname(server->global_list,
+ nick, server_name,
+ &clients_count);
+ }
+ }
+
+ if (!clients) {
+ /* Such a client really does not exist in the SILC network. */
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_NICK,
- 3, tmp, strlen(tmp));
+ 3, nick, strlen(nick));
goto out;
}
- /* Send IDENTIFY reply */
- idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
- tmp = silc_argument_get_first_arg(cmd->args, NULL);
- packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
- SILC_STATUS_OK, 0, 2,
- 2, idp->data, idp->len,
- 3, nick, strlen(nick));
- if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
- void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
- silc_server_packet_send_dest(server, cmd->sock,
- SILC_PACKET_COMMAND_REPLY, 0,
- id, cmd->packet->src_id_type,
- packet->data, packet->len, FALSE);
- silc_free(id);
- } else {
- silc_server_packet_send(server, cmd->sock,
- SILC_PACKET_COMMAND_REPLY, 0,
- packet->data, packet->len, FALSE);
- }
+ /* Send the command reply to the client */
+ silc_server_command_identify_send_reply(cmd, clients, clients_count);
- silc_buffer_free(packet);
- silc_buffer_free(idp);
+ out:
+ if (clients)
+ silc_free(clients);
if (client_id)
silc_free(client_id);
+ if (nick)
+ silc_free(nick);
+ if (server_name)
+ silc_free(server_name);
+
+ return ret;
+}
+
+static int
+silc_server_command_identify_from_server(SilcServerCommandContext cmd)
+{
+ SilcServer server = cmd->server;
+ char *nick = NULL, *server_name = NULL;
+ int count = 0, clients_count;
+ SilcClientID *client_id = NULL;
+ SilcClientEntry *clients = NULL, entry;
+ int ret = 0;
+
+ /* Parse the IDENTIFY request */
+ if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
+ &server_name, &count))
+ return 0;
+
+ /* Process the command request. Let's search for the requested client and
+ send reply to the requesting server. */
+
+ if (client_id) {
+ entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
+ if (entry) {
+ clients = silc_calloc(1, sizeof(*clients));
+ clients[0] = entry;
+ clients_count = 1;
+ }
+ } else {
+ clients = silc_idlist_get_clients_by_nickname(server->local_list,
+ nick, server_name,
+ &clients_count);
+ if (!clients)
+ clients = silc_idlist_get_clients_by_hash(server->local_list,
+ nick, server->md5hash,
+ &clients_count);
+ }
+
+ /* If we are router we will check our global list as well. */
+ if (!clients && server->server_type == SILC_ROUTER) {
+ if (client_id) {
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
+ if (entry) {
+ clients = silc_calloc(1, sizeof(*clients));
+ clients[0] = entry;
+ clients_count = 1;
+ }
+ } else {
+ clients = silc_idlist_get_clients_by_nickname(server->global_list,
+ nick, server_name,
+ &clients_count);
+ if (!clients)
+ clients = silc_idlist_get_clients_by_hash(server->global_list,
+ nick, server->md5hash,
+ &clients_count);
+ }
+ }
+
+ if (!clients) {
+ /* Such a client really does not exist in the SILC network. */
+ silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_ERR_NO_SUCH_NICK,
+ 3, nick, strlen(nick));
+ goto out;
+ }
+
+ /* Send the command reply to the client */
+ silc_server_command_identify_send_reply(cmd, clients, clients_count);
out:
+ if (clients)
+ silc_free(clients);
+ if (client_id)
+ silc_free(client_id);
if (nick)
silc_free(nick);
if (server_name)
silc_free(server_name);
- silc_server_command_free(cmd);
+
+ return ret;
+}
+
+SILC_SERVER_CMD_FUNC(identify)
+{
+ SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+ int ret;
+
+ SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
+
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
+ ret = silc_server_command_identify_from_client(cmd);
+ else
+ ret = silc_server_command_identify_from_server(cmd);
+
+ if (!ret)
+ silc_server_command_free(cmd);
}
/* Checks string for bad characters and returns TRUE if they are found. */
channel_id = silc_id_payload_parse_id(tmp, tmp_len);
/* Check whether the channel exists */
- channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
if (!channel) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
SILC_STATUS_ERR_NO_SUCH_CHANNEL);
channel_id = silc_id_payload_parse_id(tmp, len);
/* Check whether the channel exists */
- channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
if (!channel) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NO_SUCH_CHANNEL);
if (chl->client == sender) {
if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
- SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+ SILC_STATUS_ERR_NO_CHANNEL_PRIV);
goto out;
}
break;
/* 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, dest_id);
+ dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
if (dest)
dest_sock = (SilcSocketConnection)dest->connection;
else
client = (SilcClientEntry)cmd->sock->user_data;
/* Get channel entry */
- channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
+ channel = silc_idlist_find_channel_by_name(server->local_list,
+ channel_name, NULL);
if (channel) {
/* Join the client to the channel by adding it to channel's user list.
Add also the channel to client entry's channels list for fast cross-
real easy. */
if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
- client = silc_idlist_find_client_by_id(server->local_list, id);
+ client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
if (!client) {
/* XXX */
SILC_LOG_ERROR(("Forwarded join command did not find the client who "
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- int argc, tmp_len;
+ int tmp_len;
char *tmp, *channel_name = NULL, *cipher = NULL;
SilcChannelEntry channel;
unsigned int umode = 0;
int created = FALSE;
- SILC_LOG_DEBUG(("Start"));
-
- /* Check number of parameters */
- argc = silc_argument_get_arg_num(cmd->args);
- if (argc < 1) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
- }
- if (argc > 3) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
- SILC_STATUS_ERR_TOO_MANY_PARAMS);
- goto out;
- }
+ SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 3);
/* Get channel name */
tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
/* See if the channel exists */
- channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
+ channel = silc_idlist_find_channel_by_name(server->local_list,
+ channel_name, NULL);
if (!channel) {
/* Channel not found */
/* We are router and the channel does not seem exist so we will check
our global list as well for the channel. */
channel = silc_idlist_find_channel_by_name(server->global_list,
- channel_name);
+ channel_name, NULL);
if (!channel) {
/* Channel really does not exist, create it */
channel = silc_server_create_new_channel(server, server->id, cipher,
SILC_GET32_MSB(mode_mask, tmp_mask);
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
if (!channel) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_NO_SUCH_CHANNEL);
channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
if (!channel) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_SUCH_CHANNEL);
client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
/* Get target client's entry */
- target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
+ target_client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, NULL);
if (!target_client) {
/* XXX If target client is not one of mine send to primary route */
}
id = silc_id_payload_parse_id(tmp, len);
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, id);
+ channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
if (!channel) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
SILC_STATUS_ERR_NO_SUCH_CHANNEL);
/* Check whether the channel exists. If we are normal server and the
channel does not exist we will send this same command to our router
which will know if the channel exists. */
- channel = silc_idlist_find_channel_by_id(server->local_list, id);
+ channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
if (!channel) {
if (server->server_type == SILC_SERVER && !server->standalone) {
/* XXX Send names command */
/* 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);
+ 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;
"No such nickname: Private message not sent");
}
-/* Relays received command reply packet to the correct destination. The
- destination must be one of our locally connected client or the packet
- will be ignored. This is called when server has forwarded one of
- client's command request to router and router has now replied to the
- command. */
+/* Processes incoming command reply packet. The command reply packet may
+ be destined to one of our clients or it may directly for us. We will
+ call the command reply routine after processing the packet. */
-void silc_server_packet_relay_command_reply(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+void silc_server_command_reply(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
- SilcClientEntry client;
- SilcClientID *id;
+ SilcClientEntry client = NULL;
SilcSocketConnection dst_sock;
SilcIDListData idata;
+ SilcClientID *id = NULL;
SILC_LOG_DEBUG(("Start"));
sock->type != SILC_SOCKET_TYPE_ROUTER)
return;
- /* Destination must be client */
- if (packet->dst_id_type != SILC_ID_CLIENT)
+ if (packet->dst_id_type == SILC_ID_CHANNEL)
return;
- /* Execute command reply locally for the command */
- silc_server_command_reply_process(server, sock, buffer);
-
- id = silc_id_str2id(packet->dst_id, SILC_ID_CLIENT);
-
- /* Destination must be one of ours */
- client = silc_idlist_find_client_by_id(server->local_list, id);
- if (!client) {
- SILC_LOG_ERROR(("Cannot relay command reply to unknown client"));
- silc_free(id);
- return;
+ if (packet->dst_id_type == SILC_ID_CLIENT) {
+ /* Destination must be one of ours */
+ id = silc_id_str2id(packet->dst_id, SILC_ID_CLIENT);
+ client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
+ if (!client) {
+ SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
+ silc_free(id);
+ return;
+ }
}
- /* Relay the packet to the client */
-
- dst_sock = (SilcSocketConnection)client->connection;
- silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
- + packet->dst_id_len + packet->padlen);
-
- silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
- silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
+ if (packet->dst_id_type == SILC_ID_SERVER) {
+ /* For now this must be for us */
+ if (SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
+ SILC_LOG_ERROR(("Cannot process command reply to unknown server"));
+ return;
+ }
+ }
- idata = (SilcIDListData)client;
+ /* Execute command reply locally for the command */
+ silc_server_command_reply_process(server, sock, buffer);
- /* Encrypt packet */
- silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf,
- buffer->len);
+ if (packet->dst_id_type == SILC_ID_CLIENT && client && id) {
+ /* Relay the packet to the client */
+
+ dst_sock = (SilcSocketConnection)client->connection;
+ silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
+ + packet->dst_id_len + packet->padlen);
+
+ silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
+ silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
+
+ idata = (SilcIDListData)client;
- /* Send the packet */
- silc_server_packet_send_real(server, dst_sock, TRUE);
+ /* Encrypt packet */
+ silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf,
+ buffer->len);
+
+ /* Send the packet */
+ silc_server_packet_send_real(server, dst_sock, TRUE);
- silc_free(id);
+ silc_free(id);
+ }
}
/* Process received channel message. The message can be originated from
/* Find channel entry */
id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
- channel = silc_idlist_find_channel_by_id(server->local_list, id);
+ channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
if (!channel) {
SILC_LOG_DEBUG(("Could not find channel"));
goto out;
goto out;
/* Get the channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, id);
+ channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
if (!channel) {
SILC_LOG_ERROR(("Received key for non-existent channel"));
goto out;
SilcSocketConnection router_sock;
SilcIDPayload idp;
SilcIdType id_type;
+ unsigned char *hash = NULL;
void *id, *tmpid;
SILC_LOG_DEBUG(("Processing new ID"));
sock->type == SILC_SOCKET_TYPE_SERVER ?
"Server" : "Router", sock->hostname));
- /* Add the client to our local list. We are router and we keep
- cell specific local database of all clients in the cell. */
- silc_idlist_add_client(id_list, NULL, NULL, NULL, id, router, router_sock);
+ /* As a router we keep information of all global information in our global
+ list. Cell wide information however is kept in the local list. The
+ client is put to global list and we will take the hash value of the
+ Client ID and save it to the ID Cache system for fast searching in the
+ future. */
+ hash = silc_calloc(sizeof(((SilcClientID *)id)->hash),
+ sizeof(unsigned char));
+ memcpy(hash, ((SilcClientID *)id)->hash,
+ sizeof(((SilcClientID *)id)->hash));
+ silc_idlist_add_client(id_list, hash, NULL, NULL, id, router, router_sock);
+#if 0
+ /* XXX Adding two ID's with same IP number replaces the old entry thus
+ gives wrong route. Thus, now disabled until figured out a better way
+ to do this or when removed the whole thing. This could be removed
+ because entry->router->connection gives always the most optimal route
+ for the ID anyway (unless new routes (faster perhaps) are established
+ after receiving this ID, this we don't know however). */
/* Add route cache for this ID */
silc_server_route_add(silc_server_route_hash(
((SilcClientID *)id)->ip.s_addr,
server->id->port), ((SilcClientID *)id)->ip.s_addr,
router);
+#endif
break;
case SILC_ID_SERVER:
sock->type == SILC_SOCKET_TYPE_SERVER ?
"Server" : "Router", sock->hostname));
- /* Add the server to our local list. We are router and we keep
- cell specific local database of all servers in the cell. */
+ /* As a router we keep information of all global information in our global
+ list. Cell wide information however is kept in the local list. */
silc_idlist_add_server(id_list, NULL, 0, id, router, router_sock);
+#if 0
/* Add route cache for this ID */
silc_server_route_add(silc_server_route_hash(
((SilcServerID *)id)->ip.s_addr,
((SilcServerID *)id)->port),
((SilcServerID *)id)->ip.s_addr,
router);
+#endif
break;
case SILC_ID_CHANNEL:
/* XXX routers should check server->global_list as well */
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
if (!channel)
goto out;
/* XXX routers should check server->global_list as well */
/* Get client entry */
- client = silc_idlist_find_client_by_id(server->local_list, client_id);
+ client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
if (!client)
goto out;
goto out;
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
if (!channel) {
silc_free(channel_id);
goto out;
silc_free(tmpid);
/* Find the channel */
- channel = silc_idlist_find_channel_by_id(id_list, channel_id);
+ channel = silc_idlist_find_channel_by_id(id_list, channel_id, NULL);
if (!channel) {
SILC_LOG_ERROR(("Received channel user for non-existent channel"));
goto out;
}
/* Get client entry */
- client = silc_idlist_find_client_by_id(id_list, client_id);
+ client = silc_idlist_find_client_by_id(id_list, client_id, NULL);
if (!client) {
/* This is new client to us, add entry to ID list */
client = silc_idlist_add_client(id_list, NULL, NULL, NULL,