+Tue Feb 4 22:53:26 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * NULL terminate allocated string in silc_buffer_strformat.
+ Affected file lib/silcutil/silcbuffmt.c.
+
+ * Rewrote the invite/ban list string handling in server to
+ use SilcBuffer instead. Affected files are silcd/command.c
+ and silcd/server_util.c.
+
+Mon Feb 3 14:43:52 CET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed double free in CMODE command when setting new HMAC
+ for channel. Affected file silcd/command.c.
+
+ * Added couple of missing memset's to zero sensitive memory.
+ Affected files silcd/command.c, lib/silcclient/command.c.
+
+Sun Jan 26 12:20:30 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed a double free in INVITE command error handling in
+ server. Affected file silcd/command.c.
+
+ * Added macros SILC_SWAB_[16|32] to swab byte order of
+ 16-bit and 32-bit unsigned integers. Affected file
+ lib/silcutil/silctypes.h.
+
+ * Use the SILC_SWAB_16 instead of htons() in server when
+ handling ports since the ports in structures are always
+ in little-endian order (regardless of platform). Affected
+ file silcd/serverid.c and silcd/server_backup.c.
+
+Tue Jan 21 17:18:04 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Send DISCONNECT in close admin command in server. Affected
+ file silcd/command.c.
+
+ * Check whether we are already connecting to a remote router
+ (in addition of checking whether we are already connected)
+ before creating new connection. Affected file silcd/server.c.
+
+Thu Jan 16 18:47:00 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added better compiler and compiler flags checking in
+ configure.
+
+ * Check that socket is valid after QoS is applied to data.
+ Affected file lib/silcutil/unix/silcunixsockconn.c.
+
+ * Make sure the socket connecetion is not closed to early
+ when closing connection in server. Also make sure the
+ connection is always closed after error in a protocol.
+ Affected file silcd/server.c.
+
+Wed Jan 15 11:03:36 CET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Removed --session and --dummy options from Irssi SILC Client.
+ -d option is available only if --enable-debug was given.
+ Affected files are irssi/src/silc/core/silc-core,
+ irssi/src/core/session.c and irssi/src/fe-text/silc.c.
+
+Tue Jan 14 12:25:09 CET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added silc_buffer_steal to steal the data from the buffer.
+ Affected file lib/silcutil/silcbuffer.h.
+
+Sat Jan 11 18:16:29 CET 2003 Giovanni Giacobbi <giovanni@giacobbi.net>
+
+ * Fixed server crash with double Primary block in config file.
+
+ Fixed also various memory leaks around the config file
+ parser. Affected files lib/silcutil/silcconfig.c,
+ silcd/serverconfig.c.
+
+ * Changed my nickname (Johnny Mnemonic) to my real name, this
+ means that bugs introduced by him were actually introduced
+ by me!
+
+Tue Jan 7 21:58:53 CET 2003 Jochen Eisinger <c0ffee@penguin-breeder.org>
+
+ * Don't display "foo appears as foo\nYou're now known as foo"
+ messages. Affected file irssi/src/silc/core/client_ops.c
+
+Tue Jan 7 20:08:15 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed error handling of invalid client entry when calling
+ commands in server. Fixes a crash. Affected file
+ silcd/command.c.
+
Thu Dec 26 14:19:29 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* Added some sanity checks in server for correctness of the
S: 53850 Lappeenranta
S: Finland
-N: Johnny Mnemonic
+N: Giovanni Giacobbi
+E: giovanni@giacobbi.net
E: johnny@themnemonic.org
-W: http://www.themnemonic.org/
-P: 1024D/34E2AB40 9AC6 1460 A5D0 4DB7 70D0 5DA5 C17F 50CD 34E2 AB40
+P: 1024D/B2D79FC1 6247 640C 1C90 1EE4 D800 E4E2 2D58 3DF1 B2D7 9FC1
+D: silcconfig, silclog, various patches around
D: RPM packages
-D: silclog, misc bugfixes
S: 35100 Padova
S: Italy
Quick Installation
==================
- To configure and compile SILC package give the comands:
+ To configure and compile SILC package give the commands:
./configure
make (or gmake)
/usr/local/silc/ directory. System wide configuration files are installed
into the /etc/silc/ directory.
+You may need to add the /usr/local/silc path to your PATH environment
+variable after the installation.
+
Some Configuration Options
==========================
TODO for SILC Server 1.0
========================
+ o INVITE and BAN notifys send the entire list as notify, but only the
+ added/removed info should be sent.
+
+ o The CMODE cipher & hmac change problem (#101).
+
o Fix CUMODE_CHANGE and CMODE_CHANGE for founder key things.
o 1.2 backup router support
Stuff that needs to be done in order to complete the Tooolkit Reference
Manual (Do these to 0.9.x).
- o Document the "notify" and "command_reply" client operations variable
- argument lists for all possible notify types and command replys.
-
o Write "Programming with Toolkit" document, describing how to build
Toolkit, how the build system works, where is everything, how
new (external) projects can be glued into Toolkit (use irssi as an
example), and how external projects can use Toolkit without gluing into
it (how to link etc), debugging, architecture, types, etc.
- o Write "Platform Implementations" document to describe what platforms
- Toolkit support, what has been implemented, what has not been, what
- works differently etc.
-
o Searching of predefined keywords, exact and partial matches (would be
nice).
of the modes require special privileges, such as channel operator
or channel founder privileges to work. The mode is added by
adding + before the option(s) and removed by adding - before the
-option(s). The following modes are available:
+option(s). The (*) mark below means that only founder may set/unset
+that mode. Other modes both channel operator and founder may manage.
+
+The following modes are available:
p Set/unset channel as private channel
s Set/unset channel as secret channel
- k Set/unset that channel uses private channel key
+ k Enable/disable channel private key usage (*)
i Set/unset channel as invite only channel
t Set/unset that only channel operator or
founder may set channel topic
m Set/unset user silencing. Normal users
- are not able to talk on channel. Only
- channel founder may set this mode
+ are not able to talk on channel. (*)
M Set/unset operator silencing. Operators
- are not able to talk on channel. Only
- channel founder may set this mode
+ are not able to talk on channel. (*)
l <limit> Set/unset channel's user limit
a <passphrase> Set/unset passphrase for channel that must
- be provided when joining to the channel.
- c <cipher> Set/unset channel's cipher
- h <hmac> Set/unset channel's hmac
+ be provided when joining to the channel. (*)
+ c <cipher> Set/unset channel's cipher (*)
+ h <hmac> Set/unset channel's hmac (*)
f [<pubkeyfile> <privkeyfile> [<privkey passphrase>]]
- Set/unset channel founder authentication.
+ Set/unset channel founder authentication. (*)
Channel founder may set this mode so that
if the client leaves the channel it can
claim the founder rights when it returns
require any arguments. If mode requires an argument then only
one mode can be set at once.
-See also: CUMODE, UMODE, JOIN
+When the +k (channel private key mode) mode is set the channel's
+default cipher and HMAC are not used. The private key (see /HELP KEY
+for help how to set the private key) defines the cipher and HMAC for
+the channel while +k mode is set. Also the +c and +h modes are ignored
+when channel private key is set.
+
+See also: CUMODE, UMODE, JOIN, KEY
Examples:
- /KILL myself -pubkey
+ /KILL myself -pubkey
- Kill yourself with nickname "myself" from network.
+ Kill yourself with nickname "myself" from network.
- /SILCOPER user
- /KILL someclient You have been killed
+ /SILCOPER user
+ /KILL someclient You have been killed
- Become SILC operator and kill client named
- "someclient", with comment "You have been killed".
+ Become SILC operator and kill client named
+ "someclient", with comment "You have been killed".
See also: OPER, SILCOPER
# define INADDR_NONE INADDR_BROADCAST
#endif
-union sockaddr_union {
+union irssi_sockaddr_union {
struct sockaddr sa;
struct sockaddr_in sin;
#ifdef HAVE_IPV6
#else
static
#endif
-void sin_set_ip(union sockaddr_union *so, const IPADDR *ip)
+void sin_set_ip(union irssi_sockaddr_union *so, const IPADDR *ip)
{
if (ip == NULL) {
#ifdef HAVE_IPV6
memcpy(&so->sin.sin_addr, &ip->ip, 4);
}
-void sin_get_ip(const union sockaddr_union *so, IPADDR *ip)
+void sin_get_ip(const union irssi_sockaddr_union *so, IPADDR *ip)
{
ip->family = so->sin.sin_family;
#else
static
#endif
-void sin_set_port(union sockaddr_union *so, int port)
+void sin_set_port(union irssi_sockaddr_union *so, int port)
{
#ifdef HAVE_IPV6
if (so->sin.sin_family == AF_INET6)
#else
static
#endif
-int sin_get_port(union sockaddr_union *so)
+int sin_get_port(union irssi_sockaddr_union *so)
{
#ifdef HAVE_IPV6
if (so->sin.sin_family == AF_INET6)
/* Connect to socket with ip address */
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
{
- union sockaddr_union so;
+ union irssi_sockaddr_union so;
int handle, ret, opt = 1;
if (my_ip != NULL && ip->family != my_ip->family) {
address. */
GIOChannel *net_listen(IPADDR *my_ip, int *port)
{
- union sockaddr_union so;
+ union irssi_sockaddr_union so;
int ret, handle, opt = 1;
socklen_t len;
/* Accept a connection on a socket */
GIOChannel *net_accept(GIOChannel *handle, IPADDR *addr, int *port)
{
- union sockaddr_union so;
+ union irssi_sockaddr_union so;
int ret;
socklen_t addrlen;
/* Get socket address/port */
int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
{
- union sockaddr_union so;
+ union irssi_sockaddr_union so;
socklen_t addrlen;
g_return_val_if_fail(handle != NULL, -1);
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
{
#ifdef HAVE_IPV6
- union sockaddr_union *so;
+ union irssi_sockaddr_union *so;
struct addrinfo hints, *ai, *ailist;
int ret, count;
#else
count = 0;
for (ai = ailist; ai != NULL && count < 2; ai = ai->ai_next) {
- so = (union sockaddr_union *) ai->ai_addr;
+ so = (union irssi_sockaddr_union *) ai->ai_addr;
if (ai->ai_family == AF_INET6 && ip6->family == 0) {
sin_get_ip(so, ip6);
void session_init(void)
{
static struct poptOption options[] = {
+#if 0 /* --session is not available in SILC Client */
{ "session", 0, POPT_ARG_STRING, &session_file, 0, "Used by /UPGRADE command", "PATH" },
+#endif
{ NULL, '\0', 0, NULL }
};
static struct poptOption options[] = {
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, version_options, 0, NULL, NULL },
POPT_AUTOHELP
- { "connect", 'c', POPT_ARG_STRING, &autocon_server, 0, "Automatically connect to server/ircnet", "SERVER" },
+ { "connect", 'c', POPT_ARG_STRING, &autocon_server, 0, "Automatically connect to server", "SERVER" },
{ "password", 'w', POPT_ARG_STRING, &autocon_password, 0, "Autoconnect password", "PASSWORD" },
{ "port", 'p', POPT_ARG_INT, &autocon_port, 0, "Autoconnect port", "PORT" },
{ "noconnect", '!', POPT_ARG_NONE, &no_autoconnect, 0, "Disable autoconnecting", NULL },
{
HISTORY_REC *history;
char *str, *add_history;
+ gint flags = (redir ? redir->flags : 0);
str = gui_entry_get_text(active_entry);
active_win->active_server,
active_win->active);
} else {
- if (redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN)
+ if (flags & ENTRY_REDIRECT_FLAG_HIDDEN && add_history) {
+ memset(add_history, 0, strlen(add_history));
g_free_and_null(add_history);
+ }
handle_entry_redirect(str);
+ if (flags & ENTRY_REDIRECT_FLAG_HIDDEN && str)
+ memset(str, 0, strlen(str));
}
if (add_history != NULL) {
int main(int argc, char **argv)
{
static struct poptOption options[] = {
+#if 0 /* --dummy is not available in SILC Client */
{ "dummy", 'd', POPT_ARG_NONE, &dummy, 0, "Use the dummy terminal mode", NULL },
+#endif
{ NULL, '\0', 0, NULL }
};
return;
nicks = nicklist_get_same(SERVER(server), client_entry->nickname);
- if (nicks != NULL) {
+ if ((nicks != NULL) &&
+ (strcmp(SERVER(server)->nick, client_entry->nickname))) {
char buf[512];
SilcClientEntry collider, old;
"List supported HMACs", NULL },
{ "list-pkcs", 0, POPT_ARG_NONE, NULL, 0,
"List supported PKCSs", NULL },
+#ifdef SILC_DEBUG
{ "debug", 'd', POPT_ARG_STRING, NULL, 0,
"Enable debugging", "STRING" },
+#endif /* SILC_DEBUG */
{ "create-key-pair", 'C', POPT_ARG_NONE, NULL, 0,
"Create new public key pair", NULL },
{ "pkcs", 0, POPT_ARG_STRING, &opt_pkcs, 0,
SILC_LOG_DEBUG(("Client entry is invalid"));
silc_server_command_free(timeout->ctx);
silc_free(timeout);
+ return;
}
/* Update access time */
if (!client) {
SILC_LOG_DEBUG(("Client entry is invalid"));
silc_server_command_free(ctx);
+ return;
}
timeout = silc_calloc(1, sizeof(*timeout));
silc_server_command_invite,
silc_server_command_dup(cmd));
cmd->pending = TRUE;
- silc_free(channel_id);
- silc_free(dest_id);
goto out;
}
channel->invite_list)),
SILC_STR_END);
silc_hash_table_list(channel->invite_list, &htl);
- while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
- if (type == 1)
- list = silc_argument_payload_encode_one(list, (char *)tmp2,
- strlen((char *)tmp2), type);
- else
- list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
- type);
- }
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
+ list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ type);
silc_hash_table_list_reset(&htl);
}
SILC_STR_END);
silc_hash_table_list(channel->invite_list, &htl);
- while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
- if (tmp_len == 1)
- invite_list = silc_argument_payload_encode_one(invite_list,
- (char *)reply,
- strlen((char *)reply),
- tmp_len);
- else
- invite_list = silc_argument_payload_encode_one(invite_list,
- reply->data,
- reply->len, tmp_len);
- }
+ while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
+ invite_list = silc_argument_payload_encode_one(invite_list,
+ reply->data,
+ reply->len, tmp_len);
silc_hash_table_list_reset(&htl);
}
SILC_STR_END);
silc_hash_table_list(channel->ban_list, &htl);
- while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
- if (tmp_len == 1)
- ban_list = silc_argument_payload_encode_one(ban_list,
- (char *)reply,
- strlen((char *)reply),
- tmp_len);
- else
- ban_list = silc_argument_payload_encode_one(ban_list,
- reply->data,
- reply->len, tmp_len);
- }
+ while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
+ ban_list = silc_argument_payload_encode_one(ban_list,
+ reply->data,
+ reply->len, tmp_len);
silc_hash_table_list_reset(&htl);
}
silc_buffer_free(ban_list);
out:
+ if (passphrase)
+ memset(passphrase, 0, strlen(passphrase));
silc_free(passphrase);
}
hmac = channel->hmac_name;
/* Delete old hmac and allocate default one */
- silc_hmac_free(channel->hmac);
if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
channel->ban_list)),
SILC_STR_END);
silc_hash_table_list(channel->ban_list, &htl);
- while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
- if (type == 1)
- list = silc_argument_payload_encode_one(list, (char *)tmp2,
- strlen((char *)tmp2), type);
- else
- list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
- type);
- }
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
+ list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ type);
silc_hash_table_list_reset(&htl);
}
/* Close the connection to the server */
sock = (SilcSocketConnection)server_entry->connection;
- /* If we shutdown primary router connection manually then don't trigger
- any reconnect or backup router connections, by setting the router
- to NULL here. */
+ server->backup_noswitch = TRUE;
if (server->router == server_entry) {
server->id_entry->router = NULL;
server->router = NULL;
server->standalone = TRUE;
}
- silc_server_free_sock_user_data(server, sock, NULL);
- silc_server_close_connection(server, sock);
-
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_BANNED_FROM_SERVER,
+ "Closed by administrator");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ server->backup_noswitch = FALSE;
+
out:
silc_server_command_free(cmd);
}
if (sock && ((sock->hostname && !strcasecmp(sock->hostname, hostname)) ||
(sock->ip && !strcasecmp(sock->ip, hostname)))
- && server->id->port == htons(port))
+ && server->id->port == SILC_SWAB_16(port))
break;
id_cache = NULL;
return NULL;
}
+ /* Make sure this client hasn't registered already */
+ if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ "Too many registrations");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ return NULL;
+ }
+
/* Parse incoming packet */
ret = silc_buffer_unformat(buffer,
SILC_STR_UI16_NSTRING_ALLOC(&username,
local = FALSE;
}
+ /* Make sure this server hasn't registered already */
+ if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ "Too many registrations");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ return NULL;
+ }
+
/* Parse the incoming packet */
ret = silc_buffer_unformat(buffer,
SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
server_entry = silc_idlist_find_server_by_id(server->local_list,
server_id, TRUE, NULL);
if (server_entry) {
- silc_idcache_del_by_context(server->local_list->servers, server_entry);
+ if (SILC_IS_LOCAL(server_entry)) {
+ silc_server_disconnect_remote(server, server_entry->connection,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ "Too many registrations");
+ if (((SilcSocketConnection)server_entry->connection)->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ } else {
+ silc_idcache_del_by_context(server->local_list->servers, server_entry);
+ }
} else {
server_entry = silc_idlist_find_server_by_id(server->global_list,
server_id, TRUE, NULL);
- if (server_entry)
- silc_idcache_del_by_context(server->global_list->servers, server_entry);
+ if (server_entry) {
+ if (SILC_IS_LOCAL(server_entry)) {
+ silc_server_disconnect_remote(server, server_entry->connection,
+ SILC_STATUS_ERR_OPERATION_ALLOWED,
+ "Too many registrations");
+ if (((SilcSocketConnection)server_entry->connection)->user_data)
+ silc_server_free_sock_user_data(server, server_entry->connection,
+ NULL);
+ } else {
+ silc_idcache_del_by_context(server->global_list->servers,
+ server_entry);
+ }
+ }
}
/* Update server entry */
idata->status |= SILC_IDLIST_STATUS_REGISTERED;
new_server->server_name = server_name;
new_server->id = server_id;
-
+
SILC_LOG_DEBUG(("New server id(%s)",
silc_id_render(server_id, SILC_ID_SERVER)));
{
if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
(SILC_IS_DISCONNECTED(sock) == FALSE)) {
+ SILC_LOG_DEBUG(("Purging ourgoing queue"));
server->stat.packets_sent++;
silc_packet_send(sock, TRUE);
SILC_UNSET_OUTBUF_PENDING(sock);
timeout. It expires as soon as the caller calls silc_server_run. This
task performs authentication protocol and key exchange with our
primary router. */
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
- (void *)server, 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_server_create_connections(server);
/* Add listener task to the scheduler. This task receives new connections
to the server. This task remains on the queue until the end of the
}
}
- /* Go through all configured routers after rehash */
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
- (void *)server, 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ /* Create connections after rehash */
+ silc_server_create_connections(server);
/* Check whether our router status has changed */
if (newconfig->servers) {
server->wait_backup = TRUE;
if (ptr->initiator) {
- /* Check whether we are connected to this host already */
+ /* Check whether we are connecting or connected to this host already */
if (silc_server_num_sockets_by_remote(server,
silc_net_is_ip(ptr->host) ?
ptr->host : NULL,
SILC_LOG_DEBUG(("We are already connected to this router"));
continue;
}
+ if (silc_server_num_sockets_by_remote(server,
+ silc_net_is_ip(ptr->host) ?
+ ptr->host : NULL,
+ silc_net_is_ip(ptr->host) ?
+ NULL : ptr->host, ptr->port,
+ SILC_SOCKET_TYPE_UNKNOWN)) {
+ SILC_LOG_DEBUG(("We are already connecting to this router"));
+ continue;
+ }
/* Allocate connection object for hold connection specific stuff. */
sconn = silc_calloc(1, sizeof(*sconn));
else
silc_server_free_sock_user_data(server, sock, NULL);
} else if (server->router_conn && server->router_conn->sock == sock &&
- !server->router && server->standalone)
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
- server, 1, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ !server->router && server->standalone) {
+ silc_server_create_connections(server);
+ }
silc_server_close_connection(server, sock);
return;
if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router)
server->backup_noswitch = TRUE;
+ SILC_SET_DISCONNECTING(sock);
if (sock->user_data)
silc_server_free_sock_user_data(server, sock, NULL);
silc_server_close_connection(server, sock);
if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router)
server->backup_noswitch = TRUE;
+ SILC_SET_DISCONNECTING(sock);
if (sock->user_data)
silc_server_free_sock_user_data(server, sock, NULL);
silc_server_close_connection(server, sock);
message ? message : ""));
silc_free(message);
+ /* Do not switch to backup in case of error */
+ server->backup_noswitch = (status == SILC_STATUS_OK ? FALSE : TRUE);
+
/* Handle the disconnection from our end too */
+ SILC_SET_DISCONNECTING(sock);
if (sock->user_data && SILC_IS_LOCAL(sock->user_data))
silc_server_free_sock_user_data(server, sock, NULL);
silc_server_close_connection(server, sock);
+ server->backup_noswitch = FALSE;
}
break;
if (!server->sockets[sock->sock] && SILC_IS_DISCONNECTED(sock)) {
silc_schedule_unset_listen_fd(server->schedule, sock->sock);
silc_schedule_task_del_by_fd(server->schedule, sock->sock);
+ silc_net_close_connection(sock->sock);
silc_schedule_task_add(server->schedule, sock->sock,
silc_server_close_connection_final,
(void *)sock, 0, 1, SILC_TASK_TIMEOUT,
/* Unregister all tasks */
silc_schedule_task_del_by_fd(server->schedule, sock->sock);
- /* Close the actual connection */
- silc_net_close_connection(sock->sock);
server->sockets[sock->sock] = NULL;
/* If sock->user_data is NULL then we'll check for active protocols
}
}
+ /* Close the actual connection */
+ silc_net_close_connection(sock->sock);
+
/* We won't listen for this connection anymore */
silc_schedule_unset_listen_fd(server->schedule, sock->sock);
char *cp;
int len;
- if (!sock || SILC_IS_DISCONNECTED(sock))
+ if (!sock)
+ return;
+
+ if (SILC_IS_DISCONNECTED(sock)) {
+ silc_server_close_connection(server, sock);
return;
+ }
memset(buf, 0, sizeof(buf));
va_start(ap, status);
if (server->router == user_data) {
/* Check whether we have a backup router connection */
if (!backup_router || backup_router == user_data) {
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
- server, 1, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
-
+ silc_server_create_connections(server);
server->id_entry->router = NULL;
server->router = NULL;
server->standalone = TRUE;
} else if (server->server_type == SILC_SERVER &&
sock->type == SILC_SOCKET_TYPE_ROUTER) {
/* Reconnect to the router (backup) */
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
- server, 1, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_server_create_connections(server);
}
- SILC_SERVER_SEND_OPERS(server, FALSE, TRUE, SILC_NOTIFY_TYPE_NONE,
- ("Server %s signoff", user_data->server_name));
+ if (user_data->server_name)
+ SILC_SERVER_SEND_OPERS(server, FALSE, TRUE, SILC_NOTIFY_TYPE_NONE,
+ ("Server %s signoff", user_data->server_name));
if (!backup_router) {
/* Remove all servers that are originated from this server, and
/* Generate HMAC key from the channel key data and set it */
if (!channel->hmac)
- silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac);
+ if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) {
+ memset(channel->key, 0, channel->key_len / 8);
+ silc_free(channel->key);
+ channel->channel_key = NULL;
+ return FALSE;
+ }
silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, len, hash);
silc_hmac_set_key(channel->hmac, hash,
silc_hash_len(silc_hmac_get_hash(channel->hmac)));
/* Generate HMAC key from the channel key data and set it */
if (!channel->hmac)
- silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac);
+ if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) {
+ memset(channel->key, 0, channel->key_len / 8);
+ silc_free(channel->key);
+ channel->channel_key = NULL;
+ return FALSE;
+ }
silc_hash_make(silc_hmac_get_hash(channel->hmac), tmp, tmp_len, hash);
silc_hmac_set_key(channel->hmac, hash,
silc_hash_len(silc_hmac_get_hash(channel->hmac)));
if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
/* Error occured during protocol */
- SILC_LOG_ERROR(("Error occurred during rekey protocol with
- %s (%s)", sock->hostname, sock->ip));
+ SILC_LOG_ERROR(("Error occurred during rekey protocol with "
+ "%s (%s)", sock->hostname, sock->ip));
silc_protocol_cancel(protocol, server->schedule);
silc_protocol_free(protocol);
sock->protocol = NULL;
if (ctx->ske)
silc_ske_free(ctx->ske);
silc_free(ctx);
+
+ /* Reconnect */
+ SILC_SET_DISCONNECTING(sock);
+ server->backup_noswitch = TRUE;
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_close_connection(server, sock);
+ silc_server_create_connections(server);
return;
}
if (!server->backup->servers[i].server) {
server->backup->servers[i].server = backup_server;
server->backup->servers[i].local = local;
- server->backup->servers[i].port = htons(port);
+ server->backup->servers[i].port = SILC_SWAB_16(port);
memset(server->backup->servers[i].ip.data, 0,
sizeof(server->backup->servers[i].ip.data));
silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
(i + 1));
server->backup->servers[i].server = backup_server;
server->backup->servers[i].local = local;
- server->backup->servers[i].port = htons(port);
+ server->backup->servers[i].port = SILC_SWAB_16(port);
memset(server->backup->servers[i].ip.data, 0,
sizeof(server->backup->servers[i].ip.data));
silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
SILC_LOG_DEBUG(("Sending RESUMED to %s",
server_entry->server_name));
+ SILC_LOG_INFO(("Sending RESUMED to %s",
+ server_entry->server_name));
server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
SILC_LOG_DEBUG(("Sending RESUMED to %s",
server_entry->server_name));
+ SILC_LOG_INFO(("Sending RESUMED to %s",
+ server_entry->server_name));
server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
server->backup_noswitch = TRUE;
server->server_type = SILC_BACKUP_ROUTER;
+ if (ctx->sock == sock)
+ ctx->sock = NULL;
if (sock->user_data)
silc_server_free_sock_user_data(server, sock, NULL);
silc_server_close_connection(server, sock);
-
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
- server, 1, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_server_create_connections(server);
if (!silc_idcache_list_next(list, &id_cache))
break;
protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
server->backup_noswitch = TRUE;
server->server_type = SILC_BACKUP_ROUTER;
+ if (ctx->sock == sock)
+ ctx->sock = NULL;
if (sock->user_data)
silc_server_free_sock_user_data(server, sock, NULL);
silc_server_close_connection(server, sock);
-
- silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
- server, 1, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_server_create_connections(server);
if (!silc_idcache_list_next(list, &id_cache))
break;
protocol->state != SILC_PROTOCOL_STATE_FAILURE)
SILC_LOG_INFO(("Backup resuming protocol ended successfully"));
- if (ctx->sock->protocol)
+ if (ctx->sock && ctx->sock->protocol)
ctx->sock->protocol = NULL;
silc_protocol_free(protocol);
silc_free(ctx->sessions);
while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
if (type == t) {
if (type == 1) {
- if (silc_string_match((char *)entry, tmp)) {
+ if (silc_string_match(entry->data, tmp)) {
ret = TRUE;
break;
}
return ret;
}
-static void silc_server_inviteban_dummy_dest(void *key, void *context,
- void *user_context)
-{
- /* Nothing */
-}
-
/* Process invite or ban information */
void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
if (type == 1) {
/* Invite string. Get the old invite string from hash table
and append this at the end of the existing one. */
- char *string = NULL;
- silc_hash_table_find(list, (void *)1,
- NULL, (void **)&string);
- silc_hash_table_del_ext(list, (void *)1, NULL, NULL, NULL, NULL,
- silc_server_inviteban_dummy_dest, NULL);
- if (!string)
- string = silc_calloc(len + 2, sizeof(*string));
- else
- string = silc_realloc(string, sizeof(*string) *
- (strlen(string) + len + 2));
- memset(string + strlen(string), 0, len + 2);
+ if (!silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
+ tmp2 = silc_calloc(1, sizeof(*tmp2));
+ silc_hash_table_add(list, (void *)1, tmp2);
+ }
if (tmp[len - 1] == ',')
tmp[len - 1] = '\0';
- strncat(string, tmp, len);
- strncat(string, ",", 1);
-
- /* Add new invite string to invite list */
- silc_hash_table_add(list, (void *)1, string);
+ if (len) {
+ silc_buffer_strformat(tmp2, tmp, SILC_STR_END);
+ silc_buffer_strformat(tmp2, ",", SILC_STR_END);
+ }
} else if (type == 2) {
/* Public key. Check first if the public key is already on the
the requested string. */
char *string = NULL, *start, *end, *n;
- if (silc_hash_table_find(list, (void *)1, NULL, (void **)&string)) {
- if (!strncmp(string, tmp, strlen(string) - 1)) {
+ if (silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
+ string = tmp2->head;
+ if (tmp2->truelen && !strncmp(string, tmp, tmp2->truelen - 1)) {
+ /* Delete entire string */
silc_hash_table_del(list, (void *)1);
- string = NULL;
- } else {
+ } else if (tmp2->truelen) {
+ /* Delete part of the string */
start = strstr(string, tmp);
if (start && strlen(start) >= len) {
end = start + len;
n = silc_calloc(strlen(string) - len, sizeof(*n));
strncat(n, string, start - string);
strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
- silc_hash_table_del(list, (void *)1);
- string = n;
+ silc_free(tmp2->head);
+ silc_buffer_set(tmp2, n, strlen(n));
}
}
-
- /* Add new invite string to invite list */
- if (string)
- silc_hash_table_add(list, (void *)1, string);
}
} else if (type == 2) {
}
}
-/* Destructor for invite or ban list entrys */
+/* Destructor for invite and ban list entrys */
void silc_server_inviteban_destruct(void *key, void *context,
void *user_context)
{
- switch ((SilcUInt32)key) {
- case 1:
- /* Invite string */
- silc_free(context);
- break;
- case 2:
- case 3:
- /* Public key/Channel ID SilcBuffer */
- silc_buffer_free(context);
- break;
- default:
- break;
- }
+ silc_buffer_free(context);
+}
+
+/* Creates connections accoring to configuration. */
+
+void silc_server_create_connections(SilcServer server)
+{
+ silc_schedule_task_del_by_callback(server->schedule,
+ silc_server_connect_to_router);
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_connect_to_router, server, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
}
void silc_server_inviteban_destruct(void *key, void *context,
void *user_context);
+/* Creates connections accoring to configuration. */
+void silc_server_create_connections(SilcServer server);
+
#endif /* SERVER_UTIL_H */
serverconfig.c
- Author: Johnny Mnemonic <johnny@themnemonic.org>
+ Author: Giovanni Giacobbi <giovanni@giacobbi.net>
Copyright (C) 1997 - 2002 Pekka Riikonen
SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
SilcServerConfigServerInfo *server_info = config->server_info;
- /* if there isn't the struct alloc it */
+ SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
+ type, name, context));
+
+ /* if there isn't the main struct alloc it */
if (!server_info)
config->server_info = server_info = (SilcServerConfigServerInfo *)
silc_calloc(1, sizeof(*server_info));
if (type == SILC_CONFIG_ARG_BLOCK) {
if (!strcmp(name, "primary")) {
+ if (server_info->primary) {
+ SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+ "Double primary specification."));
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
CONFIG_IS_DOUBLE(server_info->primary);
- if (!tmp)
- return SILC_CONFIG_OK;
+
+ /* now check the temporary struct, don't accept empty block and
+ make sure all fields are there */
+ if (!tmp || !tmp->server_ip || !tmp->port) {
+ got_errno = SILC_CONFIG_EMISSFIELDS;
+ goto got_err;
+ }
server_info->primary = tmp;
config->tmp = NULL;
return SILC_CONFIG_OK;
} else if (!strcmp(name, "secondary")) {
if (!tmp)
return SILC_CONFIG_OK;
+ if (!tmp || !tmp->server_ip || !tmp->port) {
+ got_errno = SILC_CONFIG_EMISSFIELDS;
+ goto got_err;
+ }
SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
config->tmp = NULL;
return SILC_CONFIG_OK;
return SILC_CONFIG_OK;
got_err:
- silc_free(tmp);
- silc_free(config->tmp);
- config->tmp = NULL;
+ /* here we need to check if tmp exists because this function handles
+ * misc data (multiple fields and single-only fields) */
+ if (tmp) {
+ silc_free(tmp->server_ip);
+ silc_free(tmp);
+ config->tmp = NULL;
+ }
return got_errno;
}
}
}
silc_server_config_destroy(config_new);
+ silc_config_close(file);
return NULL;
}
serverconfig.h
- Author: Johnny Mnemonic <johnny@themnemonic.org>
+ Author: Giovanni Giacobbi <giovanni@giacobbi.net>
Copyright (C) 1997 - 2002 Pekka Riikonen
}
(*new_id)->ip.data_len = silc_net_is_ip4(ip) ? 4 : 16;
- (*new_id)->port = htons(port);
+ (*new_id)->port = SILC_SWAB_16(port);
(*new_id)->rnd = silc_rng_get_rn16(rng);
SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_SERVER)));
#undef STAT_OUTPUT
#ifdef SILC_DEBUG
+ /* Dump internal flags */
+ fprintf(fdd, "\nDumping internal flags\n");
+ fprintf(fdd, " server_type : %d\n", silcd->server_type);
+ fprintf(fdd, " standalone : %d\n", silcd->standalone);
+ fprintf(fdd, " listenning : %d\n", silcd->listenning);
+ fprintf(fdd, " background : %d\n", silcd->background);
+ fprintf(fdd, " backup_router : %d\n", silcd->backup_router);
+ fprintf(fdd, " backup_primary : %d\n", silcd->backup_primary);
+ fprintf(fdd, " backup_noswitch : %d\n", silcd->backup_noswitch);
+ fprintf(fdd, " wait_backup : %d\n", silcd->wait_backup);
+ if (silcd->router)
+ fprintf(fdd, " primary router : %s\n",
+ silcd->router->server_name ? silcd->router->server_name : "");
+
+ /* Dump socket connections */
+ {
+ int i;
+ SilcSocketConnection s;
+
+ fprintf(fdd, "\nDumping socket connections\n");
+ for (i = 0; i < silcd->config->param.connections_max; i++) {
+ s = silcd->sockets[i];
+ if (!s)
+ continue;
+ fprintf(fdd, " %d: host %s ip %s port %d type %d flags 0x%x\n",
+ s->sock, s->hostname ? s->hostname : "N/A",
+ s->ip ? s->ip : "N/A", s->port, s->type,
+ (unsigned int)s->flags);
+ }
+ }
+
/* Dump lists */
{
SilcIDCacheList list = NULL;
AC_PREREQ(2.52)
AC_CONFIG_HEADERS(includes/silcdefs.h)
+CFLAGS=
AC_PROG_CC
AC_C_INLINE
AC_C_CONST
AC_PROG_LN_S
AC_SUBST(LN_S)
-# Distribution definition. ./prepare will automatically add here a correct
-# value. Do not edit!
-#
+##
+## Distribution definition. ./prepare will automatically add here a correct
+## value. Do not edit!
+##
silc_dist=SILC_PACKAGE
SILC_DIST_SUBDIRS="SILC_DISTRIBUTION_SUBDIRS"
AC_DEFINE(SILC_DIST_DEFINE)
-# XXX
-# Compiler flags
-#
-if test "$GCC"; then
- CFLAGS="-Wall -finline-functions $CFLAGS"
-fi
-#
-# Library versioning.
-#
+##
+## Library versioning.
+##
# Do the releases and library versioning according to following rules:
#
# - If any code has changed in library, increment [LIB]_REVISION
AC_CHECK_FUNC(getopt_long, have_getopt_long=1, have_getopt_long=0)
AM_CONDITIONAL(HAVE_GETOPT_LONG, test x$have_getopt_long = x1)
-
##
## Enable/disable checking
##
yes)
AC_MSG_RESULT(yes)
AC_DEFINE(SILC_DEBUG)
- CFLAGS="-O -g $CFLAGS"
summary_debug="yes"
;;
*)
AC_MSG_RESULT(no)
- CFLAGS="-O2 -g $CFLAGS"
;;
esac
],
[
- CFLAGS="-O2 -g $CFLAGS"
AC_MSG_RESULT(no)
])
])
+##
+## Compiler and compiler flag checks
+##
+
+# Function to check if compiler flag works
+# Usage: SILC_ADD_CFLAGS(FLAGS, [ACTION-IF-FAILED])
+AC_DEFUN(SILC_ADD_CFLAGS,
+[ tmp_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $1"
+ AC_MSG_CHECKING(whether $CC accepts $1 flag)
+ AC_TRY_LINK(, , AC_MSG_RESULT(yes), [AC_MSG_RESULT(no)
+ CFLAGS="$tmp_CFLAGS"
+ $2])
+ unset tmp_CFLAGS
+])
+
+if test "$GCC"; then
+ # GCC specific options
+ if test "x$summary_debug" = "xyes"; then
+ SILC_ADD_CFLAGS(-g -O)
+ else
+ SILC_ADD_CFLAGS(-g -O2)
+ fi
+ SILC_ADD_CFLAGS(-Wall -finline-functions)
+else
+ # Other compilers
+ case "$target" in
+ alpha*-dec-osf*)
+ SILC_ADD_CFLAGS(-g3 -O2, SILC_ADD_CFLAGS(-g3 -O, SILC_ADD_CFLAGS(-O)))
+ ;;
+ *)
+ SILC_ADD_CFLAGS(-g)
+ SILC_ADD_CFLAGS(-O2, SILC_ADD_CFLAGS(-O))
+ ;;
+ esac
+
+ # Intel C++ Compiler needs -restrict
+ if test "x$CC" = "xicc"; then
+ SILC_ADD_CFLAGS(-restrict)
+ fi
+fi
+
+
##
## Installation
##
echo " Installation prefix ...........: $prefix"
echo " bin directory .................: $s_bindir"
echo " sbin directory ................: $s_sbindir"
+echo " etc directory .................: $ETCDIR"
echo " man directory .................: $s_mandir"
echo " help directory ................: $HELPDIR"
echo " doc directory .................: $DOCDIR"
else
sim_support="yes"
fi
+if test x$has_iconv = xfalse; then
+ iconv_support="no"
+else
+ iconv_support="yes"
+fi
echo " SIM support ...................: $sim_support"
echo " IPv6 support ..................: $summary_ipv6"
+echo " Iconv support .................: $iconv_support"
echo " Assembler optimizations .......: $summary_asm"
mp="MPI"
SILC is designed and written by Pekka Riikonen <priikone@iki.fi> and rest
of the SILC Project.
-Configuration file format and parser is by Johnny Mnemonic.
+Configuration file format and parser is by Giovanni Giacobbi
+<giovanni@giacobbi.net>.
This manpage was written by Mika 'Bostik' Boström <bostik@lut.fi>
<li><a href="intro_reference.html">Introduction to the Manual</a><br />
<li><a href="programming_conv.html">Programming Conventions</a><br />
<li><a href="building.html">Building the Toolkit</a>
+<li><a href="platforms.html">Platform Implementations</a>
+
+<br /><br />
+<b>Guides & Tutorials</b>
+<br /><br />
+<li><a href="silcclientlib.html">Client Library Guides & Reference</a>
+<li><a href="silcrng_intro.html">Introduction to SILC Random Number Generator</a>
<br /><br />
<b>Toolkit Reference</b>
--- /dev/null
+<big><b>Command Reply Arguments</b></big>
+
+<br /> <br />
+The SILC Client Library 'command_reply client operation (which is part of the
+<a href="silcclient-SilcClientOperations.html">
+SilcClientOperation</a> callback functions) returns command replies
+from the SILC Server for commands that the client has earlier sent to the
+server. The 'command_reply' client operation implementation has a variable
+argument list to deliver <a href="silccommand-SilcCommand.html">SilcCommand</a>
+specific arguments to the application. This document describes these
+arguments for all command replies to help SILC client software developers
+to process them.
+
+<br /> <br /> <br />
+<b>command_reply Client Library operation</b>
+
+<br /> <br />
+The 'command_reply' client operation callback function prototype is as follows:
+
+<br /> <br />
+<tt>
+
+void (*command_reply)(SilcClient client, SilcClientConnection conn,<br />
+
+SilcCommandPayload cmd_payload, bool success, SilcCommand command,<br />
+
+SilcStatus status, ...);
+</tt>
+
+<br /> <br />
+The first argument 'client' is the SILC Client Library context, the 'conn'
+is the context for the connection to the remote server, the 'cmd_payload'
+is the raw SilcCommandPayload and application usually ignores it, the
+'success' boolean value indicates whether the earlier command was a success
+or not, the 'command' is the command reply enumeration, and the 'status'
+indicates the status of the command reply. If 'success' is FALSE then
+'status' includes error status.
+
+<br /> <br />
+Rest of the arguments are 'command' specific and implementation should
+handle them by the SilcCommand for example in a <tt>switch</tt> statement.
+The commands are defined in lib/silccore/silccomand.h header file. A short
+example:
+
+<br /> <br />
+<tt>
+ switch(type)<br />
+ {<br />
+ case SILC_COMMAND_WHOIS:<br />
+ ...<br />
+ break;<br />
+ case SILC_COMMAND_WHOWAS:<br />
+ ...<br />
+ break;<br />
+ case SILC_COMMAND_NICK:<br />
+ ...<br />
+ break;<br />
+ ...<br />
+ }
+</tt>
+
+<br /> <br /> <br />
+<b>Arguments</b>
+
+<br /> <br />
+The following table describes all commands and arguments that the client
+library sends in the 'command_reply' client operation to the application.
+By default all arguments that the library sends to application are valid
+pointers. However, it is possible that some pointers may be NULL. If
+this is the case it is separately mentioned that the argument may be NULL.
+In this case application must ignore that argument. The 'command_reply'
+arguments per SilcCommand is as follows:
+
+<br /> <br />
+<table border="1" width="100%" cellpadding="3" cellspacing="0">
+
+<tr>
+<td><small>Name</td>
+<td><small>Description</td>
+<td width="50%"><small>Variable Arguments</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_WHOIS</td>
+<td><small>
+Returns information about user. The following pointers may be NULL: 'channels',
+'fingerprint', 'channel_usermodes' and 'attrs'. If 'fingerprint' is valid its
+length is 20 bytes. If 'channels' is valid it can be parsed with
+silc_channel_payload_parse_list function. It is the list of channels user
+has joined. If the 'channel_usermodes' is valid it can be parsed with
+silc_get_mode_list function. It is the list of the user's modes on the
+joined channels. The 'attr' is the Requested Attributes that may have been
+returned by the client and it can be parsed by traversing the SilcDList
+and using silc_attribute_get_attribute function.
+</td>
+<td width="50%"><small>SilcClientEntry client_entry, char *nickname,
+char *username, char *realname, SilcBuffer channels, SilcUInt32 usermode,
+SilcUInt32 idletime, unsigned char *fingerprint, SilcBuffer channel_usermodes,
+SilcDList attrs
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_WHOWAS</td>
+<td><small>
+Returns history information about user. The 'client_entry' and 'realname'
+may be NULL.
+</td>
+<td width="50%"><small>SilcClientEntry client_entry, char *nickname,
+char *username, char *realname
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_IDENTIFY</td>
+<td><small>
+Returns information about user, channel or server. This is similar to
+WHOIS command but does not return so much information and can be used to
+get information about channels and servers too. Application should ignore
+this command reply. The 'name' and 'info' may be NULL.
+</td>
+<td width="50%"><small>void *entry, char *name, char *info
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_NICK</td>
+<td><small>
+Returns the new Client ID after user has changed nickname.
+</td>
+<td width="50%"><small>SilcClientEntry local_entry, char *nickname
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_LIST</td>
+<td><small>
+Returns the list of channel in the SILC network. Each call of command reply
+returns one channel. This means that the command reply is called multiple
+times to return list of channels. The 'channel_topic' may be NULL.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, char *channel_name,
+char *channel_topic, SilcUInt32 user_count
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_TOPIC</td>
+<td><small>
+Returns the topic of the channel.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, char *topic
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_INVITE</td>
+<td><small>
+Returns the invite list of the channel. Called also even if invite list
+was not modified but SILC_COMMAND_INVITE command was used to invite a user
+into a channel. In this case the invite list is not returned by the
+server and 'invite_list' is NULL. The 'invite_list' is list of
+SilcArgumentPayloads. The first 2 bytes are the number of arguments in
+the list and can be parsed with SILC_GET16_MSB macro. The list can be
+parsed with silc_argument_payload_parse function.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, SilcBuffer invite_list
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_KILL</td>
+<td><small>
+Called after killing a client. There is no arguments to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_INFO</td>
+<td><small>
+Returns information about the server user is connected to.
+</td>
+<td width="50%"><small>SilcServerEntry server, char *server_name,
+char *server_info
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_STATS</td>
+<td><small>
+Returns network statistics from the server. The 'stats_buffer' of length of
+'buffer_length' bytes includes 32-bit integers one after the other each
+representing some statistics. The integers can be parsed for example with
+SILC_GET32_MSB macro. The integers in the buffer are: starttime, uptime,
+local_clients, local_channels, local_serverops, local_routerops, cell_clients,
+cell_channels, cell_servers, all_clients, all_channel, all_servers,
+all_routers, all_serverops, all_routerops. All integers are always present.
+</td>
+<td width="50%"><small>unsigned char *stats_buffer, SilcUInt32 buffer_length
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_PING</td>
+<td><small>
+Returns reply to earlier ping. There is no arguments to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_OPER</td>
+<td><small>
+Returns reply to earlier SILC_COMMAND_OPER command. There is no arguments
+to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_JOIN</td>
+<td><small>
+Reply received when user joined a channel. The 'ignored' argument can
+be ignored by the application. The 'topic' and 'hmac_name' may be NULL.
+The 'key_payload' is usually ignored by the application. The 'list_count'
+is the number of entries in both 'client_id_list' and 'client_mode_list'.
+The 'client_id_list' is a list of clients on the channel and 'client_mode_list'
+includes those clients' modes on the channel. If application likes to
+resolve information about the clients on the channel it may call
+silc_client_get_clients_by_list function and pass the 'client_id_list' as
+argument to it. The 'client_mode_list' includes 32-bit integers one after
+the other and they are in same order as clients in 'client_mode_list'.
+If application resolves the information with silc_client_get_clients_by_list
+parsing the 'client_mode_list' is not necessary.
+</td>
+<td width="50%"><small>char *channel_name, SilcChannelEntry channel,
+SilcUInt32 channel_mode, int ignored, SilcBuffer key_payload, NULL, NULL,
+char *topic, char *hmac_name, SilcUInt32 list_count, SilcBuffer client_id_list,
+SilcBuffer client_mode_list
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_MOTD</td>
+<td><small>
+Returns the Message of the Day from the server. The 'motd' may be NULL.
+</td>
+<td width="50%"><small>char *motd
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_UMODE</td>
+<td><small>
+Returns the user mode after changing it.
+</td>
+<td width="50%"><small>SilcUInt32 user_mode
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_CMODE</td>
+<td><small>
+Returns channel's mode after changing it.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, SilcUInt32 mode
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_CUMODE</td>
+<td><small>
+Returns user's mode on channel after changing it.
+</td>
+<td width="50%"><small>SilcUInt32 mode, SilcChannelEntry channel,
+SilcClientEntry target_client
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_KICK</td>
+<td><small>
+Called after kicking a client. There is no arguments to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_BAN</td>
+<td><small>
+Returns channel's ban list. The 'ban_list' may be NULL. The construction
+of that list is equivalent to invite list. See description of
+SILC_COMMAND_INVITE command reply.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, SilcBuffer ban_list
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_DETACH</td>
+<td><small>
+Called after being detached from the SILC network. There is no arguments
+to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_WATCH</td>
+<td><small>
+Called after modifying the watch list in the server. There is no arguments
+to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_SILCOPER</td>
+<td><small>
+Returns reply to earlier SILC_COMMAND_SILCOPER command. There is no
+arguments to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_LEAVE</td>
+<td><small>
+Called after leaving the channel.
+</td>
+<td width="50%"><small>SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_USERS</td>
+<td><small>
+Returns list of users in channel. If application wishes not to parse
+the raw lists the channel->user_list hash table is updated before calling
+this command reply and application may traverse that table instead of
+parssing the raw lists.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, SilcUInt32 list_count,
+SilcBuffer client_id_list, SilcBuffer client_mode_list
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_GETKEY</td>
+<td><small>
+Returns public key of client or server. The 'public_key' may be NULL.
+The 'entry_type' is used to check what type of pointer the entry' is. For
+SILC_ID_CLIENT SilcClientEntry and for SILC_ID_SERVER SilcServerEntry.
+</td>
+<td width="50%"><small>SilcIdType entry_type, void *entry,
+SilcPublicKey public_key
+</td>
+</tr>
+
+</table>
+
+<br /> <br />
+SILC protocol defines some additional commands but command replies to
+those commands are not delivered to the application. Only the command
+replies listed above are delivered to application.
--- /dev/null
+<big><b>SilcNotifyType Arguments</b></big>
+
+<br /> <br />
+The SILC Client Library 'notify' client operation (which is part of the
+<a href="silcclient-SilcClientOperations.html">
+SilcClientOperation</a> callback functions) returns different kind of
+notifications from the SILC server to the SILC client. The 'notify'
+client operation implementation has a variable argument list to deliver
+<a href="silcnotify-SilcNotifyType.html">SilcNotifyType</a> type specific arguments to the application. This document
+describes these arguments for all notify types to help SILC client
+software developers to handle the incoming notifications.
+
+<br /> <br /> <br />
+<b>notify Client Library operation</b>
+
+<br /> <br />
+The 'notify' client operation callback function prototype is as follows:
+
+<br /> <br />
+<tt>
+ void (*notify)(SilcClient client, SilcClientConnection conn,
+SilcNotifyType type, ...);
+</tt>
+
+<br /> <br />
+The first argument 'client' is the SILC Client Library context, the `conn'
+is the context for the connection to the remote server, and the `type' is
+the notify type enumeration sent by the server. Rest of the arguments are
+`type' specific and implementation should handle them by the
+SilcNotifyType for example in a <tt>switch</tt> statement. The notify
+types are defined in lib/silccore/silcnotify.h header file. A short
+example:
+
+<br /> <br />
+<tt>
+ switch(type)<br />
+ {<br />
+ case SILC_NOTIFY_TYPE_NONE:<br />
+ ...<br />
+ break;<br />
+ case SILC_NOTIFY_TYPE_INVITE:<br />
+ ...<br />
+ break;<br />
+ case SILC_NOTIFY_TYPE_JOIN:<br />
+ ...<br />
+ break;<br />
+ ...<br />
+ }
+</tt>
+
+<br /> <br /> <br />
+<b>Arguments</b>
+
+<br /> <br />
+The following table describes all notify types and arguments that the
+client library sends in the 'notify' client operation to the application.
+By default all arguments that the library sends to application are valid
+pointers. However, it is possible that some pointers may be NULL. If
+this is the case it is separately mentioned that the argument may be NULL.
+In this case application must ignore that argument. The SilcNotifyType
+arguments per notify type is as follows:
+
+<br /> <br />
+<table border="1" width="100%" cellpadding="3" cellspacing="0">
+
+<tr>
+<td><small>Name</td>
+<td><small>Description</td>
+<td width="50%"><small>Variable Arguments</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_NONE</td>
+<td><small>
+A message from server that usually does not include any critical
+information. Application may ignore this or display it for the user.
+The 'message' argument may be NULL.
+</td>
+<td width="50%"><small>char *message</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_INVITE</td>
+<td><small>
+Sent to the client if the user is invited on a channel. The 'channel_name'
+argument may be NULL.
+</td>
+<td width="50%"><small>SilcClientChannel channel, char *channel_name,
+SilcClientEntry inviter
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_JOIN</td>
+<td><small>
+Sent when someone joins to a channel.
+</td>
+<td width="50%"><small>SilcClientEntry joining_client, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_LEAVE</td>
+<td><small>
+Sent when someone leaves (parts) the channel.
+</td>
+<td width="50%"><small>SilcClientEntry leaving_client, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_SIGNOFF</td>
+<td><small>
+Sent when someone signoff the SILC network. The 'signoff_message' may be
+NULL. The 'leaving_client' SilcClientEntry may be incomplete and contain
+NULL pointers, application must check it's pointers before attempting to
+display for example nickname information.
+</td>
+<td width="50%"><small>SilcClientEntry signoff_client, char *signoff_message
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_TOPIC_SET</td>
+<td><small>
+Sent when the topic of a channel is set/changed. The 'setter_id_type'
+is used to check what type of pointer the 'setter_entry' is. For
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
+SILC_ID_CHANNEL SilcChannelEntry.
+</td>
+<td width="50%"><small>SilcIdType setter_id_type, void *setter_entry,
+char *topic, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_NICK_CHANGE</td>
+<td><small>
+Sent when someone changes their nickname. The 'old_client_entry' includes
+the old nickname and the 'new_client_entry' includes the new nickname.
+Application must understand that the 'old_client_entry' pointer becomes
+invalid after returning from the function.
+</td>
+<td width="50%"><small>SilcClientEntry old_client_entry,
+SilcClientEntry new_client_entry
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_CMODE_CHANGE</td>
+<td><small>
+Sent when channel's mode has changed. The 'changer_id_type'
+is used to check what type of pointer the 'changer_entry' is. For
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
+SILC_ID_CHANNEL SilcChannelEntry. The 'mode' is the mode mask after the
+change. The 'hmac_name' argument may be NULL.
+</td>
+<td width="50%"><small>SilcIdType changer_id_type, void *changer_entry,
+SilcUInt32 mode, NULL, char *hmac_name, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_CUMODE_CHANGE</td>
+<td><small>
+Sent when a users mode on a channel has changed. The 'changer_id_type'
+is used to check what type of pointer the 'changer_entry' is. For
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
+SILC_ID_CHANNEL SilcChannelEntry. The 'mode' is the mode mask after the
+change. The 'target_client' is the client whose mode was changed.
+</td>
+<td width="50%"><small>SilcIdType changer_id_type, void *changer_entry,
+SilcUInt32 mode, SilcClientEntry target_client, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_MOTD</td>
+<td><small>
+Message of the Day from the server.
+</td>
+<td width="50%"><small>char *motd
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_CHANNEL_CHANGE</td>
+<td><small>
+Sent when a channel's Channel ID changes. It is possible that channel's
+ID changes and this notify is sent by the server when this happens.
+Usually application does not need to handle this notify type and may
+safely ignore it when received.
+</td>
+<td width="50%"><small>SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_SERVER_SIGNOFF</td>
+<td><small>
+Sent when a server quits the network. The 'clients' is an array
+SilcClientEntry pointers of size of 'clients_count'. Each client in the
+entry is one client signing off from the SILC network.
+</td>
+<td width="50%"><small>NULL, SilcClientEntry *clients, SilcUInt32 clients_count
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_KICKED</td>
+<td><small>
+Sent when a client (possibly our client) is kicked from a channel. The
+'kick_message' may be NULL. If our client was kicked then 'kicked' is our
+local SilcClientEntry pointer.
+</td>
+<td width="50%"><small>SilcClientEntry kicked, char *kick_message,
+SilcClientEntry kicker, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_KILLED</td>
+<td><small>
+Sent when a client (possibly our client) is killed from the network. The
+'kill_message' may be NULL. If our client was killed then 'killed' is our
+local SilcClientEntry pointer. The 'killer_type' is used to check what
+type of pointer the 'killer' is. For SILC_ID_CLIENT SilcClientEntry, for
+SILC_ID_SERVER SilcServerEntry and for SILC_ID_CHANNEL SilcChannelEntry.
+</td>
+<td width="50%"><small>SilcClientEntry killed, char *kill_message,
+SilcIdType killer_type, void *killer, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_ERROR</td>
+<td><small>
+Sent when an error occurs while handling some operation (except command)
+from the client. Application usually cannot handle this notify type and
+may safely ignore it.
+</td>
+<td width="50%"><small>SilcStatus error
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_WATCH</td>
+<td><small>
+Sent to notify some status change of a client we are wathing. The
+SILC_COMMAND_WATCH is used to manage clients we are wathing and this
+notify type is used to deliver information about that client. If the
+client just changed nickname the 'new_nickname' includes the new nickname.
+Otherwise this pointer is NULL. The 'user_mode' is the client's mode in
+the SILC network. The 'notification' contains the notify type that
+happened for the 'watched_client' (for example
+SILC_NOTIFY_TYPE_NICK_CHANGE if the client changed their nickname).
+</td>
+<td width="50%"><small>SilcClientEntry watched_client, char *new_nickname,
+SilcUInt32 user_mode, SilcNotifyType notification
+</td>
+</tr>
+
+</table>
+
+<br /> <br />
+SILC protocol defines some additional notify types but those notify types
+are not delivered to the application. Some of those notify types are only
+delivered between servers and routers and clients never receive them.
+Only the notify types listed above are delivered to application.
--- /dev/null
+<big><b>Platform Implementations</b></big>
+
+<br /> <br />
+This document describes the implementation issues with different platforms
+that the SILC Toolkit support. Some of the supported platforms does not
+support all the features delivered with the Toolkit or they may behave
+differently from other platforms. This document descibres these
+differences between platforms.
+
+<br /> <br />
+<li><a href="#unix">Unix & Linux Implementation</a><br />
+<li><a href="#windows">Windows Implementation</a><br />
+<li><a href="#macosx">Mac OS X Implementation</a>
+
+<br /> <br /> <br />
+<b>Supported Platforms</b>
+
+<br /> <br />
+SILC Toolkit supports by default all Unix and Linux platforms, Windows
+platforms from Windows 98 and newer, and Mac OS X. In the future there is
+also plans to add support for other platforms such as Symbian OS (EPOC).
+
+<br /> <br /> <br />
+<b><a name="unix"></a>Unix Implementation</b>
+
+<br /> <br />
+All features and components delivered with the SILC Toolkit work on all
+Unix and Linux platforms. There are no special Unix platform related
+implementation issues with current version of SILC Toolkit.
+
+
+<br /> <br /> <br />
+<b><a name="windows"></a>Windows Implementation</b>
+
+<br /> <br />
+By default all features and components delivered with SILC Toolkit are
+supported on Windows. However, there are some certain issues with the
+Windows version of the SILC Toolkit.
+
+<br /> <br />
+<li>Toolkit users should not use <tt>silc_client_run</tt> function to
+execute the Client Library. Instead the <tt>silc_client_run_one</tt> should
+be used, for example as an timer task and the Windows application's own
+message loop should be used as the main message loop.
+
+<li>The function <tt>silc_net_create_connection_async</tt> is not actually
+asynchronous on Windows, but synchronous and it will block the process
+while the connection is created. This means also that the function
+<tt>silc_client_connect_to_server</tt> is not asynchronous but
+synchronous.
+
+
+<br /> <br /> <br />
+<b><a name="macosx"></a>Mac OS X Implementation</b>
+
+<br /> <br />
+All features and components delivered with the SILC Toolkit work on Mac
+OS X platform. There are no special Mac OS X platform related
+implementation issues with current version of SILC Toolkit.
+
<!--
@LIBRARY=SILC Client Library
@FILENAME=silcclientlib.html
-@LINK=silcclient_using.html:Using SILC Client Library
-@LINK=silcclient.html:Client Library Interface
+@LINK=silcclient_using.html:Using SILC Client Library Tutorial
+@LINK=command_reply_args.html:Arguments for <b>command_reply</b> Client Operation
+@LINK=notifyargs.html:Arguments for <b>notify</b> Client Operation
+@LINK=silcclient.html:Client Library Interface Reference
-->
<big><b>SILC Client Library</b></big>
client_entry2->fingerprint = client_entry->fingerprint;
client_entry2->fingerprint_len = client_entry->fingerprint_len;
client_entry->fingerprint = NULL;
- client_entry->fingerprint_len = NULL;
+ client_entry->fingerprint_len = 0;
silc_client_update_client(client, conn, client_entry2, tmp, NULL, NULL,
client_entry->mode);
silc_buffer_free(idp);
if (auth)
silc_buffer_free(auth);
+ if (passphrase)
+ memset(passphrase, 0, strlen(passphrase));
silc_free(passphrase);
/* Notify application */
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
+ silc_buffer_clear(auth);
silc_buffer_free(auth);
/* Notify application */
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
+ silc_buffer_clear(auth);
silc_buffer_free(auth);
/* Notify application */
function. */
if (ctx->responder == TRUE) {
protocol->state++;
- silc_protocol_execute(protocol, client->schedule, 0, 100000);
+ silc_protocol_execute(protocol, client->schedule, 0, 1);
}
}
/* Advance protocol state and call the next state if we are responder */
protocol->state++;
if (ctx->responder == TRUE)
- silc_protocol_execute(protocol, client->schedule, 0, 100000);
+ silc_protocol_execute(protocol, client->schedule, 0, 1);
}
break;
case 2:
/* Advance protocol state and call next state if we are initiator */
protocol->state++;
if (ctx->responder == FALSE)
- silc_protocol_execute(protocol, client->schedule, 0, 100000);
+ silc_protocol_execute(protocol, client->schedule, 0, 1);
}
break;
case 3:
message to a specific connection. `conn', however, may be NULL.
The `type' indicates the type of the message sent by the library.
The application can for example filter the message according the
- type. */
+ type. The variable argument list is arguments to the formatted
+ message that `msg' may be. */
void (*say)(SilcClient client, SilcClientConnection conn,
SilcClientMessageType type, char *msg, ...);
silcattrs.h
endif
-EXTRA_DIST = *.h
+EXTRA_DIST = *.h tests
include $(top_srcdir)/Makefile.defines.in
SILC_STR_UI_XNSTRING(pk, pk_len),
SILC_STR_END);
- ret = silc_memdup(buf->data, buf->len);
- if (!ret)
- return NULL;
-
- if (ret_len)
- *ret_len = buf->len;
+ ret = silc_buffer_steal(buf, ret_len);
- silc_buffer_clear(buf);
silc_buffer_free(buf);
silc_free(id_data);
silc_free(pk);
SilcMPInt mp_tmp;
SilcMPInt mp_dst;
unsigned char *padded;
- SilcUInt32 padded_len, len = key->bits / 8;
+ SilcUInt32 padded_len, len = (key->bits + 7) / 8;
/* Pad data */
if (!RSA_FormatBlock(&padded, &padded_len, len,
silc_mp_init(&mp_tmp);
silc_mp_init(&mp_dst);
- silc_mp_set_ui(&mp_tmp, 0);
- silc_mp_set_ui(&mp_dst, 0);
/* Data to MP */
silc_mp_bin2mp(padded, padded_len, &mp_tmp);
silc_mp_init(&mp_tmp);
silc_mp_init(&mp_dst);
- silc_mp_set_ui(&mp_tmp, 0);
- silc_mp_set_ui(&mp_dst, 0);
/* Data to MP */
silc_mp_bin2mp(src, src_len, &mp_tmp);
rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
/* MP to data */
- padded = silc_mp_mp2bin(&mp_dst, key->bits / 8, &padded_len);
+ padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
/* Unpad data */
unpadded = RSA_DecodeOneBlock(padded, padded_len, 0,
SilcMPInt mp_dst;
unsigned char *padded;
SilcUInt32 padded_len;
- SilcUInt32 len = key->bits / 8;
+ SilcUInt32 len = (key->bits + 7) / 8;
/* Pad data */
if (!RSA_FormatBlock(&padded, &padded_len, len, RSA_BlockPrivate,
silc_mp_init(&mp_tmp);
silc_mp_init(&mp_dst);
- silc_mp_set_ui(&mp_tmp, 0);
- silc_mp_set_ui(&mp_dst, 0);
/* Data to MP */
silc_mp_bin2mp(padded, len, &mp_tmp);
SilcMPInt mp_tmp2;
SilcMPInt mp_dst;
unsigned char *verify, *unpadded;
- SilcUInt32 verify_len, len = key->bits / 8;
+ SilcUInt32 verify_len, len = (key->bits + 7) / 8;
silc_mp_init(&mp_tmp2);
silc_mp_init(&mp_dst);
- silc_mp_set_ui(&mp_tmp2, 0);
- silc_mp_set_ui(&mp_dst, 0);
/* Format the signature into MP int */
silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
unsigned char tmp[4];
e = silc_mp_mp2bin(&key->e, 0, &e_len);
- n = silc_mp_mp2bin(&key->n, key->bits / 8, &n_len);
+ n = silc_mp_mp2bin(&key->n, (key->bits + 7) / 8, &n_len);
*ret_len = e_len + 4 + n_len + 4;
ret = silc_calloc(*ret_len, sizeof(unsigned char));
unsigned char tmp[4];
e = silc_mp_mp2bin(&key->e, 0, &e_len);
- n = silc_mp_mp2bin(&key->n, key->bits / 8, &n_len);
+ n = silc_mp_mp2bin(&key->n, (key->bits + 7) / 8, &n_len);
d = silc_mp_mp2bin(&key->d, 0, &d_len);
*ret_len = e_len + 4 + n_len + 4 + d_len + 4;
silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &key->n);
- key->bits = n_len * 8;
+ key->bits = silc_mp_sizeinbase(&key->n, 2);
key->pub_set = TRUE;
return key->bits;
silc_mp_bin2mp(key_data + 4 + e_len + 4 + n_len + 4, d_len, &key->d);
- key->bits = n_len * 8;
+ key->bits = silc_mp_sizeinbase(&key->n, 2);
key->prv_set = TRUE;
key->pub_set = TRUE;
SILC_PKCS_API_ENCRYPT(rsa)
{
RsaKey *key = (RsaKey *)context;
- int i, tmplen;
+ int tmplen;
SilcMPInt mp_tmp;
SilcMPInt mp_dst;
silc_mp_init(&mp_tmp);
silc_mp_init(&mp_dst);
- silc_mp_set_ui(&mp_tmp, 0);
- silc_mp_set_ui(&mp_dst, 0);
/* Format the data into MP int */
- for (i = 0; i < src_len; i++) {
- silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
- silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
- }
+ silc_mp_bin2mp(src, src_len, &mp_tmp);
/* Encrypt */
rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
tmplen = (key->bits + 7) / 8;
/* Format the MP int back into data */
- for (i = tmplen; i > 0; i--) {
- dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
- silc_mp_div_2exp(&mp_dst, &mp_dst, 8);
- }
+ silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
*dst_len = tmplen;
silc_mp_uninit(&mp_tmp);
SILC_PKCS_API_DECRYPT(rsa)
{
RsaKey *key = (RsaKey *)context;
- int i, tmplen;
+ int tmplen;
SilcMPInt mp_tmp;
SilcMPInt mp_dst;
silc_mp_init(&mp_tmp);
silc_mp_init(&mp_dst);
- silc_mp_set_ui(&mp_tmp, 0);
- silc_mp_set_ui(&mp_dst, 0);
/* Format the data into MP int */
- for (i = 0; i < src_len; i++) {
- silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
- silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
- }
+ silc_mp_bin2mp(src, src_len, &mp_tmp);
/* Decrypt */
rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
tmplen = (key->bits + 7) / 8;
/* Format the MP int back into data */
- for (i = tmplen; i > 0; i--) {
- dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
- silc_mp_div_2exp(&mp_dst, &mp_dst, 8);
- }
+ silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
*dst_len = tmplen;
silc_mp_uninit(&mp_tmp);
SILC_PKCS_API_SIGN(rsa)
{
RsaKey *key = (RsaKey *)context;
- int i, tmplen;
+ int tmplen;
SilcMPInt mp_tmp;
SilcMPInt mp_dst;
silc_mp_init(&mp_tmp);
silc_mp_init(&mp_dst);
- silc_mp_set_ui(&mp_tmp, 0);
- silc_mp_set_ui(&mp_dst, 0);
/* Format the data into MP int */
- for (i = 0; i < src_len; i++) {
- silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
- silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
- }
+ silc_mp_bin2mp(src, src_len, &mp_tmp);
/* Sign */
rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
tmplen = (key->bits + 7) / 8;
/* Format the MP int back into data */
- for (i = tmplen; i > 0; i--) {
- dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
- silc_mp_div_2exp(&mp_dst, &mp_dst, 8);
- }
+ silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
*dst_len = tmplen;
silc_mp_uninit(&mp_tmp);
SILC_PKCS_API_VERIFY(rsa)
{
RsaKey *key = (RsaKey *)context;
- int i, ret;
+ int ret;
SilcMPInt mp_tmp, mp_tmp2;
SilcMPInt mp_dst;
silc_mp_init(&mp_tmp);
silc_mp_init(&mp_tmp2);
silc_mp_init(&mp_dst);
- silc_mp_set_ui(&mp_tmp, 0);
- silc_mp_set_ui(&mp_tmp2, 0);
- silc_mp_set_ui(&mp_dst, 0);
/* Format the signature into MP int */
- for (i = 0; i < signature_len; i++) {
- silc_mp_mul_2exp(&mp_tmp2, &mp_tmp2, 8);
- silc_mp_add_ui(&mp_tmp2, &mp_tmp2, signature[i]);
- }
+ silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
/* Verify */
rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
/* Format the data into MP int */
- for (i = 0; i < data_len; i++) {
- silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
- silc_mp_add_ui(&mp_tmp, &mp_tmp, data[i]);
- }
+ silc_mp_bin2mp(data, data_len, &mp_tmp);
ret = TRUE;
SilcBuffer buf;
unsigned char *ret;
- buf = silc_buffer_alloc(public_key->len + 4);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(public_key->len + 4);
+ if (!buf)
+ return NULL;
silc_buffer_format(buf,
SILC_STR_UI_INT(public_key->len),
SILC_STR_UI_XNSTRING(public_key->pk,
public_key->pk_len),
SILC_STR_END);
- if (len)
- *len = public_key->len + 4;
- ret = silc_calloc(buf->len, sizeof(*ret));
- memcpy(ret, buf->data, buf->len);
+ ret = silc_buffer_steal(buf, len);
silc_buffer_free(buf);
-
return ret;
}
SilcUInt32 totlen;
totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
- buf = silc_buffer_alloc(totlen + 4);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(totlen + 4);
+ if (!buf)
+ return NULL;
silc_buffer_format(buf,
SILC_STR_UI_INT(totlen),
SILC_STR_UI32_STRING(identifier),
SILC_STR_UI_XNSTRING(pk, pk_len),
SILC_STR_END);
- if (len)
- *len = totlen + 4;
- ret = silc_calloc(buf->len, sizeof(*ret));
- memcpy(ret, buf->data, buf->len);
+ ret = silc_buffer_steal(buf, len);
silc_buffer_free(buf);
-
return ret;
}
bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
SilcPublicKey *public_key)
{
- SilcBuffer buf;
+ SilcBufferStruct buf;
SilcPKCS alg;
SilcUInt16 pkcs_len, identifier_len;
SilcUInt32 totlen, key_len;
unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
int ret;
- buf = silc_buffer_alloc(data_len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
- silc_buffer_put(buf, data, data_len);
+ silc_buffer_set(&buf, data, data_len);
/* Get length */
- ret = silc_buffer_unformat(buf,
+ ret = silc_buffer_unformat(&buf,
SILC_STR_UI_INT(&totlen),
SILC_STR_END);
- if (ret == -1) {
- silc_buffer_free(buf);
+ if (ret == -1)
return FALSE;
- }
#if 1 /* Backwards support, remove! */
if (totlen == data_len)
totlen -= 4;
#endif
- if (totlen + 4 != data_len) {
- silc_buffer_free(buf);
+ if (totlen + 4 != data_len)
return FALSE;
- }
/* Get algorithm name and identifier */
- silc_buffer_pull(buf, 4);
+ silc_buffer_pull(&buf, 4);
ret =
- silc_buffer_unformat(buf,
+ silc_buffer_unformat(&buf,
SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
SILC_STR_END);
}
/* Get key data. We assume that rest of the buffer is key data. */
- silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
- key_len = buf->len;
- ret = silc_buffer_unformat(buf,
+ silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
+ key_len = buf.len;
+ ret = silc_buffer_unformat(&buf,
SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
SILC_STR_END);
if (ret == -1)
(*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
}
- silc_buffer_free(buf);
return TRUE;
err:
- if (pkcs_name)
- silc_free(pkcs_name);
- if (ident)
- silc_free(ident);
- if (key_data)
- silc_free(key_data);
- silc_buffer_free(buf);
+ silc_free(pkcs_name);
+ silc_free(ident);
+ silc_free(key_data);
return FALSE;
}
SilcUInt32 totlen;
totlen = 2 + strlen(private_key->name) + private_key->prv_len;
- buf = silc_buffer_alloc(totlen);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(totlen);
+ if (!buf)
+ return NULL;
silc_buffer_format(buf,
SILC_STR_UI_SHORT(strlen(private_key->name)),
SILC_STR_UI_XNSTRING(private_key->prv,
private_key->prv_len),
SILC_STR_END);
- if (len)
- *len = totlen;
- ret = silc_calloc(buf->len, sizeof(*ret));
- memcpy(ret, buf->data, buf->len);
- silc_buffer_clear(buf);
+ ret = silc_buffer_steal(buf, len);
silc_buffer_free(buf);
-
return ret;
}
SilcUInt32 totlen;
totlen = 2 + strlen(pkcs) + prv_len;
- buf = silc_buffer_alloc(totlen);
- silc_buffer_pull_tail(buf, totlen);
+ buf = silc_buffer_alloc_size(totlen);
+ if (!buf)
+ return NULL;
silc_buffer_format(buf,
SILC_STR_UI_SHORT(strlen(pkcs)),
SILC_STR_UI32_STRING(pkcs),
SILC_STR_UI_XNSTRING(prv, prv_len),
SILC_STR_END);
- if (len)
- *len = totlen;
- ret = silc_calloc(buf->len, sizeof(*ret));
- memcpy(ret, buf->data, buf->len);
- silc_buffer_clear(buf);
+ ret = silc_buffer_steal(buf, len);
silc_buffer_free(buf);
-
return ret;
}
bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
SilcPrivateKey *private_key)
{
- SilcBuffer buf;
+ SilcBufferStruct buf;
SilcPKCS alg;
SilcUInt16 pkcs_len;
SilcUInt32 key_len;
unsigned char *pkcs_name = NULL, *key_data = NULL;
int ret;
- buf = silc_buffer_alloc(data_len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
- silc_buffer_put(buf, data, data_len);
+ silc_buffer_set(&buf, data, data_len);
/* Get algorithm name and identifier */
ret =
- silc_buffer_unformat(buf,
+ silc_buffer_unformat(&buf,
SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
SILC_STR_END);
if (ret == -1) {
goto err;
}
- if (pkcs_len < 1 || pkcs_len > buf->truelen) {
+ if (pkcs_len < 1 || pkcs_len > buf.truelen) {
SILC_LOG_DEBUG(("Malformed private key buffer"));
goto err;
}
}
/* Get key data. We assume that rest of the buffer is key data. */
- silc_buffer_pull(buf, 2 + pkcs_len);
- key_len = buf->len;
- ret = silc_buffer_unformat(buf,
+ silc_buffer_pull(&buf, 2 + pkcs_len);
+ key_len = buf.len;
+ ret = silc_buffer_unformat(&buf,
SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
SILC_STR_END);
if (ret == -1)
(*private_key)->prv_len = key_len;
}
- silc_buffer_clear(buf);
- silc_buffer_free(buf);
return TRUE;
err:
- if (pkcs_name)
- silc_free(pkcs_name);
- if (key_data)
- silc_free(key_data);
- silc_buffer_clear(buf);
- silc_buffer_free(buf);
+ silc_free(pkcs_name);
+ silc_free(key_data);
return FALSE;
}
{
SilcBuffer buf;
SilcUInt32 len;
+ unsigned char *tmp = NULL;
switch(encoding) {
case SILC_PKCS_FILE_BIN:
break;
case SILC_PKCS_FILE_PEM:
- data = silc_pem_encode_file(data, data_len);
+ tmp = data = silc_pem_encode_file(data, data_len);
data_len = strlen(data);
break;
}
len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
- buf = silc_buffer_alloc(len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(len);
+ if (!buf) {
+ silc_free(tmp);
+ return FALSE;
+ }
silc_buffer_format(buf,
SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
/* Save into file */
if (silc_file_writefile(filename, buf->data, buf->len)) {
+ silc_free(tmp);
silc_buffer_free(buf);
return FALSE;
}
+ silc_free(tmp);
silc_buffer_free(buf);
return TRUE;
}
SilcUInt32 silc_rng_get_rn32(SilcRng rng)
{
unsigned char rn[4];
- SilcUInt16 num;
+ SilcUInt32 num;
rn[0] = silc_rng_get_byte(rng);
rn[1] = silc_rng_get_byte(rng);
*
* DESCRIPTION
*
- * Return the size of the integer in base `base'. Note that this size
- * is probably only an approximation. However, it is guaranteed that
- * the returned size is always at least the size of the integer, however,
- * it may be larger.
+ * Return the size of the integer in base `base'.
+ *
+ * NOTES
+ *
+ * For any other base but 2 this function usually returns only an
+ * approximated size in the base. It is however guaranteed that the
+ * the returned size is always at least the size of the integer or
+ * larger.
+ *
+ * For base 2 this returns the exact bit-size of the integer.
*
***/
size_t silc_mp_sizeinbase(SilcMPInt *mp, int base);
* Set `dst' integer from string `str' of base `base'. The `dst' must
* already be initialized.
*
+ * NOTES
+ *
+ * For base 2 the string must be in ASCII bit presentation, not in
+ * binary. Use the silc_mp_bin2mp to decode binary into integer.
+ *
***/
void silc_mp_set_str(SilcMPInt *dst, const char *str, int base);
* must already have space allocated. The function returns the same
* as `str' or NULL on error.
*
+ * NOTES
+ *
+ * For base 2 the returned string is in ASCII bit presentation, not
+ * in binary. Use the silc_mp_mp2bin to encode integer into binary.
+ *
***/
char *silc_mp_get_str(char *str, SilcMPInt *mp, int base);
if (status != SILC_SKE_STATUS_OK)
return status;
- /* Take a copy of the payload buffer for future use. It is used to
- compute the HASH value. */
- ske->start_payload_copy = silc_buffer_copy(payload_buf);
- ske->start_payload = start_payload;
-
/* Send the packet. */
if (ske->callbacks->send_packet)
(*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
ske->callbacks->context);
- silc_buffer_free(payload_buf);
+ /* Save the the payload buffer for future use. It is later used to
+ compute the HASH value. */
+ ske->start_payload_copy = payload_buf;
+ ske->start_payload = start_payload;
return status;
}
ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
return ske->status;
}
- payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
- memcpy(payload->sign_data, sign, sign_len);
- memset(sign, 0, sizeof(sign));
+ payload->sign_data = silc_memdup(sign, sign_len);
payload->sign_len = sign_len;
+ memset(sign, 0, sizeof(sign));
}
status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
if (status != SILC_SKE_STATUS_OK)
goto err;
- ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
- memcpy(ske->hash, hash, hash_len);
+ ske->hash = silc_memdup(hash, hash_len);
ske->hash_len = hash_len;
SILC_LOG_DEBUG(("Verifying signature (HASH)"));
ske->users++;
(*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
- payload->pk_type, ske->callbacks->context,
- silc_ske_initiator_finish_final, NULL);
+ payload->pk_type, ske->callbacks->context,
+ silc_ske_initiator_finish_final, NULL);
/* We will continue to the final state after the public key has
been verified by the caller. */
err:
if (remote_payload)
silc_ske_payload_start_free(remote_payload);
- if (payload)
- silc_free(payload);
+ silc_free(payload);
if (status == SILC_SKE_STATUS_OK)
return SILC_SKE_STATUS_ERROR;
if (status != SILC_SKE_STATUS_OK)
goto err;
- ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
- memcpy(ske->hash, hash, hash_len);
+ ske->hash = silc_memdup(hash, hash_len);
ske->hash_len = hash_len;
SILC_LOG_DEBUG(("Signing HASH value"));
status = SILC_SKE_STATUS_SIGNATURE_ERROR;
goto err;
}
- ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
- memcpy(ske->ke2_payload->sign_data, sign, sign_len);
- memset(sign, 0, sizeof(sign));
+ ske->ke2_payload->sign_data = silc_memdup(sign, sign_len);
ske->ke2_payload->sign_len = sign_len;
+ memset(sign, 0, sizeof(sign));
}
ske->ke2_payload->pk_type = pk_type;
SilcSKEStatus silc_ske_end(SilcSKE ske)
{
- SilcBuffer packet;
+ SilcBufferStruct packet;
+ unsigned char data[4];
SILC_LOG_DEBUG(("Start"));
- packet = silc_buffer_alloc_size(4);
- if (!packet)
- return SILC_SKE_STATUS_OUT_OF_MEMORY;
- silc_buffer_format(packet,
- SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
- SILC_STR_END);
+ SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, data);
+ silc_buffer_set(&packet, data, 4);
if (ske->callbacks->send_packet)
- (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
+ (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_SUCCESS,
ske->callbacks->context);
- silc_buffer_free(packet);
-
return SILC_SKE_STATUS_OK;
}
SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
{
- SilcBuffer packet;
+ SilcBufferStruct packet;
+ unsigned char data[4];
SILC_LOG_DEBUG(("Start"));
if (status > SILC_SKE_STATUS_INVALID_COOKIE)
status = SILC_SKE_STATUS_BAD_PAYLOAD;
- packet = silc_buffer_alloc_size(4);
- if (!packet)
- return SILC_SKE_STATUS_OUT_OF_MEMORY;
- silc_buffer_format(packet,
- SILC_STR_UI_INT((SilcUInt32)status),
- SILC_STR_END);
+ SILC_PUT32_MSB((SilcUInt32)status, data);
+ silc_buffer_set(&packet, data, 4);
if (ske->callbacks->send_packet)
- (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
+ (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_FAILURE,
ske->callbacks->context);
- silc_buffer_free(packet);
-
return SILC_SKE_STATUS_OK;
}
{
if (sb) {
#if defined(SILC_DEBUG)
- memset(sb->head, 'F', sb->truelen);
+ if (sb->head)
+ memset(sb->head, 'F', sb->truelen);
#endif
silc_free(sb->head);
silc_free(sb);
}
}
+/****f* silcutil/SilcBufferAPI/silc_buffer_steal
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len);
+ *
+ * DESCRIPTION
+ *
+ * Steals the data from the buffer `sb'. This returns pointer to the
+ * start of the buffer and the true length of that buffer. The `sb'
+ * cannot be used anymore after calling this function because the
+ * data buffer was stolen. The `sb' must be freed with silc_buffer_free.
+ * The caller is responsible of freeing the stolen data buffer with
+ * silc_free.
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len)
+{
+ unsigned char *buf = sb->head;
+ if (data_len)
+ *data_len = sb->truelen;
+ sb->head = sb->data = sb->tail = sb->end = NULL;
+ sb->len = sb->truelen = 0;
+ return buf;
+}
+
/****f* silcutil/SilcBufferAPI/silc_buffer_set
*
* SYNOPSIS
goto ok;
dst->head = silc_realloc(dst->head, sizeof(*dst->head) *
- (strlen(string) + len));
+ (strlen(string) + len + 1));
+ if (!dst->head)
+ return -1;
memcpy(dst->head + len, string, strlen(string));
len += strlen(string);
+ dst->head[len] = '\0';
}
SILC_LOG_DEBUG(("Error occured while formatting buffer"));
ok:
dst->end = dst->head + len;
- dst->tail = dst->data = dst->end;
- dst->len = 0;
- dst->truelen = len;
+ dst->data = dst->head;
+ dst->tail = dst->end;
+ dst->len = dst->truelen = len;
va_end(va);
return len;
silcconfig.c
- Author: Johnny Mnemonic <johnny@themnemonic.org>
+ Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 2002 - 2003 Giovanni Giacobbi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
}
return NULL;
}
-/* ... */
+/* Converts a string in the type specified. returns a dynamically
+ * allocated pointer. */
static void *silc_config_marshall(SilcConfigType type, const char *val)
{
void *pt;
}
else {
void *pt;
- int ret;
+ int ret = 0; /* very important in case of no cb */
if (*(*p)++ != '=')
return SILC_CONFIG_EEXPECTEDEQUAL;
pt = silc_config_marshall(thisopt->type, buf);
if (!pt)
return SILC_CONFIG_EINVALIDTEXT;
- if (thisopt->cb) {
+ if (thisopt->cb)
ret = thisopt->cb(thisopt->type, thisopt->name, file->line,
pt, thisopt->context);
- if (ret) {
- SILC_CONFIG_DEBUG(("Callback refused the value [ret=%d]", ret));
- return ret;
- }
- }
+
+ /* since we have to free "pt" both on failure and on success, we
+ assume that ret == 0 if we didn't actually call any cb. */
silc_free(pt);
+ if (ret) {
+ SILC_CONFIG_DEBUG(("Callback refused the value [ret=%d]", ret));
+ return ret;
+ }
}
continue;
silcconfig.h
- Author: Johnny Mnemonic <johnny@themnemonic.org>
+ Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 2002 - 2003 Giovanni Giacobbi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
silclog.c
- Author: Johnny Mnemonic <johnny@themnemonic.org>
+ Author: Giovanni Giacobbi <giovanni@giacobbi.net>
Copyright (C) 1997 - 2002 Pekka Riikonen
silclog.h
- Author: Johnny Mnemonic <johnny@themnemonic.org>
+ Author: Giovanni Giacobbi <giovanni@giacobbi.net>
Copyright (C) 1997 - 2002 Pekka Riikonen
task = schedule->generic_queue->task;
while(1) {
- /* Validity of the task is checked always before and after
+ /* Validity of the task and fd is checked always before and after
execution beacuse the task might have been unregistered
in the callback function, ie. it is not valid anymore. */
/* Is the task ready for reading */
- if (task->valid && schedule->fd_list[i].revents & SILC_TASK_READ) {
+ if (task->valid && schedule->fd_list[i].revents & SILC_TASK_READ &&
+ fd == schedule->fd_list[i].fd) {
silc_mutex_unlock(schedule->generic_queue->lock);
SILC_SCHEDULE_UNLOCK(schedule);
task->callback(schedule, schedule->app_context,
}
/* Is the task ready for writing */
- if (task->valid && schedule->fd_list[i].revents & SILC_TASK_WRITE) {
+ if (task->valid && schedule->fd_list[i].revents & SILC_TASK_WRITE &&
+ fd == schedule->fd_list[i].fd) {
silc_mutex_unlock(schedule->generic_queue->lock);
SILC_SCHEDULE_UNLOCK(schedule);
task->callback(schedule, schedule->app_context,
if (!schedule->valid)
return NULL;
- SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd,
- type, priority));
-
queue = SILC_SCHEDULE_GET_QUEUE(type);
/* If the task is generic task, we check whether this task has already
if (type == SILC_TASK_GENERIC) {
silc_mutex_lock(queue->lock);
+ SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd,
+ type, priority));
+
if (queue->task) {
SilcTask task = queue->task;
while(1) {
}
newtask = silc_calloc(1, sizeof(*newtask));
+ if (!newtask)
+ return NULL;
+
+ SILC_LOG_DEBUG(("Registering new task %p, fd=%d type=%d priority=%d",
+ newtask, fd, type, priority));
+
newtask->fd = fd;
newtask->context = context;
newtask->callback = callback;
return TRUE;
}
- SILC_LOG_DEBUG(("Removing task"));
+ SILC_LOG_DEBUG(("Removing task %p", task));
/* Unregister the task */
old = first;
typedef unsigned long long SilcUInt64;
typedef signed long long SilcInt64;
#else
-typedef SilcUInt32 SilcUInt64; /* XXX Use Windows's own 64 bit types */
-typedef SilcInt32 SilcInt64;
+typedef unsigned __int64 SilcUInt64;
+typedef signed __int64 SilcInt64;
#endif
#else
typedef SilcUInt32 SilcUInt64;
/* Macros */
-#define GET_WORD(cp) ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24 \
- | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16) \
- | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8) \
+#define SILC_GET_WORD(cp) ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24 \
+ | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16) \
+ | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8) \
| ((SilcUInt32)(SilcUInt8)(cp)[3])
/****d* silcutil/SILCTypes/SILC_GET16_MSB
*
* SOURCE
*/
-#define SILC_GET64_MSB(l, cp) \
-do { \
- (l) = ((((SilcUInt64)GET_WORD((cp))) << 32) | \
- ((SilcUInt64)GET_WORD((cp) + 4))); \
+#define SILC_GET64_MSB(l, cp) \
+do { \
+ (l) = ((((SilcUInt64)SILC_GET_WORD((cp))) << 32) | \
+ ((SilcUInt64)SILC_GET_WORD((cp) + 4))); \
} while(0)
/***/
} while(0)
/***/
+/****d* silcutil/SILCTypes/SILC_SWAB_16
+ *
+ * NAME
+ *
+ * #define SILC_SWAB_16 ...
+ *
+ * DESCRIPTION
+ *
+ * Swabs 16-bit unsigned integer byte order.
+ *
+ * SOURCE
+ */
+#define SILC_SWAB_16(l) \
+ ((SilcUInt16)(((SilcUInt16)(l) & (SilcUInt16)0x00FFU) << 8) | \
+ (((SilcUInt16)(l) & (SilcUInt16)0xFF00U) >> 8))
+/***/
+
+/****d* silcutil/SILCTypes/SILC_SWAB_32
+ *
+ * NAME
+ *
+ * #define SILC_SWAB_32 ...
+ *
+ * DESCRIPTION
+ *
+ * Swabs 32-bit unsigned integer byte order.
+ *
+ * SOURCE
+ */
+#define SILC_SWAB_32(l) \
+ ((SilcUInt32)(((SilcUInt32)(l) & (SilcUInt32)0x000000FFUL) << 24) | \
+ (((SilcUInt32)(l) & (SilcUInt32)0x0000FF00UL) << 8) | \
+ (((SilcUInt32)(l) & (SilcUInt32)0x00FF0000UL) >> 8) | \
+ (((SilcUInt32)(l) & (SilcUInt32)0xFF000000UL) >> 24))
+/***/
+
#endif /* SILCTYPES_H */
{
SilcSocketConnection sock = context;
sock->qos->applied = TRUE;
- silc_schedule_set_listen_fd(sock->qos->schedule, sock->sock,
- (SILC_TASK_READ | SILC_TASK_WRITE), TRUE);
+ if (sock->users > 1)
+ silc_schedule_set_listen_fd(sock->qos->schedule, sock->sock,
+ (SILC_TASK_READ | SILC_TASK_WRITE), TRUE);
sock->qos->applied = FALSE;
silc_socket_free(sock);
}
# SILC Distribution versions. Set here or give the version on the command
# line as argument.
#
-SILC_VERSION=0.9.7 # Base version
+SILC_VERSION=0.9.8 # Base version
#############################################################################
#
# stripspaces.tcl - strip trailing spaces from source files
#
-# Author: Johnny Mnemonic <johnny@themnemonic.org>
+# Author: Giovanni Giacobbi <giovanni@giacobbi.net>
#
-# Copyright (C) 2002 Johnny Mnemonic
+# Copyright (C) 2002 - 2003 Giovanni Giacobbi
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
silc_install_prefix=@prefix@
SILC_COMMON_LIBS= @LIBS@ -L$(silc_install_prefix)/lib \
- -L/usr/local/silc/lib -lsilc -lsilcclient
+ -L/usr/local/silc/lib -lsilc -lsilcclient -lsilc
SILC_CFLAGS=@CFLAGS@
CC=@CC@
LIBTOOL = @LIBTOOL@