From: Pekka Riikonen Date: Mon, 9 Jun 2008 13:50:02 +0000 (+0300) Subject: Merge branch 'silc.1.1.branch' of silc repo X-Git-Tag: 1.2.beta4~12 X-Git-Url: http://git.silcnet.org/gitweb/?p=runtime.git;a=commitdiff_plain;h=afcd9ed820b767d8b6676a9156fa561b24ac2363;hp=-c Merge branch 'silc.1.1.branch' of silc repo Conflicts: CHANGES Makefile.ad Makefile.defines_int.in README.PLUGIN TODO apps/Makefile.ad apps/autodist/CHANGES apps/autodist/autodist.in apps/autodist/doc/autodist.1.in apps/autodist/doc/autodist.texi apps/irssi/Makefile.am apps/irssi/configure.ad apps/irssi/configure.in apps/irssi/docs/Makefile.am apps/irssi/docs/help/Makefile.am.gen apps/irssi/docs/help/in/cmode.in apps/irssi/docs/help/in/cumode.in apps/irssi/docs/help/in/key.in apps/irssi/scripts/Makefile.am apps/irssi/scripts/examples/Makefile.am apps/irssi/src/Makefile.am apps/irssi/src/core/Makefile.am apps/irssi/src/core/modules-load.c apps/irssi/src/fe-common/silc/Makefile.am apps/irssi/src/fe-common/silc/fe-common-silc.c apps/irssi/src/fe-common/silc/fe-silc-messages.c apps/irssi/src/fe-common/silc/module-formats.c apps/irssi/src/fe-text/Makefile.am apps/irssi/src/perl/Makefile.am apps/irssi/src/silc/core/Makefile.am apps/irssi/src/silc/core/client_ops.c apps/irssi/src/silc/core/clientutil.c apps/irssi/src/silc/core/silc-core.c apps/irssi/src/silc/core/silc-servers.c apps/silcd/Makefile.am apps/silcd/command.c apps/silcd/command_reply.c apps/silcd/idlist.c apps/silcd/idlist.h apps/silcd/packet_receive.c apps/silcd/packet_send.c apps/silcd/server.c apps/silcd/server.h apps/silcd/server_backup.c apps/silcd/server_http.c apps/silcd/server_internal.h apps/silcd/server_query.c apps/silcd/server_query.h apps/silcd/server_util.c apps/silcd/server_util.h apps/silcd/serverconfig.c apps/silcd/serverconfig.h apps/silcd/serverid.c apps/silcd/silcd.c configure.ad distdir/autodist distdir/client distdir/common distdir/default distdir/post-dist distdir/pre-dist-client distdir/pre-dist-toolkit distdir/server distdir/toolkit doc/Makefile.ad doc/example_silcd.conf.in doc/examples/silcd.prv doc/examples/silcd.pub doc/silcalgs.conf doc/silcd.conf.yo includes/silc.h.in includes/silcversion.h.in lib/Makefile.ad lib/configure.ad lib/contrib/Makefile.ad lib/doc/command_reply_args.html lib/doc/notifyargs.html lib/doc/porting.html lib/doc/silcclient_using.html lib/silcapputil/silcapputil.c lib/silcapputil/silcidcache.c lib/silcapputil/silcidcache.h lib/silcasn1/silcasn1_decode.c lib/silcasn1/silcasn1_encode.c lib/silcclient/client.c lib/silcclient/client_connect.c lib/silcclient/client_entry.c lib/silcclient/client_entry.h lib/silcclient/client_keyagr.c lib/silcclient/client_notify.c lib/silcclient/client_register.c lib/silcclient/command.c lib/silcclient/command_reply.c lib/silcclient/silcclient.h lib/silcclient/silcclient_entry.h lib/silccore/DIRECTORY lib/silccore/README lib/silccore/silcargument.c lib/silccore/silcattrs.c lib/silccore/silcnotify.c lib/silccore/silcpacket.c lib/silccore/silcpacket.h lib/silccrypt/Makefile.ad lib/silccrypt/aes.c lib/silccrypt/aes_x86.asm lib/silccrypt/aes_x86_64.asm lib/silccrypt/ciphers.h lib/silccrypt/configure.ad lib/silccrypt/rijndael_internal.h lib/silccrypt/silccipher.c lib/silccrypt/silcpk.c lib/silccrypt/silcpkcs.c lib/silccrypt/silcpkcs1.c lib/silcmath/configure.ad lib/silcsftp/sftp_client.c lib/silcsftp/sftp_fs_memory.c lib/silcsim/Makefile.ad lib/silcske/silcconnauth.c lib/silcske/silcske.c lib/silcske/silcske.h lib/silcskr/silcskr.c lib/silcutil/silcatomic.h lib/silcutil/silcbuffer.h lib/silcutil/silcbuffmt.c lib/silcutil/silcdlist.h lib/silcutil/silcfsm.c lib/silcutil/silclog.c lib/silcutil/silcmime.c lib/silcutil/silcnet.h lib/silcutil/silcschedule.c lib/silcutil/silcschedule.h lib/silcutil/silcschedule_i.h lib/silcutil/silcsocketstream_i.h lib/silcutil/silcstack.h lib/silcutil/silctime.c lib/silcutil/silcutil.c lib/silcutil/stacktrace.c lib/silcutil/tests/test_silcschedule.c lib/silcutil/unix/silcunixnet.c lib/silcutil/unix/silcunixthread.c tutorial/mybot/Makefile tutorial/mybot/mybot.c win32/libsilc/libsilc.def win32/libsilcclient/libsilcclient.def --- afcd9ed820b767d8b6676a9156fa561b24ac2363 diff --combined CHANGES index c5f1ab51,128c76fc..9128a66f --- a/CHANGES +++ b/CHANGES @@@ -1,3 -1,185 +1,185 @@@ + Thu Mar 13 13:31:35 EET 2008 Pekka Riikonen + + * 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 + + * 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 + + * Fixed printable fingerprint bufferoverlfow, RedHat bug 372021. + Affected file is lib/silcutil/silcutil.c. + + Sun Dec 30 14:00:46 EET 2007 Pekka Riikonen + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * SILC Server 1.1 Beta4. + + Sun Nov 11 14:15:48 EET 2007 Pekka Riikonen + + * SILC Toolkit 1.1.5. - ++ + Sun Nov 11 11:22:35 EET 2007 Pekka Riikonen + + * 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 + + * SILC Client 1.1.3. + + Mon Nov 5 23:07:58 EET 2007 Pekka Riikonen + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * SILC Toolkit 1.1.3. + + * Fixed possible buffer overflows from SILC Config code. + Patch from Jérémy Bobbio. Affected file is + lib/silcutil/silcconfig.c. + + Sun Aug 26 12:28:49 EEST 2007 Pekka Riikonen + + * 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 + + * 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 + + * 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 + + * 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 + + * SILC Toolkit 1.1.2. + + * SILC Client 1.1.2. + + Mon Jul 2 17:28:47 CEST 2007 Pekka Riikonen + + * 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 * 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 @@@ -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 - * 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]. @@@ -144,7 -326,7 +326,7 @@@ 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 * Added SILC_VERIFY macro which is equivalent to SILC_ASSERT - but is compiled always in. Affected file is + but is compiled always in. Affected file is lib/silcutil/silclog.h. * Use SILC_VERIFY in FSM macros instead of SILC_ASSERT which is @@@ -461,7 -643,7 +643,7 @@@ Wed May 9 19:51:28 EEST 2007 Pekka Ri on WIN32. Affected files are lib/silcutil/silclog_i.h and silclog.c. - * Rewrote WIN32 SILC Scheduler. It now handles non-blocking file + * Rewrote WIN32 SILC Scheduler. It now handles non-blocking file descriptors and sockets better. Though, room for optimization remains. Affected file is lib/silcutil/win32/silcwin32schedule.c. diff --combined distdir/post-dist index cf1f93bd,8323ec7e..3f27c9e9 --- a/distdir/post-dist +++ b/distdir/post-dist @@@ -6,8 -6,9 +6,8 @@@ package=$ distdir=$4 if test -f $distdir.tar.gz; then - sha1sum $distdir.tar.gz > $distdir.tar.gz.sha1 + sha512sum $distdir.tar.gz > $distdir.tar.gz.sum fi if test -f $distdir.tar.bz2; then - sha1sum $distdir.tar.bz2 > $distdir.tar.bz2.sha1 + sha512sum $distdir.tar.bz2 > $distdir.tar.bz2.sum fi - diff --combined lib/silcutil/silcbuffmt.c index 838177d1,98836b61..db798c40 --- a/lib/silcutil/silcbuffmt.c +++ b/lib/silcutil/silcbuffmt.c @@@ -4,7 -4,7 +4,7 @@@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@@ -16,8 -16,9 +16,8 @@@ GNU General Public License for more details. */ -/* $Id$ */ -#include "silc.h" +#include "silcruntime.h" /************************** Types and definitions ***************************/ @@@ -30,317 -31,112 +30,317 @@@ do { flen += req; \ } while(0) -/* Check that there is data to be unformatted */ -#define UNFORMAT_HAS_SPACE(b, req) \ -do { \ - if (silc_unlikely(req > silc_buffer_len(b))) \ - goto fail; \ - if (silc_unlikely((req + 1) <= 0)) \ - goto fail; \ +/* Check that buffer has enough room to format data in it, if not + allocate more. This will append, thus not replacing any existing data. */ +#define FORMAT_HAS_SPACE_APPEND(s, b, req) \ +do { \ + if (silc_buffer_len(b) < req) \ + if (silc_unlikely(!silc_buffer_sappend(s, b, req - silc_buffer_len(b)))) \ + goto fail; \ + flen += req; \ } while(0) +/* Check that there is data to be unformatted */ +#define UNFORMAT_HAS_SPACE(b, req) \ +do { \ + if (silc_unlikely(req > silc_buffer_len(b))) { \ + silc_set_errno(SILC_ERR_OVERFLOW); \ + goto fail; \ + } \ + if (silc_unlikely((req + 1) <= 0)) { \ + silc_set_errno(SILC_ERR_OVERFLOW); \ + goto fail; \ + } \ +} while(0) -/******************************* Formatting *********************************/ - -int silc_buffer_format(SilcBuffer dst, ...) -{ - va_list ap; - int ret; - - va_start(ap, dst); - ret = silc_buffer_sformat_vp(NULL, dst, ap); - va_end(ap); - - return ret; -} - -int silc_buffer_format_vp(SilcBuffer dst, va_list ap) +#if defined(SILC_DEBUG) +static const char *silc_param_string(SilcParam fmt) { - return silc_buffer_sformat_vp(NULL, dst, ap); + if (fmt == SILC_PARAM_SINT8) + return "SINT8"; + if (fmt == SILC_PARAM_UINT8) + return "UINT8"; + if (fmt == SILC_PARAM_SINT16) + return "SINT16"; + if (fmt == SILC_PARAM_UINT16) + return "UINT16"; + if (fmt == SILC_PARAM_SINT32) + return "SINT32"; + if (fmt == SILC_PARAM_UINT32) + return "UINT32"; + if (fmt == SILC_PARAM_SINT64) + return "SINT64"; + if (fmt == SILC_PARAM_UINT64) + return "UINT64"; + if (fmt == SILC_PARAM_SICHAR) + return "SICHAR"; + if (fmt == (SILC_PARAM_SICHAR | SILC_PARAM_ALLOC)) + return "SICHAR ALLOC"; + if (fmt == SILC_PARAM_UICHAR) + return "UICHAR"; + if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_ALLOC)) + return "UICHAR ALLOC"; + if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_REPLACE)) + return "UICHAR REPLACE"; + if (fmt == SILC_PARAM_BUFFER) + return "BUFFER"; + if (fmt == (SILC_PARAM_BUFFER | SILC_PARAM_ALLOC)) + return "BUFFER ALLOC"; + if (fmt == SILC_PARAM_PTR) + return "PTR"; + if (fmt == SILC_PARAM_END) + return "END"; + if (fmt == SILC_PARAM_UI8_STRING) + return "UI8_STRING"; + if (fmt == SILC_PARAM_UI16_STRING) + return "UI16_STRING"; + if (fmt == SILC_PARAM_UI32_STRING) + return "UI32_STRING"; + if (fmt == SILC_PARAM_UI8_NSTRING) + return "UI8_STRING"; + if (fmt == SILC_PARAM_UI16_NSTRING) + return "UI16_STRING"; + if (fmt == SILC_PARAM_UI32_NSTRING) + return "UI32_STRING"; + if (fmt == (SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC)) + return "UI8_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC)) + return "UI16_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC)) + return "UI32_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC)) + return "UI8_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC)) + return "UI16_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC)) + return "UI32_STRING"; + if (fmt == SILC_PARAM_OFFSET) + return "OFFSET"; + if (fmt == SILC_PARAM_ADVANCE) + return "ADDVANCE"; + if (fmt == SILC_PARAM_FUNC) + return "FUNC"; + if (fmt == SILC_PARAM_REGEX) + return "REGEX"; + if (fmt == SILC_PARAM_OFFSET_START) + return "OFFSET_START"; + if (fmt == SILC_PARAM_OFFSET_END) + return "OFFSET_END"; + if (fmt == SILC_PARAM_DELETE) + return "DELETE"; + return ""; } +#endif /* SILC_DEBUG */ -int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...) -{ - va_list ap; - int ret; - - va_start(ap, dst); - ret = silc_buffer_sformat_vp(stack, dst, ap); - va_end(ap); - - return ret; -} +/******************************* Formatting *********************************/ -int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap) +int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap, + SilcBool process) { - SilcBufferParamType fmt; + SilcParam fmt; int flen = 0; SilcBool advance = FALSE; /* Parse the arguments by formatting type. */ while (1) { - fmt = va_arg(ap, SilcBufferParamType); + fmt = va_arg(ap, SilcParam); + +#if defined(SILC_DEBUG) + if (process) + SILC_LOG_DEBUG(("Buffer format type %s (%d)", + silc_param_string(fmt), fmt)); +#endif /* SILC_DEBUG */ - switch(fmt) { + switch (fmt) { case SILC_PARAM_FUNC: { - SilcBufferFormatFunc func = NULL; - SilcBufferSFormatFunc funcs = NULL; + SilcBufferFormatFunc func; void *val; void *context; int tmp_len; - if (!stack) - func = va_arg(ap, SilcBufferFormatFunc); - else - funcs = va_arg(ap, SilcBufferSFormatFunc); + + func = va_arg(ap, SilcBufferFormatFunc); val = va_arg(ap, void *); context = va_arg(ap, void *); - if (!stack) - tmp_len = func(dst, val, context); - else - tmp_len = funcs(stack, dst, val, context); + + if (!process) + break; + + tmp_len = func(stack, dst, val, context); if (tmp_len < 0) goto fail; if (tmp_len) { silc_buffer_pull(dst, tmp_len); flen += tmp_len; } + break; } - break; + + case SILC_PARAM_REGEX: + { + const char *regex = va_arg(ap, char *); + SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags); + SilcBufferStruct match; + SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0; + SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0; + SilcBool ret; + SilcUInt32 inclusive_pos = 0; + int matched = 0, ret_len; + va_list cp; + + if (!process) + break; + + if (!regex) + break; + + if (match_nl) { + start_nl_match: + /* Match for '\n' in the buffer. If not found, treat as line + without '\n' (buffer has only one line, or this is last line). */ + if (silc_regex_buffer(dst, "\n", &match, NULL)) + dst->tail = match.tail; + } + + start_match: + /* Match */ + ret = silc_regex_buffer(dst, regex, &match, NULL); + ret ^= (rflags & SILC_STR_REGEX_NOT) != 0; + if (!ret) { + if (!matched && rflags & SILC_STR_REGEX_MISMATCH) { + silc_set_errno(SILC_ERR_NOT_FOUND); + goto fail; + } + goto end_match; + } + matched++; + + if (rflags & SILC_STR_REGEX_NOT) + match = *dst; + + if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) { + /* Advance buffer after match */ + flen += (match.data - dst->data); + if (!silc_buffer_pull(dst, (match.data - dst->data))) + goto fail; + } + + if (rflags & SILC_STR_REGEX_INCLUSIVE) { + inclusive_pos = dst->tail - match.tail; + dst->tail = match.tail; + } + + /* Recursively format */ + silc_va_copy(cp, ap); + ret_len = silc_buffer_sformat_vp_i(stack, dst, cp, TRUE); + va_end(cp); + if (ret_len < 0) + goto fail; + + if (rflags & SILC_STR_REGEX_INCLUSIVE) + if (!silc_buffer_pull_tail(dst, inclusive_pos)) + goto fail; + + /* Advance buffer after formatting */ + flen += ret_len; + if (!silc_buffer_pull(dst, ret_len)) + goto fail; + + if (match_all && (!match_nl || silc_buffer_len(dst) > 1)) + goto start_match; + + end_match: + if (match_nl) { + /* Go to next line, it is at the end of the data area. Adjust + the tail area of the target buffer to show rest of the buffer. */ + flen += (dst->tail - dst->data); + if (!silc_buffer_pull(dst, (dst->tail - dst->data))) + goto fail; + if (!silc_buffer_pull_tail(dst, silc_buffer_taillen(dst))) + goto fail; + + if (silc_buffer_len(dst) > 0) + goto start_nl_match; + } + + /* Skip to the next SILC_PARAM_END */ + silc_buffer_sformat_vp_i(NULL, NULL, ap, FALSE); + break; + } + case SILC_PARAM_UI8_STRING: case SILC_PARAM_UI16_STRING: case SILC_PARAM_UI32_STRING: - case SILC_PARAM_UI8_STRING_ALLOC: - case SILC_PARAM_UI16_STRING_ALLOC: - case SILC_PARAM_UI32_STRING_ALLOC: + case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC: + case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC: + case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC: { - unsigned char *x = va_arg(ap, unsigned char *); + char *x = va_arg(ap, char *); SilcUInt32 tmp_len = x ? strlen(x) : 0; + + if (!process) + break; + if (x && tmp_len) { FORMAT_HAS_SPACE(stack, dst, tmp_len); - silc_buffer_put(dst, x, tmp_len); + silc_buffer_put(dst, (unsigned char *)x, tmp_len); silc_buffer_pull(dst, tmp_len); } break; } + + case SILC_PARAM_UICHAR | SILC_PARAM_REPLACE: + { + unsigned char *x = va_arg(ap, unsigned char *); + SilcUInt32 x_len = va_arg(ap, SilcUInt32); + + if (!process) + break; + + if (!x) + break; + + if (silc_buffer_len(dst) == x_len) { + /* Replace */ + if (x_len) { + silc_buffer_put(dst, x, x_len); + silc_buffer_pull(dst, x_len); + flen += x_len; + } + } else if (silc_buffer_len(dst) < x_len) { + /* Append */ + if (x_len) { + FORMAT_HAS_SPACE_APPEND(stack, dst, x_len); + silc_buffer_put(dst, x, x_len); + silc_buffer_pull(dst, x_len); + } + } else { + /* Delete */ + if (x_len) { + silc_buffer_put(dst, x, x_len); + silc_buffer_pull(dst, x_len); + flen += x_len; + } + goto delete_rest; + } + break; + } + case SILC_PARAM_UI8_NSTRING: case SILC_PARAM_UI16_NSTRING: case SILC_PARAM_UI32_NSTRING: - case SILC_PARAM_UI_XNSTRING: - case SILC_PARAM_DATA: - case SILC_PARAM_UI8_NSTRING_ALLOC: - case SILC_PARAM_UI16_NSTRING_ALLOC: - case SILC_PARAM_UI32_NSTRING_ALLOC: - case SILC_PARAM_UI_XNSTRING_ALLOC: - case SILC_PARAM_DATA_ALLOC: + case SILC_PARAM_UICHAR: + case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC: + case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC: + case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC: + case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC: { unsigned char *x = va_arg(ap, unsigned char *); SilcUInt32 tmp_len = va_arg(ap, SilcUInt32); + + if (!process) + break; + if (x && tmp_len) { FORMAT_HAS_SPACE(stack, dst, tmp_len); silc_buffer_put(dst, x, tmp_len); @@@ -348,132 -144,87 +348,132 @@@ } break; } - case SILC_PARAM_UI8_CHAR: + + case SILC_PARAM_UINT8: { unsigned char x = (unsigned char)va_arg(ap, int); + + if (!process) + break; + FORMAT_HAS_SPACE(stack, dst, 1); silc_buffer_put(dst, &x, 1); silc_buffer_pull(dst, 1); break; } - case SILC_PARAM_UI16_SHORT: + + case SILC_PARAM_UINT16: { unsigned char xf[2]; SilcUInt16 x = (SilcUInt16)va_arg(ap, int); + + if (!process) + break; + FORMAT_HAS_SPACE(stack, dst, 2); SILC_PUT16_MSB(x, xf); silc_buffer_put(dst, xf, 2); silc_buffer_pull(dst, 2); break; } - case SILC_PARAM_UI32_INT: + + case SILC_PARAM_UINT32: { unsigned char xf[4]; SilcUInt32 x = va_arg(ap, SilcUInt32); + + if (!process) + break; + FORMAT_HAS_SPACE(stack, dst, 4); SILC_PUT32_MSB(x, xf); silc_buffer_put(dst, xf, 4); silc_buffer_pull(dst, 4); break; } - case SILC_PARAM_UI64_INT: + + case SILC_PARAM_UINT64: { unsigned char xf[8]; SilcUInt64 x = va_arg(ap, SilcUInt64); + + if (!process) + break; + FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64)); SILC_PUT64_MSB(x, xf); silc_buffer_put(dst, xf, sizeof(SilcUInt64)); silc_buffer_pull(dst, sizeof(SilcUInt64)); break; } - case SILC_PARAM_SI8_CHAR: + + case SILC_PARAM_SINT8: { char x = (char)va_arg(ap, int); + + if (!process) + break; + FORMAT_HAS_SPACE(stack, dst, 1); - silc_buffer_put(dst, &x, 1); + silc_buffer_put(dst, (unsigned char *)&x, 1); silc_buffer_pull(dst, 1); break; } - case SILC_PARAM_SI16_SHORT: + + case SILC_PARAM_SINT16: { unsigned char xf[2]; SilcInt16 x = (SilcInt16)va_arg(ap, int); + + if (!process) + break; + FORMAT_HAS_SPACE(stack, dst, 2); SILC_PUT16_MSB(x, xf); silc_buffer_put(dst, xf, 2); silc_buffer_pull(dst, 2); break; } - case SILC_PARAM_SI32_INT: + + case SILC_PARAM_SINT32: { unsigned char xf[4]; SilcInt32 x = va_arg(ap, SilcInt32); + + if (!process) + break; + FORMAT_HAS_SPACE(stack, dst, 4); SILC_PUT32_MSB(x, xf); silc_buffer_put(dst, xf, 4); silc_buffer_pull(dst, 4); break; } - case SILC_PARAM_SI64_INT: + + case SILC_PARAM_SINT64: { unsigned char xf[8]; SilcInt64 x = va_arg(ap, SilcInt64); + + if (!process) + break; + FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64)); SILC_PUT64_MSB(x, xf); silc_buffer_put(dst, xf, sizeof(SilcInt64)); silc_buffer_pull(dst, sizeof(SilcInt64)); break; } + case SILC_PARAM_BUFFER: - case SILC_PARAM_BUFFER_ALLOC: + case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC: { SilcBuffer x = va_arg(ap, SilcBuffer); unsigned char xf[4]; + + if (!process) + break; + if (x && silc_buffer_len(x)) { FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4); SILC_PUT32_MSB(silc_buffer_len(x), xf); @@@ -484,55 -235,14 +484,55 @@@ } } break; + + case SILC_PARAM_DELETE: + { + int n = va_arg(ap, int); + + if (!process) + break; + + if (n == -1) { + /* Move all data from tail to data area */ + if (dst->data != dst->tail) { + delete_rest: + n = silc_buffer_len(dst); + memmove(dst->data, dst->tail, silc_buffer_taillen(dst)); + silc_buffer_push_tail(dst, n); + if (!silc_buffer_srealloc(stack, dst, + silc_buffer_truelen(dst) - n)) + goto fail; + } + break; + } + + if (n > silc_buffer_len(dst)) + goto fail; + + memmove(dst->data, dst->data + n, (silc_buffer_len(dst) - n) + + silc_buffer_taillen(dst)); + silc_buffer_push_tail(dst, silc_buffer_len(dst) - n); + if (!silc_buffer_srealloc(stack, dst, silc_buffer_truelen(dst) - n)) + goto fail; + + break; + } + case SILC_PARAM_OFFSET: { int offst = va_arg(ap, int); + + if (!process) + break; + if (!offst) break; + if (offst > 1) { - if (offst > silc_buffer_len(dst)) + if (offst > silc_buffer_len(dst)) { + silc_set_errno(SILC_ERR_OVERFLOW); goto fail; + } silc_buffer_pull(dst, offst); flen += offst; } else { @@@ -541,37 -251,15 +541,37 @@@ } break; } + + case SILC_PARAM_OFFSET_START: + if (!process) + break; + if (!silc_buffer_push(dst, flen)) + goto fail; + flen = 0; + break; + + case SILC_PARAM_OFFSET_END: + if (!process) + break; + flen += silc_buffer_len(dst); + silc_buffer_pull(dst, silc_buffer_len(dst)); + break; + case SILC_PARAM_ADVANCE: + if (!process) + break; advance = TRUE; break; + case SILC_PARAM_END: goto ok; break; + default: SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not " "format the data.", fmt)); + silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT, + "Bad buffer formatting type %d", fmt); goto fail; break; } @@@ -579,83 -267,78 +579,83 @@@ fail: SILC_LOG_DEBUG(("Error occured while formatting data")); - if (!advance) + if (process && !advance) silc_buffer_push(dst, flen); return -1; ok: /* Push the buffer back to where it belongs. */ - if (!advance) + if (process && !advance) silc_buffer_push(dst, flen); return flen; } - -/****************************** Unformatting ********************************/ - -int silc_buffer_unformat(SilcBuffer src, ...) +int silc_buffer_format(SilcBuffer dst, ...) { va_list ap; int ret; - va_start(ap, src); - ret = silc_buffer_sunformat_vp(NULL, src, ap); + va_start(ap, dst); + ret = silc_buffer_sformat_vp(NULL, dst, ap); va_end(ap); return ret; } -int silc_buffer_unformat_vp(SilcBuffer src, va_list ap) +int silc_buffer_format_vp(SilcBuffer dst, va_list ap) { - return silc_buffer_sunformat_vp(NULL, src, ap); + return silc_buffer_sformat_vp(NULL, dst, ap); } -int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...) +int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...) { va_list ap; int ret; - va_start(ap, src); - ret = silc_buffer_sunformat_vp(stack, src, ap); + va_start(ap, dst); + ret = silc_buffer_sformat_vp(stack, dst, ap); va_end(ap); return ret; } -int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap) +int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap) { - SilcBufferParamType fmt; + return silc_buffer_sformat_vp_i(stack, dst, ap, TRUE); +} + +/****************************** Unformatting ********************************/ + +int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap, + SilcBool process) +{ + SilcParam fmt; unsigned char *start_ptr = src->data; int len = 0; SilcBool advance = FALSE; /* Parse the arguments by formatting type. */ - while(1) { - fmt = va_arg(ap, SilcBufferParamType); + while (1) { + fmt = va_arg(ap, SilcParam); + + SILC_LOG_DEBUG(("Buffer unformat type %s (%d)", + silc_param_string(fmt), fmt)); - switch(fmt) { + switch (fmt) { case SILC_PARAM_FUNC: { - SilcBufferUnformatFunc func = NULL; - SilcBufferSUnformatFunc funcs = NULL; + SilcBufferUnformatFunc func; void **val; void *context; int tmp_len; - if (!stack) - func = va_arg(ap, SilcBufferUnformatFunc); - else - funcs = va_arg(ap, SilcBufferSUnformatFunc); + func = va_arg(ap, SilcBufferUnformatFunc); val = va_arg(ap, void **); context = va_arg(ap, void *); - if (!stack) - tmp_len = func(src, val, context); - else - tmp_len = funcs(stack, src, val, context); + + if (!process) + break; + + tmp_len = func(stack, src, val, context); if (tmp_len < 0) goto fail; if (tmp_len) { @@@ -663,250 -346,107 +663,251 @@@ silc_buffer_pull(src, tmp_len); } } - case SILC_PARAM_UI_XNSTRING: - case SILC_PARAM_DATA: + break; + + case SILC_PARAM_REGEX: + { + const char *regex = va_arg(ap, char *); + SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags); + SilcBufferStruct match; + SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0; + SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0; + SilcBool ret; + SilcUInt32 inclusive_pos = 0; + int matched = 0, ret_len; + va_list cp; + + if (!process) + break; + + if (!regex) + break; + + if (match_nl) { + start_nl_match: + /* Match for '\n' in the buffer. If not found, treat as line + without '\n' (buffer has only one line, or this is last line). */ + if (silc_regex_buffer(src, "\n", &match, NULL)) + src->tail = match.tail; + } + + start_match: + /* Match */ + ret = silc_regex_buffer(src, regex, &match, NULL); + ret ^= (rflags & SILC_STR_REGEX_NOT) != 0; + if (!ret) { + if (!matched && rflags & SILC_STR_REGEX_MISMATCH) { + silc_set_errno(SILC_ERR_NOT_FOUND); + goto fail; + } + goto end_match; + } + matched++; + + if (rflags & SILC_STR_REGEX_NOT) + match = *src; + + if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) { + /* Advance buffer after match */ + if (!silc_buffer_pull(src, (match.data - src->data))) + goto fail; + } + + if (rflags & SILC_STR_REGEX_INCLUSIVE) { + inclusive_pos = src->tail - match.tail; + src->tail = match.tail; + } + + /* Recursively format */ + silc_va_copy(cp, ap); + ret_len = silc_buffer_sunformat_vp_i(stack, src, cp, TRUE); + va_end(cp); + if (ret_len < 0) + goto fail; + + if (rflags & SILC_STR_REGEX_INCLUSIVE) + if (!silc_buffer_pull_tail(src, inclusive_pos)) + goto fail; + + /* Advance buffer after formatting */ + if (!silc_buffer_pull(src, ret_len)) + goto fail; + + if (match_all && (!match_nl || silc_buffer_len(src) > 1)) + goto start_match; + + end_match: + if (match_nl) { + /* Go to next line, it is at the end of the data area. Adjust + the tail area of the target buffer to show rest of the buffer. */ + if (!silc_buffer_pull(src, (src->tail - src->data))) + goto fail; + if (!silc_buffer_pull_tail(src, silc_buffer_taillen(src))) + goto fail; + + if (silc_buffer_len(src) > 0) + goto start_nl_match; + } + + /* Skip to the next SILC_PARAM_END */ + silc_buffer_sunformat_vp_i(NULL, src, ap, FALSE); + break; + } + break; + + case SILC_PARAM_UICHAR: { unsigned char **x = va_arg(ap, unsigned char **); SilcUInt32 len2 = va_arg(ap, SilcUInt32); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, len2); if (silc_likely(len2 && x)) *x = src->data; silc_buffer_pull(src, len2); break; } - case SILC_PARAM_UI_XNSTRING_ALLOC: - case SILC_PARAM_DATA_ALLOC: + + case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC: { unsigned char **x = va_arg(ap, unsigned char **); SilcUInt32 len2 = va_arg(ap, SilcUInt32); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, len2); if (silc_likely(len2 && x)) { *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char)); - memcpy(*x, src->data, len2); + if (*x) + memcpy(*x, src->data, len2); } silc_buffer_pull(src, len2); break; } - case SILC_PARAM_UI8_CHAR: + + case SILC_PARAM_UINT8: { unsigned char *x = va_arg(ap, unsigned char *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 1); if (silc_likely(x)) *x = src->data[0]; silc_buffer_pull(src, 1); break; } - case SILC_PARAM_UI16_SHORT: + + case SILC_PARAM_UINT16: { SilcUInt16 *x = va_arg(ap, SilcUInt16 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 2); if (silc_likely(x)) SILC_GET16_MSB(*x, src->data); silc_buffer_pull(src, 2); break; } - case SILC_PARAM_UI32_INT: + + case SILC_PARAM_UINT32: { SilcUInt32 *x = va_arg(ap, SilcUInt32 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 4); if (silc_likely(x)) SILC_GET32_MSB(*x, src->data); silc_buffer_pull(src, 4); break; } - case SILC_PARAM_UI64_INT: + + case SILC_PARAM_UINT64: { SilcUInt64 *x = va_arg(ap, SilcUInt64 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64)); if (silc_likely(x)) SILC_GET64_MSB(*x, src->data); silc_buffer_pull(src, sizeof(SilcUInt64)); break; } - case SILC_PARAM_SI8_CHAR: + + case SILC_PARAM_SINT8: { char *x = va_arg(ap, char *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 1); if (silc_likely(x)) *x = src->data[0]; silc_buffer_pull(src, 1); break; } - case SILC_PARAM_SI16_SHORT: + + case SILC_PARAM_SINT16: { SilcInt16 *x = va_arg(ap, SilcInt16 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 2); if (silc_likely(x)) SILC_GET16_MSB(*x, src->data); silc_buffer_pull(src, 2); break; } - case SILC_PARAM_SI32_INT: + + case SILC_PARAM_SINT32: { SilcInt32 *x = va_arg(ap, SilcInt32 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 4); if (silc_likely(x)) SILC_GET32_MSB(*x, src->data); silc_buffer_pull(src, 4); break; } - case SILC_PARAM_SI64_INT: + + case SILC_PARAM_SINT64: { SilcInt64 *x = va_arg(ap, SilcInt64 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64)); if (silc_likely(x)) SILC_GET64_MSB(*x, src->data); silc_buffer_pull(src, sizeof(SilcInt64)); break; } + case SILC_PARAM_UI8_STRING: { SilcUInt8 len2; unsigned char **x = va_arg(ap, unsigned char **); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 1); len2 = (SilcUInt8)src->data[0]; silc_buffer_pull(src, 1); @@@ -916,73 -456,55 +917,74 @@@ silc_buffer_pull(src, len2); break; } - case SILC_PARAM_UI16_STRING: - { - SilcUInt16 len2; - unsigned char **x = va_arg(ap, unsigned char **); - UNFORMAT_HAS_SPACE(src, 2); - SILC_GET16_MSB(len2, src->data); - silc_buffer_pull(src, 2); - UNFORMAT_HAS_SPACE(src, len2); - if (silc_likely(x)) - *x = src->data; - silc_buffer_pull(src, len2); - break; - } - case SILC_PARAM_UI8_STRING_ALLOC: + + case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC: { SilcUInt8 len2; unsigned char **x = va_arg(ap, unsigned char **); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 1); len2 = (SilcUInt8)src->data[0]; silc_buffer_pull(src, 1); UNFORMAT_HAS_SPACE(src, len2); if (silc_likely(x && len2)) { *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char)); - if (*x) - memcpy(*x, src->data, len2); + memcpy(*x, src->data, len2); } silc_buffer_pull(src, len2); break; } - case SILC_PARAM_UI16_STRING_ALLOC: + + case SILC_PARAM_UI16_STRING: { SilcUInt16 len2; unsigned char **x = va_arg(ap, unsigned char **); + + if (!process) + break; + + UNFORMAT_HAS_SPACE(src, 2); + SILC_GET16_MSB(len2, src->data); + silc_buffer_pull(src, 2); + UNFORMAT_HAS_SPACE(src, len2); + if (silc_likely(x)) + *x = src->data; + silc_buffer_pull(src, len2); + break; + } + + case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC: + { + SilcUInt16 len2; + unsigned char **x = va_arg(ap, unsigned char **); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 2); SILC_GET16_MSB(len2, src->data); silc_buffer_pull(src, 2); UNFORMAT_HAS_SPACE(src, len2); if (silc_likely(x && len2)) { *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char)); - memcpy(*x, src->data, len2); + if (*x) + memcpy(*x, src->data, len2); } silc_buffer_pull(src, len2); break; } + case SILC_PARAM_UI32_STRING: { SilcUInt32 len2; unsigned char **x = va_arg(ap, unsigned char **); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 4); SILC_GET32_MSB(len2, src->data); silc_buffer_pull(src, 4); @@@ -992,36 -514,27 +994,37 @@@ silc_buffer_pull(src, len2); break; } - case SILC_PARAM_UI32_STRING_ALLOC: + + case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC: { SilcUInt32 len2; unsigned char **x = va_arg(ap, unsigned char **); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 4); SILC_GET32_MSB(len2, src->data); silc_buffer_pull(src, 4); UNFORMAT_HAS_SPACE(src, len2); if (silc_likely(x && len2)) { *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char)); - memcpy(*x, src->data, len2); + if (*x) + memcpy(*x, src->data, len2); } silc_buffer_pull(src, len2); break; } + case SILC_PARAM_UI8_NSTRING: { SilcUInt8 len2; unsigned char **x = va_arg(ap, unsigned char **); SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 1); len2 = (SilcUInt8)src->data[0]; silc_buffer_pull(src, 1); @@@ -1033,16 -546,27 +1036,16 @@@ silc_buffer_pull(src, len2); break; } - case SILC_PARAM_UI16_NSTRING: - { - SilcUInt16 len2; - unsigned char **x = va_arg(ap, unsigned char **); - SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *); - UNFORMAT_HAS_SPACE(src, 2); - SILC_GET16_MSB(len2, src->data); - silc_buffer_pull(src, 2); - UNFORMAT_HAS_SPACE(src, len2); - if (len3) - *len3 = len2; - if (x) - *x = src->data; - silc_buffer_pull(src, len2); - break; - } - case SILC_PARAM_UI8_NSTRING_ALLOC: + + case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC: { SilcUInt8 len2; unsigned char **x = va_arg(ap, unsigned char **); SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 1); len2 = (SilcUInt8)src->data[0]; silc_buffer_pull(src, 1); @@@ -1051,42 -575,17 +1054,42 @@@ *len3 = len2; if (x && len2) { *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char)); - if (*x) - memcpy(*x, src->data, len2); + memcpy(*x, src->data, len2); } silc_buffer_pull(src, len2); break; } - case SILC_PARAM_UI16_NSTRING_ALLOC: + + case SILC_PARAM_UI16_NSTRING: { SilcUInt16 len2; unsigned char **x = va_arg(ap, unsigned char **); SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *); + + if (!process) + break; + + UNFORMAT_HAS_SPACE(src, 2); + SILC_GET16_MSB(len2, src->data); + silc_buffer_pull(src, 2); + UNFORMAT_HAS_SPACE(src, len2); + if (len3) + *len3 = len2; + if (x) + *x = src->data; + silc_buffer_pull(src, len2); + break; + } + + case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC: + { + SilcUInt16 len2; + unsigned char **x = va_arg(ap, unsigned char **); + SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 2); SILC_GET16_MSB(len2, src->data); silc_buffer_pull(src, 2); @@@ -1095,21 -594,17 +1098,22 @@@ *len3 = len2; if (x && len2) { *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char)); - memcpy(*x, src->data, len2); + if (*x) + memcpy(*x, src->data, len2); } silc_buffer_pull(src, len2); break; } + case SILC_PARAM_UI32_NSTRING: { SilcUInt32 len2; unsigned char **x = va_arg(ap, unsigned char **); SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *); + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 4); SILC_GET32_MSB(len2, src->data); silc_buffer_pull(src, 4); @@@ -1121,38 -616,10 +1125,38 @@@ silc_buffer_pull(src, len2); break; } + + case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC: + { + SilcUInt32 len2; + unsigned char **x = va_arg(ap, unsigned char **); + SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *); + + if (!process) + break; + + UNFORMAT_HAS_SPACE(src, 4); + SILC_GET32_MSB(len2, src->data); + silc_buffer_pull(src, 4); + UNFORMAT_HAS_SPACE(src, len2); + if (len3) + *len3 = len2; + if (silc_likely(x && len2)) { + *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char)); + memcpy(*x, src->data, len2); + } + silc_buffer_pull(src, len2); + break; + } + case SILC_PARAM_BUFFER: { SilcBuffer x = va_arg(ap, SilcBuffer); SilcUInt32 len2; + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 4); SILC_GET32_MSB(len2, src->data); silc_buffer_pull(src, 4); @@@ -1161,36 -628,26 +1165,37 @@@ silc_buffer_pull(src, len2); } break; - case SILC_PARAM_BUFFER_ALLOC: + + case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC: { SilcBuffer x = va_arg(ap, SilcBuffer); SilcUInt32 len2; + + if (!process) + break; + UNFORMAT_HAS_SPACE(src, 4); SILC_GET32_MSB(len2, src->data); silc_buffer_pull(src, 4); UNFORMAT_HAS_SPACE(src, len2); - silc_buffer_sformat(stack, x, - SILC_STR_DATA(src->data, len2), - SILC_STR_END); + if (silc_buffer_sformat(stack, x, + SILC_STR_DATA(src->data, len2), + SILC_STR_END) < 0) + goto fail; silc_buffer_pull(src, len2); } break; + case SILC_PARAM_OFFSET: { int offst = va_arg(ap, int); + + if (!process) + break; + if (!offst) break; + if (offst > 1) { UNFORMAT_HAS_SPACE(src, offst); silc_buffer_pull(src, offst); @@@ -1199,37 -656,15 +1204,37 @@@ } break; } + + case SILC_PARAM_OFFSET_START: + if (!process) + break; + silc_buffer_push(src, (src->data - start_ptr)); + break; + + case SILC_PARAM_OFFSET_END: + if (!process) + break; + silc_buffer_pull(src, silc_buffer_len(src)); + break; + case SILC_PARAM_ADVANCE: + if (!process) + break; advance = TRUE; break; + case SILC_PARAM_END: goto ok; break; + + case SILC_PARAM_DELETE: + break; + default: SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not " "format the data.", fmt)); + silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT, + "Bad buffer formatting type %d", fmt); goto fail; break; } @@@ -1237,55 -672,19 +1242,55 @@@ fail: SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt)); - len = src->data - start_ptr; - silc_buffer_push(src, len); + if (process && !advance) { + len = src->data - start_ptr; + silc_buffer_push(src, len); + } return -1; ok: + len = src->data - start_ptr; + /* Push the buffer back to the start. */ - if (!advance) { - len = src->data - start_ptr; + if (process && !advance) silc_buffer_push(src, len); - } + return len; } +int silc_buffer_unformat(SilcBuffer src, ...) +{ + va_list ap; + int ret; + + va_start(ap, src); + ret = silc_buffer_sunformat_vp(NULL, src, ap); + va_end(ap); + + return ret; +} + +int silc_buffer_unformat_vp(SilcBuffer src, va_list ap) +{ + return silc_buffer_sunformat_vp(NULL, src, ap); +} + +int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...) +{ + va_list ap; + int ret; + + va_start(ap, src); + ret = silc_buffer_sunformat_vp(stack, src, ap); + va_end(ap); + + return ret; +} + +int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap) +{ + return silc_buffer_sunformat_vp_i(stack, src, ap, TRUE); +} /**************************** Utility functions *****************************/ diff --combined lib/silcutil/silcconfig.c index 0568bd42,f9fe8437..0a9a3464 --- a/lib/silcutil/silcconfig.c +++ b/lib/silcutil/silcconfig.c @@@ -4,7 -4,7 +4,7 @@@ Author: Giovanni Giacobbi - Copyright (C) 2002 - 2006 Giovanni Giacobbi + Copyright (C) 2002 - 2008 Giovanni Giacobbi This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@@ -16,8 -16,9 +16,8 @@@ GNU General Public License for more details. */ -/* $Id$ */ -#include "silc.h" +#include "silcruntime.h" /* limit debug logging verbosity */ #if 0 @@@ -26,6 -27,8 +26,8 @@@ #define SILC_CONFIG_DEBUG(fmt) #endif + #define BUF_SIZE 255 + /* this is the option struct and currently it is only used internally to * the module and other structs. */ typedef struct SilcConfigOptionStruct { @@@ -111,11 -114,14 +113,14 @@@ static void my_skip_line(SilcConfigFil * a separator is any non alphanumeric character nor "_" or "-" */ static char *my_next_token(SilcConfigFile *file, char *to) { + unsigned int count = 0; register char *o; my_trim_spaces(file); o = file->p; - while (isalnum((int)*o) || (*o == '_') || (*o == '-')) + while ((isalnum((int)*o) || (*o == '_') || (*o == '-')) && count < BUF_SIZE) { + count++; *to++ = *o++; + } *to = '\0'; file->p = o; return to; @@@ -129,24 -135,30 +134,30 @@@ static char *my_get_string(SilcConfigFi my_trim_spaces(file); o = file->p; if (*o == '"') { - char *quot = strchr(++o, '"'); - int len = quot - o; - if (!quot) { /* XXX FIXME: gotta do something here */ - printf("Bullshit, missing matching \""); - exit(1); + unsigned int count = 0; + char *d = to; + while (count < BUF_SIZE) { + o++; + if (*o == '"') { + break; + } + if (*o == '\\') { + o++; + } + count++; + *d++ = *o; } - if (len <= 0) - *to = '\0'; - else { - strncpy(to, o, len); - to[len] = '\0'; + if (count >= BUF_SIZE) { /* XXX FIXME: gotta do something here */ + fprintf(stderr, "Bullshit, missing matching \""); + exit(1); } + *d = '\0'; /* update stream pointer */ - file->p = quot + 1; - return to; + file->p = o + 1; + } else { + /* we don't need quote parsing, fall-back to token extractor */ + my_next_token(file, to); } - /* we don't need quote parsing, fall-back to token extractor */ - my_next_token(file, to); return to; } @@@ -262,7 -274,7 +273,7 @@@ SilcConfigFile *silc_config_open(const SilcUInt32 filelen; SilcConfigFile *ret; - if (!(buffer = silc_file_readfile(configfile, &filelen))) + if (!(buffer = silc_file_readfile(configfile, &filelen, NULL))) return NULL; ret = silc_calloc(1, sizeof(*ret)); @@@ -453,7 -465,7 +464,7 @@@ static int silc_config_main_internal(Si /* loop throught statements */ while (1) { - char buf[255]; + char buf[BUF_SIZE]; SilcConfigOption *thisopt; /* makes it pointing to the next interesting char */ diff --combined lib/silcutil/silcfdstream.c index 5ba65ba9,1ae8d413..f0032e8b --- a/lib/silcutil/silcfdstream.c +++ b/lib/silcutil/silcfdstream.c @@@ -17,23 -17,23 +17,23 @@@ */ -#include "silc.h" +#include "silcruntime.h" /************************** Types and definitions ***************************/ - #define SILC_IS_FD_STREAM(s) (s->ops == &silc_fd_stream_ops) + #define SILC_IS_FD_STREAM(s) (s && s->ops == &silc_fd_stream_ops) const SilcStreamOps silc_fd_stream_ops; /* FD stream context */ typedef struct { const SilcStreamOps *ops; + SilcStack stack; SilcSchedule schedule; SilcStreamNotifier notifier; void *notifier_context; int fd1; int fd2; - int error; } *SilcFDStream; @@@ -67,36 -67,28 +67,36 @@@ SILC_TASK_CALLBACK(silc_fd_stream_io /* Create file descriptor stream */ -SilcStream silc_fd_stream_create(int fd) +SilcStream silc_fd_stream_create(int fd, SilcStack stack) { - if (fd < 1) + if (fd < 1) { + silc_set_errno_reason(SILC_ERR_BAD_FD, "Bad file descriptor %d", fd); return NULL; - return silc_fd_stream_create2(fd, 0); + } + return silc_fd_stream_create2(fd, 0, stack); } /* Create stream with two file descriptors */ -SilcStream silc_fd_stream_create2(int read_fd, int write_fd) +SilcStream silc_fd_stream_create2(int read_fd, int write_fd, SilcStack stack) { SilcFDStream stream; - stream = silc_calloc(1, sizeof(*stream)); - if (!stream) + if (stack) + stack = silc_stack_alloc(0, stack); + + stream = silc_scalloc(stack, 1, sizeof(*stream)); + if (!stream) { + silc_stack_free(stack); return NULL; + } SILC_LOG_DEBUG(("Creating new fd stream %p", stream)); stream->ops = &silc_fd_stream_ops; stream->fd1 = read_fd; stream->fd2 = write_fd; + stream->stack = stack; return stream; } @@@ -104,27 -96,24 +104,27 @@@ /* Create by opening file */ SilcStream silc_fd_stream_file(const char *filename, SilcBool reading, - SilcBool writing) + SilcBool writing, SilcStack stack) { const char *read_file = NULL, *write_file = NULL; - if (!filename) + if (!filename) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return NULL; + } if (writing) write_file = filename; if (reading) read_file = filename; - return silc_fd_stream_file2(read_file, write_file); + return silc_fd_stream_file2(read_file, write_file, stack); } /* Create by opening two files */ -SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file) +SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file, + SilcStack stack) { SilcStream stream; int fd1 = 0, fd2 = 0; @@@ -147,7 -136,7 +147,7 @@@ return NULL; } - stream = silc_fd_stream_create2(fd1, fd2); + stream = silc_fd_stream_create2(fd1, fd2, stack); if (!stream) { silc_file_close(fd1); silc_file_close(fd2); @@@ -174,6 -163,18 +174,6 @@@ SilcBool silc_fd_stream_get_info(SilcSt return TRUE; } -/* Return errno */ - -int silc_fd_stream_get_error(SilcStream stream) -{ - SilcFDStream fd_stream = stream; - - if (!SILC_IS_FD_STREAM(fd_stream)) - return 0; - - return fd_stream->error; -} - /* Read */ int silc_fd_stream_read(SilcStream stream, unsigned char *buf, @@@ -193,13 -194,12 +193,13 @@@ SILC_LOG_DEBUG(("Could not read immediately, will do it later")); silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd1, SILC_TASK_READ, FALSE); + silc_set_errno_posix(errno); return -1; } SILC_LOG_DEBUG(("Cannot read from fd: %d:%s", fd_stream->fd1, strerror(errno))); silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1); - fd_stream->error = errno; + silc_set_errno_posix(errno); return -2; } @@@ -230,12 -230,11 +230,12 @@@ int silc_fd_stream_write(SilcStream str SILC_LOG_DEBUG(("Could not write immediately, will do it later")); silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd2, SILC_TASK_READ | SILC_TASK_WRITE, FALSE); + silc_set_errno_posix(errno); return -1; } SILC_LOG_DEBUG(("Cannot write to fd: %s", strerror(errno))); silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2); - fd_stream->error = errno; + silc_set_errno_posix(errno); return -2; } @@@ -278,12 -277,8 +278,12 @@@ SilcBool silc_fd_stream_close(SilcStrea void silc_fd_stream_destroy(SilcStream stream) { + SilcFDStream fd_stream = stream; + SilcStack stack = fd_stream->stack; + silc_fd_stream_close(stream); - silc_free(stream); + silc_sfree(stack, stream); + silc_stack_free(stack); } /* Sets stream notification callback for the stream */ diff --combined lib/silcutil/silcsocketstream.c index 7f61e518,af8f2c34..8d3056ed --- a/lib/silcutil/silcsocketstream.c +++ b/lib/silcutil/silcsocketstream.c @@@ -17,7 -17,7 +17,7 @@@ */ -#include "silc.h" +#include "silcruntime.h" /************************** Types and definitions ***************************/ @@@ -43,7 -43,7 +43,7 @@@ SilcSchedule silc_socket_stream_get_sch /* Internal async host lookup context. */ typedef struct { SilcSocketStream stream; - SilcSocketStreamStatus status; + SilcResult status; SilcSocketStreamCallback callback; SilcAsyncOperation op; void *context; @@@ -71,7 -71,7 +71,7 @@@ SILC_TASK_CALLBACK(silc_socket_host_loo return; } - if (lookup->status != SILC_SOCKET_OK) { + if (lookup->status != SILC_OK) { SILC_LOG_DEBUG(("Socket stream lookup failed")); stream->schedule = NULL; silc_socket_stream_destroy(stream); @@@ -99,24 -99,24 +99,24 @@@ static void *silc_socket_host_lookup_st silc_net_check_host_by_sock(stream->sock, &stream->hostname, &stream->ip); if (!stream->ip) { - lookup->status = SILC_SOCKET_UNKNOWN_IP; + lookup->status = SILC_ERR_UNKNOWN_IP; goto out; } if (!stream->hostname && lookup->require_fqdn) { - lookup->status = SILC_SOCKET_UNKNOWN_HOST; + lookup->status = SILC_ERR_UNKNOWN_HOST; goto out; } if (!stream->hostname) { - stream->hostname = strdup(stream->ip); + stream->hostname = silc_strdup(stream->ip); if (!stream->hostname) { - lookup->status = SILC_SOCKET_NO_MEMORY; + lookup->status = SILC_ERR_OUT_OF_MEMORY; goto out; } } - lookup->status = SILC_SOCKET_OK; + lookup->status = SILC_OK; out: silc_schedule_task_add_timeout(schedule, silc_socket_host_lookup_finish, @@@ -152,27 -152,17 +152,27 @@@ silc_socket_tcp_stream_create(SilcSocke SilcSocketStream stream; SilcSocketHostLookup l; - if (!sock || !schedule) { - SILC_LOG_ERROR(("Missing arguments to silc_socket_tcp_stream_create")); + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + if (callback) + callback(silc_errno, NULL, context); + return NULL; + } + } + + if (!sock) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); if (callback) - callback(SILC_SOCKET_ERROR, NULL, context); + callback(silc_errno, NULL, context); return NULL; } stream = silc_calloc(1, sizeof(*stream)); if (!stream) { if (callback) - callback(SILC_SOCKET_NO_MEMORY, NULL, context); + callback(silc_errno, NULL, context); return NULL; } @@@ -187,7 -177,7 +187,7 @@@ if (!l) { silc_free(stream); if (callback) - callback(SILC_SOCKET_NO_MEMORY, NULL, context); + callback(silc_errno, NULL, context); return NULL; } @@@ -203,7 -193,7 +203,7 @@@ silc_free(stream); silc_free(l); if (callback) - callback(SILC_SOCKET_ERROR, NULL, context); + callback(silc_errno, NULL, context); return NULL; } @@@ -213,7 -203,7 +213,7 @@@ return l->op; } else { /* No lookup */ - l->status = SILC_SOCKET_OK; + l->status = SILC_OK; silc_socket_host_lookup_finish(schedule, silc_schedule_get_context(schedule), 0, 0, l); @@@ -229,14 -219,6 +229,14 @@@ SilcStream silc_socket_udp_stream_creat { SilcSocketStream stream; + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + } + stream = silc_calloc(1, sizeof(*stream)); if (!stream) return NULL; @@@ -314,17 -296,17 +314,17 @@@ SilcBool silc_socket_stream_set_info(Si if (hostname) { silc_free(socket_stream->hostname); - socket_stream->hostname = strdup(hostname); + socket_stream->hostname = silc_strdup(hostname); if (!socket_stream->hostname) return FALSE; } if (ip) { silc_free(socket_stream->ip); - socket_stream->ip = strdup(ip); + socket_stream->ip = silc_strdup(ip); if (!socket_stream->ip) return FALSE; if (!socket_stream->hostname) { - socket_stream->hostname = strdup(ip); + socket_stream->hostname = silc_strdup(ip); if (!socket_stream->hostname) return FALSE; } @@@ -335,6 -317,19 +335,6 @@@ return TRUE; } -/* Return socket errno */ - -int silc_socket_stream_get_error(SilcStream stream) -{ - SilcSocketStream socket_stream = stream; - - if (!SILC_IS_SOCKET_STREAM(socket_stream) && - !SILC_IS_SOCKET_STREAM_UDP(socket_stream)) - return 0; - - return socket_stream->sock_error; -} - /* Set QoS for socket stream */ SilcBool silc_socket_stream_set_qos(SilcStream stream, @@@ -355,6 -350,7 +355,7 @@@ !limit_sec && !limit_usec) { silc_schedule_task_del_by_context(socket_stream->schedule, socket_stream->qos); + silc_free(socket_stream->qos->buffer); silc_free(socket_stream->qos); socket_stream->qos = NULL; return TRUE; @@@ -375,7 -371,8 +376,8 @@@ socket_stream->qos->cur_rate = 0; socket_stream->qos->sock = socket_stream; - socket_stream->qos->buffer = silc_malloc(read_limit_bytes); + socket_stream->qos->buffer = silc_realloc(socket_stream->qos->buffer, + read_limit_bytes); if (!socket_stream->qos->buffer) return FALSE; diff --combined lib/silcutil/silcsocketstream_i.h index 894c4b1e,13013f25..aa080ccc --- a/lib/silcutil/silcsocketstream_i.h +++ b/lib/silcutil/silcsocketstream_i.h @@@ -4,7 -4,7 +4,7 @@@ Author: Pekka Riikonen - Copyright (C) 2005 - 2008 Pekka Riikonen + Copyright (C) 2005 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@@ -47,27 -47,19 +47,27 @@@ struct SilcSocketStreamStruct SilcSocket sock; char *hostname; char *ip; - SilcUInt16 port; - SilcUInt16 sock_error; SilcSocketQos qos; SilcStreamNotifier notifier; void *notifier_context; + SilcUInt16 port; unsigned int ipv6 : 1; /* UDP IPv6 */ unsigned int connected : 1; /* UDP connected state */ }; - #define SILC_IS_SOCKET_STREAM(s) (s->ops == &silc_socket_stream_ops) - #define SILC_IS_SOCKET_STREAM_UDP(s) (s->ops == &silc_socket_udp_stream_ops) + #define SILC_IS_SOCKET_STREAM(s) (s && s->ops == &silc_socket_stream_ops) + #define SILC_IS_SOCKET_STREAM_UDP(s) (s && s->ops == &silc_socket_udp_stream_ops) extern const SilcStreamOps silc_socket_stream_ops; extern const SilcStreamOps silc_socket_udp_stream_ops; +/* Backwards support */ +#define SilcSocketStreamStatus SilcResult +#define silc_socket_stream_get_error(stream) silc_errno +#define SILC_SOCKET_OK SILC_OK +#define SILC_SOCKET_UNKNOWN_IP SILC_ERR_UNKNOWN_IP +#define SILC_SOCKET_UNKNOWN_HOST SILC_ERR_UNKNOWN_HOST +#define SILC_SOCKET_NO_MEMORY SILC_ERR_OUT_OF_MEMORY +#define SILC_SOCKET_ERROR SILC_ERR + #endif /* SILCSOCKETSTREAM_I_H */ diff --combined lib/silcutil/unix/silcunixnet.c index f18af24e,2332672d..c216ccca --- a/lib/silcutil/unix/silcunixnet.c +++ b/lib/silcutil/unix/silcunixnet.c @@@ -4,7 -4,7 +4,7 @@@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@@ -16,8 -16,10 +16,8 @@@ GNU General Public License for more details. */ -/* $Id$ */ -#include "silc.h" -#include "silcnet.h" +#include "silcruntime.h" /************************** Types and definitions ***************************/ @@@ -49,31 -51,26 +49,31 @@@ static SilcBool silc_net_set_sockaddr(S if (ip_addr) { if (!silc_net_is_ip(ip_addr)) { SILC_LOG_ERROR(("%s is not IP address", ip_addr)); + silc_set_errno_reason(SILC_ERR_BAD_IP, "%s is not an IP address", + ip_addr); return FALSE; } if (silc_net_is_ip4(ip_addr)) { /* IPv4 address */ len = sizeof(addr->sin.sin_addr); - silc_net_addr2bin(ip_addr, - (unsigned char *)&addr->sin.sin_addr.s_addr, len); + if (!silc_net_addr2bin(ip_addr, + (unsigned char *)&addr->sin.sin_addr.s_addr, len)) + return FALSE; addr->sin.sin_family = AF_INET; addr->sin.sin_port = port ? htons(port) : 0; } else { #ifdef HAVE_IPV6 /* IPv6 address */ len = sizeof(addr->sin6.sin6_addr); - silc_net_addr2bin(ip_addr, - (unsigned char *)&addr->sin6.sin6_addr, len); + if (!silc_net_addr2bin(ip_addr, + (unsigned char *)&addr->sin6.sin6_addr, len)) + return FALSE; addr->sin6.sin6_family = AF_INET6; addr->sin6.sin6_port = port ? htons(port) : 0; #else SILC_LOG_ERROR(("IPv6 support is not compiled in")); + silc_set_errno(SILC_ERR_NOT_SUPPORTED); return FALSE; #endif } @@@ -92,15 -89,15 +92,15 @@@ /* Deliver new stream to upper layer */ -static void silc_net_accept_stream(SilcSocketStreamStatus status, +static void silc_net_accept_stream(SilcResult status, SilcStream stream, void *context) { SilcNetListener listener = context; - if (status != SILC_SOCKET_OK) + if (status != SILC_OK) return; - listener->callback(SILC_NET_OK, stream, listener->context); + listener->callback(SILC_OK, stream, listener->context); } /* Accept incoming connection and notify upper layer */ @@@ -141,18 -138,8 +141,18 @@@ silc_net_tcp_create_listener(const cha SILC_LOG_DEBUG(("Creating TCP listener")); - if (port < 0 || !schedule || !callback) + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } + + if (port < 0 || !callback) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; + } listener = silc_calloc(1, sizeof(*listener)); if (!listener) @@@ -189,9 -176,7 +189,9 @@@ /* Create the socket */ sock = socket(server.sin.sin_family, SOCK_STREAM, 0); if (sock < 0) { - SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno))); + silc_set_errno_posix(errno); + SILC_LOG_ERROR(("Cannot create socket: %s", + silc_errno_string(silc_errno))); goto err; } @@@ -206,9 -191,7 +206,9 @@@ /* Bind the listener socket */ rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server)); if (rval < 0) { - SILC_LOG_ERROR(("Cannot bind socket: %s", strerror(errno))); + silc_set_errno_posix(errno); + SILC_LOG_ERROR(("Cannot bind socket: %s", + silc_errno_string(silc_errno))); close(sock); goto err; } @@@ -216,9 -199,7 +216,9 @@@ /* Specify that we are listenning */ rval = listen(sock, 64); if (rval < 0) { - SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno))); + silc_set_errno_posix(errno); + SILC_LOG_ERROR(("Cannot set socket listenning: %s", + silc_errno_string(silc_errno))); close(sock); goto err; } @@@ -242,140 -223,6 +242,140 @@@ return NULL; } +/* Create TCP listener, multiple ports */ + +SilcNetListener +silc_net_tcp_create_listener2(const char *local_ip_addr, int *ports, + SilcUInt32 port_count, + SilcBool ignore_port_error, + SilcBool lookup, SilcBool require_fqdn, + SilcSchedule schedule, + SilcNetCallback callback, void *context) +{ + SilcNetListener listener = NULL; + SilcSockaddr server; + int i, sock, rval; + const char *ipany = "0.0.0.0"; + + SILC_LOG_DEBUG(("Creating TCP listener")); + + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } + + if (!callback) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + + listener = silc_calloc(1, sizeof(*listener)); + if (!listener) + return NULL; + listener->schedule = schedule; + listener->callback = callback; + listener->context = context; + listener->require_fqdn = require_fqdn; + listener->lookup = lookup; + + if (port_count > 0) { + listener->socks = silc_calloc(port_count, sizeof(*listener->socks)); + if (!listener->socks) + return NULL; + } else { + listener->socks = silc_calloc(1, sizeof(*listener->socks)); + if (!listener->socks) + return NULL; + + port_count = 1; + } + + /* Bind to ports */ + for (i = 0; i < port_count; i++) { + SILC_LOG_DEBUG(("Binding to local address %s:%d", + local_ip_addr ? local_ip_addr : ipany, + ports ? ports[i] : 0)); + + /* Set sockaddr for server */ + if (!silc_net_set_sockaddr(&server, + local_ip_addr ? local_ip_addr : ipany, + ports ? ports[i] : 0)) { + if (ignore_port_error) + continue; + goto err; + } + + /* Create the socket */ + sock = socket(server.sin.sin_family, SOCK_STREAM, 0); + if (sock < 0) { + if (ignore_port_error) + continue; + silc_set_errno_posix(errno); + SILC_LOG_ERROR(("Cannot create socket: %s", + silc_errno_string(silc_errno))); + goto err; + } + + /* Set the socket options */ + rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1); + if (rval < 0) { + close(sock); + if (ignore_port_error) + continue; + SILC_LOG_ERROR(("Cannot set socket options: %s", + silc_errno_string(silc_errno))); + goto err; + } + + /* Bind the listener socket */ + rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server)); + if (rval < 0) { + close(sock); + if (ignore_port_error) + continue; + silc_set_errno_posix(errno); + SILC_LOG_ERROR(("Cannot bind socket: %s", + silc_errno_string(silc_errno))); + goto err; + } + + /* Specify that we are listenning */ + rval = listen(sock, 64); + if (rval < 0) { + close(sock); + if (ignore_port_error) + continue; + silc_set_errno_posix(errno); + SILC_LOG_ERROR(("Cannot set socket listenning: %s", + silc_errno_string(silc_errno))); + goto err; + } + + /* Set the server socket to non-blocking mode */ + silc_net_set_socket_nonblock(sock); + + /* Schedule for incoming connections */ + silc_schedule_task_add_fd(schedule, sock, silc_net_accept, listener); + + SILC_LOG_DEBUG(("TCP listener created, fd=%d", sock)); + listener->socks[i] = sock; + listener->socks_count++; + } + + if (ignore_port_error && !listener->socks_count) + goto err; + + return listener; + + err: + if (listener) + silc_net_close_listener(listener); + return NULL; +} + /* Close network listener */ void silc_net_close_listener(SilcNetListener listener) @@@ -410,13 -257,8 +410,13 @@@ silc_net_udp_connect(const char *local_ SILC_LOG_DEBUG(("Creating UDP stream")); - if (!schedule) - goto err; + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } /* Bind to local addresses */ SILC_LOG_DEBUG(("Binding to local address %s", @@@ -430,24 -272,20 +430,24 @@@ /* Create the socket */ sock = socket(server.sin.sin_family, SOCK_DGRAM, 0); if (sock < 0) { - SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno))); + silc_set_errno_posix(errno); + SILC_LOG_ERROR(("Cannot create socket: %s", + silc_errno_string(silc_errno))); goto err; } /* Set the socket options */ rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1); if (rval < 0) { - SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); + SILC_LOG_ERROR(("Cannot set socket options: %s", + silc_errno_string(silc_errno))); goto err; } #ifdef SO_REUSEPORT rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEPORT, 1); if (rval < 0) { - SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno))); + SILC_LOG_ERROR(("Cannot set socket options: %s", + silc_errno_string(silc_errno))); goto err; } #endif /* SO_REUSEPORT */ @@@ -455,8 -293,7 +455,8 @@@ /* Bind the listener socket */ rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server)); if (rval < 0) { - SILC_LOG_DEBUG(("Cannot bind socket: %s", strerror(errno))); + silc_set_errno_posix(errno); + SILC_LOG_DEBUG(("Cannot bind socket: %s", silc_errno_string(silc_errno))); goto err; } @@@ -467,9 -304,7 +467,9 @@@ rval = connect(sock, &server.sa, SIZEOF_SOCKADDR(server)); if (rval < 0) { - SILC_LOG_DEBUG(("Cannot connect UDP stream: %s", strerror(errno))); + silc_set_errno_posix(errno); + SILC_LOG_DEBUG(("Cannot connect UDP stream: %s", + silc_errno_string(silc_errno))); goto err; } } @@@ -522,8 -357,7 +522,8 @@@ int silc_net_udp_receive(SilcStream str SilcSocketStream sock = stream; SilcSockaddr s; struct sockaddr *from; - int len, flen; + int len; + unsigned int flen; SILC_LOG_DEBUG(("Reading data from UDP socket %d", sock->sock)); @@@ -542,7 -376,6 +542,7 @@@ len = recv(sock->sock, ret_data, data_size, 0); if (len < 0) { + silc_set_errno_posix(errno); if (errno == EAGAIN || errno == EINTR) { SILC_LOG_DEBUG(("Could not read immediately, will do it later")); silc_schedule_set_listen_fd(sock->schedule, sock->sock, @@@ -552,6 -385,7 +552,6 @@@ SILC_LOG_DEBUG(("Cannot read from UDP socket: %d:%s", sock->sock, strerror(errno))); silc_schedule_unset_listen_fd(sock->schedule, sock->sock); - sock->sock_error = errno; return -2; } @@@ -602,7 -436,6 +602,7 @@@ int silc_net_udp_send(SilcStream stream ret = sendto(sock->sock, data, data_len, 0, &remote.sa, SIZEOF_SOCKADDR(remote)); if (ret < 0) { + silc_set_errno_posix(errno); if (errno == EAGAIN || errno == EINTR) { SILC_LOG_DEBUG(("Could not send immediately, will do it later")); silc_schedule_set_listen_fd(sock->schedule, sock->sock, @@@ -611,6 -444,7 +611,6 @@@ } SILC_LOG_DEBUG(("Cannot send to UDP socket: %s", strerror(errno))); silc_schedule_unset_listen_fd(sock->schedule, sock->sock); - sock->sock_error = errno; return -2; } @@@ -628,7 -462,8 +628,7 @@@ /* Asynchronous TCP/IP connecting */ typedef struct { - SilcNetStatus status; - SilcSocketStreamStatus stream_status; + SilcResult status; SilcStream stream; SilcFSMStruct fsm; SilcFSMEventStruct event; @@@ -677,7 -512,7 +677,7 @@@ SILC_FSM_STATE(silc_net_connect_st_star "host", conn->remote)); /** Network unreachable */ - conn->status = SILC_NET_HOST_UNREACHABLE; + conn->status = SILC_ERR_UNREACHABLE; silc_fsm_next(fsm, silc_net_connect_st_finish); return SILC_FSM_CONTINUE; } @@@ -700,7 -535,6 +700,7 @@@ } /** Cannot create socket */ + silc_set_errno_posix(errno); SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno))); silc_fsm_next(fsm, silc_net_connect_st_finish); return SILC_FSM_CONTINUE; @@@ -722,7 -556,6 +722,7 @@@ rval = connect(sock, &desthost.sa, SIZEOF_SOCKADDR(desthost)); if (rval < 0) { if (errno != EINPROGRESS) { + silc_set_errno_posix(errno); shutdown(sock, 2); close(sock); @@@ -733,8 -566,7 +733,8 @@@ } /** Cannot connect to remote host */ - SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno))); + SILC_LOG_ERROR(("Cannot connect to remote host: %s", + silc_errno_string(silc_errno))); silc_fsm_next(fsm, silc_net_connect_st_finish); return SILC_FSM_CONTINUE; } @@@ -761,12 -593,12 +761,12 @@@ return SILC_FSM_CONTINUE; } -static void silc_net_connect_wait_stream(SilcSocketStreamStatus status, +static void silc_net_connect_wait_stream(SilcResult status, SilcStream stream, void *context) { SilcNetConnect conn = context; conn->sop = NULL; - conn->stream_status = status; + conn->status = status; conn->stream = stream; SILC_FSM_CALL_CONTINUE(&conn->fsm); } @@@ -801,13 -633,21 +801,13 @@@ SILC_FSM_STATE(silc_net_connect_st_conn return SILC_FSM_CONTINUE; } -#if defined(ECONNREFUSED) - if (opt == ECONNREFUSED) - conn->status = SILC_NET_CONNECTION_REFUSED; -#endif /* ECONNREFUSED */ -#if defined(ETIMEDOUT) - if (opt == ETIMEDOUT) - conn->status = SILC_NET_CONNECTION_TIMEOUT; -#endif /* ETIMEDOUT */ -#if defined(ENETUNREACH) - if (opt == ENETUNREACH) - conn->status = SILC_NET_HOST_UNREACHABLE; -#endif /* ENETUNREACH */ + /* Set error */ + silc_set_errno_posix(opt); + conn->status = silc_errno; /** Connecting failed */ - SILC_LOG_DEBUG(("Connecting failed, error %s", strerror(opt))); + SILC_LOG_DEBUG(("Connecting failed, error %s", + silc_errno_string(silc_errno))); silc_fsm_next(fsm, silc_net_connect_st_finish); return SILC_FSM_CONTINUE; } @@@ -831,15 -671,21 +831,15 @@@ SILC_FSM_STATE(silc_net_connect_st_stre return SILC_FSM_CONTINUE; } - if (conn->stream_status != SILC_SOCKET_OK) { + if (conn->status != SILC_OK) { /** Stream creation failed */ - if (conn->stream_status == SILC_SOCKET_UNKNOWN_IP) - conn->status = SILC_NET_UNKNOWN_IP; - else if (conn->stream_status == SILC_SOCKET_UNKNOWN_HOST) - conn->status = SILC_NET_UNKNOWN_HOST; - else - conn->status = SILC_NET_ERROR; silc_fsm_next(fsm, silc_net_connect_st_finish); return SILC_FSM_CONTINUE; } /** Stream created successfully */ SILC_LOG_DEBUG(("Connected successfully, sock %d", conn->sock)); - conn->status = SILC_NET_OK; + conn->status = SILC_OK; silc_fsm_next(fsm, silc_net_connect_st_finish); return SILC_FSM_CONTINUE; } @@@ -855,6 -701,9 +855,9 @@@ SILC_FSM_STATE(silc_net_connect_st_fini silc_async_free(conn->op); } + if (conn->sock && conn->status != SILC_NET_OK) + silc_net_close_connection(conn->sock); + return SILC_FSM_FINISH; } @@@ -890,25 -739,15 +893,25 @@@ SilcAsyncOperation silc_net_tcp_connect { SilcNetConnect conn; - if (!remote_ip_addr || remote_port < 1 || !schedule || !callback) + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + } + + if (!remote_ip_addr || remote_port < 1 || !callback) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return NULL; + } SILC_LOG_DEBUG(("Creating connection to host %s port %d", remote_ip_addr, remote_port)); conn = silc_calloc(1, sizeof(*conn)); if (!conn) { - callback(SILC_NET_NO_MEMORY, NULL, context); + callback(silc_errno, NULL, context); return NULL; } @@@ -916,25 -755,25 +919,25 @@@ conn->op = silc_async_alloc(silc_net_connect_abort, NULL, conn); if (!conn->op) { silc_free(conn); - callback(SILC_NET_NO_MEMORY, NULL, context); + callback(silc_errno, NULL, context); return NULL; } if (local_ip_addr) - conn->local_ip = strdup(local_ip_addr); - conn->remote = strdup(remote_ip_addr); + conn->local_ip = silc_strdup(local_ip_addr); + conn->remote = silc_strdup(remote_ip_addr); if (!conn->remote) { silc_async_free(conn->op); silc_free(conn->local_ip); silc_free(conn); - callback(SILC_NET_NO_MEMORY, NULL, context); + callback(silc_errno, NULL, context); return NULL; } conn->port = remote_port; conn->callback = callback; conn->context = context; conn->retry = 1; - conn->status = SILC_NET_ERROR; + conn->status = SILC_ERR; silc_fsm_init(&conn->fsm, conn, silc_net_connect_destructor, NULL, schedule); silc_fsm_start(&conn->fsm, silc_net_connect_st_start); @@@ -954,10 -793,7 +957,10 @@@ void silc_net_close_connection(int sock int silc_net_set_socket_nonblock(SilcSocket sock) { - return fcntl((int)sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK); + int ret = fcntl((int)sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK); + if (ret) + silc_set_errno_posix(errno); + return ret; } /* Converts the IP number string from numbers-and-dots notation to @@@ -970,17 -806,9 +973,17 @@@ SilcBool silc_net_addr2bin(const char * if (silc_net_is_ip4(addr)) { /* IPv4 address */ struct in_addr tmp; + + if (bin_len < 4) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + ret = inet_aton(addr, &tmp); - if (bin_len < 4) + if (!ret) { + silc_set_errno_posix(errno); return FALSE; + } memcpy(bin, (unsigned char *)&tmp.s_addr, 4); #ifdef HAVE_IPV6 @@@ -989,10 -817,8 +992,10 @@@ SilcSockaddr *s; /* IPv6 address */ - if (bin_len < 16) + if (bin_len < 16) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return FALSE; + } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; diff --combined lib/silcutil/unix/silcunixschedule.c index 5626eef5,80e8fbf2..1543d16e --- a/lib/silcutil/unix/silcunixschedule.c +++ b/lib/silcutil/unix/silcunixschedule.c @@@ -16,8 -16,9 +16,8 @@@ GNU General Public License for more details. */ -/* $Id$ */ -#include "silc.h" +#include "silcruntime.h" #if defined(HAVE_EPOLL_WAIT) #include @@@ -287,6 -288,7 +287,7 @@@ SilcBool silc_schedule_internal_schedul SILC_LOG_DEBUG(("epoll_ctl (DEL): %s", strerror(errno))); return FALSE; } + task->scheduled = FALSE; return TRUE; } @@@ -353,7 -355,7 +354,7 @@@ void *silc_schedule_internal_init(SilcS SilcUnixScheduler internal; int i; - internal = silc_calloc(1, sizeof(*internal)); + internal = silc_scalloc(schedule->stack, 1, sizeof(*internal)); if (!internal) return NULL; @@@ -393,6 -395,7 +394,6 @@@ #ifdef SILC_THREADS if (pipe(internal->wakeup_pipe)) { SILC_LOG_ERROR(("pipe() fails: %s", strerror(errno))); - silc_free(internal); return NULL; } @@@ -436,6 -439,8 +437,6 @@@ void silc_schedule_internal_uninit(Silc #elif defined(HAVE_POLL) && defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) silc_free(internal->fds); #endif /* HAVE_POLL && HAVE_SETRLIMIT && RLIMIT_NOFILE */ - - silc_free(internal); } /* Wakes up the scheduler */ diff --combined lib/silcutil/unix/silcunixsocketstream.c index 552fa611,60d458d4..35b0ceed --- a/lib/silcutil/unix/silcunixsocketstream.c +++ b/lib/silcutil/unix/silcunixsocketstream.c @@@ -16,8 -16,9 +16,8 @@@ GNU General Public License for more details. */ -/* $Id$ */ -#include "silc.h" +#include "silcruntime.h" /************************ Static utility functions **************************/ @@@ -76,7 -77,6 +76,7 @@@ int silc_socket_stream_read(SilcStream if (!sock->qos) { len = read(sock->sock, buf, buf_len); if (len < 0) { + silc_set_errno_posix(errno); if (errno == EAGAIN || errno == EINTR) { SILC_LOG_DEBUG(("Could not read immediately, will do it later")); silc_schedule_set_listen_fd(sock->schedule, sock->sock, @@@ -88,6 -88,7 +88,6 @@@ SILC_LOG_DEBUG(("Cannot read from socket: %d:%s", sock->sock, strerror(errno))); silc_schedule_unset_listen_fd(sock->schedule, sock->sock); - sock->sock_error = errno; return -2; } @@@ -105,8 -106,9 +105,9 @@@ /* If QoS was applied, return the data that was pending. */ if (sock->qos->applied && sock->qos->data_len) { memcpy(buf, qosbuf, sock->qos->data_len); + len = sock->qos->data_len; sock->qos->data_len = 0; - return sock->qos->data_len; + return len; } /* If we have active QoS data pending, return with no data */ @@@ -115,12 -117,12 +116,13 @@@ return -1; } - /* Read the data from the socket. Never read more than the max limit. */ + /* Read the data from the socket. The qosbuf size is always the max + read limit size. */ len = (buf_len < sock->qos->read_limit_bytes ? buf_len : sock->qos->read_limit_bytes); len = read(sock->sock, qosbuf, len); if (len < 0) { + silc_set_errno_posix(errno); if (errno == EAGAIN || errno == EINTR) { SILC_LOG_DEBUG(("Could not read immediately, will do it later")); silc_schedule_set_listen_fd(sock->schedule, sock->sock, @@@ -134,6 -136,7 +136,6 @@@ silc_schedule_unset_listen_fd(sock->schedule, sock->sock); silc_schedule_task_del_by_context(sock->schedule, sock->qos); sock->qos->data_len = 0; - sock->sock_error = errno; return -2; } @@@ -185,7 -188,6 +187,7 @@@ int silc_socket_stream_write(SilcStrea ret = write(sock->sock, data, data_len); if (ret < 0) { + silc_set_errno_posix(errno); if (errno == EAGAIN || errno == EINTR) { SILC_LOG_DEBUG(("Could not write immediately, will do it later")); silc_schedule_set_listen_fd(sock->schedule, sock->sock, @@@ -194,6 -196,7 +196,6 @@@ } SILC_LOG_DEBUG(("Cannot write to socket: %s", strerror(errno))); silc_schedule_unset_listen_fd(sock->schedule, sock->sock); - sock->sock_error = errno; return -2; } @@@ -229,6 -232,27 +231,6 @@@ int silc_socket_udp_stream_write(SilcSt return silc_socket_stream_write(stream, data, data_len); } -#if 0 -/* Returns human readable socket error message */ - -SilcBool silc_socket_get_error(SilcStream sock, char *error, - SilcUInt32 error_len) -{ - char *err; - - if (!sock->sock_error) - return FALSE; - - err = strerror(sock->sock_error); - if (strlen(err) > error_len) - return FALSE; - - memset(error, 0, error_len); - memcpy(error, err, strlen(err)); - return TRUE; -} -#endif - /* Closes socket */ SilcBool silc_socket_stream_close(SilcStream stream)