+Sun Nov 11 10:49:10 EET 2001 Pekka Riikonen <priikone@silcnet.org>
+
+ * Use ++server->cmd_ident when sending commands in server,
+ instead of random number. Affected file silcd/command.c.
+
+ * Fixed GETKEY command reply to call actually GETKEY pending
+ command callbacks. Affected file silcd/command_reply.c.
+
+ * A bit stricter check for nicknames. Check for same nickname
+ in NICK command also. Affected file silcd/command.c.
+
+ * Do not call INFO command everytime client ID changes, only
+ during first connecting. Affected file lib/silcclient/client.c.
+
+ * Set the new nickname only after successful command reply for
+ NICK command is returned by server. Affected file
+ lib/silcclient/command.c.
+
+ * Remove nicknames from nicklist during server_signoff notify.
+ Should fix /NAMES bit more. The affected file is
+ irssi/src/silc/core/silc-channels.c.
+
+ * Added `fingerprint' field to the SilcIDListData in the
+ silcd/idlist.h to hold the fingerprint of the client's
+ public key.
+
+ Send the fingerprint of the client's public key in WHOIS
+ command reply.
+
+ Affected files silcd/command.c, and silcd/idlist.[ch].
+
+ * Added silc_fingerprint into lib/silcutil/silcutil.[ch] to
+ create fingerprint from given data.
+
+ * Show the fingerprint of the client's public key in WHOIS.
+ Affected files irssi/src/module-formats.[ch] and
+ irssi/src/silc/core/client_ops.c.
+
+ * Format the multiple same nicknames also during JOIN and
+ NICK_CHANGE notifys. Affected file is
+ lib/silcclient/client_notify.c.
+
+ * Do not print error on screen for invalid private message
+ payload since it can come if someone is sending private
+ messages with wrong key. Affected file
+ lib/silccore/silcprivate.c.
+
+ * Fixed multiple concurrent /PING crash. Affected file
+ lib/silcclient/command.c.
+
+ * Changed the wrong ID encoding. All IP addresses must be
+ in MSB first order in encoded format. They were encoded
+ wrong and was in LSB format. Affected files are
+ silcd/serverid.c, lib/silcutil/silcutil.c.
+
+ * Remove silc_net_addr2bin_ne from lib/silcutil/silcnet.[ch].
+
+ * Call the `connect' client operation through the scheduler
+ in case of error. Affected file lib/silcclient/client.c.
+
+ * Call the `failure' client operation even if the error
+ occurred locally during a protocol. Affected file is
+ lib/silcclient/protocol.c.
+
+ * Added support of sending LIST command to router from normal
+ server. This way normal server can get list of all channels
+ in the network too. Fixed the channel list sending in the
+ server too. Affected files are silcd/command.c, and
+ silcd/command_reply.[ch].
+
+ * Added silc_server_update_channels_by_server and
+ silc_server_remove_channels_by_server. They are used during
+ disconnection of primary router and in backup router protocol.
+ Affected file silcd/server_util.[ch], silcd/server.c and
+ silcd/server_backup.c.
+
+ * Fixed channel adding to global list in IDENTIFY command
+ reply in server. Affected file silcd/command_reply.c.
+
Sat Nov 10 21:39:22 EET 2001 Pekka Riikonen <priikone@silcnet.org>
* If the incoming packet type is REKEY or REKEY_DONE process
TODO/bugs in Irssi SILC client
==============================
- o /NAMES kees showing things wrong after JOIN and after ppl has left
- channel.
-
o Add local command to switch the channel's private key when channel has
several private keys. Currently sending channel messages with many
keys is not possible because changing the key is not possible by the
TODO/bugs In SILC Client Library
================================
- o key agreement with itself causes the packet sequence numbers go grazy.
-
- o WHOIS shows the formatted nickname wrong in some circumstances.
-
- o Set incrorrect key and /MSG him, screen gets screwed.
-
- o Crashes if lots of concurrent /PING's.
-
o JOIN command's argument handling is buggy. See the XXX in the code.
If it is, there is no reason to send it to the router, since the server
knows it best.
- o Add support for sending the LIST command to primary router on normal
- server to receive all the created channels. Currently the command
- returns only the channels the server knows about. The protocol spec
- does not prohibit of sending the LIST to the router.
-
o Incomplete IPv6 support:
o silcd/serverid.c and its routines supports only IPv4.
{ NULL, "Who Queries", 0 },
{ "whois", "{nick $0} {nickhost $1@$2}%: nickname : $3 ($4)", 5, { 0, 0, 0, 0, 0 } },
- { "whois_realname", " realname : $0", 1, { 0 } },
- { "whois_channels", " channels : $0", 1, { 0 } },
- { "whois_modes", " modes : $0", 1, { 0 } },
- { "whois_idle", " idle : $0", 1, { 0 } },
+ { "whois_realname", " realname : $0", 1, { 0 } },
+ { "whois_channels", " channels : $0", 1, { 0 } },
+ { "whois_modes", " modes : $0", 1, { 0 } },
+ { "whois_idle", " idle : $0", 1, { 0 } },
+ { "whois_fingerprint", " fingerprint : $0", 1, { 0 } },
{ "whowas", "{nick $0} was {nickhost $1} ($2)", 3, { 0, 0, 0 } },
{ "users_header", "Users on {channelhilight $0}", 1, { 0 } },
{ "users", " %|{nick $[!20]0} $[!5]1 $2@$3 {comment {hilight $4}}", 5, { 0, 0, 0, 0, 0 } },
SILCTXT_WHOIS_CHANNELS,
SILCTXT_WHOIS_MODES,
SILCTXT_WHOIS_IDLE,
+ SILCTXT_WHOIS_FINGERPRINT,
SILCTXT_WHOWAS_USERINFO,
SILCTXT_USERS_HEADER,
SILCTXT_USERS,
/* Called to indicate that connection was either successfully established
or connecting failed. This is also the first time application receives
- the SilcClientConnection objecet which it should save somewhere. */
+ the SilcClientConnection object which it should save somewhere. */
void silc_connect(SilcClient client, SilcClientConnection conn, int success)
{
case SILC_COMMAND_WHOIS:
{
char buf[1024], *nickname, *username, *realname, *nick;
+ unsigned char *fingerprint;
uint32 idle, mode;
SilcBuffer channels;
SilcClientEntry client_entry;
channels = va_arg(vp, SilcBuffer);
mode = va_arg(vp, uint32);
idle = va_arg(vp, uint32);
+ fingerprint = va_arg(vp, unsigned char *);
silc_parse_userfqdn(nickname, &nick, NULL);
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_WHOIS_IDLE, buf);
}
+
+ if (fingerprint) {
+ fingerprint = silc_fingerprint(fingerprint, 20);
+ printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+ SILCTXT_WHOIS_FINGERPRINT, fingerprint);
+ silc_free(fingerprint);
+ }
}
break;
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_LIST_HEADER);
- snprintf(users, sizeof(users) - 1, "%d", usercount);
+ if (!usercount)
+ snprintf(users, sizeof(users) - 1, "N/A");
+ else
+ snprintf(users, sizeof(users) - 1, "%d", usercount);
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_LIST,
name, users, topic ? topic : "");
clients_count = va_arg(va, uint32);
for (i = 0; i < clients_count; i++) {
+ GSList *nicks, *tmp;
+
memset(userhost, 0, sizeof(userhost));
if (clients[i]->username)
snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
signal_emit("message quit", 4, server, clients[i]->nickname,
clients[i]->username ? userhost : "",
"server signoff");
+
+ nicks = nicklist_get_same_unique(SERVER(server), clients[i]);
+ for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
+ CHANNEL_REC *channel = tmp->data;
+ NICK_REC *nickrec = tmp->next->data;
+ nicklist_remove(channel, nickrec);
+ }
}
}
{ "list-pkcs", 'P', POPT_ARG_NONE, &opt_list_pkcs, 0,
"List supported PKCSs", NULL },
{ "debug", 'd', POPT_ARG_STRING, &opt_debug, 0,
- "Enable debugging", NULL },
+ "Enable debugging", "STRING" },
{ "version", 'V', POPT_ARG_NONE, &opt_version, 0,
"Show version", NULL },
{ NULL, '\0', 0, NULL }
silc_log_set_debug_string(opt_debug);
silc_log_set_callbacks(silc_log_info, silc_log_warning,
silc_log_error, NULL);
+#ifndef SILC_DEBUG
+ fprintf(stdout,
+ "Run-time debugging is not enabled. To enable it recompile\n"
+ "the client with --enable-debug configuration option.\n");
+#endif
}
/* Do some irssi initializing */
uint16 ident = silc_command_get_ident(cmd->payload);
char nh[256], uh[256];
unsigned char idle[4], mode[4];
+ unsigned char *fingerprint;
SilcSocketConnection hsock;
len = 0;
}
channels = silc_server_get_client_channel_list(server, entry);
+
+ if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
+ fingerprint = entry->data.fingerprint;
+ else
+ fingerprint = NULL;
SILC_PUT32_MSB(entry->mode, mode);
SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
}
- if (channels)
- packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, ident, 7,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh),
- 4, uh, strlen(uh),
- 5, entry->userinfo,
- strlen(entry->userinfo),
- 6, channels->data,
- channels->len,
- 7, mode, 4,
- 8, idle, 4);
- else
- packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, ident, 6,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh),
- 4, uh, strlen(uh),
- 5, entry->userinfo,
- strlen(entry->userinfo),
- 7, mode, 4,
- 8, idle, 4);
-
+ packet =
+ silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
+ status, ident, 8,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh),
+ 4, uh, strlen(uh),
+ 5, entry->userinfo,
+ strlen(entry->userinfo),
+ 6, channels ? channels->data : NULL,
+ channels ? channels->len : 0,
+ 7, mode, 4,
+ 8, idle, 4,
+ 9, fingerprint,
+ fingerprint ? 20 : 0);
+
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
0, packet->data, packet->len, FALSE);
uint16 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_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
/* Send WHOIS command to our router */
continue;
old_ident = silc_command_get_ident(cmd->payload);
- silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ silc_command_set_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
/* Send WHOWAS command */
uint16 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_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
/* Send WHOWAS command to our router */
uint16 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_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
/* Send IDENTIFY command to our router */
if (nick[i] == '?') return TRUE;
if (nick[i] == ',') return TRUE;
if (nick[i] == '@') return TRUE;
+ if (nick[i] == ':') return TRUE;
+ if (nick[i] == '/') return TRUE;
+ if (nick[i] == '[') return TRUE;
+ if (nick[i] == '[') return TRUE;
+ if (nick[i] == '(') return TRUE;
+ if (nick[i] == ')') return TRUE;
+ if (nick[i] == '{') return TRUE;
+ if (nick[i] == '}') return TRUE;
}
return FALSE;
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
SilcServer server = cmd->server;
- SilcBuffer packet, nidp, oidp;
+ SilcBuffer packet, nidp, oidp = NULL;
SilcClientID *new_id;
char *nick;
uint16 ident = silc_command_get_ident(cmd->payload);
if (strlen(nick) > 128)
nick[128] = '\0';
+ /* Check for same nickname */
+ if (!strcmp(client->nickname, nick)) {
+ nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ goto send_reply;
+ }
+
/* Create new Client ID */
while (!silc_id_create_client_id(cmd->server, cmd->server->id,
cmd->server->rng,
oidp->data, oidp->len,
nidp->data, nidp->len);
+ send_reply:
/* Send the new Client ID as reply command back to client */
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
SILC_STATUS_OK, ident, 1,
silc_buffer_free(packet);
silc_buffer_free(nidp);
- silc_buffer_free(oidp);
+ if (oidp)
+ silc_buffer_free(oidp);
out:
silc_server_command_free(cmd);
if (i >= 1)
status = SILC_STATUS_LIST_ITEM;
- if (i == lch_count - 1 && gch_count)
- break;
- if (lch_count > 1 && i == lch_count - 1)
+ if (lch_count > 1 && i == lch_count - 1 && !gch_count)
status = SILC_STATUS_LIST_END;
idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
uint32 lch_count = 0, gch_count = 0;
- SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 2);
+ SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
+
+ /* If we are normal server, send the command to router, since we
+ want to know all channels in the network. */
+ if (!cmd->pending && server->server_type == SILC_SERVER &&
+ !server->standalone) {
+ SilcBuffer tmpbuf;
+ uint16 old_ident;
+
+ old_ident = silc_command_get_ident(cmd->payload);
+ silc_command_set_ident(cmd->payload, ++server->cmd_ident);
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+ silc_server_packet_send(server, 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_LIST,
+ silc_command_get_ident(cmd->payload),
+ silc_server_command_destructor,
+ silc_server_command_list,
+ silc_server_command_dup(cmd));
+ cmd->pending = TRUE;
+ silc_command_set_ident(cmd->payload, old_ident);
+ silc_buffer_free(tmpbuf);
+ return;
+ }
/* Get Channel ID */
tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
lchannels = silc_idlist_get_channels(server->local_list, channel_id,
&lch_count);
- /* Get the channels from global list if we are router */
- if (server->server_type != SILC_SERVER)
- gchannels = silc_idlist_get_channels(server->global_list, channel_id,
- &gch_count);
+ /* Get the channels from global list */
+ gchannels = silc_idlist_get_channels(server->global_list, channel_id,
+ &gch_count);
/* Send the reply */
silc_server_command_list_send_reply(cmd, lchannels, lch_count,
uint16 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_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
silc_server_packet_send(server, entry->connection,
uint16 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_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
silc_server_packet_send(server, server->router->connection,
goto out;
old_ident = silc_command_get_ident(cmd->payload);
- silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ silc_command_set_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
/* Send JOIN command to our router */
uint16 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_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
silc_server_packet_send(server, entry->connection,
uint16 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_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
silc_server_packet_send(server, server->router->connection,
!cmd->pending) {
SilcBuffer tmpbuf;
- silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ silc_command_set_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
/* Send USERS command */
goto out;
old_ident = silc_command_get_ident(cmd->payload);
- silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ silc_command_set_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
silc_server_packet_send(server, dest_sock,
uint16 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_ident(cmd->payload, ++server->cmd_ident);
tmpbuf = silc_command_payload_encode_payload(cmd->payload);
silc_server_packet_send(server, server->router->connection,
SILC_SERVER_CMD_REPLY(join, JOIN),
SILC_SERVER_CMD_REPLY(users, USERS),
SILC_SERVER_CMD_REPLY(getkey, GETKEY),
+ SILC_SERVER_CMD_REPLY(list, LIST),
{ NULL, 0 },
};
/* We don't have that server anywhere, add it. */
channel = silc_idlist_add_channel(server->global_list, strdup(name),
SILC_CHANNEL_MODE_NONE, channel_id,
- server->router->connection,
+ server->router,
NULL, NULL);
if (!channel) {
silc_free(channel_id);
}
out:
- SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
- SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
+ SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
+ SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY);
if (idp)
silc_id_payload_free(idp);
silc_free(client_id);
silc_pkcs_public_key_free(public_key);
silc_server_command_reply_free(cmd);
}
+
+SILC_SERVER_CMD_REPLY_FUNC(list)
+{
+ SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+ SilcServer server = cmd->server;
+ SilcCommandStatus status;
+ SilcChannelID *channel_id = NULL;
+ SilcChannelEntry channel;
+ uint32 len;
+ unsigned char *tmp, *name, *topic;
+ uint32 usercount = 0;
+
+ COMMAND_CHECK_STATUS_LIST;
+
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+ channel_id = silc_id_payload_parse_id(tmp, len);
+ if (!channel_id)
+ goto out;
+
+ name = silc_argument_get_arg_type(cmd->args, 3, NULL);
+ topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
+ tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
+ if (tmp)
+ SILC_GET32_MSB(usercount, tmp);
+
+ /* Add the channel entry if we do not have it already */
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel)
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel) {
+ /* If router did not find such Channel ID in its lists then this must
+ be bogus channel or some router in the net is buggy. */
+ if (server->server_type != SILC_SERVER)
+ goto out;
+
+ channel = silc_idlist_add_channel(server->global_list, strdup(name),
+ SILC_CHANNEL_MODE_NONE, channel_id,
+ server->router,
+ NULL, NULL);
+ if (!channel)
+ goto out;
+ channel_id = NULL;
+ }
+
+ if (topic) {
+ silc_free(channel->topic);
+ channel->topic = strdup(topic);
+ }
+
+ /* Pending callbacks are not executed if this was an list entry */
+ if (status != SILC_STATUS_OK &&
+ status != SILC_STATUS_LIST_END) {
+ silc_server_command_reply_free(cmd);
+ return;
+ }
+
+ out:
+ SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
+ SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY);
+ silc_free(channel_id);
+ silc_server_command_reply_free(cmd);
+}
SILC_SERVER_CMD_REPLY_FUNC(join);
SILC_SERVER_CMD_REPLY_FUNC(users);
SILC_SERVER_CMD_REPLY_FUNC(getkey);
+SILC_SERVER_CMD_REPLY_FUNC(list);
#endif
data->psn_receive = idata->psn_receive;
data->hash = idata->hash;
data->public_key = idata->public_key;
+ memcpy(data->fingerprint, idata->fingerprint, sizeof(data->fingerprint));
data->rekey = idata->rekey;
data->last_receive = idata->last_receive;
data->last_sent = idata->last_sent;
/* Public key */
SilcPublicKey public_key;
+ unsigned char fingerprint[20];
/* Re-key context */
SilcServerRekey rekey;
/* Sets the negotiated key material into use for particular connection. */
-int silc_server_protocol_ke_set_keys(SilcSKE ske,
+int silc_server_protocol_ke_set_keys(SilcServer server,
+ SilcSKE ske,
SilcSocketConnection sock,
SilcSKEKeyMaterial *keymat,
SilcCipher cipher,
/* Save the remote host's public key */
silc_pkcs_public_key_decode(ske->ke1_payload->pk_data,
ske->ke1_payload->pk_len, &idata->public_key);
+ if (ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL)
+ silc_hash_make(server->sha1hash, ske->ke1_payload->pk_data,
+ ske->ke1_payload->pk_len, idata->fingerprint);
sock->user_data = (void *)conn_data;
/* Prototypes */
void silc_server_protocols_register(void);
void silc_server_protocols_unregister(void);
-int silc_server_protocol_ke_set_keys(SilcSKE ske,
+int silc_server_protocol_ke_set_keys(SilcServer server,
+ SilcSKE ske,
SilcSocketConnection sock,
SilcSKEKeyMaterial *keymat,
SilcCipher cipher,
/* We now have the key material as the result of the key exchange
protocol. Take the key material into use. Free the raw key material
as soon as we've set them into use. */
- if (!silc_server_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
+ if (!silc_server_protocol_ke_set_keys(server, ctx->ske,
+ ctx->sock, ctx->keymat,
ctx->ske->prop->cipher,
ctx->ske->prop->pkcs,
ctx->ske->prop->hash,
/* We now have the key material as the result of the key exchange
protocol. Take the key material into use. Free the raw key material
as soon as we've set them into use. */
- if (!silc_server_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
+ if (!silc_server_protocol_ke_set_keys(server, ctx->ske,
+ ctx->sock, ctx->keymat,
ctx->ske->prop->cipher,
ctx->ske->prop->pkcs,
ctx->ske->prop->hash,
become invalid now as well. */
if (user_data->id)
silc_server_remove_clients_by_server(server, user_data, TRUE);
+ if (server->server_type == SILC_SERVER)
+ silc_server_remove_channels_by_server(server, user_data);
} else {
/* Update the client entries of this server to the new backup
router. This also removes the clients that *really* was owned
silc_server_update_clients_by_server(server, user_data, backup_router,
TRUE, TRUE);
silc_server_update_servers_by_server(server, user_data, backup_router);
+ if (server->server_type == SILC_SERVER)
+ silc_server_update_channels_by_server(server, user_data,
+ backup_router);
}
/* Free the server entry */
&channel_ids, creation_time);
/* Get channels and channel users in global list */
- silc_server_announce_get_channels(server, server->global_list,
- &channels, &channel_users,
- &channel_users_modes,
- &channel_users_modes_c,
- &channel_ids, creation_time);
+ if (server->server_type != SILC_SERVER)
+ silc_server_announce_get_channels(server, server->global_list,
+ &channels, &channel_users,
+ &channel_users_modes,
+ &channel_users_modes_c,
+ &channel_ids, creation_time);
if (channels) {
silc_buffer_push(channels, channels->data - channels->head);
server->backup->servers[i].local = local;
memset(server->backup->servers[i].ip.data, 0,
sizeof(server->backup->servers[i].ip.data));
- silc_net_addr2bin_ne(ip, server->backup->servers[i].ip.data,
- sizeof(server->backup->servers[i].ip.data));
+ silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
+ sizeof(server->backup->servers[i].ip.data));
//server->backup->servers[i].port = port;
return;
}
server->backup->servers[i].local = local;
memset(server->backup->servers[i].ip.data, 0,
sizeof(server->backup->servers[i].ip.data));
- silc_net_addr2bin_ne(ip, server->backup->servers[i].ip.data,
- sizeof(server->backup->servers[i].ip.data));
+ silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
+ sizeof(server->backup->servers[i].ip.data));
//server->backup->servers[i].port = server_id->port;
server->backup->servers_count++;
}
server->router);
silc_server_update_clients_by_server(server, ctx->sock->user_data,
server->router, TRUE, FALSE);
+ if (server->server_type == SILC_SERVER)
+ silc_server_update_channels_by_server(server, ctx->sock->user_data,
+ server->router);
packet = silc_buffer_alloc(2);
silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
silc_server_update_servers_by_server(server, backup_router, router);
silc_server_update_clients_by_server(server, backup_router,
router, TRUE, FALSE);
- silc_server_backup_replaced_del(server, backup_router);
+ if (server->server_type == SILC_SERVER)
+ silc_server_update_channels_by_server(server, backup_router, router);
+ silc_server_backup_replaced_del(server, backup_router);
silc_server_backup_add(server, backup_router,
ctx->sock->ip, ctx->sock->port,
backup_router->server_type != SILC_ROUTER ?
}
}
+/* Removes channels that are from `from. */
+
+void silc_server_remove_channels_by_server(SilcServer server,
+ SilcServerEntry from)
+{
+ SilcIDCacheList list = NULL;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcChannelEntry channel = NULL;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ if (silc_idcache_get_all(server->global_list->channels, &list)) {
+ if (silc_idcache_list_first(list, &id_cache)) {
+ while (id_cache) {
+ channel = (SilcChannelEntry)id_cache->context;
+ if (channel->router == from)
+ silc_idlist_del_channel(server->global_list, channel);
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ }
+ silc_idcache_list_free(list);
+ }
+}
+
+/* Updates channels that are from `from' to be originated from `to'. */
+
+void silc_server_update_channels_by_server(SilcServer server,
+ SilcServerEntry from,
+ SilcServerEntry to)
+{
+ SilcIDCacheList list = NULL;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcChannelEntry channel = NULL;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ if (silc_idcache_get_all(server->global_list->channels, &list)) {
+ if (silc_idcache_list_first(list, &id_cache)) {
+ while (id_cache) {
+ channel = (SilcChannelEntry)id_cache->context;
+ if (channel->router == from)
+ channel->router = to;
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ }
+ silc_idcache_list_free(list);
+ }
+}
+
/* Checks whether given channel has global users. If it does this returns
TRUE and FALSE if there is only locally connected clients on the channel. */
SilcServerEntry from,
SilcServerEntry to);
+/* Removes channels that are from `from. */
+void silc_server_remove_channels_by_server(SilcServer server,
+ SilcServerEntry from);
+
+/* Updates channels that are from `from' to be originated from `to'. */
+void silc_server_update_channels_by_server(SilcServer server,
+ SilcServerEntry from,
+ SilcServerEntry to);
+
/* Checks whether given channel has global users. If it does this returns
TRUE and FALSE if there is only locally connected clients on the channel. */
bool silc_server_channel_has_global(SilcChannelEntry channel);
/* Create the ID */
/* XXX Does not support IPv6 */
- SILC_PUT32_MSB(server.sin_addr.s_addr, (*new_id)->ip.data);
+ memcpy((*new_id)->ip.data, &server.sin_addr.s_addr, 4);
(*new_id)->ip.data_len = 4;
(*new_id)->port = server.sin_port;
(*new_id)->rnd = silc_rng_get_rn16(rng);
silc_debug = TRUE;
silc_debug_hexdump = TRUE;
silc_log_set_debug_string(optarg);
+#ifndef SILC_DEBUG
+ fprintf(stdout,
+ "Run-time debugging is not enabled. To enable it recompile\n"
+ "the server with --enable-debug configuration option.\n");
+#endif
break;
case 'f':
config_file = strdup(optarg);
binary hash digest of the public key. The fingerprint MUST NOT
be sent if the server has not verified the proof of posession of
the corresponding private key. Server can do this during the
- SILC Key Exchange protocol.
+ SILC Key Exchange protocol. The <fingerprint> is SHA1 digest.
Status messages:
-
.ti 0
Table of Contents
2.3 SILC Packet Types ......................................... 7
2.3.1 SILC Packet Payloads ................................ 16
2.3.2 Generic payloads .................................... 16
- 2.3.2.1 ID Payload .................................. 16
- 2.3.2.2 Argument Payload ............................ 17
+ 2.3.2.1 ID Payload .................................. 17
+ 2.3.2.2 Argument Payload ............................ 18
2.3.2.3 Channel Payload ............................. 18
2.3.2.4 Public Key Payload .......................... 19
- 2.3.3 Disconnect Payload .................................. 19
- 2.3.4 Success Payload ..................................... 19
- 2.3.5 Failure Payload ..................................... 20
- 2.3.6 Reject Payload ...................................... 21
+ 2.3.3 Disconnect Payload .................................. 20
+ 2.3.4 Success Payload ..................................... 21
+ 2.3.5 Failure Payload ..................................... 21
+ 2.3.6 Reject Payload ...................................... 22
2.3.7 Notify Payload ...................................... 22
- 2.3.8 Error Payload ....................................... 21
- 2.3.9 Channel Message Payload ............................. 28
- 2.3.10 Channel Key Payload ................................ 31
- 2.3.11 Private Message Payload ............................ 33
- 2.3.12 Private Message Key Payload ........................ 34
- 2.3.13 Command Payload .................................... 36
- 2.3.14 Command Reply Payload .............................. 37
- 2.3.15 Connection Auth Request Payload .................... 37
- 2.3.16 New ID Payload ..................................... 38
- 2.3.17 New Client Payload ................................. 39
- 2.3.18 New Server Payload ................................. 40
- 2.3.19 New Channel Payload ................................ 41
- 2.3.20 Key Agreement Payload .............................. 42
- 2.3.21 Resume Router Payload .............................. 43
- 2.3.22 File Transfer Payload .............................. 43
- 2.4 SILC ID Types ............................................. 44
- 2.5 Packet Encryption And Decryption .......................... 44
- 2.5.1 Normal Packet Encryption And Decryption ............. 45
- 2.5.2 Channel Message Encryption And Decryption ........... 45
- 2.5.3 Private Message Encryption And Decryption ........... 46
- 2.6 Packet MAC Generation ..................................... 47
- 2.7 Packet Padding Generation ................................. 47
- 2.8 Packet Compression ........................................ 48
- 2.9 Packet Sending ............................................ 48
- 2.10 Packet Reception ......................................... 49
- 2.11 Packet Routing ........................................... 49
- 2.12 Packet Broadcasting ...................................... 50
-3 Security Considerations ....................................... 50
-4 References .................................................... 50
-5 Author's Address .............................................. 52
+ 2.3.8 Error Payload ....................................... 28
+ 2.3.9 Channel Message Payload ............................. 29
+ 2.3.10 Channel Key Payload ................................ 32
+ 2.3.11 Private Message Payload ............................ 34
+ 2.3.12 Private Message Key Payload ........................ 35
+ 2.3.13 Command Payload .................................... 37
+ 2.3.14 Command Reply Payload .............................. 38
+ 2.3.15 Connection Auth Request Payload .................... 38
+ 2.3.16 New ID Payload ..................................... 39
+ 2.3.17 New Client Payload ................................. 40
+ 2.3.18 New Server Payload ................................. 41
+ 2.3.19 New Channel Payload ................................ 42
+ 2.3.20 Key Agreement Payload .............................. 43
+ 2.3.21 Resume Router Payload .............................. 44
+ 2.3.22 File Transfer Payload .............................. 44
+ 2.4 SILC ID Types ............................................. 46
+ 2.5 Packet Encryption And Decryption .......................... 46
+ 2.5.1 Normal Packet Encryption And Decryption ............. 46
+ 2.5.2 Channel Message Encryption And Decryption ........... 47
+ 2.5.3 Private Message Encryption And Decryption ........... 48
+ 2.6 Packet MAC Generation ..................................... 48
+ 2.7 Packet Padding Generation ................................. 49
+ 2.8 Packet Compression ........................................ 50
+ 2.9 Packet Sending ............................................ 50
+ 2.10 Packet Reception ......................................... 51
+ 2.11 Packet Routing ........................................... 51
+ 2.12 Packet Broadcasting ...................................... 52
+3 Security Considerations ....................................... 53
+4 References .................................................... 53
+5 Author's Address .............................................. 54
.ti 0
List of Figures
Payload
+
+
13 SILC_PACKET_KEY_EXCHANGE
This packet is used to start SILC Key Exchange Protocol,
This payload can be used to send an ID. ID's are variable in length
thus this payload provides a way to send variable length ID's.
-
-
-
-
-
-
-
-
-
-
-
The following diagram represents the ID Payload.
.in 5
the packet payload needing the arguments. Incorrect amount of argument
payloads MUST cause rejection of the packet.
+
+
+
+
+
+
The following diagram represents the Argument Payload.
.in 5
The following diagram represents the Channel Payload.
+
+
+
+
+
+
+
+
+
+
.in 5
.nf
1 2 3
The following diagram represents the Public Key Payload.
+
+
+
.in 5
.nf
1 2 3
not be sent in any other packet type. The following diagram represents
the Notify Payload.
+
+
+
.in 5
.nf
1 2 3
diagram represents the Private Message Payload.
+
+
+
+
+
+
.in 5
.nf
1 2 3
.in 3
+
+
.ti 0
2.4 SILC ID Types
this ID in [SILC1].
.in 3
+When encoding different IDs into the ID Payload, all fields are always
+in MSB first order. The IP address, port, and/or the random number
+are encoded in the MSB first order.
+
.ti 0
2.5 Packet Encryption And Decryption
return TRUE;
}
+/* Callback called when error has occurred during connecting to the server.
+ The `connect' client operation will be called. */
+
+SILC_TASK_CALLBACK(silc_client_connect_failure)
+{
+ SilcClientKEInternalContext *ctx =
+ (SilcClientKEInternalContext *)context;
+ SilcClient client = (SilcClient)ctx->client;
+
+ client->ops->connect(client, ctx->sock->user_data, FALSE);
+ silc_free(ctx);
+}
+
/* Start of the connection to the remote server. This is called after
succesful TCP/IP connection has been established to the remote host. */
silc_socket_free(ctx->sock);
/* Notify application of failure */
- client->ops->connect(client, ctx->sock->user_data, FALSE);
- silc_free(ctx);
+ silc_schedule_task_add(client->schedule, ctx->sock->sock,
+ silc_client_connect_failure, ctx,
+ 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
return;
}
silc_socket_free(ctx->sock);
/* Notify application of failure */
- client->ops->connect(client, ctx->sock->user_data, FALSE);
- silc_free(ctx);
+ silc_schedule_task_add(client->schedule, ctx->sock->sock,
+ silc_client_connect_failure, ctx,
+ 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
return;
}
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
int connecting = FALSE;
+ SilcClientID *client_id = silc_id_payload_get_id(idp);
SilcBuffer sidp;
if (!conn->local_entry)
/* Delete old ID from ID cache */
if (conn->local_id) {
+ /* Check whether they are different */
+ if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
+ silc_free(client_id);
+ return;
+ }
+
silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
silc_free(conn->local_id);
}
if (conn->local_id_data)
silc_free(conn->local_id_data);
- conn->local_id = silc_id_payload_get_id(idp);
+ conn->local_id = client_id;
conn->local_id_data = silc_id_payload_get_data(idp);
conn->local_id_data_len = silc_id_payload_get_len(idp);;
silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
(void *)conn->local_entry, FALSE);
- /* Issue INFO command to fetch the real server name and server information
- and other stuff. */
- sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
- silc_client_send_command(client, conn, SILC_COMMAND_INFO,
- ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
- silc_buffer_free(sidp);
+ if (connecting) {
+ /* Issue INFO comqmand to fetch the real server name and server information
+ and other stuff. */
+ sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
+ silc_client_send_command(client, conn, SILC_COMMAND_INFO,
+ ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
+ silc_buffer_free(sidp);
- /* Notify application of successful connection. We do it here now that
- we've received the Client ID and are allowed to send traffic. */
- if (connecting)
+ /* Notify application of successful connection. We do it here now that
+ we've received the Client ID and are allowed to send traffic. */
client->ops->connect(client, conn, TRUE);
+ }
}
/* Processed received Channel ID for a channel. This is called when client
client_entry->status |= SILC_CLIENT_STATUS_RESOLVING;
silc_client_notify_by_server_resolve(client, conn, packet, client_id);
goto out;
+ } else {
+ if (client_entry != conn->local_entry)
+ silc_client_nickname_format(client, conn, client_entry);
}
/* Get Channel ID */
if (!client_entry2) {
silc_client_notify_by_server_resolve(client, conn, packet, client_id);
goto out;
+ } else {
+ if (client_entry2 != conn->local_entry)
+ silc_client_nickname_format(client, conn, client_entry2);
}
/* Remove the old from cache */
silc_client_command_free(cmd);
}
+/* Pending callbcak that will be called after the NICK command was
+ replied by the server. This sets the nickname if there were no
+ errors. */
+
+SILC_CLIENT_CMD_FUNC(nick_change)
+{
+ SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+ SilcClientConnection conn = cmd->conn;
+ SilcClientCommandReplyContext reply =
+ (SilcClientCommandReplyContext)context2;
+ SilcCommandStatus status;
+
+ SILC_GET16_MSB(status, silc_argument_get_arg_type(reply->args, 1, NULL));
+ if (status == SILC_STATUS_OK) {
+ /* Set the nickname */
+ if (conn->nickname)
+ silc_free(conn->nickname);
+ conn->nickname = strdup(cmd->argv[1]);
+ }
+
+ silc_client_command_free(cmd);
+}
+
/* Command NICK. Shows current nickname/sets new nickname on current
window. */
if (cmd->argv_lens[1] > 128)
cmd->argv_lens[1] = 128;
- /* Set new nickname */
+ /* Send the NICK command */
buffer = silc_command_payload_encode(SILC_COMMAND_NICK, 1,
&cmd->argv[1],
&cmd->argv_lens[1],
SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
- if (conn->nickname)
- silc_free(conn->nickname);
- conn->nickname = strdup(cmd->argv[1]);
+
+ /* Register pending callback that will actually set the new nickname
+ if there were no errors returned by the server. */
+ silc_client_command_pending(conn, SILC_COMMAND_NICK,
+ cmd->conn->cmd_ident,
+ silc_client_command_destructor,
+ silc_client_command_nick_change,
+ silc_client_command_dup(cmd));
+ cmd->pending = 1;
/* Notify application */
COMMAND;
conn->ping[i].start_time = time(NULL);
conn->ping[i].dest_id = id;
conn->ping[i].dest_name = strdup(conn->remote_host);
- conn->ping_count++;
break;
}
}
/* Notify application */
if (!cmd->callback)
COMMAND_REPLY((ARGS, client_entry, nickname, username, realname,
- channels, mode, idle));
+ channels, mode, idle, fingerprint));
if (channels)
silc_buffer_free(channels);
silc_client_receive_new_id(cmd->client, cmd->sock, idp);
/* Notify application */
+ SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK);
COMMAND_REPLY((ARGS, conn->local_entry));
+ SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_NICK);
+ silc_client_command_reply_free(cmd);
+ return;
out:
SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_NICK);
len = 0;
for (i = 0; i < clients_count; i++)
- if (clients[i]->valid)
+ if (clients[i]->valid && clients[i] != client_entry)
len++;
if (!len)
return;
SILC_LOG_DEBUG(("Start"));
if (ske->status != SILC_SKE_STATUS_OK) {
- if (ske->status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
- client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
- "Received unsupported server %s public key",
- ctx->sock->hostname);
- } else if (ske->status == SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED) {
- client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
- "Remote host did not send its public key, even though "
- "it must send it");
- } else {
- client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
- "Error during key exchange protocol with server %s",
- ctx->sock->hostname);
- }
-
+ /* Call failure client operation */
+ client->ops->failure(client, conn, protocol, (void *)ske->status);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute(protocol, client->schedule, 0, 0);
return;
/* Decrypt the payload */
ret = silc_channel_message_payload_decrypt(buffer->data, buffer->len,
- cipher, hmac);
+ cipher, hmac);
if (ret == FALSE)
return NULL;
typedef uint16 SilcIdType;
/* The SILC ID Types */
-#define SILC_ID_NONE 0
-#define SILC_ID_SERVER 1
-#define SILC_ID_CLIENT 2
-#define SILC_ID_CHANNEL 3
+#define SILC_ID_NONE 0
+#define SILC_ID_SERVER 1
+#define SILC_ID_CLIENT 2
+#define SILC_ID_CHANNEL 3
/***/
/* The ID Lenghts. These are IPv4 based and should be noted if used directly
&new->message_len),
SILC_STR_END);
if (ret == -1) {
- SILC_LOG_ERROR(("Incorrect private message payload"));
+ SILC_LOG_DEBUG(("Incorrect private message payload"));
goto err;
}
if ((new->message_len < 1 || new->message_len > buffer->len)) {
- SILC_LOG_ERROR(("Incorrect private message payload in packet, "
+ SILC_LOG_DEBUG(("Incorrect private message payload in packet, "
"packet dropped"));
goto err;
}
char *silc_hash_fingerprint(SilcHash hash, const unsigned char *data,
uint32 data_len)
{
- char fingerprint[64], *cp;
unsigned char h[32];
- int i;
if (!hash)
silc_hash_alloc("sha1", &hash);
silc_hash_make(hash, data, data_len, h);
-
- memset(fingerprint, 0, sizeof(fingerprint));
- cp = fingerprint;
- for (i = 0; i < hash->hash->hash_len; i++) {
- snprintf(cp, sizeof(fingerprint), "%02X", h[i]);
- cp += 2;
-
- if ((i + 1) % 2 == 0)
- snprintf(cp++, sizeof(fingerprint), " ");
-
- if ((i + 1) % 10 == 0)
- snprintf(cp++, sizeof(fingerprint), " ");
- }
- i--;
- if ((i + 1) % 2 == 0)
- cp[-2] = 0;
- if ((i + 1) % 10 == 0)
- cp[-1] = 0;
-
- return strdup(fingerprint);
+ return silc_fingerprint(h, hash->hash->hash_len);
}
static const char vo[]= "aeiouy";
return;
}
- if (debug_cb)
- {
- (*debug_cb)(file, function, line, string);
- silc_free(string);
- return;
- }
+ if (debug_cb) {
+ (*debug_cb)(file, function, line, string);
+ silc_free(string);
+ return;
+ }
fprintf(stderr, "%s:%d: %s\n", function, line, string);
fflush(stderr);
return;
}
- if (debug_hexdump_cb)
- {
- (*debug_hexdump_cb)(file, function, line, data_in, len, string);
- silc_free(string);
- return;
- }
+ if (debug_hexdump_cb) {
+ (*debug_hexdump_cb)(file, function, line, data_in, len, string);
+ silc_free(string);
+ return;
+ }
fprintf(stderr, "%s:%d: %s\n", function, line, string);
silc_free(string);
void silc_log_set_debug_string(const char *debug_string)
{
silc_free(silc_debug_string);
- if (strchr(debug_string, '(') &&
- strchr(debug_string, ')'))
+ if ((strchr(debug_string, '(') &&
+ strchr(debug_string, ')')) ||
+ strchr(debug_string, '$'))
silc_debug_string = strdup(debug_string);
else
silc_debug_string = silc_string_regexify(debug_string);
* DESCRIPTION
*
* Converts the IP number string from numbers-and-dots notation to
- * binary form.
- *
- ***/
-bool silc_net_addr2bin(const char *addr, void *bin, uint32 bin_len);
-
-/****f* silcutil/SilcNetAPI/silc_net_addr2bin_ne
- *
- * SYNOPSIS
- *
- * bool silc_net_addr2bin_ne(const char *addr, unsigned char *bin,
- * uint32 bin_len);
- *
- * DESCRIPTION
- *
- * Converts the IP number string from numbers-and-dots notation to
* binary form in network byte order.
*
***/
-bool silc_net_addr2bin_ne(const char *addr, unsigned char *bin,
- uint32 bin_len);
+bool silc_net_addr2bin(const char *addr, void *bin, uint32 bin_len);
/****f* silcutil/SilcNetAPI/silc_net_check_host_by_sock
*
if (server_id->ip.data_len > 4) {
} else {
- SILC_GET32_MSB(ipv4.s_addr, server_id->ip.data);
+ memcpy(&ipv4.s_addr, server_id->ip.data, 4);
strcat(rid, inet_ntoa(ipv4));
}
if (client_id->ip.data_len > 4) {
} else {
- SILC_GET32_MSB(ipv4.s_addr, client_id->ip.data);
+ memcpy(&ipv4.s_addr, client_id->ip.data, 4);
strcat(rid, inet_ntoa(ipv4));
}
if (channel_id->ip.data_len > 4) {
} else {
- SILC_GET32_MSB(ipv4.s_addr, channel_id->ip.data);
+ memcpy(&ipv4.s_addr, channel_id->ip.data, 4);
strcat(rid, inet_ntoa(ipv4));
}
return strdup(string);
}
+
+/* Creates fingerprint from data, usually used with SHA1 digests */
+
+char *silc_fingerprint(const unsigned char *data, uint32 data_len)
+{
+ char fingerprint[64], *cp;
+ int i;
+
+ memset(fingerprint, 0, sizeof(fingerprint));
+ cp = fingerprint;
+ for (i = 0; i < data_len; i++) {
+ snprintf(cp, sizeof(fingerprint), "%02X", data[i]);
+ cp += 2;
+
+ if ((i + 1) % 2 == 0)
+ snprintf(cp++, sizeof(fingerprint), " ");
+
+ if ((i + 1) % 10 == 0)
+ snprintf(cp++, sizeof(fingerprint), " ");
+ }
+ i--;
+ if ((i + 1) % 2 == 0)
+ cp[-2] = 0;
+ if ((i + 1) % 10 == 0)
+ cp[-1] = 0;
+
+ return strdup(fingerprint);
+}
char *silc_client_chumode(uint32 mode);
char *silc_client_chumode_char(uint32 mode);
int silc_gettimeofday(struct timeval *p);
+char *silc_fingerprint(const unsigned char *data, uint32 data_len);
#endif
memcpy(bin, (unsigned char *)&tmp.s_addr, 4);
return ret != 0;
}
-
-/* Converts the IP number string from numbers-and-dots notation to
- binary form in network byte order. */
-
-bool silc_net_addr2bin_ne(const char *addr, unsigned char *bin,
- uint32 bin_len)
-{
- struct in_addr tmp;
- int ret;
-
- ret = inet_aton(addr, &tmp);
-
- if (bin_len < 4)
- return FALSE;
-
- SILC_PUT32_MSB(tmp.s_addr, bin);
-
- return ret != 0;
-}
return ret != INADDR_NONE;
}
-/* Converts the IP number string from numbers-and-dots notation to
- binary form in network byte order. */
-
-bool silc_net_addr2bin_ne(const char *addr, unsigned char *bin,
- uint32 bin_len)
-{
- unsigned long ret;
-
- ret = inet_addr(addr);
-
- if (bin_len < 4)
- return FALSE;
-
- SILC_PUT32_MSB(ret, bin);
-
- return ret != INADDR_NONE;
-}
-
/* Set socket to non-blocking mode. */
int silc_net_set_socket_nonblock(int sock)
#include "silcincludes.h"
+/* XXX GNU regex may work on Win32 too!! */
+char *silc_string_regexify(const char *string)
+{
+ return strdup(string);
+}
+
+char *silc_string_regex_combine(const char *string1, const char *string2)
+{
+ return strdup(string1);
+}
+
+int silc_string_regex_match(const char *regex, const char *string)
+{
+ return TRUE;
+}
+
+int silc_string_match(const char *string1, const char *string2)
+{
+ return TRUE;
+}
+
#define FILETIME_1970 0x019db1ded53e8000
const BYTE DWLEN = sizeof(DWORD) * 8;
# SILC Distribution versions. Set here or give the version on the command
# line as argument.
#
-SILC_VERSION=0.6.1 # Base version
+SILC_VERSION=0.6.2 # Base version
#############################################################################
--- /dev/null
+SILC Optimizations:
+===================
+
+o Library
+
+ o There is currently three (3) allocations per packet in the
+ silc_packet_receive_process, which is used to process and
+ dispatch all packets in the packet queue to the parser callback
+ function. First allocation is for parse_ctx, second for the
+ SilcPacketContext, and third for packet->buffer where the actual
+ data is saved.
+
+ The parse_ctx allocation can be removed by adding it as a
+ structure to the SilcPacketContext. When the SilcPacketContext
+ is allocated there is space for the parse context already.
+
+ The silc_packet_context_alloc should have a free list of
+ packet contexts. If free packet context is found from the list
+ it is returned instead of allocating a new one. The library
+ could at first allocate them and save them to the free list
+ until enough contexts for smooth processing exists in the list.
+ This would remove a big allocation since the structure is
+ quite big, and even bigger if it would include the parse_ctx.
+
+ The packet->buffer can be optimized too if the SilcBuffer
+ interface would support free lists as well. Maybe such could
+ be done in the same way as for SilcPacketContext. The
+ silc_buffer_alloc would check free list before actually
+ allocating new memory. Since the packets in the SILC protocol
+ usually are about the same size (due to padding) it would be
+ easy to find suitable size buffer from the free list very
+ quickly.
+
+ These naturally cause the overal memory consumption to grow
+ but would take away many allocations that can be done several
+ times in a second.
+
+ o Move the actual file descriptor task callback (the callback that
+ handles the incoming data, outgoing data etc, that is implemnted
+ in server and client separately (silc_server_packet_process and
+ silc_client_packet_proces)) to the low level socket connection
+ handling routines, and create an interface where the application
+ can register a callbacks for incoming data, outoing data and EOF
+ receiving and maybe sending too, which the library will call
+ when necessary. This way we can move the data handling in one
+ place.
+
+o Server
+
+ o When processing the decrypted and parsed packet we call the
+ silc_server_packet_parse_type function. This function has a
+ huge switch statement. Replace this switch statment with pre-
+ defined table of function pointers where each of the slot
+ in the table represents the packet type (1 for packet type
+ value 1, 2 for value 2 and so on), and call the callback
+ found in the slot. In this case we can do one-to-one mapping
+ of packet types to correct function.
+
+ o Same optimizations could be done with notify packets which
+ has huge switch statement too. Same kind of table of notify
+ callbacks would be very easy to do, and achieve one-to-one
+ mapping of notify types.
+
+ o The parser callback in the server will add a timeout task for
+ all packets. It will require registering and allocating a
+ new task to the SilcSchedule. Maybe, at least, for server
+ and router packets the parser would be called immediately
+ instead of adding it to the scheduler with 0 timeout. It
+ should be analyzed too how slow the task registering process
+ actually is, and find out ways to optimize it.