Merge commit 'origin/silc.1.1.branch' master
authorPekka Riikonen <priikone@silcnet.org>
Sun, 5 Oct 2008 14:45:59 +0000 (17:45 +0300)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 5 Oct 2008 14:45:59 +0000 (17:45 +0300)
Conflicts:

CHANGES
TODO
apps/Makefile.ad
apps/autodist/CHANGES
apps/autodist/autodist.in
apps/autodist/doc/autodist.1.in
apps/autodist/doc/autodist.texi
apps/silcd/command.c
apps/silcd/server.c
apps/silcd/server_backup.c
apps/silcd/server_query.c
configure.ad
distdir/autodist
distdir/pre-dist-client
distdir/pre-dist-toolkit
includes/silc.h.in
includes/silcversion.h.in
lib/Makefile.ad
lib/configure.ad
lib/contrib/Makefile.ad
lib/silcasn1/silcasn1.c
lib/silcasn1/silcasn1_decode.c
lib/silcasn1/silcasn1_encode.c
lib/silcclient/client.h
lib/silcclient/client_entry.c
lib/silcclient/silcclient.h
lib/silccore/silcpacket.c
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/silcsim/Makefile.ad
lib/silcske/silcconnauth.c
lib/silcske/silcske.c
lib/silcskr/silcskr.c
lib/silcutil/silcatomic.h
lib/silcutil/silcbuffer.h
lib/silcutil/silcbuffmt.c
lib/silcutil/silcconfig.c
lib/silcutil/silcdlist.h
lib/silcutil/silcfdstream.c
lib/silcutil/silcfsm.c
lib/silcutil/silclist.h
lib/silcutil/silclog.c
lib/silcutil/silcmime.c
lib/silcutil/silcmutex.h
lib/silcutil/silcnet.h
lib/silcutil/silcschedule.c
lib/silcutil/silcschedule.h
lib/silcutil/silcschedule_i.h
lib/silcutil/silcsocketstream.c
lib/silcutil/silcsocketstream_i.h
lib/silcutil/silcstack.c
lib/silcutil/silcstack.h
lib/silcutil/silcstringprep.c
lib/silcutil/silctime.c
lib/silcutil/silctypes.h
lib/silcutil/silcutil.c
lib/silcutil/stacktrace.c
lib/silcutil/tests/test_silcschedule.c
lib/silcutil/tests/test_silctime.c
lib/silcutil/unix/silcunixnet.c
lib/silcutil/unix/silcunixschedule.c
lib/silcutil/unix/silcunixsocketstream.c
lib/silcutil/unix/silcunixthread.c
lib/silcutil/win32/silcwin32schedule.c
win32/libsilc/libsilc.def

20 files changed:
1  2 
CHANGES
TODO
apps/silcd/server.c
config.guess
configure.ad
distdir/server
distdir/toolkit
lib/Makefile.ad
lib/silcapputil/silcidcache.c
lib/silcclient/client.c
lib/silcclient/client_channel.c
lib/silcclient/client_entry.c
lib/silcclient/client_internal.h
lib/silcclient/client_register.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silccore/silccommand.h
lib/silccore/silcpacket.c
lib/silcske/silcconnauth.c
lib/silcske/silcske.c

diff --combined CHANGES
index c5f1ab5111d546ea09568ecaad423ac39a62ea4f,128c76fc0e4f0c678163c10a901c6b3d6d69f297..dfaf9cadbae55981ea2df9552cabef5e08e93242
+++ b/CHANGES
 -        Patch from Jérémy Bobbio.  Affected file is
+ 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.
 -        from Jérémy Bobbio.
++        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.
  
@@@ -1353,7 -1535,7 +1535,7 @@@ Sun Apr  3 14:58:53 EEST 2005  Pekka Ri
          file silcd/packet_receive.c.
  
        * Added getrusage() to take noise in SILC RNG.  A patch by
--        Mika Boström.  Affected files are configure.in.pre,
++        Mika Bostrm.  Affected files are configure.in.pre,
          includes/silcincludes.h.in, lib/silccrypt/silcrng.c.
  
  Sat Apr  2 18:09:30 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
@@@ -1523,7 -1705,7 +1705,7 @@@ Wed Nov 24 18:24:05 CET 2004  Pekka Rii
  Tue Nov 23 16:54:35 CET 2004  Pekka Riikonen <priikone@silcnet.org>
  
        * Fixed Win32 scheduler to not stuck anymore.  A patch from
--        Juha Räsänen.  Affected file is
++        Juha R�s�nen.  Affected file is
          lib/silcutil/win32/silcwin32schedule.c.
  
        * Fixed QoS parsing for connection blocks in server.  Affected
@@@ -1621,7 -1803,7 +1803,7 @@@ Sat Feb 28 16:25:09 EET 2004  Pekka Rii
          on the channel.  Affected file lib/silcclient/client_channel.c.
  
        * The channel private key used to decrypt message is now
--        delivered to the application in the 'channel_messageÃ' client
++        delivered to the application in the 'channel_message' client
          operation.  Affected files are lib/silcclient/silcclient.h
          and client_channel.c.
  
@@@ -2507,7 -2689,7 +2689,7 @@@ Tue Dec 17 10:05:00 CET 2002  Pekka Rii
          Aldous <Matthew@Aldous.com>.
  
        * Added better implementation using CriticalSection of
--        SilcMutex on WIN32.  A patch by Mikko Lähteenmäki
++        SilcMutex on WIN32.  A patch by Mikko L�hteenm�ki
          <mikko.lahteenmaki@pikabaana.net>.
  
        * Added some Winsock WIN32 compatiblity defines into
@@@ -2878,7 -3060,7 +3060,7 @@@ Sun Nov 24 18:26:42 EET 2002  Pekka Rii
          notifys in Irssi SILC Client.  Affected file is
          irssi/src/silc/core/client_ops.c.  Bug #82.
  
--      * Applied Ville Räsänen's manual page and --mandir bugfix
++      * Applied Ville R�s�nen's manual page and --mandir bugfix
          patch.  Affected files are configure.in.pre and Makefile.am.pre.
          Bug #88.
  
@@@ -3057,8 -3239,8 +3239,8 @@@ Thu Nov  7 10:05:28 CET 2002  Pekka Rii
  
  Wed Nov  6 17:18:13 EET 2002  Pekka Riikonen <priikone@silcnet.org>
  
--      * Fixed manual page installation patch by Ville Räsänen.
--        USERS help page fix patch by Ville Räsänen
++      * Fixed manual page installation patch by Ville R�s�nen.
++        USERS help page fix patch by Ville R�s�nen
  
        * Changed the silc_client_command_call interface to make
          the command call simpler for the application.  The library
@@@ -3104,7 -3286,7 +3286,7 @@@ Sun Nov  3 17:59:15 EET 2002  Pekka Rii
          was missing altogether.  Affected file silcd/command_reply.c.
          Bug #44.
  
--Sun Nov  3 00:42:05 EET 2002  Mika Boström <bostik@lut.fi>
++Sun Nov  3 00:42:05 EET 2002  Mika Bostrm <bostik@lut.fi>
  
        * Added man-pages for silc(1), silcd(8) and silcd.conf(5).
          Included yodl sources for each of these. Also modified
@@@ -3305,7 -3487,7 +3487,7 @@@ Sun Oct 20 14:12:24 CEST 2002  Pekka Ri
  Sat Oct 19 13:32:15 CEST 2002  Pekka Riikonen <priikone@silcnet.org>
  
        * ROBODoc documented lib/silcutil/silcbuffer.h and
--        lib/silcutil/silcdlist.h.  Patch by Ville Räsänen
++        lib/silcutil/silcdlist.h.  Patch by Ville R�s�nen
          <ville.rasanen@iki.fi>.
  
  Fri Oct 18 10:51:04 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
@@@ -3557,7 -3739,7 +3739,7 @@@ Sun Sep 15 12:25:10 EEST 2002  Pekka Ri
          file lib/silcutil/silcutil.[ch].
  
        * Added STATS command to client library and Irssi SILC client.
--        Patch provided by Ville Räsänen <ville.rasanen@iki.fi>.
++        Patch provided by Ville R�s�nen <ville.rasanen@iki.fi>.
  
  Wed Sep 11 09:22:00 CEST 2002  Pekka Riikonen <priikone@silcnet.org>
  
@@@ -3779,7 -3961,7 +3961,7 @@@ Fri Jun 28 11:53:25 CEST 2002 Pekka Rii
  Thu Jun 27 20:07:27 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
  
        * Buffer overflow with CUMODE command's mode->mode character
--        conversion.  Reported by Ville Räsänen.  Affected file
++        conversion.  Reported by Ville R�s�nen.  Affected file
          lib/silcutil/silcutil.c.
  
  Thu Jun 27 16:54:33 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
@@@ -3867,7 -4049,7 +4049,7 @@@ Tue Jun 25 18:47:39 EEST 2002 Pekka Rii
  
        * Fixed a bug in version string parsing which could crash
          the program with specially formatted version string.
--        Bug reported and patch provided by Ville Räsänen.  Affected
++        Bug reported and patch provided by Ville R�s�nen.  Affected
          file lib/silcutil/silcutil.c.
  
        * Handle the disconnection immediately when DISCONNECT
@@@ -7679,7 -7861,7 +7861,7 @@@ Thu Sep  6 12:47:37 EEST 2001  Pekka Ri
          Added function silc_client_nickname_format to the file
          lib/silcclient/idlist.c.  It performs the nickname formatting.
  
--        Added new field `hostname´ to the SilcClientEntry context.
++        Added new field `hostname to the SilcClientEntry context.
          It holds the hostname of the client.  Affected file is
          lib/silcclient/idlist.h.
  
@@@ -11050,7 -11232,7 +11232,7 @@@ Wed Feb 21 14:17:04 EET 2001  Pekka Rii
        * Fixed buffer overflow from lib/silcclient/command.c in USERS
          command parsing.
  
--Wed Feb 21 12:44:00 EET 2001  Mika Boström <bostik@lut.fi>
++Wed Feb 21 12:44:00 EET 2001  Mika Bostrm <bostik@lut.fi>
  
        * Changed all SilcConfigServer* and silc_config_server* to
          SilcServerConfig* and silc_server_config*, respectively.
diff --combined TODO
index e24199cef0424d387bc01fcb2ffecafbb3aa1b0c,d89901f838d4d88b4a9e2383c80f75b620de1642..e6950f06db8f133972622b978e342ba7981d623d
--- 1/TODO
--- 2/TODO
+++ b/TODO
 -TODO for 1.1
 -============
 +TODO for 1.2 And Beyond
 +=======================
  
  NOTE: Any item that doesn't have (***DONE) in it, isn't done yet.  The
  (***TESTING NEEDED) means that the item has been done but not yet properly
  tested.
  
 +NOTE: A TODO entry does not mean that it is ever going to be done.  Some
 +of the entries may be just ideas, good, bad or ugly.  If you want to work
 +on some of the TODO entries simply let us know about it by dropping a note
 +to silc-devel mailing list or appear on 'silc' channel on SILCNet.
  
 -apps/silcd, The SILC Server   ****PARTLY DONE****
 -===========================
 -
 - o Fix/test GETKEY. (***DONE)
 -
 - o Fix/test MOTD. (***DONE)
 -
 - o Rewrite rehash, HUP.
 -
 - o Heartbeat-keepalive.
 -
 - o Port all code to use SILC Toolkit 1.1 APIs. (***DONE)
 -
 - o Remove protocol.[ch].  (***DONE)
 -
 - o Rewrite connecting accepting. (***DONE)
 -
 - o Rewrite async connecting. (***DONE)
 -
 - o Test backup router resuming protocol. (***DONE)
 -
 - o Check all packet receive routines that they call silc_packet_free. 
 -   (***DONE)
 -
 - o Add Web statistics module using lib/silchttp.  Give out server
 -   statistics. (***DONE)
 -
 -
 -SILC Client   ****DONE****
 -===========
 -
 - o Porting to new Toolkit API and new Client Library API (***DONE)
 -
 - o Improve help files, especially /cmode, /cumode and /key. (***DONE)
 -
 -
 -lib/silcclient, The Client Library    ***DONE****
 -==================================
 -
 - o silcclient.h clean up and API rewrites. (***DONE)
 -
 - o silcclient_entry.h finishing, all entry relates APIs to this header.
 -   (***DONE)
 -
 - o SilcChannelEntry, SilcServerEntry, SilcChannelUser, allocating,
 -   freeing, finding, etc. rewrite.  Also making them reference counted for
 -   multi threads use. (***DONE)
 -
 - o Rewrite client side WHOIS command (for whois -details). (***DONE)
 -
 - o Finish all the missing SILC packet processings, rewrites. (***DONE)
 -
 - o The client_notify.c rewrite. (***DONE)
 -
 - o Resuming to client_register.c (remove client_resume.c) (***DONE)
 -
 - o Rekey rewrite. (***DONE)
 -
 - o Remove protocol.[ch]. (***DONE)
 -
 - o File transfer rewrite. (***DONE)
 -
 - o File transfer API documentation. (***DONE)
 -
 - o Connection auth request. (***DONE)
 -
 - o Password auth test, public key auth test. (***DONE)
 -
 - o Starting key exchange directly, rewrite. (***DONE)
 -
 - o Channel messages, channel private keys, channel entires, channel
 -   search, etc. rewrite. (***DONE)
 -
 - o For many APIs leave the hash context allocations to the caller instead
 -   of using client->sha1hash and client->md5hash, or some kind of thread
 -   safe (no locking) concept. (***DONE)
 -
 - o Key agreement rewrite. (***DONE)
 -
 - o Connecting to remote client (***DONE)
 -
 - o Private message waiting API (in threads) (***TESTING NEEDED)
 -
 - o client_attrs.c, attributes rewrite. (***DONE)
 -
 - o No SilcBuffer lists back to application in command_reply operations.
 -   Convert them all to real lists and/or structures for easier use.
 -   (***DONE)
 -
 - o Nickname formatting rewrite. (***DONE)
  
 - o UDP connections. (***TESTING NEEDED)
 -
 -
 -lib/silcsftp                  ****DONE****
 +lib/silccore
  ============
  
 - o Porting to use the new util library. (***DONE)
 -
 -
 -lib/silccore/silcpacket.[ch]  ****DONE****
 -============================
 -
 - o SilcPacketEngine. (***DONE)
 -
 - o New SILC Packet API. (***DONE)
 -
 - o Implement silc_packet_engine_stop and silc_packet_stream_destroy. (***DONE)
 -
 - o IV Included flag support, UDP transport support (***TESTING NEEDED)
 -
 -
 -lib/silccore/silcid.[ch]      ****DONE****
 -========================
 -
 - o Add silc_id_str2id to accept the destination buffer as argument
 -   and thus not require any memory allocation.  Same will happen
 -   with silc_id_payload_* functions. (***DONE)
 -
 - o silc_id_str2id, silc_id2str to non-allocating routines. (***DONE)
 -
 -
 -lib/silcskr   ****DONE****
 -===========
 -
 - o Removing key from the repository is not possible currently.  It should
 -   be. (***DONE)
 -
 -
 -lib/silcske/silcske.[ch]      ***DONE****
 -========================
 -
 - o Responder rekey (***DONE)
 -
 - o IV Included flag support in SKE (***DONE)
 + o SILC_PACKET_FLAG_ACK support.  Implement ACK packet and packet payload
 +   to silcpacket.c.
  
 - o UDP transport changes; retransmission support by using exponential
 -   backoff algorithm. (***DONE)
 + o All payload encoding routines should take SilcStack as argument.
  
-  o Remove SilcCommandCb from silccommand.h.
 - o SilcConnAuth header file documentation. (***DONE)
++ o Remove SilcCommandCb from silccommand.h. (***DONE)
  
 + o All payload test routines into lib/silccore/tests/.
  
 -lib/silccrypt                 ****DONE****
 -=============
  
 - o Implement PKCS #1 sign/verify with hash OID. (***TESTING NEEDED)
 -
 - o Implement SILC Public Key Version 2 handling in sign/verify.  Implement
 -   Version (V) identifier (***DONE)
 -
 - o SILC PKCS (silcpkcs.h) reorganizing when other PK supports added.
 -   Move the SILC Public Key routines away from the crypto library into
 -   the core library (silccore).  silc_pkcs_public/private_key_* routines
 -   to silc_public/private_key_* routines.  The silc_public_key_* routines
 -   should also automatically handle SILC Public Keys, and other keys
 -   and certificates as well.  Add fe. silcpk.h into silccore.  It should
 -   also include the Public Key Payload encoding and decoding routines.
 -   (***DONE)
 -
 - o Assembler AES (***DONE)
 -
 -
 -lib/silcutil                  ****DONE****
 -============
 +lib/silcclient, The Client Library
 +==================================
  
 - o The regex code from lib/contrib might compile fine on all platforms.
 -   No need to make it silcutil/unix/ specific.  Add them to generic
 -   silcutil.c. (***DONE)
++ o LIST command should take server name as argument, a server name whose
++   channels to list.  This way it is possible to list channels from
++   any server in internet, eg.  /LIST example.com.
 - o Silc FD Stream to WIN32 (lib/silcutil/silcfdstream.h) (***TESTING NEEDED)
 + o UDP SILC connection support to SILC server
  
 - o bool -> SilcBool (***DONE)
 + o Giving WHOIS for nick that doesn't exist should remove any same
 +   named entries from the client cache.
  
 + o peer-to-peer private messages
  
 -lib/silcutil/silcbuffer.h     ****DONE****
 -=========================
 + o Private message key request notification to application.  See XXX in
 +   client_prvmsg.c.
  
 - o Remove the `truelen' field from SilcBuffer as it is entirely
 -   redundant since we can get the true length of the buffer by
 -   doing buffer->end - buffer->header.  Add silc_buffer_truelen
 -   macro instead.  Consider also removing `len' field too since
 -   it effectively is buffer->tail - buffer->data, and adding
 -   silc_buffer_len macro can do the same.  These would save
 -   totally 8 bytes of memory per buffer. (***DONE)
 + o in JOIN notify handle resolving that timedout.  Currently the user is
 +   never joined the channel if this happens.  What to do if message is
 +   received from user that hasn't been resolved/joined?
  
-  o Add the SilcStream (socket stream) from the SilcPacketStream and
-    SilcSocket from the socket stream to SilcClientConnection for easier
-    access to them for programmers.  Currently these have to be digged up
-    from the packet stream.
 + o Connection option that attemps to connect to remot host with various
 +   different mechanisms: UDP 706, TCP 706, TCP 80, TCP 443, UDP 7706 and
 +   TCP 7706.  This is the so called hole punching mechanism.
  
 -lib/silcutil/silcbuffmt.[ch]  ****DONE****
 -============================
 + o Message ACKing support.
  
 - o SilcStack aware silc_buffer_unformat (***DONE)
 + o in /cmode and /cumode with +r, maybe the public key and private key
 +   could be just some "string", which would then match to "string.pub" and
 +   "string.prv".
  
 - o SilcStack aware silc_buffer_format (***DONE)
 + o If the SILC Events (see below) are implemented, perhaps client library
 +   should provide events so that application developer has a choice of
 +   developing the SILC app with callbacks or with events.
  
 - o silc_buffer_format reallocates automatically (***DONE)
 + o Ability to recover from rekey errors, at least try to.
  
 - o SILC_STR_OFFSET (***DONE)
++ o Add the SilcStream (socket stream) from the SilcPacketStream and
++   SilcSocket from the socket stream to SilcClientConnection for easier
++   access to them for programmers.  Currently these have to be digged up
++   from the packet stream. (***DONE)
  
 -lib/silcutil/silcstack.[ch]   ****DONE****
 +SFTP Library, lib/silcsftp/
  ===========================
  
 - o Data stack implementation (***DONE)
 -
 -
 -lib/silcutil/silcstream.[ch]  ****DONE****
 -============================
 -
 - o Add abstract SilcStream. (***DONE)
 + o Read prefetch (read-ahead, reading ahead of time).  Maybe if this can
 +   be done easily.
  
  
 -lib/silcutil/silcsocketstream.[ch]    ****DONE****
 -==================================
 -
 - o Add SilcSocketStream (***DONE)
 -
 - o Add SilcSocketStream for WIN32 (***TESTING NEEDED)
 -
 - o Test QoS after the changes made to socket stream
 -
 +lib/silcske/silcske.[ch]
 +========================
  
 -lib/silcutil/silcschedule*.[ch]               ****DONE****
 -===============================
 + o Ratelimit to UDP/IP transport for incoming packets.
  
 - o Scheduler can be optimized for FD tasks by changing the fd_queue
 -   to SilcHashTable instead of using linked list.  We need to do
 -   one-to-one mapping of FD to task and hash table is more efficient
 -   for this usage.
  
 -   Also redefine the silc_select to perhaps return a separate
 -   structure of the events that actually occurred, instead of
 -   returning the events in the fd_list which is then traversed
 -   in the generic code to find the changed events.  This can be
 -   made faster by having own struct which includes only the
 -   changed events, thus the tarversing is faster since the whole
 -   fd_list is not traversed anymore (it is still traversed in the
 -   silc_select but at least it removes one extra tarversing later
 -   for the same list).
 +apps/silcd
 +==========
  
 -   Other task queues should be changed to use SilcList.  (***DONE)
 + o Deprecate the old server.  Write interface for the new lib/silcserver
 +   server library.  The interface should work on Unix/Linux systems.
  
 - o Add SILC scheduler's internal routines into a table of implementation
 -   function pointers, that the generic code then takes as extern from
 -   implementation.  These are the silc_schedule_internal_* routines.
 -   (***DONE)
 + o Consider deprecating also the old config file format and use XML
 +   istead.  This should require SILC XML API implementation first.
  
 - o Change SILC_TASK_CALLBACK to non-static, and remove the macro
 -   SILC_TASK_CALLBACK_GLOBAL. (***DONE)
 + o The configuration must support dynamic router and server connections.
 +   The silcd must work without specifying any servers or routers to
 +   connect to.
  
 - o SILC Schedule API changes to WIN32. (***DONE)
 + o The configuration must support specifying whether the server is
 +   SILC Server or SILC Router.  This should not be deduced from the
 +   configuration as it was in < 1.2.
  
 + o The configuration must support specifying the ciphers and hmacs and
 +   their order so that user can specify which algorithms take preference.
  
 -lib/silcutil/silcasync.[ch]   ****DONE****
 -===========================
  
 - o Add SilcAsyncOperation to utility library.  Any function that takes
 -   callback as an argument must/should return SilcAsyncOperation.
 -   (***DONE)
 +lib/silcserver
 +==============
  
 + o Rewrite the entire server.  Deprecate apps/silcd as the main server
 +   implementation and create lib/silcserver/.  It is a platform
 +   independent server library.  The apps/silcd will merely provide a
 +   a simple interface for the library.
  
 -lib/silcutil/silctime.[ch]    ****DONE****
 -===========================
 + o Write the SILC Server library extensively using SILC FSM.
  
 - o SilcTime. (***DONE)
 + o Server library must support multiple networks.  This means that one
 +   server must be able to create multiple connections that each reach
 +   different SILC network.  This means also that all cache's etc. must
 +   be either connection-specific or network-specific.
  
 - o system time, universal, generalized. (***DONE)
 + o Library must support dynamic router and server connections.  This means
 +   that connections are create only when they are needed, like when someone
 +   says JOIN foo@foo.bar.com or WHOIS foobar@silcnet.org.
  
 + o Library must support server-to-server connections even though protocol
 +   prohibits that.  The responder of the connection should automatically
 +   act as a router.  The two servers create an own, isolated, SILC network.
 +   To be used specifically with dynamic connections.
  
 -lib/silcutil/silcfsm.[ch]     ****DONE****
 -=========================
 + o Library must support multiple threads and must be entirely thread safe.
  
 - o SILC Finite State Machine API.  Replaces SILC Protocol API (***DONE)
 + o Library must have support for SERVICE command.
  
 + o Both UDP and TCP support for incoming connecetions.  Maintaining long
 +   term UDP sessions.
  
 -lib/silcutil/silcnet*, lib/silcutil/*/silc*net*               ****DONE****
 -===============================================
 + o The server must be able to run behind NAT device.  This means that
 +   Server ID must be based on public IP instead of private IP (See
 +   also NAT detection protocol in SILC protocol specification).
  
 - o Add UDP interface (***DONE)
 + o The following data must be in per-connection context: client id cache,
 +   server id cache, channel id cache, all statistics must be
 +   per-connection.
  
 - o Add UDP interface for WIN32 (***TESTING NEEDED)
 + o The following data must be in per-thread context: command context
 +   freelist/pool, pending commands, random number generator.
  
 - o New network interfaces (***DONE)
 + o Do inccoming packet processing in an own FSM thread in the
 +   server-threads FSM.  Same as in client library.
  
 + o Binding to other ports than 706 too.  To allow easier traversing
 +   through NATs and firewalls server should also bind to 80, 443 and 7706
 +   by default (at least try to bind).  Connections must work normally
 +   even if they were established to some other port other than 706.
  
 -lib/silcmath                  ****DONE****
 -============
 +   Connection option that attemps to connect to remot server with various
 +   different mechanisms: UDP 706, TCP 706, TCP 80, TCP 443, UDP 7706 and
 +   TCP 7706.  This is the so called hole punching mechanism.
  
 - o Test on x86_64. (***TESTING NEEDED)
 + o Ability to recover from rekey errors, at least try to.
  
 - o Change LTM and TFM function names when importing to SILC tree to avoid
 -   rare linking problems on system that has same named symbols already in
 -   the system. (***DONE)
 + o Reference count all Silc*Entry structures.
  
 -lib/silcutil/symbian/         ****DONE****
 -=====================
++ o All channel names in any command (where appropriate) must be allowed to
++   be in format channel@server so that the server can be connected to do
++   the command for the channel.  Change protocol if it doesn't allow it.
 -  o lib/silcutil/symbian routines missing or not completed.
 -    (****TESTING NEEDED)
++ o All nicknames in any command (where appropriate) must be allowed to be
++   in format nick@server so that the server can be connected to do the
++   command for the nickname.  Change protocol if it doesn't allow it.
 + Some issues that must be kept in mind from 1.0 and 1.1 silcd's:
  
 -  o Something needs to be thought to the logging globals as well,
 -    like silc_debug etc.  They won't work on EPOC.  Perhaps logging
 -    and debugging is to be disabled on EPOC.
 + o The server and router software MUST work out of the box.  After
 +   installation the server must not require any configuration to run the
 +   most basic working configuration.  No defining IP addresses, etc.
 +   The server must work just by running it.
  
 + o The SERVER_SIGNOFF notify handing is not optimal, because it'll
 +   cause sending of multiple SIGNOFF notify's instead of the one
 +   SERVER_SIGNOFF notify that the server received.  This should be
 +   optimized so that the only SERVER_SIGNOFF is sent and not
 +   SIGNOFF of notify at all (using SIGNOFF takes the idea about
 +   SERVER_SIGNOFF away entirely).
  
 -lib/silcasn1                  ****DONE****
 -============
 + o Another SERVER_SIGNOFF opt/bugfix:  Currently the signoff is
 +   sent to a client if it is on same channel as the client that
 +   signoffed.  However, the entire SERVER_SIGNOFF list is sent to
 +   the client, ie. it may receive clients that was not on the
 +   same channel.  This is actually against the specs.  It must be
 +   done per channel.  It shouldn't receive the whole list just
 +   because one client happened to be on same channel.
  
 - o ASN.1 library (***DONE)
 + o If client's public key is saved in the server (and doing public key
 +   authentication) then the hostname and the username information could
 +   be taken from the public key.  Should be a configuration option!
  
 - o Header documentation missing. (***DONE)
 + o Add a timeout to handling incoming JOIN commands.  It should be
 +   enforced that JOIN command is executed only once in a second or two
 +   seconds.  Now it is possible to accept n incoming JOIN commands
 +   and process them without any timeouts.  THis must be employed because
 +   each JOIN command will create and distribute the new channel key
 +   to everybody on the channel.
  
 - o Some string encodings missing (copy/paste matter). (***DONE)
 + o Related to above.  If multiple JOINs are received in sequence perhaps
 +   new key should be created only once, if the JOINs are handeled at the same
 +   time.  Now we create multiple keys and never end up using them because
 +   many JOINs are processed at the same time in sequence.  Only the last
 +   key ends up being used.
diff --combined apps/silcd/server.c
index 46fccfc085d68ca3bb47b682dd69c7026be39a14,c2df082c61118703639b85fca1f9ad34de233bfd..f03581bcd081bbe9135d07e59bf6ba2f103be4a4
@@@ -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
@@@ -103,12 -103,13 +103,13 @@@ static SilcBool silc_server_packet_rece
         !(idata->status & SILC_IDLIST_STATUS_REGISTERED)) &&
        packet->type != SILC_PACKET_NEW_CLIENT &&
        packet->type != SILC_PACKET_NEW_SERVER &&
+       packet->type != SILC_PACKET_RESUME_CLIENT &&
        packet->type != SILC_PACKET_CONNECTION_AUTH_REQUEST &&
        packet->type != SILC_PACKET_DISCONNECT)
      return FALSE;
  
-   /* NEW_CLIENT and NEW_SERVER are accepted only without source ID
-      and for unregistered connection. */
+   /* NEW_CLIENT and NEW_SERVER are accepted only without source ID and
+      for unregistered connection. */
    if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT ||
                         packet->type == SILC_PACKET_NEW_SERVER) &&
        (idata->status & SILC_IDLIST_STATUS_REGISTERED))
        silc_id_str2id(packet->src_id, packet->src_id_len,
                       packet->src_id_type, &client_id, sizeof(client_id))) {
        if (!SILC_ID_CLIENT_COMPARE(client->id, &client_id)) {
-       SILC_LOG_DEBUG(("Packet source is not same as sender"));
+       SILC_LOG_DEBUG(("Packet source is not same as sender, packet %s",
+                       silc_get_packet_name(packet->type)));
        return FALSE;
        }
      }
@@@ -192,14 -194,17 +194,17 @@@ static void silc_server_packet_eos(Silc
    SilcServer server = callback_context;
    SilcIDListData idata = silc_packet_get_context(stream);
  
-   SILC_LOG_DEBUG(("End of stream received"));
+   SILC_LOG_DEBUG(("End of stream received, sock %p", stream));
  
    if (!idata)
      return;
  
    if (server->router_conn && server->router_conn->sock == stream &&
        !server->router && server->standalone) {
+     if (idata->sconn && idata->sconn->callback)
+       (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
      silc_server_create_connections(server);
+     silc_server_free_sock_user_data(server, stream, NULL);
    } else {
      /* If backup disconnected then mark that resuming will not be allowed */
       if (server->server_type == SILC_ROUTER && !server->backup_router &&
          server->backup_closed = TRUE;
      }
  
+     if (idata->sconn && idata->sconn->callback)
+       (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
      silc_server_free_sock_user_data(server, stream, NULL);
    }
  
@@@ -236,6 -243,8 +243,8 @@@ SILC_TASK_CALLBACK(silc_server_packet_e
          server->backup_closed = TRUE;
      }
  
+     if (idata->sconn && idata->sconn->callback)
+       (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
      silc_server_free_sock_user_data(server, stream, NULL);
    }
  
@@@ -256,6 -265,8 +265,8 @@@ static void silc_server_packet_error(Si
    const char *ip;
    SilcUInt16 port;
  
+   SILC_LOG_DEBUG(("Packet error, sock %p", stream));
    if (!idata || !sock)
      return;
  
                  SILC_CONNTYPE_STRING(idata->conn_type),
                  silc_packet_error_string(error)));
  
+   if (!silc_packet_stream_is_valid(stream))
+     return;
    silc_schedule_task_add_timeout(server->schedule,
                                 silc_server_packet_error_timeout,
                                 stream, 0, 0);
@@@ -666,6 -680,10 +680,10 @@@ void silc_server_free(SilcServer server
      }
    }
  
+   silc_schedule_task_del_by_context(server->schedule, server);
+   silc_schedule_uninit(server->schedule);
+   server->schedule = NULL;
    silc_idcache_free(server->local_list->clients);
    silc_idcache_free(server->local_list->servers);
    silc_idcache_free(server->local_list->channels);
    silc_skr_free(server->repository);
    silc_packet_engine_stop(server->packet_engine);
  
 +  silc_schedule_task_del_by_context(server->schedule, server);
 +  silc_schedule_uninit(server->schedule);
 +  server->schedule = NULL;
 +
    silc_free(server->local_list);
    silc_free(server->global_list);
    silc_free(server->server_name);
@@@ -915,15 -929,19 +933,18 @@@ SilcBool silc_server_init(SilcServer se
      }
    }
  
 -
+   if (server->server_type != SILC_ROUTER) {
+     server->stat.servers = 1;
+     server->stat.cell_servers = 1;
+   } else {
+     server->stat.routers = 1;
+   }
    /* If we are normal server we'll retrieve network statisticial information
       once in a while from the router. */
    if (server->server_type != SILC_ROUTER)
      silc_schedule_task_add_timeout(server->schedule, silc_server_get_stats,
                                   server, 10, 0);
  
-   if (server->server_type == SILC_ROUTER)
-     server->stat.routers++;
    /* Start packet engine */
    server->packet_engine =
      silc_packet_engine_start(server->rng, server->server_type == SILC_ROUTER,
@@@ -1202,6 -1220,9 +1223,9 @@@ void silc_server_stop(SilcServer server
      while ((ps = silc_dlist_get(list))) {
        SilcIDListData idata = silc_packet_get_context(ps);
  
+       if (!silc_packet_stream_is_valid(ps))
+       continue;
        if (idata)
        idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
  
                                     silc_server_connect_router);
    silc_schedule_task_del_by_callback(server->schedule,
                                     silc_server_connect_to_router_retry);
+   silc_schedule_task_del_by_callback(server->schedule,
+                                    silc_server_connect_to_router);
  
    silc_schedule_stop(server->schedule);
  
@@@ -1246,13 -1269,10 +1272,12 @@@ SILC_TASK_CALLBACK(silc_server_purge_ex
  
    silc_dlist_start(server->expired_clients);
    while ((client = silc_dlist_get(server->expired_clients))) {
-     if (client->data.status & SILC_IDLIST_STATUS_REGISTERED)
 +      continue;
 +
      /* For unregistered clients the created timestamp is actually
         unregistered timestamp.  Make sure client remains in history
         at least 500 seconds. */
-     if (curtime - client->data.created < 500)
+     if (client->data.created && curtime - client->data.created < 500)
        continue;
  
      id_list = (client->data.status & SILC_IDLIST_STATUS_LOCAL ?
  
  void silc_server_connection_free(SilcServerConnection sconn)
  {
+   if (!sconn)
+     return;
    SILC_LOG_DEBUG(("Free connection %p", sconn));
    silc_dlist_del(sconn->server->conns, sconn);
    silc_server_config_unref(&sconn->conn);
@@@ -1306,7 -1328,8 +1333,8 @@@ void silc_server_create_connection(Silc
    sconn->no_conf = dynamic;
    sconn->server = server;
  
-   SILC_LOG_DEBUG(("Created connection %p", sconn));
+   SILC_LOG_DEBUG(("Created connection %p to %s:%d", sconn,
+                 remote_host, port));
  
    silc_schedule_task_add_timeout(server->schedule, silc_server_connect_router,
                                 sconn, 0, 0);
@@@ -1330,19 -1353,28 +1358,26 @@@ silc_server_ke_auth_compl(SilcConnAuth 
    SilcID remote_id;
    const char *ip;
  
-   SILC_LOG_DEBUG(("Connection authentication completed"));
+   SILC_LOG_DEBUG(("Connection %p authentication completed, entry %p",
+                 sconn, entry));
  
-   sconn->op = NULL;
+   entry->op = NULL;
  
    if (success == FALSE) {
      /* Authentication failed */
-     /* XXX retry connecting */
  
-     silc_server_disconnect_remote(server, sconn->sock,
-                                 SILC_STATUS_ERR_AUTH_FAILED, NULL);
+     /* Try reconnecting if configuration wants it */
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+       return;
+     }
      if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-     silc_server_connection_free(sconn);
+     silc_server_free_sock_user_data(server, sconn->sock, NULL);
 -    silc_server_disconnect_remote(server, sconn->sock,
 -                                SILC_STATUS_ERR_AUTH_FAILED, NULL);
      return;
    }
  
                                      strdup(sconn->remote_host),
                                      SILC_SERVER, NULL, NULL, sconn->sock);
      if (!id_entry) {
 +      silc_server_disconnect_remote(server, sconn->sock,
 +                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-       silc_server_connection_free(sconn);
-       silc_free(entry);
+       silc_server_free_sock_user_data(server, sconn->sock, NULL);
 -      silc_server_disconnect_remote(server, sconn->sock,
 -                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        return;
      }
  
+     /* Statistics */
+     server->stat.my_servers++;
+     if (server->server_type == SILC_ROUTER)
+       server->stat.servers++;
+     SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers));
      silc_idlist_add_data(id_entry, (SilcIDListData)entry);
      break;
  
                             SILC_STR_DATA(server->server_name,
                                           strlen(server->server_name)),
                             SILC_STR_END)) {
 +      silc_server_disconnect_remote(server, sconn->sock,
 +                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-       silc_server_connection_free(sconn);
-       silc_free(entry);
+       silc_server_free_sock_user_data(server, sconn->sock, NULL);
 -      silc_server_disconnect_remote(server, sconn->sock,
 -                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        return;
      }
  
                                                  SILC_ID_SERVER),
                                      NULL, sconn->sock);
      if (!id_entry) {
-       silc_server_disconnect_remote(server, sconn->sock,
-                                   SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+       /* Try reconnecting if configuration wants it */
+       if (!sconn->no_reconnect) {
+         silc_schedule_task_add_timeout(server->schedule,
+                                      silc_server_connect_to_router_retry,
+                                      sconn, 1, 0);
+         silc_dlist_del(server->conns, sconn);
+         return;
+       }
        if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-       silc_server_connection_free(sconn);
-       silc_free(entry);
+       silc_server_free_sock_user_data(server, sconn->sock, NULL);
 -      silc_server_disconnect_remote(server, sconn->sock,
 -                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        return;
      }
  
      idata->status |= (SILC_IDLIST_STATUS_REGISTERED |
                      SILC_IDLIST_STATUS_LOCAL);
      idata->sconn = sconn;
+     idata->sconn->callback = NULL;
+     /* Statistics */
+     server->stat.my_routers++;
+     if (server->server_type == SILC_ROUTER)
+       server->stat.routers++;
+     SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers));
  
      if (!sconn->backup) {
        /* Mark this router our primary router if we're still standalone */
          silc_server_backup_add(server, server->id_entry, ip,
                                 sconn->remote_port, TRUE);
        }
+       }
  #if 0
-       } else {
+         else {
        /* We already have primary router.  Disconnect this connection */
        SILC_LOG_DEBUG(("We already have primary router, disconnect"));
        silc_idlist_del_server(server->global_list, id_entry);
 +      silc_server_disconnect_remote(server, sconn->sock,
 +                                    SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        if (sconn->callback)
          (*sconn->callback)(server, NULL, sconn->callback_context);
-       silc_server_connection_free(sconn);
-       silc_free(entry);
+       silc_server_free_sock_user_data(server, sconn->sock, NULL);
+       silc_server_disconnect_remote(server, sconn->sock,
+                                     SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        return;
- #endif /* 0 */
        }
+ #endif /* 0 */
      } else {
        /* Add this server to be our backup router */
        id_entry->server_type = SILC_BACKUP_ROUTER;
      break;
  
    default:
 +    silc_server_disconnect_remote(server, sconn->sock,
 +                                SILC_STATUS_ERR_AUTH_FAILED, NULL);
      if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-     silc_server_connection_free(sconn);
-     silc_free(entry);
+     silc_server_free_sock_user_data(server, sconn->sock, NULL);
 -    silc_server_disconnect_remote(server, sconn->sock,
 -                                SILC_STATUS_ERR_AUTH_FAILED, NULL);
      return;
    }
  
    /* Set the entry as packet stream context */
    silc_packet_set_context(sconn->sock, id_entry);
  
-  out:
    /* Call the completion callback to indicate that we've connected to
       the router */
    if (sconn && sconn->callback)
@@@ -1550,9 -1599,9 +1602,9 @@@ static void silc_server_ke_completed(Si
  {
    SilcPacketStream sock = context;
    SilcUnknownEntry entry = silc_packet_get_context(sock);
-   SilcServerConnection sconn = silc_ske_get_context(ske);
-   SilcServer server = entry->server;
-   SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
+   SilcServerConnection sconn;
+   SilcServer server;
+   SilcServerConfigRouter *conn;
    SilcAuthMethod auth_meth = SILC_AUTH_NONE;
    void *auth_data = NULL;
    SilcUInt32 auth_data_len = 0;
    SilcHmac hmac_send, hmac_receive;
    SilcHash hash;
  
-   sconn->op = NULL;
+   server = entry->server;
+   sconn = entry->data.sconn;
+   conn = sconn->conn.ref_ptr;
+   entry->op = NULL;
+   SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry));
  
    if (status != SILC_SKE_STATUS_OK) {
      /* SKE failed */
      SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
                    silc_ske_map_status(status), entry->hostname, entry->ip));
-     /* XXX retry connecting */
      silc_ske_free(ske);
-     silc_server_disconnect_remote(server, sconn->sock,
-                                 SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+     /* Try reconnecting if configuration wants it */
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+       return;
+     }
      if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-     silc_server_connection_free(sconn);
+     silc_server_free_sock_user_data(server, sconn->sock, NULL);
 -    silc_server_disconnect_remote(server, sconn->sock,
 -                                SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
      return;
    }
  
    /* Set the keys into use.  The data will be encrypted after this. */
    if (!silc_ske_set_keys(ske, keymat, prop, &send_key, &receive_key,
                         &hmac_send, &hmac_receive, &hash)) {
+     silc_ske_free(ske);
  
-     /* XXX retry connecting */
+     /* Try reconnecting if configuration wants it */
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+       return;
+     }
  
      /* Error setting keys */
-     silc_ske_free(ske);
 +    silc_server_disconnect_remote(server, sconn->sock,
 +                                SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
      if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-     silc_server_connection_free(sconn);
+     silc_server_free_sock_user_data(server, sconn->sock, NULL);
 -    silc_server_disconnect_remote(server, sconn->sock,
 -                                SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
      return;
    }
    silc_packet_set_keys(sconn->sock, send_key, receive_key, hmac_send,
    connauth = silc_connauth_alloc(server->schedule, ske,
                                 server->config->conn_auth_timeout);
    if (!connauth) {
-     /* XXX retry connecting */
+     silc_ske_free(ske);
+     /* Try reconnecting if configuration wants it */
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+       return;
+     }
  
      /** Error allocating auth protocol */
-     silc_ske_free(ske);
 +    silc_server_disconnect_remote(server, sconn->sock,
 +                                SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
      if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
-     silc_server_connection_free(sconn);
+     silc_server_free_sock_user_data(server, sconn->sock, NULL);
 -    silc_server_disconnect_remote(server, sconn->sock,
 -                                SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
      return;
    }
  
    entry->data.rekey = rekey;
  
    /* Start connection authentication */
-   sconn->op =
+   entry->op =
      silc_connauth_initiator(connauth, server->server_type == SILC_SERVER ?
                            SILC_CONN_SERVER : SILC_CONN_ROUTER, auth_meth,
                            auth_data, auth_data_len,
@@@ -1663,6 -1740,16 +1741,16 @@@ void silc_server_start_key_exchange(Sil
    if (!sconn->sock) {
      SILC_LOG_ERROR(("Cannot connect: cannot create packet stream"));
      silc_stream_destroy(sconn->stream);
+     /* Try reconnecting if configuration wants it */
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+       return;
+     }
      if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
      silc_server_connection_free(sconn);
    if (!silc_packet_set_ids(sconn->sock, SILC_ID_SERVER, server->id,
                           0, NULL)) {
      silc_packet_stream_destroy(sconn->sock);
+     /* Try reconnecting if configuration wants it */
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+       return;
+     }
      if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
      silc_server_connection_free(sconn);
    entry = silc_calloc(1, sizeof(*entry));
    if (!entry) {
      silc_packet_stream_destroy(sconn->sock);
+     /* Try reconnecting if configuration wants it */
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+       return;
+     }
+     if (sconn->callback)
+       (*sconn->callback)(server, NULL, sconn->callback_context);
      silc_server_connection_free(sconn);
      return;
    }
    entry->server = server;
+   entry->data.sconn = sconn;
    silc_packet_set_context(sconn->sock, entry);
  
+   SILC_LOG_DEBUG(("Created unknown connection %p", entry));
    /* Set Key Exchange flags from configuration, but fall back to global
       settings too. */
    memset(&params, 0, sizeof(params));
      params.flags |= SILC_SKE_SP_FLAG_PFS;
  
    /* Start SILC Key Exchange protocol */
-   SILC_LOG_DEBUG(("Starting key exchange protocol"));
+   SILC_LOG_DEBUG(("Starting key exchange protocol, connection %p", sconn));
    ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
                       server->public_key, server->private_key, sconn);
    if (!ske) {
      silc_free(entry);
      silc_packet_stream_destroy(sconn->sock);
+     /* Try reconnecting if configuration wants it */
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+       return;
+     }
      if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
      silc_server_connection_free(sconn);
    /* Start key exchange protocol */
    params.version = silc_version_string;
    params.timeout_secs = server->config->key_exchange_timeout;
-   sconn->op = silc_ske_initiator(ske, sconn->sock, &params, NULL);
+   entry->op = silc_ske_initiator(ske, sconn->sock, &params, NULL);
  }
  
  /* Timeout callback that will be called to retry connecting to remote
@@@ -1748,7 -1870,7 +1871,7 @@@ SILC_TASK_CALLBACK(silc_server_connect_
  
    /* If we've reached max retry count, give up. */
    if ((sconn->retry_count > param->reconnect_count) &&
-       !param->reconnect_keep_trying) {
+       sconn->no_reconnect) {
      SILC_LOG_ERROR(("Could not connect, giving up"));
  
      if (sconn->callback)
@@@ -1782,7 -1904,7 +1905,7 @@@ static void silc_server_connection_esta
  
    switch (status) {
    case SILC_NET_OK:
-     SILC_LOG_DEBUG(("Connection to %s:%d established",
+     SILC_LOG_DEBUG(("Connection %p to %s:%d established", sconn,
                    sconn->remote_host, sconn->remote_port));
  
      /* Continue with key exchange protocol */
      SILC_LOG_ERROR(("Could not connect to %s:%d: %s",
                    sconn->remote_host, sconn->remote_port,
                    silc_net_get_error_string(status)));
-     if (sconn->callback)
-       (*sconn->callback)(server, NULL, sconn->callback_context);
-     silc_server_connection_free(sconn);
+     if (!sconn->no_reconnect) {
+       silc_schedule_task_add_timeout(sconn->server->schedule,
+                                    silc_server_connect_to_router_retry,
+                                    sconn, 1, 0);
+       silc_dlist_del(server->conns, sconn);
+     } else {
+       if (sconn->callback)
+       (*sconn->callback)(server, NULL, sconn->callback_context);
+       silc_server_connection_free(sconn);
+     }
      break;
  
    default:
@@@ -1849,6 -1977,8 +1978,8 @@@ SILC_TASK_CALLBACK(silc_server_connect_
        SILC_LOG_INFO(("Unconfigured %s connection %s:%d, cannot connect",
                     (sconn->backup ? "backup router" : "router"),
                     sconn->remote_host, sconn->remote_port));
+       if (sconn->callback)
+       (*sconn->callback)(server, NULL, sconn->callback_context);
        silc_server_connection_free(sconn);
        return;
      }
    if (!sconn->op) {
      SILC_LOG_ERROR(("Could not connect to router %s:%d",
                    sconn->remote_host, sconn->remote_port));
+     if (sconn->callback)
+       (*sconn->callback)(server, NULL, sconn->callback_context);
      silc_server_connection_free(sconn);
      return;
    }
@@@ -1883,6 -2015,7 +2016,7 @@@ SILC_TASK_CALLBACK(silc_server_connect_
    SilcServer server = context;
    SilcServerConnection sconn;
    SilcServerConfigRouter *ptr;
+   SilcServerConfigConnParams *param;
  
    /* Don't connect if we are shutting down. */
    if (server->server_shutdown)
        }
      }
  
+     param = (ptr->param ? ptr->param : &server->config->param);
      /* Allocate connection object for hold connection specific stuff. */
      sconn = silc_calloc(1, sizeof(*sconn));
      if (!sconn)
        sconn->backup_replace_ip = strdup(ptr->backup_replace_ip);
        sconn->backup_replace_port = ptr->backup_replace_port;
      }
+     sconn->no_reconnect = param->reconnect_keep_trying == FALSE;
  
      SILC_LOG_DEBUG(("Created connection %p", sconn));
--
      if (!server->router_conn && !sconn->backup)
        server->router_conn = sconn;
  
@@@ -2022,7 -2158,16 +2158,16 @@@ silc_server_accept_get_auth(SilcConnAut
      if (cconfig->publickeys)
        *repository = server->repository;
  
-     entry->data.conn_type = conn_type;
+     if (cconfig->publickeys) {
+       if (server->config->prefer_passphrase_auth) {
+       *repository = NULL;
+       } else {
+       *passphrase = NULL;
+       *passphrase_len = 0;
+       }
+     }
+     entry->conn_type = conn_type;
      return TRUE;
    }
  
      if (sconfig->publickeys)
        *repository = server->repository;
  
-     entry->data.conn_type = conn_type;
+     if (sconfig->publickeys) {
+       if (server->config->prefer_passphrase_auth) {
+       *repository = NULL;
+       } else {
+       *passphrase = NULL;
+       *passphrase_len = 0;
+       }
+     }
+     entry->conn_type = conn_type;
      return TRUE;
    }
  
      if (rconfig->publickeys)
        *repository = server->repository;
  
-     entry->data.conn_type = conn_type;
+     if (rconfig->publickeys) {
+       if (server->config->prefer_passphrase_auth) {
+       *repository = NULL;
+       } else {
+       *passphrase = NULL;
+       *passphrase_len = 0;
+       }
+     }
+     entry->conn_type = conn_type;
      return TRUE;
    }
  
@@@ -2092,19 -2255,23 +2255,23 @@@ silc_server_accept_auth_compl(SilcConnA
      server->stat.auth_failures++;
      silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+     silc_server_config_unref(&entry->cconfig);
+     silc_server_config_unref(&entry->sconfig);
+     silc_server_config_unref(&entry->rconfig);
+     silc_server_free_sock_user_data(server, sock, NULL);
      goto out;
    }
  
    SILC_LOG_DEBUG(("Checking whether connection is allowed"));
  
-   switch (entry->data.conn_type) {
+   switch (entry->conn_type) {
    case SILC_CONN_CLIENT:
      {
        SilcClientEntry client;
        SilcServerConfigClient *conn = entry->cconfig.ref_ptr;
  
        /* Verify whether this connection is after all allowed to connect */
-       if (!silc_server_connection_allowed(server, sock, entry->data.conn_type,
+       if (!silc_server_connection_allowed(server, sock, entry->conn_type,
                                          &server->config->param,
                                          conn->param,
                                          silc_connauth_get_ske(connauth))) {
                                        SILC_STATUS_ERR_PERM_DENIED,
                                        "We do not have connection to backup "
                                        "router established, try later");
+         silc_server_config_unref(&entry->cconfig);
+         silc_server_config_unref(&entry->sconfig);
+         silc_server_config_unref(&entry->rconfig);
+         silc_server_free_sock_user_data(server, sock, NULL);
          server->stat.auth_failures++;
  
          /* From here on, wait 20 seconds for the backup router to appear. */
        server->stat.auth_failures++;
        silc_server_disconnect_remote(server, sock,
                                      SILC_STATUS_ERR_AUTH_FAILED, NULL);
+       silc_server_config_unref(&entry->cconfig);
+       silc_server_config_unref(&entry->sconfig);
+       silc_server_config_unref(&entry->rconfig);
+       silc_server_free_sock_user_data(server, sock, NULL);
        goto out;
        }
        entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
+       entry->data.conn_type = SILC_CONN_CLIENT;
  
        /* Statistics */
        server->stat.my_clients++;
        }
  
        /* Add public key to repository */
+       SILC_LOG_DEBUG(("Add client public key to repository"));
        if (!silc_server_get_public_key_by_client(server, client, NULL))
        silc_skr_add_public_key_simple(server->repository,
                                       entry->data.public_key,
         and we do not have connection to primary router, do not allow
         the connection. */
        if (server->server_type == SILC_BACKUP_ROUTER &&
-         entry->data.conn_type == SILC_CONN_SERVER &&
+         entry->conn_type == SILC_CONN_SERVER &&
          !SILC_PRIMARY_ROUTE(server)) {
        SILC_LOG_INFO(("Will not accept server connection because we do "
                       "not have primary router connection established"));
                                      SILC_STATUS_ERR_PERM_DENIED,
                                      "We do not have connection to primary "
                                      "router established, try later");
+       silc_server_config_unref(&entry->cconfig);
+       silc_server_config_unref(&entry->sconfig);
+       silc_server_config_unref(&entry->rconfig);
+       silc_server_free_sock_user_data(server, sock, NULL);
        server->stat.auth_failures++;
        goto out;
        }
  
-       if (entry->data.conn_type == SILC_CONN_ROUTER) {
+       if (entry->conn_type == SILC_CONN_ROUTER) {
        /* Verify whether this connection is after all allowed to connect */
        if (!silc_server_connection_allowed(server, sock,
-                                           entry->data.conn_type,
+                                           entry->conn_type,
                                            &server->config->param,
                                            rconn ? rconn->param : NULL,
                                            silc_connauth_get_ske(connauth))) {
+         silc_server_config_unref(&entry->cconfig);
+         silc_server_config_unref(&entry->sconfig);
+         silc_server_config_unref(&entry->rconfig);
          server->stat.auth_failures++;
          goto out;
        }
        }
        }
  
-       if (entry->data.conn_type == SILC_CONN_SERVER) {
+       if (entry->conn_type == SILC_CONN_SERVER) {
        /* Verify whether this connection is after all allowed to connect */
        if (!silc_server_connection_allowed(server, sock,
-                                           entry->data.conn_type,
+                                           entry->conn_type,
                                            &server->config->param,
                                            srvconn ? srvconn->param : NULL,
                                            silc_connauth_get_ske(connauth))) {
                                        SILC_STATUS_ERR_PERM_DENIED,
                                        "We do not have connection to backup "
                                        "router established, try later");
+         silc_server_config_unref(&entry->cconfig);
+         silc_server_config_unref(&entry->sconfig);
+         silc_server_config_unref(&entry->rconfig);
+         silc_server_free_sock_user_data(server, sock, NULL);
          server->stat.auth_failures++;
  
          /* From here on, wait 20 seconds for the backup router to appear. */
        }
  
        SILC_LOG_DEBUG(("Remote host is %s",
-                     entry->data.conn_type == SILC_CONN_SERVER ?
+                     entry->conn_type == SILC_CONN_SERVER ?
                      "server" : (backup_router ?
                                  "backup router" : "router")));
        SILC_LOG_INFO(("Connection %s (%s) is %s", entry->hostname,
-                    entry->ip, entry->data.conn_type == SILC_CONN_SERVER ?
+                    entry->ip, entry->conn_type == SILC_CONN_SERVER ?
                     "server" : (backup_router ?
                                 "backup router" : "router")));
  
         server. We mark ourselves as router for this server if we really
         are router. */
        new_server =
-       silc_idlist_add_server((entry->data.conn_type == SILC_CONN_SERVER ?
+       silc_idlist_add_server((entry->conn_type == SILC_CONN_SERVER ?
                                server->local_list : (backup_router ?
                                                      server->local_list :
                                                      server->global_list)),
                               NULL,
-                              (entry->data.conn_type == SILC_CONN_SERVER ?
+                              (entry->conn_type == SILC_CONN_SERVER ?
                                SILC_SERVER : SILC_ROUTER),
                               NULL,
-                              (entry->data.conn_type == SILC_CONN_SERVER ?
+                              (entry->conn_type == SILC_CONN_SERVER ?
                                server->id_entry : (backup_router ?
                                                    server->id_entry : NULL)),
                               sock);
        SILC_LOG_ERROR(("Could not add new server to cache"));
        silc_server_disconnect_remote(server, sock,
                                      SILC_STATUS_ERR_AUTH_FAILED, NULL);
+       silc_server_config_unref(&entry->cconfig);
+       silc_server_config_unref(&entry->sconfig);
+       silc_server_config_unref(&entry->rconfig);
+       silc_server_free_sock_user_data(server, sock, NULL);
        server->stat.auth_failures++;
        goto out;
        }
        entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
+       entry->data.conn_type = entry->conn_type;
  
        id_entry = (void *)new_server;
  
    sconn->remote_port = port;
    silc_dlist_add(server->conns, sconn);
    idata->sconn = sconn;
+   idata->sconn->callback = NULL;
    idata->last_receive = time(NULL);
  
    /* Add the common data structure to the ID entry. */
@@@ -2467,6 -2661,10 +2661,10 @@@ silc_server_accept_completed(SilcSKE sk
      silc_ske_free(ske);
      silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+     silc_server_config_unref(&entry->cconfig);
+     silc_server_config_unref(&entry->sconfig);
+     silc_server_config_unref(&entry->rconfig);
+     silc_server_free_sock_user_data(server, sock, NULL);
      return;
    }
  
      silc_ske_free(ske);
      silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+     silc_server_free_sock_user_data(server, sock, NULL);
      return;
    }
    silc_packet_set_keys(sock, send_key, receive_key, hmac_send,
    pk = silc_pkcs_public_key_encode(idata->public_key, &pk_len);
    silc_hash_make(server->sha1hash, pk, pk_len, idata->fingerprint);
  
+   silc_hash_alloc(silc_hash_get_name(prop->hash), &idata->hash);
    SILC_LOG_DEBUG(("Starting connection authentication"));
    server->stat.auth_attempts++;
  
      silc_ske_free(ske);
      silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+     silc_server_config_unref(&entry->cconfig);
+     silc_server_config_unref(&entry->sconfig);
+     silc_server_config_unref(&entry->rconfig);
+     silc_server_free_sock_user_data(server, sock, NULL);
      return;
    }
  
@@@ -2558,6 -2763,8 +2763,8 @@@ static void silc_server_accept_new_conn
    }
    server->stat.conn_num++;
  
+   SILC_LOG_DEBUG(("Created packet stream %p", packet_stream));
    /* Set source ID to packet stream */
    if (!silc_packet_set_ids(packet_stream, SILC_ID_SERVER, server->id,
                           0, NULL)) {
      silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_BANNED_FROM_SERVER,
                                  deny->reason);
+     silc_server_free_sock_user_data(server, packet_stream, NULL);
      return;
    }
  
      server->stat.conn_failures++;
      silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL);
+     silc_server_free_sock_user_data(server, packet_stream, NULL);
      return;
    }
  
      server->stat.conn_failures++;
      silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+     silc_server_free_sock_user_data(server, packet_stream, NULL);
      return;
    }
    entry->hostname = hostname;
    entry->port = port;
    entry->server = server;
    entry->data.conn_type = SILC_CONN_UNKNOWN;
+   entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
    silc_packet_set_context(packet_stream, entry);
  
+   SILC_LOG_DEBUG(("Created unknown connection %p", entry));
    silc_server_config_ref(&entry->cconfig, server->config, cconfig);
    silc_server_config_ref(&entry->sconfig, server->config, sconfig);
    silc_server_config_ref(&entry->rconfig, server->config, rconfig);
      server->stat.conn_failures++;
      silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+     silc_server_free_sock_user_data(server, packet_stream, NULL);
      return;
    }
    silc_ske_set_callbacks(ske, silc_server_verify_key,
@@@ -2761,9 -2975,9 +2975,9 @@@ static void silc_server_rekey(SilcServe
    SilcIDListData idata = silc_packet_get_context(sock);
    SilcSKE ske;
  
-   SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]",
+   SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s], sock %p",
                  idata->sconn->remote_host, idata->sconn->remote_port,
-                 SILC_CONNTYPE_STRING(idata->conn_type)));
+                 SILC_CONNTYPE_STRING(idata->conn_type), sock));
  
    /* Allocate SKE */
    ske = silc_ske_alloc(server->rng, server->schedule, NULL,
  
  SILC_TASK_CALLBACK(silc_server_close_connection_final)
  {
-   silc_packet_stream_destroy(context);
+   silc_packet_stream_unref(context);
  }
  
  /* Closes connection to socket connection */
@@@ -2801,6 -3015,9 +3015,7 @@@ void silc_server_close_connection(SilcS
    const char *hostname;
    SilcUInt16 port;
  
 -    return;
 -
+   if (!silc_packet_stream_is_valid(sock))
    memset(tmp, 0, sizeof(tmp));
    //  silc_socket_get_error(sock, tmp, sizeof(tmp));
    silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
      idata->sconn = NULL;
    }
  
+   /* Take a reference and then destroy the stream.  The last reference
+      is released later in a timeout callback. */
+   silc_packet_stream_ref(sock);
+   silc_packet_stream_destroy(sock);
    /* Close connection with timeout */
    server->stat.conn_num--;
    silc_schedule_task_del_by_all(server->schedule, 0,
@@@ -2839,7 -3061,7 +3059,7 @@@ void silc_server_disconnect_remote(Silc
    if (!sock)
      return;
  
-   SILC_LOG_DEBUG(("Disconnecting remote host"));
+   SILC_LOG_DEBUG(("Disconnecting remote host, sock %p", sock));
  
    va_start(ap, status);
    cp = va_arg(ap, char *);
@@@ -2907,8 -3129,10 +3127,10 @@@ void silc_server_free_client_data(SilcS
    SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
    silc_schedule_task_del_by_context(server->schedule, client);
  
-   if (client->data.sconn)
+   if (client->data.sconn) {
      silc_server_connection_free(client->data.sconn);
+     client->data.sconn = NULL;
+   }
  
    /* We will not delete the client entry right away. We will take it
       into history (for WHOWAS command) for 5 minutes, unless we're
      client->router = NULL;
      client->connection = NULL;
      client->data.created = silc_time();
+     silc_dlist_del(server->expired_clients, client);
      silc_dlist_add(server->expired_clients, client);
    } else {
      /* Delete directly since we're shutting down server */
@@@ -2936,16 -3161,21 +3159,21 @@@ void silc_server_free_sock_user_data(Si
                                     SilcPacketStream sock,
                                     const char *signoff_message)
  {
-   SilcIDListData idata = silc_packet_get_context(sock);
+   SilcIDListData idata;
    const char *ip;
    SilcUInt16 port;
  
-   SILC_LOG_DEBUG(("Start"));
+   if (!sock)
+     return;
  
+   SILC_LOG_DEBUG(("Start, sock %p", sock));
+   idata = silc_packet_get_context(sock);
    if (!idata)
      return;
  
-   silc_schedule_task_del_by_context(server->schedule, sock);
+   silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_rekey,
+                               sock);
  
    /* Cancel active protocols */
    if (idata) {
  
            /* We'll need to constantly try to reconnect to the primary
               router so that we'll see when it comes back online. */
-           silc_server_create_connection(server, FALSE, FALSE, ip, port,
+           silc_server_create_connection(server, TRUE, FALSE, ip, port,
                                         silc_server_backup_connected,
                                         NULL);
          }
        }
        server->backup_noswitch = FALSE;
  
-       if (idata->sconn)
+       if (idata->sconn) {
        silc_server_connection_free(idata->sconn);
+       idata->sconn = NULL;
+       }
  
        /* Statistics */
        if (idata->conn_type == SILC_CONN_SERVER) {
      {
        SilcUnknownEntry entry = (SilcUnknownEntry)idata;
  
-       SILC_LOG_DEBUG(("Freeing unknown connection data"));
+       SILC_LOG_DEBUG(("Freeing unknown connection data %p", entry));
+       if (idata->sconn) {
+       if (server->router_conn == idata->sconn) {
+         if (!server->no_reconnect)
+           silc_server_create_connections(server);
+         server->router_conn = NULL;
+       }
  
-       if (idata->sconn)
        silc_server_connection_free(idata->sconn);
+       idata->sconn = NULL;
+       }
        silc_idlist_del_data(idata);
        silc_free(entry);
        silc_packet_set_context(sock, NULL);
@@@ -3849,6 -4089,7 +4087,7 @@@ static void silc_server_announce_get_se
    SilcIDCacheEntry id_cache;
    SilcServerEntry entry;
    SilcBuffer idp;
+   void *tmp;
  
    /* Go through all clients in the list */
    if (silc_idcache_get_all(id_list->servers, &list)) {
  
        idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
  
-       *servers = silc_buffer_realloc(*servers,
-                                    (*servers ?
-                                     silc_buffer_truelen((*servers)) +
-                                     silc_buffer_len(idp) :
-                                     silc_buffer_len(idp)));
+       tmp = silc_buffer_realloc(*servers,
+                               (*servers ?
+                                silc_buffer_truelen((*servers)) +
+                                silc_buffer_len(idp) :
+                                silc_buffer_len(idp)));
+       if (!tmp)
+       return;
+       *servers = tmp;
        silc_buffer_pull_tail(*servers, ((*servers)->end - (*servers)->data));
        silc_buffer_put(*servers, idp->data, silc_buffer_len(idp));
        silc_buffer_pull(*servers, silc_buffer_len(idp));
@@@ -3943,6 -4187,7 +4185,7 @@@ static void silc_server_announce_get_cl
    SilcBuffer idp;
    SilcBuffer tmp;
    unsigned char mode[4];
+   void *tmp2;
  
    /* Go through all clients in the list */
    if (silc_idcache_get_all(id_list->clients, &list)) {
                      silc_id_render(client->id, SILC_ID_CLIENT)));
  
        idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+       if (!idp)
+       return;
  
-       *clients = silc_buffer_realloc(*clients,
-                                    (*clients ?
-                                     silc_buffer_truelen((*clients)) +
-                                     silc_buffer_len(idp) :
-                                     silc_buffer_len(idp)));
+       tmp2 = silc_buffer_realloc(*clients,
+                               (*clients ?
+                                silc_buffer_truelen((*clients)) +
+                                silc_buffer_len(idp) :
+                                silc_buffer_len(idp)));
+       if (!tmp2)
+       return;
+       *clients = tmp2;
        silc_buffer_pull_tail(*clients, ((*clients)->end - (*clients)->data));
        silc_buffer_put(*clients, idp->data, silc_buffer_len(idp));
        silc_buffer_pull(*clients, silc_buffer_len(idp));
        silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_UMODE_CHANGE,
                                           2, idp->data, silc_buffer_len(idp),
                                           mode, 4);
-       *umodes = silc_buffer_realloc(*umodes,
-                                   (*umodes ?
-                                    silc_buffer_truelen((*umodes)) +
-                                    silc_buffer_len(tmp) :
-                                    silc_buffer_len(tmp)));
+       tmp2 = silc_buffer_realloc(*umodes,
+                                (*umodes ?
+                                 silc_buffer_truelen((*umodes)) +
+                                 silc_buffer_len(tmp) :
+                                 silc_buffer_len(tmp)));
+       if (!tmp2)
+       return;
+       *umodes = tmp2;
        silc_buffer_pull_tail(*umodes, ((*umodes)->end - (*umodes)->data));
        silc_buffer_put(*umodes, tmp->data, silc_buffer_len(tmp));
        silc_buffer_pull(*umodes, silc_buffer_len(tmp));
@@@ -4067,6 -4320,7 +4318,7 @@@ void silc_server_announce_get_inviteban
  {
    SilcBuffer list, idp, idp2, tmp2;
    SilcUInt32 type;
+   void *ptype;
    SilcHashTableList htl;
    const unsigned char a[1] = { 0x03 };
  
      type = silc_hash_table_count(channel->invite_list);
      SILC_PUT16_MSB(type, list->data);
      silc_hash_table_list(channel->invite_list, &htl);
-     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
-       list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
-                                               type);
+     while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2))
+       list = silc_argument_payload_encode_one(list, tmp2->data,
+                                             silc_buffer_len(tmp2),
+                                             SILC_PTR_TO_32(ptype));
      silc_hash_table_list_reset(&htl);
  
      idp2 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
      type = silc_hash_table_count(channel->ban_list);
      SILC_PUT16_MSB(type, list->data);
      silc_hash_table_list(channel->ban_list, &htl);
-     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
-       list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
-                                               type);
+     while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2))
+       list = silc_argument_payload_encode_one(list, tmp2->data,
+                                             silc_buffer_len(tmp2),
+                                             SILC_PTR_TO_32(ptype));
      silc_hash_table_list_reset(&htl);
  
      *ban =
@@@ -4133,6 -4389,7 +4387,7 @@@ void silc_server_announce_get_channel_u
    int len;
    unsigned char mode[4], ulimit[4];
    char *hmac;
+   void *tmp2;
  
    SILC_LOG_DEBUG(("Start"));
  
                                        SILC_CHANNEL_MODE_ULIMIT ?
                                        sizeof(ulimit) : 0));
    len = silc_buffer_len(tmp);
-   *channel_modes =
+   tmp2 =
      silc_buffer_realloc(*channel_modes,
                        (*channel_modes ?
                         silc_buffer_truelen((*channel_modes)) + len : len));
+   if (!tmp2)
+     return;
+   *channel_modes = tmp2;
    silc_buffer_pull_tail(*channel_modes,
                        ((*channel_modes)->end -
                         (*channel_modes)->data));
                                             chidp->data,
                                             silc_buffer_len(chidp));
      len = silc_buffer_len(tmp);
-     *channel_users =
+     tmp2 =
        silc_buffer_realloc(*channel_users,
                          (*channel_users ?
                           silc_buffer_truelen((*channel_users)) + len : len));
+     if (!tmp2)
+       return;
+     *channel_users = tmp2;
      silc_buffer_pull_tail(*channel_users,
                          ((*channel_users)->end -
                           (*channel_users)->data));
                                             fkey ? fkey->data : NULL,
                                             fkey ? silc_buffer_len(fkey) : 0);
      len = silc_buffer_len(tmp);
-     *channel_users_modes =
+     tmp2 =
        silc_buffer_realloc(*channel_users_modes,
                          (*channel_users_modes ?
                           silc_buffer_truelen((*channel_users_modes)) +
                           len : len));
+     if (!tmp2)
+       return;
+     *channel_users_modes = tmp2;
      silc_buffer_pull_tail(*channel_users_modes,
                          ((*channel_users_modes)->end -
                           (*channel_users_modes)->data));
@@@ -4268,6 -4534,7 +4532,7 @@@ void silc_server_announce_get_channels(
    SilcUInt16 name_len;
    int len;
    int i = *channel_users_modes_c;
+   void *tmp;
    SilcBool announce;
  
    SILC_LOG_DEBUG(("Start"));
  
        if (announce) {
        len = 4 + name_len + id_len + 4;
-       *channels =
+       tmp =
          silc_buffer_realloc(*channels,
                              (*channels ?
                               silc_buffer_truelen((*channels)) +
                               len : len));
+       if (!tmp)
+         break;
+       *channels = tmp;
        silc_buffer_pull_tail(*channels,
                              ((*channels)->end - (*channels)->data));
        silc_buffer_format(*channels,
  
        if (announce) {
        /* Channel user modes */
-       *channel_users_modes = silc_realloc(*channel_users_modes,
-                                           sizeof(**channel_users_modes) *
-                                           (i + 1));
+       tmp = silc_realloc(*channel_users_modes,
+                           sizeof(**channel_users_modes) * (i + 1));
+       if (!tmp)
+         break;
+       *channel_users_modes = tmp;
        (*channel_users_modes)[i] = NULL;
-       *channel_modes = silc_realloc(*channel_modes,
-                                     sizeof(**channel_modes) * (i + 1));
+       tmp = silc_realloc(*channel_modes,
+                          sizeof(**channel_modes) * (i + 1));
+       if (!tmp)
+         break;
+       *channel_modes = tmp;
        (*channel_modes)[i] = NULL;
-       *channel_ids = silc_realloc(*channel_ids,
-                                     sizeof(**channel_ids) * (i + 1));
+       tmp = silc_realloc(*channel_ids,
+                          sizeof(**channel_ids) * (i + 1));
+       if (!tmp)
+         break;
+       *channel_ids = tmp;
        (*channel_ids)[i] = NULL;
        silc_server_announce_get_channel_users(server, channel,
                                               &(*channel_modes)[i],
        (*channel_ids)[i] = channel->id;
  
        /* Channel's topic */
-       *channel_topics = silc_realloc(*channel_topics,
-                                      sizeof(**channel_topics) * (i + 1));
+       tmp = silc_realloc(*channel_topics,
+                          sizeof(**channel_topics) * (i + 1));
+       if (!tmp)
+         break;
+       *channel_topics = tmp;
        (*channel_topics)[i] = NULL;
        silc_server_announce_get_channel_topic(server, channel,
                                               &(*channel_topics)[i]);
  
        /* Channel's invite and ban list */
-       *channel_invites = silc_realloc(*channel_invites,
-                                       sizeof(**channel_invites) * (i + 1));
+       tmp = silc_realloc(*channel_invites,
+                          sizeof(**channel_invites) * (i + 1));
+       if (!tmp)
+         break;
+       *channel_invites = tmp;
        (*channel_invites)[i] = NULL;
-       *channel_bans = silc_realloc(*channel_bans,
-                                    sizeof(**channel_bans) * (i + 1));
+       tmp = silc_realloc(*channel_bans,
+                          sizeof(**channel_bans) * (i + 1));
+       if (!tmp)
+         break;
+       *channel_bans = tmp;
        (*channel_bans)[i] = NULL;
        silc_server_announce_get_inviteban(server, channel,
                                           &(*channel_invites)[i],
diff --combined config.guess
index 951383e35544d8c861019b06e0ec4a58f1657a5f,e3ef63f6cb4c2670b7723cdc44eb290ec8693b1a..0000000000000000000000000000000000000000
deleted file mode 100755,100755
+++ /dev/null
@@@ -1,1516 -1,1471 +1,0 @@@
--#! /bin/sh
--# Attempt to guess a canonical system name.
--#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- #   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
- #   Inc.
 -#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
--
- timestamp='2007-05-17'
 -timestamp='2005-12-13'
--
--# This file is free software; you can redistribute it and/or modify it
--# under the terms of the GNU General Public License as published by
--# the Free Software Foundation; either version 2 of the License, or
--# (at your option) any later version.
--#
--# This program is distributed in the hope that it will be useful, but
--# WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--# General Public License for more details.
--#
--# You should have received a copy of the GNU General Public License
--# along with this program; if not, write to the Free Software
--# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
--# 02110-1301, USA.
--#
--# As a special exception to the GNU General Public License, if you
--# distribute this file as part of a program that contains a
--# configuration script generated by Autoconf, you may include it under
--# the same distribution terms that you use for the rest of that program.
--
--
--# Originally written by Per Bothner <per@bothner.com>.
--# Please send patches to <config-patches@gnu.org>.  Submit a context
--# diff and a properly formatted ChangeLog entry.
--#
--# This script attempts to guess a canonical system name similar to
--# config.sub.  If it succeeds, it prints the system name on stdout, and
--# exits with 0.  Otherwise, it exits with 1.
--#
--# The plan is that this can be called by configure scripts if you
--# don't specify an explicit build system type.
--
--me=`echo "$0" | sed -e 's,.*/,,'`
--
--usage="\
--Usage: $0 [OPTION]
--
--Output the configuration name of the system \`$me' is run on.
--
--Operation modes:
--  -h, --help         print this help, then exit
--  -t, --time-stamp   print date of last modification, then exit
--  -v, --version      print version number, then exit
--
--Report bugs and patches to <config-patches@gnu.org>."
--
--version="\
--GNU config.guess ($timestamp)
--
--Originally written by Per Bothner.
--Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
--Free Software Foundation, Inc.
--
--This is free software; see the source for copying conditions.  There is NO
--warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
--
--help="
--Try \`$me --help' for more information."
--
--# Parse command line
--while test $# -gt 0 ; do
--  case $1 in
--    --time-stamp | --time* | -t )
--       echo "$timestamp" ; exit ;;
--    --version | -v )
--       echo "$version" ; exit ;;
--    --help | --h* | -h )
--       echo "$usage"; exit ;;
--    -- )     # Stop option processing
--       shift; break ;;
--    - )       # Use stdin as input.
--       break ;;
--    -* )
--       echo "$me: invalid option $1$help" >&2
--       exit 1 ;;
--    * )
--       break ;;
--  esac
--done
--
--if test $# != 0; then
--  echo "$me: too many arguments$help" >&2
--  exit 1
--fi
--
--trap 'exit 1' 1 2 15
--
--# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
--# compiler to aid in system detection is discouraged as it requires
--# temporary files to be created and, as you can see below, it is a
--# headache to deal with in a portable fashion.
--
--# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
--# use `HOST_CC' if defined, but it is deprecated.
--
--# Portable tmp directory creation inspired by the Autoconf team.
--
--set_cc_for_build='
--trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
--trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
--: ${TMPDIR=/tmp} ;
-  { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
 - { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
-- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
-- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
-- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
--dummy=$tmp/dummy ;
--tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
--case $CC_FOR_BUILD,$HOST_CC,$CC in
-- ,,)    echo "int x;" > $dummy.c ;
--      for c in cc gcc c89 c99 ; do
--        if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
--           CC_FOR_BUILD="$c"; break ;
--        fi ;
--      done ;
--      if test x"$CC_FOR_BUILD" = x ; then
--        CC_FOR_BUILD=no_compiler_found ;
--      fi
--      ;;
-- ,,*)   CC_FOR_BUILD=$CC ;;
-- ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
--esac ; set_cc_for_build= ;'
--
--# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
--# (ghazi@noc.rutgers.edu 1994-08-24)
--if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
--      PATH=$PATH:/.attbin ; export PATH
--fi
--
--UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
--UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
--UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
--UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
--
--# Note: order is significant - the case branches are not exclusive.
--
--case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
--    *:NetBSD:*:*)
--      # NetBSD (nbsd) targets should (where applicable) match one or
--      # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
--      # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
--      # switched to ELF, *-*-netbsd* would select the old
--      # object file format.  This provides both forward
--      # compatibility and a consistent mechanism for selecting the
--      # object file format.
--      #
--      # Note: NetBSD doesn't particularly care about the vendor
--      # portion of the name.  We always set it to "unknown".
--      sysctl="sysctl -n hw.machine_arch"
--      UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
--          /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
--      case "${UNAME_MACHINE_ARCH}" in
--          armeb) machine=armeb-unknown ;;
--          arm*) machine=arm-unknown ;;
--          sh3el) machine=shl-unknown ;;
--          sh3eb) machine=sh-unknown ;;
-           sh5el) machine=sh5le-unknown ;;
--          *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
--      esac
--      # The Operating System including object format, if it has switched
--      # to ELF recently, or will in the future.
--      case "${UNAME_MACHINE_ARCH}" in
--          arm*|i386|m68k|ns32k|sh3*|sparc|vax)
--              eval $set_cc_for_build
--              if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
--                      | grep __ELF__ >/dev/null
--              then
--                  # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
--                  # Return netbsd for either.  FIX?
--                  os=netbsd
--              else
--                  os=netbsdelf
--              fi
--              ;;
--          *)
--              os=netbsd
--              ;;
--      esac
--      # The OS release
--      # Debian GNU/NetBSD machines have a different userland, and
--      # thus, need a distinct triplet. However, they do not need
--      # kernel version information, so it can be replaced with a
--      # suitable tag, in the style of linux-gnu.
--      case "${UNAME_VERSION}" in
--          Debian*)
--              release='-gnu'
--              ;;
--          *)
--              release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
--              ;;
--      esac
--      # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
--      # contains redundant information, the shorter form:
--      # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
--      echo "${machine}-${os}${release}"
--      exit ;;
--    *:OpenBSD:*:*)
--      UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
--      echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
--      exit ;;
--    *:ekkoBSD:*:*)
--      echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
-       exit ;;
-     *:SolidBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
--      exit ;;
--    macppc:MirBSD:*:*)
-       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
 -      echo powerppc-unknown-mirbsd${UNAME_RELEASE}
--      exit ;;
--    *:MirBSD:*:*)
--      echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
--      exit ;;
--    alpha:OSF1:*:*)
--      case $UNAME_RELEASE in
--      *4.0)
--              UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
--              ;;
--      *5.*)
--              UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
--              ;;
--      esac
--      # According to Compaq, /usr/sbin/psrinfo has been available on
--      # OSF/1 and Tru64 systems produced since 1995.  I hope that
--      # covers most systems running today.  This code pipes the CPU
--      # types through head -n 1, so we only detect the type of CPU 0.
--      ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
--      case "$ALPHA_CPU_TYPE" in
--          "EV4 (21064)")
--              UNAME_MACHINE="alpha" ;;
--          "EV4.5 (21064)")
--              UNAME_MACHINE="alpha" ;;
--          "LCA4 (21066/21068)")
--              UNAME_MACHINE="alpha" ;;
--          "EV5 (21164)")
--              UNAME_MACHINE="alphaev5" ;;
--          "EV5.6 (21164A)")
--              UNAME_MACHINE="alphaev56" ;;
--          "EV5.6 (21164PC)")
--              UNAME_MACHINE="alphapca56" ;;
--          "EV5.7 (21164PC)")
--              UNAME_MACHINE="alphapca57" ;;
--          "EV6 (21264)")
--              UNAME_MACHINE="alphaev6" ;;
--          "EV6.7 (21264A)")
--              UNAME_MACHINE="alphaev67" ;;
--          "EV6.8CB (21264C)")
--              UNAME_MACHINE="alphaev68" ;;
--          "EV6.8AL (21264B)")
--              UNAME_MACHINE="alphaev68" ;;
--          "EV6.8CX (21264D)")
--              UNAME_MACHINE="alphaev68" ;;
--          "EV6.9A (21264/EV69A)")
--              UNAME_MACHINE="alphaev69" ;;
--          "EV7 (21364)")
--              UNAME_MACHINE="alphaev7" ;;
--          "EV7.9 (21364A)")
--              UNAME_MACHINE="alphaev79" ;;
--      esac
--      # A Pn.n version is a patched version.
--      # A Vn.n version is a released version.
--      # A Tn.n version is a released field test version.
--      # A Xn.n version is an unreleased experimental baselevel.
--      # 1.2 uses "1.2" for uname -r.
--      echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
--      exit ;;
--    Alpha\ *:Windows_NT*:*)
--      # How do we know it's Interix rather than the generic POSIX subsystem?
--      # Should we change UNAME_MACHINE based on the output of uname instead
--      # of the specific Alpha model?
--      echo alpha-pc-interix
--      exit ;;
--    21064:Windows_NT:50:3)
--      echo alpha-dec-winnt3.5
--      exit ;;
--    Amiga*:UNIX_System_V:4.0:*)
--      echo m68k-unknown-sysv4
--      exit ;;
--    *:[Aa]miga[Oo][Ss]:*:*)
--      echo ${UNAME_MACHINE}-unknown-amigaos
--      exit ;;
--    *:[Mm]orph[Oo][Ss]:*:*)
--      echo ${UNAME_MACHINE}-unknown-morphos
--      exit ;;
--    *:OS/390:*:*)
--      echo i370-ibm-openedition
--      exit ;;
--    *:z/VM:*:*)
--      echo s390-ibm-zvmoe
--      exit ;;
--    *:OS400:*:*)
--        echo powerpc-ibm-os400
--      exit ;;
--    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
--      echo arm-acorn-riscix${UNAME_RELEASE}
--      exit ;;
--    arm:riscos:*:*|arm:RISCOS:*:*)
--      echo arm-unknown-riscos
--      exit ;;
--    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
--      echo hppa1.1-hitachi-hiuxmpp
--      exit ;;
--    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
--      # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
--      if test "`(/bin/universe) 2>/dev/null`" = att ; then
--              echo pyramid-pyramid-sysv3
--      else
--              echo pyramid-pyramid-bsd
--      fi
--      exit ;;
--    NILE*:*:*:dcosx)
--      echo pyramid-pyramid-svr4
--      exit ;;
--    DRS?6000:unix:4.0:6*)
--      echo sparc-icl-nx6
--      exit ;;
--    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
--      case `/usr/bin/uname -p` in
--          sparc) echo sparc-icl-nx7; exit ;;
--      esac ;;
--    sun4H:SunOS:5.*:*)
--      echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
--      exit ;;
--    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
--      echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
--      exit ;;
-     i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*)
 -    i86pc:SunOS:5.*:*)
--      echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
--      exit ;;
--    sun4*:SunOS:6*:*)
--      # According to config.sub, this is the proper way to canonicalize
--      # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
--      # it's likely to be more like Solaris than SunOS4.
--      echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
--      exit ;;
--    sun4*:SunOS:*:*)
--      case "`/usr/bin/arch -k`" in
--          Series*|S4*)
--              UNAME_RELEASE=`uname -v`
--              ;;
--      esac
--      # Japanese Language versions have a version number like `4.1.3-JL'.
--      echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
--      exit ;;
--    sun3*:SunOS:*:*)
--      echo m68k-sun-sunos${UNAME_RELEASE}
--      exit ;;
--    sun*:*:4.2BSD:*)
--      UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
--      test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
--      case "`/bin/arch`" in
--          sun3)
--              echo m68k-sun-sunos${UNAME_RELEASE}
--              ;;
--          sun4)
--              echo sparc-sun-sunos${UNAME_RELEASE}
--              ;;
--      esac
--      exit ;;
--    aushp:SunOS:*:*)
--      echo sparc-auspex-sunos${UNAME_RELEASE}
--      exit ;;
--    # The situation for MiNT is a little confusing.  The machine name
--    # can be virtually everything (everything which is not
--    # "atarist" or "atariste" at least should have a processor
--    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
--    # to the lowercase version "mint" (or "freemint").  Finally
--    # the system name "TOS" denotes a system which is actually not
--    # MiNT.  But MiNT is downward compatible to TOS, so this should
--    # be no problem.
--    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
--        echo m68k-atari-mint${UNAME_RELEASE}
--      exit ;;
--    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
--      echo m68k-atari-mint${UNAME_RELEASE}
--        exit ;;
--    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
--        echo m68k-atari-mint${UNAME_RELEASE}
--      exit ;;
--    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
--        echo m68k-milan-mint${UNAME_RELEASE}
--        exit ;;
--    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
--        echo m68k-hades-mint${UNAME_RELEASE}
--        exit ;;
--    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
--        echo m68k-unknown-mint${UNAME_RELEASE}
--        exit ;;
--    m68k:machten:*:*)
--      echo m68k-apple-machten${UNAME_RELEASE}
--      exit ;;
--    powerpc:machten:*:*)
--      echo powerpc-apple-machten${UNAME_RELEASE}
--      exit ;;
--    RISC*:Mach:*:*)
--      echo mips-dec-mach_bsd4.3
--      exit ;;
--    RISC*:ULTRIX:*:*)
--      echo mips-dec-ultrix${UNAME_RELEASE}
--      exit ;;
--    VAX*:ULTRIX*:*:*)
--      echo vax-dec-ultrix${UNAME_RELEASE}
--      exit ;;
--    2020:CLIX:*:* | 2430:CLIX:*:*)
--      echo clipper-intergraph-clix${UNAME_RELEASE}
--      exit ;;
--    mips:*:*:UMIPS | mips:*:*:RISCos)
--      eval $set_cc_for_build
--      sed 's/^        //' << EOF >$dummy.c
--#ifdef __cplusplus
--#include <stdio.h>  /* for printf() prototype */
--      int main (int argc, char *argv[]) {
--#else
--      int main (argc, argv) int argc; char *argv[]; {
--#endif
--      #if defined (host_mips) && defined (MIPSEB)
--      #if defined (SYSTYPE_SYSV)
--        printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
--      #endif
--      #if defined (SYSTYPE_SVR4)
--        printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
--      #endif
--      #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
--        printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
--      #endif
--      #endif
--        exit (-1);
--      }
--EOF
--      $CC_FOR_BUILD -o $dummy $dummy.c &&
--        dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
--        SYSTEM_NAME=`$dummy $dummyarg` &&
--          { echo "$SYSTEM_NAME"; exit; }
--      echo mips-mips-riscos${UNAME_RELEASE}
--      exit ;;
--    Motorola:PowerMAX_OS:*:*)
--      echo powerpc-motorola-powermax
--      exit ;;
--    Motorola:*:4.3:PL8-*)
--      echo powerpc-harris-powermax
--      exit ;;
--    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
--      echo powerpc-harris-powermax
--      exit ;;
--    Night_Hawk:Power_UNIX:*:*)
--      echo powerpc-harris-powerunix
--      exit ;;
--    m88k:CX/UX:7*:*)
--      echo m88k-harris-cxux7
--      exit ;;
--    m88k:*:4*:R4*)
--      echo m88k-motorola-sysv4
--      exit ;;
--    m88k:*:3*:R3*)
--      echo m88k-motorola-sysv3
--      exit ;;
--    AViiON:dgux:*:*)
--        # DG/UX returns AViiON for all architectures
--        UNAME_PROCESSOR=`/usr/bin/uname -p`
--      if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
--      then
--          if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
--             [ ${TARGET_BINARY_INTERFACE}x = x ]
--          then
--              echo m88k-dg-dgux${UNAME_RELEASE}
--          else
--              echo m88k-dg-dguxbcs${UNAME_RELEASE}
--          fi
--      else
--          echo i586-dg-dgux${UNAME_RELEASE}
--      fi
--      exit ;;
--    M88*:DolphinOS:*:*)       # DolphinOS (SVR3)
--      echo m88k-dolphin-sysv3
--      exit ;;
--    M88*:*:R3*:*)
--      # Delta 88k system running SVR3
--      echo m88k-motorola-sysv3
--      exit ;;
--    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
--      echo m88k-tektronix-sysv3
--      exit ;;
--    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
--      echo m68k-tektronix-bsd
--      exit ;;
--    *:IRIX*:*:*)
--      echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
--      exit ;;
--    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
--      echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
--      exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
--    i*86:AIX:*:*)
--      echo i386-ibm-aix
--      exit ;;
--    ia64:AIX:*:*)
--      if [ -x /usr/bin/oslevel ] ; then
--              IBM_REV=`/usr/bin/oslevel`
--      else
--              IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
--      fi
--      echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
--      exit ;;
--    *:AIX:2:3)
--      if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
--              eval $set_cc_for_build
--              sed 's/^                //' << EOF >$dummy.c
--              #include <sys/systemcfg.h>
--
--              main()
--                      {
--                      if (!__power_pc())
--                              exit(1);
--                      puts("powerpc-ibm-aix3.2.5");
--                      exit(0);
--                      }
--EOF
--              if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
--              then
--                      echo "$SYSTEM_NAME"
--              else
--                      echo rs6000-ibm-aix3.2.5
--              fi
--      elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
--              echo rs6000-ibm-aix3.2.4
--      else
--              echo rs6000-ibm-aix3.2
--      fi
--      exit ;;
--    *:AIX:*:[45])
--      IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
--      if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
--              IBM_ARCH=rs6000
--      else
--              IBM_ARCH=powerpc
--      fi
--      if [ -x /usr/bin/oslevel ] ; then
--              IBM_REV=`/usr/bin/oslevel`
--      else
--              IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
--      fi
--      echo ${IBM_ARCH}-ibm-aix${IBM_REV}
--      exit ;;
--    *:AIX:*:*)
--      echo rs6000-ibm-aix
--      exit ;;
--    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
--      echo romp-ibm-bsd4.4
--      exit ;;
--    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
--      echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
--      exit ;;                             # report: romp-ibm BSD 4.3
--    *:BOSX:*:*)
--      echo rs6000-bull-bosx
--      exit ;;
--    DPX/2?00:B.O.S.:*:*)
--      echo m68k-bull-sysv3
--      exit ;;
--    9000/[34]??:4.3bsd:1.*:*)
--      echo m68k-hp-bsd
--      exit ;;
--    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
--      echo m68k-hp-bsd4.4
--      exit ;;
--    9000/[34678]??:HP-UX:*:*)
--      HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
--      case "${UNAME_MACHINE}" in
--          9000/31? )            HP_ARCH=m68000 ;;
--          9000/[34]?? )         HP_ARCH=m68k ;;
--          9000/[678][0-9][0-9])
--              if [ -x /usr/bin/getconf ]; then
--                  sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
--                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
--                    case "${sc_cpu_version}" in
--                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
--                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
--                      532)                      # CPU_PA_RISC2_0
--                        case "${sc_kernel_bits}" in
--                          32) HP_ARCH="hppa2.0n" ;;
--                          64) HP_ARCH="hppa2.0w" ;;
--                        '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
--                        esac ;;
--                    esac
--              fi
--              if [ "${HP_ARCH}" = "" ]; then
--                  eval $set_cc_for_build
--                  sed 's/^              //' << EOF >$dummy.c
--
--              #define _HPUX_SOURCE
--              #include <stdlib.h>
--              #include <unistd.h>
--
--              int main ()
--              {
--              #if defined(_SC_KERNEL_BITS)
--                  long bits = sysconf(_SC_KERNEL_BITS);
--              #endif
--                  long cpu  = sysconf (_SC_CPU_VERSION);
--
--                  switch (cpu)
--                      {
--                      case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
--                      case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
--                      case CPU_PA_RISC2_0:
--              #if defined(_SC_KERNEL_BITS)
--                          switch (bits)
--                              {
--                              case 64: puts ("hppa2.0w"); break;
--                              case 32: puts ("hppa2.0n"); break;
--                              default: puts ("hppa2.0"); break;
--                              } break;
--              #else  /* !defined(_SC_KERNEL_BITS) */
--                          puts ("hppa2.0"); break;
--              #endif
--                      default: puts ("hppa1.0"); break;
--                      }
--                  exit (0);
--              }
--EOF
--                  (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
--                  test -z "$HP_ARCH" && HP_ARCH=hppa
--              fi ;;
--      esac
--      if [ ${HP_ARCH} = "hppa2.0w" ]
--      then
--          eval $set_cc_for_build
--
--          # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
--          # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
--          # generating 64-bit code.  GNU and HP use different nomenclature:
--          #
--          # $ CC_FOR_BUILD=cc ./config.guess
--          # => hppa2.0w-hp-hpux11.23
--          # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
--          # => hppa64-hp-hpux11.23
--
--          if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
--              grep __LP64__ >/dev/null
--          then
--              HP_ARCH="hppa2.0w"
--          else
--              HP_ARCH="hppa64"
--          fi
--      fi
--      echo ${HP_ARCH}-hp-hpux${HPUX_REV}
--      exit ;;
--    ia64:HP-UX:*:*)
--      HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
--      echo ia64-hp-hpux${HPUX_REV}
--      exit ;;
--    3050*:HI-UX:*:*)
--      eval $set_cc_for_build
--      sed 's/^        //' << EOF >$dummy.c
--      #include <unistd.h>
--      int
--      main ()
--      {
--        long cpu = sysconf (_SC_CPU_VERSION);
--        /* The order matters, because CPU_IS_HP_MC68K erroneously returns
--           true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
--           results, however.  */
--        if (CPU_IS_PA_RISC (cpu))
--          {
--            switch (cpu)
--              {
--                case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
--                case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
--                case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
--                default: puts ("hppa-hitachi-hiuxwe2"); break;
--              }
--          }
--        else if (CPU_IS_HP_MC68K (cpu))
--          puts ("m68k-hitachi-hiuxwe2");
--        else puts ("unknown-hitachi-hiuxwe2");
--        exit (0);
--      }
--EOF
--      $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
--              { echo "$SYSTEM_NAME"; exit; }
--      echo unknown-hitachi-hiuxwe2
--      exit ;;
--    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
--      echo hppa1.1-hp-bsd
--      exit ;;
--    9000/8??:4.3bsd:*:*)
--      echo hppa1.0-hp-bsd
--      exit ;;
--    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
--      echo hppa1.0-hp-mpeix
--      exit ;;
--    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
--      echo hppa1.1-hp-osf
--      exit ;;
--    hp8??:OSF1:*:*)
--      echo hppa1.0-hp-osf
--      exit ;;
--    i*86:OSF1:*:*)
--      if [ -x /usr/sbin/sysversion ] ; then
--          echo ${UNAME_MACHINE}-unknown-osf1mk
--      else
--          echo ${UNAME_MACHINE}-unknown-osf1
--      fi
--      exit ;;
--    parisc*:Lites*:*:*)
--      echo hppa1.1-hp-lites
--      exit ;;
--    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
--      echo c1-convex-bsd
--        exit ;;
--    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
--      if getsysinfo -f scalar_acc
--      then echo c32-convex-bsd
--      else echo c2-convex-bsd
--      fi
--        exit ;;
--    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
--      echo c34-convex-bsd
--        exit ;;
--    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
--      echo c38-convex-bsd
--        exit ;;
--    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
--      echo c4-convex-bsd
--        exit ;;
--    CRAY*Y-MP:*:*:*)
--      echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
--      exit ;;
--    CRAY*[A-Z]90:*:*:*)
--      echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
--      | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
--            -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
--            -e 's/\.[^.]*$/.X/'
--      exit ;;
--    CRAY*TS:*:*:*)
--      echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
--      exit ;;
--    CRAY*T3E:*:*:*)
--      echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
--      exit ;;
--    CRAY*SV1:*:*:*)
--      echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
--      exit ;;
--    *:UNICOS/mp:*:*)
--      echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
--      exit ;;
--    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
--      FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
--        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
--        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
--        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
--        exit ;;
--    5000:UNIX_System_V:4.*:*)
--        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
--        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
--        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
--      exit ;;
--    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
--      echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
--      exit ;;
--    sparc*:BSD/OS:*:*)
--      echo sparc-unknown-bsdi${UNAME_RELEASE}
--      exit ;;
--    *:BSD/OS:*:*)
--      echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
--      exit ;;
--    *:FreeBSD:*:*)
-       case ${UNAME_MACHINE} in
-           pc98)
-               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-           amd64)
-               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-           *)
-               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-       esac
 -      echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
--      exit ;;
--    i*:CYGWIN*:*)
--      echo ${UNAME_MACHINE}-pc-cygwin
--      exit ;;
-     *:MINGW*:*)
 -    i*:MINGW*:*)
--      echo ${UNAME_MACHINE}-pc-mingw32
--      exit ;;
--    i*:windows32*:*)
--      # uname -m includes "-pc" on this system.
--      echo ${UNAME_MACHINE}-mingw32
--      exit ;;
--    i*:PW*:*)
--      echo ${UNAME_MACHINE}-pc-pw32
--      exit ;;
-     *:Interix*:[3456]*)
-       case ${UNAME_MACHINE} in
-           x86) 
-               echo i586-pc-interix${UNAME_RELEASE}
-               exit ;;
-           EM64T | authenticamd)
-               echo x86_64-unknown-interix${UNAME_RELEASE}
-               exit ;;
-       esac ;;
 -    x86:Interix*:[345]*)
 -      echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
 -      exit ;;
--    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
--      echo i${UNAME_MACHINE}-pc-mks
--      exit ;;
--    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
--      # How do we know it's Interix rather than the generic POSIX subsystem?
--      # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
--      # UNAME_MACHINE based on the output of uname instead of i386?
--      echo i586-pc-interix
--      exit ;;
--    i*:UWIN*:*)
--      echo ${UNAME_MACHINE}-pc-uwin
--      exit ;;
--    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
--      echo x86_64-unknown-cygwin
--      exit ;;
--    p*:CYGWIN*:*)
--      echo powerpcle-unknown-cygwin
--      exit ;;
--    prep*:SunOS:5.*:*)
--      echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
--      exit ;;
--    *:GNU:*:*)
--      # the GNU system
--      echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
--      exit ;;
--    *:GNU/*:*:*)
--      # other systems with GNU libc and userland
--      echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
--      exit ;;
--    i*86:Minix:*:*)
--      echo ${UNAME_MACHINE}-pc-minix
--      exit ;;
--    arm*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
-     avr32*:Linux:*:*)
--      echo ${UNAME_MACHINE}-unknown-linux-gnu
--      exit ;;
--    cris:Linux:*:*)
--      echo cris-axis-linux-gnu
--      exit ;;
--    crisv32:Linux:*:*)
--      echo crisv32-axis-linux-gnu
--      exit ;;
--    frv:Linux:*:*)
--      echo frv-unknown-linux-gnu
--      exit ;;
--    ia64:Linux:*:*)
--      echo ${UNAME_MACHINE}-unknown-linux-gnu
--      exit ;;
--    m32r*:Linux:*:*)
--      echo ${UNAME_MACHINE}-unknown-linux-gnu
--      exit ;;
--    m68*:Linux:*:*)
--      echo ${UNAME_MACHINE}-unknown-linux-gnu
--      exit ;;
--    mips:Linux:*:*)
--      eval $set_cc_for_build
--      sed 's/^        //' << EOF >$dummy.c
--      #undef CPU
--      #undef mips
--      #undef mipsel
--      #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
--      CPU=mipsel
--      #else
--      #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
--      CPU=mips
--      #else
--      CPU=
--      #endif
--      #endif
--EOF
-       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-           /^CPU/{
-               s: ::g
-               p
-           }'`"
 -      eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`"
--      test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
--      ;;
--    mips64:Linux:*:*)
--      eval $set_cc_for_build
--      sed 's/^        //' << EOF >$dummy.c
--      #undef CPU
--      #undef mips64
--      #undef mips64el
--      #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
--      CPU=mips64el
--      #else
--      #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
--      CPU=mips64
--      #else
--      CPU=
--      #endif
--      #endif
--EOF
-       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-           /^CPU/{
-               s: ::g
-               p
-           }'`"
 -      eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`"
--      test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
--      ;;
--    or32:Linux:*:*)
--      echo or32-unknown-linux-gnu
--      exit ;;
--    ppc:Linux:*:*)
--      echo powerpc-unknown-linux-gnu
--      exit ;;
--    ppc64:Linux:*:*)
--      echo powerpc64-unknown-linux-gnu
--      exit ;;
--    alpha:Linux:*:*)
--      case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
--        EV5)   UNAME_MACHINE=alphaev5 ;;
--        EV56)  UNAME_MACHINE=alphaev56 ;;
--        PCA56) UNAME_MACHINE=alphapca56 ;;
--        PCA57) UNAME_MACHINE=alphapca56 ;;
--        EV6)   UNAME_MACHINE=alphaev6 ;;
--        EV67)  UNAME_MACHINE=alphaev67 ;;
--        EV68*) UNAME_MACHINE=alphaev68 ;;
--        esac
--      objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
--      if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
--      echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
--      exit ;;
--    parisc:Linux:*:* | hppa:Linux:*:*)
--      # Look for CPU level
--      case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
--        PA7*) echo hppa1.1-unknown-linux-gnu ;;
--        PA8*) echo hppa2.0-unknown-linux-gnu ;;
--        *)    echo hppa-unknown-linux-gnu ;;
--      esac
--      exit ;;
--    parisc64:Linux:*:* | hppa64:Linux:*:*)
--      echo hppa64-unknown-linux-gnu
--      exit ;;
--    s390:Linux:*:* | s390x:Linux:*:*)
--      echo ${UNAME_MACHINE}-ibm-linux
--      exit ;;
--    sh64*:Linux:*:*)
--      echo ${UNAME_MACHINE}-unknown-linux-gnu
--      exit ;;
--    sh*:Linux:*:*)
--      echo ${UNAME_MACHINE}-unknown-linux-gnu
--      exit ;;
--    sparc:Linux:*:* | sparc64:Linux:*:*)
--      echo ${UNAME_MACHINE}-unknown-linux-gnu
--      exit ;;
--    vax:Linux:*:*)
--      echo ${UNAME_MACHINE}-dec-linux-gnu
--      exit ;;
--    x86_64:Linux:*:*)
--      echo x86_64-unknown-linux-gnu
-       exit ;;
-     xtensa:Linux:*:*)
-       echo xtensa-unknown-linux-gnu
--      exit ;;
--    i*86:Linux:*:*)
--      # The BFD linker knows what the default object file format is, so
--      # first see if it will tell us. cd to the root directory to prevent
--      # problems with other programs or directories called `ld' in the path.
--      # Set LC_ALL=C to ensure ld outputs messages in English.
--      ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
--                       | sed -ne '/supported targets:/!d
--                                  s/[         ][      ]*/ /g
--                                  s/.*supported targets: *//
--                                  s/ .*//
--                                  p'`
--        case "$ld_supported_targets" in
--        elf32-i386)
--              TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
--              ;;
--        a.out-i386-linux)
--              echo "${UNAME_MACHINE}-pc-linux-gnuaout"
--              exit ;;
--        coff-i386)
--              echo "${UNAME_MACHINE}-pc-linux-gnucoff"
--              exit ;;
--        "")
--              # Either a pre-BFD a.out linker (linux-gnuoldld) or
--              # one that does not give us useful --help.
--              echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
--              exit ;;
--      esac
--      # Determine whether the default compiler is a.out or elf
--      eval $set_cc_for_build
--      sed 's/^        //' << EOF >$dummy.c
--      #include <features.h>
--      #ifdef __ELF__
--      # ifdef __GLIBC__
--      #  if __GLIBC__ >= 2
--      LIBC=gnu
--      #  else
--      LIBC=gnulibc1
--      #  endif
--      # else
--      LIBC=gnulibc1
--      # endif
--      #else
-       #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
 -      #if defined(__INTEL_COMPILER) || defined(__PGI)
--      LIBC=gnu
--      #else
--      LIBC=gnuaout
--      #endif
--      #endif
--      #ifdef __dietlibc__
--      LIBC=dietlibc
--      #endif
--EOF
-       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-           /^LIBC/{
-               s: ::g
-               p
-           }'`"
 -      eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^LIBC/{s: ::g;p;}'`"
--      test x"${LIBC}" != x && {
--              echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
--              exit
--      }
--      test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
--      ;;
--    i*86:DYNIX/ptx:4*:*)
--      # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
--      # earlier versions are messed up and put the nodename in both
--      # sysname and nodename.
--      echo i386-sequent-sysv4
--      exit ;;
--    i*86:UNIX_SV:4.2MP:2.*)
--        # Unixware is an offshoot of SVR4, but it has its own version
--        # number series starting with 2...
--        # I am not positive that other SVR4 systems won't match this,
--      # I just have to hope.  -- rms.
--        # Use sysv4.2uw... so that sysv4* matches it.
--      echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
--      exit ;;
--    i*86:OS/2:*:*)
--      # If we were able to find `uname', then EMX Unix compatibility
--      # is probably installed.
--      echo ${UNAME_MACHINE}-pc-os2-emx
--      exit ;;
--    i*86:XTS-300:*:STOP)
--      echo ${UNAME_MACHINE}-unknown-stop
--      exit ;;
--    i*86:atheos:*:*)
--      echo ${UNAME_MACHINE}-unknown-atheos
--      exit ;;
--    i*86:syllable:*:*)
--      echo ${UNAME_MACHINE}-pc-syllable
--      exit ;;
--    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
--      echo i386-unknown-lynxos${UNAME_RELEASE}
--      exit ;;
--    i*86:*DOS:*:*)
--      echo ${UNAME_MACHINE}-pc-msdosdjgpp
--      exit ;;
--    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
--      UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
--      if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
--              echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
--      else
--              echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
--      fi
--      exit ;;
--    i*86:*:5:[678]*)
--      # UnixWare 7.x, OpenUNIX and OpenServer 6.
--      case `/bin/uname -X | grep "^Machine"` in
--          *486*)           UNAME_MACHINE=i486 ;;
--          *Pentium)        UNAME_MACHINE=i586 ;;
--          *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
--      esac
--      echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
--      exit ;;
--    i*86:*:3.2:*)
--      if test -f /usr/options/cb.name; then
--              UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
--              echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
--      elif /bin/uname -X 2>/dev/null >/dev/null ; then
--              UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
--              (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
--              (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
--                      && UNAME_MACHINE=i586
--              (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
--                      && UNAME_MACHINE=i686
--              (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
--                      && UNAME_MACHINE=i686
--              echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
--      else
--              echo ${UNAME_MACHINE}-pc-sysv32
--      fi
--      exit ;;
--    pc:*:*:*)
--      # Left here for compatibility:
--        # uname -m prints for DJGPP always 'pc', but it prints nothing about
--        # the processor, so we play safe by assuming i386.
--      echo i386-pc-msdosdjgpp
--        exit ;;
--    Intel:Mach:3*:*)
--      echo i386-pc-mach3
--      exit ;;
--    paragon:*:*:*)
--      echo i860-intel-osf1
--      exit ;;
--    i860:*:4.*:*) # i860-SVR4
--      if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
--        echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
--      else # Add other i860-SVR4 vendors below as they are discovered.
--        echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
--      fi
--      exit ;;
--    mini*:CTIX:SYS*5:*)
--      # "miniframe"
--      echo m68010-convergent-sysv
--      exit ;;
--    mc68k:UNIX:SYSTEM5:3.51m)
--      echo m68k-convergent-sysv
--      exit ;;
--    M680?0:D-NIX:5.3:*)
--      echo m68k-diab-dnix
--      exit ;;
--    M68*:*:R3V[5678]*:*)
--      test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
--    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
--      OS_REL=''
--      test -r /etc/.relid \
--      && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
--      /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
--        && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
--      /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
--        && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
--    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
--        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
--          && { echo i486-ncr-sysv4; exit; } ;;
--    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
--      echo m68k-unknown-lynxos${UNAME_RELEASE}
--      exit ;;
--    mc68030:UNIX_System_V:4.*:*)
--      echo m68k-atari-sysv4
--      exit ;;
--    TSUNAMI:LynxOS:2.*:*)
--      echo sparc-unknown-lynxos${UNAME_RELEASE}
--      exit ;;
--    rs6000:LynxOS:2.*:*)
--      echo rs6000-unknown-lynxos${UNAME_RELEASE}
--      exit ;;
--    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
--      echo powerpc-unknown-lynxos${UNAME_RELEASE}
--      exit ;;
--    SM[BE]S:UNIX_SV:*:*)
--      echo mips-dde-sysv${UNAME_RELEASE}
--      exit ;;
--    RM*:ReliantUNIX-*:*:*)
--      echo mips-sni-sysv4
--      exit ;;
--    RM*:SINIX-*:*:*)
--      echo mips-sni-sysv4
--      exit ;;
--    *:SINIX-*:*:*)
--      if uname -p 2>/dev/null >/dev/null ; then
--              UNAME_MACHINE=`(uname -p) 2>/dev/null`
--              echo ${UNAME_MACHINE}-sni-sysv4
--      else
--              echo ns32k-sni-sysv
--      fi
--      exit ;;
--    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
--                      # says <Richard.M.Bartel@ccMail.Census.GOV>
--        echo i586-unisys-sysv4
--        exit ;;
--    *:UNIX_System_V:4*:FTX*)
--      # From Gerald Hewes <hewes@openmarket.com>.
--      # How about differentiating between stratus architectures? -djm
--      echo hppa1.1-stratus-sysv4
--      exit ;;
--    *:*:*:FTX*)
--      # From seanf@swdc.stratus.com.
--      echo i860-stratus-sysv4
--      exit ;;
--    i*86:VOS:*:*)
--      # From Paul.Green@stratus.com.
--      echo ${UNAME_MACHINE}-stratus-vos
--      exit ;;
--    *:VOS:*:*)
--      # From Paul.Green@stratus.com.
--      echo hppa1.1-stratus-vos
--      exit ;;
--    mc68*:A/UX:*:*)
--      echo m68k-apple-aux${UNAME_RELEASE}
--      exit ;;
--    news*:NEWS-OS:6*:*)
--      echo mips-sony-newsos6
--      exit ;;
--    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
--      if [ -d /usr/nec ]; then
--              echo mips-nec-sysv${UNAME_RELEASE}
--      else
--              echo mips-unknown-sysv${UNAME_RELEASE}
--      fi
--        exit ;;
--    BeBox:BeOS:*:*)   # BeOS running on hardware made by Be, PPC only.
--      echo powerpc-be-beos
--      exit ;;
--    BeMac:BeOS:*:*)   # BeOS running on Mac or Mac clone, PPC only.
--      echo powerpc-apple-beos
--      exit ;;
--    BePC:BeOS:*:*)    # BeOS running on Intel PC compatible.
--      echo i586-pc-beos
--      exit ;;
--    SX-4:SUPER-UX:*:*)
--      echo sx4-nec-superux${UNAME_RELEASE}
--      exit ;;
--    SX-5:SUPER-UX:*:*)
--      echo sx5-nec-superux${UNAME_RELEASE}
--      exit ;;
--    SX-6:SUPER-UX:*:*)
--      echo sx6-nec-superux${UNAME_RELEASE}
-       exit ;;
-     SX-7:SUPER-UX:*:*)
-       echo sx7-nec-superux${UNAME_RELEASE}
-       exit ;;
-     SX-8:SUPER-UX:*:*)
-       echo sx8-nec-superux${UNAME_RELEASE}
-       exit ;;
-     SX-8R:SUPER-UX:*:*)
-       echo sx8r-nec-superux${UNAME_RELEASE}
--      exit ;;
--    Power*:Rhapsody:*:*)
--      echo powerpc-apple-rhapsody${UNAME_RELEASE}
--      exit ;;
--    *:Rhapsody:*:*)
--      echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
--      exit ;;
--    *:Darwin:*:*)
--      UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
--      case $UNAME_PROCESSOR in
--          unknown) UNAME_PROCESSOR=powerpc ;;
--      esac
--      echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
--      exit ;;
--    *:procnto*:*:* | *:QNX:[0123456789]*:*)
--      UNAME_PROCESSOR=`uname -p`
--      if test "$UNAME_PROCESSOR" = "x86"; then
--              UNAME_PROCESSOR=i386
--              UNAME_MACHINE=pc
--      fi
--      echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
--      exit ;;
--    *:QNX:*:4*)
--      echo i386-pc-qnx
--      exit ;;
--    NSE-?:NONSTOP_KERNEL:*:*)
--      echo nse-tandem-nsk${UNAME_RELEASE}
--      exit ;;
--    NSR-?:NONSTOP_KERNEL:*:*)
--      echo nsr-tandem-nsk${UNAME_RELEASE}
--      exit ;;
--    *:NonStop-UX:*:*)
--      echo mips-compaq-nonstopux
--      exit ;;
--    BS2000:POSIX*:*:*)
--      echo bs2000-siemens-sysv
--      exit ;;
--    DS/*:UNIX_System_V:*:*)
--      echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
--      exit ;;
--    *:Plan9:*:*)
--      # "uname -m" is not consistent, so use $cputype instead. 386
--      # is converted to i386 for consistency with other x86
--      # operating systems.
--      if test "$cputype" = "386"; then
--          UNAME_MACHINE=i386
--      else
--          UNAME_MACHINE="$cputype"
--      fi
--      echo ${UNAME_MACHINE}-unknown-plan9
--      exit ;;
--    *:TOPS-10:*:*)
--      echo pdp10-unknown-tops10
--      exit ;;
--    *:TENEX:*:*)
--      echo pdp10-unknown-tenex
--      exit ;;
--    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
--      echo pdp10-dec-tops20
--      exit ;;
--    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
--      echo pdp10-xkl-tops20
--      exit ;;
--    *:TOPS-20:*:*)
--      echo pdp10-unknown-tops20
--      exit ;;
--    *:ITS:*:*)
--      echo pdp10-unknown-its
--      exit ;;
--    SEI:*:*:SEIUX)
--        echo mips-sei-seiux${UNAME_RELEASE}
--      exit ;;
--    *:DragonFly:*:*)
--      echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
--      exit ;;
--    *:*VMS:*:*)
--      UNAME_MACHINE=`(uname -p) 2>/dev/null`
--      case "${UNAME_MACHINE}" in
--          A*) echo alpha-dec-vms ; exit ;;
--          I*) echo ia64-dec-vms ; exit ;;
--          V*) echo vax-dec-vms ; exit ;;
--      esac ;;
--    *:XENIX:*:SysV)
--      echo i386-pc-xenix
--      exit ;;
--    i*86:skyos:*:*)
--      echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
--      exit ;;
--    i*86:rdos:*:*)
--      echo ${UNAME_MACHINE}-pc-rdos
--      exit ;;
--esac
--
--#echo '(No uname command or uname output not recognized.)' 1>&2
--#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
--
--eval $set_cc_for_build
--cat >$dummy.c <<EOF
--#ifdef _SEQUENT_
--# include <sys/types.h>
--# include <sys/utsname.h>
--#endif
--main ()
--{
--#if defined (sony)
--#if defined (MIPSEB)
--  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
--     I don't know....  */
--  printf ("mips-sony-bsd\n"); exit (0);
--#else
--#include <sys/param.h>
--  printf ("m68k-sony-newsos%s\n",
--#ifdef NEWSOS4
--          "4"
--#else
--        ""
--#endif
--         ); exit (0);
--#endif
--#endif
--
--#if defined (__arm) && defined (__acorn) && defined (__unix)
--  printf ("arm-acorn-riscix\n"); exit (0);
--#endif
--
--#if defined (hp300) && !defined (hpux)
--  printf ("m68k-hp-bsd\n"); exit (0);
--#endif
--
--#if defined (NeXT)
--#if !defined (__ARCHITECTURE__)
--#define __ARCHITECTURE__ "m68k"
--#endif
--  int version;
--  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
--  if (version < 4)
--    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
--  else
--    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
--  exit (0);
--#endif
--
--#if defined (MULTIMAX) || defined (n16)
--#if defined (UMAXV)
--  printf ("ns32k-encore-sysv\n"); exit (0);
--#else
--#if defined (CMU)
--  printf ("ns32k-encore-mach\n"); exit (0);
--#else
--  printf ("ns32k-encore-bsd\n"); exit (0);
--#endif
--#endif
--#endif
--
--#if defined (__386BSD__)
--  printf ("i386-pc-bsd\n"); exit (0);
--#endif
--
--#if defined (sequent)
--#if defined (i386)
--  printf ("i386-sequent-dynix\n"); exit (0);
--#endif
--#if defined (ns32000)
--  printf ("ns32k-sequent-dynix\n"); exit (0);
--#endif
--#endif
--
--#if defined (_SEQUENT_)
--    struct utsname un;
--
--    uname(&un);
--
--    if (strncmp(un.version, "V2", 2) == 0) {
--      printf ("i386-sequent-ptx2\n"); exit (0);
--    }
--    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
--      printf ("i386-sequent-ptx1\n"); exit (0);
--    }
--    printf ("i386-sequent-ptx\n"); exit (0);
--
--#endif
--
--#if defined (vax)
--# if !defined (ultrix)
--#  include <sys/param.h>
--#  if defined (BSD)
--#   if BSD == 43
--      printf ("vax-dec-bsd4.3\n"); exit (0);
--#   else
--#    if BSD == 199006
--      printf ("vax-dec-bsd4.3reno\n"); exit (0);
--#    else
--      printf ("vax-dec-bsd\n"); exit (0);
--#    endif
--#   endif
--#  else
--    printf ("vax-dec-bsd\n"); exit (0);
--#  endif
--# else
--    printf ("vax-dec-ultrix\n"); exit (0);
--# endif
--#endif
--
--#if defined (alliant) && defined (i860)
--  printf ("i860-alliant-bsd\n"); exit (0);
--#endif
--
--  exit (1);
--}
--EOF
--
--$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
--      { echo "$SYSTEM_NAME"; exit; }
--
--# Apollos put the system type in the environment.
--
--test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
--
--# Convex versions that predate uname can use getsysinfo(1)
--
--if [ -x /usr/convex/getsysinfo ]
--then
--    case `getsysinfo -f cpu_type` in
--    c1*)
--      echo c1-convex-bsd
--      exit ;;
--    c2*)
--      if getsysinfo -f scalar_acc
--      then echo c32-convex-bsd
--      else echo c2-convex-bsd
--      fi
--      exit ;;
--    c34*)
--      echo c34-convex-bsd
--      exit ;;
--    c38*)
--      echo c38-convex-bsd
--      exit ;;
--    c4*)
--      echo c4-convex-bsd
--      exit ;;
--    esac
--fi
--
--cat >&2 <<EOF
--$0: unable to guess system type
--
--This script, last modified $timestamp, has failed to recognize
--the operating system you are using. It is advised that you
--download the most up to date version of the config scripts from
--
--  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
--and
--  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
--
--If the version you run ($0) is already up to date, please
--send the following data and any information you think might be
--pertinent to <config-patches@gnu.org> in order to provide the needed
--information to handle your system.
--
--config.guess timestamp = $timestamp
--
--uname -m = `(uname -m) 2>/dev/null || echo unknown`
--uname -r = `(uname -r) 2>/dev/null || echo unknown`
--uname -s = `(uname -s) 2>/dev/null || echo unknown`
--uname -v = `(uname -v) 2>/dev/null || echo unknown`
--
--/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
--/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
--
--hostinfo               = `(hostinfo) 2>/dev/null`
--/bin/universe          = `(/bin/universe) 2>/dev/null`
--/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
--/bin/arch              = `(/bin/arch) 2>/dev/null`
--/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
--/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
--
--UNAME_MACHINE = ${UNAME_MACHINE}
--UNAME_RELEASE = ${UNAME_RELEASE}
--UNAME_SYSTEM  = ${UNAME_SYSTEM}
--UNAME_VERSION = ${UNAME_VERSION}
--EOF
--
--exit 1
--
--# Local variables:
--# eval: (add-hook 'write-file-hooks 'time-stamp)
--# time-stamp-start: "timestamp='"
--# time-stamp-format: "%:y-%02m-%02d"
--# time-stamp-end: "'"
--# End:
diff --combined configure.ad
index c85bab2a6e316ef520da6880b9b1052f2f7a5977,c99faef62d772ccaec7564652532ca580826285b..08bc39156879b5354683f5334c3277ba694aa99a
@@@ -3,7 -3,7 +3,7 @@@
  #
  #  Author: Pekka Riikonen <priikone@silcnet.org>
  #
 -#  Copyright (C) 2000 - 2007 Pekka Riikonen
 +#  Copyright (C) 2000 - 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
@@@ -29,86 -29,74 +29,86 @@@ AC_PROG_EGRE
  AC_SUBST(LN_S)
  AC_PATH_PROG(sedpath, sed)
  
 -#ifdef SILC_DIST_COMPILER
 -# Put here any platform specific stuff
 +AC_PROG_CC
 +AM_PROG_AS
 +AC_C_INLINE
 +AC_C_CONST
 +
 +AC_PROG_RANLIB
 +#ifndef SILC_DIST_TOOLKIT
 +AC_DISABLE_SHARED
 +#endif SILC_DIST_TOOLKIT
 +#ifdef SILC_DIST_INPLACE
 +AC_DISABLE_SHARED
 +#endif SILC_DIST_INPLACE
 +AC_PROG_LIBTOOL
 +
 +SILC_TOP_SRCDIR=`pwd`
 +
 +
 +##
 +## Library versioning.
 +##
 +
 +# Do the releases and library versioning according to following rules:
 +#
 +#  - If any code has changed in library, increment [LIB]_REVISION
 +#  - If functions were added, removed or changed, set [LIB]_REVISION to 0
 +#  - If functions were added, removed or changed, increment [LIB]_CURRENT
 +#  - If functions were added, increment [LIB]_AGE
 +#  - If functions were removed, set [LIB]_AGE to 0
 +#
 +# where [LIB] is LIBSILC, LIBSILCCLIENT or LIBSILCSERVER, and where
 +# "functions" means functions public interfaces (API).
 +#
 +# The LIB_BASE_VERSION defines the SILC software major.minor version and
 +# it is increment only when these version numbers actually change.
  #
 -case "$target" in
 -  *-*-linux*)
 -    check_threads=true
 -    CFLAGS=`echo $CFLAGS -D_GNU_SOURCE`
 -    ;;
 -  *-*-freebsd*)
 -    check_threads=true
 -    ;;
 -  *-*-netbsd*)
 -    check_threads=true
 -    ;;
 -  *-*-*bsd*)
 -    check_threads=false
 -    ;;
 -  *)
 -    check_threads=true
 -    ;;
 -esac
  
 -# Get CPU
 -cpu_i386=false
 -cpu_ix86=false
 -cpu_x86_64=false
 -cpu_ppc=false
 -cpu_ia64=false
 -case "$host_cpu" in
 -  i386)
 -    AC_DEFINE([SILC_I386], [], [SILC_I386])
 -    AC_DEFINE([SILC_I486], [], [SILC_I486])
 -    cpu_i386=true
 -    cpu_ix86=true
 -    ;;
 -  i?86)
 -    AC_DEFINE([SILC_I486], [], [SILC_I486])
 -    cpu_ix86=true
 -    ;;
 -  x86_64)
 -    AC_DEFINE([SILC_X86_64], [], [SILC_X86_64])
 -    cpu_x86_64=true
 -    ;;
 -  powerpc*)
 -    AC_DEFINE([SILC_POWERPC], [], [SILC_POWERPC])
 -    cpu_ppc=true
 -    ;;
 -  ia64)
 -    AC_DEFINE([SILC_IA64], [], [SILC_IA64])
 -    cpu_ia64=true
 -    ;;
 -esac
 -AM_CONDITIONAL(SILC_I386, test x$cpu_i386 = xtrue)
 -AM_CONDITIONAL(SILC_I486, test x$cpu_ix86 = xtrue)
 -AM_CONDITIONAL(SILC_X86_64, test x$cpu_x86_64 = xtrue)
 -AM_CONDITIONAL(SILC_POWERPC, test x$cpu_ppc = xtrue)
 -AM_CONDITIONAL(SILC_IA64, test x$cpu_ia64 = xtrue)
 +# Base version for libraries.  Do not change this unless SILC version
 +# changes too.
 +LIB_BASE_VERSION=1.2
  
 -# Control compiler optimizations
 -CFLAGS=`echo $CFLAGS | sed 's/-O[ 0123456789s]*//g'`
 +# libsilc versions
 +LIBSILC_CURRENT=1             # prev = 0
 +LIBSILC_REVISION=0            # prev = 0
 +LIBSILC_AGE=0                 # prev = 0
  
 -AC_PROG_CC
 -AC_C_INLINE
 -AC_C_CONST
 +# libsilcclient versions
 +LIBSILCCLIENT_CURRENT=1               # prev = 0
 +LIBSILCCLIENT_REVISION=0      # prev = 0
 +LIBSILCCLIENT_AGE=0           # prev = 0
 +
 +# libsilcserver versions
 +LIBSILCSERVER_CURRENT=1               # prev = 0
 +LIBSILCSERVER_REVISION=0      # prev = 0
 +LIBSILCSERVER_AGE=0           # prev = 0
 +
 +# Substitute the version numbers
 +AC_SUBST(LIB_BASE_VERSION)
 +AC_SUBST(LIBSILC_CURRENT)
 +AC_SUBST(LIBSILC_REVISION)
 +AC_SUBST(LIBSILC_AGE)
 +AC_SUBST(LIBSILCCLIENT_CURRENT)
 +AC_SUBST(LIBSILCCLIENT_REVISION)
 +AC_SUBST(LIBSILCCLIENT_AGE)
 +AC_SUBST(LIBSILCSERVER_CURRENT)
 +AC_SUBST(LIBSILCSERVER_REVISION)
 +AC_SUBST(LIBSILCSERVER_AGE)
 +
 +
 +##
 +##  Installation
 +##
  
 -__SILC_HAVE_PTHREAD=""
 -__SILC_HAVE_SIM=""
 -__SILC_ENABLE_DEBUG=""
 +# Default installation destination
 +AC_PREFIX_DEFAULT(/usr/local)
 +if test "x$prefix" != xNONE; then
 +  silc_prefix="$prefix"
 +else
 +  silc_prefix="$ac_default_prefix"
 +  prefix="$silc_prefix"
 +fi
  
  #ifdef SILC_DIST_TOOLKIT
  toolkitver=`echo $VERSION | sed 's/\./ /g'`
  __SILC_PACKAGE_VERSION="#define __SILC_TOOLKIT_VERSION SILC_VERSION($maj,$min,$bld)"
  #endif SILC_DIST_TOOLKIT
  
 -AC_PROG_RANLIB
 -#ifndef SILC_DIST_TOOLKIT
 -AC_DISABLE_SHARED
 -#endif SILC_DIST_TOOLKIT
 -#ifdef SILC_DIST_INPLACE
 -AC_DISABLE_SHARED
 -#endif SILC_DIST_INPLACE
 -AC_PROG_LIBTOOL
  
 -# Header checking
 -#
 -AC_HEADER_STDC
 -AC_HEADER_TIME
 -AC_HEADER_STAT
++##
++## Required dependencies
++##
 -# More header checking
 -#
 -AC_CHECK_HEADERS(unistd.h string.h getopt.h errno.h fcntl.h assert.h)
 -AC_CHECK_HEADERS(sys/types.h sys/stat.h sys/time.h stddef.h)
 -AC_CHECK_HEADERS(netinet/in.h netinet/tcp.h xti.h netdb.h sys/resource.h)
 -AC_CHECK_HEADERS(pwd.h grp.h termcap.h paths.h)
 -AC_CHECK_HEADERS(ncurses.h signal.h ctype.h utime.h)
 -AC_CHECK_HEADERS(arpa/inet.h sys/mman.h limits.h termios.h locale.h langinfo.h)
 -
 -# Data type checking
 -#
 -AC_TYPE_SIGNAL
 -AC_TYPE_SIZE_T
 -AC_TYPE_MODE_T
 -AC_TYPE_UID_T
 -AC_TYPE_PID_T
 -
 -AC_CHECK_SIZEOF(long long, 0)
 -AC_SUBST(SILC_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long)
 -AC_CHECK_SIZEOF(long, 0)
 -AC_SUBST(SILC_SIZEOF_LONG, $ac_cv_sizeof_long)
 -AC_CHECK_SIZEOF(int, 0)
 -AC_SUBST(SILC_SIZEOF_INT, $ac_cv_sizeof_int)
 -AC_CHECK_SIZEOF(short, 0)
 -AC_SUBST(SILC_SIZEOF_SHORT, $ac_cv_sizeof_short)
 -AC_CHECK_SIZEOF(char, 0)
 -AC_SUBST(SILC_SIZEOF_CHAR, $ac_cv_sizeof_char)
 -AC_CHECK_SIZEOF(void *, 0)
 -AC_SUBST(SILC_SIZEOF_VOID_P, $ac_cv_sizeof_void_p)
 -AC_CHECK_TYPES(long long)
 -AC_CHECK_TYPES(long double)
 -
 -# Function to check if compiler flag works
 -# Usage: SILC_ADD_CFLAGS(FLAGS, [ACTION-IF-FAILED])
 -AC_DEFUN([SILC_ADD_CFLAGS],
 -[ tmp_CFLAGS="$CFLAGS"
 -  CFLAGS="$CFLAGS $1"
 -  AC_MSG_CHECKING(whether $CC accepts $1 flag)
 -  AC_TRY_LINK([], [], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)
 -                                     CFLAGS="$tmp_CFLAGS"
 -                                     $2])
 -  unset tmp_CFLAGS
 -])
 -
 -# Function to check if compiler flag works, destination specifiable
 -# Usage: SILC_ADD_CC_FLAGS(VAR, FLAGS, [ACTION-IF-FAILED])
 -AC_DEFUN([SILC_ADD_CC_FLAGS],
 -[ tmp_CFLAGS="$1_CFLAGS"
 -  $1_CFLAGS="${$1_CFLAGS} $2"
 -  AC_MSG_CHECKING(whether $CC accepts $2 flag)
 -  AC_TRY_LINK([], [], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)
 -                                     $1_CFLAGS="$tmp_CFLAGS"
 -                                     $3])
 -  unset tmp_CFLAGS
 -])
 -
 -# Function and library checking
 -#
 -AC_CHECK_FUNC(gethostbyname, [],
 -  [
 -    AC_CHECK_LIB(nsl, gethostbyname, LIBS="$LIBS -lnsl")
 -    AC_CHECK_FUNC(res_gethostbyname, [],
 -       AC_CHECK_LIB(resolv, res_gethostbyname, LIBS="$LIBS -lresolv")
 -    )
 -  ])
 -AC_CHECK_FUNC(socket, [],
 -  AC_CHECK_LIB(socket, socket, LIBS="$LIBS -lsocket")
 -)
 -AC_CHECK_FUNCS(gethostname gethostbyaddr getservbyname getservbyport)
 -AC_CHECK_FUNCS(poll select listen bind shutdown close connect setsockopt)
 -AC_CHECK_FUNCS(setrlimit time ctime utime gettimeofday getrusage)
 -AC_CHECK_FUNCS(chmod fcntl stat fstat getenv putenv strerror)
 -AC_CHECK_FUNCS(getpid getgid getsid getpgid getpgrp getuid sched_yield)
 -AC_CHECK_FUNCS(setgroups initgroups nl_langinfo nanosleep)
 -AC_CHECK_FUNCS(strchr snprintf strstr strcpy strncpy memcpy memset memmove)
 -
 -# lib/contrib conditionals
 -#
 -AC_CHECK_HEADER(regex.h,
 -  [
 -    AC_DEFINE([HAVE_REGEX_H], [], [HAVE_REGEX_H])
 -    have_regex=1
 -  ], have_regex=0
 -)
 -AM_CONDITIONAL(HAVE_REGEX, test x$have_regex = x1)
++compile_libs=true
++LIBSUBDIR=lib
++LDFLAGS="-L\$(silc_top_srcdir)/lib $LDFLAGS"
 -AC_CHECK_FUNC(getopt_long,
 -  [
 -    AC_DEFINE([HAVE_GETOPT_LONG], [], [HAVE_GETOPT_LONG])
 -    have_getopt_long=1
 -  ], have_getopt_long=0
 -)
++# SILC Runtime Toolkit checking
++AC_ARG_WITH(srt-includes,
++  [  --with-srt-includes=DIR  SILC Runtime Toolkit includes [search in DIR]],
++  [ac_srt_includes="$withval"], [ac_srt_includes="no"])
++AC_ARG_WITH(srt-libs,
++  [  --with-srt-libs=DIR      SILC Runtime Toolkit libraries [search in DIR]],
++  [ac_srt_libs="$withval"], [ac_srt_libs="no"])
 -AC_CHECK_FUNC(getopt,
 -  [
 -    AC_DEFINE([HAVE_GETOPT], [], [HAVE_GETOPT])
 -    have_getopt=1
 -  ], have_getopt=0
 -)
++if test -n "$with_srt_includes" || test -n "$with_srt_libs"; then
++  # Manually provided libs
++  if test "$ac_srt_includes" != "no"; then
++    SILC_LIB_INCLUDES="-I$ac_srt_includes"
++  fi
++  if test "$ac_srt_libs" != "no"; then
++    LDFLAGS="-L$ac_srt_libs $LDFLAGS"
++  fi
 -##
 -##  Enable/disable checking
 -##
++  # Check libs to link against
++  f=`$EGREP __SILC_HAVE_PTHREAD $ac_srt_includes/silc.h`
++  if test -n "$f"; then
++    LIBS="$LIBS -lpthread"
++    has_threads=true
++  fi
++else
++  # pkg-config check
++  PKG_CHECK_MODULES(SRT, [srt >= 1.2])
++  LIBS="$SRT_LIBS $LIBS"
++  CFLAGS="$CFLAGS $SRT_CFLAGS"
++fi
 -# IPv6 support
 -#
 -AC_MSG_CHECKING(whether to enable IPv6 support)
 -AC_ARG_ENABLE(ipv6,
 -  [  --enable-ipv6           enable IPv6 support],
 -  [
 -    case "${enableval}" in
 -      yes)
 -        want_ipv6=true
 -        check_ipv6=false
 -      summary_ipv6="yes"
 -        AC_DEFINE([HAVE_IPV6], [], [HAVE_IPV6])
 -        AC_MSG_RESULT(yes)
 -        ;;
 -      *)
 -        want_ipv6=false
 -        check_ipv6=false
 -      summary_ipv6="no"
 -        AC_MSG_RESULT(no)
 -        ;;
 -    esac
 -  ],
 -    check_ipv6=true
 -  )
++# SILC Crypto Toolkit checking
++AC_ARG_WITH(sct-includes,
++  [  --with-sct-includes=DIR  SILC Crypto Toolkit includes [search in DIR]],
++  [ac_sct_includes="$withval"], [ac_sct_includes="no"])
++AC_ARG_WITH(sct-libs,
++  [  --with-sct-libs=DIR      SILC Crypto Toolkit libraries [search in DIR]],
++  [ac_sct_libs="$withval"], [ac_sct_libs="no"])
 -if test x$check_ipv6 = xtrue; then
 -  summary_ipv6="no"
 -  AC_TRY_COMPILE(
 -    [
 -      #ifdef HAVE_SYS_TYPES_H
 -      #include <sys/types.h>
 -      #endif
 -      #ifdef HAVE_NETINET_TCP_H
 -      #include <netinet/tcp.h>
 -      #endif
 -      #ifdef HAVE_NETDB_H
 -      #include <netdb.h>
 -      #endif
 -      #include <sys/socket.h>
 -      #ifdef HAVE_NETINET_IN_H
 -      #include <netinet/in.h>
 -      #endif
 -    ],
 -    [
 -      struct sockaddr_in6 sin6;
 -      int family = AF_INET6;
 -    ],
 -    [
 -      AC_DEFINE([HAVE_IPV6], [], [HAVE_IPV6])
 -      AC_MSG_RESULT(yes)
 -      summary_ipv6="yes"
 -    ],
 -      AC_MSG_RESULT(no)
 -    )
++if test -n "$with_sct_includes" || test -n "$with_sct_libs"; then
++  # Manually provided libs
++  if test "$ac_sct_includes" != "no"; then
++    SILC_LIB_INCLUDES="-I$ac_sct_includes"
++  fi
++  if test "$ac_sct_libs" != "no"; then
++    LDFLAGS="-L$ac_sct_libs $LDFLAGS"
++  fi
++
++  # Check libs to link against
++  f=`$EGREP __SILC_HAVE_PTHREAD $ac_sct_includes/silc.h`
++  if test -n "$f"; then
++    LIBS="$LIBS -lpthread"
++    has_threads=true
++  fi
++else
++  # pkg-config check
++  PKG_CHECK_MODULES(SCT, [sct >= 1.2])
++  LIBS="$SCT_LIBS $LIBS"
++  CFLAGS="$CFLAGS $SCT_CFLAGS"
+ fi
 -# Debug checking
 -#
 -AC_MSG_CHECKING(whether to enable debugging)
 -summary_debug="no"
 -__SILC_ENABLE_DEBUG=""
 -AC_ARG_ENABLE(debug,
 -  [  --enable-debug          enable debugging],
 -  [
 -    case "${enableval}" in
 -      yes)
 -        AC_MSG_RESULT(yes)
 -        AC_DEFINE([SILC_DEBUG], [], [enable-debug])
 -      summary_debug="yes"
 -        __SILC_ENABLE_DEBUG="#define __SILC_ENABLE_DEBUG 1"
 -        ;;
 -      *)
 -        AC_MSG_RESULT(no)
 -        ;;
 -    esac
 -  ],
 -  [
 -    AC_MSG_RESULT(no)
 -  ])
 -# Disable all compiler optimizations
 -#
 -AC_MSG_CHECKING(whether to enable compiler optimizations)
 -want_cc_optimizations=true
 -AC_ARG_ENABLE(optimizations,
 -  [  --disable-optimizations do not use any compiler optimizations],
 -  [
 -    AC_MSG_RESULT(no)
 -    AC_DEFINE([SILC_NO_CC_OPTIMIZATIONS], [], [SILC_NO_CC_OPTIMIZATIONS])
 -    want_cc_optimizations=false
 -  ],
 -  [
 -    AC_MSG_RESULT(yes)
 -    want_cc_optimizations=true
 -  ])
 -AM_CONDITIONAL(SILC_NO_CC_OPTIMIZATIONS, test x$want_cc_optimizations = xfalse)
 +##
 +## Detect CPU
 +##
  
 -# Disable all assembler optimizations
 -#
 -AC_MSG_CHECKING(whether to enable assembler optimizations)
 -want_asm=true
 -AC_ARG_ENABLE(asm,
 -  [  --disable-asm           do not use assembler optimizations],
 +# Disable all CPU feature optimizations
 +AC_MSG_CHECKING(whether to enable CPU feature optimizations)
 +AC_ARG_ENABLE(cpu-optimizations,
 +  [  --disable-cpu-optimizations  do not use any CPU feature optimizations],
    [
      AC_MSG_RESULT(no)
 -    AC_DEFINE([SILC_NO_ASM], [], [SILC_NO_ASM])
 -    want_asm=false
 +    AC_DEFINE([SILC_NO_CPU_OPTIMIZATIONS], [], [SILC_NO_CPU_OPTIMIZATIONS])
 +    want_cpu_optimizations=false
    ],
    [
      AC_MSG_RESULT(yes)
 -    want_asm=true
 +    want_cpu_optimizations=true
    ])
 -AM_CONDITIONAL(SILC_NO_ASM, test x$want_asm = xfalse)
 +AM_CONDITIONAL(SILC_NO_CPU_OPTIMIZATIONS,
 +               test x$want_cpu_optimizations = xfalse)
  
 -# Check for assembler
 -#
 -SILC_ASSEMBLER=""
 -have_assembler=false
 -if test x$want_asm = xtrue; then
 -  AC_PATH_PROG([NASM], [nasm], [no])
 -  if test "x$NASM" != "xno"; then
 -    if test x$cpu_x86_64 = xtrue; then
 -      SILC_ASSEMBLER="$NASM -O2 -felf64"
 -    else
 -      SILC_ASSEMBLER="$NASM -O2 -felf"
 +SILC_SYSTEM_IS_SMP(AC_DEFINE([SILC_SMP], [], [SILC_SMP]), [],
 +                   AC_DEFINE([SILC_SMP], [], [SILC_SMP]))
 +cpu_i386=false
 +cpu_i486=false
 +cpu_i586=false
 +cpu_i686=false
 +cpu_i786=false
 +cpu_x86_64=false
 +cpu_ppc=false
 +cpu_ia64=false
 +case "$host_cpu" in
 +  # All following Intels are considered 32-bit CPUs.
 +  i?86)
 +    # All CPUs of today are considered i386 and i486 compatible */
 +    cpu_i386=true
 +    cpu_i486=true
 +
 +    if test "x$host_cpu" = "xi586"; then
 +      cpu_i586=true
      fi
 -    have_assembler=true
 -  fi
  
 -  AC_PATH_PROG([YASM], [yasm], [no])
 -  if test "x$YASM" != "xno"; then
 -    if test x$cpu_x86_64 = xtrue; then
 -      SILC_ASSEMBLER="$YASM -Xgnu -felf64"
 -    else
 -      SILC_ASSEMBLER="$YASM -Xgnu -felf"
 +    if test "x$host_cpu" = "xi686"; then
 +      cpu_i586=true
 +      cpu_i686=true
 +    fi
 +
 +    if test "x$host_cpu" = "xi786"; then
 +      cpu_i586=true
 +      cpu_i686=true
 +      cpu_i786=true
 +    fi
 +
 +    # Check for specific CPU features
 +    SILC_CPU_FLAG(mmx, true, AC_DEFINE([SILC_CPU_MMX], [], [SILC_CPU_MMX]), [])
 +    SILC_CPU_FLAG(sse2, true, AC_DEFINE([SILC_CPU_SSE2], [], [SILC_CPU_SSE2]), [])
 +    SILC_CPU_FLAG(pni, true, AC_DEFINE([SILC_CPU_SSE3], [], [SILC_CPU_SSE3]), [])
 +    SILC_CPU_FLAG(ssse3, true, AC_DEFINE([SILC_CPU_SSSE3], [], [SILC_CPU_SSSE3]), [])
 +    SILC_CPU_FLAG(sse4, true, AC_DEFINE([SILC_CPU_SSE4], [], [SILC_CPU_SSE4]), [])
 +    ;;
 +
 +  # Intel IA-64, 64-bit CPU (not x86_64 compatible)
 +  ia64)
 +    AC_DEFINE([SILC_IA64], [], [SILC_IA64])
 +    cpu_ia64=true
 +    ;;
 +
 +  # AMD/Intel x86_64, 64-bit CPU
 +  x86_64)
 +    cpu_x86_64=true
 +
 +    # Check for specific CPU features
 +    SILC_CPU_FLAG(mmx, true, AC_DEFINE([SILC_CPU_MMX], [], [SILC_CPU_MMX]), [])
 +    SILC_CPU_FLAG(sse2, true, AC_DEFINE([SILC_CPU_SSE2], [], [SILC_CPU_SSE2]), [])
 +    SILC_CPU_FLAG(pni, true, AC_DEFINE([SILC_CPU_SSE3], [], [SILC_CPU_SSE3]), [])
 +    SILC_CPU_FLAG(ssse3, true, AC_DEFINE([SILC_CPU_SSSE3], [], [SILC_CPU_SSSE3]), [])
 +    SILC_CPU_FLAG(sse4, true, AC_DEFINE([SILC_CPU_SSE4], [], [SILC_CPU_SSE4]), [])
 +    ;;
 +
 +  # PowerPC, 32-bit and 64-bit CPUs
 +  powerpc*)
 +    cpu_ppc=true
 +    ;;
 +esac
 +AM_CONDITIONAL(SILC_I386, test x$cpu_i386 = xtrue)
 +AM_CONDITIONAL(SILC_I486, test x$cpu_i486 = xtrue)
 +AM_CONDITIONAL(SILC_I586, test x$cpu_i586 = xtrue)
 +AM_CONDITIONAL(SILC_I686, test x$cpu_i686 = xtrue)
 +AM_CONDITIONAL(SILC_7686, test x$cpu_i786 = xtrue)
 +AM_CONDITIONAL(SILC_X86_64, test x$cpu_x86_64 = xtrue)
 +AM_CONDITIONAL(SILC_POWERPC, test x$cpu_ppc = xtrue)
 +AM_CONDITIONAL(SILC_IA64, test x$cpu_ia64 = xtrue)
 +
 +if test x$want_cpu_optimizations = xtrue; then
 +  # Set some compiler options based on CPU
 +  if test "x$CC" = "xicc"; then
 +    # ICC flags
 +    if test x$x_have_cpu_sse4 = xtrue; then
 +      SILC_ADD_CFLAGS(-axS)
 +    fi
 +    if test x$x_have_cpu_ssse3 = xtrue; then
 +      SILC_ADD_CFLAGS(-axT)
 +    elif test x$x_have_cpu_pni = xtrue; then
 +      SILC_ADD_CFLAGS(-axP)
 +    elif test x$x_have_cpu_sse2 = xtrue; then
 +      SILC_ADD_CFLAGS(-axW)
 +    fi
 +  else
 +    # Other compilers
 +    if test x$x_have_cpu_sse2 = xtrue; then
 +      SILC_ADD_CFLAGS(-msse2)
 +    fi
 +    if test x$x_have_cpu_pni = xtrue; then
 +      SILC_ADD_CFLAGS(-msse3)
 +    fi
 +    if test x$x_have_cpu_ssse3 = xtrue; then
 +      SILC_ADD_CFLAGS(-mssse3)
 +    fi
 +    if test x$x_have_cpu_sse4 = xtrue; then
 +      SILC_ADD_CFLAGS(-msse4)
      fi
 -    have_assembler=true
    fi
  fi
 -AC_SUBST(SILC_ASSEMBLER)
 +
  
  ##
 -## va_copy checks
 +## Put here any platform specific stuff
  ##
 -va_copy=false
 -AC_MSG_CHECKING(for va_copy)
 -AC_TRY_COMPILE(
 -  [
 -    #include <stdarg.h>
 -    #include <stdlib.h>
 -  ],
 -  [
 -    int t(int x, ...)
 -    {
 -      va_list va, cp;
 -      va_start(va, x);
 -      va_copy(cp, va);
 -      if (va_arg(cp, int) != 0xff11)
 -        return 1;
 -      va_end(va);
 -      va_end(cp);
 -      return 0;
 -    }
 -    int main()
 -    {
 -      return t(0, 0xff11);
 -    }
 -  ],
 -  [
 -    AC_DEFINE([HAVE_VA_COPY], [], [HAVE_VA_COPY])
 -    AC_MSG_RESULT(yes)
 -    va_copy=true
 -  ],
 -  [
 -    AC_MSG_RESULT(no)
 -    va_copy=false
 -  ]
 -)
  
 -if test x$va_copy = xfalse; then
 -  AC_MSG_CHECKING(for __va_copy)
 -  AC_TRY_COMPILE(
 -  [
 -    #include <stdarg.h>
 -    #include <stdlib.h>
 -  ],
 -  [
 -    int t(int x, ...)
 -    {
 -      va_list va, cp;
 -      va_start(va, x);
 -      __va_copy(cp, va);
 -      if (va_arg(cp, int) != 0xff11)
 -        return 1;
 -      va_end(va);
 -      va_end(cp);
 -      return 0;
 -    }
 -    int main()
 -    {
 -      return t(0, 0xff11);
 -    }
 -  ],
 -  [
 -    AC_DEFINE([HAVE___VA_COPY], [], [HAVE___VA_COPY])
 -    AC_MSG_RESULT(yes)
 -    va_copy=true
 -  ],
 -  [
 -    AC_MSG_RESULT(no)
 -    va_copy=false
 -  ]
 -  )
 -fi
 +case "$target" in
 +  *-*-linux*)
 +    CFLAGS=`echo $CFLAGS -D_GNU_SOURCE`
 +    ;;
 +  *-*-freebsd*)
 +    ;;
 +  *-*-netbsd*)
 +    ;;
 +  *-*-*bsd*)
 +    ;;
 +  *)
 +    ;;
 +esac
 +
 +
 +##
 +## Header checking
 +##
 +AC_HEADER_STDC
 +
 +# More header checking
 +#
 +AC_CHECK_HEADERS(unistd.h assert.h time.h fcntl.h stdarg.h)
 +AC_CHECK_HEADERS(sys/types.h sys/times.h sys/time.h)
 +
 +# Check for big-endian machines
 +AC_C_BIGENDIAN
  
 -if test x$va_copy = xfalse; then
 -  AC_RUN_IFELSE(
 -    [
 -      #include <stdarg.h>
 -      #include <stdlib.h>
 -      int t(int x, ...)
 -      {
 -        va_list va, cp;
 -        va_start(va, x);
 -        cp = va;
 -        if (va_arg(cp, int) != 0xff11)
 -          return 1;
 -        va_end(va);
 -        va_end(cp);
 -        return 0;
 -      }
 -      int main()
 -      {
 -        return t(0, 0xff11);
 -      }
 -    ],
 -    [va_copy=false],
 -    [
 -      AC_DEFINE([SILC_VA_COPY_ARRAY], [], [SILC_VA_COPY_ARRAY])
 -    ],
 -    [va=copy=false]
 -  )
 -fi
  
  ##
  ## Compiler and compiler flag checks
  ##
  
 +# Disable all compiler optimizations
 +AC_MSG_CHECKING(whether to enable compiler optimizations)
 +AC_ARG_ENABLE(optimizations,
 +  [  --disable-optimizations do not use any compiler optimizations],
 +  [
 +    AC_MSG_RESULT(no)
 +    AC_DEFINE([SILC_NO_CC_OPTIMIZATIONS], [], [SILC_NO_CC_OPTIMIZATIONS])
 +    want_cc_optimizations=false
 +  ],
 +  [
 +    AC_MSG_RESULT(yes)
 +    want_cc_optimizations=true
 +  ])
 +AM_CONDITIONAL(SILC_NO_CC_OPTIMIZATIONS, test x$want_cc_optimizations = xfalse)
 +
  if test "$GCC"; then
    # GCC specific options
    if test "x$summary_debug" = "xyes"; then
@@@ -333,13 -511,9 +402,13 @@@ els
        ;;
    esac
  
 -  # Intel C++ Compiler needs -restrict
 +  # Intel C++ Compiler flags
    if test "x$CC" = "xicc"; then
      SILC_ADD_CFLAGS(-restrict)
 +    SILC_ADD_CFLAGS(-finline-functions)
 +
 +    # Don't define __GNUC__ except for system includes
 +    SILC_ADD_CFLAGS(-gcc-sys)
    fi
  fi
  
@@@ -367,166 -541,66 +436,102 @@@ if test x$want_cc_optimizations = xtrue
    fi
  fi
  
 -#
 -# Workaround a bug in GCC 2.x which causes memory exhaustion
 -# when compiling sha1 with optimizations on UltraSPARC.
 -#
 -FIX_SHA1='#'
 -if test "$GCC" -a "$host_cpu" = "sparc64"; then
 -  AC_MSG_CHECKING(whether to enable GCC 2.x workaround for SHA1)
 -  AC_TRY_COMPILE(
 -    [
 -      #if defined(__sparc64__) && (__GNUC__ == 2)
 -      #else
 -      choke me
 -      #endif
 -    ],
 -    [],
 -    [
 -      FIX_SHA1=''
 -      AC_MSG_RESULT(yes)
 -    ],
 -      AC_MSG_RESULT(no)
 -    )
 -fi
 -AC_SUBST(FIX_SHA1)
 -#endif SILC_DIST_COMPILER
  
  ##
 -##  Installation
 +## Function and libary checking
  ##
  
 -# Default installation destination
 +
 +##
 +##  Enable/disable checking
 +##
 +
 +#ifdef SILC_DIST_INPLACE
  #
 -AC_PREFIX_DEFAULT(/usr/local)
 -if test "x$prefix" != xNONE; then
 -  silc_prefix="$prefix"
 -else
 -  silc_prefix="$ac_default_prefix"
 -  prefix="$silc_prefix"
 -fi
 +# Profiling options (never delivered to distributions)
 +#
 +AC_MSG_CHECKING(whether to enable gprof)
 +AC_ARG_ENABLE(gprof,
 +  [  --enable-gprof          enable gprof profiling],
 +  [
 +    case "${enableval}" in
 +      yes)
 +        AC_MSG_RESULT(yes)
 +        SILC_ADD_CFLAGS(-pg)
 +        LIBS="$LIBS -pg"
 +        ;;
 +      *)
 +        AC_MSG_RESULT(no)
 +        ;;
 +    esac
 +  ],
 +  [
 +    AC_MSG_RESULT(no)
 +  ])
 +
 +AC_MSG_CHECKING(whether to enable gcov)
 +AC_ARG_ENABLE(gcov,
 +  [  --enable-gcov           enable gcov],
 +  [
 +    case "${enableval}" in
 +      yes)
 +        AC_MSG_RESULT(yes)
 +        SILC_ADD_CFLAGS(-fprofile-arcs)
 +        LIBS="$LIBS -lgcov"
 +        ;;
 +      *)
 +        AC_MSG_RESULT(no)
 +        ;;
 +    esac
 +  ],
 +  [
 +    AC_MSG_RESULT(no)
 +  ])
 +#endif SILC_DIST_INPLACE
 +
 +# Debug checking
 +AC_MSG_CHECKING(whether to enable debugging)
 +summary_debug="no"
 +AC_ARG_ENABLE(debug,
 +  [  --enable-debug          enable debugging],
 +  [
 +    case "${enableval}" in
 +      yes)
 +        AC_MSG_RESULT(yes)
 +      summary_debug="yes"
 +        ;;
 +      *)
 +        AC_MSG_RESULT(no)
 +        ;;
 +    esac
 +  ],
 +  [
 +    AC_MSG_RESULT(no)
 +  ])
  
 -#ifndef SILC_DIST_AUTODIST
 -ETCDIR=`eval echo $sysconfdir`;ETCDIR=`eval echo $ETCDIR`
 -AC_SUBST(ETCDIR)
 -AC_DEFINE_UNQUOTED([SILC_ETCDIR], "$ETCDIR", [SILC_ETCDIR])
 +# Disable all assembler optimizations
 +AC_MSG_CHECKING(whether to enable assembler optimizations)
 +want_asm=true
 +AC_ARG_ENABLE(asm,
 +  [  --disable-asm           do not use assembler optimizations],
 +  [
 +    AC_MSG_RESULT(no)
 +    AC_DEFINE([SILC_NO_ASM], [], [SILC_NO_ASM])
 +    want_asm=false
 +  ],
 +  [
 +    AC_MSG_RESULT(yes)
 +    want_asm=true
 +  ])
 +AM_CONDITIONAL(SILC_NO_ASM, test x$want_asm = xfalse)
  
 -DOCDIR=`eval echo $docdir`;DOCDIR=`eval echo $DOCDIR`
 -AC_SUBST(DOCDIR)
 -AC_DEFINE_UNQUOTED([SILC_DOCDIR], "$DOCDIR", [SILC_DOCDIR])
 -#endif SILC_DIST_AUTODIST
  
 -#ifdef SILC_DIST_COMPILER
  ##
  ##  With/without checkings
  ##
  
 -#
 -# SILC library checking
--compile_libs=true
--LIBSUBDIR=lib
- LDFLAGS="-L\$(silc_top_srcdir)/lib $LDFLAGS"
- # SILC Runtime Toolkit checking
- AC_ARG_WITH(srt-includes,
-   [  --with-srt-includes=DIR  SILC Runtime Toolkit includes [search in DIR]],
-   [ac_srt_includes="$withval"], [ac_srt_includes="no"])
- AC_ARG_WITH(srt-libs,
-   [  --with-srt-libs=DIR      SILC Runtime Toolkit libraries [search in DIR]],
-   [ac_srt_libs="$withval"], [ac_srt_libs="no"])
- if test -n "$with_srt_includes" || test -n "$with_srt_libs"; then
-   # Manually provided libs
-   if test "$ac_srt_includes" != "no"; then
-     SILC_LIB_INCLUDES="-I$ac_srt_includes"
-   fi
-   if test "$ac_srt_libs" != "no"; then
-     LDFLAGS="-L$ac_srt_libs $LDFLAGS"
-   fi
-   # Check libs to link against
-   f=`$EGREP __SILC_HAVE_PTHREAD $ac_srt_includes/silc.h`
-   if test -n "$f"; then
-     LIBS="$LIBS -lpthread"
-     has_threads=true
-   fi
- else
-   # pkg-config check
-   PKG_CHECK_MODULES(SRT, [srt >= 1.2])
-   LIBS="$SRT_LIBS $LIBS"
-   CFLAGS="$CFLAGS $SRT_CFLAGS"
- fi
- # SILC Crypto Toolkit checking
- AC_ARG_WITH(sct-includes,
-   [  --with-sct-includes=DIR  SILC Crypto Toolkit includes [search in DIR]],
-   [ac_sct_includes="$withval"], [ac_sct_includes="no"])
- AC_ARG_WITH(sct-libs,
-   [  --with-sct-libs=DIR      SILC Crypto Toolkit libraries [search in DIR]],
-   [ac_sct_libs="$withval"], [ac_sct_libs="no"])
- if test -n "$with_sct_includes" || test -n "$with_sct_libs"; then
-   # Manually provided libs
-   if test "$ac_sct_includes" != "no"; then
-     SILC_LIB_INCLUDES="-I$ac_sct_includes"
-   fi
-   if test "$ac_sct_libs" != "no"; then
-     LDFLAGS="-L$ac_sct_libs $LDFLAGS"
-   fi
-   # Check libs to link against
-   f=`$EGREP __SILC_HAVE_PTHREAD $ac_sct_includes/silc.h`
-   if test -n "$f"; then
-     LIBS="$LIBS -lpthread"
-     has_threads=true
-   fi
- else
-   # pkg-config check
-   PKG_CHECK_MODULES(SCT, [sct >= 1.2])
-   LIBS="$SCT_LIBS $LIBS"
-   CFLAGS="$CFLAGS $SCT_CFLAGS"
- fi
--
  #ifndef SILC_DIST_TOOLKIT
 +# SILC Protocol Toolkit checking
  AC_ARG_WITH(silc-includes,
    [  --with-silc-includes=DIR SILC Toolkit includes [search in DIR]],
    [ac_silc_includes="$withval"], [ac_silc_includes="no"])
@@@ -546,6 -620,8 +551,6 @@@ if test -n "$with_silc_includes" || tes
      compile_libs=false
      LIBSUBDIR=
      LDFLAGS="-L$ac_silc_libs $LDFLAGS"
 -  else
 -    LDFLAGS="-L\$(silc_top_srcdir)/lib $LDFLAGS"
    fi
  
    # Check libs to link against
  
  else
    # pkg-config check
 -  PKG_CHECK_MODULES(SILC, [silc >= 1.1], compile_libs=false, compile_libs=true)
 +  PKG_CHECK_MODULES(SILC, [silc >= 1.2], compile_libs=false, compile_libs=true)
  #ifdef SILC_DIST_CLIENTLIB
 -  PKG_CHECK_MODULES(SILCCLIENT, [silcclient >= 1.1.1], compile_libs=false, compile_libs=true)
 +  PKG_CHECK_MODULES(SILCCLIENT, [silcclient >= 1.2], compile_libs=false, compile_libs=true)
  #endif SILC_DIST_CLIENTLIB
  #ifdef SILC_DIST_SERVERLIB
    PKG_CHECK_MODULES(SILCSERVER, silcserver, compile_libs=false, compile_libs=true)
      LIBS="$LIBS $SILCSERVER_LIBS"
      CFLAGS="$CFLAGS $SILCSERVER_CFLAGS"
  #endif SILC_DIST_SERVERLIB
 -  else
 -    LDFLAGS="-L\$(silc_top_srcdir)/lib $LDFLAGS"
    fi
  fi
 -#else SILC_DIST_TOOLKIT
 -LDFLAGS="-L\$(silc_top_srcdir)/lib $LDFLAGS"
  #endif SILC_DIST_TOOLKIT
  
 -#ifdef SILC_DIST_SIM
 -# SIM support checking
 -# XXX These needs to be changed as more supported platforms appear.
 -# XXX This probably needs to be made platform dependant check.
 -#
 -sim_support=false
 -AC_MSG_CHECKING(for SIM support)
 -AC_MSG_RESULT()
 -AC_CHECK_HEADERS(dlfcn.h,
 -  [
 -    AC_CHECK_LIB(dl, dlopen,
 -      [
 -        AC_DEFINE([SILC_SIM], [], [HAVE_SIM])
 -        sim_support=true
 -        LIBS="$LIBS -ldl"
 -      ],
 -      [
 -        AC_CHECK_LIB(c, dlopen,
 -          [
 -            AC_DEFINE([SILC_SIM], [], [HAVE_SIM])
 -            sim_support=true
 -          ])
 -      ])
 -   ])
 -
 -AM_CONDITIONAL(SILC_SIM, test x$sim_support = xtrue)
 -if test x$sim_support = xtrue; then
 -  AC_MSG_RESULT(Enabled SIM support.)
 -  __SILC_HAVE_SIM="#define __SILC_HAVE_SIM 1"
 -else
 -  AC_MSG_RESULT(No SIM support found.)
 +if test x$compile_libs = xtrue; then
 +SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silccore"
 +SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcapputil"
 +SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcske"
 +#ifdef SILC_DIST_SFTP
 +SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcsftp"
 +#endif SILC_DIST_SFTP
 +#ifdef SILC_DIST_CLIENTLIB
 +SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcclient"
 +#endif SILC_DIST_CLIENTLIB
 +#ifdef SILC_DIST_SERVERLIB
 +SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcserver"
 +#endif SILC_DIST_SERVERLIB
- #ifdef SILC_DIST_HTTP
- SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silchttp"
- #endif SILC_DIST_HTTP
 +#ifdef SILC_DIST_VCARD
 +SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcvcard"
 +#endif SILC_DIST_VCARD
  fi
 -#endif SILC_DIST_SIM
  
  # SOCKS4 support checking
 -#
  SAVE_LIBS="$LIBS"
  SAVE_CFLAGS="$CFLAGS"
  SAVE_LDFLAGS="$LDFLAGS"
@@@ -649,6 -743,7 +651,6 @@@ AC_ARG_WITH(socks4
    )
  
  # SOCKS5 support checking
 -#
  SAVE_LIBS="$LIBS"
  SAVE_CFLAGS="$CFLAGS"
  SAVE_LDFLAGS="$LDFLAGS"
@@@ -720,10 -815,467 +722,10 @@@ if test "x$socks" = "x5"; the
    AC_DEFINE([Rgethostbyname], [SOCKSgethostbyname], [Socks])
  fi
  
 -#ifdef SILC_DIST_MATH
 -# MP library checking. First check whether user wants to use GMP and use
 -# it if found. If not or not defined then compile the default library in the
 -# source tree.
 -#
 -mp_gmp=false
 -SAVE_LIBS="$LIBS"
 -SAVE_CFLAGS="$CFLAGS"
 -SAVE_LDFLAGS="$LDFLAGS"
 -AC_MSG_CHECKING(whether to search for GMP)
 -AC_ARG_WITH(gmp,
 -  [[  --with-gmp[=DIR]        use GMP instead of SILC Math [search in DIR/lib and DIR/include]]],
 -  [
 -    case "$withval" in
 -      no)
 -        AC_MSG_RESULT(no)
 -        ;;
 -      *)
 -        AC_MSG_RESULT(yes)
 -
 -        if test -d "$withval/include"; then
 -          CFLAGS="$CFLAGS -I$withval/include"
 -        fi
 -        if test -d "$withval/lib"; then
 -          LDFLAGS="$LDFLAGS -L$withval/lib"
 -        fi
 -
 -        LIBS="-lgmp $LIBS"
 -        ;;
 -    esac
 -
 -    AC_CHECK_LIB(gmp, __gmpz_init,
 -      [
 -        mp_gmp=true
 -        AC_DEFINE([SILC_MP_GMP], [], [GMP])
 -        AC_MSG_RESULT(Using GMP as a MP library.)
 -      ],
 -      [
 -        LIBS="$SAVE_LIBS"
 -        CFLAGS="$SAVE_CFLAGS"
 -        LDFLAGS="$SAVE_LDFLAGS"
 -      ])
 -  ],
 -    AC_MSG_RESULT(no)
 -  )
 -
 -AM_CONDITIONAL(SILC_MP_GMP, test x$mp_gmp = xtrue)
 -AM_CONDITIONAL(SILC_MP_SILCMATH, test x$mp_gmp = xfalse)
 -if test x$mp_gmp = xfalse; then
 -  AC_DEFINE([SILC_MP_SILCMATH], [], [SILCMATH])
 -  AC_MSG_RESULT(Using SILC Math as a MP library.)
 -fi
 -#endif SILC_DIST_MATH
 -
 -# iconv support
 -#
 -check_iconv=true
 -has_iconv=false
 -SAVE_LIBS="$LIBS"
 -SAVE_CFLAGS="$CFLAGS"
 -SAVE_LDFLAGS="$LDFLAGS"
 -SAVE_CPPFLAGS="$CPPFLAGS"
 -AC_MSG_CHECKING(whether to implicit search for libiconv)
 -AC_ARG_WITH(iconv,
 -  [[  --with-iconv[=DIR]      use libiconv [search in DIR/include and DIR/lib]]],
 -  [
 -    case "${withval}" in
 -      no)
 -        AC_MSG_RESULT(no)
 -        AC_CHECK_HEADERS(iconv.h,
 -          [
 -            AC_CHECK_FUNC(iconv, has_iconv=true)
 -          ])
 -        check_iconv=false
 -        ;;
 -      *)
 -        AC_MSG_RESULT(yes)
 -        if test -d $withval/include; then
 -          CPPFLAGS="$CPPFLAGS -I$withval/include"
 -          CFLAGS="$CFLAGS -I$withval/include"
 -        fi
 -        if test -d $withval/lib; then
 -          LDFLAGS="$LDFLAGS -L$withval/lib"
 -        fi
 -        ;;
 -    esac
 -  ],
 -  [
 -    AC_MSG_RESULT(no)
 -    AC_CHECK_HEADERS(iconv.h,
 -      [
 -        AC_CHECK_FUNCS(iconv,
 -          [
 -            has_iconv=true
 -            check_iconv=false
 -          ])
 -      ])
 -  ])
 -
 -if test x$check_iconv = xtrue; then
 -  AC_MSG_RESULT(Searching for iconv...)
 -
 -  # XXX
 -  unset ac_cv_header__iconv_h_ ac_cv_header_iconv_h || true
 -
 -  AC_CHECK_HEADERS(iconv.h,
 -    [
 -      LIBS="$LIBS -liconv"
 -      AC_MSG_CHECKING(for iconv in -liconv)
 -      AC_TRY_LINK(
 -        [
 -          #include <stdlib.h>
 -          #include <iconv.h>
 -        ],
 -        [
 -          iconv_t cd = iconv_open("", "");
 -          iconv(cd, NULL, NULL, NULL, NULL);
 -          iconv_close(cd);
 -        ],
 -        [
 -          echo "yes"
 -          AC_DEFINE([HAVE_ICONV], [], [Define if you have the iconv() function.])
 -          has_iconv=true
 -          check_iconv=false
 -        ],
 -        [
 -          echo "no"
 -          LIBS="$SAVE_LIBS"
 -          CFLAGS="$SAVE_CFLAGS"
 -          LDFLAGS="$SAVE_LDFLAGS"
 -          CPPFLAGS="$SAVE_CPPFLAGS"
 -        ])
 -     ])
 -fi
 -
 -if test x$check_iconv = xtrue; then
 -  # search for iconv library..
 -  SAVE_LIBS="$LIBS"
 -  SAVE_CFLAGS="$CFLAGS"
 -  SAVE_LDFLAGS="$LDFLAGS"
 -  SAVE_CPPFLAGS="$CPPFLAGS"
 -
 -  for dir in `echo "/usr/local /usr/pkg /usr/contrib"`; do
 -    if test x$has_iconv = xfalse; then
 -      AC_MSG_RESULT(searching in $dir...)
 -
 -      if test -d $dir/include; then
 -        CPPFLAGS="$CPPFLAGS -I$dir/include"
 -        CFLAGS="$CFLAGS -I$dir/include"
 -      fi
 -      if test -d $dir/lib; then
 -        LDFLAGS="$LDFLAGS -L$dir/lib"
 -      fi
 -
 -      # XXX
 -      unset ac_cv_header__iconv_h_ ac_cv_header_iconv_h || true
 -
 -      AC_CHECK_HEADERS(iconv.h,
 -        [
 -          LIBS="$LIBS -liconv"
 -          AC_MSG_CHECKING(for iconv in -liconv)
 -          AC_TRY_LINK(
 -            [
 -              #include <stdlib.h>
 -              #include <iconv.h>
 -            ],
 -            [
 -              iconv_t cd = iconv_open("", "");
 -              iconv(cd, NULL, NULL, NULL, NULL);
 -              iconv_close(cd);
 -            ],
 -            [
 -              echo "yes"
 -              has_iconv=true
 -              AC_DEFINE([HAVE_ICONV], [], [Define if you have the iconv() function.])
 -            ],
 -            [
 -              echo "no"
 -              has_iconv=false
 -
 -              LIBS="$SAVE_LIBS"
 -              CFLAGS="$SAVE_CFLAGS"
 -              LDFLAGS="$SAVE_LDFLAGS"
 -              CPPFLAGS="$SAVE_CPPFLAGS"
 -            ])
 -         ],
 -         [
 -           CFLAGS="$SAVE_CFLAGS"
 -           LDFLAGS="$SAVE_LDFLAGS"
 -           CPPFLAGS="$SAVE_CPPFLAGS"
 -         ])
 -      fi
 -    done
 -fi
 -
 -if test x$has_iconv = xtrue; then
 -  # (1) Some implementations of iconv won't convert from UTF-8 to UTF-8.
 -  # (2) In glibc-2.1.2 and earlier there is a bug that messes up ob and
 -  #     obl when args 2 and 3 are 0 (fixed in glibc-2.1.3).
 -  #
 -  AC_CACHE_CHECK([whether this iconv is good enough], ac_iconv_good,
 -    AC_TRY_RUN(
 -      [
 -        #include <iconv.h>
 -        int main() {
 -          iconv_t cd;
 -        changequote(, )dnl
 -          char buf[4];
 -        changequote([, ])dnl
 -          char *ob;
 -          size_t obl;
 -          ob = buf, obl = sizeof(buf);
 -          return ((cd = iconv_open("UTF-8", "UTF-8")) != (iconv_t)(-1) &&
 -                 (iconv(cd, 0, 0, &ob, &obl) ||
 -                 !(ob == buf && obl == sizeof(buf)) ||
 -                 iconv_close(cd)));
 -        }
 -      ],
 -      [
 -        ac_iconv_good=yes
 -      ],
 -      [
 -        ac_iconv_good=no
 -      ],
 -      [
 -        ac_iconv_good=yes
 -      ])
 -    )
 -
 -  if test x$ac_iconv_good = xno; then
 -    AC_MSG_RESULT(Try using libiconv instead.)
 -  fi
 -fi
 -
 -# POSIX threads support
 -#
 -AC_MSG_CHECKING(whether to search for POSIX threads)
 -AC_ARG_WITH(pthreads,
 -  [[  --with-pthreads[=DIR]   use POSIX threads [search in DIR/include and DIR/lib]]],
 -  [
 -    case "${withval}" in
 -      no)
 -        check_threads=false
 -        ;;
 -      *)
 -        if test -d $withval/include; then
 -          CPPFLAGS="$CPPFLAGS -I$withval/include"
 -          CFLAGS="$CFLAGS -I$withval/include"
 -        fi
 -        if test -d $withval/lib; then
 -          LDFLAGS="$LDFLAGS -L$withval/lib"
 -        fi
 -
 -        check_threads=true
 -        ;;
 -    esac
 -  ])
 -
 -if test x$check_threads = xtrue; then
 -  has_threads=false
 -  SAVE_LIBS="$LIBS"
 -  SAVE_CFLAGS="$CFLAGS"
 -  SAVE_LDFLAGS="$LDFLAGS"
 -  SAVE_CPPFLAGS="$CPPFLAGS"
 -
 -  AC_MSG_RESULT(yes)
 -  AC_CHECK_HEADERS(pthread.h,
 -    [
 -      LIBS="$LIBS -lpthread"
 -      AC_CHECK_LIB(pthread, pthread_attr_init, has_threads=true,
 -        [
 -          # FreeBSD
 -          case "${target}" in
 -            *-*-freebsd*)
 -              LIBS="$SAVE_LIBS -pthread"
 -              AC_CHECK_LIB(c_r, pthread_attr_init, has_threads=true, LIBS="$SAVE_LIBS")
 -              ;;
 -            *)
 -              LIBS="$SAVE_LIBS"
 -              ;;
 -          esac
 -        ])
 -    ],
 -    [
 -      # search for pthread library..
 -      for dir in `echo "/usr/local /usr/pkg /usr/contrib /usr/pkg/pthreads /usr/local/pthreads"`; do
 -        if test x$has_threads = xfalse; then
 -          AC_MSG_RESULT(searching in $dir...)
 -
 -          if test -d $dir/include; then
 -            CPPFLAGS="$CPPFLAGS -I$dir/include"
 -            CFLAGS="$CFLAGS -I$dir/include"
 -          fi
 -          if test -d $dir/lib; then
 -            LDFLAGS="$LDFLAGS -L$dir/lib"
 -          fi
 -
 -          # XXX
 -          unset ac_cv_header__pthread_h_ ac_cv_header_pthread_h || true
 -
 -          AC_CHECK_HEADERS(pthread.h,
 -            [
 -              LIBS="$LIBS -lpthread"
 -              AC_CHECK_LIB(pthread, pthread_attr_init, has_threads=true,
 -                [
 -                  has_threads=false
 -
 -                  LIBS="$SAVE_LIBS"
 -                  CFLAGS="$SAVE_CFLAGS"
 -                  LDFLAGS="$SAVE_LDFLAGS"
 -                  CPPFLAGS="$SAVE_CPPFLAGS"
 -                ])
 -            ],
 -            [
 -              CFLAGS="$SAVE_CFLAGS"
 -              LDFLAGS="$SAVE_LDFLAGS"
 -              CPPFLAGS="$SAVE_CPPFLAGS"
 -            ])
 -        fi
 -      done
 -    ])
 -else
 -  AC_MSG_RESULT(no)
 -  has_threads=false
 -fi
 -
 -__SILC_HAVE_PTHREAD=""
 -AM_CONDITIONAL(SILC_THREADS, test x$has_threads = xtrue)
 -if test x$has_threads = xtrue; then
 -  CFLAGS="$CFLAGS -D_REENTRANT"
 -
 -  # XXX possibly incomplete
 -  case "${target}" in
 -    *-*-aix*)
 -      CFLAGS="$CFLAGS -D_THREAD_SAFE"
 -      if test x"$GCC" = xyes; then
 -        CFLAGS="$CFLAGS -mthreads"
 -      fi
 -      ;;
 -    *-*-freebsd*)
 -      CFLAGS="$CFLAGS -D_THREAD_SAFE"
 -      ;;
 -    *-*-sysv5uw7*)  # UnixWare 7
 -      if test "$GCC" != "yes"; then
 -        CFLAGS="$CFLAGS -Kthread"
 -      else
 -        CFLAGS="$CFLAGS -pthread"
 -      fi
 -      ;;
 -    *-dg-dgux*)  # DG/UX
 -      CFLAGS="$CFLAGS -D_POSIX4A_DRAFT10_SOURCE"
 -      ;;
 -   esac
 -
 -  # Check for threads
 -  AC_CHECK_FUNC(pthread_create)
 -
 -  # Check for read/write locks
 -  AC_CHECK_FUNC(pthread_rwlock_init,
 -  [
 -    AC_RUN_IFELSE(
 -      [
 -        #include <pthread.h>
 -        int main()
 -        {
 -          pthread_rwlock_t rwlock;
 -          pthread_rwlock_init(&rwlock, NULL);
 -          pthread_rwlock_destroy(&rwlock);
 -          return 0;
 -        }
 -      ],
 -      [],
 -      [
 -      # Rwlock not defined
 -        CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600"
 -      ]
 -    )
 -  ],
 -  [
 -    # Rwlock not defined
 -    CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600"
 -  ])
 -
 -  AC_DEFINE([SILC_HAVE_PTHREAD], [], [HAVE_PTHREAD])
 -  AC_DEFINE([SILC_THREADS], [], [HAVE_THREAD])
 -  __SILC_HAVE_PTHREAD="#define __SILC_HAVE_PTHREAD 1"
 -fi
 -
 -#
 -# Check for timezone and tm_gmtoff for timezone information
 -#
 -AC_MSG_CHECKING(whether system has timezone)
 -AC_RUN_IFELSE(
 -  [
 -    #include <stdio.h>
 -    #include <time.h>
 -    int main()
 -    {
 -      timezone = 0;
 -      return 0;
 -    }
 -  ],
 -  [ AC_MSG_RESULT(yes)
 -    AC_DEFINE([HAVE_TIMEZONE], [], [HAVE_TIMEZONE]) ],
 -  [ AC_MSG_RESULT(no) ],
 -  [ AC_MSG_RESULT(no) ]
 -)
 -AC_MSG_CHECKING(whether system has tm_gmtoff)
 -AC_RUN_IFELSE(
 -  [
 -    #include <stdio.h>
 -    #include <time.h>
 -    int main()
 -    {
 -      struct tm tm;
 -      tm.tm_gmtoff = 0;
 -      return 0;
 -    }
 -  ],
 -  [ AC_MSG_RESULT(yes)
 -    AC_DEFINE([HAVE_TM_GMTOFF], [], [HAVE_TM_GMTOFF]) ],
 -  [ AC_MSG_RESULT(no) ],
 -  [ AC_MSG_RESULT(no) ]
 -)
 -AC_MSG_CHECKING(whether system has __tm_gmtoff)
 -AC_RUN_IFELSE(
 -  [
 -    #include <stdio.h>
 -    #include <time.h>
 -    int main()
 -    {
 -      struct tm tm;
 -      tm.__tm_gmtoff = 0;
 -      return 0;
 -    }
 -  ],
 -  [ AC_MSG_RESULT(yes)
 -    AC_DEFINE([HAVE___TM_GMTOFF], [], [HAVE___TM_GMTOFF]) ],
 -  [ AC_MSG_RESULT(no) ],
 -  [ AC_MSG_RESULT(no) ]
 -)
 -AC_MSG_CHECKING(whether system has __tm_gmtoff__)
 -AC_RUN_IFELSE(
 -  [
 -    #include <stdio.h>
 -    #include <time.h>
 -    int main()
 -    {
 -      struct tm tm;
 -      tm.__tm_gmtoff__ = 0;
 -      return 0;
 -    }
 -  ],
 -  [ AC_MSG_RESULT(yes)
 -    AC_DEFINE([HAVE___TM_GMTOFF__], [], [HAVE___TM_GMTOFF__]) ],
 -  [ AC_MSG_RESULT(no) ],
 -  [ AC_MSG_RESULT(no) ]
 -)
  
 -# Native WIN32 compilation under cygwin
 -#
 +##
 +## Native WIN32 compilation under cygwin
 +##
  AC_MSG_CHECKING(whether to compile native WIN32 code)
  AC_ARG_WITH(win32,
    [  --with-win32            compile native WIN32 (MinGW) code (-mno-cygwin)],
    ])
  AM_CONDITIONAL(SILC_WIN32, test x$win32_support = xtrue)
  
 -# Native Symbian OS support (disabled by default)
 -#
 -AM_CONDITIONAL(SILC_SYMBIAN, test xfalse = xtrue)
 -
 -# Native BeOS support (disabled by default)
 -#
 -AM_CONDITIONAL(SILC_BEOS, test xfalse = xtrue)
 -
 -# Native OS2 support (disabled by default)
 -#
 -AM_CONDITIONAL(SILC_OS2, test xfalse = xtrue)
  
  #ifdef SILC_DIST_SERVER
  without_silcd=false
@@@ -751,49 -1314,62 +753,49 @@@ without_irssi=fals
  without_silcd=false
  #endif SILC_DIST_INPLACE
  
 -libtoolfix=true
 -AC_MSG_CHECKING(whether to do libtoolfix)
 -AC_ARG_WITH(libtoolfix,
 -  [  --without-libtoolfix    Do not fix libtool, for package builders],
 -  [
 -    AC_MSG_RESULT(no)
 -    libtoolfix=false
 -  ],
 -  [
 -    AC_MSG_RESULT(yes)
 -  ])
 -
 -AC_SUBST(ETCDIR)
 -AC_DEFINE_UNQUOTED([SILC_ETCDIR], "$ETCDIR", [SILC_ETCDIR])
 -#endif SILC_DIST_COMPILER
  
  ##
 -##  Misc
 +## Include configure fragments
  ##
 +AD_INCLUDE_CONFIGURE
  
 -# Make enable-shared aware
 -AM_CONDITIONAL(SILC_ENABLE_SHARED, test "$enable_shared" = yes)
 -
 -SILC_TOP_SRCDIR=`pwd`
  
 -# Included configure scripts
 -AD_INCLUDE_CONFIGURE
 +##
 +## Outputs and substitutions
 +##
  
 -#ifdef SILC_DIST_COMPILER
 -#
 -# Substitutions
 -#
  AC_SUBST(LIBSUBDIR)
  AC_SUBST(SILC_TOP_SRCDIR)
  AC_SUBST(LDFLAGS)
  AC_SUBST(LIBS)
  AC_SUBST(SILC_LIB_INCLUDES)
 -AC_SUBST(__SILC_HAVE_PTHREAD)
 -AC_SUBST(__SILC_HAVE_SIM)
 -AC_SUBST(__SILC_ENABLE_DEBUG)
  AC_SUBST(__SILC_PACKAGE_VERSION)
  
 -#
 -# Fix the libtool to support run-time configuration.  This allows us
 -# to in run-time specify when to compile shared/static libraries without
 -# need to reconfigure the entire libtool.
 -#
 -if test x$libtoolfix = xtrue; then
 -  ./libtoolfix $SILC_TOP_SRCDIR/ltmain.sh
 -fi
 -AM_CONDITIONAL(SILC_LIBTOOLFIX, test x$libtoolfix = xtrue)
 +AC_SUBST(ETCDIR)
 +AC_DEFINE_UNQUOTED([SILC_ETCDIR], "$ETCDIR", [SILC_ETCDIR])
 +
 +#ifndef SILC_DIST_AUTODIST
 +ETCDIR=`eval echo $sysconfdir`;ETCDIR=`eval echo $ETCDIR`
 +AC_SUBST(ETCDIR)
 +AC_DEFINE_UNQUOTED([SILC_ETCDIR], "$ETCDIR", [SILC_ETCDIR])
 +
 +DOCDIR=`eval echo $docdir`;DOCDIR=`eval echo $DOCDIR`
 +AC_SUBST(DOCDIR)
 +AC_DEFINE_UNQUOTED([SILC_DOCDIR], "$DOCDIR", [SILC_DOCDIR])
 +#endif SILC_DIST_AUTODIST
 +
 +# Native Symbian OS support (disabled by default)
 +AM_CONDITIONAL(SILC_SYMBIAN, test xfalse = xtrue)
 +
 +# Make enable-shared aware
 +AM_CONDITIONAL(SILC_ENABLE_SHARED, test "$enable_shared" = yes)
  
  INCLUDE_DEFINES_INT="include \$(top_srcdir)/Makefile.defines_int"
  AC_SUBST(INCLUDE_DEFINES_INT)
  
 -#endif SILC_DIST_COMPILER
 +DATE=`date`
 +AC_SUBST(DATE)
 +
  
  #
  # Makefile outputs
@@@ -803,11 -1379,13 +805,11 @@@ Makefil
  #ifdef SILC_DIST_DOC
  doc/Makefile
  #endif SILC_DIST_DOC
 -#ifdef SILC_DIST_COMPILER
  Makefile.defines
  Makefile.defines_int
  includes/Makefile
  includes/silcversion.h
  includes/silc.h
 -#endif SILC_DIST_COMPILER
  #ifdef SILC_DIST_APPS
  apps/Makefile
  #endif SILC_DIST_APPS
@@@ -824,60 -1402,9 +826,51 @@@ tutorial/Makefile.defines_in
  )
  #endif SILC_DIST_TOOLKIT
  
- #ifdef SILC_DIST_HTTP
- AC_CONFIG_FILES(
- lib/silchttp/Makefile
- #ifdef SILC_DIST_INPLACE
- lib/silchttp/tests/Makefile
- #endif SILC_DIST_INPLACE
- )
- #endif SILC_DIST_HTTP
 +if test x$compile_libs = xtrue; then
 +
 +AC_CONFIG_FILES(
 +lib/Makefile
 +lib/silccore/Makefile
 +lib/silcske/Makefile
 +lib/silcapputil/Makefile
 +#ifdef SILC_DIST_SFTP
 +lib/silcsftp/Makefile
 +lib/silcsftp/tests/Makefile
 +#endif SILC_DIST_SFTP
 +)
 +
 +#ifdef SILC_DIST_TOOLKIT
 +AC_CONFIG_FILES(
 +lib/silc.pc
 +lib/silcclient.pc
 +lib/silcserver.pc
 +)
 +#endif SILC_DIST_TOOLKIT
 +
 +#ifdef SILC_DIST_CLIENTLIB
 +AC_CONFIG_FILES(
 +lib/silcclient/Makefile
 +lib/silcclient/tests/Makefile
 +)
 +#endif SILC_DIST_CLIENTLIB
 +
 +#ifdef SILC_DIST_SERVERLIB
 +AC_CONFIG_FILES(
 +lib/silcserver/Makefile
 +lib/silcserver/tests/Makefile
 +)
 +#endif SILC_DIST_SERVERLIB
 +
 +#ifdef SILC_DIST_VCARD
 +AC_CONFIG_FILES(
 +lib/silcvcard/Makefile
 +)
 +#endif SILC_DIST_VCARD
 +
 +fi    # compile_libs
 +
  AC_OUTPUT
  
 -#ifdef SILC_DIST_COMPILER
  s_bindir=`eval echo $bindir`;s_bindir=`eval echo $s_bindir`
  s_sbindir=`eval echo $sbindir`;s_sbindir=`eval echo $s_sbindir`
  s_mandir=`eval echo $mandir`;s_mandir=`eval echo $s_mandir`
@@@ -898,6 -1425,9 +891,6 @@@ echo " sbin directory ................
  echo " etc directory .................: $ETCDIR"
  echo " man directory .................: $s_mandir"
  echo " doc directory .................: $DOCDIR"
 -#ifdef SILC_DIST_SIM
 -echo " SIM directory .................: $MODULESDIR"
 -#endif SILC_DIST_SIM
  #ifdef SILC_DIST_INCLUDES
  echo " include directory .............: $s_includedir"
  #endif SILC_DIST_INCLUDES
  echo " Compile SILC Server ...........: $silcd"
  #endif SILC_DIST_SERVER
  
 -#ifdef SILC_DIST_SIM
 -if test x$sim_support = xfalse; then
 -  sim_support="no"
 -else
 -  sim_support="yes"
 -fi
 -echo " SIM support ...................: $sim_support"
 -#endif SILC_DIST_SIM
 -
 -echo " IPv6 support ..................: $summary_ipv6"
 -
 -if test x$has_iconv = xfalse; then
 -  iconv_support="no"
 -else
 -  iconv_support="yes"
 -fi
 -echo " Iconv support .................: $iconv_support"
 -
 -if test x$want_asm = xfalse; then
 -  summary_asm="no"
 -else
 -  summary_asm="yes"
 -fi
 -echo " Assembler optimizations .......: $summary_asm"
 -
 -#ifdef SILC_DIST_MATH
 -if test x$mp_gmp = xtrue; then
 -  echo " Arithmetic library ............: GMP"
 -fi
 -#endif SILC_DIST_MATH
 -
 -threads="no"
 -if test x$has_threads = xtrue; then
 -  threads="yes"
 -fi
 -echo " Multi-threads support .........: $threads"
  echo " Debugging enabled .............: $summary_debug"
  echo ""
  echo "Compile the sources with 'make' or 'gmake' command."
 -#endif SILC_DIST_COMPILER
diff --combined distdir/server
index 4734b305562c8373c48a1d6c33f2b2b8f4389b5f,793321e18a9c564a64d85e1dfd7a7b6abc064119..a35f758731bfc16ebf9c565da11763c0756d7f47
@@@ -4,10 -4,10 +4,9 @@@ bug-report silc-devel@lists.silcnet.or
  
  inherit common
  define SILC_DIST_SERVER
- #define SILC_DIST_SERVERLIB
--define SILC_DIST_HTTP
  undef SILC_DIST_SFTP
  undef SILC_DIST_VCARD
  
+ pre-dist-hook distdir/pre-dist-server
  post-process-dist-hook distdir/post-process-dist
  post-dist-hook distdir/post-dist
diff --combined distdir/toolkit
index ddbb2732082757d3af3dc39ba7775fbe31dccc19,9d32fc2980d9d1108b7cfa6f7fee4ceb34acd9ec..cb054865e255032ba03d8fd1ad4074f30a9a72dc
@@@ -15,7 -15,8 +15,6 @@@ license-header distdir/GPL-header distd
  # Distdefs
  define SILC_DIST_TOOLKIT
  define SILC_DIST_CLIENTLIB
--define SILC_DIST_HTTP
 -define SILC_DIST_SIM
  
  # Includes
  include README.CVS
diff --combined lib/Makefile.ad
index df5d76eb991692d00c531fe35bae40d7f6d1fafd,df6fa0a530dfe4d68d04638383dbf5a42ccfc012..9312320c993b48e7c9f6d1c037212257b45f269f
@@@ -3,7 -3,7 +3,7 @@@
  #
  #  Author: Pekka Riikonen <priikone@silcnet.org>
  #
 -#  Copyright (C) 2000 - 2005, 2007 Pekka Riikonen
 +#  Copyright (C) 2000 - 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
@@@ -19,12 -19,29 +19,9 @@@ AUTOMAKE_OPTIONS = 1.0 no-dependencies 
  
  # SILC Library dirs
  SILCLIB_DIRS =                \
 -      contrib         \
        silccore        \
 -      silcutil        \
        silcapputil     \
 -#ifdef SILC_DIST_CRYPTO
 -      silccrypt       \
 -#endif SILC_DIST_CRYPTO
 -#ifdef SILC_DIST_SKR
 -      silcskr         \
 -#endif SILC_DIST_SKR
 -#ifdef SILC_DIST_MATH
 -      silcmath        \
 -#endif SILC_DIST_MATH
 -#ifdef SILC_DIST_SIM
 -      silcsim         \
 -#endif SILC_DIST_SIM
 -#ifdef SILC_DIST_ASN1
 -      silcasn1        \
 -#endif SILC_DIST_ASN1
        silcske         \
--#ifdef SILC_DIST_HTTP
--      silchttp        \
--#endif SILC_DIST_HTTP
  #ifdef SILC_DIST_SFTP
        silcsftp        \
  #endif SILC_DIST_SFTP
index d189e9321ee8568cab41ec777d86d324de3946f9,831970d5dd940e3b298795f8863e2fbbe91b396a..f549b770b4a3a007efb24e3a02a1af4c090eb6e5
@@@ -4,7 -4,7 +4,7 @@@
  
    Author: Pekka Riikonen <priikone@silcnet.org>
  
--  Copyright (C) 2000 - 2007 Pekka Riikonen
++  Copyright (C) 2000 - 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
@@@ -78,15 -78,15 +78,15 @@@ SilcIDCache silc_idcache_alloc(SilcUInt
    if (!cache)
      return NULL;
  
 -  cache->id_table = silc_hash_table_alloc(count, silc_hash_id,
 +  cache->id_table = silc_hash_table_alloc(NULL, count, silc_hash_id,
                                          SILC_32_TO_PTR(id_type),
                                          silc_hash_id_compare,
                                          SILC_32_TO_PTR(id_type),
                                          NULL, NULL, TRUE);
 -  cache->name_table = silc_hash_table_alloc(count, silc_hash_utf8_string, NULL,
 -                                          silc_hash_utf8_compare, NULL,
 +  cache->name_table = silc_hash_table_alloc(NULL, count, silc_hash_utf8_string,
 +                                          NULL, silc_hash_utf8_compare, NULL,
                                            NULL, NULL, TRUE);
 -  cache->context_table = silc_hash_table_alloc(count, silc_hash_ptr, NULL,
 +  cache->context_table = silc_hash_table_alloc(NULL, count, silc_hash_ptr, NULL,
                                               NULL, NULL, NULL, NULL, TRUE);
    cache->destructor = destructor;
    cache->context = destructor_context;
@@@ -142,9 -142,8 +142,8 @@@ silc_idcache_add(SilcIDCache cache, cha
    if (id) {
      /* See if this entry is added already to cache */
      if (silc_idcache_find_by_id_one(cache, id, NULL)) {
-       SILC_LOG_ERROR(("Attempted to add same ID twice to ID Cache, id %s",
+       SILC_LOG_DEBUG(("Attempted to add same ID twice to ID Cache, id %s",
                      silc_id_render(id, cache->id_type)));
-       SILC_ASSERT(FALSE);
        goto err;
      }
    }
diff --combined lib/silcclient/client.c
index fa139d2e31461155f6507c5e2982ed61de42a4f6,3ab7ba17b4aa96fc872496dce38c17ae078227d7..449fc375ce152b33bca4e0c3bbd06ce53870766d
@@@ -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,6 -16,7 +16,6 @@@
    GNU General Public License for more details.
  
  */
 -/* $Id$ */
  
  #include "silc.h"
  #include "silcclient.h"
@@@ -54,7 -55,7 +54,7 @@@ static void silc_client_connection_fini
    SilcClient client = silc_fsm_get_state_context(fsm);
  
    /* Signal client that we have finished */
-   silc_atomic_sub_int16(&client->internal->conns, 1);
+   silc_atomic_sub_int32(&client->internal->conns, 1);
    client->internal->connection_closed = TRUE;
    SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
  
@@@ -148,15 -149,7 +148,15 @@@ static void silc_client_packet_error(Si
                                     void *callback_context,
                                     void *stream_context)
  {
 -  /* Nothing */
 +  SilcClient client = callback_context;
 +  SilcClientConnection conn = stream_context;
 +
 +  /* Read and write errors are silent */
 +  if (error == SILC_PACKET_ERR_READ || error == SILC_PACKET_ERR_WRITE)
 +    return;
 +
 +  client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
 +                           (char *)silc_packet_error_string(error));
  }
  
  /* Packet stream callbacks */
@@@ -536,7 -529,7 +536,7 @@@ SILC_FSM_STATE(silc_client_st_run
      /* A connection finished */
      SILC_LOG_DEBUG(("Event: connection closed"));
      client->internal->connection_closed = FALSE;
-     if (silc_atomic_get_int16(&client->internal->conns) == 0 &&
+     if (silc_atomic_get_int32(&client->internal->conns) == 0 &&
        client->internal->stop)
        SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
      return SILC_FSM_CONTINUE;
    if (client->internal->stop) {
      /* Stop client libarry.  If we have running connections, wait until
         they finish first. */
-     if (silc_atomic_get_int16(&client->internal->conns) == 0) {
+     if (silc_atomic_get_int32(&client->internal->conns) == 0) {
        SILC_LOG_DEBUG(("Event: stop"));
        silc_fsm_next(fsm, silc_client_st_stop);
      }
@@@ -681,7 -674,7 +681,7 @@@ silc_client_add_connection(SilcClient c
    silc_fsm_start(thread, silc_client_connection_st_start);
  
    SILC_LOG_DEBUG(("New connection %p", conn));
-   silc_atomic_add_int16(&client->internal->conns, 1);
+   silc_atomic_add_int32(&client->internal->conns, 1);
  
    return conn;
  }
@@@ -945,7 -938,7 +945,7 @@@ SilcClient silc_client_alloc(SilcClient
      nickname_format[sizeof(new_client->internal->
                           params->nickname_format) - 1] = 0;
  
-   silc_atomic_init16(&new_client->internal->conns, 0);
+   silc_atomic_init32(&new_client->internal->conns, 0);
  
    return new_client;
  }
  
  void silc_client_free(SilcClient client)
  {
-   silc_schedule_uninit(client->schedule);
+   if (client->schedule)
+     silc_schedule_uninit(client->schedule);
  
    if (client->rng)
      silc_rng_free(client->rng);
  
 -  if (!client->internal->params->dont_register_crypto_library) {
 -    silc_cipher_unregister_all();
 -    silc_pkcs_unregister_all();
 -    silc_hash_unregister_all();
 -    silc_hmac_unregister_all();
 -  }
 +  if (!client->internal->params->dont_register_crypto_library)
 +    silc_crypto_uninit();
  
-   silc_packet_engine_stop(client->internal->packet_engine);
-   silc_dlist_uninit(client->internal->ftp_sessions);
-   silc_atomic_uninit16(&client->internal->conns);
-   silc_mutex_free(client->internal->lock);
+   if (client->internal->packet_engine)
+     silc_packet_engine_stop(client->internal->packet_engine);
+   if (client->internal->ftp_sessions)
+     silc_dlist_uninit(client->internal->ftp_sessions);
+   if (client->internal->lock)
+     silc_mutex_free(client->internal->lock);
+   silc_atomic_uninit32(&client->internal->conns);
    silc_free(client->username);
    silc_free(client->hostname);
    silc_free(client->realname);
@@@ -1026,10 -1027,15 +1030,10 @@@ SilcBool silc_client_init(SilcClient cl
    if (!client->internal->ftp_sessions)
      return FALSE;
  
 -  if (!client->internal->params->dont_register_crypto_library) {
 +  if (!client->internal->params->dont_register_crypto_library)
      /* Initialize the crypto library.  If application has done this already
 -       this has no effect.  Also, we will not be overriding something
 -       application might have registered earlier. */
 -    silc_cipher_register_default();
 -    silc_pkcs_register_default();
 -    silc_hash_register_default();
 -    silc_hmac_register_default();
 -  }
 +       this has no effect. */
 +    silc_crypto_init(NULL);
  
    /* Initialize random number generator */
    client->rng = silc_rng_alloc();
    silc_rng_global_init(client->rng);
  
    /* Initialize the scheduler */
 -  client->schedule = silc_schedule_init(0, client);
 +  client->schedule = silc_schedule_init(0, client, NULL, NULL);
    if (!client->schedule)
      return FALSE;
  
index 2075d8073b0c6230c6e605b6d7a1aebd08430e17,4120695d76af08286853fa5fc5bdf31f0f767220..7dd4f0a6ad59a23572262fb48970de4decda3616
  
  /************************** Channel Message Send ****************************/
  
 +typedef struct {
 +  SilcClient client;
 +  SilcClientConnection conn;
 +  SilcChannelEntry channel;
 +} *SilcClientChannelMessageContext;
 +
 +/* Message payload encoding callback */
 +
 +static void silc_client_send_channel_message_final(SilcBuffer message,
 +                                                 void *context)
 +{
 +  SilcClientChannelMessageContext c = context;
 +
 +  /* Send the channel message */
 +  if (message)
 +    silc_packet_send_ext(c->conn->stream, SILC_PACKET_CHANNEL_MESSAGE, 0,
 +                       0, NULL, SILC_ID_CHANNEL, &c->channel->id,
 +                       silc_buffer_datalen(message), NULL, NULL);
 +
 +  silc_client_unref_channel(c->client, c->conn, c->channel);
 +  silc_free(c);
 +}
 +
  /* Sends channel message to `channel'. */
  
  SilcBool silc_client_send_channel_message(SilcClient client,
                                          unsigned char *data,
                                          SilcUInt32 data_len)
  {
 +  SilcClientChannelMessageContext c;
    SilcChannelUser chu;
 -  SilcBuffer buffer;
    SilcCipher cipher;
    SilcHmac hmac;
 -  SilcBool ret;
    SilcID sid, rid;
  
    SILC_LOG_DEBUG(("Sending channel message"));
  
    if (silc_unlikely(!client || !conn || !channel))
      return FALSE;
 -  if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash))
 +  if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash)) {
 +    SILC_LOG_ERROR(("Cannot send signed message without hash, missing "
 +                  "arguments"));
      return FALSE;
 +  }
    if (silc_unlikely(conn->internal->disconnected))
      return FALSE;
  
      return FALSE;
    }
  
 -  /* Encode the message payload. This also encrypts the message payload. */
 +  c = silc_calloc(1, sizeof(*c));
 +  if (!c)
 +    return FALSE;
 +
 +  c->client = client;
 +  c->conn = conn;
 +  c->channel = silc_client_ref_channel(client, conn, channel);
 +
    sid.type = SILC_ID_CLIENT;
    sid.u.client_id = chu->client->id;
    rid.type = SILC_ID_CHANNEL;
    rid.u.channel_id = chu->channel->id;
 -  buffer = silc_message_payload_encode(flags, data, data_len, TRUE, FALSE,
 -                                     cipher, hmac, client->rng, NULL,
 -                                     conn->private_key, hash, &sid, &rid,
 -                                     NULL);
 -  if (silc_unlikely(!buffer)) {
 -    SILC_LOG_ERROR(("Error encoding channel message"));
 -    return FALSE;
 -  }
  
 -  /* Send the channel message */
 -  ret = silc_packet_send_ext(conn->stream, SILC_PACKET_CHANNEL_MESSAGE, 0,
 -                           0, NULL, SILC_ID_CHANNEL, &channel->id,
 -                           silc_buffer_datalen(buffer), NULL, NULL);
 +  /* Encode the message payload. This also encrypts the message payload. */
 +  silc_message_payload_encode(flags, data, data_len, TRUE, FALSE,
 +                            cipher, hmac, client->rng, NULL,
 +                            conn->private_key, hash, &sid, &rid, NULL,
 +                            silc_client_send_channel_message_final, c);
  
 -  silc_buffer_free(buffer);
 -  return ret;
 +  return TRUE;
  }
  
  /************************* Channel Message Receive **************************/
@@@ -650,8 -626,14 +650,14 @@@ SilcBool silc_client_del_channel_privat
    }
  
    channel->internal.curr_key = NULL;
-   channel->cipher = silc_cipher_get_name(channel->internal.send_key);
-   channel->hmac = silc_hmac_get_name(channel->internal.hmac);
+   if (channel->internal.send_key)
+     channel->cipher = silc_cipher_get_name(channel->internal.send_key);
+   else
+     channel->cipher = NULL;
+   if (channel->internal.hmac)
+     channel->hmac = silc_hmac_get_name(channel->internal.hmac);
+   else
+     channel->hmac = NULL;
  
    silc_dlist_uninit(channel->internal.private_keys);
    channel->internal.private_keys = NULL;
index 32f272ec189b8fdff80cd6593cd9e72c3675b58c,4664dbaa75f770446b457b8b7d830b67cab2d524..017f8f8a7aebed168f14779bff0149df5d0b944b
@@@ -85,8 -85,13 +85,8 @@@ SilcDList silc_client_get_clients_local
    if (!silc_client_nickname_parse(client, conn, (char *)nick, &parsed))
      return NULL;
  
 -  if (!get_all && parsed)
 +  if (!get_all)
      format = (char *)nick;
 -  if (!parsed) {
 -    parsed = silc_memdup(nick, strlen(nick));
 -    if (!parsed)
 -      return NULL;
 -  }
  
    SILC_LOG_DEBUG(("Find clients by nickname %s", parsed));
  
    }
    silc_list_start(list);
  
 -  if (!format && get_all) {
 +  if (get_all) {
      /* Take all without any further checking */
      while ((id_cache = silc_list_get(list))) {
        entry = id_cache->context;
@@@ -512,6 -517,7 +512,6 @@@ SilcUInt16 silc_client_get_clients_by_l
    SilcUInt32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0;
    SilcUInt16 idp_len, cmd_ident;
    SilcID id;
 -  va_list tmp;
    int i;
  
    SILC_LOG_DEBUG(("Resolve clients from Client ID list"));
  
    /* We have the clients in cache, get them and call the completion */
    silc_client_get_clients_list_cb(client, conn, SILC_COMMAND_WHOIS,
 -                                SILC_STATUS_OK, SILC_STATUS_OK, in, tmp);
 +                                SILC_STATUS_OK, SILC_STATUS_OK, in, NULL);
    return 0;
  
   err:
@@@ -785,7 -791,8 +785,8 @@@ SilcClientEntry silc_client_add_client(
      return NULL;
  
    silc_rwlock_alloc(&client_entry->internal.lock);
-   silc_atomic_init16(&client_entry->internal.refcnt, 0);
+   silc_atomic_init32(&client_entry->internal.refcnt, 0);
+   silc_atomic_init32(&client_entry->internal.deleted, 1);
    client_entry->id = *id;
    client_entry->mode = mode;
    client_entry->realname = userinfo ? strdup(userinfo) : NULL;
                      client_entry->hostname,
                      sizeof(client_entry->hostname));
  
 -  client_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, NULL, NULL,
 -                                               NULL, NULL, NULL, TRUE);
 +  client_entry->channels = silc_hash_table_alloc(NULL, 1, silc_hash_ptr, NULL,
 +                                               NULL, NULL, NULL, NULL, TRUE);
    if (!client_entry->channels) {
      silc_free(client_entry->realname);
      silc_free(client_entry);
@@@ -989,7 -996,8 +990,8 @@@ void silc_client_del_client_entry(SilcC
    silc_client_ftp_session_free_client(client, client_entry);
    if (client_entry->internal.ke)
      silc_client_abort_key_agreement(client, conn, client_entry);
-   silc_atomic_uninit16(&client_entry->internal.refcnt);
+   silc_atomic_uninit32(&client_entry->internal.deleted);
+   silc_atomic_uninit32(&client_entry->internal.refcnt);
    silc_rwlock_free(client_entry->internal.lock);
    silc_free(client_entry);
  }
  SilcBool silc_client_del_client(SilcClient client, SilcClientConnection conn,
                                SilcClientEntry client_entry)
  {
-   SilcBool ret;
    if (!client_entry)
      return FALSE;
  
-   if (silc_atomic_sub_int16(&client_entry->internal.refcnt, 1) > 0)
-     return FALSE;
-   SILC_LOG_DEBUG(("Deleting client %p", client_entry));
-   silc_mutex_lock(conn->internal->lock);
-   ret = silc_idcache_del_by_context(conn->internal->client_cache,
-                                   client_entry, NULL);
-   silc_mutex_unlock(conn->internal->lock);
+   SILC_LOG_DEBUG(("Marking client entry %p deleted"));
  
-   if (ret) {
-     /* Remove from channels */
-     silc_client_remove_from_channels(client, conn, client_entry);
-     /* Free the client entry data */
-     silc_client_del_client_entry(client, conn, client_entry);
+   if (silc_atomic_sub_int32(&client_entry->internal.deleted, 1) != 0) {
+     SILC_LOG_DEBUG(("Client entry %p already marked deleted"));
+     return FALSE;
    }
  
-   return ret;
+   silc_client_unref_client(client, conn, client_entry);
+   return TRUE;
  }
  
  /* Internal routine used to find client by ID and if not found this creates
@@@ -1066,10 -1062,10 +1056,10 @@@ SilcClientEntry silc_client_ref_client(
                                       SilcClientConnection conn,
                                       SilcClientEntry client_entry)
  {
-   silc_atomic_add_int16(&client_entry->internal.refcnt, 1);
+   silc_atomic_add_int32(&client_entry->internal.refcnt, 1);
    SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
-                 silc_atomic_get_int16(&client_entry->internal.refcnt) - 1,
-                 silc_atomic_get_int16(&client_entry->internal.refcnt)));
+                 silc_atomic_get_int32(&client_entry->internal.refcnt) - 1,
+                 silc_atomic_get_int32(&client_entry->internal.refcnt)));
    return client_entry;
  }
  
  void silc_client_unref_client(SilcClient client, SilcClientConnection conn,
                              SilcClientEntry client_entry)
  {
-   if (client_entry) {
-     SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
-                   silc_atomic_get_int16(&client_entry->internal.refcnt),
-                   silc_atomic_get_int16(&client_entry->internal.refcnt) - 1));
-     silc_client_del_client(client, conn, client_entry);
+   SilcBool ret;
+   if (!client_entry)
+     return;
+   SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
+                 silc_atomic_get_int32(&client_entry->internal.refcnt),
+                 silc_atomic_get_int32(&client_entry->internal.refcnt) - 1));
+   if (silc_atomic_sub_int32(&client_entry->internal.refcnt, 1) > 0)
+     return;
+   SILC_LOG_DEBUG(("Deleting client %p (%d)", client_entry,
+                 silc_atomic_get_int32(&client_entry->internal.deleted)));
+   silc_mutex_lock(conn->internal->lock);
+   ret = silc_idcache_del_by_context(conn->internal->client_cache,
+                                   client_entry, NULL);
+   silc_mutex_unlock(conn->internal->lock);
+   if (ret) {
+     /* Remove from channels */
+     silc_client_remove_from_channels(client, conn, client_entry);
+     /* Free the client entry data */
+     silc_client_del_client_entry(client, conn, client_entry);
    }
  }
  
@@@ -1275,6 -1292,7 +1286,7 @@@ SilcClientEntry silc_client_nickname_fo
    }
  
    newnick[off] = 0;
+   memset(client_entry->nickname, 0, sizeof(client_entry->nickname));
    memcpy(client_entry->nickname, newnick, strlen(newnick));
    silc_client_list_free(client, conn, clients);
  
@@@ -1293,7 -1311,7 +1305,7 @@@ SilcBool silc_client_nickname_parse(Sil
    int len;
  
    if (!client->internal->params->nickname_format[0]) {
 -    *ret_nick = NULL;
 +    *ret_nick = silc_strdup(nickname);
      return TRUE;
    }
  
@@@ -1619,7 -1637,8 +1631,8 @@@ SilcChannelEntry silc_client_add_channe
      return NULL;
  
    silc_rwlock_alloc(&channel->internal.lock);
-   silc_atomic_init16(&channel->internal.refcnt, 0);
+   silc_atomic_init32(&channel->internal.refcnt, 0);
+   silc_atomic_init32(&channel->internal.deleted, 1);
    channel->id = *channel_id;
    channel->mode = mode;
  
  
    if (!channel->channel_name) {
      silc_rwlock_free(channel->internal.lock);
-     silc_atomic_uninit16(&channel->internal.refcnt);
+     silc_atomic_uninit32(&channel->internal.refcnt);
      silc_free(channel);
      return NULL;
    }
  
 -  channel->user_list = silc_hash_table_alloc(1, silc_hash_ptr, NULL, NULL,
 +  channel->user_list = silc_hash_table_alloc(NULL, 1, silc_hash_ptr, NULL, NULL,
                                             NULL, NULL, NULL, TRUE);
    if (!channel->user_list) {
      silc_rwlock_free(channel->internal.lock);
-     silc_atomic_uninit16(&channel->internal.refcnt);
+     silc_atomic_uninit32(&channel->internal.refcnt);
      silc_free(channel->channel_name);
      silc_free(channel);
      return NULL;
                                          SILC_STRING_UTF8, 256, NULL);
    if (!channel_namec) {
      silc_rwlock_free(channel->internal.lock);
-     silc_atomic_uninit16(&channel->internal.refcnt);
+     silc_atomic_uninit32(&channel->internal.refcnt);
      silc_free(channel->channel_name);
      silc_hash_table_free(channel->user_list);
      silc_free(channel);
    if (!silc_idcache_add(conn->internal->channel_cache, channel_namec,
                        &channel->id, channel)) {
      silc_rwlock_free(channel->internal.lock);
-     silc_atomic_uninit16(&channel->internal.refcnt);
+     silc_atomic_uninit32(&channel->internal.refcnt);
      silc_free(channel_namec);
      silc_free(channel->channel_name);
      silc_hash_table_free(channel->user_list);
  SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn,
                                 SilcChannelEntry channel)
  {
-   SilcIDCacheEntry id_cache;
-   SilcBool ret = TRUE;
-   SilcCipher key;
-   SilcHmac hmac;
-   char *namec;
 +
    if (!channel)
      return FALSE;
  
-   if (silc_atomic_sub_int16(&channel->internal.refcnt, 1) > 0)
-     return FALSE;
-   SILC_LOG_DEBUG(("Deleting channel %p", channel));
+   SILC_LOG_DEBUG(("Marking channel entry %p deleted"));
  
-   silc_mutex_lock(conn->internal->lock);
-   if (silc_idcache_find_by_context(conn->internal->channel_cache, channel,
-                                  &id_cache)) {
-     namec = id_cache->name;
-     ret = silc_idcache_del_by_context(conn->internal->channel_cache,
-                                     channel, NULL);
-     silc_free(namec);
-   }
-   silc_mutex_unlock(conn->internal->lock);
 +
-   if (!ret)
+   if (silc_atomic_sub_int32(&channel->internal.deleted, 1) != 0) {
+     SILC_LOG_DEBUG(("Channel entry %p already marked deleted"));
      return FALSE;
-   silc_client_empty_channel(client, conn, channel);
 +  silc_client_del_channel_private_keys(client, conn, channel);
-   silc_hash_table_free(channel->user_list);
-   silc_free(channel->channel_name);
-   silc_free(channel->topic);
-   if (channel->founder_key)
-     silc_pkcs_public_key_free(channel->founder_key);
-   if (channel->internal.send_key)
-     silc_cipher_free(channel->internal.send_key);
-   if (channel->internal.receive_key)
-     silc_cipher_free(channel->internal.receive_key);
-   if (channel->internal.hmac)
-     silc_hmac_free(channel->internal.hmac);
-   if (channel->internal.old_channel_keys) {
-     silc_dlist_start(channel->internal.old_channel_keys);
-     while ((key = silc_dlist_get(channel->internal.old_channel_keys)))
-       silc_cipher_free(key);
-     silc_dlist_uninit(channel->internal.old_channel_keys);
    }
-   if (channel->internal.old_hmacs) {
-     silc_dlist_start(channel->internal.old_hmacs);
-     while ((hmac = silc_dlist_get(channel->internal.old_hmacs)))
-       silc_hmac_free(hmac);
-     silc_dlist_uninit(channel->internal.old_hmacs);
-   }
-   if (channel->channel_pubkeys)
-     silc_argument_list_free(channel->channel_pubkeys,
-                           SILC_ARGUMENT_PUBLIC_KEY);
-   silc_atomic_uninit16(&channel->internal.refcnt);
-   silc_rwlock_free(channel->internal.lock);
-   silc_schedule_task_del_by_context(conn->client->schedule, channel);
-   silc_free(channel);
  
-   return ret;
+   silc_client_unref_channel(client, conn, channel);
+   return TRUE;
  }
  
  /* Replaces the channel ID of the `channel' to `new_id'. Returns FALSE
@@@ -1799,10 -1769,10 +1766,10 @@@ SilcChannelEntry silc_client_ref_channe
                                         SilcClientConnection conn,
                                         SilcChannelEntry channel_entry)
  {
-   silc_atomic_add_int16(&channel_entry->internal.refcnt, 1);
+   silc_atomic_add_int32(&channel_entry->internal.refcnt, 1);
    SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry,
-                 silc_atomic_get_int16(&channel_entry->internal.refcnt) - 1,
-                 silc_atomic_get_int16(&channel_entry->internal.refcnt)));
+                 silc_atomic_get_int32(&channel_entry->internal.refcnt) - 1,
+                 silc_atomic_get_int32(&channel_entry->internal.refcnt)));
    return channel_entry;
  }
  
  void silc_client_unref_channel(SilcClient client, SilcClientConnection conn,
                               SilcChannelEntry channel_entry)
  {
-   if (channel_entry) {
-     SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry,
-                   silc_atomic_get_int16(&channel_entry->internal.refcnt),
-                   silc_atomic_get_int16(&channel_entry->internal.refcnt)
-                   - 1));
-     silc_client_del_channel(client, conn, channel_entry);
+   SilcIDCacheEntry id_cache;
+   SilcBool ret = TRUE;
+   SilcCipher key;
+   SilcHmac hmac;
+   char *namec;
+   if (!channel_entry)
+     return;
+   SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry,
+                 silc_atomic_get_int32(&channel_entry->internal.refcnt),
+                 silc_atomic_get_int32(&channel_entry->internal.refcnt)
+                 - 1));
+   if (silc_atomic_sub_int32(&channel_entry->internal.refcnt, 1) > 0)
+     return;
+   SILC_LOG_DEBUG(("Deleting channel %p", channel_entry));
+   silc_mutex_lock(conn->internal->lock);
+   if (silc_idcache_find_by_context(conn->internal->channel_cache, channel_entry,
+                                  &id_cache)) {
+     namec = id_cache->name;
+     ret = silc_idcache_del_by_context(conn->internal->channel_cache,
+                                     channel_entry, NULL);
+     silc_free(namec);
    }
+   silc_mutex_unlock(conn->internal->lock);
+   if (!ret)
+     return;
+   silc_client_empty_channel(client, conn, channel_entry);
+   silc_client_del_channel_private_keys(client, conn, channel_entry);
+   silc_hash_table_free(channel_entry->user_list);
+   silc_free(channel_entry->channel_name);
+   silc_free(channel_entry->topic);
+   if (channel_entry->founder_key)
+     silc_pkcs_public_key_free(channel_entry->founder_key);
+   if (channel_entry->internal.send_key)
+     silc_cipher_free(channel_entry->internal.send_key);
+   if (channel_entry->internal.receive_key)
+     silc_cipher_free(channel_entry->internal.receive_key);
+   if (channel_entry->internal.hmac)
+     silc_hmac_free(channel_entry->internal.hmac);
+   if (channel_entry->internal.old_channel_keys) {
+     silc_dlist_start(channel_entry->internal.old_channel_keys);
+     while ((key = silc_dlist_get(channel_entry->internal.old_channel_keys)))
+       silc_cipher_free(key);
+     silc_dlist_uninit(channel_entry->internal.old_channel_keys);
+   }
+   if (channel_entry->internal.old_hmacs) {
+     silc_dlist_start(channel_entry->internal.old_hmacs);
+     while ((hmac = silc_dlist_get(channel_entry->internal.old_hmacs)))
+       silc_hmac_free(hmac);
+     silc_dlist_uninit(channel_entry->internal.old_hmacs);
+   }
+   if (channel_entry->channel_pubkeys)
+     silc_argument_list_free(channel_entry->channel_pubkeys,
+                           SILC_ARGUMENT_PUBLIC_KEY);
+   silc_atomic_uninit32(&channel_entry->internal.deleted);
+   silc_atomic_uninit32(&channel_entry->internal.refcnt);
+   silc_rwlock_free(channel_entry->internal.lock);
+   silc_schedule_task_del_by_context(conn->client->schedule, channel_entry);
+   silc_free(channel_entry);
  }
  
  /* Free channel entry list */
@@@ -2052,7 -2080,7 +2077,7 @@@ SilcServerEntry silc_client_add_server(
      return NULL;
  
    silc_rwlock_alloc(&server_entry->internal.lock);
-   silc_atomic_init8(&server_entry->internal.refcnt, 0);
+   silc_atomic_init32(&server_entry->internal.refcnt, 0);
    server_entry->id = *server_id;
    if (server_name)
      server_entry->server_name = strdup(server_name);
@@@ -2104,7 -2132,7 +2129,7 @@@ SilcBool silc_client_del_server(SilcCli
    if (!server)
      return FALSE;
  
-   if (silc_atomic_sub_int8(&server->internal.refcnt, 1) > 0)
+   if (silc_atomic_sub_int32(&server->internal.refcnt, 1) > 0)
      return FALSE;
  
    SILC_LOG_DEBUG(("Deleting server %p", server));
    silc_free(server->server_info);
    if (server->public_key)
      silc_pkcs_public_key_free(server->public_key);
-   silc_atomic_uninit8(&server->internal.refcnt);
+   silc_atomic_uninit32(&server->internal.refcnt);
    silc_rwlock_free(server->internal.lock);
    silc_free(server);
  
@@@ -2191,10 -2219,10 +2216,10 @@@ SilcServerEntry silc_client_ref_server(
                                       SilcClientConnection conn,
                                       SilcServerEntry server_entry)
  {
-   silc_atomic_add_int8(&server_entry->internal.refcnt, 1);
+   silc_atomic_add_int32(&server_entry->internal.refcnt, 1);
    SILC_LOG_DEBUG(("Server %p refcnt %d->%d", server_entry,
-                 silc_atomic_get_int8(&server_entry->internal.refcnt) - 1,
-                 silc_atomic_get_int8(&server_entry->internal.refcnt)));
+                 silc_atomic_get_int32(&server_entry->internal.refcnt) - 1,
+                 silc_atomic_get_int32(&server_entry->internal.refcnt)));
    return server_entry;
  }
  
@@@ -2205,8 -2233,8 +2230,8 @@@ void silc_client_unref_server(SilcClien
  {
    if (server_entry) {
      SILC_LOG_DEBUG(("Server %p refcnt %d->%d", server_entry,
-                   silc_atomic_get_int8(&server_entry->internal.refcnt),
-                   silc_atomic_get_int8(&server_entry->internal.refcnt)
+                   silc_atomic_get_int32(&server_entry->internal.refcnt),
+                   silc_atomic_get_int32(&server_entry->internal.refcnt)
                    - 1));
      silc_client_del_server(client, conn, server_entry);
    }
index fd04fa3b0749477f60bd11dd8f2841806c33e651,54582e20e3af80fb0b1143397209fb85c8dc5f63..a297182024c827335a6caf89aa4e7ac4de015e22
@@@ -108,7 -108,7 +108,7 @@@ struct SilcClientInternalStruct 
    char *silc_client_version;           /* Version set by application */
    SilcClientRunning running;           /* Running/Stopped callback */
    void *running_context;               /* Context for runnign callback */
-   SilcAtomic16 conns;                  /* Number of connections in client */
+   SilcAtomic32 conns;                  /* Number of connections in client */
    SilcUInt16 next_session_id;          /* Next FTP session ID */
  
    /* Events */
@@@ -185,10 -185,8 +185,10 @@@ silc_client_add_connection(SilcClient c
                           char *remote_host, int port,
                           SilcClientConnectCallback callback,
                           void *context);
 -SilcBuffer silc_client_attributes_process(SilcClient client,
 -                                          SilcClientConnection conn,
 -                                          SilcDList attrs);
 +void silc_client_attributes_process(SilcClient client,
 +                                  SilcClientConnection conn,
 +                                  SilcDList attrs,
 +                                  SilcPKCSSignCb sign_cb,
 +                                  void *context);
  
  #endif /* CLIENT_INTERNAL_H */
index 72f10c1d1a5c4445614ee4c8ba6b95af7e70299b,a3cafe478b9697cf9bb6f153b4a5cf7e924af764..efbeaa24d9cae4534d01d65ad53e221b9ec83fb7
@@@ -28,10 -28,7 +28,10 @@@ typedef struct 
    SilcClient client;
    SilcClientConnection conn;
    SilcBufferStruct detach;
 +  SilcBuffer auth;
    char *nickname;
 +  unsigned char *id;
 +  SilcUInt32 id_len;
    SilcUInt32 channel_count;
  } *SilcClientResumeSession;
  
@@@ -71,23 -68,6 +71,23 @@@ silc_client_resume_command_callback(Sil
    va_end(ap);
  }
  
 +/* Resume authentication data generation callback */
 +
 +static void silc_client_resume_auth_generated(const SilcBuffer data,
 +                                            void *context)
 +{
 +  SilcClientConnection conn = context;
 +  SilcClientResumeSession resume =
 +    silc_fsm_get_state_context(&conn->internal->event_thread);
 +
 +  if (!data)
 +    silc_fsm_next(&conn->internal->event_thread, silc_client_st_resume_error);
 +  else
 +    resume->auth = silc_buffer_copy(data);
 +
 +  SILC_FSM_CALL_CONTINUE_SYNC(&conn->internal->event_thread);
 +}
 +
  
  /****************************** NEW_ID packet *******************************/
  
@@@ -299,6 -279,7 +299,6 @@@ SILC_FSM_STATE(silc_client_st_resume
    SilcClientConnection conn = fsm_context;
    SilcClient client = conn->client;
    SilcClientResumeSession resume;
 -  SilcBuffer auth;
    unsigned char *id;
    SilcUInt16 id_len;
    SilcClientID client_id;
      silc_fsm_next(fsm, silc_client_st_resume_error);
      return SILC_FSM_CONTINUE;
    }
 +  resume->id = id;
 +  resume->id_len = id_len;
  
    /* Generate authentication data that server will verify */
 -  auth = silc_auth_public_key_auth_generate(conn->public_key,
 -                                          conn->private_key,
 -                                          client->rng,
 -                                          conn->internal->hash,
 -                                          &client_id, SILC_ID_CLIENT);
 -  if (!auth) {
 -    /** Out of memory */
 -    silc_fsm_next(fsm, silc_client_st_resume_error);
 -    return SILC_FSM_CONTINUE;
 -  }
 +  silc_fsm_next(fsm, silc_client_st_resume_send);
 +  SILC_FSM_CALL(silc_auth_public_key_auth_generate(
 +                               conn->public_key, conn->private_key,
 +                               client->rng, conn->internal->hash,
 +                               &client_id, SILC_ID_CLIENT,
 +                               silc_client_resume_auth_generated, conn));
 +  /* NOT REACHED */
 +}
 +
 +/* Send RESUME_CLIENT packet */
 +
 +SILC_FSM_STATE(silc_client_st_resume_send)
 +{
 +  SilcClientConnection conn = fsm_context;
 +  SilcClientResumeSession resume = state_context;
 +
 +  SILC_LOG_DEBUG(("Send RESUME_CLIENT packet"));
  
    /* Send RESUME_CLIENT packet to resume to network */
    if (!silc_packet_send_va(conn->stream, SILC_PACKET_RESUME_CLIENT, 0,
 -                         SILC_STR_UI_SHORT(id_len),
 -                         SILC_STR_DATA(id, id_len),
 -                         SILC_STR_DATA(silc_buffer_data(auth),
 -                                       silc_buffer_len(auth)),
 +                         SILC_STR_UI_SHORT(resume->id_len),
 +                         SILC_STR_DATA(resume->id, resume->id_len),
 +                         SILC_STR_DATA(silc_buffer_data(resume->auth),
 +                                       silc_buffer_len(resume->auth)),
                           SILC_STR_END)) {
      /** Error sending packet */
      SILC_LOG_DEBUG(("Error sending packet"));
@@@ -591,25 -563,26 +591,26 @@@ SILC_FSM_STATE(silc_client_st_resume_co
                                      &conn->local_entry->id);
  
    /* Call JOIN command replies for all joined channel */
-   silc_idcache_get_all(conn->internal->channel_cache, &channels);
-   silc_list_start(channels);
-   while ((entry = silc_list_get(channels))) {
-     SilcHashTableList htl;
-     const char *cipher, *hmac;
-     channel = entry->context;
-     cipher = (channel->internal.send_key ?
-             silc_cipher_get_name(channel->internal.send_key) : NULL);
-     hmac = (channel->internal.hmac ?
-           silc_hmac_get_name(channel->internal.hmac) : NULL);
-     silc_hash_table_list(channel->user_list, &htl);
-     silc_client_resume_command_callback(client, conn, SILC_COMMAND_JOIN,
-                                       channel->channel_name, channel,
-                                       channel->mode, &htl, channel->topic,
-                                       cipher, hmac, channel->founder_key,
-                                       channel->channel_pubkeys,
-                                       channel->user_limit);
-     silc_hash_table_list_reset(&htl);
+   if (silc_idcache_get_all(conn->internal->channel_cache, &channels)) {
+     silc_list_start(channels);
+     while ((entry = silc_list_get(channels))) {
+       SilcHashTableList htl;
+       const char *cipher, *hmac;
+       channel = entry->context;
+       cipher = (channel->internal.send_key ?
+               silc_cipher_get_name(channel->internal.send_key) : NULL);
+       hmac = (channel->internal.hmac ?
+             silc_hmac_get_name(channel->internal.hmac) : NULL);
+       silc_hash_table_list(channel->user_list, &htl);
+       silc_client_resume_command_callback(client, conn, SILC_COMMAND_JOIN,
+                                         channel->channel_name, channel,
+                                         channel->mode, &htl, channel->topic,
+                                         cipher, hmac, channel->founder_key,
+                                         channel->channel_pubkeys,
+                                         channel->user_limit);
+       silc_hash_table_list_reset(&htl);
+     }
    }
  
    conn->internal->registering = FALSE;
diff --combined lib/silcclient/command.c
index a50ab52304b83e575d2dc274cea5d8e75e038170,0e72368ded59126cb750a12bb3413d47c57a6ee3..b5827f22819405d28285b296fdb10e15997d93c9
@@@ -411,6 -411,7 +411,7 @@@ SilcUInt16 silc_client_command_call(Sil
    SilcUInt32 argc = 0;
    unsigned char **argv = NULL;
    SilcUInt32 *argv_lens = NULL, *argv_types = NULL;
+   SilcUInt16 cmd_ident;
    SilcClientCommand command;
    SilcClientCommandContext cmd;
    char *arg;
    cmd->argv = argv;
    cmd->argv_lens = argv_lens;
    cmd->argv_types = argv_types;
-   cmd->cmd_ident = silc_client_cmd_ident(conn);
+   cmd_ident = cmd->cmd_ident = silc_client_cmd_ident(conn);
    cmd->called = TRUE;
    cmd->verbose = TRUE;
    silc_list_init(cmd->reply_callbacks,
                       silc_client_command_destructor, NULL, FALSE);
    silc_fsm_start_sync(&cmd->thread, command->command);
  
-   return cmd->cmd_ident;
+   return cmd_ident;
  }
  
  /* Generic function to send any command. The arguments must be sent already
@@@ -696,7 -697,7 +697,7 @@@ SILC_FSM_STATE(silc_client_command_whoi
      SilcAttributeObjPk obj;
      SilcPublicKey pk;
  
 -    if (!silc_pkcs_load_public_key(pubkey, &pk)) {
 +    if (!silc_pkcs_load_public_key(pubkey, SILC_PKCS_ANY, &pk)) {
        SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
          "Could not load public key %s, check the filename",
          pubkey);
        goto out;
        break;
      }
 -    obj.data = silc_pkcs_public_key_encode(pk, &obj.data_len);
 +    obj.data = silc_pkcs_public_key_encode(NULL, pk, &obj.data_len);
  
      attrs = silc_attribute_payload_encode(attrs,
                                            SILC_ATTRIBUTE_USER_PUBLIC_KEY,
    }
  
    if (nick) {
 -    silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname);
 -    if (!nickname)
 -      nickname = strdup(cmd->argv[1]);
 +    if (!silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname))
 +      goto out;
    }
  
    /* Send command */
@@@ -1050,10 -1052,7 +1051,10 @@@ SILC_FSM_STATE(silc_client_command_invi
    /* Parse the typed nickname. */
    if (cmd->argc == 3) {
      if (cmd->argv[2][0] != '+' && cmd->argv[2][0] != '-') {
 -      silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname);
 +      if (!silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname)) {
 +      silc_client_unref_channel(client, conn, channel);
 +      goto out;
 +      }
  
        /* Find client entry */
        clients = silc_client_get_clients_local(client, conn, cmd->argv[2],
        action[0] = 0x01;
  
        /* Check if it is public key file to be added to invite list */
 -      silc_pkcs_load_public_key(cmd->argv[2] + 1, &pubkey);
 +      silc_pkcs_load_public_key(cmd->argv[2] + 1, SILC_PKCS_ANY, &pubkey);
        invite = cmd->argv[2];
        if (!pubkey)
        invite++;
                       SILC_STR_UI_SHORT(1),
                       SILC_STR_END);
      if (pubkey) {
 -      chidp = silc_public_key_payload_encode(pubkey);
 +      chidp = silc_public_key_payload_encode(NULL, pubkey);
        args = silc_argument_payload_encode_one(args, silc_buffer_data(chidp),
                                              silc_buffer_len(chidp), 2);
        silc_buffer_free(chidp);
@@@ -1178,55 -1177,6 +1179,55 @@@ SILC_FSM_STATE(silc_client_command_quit
  
  /********************************** KILL ************************************/
  
 +/* Signature callback */
 +
 +static void silc_client_command_kill_signed(const SilcBuffer buffer,
 +                                          void *context)
 +{
 +  SilcClientCommandContext cmd = context;
 +
 +  if (!buffer) {
 +    silc_fsm_finish(&cmd->thread);
 +    return;
 +  }
 +
 +  silc_fsm_set_state_context(&cmd->thread, buffer);
 +  SILC_FSM_CALL_CONTINUE_SYNC(&cmd->thread);
 +}
 +
 +/* Send KILL command */
 +
 +SILC_FSM_STATE(silc_client_command_kill_send)
 +{
 +  SilcClientCommandContext cmd = fsm_context;
 +  SilcClientConnection conn = cmd->conn;
 +  SilcClient client = conn->client;
 +  SilcBuffer idp, auth = state_context;
 +  SilcClientEntry target = cmd->context;
 +  char *comment = NULL;
 +
 +  if (cmd->argc >= 3)
 +    if (strcasecmp(cmd->argv[2], "-pubkey"))
 +      comment = cmd->argv[2];
 +
 +  /* Send the KILL command to the server */
 +  idp = silc_id_payload_encode(&target->id, SILC_ID_CLIENT);
 +  silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 3,
 +                            1, silc_buffer_datalen(idp),
 +                            2, comment, comment ? strlen(comment) : 0,
 +                            3, silc_buffer_datalen(auth));
 +
 +  silc_buffer_free(idp);
 +  silc_client_unref_client(client, conn, target);
 +
 +  /* Notify application */
 +  COMMAND(SILC_STATUS_OK);
 +
 +  /** Wait for command reply */
 +  silc_fsm_next(fsm, silc_client_command_reply_wait);
 +  return SILC_FSM_CONTINUE;
 +}
 +
  /* Command KILL. Router operator can use this command to remove an client
     fromthe SILC Network. */
  
@@@ -1235,9 -1185,10 +1236,9 @@@ SILC_FSM_STATE(silc_client_command_kill
    SilcClientCommandContext cmd = fsm_context;
    SilcClientConnection conn = cmd->conn;
    SilcClient client = conn->client;
 -  SilcBuffer idp, auth = NULL;
    SilcClientEntry target;
    SilcDList clients;
 -  char *nickname = NULL, *comment = NULL;
 +  char *nickname = NULL;
  
    if (cmd->argc < 2) {
      SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
                                          cmd));
  
    target = silc_dlist_get(clients);
 +  cmd->context = silc_client_ref_client(client, conn, target);
  
 -  if (cmd->argc >= 3) {
 -    if (strcasecmp(cmd->argv[2], "-pubkey"))
 -      comment = cmd->argv[2];
 +  silc_free(nickname);
 +  silc_client_list_free(client, conn, clients);
 +
 +  /** Send KILL */
 +  silc_fsm_next(fsm, silc_client_command_kill_send);
  
 +  if (cmd->argc >= 3) {
      if (!strcasecmp(cmd->argv[2], "-pubkey") ||
        (cmd->argc >= 4 && !strcasecmp(cmd->argv[3], "-pubkey"))) {
        /* Encode the public key authentication payload */
 -      auth = silc_auth_public_key_auth_generate(conn->public_key,
 -                                              conn->private_key,
 -                                              conn->client->rng,
 -                                              conn->internal->sha1hash,
 -                                              &target->id, SILC_ID_CLIENT);
 +      SILC_FSM_CALL(silc_auth_public_key_auth_generate(
 +                                       conn->public_key,
 +                                       conn->private_key,
 +                                       conn->client->rng,
 +                                       conn->internal->sha1hash,
 +                                       &target->id, SILC_ID_CLIENT,
 +                                       silc_client_command_kill_signed,
 +                                       cmd));
 +      /* NOT REACHED */
      }
    }
  
 -  /* Send the KILL command to the server */
 -  idp = silc_id_payload_encode(&target->id, SILC_ID_CLIENT);
 -  silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 3,
 -                            1, silc_buffer_datalen(idp),
 -                            2, comment, comment ? strlen(comment) : 0,
 -                            3, silc_buffer_datalen(auth));
 -  silc_buffer_free(idp);
 -  silc_buffer_free(auth);
 -  silc_free(nickname);
 -  silc_client_list_free(client, conn, clients);
 -
 -  /* Notify application */
 -  COMMAND(SILC_STATUS_OK);
 -
 -  /** Wait for command reply */
 -  silc_fsm_next(fsm, silc_client_command_reply_wait);
    return SILC_FSM_CONTINUE;
  }
  
@@@ -1365,33 -1324,6 +1366,33 @@@ SILC_FSM_STATE(silc_client_command_ping
  
  /********************************** JOIN ************************************/
  
 +typedef struct {
 +  int type;
 +  SilcBuffer auth;
 +  SilcBuffer cauth;
 +} *SilcClientJoinContext;
 +
 +/* Signature callback */
 +
 +static void silc_client_command_join_signed(const SilcBuffer buffer,
 +                                          void *context)
 +{
 +  SilcClientCommandContext cmd = context;
 +  SilcClientJoinContext j = cmd->context;
 +
 +  if (!buffer) {
 +    silc_fsm_finish(&cmd->thread);
 +    return;
 +  }
 +
 +  if (!j->type)
 +    j->auth = silc_buffer_copy(buffer);
 +  else
 +    j->cauth = silc_buffer_copy(buffer);
 +
 +  SILC_FSM_CALL_CONTINUE(&cmd->thread);
 +}
 +
  /* Command JOIN. Joins to a channel. */
  
  SILC_FSM_STATE(silc_client_command_join)
    SilcClientConnection conn = cmd->conn;
    SilcClient client = conn->client;
    SilcChannelEntry channel = NULL;
 +  SilcClientJoinContext j = cmd->context;
    SilcBuffer auth = NULL, cauth = NULL;
    char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL;
    int i, passphrase_len = 0;
      } else if (!strcasecmp(cmd->argv[i], "-hmac") && cmd->argc > i + 1) {
        hmac = cmd->argv[++i];
      } else if (!strcasecmp(cmd->argv[i], "-founder")) {
 -      auth = silc_auth_public_key_auth_generate(conn->public_key,
 -                                              conn->private_key,
 -                                              conn->client->rng,
 -                                              conn->internal->sha1hash,
 -                                              conn->local_id,
 -                                              SILC_ID_CLIENT);
 +      if (!j || !j->auth) {
 +      if (!j) {
 +        j = silc_calloc(1, sizeof(*j));
 +        if (!j)
 +          goto out;
 +        cmd->context = j;
 +      }
 +      j->type = 0;
 +      silc_free(passphrase);
 +      silc_client_unref_channel(client, conn, channel);
 +      SILC_FSM_CALL(silc_auth_public_key_auth_generate(
 +                                         conn->public_key,
 +                                         conn->private_key,
 +                                         conn->client->rng,
 +                                         conn->internal->sha1hash,
 +                                         conn->local_id,
 +                                         SILC_ID_CLIENT,
 +                                         silc_client_command_join_signed,
 +                                         cmd));
 +      /* NOT REACHED */
 +      }
      } else if (!strcasecmp(cmd->argv[i], "-auth")) {
        SilcPublicKey pubkey = conn->public_key;
        SilcPrivateKey privkey = conn->private_key;
 -      unsigned char *pk, pkhash[SILC_HASH_MAXLEN], *pubdata;
 +      unsigned char *pk, pkhash[SILC_HASH_MAXLEN], pubdata[128];
        SilcUInt32 pk_len;
  
 -      if (cmd->argc >= i + 3) {
 -      char *pass = "";
 -      if (cmd->argc >= i + 4) {
 -        pass = cmd->argv[i + 3];
 -        i++;
 +      if (!j || !j->cauth) {
 +      if (!j) {
 +        j = silc_calloc(1, sizeof(*j));
 +        if (!j)
 +          goto out;
 +        cmd->context = j;
        }
 -      if (!silc_load_key_pair(cmd->argv[i + 1], cmd->argv[i + 2], pass,
 -                              &pubkey, &privkey)) {
 -        SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
 -            "Could not load key pair, check your arguments");
 -        COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
 -        goto out;
 +
 +      if (cmd->argc >= i + 3) {
 +        char *pass = "";
 +        if (cmd->argc >= i + 4) {
 +          pass = cmd->argv[i + 3];
 +          i++;
 +        }
 +        if (!silc_load_key_pair(cmd->argv[i + 1], cmd->argv[i + 2], pass,
 +                                &pubkey, &privkey)) {
 +          SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
 +              "Could not load key pair, check your arguments");
 +          COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
 +          goto out;
 +        }
 +        i += 2;
        }
 -      i += 2;
 -      }
  
 -      pk = silc_pkcs_public_key_encode(pubkey, &pk_len);
 -      silc_hash_make(conn->internal->sha1hash, pk, pk_len, pkhash);
 -      silc_free(pk);
 -      pubdata = silc_rng_get_rn_data(conn->client->rng, 128);
 -      memcpy(pubdata, pkhash, 20);
 -      cauth = silc_auth_public_key_auth_generate_wpub(pubkey, privkey,
 -                                                    pubdata, 128,
 -                                                    conn->internal->sha1hash,
 -                                                    conn->local_id,
 -                                                    SILC_ID_CLIENT);
 -      memset(pubdata, 0, 128);
 -      silc_free(pubdata);
 +      j->type = 1;
 +      pk = silc_pkcs_public_key_encode(NULL, pubkey, &pk_len);
 +      silc_hash_make(conn->internal->sha1hash, pk, pk_len, pkhash);
 +      silc_free(pk);
 +      silc_rng_get_rn_data(conn->client->rng, sizeof(pubdata), pubdata,
 +                           sizeof(pubdata));
 +      memcpy(pubdata, pkhash, 20);
 +      silc_free(passphrase);
 +      silc_client_unref_channel(client, conn, channel);
 +      SILC_FSM_CALL(silc_auth_public_key_auth_generate_wpub(
 +                                         pubkey, privkey,
 +                                         pubdata, sizeof(pubdata),
 +                                         conn->internal->sha1hash,
 +                                         client->rng,
 +                                         conn->local_id,
 +                                         SILC_ID_CLIENT,
 +                                         silc_client_command_join_signed,
 +                                         cmd));
 +      /* NOT REACHED */
 +      }
      } else {
        /* Passphrases must be UTF-8 encoded, so encode if it is not */
        if (!silc_utf8_valid(cmd->argv[i], cmd->argv_lens[i])) {
                              6, silc_buffer_datalen(auth),
                              7, silc_buffer_datalen(cauth));
  
 -  silc_buffer_free(auth);
 -  silc_buffer_free(cauth);
    if (passphrase)
      memset(passphrase, 0, strlen(passphrase));
    silc_free(passphrase);
    silc_client_unref_channel(client, conn, channel);
 +  if (j) {
 +    silc_buffer_free(j->auth);
 +    silc_buffer_free(j->cauth);
 +    silc_free(j);
 +  }
  
    /* Notify application */
    COMMAND(SILC_STATUS_OK);
@@@ -1734,22 -1631,6 +1735,22 @@@ SILC_FSM_STATE(silc_client_command_umod
  
  /********************************** CMODE ***********************************/
  
 +/* Signature callback */
 +
 +static void silc_client_command_cmode_signed(const SilcBuffer buffer,
 +                                           void *context)
 +{
 +  SilcClientCommandContext cmd = context;
 +
 +  if (!buffer) {
 +    silc_fsm_finish(&cmd->thread);
 +    return;
 +  }
 +
 +  silc_fsm_set_state_context(&cmd->thread, buffer);
 +  SILC_FSM_CALL_CONTINUE_SYNC(&cmd->thread);
 +}
 +
  /* CMODE command. Sets channel mode. Modes that does not require any arguments
     can be set several at once. Those modes that require argument must be set
     separately (unless set with modes that does not require arguments). */
@@@ -1759,9 -1640,8 +1760,9 @@@ SILC_FSM_STATE(silc_client_command_cmod
    SilcClientCommandContext cmd = fsm_context;
    SilcClientConnection conn = cmd->conn;
    SilcClient client = conn->client;
 +  SilcBuffer auth = state_context;
    SilcChannelEntry channel = NULL;
 -  SilcBuffer chidp, auth = NULL, pk = NULL;
 +  SilcBuffer chidp, pk = NULL;
    unsigned char *name, *cp, modebuf[4], tmp[4], *arg = NULL;
    SilcUInt32 mode, add, type, len, arg_len = 0;
    int i;
        break;
      case 'f':
        if (add) {
 -      SilcPublicKey pubkey = conn->public_key;
 -      SilcPrivateKey privkey = conn->private_key;
 -
 -      mode |= SILC_CHANNEL_MODE_FOUNDER_AUTH;
 -      type = 7;
 -
 -      if (cmd->argc >= 5) {
 -        char *pass = "";
 -        if (cmd->argc >= 6)
 -          pass = cmd->argv[5];
 -        if (!silc_load_key_pair(cmd->argv[3], cmd->argv[4], pass,
 -                                &pubkey, &privkey)) {
 -          SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
 -              "Could not load key pair, check your arguments");
 -          COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
 -          goto out;
 +      if (!auth) {
 +        SilcPublicKey pubkey = conn->public_key;
 +        SilcPrivateKey privkey = conn->private_key;
 +
 +        mode |= SILC_CHANNEL_MODE_FOUNDER_AUTH;
 +        type = 7;
 +
 +        if (cmd->argc >= 5) {
 +          char *pass = "";
 +          if (cmd->argc >= 6)
 +            pass = cmd->argv[5];
 +          if (!silc_load_key_pair(cmd->argv[3], cmd->argv[4], pass,
 +                                  &pubkey, &privkey)) {
 +            SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
 +                "Could not load key pair, check your arguments");
 +            COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
 +            goto out;
 +          }
          }
 -      }
  
 -      pk = silc_public_key_payload_encode(pubkey);
 -      auth = silc_auth_public_key_auth_generate(pubkey, privkey,
 -                                                conn->client->rng,
 -                                                conn->internal->sha1hash,
 -                                                conn->local_id,
 -                                                SILC_ID_CLIENT);
 +        pk = silc_public_key_payload_encode(NULL, pubkey);
 +        silc_client_unref_channel(client, conn, channel);
 +        SILC_FSM_CALL(silc_auth_public_key_auth_generate(
 +                                           pubkey, privkey,
 +                                           conn->client->rng,
 +                                           conn->internal->sha1hash,
 +                                           conn->local_id,
 +                                           SILC_ID_CLIENT,
 +                                           silc_client_command_cmode_signed,
 +                                           cmd));
 +        /* NOT REACHED */
 +      }
        arg = silc_buffer_data(auth);
        arg_len = silc_buffer_len(auth);
        } else {
        for (k = 3; k < cmd->argc; k++) {
          if (cmd->argv[k][0] == '+')
            chadd = TRUE;
 -        if (!silc_pkcs_load_public_key(cmd->argv[k] + 1, &chpk)) {
 +        if (!silc_pkcs_load_public_key(cmd->argv[k] + 1, SILC_PKCS_ANY,
 +                                       &chpk)) {
            SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
                "Could not load public key %s, check the filename",
                cmd->argv[k]);
          }
  
          if (chpk) {
 -          pk = silc_public_key_payload_encode(chpk);
 +          pk = silc_public_key_payload_encode(NULL, chpk);
            auth = silc_argument_payload_encode_one(auth,
                                                    silc_buffer_datalen(pk),
                                                    chadd ? 0x00 : 0x01);
  
  /********************************* CUMODE ***********************************/
  
 +/* Signature callback */
 +
 +static void silc_client_command_cumode_signed(const SilcBuffer buffer,
 +                                            void *context)
 +{
 +  SilcClientCommandContext cmd = context;
 +
 +  if (!buffer) {
 +    silc_fsm_finish(&cmd->thread);
 +    return;
 +  }
 +
 +  silc_fsm_set_state_context(&cmd->thread, buffer);
 +  SILC_FSM_CALL_CONTINUE_SYNC(&cmd->thread);
 +}
 +
  /* CUMODE command. Changes client's mode on a channel. */
  
  SILC_FSM_STATE(silc_client_command_cumode)
    SilcClientCommandContext cmd = fsm_context;
    SilcClientConnection conn = cmd->conn;
    SilcClient client = conn->client;
 +  SilcBuffer auth = state_context;
    SilcChannelEntry channel = NULL;
    SilcChannelUser chu;
    SilcClientEntry client_entry;
 -  SilcBuffer clidp, chidp, auth = NULL;
 +  SilcBuffer clidp, chidp;
    SilcDList clients = NULL;
    unsigned char *name, *cp, modebuf[4];
    SilcUInt32 mode = 0, add, len;
    }
  
    /* Parse the typed nickname. */
 -  silc_client_nickname_parse(client, conn, cmd->argv[3], &nickname);
 +  if (!silc_client_nickname_parse(client, conn, cmd->argv[3], &nickname))
 +    goto out;
  
    /* Find client entry */
    clients = silc_client_get_clients_local(client, conn, cmd->argv[3], FALSE);
        break;
      case 'f':
        if (add) {
 -      SilcPublicKey pubkey = conn->public_key;
 -      SilcPrivateKey privkey = conn->private_key;
 -
 -      if (cmd->argc >= 6) {
 -        char *pass = "";
 -        if (cmd->argc >= 7)
 -          pass = cmd->argv[6];
 -        if (!silc_load_key_pair(cmd->argv[4], cmd->argv[5], pass,
 -                                &pubkey, &privkey)) {
 -          SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
 -              "Could not load key pair, check your arguments");
 -          COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
 -          goto out;
 +      if (!auth) {
 +        SilcPublicKey pubkey = conn->public_key;
 +        SilcPrivateKey privkey = conn->private_key;
 +
 +        if (cmd->argc >= 6) {
 +          char *pass = "";
 +          if (cmd->argc >= 7)
 +            pass = cmd->argv[6];
 +          if (!silc_load_key_pair(cmd->argv[4], cmd->argv[5], pass,
 +                                  &pubkey, &privkey)) {
 +            SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
 +                "Could not load key pair, check your arguments");
 +            COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
 +            goto out;
 +          }
          }
 +
 +        silc_free(nickname);
 +        silc_client_list_free(client, conn, clients);
 +        silc_client_unref_channel(client, conn, channel);
 +
 +        SILC_FSM_CALL(silc_auth_public_key_auth_generate(
 +                                           pubkey, privkey,
 +                                           conn->client->rng,
 +                                           conn->internal->sha1hash,
 +                                           conn->local_id,
 +                                           SILC_ID_CLIENT,
 +                                           silc_client_command_cumode_signed,
 +                                           cmd));
 +        /* NOT REACHED */
        }
  
 -      auth = silc_auth_public_key_auth_generate(pubkey, privkey,
 -                                                conn->client->rng,
 -                                                conn->internal->sha1hash,
 -                                                conn->local_id,
 -                                                SILC_ID_CLIENT);
        mode |= SILC_CHANNEL_UMODE_CHANFO;
        } else {
        mode &= ~SILC_CHANNEL_UMODE_CHANFO;
@@@ -2369,7 -2212,6 +2370,7 @@@ SILC_FSM_STATE(silc_client_command_kick
  typedef struct {
    unsigned char *passphrase;
    SilcUInt32 passphrase_len;
 +  SilcBuffer auth;
  } *SilcClientCommandOper;
  
  /* Ask passphrase callback */
@@@ -2388,19 -2230,6 +2389,19 @@@ static void silc_client_command_oper_cb
    SILC_FSM_CALL_CONTINUE(&cmd->thread);
  }
  
 +static void silc_client_command_oper_sign_cb(const SilcBuffer data,
 +                                           void *context)
 +{
 +  SilcClientCommandContext cmd = context;
 +  SilcClientCommandOper oper = cmd->context;
 +
 +  if (data)
 +    oper->auth = silc_buffer_copy(data);
 +
 +  /* Continue */
 +  SILC_FSM_CALL_CONTINUE(&cmd->thread);
 +}
 +
  /* Send OPER/SILCOPER command */
  
  SILC_FSM_STATE(silc_client_command_oper_send)
    SilcClientCommandContext cmd = fsm_context;
    SilcClientConnection conn = cmd->conn;
    SilcClientCommandOper oper = cmd->context;
 -  SilcBuffer auth;
 -
 -  if (!oper || !oper->passphrase) {
 -    /* Encode the public key authentication payload */
 -    auth = silc_auth_public_key_auth_generate(conn->public_key,
 -                                            conn->private_key,
 -                                            conn->client->rng,
 -                                            conn->internal->hash,
 -                                            conn->local_id,
 -                                            SILC_ID_CLIENT);
 -  } else {
 -    /* Encode the password authentication payload */
 -    auth = silc_auth_payload_encode(SILC_AUTH_PASSWORD, NULL, 0,
 -                                  oper->passphrase, oper->passphrase_len);
 -  }
 +  SilcBuffer auth = oper ? oper->auth : NULL;
  
    silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 2,
                              1, cmd->argv[1], strlen(cmd->argv[1]),
    return SILC_FSM_CONTINUE;
  }
  
 +/* Get authentication data */
 +
 +SILC_FSM_STATE(silc_client_command_oper_get_auth)
 +{
 +  SilcClientCommandContext cmd = fsm_context;
 +  SilcClientConnection conn = cmd->conn;
 +  SilcClientCommandOper oper = cmd->context;
 +
 +  silc_fsm_next(fsm, silc_client_command_oper_send);
 +
 +  if (!oper || !oper->passphrase) {
 +    /* Encode the public key authentication payload */
 +    SILC_FSM_CALL(silc_auth_public_key_auth_generate(
 +                                     conn->public_key,
 +                                     conn->private_key,
 +                                     conn->client->rng,
 +                                     conn->internal->hash,
 +                                     conn->local_id, SILC_ID_CLIENT,
 +                                     silc_client_command_oper_sign_cb,
 +                                     oper));
 +    /* NOT REACHED */
 +  }
 +
 +  /* Encode the password authentication payload */
 +  oper->auth = silc_auth_payload_encode(NULL, SILC_AUTH_PASSWORD, NULL, 0,
 +                                      oper->passphrase, oper->passphrase_len);
 +
 +  return SILC_FSM_CONTINUE;
 +}
 +
  /* OPER command. Used to obtain server operator privileges. */
  
  SILC_FSM_STATE(silc_client_command_oper)
      return SILC_FSM_FINISH;
    }
  
 -  silc_fsm_next(fsm, silc_client_command_oper_send);
 +  silc_fsm_next(fsm, silc_client_command_oper_get_auth);
  
    /* Get passphrase */
    if (cmd->argc < 3) {
@@@ -2569,7 -2382,7 +2570,7 @@@ SILC_FSM_STATE(silc_client_command_ban
        action[0] = 0x01;
  
      /* Check if it is public key file to be added to invite list */
 -    silc_pkcs_load_public_key(cmd->argv[2] + 1, &pubkey);
 +    silc_pkcs_load_public_key(cmd->argv[2] + 1, SILC_PKCS_ANY, &pubkey);
      ban = cmd->argv[2];
      if (!pubkey)
        ban++;
                       SILC_STR_UI_SHORT(1),
                       SILC_STR_END);
      if (pubkey) {
 -      chidp = silc_public_key_payload_encode(pubkey);
 +      chidp = silc_public_key_payload_encode(NULL, pubkey);
        args = silc_argument_payload_encode_one(args,
                                              silc_buffer_datalen(chidp), 2);
        silc_buffer_free(chidp);
@@@ -2669,7 -2482,7 +2670,7 @@@ SILC_FSM_STATE(silc_client_command_watc
      SilcPublicKey pk;
      SilcBuffer buffer;
  
 -    if (!silc_pkcs_load_public_key(pubkey, &pk)) {
 +    if (!silc_pkcs_load_public_key(pubkey, SILC_PKCS_ANY, &pk)) {
        SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
          "Could not load public key %s, check the filename", pubkey);
        COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
      silc_buffer_format(args,
                       SILC_STR_UI_SHORT(1),
                       SILC_STR_END);
 -    buffer = silc_public_key_payload_encode(pk);
 +    buffer = silc_public_key_payload_encode(NULL, pk);
      args = silc_argument_payload_encode_one(args, silc_buffer_datalen(buffer),
                                            pubkey_add ? 0x00 : 0x01);
      silc_buffer_free(buffer);
@@@ -3015,60 -2828,17 +3016,60 @@@ void silc_client_commands_unregister(Si
  
  /****************** Client Side Incoming Command Handling *******************/
  
 -/* Reply to WHOIS command from server */
 +typedef struct {
 +  SilcClientConnection conn;
 +  SilcUInt16 cmd_ident;
 +} *SilcClientProcessWhois;
 +
 +/* Send reply to WHOIS from server */
 +
 +static void
 +silc_client_command_process_whois_send(SilcBool success,
 +                                     const unsigned char *data,
 +                                     SilcUInt32 data_len, void *context)
 +{
 +  SilcClientProcessWhois w = context;
 +  SilcBufferStruct buffer;
 +  SilcBuffer packet;
 +
 +  if (!data) {
 +    silc_free(w);
 +    return;
 +  }
 +
 +  silc_buffer_set(&buffer, (unsigned char *)data, data_len);
 +
 +  /* Send the attributes back in COMMAND_REPLY packet */
 +  packet =
 +    silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
 +                                       SILC_STATUS_OK, 0, w->cmd_ident,
 +                                       1, 11, buffer.data,
 +                                       silc_buffer_len(&buffer));
 +  if (!packet) {
 +    silc_free(w);
 +    return;
 +  }
 +
 +  SILC_LOG_DEBUG(("Sending back requested WHOIS attributes"));
 +
 +  silc_packet_send(w->conn->stream, SILC_PACKET_COMMAND_REPLY, 0,
 +                 silc_buffer_datalen(packet));
 +
 +  silc_buffer_free(packet);
 +  silc_free(w);
 +}
 +
 +/* Process WHOIS command from server */
  
  static void silc_client_command_process_whois(SilcClient client,
                                              SilcClientConnection conn,
                                              SilcCommandPayload payload,
                                              SilcArgumentPayload args)
  {
 +  SilcClientProcessWhois w;
    SilcDList attrs;
    unsigned char *tmp;
    SilcUInt32 tmp_len;
 -  SilcBuffer buffer, packet;
  
    SILC_LOG_DEBUG(("Received WHOIS command"));
  
    if (!attrs)
      return;
  
 -  /* Process requested attributes */
 -  buffer = silc_client_attributes_process(client, conn, attrs);
 -  if (!buffer) {
 +  w = silc_calloc(1, sizeof(*w));
 +  if (!w) {
      silc_attribute_payload_list_free(attrs);
      return;
    }
 +  w->conn = conn;
 +  w->cmd_ident = silc_command_get_ident(payload);
  
 -  /* Send the attributes back in COMMAND_REPLY packet */
 -  packet =
 -    silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
 -                                       SILC_STATUS_OK, 0,
 -                                       silc_command_get_ident(payload),
 -                                       1, 11, buffer->data,
 -                                       silc_buffer_len(buffer));
 -  if (!packet) {
 -    silc_buffer_free(buffer);
 -    return;
 -  }
 -
 -  SILC_LOG_DEBUG(("Sending back requested WHOIS attributes"));
 -
 -  silc_packet_send(conn->stream, SILC_PACKET_COMMAND_REPLY, 0,
 -                 silc_buffer_datalen(packet));
 -
 -  silc_buffer_free(packet);
 -  silc_buffer_free(buffer);
 +  /* Process requested attributes */
 +  silc_client_attributes_process(client, conn, attrs,
 +                               silc_client_command_process_whois_send, w);
 +  silc_attribute_payload_list_free(attrs);
  }
  
  /* Client is able to receive some command packets even though they are
index bf80d064126e095f3d539d0e47061b4295637190,29e05e73fe086b419299d922f1e196da594b2cfa..ede887535fdcdc97b6219d0c8d73f11b45867021
@@@ -118,6 -118,7 +118,7 @@@ static void silc_client_command_process
      client_entry = silc_client_get_client_by_id(client, conn, &id.u.client_id);
      if (client_entry) {
        silc_client_remove_from_channels(client, conn, client_entry);
+       client_entry->internal.valid = FALSE;
        silc_client_del_client(client, conn, client_entry);
        silc_client_unref_client(client, conn, client_entry);
      }
@@@ -947,6 -948,7 +948,7 @@@ SILC_FSM_STATE(silc_client_command_repl
    /* Remove the client */
    if (client_entry) {
      silc_client_remove_from_channels(client, conn, client_entry);
+     client_entry->internal.valid = FALSE;
      silc_client_del_client(client, conn, client_entry);
      silc_client_unref_client(client, conn, client_entry);
    }
@@@ -1111,29 -1113,6 +1113,29 @@@ silc_client_command_reply_join_resolved
  {
    SilcClientCommandContext cmd = context;
    SilcChannelEntry channel = cmd->context;
 +  SilcCommandPayload payload = silc_fsm_get_state_context(&cmd->thread);
 +  SilcArgumentPayload args = silc_command_get_args(payload);
 +  SilcUInt32 list_count;
 +  unsigned char *tmp;
 +  char msg[512];
 +
 +  if (!clients) {
 +    silc_snprintf(msg, sizeof(msg), "Error resolving channel %s user list",
 +                channel->channel_name);
 +    SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, msg);
 +  } else {
 +    tmp = silc_argument_get_arg_type(args, 12, NULL);
 +    if (tmp) {
 +      SILC_GET32_MSB(list_count, tmp);
 +      if (list_count - silc_dlist_count(clients) > 5) {
 +      silc_snprintf(msg, sizeof(msg),
 +                    "Channel %s user list was not fully resolved. "
 +                    "The channel may not be fully synced.",
 +                    channel->channel_name);
 +      SAY(client, conn, SILC_CLIENT_MESSAGE_WARNING, msg);
 +      }
 +    }
 +  }
  
    channel->internal.resolve_cmd_ident = 0;
    silc_client_unref_channel(client, conn, channel);
@@@ -1195,7 -1174,7 +1197,7 @@@ SILC_FSM_STATE(silc_client_command_repl
  
    /* Get the list count */
    tmp = silc_argument_get_arg_type(args, 12, &len);
 -  if (!tmp) {
 +  if (!tmp || len != 4) {
      ERROR_CALLBACK(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
      goto out;
    }
    /* Add clients we received in the reply to the channel */
    for (i = 0; i < list_count; i++) {
      SilcUInt16 idp_len;
 -    SilcUInt32 mode;
      SilcID id;
      SilcClientEntry client_entry;
  
@@@ -1509,20 -1489,6 +1511,20 @@@ SILC_FSM_STATE(silc_client_command_repl
    silc_client_command_callback(cmd, channel, mode, public_key,
                               channel->channel_pubkeys, channel->user_limit);
  
 +  silc_rwlock_wrlock(channel->internal.lock);
 +
 +  /* If founder key changed, update it */
 +  if (public_key &&
 +      (!channel->founder_key ||
 +       !silc_pkcs_public_key_compare(public_key, channel->founder_key))) {
 +    if (channel->founder_key)
 +      silc_pkcs_public_key_free(channel->founder_key);
 +    channel->founder_key = public_key;
 +    public_key = NULL;
 +  }
 +
 +  silc_rwlock_unlock(channel->internal.lock);
 +
   out:
    silc_client_unref_channel(client, conn, channel);
    if (public_key)
index eb0d176efce4540e4abd95160149d390be4d24b6,eb0d176efce4540e4abd95160149d390be4d24b6..059797e5bc5d03c95beb5dc299490f94d19b6b66
@@@ -4,7 -4,7 +4,7 @@@
  
    Author: Pekka Riikonen <priikone@silcnet.org>
  
--  Copyright (C) 1997 - 2006 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
  #ifndef SILCCOMMAND_H
  #define SILCCOMMAND_H
  
--/****f* silccore/SilcCommandAPI/SilcCommandCb
-- *
-- * SYNOPSIS
-- *
-- *    typedef void (*SilcCommandCb)(void *context, void *context2);
-- *
-- * DESCRIPTION
-- *
-- *    Command function callback. The actual command function pointer.
-- *    This is generic command callback that the application may choose to
-- *    use with its command routines.  However, none of the generic
-- *    routines depend on this callback so application may freely define
-- *    their own command callback if desired.
-- *
-- ***/
--typedef void (*SilcCommandCb)(void *context, void *context2);
--
  /****s* silccore/SilcCommandAPI/SilcCommandPayload
   *
   * NAME
index d2696bbe8c624795fa438aed5b2287ee9f775e6a,f552ca6d1741aebf31648e1c694d34c302792ac3..26f721f56f0d34448725a4c7a1e43673702e1429
@@@ -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
@@@ -40,7 -40,7 +40,7 @@@ struct SilcPacketEngineStruct 
    SilcMutex lock;                      /* Engine lock */
    SilcRng rng;                                 /* RNG for engine */
    SilcHashTable contexts;              /* Per scheduler contexts */
-   SilcPacketCallbacks *callbacks;      /* Packet callbacks */
+   const SilcPacketCallbacks *callbacks;        /* Packet callbacks */
    void *callback_context;              /* Context for callbacks */
    SilcList streams;                    /* All streams in engine */
    SilcList packet_pool;                        /* Free list for received packets */
@@@ -51,7 -51,7 +51,7 @@@
  /* Packet processor context */
  typedef struct SilcPacketProcessStruct {
    SilcPacketType *types;               /* Packets to process */
-   SilcPacketCallbacks *callbacks;      /* Callbacks or NULL */
+   const SilcPacketCallbacks *callbacks;        /* Callbacks or NULL */
    void *callback_context;
    SilcInt32 priority;                  /* Priority */
  } *SilcPacketProcess;
@@@ -81,7 -81,7 +81,7 @@@ struct SilcPacketStreamStruct 
    unsigned char *dst_id;               /* Destination ID */
    SilcUInt32 send_psn;                         /* Sending sequence */
    SilcUInt32 receive_psn;              /* Receiving sequence */
-   SilcAtomic8 refcnt;                  /* Reference counter */
+   SilcAtomic32 refcnt;                         /* Reference counter */
    SilcUInt8 sid;                       /* Security ID, set if IV included */
    unsigned int src_id_len  : 6;
    unsigned int src_id_type : 2;
@@@ -336,7 -336,6 +336,6 @@@ static inline SilcBool silc_packet_stre
        silc_mutex_unlock(ps->lock);
        if (ret == -1) {
          /* Cannot read now, do it later. */
-         silc_buffer_pull(inbuf, silc_buffer_len(inbuf));
          return FALSE;
        }
  
  
      if (ret == -1) {
        /* Cannot read now, do it later. */
-       silc_buffer_pull(inbuf, silc_buffer_len(inbuf));
        return FALSE;
      }
  
@@@ -542,7 -540,7 +540,7 @@@ static void silc_packet_engine_context_
  
  SilcPacketEngine
  silc_packet_engine_start(SilcRng rng, SilcBool router,
-                        SilcPacketCallbacks *callbacks,
+                        const SilcPacketCallbacks *callbacks,
                         void *callback_context)
  {
    SilcPacketEngine engine;
    if (!engine)
      return NULL;
  
 -  engine->contexts = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
 +  engine->contexts = silc_hash_table_alloc(NULL, 0, silc_hash_ptr,
 +                                         NULL, NULL, NULL,
                                           silc_packet_engine_context_destr,
                                           engine, TRUE);
    if (!engine->contexts) {
@@@ -624,7 -621,7 +622,7 @@@ void silc_packet_engine_stop(SilcPacket
    silc_free(engine);
  }
  
- static const char *packet_error[] = {
+ static const char * const packet_error[] = {
    "Cannot read from stream",
    "Cannot write to stream",
    "Packet MAC failed",
@@@ -698,7 -695,7 +696,7 @@@ SilcPacketStream silc_packet_stream_cre
      return NULL;
  
    ps->stream = stream;
-   silc_atomic_init8(&ps->refcnt, 1);
+   silc_atomic_init32(&ps->refcnt, 1);
    silc_mutex_alloc(&ps->lock);
  
    /* Allocate out buffer */
                            (void *)&ps->sc)) {
      ps->sc = silc_calloc(1, sizeof(*ps->sc));
      if (!ps->sc) {
-       silc_packet_stream_destroy(ps);
        silc_mutex_unlock(engine->lock);
+       silc_packet_stream_destroy(ps);
        return NULL;
      }
      ps->sc->engine = engine;
      if (!inbuf) {
        silc_free(ps->sc);
        ps->sc = NULL;
-       silc_packet_stream_destroy(ps);
        silc_mutex_unlock(engine->lock);
+       silc_packet_stream_destroy(ps);
        return NULL;
      }
      silc_buffer_reset(inbuf);
        silc_buffer_free(inbuf);
        silc_free(ps->sc);
        ps->sc = NULL;
-       silc_packet_stream_destroy(ps);
        silc_mutex_unlock(engine->lock);
+       silc_packet_stream_destroy(ps);
        return NULL;
      }
      silc_dlist_add(ps->sc->inbufs, inbuf);
        silc_dlist_del(ps->sc->inbufs, inbuf);
        silc_free(ps->sc);
        ps->sc = NULL;
-       silc_packet_stream_destroy(ps);
        silc_mutex_unlock(engine->lock);
+       silc_packet_stream_destroy(ps);
        return NULL;
      }
    }
  
    /* If this is UDP stream, allocate UDP remote stream hash table */
    if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
 -    engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
 -                                             silc_hash_string_compare, NULL,
 -                                             silc_packet_engine_hash_destr,
 -                                             NULL, TRUE);
 +    engine->udp_remote =
 +      silc_hash_table_alloc(NULL, 0, silc_hash_string_case, NULL,
 +                          silc_hash_string_case_compare, NULL,
 +                          silc_packet_engine_hash_destr, NULL, TRUE);
  
    silc_mutex_unlock(engine->lock);
  
@@@ -819,7 -816,7 +817,7 @@@ SilcPacketStream silc_packet_stream_add
      return NULL;
    ps->sc = stream->sc;
  
-   silc_atomic_init8(&ps->refcnt, 1);
+   silc_atomic_init32(&ps->refcnt, 1);
    silc_mutex_alloc(&ps->lock);
  
    /* Set the UDP packet stream as underlaying stream */
@@@ -887,7 -884,9 +885,9 @@@ void silc_packet_stream_destroy(SilcPac
    if (!stream)
      return;
  
-   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0) {
+   if (silc_atomic_sub_int32(&stream->refcnt, 1) > 0) {
+     if (stream->destroyed)
+       return;
      stream->destroyed = TRUE;
  
      SILC_LOG_DEBUG(("Marking packet stream %p destroyed", stream));
  
    if (!stream->udp) {
      /* Delete from engine */
-     engine = stream->sc->engine;
-     silc_mutex_lock(engine->lock);
-     silc_list_del(engine->streams, stream);
-     /* Remove per scheduler context, if it is not used anymore */
      if (stream->sc) {
+       engine = stream->sc->engine;
+       silc_mutex_lock(engine->lock);
+       silc_list_del(engine->streams, stream);
+       /* Remove per scheduler context, if it is not used anymore */
        stream->sc->stream_count--;
        if (!stream->sc->stream_count)
        silc_hash_table_del(engine->contexts, stream->sc->schedule);
+       silc_mutex_unlock(engine->lock);
      }
-     silc_mutex_unlock(engine->lock);
  
      /* Destroy the underlaying stream */
      if (stream->stream)
    silc_free(stream->src_id);
    silc_free(stream->dst_id);
  
-   silc_atomic_uninit8(&stream->refcnt);
+   silc_atomic_uninit32(&stream->refcnt);
    silc_mutex_free(stream->lock);
    silc_free(stream);
  }
@@@ -1001,7 -1001,7 +1002,7 @@@ void silc_packet_stream_set_iv_included
  /* Links `callbacks' to `stream' for specified packet types */
  
  static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
-                                          SilcPacketCallbacks *callbacks,
+                                          const SilcPacketCallbacks *callbacks,
                                           void *callback_context,
                                           int priority, va_list ap)
  {
      stream->process = silc_dlist_init();
      if (!stream->process) {
        silc_mutex_unlock(stream->lock);
+       silc_free(p);
        return FALSE;
      }
    }
  /* Links `callbacks' to `stream' for specified packet types */
  
  SilcBool silc_packet_stream_link(SilcPacketStream stream,
-                                SilcPacketCallbacks *callbacks,
+                                const SilcPacketCallbacks *callbacks,
                                 void *callback_context,
                                 int priority, ...)
  {
  /* Unlinks `callbacks' from `stream'. */
  
  void silc_packet_stream_unlink(SilcPacketStream stream,
-                              SilcPacketCallbacks *callbacks,
+                              const SilcPacketCallbacks *callbacks,
                               void *callback_context)
  {
    SilcPacketProcess p;
@@@ -1153,10 -1154,10 +1155,10 @@@ SilcBool silc_packet_get_sender(SilcPac
  
  void silc_packet_stream_ref(SilcPacketStream stream)
  {
-   silc_atomic_add_int8(&stream->refcnt, 1);
+   silc_atomic_add_int32(&stream->refcnt, 1);
    SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
-                 silc_atomic_get_int8(&stream->refcnt) - 1,
-                 silc_atomic_get_int8(&stream->refcnt)));
+                 silc_atomic_get_int32(&stream->refcnt) - 1,
+                 silc_atomic_get_int32(&stream->refcnt)));
  }
  
  /* Unreference packet stream */
  void silc_packet_stream_unref(SilcPacketStream stream)
  {
    SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
-                 silc_atomic_get_int8(&stream->refcnt),
-                 silc_atomic_get_int8(&stream->refcnt) - 1));
-   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0)
+                 silc_atomic_get_int32(&stream->refcnt),
+                 silc_atomic_get_int32(&stream->refcnt) - 1));
+   if (silc_atomic_sub_int32(&stream->refcnt, 1) > 0)
      return;
-   silc_atomic_add_int8(&stream->refcnt, 1);
+   silc_atomic_add_int32(&stream->refcnt, 1);
    silc_packet_stream_destroy(stream);
  }
  
@@@ -1323,6 -1324,7 +1325,7 @@@ SilcBool silc_packet_set_ids(SilcPacket
  {
    SilcUInt32 len;
    unsigned char tmp[32];
+   void *tmp_id;
  
    if (!src_id && !dst_id)
      return FALSE;
    if (src_id) {
      SILC_LOG_DEBUG(("Setting source ID to packet stream %p", stream));
  
-     silc_free(stream->src_id);
      if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
        silc_mutex_unlock(stream->lock);
        return FALSE;
      }
-     stream->src_id = silc_memdup(tmp, len);
-     if (!stream->src_id) {
+     tmp_id = silc_memdup(tmp, len);
+     if (!tmp_id) {
        silc_mutex_unlock(stream->lock);
        return FALSE;
      }
+     silc_free(stream->src_id);
+     stream->src_id = tmp_id;
      stream->src_id_type = src_id_type;
      stream->src_id_len = len;
    }
    if (dst_id) {
      SILC_LOG_DEBUG(("Setting destination ID to packet stream %p", stream));
  
-     silc_free(stream->dst_id);
      if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
        silc_mutex_unlock(stream->lock);
        return FALSE;
      }
-     stream->dst_id = silc_memdup(tmp, len);
-     if (!stream->dst_id) {
+     tmp_id = silc_memdup(tmp, len);
+     if (!tmp_id) {
        silc_mutex_unlock(stream->lock);
        return FALSE;
      }
+     silc_free(stream->dst_id);
+     stream->dst_id = tmp_id;
      stream->dst_id_type = dst_id_type;
      stream->dst_id_len = len;
    }
@@@ -1490,7 -1494,7 +1495,7 @@@ static inline void silc_packet_send_ctr
  
      SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
  
 -    /* Set new nonce to counter block */
 +    /* Set new IV to counter block */
      memcpy(iv + 4, ret_iv, 8);
    } else {
      /* Increment 64-bit packet counter */
    SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
  }
  
 -/* Internal routine to assemble outgoing packet.  Assembles and encryptes
 +/* Internal routine to assemble outgoing packet.  Assembles and encrypts
     the packet.  The silc_packet_stream_write needs to be called to send it
     after this returns TRUE. */
  
@@@ -1614,12 -1618,6 +1619,12 @@@ static inline SilcBool silc_packet_send
  
    silc_mutex_lock(stream->lock);
  
 +  if (silc_unlikely(stream->destroyed)) {
 +    SILC_LOG_DEBUG(("Stream %p is destroyed, cannot send packet", stream));
 +    silc_mutex_unlock(stream->lock);
 +    return FALSE;
 +  }
 +
    /* Get packet pointer from the outgoing buffer */
    if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
                                              + psnlen, hmac, &packet))) {
@@@ -2346,7 -2344,7 +2351,7 @@@ silc_packet_wait_packet_receive(SilcPac
                                void *stream_context);
  
  /* Packet waiting callbacks */
- static SilcPacketCallbacks silc_packet_wait_cbs =
+ static const SilcPacketCallbacks silc_packet_wait_cbs =
  {
    silc_packet_wait_packet_receive, NULL, NULL
  };
@@@ -2535,7 -2533,7 +2540,7 @@@ typedef struct 
  } *SilcPacketWrapperStream;
  
  /* Packet wrapper callbacks */
- static SilcPacketCallbacks silc_packet_wrap_cbs =
+ static const SilcPacketCallbacks silc_packet_wrap_cbs =
  {
    silc_packet_wrap_packet_receive, NULL, NULL
  };
index 06161b3344f861a978db95727f1534547897d110,3e92d0ed86a50ca24b08748836f17651d1b3255e..d44e9faf35d7354fdb4632267f405ddd16cd2d4b
  
  /************************** Types and definitions ***************************/
  
 +SILC_FSM_STATE(silc_connauth_st_initiator_start);
 +SILC_FSM_STATE(silc_connauth_st_initiator_auth_send);
 +SILC_FSM_STATE(silc_connauth_st_initiator_result);
 +SILC_FSM_STATE(silc_connauth_st_initiator_failure);
 +SILC_FSM_STATE(silc_connauth_st_responder_start);
 +SILC_FSM_STATE(silc_connauth_st_responder_authenticate);
 +SILC_FSM_STATE(silc_connauth_st_responder_authenticate_pk);
 +SILC_FSM_STATE(silc_connauth_st_responder_success);
 +SILC_FSM_STATE(silc_connauth_st_responder_failure);
 +
  static SilcBool silc_connauth_packet_receive(SilcPacketEngine engine,
                                             SilcPacketStream stream,
                                             SilcPacket packet,
@@@ -43,7 -33,6 +43,7 @@@ struct SilcConnAuthStruct 
    SilcSKE ske;
    SilcFSM fsm;
    SilcAsyncOperationStruct op;
 +  SilcAsyncOperation key_op;
    SilcConnectionType conn_type;
    SilcAuthMethod auth_method;
    void *auth_data;
@@@ -87,44 -76,19 +87,44 @@@ static SilcBool silc_connauth_packet_re
  static void silc_connauth_abort(SilcAsyncOperation op, void *context)
  {
    SilcConnAuth connauth = context;
 +  if (connauth->key_op)
 +    silc_async_abort(connauth->key_op, NULL, NULL);
    connauth->aborted = TRUE;
  }
  
 +/* Signature callback */
 +
 +static void silc_connauth_get_signature_cb(SilcBool success,
 +                                         const unsigned char *signature,
 +                                         SilcUInt32 signature_len,
 +                                         void *context)
 +{
 +  SilcConnAuth connauth = context;
 +
 +  connauth->key_op = NULL;
 +
 +  if (!success) {
 +    silc_fsm_next(connauth->fsm, silc_connauth_st_initiator_failure);
 +    SILC_FSM_CALL_CONTINUE(connauth->fsm);
 +    return;
 +  }
 +
 +  connauth->auth_data = silc_memdup(signature, signature_len);
 +  connauth->auth_data_len = signature_len;
 +
 +  SILC_FSM_CALL_CONTINUE(connauth->fsm);
 +}
 +
  /* Generates signature for public key based authentication */
  
 -static SilcBool silc_connauth_get_signature(SilcConnAuth connauth,
 -                                          unsigned char **auth_data,
 -                                          SilcUInt32 *auth_data_len)
 +static SilcAsyncOperation
 +silc_connauth_get_signature(SilcConnAuth connauth)
  {
 -  int len;
 +  SilcAsyncOperation op;
    SilcSKE ske;
    SilcPrivateKey private_key;
    SilcBuffer auth;
 +  int len;
  
    SILC_LOG_DEBUG(("Compute signature"));
  
       KE Start Payload. */
    len = ske->hash_len + silc_buffer_len(ske->start_payload_copy);
    auth = silc_buffer_alloc_size(len);
 -  if (!auth)
 -    return FALSE;
 +  if (!auth) {
 +    silc_connauth_get_signature_cb(FALSE, NULL, 0, connauth);
 +    return NULL;
 +  }
    silc_buffer_format(auth,
 -                   SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
 -                   SILC_STR_UI_XNSTRING(
 -                             ske->start_payload_copy->data,
 -                             silc_buffer_len(ske->start_payload_copy)),
 +                   SILC_STR_DATA(ske->hash, ske->hash_len),
 +                   SILC_STR_DATA(ske->start_payload_copy->data,
 +                                 silc_buffer_len(ske->start_payload_copy)),
                     SILC_STR_END);
  
 -  len = ((silc_pkcs_private_key_get_len(private_key) + 7) / 8) + 1;
 -  *auth_data = silc_calloc(len, sizeof(**auth_data));
 -  if (*auth_data == NULL) {
 -    silc_buffer_free(auth);
 -    return FALSE;
 -  }
 -
    /* Compute signature */
 -  if (!silc_pkcs_sign(private_key, auth->data, silc_buffer_len(auth),
 -                    *auth_data, len, auth_data_len, TRUE, ske->prop->hash)) {
 -    silc_free(*auth_data);
 -    silc_buffer_free(auth);
 -    return FALSE;
 -  }
 +  op = silc_pkcs_sign_async(private_key, auth->data, silc_buffer_len(auth),
 +                          TRUE, ske->prop->hash, ske->rng,
 +                          silc_connauth_get_signature_cb, connauth);
  
    silc_buffer_free(auth);
 -  return TRUE;
 +
 +  return op;
 +}
 +
 +/* Verify callback */
 +
 +static void silc_connauth_verify_signature_cb(SilcBool success,
 +                                            void *context)
 +{
 +  SilcConnAuth connauth = context;
 +
 +  connauth->key_op = NULL;
 +  silc_free(connauth->auth_data);
 +
 +  if (!success) {
 +    SILC_LOG_DEBUG(("Invalid signature"));
 +    silc_fsm_next(connauth->fsm, silc_connauth_st_responder_failure);
 +    SILC_FSM_CALL_CONTINUE(connauth->fsm);
 +    return;
 +  }
 +
 +  SILC_LOG_DEBUG(("Signature is Ok"));
 +  SILC_FSM_CALL_CONTINUE(connauth->fsm);
  }
  
  /* Verifies digital signature */
  
 -static SilcBool silc_connauth_verify_signature(SilcConnAuth connauth,
 -                                             SilcPublicKey pub_key,
 -                                             unsigned char *sign,
 -                                             SilcUInt32 sign_len)
 +static SilcAsyncOperation
 +silc_connauth_verify_signature(SilcConnAuth connauth,
 +                             SilcPublicKey pub_key,
 +                             unsigned char *sign,
 +                             SilcUInt32 sign_len)
  {
 -  int len;
 +  SilcAsyncOperation op;
    SilcBuffer auth;
    SilcSKE ske = connauth->ske;
 +  int len;
  
 -  if (!pub_key || !sign)
 -    return FALSE;
 +  if (!pub_key || !sign) {
 +    silc_connauth_verify_signature_cb(FALSE, connauth);
 +    return NULL;
 +  }
  
    /* Make the authentication data. Protocol says it is HASH plus
       KE Start Payload. */
    len = ske->hash_len + silc_buffer_len(ske->start_payload_copy);
    auth = silc_buffer_alloc_size(len);
 -  if (!auth)
 -    return FALSE;
 +  if (!auth) {
 +    silc_connauth_verify_signature_cb(FALSE, connauth);
 +    return NULL;
 +  }
    silc_buffer_format(auth,
                     SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
                     SILC_STR_UI_XNSTRING(
                     SILC_STR_END);
  
    /* Verify signature */
 -  if (!silc_pkcs_verify(pub_key, sign, sign_len, auth->data,
 -                      silc_buffer_len(auth), ske->prop->hash)) {
 -    silc_buffer_free(auth);
 -    return FALSE;
 -  }
 +  op = silc_pkcs_verify_async(pub_key, sign, sign_len, auth->data,
 +                            silc_buffer_len(auth), TRUE, ske->prop->hash,
 +                            silc_connauth_verify_signature_cb, connauth);
  
    silc_buffer_free(auth);
  
 -  return TRUE;
 +  return op;
  }
  
  /* Timeout */
@@@ -225,8 -172,6 +225,8 @@@ SILC_TASK_CALLBACK(silc_connauth_timeou
  {
    SilcConnAuth connauth = context;
    SILC_LOG_DEBUG(("Protocol timeout"));
 +  if (connauth->key_op)
 +    silc_async_abort(connauth->key_op, NULL, NULL);
    connauth->aborted = TRUE;
    silc_fsm_continue_sync(connauth->fsm);
  }
@@@ -310,9 -255,18 +310,9 @@@ SilcSKE silc_connauth_get_ske(SilcConnA
  
  /******************************** Initiator *********************************/
  
 -SILC_FSM_STATE(silc_connauth_st_initiator_start);
 -SILC_FSM_STATE(silc_connauth_st_initiator_result);
 -SILC_FSM_STATE(silc_connauth_st_initiator_failure);
 -
  SILC_FSM_STATE(silc_connauth_st_initiator_start)
  {
    SilcConnAuth connauth = fsm_context;
 -  SilcBuffer packet;
 -  int payload_len = 0;
 -  unsigned char *auth_data = NULL;
 -  SilcUInt32 auth_data_len = 0;
 -  SilcPacketFlags flags = 0;
  
    SILC_LOG_DEBUG(("Start"));
  
                                   silc_connauth_timeout, connauth,
                                   connauth->timeout_secs, 0);
  
 +  /** Generate auth data */
 +  silc_fsm_next(fsm, silc_connauth_st_initiator_auth_send);
 +
 +  /* Get authentication data */
    switch (connauth->auth_method) {
    case SILC_AUTH_NONE:
      /* No authentication required */
 +    connauth->auth_data = NULL;
 +    connauth->auth_data_len = 0;
 +    return SILC_FSM_CONTINUE;
      break;
  
    case SILC_AUTH_PASSWORD:
 -    auth_data = silc_memdup(connauth->auth_data, connauth->auth_data_len);
 -    if (!auth_data) {
 -      /** Out of memory */
 -      silc_fsm_next(fsm, silc_connauth_st_initiator_failure);
 -      return SILC_FSM_CONTINUE;
 -    }
 -    auth_data_len = connauth->auth_data_len;
 -    flags = SILC_PACKET_FLAG_LONG_PAD;
 +    /* We have authentication data already */
 +    return SILC_FSM_CONTINUE;
      break;
  
    case SILC_AUTH_PUBLIC_KEY:
 -    if (!silc_connauth_get_signature(connauth, &auth_data, &auth_data_len)) {
 -      /** Error computing signature */
 -      silc_fsm_next(fsm, silc_connauth_st_initiator_failure);
 -      return SILC_FSM_CONTINUE;
 -    }
 +    /* Compute signature */
 +    SILC_FSM_CALL(connauth->key_op = silc_connauth_get_signature(connauth));
 +    /* NOT REACHED */
      break;
    }
  
 -  payload_len = 4 + auth_data_len;
 +  silc_fsm_next(fsm, silc_connauth_st_initiator_failure);
 +  return SILC_FSM_CONTINUE;
 +}
 +
 +SILC_FSM_STATE(silc_connauth_st_initiator_auth_send)
 +{
 +  SilcConnAuth connauth = fsm_context;
 +  SilcBuffer packet;
 +  int payload_len ;
 +  SilcPacketFlags flags = 0;
 +
 +  if (connauth->auth_method == SILC_AUTH_PASSWORD)
 +    flags |= SILC_PACKET_FLAG_LONG_PAD;
 +
 +  payload_len = 4 + connauth->auth_data_len;
    packet = silc_buffer_alloc_size(payload_len);
    if (!packet) {
      /** Out of memory */
    silc_buffer_format(packet,
                     SILC_STR_UI_SHORT(payload_len),
                     SILC_STR_UI_SHORT(connauth->conn_type),
 -                   SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
 +                   SILC_STR_DATA(connauth->auth_data,
 +                                 connauth->auth_data_len),
                     SILC_STR_END);
  
 +  silc_free(connauth->auth_data);
 +
    /* Send the packet */
    if (!silc_packet_send(connauth->ske->stream, SILC_PACKET_CONNECTION_AUTH,
                        flags, packet->data, silc_buffer_len(packet))) {
      return SILC_FSM_CONTINUE;
    }
  
 -  if (auth_data) {
 -    memset(auth_data, 0, auth_data_len);
 -    silc_free(auth_data);
 -  }
    silc_buffer_free(packet);
  
    /** Wait for responder */
@@@ -481,14 -423,10 +481,14 @@@ silc_connauth_initiator(SilcConnAuth co
  
    connauth->conn_type = conn_type;
    connauth->auth_method = auth_method;
 -  connauth->auth_data = auth_data;
 -  connauth->auth_data_len = auth_data_len;
    connauth->completion = completion;
    connauth->context = context;
 +  connauth->auth_data = auth_data;
 +  connauth->auth_data_len = auth_data_len;
 +
 +  if (connauth->auth_method == SILC_AUTH_PASSWORD)
 +    connauth->auth_data = silc_memdup(connauth->auth_data,
 +                                    connauth->auth_data_len);
  
    /* Link to packet stream to get packets */
    silc_packet_stream_link(connauth->ske->stream,
  
  /******************************** Responder *********************************/
  
 -SILC_FSM_STATE(silc_connauth_st_responder_start);
 -SILC_FSM_STATE(silc_connauth_st_responder_authenticate);
 -SILC_FSM_STATE(silc_connauth_st_responder_authenticate_pk);
 -SILC_FSM_STATE(silc_connauth_st_responder_success);
 -SILC_FSM_STATE(silc_connauth_st_responder_failure);
 -
  SILC_FSM_STATE(silc_connauth_st_responder_start)
  {
    SilcConnAuth connauth = fsm_context;
@@@ -661,8 -605,7 +661,8 @@@ SILC_FSM_STATE(silc_connauth_st_respond
  
      /** Find public key */
      silc_fsm_next(fsm, silc_connauth_st_responder_authenticate_pk);
 -    SILC_FSM_CALL(silc_skr_find(repository, silc_fsm_get_schedule(fsm),
 +    SILC_FSM_CALL(connauth->key_op =
 +                silc_skr_find(repository, silc_fsm_get_schedule(fsm),
                                find, silc_connauth_skr_callback,
                                connauth));
      /* NOT REACHED */
@@@ -696,14 -639,25 +696,16 @@@ SILC_FSM_STATE(silc_connauth_st_respond
    SILC_LOG_DEBUG(("Found %d public keys",
                  silc_dlist_count(connauth->public_keys)));
  
 -  /* Verify signature */
 +  /** Verify signature */
    key = silc_dlist_get(connauth->public_keys);
 -  if (!silc_connauth_verify_signature(connauth, key->key,
 -                                    connauth->auth_data,
 -                                    connauth->auth_data_len)) {
 -    /** Invalid signature */
 -    SILC_LOG_DEBUG(("Invalid signature"));
 -    silc_free(connauth->auth_data);
 -    silc_fsm_next(fsm, silc_connauth_st_responder_failure);
 -    return SILC_FSM_CONTINUE;
 -  }
 -
 -  silc_free(connauth->auth_data);
 +  silc_fsm_next(fsm, silc_connauth_st_responder_success);
 +  SILC_FSM_CALL(connauth->key_op =
 +              silc_connauth_verify_signature(connauth, key->key,
 +                                             connauth->auth_data,
 +                                             connauth->auth_data_len));
 +  /* NOT REACHED */
+   SILC_LOG_DEBUG(("Signature is Ok"));
 -
 -  /** Authentication successful */
 -  silc_fsm_next(fsm, silc_connauth_st_responder_success);
 -  return SILC_FSM_CONTINUE;
  }
  
  SILC_FSM_STATE(silc_connauth_st_responder_success)
diff --combined lib/silcske/silcske.c
index 7331e23513c5c61d82c250bd35ab6bcb475b587d,caf2579628bf9a1a426057a5179f2949dfa5d07e..fece34b67a8ee872a0e4cf792f6153a0f7311afe
@@@ -4,7 -4,7 +4,7 @@@
  
    Author: Pekka Riikonen <priikone@silcnet.org>
  
-   Copyright (C) 2000 - 2007 Pekka Riikonen
+   Copyright (C) 2000 - 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
@@@ -37,10 -37,8 +37,10 @@@ struct SilcSKECallbacksStruct 
  SILC_FSM_STATE(silc_ske_st_initiator_start);
  SILC_FSM_STATE(silc_ske_st_initiator_phase1);
  SILC_FSM_STATE(silc_ske_st_initiator_phase2);
 +SILC_FSM_STATE(silc_ske_st_initiator_phase2_send);
  SILC_FSM_STATE(silc_ske_st_initiator_phase3);
  SILC_FSM_STATE(silc_ske_st_initiator_phase4);
 +SILC_FSM_STATE(silc_ske_st_initiator_phase5);
  SILC_FSM_STATE(silc_ske_st_initiator_end);
  SILC_FSM_STATE(silc_ske_st_initiator_aborted);
  SILC_FSM_STATE(silc_ske_st_initiator_error);
@@@ -50,7 -48,6 +50,7 @@@ SILC_FSM_STATE(silc_ske_st_responder_ph
  SILC_FSM_STATE(silc_ske_st_responder_phase2);
  SILC_FSM_STATE(silc_ske_st_responder_phase4);
  SILC_FSM_STATE(silc_ske_st_responder_phase5);
 +SILC_FSM_STATE(silc_ske_st_responder_phase5_send);
  SILC_FSM_STATE(silc_ske_st_responder_end);
  SILC_FSM_STATE(silc_ske_st_responder_aborted);
  SILC_FSM_STATE(silc_ske_st_responder_failure);
@@@ -139,8 -136,6 +139,8 @@@ static SilcPacketCallbacks silc_ske_str
  static void silc_ske_abort(SilcAsyncOperation op, void *context)
  {
    SilcSKE ske = context;
 +  if (ske->key_op)
 +    silc_async_abort(ske->key_op, NULL, NULL);
    ske->aborted = TRUE;
  }
  
@@@ -633,7 -628,7 +633,7 @@@ static SilcSKEStatus silc_ske_create_rn
                                         SilcMPInt *rnd)
  {
    SilcSKEStatus status = SILC_SKE_STATUS_OK;
 -  unsigned char *string;
 +  unsigned char string[2048];
    SilcUInt32 l;
  
    if (!len)
    l = ((len - 1) / 8);
  
    /* Get the random number as string */
 -  string = silc_rng_get_rn_data(ske->rng, l);
 -  if (!string)
 +  if (!silc_rng_get_rn_data(ske->rng, l, string, sizeof(string)))
      return SILC_SKE_STATUS_OUT_OF_MEMORY;
  
    /* Decode the string into a MP integer */
      status = SILC_SKE_STATUS_ERROR;
  
    memset(string, 'F', l);
 -  silc_free(string);
  
    return status;
  }
@@@ -863,7 -860,7 +863,7 @@@ silc_ske_assemble_security_properties(S
    rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
  
    /* Get supported encryption algorithms */
 -  rp->enc_alg_list = silc_cipher_get_supported();
 +  rp->enc_alg_list = silc_cipher_get_supported(TRUE);
    rp->enc_alg_len = strlen(rp->enc_alg_list);
  
    /* Get supported hash algorithms */
@@@ -1003,86 -1000,6 +1003,86 @@@ SILC_TASK_CALLBACK(silc_ske_timeout
    silc_fsm_continue_sync(&ske->fsm);
  }
  
 +/* Initiator signature callback */
 +
 +static void silc_ske_initiator_sign_cb(SilcBool success,
 +                                     const unsigned char *signature,
 +                                     SilcUInt32 signature_len,
 +                                     void *context)
 +{
 +  SilcSKE ske = context;
 +
 +  ske->key_op = NULL;
 +
 +  if (ske->aborted) {
 +    silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure);
 +    SILC_FSM_CALL_CONTINUE(&ske->fsm);
 +    return;
 +  }
 +
 +  ske->ke1_payload->sign_data = silc_memdup(signature, signature_len);
 +  if (ske->ke1_payload->sign_data)
 +    ske->ke1_payload->sign_len = signature_len;
 +
 +  SILC_FSM_CALL_CONTINUE(&ske->fsm);
 +}
 +
 +/* Responder signature callback */
 +
 +static void silc_ske_responder_sign_cb(SilcBool success,
 +                                     const unsigned char *signature,
 +                                     SilcUInt32 signature_len,
 +                                     void *context)
 +{
 +  SilcSKE ske = context;
 +
 +  ske->key_op = NULL;
 +
 +  if (ske->aborted) {
 +    silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure);
 +    SILC_FSM_CALL_CONTINUE(&ske->fsm);
 +    return;
 +  }
 +
 +  ske->ke2_payload->sign_data = silc_memdup(signature, signature_len);
 +  if (ske->ke2_payload->sign_data)
 +    ske->ke2_payload->sign_len = signature_len;
 +
 +  SILC_FSM_CALL_CONTINUE(&ske->fsm);
 +}
 +
 +/* Verify callback */
 +
 +static void silc_ske_verify_cb(SilcBool success, void *context)
 +{
 +  SilcSKE ske = context;
 +
 +  ske->key_op = NULL;
 +
 +  if (ske->aborted) {
 +    if (ske->responder)
 +      silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure);
 +    else
 +      silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure);
 +    SILC_FSM_CALL_CONTINUE(&ske->fsm);
 +    return;
 +  }
 +
 +  if (!success) {
 +    SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
 +    ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
 +    if (ske->responder)
 +      silc_fsm_next(&ske->fsm, silc_ske_st_responder_error);
 +    else
 +      silc_fsm_next(&ske->fsm, silc_ske_st_initiator_error);
 +    SILC_FSM_CALL_CONTINUE(&ske->fsm);
 +    return;
 +  }
 +
 +  SILC_LOG_DEBUG(("Signature is Ok"));
 +  SILC_FSM_CALL_CONTINUE(&ske->fsm);
 +}
 +
  /******************************* Protocol API *******************************/
  
  /* Allocates new SKE object. */
@@@ -1420,6 -1337,7 +1420,6 @@@ SILC_FSM_STATE(silc_ske_st_initiator_ph
  {
    SilcSKE ske = fsm_context;
    SilcSKEStatus status;
 -  SilcBuffer payload_buf;
    SilcMPInt *x;
    SilcSKEKEPayload payload;
    SilcUInt32 pk_len;
    silc_mp_init(&payload->x);
    silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
                  &ske->prop->group->group);
 +  ske->x = x;
  
    /* Get public key */
 -  payload->pk_data = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
 +  payload->pk_data = silc_pkcs_public_key_encode(NULL, ske->public_key,
 +                                               &pk_len);
    if (!payload->pk_data) {
      /** Error encoding public key */
      silc_mp_uninit(x);
      silc_free(x);
 +    ske->x = NULL;
      silc_mp_uninit(&payload->x);
      silc_free(payload);
      ske->ke1_payload = NULL;
    payload->pk_len = pk_len;
    payload->pk_type = silc_pkcs_get_type(ske->public_key);
  
 +  /** Send KE1 packet */
 +  silc_fsm_next(fsm, silc_ske_st_initiator_phase2_send);
 +
    /* Compute signature data if we are doing mutual authentication */
    if (ske->private_key && ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) {
 -    unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1];
 -    SilcUInt32 hash_len, sign_len;
 +    unsigned char hash[SILC_HASH_MAXLEN];
 +    SilcUInt32 hash_len;
  
      SILC_LOG_DEBUG(("We are doing mutual authentication"));
      SILC_LOG_DEBUG(("Computing HASH_i value"));
      SILC_LOG_DEBUG(("Signing HASH_i value"));
  
      /* Sign the hash value */
 -    if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
 -                      sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) {
 -      /** Error computing signature */
 -      silc_mp_uninit(x);
 -      silc_free(x);
 -      silc_mp_uninit(&payload->x);
 -      silc_free(payload->pk_data);
 -      silc_free(payload);
 -      ske->ke1_payload = NULL;
 -      ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
 -      silc_fsm_next(fsm, silc_ske_st_initiator_error);
 -      return SILC_FSM_CONTINUE;
 -    }
 -    payload->sign_data = silc_memdup(sign, sign_len);
 -    if (payload->sign_data)
 -      payload->sign_len = sign_len;
 -    memset(sign, 0, sizeof(sign));
 +    SILC_FSM_CALL(ske->key_op =
 +                silc_pkcs_sign_async(ske->private_key, hash, hash_len, FALSE,
 +                                     ske->prop->hash, ske->rng,
 +                                     silc_ske_initiator_sign_cb, ske));
 +    /* NOT REACHED */
    }
  
 +  return SILC_FSM_CONTINUE;
 +}
 +
 +/* Send KE1 packet */
 +
 +SILC_FSM_STATE(silc_ske_st_initiator_phase2_send)
 +{
 +  SilcSKE ske = fsm_context;
 +  SilcSKEStatus status;
 +  SilcBuffer payload_buf;
 +  SilcSKEKEPayload payload;
 +
 +  SILC_LOG_DEBUG(("Start"));
 +
 +  payload = ske->ke1_payload;
 +
    status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
    if (status != SILC_SKE_STATUS_OK) {
      /** Error encoding KE payload */
 -    silc_mp_uninit(x);
 -    silc_free(x);
      silc_mp_uninit(&payload->x);
      silc_free(payload->pk_data);
      silc_free(payload->sign_data);
      return SILC_FSM_CONTINUE;
    }
  
 -  ske->x = x;
 -
 -  /* Check for backwards compatibility */
 -
    /* Send the packet. */
    if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE_1, 0,
                            silc_buffer_data(payload_buf),
@@@ -1681,6 -1595,7 +1681,6 @@@ SILC_FSM_STATE(silc_ske_st_initiator_ph
    SilcSKEKEPayload payload;
    unsigned char hash[SILC_HASH_MAXLEN];
    SilcUInt32 hash_len;
 -  int key_len, block_len;
  
    if (ske->aborted) {
      /** Aborted */
    ske->hash = silc_memdup(hash, hash_len);
    ske->hash_len = hash_len;
  
 +  /** Send reply */
 +  silc_fsm_next(fsm, silc_ske_st_initiator_phase5);
 +
    if (ske->prop->public_key) {
      SILC_LOG_DEBUG(("Public key is authentic"));
      SILC_LOG_DEBUG(("Verifying signature (HASH)"));
  
      /* Verify signature */
 -    if (!silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
 -                        payload->sign_len, hash, hash_len, NULL)) {
 -      SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
 -      status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
 -      goto err;
 -    }
 +    SILC_FSM_CALL(ske->key_op =
 +                silc_pkcs_verify_async(ske->prop->public_key,
 +                                       payload->sign_data,
 +                                       payload->sign_len, hash,
 +                                       hash_len, FALSE, NULL,
 +                                       silc_ske_verify_cb, ske));
 +    /* NOT REACHED */
 +  }
-   return SILC_FSM_CONTINUE;
 + err:
 +  memset(hash, 'F', sizeof(hash));
 +  silc_ske_payload_ke_free(payload);
 +  ske->ke2_payload = NULL;
 +
 +  silc_mp_uninit(ske->KEY);
 +  silc_free(ske->KEY);
 +  ske->KEY = NULL;
  
 -    SILC_LOG_DEBUG(("Signature is Ok"));
 -    memset(hash, 'F', hash_len);
 +  if (ske->hash) {
 +    memset(ske->hash, 'F', hash_len);
 +    silc_free(ske->hash);
 +    ske->hash = NULL;
    }
  
 +  if (status == SILC_SKE_STATUS_OK)
 +    status = SILC_SKE_STATUS_ERROR;
 +
 +  /** Error */
 +  ske->status = status;
 +  silc_fsm_next(fsm, silc_ske_st_initiator_error);
 +  return SILC_FSM_CONTINUE;
 +}
 +
 +/* Process key material */
 +
 +SILC_FSM_STATE(silc_ske_st_initiator_phase5)
 +{
 +  SilcSKE ske = fsm_context;
 +  SilcSKEStatus status;
 +  unsigned char tmp[4];
 +  SilcUInt32 hash_len;
 +  int key_len, block_len;
 +
    ske->status = SILC_SKE_STATUS_OK;
  
    /* In case we are doing rekey move to finish it.  */
    if (!ske->keymat) {
      SILC_LOG_ERROR(("Error processing key material"));
      status = SILC_SKE_STATUS_ERROR;
 -    goto err;
 +    silc_fsm_next(fsm, silc_ske_st_initiator_error);
 +    return SILC_FSM_CONTINUE;
    }
  
    /* Send SUCCESS packet */
 -  SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash);
 -  if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, hash, 4)) {
 +  SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, tmp);
 +  if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, tmp, 4)) {
      /** Error sending packet */
      SILC_LOG_DEBUG(("Error sending packet"));
      ske->status = SILC_SKE_STATUS_ERROR;
    /** Waiting completion */
    silc_fsm_next(fsm, silc_ske_st_initiator_end);
    return SILC_FSM_WAIT;
 -
 - err:
 -  memset(hash, 'F', sizeof(hash));
 -  silc_ske_payload_ke_free(payload);
 -  ske->ke2_payload = NULL;
 -
 -  silc_mp_uninit(ske->KEY);
 -  silc_free(ske->KEY);
 -  ske->KEY = NULL;
 -
 -  if (ske->hash) {
 -    memset(ske->hash, 'F', hash_len);
 -    silc_free(ske->hash);
 -    ske->hash = NULL;
 -  }
 -
 -  if (status == SILC_SKE_STATUS_OK)
 -    status = SILC_SKE_STATUS_ERROR;
 -
 -  /** Error */
 -  ske->status = status;
 -  silc_fsm_next(fsm, silc_ske_st_initiator_error);
 -  return SILC_FSM_CONTINUE;
  }
  
  /* Protocol completed */
@@@ -1883,8 -1783,7 +1880,8 @@@ SILC_FSM_STATE(silc_ske_st_initiator_fa
    SilcSKE ske = fsm_context;
    SilcUInt32 error = SILC_SKE_STATUS_ERROR;
  
 -  if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
 +  if (ske->packet && ske->packet->type == SILC_PACKET_FAILURE &&
 +      silc_buffer_len(&ske->packet->buffer) == 4) {
      SILC_GET32_MSB(error, ske->packet->buffer.data);
      ske->status = error;
      silc_packet_free(ske->packet);
@@@ -2127,15 -2026,9 +2124,9 @@@ SILC_FSM_STATE(silc_ske_st_responder_ph
    silc_packet_free(ske->packet);
    ske->packet = NULL;
  
-   /* Verify the received public key and verify the signature if we are
-      doing mutual authentication. */
-   if (ske->start_payload &&
-       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
-     SILC_LOG_DEBUG(("We are doing mutual authentication"));
-     if (!recv_payload->pk_data && (ske->callbacks->verify_key ||
-                                  ske->repository)) {
+   /* Verify public key, except in rekey, when it is not sent */
+   if (!ske->rekey) {
+     if (!recv_payload->pk_data) {
        /** Public key not provided */
        SILC_LOG_ERROR(("Remote end did not send its public key (or "
                      "certificate), even though we require it"));
      }
  
      /* Decode the remote's public key */
-     if (recv_payload->pk_data &&
-       !silc_pkcs_public_key_alloc(recv_payload->pk_type,
+     if (!silc_pkcs_public_key_alloc(recv_payload->pk_type,
                                    recv_payload->pk_data,
                                    recv_payload->pk_len,
                                    &ske->prop->public_key)) {
        return SILC_FSM_CONTINUE;
      }
  
-     if (ske->prop->public_key && (ske->callbacks->verify_key ||
-                                 ske->repository)) {
-       SILC_LOG_DEBUG(("Verifying public key"));
+     SILC_LOG_DEBUG(("Verifying public key"));
  
-       /** Waiting public key verification */
-       silc_fsm_next(fsm, silc_ske_st_responder_phase4);
+     /** Waiting public key verification */
+     silc_fsm_next(fsm, silc_ske_st_responder_phase4);
  
-       /* If repository is provided, verify the key from there. */
-       if (ske->repository) {
-       SilcSKRFind find;
+     /* If repository is provided, verify the key from there. */
+     if (ske->repository) {
+       SilcSKRFind find;
  
-       find = silc_skr_find_alloc();
-       if (!find) {
-         ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
-         silc_fsm_next(fsm, silc_ske_st_responder_error);
-         return SILC_FSM_CONTINUE;
-       }
-       silc_skr_find_set_pkcs_type(find,
-                                   silc_pkcs_get_type(ske->prop->public_key));
-       silc_skr_find_set_public_key(find, ske->prop->public_key);
-       silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
-       /* Find key from repository */
-       SILC_FSM_CALL(silc_skr_find(ske->repository,
-                                   silc_fsm_get_schedule(fsm), find,
-                                   silc_ske_skr_callback, ske));
-       } else {
-       /* Verify from application */
+       find = silc_skr_find_alloc();
+       if (!find) {
+       ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
+       silc_fsm_next(fsm, silc_ske_st_responder_error);
+       return SILC_FSM_CONTINUE;
+       }
+       silc_skr_find_set_pkcs_type(find,
+                                 silc_pkcs_get_type(ske->prop->public_key));
+       silc_skr_find_set_public_key(find, ske->prop->public_key);
+       silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
+       /* Find key from repository */
+       SILC_FSM_CALL(silc_skr_find(ske->repository,
+                                 silc_fsm_get_schedule(fsm), find,
+                                 silc_ske_skr_callback, ske));
+     } else {
+       /* Verify from application */
+       if (ske->callbacks->verify_key)
        SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
                                                 ske->callbacks->context,
                                                 silc_ske_pk_verified, NULL));
-       }
-       /* NOT REACHED */
      }
    }
  
    return SILC_FSM_CONTINUE;
  }
  
 -/* Phase-4. Generate KE2 payload */
 +/* Phase-4. Generate KE2 payload, verify signature */
  
  SILC_FSM_STATE(silc_ske_st_responder_phase4)
  {
    SilcSKE ske = fsm_context;
    SilcSKEStatus status;
 -  SilcSKEKEPayload recv_payload, send_payload;
 -  SilcMPInt *x, *KEY;
 +  SilcSKEKEPayload recv_payload;
  
    if (ske->aborted) {
      /** Aborted */
  
    recv_payload = ske->ke1_payload;
  
 +  /** Send KE2 packet */
 +  silc_fsm_next(fsm, silc_ske_st_responder_phase5);
 +
    /* The public key verification was performed only if the Mutual
       Authentication flag is set. */
    if (ske->start_payload &&
      unsigned char hash[SILC_HASH_MAXLEN];
      SilcUInt32 hash_len;
  
-     SILC_LOG_DEBUG(("Public key is authentic"));
+     SILC_LOG_DEBUG(("We are doing mutual authentication"));
  
      /* Compute the hash value */
      status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
      SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
  
      /* Verify signature */
 -    if (!silc_pkcs_verify(ske->prop->public_key, recv_payload->sign_data,
 -                        recv_payload->sign_len, hash, hash_len, NULL)) {
 -      /** Incorrect signature */
 -      SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
 -      ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
 -      silc_fsm_next(fsm, silc_ske_st_responder_error);
 -      return SILC_FSM_CONTINUE;
 -    }
 +    SILC_FSM_CALL(ske->key_op =
 +                silc_pkcs_verify_async(ske->prop->public_key,
 +                                       recv_payload->sign_data,
 +                                       recv_payload->sign_len,
 +                                       hash, hash_len, FALSE, NULL,
 +                                       silc_ske_verify_cb, ske));
 +    /* NOT REACHED */
 +  }
  
 -    SILC_LOG_DEBUG(("Signature is Ok"));
 +  return SILC_FSM_CONTINUE;
 +}
  
 -    memset(hash, 'F', hash_len);
 -  }
 +/* Phase-5.  Send KE2 payload */
 +
 +SILC_FSM_STATE(silc_ske_st_responder_phase5)
 +{
 +  SilcSKE ske = fsm_context;
 +  SilcSKEStatus status;
 +  unsigned char hash[SILC_HASH_MAXLEN], *pk;
 +  SilcUInt32 hash_len, pk_len;
 +  SilcMPInt *x, *KEY;
 +  SilcSKEKEPayload send_payload;
 +
 +  SILC_LOG_DEBUG(("Start"));
  
    /* Create the random number x, 1 < x < q. */
    x = silc_calloc(1, sizeof(*x));
                  &ske->prop->group->group);
    ske->KEY = KEY;
  
 -  /** Send KE2 payload */
 -  silc_fsm_next(fsm, silc_ske_st_responder_phase5);
 -  return SILC_FSM_CONTINUE;
 -}
 -
 -/* Phase-5.  Send KE2 payload */
 -
 -SILC_FSM_STATE(silc_ske_st_responder_phase5)
 -{
 -  SilcSKE ske = fsm_context;
 -  SilcSKEStatus status;
 -  SilcBuffer payload_buf;
 -  unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1], *pk;
 -  SilcUInt32 hash_len, sign_len, pk_len;
 -
 -  SILC_LOG_DEBUG(("Start"));
 -
    if (ske->public_key && ske->private_key) {
      SILC_LOG_DEBUG(("Getting public key"));
  
      /* Get the public key */
 -    pk = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
 +    pk = silc_pkcs_public_key_encode(NULL, ske->public_key, &pk_len);
      if (!pk) {
        /** Error encoding public key */
        status = SILC_SKE_STATUS_OUT_OF_MEMORY;
    ske->hash = silc_memdup(hash, hash_len);
    ske->hash_len = hash_len;
  
 +  /** Send KE2 packet */
 +  silc_fsm_next(fsm, silc_ske_st_responder_phase5_send);
 +
    if (ske->public_key && ske->private_key) {
      SILC_LOG_DEBUG(("Signing HASH value"));
  
      /* Sign the hash value */
 -    if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
 -                      sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) {
 -      /** Error computing signature */
 -      status = SILC_SKE_STATUS_SIGNATURE_ERROR;
 -      silc_fsm_next(fsm, silc_ske_st_responder_error);
 -      return SILC_FSM_CONTINUE;
 -    }
 -    ske->ke2_payload->sign_data = silc_memdup(sign, sign_len);
 -    ske->ke2_payload->sign_len = sign_len;
 -    memset(sign, 0, sizeof(sign));
 +    SILC_FSM_CALL(ske->key_op =
 +                silc_pkcs_sign_async(ske->private_key, hash, hash_len, FALSE,
 +                                     ske->prop->hash, ske->rng,
 +                                     silc_ske_responder_sign_cb, ske));
 +    /* NOT REACHED */
    }
 +
 +  return SILC_FSM_CONTINUE;
 +}
 +
 +/* Send KE2 packet */
 +
 +SILC_FSM_STATE(silc_ske_st_responder_phase5_send)
 +{
 +  SilcSKE ske = fsm_context;
 +  SilcSKEStatus status;
 +  SilcBuffer payload_buf;
 +
    ske->ke2_payload->pk_type = silc_pkcs_get_type(ske->public_key);
  
    /* Encode the Key Exchange Payload */
@@@ -2473,8 -2356,7 +2460,8 @@@ SILC_FSM_STATE(silc_ske_st_responder_fa
  
    SILC_LOG_DEBUG(("Key exchange protocol failed"));
  
 -  if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
 +  if (ske->packet && ske->packet->type == SILC_PACKET_FAILURE &&
 +      silc_buffer_len(&ske->packet->buffer) == 4) {
      SILC_GET32_MSB(error, ske->packet->buffer.data);
      ske->status = error;
      silc_packet_free(ske->packet);
@@@ -3533,7 -3415,7 +3520,7 @@@ SilcBool silc_ske_set_keys(SilcSKE ske
            memcpy(iv + 4, keymat->receive_iv, 8);
          else
            memset(iv + 4, 0, 12);
-       }
+       }
  
        silc_cipher_set_iv(*ret_receive_key, iv);
        } else {