Added IV Included support to allow packet send/receive on UDP.
authorPekka Riikonen <priikone@silcnet.org>
Wed, 19 Jul 2006 09:35:32 +0000 (09:35 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 19 Jul 2006 09:35:32 +0000 (09:35 +0000)
lib/silccore/DIRECTORY
lib/silccore/Makefile.ad
lib/silccore/silcidcache.c [deleted file]
lib/silccore/silcidcache.h [deleted file]
lib/silccore/silcpacket.c
lib/silccore/silcpacket.h

index 6d0fbb6fa9bc87fca0fe6fce07d33639ccfeee31..7e0226feb10379c5278f36b8d1fe11dc2adfcd2c 100644 (file)
@@ -9,7 +9,6 @@
 @LINK=silcstatus.html:SILC Status Types
 @LINK=silcmode.html:SILC Modes
 @LINK=silcid.html:SILC ID Interface
-@LINK=silcidcache.html:SILC ID Cache Interface
 @LINK=silcargument.html:SILC Argument Interface
 @LINK=silcattrs.html:SILC Attributes Interface
 @LINK=silcpacket.html:Packet Protocol Interface
index 7d9507e66f502217d2d8cca3722e042945482552..db653271e610f1b5458f1e37c2e874f135733aaf 100644 (file)
@@ -21,7 +21,6 @@ noinst_LTLIBRARIES = libsilccore.la
 
 libsilccore_la_SOURCES =       \
        silcid.c                \
-       silcidcache.c           \
        silcmessage.c           \
        silcchannel.c           \
        silccommand.c           \
@@ -39,7 +38,6 @@ include_HEADERS =     \
        silcchannel.h   \
        silcmessage.h   \
        silccommand.h   \
-       silcidcache.h   \
        silcid.h        \
        silcmode.h      \
        silcnotify.h    \
diff --git a/lib/silccore/silcidcache.c b/lib/silccore/silcidcache.c
deleted file mode 100644 (file)
index 0d05b46..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
-
-  silcidcache.c
-
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
-
-  Copyright (C) 2000 - 2006 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
-  the Free Software Foundation; version 2 of the License.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-*/
-/* $Id$ */
-
-#include "silc.h"
-#include "silcidcache.h"
-
-/************************** Types and definitions ***************************/
-
-/* ID Cache context */
-struct SilcIDCacheStruct {
-  SilcHashTable id_table;           /* ID hash table */
-  SilcHashTable name_table;         /* Name hash table */
-  SilcHashTable context_table;      /* Context hash table */
-  SilcIDCacheDestructor destructor;  /* Entry destructor */
-  void *context;                    /* Destructor context */
-  SilcIdType id_type;               /* Type of ID cache */
-};
-
-
-/************************ Static utility functions **************************/
-
-/* Callback that is called by the hash table routine when traversing
-   entries in the hash table. */
-
-static void silc_idcache_get_all_foreach(void *key, void *context,
-                                        void *user_context)
-{
-  SilcList *list = user_context;
-  if (!context)
-    return;
-  silc_list_add(*list, context);
-}
-
-/* Cache entry destructor */
-
-static void silc_idcache_destructor(SilcIDCache cache,
-                                   SilcIDCacheEntry entry,
-                                   void *app_context)
-{
-  if (cache->destructor)
-    cache->destructor(cache, entry, cache->destructor, app_context);
-
-  memset(entry, 'F', sizeof(*entry));
-  silc_free(entry);
-}
-
-
-/****************************** Public API **********************************/
-
-/* Allocates new ID cache object. */
-
-SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type,
-                              SilcIDCacheDestructor destructor,
-                              void *destructor_context)
-{
-  SilcIDCache cache;
-
-  SILC_LOG_DEBUG(("Allocating new cache"));
-
-  cache = silc_calloc(1, sizeof(*cache));
-  if (!cache)
-    return NULL;
-
-  cache->id_table = silc_hash_table_alloc(count, silc_hash_id,
-                                         SILC_32_TO_PTR(id_type),
-                                         silc_hash_id_compare,
-                                         SILC_32_TO_PTR(id_type),
-                                         NULL, NULL, TRUE);
-  cache->name_table = silc_hash_table_alloc(count, silc_hash_utf8_string, NULL,
-                                           silc_hash_utf8_compare, NULL,
-                                           NULL, NULL, TRUE);
-  cache->context_table = silc_hash_table_alloc(count, silc_hash_ptr, NULL,
-                                              NULL, NULL, NULL, NULL, TRUE);
-  cache->destructor = destructor;
-  cache->context = destructor_context;
-  cache->id_type = id_type;
-
-  if (!cache->id_table || !cache->name_table || !cache->context_table) {
-    if (cache->id_table)
-      silc_hash_table_free(cache->id_table);
-    if (cache->name_table)
-      silc_hash_table_free(cache->name_table);
-    if (cache->context_table)
-      silc_hash_table_free(cache->context_table);
-    silc_free(cache);
-    return NULL;
-  }
-
-  return cache;
-}
-
-/* Frees ID cache object and cache entries */
-
-void silc_idcache_free(SilcIDCache cache)
-{
-  silc_hash_table_free(cache->id_table);
-  silc_hash_table_free(cache->name_table);
-  silc_hash_table_free(cache->context_table);
-  silc_free(cache);
-}
-
-/* Add new entry to cache */
-
-SilcIDCacheEntry
-silc_idcache_add(SilcIDCache cache, char *name, void *id, void *context)
-{
-  SilcIDCacheEntry c;
-
-  if (!id)
-    return NULL;
-
-  /* Allocate new cache entry */
-  c = silc_calloc(1, sizeof(*c));
-  if (!c)
-    return NULL;
-
-  c->id = id;
-  c->name = name;
-  c->context = context;
-
-  SILC_LOG_DEBUG(("Adding cache entry %p", c));
-
-  /* Add the new entry to the hash tables */
-
-  if (id) {
-    if (silc_idcache_find_by_id_one(cache, id, NULL)) {
-      SILC_LOG_ERROR(("Attempted to add same ID twice to ID Cache"));
-      goto err;
-    }
-    if (!silc_hash_table_add(cache->id_table, id, c))
-      goto err;
-  }
-  if (name)
-    if (!silc_hash_table_add(cache->name_table, name, c))
-      goto err;
-  if (context)
-    if (!silc_hash_table_add(cache->context_table, context, c))
-      goto err;
-
-  return c;
-
- err:
-  if (c->name)
-    silc_hash_table_del_by_context(cache->name_table, c->name, c);
-  if (c->context)
-    silc_hash_table_del_by_context(cache->context_table, c->context, c);
-  if (c->id)
-    silc_hash_table_del_by_context(cache->id_table, c->id, c);
-  silc_free(c);
-
-  return NULL;
-}
-
-/* Delete cache entry from cache. */
-
-SilcBool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry entry,
-                         void *app_context)
-{
-  SilcBool ret = FALSE;
-
-  SILC_LOG_DEBUG(("Deleting cache entry %p", entry));
-
-  if (entry->name)
-    ret = silc_hash_table_del_by_context(cache->name_table, entry->name,
-                                        entry);
-  if (entry->context)
-    ret = silc_hash_table_del_by_context(cache->context_table, entry->context,
-                                        entry);
-  if (entry->id)
-    ret = silc_hash_table_del_by_context(cache->id_table, entry->id,
-                                        entry);
-
-  if (ret)
-    silc_idcache_destructor(cache, entry, app_context);
-
-  return ret;
-}
-
-/* Deletes ID cache entry by ID. */
-
-SilcBool silc_idcache_del_by_id(SilcIDCache cache, void *id,
-                               void *app_context)
-{
-  SilcIDCacheEntry c;
-
-  if (!silc_hash_table_find(cache->id_table, id, NULL, (void **)&c))
-    return FALSE;
-
-  return silc_idcache_del(cache, c, app_context);
-}
-
-/* Deletes ID cache entry by context. */
-
-SilcBool silc_idcache_del_by_context(SilcIDCache cache, void *context,
-                                    void *app_context)
-{
-  SilcIDCacheEntry c;
-
-  if (!silc_hash_table_find(cache->context_table, context, NULL, (void **)&c))
-    return FALSE;
-
-  return silc_idcache_del(cache, c, app_context);
-}
-
-/* Update entry */
-
-SilcBool silc_idcache_update(SilcIDCache cache, SilcIDCacheEntry entry,
-                            void *old_id, void *new_id,
-                            char *old_name, char *new_name)
-{
-  if (old_id && new_id) {
-    if (!silc_hash_table_del_by_context(cache->id_table, old_id, entry))
-      return FALSE;
-
-    if (cache->id_type == SILC_ID_CLIENT)
-      *(SilcClientID *)entry->id = *(SilcClientID *)new_id;
-    if (cache->id_type == SILC_ID_SERVER)
-      *(SilcServerID *)entry->id = *(SilcServerID *)new_id;
-    if (cache->id_type == SILC_ID_CHANNEL)
-      *(SilcChannelID *)entry->id = *(SilcChannelID *)new_id;
-
-    if (!silc_hash_table_add(cache->id_table, entry->id, entry))
-      return FALSE;
-  }
-
-  if (old_name && new_name) {
-    if (!silc_hash_table_del_by_context(cache->name_table, old_name, entry))
-      return FALSE;
-
-    entry->name = new_name;
-
-    if (!silc_hash_table_add(cache->name_table, entry->name, entry))
-      return FALSE;
-  }
-
-  return TRUE;
-}
-
-/* Returns all cache entrys from the ID cache to the `ret' ID Cache List. */
-
-SilcBool silc_idcache_get_all(SilcIDCache cache, SilcList *ret_list)
-{
-  if (!ret_list)
-    return FALSE;
-
-  if (!silc_hash_table_count(cache->id_table))
-    return FALSE;
-
-  silc_hash_table_foreach(cache->id_table, silc_idcache_get_all_foreach,
-                         ret_list);
-
-  if (!silc_list_count(*ret_list))
-    return FALSE;
-
-  return TRUE;
-}
-
-/* Find ID Cache entry by ID. May return multiple entries. */
-
-SilcBool silc_idcache_find_by_id(SilcIDCache cache, void *id,
-                                SilcList *ret_list)
-{
-  if (!ret_list)
-    return FALSE;
-
-  if (!silc_hash_table_count(cache->id_table))
-    return FALSE;
-
-  silc_hash_table_find_foreach(cache->id_table, id,
-                              silc_idcache_get_all_foreach, ret_list);
-
-  if (!silc_list_count(*ret_list))
-    return FALSE;
-
-  return TRUE;
-}
-
-/* Find one specific ID entry.  Compare full IDs */
-
-SilcBool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
-                                    SilcIDCacheEntry *ret)
-{
-  return silc_hash_table_find_ext(cache->id_table, id, NULL, (void *)ret,
-                                 NULL, NULL,
-                                 silc_hash_id_compare_full,
-                                 SILC_32_TO_PTR(cache->id_type));
-}
-
-/* Finds cache entry by context. */
-
-SilcBool silc_idcache_find_by_context(SilcIDCache cache, void *context,
-                                     SilcIDCacheEntry *ret)
-{
-  return silc_hash_table_find(cache->context_table, context, NULL,
-                             (void *)ret);
-}
-
-/* Find ID Cache entry by name. Returns list of cache entries. */
-
-SilcBool silc_idcache_find_by_name(SilcIDCache cache, char *name,
-                                  SilcList *ret_list)
-{
-  if (!ret_list)
-    return FALSE;
-
-  if (!silc_hash_table_count(cache->name_table))
-    return FALSE;
-
-  silc_hash_table_find_foreach(cache->name_table, name,
-                              silc_idcache_get_all_foreach, ret_list);
-
-  if (!silc_list_count(*ret_list))
-    return FALSE;
-
-  return TRUE;
-}
-
-/* Find ID Cache entry by name. Returns one cache entry. */
-
-SilcBool silc_idcache_find_by_name_one(SilcIDCache cache, char *name,
-                                      SilcIDCacheEntry *ret)
-{
-  return silc_hash_table_find(cache->name_table, name, NULL, (void *)ret);
-}
diff --git a/lib/silccore/silcidcache.h b/lib/silccore/silcidcache.h
deleted file mode 100644 (file)
index 7b84e7b..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
-
-  silcidcache.h
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2000 - 2006 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
-  the Free Software Foundation; version 2 of the License.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-*/
-
-/****h* silccore/SILC ID Cache Interface
- *
- * DESCRIPTION
- *
- * SILC ID Cache is an cache for all kinds of ID's used in the SILC
- * protocol.  Application can save here the ID's it uses and the interface
- * provides fast retrieval of the ID's from the cache.
- *
- ***/
-
-#ifndef SILCIDCACHE_H
-#define SILCIDCACHE_H
-
-/****s* silccore/SilcIDCacheAPI/SilcIDCacheEntry
- *
- * NAME
- *
- *    typedef struct SilcIDCacheEntryStruct { ... } SilcIDCacheEntry;
- *
- * DESCRIPTION
- *
- *    This is an entry in the SILC ID Cache system.  This context is
- *    allocated by adding new entry to ID cache by calling silc_idcache_add.
- *    Each of the fields in the structure are allocated by the caller.
- *
- * SOURCE
- */
-typedef struct SilcIDCacheEntryStruct {
-  struct SilcIDCacheEntryStruct *next;
-  void *id;                           /* Associated ID */
-  char *name;                         /* Associated entry name */
-  void *context;                      /* Associated context */
-} *SilcIDCacheEntry;
-/***/
-
-/****s* silccore/SilcIDCacheAPI/SilcIDCache
- *
- * NAME
- *
- *    typedef struct SilcIDCacheStruct *SilcIDCache;
- *
- * DESCRIPTION
- *
- *    This context is the actual ID Cache and is allocated by
- *    silc_idcache_alloc and given as argument usually to all
- *    silc_idcache_* functions.  It is freed by the
- *    silc_idcache_free function.
- *
- ***/
-typedef struct SilcIDCacheStruct *SilcIDCache;
-
-/****f* silccore/SilcIDCacheAPI/SilcIDCacheDestructor
- *
- * SYNOPSIS
- *
- *    typedef void (*SilcIDCacheDestructor)(SilcIDCache cache,
- *                                          const SilcIDCacheEntry entry,
- *                                          void *destructor_context,
- *                                          void *app_context);
- *
- * DESCRIPTION
- *
- *    Destructor callback given as argument to silc_idcache_alloc.  This
- *    is called when an entry is deleted from the cache.  Application
- *    must free the contents of the `entry'.
- *
- ***/
-typedef void (*SilcIDCacheDestructor)(SilcIDCache cache,
-                                     const SilcIDCacheEntry entry,
-                                     void *destructor_context,
-                                     void *app_context);
-
-/* Prototypes */
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_alloc
- *
- * SYNOPSIS
- *
- *    SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type,
- *                                   SilcIDCacheDestructor destructor,
- *                                   void *destructor_context,
- *                                   SilcBool delete_id, SilcBool delete_name);
- *
- * DESCRIPTION
- *
- *    Allocates new ID cache object. The initial amount of allocated entries
- *    can be sent as argument. If `count' is 0 the system uses default values.
- *    The `id_type' defines the types of the ID's that will be saved to the
- *    cache.
- *
- ***/
-SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type,
-                              SilcIDCacheDestructor destructor,
-                              void *destructor_context);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_free
- *
- * SYNOPSIS
- *
- *    void silc_idcache_free(SilcIDCache cache);
- *
- * DESCRIPTION
- *
- *    Frees ID cache context and all cache entries.
- *
- ***/
-void silc_idcache_free(SilcIDCache cache);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_add
- *
- * SYNOPSIS
- *
- *    SilcIDCacheEntry
- *    silc_idcache_add(SilcIDCache cache, char *name, void *id, void *context);
- *
- * DESCRIPTION
- *
- *    Add new entry to the cache.  Returns the allocated cache entry if the
- *    entry was added successfully, or NULL if error occurred.  The `name' is
- *    the name associated with the ID, the `id' the actual ID and the
- *    `context' a caller specific context.
- *
- *    The `name', `id' and `context' pointers will be stored in the cache,
- *    and if the caller frees these pointers the caller is also responsible
- *    of deleting the cache entry.
- *
- ***/
-SilcIDCacheEntry
-silc_idcache_add(SilcIDCache cache, char *name, void *id, void *context);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_del
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry entry,
- *                              void *app_context);
- *
- * DESCRIPTION
- *
- *    Delete cache entry from cache.  Returns TRUE if the entry was deleted.
- *    The destructor will be called for the entry.  The `app_context' is
- *    delivered to the destructor.
- *
- ***/
-SilcBool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry entry,
-                         void *app_context);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_del_by_id
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_del_by_id(SilcIDCache cache, void *id,
- *                                    void *app_context);
- *
- * DESCRIPTION
- *
- *    Delete cache entry by ID.  Returns TRUE if the entry was deleted.
- *    The destructor will be called for the entry.  The `app_context' is
- *    delivered to the destructor.
- *
- ***/
-SilcBool silc_idcache_del_by_id(SilcIDCache cache, void *id,
-                               void *app_context);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_del_by_context
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_del_by_context(SilcIDCache cache, void *context);
- *
- * DESCRIPTION
- *
- *    Deletes cachen entry by the user specified context.  Returns TRUE
- *    if the entry was deleted.  The destructor will be called for the
- *    entry.  The `app_context' is delivered to the destructor.
- *
- ***/
-SilcBool silc_idcache_del_by_context(SilcIDCache cache, void *context,
-                                    void *app_context);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_update_id
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_update(SilcIDCache cache, SilcIDCacheEntry entry,
- *                                 void *old_id, void *new_id,
- *                                 char *old_name, char *new_name);
- *
- * DESCRIPTION
- *
- *    Updates cache `entry' with new values.  If the `new_id' is non-NULL
- *    then the new value will be copied over the old value in the `entry'.
- *    If the `new_name' is non-NULL then the `entry' will be updated with
- *    `new_name'.  The caller is responsible of freeing the old name if it
- *    was updated with new one.  The old ID value does not need to be freed
- *    as the new value is copied over the old value.
- *
- ***/
-SilcBool silc_idcache_update(SilcIDCache cache, SilcIDCacheEntry entry,
-                            void *old_id, void *new_id,
-                            char *old_name, char *new_name);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_get_all
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_get_all(SilcIDCache cache, SilcList *ret_list);
- *
- * DESCRIPTION
- *
- *    Returns all cache entries into the SilcList `ret_list' pointer.  Each
- *    entry in the list is SilcIDCacheEntry.  Returns FALSE if the cache
- *    is empty.
- *
- ***/
-SilcBool silc_idcache_get_all(SilcIDCache cache, SilcList *ret_list);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_id
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_find_by_id(SilcIDCache cache, void *id,
- *                                     SilcList *ret_list);
- *
- * DESCRIPTION
- *
- *    Find ID Cache entry by ID.  This may return multiple entries.
- *    The entires are returned into the `ret_list' SilcList context.
- *    Returns TRUE if entry was found.
- *
- * NOTES
- *
- *    If this function is used to find Client ID (SilcClientID), only the
- *    hash portion of the Client ID is compared.  Use the function
- *    silc_idcache_find_by_id_one to find exact match for Client ID (full
- *    ID is compared and not only the hash).
- *
- *    Comparing only the hash portion of Client ID allows searching of
- *    Client ID's by nickname, because the hash is based on the nickname.
- *    As nicknames are not unique, multiple entries may be found.
- *
- ***/
-SilcBool silc_idcache_find_by_id(SilcIDCache cache, void *id,
-                                SilcList *ret_list);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_id_one
- *
- * SYNOPSIS
- *
- *     SilcBool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
- *                                          SilcIDCacheEntry *ret);
- *
- * DESCRIPTION
- *
- *    Find ID Cache entry by ID.  Returns only one entry from the cache
- *    and the found entry is considered to be exact match.  Returns TRUE
- *    if the entry was found.
- *
- ***/
-SilcBool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
-                                    SilcIDCacheEntry *ret);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_context
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_find_by_context(SilcIDCache cache, void *context,
- *                                      SilcIDCacheEntry *ret);
- *
- * DESCRIPTION
- *
- *    Find cache entry by user specified context. Returns TRUE if the
- *    entry was found.
- *
- ***/
-SilcBool silc_idcache_find_by_context(SilcIDCache cache, void *context,
-                                     SilcIDCacheEntry *ret);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_name
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_find_by_name(SilcIDCache cache, char *name,
- *                                       SilcList *ret_list);
- *
- * DESCRIPTION
- *
- *    Find cache entries by the name associated with the ID.  This may
- *    return multiple entries to the `ret_list' SilcList context.  Returns
- *    TRUE if the entry was found.
- *
- ***/
-SilcBool silc_idcache_find_by_name(SilcIDCache cache, char *name,
-                                  SilcList *ret_list);
-
-/****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_name_one
- *
- * SYNOPSIS
- *
- *    SilcBool silc_idcache_find_by_name_one(SilcIDCache cache, char *name,
- *                                       SilcIDCacheEntry *ret);
- *
- * DESCRIPTION
- *
- *    Find cache entry by the name associated with the ID.  This returns
- *    one entry and the found entry is considered to be exact match.
- *    Returns TRUE if the entry was found.
- *
- ***/
-SilcBool silc_idcache_find_by_name_one(SilcIDCache cache, char *name,
-                                      SilcIDCacheEntry *ret);
-
-#endif /* SILCIDCACHE_H */
index 685b68c587c959deb7cd08799b2c9741c8063fdc..5c584d190f2fec507d9e421858d5f45ee9c05ca7 100644 (file)
@@ -69,6 +69,7 @@ struct SilcPacketStreamStruct {
   SilcUInt8 refcnt;                     /* Reference counter */
   unsigned int is_router   : 1;                 /* Set if router stream */
   unsigned int destroyed   : 1;                 /* Set if destroyed */
+  unsigned int iv_included : 1;          /* Set if IV included */
 };
 
 /* Initial size of stream buffers */
@@ -77,10 +78,9 @@ struct SilcPacketStreamStruct {
 /* Header length without source and destination ID's. */
 #define SILC_PACKET_HEADER_LEN 10
 
-/* Minimum length of SILC Packet Header. This much is decrypted always
-   when packet is received to be able to get all the relevant data out
-   from the header. */
+/* Minimum length of SILC Packet Header. */
 #define SILC_PACKET_MIN_HEADER_LEN 16
+#define SILC_PACKET_MIN_HEADER_LEN_IV 32
 
 /* Maximum padding length */
 #define SILC_PACKET_MAX_PADLEN 128
@@ -91,9 +91,6 @@ struct SilcPacketStreamStruct {
 /* Minimum packet length */
 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
 
-
-/* Macros */
-
 /* Returns true length of the packet. */
 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
 do {                                                                    \
@@ -465,6 +462,12 @@ void silc_packet_stream_set_router(SilcPacketStream stream)
   stream->is_router = TRUE;
 }
 
+/* Mark to include IV in ciphertext */
+
+void silc_packet_stream_set_iv_included(SilcPacketStream stream)
+{
+  stream->iv_included = TRUE;
+}
 
 /* Links `callbacks' to `stream' for specified packet types */
 
@@ -836,9 +839,9 @@ static SilcBool silc_packet_send_raw(SilcPacketStream stream,
                                     SilcCipher cipher,
                                     SilcHmac hmac)
 {
-  unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
+  unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[32], psn[4];
   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
-  int i, enclen, truelen, padlen;
+  int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
   SilcBufferStruct packet;
 
   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
@@ -853,6 +856,13 @@ static SilcBool silc_packet_send_raw(SilcPacketStream stream,
   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
                      src_id_len + dst_id_len);
 
+  /* If IV is included, the IV and sequence number is added to packet */
+  if (stream->iv_included && cipher) {
+    ivlen = block_len;
+    psnlen = sizeof(psn);
+    memcpy(iv, silc_cipher_get_iv(cipher), block_len);
+  }
+
   /* We automatically figure out the packet structure from the packet
      type and flags, and calculate correct length.  Private messages with
      private keys and channel messages are special packets as their
@@ -862,21 +872,21 @@ static SilcBool silc_packet_send_raw(SilcPacketStream stream,
       type == SILC_PACKET_CHANNEL_MESSAGE) {
 
     /* Padding is calculated from header + IDs */
-    SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
-                       src_id_len +
-                       dst_id_len), block_len, padlen);
+    SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
+                       psnlen), block_len, padlen);
 
     /* Length to encrypt, header + IDs + padding. */
-    enclen = SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len + padlen;
+    enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
+             padlen + psnlen);
   } else {
 
     /* Padding is calculated from true length of the packet */
     if (flags & SILC_PACKET_FLAG_LONG_PAD)
-      SILC_PACKET_PADLEN_MAX(truelen, block_len, padlen);
+      SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
     else
-      SILC_PACKET_PADLEN(truelen, block_len, padlen);
+      SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
 
-    enclen += padlen;
+    enclen += padlen + psnlen;
   }
 
   /* Remove implementation specific flags */
@@ -889,14 +899,19 @@ static SilcBool silc_packet_send_raw(SilcPacketStream stream,
   silc_mutex_lock(stream->lock);
 
   /* Get packet pointer from the outgoing buffer */
-  if (!silc_packet_send_prepare(stream, truelen + padlen, hmac, &packet)) {
+  if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
+                               hmac, &packet)) {
     silc_mutex_unlock(stream->lock);
     return FALSE;
   }
 
+  SILC_PUT32_MSB(stream->send_psn, psn);
+
   /* Create the packet.  This creates the SILC header, adds padding, and
      the actual packet data. */
   i = silc_buffer_format(&packet,
+                        SILC_STR_UI_XNSTRING(iv, ivlen),
+                        SILC_STR_UI_XNSTRING(psn, psnlen),
                         SILC_STR_UI_SHORT(truelen),
                         SILC_STR_UI_CHAR(flags),
                         SILC_STR_UI_CHAR(type),
@@ -917,13 +932,13 @@ static SilcBool silc_packet_send_raw(SilcPacketStream stream,
   }
 
   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
-                  packet.data, silc_buffer_len(&packet));
+                  silc_buffer_data(&packet), silc_buffer_len(&packet));
 
   /* Encrypt the packet */
   if (cipher) {
     SILC_LOG_DEBUG(("Encrypting packet"));
-    if (!silc_cipher_encrypt(cipher, packet.data, packet.data,
-                            enclen, NULL)) {
+    if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
+                            packet.data + ivlen, enclen, NULL)) {
       SILC_LOG_ERROR(("Packet encryption failed"));
       silc_mutex_unlock(stream->lock);
       return FALSE;
@@ -932,14 +947,12 @@ static SilcBool silc_packet_send_raw(SilcPacketStream stream,
 
   /* Compute HMAC */
   if (hmac) {
-    unsigned char psn[4];
     SilcUInt32 mac_len;
 
     /* MAC is computed from the entire encrypted packet data, and put
        to the end of the packet. */
     silc_hmac_init(hmac);
-    SILC_PUT32_MSB(stream->send_psn, psn);
-    silc_hmac_update(hmac, psn, 4);
+    silc_hmac_update(hmac, psn, sizeof(psn));
     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
     silc_hmac_final(hmac, packet.tail, &mac_len);
     silc_buffer_pull_tail(&packet, mac_len);
@@ -1041,6 +1054,7 @@ static SilcBool silc_packet_check_mac(SilcHmac hmac,
                                      const unsigned char *data,
                                      SilcUInt32 data_len,
                                      const unsigned char *packet_mac,
+                                     const unsigned char *packet_seq,
                                      SilcUInt32 sequence)
 {
   /* Check MAC */
@@ -1052,8 +1066,13 @@ static SilcBool silc_packet_check_mac(SilcHmac hmac,
 
     /* Compute HMAC of packet */
     silc_hmac_init(hmac);
-    SILC_PUT32_MSB(sequence, psn);
-    silc_hmac_update(hmac, psn, 4);
+
+    if (!packet_seq) {
+      SILC_PUT32_MSB(sequence, psn);
+      silc_hmac_update(hmac, psn, 4);
+    } else
+      silc_hmac_update(hmac, packet_seq, 4);
+
     silc_hmac_update(hmac, data, data_len);
     silc_hmac_final(hmac, mac, &mac_len);
 
@@ -1295,16 +1314,19 @@ static void silc_packet_read_process(SilcPacketStream stream)
 {
   SilcPacket packet;
   SilcUInt16 packetlen;
-  SilcUInt32 paddedlen, mac_len, block_len;
+  SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
-  unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
+  unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
   SilcBool normal = TRUE;
   int ret;
 
   /* Parse the packets from the data */
   while (silc_buffer_len(&stream->inbuf) > 0) {
+    ivlen = psnlen = 0;
 
-    if (silc_buffer_len(&stream->inbuf) < SILC_PACKET_MIN_HEADER_LEN) {
+    if (silc_buffer_len(&stream->inbuf) <
+       stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN :
+       SILC_PACKET_MIN_HEADER_LEN_IV) {
       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
       return;
     }
@@ -1317,10 +1339,24 @@ static void silc_packet_read_process(SilcPacketStream stream)
     /* Decrypt first block of the packet to get the length field out */
     if (stream->receive_key) {
       block_len = silc_cipher_get_block_len(stream->receive_key);
-      memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
-      silc_cipher_decrypt(stream->receive_key, stream->inbuf.data,
+
+      if (stream->iv_included) {
+       /* IV is included in the ciphertext */
+       memcpy(iv, stream->inbuf.data, block_len);
+       ivlen = block_len;
+       psnlen = 4;
+      } else
+       memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
+
+      silc_cipher_decrypt(stream->receive_key, stream->inbuf.data + ivlen,
                          tmp, block_len, iv);
+
       header = tmp;
+      if (stream->iv_included) {
+       /* Take sequence number from packet */
+       packet_seq = header;
+       header += 4;
+      }
     } else {
       block_len = SILC_PACKET_MIN_HEADER_LEN;
       header = stream->inbuf.data;
@@ -1340,7 +1376,7 @@ static void silc_packet_read_process(SilcPacketStream stream)
       return;
     }
 
-    if (silc_buffer_len(&stream->inbuf) < paddedlen + mac_len) {
+    if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
                      "(%d bytes)",
                      paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
@@ -1350,8 +1386,9 @@ static void silc_packet_read_process(SilcPacketStream stream)
 
     /* Check MAC of the packet */
     if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
-                              paddedlen, stream->inbuf.data + paddedlen,
-                              stream->receive_psn)) {
+                              paddedlen + ivlen,
+                              stream->inbuf.data + ivlen + paddedlen,
+                              packet_seq, stream->receive_psn)) {
       silc_mutex_unlock(stream->lock);
       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
       silc_mutex_lock(stream->lock);
@@ -1408,15 +1445,16 @@ static void silc_packet_read_process(SilcPacketStream stream)
     }
 
     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
-                     stream->receive_psn, paddedlen + mac_len),
-                    stream->inbuf.data, paddedlen + mac_len);
+                     stream->receive_psn, paddedlen + ivlen + mac_len),
+                    stream->inbuf.data, paddedlen + ivlen + mac_len);
 
     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
     silc_buffer_pull_tail(&packet->buffer, paddedlen);
-    silc_buffer_put(&packet->buffer, header, block_len);
-    silc_buffer_pull(&packet->buffer, block_len);
-    silc_buffer_put(&packet->buffer, stream->inbuf.data + block_len,
-                   paddedlen - block_len);
+    silc_buffer_put(&packet->buffer, header, block_len - psnlen);
+    silc_buffer_pull(&packet->buffer, block_len - psnlen);
+    silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
+                                     psnlen + (block_len - psnlen)),
+                   paddedlen - ivlen - psnlen - (block_len - psnlen));
     if (stream->receive_key) {
       silc_cipher_set_iv(stream->receive_key, iv);
       ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
index 5bf28c99e829397ae280cbe85133964465ff396c..c72f301e9a8011c077c20f31d6a613be83a53fb5 100644 (file)
@@ -432,6 +432,24 @@ void silc_packet_stream_destroy(SilcPacketStream stream);
  ***/
 void silc_packet_stream_set_router(SilcPacketStream stream);
 
+/****f* silccore/SilcPacketAPI/silc_packet_stream_set_iv_included
+ *
+ * SYNOPSIS
+ *
+ *    void silc_packet_stream_set_iv_included(SilcPacketStream stream);
+ *
+ * DESCRIPTION
+ *
+ *    Sets an IV Included property for the stream indicated by `stream'.
+ *    This means that the IV used in the encryption will be included in
+ *    the resulted ciphertext.  This makes it possible to send and receive
+ *    packets on unreliable network transport protocol, such as UDP/IP.
+ *    This must be called if the underlaying stream in the `stream' is UDP
+ *    stream.
+ *
+ ***/
+void silc_packet_stream_set_iv_included(SilcPacketStream stream);
+
 /****f* silccore/SilcPacketAPI/silc_packet_stream_get_stream
  *
  * SYNOPSIS