+Sat Dec 23 21:55:07 EET 2000 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Fixed a bug in Client library. IDENTIFY and WHOIS reply functions
+ now correctly save the received data.
+
+ * silc_server_free_sock_user_data now notifies routers in the
+ network about entities leaving the network.
+
+ At the same time implemented functions silc_server_remove_id
+ and silc_server_send_remove_id to receive and send REMOVE_ID
+ packets. The packet is used to notify routers in the network
+ about leaving entities. The ID removed will become invalid in
+ the network.
+
+ * Added function silc_idlist_del_server into server. Removes and
+ free's server entry from ID list.
+
+ * silc_server_private_message function now checks, if we are router,
+ that the destination ID really is valid ID, naturally.
+
+ * In router when NEW_ID packet is received (for new client) the
+ hash of the Client ID is saved in the ID Cache but the
+ client->nickname is set to NULL, instead of putting the hash
+ to it as well.
+
+ IDENTIFY command now also checks that client->nickname must be
+ valid. If it is not if will request the data from the server who
+ owns the client. Added new function
+ silc_server_command_identify_check.
+
+ * Added silc_command_set_command into lib/silccore/silcommand.[ch]
+ to set the command to already allocated Command Payload.
+
+ * Tested private message sending in router environment with two
+ routers, two servers and two clients. Fixed minor bugs and now
+ it works fine.
+
+ * Fixed segfault from client's NAMES command. Used to crash if
+ not on any channel.
+
+ * Forwarded packets must not be routed even if it is not destined
+ to the receiver. Changed server code comply with this.
+
Sun Dec 17 14:40:08 EET 2000 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Added `require_reverse_mapping' boolean value to ServerParams
[cipher]
-twofish:/home/silc/silc/lib/silcsim/modules/twofish.sim.so:16:16
-rc6:/home/silc/silc/lib/silcsim/modules/rc6.sim.so:16:16
-mars:/home/silc/silc/lib/silcsim/modules/mars.sim.so:16:16
-none:/home/silc/silc/lib/silcsim/modules/none.sim.so:0:0
+twofish:../lib/silcsim/modules/twofish.sim.so:16:16
+rc6:../lib/silcsim/modules/rc6.sim.so:16:16
+mars:../lib/silcsim/modules/mars.sim.so:16:16
+none:../lib/silcsim/modules/none.sim.so:0:0
[hash]
md5::64:16
mandatory fields that WHOIS command reply requires. Check for these and
make query from the server who owns the client if some fields are
missing. */
- if (!cmd->pending && server->server_type == SILC_ROUTER &&
+ if (server->server_type == SILC_ROUTER &&
!silc_server_command_whois_check(cmd, clients, clients_count)) {
ret = -1;
goto out;
return TRUE;
}
+/* Checks that all mandatory fields are present. If not then send WHOIS
+ request to the server who owns the client. We use WHOIS because we want
+ to get as much information as possible at once. */
+
+static char
+silc_server_command_identify_check(SilcServerCommandContext cmd,
+ SilcClientEntry *clients,
+ unsigned int clients_count)
+{
+ SilcServer server = cmd->server;
+ int i;
+ SilcClientEntry entry;
+
+ for (i = 0; i < clients_count; i++) {
+ entry = clients[i];
+
+ if (!entry->nickname) {
+ 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));
+ silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+ /* Send WHOIS request. We send WHOIS since we're doing the requesting
+ now anyway so make it a good one. */
+ silc_server_packet_send(server, entry->router->connection,
+ SILC_PACKET_COMMAND, cmd->packet->flags,
+ tmpbuf->data, tmpbuf->len, TRUE);
+
+ /* Reprocess this packet after received reply */
+ silc_server_command_pending(server, SILC_COMMAND_WHOIS,
+ silc_command_get_ident(cmd->payload),
+ silc_server_command_identify, (void *)cmd);
+ cmd->pending = TRUE;
+
+ /* Put old data back to the Command Payload we just changed */
+ silc_command_set_ident(cmd->payload, old_ident);
+ silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
+
+ silc_buffer_free(tmpbuf);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
static void
silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
SilcClientEntry *clients,
goto out;
}
+ /* Check that all mandatory fields are present and request those data
+ from the server who owns the client if necessary. */
+ if (!cmd->pending && server->server_type == SILC_ROUTER &&
+ !silc_server_command_identify_check(cmd, clients, clients_count)) {
+ ret = -1;
+ goto out;
+ }
+
/* Send the command reply to the client */
silc_server_command_identify_send_reply(cmd, clients, clients_count);
goto out;
}
- /* Send the command reply to the client */
+ /* Check that all mandatory fields are present and request those data
+ from the server who owns the client if necessary. */
+ if (!cmd->pending && server->server_type == SILC_ROUTER &&
+ !silc_server_command_identify_check(cmd, clients, clients_count)) {
+ ret = -1;
+ goto out;
+ }
+
+ /* Send the command reply */
silc_server_command_identify_send_reply(cmd, clients, clients_count);
out:
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcBuffer packet, idp;
- unsigned int argc;
char info_string[256], *dest_server;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
SilcChannelClientEntry chl;
SilcBuffer reply, chidp, clidp;
+ SILC_LOG_DEBUG(("Start"));
+
if (!channel)
return;
return server;
}
+/* Removes and free's server entry from ID list */
+
+void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
+{
+ if (entry) {
+ /* Remove from cache */
+ if (entry->id)
+ silc_idcache_del_by_id(id_list->servers, SILC_ID_SERVER,
+ (void *)entry->id);
+
+ /* Free data */
+ if (entry->server_name)
+ silc_free(entry->server_name);
+ if (entry->id)
+ silc_free(entry->id);
+ }
+}
+
/******************************************************************************
Client entry functions
called when new client connection is accepted to the server. */
SilcClientEntry
-silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
- char *userinfo, SilcClientID *id,
+silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
+ char *username, char *userinfo, SilcClientID *id,
SilcServerEntry router, void *connection)
{
SilcClientEntry client;
silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
client_list);
- if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
+ if (!silc_idcache_add(id_list->clients, nickname, SILC_ID_CLIENT,
(void *)client->id, (void *)client, TRUE)) {
silc_free(client);
return NULL;
replace it with the hash of new Client ID */
if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
silc_free(id_cache->data);
- id_cache->data = silc_calloc(sizeof(new_id->hash),
- sizeof(unsigned char));
+ id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
silc_idcache_sort_by_data(id_list->clients);
}
/* Generic data structure. DO NOT add anything before this! */
SilcIDListDataStruct data;
- char *nickname;
+ unsigned char *nickname;
char *username;
char *userinfo;
SilcClientID *id;
SilcServerEntry
silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
SilcServerID *new_id);
+void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry);
SilcClientEntry
-silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
- char *userinfo, SilcClientID *id,
+silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
+ char *username, char *userinfo, SilcClientID *id,
SilcServerEntry router, void *connection);
void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
SilcClientEntry *
SILC_LOG_DEBUG(("Start"));
- if (!packet->dst_id) {
- SILC_LOG_ERROR(("Bad Client ID in private message packet, dropped"));
+ if (!packet->dst_id)
goto err;
- }
/* Decode destination Client ID */
id = silc_id_str2id(packet->dst_id, SILC_ID_CLIENT);
we will send the packet to that server. */
router = (SilcServerEntry)dst_sock->user_data;
idata = (SilcIDListData)router;
- // assert(client->router == server->id_entry);
+ //assert(client->router == server->id_entry);
silc_server_send_private_message(server, dst_sock,
idata->send_key,
/* 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) {
- dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
- router = (SilcServerEntry)dst_sock->user_data;
- idata = (SilcIDListData)router;
+ /* 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);
- return;
+ /* Get fastest route and send packet. */
+ if (router)
+ silc_server_send_private_message(server, dst_sock,
+ idata->send_key,
+ idata->hmac, packet);
+ return;
+ }
}
err:
switch(id_type) {
case SILC_ID_CLIENT:
- SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
- silc_id_render(id, SILC_ID_CLIENT),
- sock->type == SILC_SOCKET_TYPE_SERVER ?
- "Server" : "Router", sock->hostname));
+ {
+ SilcClientEntry entry;
+
+ SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_CLIENT),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
- /* 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);
+ /* 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));
+ entry = silc_idlist_add_client(id_list, hash, NULL, NULL, id,
+ router, router_sock);
+ entry->nickname = NULL;
#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);
+ /* 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:
silc_free(tmpid1);
silc_free(tmpid2);
}
+
+/* Processes incoming REMOVE_ID packet. The packet is used to notify routers
+ that certain ID should be removed. After that the ID will become invalid. */
+
+void silc_server_remove_id(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcIDList id_list;
+ SilcIDPayload idp;
+ SilcIdType id_type;
+ void *id, *id_entry;
+
+ if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ server->server_type == SILC_SERVER ||
+ packet->src_id_type != SILC_ID_SERVER)
+ return;
+
+ idp = silc_id_payload_parse(packet->buffer);
+ if (!idp)
+ return;
+
+ id_type = silc_id_payload_get_type(idp);
+
+ id = silc_id_payload_get_id(idp);
+ if (!id)
+ goto out;
+
+ /* If the sender of this packet is server and we are router we need to
+ broadcast this packet to other routers in the network. */
+ if (!server->standalone && server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received Remove ID packet"));
+ silc_server_packet_send(server, server->router->connection,
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ packet->buffer->data, packet->buffer->len, FALSE);
+ }
+
+ if (sock->type == SILC_SOCKET_TYPE_SERVER)
+ id_list = server->local_list;
+ else
+ id_list = server->global_list;
+
+ /* Remove the ID */
+ switch(id_type) {
+ case SILC_ID_CLIENT:
+ id_entry = silc_idlist_find_client_by_id(id_list, (SilcClientID *)id,
+ NULL);
+ if (id_entry) {
+ silc_idlist_del_client(id_list, (SilcClientEntry)id_entry);
+
+ SILC_LOG_DEBUG(("Removed client id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_CLIENT),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+ }
+ break;
+
+ case SILC_ID_SERVER:
+ id_entry = silc_idlist_find_server_by_id(id_list, (SilcServerID *)id,
+ NULL);
+ if (id_entry) {
+ silc_idlist_del_server(id_list, (SilcServerEntry)id_entry);
+
+ SILC_LOG_DEBUG(("Removed server id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_SERVER),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+ }
+ break;
+
+ case SILC_ID_CHANNEL:
+ id_entry = silc_idlist_find_channel_by_id(id_list, (SilcChannelID *)id,
+ NULL);
+ if (id_entry) {
+ silc_idlist_del_channel(id_list, (SilcChannelEntry)id_entry);
+
+ SILC_LOG_DEBUG(("Removed channel id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_CHANNEL),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ out:
+ silc_id_payload_free(idp);
+}
void silc_server_new_channel_user(SilcServer server,
SilcSocketConnection sock,
SilcPacketContext *packet);
+void silc_server_remove_id(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet);
#endif
packet->data, packet->len, TRUE);
silc_buffer_free(packet);
}
+
+/* Function used to send REMOVE_ID packet. The packet is used to notify
+ routers that certain ID should be removed. After that the ID will become
+ invalid. If the argument `broadcast' is TRUE then the packet is sent as
+ broadcast packet. */
+
+void silc_server_send_remove_id(SilcServer server,
+ SilcSocketConnection sock,
+ int broadcast,
+ void *id, unsigned int id_len,
+ SilcIdType id_type)
+{
+ SilcBuffer idp;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ idp = silc_id_payload_encode(id, id_type);
+ silc_server_packet_send(server, sock, SILC_PACKET_REMOVE_ID,
+ broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
+ idp->data, idp->len, FALSE);
+ silc_buffer_free(idp);
+}
SilcSocketConnection sock,
SilcCommand command,
unsigned int argc, ...);
+void silc_server_send_remove_id(SilcServer server,
+ SilcSocketConnection sock,
+ int broadcast,
+ void *id, unsigned int id_len,
+ SilcIdType id_type);
#endif
SILC_LOG_DEBUG(("Processing packet"));
/* Packet sending */
- if (type == SILC_TASK_WRITE) {
- SILC_LOG_DEBUG(("Writing data to connection"));
+ if (type == SILC_TASK_WRITE) {
if (sock->outbuf->data - sock->outbuf->head)
silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
}
/* Packet receiving */
- SILC_LOG_DEBUG(("Reading data from connection"));
/* Read some data from connection */
ret = silc_packet_receive(sock);
/* Route the packet if it is not destined to us. Other ID types but
server are handled separately after processing them. */
if (packet->dst_id_type == SILC_ID_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_FORWARDED) &&
sock->type != SILC_SOCKET_TYPE_CLIENT &&
SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
case SILC_PACKET_CHANNEL_MESSAGE:
/*
* Received channel message. Channel messages are special packets
- * (although probably most common ones) hence they are handled
+ * (although probably most common ones) thus they are handled
* specially.
*/
SILC_LOG_DEBUG(("Channel Message packet"));
*/
case SILC_PACKET_COMMAND:
/*
- * Recived command. Allocate command context and execute the command.
+ * Recived command. Processes the command request and allocates the
+ * command context and calls the command.
*/
SILC_LOG_DEBUG(("Command packet"));
silc_server_command_process(server, sock, packet);
case SILC_PACKET_COMMAND_REPLY:
/*
- * Received command reply packet. Servers never send commands thus
- * they don't receive command reply packets either, except in cases
- * where server has forwarded command packet coming from client.
- * This must be the case here or we will ignore the packet.
+ * Received command reply packet. Received command reply to command. It
+ * may be reply to command sent by us or reply to command sent by client
+ * that we've forwarded.
*/
SILC_LOG_DEBUG(("Command Reply packet"));
silc_server_command_reply(server, sock, packet);
case SILC_PACKET_PRIVATE_MESSAGE_KEY:
/*
- * XXX
+ * Private message key packet.
*/
break;
break;
case SILC_PACKET_CONNECTION_AUTH_REQUEST:
- /* If we receive this packet we will send to the other end information
- about our mandatory authentication method for the connection.
- This packet maybe received at any time. */
+ /*
+ * Connection authentication request packet. When we receive this packet
+ * we will send to the other end information about our mandatory
+ * authentication method for the connection. This packet maybe received
+ * at any time.
+ */
SILC_LOG_DEBUG(("Connection authentication request packet"));
break;
* Received remove ID Packet.
*/
SILC_LOG_DEBUG(("Remove ID packet"));
+ silc_server_remove_id(server, sock, packet);
break;
case SILC_PACKET_REMOVE_CHANNEL_USER:
silc_server_close_connection(server, sock);
}
-/* Free's user_data pointer from socket connection object. As this
- pointer maybe anything we wil switch here to find the correct
- data type and free it the way it needs to be free'd. */
+/* Free's user_data pointer from socket connection object. This also sends
+ appropriate notify packets to the network to inform about leaving
+ entities. */
void silc_server_free_sock_user_data(SilcServer server,
SilcSocketConnection sock)
/* XXX must take some info to history before freeing */
+ /* Send REMOVE_ID packet to routers. */
+ silc_server_send_remove_id(server, server->router->connection,
+ server->server_type == SILC_SERVER ?
+ FALSE : TRUE, user_data->id,
+ SILC_ID_CLIENT_LEN, SILC_ID_CLIENT);
+
/* Free the client entry and everything in it */
silc_idlist_del_data(user_data);
silc_idlist_del_client(server->local_list, user_data);
case SILC_SOCKET_TYPE_SERVER:
case SILC_SOCKET_TYPE_ROUTER:
{
+ SilcServerEntry user_data = (SilcServerEntry)sock->user_data;
+ /* Send REMOVE_ID packet to routers. */
+ silc_server_send_remove_id(server, server->router->connection,
+ server->server_type == SILC_SERVER ?
+ FALSE : TRUE, user_data->id,
+ SILC_ID_SERVER_LEN, SILC_ID_SERVER);
break;
}
break;
unsigned char channel_key[32];
unsigned int len;
+ if (!channel->channel_key)
+ return;
+
if (key_len)
len = key_len;
else if (channel->key_len)
len = channel->key_len / 8;
else
- len = 32;
+ len = sizeof(channel_key);
/* Create channel key */
for (i = 0; i < len; i++) channel_key[i] = silc_rng_get_byte(server->rng);
[Cipher]
-rc6:/home/silc/silc/lib/silcsim/modules/rc6.sim.so:16:16
-twofish:/home/silc/silc/lib/silcsim/modules/twofish.sim.so:16:16
-mars:/home/silc/silc/lib/silcsim/modules/mars.sim.so:16:16
-none:/home/silc/silc/lib/silcsim/modules/none.sim.so:0:0
+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
[HashFunction]
md5::64:16
Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
[ServerInfo]
-lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:212.146.8.246:Kuopio, Finland:1334
[ListenPort]
-10.2.1.7:10.2.1.7:1334
+212.146.8.246:212.146.8.246:1334
[Logging]
infologfile:silcd2.log:10000
[AdminConnection]
[ServerConnection]
-10.2.1.7:passwd:priikone:1333:1:1
+212.146.8.246:passwd:priikone:1333:1:1
[RouterConnection]
-10.2.1.7:passwd:priikone:1335:1:1:1
+212.146.8.246:passwd:priikone:1335:1:1:0
[DenyConnection]
[RedirectClient]
goto out;
}
- if (cmd->argv[1][0] == '*')
+ if (cmd->argv[1][0] == '*') {
+ if (!conn->current_channel) {
+ cmd->client->ops->say(cmd->client, conn, "You are not on any channel");
+ COMMAND_ERROR;
+ goto out;
+ }
name = conn->current_channel->channel_name;
- else
+ } else {
name = cmd->argv[1];
+ }
+
+ if (!conn->current_channel) {
+ cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
+ COMMAND_ERROR;
+ goto out;
+ }
/* Get the Channel ID of the channel */
if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
if (realname)
client_entry->realname = strdup(realname);
+ id_cache->data = client_entry->nickname;
+
silc_free(client_id);
}
if (username)
client_entry->username = strdup(username);
+
+ id_cache->data = client_entry->nickname;
+
silc_free(client_id);
}
}
{
payload->ident = ident;
}
+
+/* Function to set the command to already allocated Command Payload. */
+
+void silc_command_set_command(SilcCommandPayload payload, SilcCommand command)
+{
+ payload->cmd = command;
+}
SilcArgumentPayload silc_command_get_args(SilcCommandPayload payload);
unsigned short silc_command_get_ident(SilcCommandPayload payload);
void silc_command_set_ident(SilcCommandPayload payload, unsigned short ident);
+void silc_command_set_command(SilcCommandPayload payload, SilcCommand command);
#endif