Merge branch 'silc.1.1.branch' of silc repo
authorPekka Riikonen <priikone@silcnet.org>
Mon, 9 Jun 2008 13:50:02 +0000 (16:50 +0300)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 9 Jun 2008 13:50:02 +0000 (16:50 +0300)
Conflicts:

CHANGES
Makefile.ad
Makefile.defines_int.in
README.PLUGIN
TODO
apps/Makefile.ad
apps/autodist/CHANGES
apps/autodist/autodist.in
apps/autodist/doc/autodist.1.in
apps/autodist/doc/autodist.texi
apps/irssi/Makefile.am
apps/irssi/configure.ad
apps/irssi/configure.in
apps/irssi/docs/Makefile.am
apps/irssi/docs/help/Makefile.am.gen
apps/irssi/docs/help/in/cmode.in
apps/irssi/docs/help/in/cumode.in
apps/irssi/docs/help/in/key.in
apps/irssi/scripts/Makefile.am
apps/irssi/scripts/examples/Makefile.am
apps/irssi/src/Makefile.am
apps/irssi/src/core/Makefile.am
apps/irssi/src/core/modules-load.c
apps/irssi/src/fe-common/silc/Makefile.am
apps/irssi/src/fe-common/silc/fe-common-silc.c
apps/irssi/src/fe-common/silc/fe-silc-messages.c
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/fe-text/Makefile.am
apps/irssi/src/perl/Makefile.am
apps/irssi/src/silc/core/Makefile.am
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/clientutil.c
apps/irssi/src/silc/core/silc-core.c
apps/irssi/src/silc/core/silc-servers.c
apps/silcd/Makefile.am
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_backup.c
apps/silcd/server_http.c
apps/silcd/server_internal.h
apps/silcd/server_query.c
apps/silcd/server_query.h
apps/silcd/server_util.c
apps/silcd/server_util.h
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
apps/silcd/serverid.c
apps/silcd/silcd.c
configure.ad
distdir/autodist
distdir/client
distdir/common
distdir/default
distdir/post-dist
distdir/pre-dist-client
distdir/pre-dist-toolkit
distdir/server
distdir/toolkit
doc/Makefile.ad
doc/example_silcd.conf.in
doc/examples/silcd.prv
doc/examples/silcd.pub
doc/silcalgs.conf
doc/silcd.conf.yo
includes/silc.h.in
includes/silcversion.h.in
lib/Makefile.ad
lib/configure.ad
lib/contrib/Makefile.ad
lib/doc/command_reply_args.html
lib/doc/notifyargs.html
lib/doc/porting.html
lib/doc/silcclient_using.html
lib/silcapputil/silcapputil.c
lib/silcapputil/silcidcache.c
lib/silcapputil/silcidcache.h
lib/silcasn1/silcasn1_decode.c
lib/silcasn1/silcasn1_encode.c
lib/silcclient/client.c
lib/silcclient/client_connect.c
lib/silcclient/client_entry.c
lib/silcclient/client_entry.h
lib/silcclient/client_keyagr.c
lib/silcclient/client_notify.c
lib/silcclient/client_register.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/silcclient.h
lib/silcclient/silcclient_entry.h
lib/silccore/DIRECTORY
lib/silccore/README
lib/silccore/silcargument.c
lib/silccore/silcattrs.c
lib/silccore/silcnotify.c
lib/silccore/silcpacket.c
lib/silccore/silcpacket.h
lib/silccrypt/Makefile.ad
lib/silccrypt/aes.c
lib/silccrypt/aes_x86.asm
lib/silccrypt/aes_x86_64.asm
lib/silccrypt/ciphers.h
lib/silccrypt/configure.ad
lib/silccrypt/rijndael_internal.h
lib/silccrypt/silccipher.c
lib/silccrypt/silcpk.c
lib/silccrypt/silcpkcs.c
lib/silccrypt/silcpkcs1.c
lib/silcmath/configure.ad
lib/silcsftp/sftp_client.c
lib/silcsftp/sftp_fs_memory.c
lib/silcsim/Makefile.ad
lib/silcske/silcconnauth.c
lib/silcske/silcske.c
lib/silcske/silcske.h
lib/silcskr/silcskr.c
lib/silcutil/silcatomic.h
lib/silcutil/silcbuffer.h
lib/silcutil/silcbuffmt.c
lib/silcutil/silcdlist.h
lib/silcutil/silcfsm.c
lib/silcutil/silclog.c
lib/silcutil/silcmime.c
lib/silcutil/silcnet.h
lib/silcutil/silcschedule.c
lib/silcutil/silcschedule.h
lib/silcutil/silcschedule_i.h
lib/silcutil/silcsocketstream_i.h
lib/silcutil/silcstack.h
lib/silcutil/silctime.c
lib/silcutil/silcutil.c
lib/silcutil/stacktrace.c
lib/silcutil/tests/test_silcschedule.c
lib/silcutil/unix/silcunixnet.c
lib/silcutil/unix/silcunixthread.c
tutorial/mybot/Makefile
tutorial/mybot/mybot.c
win32/libsilc/libsilc.def
win32/libsilcclient/libsilcclient.def

1  2 
CHANGES
distdir/post-dist
lib/silcutil/silcbuffmt.c
lib/silcutil/silcconfig.c
lib/silcutil/silcfdstream.c
lib/silcutil/silcsocketstream.c
lib/silcutil/silcsocketstream_i.h
lib/silcutil/unix/silcunixnet.c
lib/silcutil/unix/silcunixschedule.c
lib/silcutil/unix/silcunixsocketstream.c

diff --combined CHANGES
index c5f1ab5111d546ea09568ecaad423ac39a62ea4f,128c76fc0e4f0c678163c10a901c6b3d6d69f297..9128a66f2e584adfbce11922e600ca969e654456
+++ b/CHANGES
 -      
+ Thu Mar 13 13:31:35 EET 2008  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed silcd crash in NEW_CLIENT packet handling when nickname
+         is not present in the packet.  Affected files are
+         apps/silcd/packet_receive.c.
+ Fri Feb 22 16:12:27 EET 2008  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed partial encryption in CTR mode in AES.  Change does not
+         affect interoperability in SILC due to the way CTR is used in
+         SILC.  But, fixed anyway.  Affected files are
+         lib/silccrypt/aes.c and rijndael_internal.h.
+ Tue Jan  8 09:41:57 EET 2008  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed printable fingerprint bufferoverlfow, RedHat bug 372021.
+         Affected file is lib/silcutil/silcutil.c.
+ Sun Dec 30 14:00:46 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed unix signal delivery in SILC scheduler.  Affected file
+         is lib/silcutil/unix/silcunixschedule.c.
+ Sun Nov 18 16:43:04 CET 2007  Jochen Eisinger <coffee@silcnet.org>
+       * Add -avoid-version and -rpath flags when compiling the plugin.
+         Affected file is apps/irssi/src/fe-common/silc/Makefile.in
+ Thu Nov 15 18:03:53 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Reprocess JOIN command synchronously after resolving channel
+         user list.  Affected file is lib/silcclient/command_reply.c.
+       * In JOIN command reply check if the channel key is already
+         saved.  If it is we have received new key from server while
+         resolving user and must not save the old key.  Affected file
+         is lib/silcclient/command_reply.c.
+       * Remove all channel keys and hmacs after giving LEAVE command.
+         Affected file is lib/silcclient/command_reply.c.
+ Tue Nov 13 18:24:56 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Added missing channel unreferencing in CMODE, CUMODE,
+         TOPIC, INVITE, BAN and KICK command replies.  Affected
+         file is lib/silcclient/command_reply.c.
+ Sun Nov 11 23:04:54 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+       * Free stream data and abort ongoing protocols correctly
+         for primary router connections receiving end of stream.
+         Affected file is apps/silcd/server.c.
+ Sun Nov 11 16:02:12 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+       * SILC Server 1.1 Beta4.
+ Sun Nov 11 14:15:48 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * SILC Toolkit 1.1.5.
++
+ Sun Nov 11 11:22:35 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed connection authentication with public keys to use
+         correct public key as responder.  Affected file is
+         lib/silcske/silcconnauth.c.
+       * Fixed public key authentication in server.  Affected file is
+         apps/silcd/serverconfig.c.
+       * Fixed OPER and SILCOPER public key authentication.  Affected
+         file is apps/silcd/server.c.
+       * Fixed prefer_passphrase_auth flag in server.  Fixed
+         disconnection of unauthenticated connection.  Affected file is
+         apps/silcd/server.c.
+       * Fixed client resuming in server.  Affected file is
+         apps/silcd/packet_receive.c.
+       * Fixed IDENTIFY and WHOWAS command reply to correctly update
+         client entries (fixes a crash).  Affected file is
+         apps/silcd/command_reply.c.
+ Tue Nov  6 16:39:20 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * SILC Client 1.1.3.
+ Mon Nov  5 23:07:58 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Zero tail of CTR mode IV in IV Included mode.  Change does
+         not cause compatibility issues.  Affected file is
+         lib/silcske/silcske.c.
+ Mon Nov  5 22:24:25 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * SILC Toolkit 1.1.4.
+       * Fixed CTR mode rekey.  Affected file is lib/silcske/silcske.c.
+       * Rewrote the IV Included CTR mode encryption/decryption in
+         packet engine.  Affected file is lib/silccore/silcpacket.c.
+ Sun Nov  4 15:20:25 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Removed module_path and module options from the server
+         config file format.  Affected file is apps/silcd/serverconfig.c.
+       * Fixed non-IPv6 compilation error.  Affected file is
+         lib/silcutil/unix/silcunixnet.c.
+ Sat Nov  3 23:23:38 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Do not free packet engine before uninitializing scheduler.
+         Do not disconnct already disconnected streams.  Affected
+         files are in apps/silcd/.
+       * Fixed setting correct ID for re-encrypted channel messages
+         in router-to-router connections.  Affected file is
+         apps/silcd/packet_send.c.
+ Sun Sep 30 15:16:18 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed channel private key deleting when deleting the channel.
+         Affected file is lib/silcclient/client_channel.c.
+ Sun Sep  9 17:52:49 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+       * SILC Toolkit 1.1.3.
+       * Fixed possible buffer overflows from SILC Config code.
+         Patch from Jérémy Bobbio.  Affected file is
+         lib/silcutil/silcconfig.c.
+ Sun Aug 26 12:28:49 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed TIMEOUT handling in user info resolving during JOINing,
+         fixes crash.  Affected file is lib/silcclient/client_notify.c.
+       * Fixed mandatory UN and HN SILC public key identifier checking
+         (both must be present).  Affected file is
+         lib/silccrypt/silcpk.c.
+ Tue Aug  7 20:56:06 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed alignment issues with 64-bit CPUs.  Affected files
+         are lib/silcutil/silcschedule.c and unix/silcunixschedule.c.
+       * Added "There are now xx nick's" to "are xx nicks".  Affected
+         file is apps/irssi/src/fe-common/silc/module-formats.c.
+ Sat Aug 4 18:37:22 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+       * Fixed USERS command user mode handling (integer overflow).
+         Affected file is lib/silcclient/command_reply.c.
+ Thu Jul 19 21:08:49 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+       * Fixed big-endian issues from aes implementation.  Affected
+         files are lib/silccrypt/aes.c.
+       * Fixed lib/silcutil/silcatomic.h compilation on IA64.  Patch
+         from Jérémy Bobbio.
+       * Fixed public key identifier parsing to check lengths
+         correctly.  Affected file is lib/silccrypt/silcpk.c.
+ Wed Jul  4 08:06:38 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+       * SILC Toolkit 1.1.2.
+       * SILC Client 1.1.2.
+ Mon Jul  2 17:28:47 CEST 2007  Pekka Riikonen <priikone@silcnet.org>
+       * In silc_client_free check that scheduler is allocated before
+         trying to free it.  Affected file is lib/silcclient/client.c.
+       * Fixed buffer overflow in NICK_CHANGE notify.  The destination
+         buffer for old nickname was too small.  Affected file is
+         lib/silclient/client_notify.c.
  Sun Jul  1 19:15:15 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
  
        * SILC Server 1.1 Beta1.
@@@ -61,7 -243,7 +243,7 @@@ Mon Jun 18 23:47:22 EEST 2007  Pekka Ri
        * Use SILC_VERIFY to assert that silc_rwlock_wrlock can be
          called only once per thread on Unix.  Affected file is
          lib/silcutil/unix/silcunixthread.c.  Added same for mutex
-         as well.   Documented same on the API in 
+         as well.   Documented same on the API in
          lib/silcutil/silcmutex.h.
  
        * Fixed USERS command reply write-lock unlocking.  Affected file
@@@ -84,7 -266,7 +266,7 @@@ Thu Jun 14 21:15:31 CEST 2007  Jochen E
          apps/irssi/src/core/modules-load.c
  
        * Don't delete hilight entry (because it's just a pointer, not a
-         copy).  Affected file is 
+         copy).  Affected file is
          apps/irssi/src/fe-common/silc/fe-silc-messages.c
  
  Mon Jun 11 22:10:17 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
@@@ -135,7 -317,7 +317,7 @@@ Thu Jun  7 21:25:31 EEST 2007  Pekka Ri
  
  Wed Jun  6 18:33:05 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
  
-       * Added notify callback to silc_schedule_init which can be used to 
+       * Added notify callback to silc_schedule_init which can be used to
          set a notify callback for scheduler which is called when task is
          added to scheduler or deleted from scheduler.  Affected file
          is lib/silcutil/silcschedule.[ch].
          was very short.  Affected file is lib/silcutil/silcschedule.c.
  
        * Rewrote the SILC scheduler handling in SILC Client to not poll
-         every few msecs but to use the new notify callback.  Affected 
+         every few msecs but to use the new notify callback.  Affected
          file is apps/irssi/src/silc/core/silc-core.c.
  
        * Fixed SFTP client library read buffer size which was too small.
@@@ -320,7 -502,7 +502,7 @@@ Fri May 18 18:10:36 EEST 2007  Pekka Ri
          better.  Affected file is lib/silccilent/client_entry.c.
  
        * Added "foo#2 appears as foo" support to SILC Client when user
-         leaves or quits and one formatted nickname remain.  Affected file 
+         leaves or quits and one formatted nickname remain.  Affected file
          is apps/irssi/src/silc/core/client_ops.c.
  
        * Send SilcChannelEntry to application in SILC_NOTIFY_TYPE_SIGNOFF.
@@@ -382,7 -564,7 +564,7 @@@ Wed May 16 09:34:10 EEST 2007  Pekka Ri
  Tue May 15 23:55:41 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
  
        * Added SILC_VERIFY macro which is equivalent to SILC_ASSERT
-         but is compiled always in.  Affected file is 
+         but is compiled always in.  Affected file is
          lib/silcutil/silclog.h.
  
        * Use SILC_VERIFY in FSM macros instead of SILC_ASSERT which is
@@@ -461,7 -643,7 +643,7 @@@ Wed May  9 19:51:28 EEST 2007  Pekka Ri
          on WIN32.  Affected files are lib/silcutil/silclog_i.h and
          silclog.c.
  
-       * Rewrote WIN32 SILC Scheduler.  It now handles non-blocking file 
+       * Rewrote WIN32 SILC Scheduler.  It now handles non-blocking file
          descriptors and sockets better.  Though, room for optimization
          remains.  Affected file is lib/silcutil/win32/silcwin32schedule.c.
  
diff --combined distdir/post-dist
index cf1f93bdc670098ac3fc24250688dfee898ee5c3,8323ec7e3e6b713952a36784f10838dc61f8916a..3f27c9e9a5d58b7b290c1beadf1a8f49c031d262
@@@ -6,8 -6,9 +6,8 @@@ package=$
  distdir=$4
  
  if test -f $distdir.tar.gz; then
-   sha1sum $distdir.tar.gz > $distdir.tar.gz.sha1
+   sha512sum $distdir.tar.gz > $distdir.tar.gz.sum
  fi
  if test -f $distdir.tar.bz2; then
-   sha1sum $distdir.tar.bz2 > $distdir.tar.bz2.sha1
+   sha512sum $distdir.tar.bz2 > $distdir.tar.bz2.sum
  fi
 -
index 838177d183932c0bb5a9fa465d572ca5b1df459c,98836b61768a3771c2b8a7059db6e7cab728b0d3..db798c4040df70e622b7b1c47a1f4fd4367eccfe
@@@ -4,7 -4,7 +4,7 @@@
  
    Author: Pekka Riikonen <priikone@silcnet.org>
  
 -  Copyright (C) 1997 - 2007 Pekka Riikonen
 +  Copyright (C) 1997 - 2008 Pekka Riikonen
  
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@@ -16,8 -16,9 +16,8 @@@
    GNU General Public License for more details.
  
  */
 -/* $Id$ */
  
 -#include "silc.h"
 +#include "silcruntime.h"
  
  /************************** Types and definitions ***************************/
  
@@@ -30,317 -31,112 +30,317 @@@ do {                                                    
    flen += req;                                                \
  } while(0)
  
 -/* Check that there is data to be unformatted */
 -#define UNFORMAT_HAS_SPACE(b, req)            \
 -do {                                          \
 -  if (silc_unlikely(req > silc_buffer_len(b)))        \
 -    goto fail;                                        \
 -  if (silc_unlikely((req + 1) <= 0))          \
 -    goto fail;                                        \
 +/* Check that buffer has enough room to format data in it, if not
 +   allocate more.  This will append, thus not replacing any existing data. */
 +#define FORMAT_HAS_SPACE_APPEND(s, b, req)                            \
 +do {                                                                  \
 +  if (silc_buffer_len(b) < req)                                               \
 +    if (silc_unlikely(!silc_buffer_sappend(s, b, req - silc_buffer_len(b)))) \
 +      goto fail;                                                      \
 +  flen += req;                                                                \
  } while(0)
  
 +/* Check that there is data to be unformatted */
 +#define UNFORMAT_HAS_SPACE(b, req)                    \
 +do {                                                  \
 +  if (silc_unlikely(req > silc_buffer_len(b))) {      \
 +    silc_set_errno(SILC_ERR_OVERFLOW);                        \
 +    goto fail;                                                \
 +  }                                                   \
 +  if (silc_unlikely((req + 1) <= 0)) {                        \
 +    silc_set_errno(SILC_ERR_OVERFLOW);                        \
 +    goto fail;                                                \
 +  }                                                   \
 +} while(0)
  
 -/******************************* Formatting *********************************/
 -
 -int silc_buffer_format(SilcBuffer dst, ...)
 -{
 -  va_list ap;
 -  int ret;
 -
 -  va_start(ap, dst);
 -  ret = silc_buffer_sformat_vp(NULL, dst, ap);
 -  va_end(ap);
 -
 -  return ret;
 -}
 -
 -int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
 +#if defined(SILC_DEBUG)
 +static const char *silc_param_string(SilcParam fmt)
  {
 -  return silc_buffer_sformat_vp(NULL, dst, ap);
 +  if (fmt == SILC_PARAM_SINT8)
 +    return "SINT8";
 +  if (fmt == SILC_PARAM_UINT8)
 +    return "UINT8";
 +  if (fmt == SILC_PARAM_SINT16)
 +    return "SINT16";
 +  if (fmt == SILC_PARAM_UINT16)
 +    return "UINT16";
 +  if (fmt == SILC_PARAM_SINT32)
 +    return "SINT32";
 +  if (fmt == SILC_PARAM_UINT32)
 +    return "UINT32";
 +  if (fmt == SILC_PARAM_SINT64)
 +    return "SINT64";
 +  if (fmt == SILC_PARAM_UINT64)
 +    return "UINT64";
 +  if (fmt == SILC_PARAM_SICHAR)
 +    return "SICHAR";
 +  if (fmt == (SILC_PARAM_SICHAR | SILC_PARAM_ALLOC))
 +    return "SICHAR ALLOC";
 +  if (fmt == SILC_PARAM_UICHAR)
 +    return "UICHAR";
 +  if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_ALLOC))
 +    return "UICHAR ALLOC";
 +  if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_REPLACE))
 +    return "UICHAR REPLACE";
 +  if (fmt == SILC_PARAM_BUFFER)
 +    return "BUFFER";
 +  if (fmt == (SILC_PARAM_BUFFER | SILC_PARAM_ALLOC))
 +    return "BUFFER ALLOC";
 +  if (fmt == SILC_PARAM_PTR)
 +    return "PTR";
 +  if (fmt == SILC_PARAM_END)
 +    return "END";
 +  if (fmt == SILC_PARAM_UI8_STRING)
 +    return "UI8_STRING";
 +  if (fmt == SILC_PARAM_UI16_STRING)
 +    return "UI16_STRING";
 +  if (fmt == SILC_PARAM_UI32_STRING)
 +    return "UI32_STRING";
 +  if (fmt == SILC_PARAM_UI8_NSTRING)
 +    return "UI8_STRING";
 +  if (fmt == SILC_PARAM_UI16_NSTRING)
 +    return "UI16_STRING";
 +  if (fmt == SILC_PARAM_UI32_NSTRING)
 +    return "UI32_STRING";
 +  if (fmt == (SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC))
 +    return "UI8_STRING ALLOC";
 +  if (fmt == (SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC))
 +    return "UI16_STRING ALLOC";
 +  if (fmt == (SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC))
 +    return "UI32_STRING ALLOC";
 +  if (fmt == (SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC))
 +    return "UI8_STRING ALLOC";
 +  if (fmt == (SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC))
 +    return "UI16_STRING ALLOC";
 +  if (fmt == (SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC))
 +    return "UI32_STRING";
 +  if (fmt == SILC_PARAM_OFFSET)
 +    return "OFFSET";
 +  if (fmt == SILC_PARAM_ADVANCE)
 +    return "ADDVANCE";
 +  if (fmt == SILC_PARAM_FUNC)
 +    return "FUNC";
 +  if (fmt == SILC_PARAM_REGEX)
 +    return "REGEX";
 +  if (fmt == SILC_PARAM_OFFSET_START)
 +    return "OFFSET_START";
 +  if (fmt == SILC_PARAM_OFFSET_END)
 +    return "OFFSET_END";
 +  if (fmt == SILC_PARAM_DELETE)
 +    return "DELETE";
 +  return "";
  }
 +#endif /* SILC_DEBUG */
  
 -int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
 -{
 -  va_list ap;
 -  int ret;
 -
 -  va_start(ap, dst);
 -  ret = silc_buffer_sformat_vp(stack, dst, ap);
 -  va_end(ap);
 -
 -  return ret;
 -}
 +/******************************* Formatting *********************************/
  
 -int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
 +int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
 +                           SilcBool process)
  {
 -  SilcBufferParamType fmt;
 +  SilcParam fmt;
    int flen = 0;
    SilcBool advance = FALSE;
  
    /* Parse the arguments by formatting type. */
    while (1) {
 -    fmt = va_arg(ap, SilcBufferParamType);
 +    fmt = va_arg(ap, SilcParam);
 +
 +#if defined(SILC_DEBUG)
 +    if (process)
 +      SILC_LOG_DEBUG(("Buffer format type %s (%d)",
 +                    silc_param_string(fmt), fmt));
 +#endif /* SILC_DEBUG */
  
 -    switch(fmt) {
 +    switch (fmt) {
      case SILC_PARAM_FUNC:
        {
 -      SilcBufferFormatFunc func = NULL;
 -      SilcBufferSFormatFunc funcs = NULL;
 +      SilcBufferFormatFunc func;
        void *val;
        void *context;
        int tmp_len;
 -      if (!stack)
 -        func = va_arg(ap, SilcBufferFormatFunc);
 -      else
 -        funcs = va_arg(ap, SilcBufferSFormatFunc);
 +
 +      func = va_arg(ap, SilcBufferFormatFunc);
        val = va_arg(ap, void *);
        context = va_arg(ap, void *);
 -      if (!stack)
 -        tmp_len = func(dst, val, context);
 -      else
 -        tmp_len = funcs(stack, dst, val, context);
 +
 +      if (!process)
 +        break;
 +
 +      tmp_len = func(stack, dst, val, context);
        if (tmp_len < 0)
          goto fail;
        if (tmp_len) {
          silc_buffer_pull(dst, tmp_len);
          flen += tmp_len;
        }
 +      break;
        }
 -      break;
 +
 +    case SILC_PARAM_REGEX:
 +      {
 +      const char *regex = va_arg(ap, char *);
 +      SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags);
 +      SilcBufferStruct match;
 +      SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
 +      SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
 +      SilcBool ret;
 +      SilcUInt32 inclusive_pos = 0;
 +      int matched = 0, ret_len;
 +      va_list cp;
 +
 +      if (!process)
 +        break;
 +
 +      if (!regex)
 +        break;
 +
 +      if (match_nl) {
 +      start_nl_match:
 +        /* Match for '\n' in the buffer.  If not found, treat as line
 +           without '\n' (buffer has only one line, or this is last line). */
 +        if (silc_regex_buffer(dst, "\n", &match, NULL))
 +          dst->tail = match.tail;
 +      }
 +
 +      start_match:
 +      /* Match */
 +      ret = silc_regex_buffer(dst, regex, &match, NULL);
 +      ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
 +      if (!ret) {
 +        if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
 +          silc_set_errno(SILC_ERR_NOT_FOUND);
 +          goto fail;
 +        }
 +        goto end_match;
 +      }
 +      matched++;
 +
 +      if (rflags & SILC_STR_REGEX_NOT)
 +        match = *dst;
 +
 +      if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
 +        /* Advance buffer after match */
 +        flen += (match.data - dst->data);
 +        if (!silc_buffer_pull(dst, (match.data - dst->data)))
 +          goto fail;
 +      }
 +
 +      if (rflags & SILC_STR_REGEX_INCLUSIVE) {
 +        inclusive_pos = dst->tail - match.tail;
 +        dst->tail = match.tail;
 +      }
 +
 +      /* Recursively format */
 +      silc_va_copy(cp, ap);
 +      ret_len = silc_buffer_sformat_vp_i(stack, dst, cp, TRUE);
 +      va_end(cp);
 +      if (ret_len < 0)
 +        goto fail;
 +
 +      if (rflags & SILC_STR_REGEX_INCLUSIVE)
 +        if (!silc_buffer_pull_tail(dst, inclusive_pos))
 +          goto fail;
 +
 +      /* Advance buffer after formatting */
 +      flen += ret_len;
 +      if (!silc_buffer_pull(dst, ret_len))
 +        goto fail;
 +
 +      if (match_all && (!match_nl || silc_buffer_len(dst) > 1))
 +        goto start_match;
 +
 +      end_match:
 +      if (match_nl) {
 +        /* Go to next line, it is at the end of the data area.  Adjust
 +           the tail area of the target buffer to show rest of the buffer. */
 +        flen += (dst->tail - dst->data);
 +        if (!silc_buffer_pull(dst, (dst->tail - dst->data)))
 +          goto fail;
 +        if (!silc_buffer_pull_tail(dst, silc_buffer_taillen(dst)))
 +          goto fail;
 +
 +        if (silc_buffer_len(dst) > 0)
 +          goto start_nl_match;
 +      }
 +
 +      /* Skip to the next SILC_PARAM_END */
 +      silc_buffer_sformat_vp_i(NULL, NULL, ap, FALSE);
 +      break;
 +      }
 +
      case SILC_PARAM_UI8_STRING:
      case SILC_PARAM_UI16_STRING:
      case SILC_PARAM_UI32_STRING:
 -    case SILC_PARAM_UI8_STRING_ALLOC:
 -    case SILC_PARAM_UI16_STRING_ALLOC:
 -    case SILC_PARAM_UI32_STRING_ALLOC:
 +    case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
 +    case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
 +    case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
        {
 -      unsigned char *x = va_arg(ap, unsigned char *);
 +      char *x = va_arg(ap, char *);
        SilcUInt32 tmp_len = x ? strlen(x) : 0;
 +
 +      if (!process)
 +        break;
 +
        if (x && tmp_len) {
          FORMAT_HAS_SPACE(stack, dst, tmp_len);
 -        silc_buffer_put(dst, x, tmp_len);
 +        silc_buffer_put(dst, (unsigned char *)x, tmp_len);
          silc_buffer_pull(dst, tmp_len);
        }
        break;
        }
 +
 +    case SILC_PARAM_UICHAR | SILC_PARAM_REPLACE:
 +      {
 +      unsigned char *x = va_arg(ap, unsigned char *);
 +      SilcUInt32 x_len = va_arg(ap, SilcUInt32);
 +
 +      if (!process)
 +        break;
 +
 +      if (!x)
 +        break;
 +
 +      if (silc_buffer_len(dst) == x_len) {
 +        /* Replace */
 +        if (x_len) {
 +          silc_buffer_put(dst, x, x_len);
 +          silc_buffer_pull(dst, x_len);
 +          flen += x_len;
 +        }
 +      } else if (silc_buffer_len(dst) < x_len) {
 +        /* Append */
 +        if (x_len) {
 +          FORMAT_HAS_SPACE_APPEND(stack, dst, x_len);
 +          silc_buffer_put(dst, x, x_len);
 +          silc_buffer_pull(dst, x_len);
 +        }
 +      } else {
 +        /* Delete */
 +        if (x_len) {
 +          silc_buffer_put(dst, x, x_len);
 +          silc_buffer_pull(dst, x_len);
 +          flen += x_len;
 +        }
 +        goto delete_rest;
 +      }
 +      break;
 +      }
 +
      case SILC_PARAM_UI8_NSTRING:
      case SILC_PARAM_UI16_NSTRING:
      case SILC_PARAM_UI32_NSTRING:
 -    case SILC_PARAM_UI_XNSTRING:
 -    case SILC_PARAM_DATA:
 -    case SILC_PARAM_UI8_NSTRING_ALLOC:
 -    case SILC_PARAM_UI16_NSTRING_ALLOC:
 -    case SILC_PARAM_UI32_NSTRING_ALLOC:
 -    case SILC_PARAM_UI_XNSTRING_ALLOC:
 -    case SILC_PARAM_DATA_ALLOC:
 +    case SILC_PARAM_UICHAR:
 +    case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
 +    case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
 +    case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
 +    case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
        {
        unsigned char *x = va_arg(ap, unsigned char *);
        SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
 +
 +      if (!process)
 +        break;
 +
        if (x && tmp_len) {
          FORMAT_HAS_SPACE(stack, dst, tmp_len);
          silc_buffer_put(dst, x, tmp_len);
        }
        break;
        }
 -    case SILC_PARAM_UI8_CHAR:
 +
 +    case SILC_PARAM_UINT8:
        {
        unsigned char x = (unsigned char)va_arg(ap, int);
 +
 +      if (!process)
 +        break;
 +
        FORMAT_HAS_SPACE(stack, dst, 1);
        silc_buffer_put(dst, &x, 1);
        silc_buffer_pull(dst, 1);
        break;
        }
 -    case SILC_PARAM_UI16_SHORT:
 +
 +    case SILC_PARAM_UINT16:
        {
        unsigned char xf[2];
        SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
 +
 +      if (!process)
 +        break;
 +
        FORMAT_HAS_SPACE(stack, dst, 2);
        SILC_PUT16_MSB(x, xf);
        silc_buffer_put(dst, xf, 2);
        silc_buffer_pull(dst, 2);
        break;
        }
 -    case SILC_PARAM_UI32_INT:
 +
 +    case SILC_PARAM_UINT32:
        {
        unsigned char xf[4];
        SilcUInt32 x = va_arg(ap, SilcUInt32);
 +
 +      if (!process)
 +        break;
 +
        FORMAT_HAS_SPACE(stack, dst, 4);
        SILC_PUT32_MSB(x, xf);
        silc_buffer_put(dst, xf, 4);
        silc_buffer_pull(dst, 4);
        break;
        }
 -    case SILC_PARAM_UI64_INT:
 +
 +    case SILC_PARAM_UINT64:
        {
        unsigned char xf[8];
        SilcUInt64 x = va_arg(ap, SilcUInt64);
 +
 +      if (!process)
 +        break;
 +
        FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
        SILC_PUT64_MSB(x, xf);
        silc_buffer_put(dst, xf, sizeof(SilcUInt64));
        silc_buffer_pull(dst, sizeof(SilcUInt64));
        break;
        }
 -    case SILC_PARAM_SI8_CHAR:
 +
 +    case SILC_PARAM_SINT8:
        {
        char x = (char)va_arg(ap, int);
 +
 +      if (!process)
 +        break;
 +
        FORMAT_HAS_SPACE(stack, dst, 1);
 -      silc_buffer_put(dst, &x, 1);
 +      silc_buffer_put(dst, (unsigned char *)&x, 1);
        silc_buffer_pull(dst, 1);
        break;
        }
 -    case SILC_PARAM_SI16_SHORT:
 +
 +    case SILC_PARAM_SINT16:
        {
        unsigned char xf[2];
        SilcInt16 x = (SilcInt16)va_arg(ap, int);
 +
 +      if (!process)
 +        break;
 +
        FORMAT_HAS_SPACE(stack, dst, 2);
        SILC_PUT16_MSB(x, xf);
        silc_buffer_put(dst, xf, 2);
        silc_buffer_pull(dst, 2);
        break;
        }
 -    case SILC_PARAM_SI32_INT:
 +
 +    case SILC_PARAM_SINT32:
        {
        unsigned char xf[4];
        SilcInt32 x = va_arg(ap, SilcInt32);
 +
 +      if (!process)
 +        break;
 +
        FORMAT_HAS_SPACE(stack, dst, 4);
        SILC_PUT32_MSB(x, xf);
        silc_buffer_put(dst, xf, 4);
        silc_buffer_pull(dst, 4);
        break;
        }
 -    case SILC_PARAM_SI64_INT:
 +
 +    case SILC_PARAM_SINT64:
        {
        unsigned char xf[8];
        SilcInt64 x = va_arg(ap, SilcInt64);
 +
 +      if (!process)
 +        break;
 +
        FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
        SILC_PUT64_MSB(x, xf);
        silc_buffer_put(dst, xf, sizeof(SilcInt64));
        silc_buffer_pull(dst, sizeof(SilcInt64));
        break;
        }
 +
      case SILC_PARAM_BUFFER:
 -    case SILC_PARAM_BUFFER_ALLOC:
 +    case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
        {
        SilcBuffer x = va_arg(ap, SilcBuffer);
        unsigned char xf[4];
 +
 +      if (!process)
 +        break;
 +
        if (x && silc_buffer_len(x)) {
          FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
          SILC_PUT32_MSB(silc_buffer_len(x), xf);
        }
        }
        break;
 +
 +    case SILC_PARAM_DELETE:
 +      {
 +      int n = va_arg(ap, int);
 +
 +      if (!process)
 +        break;
 +
 +      if (n == -1) {
 +        /* Move all data from tail to data area */
 +        if (dst->data != dst->tail) {
 +        delete_rest:
 +          n = silc_buffer_len(dst);
 +          memmove(dst->data, dst->tail, silc_buffer_taillen(dst));
 +          silc_buffer_push_tail(dst, n);
 +          if (!silc_buffer_srealloc(stack, dst,
 +                                    silc_buffer_truelen(dst) - n))
 +            goto fail;
 +        }
 +        break;
 +      }
 +
 +      if (n > silc_buffer_len(dst))
 +        goto fail;
 +
 +      memmove(dst->data, dst->data + n, (silc_buffer_len(dst) - n) +
 +              silc_buffer_taillen(dst));
 +      silc_buffer_push_tail(dst, silc_buffer_len(dst) - n);
 +      if (!silc_buffer_srealloc(stack, dst, silc_buffer_truelen(dst) - n))
 +        goto fail;
 +
 +      break;
 +      }
 +
      case SILC_PARAM_OFFSET:
        {
        int offst = va_arg(ap, int);
 +
 +      if (!process)
 +        break;
 +
        if (!offst)
          break;
 +
        if (offst > 1) {
 -        if (offst > silc_buffer_len(dst))
 +        if (offst > silc_buffer_len(dst)) {
 +          silc_set_errno(SILC_ERR_OVERFLOW);
            goto fail;
 +        }
          silc_buffer_pull(dst, offst);
          flen += offst;
        } else {
        }
        break;
        }
 +
 +    case SILC_PARAM_OFFSET_START:
 +      if (!process)
 +      break;
 +      if (!silc_buffer_push(dst, flen))
 +      goto fail;
 +      flen = 0;
 +      break;
 +
 +    case SILC_PARAM_OFFSET_END:
 +      if (!process)
 +      break;
 +      flen += silc_buffer_len(dst);
 +      silc_buffer_pull(dst, silc_buffer_len(dst));
 +      break;
 +
      case SILC_PARAM_ADVANCE:
 +      if (!process)
 +      break;
        advance = TRUE;
        break;
 +
      case SILC_PARAM_END:
        goto ok;
        break;
 +
      default:
        SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
                      "format the data.", fmt));
 +      silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
 +                          "Bad buffer formatting type %d", fmt);
        goto fail;
        break;
      }
  
   fail:
    SILC_LOG_DEBUG(("Error occured while formatting data"));
 -  if (!advance)
 +  if (process && !advance)
      silc_buffer_push(dst, flen);
    return -1;
  
   ok:
    /* Push the buffer back to where it belongs. */
 -  if (!advance)
 +  if (process && !advance)
      silc_buffer_push(dst, flen);
    return flen;
  }
  
 -
 -/****************************** Unformatting ********************************/
 -
 -int silc_buffer_unformat(SilcBuffer src, ...)
 +int silc_buffer_format(SilcBuffer dst, ...)
  {
    va_list ap;
    int ret;
  
 -  va_start(ap, src);
 -  ret = silc_buffer_sunformat_vp(NULL, src, ap);
 +  va_start(ap, dst);
 +  ret = silc_buffer_sformat_vp(NULL, dst, ap);
    va_end(ap);
  
    return ret;
  }
  
 -int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
 +int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
  {
 -  return silc_buffer_sunformat_vp(NULL, src, ap);
 +  return silc_buffer_sformat_vp(NULL, dst, ap);
  }
  
 -int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
 +int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
  {
    va_list ap;
    int ret;
  
 -  va_start(ap, src);
 -  ret = silc_buffer_sunformat_vp(stack, src, ap);
 +  va_start(ap, dst);
 +  ret = silc_buffer_sformat_vp(stack, dst, ap);
    va_end(ap);
  
    return ret;
  }
  
 -int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
 +int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
  {
 -  SilcBufferParamType fmt;
 +  return silc_buffer_sformat_vp_i(stack, dst, ap, TRUE);
 +}
 +
 +/****************************** Unformatting ********************************/
 +
 +int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
 +                             SilcBool process)
 +{
 +  SilcParam fmt;
    unsigned char *start_ptr = src->data;
    int len = 0;
    SilcBool advance = FALSE;
  
    /* Parse the arguments by formatting type. */
 -  while(1) {
 -    fmt = va_arg(ap, SilcBufferParamType);
 +  while (1) {
 +    fmt = va_arg(ap, SilcParam);
 +
 +    SILC_LOG_DEBUG(("Buffer unformat type %s (%d)",
 +                  silc_param_string(fmt), fmt));
  
 -    switch(fmt) {
 +    switch (fmt) {
      case SILC_PARAM_FUNC:
        {
 -      SilcBufferUnformatFunc func = NULL;
 -      SilcBufferSUnformatFunc funcs = NULL;
 +      SilcBufferUnformatFunc func;
        void **val;
        void *context;
        int tmp_len;
 -      if (!stack)
 -        func = va_arg(ap, SilcBufferUnformatFunc);
 -      else
 -        funcs = va_arg(ap, SilcBufferSUnformatFunc);
 +      func = va_arg(ap, SilcBufferUnformatFunc);
        val = va_arg(ap, void **);
        context = va_arg(ap, void *);
 -      if (!stack)
 -        tmp_len = func(src, val, context);
 -      else
 -        tmp_len = funcs(stack, src, val, context);
 +
 +      if (!process)
 +        break;
 +
 +      tmp_len = func(stack, src, val, context);
        if (tmp_len < 0)
          goto fail;
        if (tmp_len) {
          silc_buffer_pull(src, tmp_len);
        }
        }
 -    case SILC_PARAM_UI_XNSTRING:
 -    case SILC_PARAM_DATA:
 +      break;
 +
 +    case SILC_PARAM_REGEX:
 +      {
 +      const char *regex = va_arg(ap, char *);
 +      SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags);
 +      SilcBufferStruct match;
 +      SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
 +      SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
 +      SilcBool ret;
 +      SilcUInt32 inclusive_pos = 0;
 +      int matched = 0, ret_len;
 +      va_list cp;
 +
 +      if (!process)
 +        break;
 +
 +      if (!regex)
 +        break;
 +
 +      if (match_nl) {
 +      start_nl_match:
 +        /* Match for '\n' in the buffer.  If not found, treat as line
 +           without '\n' (buffer has only one line, or this is last line). */
 +        if (silc_regex_buffer(src, "\n", &match, NULL))
 +          src->tail = match.tail;
 +      }
 +
 +      start_match:
 +      /* Match */
 +      ret = silc_regex_buffer(src, regex, &match, NULL);
 +      ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
 +      if (!ret) {
 +        if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
 +          silc_set_errno(SILC_ERR_NOT_FOUND);
 +          goto fail;
 +        }
 +        goto end_match;
 +      }
 +      matched++;
 +
 +      if (rflags & SILC_STR_REGEX_NOT)
 +        match = *src;
 +
 +      if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
 +        /* Advance buffer after match */
 +        if (!silc_buffer_pull(src, (match.data - src->data)))
 +          goto fail;
 +      }
 +
 +      if (rflags & SILC_STR_REGEX_INCLUSIVE) {
 +        inclusive_pos = src->tail - match.tail;
 +        src->tail = match.tail;
 +      }
 +
 +      /* Recursively format */
 +      silc_va_copy(cp, ap);
 +      ret_len = silc_buffer_sunformat_vp_i(stack, src, cp, TRUE);
 +      va_end(cp);
 +      if (ret_len < 0)
 +        goto fail;
 +
 +      if (rflags & SILC_STR_REGEX_INCLUSIVE)
 +        if (!silc_buffer_pull_tail(src, inclusive_pos))
 +          goto fail;
 +
 +      /* Advance buffer after formatting */
 +      if (!silc_buffer_pull(src, ret_len))
 +        goto fail;
 +
 +      if (match_all && (!match_nl || silc_buffer_len(src) > 1))
 +        goto start_match;
 +
 +      end_match:
 +      if (match_nl) {
 +        /* Go to next line, it is at the end of the data area.  Adjust
 +           the tail area of the target buffer to show rest of the buffer. */
 +        if (!silc_buffer_pull(src, (src->tail - src->data)))
 +          goto fail;
 +        if (!silc_buffer_pull_tail(src, silc_buffer_taillen(src)))
 +          goto fail;
 +
 +        if (silc_buffer_len(src) > 0)
 +          goto start_nl_match;
 +      }
 +
 +      /* Skip to the next SILC_PARAM_END */
 +      silc_buffer_sunformat_vp_i(NULL, src, ap, FALSE);
 +      break;
 +      }
 +      break;
 +
 +    case SILC_PARAM_UICHAR:
        {
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt32 len2 = va_arg(ap, SilcUInt32);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, len2);
        if (silc_likely(len2 && x))
          *x = src->data;
        silc_buffer_pull(src, len2);
        break;
        }
 -    case SILC_PARAM_UI_XNSTRING_ALLOC:
 -    case SILC_PARAM_DATA_ALLOC:
 +
 +    case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
        {
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt32 len2 = va_arg(ap, SilcUInt32);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, len2);
        if (silc_likely(len2 && x)) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
        }
 -    case SILC_PARAM_UI8_CHAR:
 +
 +    case SILC_PARAM_UINT8:
        {
        unsigned char *x = va_arg(ap, unsigned char *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 1);
        if (silc_likely(x))
          *x = src->data[0];
        silc_buffer_pull(src, 1);
        break;
        }
 -    case SILC_PARAM_UI16_SHORT:
 +
 +    case SILC_PARAM_UINT16:
        {
        SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 2);
        if (silc_likely(x))
          SILC_GET16_MSB(*x, src->data);
        silc_buffer_pull(src, 2);
        break;
        }
 -    case SILC_PARAM_UI32_INT:
 +
 +    case SILC_PARAM_UINT32:
        {
        SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 4);
        if (silc_likely(x))
          SILC_GET32_MSB(*x, src->data);
        silc_buffer_pull(src, 4);
        break;
        }
 -    case SILC_PARAM_UI64_INT:
 +
 +    case SILC_PARAM_UINT64:
        {
        SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
        if (silc_likely(x))
          SILC_GET64_MSB(*x, src->data);
        silc_buffer_pull(src, sizeof(SilcUInt64));
        break;
        }
 -    case SILC_PARAM_SI8_CHAR:
 +
 +    case SILC_PARAM_SINT8:
        {
        char *x = va_arg(ap, char *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 1);
        if (silc_likely(x))
          *x = src->data[0];
        silc_buffer_pull(src, 1);
        break;
        }
 -    case SILC_PARAM_SI16_SHORT:
 +
 +    case SILC_PARAM_SINT16:
        {
        SilcInt16 *x = va_arg(ap, SilcInt16 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 2);
        if (silc_likely(x))
          SILC_GET16_MSB(*x, src->data);
        silc_buffer_pull(src, 2);
        break;
        }
 -    case SILC_PARAM_SI32_INT:
 +
 +    case SILC_PARAM_SINT32:
        {
        SilcInt32 *x = va_arg(ap, SilcInt32 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 4);
        if (silc_likely(x))
          SILC_GET32_MSB(*x, src->data);
        silc_buffer_pull(src, 4);
        break;
        }
 -    case SILC_PARAM_SI64_INT:
 +
 +    case SILC_PARAM_SINT64:
        {
        SilcInt64 *x = va_arg(ap, SilcInt64 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
        if (silc_likely(x))
          SILC_GET64_MSB(*x, src->data);
        silc_buffer_pull(src, sizeof(SilcInt64));
        break;
        }
 +
      case SILC_PARAM_UI8_STRING:
        {
        SilcUInt8 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 1);
        len2 = (SilcUInt8)src->data[0];
        silc_buffer_pull(src, 1);
        silc_buffer_pull(src, len2);
        break;
        }
 -    case SILC_PARAM_UI16_STRING:
 -      {
 -      SilcUInt16 len2;
 -      unsigned char **x = va_arg(ap, unsigned char **);
 -      UNFORMAT_HAS_SPACE(src, 2);
 -      SILC_GET16_MSB(len2, src->data);
 -      silc_buffer_pull(src, 2);
 -      UNFORMAT_HAS_SPACE(src, len2);
 -      if (silc_likely(x))
 -        *x = src->data;
 -      silc_buffer_pull(src, len2);
 -      break;
 -      }
 -    case SILC_PARAM_UI8_STRING_ALLOC:
 +
 +    case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
        {
        SilcUInt8 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 1);
        len2 = (SilcUInt8)src->data[0];
        silc_buffer_pull(src, 1);
        UNFORMAT_HAS_SPACE(src, len2);
        if (silc_likely(x && len2)) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
 -        if (*x)
 -          memcpy(*x, src->data, len2);
 +        memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
        }
 -    case SILC_PARAM_UI16_STRING_ALLOC:
 +
 +    case SILC_PARAM_UI16_STRING:
        {
        SilcUInt16 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
 +
 +      if (!process)
 +        break;
 +
 +      UNFORMAT_HAS_SPACE(src, 2);
 +      SILC_GET16_MSB(len2, src->data);
 +      silc_buffer_pull(src, 2);
 +      UNFORMAT_HAS_SPACE(src, len2);
 +      if (silc_likely(x))
 +        *x = src->data;
 +      silc_buffer_pull(src, len2);
 +      break;
 +      }
 +
 +    case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
 +      {
 +      SilcUInt16 len2;
 +      unsigned char **x = va_arg(ap, unsigned char **);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 2);
        SILC_GET16_MSB(len2, src->data);
        silc_buffer_pull(src, 2);
        UNFORMAT_HAS_SPACE(src, len2);
        if (silc_likely(x && len2)) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
        }
 +
      case SILC_PARAM_UI32_STRING:
        {
        SilcUInt32 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 4);
        SILC_GET32_MSB(len2, src->data);
        silc_buffer_pull(src, 4);
        silc_buffer_pull(src, len2);
        break;
        }
 -    case SILC_PARAM_UI32_STRING_ALLOC:
 +
 +    case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
        {
        SilcUInt32 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 4);
        SILC_GET32_MSB(len2, src->data);
        silc_buffer_pull(src, 4);
        UNFORMAT_HAS_SPACE(src, len2);
        if (silc_likely(x && len2)) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
        }
 +
      case SILC_PARAM_UI8_NSTRING:
        {
        SilcUInt8 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 1);
        len2 = (SilcUInt8)src->data[0];
        silc_buffer_pull(src, 1);
        silc_buffer_pull(src, len2);
        break;
        }
 -    case SILC_PARAM_UI16_NSTRING:
 -      {
 -      SilcUInt16 len2;
 -      unsigned char **x = va_arg(ap, unsigned char **);
 -      SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
 -      UNFORMAT_HAS_SPACE(src, 2);
 -      SILC_GET16_MSB(len2, src->data);
 -      silc_buffer_pull(src, 2);
 -      UNFORMAT_HAS_SPACE(src, len2);
 -      if (len3)
 -        *len3 = len2;
 -      if (x)
 -        *x = src->data;
 -      silc_buffer_pull(src, len2);
 -      break;
 -      }
 -    case SILC_PARAM_UI8_NSTRING_ALLOC:
 +
 +    case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
        {
        SilcUInt8 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 1);
        len2 = (SilcUInt8)src->data[0];
        silc_buffer_pull(src, 1);
          *len3 = len2;
        if (x && len2) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
 -        if (*x)
 -          memcpy(*x, src->data, len2);
 +        memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
        }
 -    case SILC_PARAM_UI16_NSTRING_ALLOC:
 +
 +    case SILC_PARAM_UI16_NSTRING:
        {
        SilcUInt16 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
 +
 +      if (!process)
 +        break;
 +
 +      UNFORMAT_HAS_SPACE(src, 2);
 +      SILC_GET16_MSB(len2, src->data);
 +      silc_buffer_pull(src, 2);
 +      UNFORMAT_HAS_SPACE(src, len2);
 +      if (len3)
 +        *len3 = len2;
 +      if (x)
 +        *x = src->data;
 +      silc_buffer_pull(src, len2);
 +      break;
 +      }
 +
 +    case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
 +      {
 +      SilcUInt16 len2;
 +      unsigned char **x = va_arg(ap, unsigned char **);
 +      SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 2);
        SILC_GET16_MSB(len2, src->data);
        silc_buffer_pull(src, 2);
          *len3 = len2;
        if (x && len2) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
        }
 +
      case SILC_PARAM_UI32_NSTRING:
        {
        SilcUInt32 len2;
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 4);
        SILC_GET32_MSB(len2, src->data);
        silc_buffer_pull(src, 4);
        silc_buffer_pull(src, len2);
        break;
        }
 +
 +    case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
 +      {
 +      SilcUInt32 len2;
 +      unsigned char **x = va_arg(ap, unsigned char **);
 +      SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
 +
 +      if (!process)
 +        break;
 +
 +      UNFORMAT_HAS_SPACE(src, 4);
 +      SILC_GET32_MSB(len2, src->data);
 +      silc_buffer_pull(src, 4);
 +      UNFORMAT_HAS_SPACE(src, len2);
 +      if (len3)
 +        *len3 = len2;
 +      if (silc_likely(x && len2)) {
 +        *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
 +        memcpy(*x, src->data, len2);
 +      }
 +      silc_buffer_pull(src, len2);
 +      break;
 +      }
 +
      case SILC_PARAM_BUFFER:
        {
        SilcBuffer x = va_arg(ap, SilcBuffer);
        SilcUInt32 len2;
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 4);
        SILC_GET32_MSB(len2, src->data);
        silc_buffer_pull(src, 4);
        silc_buffer_pull(src, len2);
        }
        break;
 -    case SILC_PARAM_BUFFER_ALLOC:
 +
 +    case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
        {
        SilcBuffer x = va_arg(ap, SilcBuffer);
        SilcUInt32 len2;
 +
 +      if (!process)
 +        break;
 +
        UNFORMAT_HAS_SPACE(src, 4);
        SILC_GET32_MSB(len2, src->data);
        silc_buffer_pull(src, 4);
        UNFORMAT_HAS_SPACE(src, len2);
-       silc_buffer_sformat(stack, x,
-                           SILC_STR_DATA(src->data, len2),
-                           SILC_STR_END);
+       if (silc_buffer_sformat(stack, x,
+                               SILC_STR_DATA(src->data, len2),
+                               SILC_STR_END) < 0)
+         goto fail;
        silc_buffer_pull(src, len2);
        }
        break;
 +
      case SILC_PARAM_OFFSET:
        {
        int offst = va_arg(ap, int);
 +
 +      if (!process)
 +        break;
 +
        if (!offst)
          break;
 +
        if (offst > 1) {
          UNFORMAT_HAS_SPACE(src, offst);
          silc_buffer_pull(src, offst);
        }
        break;
        }
 +
 +    case SILC_PARAM_OFFSET_START:
 +      if (!process)
 +      break;
 +      silc_buffer_push(src, (src->data - start_ptr));
 +      break;
 +
 +    case SILC_PARAM_OFFSET_END:
 +      if (!process)
 +      break;
 +      silc_buffer_pull(src, silc_buffer_len(src));
 +      break;
 +
      case SILC_PARAM_ADVANCE:
 +      if (!process)
 +      break;
        advance = TRUE;
        break;
 +
      case SILC_PARAM_END:
        goto ok;
        break;
 +
 +    case SILC_PARAM_DELETE:
 +      break;
 +
      default:
        SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
                      "format the data.", fmt));
 +      silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
 +                          "Bad buffer formatting type %d", fmt);
        goto fail;
        break;
      }
  
   fail:
    SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
 -  len = src->data - start_ptr;
 -  silc_buffer_push(src, len);
 +  if (process && !advance) {
 +    len = src->data - start_ptr;
 +    silc_buffer_push(src, len);
 +  }
    return -1;
  
   ok:
 +  len = src->data - start_ptr;
 +
    /* Push the buffer back to the start. */
 -  if (!advance) {
 -    len = src->data - start_ptr;
 +  if (process && !advance)
      silc_buffer_push(src, len);
 -  }
 +
    return len;
  }
  
 +int silc_buffer_unformat(SilcBuffer src, ...)
 +{
 +  va_list ap;
 +  int ret;
 +
 +  va_start(ap, src);
 +  ret = silc_buffer_sunformat_vp(NULL, src, ap);
 +  va_end(ap);
 +
 +  return ret;
 +}
 +
 +int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
 +{
 +  return silc_buffer_sunformat_vp(NULL, src, ap);
 +}
 +
 +int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
 +{
 +  va_list ap;
 +  int ret;
 +
 +  va_start(ap, src);
 +  ret = silc_buffer_sunformat_vp(stack, src, ap);
 +  va_end(ap);
 +
 +  return ret;
 +}
 +
 +int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
 +{
 +  return silc_buffer_sunformat_vp_i(stack, src, ap, TRUE);
 +}
  
  /**************************** Utility functions *****************************/
  
index 0568bd42eb04ce8b0b458c3fa3c7db30866f1fb6,f9fe84373974c0b054db7bfaee6d730d7191b180..0a9a34644f79cff40f3c040bba26aa2e100fe3a2
@@@ -4,7 -4,7 +4,7 @@@
  
    Author: Giovanni Giacobbi <giovanni@giacobbi.net>
  
 -  Copyright (C) 2002 - 2006 Giovanni Giacobbi
 +  Copyright (C) 2002 - 2008 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
@@@ -16,8 -16,9 +16,8 @@@
    GNU General Public License for more details.
  
  */
 -/* $Id$ */
  
 -#include "silc.h"
 +#include "silcruntime.h"
  
  /* limit debug logging verbosity */
  #if 0
@@@ -26,6 -27,8 +26,8 @@@
  #define SILC_CONFIG_DEBUG(fmt)
  #endif
  
+ #define BUF_SIZE 255
  /* this is the option struct and currently it is only used internally to
   * the module and other structs. */
  typedef struct SilcConfigOptionStruct {
@@@ -111,11 -114,14 +113,14 @@@ static void my_skip_line(SilcConfigFil
   * a separator is any non alphanumeric character nor "_" or "-" */
  static char *my_next_token(SilcConfigFile *file, char *to)
  {
+   unsigned int count = 0;
    register char *o;
    my_trim_spaces(file);
    o = file->p;
-   while (isalnum((int)*o) || (*o == '_') || (*o == '-'))
+   while ((isalnum((int)*o) || (*o == '_') || (*o == '-')) && count < BUF_SIZE) {
+     count++;
      *to++ = *o++;
+   }
    *to = '\0';
    file->p = o;
    return to;
@@@ -129,24 -135,30 +134,30 @@@ static char *my_get_string(SilcConfigFi
    my_trim_spaces(file);
    o = file->p;
    if (*o == '"') {
-     char *quot = strchr(++o, '"');
-     int len = quot - o;
-     if (!quot) { /* XXX FIXME: gotta do something here */
-       printf("Bullshit, missing matching \"");
-       exit(1);
+     unsigned int count = 0;
+     char *d = to;
+     while (count < BUF_SIZE) {
+       o++;
+       if (*o == '"') {
+           break;
+       }
+       if (*o == '\\') {
+           o++;
+       }
+       count++;
+       *d++ = *o;
      }
-     if (len <= 0)
-       *to = '\0';
-     else {
-       strncpy(to, o, len);
-       to[len] = '\0';
+     if (count >= BUF_SIZE) { /* XXX FIXME: gotta do something here */
+       fprintf(stderr, "Bullshit, missing matching \"");
+       exit(1);
      }
+     *d = '\0';
      /* update stream pointer */
-     file->p = quot + 1;
-     return to;
+     file->p = o + 1;
+   } else {
+     /* we don't need quote parsing, fall-back to token extractor */
+     my_next_token(file, to);
    }
-   /* we don't need quote parsing, fall-back to token extractor */
-   my_next_token(file, to);
    return to;
  }
  
@@@ -262,7 -274,7 +273,7 @@@ SilcConfigFile *silc_config_open(const 
    SilcUInt32 filelen;
    SilcConfigFile *ret;
  
 -  if (!(buffer = silc_file_readfile(configfile, &filelen)))
 +  if (!(buffer = silc_file_readfile(configfile, &filelen, NULL)))
      return NULL;
  
    ret = silc_calloc(1, sizeof(*ret));
@@@ -453,7 -465,7 +464,7 @@@ static int silc_config_main_internal(Si
  
    /* loop throught statements */
    while (1) {
-     char buf[255];
+     char buf[BUF_SIZE];
      SilcConfigOption *thisopt;
  
      /* makes it pointing to the next interesting char */
index 5ba65ba99b8c4c36105df0c40f51ea377f029d35,1ae8d413ca730fd7c67880522ea7604052edcd69..f0032e8b7fcac3f220786f2f3acaaf0d17067f6e
  
  */
  
 -#include "silc.h"
 +#include "silcruntime.h"
  
  /************************** Types and definitions ***************************/
  
- #define SILC_IS_FD_STREAM(s) (s->ops == &silc_fd_stream_ops)
+ #define SILC_IS_FD_STREAM(s) (s && s->ops == &silc_fd_stream_ops)
  
  const SilcStreamOps silc_fd_stream_ops;
  
  /* FD stream context */
  typedef struct {
    const SilcStreamOps *ops;
 +  SilcStack stack;
    SilcSchedule schedule;
    SilcStreamNotifier notifier;
    void *notifier_context;
    int fd1;
    int fd2;
 -  int error;
  } *SilcFDStream;
  
  
@@@ -67,36 -67,28 +67,36 @@@ SILC_TASK_CALLBACK(silc_fd_stream_io
  
  /* Create file descriptor stream */
  
 -SilcStream silc_fd_stream_create(int fd)
 +SilcStream silc_fd_stream_create(int fd, SilcStack stack)
  {
 -  if (fd < 1)
 +  if (fd < 1) {
 +    silc_set_errno_reason(SILC_ERR_BAD_FD, "Bad file descriptor %d", fd);
      return NULL;
 -  return silc_fd_stream_create2(fd, 0);
 +  }
 +  return silc_fd_stream_create2(fd, 0, stack);
  }
  
  /* Create stream with two file descriptors */
  
 -SilcStream silc_fd_stream_create2(int read_fd, int write_fd)
 +SilcStream silc_fd_stream_create2(int read_fd, int write_fd, SilcStack stack)
  {
    SilcFDStream stream;
  
 -  stream = silc_calloc(1, sizeof(*stream));
 -  if (!stream)
 +  if (stack)
 +    stack = silc_stack_alloc(0, stack);
 +
 +  stream = silc_scalloc(stack, 1, sizeof(*stream));
 +  if (!stream) {
 +    silc_stack_free(stack);
      return NULL;
 +  }
  
    SILC_LOG_DEBUG(("Creating new fd stream %p", stream));
  
    stream->ops = &silc_fd_stream_ops;
    stream->fd1 = read_fd;
    stream->fd2 = write_fd;
 +  stream->stack = stack;
  
    return stream;
  }
  /* Create by opening file */
  
  SilcStream silc_fd_stream_file(const char *filename, SilcBool reading,
 -                             SilcBool writing)
 +                             SilcBool writing, SilcStack stack)
  {
    const char *read_file = NULL, *write_file = NULL;
  
 -  if (!filename)
 +  if (!filename) {
 +    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
      return NULL;
 +  }
  
    if (writing)
      write_file = filename;
    if (reading)
      read_file = filename;
  
 -  return silc_fd_stream_file2(read_file, write_file);
 +  return silc_fd_stream_file2(read_file, write_file, stack);
  }
  
  /* Create by opening two files */
  
 -SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file)
 +SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file,
 +                              SilcStack stack)
  {
    SilcStream stream;
    int fd1 = 0, fd2 = 0;
        return NULL;
    }
  
 -  stream = silc_fd_stream_create2(fd1, fd2);
 +  stream = silc_fd_stream_create2(fd1, fd2, stack);
    if (!stream) {
      silc_file_close(fd1);
      silc_file_close(fd2);
@@@ -174,6 -163,18 +174,6 @@@ SilcBool silc_fd_stream_get_info(SilcSt
    return TRUE;
  }
  
 -/* Return errno */
 -
 -int silc_fd_stream_get_error(SilcStream stream)
 -{
 -  SilcFDStream fd_stream = stream;
 -
 -  if (!SILC_IS_FD_STREAM(fd_stream))
 -    return 0;
 -
 -  return fd_stream->error;
 -}
 -
  /* Read */
  
  int silc_fd_stream_read(SilcStream stream, unsigned char *buf,
        SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
        silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd1,
                                  SILC_TASK_READ, FALSE);
 +      silc_set_errno_posix(errno);
        return -1;
      }
      SILC_LOG_DEBUG(("Cannot read from fd: %d:%s",
                    fd_stream->fd1, strerror(errno)));
      silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
 -    fd_stream->error = errno;
 +    silc_set_errno_posix(errno);
      return -2;
    }
  
@@@ -230,12 -230,11 +230,12 @@@ int silc_fd_stream_write(SilcStream str
        SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
        silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd2,
                                  SILC_TASK_READ | SILC_TASK_WRITE, FALSE);
 +      silc_set_errno_posix(errno);
        return -1;
      }
      SILC_LOG_DEBUG(("Cannot write to fd: %s", strerror(errno)));
      silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
 -    fd_stream->error = errno;
 +    silc_set_errno_posix(errno);
      return -2;
    }
  
@@@ -278,12 -277,8 +278,12 @@@ SilcBool silc_fd_stream_close(SilcStrea
  
  void silc_fd_stream_destroy(SilcStream stream)
  {
 +  SilcFDStream fd_stream = stream;
 +  SilcStack stack = fd_stream->stack;
 +
    silc_fd_stream_close(stream);
 -  silc_free(stream);
 +  silc_sfree(stack, stream);
 +  silc_stack_free(stack);
  }
  
  /* Sets stream notification callback for the stream */
index 7f61e51865a6203b3f70b10ca4f281871d955e55,af8f2c34cba0b60f6584b07dd57b10931fe115ab..8d3056edaf0173489a905b42cb90c1f34c868eb8
@@@ -17,7 -17,7 +17,7 @@@
  
  */
  
 -#include "silc.h"
 +#include "silcruntime.h"
  
  /************************** Types and definitions ***************************/
  
@@@ -43,7 -43,7 +43,7 @@@ SilcSchedule silc_socket_stream_get_sch
  /* Internal async host lookup context. */
  typedef struct {
    SilcSocketStream stream;
 -  SilcSocketStreamStatus status;
 +  SilcResult status;
    SilcSocketStreamCallback callback;
    SilcAsyncOperation op;
    void *context;
@@@ -71,7 -71,7 +71,7 @@@ SILC_TASK_CALLBACK(silc_socket_host_loo
      return;
    }
  
 -  if (lookup->status != SILC_SOCKET_OK) {
 +  if (lookup->status != SILC_OK) {
      SILC_LOG_DEBUG(("Socket stream lookup failed"));
      stream->schedule = NULL;
      silc_socket_stream_destroy(stream);
@@@ -99,24 -99,24 +99,24 @@@ static void *silc_socket_host_lookup_st
  
    silc_net_check_host_by_sock(stream->sock, &stream->hostname, &stream->ip);
    if (!stream->ip) {
 -    lookup->status = SILC_SOCKET_UNKNOWN_IP;
 +    lookup->status = SILC_ERR_UNKNOWN_IP;
      goto out;
    }
  
    if (!stream->hostname && lookup->require_fqdn) {
 -    lookup->status = SILC_SOCKET_UNKNOWN_HOST;
 +    lookup->status = SILC_ERR_UNKNOWN_HOST;
      goto out;
    }
  
    if (!stream->hostname) {
 -    stream->hostname = strdup(stream->ip);
 +    stream->hostname = silc_strdup(stream->ip);
      if (!stream->hostname) {
 -      lookup->status = SILC_SOCKET_NO_MEMORY;
 +      lookup->status = SILC_ERR_OUT_OF_MEMORY;
        goto out;
      }
    }
  
 -  lookup->status = SILC_SOCKET_OK;
 +  lookup->status = SILC_OK;
  
   out:
    silc_schedule_task_add_timeout(schedule, silc_socket_host_lookup_finish,
@@@ -152,27 -152,17 +152,27 @@@ silc_socket_tcp_stream_create(SilcSocke
    SilcSocketStream stream;
    SilcSocketHostLookup l;
  
 -  if (!sock || !schedule) {
 -    SILC_LOG_ERROR(("Missing arguments to silc_socket_tcp_stream_create"));
 +  if (!schedule) {
 +    schedule = silc_schedule_get_global();
 +    if (!schedule) {
 +      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
 +      if (callback)
 +      callback(silc_errno, NULL, context);
 +      return NULL;
 +    }
 +  }
 +
 +  if (!sock) {
 +    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
      if (callback)
 -      callback(SILC_SOCKET_ERROR, NULL, context);
 +      callback(silc_errno, NULL, context);
      return NULL;
    }
  
    stream = silc_calloc(1, sizeof(*stream));
    if (!stream) {
      if (callback)
 -      callback(SILC_SOCKET_NO_MEMORY, NULL, context);
 +      callback(silc_errno, NULL, context);
      return NULL;
    }
  
    if (!l) {
      silc_free(stream);
      if (callback)
 -      callback(SILC_SOCKET_NO_MEMORY, NULL, context);
 +      callback(silc_errno, NULL, context);
      return NULL;
    }
  
        silc_free(stream);
        silc_free(l);
        if (callback)
 -      callback(SILC_SOCKET_ERROR, NULL, context);
 +      callback(silc_errno, NULL, context);
        return NULL;
      }
  
      return l->op;
    } else {
      /* No lookup */
 -    l->status = SILC_SOCKET_OK;
 +    l->status = SILC_OK;
      silc_socket_host_lookup_finish(schedule,
                                   silc_schedule_get_context(schedule),
                                   0, 0, l);
@@@ -229,14 -219,6 +229,14 @@@ SilcStream silc_socket_udp_stream_creat
  {
    SilcSocketStream stream;
  
 +  if (!schedule) {
 +    schedule = silc_schedule_get_global();
 +    if (!schedule) {
 +      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
 +      return NULL;
 +    }
 +  }
 +
    stream = silc_calloc(1, sizeof(*stream));
    if (!stream)
      return NULL;
@@@ -314,17 -296,17 +314,17 @@@ SilcBool silc_socket_stream_set_info(Si
  
    if (hostname) {
      silc_free(socket_stream->hostname);
 -    socket_stream->hostname = strdup(hostname);
 +    socket_stream->hostname = silc_strdup(hostname);
      if (!socket_stream->hostname)
        return FALSE;
    }
    if (ip) {
      silc_free(socket_stream->ip);
 -    socket_stream->ip = strdup(ip);
 +    socket_stream->ip = silc_strdup(ip);
      if (!socket_stream->ip)
        return FALSE;
      if (!socket_stream->hostname) {
 -      socket_stream->hostname = strdup(ip);
 +      socket_stream->hostname = silc_strdup(ip);
        if (!socket_stream->hostname)
        return FALSE;
      }
    return TRUE;
  }
  
 -/* Return socket errno */
 -
 -int silc_socket_stream_get_error(SilcStream stream)
 -{
 -  SilcSocketStream socket_stream = stream;
 -
 -  if (!SILC_IS_SOCKET_STREAM(socket_stream) &&
 -      !SILC_IS_SOCKET_STREAM_UDP(socket_stream))
 -    return 0;
 -
 -  return socket_stream->sock_error;
 -}
 -
  /* Set QoS for socket stream */
  
  SilcBool silc_socket_stream_set_qos(SilcStream stream,
        !limit_sec && !limit_usec) {
      silc_schedule_task_del_by_context(socket_stream->schedule,
                                      socket_stream->qos);
+     silc_free(socket_stream->qos->buffer);
      silc_free(socket_stream->qos);
      socket_stream->qos = NULL;
      return TRUE;
    socket_stream->qos->cur_rate = 0;
    socket_stream->qos->sock = socket_stream;
  
-   socket_stream->qos->buffer = silc_malloc(read_limit_bytes);
+   socket_stream->qos->buffer = silc_realloc(socket_stream->qos->buffer,
+                                           read_limit_bytes);
    if (!socket_stream->qos->buffer)
      return FALSE;
  
index 894c4b1e581299b8256af05d9caf0b2ece04c312,13013f25ac3a75af7f33cec384c05d7b63cc8dca..aa080ccc4b8e0290eb37a44a52000470db77837e
@@@ -4,7 -4,7 +4,7 @@@
  
    Author: Pekka Riikonen <priikone@silcnet.org>
  
 -  Copyright (C) 2005 - 2008 Pekka Riikonen
 +  Copyright (C) 2005 - 2007 Pekka Riikonen
  
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@@ -47,27 -47,19 +47,27 @@@ struct SilcSocketStreamStruct 
    SilcSocket sock;
    char *hostname;
    char *ip;
 -  SilcUInt16 port;
 -  SilcUInt16 sock_error;
    SilcSocketQos qos;
    SilcStreamNotifier notifier;
    void *notifier_context;
 +  SilcUInt16 port;
    unsigned int ipv6      : 1;       /* UDP IPv6 */
    unsigned int connected : 1;     /* UDP connected state */
  };
  
- #define SILC_IS_SOCKET_STREAM(s) (s->ops == &silc_socket_stream_ops)
- #define SILC_IS_SOCKET_STREAM_UDP(s) (s->ops == &silc_socket_udp_stream_ops)
+ #define SILC_IS_SOCKET_STREAM(s) (s && s->ops == &silc_socket_stream_ops)
+ #define SILC_IS_SOCKET_STREAM_UDP(s) (s && s->ops == &silc_socket_udp_stream_ops)
  
  extern const SilcStreamOps silc_socket_stream_ops;
  extern const SilcStreamOps silc_socket_udp_stream_ops;
  
 +/* Backwards support */
 +#define SilcSocketStreamStatus SilcResult
 +#define silc_socket_stream_get_error(stream) silc_errno
 +#define SILC_SOCKET_OK SILC_OK
 +#define SILC_SOCKET_UNKNOWN_IP SILC_ERR_UNKNOWN_IP
 +#define SILC_SOCKET_UNKNOWN_HOST SILC_ERR_UNKNOWN_HOST
 +#define SILC_SOCKET_NO_MEMORY SILC_ERR_OUT_OF_MEMORY
 +#define SILC_SOCKET_ERROR SILC_ERR
 +
  #endif /* SILCSOCKETSTREAM_I_H */
index f18af24e4f8e961b859cfb0648fb80fac6b45c05,2332672d4643d125180f7923315020246153c51c..c216ccca1f04f1f1f2ed86d812480e6f12402ca0
@@@ -4,7 -4,7 +4,7 @@@
  
    Author: Pekka Riikonen <priikone@silcnet.org>
  
 -  Copyright (C) 1997 - 2007 Pekka Riikonen
 +  Copyright (C) 1997 - 2008 Pekka Riikonen
  
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    GNU General Public License for more details.
  
  */
 -/* $Id$ */
  
 -#include "silc.h"
 -#include "silcnet.h"
 +#include "silcruntime.h"
  
  /************************** Types and definitions ***************************/
  
@@@ -49,31 -51,26 +49,31 @@@ static SilcBool silc_net_set_sockaddr(S
    if (ip_addr) {
      if (!silc_net_is_ip(ip_addr)) {
        SILC_LOG_ERROR(("%s is not IP address", ip_addr));
 +      silc_set_errno_reason(SILC_ERR_BAD_IP, "%s is not an IP address",
 +                          ip_addr);
        return FALSE;
      }
  
      if (silc_net_is_ip4(ip_addr)) {
        /* IPv4 address */
        len = sizeof(addr->sin.sin_addr);
 -      silc_net_addr2bin(ip_addr,
 -                      (unsigned char *)&addr->sin.sin_addr.s_addr, len);
 +      if (!silc_net_addr2bin(ip_addr,
 +                           (unsigned char *)&addr->sin.sin_addr.s_addr, len))
 +      return FALSE;
        addr->sin.sin_family = AF_INET;
        addr->sin.sin_port = port ? htons(port) : 0;
      } else {
  #ifdef HAVE_IPV6
        /* IPv6 address */
        len = sizeof(addr->sin6.sin6_addr);
 -      silc_net_addr2bin(ip_addr,
 -                      (unsigned char *)&addr->sin6.sin6_addr, len);
 +      if (!silc_net_addr2bin(ip_addr,
 +                           (unsigned char *)&addr->sin6.sin6_addr, len))
 +      return FALSE;
        addr->sin6.sin6_family = AF_INET6;
        addr->sin6.sin6_port = port ? htons(port) : 0;
  #else
        SILC_LOG_ERROR(("IPv6 support is not compiled in"));
 +      silc_set_errno(SILC_ERR_NOT_SUPPORTED);
        return FALSE;
  #endif
      }
  
  /* Deliver new stream to upper layer */
  
 -static void silc_net_accept_stream(SilcSocketStreamStatus status,
 +static void silc_net_accept_stream(SilcResult status,
                                   SilcStream stream, void *context)
  {
    SilcNetListener listener = context;
  
 -  if (status != SILC_SOCKET_OK)
 +  if (status != SILC_OK)
      return;
  
 -  listener->callback(SILC_NET_OK, stream, listener->context);
 +  listener->callback(SILC_OK, stream, listener->context);
  }
  
  /* Accept incoming connection and notify upper layer */
@@@ -141,18 -138,8 +141,18 @@@ silc_net_tcp_create_listener(const cha
  
    SILC_LOG_DEBUG(("Creating TCP listener"));
  
 -  if (port < 0 || !schedule || !callback)
 +  if (!schedule) {
 +    schedule = silc_schedule_get_global();
 +    if (!schedule) {
 +      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
 +      goto err;
 +    }
 +  }
 +
 +  if (port < 0 || !callback) {
 +    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
      goto err;
 +  }
  
    listener = silc_calloc(1, sizeof(*listener));
    if (!listener)
      /* Create the socket */
      sock = socket(server.sin.sin_family, SOCK_STREAM, 0);
      if (sock < 0) {
 -      SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
 +      silc_set_errno_posix(errno);
 +      SILC_LOG_ERROR(("Cannot create socket: %s",
 +                    silc_errno_string(silc_errno)));
        goto err;
      }
  
      /* Bind the listener socket */
      rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
      if (rval < 0) {
 -      SILC_LOG_ERROR(("Cannot bind socket: %s", strerror(errno)));
 +      silc_set_errno_posix(errno);
 +      SILC_LOG_ERROR(("Cannot bind socket: %s",
 +                    silc_errno_string(silc_errno)));
        close(sock);
        goto err;
      }
      /* Specify that we are listenning */
      rval = listen(sock, 64);
      if (rval < 0) {
 -      SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno)));
 +      silc_set_errno_posix(errno);
 +      SILC_LOG_ERROR(("Cannot set socket listenning: %s",
 +                    silc_errno_string(silc_errno)));
        close(sock);
        goto err;
      }
    return NULL;
  }
  
 +/* Create TCP listener, multiple ports */
 +
 +SilcNetListener
 +silc_net_tcp_create_listener2(const char *local_ip_addr, int *ports,
 +                            SilcUInt32 port_count,
 +                            SilcBool ignore_port_error,
 +                            SilcBool lookup, SilcBool require_fqdn,
 +                            SilcSchedule schedule,
 +                            SilcNetCallback callback, void *context)
 +{
 +  SilcNetListener listener = NULL;
 +  SilcSockaddr server;
 +  int i, sock, rval;
 +  const char *ipany = "0.0.0.0";
 +
 +  SILC_LOG_DEBUG(("Creating TCP listener"));
 +
 +  if (!schedule) {
 +    schedule = silc_schedule_get_global();
 +    if (!schedule) {
 +      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
 +      goto err;
 +    }
 +  }
 +
 +  if (!callback) {
 +    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
 +    goto err;
 +  }
 +
 +  listener = silc_calloc(1, sizeof(*listener));
 +  if (!listener)
 +    return NULL;
 +  listener->schedule = schedule;
 +  listener->callback = callback;
 +  listener->context = context;
 +  listener->require_fqdn = require_fqdn;
 +  listener->lookup = lookup;
 +
 +  if (port_count > 0) {
 +    listener->socks = silc_calloc(port_count, sizeof(*listener->socks));
 +    if (!listener->socks)
 +      return NULL;
 +  } else {
 +    listener->socks = silc_calloc(1, sizeof(*listener->socks));
 +    if (!listener->socks)
 +      return NULL;
 +
 +    port_count = 1;
 +  }
 +
 +  /* Bind to ports */
 +  for (i = 0; i < port_count; i++) {
 +    SILC_LOG_DEBUG(("Binding to local address %s:%d",
 +                  local_ip_addr ? local_ip_addr : ipany,
 +                  ports ? ports[i] : 0));
 +
 +    /* Set sockaddr for server */
 +    if (!silc_net_set_sockaddr(&server,
 +                             local_ip_addr ? local_ip_addr : ipany,
 +                             ports ? ports[i] : 0)) {
 +      if (ignore_port_error)
 +      continue;
 +      goto err;
 +    }
 +
 +    /* Create the socket */
 +    sock = socket(server.sin.sin_family, SOCK_STREAM, 0);
 +    if (sock < 0) {
 +      if (ignore_port_error)
 +      continue;
 +      silc_set_errno_posix(errno);
 +      SILC_LOG_ERROR(("Cannot create socket: %s",
 +                    silc_errno_string(silc_errno)));
 +      goto err;
 +    }
 +
 +    /* Set the socket options */
 +    rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
 +    if (rval < 0) {
 +      close(sock);
 +      if (ignore_port_error)
 +      continue;
 +      SILC_LOG_ERROR(("Cannot set socket options: %s",
 +                    silc_errno_string(silc_errno)));
 +      goto err;
 +    }
 +
 +    /* Bind the listener socket */
 +    rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
 +    if (rval < 0) {
 +      close(sock);
 +      if (ignore_port_error)
 +      continue;
 +      silc_set_errno_posix(errno);
 +      SILC_LOG_ERROR(("Cannot bind socket: %s",
 +                    silc_errno_string(silc_errno)));
 +      goto err;
 +    }
 +
 +    /* Specify that we are listenning */
 +    rval = listen(sock, 64);
 +    if (rval < 0) {
 +      close(sock);
 +      if (ignore_port_error)
 +      continue;
 +      silc_set_errno_posix(errno);
 +      SILC_LOG_ERROR(("Cannot set socket listenning: %s",
 +                    silc_errno_string(silc_errno)));
 +      goto err;
 +    }
 +
 +    /* Set the server socket to non-blocking mode */
 +    silc_net_set_socket_nonblock(sock);
 +
 +    /* Schedule for incoming connections */
 +    silc_schedule_task_add_fd(schedule, sock, silc_net_accept, listener);
 +
 +    SILC_LOG_DEBUG(("TCP listener created, fd=%d", sock));
 +    listener->socks[i] = sock;
 +    listener->socks_count++;
 +  }
 +
 +  if (ignore_port_error && !listener->socks_count)
 +    goto err;
 +
 +  return listener;
 +
 + err:
 +  if (listener)
 +    silc_net_close_listener(listener);
 +  return NULL;
 +}
 +
  /* Close network listener */
  
  void silc_net_close_listener(SilcNetListener listener)
@@@ -410,13 -257,8 +410,13 @@@ silc_net_udp_connect(const char *local_
  
    SILC_LOG_DEBUG(("Creating UDP stream"));
  
 -  if (!schedule)
 -    goto err;
 +  if (!schedule) {
 +    schedule = silc_schedule_get_global();
 +    if (!schedule) {
 +      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
 +      goto err;
 +    }
 +  }
  
    /* Bind to local addresses */
    SILC_LOG_DEBUG(("Binding to local address %s",
    /* Create the socket */
    sock = socket(server.sin.sin_family, SOCK_DGRAM, 0);
    if (sock < 0) {
 -    SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
 +    silc_set_errno_posix(errno);
 +    SILC_LOG_ERROR(("Cannot create socket: %s",
 +                  silc_errno_string(silc_errno)));
      goto err;
    }
  
    /* Set the socket options */
    rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
    if (rval < 0) {
 -    SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno)));
 +    SILC_LOG_ERROR(("Cannot set socket options: %s",
 +                  silc_errno_string(silc_errno)));
      goto err;
    }
  #ifdef SO_REUSEPORT
    rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEPORT, 1);
    if (rval < 0) {
 -    SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno)));
 +    SILC_LOG_ERROR(("Cannot set socket options: %s",
 +                  silc_errno_string(silc_errno)));
      goto err;
    }
  #endif /* SO_REUSEPORT */
    /* Bind the listener socket */
    rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
    if (rval < 0) {
 -    SILC_LOG_DEBUG(("Cannot bind socket: %s", strerror(errno)));
 +    silc_set_errno_posix(errno);
 +    SILC_LOG_DEBUG(("Cannot bind socket: %s", silc_errno_string(silc_errno)));
      goto err;
    }
  
  
      rval = connect(sock, &server.sa, SIZEOF_SOCKADDR(server));
      if (rval < 0) {
 -      SILC_LOG_DEBUG(("Cannot connect UDP stream: %s", strerror(errno)));
 +      silc_set_errno_posix(errno);
 +      SILC_LOG_DEBUG(("Cannot connect UDP stream: %s",
 +                    silc_errno_string(silc_errno)));
        goto err;
      }
    }
@@@ -522,8 -357,7 +522,8 @@@ int silc_net_udp_receive(SilcStream str
    SilcSocketStream sock = stream;
    SilcSockaddr s;
    struct sockaddr *from;
 -  int len, flen;
 +  int len;
 +  unsigned int flen;
  
    SILC_LOG_DEBUG(("Reading data from UDP socket %d", sock->sock));
  
      len = recv(sock->sock, ret_data, data_size, 0);
  
    if (len < 0) {
 +    silc_set_errno_posix(errno);
      if (errno == EAGAIN || errno == EINTR) {
        SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
        silc_schedule_set_listen_fd(sock->schedule, sock->sock,
      SILC_LOG_DEBUG(("Cannot read from UDP socket: %d:%s",
                    sock->sock, strerror(errno)));
      silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
 -    sock->sock_error = errno;
      return -2;
    }
  
@@@ -602,7 -436,6 +602,7 @@@ int silc_net_udp_send(SilcStream stream
    ret = sendto(sock->sock, data, data_len, 0, &remote.sa,
               SIZEOF_SOCKADDR(remote));
    if (ret < 0) {
 +    silc_set_errno_posix(errno);
      if (errno == EAGAIN || errno == EINTR) {
        SILC_LOG_DEBUG(("Could not send immediately, will do it later"));
        silc_schedule_set_listen_fd(sock->schedule, sock->sock,
      }
      SILC_LOG_DEBUG(("Cannot send to UDP socket: %s", strerror(errno)));
      silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
 -    sock->sock_error = errno;
      return -2;
    }
  
  /* Asynchronous TCP/IP connecting */
  
  typedef struct {
 -  SilcNetStatus status;
 -  SilcSocketStreamStatus stream_status;
 +  SilcResult status;
    SilcStream stream;
    SilcFSMStruct fsm;
    SilcFSMEventStruct event;
@@@ -677,7 -512,7 +677,7 @@@ SILC_FSM_STATE(silc_net_connect_st_star
                    "host", conn->remote));
  
      /** Network unreachable */
 -    conn->status = SILC_NET_HOST_UNREACHABLE;
 +    conn->status = SILC_ERR_UNREACHABLE;
      silc_fsm_next(fsm, silc_net_connect_st_finish);
      return SILC_FSM_CONTINUE;
    }
      }
  
      /** Cannot create socket */
 +    silc_set_errno_posix(errno);
      SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
      silc_fsm_next(fsm, silc_net_connect_st_finish);
      return SILC_FSM_CONTINUE;
    rval = connect(sock, &desthost.sa, SIZEOF_SOCKADDR(desthost));
    if (rval < 0) {
      if (errno != EINPROGRESS) {
 +      silc_set_errno_posix(errno);
        shutdown(sock, 2);
        close(sock);
  
        }
  
        /** Cannot connect to remote host */
 -      SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
 +      SILC_LOG_ERROR(("Cannot connect to remote host: %s",
 +                    silc_errno_string(silc_errno)));
        silc_fsm_next(fsm, silc_net_connect_st_finish);
        return SILC_FSM_CONTINUE;
      }
    return SILC_FSM_CONTINUE;
  }
  
 -static void silc_net_connect_wait_stream(SilcSocketStreamStatus status,
 +static void silc_net_connect_wait_stream(SilcResult status,
                                         SilcStream stream, void *context)
  {
    SilcNetConnect conn = context;
    conn->sop = NULL;
 -  conn->stream_status = status;
 +  conn->status = status;
    conn->stream = stream;
    SILC_FSM_CALL_CONTINUE(&conn->fsm);
  }
@@@ -801,13 -633,21 +801,13 @@@ SILC_FSM_STATE(silc_net_connect_st_conn
        return SILC_FSM_CONTINUE;
      }
  
 -#if defined(ECONNREFUSED)
 -    if (opt == ECONNREFUSED)
 -      conn->status = SILC_NET_CONNECTION_REFUSED;
 -#endif /* ECONNREFUSED */
 -#if defined(ETIMEDOUT)
 -    if (opt == ETIMEDOUT)
 -      conn->status = SILC_NET_CONNECTION_TIMEOUT;
 -#endif /* ETIMEDOUT */
 -#if defined(ENETUNREACH)
 -    if (opt == ENETUNREACH)
 -      conn->status = SILC_NET_HOST_UNREACHABLE;
 -#endif /* ENETUNREACH */
 +    /* Set error */
 +    silc_set_errno_posix(opt);
 +    conn->status = silc_errno;
  
      /** Connecting failed */
 -    SILC_LOG_DEBUG(("Connecting failed, error %s", strerror(opt)));
 +    SILC_LOG_DEBUG(("Connecting failed, error %s",
 +                  silc_errno_string(silc_errno)));
      silc_fsm_next(fsm, silc_net_connect_st_finish);
      return SILC_FSM_CONTINUE;
    }
@@@ -831,15 -671,21 +831,15 @@@ SILC_FSM_STATE(silc_net_connect_st_stre
      return SILC_FSM_CONTINUE;
    }
  
 -  if (conn->stream_status != SILC_SOCKET_OK) {
 +  if (conn->status != SILC_OK) {
      /** Stream creation failed */
 -    if (conn->stream_status == SILC_SOCKET_UNKNOWN_IP)
 -      conn->status = SILC_NET_UNKNOWN_IP;
 -    else if (conn->stream_status == SILC_SOCKET_UNKNOWN_HOST)
 -      conn->status = SILC_NET_UNKNOWN_HOST;
 -    else
 -      conn->status = SILC_NET_ERROR;
      silc_fsm_next(fsm, silc_net_connect_st_finish);
      return SILC_FSM_CONTINUE;
    }
  
    /** Stream created successfully */
    SILC_LOG_DEBUG(("Connected successfully, sock %d", conn->sock));
 -  conn->status = SILC_NET_OK;
 +  conn->status = SILC_OK;
    silc_fsm_next(fsm, silc_net_connect_st_finish);
    return SILC_FSM_CONTINUE;
  }
@@@ -855,6 -701,9 +855,9 @@@ SILC_FSM_STATE(silc_net_connect_st_fini
        silc_async_free(conn->op);
    }
  
+   if (conn->sock && conn->status != SILC_NET_OK)
+     silc_net_close_connection(conn->sock);
    return SILC_FSM_FINISH;
  }
  
@@@ -890,25 -739,15 +893,25 @@@ SilcAsyncOperation silc_net_tcp_connect
  {
    SilcNetConnect conn;
  
 -  if (!remote_ip_addr || remote_port < 1 || !schedule || !callback)
 +  if (!schedule) {
 +    schedule = silc_schedule_get_global();
 +    if (!schedule) {
 +      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
 +      return NULL;
 +    }
 +  }
 +
 +  if (!remote_ip_addr || remote_port < 1 || !callback) {
 +    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
      return NULL;
 +  }
  
    SILC_LOG_DEBUG(("Creating connection to host %s port %d",
                  remote_ip_addr, remote_port));
  
    conn = silc_calloc(1, sizeof(*conn));
    if (!conn) {
 -    callback(SILC_NET_NO_MEMORY, NULL, context);
 +    callback(silc_errno, NULL, context);
      return NULL;
    }
  
    conn->op = silc_async_alloc(silc_net_connect_abort, NULL, conn);
    if (!conn->op) {
      silc_free(conn);
 -    callback(SILC_NET_NO_MEMORY, NULL, context);
 +    callback(silc_errno, NULL, context);
      return NULL;
    }
  
    if (local_ip_addr)
 -    conn->local_ip = strdup(local_ip_addr);
 -  conn->remote = strdup(remote_ip_addr);
 +    conn->local_ip = silc_strdup(local_ip_addr);
 +  conn->remote = silc_strdup(remote_ip_addr);
    if (!conn->remote) {
      silc_async_free(conn->op);
      silc_free(conn->local_ip);
      silc_free(conn);
 -    callback(SILC_NET_NO_MEMORY, NULL, context);
 +    callback(silc_errno, NULL, context);
      return NULL;
    }
    conn->port = remote_port;
    conn->callback = callback;
    conn->context = context;
    conn->retry = 1;
 -  conn->status = SILC_NET_ERROR;
 +  conn->status = SILC_ERR;
  
    silc_fsm_init(&conn->fsm, conn, silc_net_connect_destructor, NULL, schedule);
    silc_fsm_start(&conn->fsm, silc_net_connect_st_start);
@@@ -954,10 -793,7 +957,10 @@@ void silc_net_close_connection(int sock
  
  int silc_net_set_socket_nonblock(SilcSocket sock)
  {
 -  return fcntl((int)sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
 +  int ret = fcntl((int)sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
 +  if (ret)
 +    silc_set_errno_posix(errno);
 +  return ret;
  }
  
  /* Converts the IP number string from numbers-and-dots notation to
@@@ -970,17 -806,9 +973,17 @@@ SilcBool silc_net_addr2bin(const char *
    if (silc_net_is_ip4(addr)) {
      /* IPv4 address */
      struct in_addr tmp;
 +
 +    if (bin_len < 4) {
 +      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
 +      return FALSE;
 +    }
 +
      ret = inet_aton(addr, &tmp);
 -    if (bin_len < 4)
 +    if (!ret) {
 +      silc_set_errno_posix(errno);
        return FALSE;
 +    }
  
      memcpy(bin, (unsigned char *)&tmp.s_addr, 4);
  #ifdef HAVE_IPV6
      SilcSockaddr *s;
  
      /* IPv6 address */
 -    if (bin_len < 16)
 +    if (bin_len < 16) {
 +      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
        return FALSE;
 +    }
  
      memset(&hints, 0, sizeof(hints));
      hints.ai_family = AF_INET6;
index 5626eef546ae4d8a82519d7aa8f1bb55e27d5762,80e8fbf264e9a471a1732ef98b1c3c7546f8f65e..1543d16ef4b646e6b20708a49ac7900b25143da6
@@@ -16,8 -16,9 +16,8 @@@
    GNU General Public License for more details.
  
  */
 -/* $Id$ */
  
 -#include "silc.h"
 +#include "silcruntime.h"
  
  #if defined(HAVE_EPOLL_WAIT)
  #include <sys/epoll.h>
@@@ -287,6 -288,7 +287,7 @@@ SilcBool silc_schedule_internal_schedul
        SILC_LOG_DEBUG(("epoll_ctl (DEL): %s", strerror(errno)));
        return FALSE;
      }
+     task->scheduled = FALSE;
      return TRUE;
    }
  
@@@ -353,7 -355,7 +354,7 @@@ void *silc_schedule_internal_init(SilcS
    SilcUnixScheduler internal;
    int i;
  
 -  internal = silc_calloc(1, sizeof(*internal));
 +  internal = silc_scalloc(schedule->stack, 1, sizeof(*internal));
    if (!internal)
      return NULL;
  
  #ifdef SILC_THREADS
    if (pipe(internal->wakeup_pipe)) {
      SILC_LOG_ERROR(("pipe() fails: %s", strerror(errno)));
 -    silc_free(internal);
      return NULL;
    }
  
@@@ -436,6 -439,8 +437,6 @@@ void silc_schedule_internal_uninit(Silc
  #elif defined(HAVE_POLL) && defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
    silc_free(internal->fds);
  #endif /* HAVE_POLL && HAVE_SETRLIMIT && RLIMIT_NOFILE */
 -
 -  silc_free(internal);
  }
  
  /* Wakes up the scheduler */
index 552fa611167d3326b0dfbaedf6926a20fcd8c859,60d458d4a19bb39be74a42dbd3ca625cf7ee32a6..35b0ceedcde1d702dc1c37496b9fbaee9a54fc1d
@@@ -16,8 -16,9 +16,8 @@@
    GNU General Public License for more details.
  
  */
 -/* $Id$ */
  
 -#include "silc.h"
 +#include "silcruntime.h"
  
  /************************ Static utility functions **************************/
  
@@@ -76,7 -77,6 +76,7 @@@ int silc_socket_stream_read(SilcStream 
    if (!sock->qos) {
      len = read(sock->sock, buf, buf_len);
      if (len < 0) {
 +      silc_set_errno_posix(errno);
        if (errno == EAGAIN || errno == EINTR) {
        SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
        silc_schedule_set_listen_fd(sock->schedule, sock->sock,
@@@ -88,6 -88,7 +88,6 @@@
        SILC_LOG_DEBUG(("Cannot read from socket: %d:%s",
                      sock->sock, strerror(errno)));
        silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
 -      sock->sock_error = errno;
        return -2;
      }
  
    /* If QoS was applied, return the data that was pending. */
    if (sock->qos->applied && sock->qos->data_len) {
      memcpy(buf, qosbuf, sock->qos->data_len);
+     len = sock->qos->data_len;
      sock->qos->data_len = 0;
-     return sock->qos->data_len;
+     return len;
    }
  
    /* If we have active QoS data pending, return with no data */
      return -1;
    }
  
-   /* Read the data from the socket.  Never read more than the max limit. */
+   /* Read the data from the socket.  The qosbuf size is always the max
+      read limit size. */
    len = (buf_len < sock->qos->read_limit_bytes ? buf_len :
         sock->qos->read_limit_bytes);
    len = read(sock->sock, qosbuf, len);
    if (len < 0) {
 +    silc_set_errno_posix(errno);
      if (errno == EAGAIN || errno == EINTR) {
        SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
        silc_schedule_set_listen_fd(sock->schedule, sock->sock,
      silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
      silc_schedule_task_del_by_context(sock->schedule, sock->qos);
      sock->qos->data_len = 0;
 -    sock->sock_error = errno;
      return -2;
    }
  
@@@ -185,7 -188,6 +187,7 @@@ int silc_socket_stream_write(SilcStrea
  
    ret = write(sock->sock, data, data_len);
    if (ret < 0) {
 +    silc_set_errno_posix(errno);
      if (errno == EAGAIN || errno == EINTR) {
        SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
        silc_schedule_set_listen_fd(sock->schedule, sock->sock,
      }
      SILC_LOG_DEBUG(("Cannot write to socket: %s", strerror(errno)));
      silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
 -    sock->sock_error = errno;
      return -2;
    }
  
@@@ -229,6 -232,27 +231,6 @@@ int silc_socket_udp_stream_write(SilcSt
    return silc_socket_stream_write(stream, data, data_len);
  }
  
 -#if 0
 -/* Returns human readable socket error message */
 -
 -SilcBool silc_socket_get_error(SilcStream sock, char *error,
 -                             SilcUInt32 error_len)
 -{
 -  char *err;
 -
 -  if (!sock->sock_error)
 -    return FALSE;
 -
 -  err = strerror(sock->sock_error);
 -  if (strlen(err) > error_len)
 -    return FALSE;
 -
 -  memset(error, 0, error_len);
 -  memcpy(error, err, strlen(err));
 -  return TRUE;
 -}
 -#endif
 -
  /* Closes socket */
  
  SilcBool silc_socket_stream_close(SilcStream stream)