-
+ Thu Mar 13 13:31:35 EET 2008 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed silcd crash in NEW_CLIENT packet handling when nickname
+ is not present in the packet. Affected files are
+ apps/silcd/packet_receive.c.
+
+ Fri Feb 22 16:12:27 EET 2008 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed partial encryption in CTR mode in AES. Change does not
+ affect interoperability in SILC due to the way CTR is used in
+ SILC. But, fixed anyway. Affected files are
+ lib/silccrypt/aes.c and rijndael_internal.h.
+
+ Tue Jan 8 09:41:57 EET 2008 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed printable fingerprint bufferoverlfow, RedHat bug 372021.
+ Affected file is lib/silcutil/silcutil.c.
+
+ Sun Dec 30 14:00:46 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed unix signal delivery in SILC scheduler. Affected file
+ is lib/silcutil/unix/silcunixschedule.c.
+
+ Sun Nov 18 16:43:04 CET 2007 Jochen Eisinger <coffee@silcnet.org>
+
+ * Add -avoid-version and -rpath flags when compiling the plugin.
+ Affected file is apps/irssi/src/fe-common/silc/Makefile.in
+
+ Thu Nov 15 18:03:53 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Reprocess JOIN command synchronously after resolving channel
+ user list. Affected file is lib/silcclient/command_reply.c.
+
+ * In JOIN command reply check if the channel key is already
+ saved. If it is we have received new key from server while
+ resolving user and must not save the old key. Affected file
+ is lib/silcclient/command_reply.c.
+
+ * Remove all channel keys and hmacs after giving LEAVE command.
+ Affected file is lib/silcclient/command_reply.c.
+
+ Tue Nov 13 18:24:56 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added missing channel unreferencing in CMODE, CUMODE,
+ TOPIC, INVITE, BAN and KICK command replies. Affected
+ file is lib/silcclient/command_reply.c.
+
+ Sun Nov 11 23:04:54 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Free stream data and abort ongoing protocols correctly
+ for primary router connections receiving end of stream.
+ Affected file is apps/silcd/server.c.
+
+ Sun Nov 11 16:02:12 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * SILC Server 1.1 Beta4.
+
+ Sun Nov 11 14:15:48 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * SILC Toolkit 1.1.5.
++
+ Sun Nov 11 11:22:35 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed connection authentication with public keys to use
+ correct public key as responder. Affected file is
+ lib/silcske/silcconnauth.c.
+
+ * Fixed public key authentication in server. Affected file is
+ apps/silcd/serverconfig.c.
+
+ * Fixed OPER and SILCOPER public key authentication. Affected
+ file is apps/silcd/server.c.
+
+ * Fixed prefer_passphrase_auth flag in server. Fixed
+ disconnection of unauthenticated connection. Affected file is
+ apps/silcd/server.c.
+
+ * Fixed client resuming in server. Affected file is
+ apps/silcd/packet_receive.c.
+
+ * Fixed IDENTIFY and WHOWAS command reply to correctly update
+ client entries (fixes a crash). Affected file is
+ apps/silcd/command_reply.c.
+
+ Tue Nov 6 16:39:20 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * SILC Client 1.1.3.
+
+ Mon Nov 5 23:07:58 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Zero tail of CTR mode IV in IV Included mode. Change does
+ not cause compatibility issues. Affected file is
+ lib/silcske/silcske.c.
+
+ Mon Nov 5 22:24:25 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * SILC Toolkit 1.1.4.
+
+ * Fixed CTR mode rekey. Affected file is lib/silcske/silcske.c.
+
+ * Rewrote the IV Included CTR mode encryption/decryption in
+ packet engine. Affected file is lib/silccore/silcpacket.c.
+
+ Sun Nov 4 15:20:25 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Removed module_path and module options from the server
+ config file format. Affected file is apps/silcd/serverconfig.c.
+
+ * Fixed non-IPv6 compilation error. Affected file is
+ lib/silcutil/unix/silcunixnet.c.
+
+ Sat Nov 3 23:23:38 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Do not free packet engine before uninitializing scheduler.
+ Do not disconnct already disconnected streams. Affected
+ files are in apps/silcd/.
+
+ * Fixed setting correct ID for re-encrypted channel messages
+ in router-to-router connections. Affected file is
+ apps/silcd/packet_send.c.
+
+ Sun Sep 30 15:16:18 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed channel private key deleting when deleting the channel.
+ Affected file is lib/silcclient/client_channel.c.
+
+ Sun Sep 9 17:52:49 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * SILC Toolkit 1.1.3.
+
+ * Fixed possible buffer overflows from SILC Config code.
+ Patch from Jérémy Bobbio. Affected file is
+ lib/silcutil/silcconfig.c.
+
+ Sun Aug 26 12:28:49 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed TIMEOUT handling in user info resolving during JOINing,
+ fixes crash. Affected file is lib/silcclient/client_notify.c.
+
+ * Fixed mandatory UN and HN SILC public key identifier checking
+ (both must be present). Affected file is
+ lib/silccrypt/silcpk.c.
+
+ Tue Aug 7 20:56:06 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed alignment issues with 64-bit CPUs. Affected files
+ are lib/silcutil/silcschedule.c and unix/silcunixschedule.c.
+
+ * Added "There are now xx nick's" to "are xx nicks". Affected
+ file is apps/irssi/src/fe-common/silc/module-formats.c.
+
+ Sat Aug 4 18:37:22 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed USERS command user mode handling (integer overflow).
+ Affected file is lib/silcclient/command_reply.c.
+
+ Thu Jul 19 21:08:49 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed big-endian issues from aes implementation. Affected
+ files are lib/silccrypt/aes.c.
+
+ * Fixed lib/silcutil/silcatomic.h compilation on IA64. Patch
+ from Jérémy Bobbio.
+
+ * Fixed public key identifier parsing to check lengths
+ correctly. Affected file is lib/silccrypt/silcpk.c.
+
+ Wed Jul 4 08:06:38 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * SILC Toolkit 1.1.2.
+
+ * SILC Client 1.1.2.
+
+ Mon Jul 2 17:28:47 CEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * In silc_client_free check that scheduler is allocated before
+ trying to free it. Affected file is lib/silcclient/client.c.
+
+ * Fixed buffer overflow in NICK_CHANGE notify. The destination
+ buffer for old nickname was too small. Affected file is
+ lib/silclient/client_notify.c.
+
Sun Jul 1 19:15:15 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
* SILC Server 1.1 Beta1.
* 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
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>
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.
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.
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
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.
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
-
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2007 Pekka Riikonen
+ Copyright (C) 1997 - 2008 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
GNU General Public License for more details.
*/
-/* $Id$ */
-#include "silc.h"
+#include "silcruntime.h"
/************************** Types and definitions ***************************/
flen += req; \
} while(0)
-/* Check that there is data to be unformatted */
-#define UNFORMAT_HAS_SPACE(b, req) \
-do { \
- if (silc_unlikely(req > silc_buffer_len(b))) \
- goto fail; \
- if (silc_unlikely((req + 1) <= 0)) \
- goto fail; \
+/* Check that buffer has enough room to format data in it, if not
+ allocate more. This will append, thus not replacing any existing data. */
+#define FORMAT_HAS_SPACE_APPEND(s, b, req) \
+do { \
+ if (silc_buffer_len(b) < req) \
+ if (silc_unlikely(!silc_buffer_sappend(s, b, req - silc_buffer_len(b)))) \
+ goto fail; \
+ flen += req; \
} while(0)
+/* Check that there is data to be unformatted */
+#define UNFORMAT_HAS_SPACE(b, req) \
+do { \
+ if (silc_unlikely(req > silc_buffer_len(b))) { \
+ silc_set_errno(SILC_ERR_OVERFLOW); \
+ goto fail; \
+ } \
+ if (silc_unlikely((req + 1) <= 0)) { \
+ silc_set_errno(SILC_ERR_OVERFLOW); \
+ goto fail; \
+ } \
+} while(0)
-/******************************* Formatting *********************************/
-
-int silc_buffer_format(SilcBuffer dst, ...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, dst);
- ret = silc_buffer_sformat_vp(NULL, dst, ap);
- va_end(ap);
-
- return ret;
-}
-
-int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
+#if defined(SILC_DEBUG)
+static const char *silc_param_string(SilcParam fmt)
{
- return silc_buffer_sformat_vp(NULL, dst, ap);
+ if (fmt == SILC_PARAM_SINT8)
+ return "SINT8";
+ if (fmt == SILC_PARAM_UINT8)
+ return "UINT8";
+ if (fmt == SILC_PARAM_SINT16)
+ return "SINT16";
+ if (fmt == SILC_PARAM_UINT16)
+ return "UINT16";
+ if (fmt == SILC_PARAM_SINT32)
+ return "SINT32";
+ if (fmt == SILC_PARAM_UINT32)
+ return "UINT32";
+ if (fmt == SILC_PARAM_SINT64)
+ return "SINT64";
+ if (fmt == SILC_PARAM_UINT64)
+ return "UINT64";
+ if (fmt == SILC_PARAM_SICHAR)
+ return "SICHAR";
+ if (fmt == (SILC_PARAM_SICHAR | SILC_PARAM_ALLOC))
+ return "SICHAR ALLOC";
+ if (fmt == SILC_PARAM_UICHAR)
+ return "UICHAR";
+ if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_ALLOC))
+ return "UICHAR ALLOC";
+ if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_REPLACE))
+ return "UICHAR REPLACE";
+ if (fmt == SILC_PARAM_BUFFER)
+ return "BUFFER";
+ if (fmt == (SILC_PARAM_BUFFER | SILC_PARAM_ALLOC))
+ return "BUFFER ALLOC";
+ if (fmt == SILC_PARAM_PTR)
+ return "PTR";
+ if (fmt == SILC_PARAM_END)
+ return "END";
+ if (fmt == SILC_PARAM_UI8_STRING)
+ return "UI8_STRING";
+ if (fmt == SILC_PARAM_UI16_STRING)
+ return "UI16_STRING";
+ if (fmt == SILC_PARAM_UI32_STRING)
+ return "UI32_STRING";
+ if (fmt == SILC_PARAM_UI8_NSTRING)
+ return "UI8_STRING";
+ if (fmt == SILC_PARAM_UI16_NSTRING)
+ return "UI16_STRING";
+ if (fmt == SILC_PARAM_UI32_NSTRING)
+ return "UI32_STRING";
+ if (fmt == (SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC))
+ return "UI8_STRING ALLOC";
+ if (fmt == (SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC))
+ return "UI16_STRING ALLOC";
+ if (fmt == (SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC))
+ return "UI32_STRING ALLOC";
+ if (fmt == (SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC))
+ return "UI8_STRING ALLOC";
+ if (fmt == (SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC))
+ return "UI16_STRING ALLOC";
+ if (fmt == (SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC))
+ return "UI32_STRING";
+ if (fmt == SILC_PARAM_OFFSET)
+ return "OFFSET";
+ if (fmt == SILC_PARAM_ADVANCE)
+ return "ADDVANCE";
+ if (fmt == SILC_PARAM_FUNC)
+ return "FUNC";
+ if (fmt == SILC_PARAM_REGEX)
+ return "REGEX";
+ if (fmt == SILC_PARAM_OFFSET_START)
+ return "OFFSET_START";
+ if (fmt == SILC_PARAM_OFFSET_END)
+ return "OFFSET_END";
+ if (fmt == SILC_PARAM_DELETE)
+ return "DELETE";
+ return "";
}
+#endif /* SILC_DEBUG */
-int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, dst);
- ret = silc_buffer_sformat_vp(stack, dst, ap);
- va_end(ap);
-
- return ret;
-}
+/******************************* Formatting *********************************/
-int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
+int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
+ SilcBool process)
{
- SilcBufferParamType fmt;
+ SilcParam fmt;
int flen = 0;
SilcBool advance = FALSE;
/* Parse the arguments by formatting type. */
while (1) {
- fmt = va_arg(ap, SilcBufferParamType);
+ fmt = va_arg(ap, SilcParam);
+
+#if defined(SILC_DEBUG)
+ if (process)
+ SILC_LOG_DEBUG(("Buffer format type %s (%d)",
+ silc_param_string(fmt), fmt));
+#endif /* SILC_DEBUG */
- switch(fmt) {
+ switch (fmt) {
case SILC_PARAM_FUNC:
{
- SilcBufferFormatFunc func = NULL;
- SilcBufferSFormatFunc funcs = NULL;
+ SilcBufferFormatFunc func;
void *val;
void *context;
int tmp_len;
- if (!stack)
- func = va_arg(ap, SilcBufferFormatFunc);
- else
- funcs = va_arg(ap, SilcBufferSFormatFunc);
+
+ func = va_arg(ap, SilcBufferFormatFunc);
val = va_arg(ap, void *);
context = va_arg(ap, void *);
- if (!stack)
- tmp_len = func(dst, val, context);
- else
- tmp_len = funcs(stack, dst, val, context);
+
+ if (!process)
+ break;
+
+ tmp_len = func(stack, dst, val, context);
if (tmp_len < 0)
goto fail;
if (tmp_len) {
silc_buffer_pull(dst, tmp_len);
flen += tmp_len;
}
+ break;
}
- break;
+
+ case SILC_PARAM_REGEX:
+ {
+ const char *regex = va_arg(ap, char *);
+ SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags);
+ SilcBufferStruct match;
+ SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
+ SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
+ SilcBool ret;
+ SilcUInt32 inclusive_pos = 0;
+ int matched = 0, ret_len;
+ va_list cp;
+
+ if (!process)
+ break;
+
+ if (!regex)
+ break;
+
+ if (match_nl) {
+ start_nl_match:
+ /* Match for '\n' in the buffer. If not found, treat as line
+ without '\n' (buffer has only one line, or this is last line). */
+ if (silc_regex_buffer(dst, "\n", &match, NULL))
+ dst->tail = match.tail;
+ }
+
+ start_match:
+ /* Match */
+ ret = silc_regex_buffer(dst, regex, &match, NULL);
+ ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
+ if (!ret) {
+ if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
+ goto fail;
+ }
+ goto end_match;
+ }
+ matched++;
+
+ if (rflags & SILC_STR_REGEX_NOT)
+ match = *dst;
+
+ if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
+ /* Advance buffer after match */
+ flen += (match.data - dst->data);
+ if (!silc_buffer_pull(dst, (match.data - dst->data)))
+ goto fail;
+ }
+
+ if (rflags & SILC_STR_REGEX_INCLUSIVE) {
+ inclusive_pos = dst->tail - match.tail;
+ dst->tail = match.tail;
+ }
+
+ /* Recursively format */
+ silc_va_copy(cp, ap);
+ ret_len = silc_buffer_sformat_vp_i(stack, dst, cp, TRUE);
+ va_end(cp);
+ if (ret_len < 0)
+ goto fail;
+
+ if (rflags & SILC_STR_REGEX_INCLUSIVE)
+ if (!silc_buffer_pull_tail(dst, inclusive_pos))
+ goto fail;
+
+ /* Advance buffer after formatting */
+ flen += ret_len;
+ if (!silc_buffer_pull(dst, ret_len))
+ goto fail;
+
+ if (match_all && (!match_nl || silc_buffer_len(dst) > 1))
+ goto start_match;
+
+ end_match:
+ if (match_nl) {
+ /* Go to next line, it is at the end of the data area. Adjust
+ the tail area of the target buffer to show rest of the buffer. */
+ flen += (dst->tail - dst->data);
+ if (!silc_buffer_pull(dst, (dst->tail - dst->data)))
+ goto fail;
+ if (!silc_buffer_pull_tail(dst, silc_buffer_taillen(dst)))
+ goto fail;
+
+ if (silc_buffer_len(dst) > 0)
+ goto start_nl_match;
+ }
+
+ /* Skip to the next SILC_PARAM_END */
+ silc_buffer_sformat_vp_i(NULL, NULL, ap, FALSE);
+ break;
+ }
+
case SILC_PARAM_UI8_STRING:
case SILC_PARAM_UI16_STRING:
case SILC_PARAM_UI32_STRING:
- case SILC_PARAM_UI8_STRING_ALLOC:
- case SILC_PARAM_UI16_STRING_ALLOC:
- case SILC_PARAM_UI32_STRING_ALLOC:
+ case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
+ case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
+ case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
{
- unsigned char *x = va_arg(ap, unsigned char *);
+ char *x = va_arg(ap, char *);
SilcUInt32 tmp_len = x ? strlen(x) : 0;
+
+ if (!process)
+ break;
+
if (x && tmp_len) {
FORMAT_HAS_SPACE(stack, dst, tmp_len);
- silc_buffer_put(dst, x, tmp_len);
+ silc_buffer_put(dst, (unsigned char *)x, tmp_len);
silc_buffer_pull(dst, tmp_len);
}
break;
}
+
+ case SILC_PARAM_UICHAR | SILC_PARAM_REPLACE:
+ {
+ unsigned char *x = va_arg(ap, unsigned char *);
+ SilcUInt32 x_len = va_arg(ap, SilcUInt32);
+
+ if (!process)
+ break;
+
+ if (!x)
+ break;
+
+ if (silc_buffer_len(dst) == x_len) {
+ /* Replace */
+ if (x_len) {
+ silc_buffer_put(dst, x, x_len);
+ silc_buffer_pull(dst, x_len);
+ flen += x_len;
+ }
+ } else if (silc_buffer_len(dst) < x_len) {
+ /* Append */
+ if (x_len) {
+ FORMAT_HAS_SPACE_APPEND(stack, dst, x_len);
+ silc_buffer_put(dst, x, x_len);
+ silc_buffer_pull(dst, x_len);
+ }
+ } else {
+ /* Delete */
+ if (x_len) {
+ silc_buffer_put(dst, x, x_len);
+ silc_buffer_pull(dst, x_len);
+ flen += x_len;
+ }
+ goto delete_rest;
+ }
+ break;
+ }
+
case SILC_PARAM_UI8_NSTRING:
case SILC_PARAM_UI16_NSTRING:
case SILC_PARAM_UI32_NSTRING:
- case SILC_PARAM_UI_XNSTRING:
- case SILC_PARAM_DATA:
- case SILC_PARAM_UI8_NSTRING_ALLOC:
- case SILC_PARAM_UI16_NSTRING_ALLOC:
- case SILC_PARAM_UI32_NSTRING_ALLOC:
- case SILC_PARAM_UI_XNSTRING_ALLOC:
- case SILC_PARAM_DATA_ALLOC:
+ case SILC_PARAM_UICHAR:
+ case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
+ case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
+ case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
+ case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
{
unsigned char *x = va_arg(ap, unsigned char *);
SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
+
+ if (!process)
+ break;
+
if (x && tmp_len) {
FORMAT_HAS_SPACE(stack, dst, tmp_len);
silc_buffer_put(dst, x, tmp_len);
}
break;
}
- case SILC_PARAM_UI8_CHAR:
+
+ case SILC_PARAM_UINT8:
{
unsigned char x = (unsigned char)va_arg(ap, int);
+
+ if (!process)
+ break;
+
FORMAT_HAS_SPACE(stack, dst, 1);
silc_buffer_put(dst, &x, 1);
silc_buffer_pull(dst, 1);
break;
}
- case SILC_PARAM_UI16_SHORT:
+
+ case SILC_PARAM_UINT16:
{
unsigned char xf[2];
SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
+
+ if (!process)
+ break;
+
FORMAT_HAS_SPACE(stack, dst, 2);
SILC_PUT16_MSB(x, xf);
silc_buffer_put(dst, xf, 2);
silc_buffer_pull(dst, 2);
break;
}
- case SILC_PARAM_UI32_INT:
+
+ case SILC_PARAM_UINT32:
{
unsigned char xf[4];
SilcUInt32 x = va_arg(ap, SilcUInt32);
+
+ if (!process)
+ break;
+
FORMAT_HAS_SPACE(stack, dst, 4);
SILC_PUT32_MSB(x, xf);
silc_buffer_put(dst, xf, 4);
silc_buffer_pull(dst, 4);
break;
}
- case SILC_PARAM_UI64_INT:
+
+ case SILC_PARAM_UINT64:
{
unsigned char xf[8];
SilcUInt64 x = va_arg(ap, SilcUInt64);
+
+ if (!process)
+ break;
+
FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
SILC_PUT64_MSB(x, xf);
silc_buffer_put(dst, xf, sizeof(SilcUInt64));
silc_buffer_pull(dst, sizeof(SilcUInt64));
break;
}
- case SILC_PARAM_SI8_CHAR:
+
+ case SILC_PARAM_SINT8:
{
char x = (char)va_arg(ap, int);
+
+ if (!process)
+ break;
+
FORMAT_HAS_SPACE(stack, dst, 1);
- silc_buffer_put(dst, &x, 1);
+ silc_buffer_put(dst, (unsigned char *)&x, 1);
silc_buffer_pull(dst, 1);
break;
}
- case SILC_PARAM_SI16_SHORT:
+
+ case SILC_PARAM_SINT16:
{
unsigned char xf[2];
SilcInt16 x = (SilcInt16)va_arg(ap, int);
+
+ if (!process)
+ break;
+
FORMAT_HAS_SPACE(stack, dst, 2);
SILC_PUT16_MSB(x, xf);
silc_buffer_put(dst, xf, 2);
silc_buffer_pull(dst, 2);
break;
}
- case SILC_PARAM_SI32_INT:
+
+ case SILC_PARAM_SINT32:
{
unsigned char xf[4];
SilcInt32 x = va_arg(ap, SilcInt32);
+
+ if (!process)
+ break;
+
FORMAT_HAS_SPACE(stack, dst, 4);
SILC_PUT32_MSB(x, xf);
silc_buffer_put(dst, xf, 4);
silc_buffer_pull(dst, 4);
break;
}
- case SILC_PARAM_SI64_INT:
+
+ case SILC_PARAM_SINT64:
{
unsigned char xf[8];
SilcInt64 x = va_arg(ap, SilcInt64);
+
+ if (!process)
+ break;
+
FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
SILC_PUT64_MSB(x, xf);
silc_buffer_put(dst, xf, sizeof(SilcInt64));
silc_buffer_pull(dst, sizeof(SilcInt64));
break;
}
+
case SILC_PARAM_BUFFER:
- case SILC_PARAM_BUFFER_ALLOC:
+ case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
{
SilcBuffer x = va_arg(ap, SilcBuffer);
unsigned char xf[4];
+
+ if (!process)
+ break;
+
if (x && silc_buffer_len(x)) {
FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
SILC_PUT32_MSB(silc_buffer_len(x), xf);
}
}
break;
+
+ case SILC_PARAM_DELETE:
+ {
+ int n = va_arg(ap, int);
+
+ if (!process)
+ break;
+
+ if (n == -1) {
+ /* Move all data from tail to data area */
+ if (dst->data != dst->tail) {
+ delete_rest:
+ n = silc_buffer_len(dst);
+ memmove(dst->data, dst->tail, silc_buffer_taillen(dst));
+ silc_buffer_push_tail(dst, n);
+ if (!silc_buffer_srealloc(stack, dst,
+ silc_buffer_truelen(dst) - n))
+ goto fail;
+ }
+ break;
+ }
+
+ if (n > silc_buffer_len(dst))
+ goto fail;
+
+ memmove(dst->data, dst->data + n, (silc_buffer_len(dst) - n) +
+ silc_buffer_taillen(dst));
+ silc_buffer_push_tail(dst, silc_buffer_len(dst) - n);
+ if (!silc_buffer_srealloc(stack, dst, silc_buffer_truelen(dst) - n))
+ goto fail;
+
+ break;
+ }
+
case SILC_PARAM_OFFSET:
{
int offst = va_arg(ap, int);
+
+ if (!process)
+ break;
+
if (!offst)
break;
+
if (offst > 1) {
- if (offst > silc_buffer_len(dst))
+ if (offst > silc_buffer_len(dst)) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto fail;
+ }
silc_buffer_pull(dst, offst);
flen += offst;
} else {
}
break;
}
+
+ case SILC_PARAM_OFFSET_START:
+ if (!process)
+ break;
+ if (!silc_buffer_push(dst, flen))
+ goto fail;
+ flen = 0;
+ break;
+
+ case SILC_PARAM_OFFSET_END:
+ if (!process)
+ break;
+ flen += silc_buffer_len(dst);
+ silc_buffer_pull(dst, silc_buffer_len(dst));
+ break;
+
case SILC_PARAM_ADVANCE:
+ if (!process)
+ break;
advance = TRUE;
break;
+
case SILC_PARAM_END:
goto ok;
break;
+
default:
SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
"format the data.", fmt));
+ silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
+ "Bad buffer formatting type %d", fmt);
goto fail;
break;
}
fail:
SILC_LOG_DEBUG(("Error occured while formatting data"));
- if (!advance)
+ if (process && !advance)
silc_buffer_push(dst, flen);
return -1;
ok:
/* Push the buffer back to where it belongs. */
- if (!advance)
+ if (process && !advance)
silc_buffer_push(dst, flen);
return flen;
}
-
-/****************************** Unformatting ********************************/
-
-int silc_buffer_unformat(SilcBuffer src, ...)
+int silc_buffer_format(SilcBuffer dst, ...)
{
va_list ap;
int ret;
- va_start(ap, src);
- ret = silc_buffer_sunformat_vp(NULL, src, ap);
+ va_start(ap, dst);
+ ret = silc_buffer_sformat_vp(NULL, dst, ap);
va_end(ap);
return ret;
}
-int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
+int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
{
- return silc_buffer_sunformat_vp(NULL, src, ap);
+ return silc_buffer_sformat_vp(NULL, dst, ap);
}
-int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
+int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
{
va_list ap;
int ret;
- va_start(ap, src);
- ret = silc_buffer_sunformat_vp(stack, src, ap);
+ va_start(ap, dst);
+ ret = silc_buffer_sformat_vp(stack, dst, ap);
va_end(ap);
return ret;
}
-int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
+int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
{
- SilcBufferParamType fmt;
+ return silc_buffer_sformat_vp_i(stack, dst, ap, TRUE);
+}
+
+/****************************** Unformatting ********************************/
+
+int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
+ SilcBool process)
+{
+ SilcParam fmt;
unsigned char *start_ptr = src->data;
int len = 0;
SilcBool advance = FALSE;
/* Parse the arguments by formatting type. */
- while(1) {
- fmt = va_arg(ap, SilcBufferParamType);
+ while (1) {
+ fmt = va_arg(ap, SilcParam);
+
+ SILC_LOG_DEBUG(("Buffer unformat type %s (%d)",
+ silc_param_string(fmt), fmt));
- switch(fmt) {
+ switch (fmt) {
case SILC_PARAM_FUNC:
{
- SilcBufferUnformatFunc func = NULL;
- SilcBufferSUnformatFunc funcs = NULL;
+ SilcBufferUnformatFunc func;
void **val;
void *context;
int tmp_len;
- if (!stack)
- func = va_arg(ap, SilcBufferUnformatFunc);
- else
- funcs = va_arg(ap, SilcBufferSUnformatFunc);
+ func = va_arg(ap, SilcBufferUnformatFunc);
val = va_arg(ap, void **);
context = va_arg(ap, void *);
- if (!stack)
- tmp_len = func(src, val, context);
- else
- tmp_len = funcs(stack, src, val, context);
+
+ if (!process)
+ break;
+
+ tmp_len = func(stack, src, val, context);
if (tmp_len < 0)
goto fail;
if (tmp_len) {
silc_buffer_pull(src, tmp_len);
}
}
- case SILC_PARAM_UI_XNSTRING:
- case SILC_PARAM_DATA:
+ break;
+
+ case SILC_PARAM_REGEX:
+ {
+ const char *regex = va_arg(ap, char *);
+ SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags);
+ SilcBufferStruct match;
+ SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
+ SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
+ SilcBool ret;
+ SilcUInt32 inclusive_pos = 0;
+ int matched = 0, ret_len;
+ va_list cp;
+
+ if (!process)
+ break;
+
+ if (!regex)
+ break;
+
+ if (match_nl) {
+ start_nl_match:
+ /* Match for '\n' in the buffer. If not found, treat as line
+ without '\n' (buffer has only one line, or this is last line). */
+ if (silc_regex_buffer(src, "\n", &match, NULL))
+ src->tail = match.tail;
+ }
+
+ start_match:
+ /* Match */
+ ret = silc_regex_buffer(src, regex, &match, NULL);
+ ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
+ if (!ret) {
+ if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
+ goto fail;
+ }
+ goto end_match;
+ }
+ matched++;
+
+ if (rflags & SILC_STR_REGEX_NOT)
+ match = *src;
+
+ if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
+ /* Advance buffer after match */
+ if (!silc_buffer_pull(src, (match.data - src->data)))
+ goto fail;
+ }
+
+ if (rflags & SILC_STR_REGEX_INCLUSIVE) {
+ inclusive_pos = src->tail - match.tail;
+ src->tail = match.tail;
+ }
+
+ /* Recursively format */
+ silc_va_copy(cp, ap);
+ ret_len = silc_buffer_sunformat_vp_i(stack, src, cp, TRUE);
+ va_end(cp);
+ if (ret_len < 0)
+ goto fail;
+
+ if (rflags & SILC_STR_REGEX_INCLUSIVE)
+ if (!silc_buffer_pull_tail(src, inclusive_pos))
+ goto fail;
+
+ /* Advance buffer after formatting */
+ if (!silc_buffer_pull(src, ret_len))
+ goto fail;
+
+ if (match_all && (!match_nl || silc_buffer_len(src) > 1))
+ goto start_match;
+
+ end_match:
+ if (match_nl) {
+ /* Go to next line, it is at the end of the data area. Adjust
+ the tail area of the target buffer to show rest of the buffer. */
+ if (!silc_buffer_pull(src, (src->tail - src->data)))
+ goto fail;
+ if (!silc_buffer_pull_tail(src, silc_buffer_taillen(src)))
+ goto fail;
+
+ if (silc_buffer_len(src) > 0)
+ goto start_nl_match;
+ }
+
+ /* Skip to the next SILC_PARAM_END */
+ silc_buffer_sunformat_vp_i(NULL, src, ap, FALSE);
+ break;
+ }
+ break;
+
+ case SILC_PARAM_UICHAR:
{
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt32 len2 = va_arg(ap, SilcUInt32);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, len2);
if (silc_likely(len2 && x))
*x = src->data;
silc_buffer_pull(src, len2);
break;
}
- case SILC_PARAM_UI_XNSTRING_ALLOC:
- case SILC_PARAM_DATA_ALLOC:
+
+ case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
{
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt32 len2 = va_arg(ap, SilcUInt32);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, len2);
if (silc_likely(len2 && x)) {
*x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
- memcpy(*x, src->data, len2);
+ if (*x)
+ memcpy(*x, src->data, len2);
}
silc_buffer_pull(src, len2);
break;
}
- case SILC_PARAM_UI8_CHAR:
+
+ case SILC_PARAM_UINT8:
{
unsigned char *x = va_arg(ap, unsigned char *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 1);
if (silc_likely(x))
*x = src->data[0];
silc_buffer_pull(src, 1);
break;
}
- case SILC_PARAM_UI16_SHORT:
+
+ case SILC_PARAM_UINT16:
{
SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 2);
if (silc_likely(x))
SILC_GET16_MSB(*x, src->data);
silc_buffer_pull(src, 2);
break;
}
- case SILC_PARAM_UI32_INT:
+
+ case SILC_PARAM_UINT32:
{
SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 4);
if (silc_likely(x))
SILC_GET32_MSB(*x, src->data);
silc_buffer_pull(src, 4);
break;
}
- case SILC_PARAM_UI64_INT:
+
+ case SILC_PARAM_UINT64:
{
SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
if (silc_likely(x))
SILC_GET64_MSB(*x, src->data);
silc_buffer_pull(src, sizeof(SilcUInt64));
break;
}
- case SILC_PARAM_SI8_CHAR:
+
+ case SILC_PARAM_SINT8:
{
char *x = va_arg(ap, char *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 1);
if (silc_likely(x))
*x = src->data[0];
silc_buffer_pull(src, 1);
break;
}
- case SILC_PARAM_SI16_SHORT:
+
+ case SILC_PARAM_SINT16:
{
SilcInt16 *x = va_arg(ap, SilcInt16 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 2);
if (silc_likely(x))
SILC_GET16_MSB(*x, src->data);
silc_buffer_pull(src, 2);
break;
}
- case SILC_PARAM_SI32_INT:
+
+ case SILC_PARAM_SINT32:
{
SilcInt32 *x = va_arg(ap, SilcInt32 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 4);
if (silc_likely(x))
SILC_GET32_MSB(*x, src->data);
silc_buffer_pull(src, 4);
break;
}
- case SILC_PARAM_SI64_INT:
+
+ case SILC_PARAM_SINT64:
{
SilcInt64 *x = va_arg(ap, SilcInt64 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
if (silc_likely(x))
SILC_GET64_MSB(*x, src->data);
silc_buffer_pull(src, sizeof(SilcInt64));
break;
}
+
case SILC_PARAM_UI8_STRING:
{
SilcUInt8 len2;
unsigned char **x = va_arg(ap, unsigned char **);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 1);
len2 = (SilcUInt8)src->data[0];
silc_buffer_pull(src, 1);
silc_buffer_pull(src, len2);
break;
}
- case SILC_PARAM_UI16_STRING:
- {
- SilcUInt16 len2;
- unsigned char **x = va_arg(ap, unsigned char **);
- UNFORMAT_HAS_SPACE(src, 2);
- SILC_GET16_MSB(len2, src->data);
- silc_buffer_pull(src, 2);
- UNFORMAT_HAS_SPACE(src, len2);
- if (silc_likely(x))
- *x = src->data;
- silc_buffer_pull(src, len2);
- break;
- }
- case SILC_PARAM_UI8_STRING_ALLOC:
+
+ case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
{
SilcUInt8 len2;
unsigned char **x = va_arg(ap, unsigned char **);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 1);
len2 = (SilcUInt8)src->data[0];
silc_buffer_pull(src, 1);
UNFORMAT_HAS_SPACE(src, len2);
if (silc_likely(x && len2)) {
*x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
- if (*x)
- memcpy(*x, src->data, len2);
+ memcpy(*x, src->data, len2);
}
silc_buffer_pull(src, len2);
break;
}
- case SILC_PARAM_UI16_STRING_ALLOC:
+
+ case SILC_PARAM_UI16_STRING:
{
SilcUInt16 len2;
unsigned char **x = va_arg(ap, unsigned char **);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, 2);
+ SILC_GET16_MSB(len2, src->data);
+ silc_buffer_pull(src, 2);
+ UNFORMAT_HAS_SPACE(src, len2);
+ if (silc_likely(x))
+ *x = src->data;
+ silc_buffer_pull(src, len2);
+ break;
+ }
+
+ case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
+ {
+ SilcUInt16 len2;
+ unsigned char **x = va_arg(ap, unsigned char **);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 2);
SILC_GET16_MSB(len2, src->data);
silc_buffer_pull(src, 2);
UNFORMAT_HAS_SPACE(src, len2);
if (silc_likely(x && len2)) {
*x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
- memcpy(*x, src->data, len2);
+ if (*x)
+ memcpy(*x, src->data, len2);
}
silc_buffer_pull(src, len2);
break;
}
+
case SILC_PARAM_UI32_STRING:
{
SilcUInt32 len2;
unsigned char **x = va_arg(ap, unsigned char **);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 4);
SILC_GET32_MSB(len2, src->data);
silc_buffer_pull(src, 4);
silc_buffer_pull(src, len2);
break;
}
- case SILC_PARAM_UI32_STRING_ALLOC:
+
+ case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
{
SilcUInt32 len2;
unsigned char **x = va_arg(ap, unsigned char **);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 4);
SILC_GET32_MSB(len2, src->data);
silc_buffer_pull(src, 4);
UNFORMAT_HAS_SPACE(src, len2);
if (silc_likely(x && len2)) {
*x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
- memcpy(*x, src->data, len2);
+ if (*x)
+ memcpy(*x, src->data, len2);
}
silc_buffer_pull(src, len2);
break;
}
+
case SILC_PARAM_UI8_NSTRING:
{
SilcUInt8 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 1);
len2 = (SilcUInt8)src->data[0];
silc_buffer_pull(src, 1);
silc_buffer_pull(src, len2);
break;
}
- case SILC_PARAM_UI16_NSTRING:
- {
- SilcUInt16 len2;
- unsigned char **x = va_arg(ap, unsigned char **);
- SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
- UNFORMAT_HAS_SPACE(src, 2);
- SILC_GET16_MSB(len2, src->data);
- silc_buffer_pull(src, 2);
- UNFORMAT_HAS_SPACE(src, len2);
- if (len3)
- *len3 = len2;
- if (x)
- *x = src->data;
- silc_buffer_pull(src, len2);
- break;
- }
- case SILC_PARAM_UI8_NSTRING_ALLOC:
+
+ case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
{
SilcUInt8 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 1);
len2 = (SilcUInt8)src->data[0];
silc_buffer_pull(src, 1);
*len3 = len2;
if (x && len2) {
*x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
- if (*x)
- memcpy(*x, src->data, len2);
+ memcpy(*x, src->data, len2);
}
silc_buffer_pull(src, len2);
break;
}
- case SILC_PARAM_UI16_NSTRING_ALLOC:
+
+ case SILC_PARAM_UI16_NSTRING:
{
SilcUInt16 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, 2);
+ SILC_GET16_MSB(len2, src->data);
+ silc_buffer_pull(src, 2);
+ UNFORMAT_HAS_SPACE(src, len2);
+ if (len3)
+ *len3 = len2;
+ if (x)
+ *x = src->data;
+ silc_buffer_pull(src, len2);
+ break;
+ }
+
+ case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
+ {
+ SilcUInt16 len2;
+ unsigned char **x = va_arg(ap, unsigned char **);
+ SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 2);
SILC_GET16_MSB(len2, src->data);
silc_buffer_pull(src, 2);
*len3 = len2;
if (x && len2) {
*x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
- memcpy(*x, src->data, len2);
+ if (*x)
+ memcpy(*x, src->data, len2);
}
silc_buffer_pull(src, len2);
break;
}
+
case SILC_PARAM_UI32_NSTRING:
{
SilcUInt32 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 4);
SILC_GET32_MSB(len2, src->data);
silc_buffer_pull(src, 4);
silc_buffer_pull(src, len2);
break;
}
+
+ case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
+ {
+ SilcUInt32 len2;
+ unsigned char **x = va_arg(ap, unsigned char **);
+ SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
+
+ if (!process)
+ break;
+
+ UNFORMAT_HAS_SPACE(src, 4);
+ SILC_GET32_MSB(len2, src->data);
+ silc_buffer_pull(src, 4);
+ UNFORMAT_HAS_SPACE(src, len2);
+ if (len3)
+ *len3 = len2;
+ if (silc_likely(x && len2)) {
+ *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
+ memcpy(*x, src->data, len2);
+ }
+ silc_buffer_pull(src, len2);
+ break;
+ }
+
case SILC_PARAM_BUFFER:
{
SilcBuffer x = va_arg(ap, SilcBuffer);
SilcUInt32 len2;
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 4);
SILC_GET32_MSB(len2, src->data);
silc_buffer_pull(src, 4);
silc_buffer_pull(src, len2);
}
break;
- case SILC_PARAM_BUFFER_ALLOC:
+
+ case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
{
SilcBuffer x = va_arg(ap, SilcBuffer);
SilcUInt32 len2;
+
+ if (!process)
+ break;
+
UNFORMAT_HAS_SPACE(src, 4);
SILC_GET32_MSB(len2, src->data);
silc_buffer_pull(src, 4);
UNFORMAT_HAS_SPACE(src, len2);
- silc_buffer_sformat(stack, x,
- SILC_STR_DATA(src->data, len2),
- SILC_STR_END);
+ if (silc_buffer_sformat(stack, x,
+ SILC_STR_DATA(src->data, len2),
+ SILC_STR_END) < 0)
+ goto fail;
silc_buffer_pull(src, len2);
}
break;
+
case SILC_PARAM_OFFSET:
{
int offst = va_arg(ap, int);
+
+ if (!process)
+ break;
+
if (!offst)
break;
+
if (offst > 1) {
UNFORMAT_HAS_SPACE(src, offst);
silc_buffer_pull(src, offst);
}
break;
}
+
+ case SILC_PARAM_OFFSET_START:
+ if (!process)
+ break;
+ silc_buffer_push(src, (src->data - start_ptr));
+ break;
+
+ case SILC_PARAM_OFFSET_END:
+ if (!process)
+ break;
+ silc_buffer_pull(src, silc_buffer_len(src));
+ break;
+
case SILC_PARAM_ADVANCE:
+ if (!process)
+ break;
advance = TRUE;
break;
+
case SILC_PARAM_END:
goto ok;
break;
+
+ case SILC_PARAM_DELETE:
+ break;
+
default:
SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
"format the data.", fmt));
+ silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
+ "Bad buffer formatting type %d", fmt);
goto fail;
break;
}
fail:
SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
- len = src->data - start_ptr;
- silc_buffer_push(src, len);
+ if (process && !advance) {
+ len = src->data - start_ptr;
+ silc_buffer_push(src, len);
+ }
return -1;
ok:
+ len = src->data - start_ptr;
+
/* Push the buffer back to the start. */
- if (!advance) {
- len = src->data - start_ptr;
+ if (process && !advance)
silc_buffer_push(src, len);
- }
+
return len;
}
+int silc_buffer_unformat(SilcBuffer src, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, src);
+ ret = silc_buffer_sunformat_vp(NULL, src, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
+{
+ return silc_buffer_sunformat_vp(NULL, src, ap);
+}
+
+int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, src);
+ ret = silc_buffer_sunformat_vp(stack, src, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
+{
+ return silc_buffer_sunformat_vp_i(stack, src, ap, TRUE);
+}
/**************************** Utility functions *****************************/
Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- Copyright (C) 2002 - 2006 Giovanni Giacobbi
+ Copyright (C) 2002 - 2008 Giovanni Giacobbi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
GNU General Public License for more details.
*/
-/* $Id$ */
-#include "silc.h"
+#include "silcruntime.h"
/* limit debug logging verbosity */
#if 0
#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 {
* 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;
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;
}
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));
/* loop throught statements */
while (1) {
- char buf[255];
+ char buf[BUF_SIZE];
SilcConfigOption *thisopt;
/* makes it pointing to the next interesting char */
*/
-#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;
/* Create file descriptor stream */
-SilcStream silc_fd_stream_create(int fd)
+SilcStream silc_fd_stream_create(int fd, SilcStack stack)
{
- if (fd < 1)
+ if (fd < 1) {
+ silc_set_errno_reason(SILC_ERR_BAD_FD, "Bad file descriptor %d", fd);
return NULL;
- return silc_fd_stream_create2(fd, 0);
+ }
+ return silc_fd_stream_create2(fd, 0, stack);
}
/* Create stream with two file descriptors */
-SilcStream silc_fd_stream_create2(int read_fd, int write_fd)
+SilcStream silc_fd_stream_create2(int read_fd, int write_fd, SilcStack stack)
{
SilcFDStream stream;
- stream = silc_calloc(1, sizeof(*stream));
- if (!stream)
+ if (stack)
+ stack = silc_stack_alloc(0, stack);
+
+ stream = silc_scalloc(stack, 1, sizeof(*stream));
+ if (!stream) {
+ silc_stack_free(stack);
return NULL;
+ }
SILC_LOG_DEBUG(("Creating new fd stream %p", stream));
stream->ops = &silc_fd_stream_ops;
stream->fd1 = read_fd;
stream->fd2 = write_fd;
+ stream->stack = stack;
return stream;
}
/* Create by opening file */
SilcStream silc_fd_stream_file(const char *filename, SilcBool reading,
- SilcBool writing)
+ SilcBool writing, SilcStack stack)
{
const char *read_file = NULL, *write_file = NULL;
- if (!filename)
+ if (!filename) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
if (writing)
write_file = filename;
if (reading)
read_file = filename;
- return silc_fd_stream_file2(read_file, write_file);
+ return silc_fd_stream_file2(read_file, write_file, stack);
}
/* Create by opening two files */
-SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file)
+SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file,
+ SilcStack stack)
{
SilcStream stream;
int fd1 = 0, fd2 = 0;
return NULL;
}
- stream = silc_fd_stream_create2(fd1, fd2);
+ stream = silc_fd_stream_create2(fd1, fd2, stack);
if (!stream) {
silc_file_close(fd1);
silc_file_close(fd2);
return TRUE;
}
-/* Return errno */
-
-int silc_fd_stream_get_error(SilcStream stream)
-{
- SilcFDStream fd_stream = stream;
-
- if (!SILC_IS_FD_STREAM(fd_stream))
- return 0;
-
- return fd_stream->error;
-}
-
/* Read */
int silc_fd_stream_read(SilcStream stream, unsigned char *buf,
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd1,
SILC_TASK_READ, FALSE);
+ silc_set_errno_posix(errno);
return -1;
}
SILC_LOG_DEBUG(("Cannot read from fd: %d:%s",
fd_stream->fd1, strerror(errno)));
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
- fd_stream->error = errno;
+ silc_set_errno_posix(errno);
return -2;
}
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;
}
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 */
*/
-#include "silc.h"
+#include "silcruntime.h"
/************************** Types and definitions ***************************/
/* Internal async host lookup context. */
typedef struct {
SilcSocketStream stream;
- SilcSocketStreamStatus status;
+ SilcResult status;
SilcSocketStreamCallback callback;
SilcAsyncOperation op;
void *context;
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);
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,
SilcSocketStream stream;
SilcSocketHostLookup l;
- if (!sock || !schedule) {
- SILC_LOG_ERROR(("Missing arguments to silc_socket_tcp_stream_create"));
+ if (!schedule) {
+ schedule = silc_schedule_get_global();
+ if (!schedule) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ if (callback)
+ callback(silc_errno, NULL, context);
+ return NULL;
+ }
+ }
+
+ if (!sock) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
if (callback)
- callback(SILC_SOCKET_ERROR, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
stream = silc_calloc(1, sizeof(*stream));
if (!stream) {
if (callback)
- callback(SILC_SOCKET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
if (!l) {
silc_free(stream);
if (callback)
- callback(SILC_SOCKET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
silc_free(stream);
silc_free(l);
if (callback)
- callback(SILC_SOCKET_ERROR, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
return l->op;
} else {
/* No lookup */
- l->status = SILC_SOCKET_OK;
+ l->status = SILC_OK;
silc_socket_host_lookup_finish(schedule,
silc_schedule_get_context(schedule),
0, 0, l);
{
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;
if (hostname) {
silc_free(socket_stream->hostname);
- socket_stream->hostname = strdup(hostname);
+ socket_stream->hostname = silc_strdup(hostname);
if (!socket_stream->hostname)
return FALSE;
}
if (ip) {
silc_free(socket_stream->ip);
- socket_stream->ip = strdup(ip);
+ socket_stream->ip = silc_strdup(ip);
if (!socket_stream->ip)
return FALSE;
if (!socket_stream->hostname) {
- socket_stream->hostname = strdup(ip);
+ socket_stream->hostname = silc_strdup(ip);
if (!socket_stream->hostname)
return FALSE;
}
return TRUE;
}
-/* Return socket errno */
-
-int silc_socket_stream_get_error(SilcStream stream)
-{
- SilcSocketStream socket_stream = stream;
-
- if (!SILC_IS_SOCKET_STREAM(socket_stream) &&
- !SILC_IS_SOCKET_STREAM_UDP(socket_stream))
- return 0;
-
- return socket_stream->sock_error;
-}
-
/* Set QoS for socket stream */
SilcBool silc_socket_stream_set_qos(SilcStream stream,
!limit_sec && !limit_usec) {
silc_schedule_task_del_by_context(socket_stream->schedule,
socket_stream->qos);
+ silc_free(socket_stream->qos->buffer);
silc_free(socket_stream->qos);
socket_stream->qos = NULL;
return TRUE;
socket_stream->qos->cur_rate = 0;
socket_stream->qos->sock = socket_stream;
- socket_stream->qos->buffer = silc_malloc(read_limit_bytes);
+ socket_stream->qos->buffer = silc_realloc(socket_stream->qos->buffer,
+ read_limit_bytes);
if (!socket_stream->qos->buffer)
return FALSE;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2005 - 2008 Pekka Riikonen
+ Copyright (C) 2005 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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 */
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2007 Pekka Riikonen
+ Copyright (C) 1997 - 2008 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
GNU General Public License for more details.
*/
-/* $Id$ */
-#include "silc.h"
-#include "silcnet.h"
+#include "silcruntime.h"
/************************** Types and definitions ***************************/
if (ip_addr) {
if (!silc_net_is_ip(ip_addr)) {
SILC_LOG_ERROR(("%s is not IP address", ip_addr));
+ silc_set_errno_reason(SILC_ERR_BAD_IP, "%s is not an IP address",
+ ip_addr);
return FALSE;
}
if (silc_net_is_ip4(ip_addr)) {
/* IPv4 address */
len = sizeof(addr->sin.sin_addr);
- silc_net_addr2bin(ip_addr,
- (unsigned char *)&addr->sin.sin_addr.s_addr, len);
+ if (!silc_net_addr2bin(ip_addr,
+ (unsigned char *)&addr->sin.sin_addr.s_addr, len))
+ return FALSE;
addr->sin.sin_family = AF_INET;
addr->sin.sin_port = port ? htons(port) : 0;
} else {
#ifdef HAVE_IPV6
/* IPv6 address */
len = sizeof(addr->sin6.sin6_addr);
- silc_net_addr2bin(ip_addr,
- (unsigned char *)&addr->sin6.sin6_addr, len);
+ if (!silc_net_addr2bin(ip_addr,
+ (unsigned char *)&addr->sin6.sin6_addr, len))
+ return FALSE;
addr->sin6.sin6_family = AF_INET6;
addr->sin6.sin6_port = port ? htons(port) : 0;
#else
SILC_LOG_ERROR(("IPv6 support is not compiled in"));
+ silc_set_errno(SILC_ERR_NOT_SUPPORTED);
return FALSE;
#endif
}
/* Deliver new stream to upper layer */
-static void silc_net_accept_stream(SilcSocketStreamStatus status,
+static void silc_net_accept_stream(SilcResult status,
SilcStream stream, void *context)
{
SilcNetListener listener = context;
- if (status != SILC_SOCKET_OK)
+ if (status != SILC_OK)
return;
- listener->callback(SILC_NET_OK, stream, listener->context);
+ listener->callback(SILC_OK, stream, listener->context);
}
/* Accept incoming connection and notify upper layer */
SILC_LOG_DEBUG(("Creating TCP listener"));
- if (port < 0 || !schedule || !callback)
+ if (!schedule) {
+ schedule = silc_schedule_get_global();
+ if (!schedule) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ goto err;
+ }
+ }
+
+ if (port < 0 || !callback) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
goto err;
+ }
listener = silc_calloc(1, sizeof(*listener));
if (!listener)
/* Create the socket */
sock = socket(server.sin.sin_family, SOCK_STREAM, 0);
if (sock < 0) {
- SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot create socket: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
/* Bind the listener socket */
rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval < 0) {
- SILC_LOG_ERROR(("Cannot bind socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot bind socket: %s",
+ silc_errno_string(silc_errno)));
close(sock);
goto err;
}
/* Specify that we are listenning */
rval = listen(sock, 64);
if (rval < 0) {
- SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot set socket listenning: %s",
+ silc_errno_string(silc_errno)));
close(sock);
goto err;
}
return NULL;
}
+/* Create TCP listener, multiple ports */
+
+SilcNetListener
+silc_net_tcp_create_listener2(const char *local_ip_addr, int *ports,
+ SilcUInt32 port_count,
+ SilcBool ignore_port_error,
+ SilcBool lookup, SilcBool require_fqdn,
+ SilcSchedule schedule,
+ SilcNetCallback callback, void *context)
+{
+ SilcNetListener listener = NULL;
+ SilcSockaddr server;
+ int i, sock, rval;
+ const char *ipany = "0.0.0.0";
+
+ SILC_LOG_DEBUG(("Creating TCP listener"));
+
+ if (!schedule) {
+ schedule = silc_schedule_get_global();
+ if (!schedule) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ goto err;
+ }
+ }
+
+ if (!callback) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ goto err;
+ }
+
+ listener = silc_calloc(1, sizeof(*listener));
+ if (!listener)
+ return NULL;
+ listener->schedule = schedule;
+ listener->callback = callback;
+ listener->context = context;
+ listener->require_fqdn = require_fqdn;
+ listener->lookup = lookup;
+
+ if (port_count > 0) {
+ listener->socks = silc_calloc(port_count, sizeof(*listener->socks));
+ if (!listener->socks)
+ return NULL;
+ } else {
+ listener->socks = silc_calloc(1, sizeof(*listener->socks));
+ if (!listener->socks)
+ return NULL;
+
+ port_count = 1;
+ }
+
+ /* Bind to ports */
+ for (i = 0; i < port_count; i++) {
+ SILC_LOG_DEBUG(("Binding to local address %s:%d",
+ local_ip_addr ? local_ip_addr : ipany,
+ ports ? ports[i] : 0));
+
+ /* Set sockaddr for server */
+ if (!silc_net_set_sockaddr(&server,
+ local_ip_addr ? local_ip_addr : ipany,
+ ports ? ports[i] : 0)) {
+ if (ignore_port_error)
+ continue;
+ goto err;
+ }
+
+ /* Create the socket */
+ sock = socket(server.sin.sin_family, SOCK_STREAM, 0);
+ if (sock < 0) {
+ if (ignore_port_error)
+ continue;
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot create socket: %s",
+ silc_errno_string(silc_errno)));
+ goto err;
+ }
+
+ /* Set the socket options */
+ rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
+ if (rval < 0) {
+ close(sock);
+ if (ignore_port_error)
+ continue;
+ SILC_LOG_ERROR(("Cannot set socket options: %s",
+ silc_errno_string(silc_errno)));
+ goto err;
+ }
+
+ /* Bind the listener socket */
+ rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
+ if (rval < 0) {
+ close(sock);
+ if (ignore_port_error)
+ continue;
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot bind socket: %s",
+ silc_errno_string(silc_errno)));
+ goto err;
+ }
+
+ /* Specify that we are listenning */
+ rval = listen(sock, 64);
+ if (rval < 0) {
+ close(sock);
+ if (ignore_port_error)
+ continue;
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot set socket listenning: %s",
+ silc_errno_string(silc_errno)));
+ goto err;
+ }
+
+ /* Set the server socket to non-blocking mode */
+ silc_net_set_socket_nonblock(sock);
+
+ /* Schedule for incoming connections */
+ silc_schedule_task_add_fd(schedule, sock, silc_net_accept, listener);
+
+ SILC_LOG_DEBUG(("TCP listener created, fd=%d", sock));
+ listener->socks[i] = sock;
+ listener->socks_count++;
+ }
+
+ if (ignore_port_error && !listener->socks_count)
+ goto err;
+
+ return listener;
+
+ err:
+ if (listener)
+ silc_net_close_listener(listener);
+ return NULL;
+}
+
/* Close network listener */
void silc_net_close_listener(SilcNetListener listener)
SILC_LOG_DEBUG(("Creating UDP stream"));
- if (!schedule)
- goto err;
+ if (!schedule) {
+ schedule = silc_schedule_get_global();
+ if (!schedule) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ goto err;
+ }
+ }
/* Bind to local addresses */
SILC_LOG_DEBUG(("Binding to local address %s",
/* Create the socket */
sock = socket(server.sin.sin_family, SOCK_DGRAM, 0);
if (sock < 0) {
- SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot create socket: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
/* Set the socket options */
rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
if (rval < 0) {
- SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno)));
+ SILC_LOG_ERROR(("Cannot set socket options: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
#ifdef SO_REUSEPORT
rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEPORT, 1);
if (rval < 0) {
- SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno)));
+ SILC_LOG_ERROR(("Cannot set socket options: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
#endif /* SO_REUSEPORT */
/* Bind the listener socket */
rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval < 0) {
- SILC_LOG_DEBUG(("Cannot bind socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_DEBUG(("Cannot bind socket: %s", silc_errno_string(silc_errno)));
goto err;
}
rval = connect(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval < 0) {
- SILC_LOG_DEBUG(("Cannot connect UDP stream: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_DEBUG(("Cannot connect UDP stream: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
}
SilcSocketStream sock = stream;
SilcSockaddr s;
struct sockaddr *from;
- int len, flen;
+ int len;
+ unsigned int flen;
SILC_LOG_DEBUG(("Reading data from UDP socket %d", sock->sock));
len = recv(sock->sock, ret_data, data_size, 0);
if (len < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
SILC_LOG_DEBUG(("Cannot read from UDP socket: %d:%s",
sock->sock, strerror(errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = errno;
return -2;
}
ret = sendto(sock->sock, data, data_len, 0, &remote.sa,
SIZEOF_SOCKADDR(remote));
if (ret < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not send immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
}
SILC_LOG_DEBUG(("Cannot send to UDP socket: %s", strerror(errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = errno;
return -2;
}
/* Asynchronous TCP/IP connecting */
typedef struct {
- SilcNetStatus status;
- SilcSocketStreamStatus stream_status;
+ SilcResult status;
SilcStream stream;
SilcFSMStruct fsm;
SilcFSMEventStruct event;
"host", conn->remote));
/** Network unreachable */
- conn->status = SILC_NET_HOST_UNREACHABLE;
+ conn->status = SILC_ERR_UNREACHABLE;
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
}
}
/** Cannot create socket */
+ silc_set_errno_posix(errno);
SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
rval = connect(sock, &desthost.sa, SIZEOF_SOCKADDR(desthost));
if (rval < 0) {
if (errno != EINPROGRESS) {
+ silc_set_errno_posix(errno);
shutdown(sock, 2);
close(sock);
}
/** Cannot connect to remote host */
- SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
+ SILC_LOG_ERROR(("Cannot connect to remote host: %s",
+ silc_errno_string(silc_errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
}
return SILC_FSM_CONTINUE;
}
-static void silc_net_connect_wait_stream(SilcSocketStreamStatus status,
+static void silc_net_connect_wait_stream(SilcResult status,
SilcStream stream, void *context)
{
SilcNetConnect conn = context;
conn->sop = NULL;
- conn->stream_status = status;
+ conn->status = status;
conn->stream = stream;
SILC_FSM_CALL_CONTINUE(&conn->fsm);
}
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;
}
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;
}
silc_async_free(conn->op);
}
+ if (conn->sock && conn->status != SILC_NET_OK)
+ silc_net_close_connection(conn->sock);
+
return SILC_FSM_FINISH;
}
{
SilcNetConnect conn;
- if (!remote_ip_addr || remote_port < 1 || !schedule || !callback)
+ if (!schedule) {
+ schedule = silc_schedule_get_global();
+ if (!schedule) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return NULL;
+ }
+ }
+
+ if (!remote_ip_addr || remote_port < 1 || !callback) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
SILC_LOG_DEBUG(("Creating connection to host %s port %d",
remote_ip_addr, remote_port));
conn = silc_calloc(1, sizeof(*conn));
if (!conn) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
conn->op = silc_async_alloc(silc_net_connect_abort, NULL, conn);
if (!conn->op) {
silc_free(conn);
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
if (local_ip_addr)
- conn->local_ip = strdup(local_ip_addr);
- conn->remote = strdup(remote_ip_addr);
+ conn->local_ip = silc_strdup(local_ip_addr);
+ conn->remote = silc_strdup(remote_ip_addr);
if (!conn->remote) {
silc_async_free(conn->op);
silc_free(conn->local_ip);
silc_free(conn);
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
conn->port = remote_port;
conn->callback = callback;
conn->context = context;
conn->retry = 1;
- conn->status = SILC_NET_ERROR;
+ conn->status = SILC_ERR;
silc_fsm_init(&conn->fsm, conn, silc_net_connect_destructor, NULL, schedule);
silc_fsm_start(&conn->fsm, silc_net_connect_st_start);
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
if (silc_net_is_ip4(addr)) {
/* IPv4 address */
struct in_addr tmp;
+
+ if (bin_len < 4) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return FALSE;
+ }
+
ret = inet_aton(addr, &tmp);
- if (bin_len < 4)
+ if (!ret) {
+ silc_set_errno_posix(errno);
return FALSE;
+ }
memcpy(bin, (unsigned char *)&tmp.s_addr, 4);
#ifdef HAVE_IPV6
SilcSockaddr *s;
/* IPv6 address */
- if (bin_len < 16)
+ if (bin_len < 16) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
GNU General Public License for more details.
*/
-/* $Id$ */
-#include "silc.h"
+#include "silcruntime.h"
#if defined(HAVE_EPOLL_WAIT)
#include <sys/epoll.h>
SILC_LOG_DEBUG(("epoll_ctl (DEL): %s", strerror(errno)));
return FALSE;
}
+ task->scheduled = FALSE;
return TRUE;
}
SilcUnixScheduler internal;
int i;
- internal = silc_calloc(1, sizeof(*internal));
+ internal = silc_scalloc(schedule->stack, 1, sizeof(*internal));
if (!internal)
return NULL;
#ifdef SILC_THREADS
if (pipe(internal->wakeup_pipe)) {
SILC_LOG_ERROR(("pipe() fails: %s", strerror(errno)));
- silc_free(internal);
return NULL;
}
#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 */
GNU General Public License for more details.
*/
-/* $Id$ */
-#include "silc.h"
+#include "silcruntime.h"
/************************ Static utility functions **************************/
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,
SILC_LOG_DEBUG(("Cannot read from socket: %d:%s",
sock->sock, strerror(errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = errno;
return -2;
}
/* If QoS was applied, return the data that was pending. */
if (sock->qos->applied && sock->qos->data_len) {
memcpy(buf, qosbuf, sock->qos->data_len);
+ len = sock->qos->data_len;
sock->qos->data_len = 0;
- return sock->qos->data_len;
+ return len;
}
/* If we have active QoS data pending, return with no data */
return -1;
}
- /* Read the data from the socket. Never read more than the max limit. */
+ /* Read the data from the socket. The qosbuf size is always the max
+ read limit size. */
len = (buf_len < sock->qos->read_limit_bytes ? buf_len :
sock->qos->read_limit_bytes);
len = read(sock->sock, qosbuf, len);
if (len < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
silc_schedule_task_del_by_context(sock->schedule, sock->qos);
sock->qos->data_len = 0;
- sock->sock_error = errno;
return -2;
}
ret = write(sock->sock, data, data_len);
if (ret < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
}
SILC_LOG_DEBUG(("Cannot write to socket: %s", strerror(errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = errno;
return -2;
}
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)