/*
** Copyright (C) 2001-2008 by Carnegie Mellon University.
**
** @OPENSOURCE_HEADER_START@
**
** Use of the SILK system and related source code is subject to the terms
** of the following licenses:
**
** GNU Public License (GPL) Rights pursuant to Version 2, June 1991
** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013
**
** NO WARRANTY
**
** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
** DELIVERABLES UNDER THIS LICENSE.
**
** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
** Mellon University, its trustees, officers, employees, and agents from
** all claims or demands made against them (and any related losses,
** expenses, or attorney's fees) arising out of, or relating to Licensee's
** and/or its sub licensees' negligent use or willful misuse of or
** negligent conduct or willful misconduct regarding the Software,
** facilities, or other rights or assistance granted by Carnegie Mellon
** University under this License, including, but not limited to, any
** claims of product liability, personal injury, death, damage to
** property, or violation of any laws or regulations.
**
** Carnegie Mellon University Software Engineering Institute authored
** documents are sponsored by the U.S. Department of Defense under
** Contract F19628-00-C-0003. Carnegie Mellon University retains
** copyrights in all material produced under this contract. The U.S.
** Government retains a non-exclusive, royalty-free license to publish or
** reproduce these documents, or allow others to do so, for U.S.
** Government purposes only pursuant to the copyright license under the
** contract clause at 252.227.7013.
**
** @OPENSOURCE_HEADER_END@
*/
#ifndef _SILK_H
#define _SILK_H

#include "silk_config.h"

RCSIDENTVAR(rcsID_SILK_H, "$SiLK: silk.h 11926 2008-07-02 18:27:07Z mthomas $");


/* Define an enumeration type for endianess */
typedef enum silk_endian_en {
    SILK_ENDIAN_BIG,
    SILK_ENDIAN_LITTLE,
    SILK_ENDIAN_NATIVE,
    SILK_ENDIAN_ANY
} silk_endian_t;


/* Defines generic file header and supported file types */
#include "silk_files.h"

/* Name of environment variable pointing to the root of install */
#define ENV_SILK_PATH "SILK_PATH"

/* First look for plugins in these sub-directories of $SILK_PATH; if
 * that fails, look for plugins in these sub-directories of the
 * binary's parent directory; if that fails, use platform's default
 * (LD_LIBRARY_PATH or similar). */
#define SILK_SUBDIR_PLUGINS                    \
    { "lib64/silk", "share/lib64", "lib64",    \
      "lib/silk",  "share/lib", "lib",         \
      (char*)NULL }

/* Subdirectory of $SILK_PATH for support files */
#define SILK_SUBDIR_SUPPORT "share"

/* Define an ip address structure. */
typedef union ipUnion_un {
    uint32_t    ipu_ipv4;
#if SK_ENABLE_IPV6
    uint8_t     ipu_ipv6[16];
#endif
} ipUnion;

/* Get and Set the V4 part of the address structure */
#define ipUnionGetV4(ipu)                       \
    ((ipu)->ipu_ipv4)

#define ipUnionSetV4(ipu, in_vp)                                \
    memcpy(&((ipu)->ipu_ipv4), (in_vp), 4)

#if SK_ENABLE_IPV6

/* Get and Set the V6 parts of the address structure */
#define ipUnionGetV6(ipu, out_vp)               \
    memcpy((out_vp), (ipu)->ipu_ipv6, 16)

#define ipUnionSetV6(ipu, in_vp)               \
    memcpy((ipu)->ipu_ipv6, (in_vp), 16)

/* Write the V4 address into a V6 location */
#define ipUnionGetV4AsV6(ipu, ipv6)                               \
    do {                                                          \
        uint32_t ipug4a6 = htonl(ipUnionGetV4(ipu));              \
        memset((ipv6), 0, 10);                                    \
        memset((((uint8_t*)(ipv6)) + 10), 0xff, 2);               \
        memcpy((((uint8_t*)(ipv6)) + 12), &ipug4a6, 4);           \
    } while(0)

/* Convert a V4 ipUnion to V6 */
#define ipUnion4to6(src_ipu, dst_ipu)                   \
    ipUnionGetV4AsV6((src_ipu), (dst_ipu)->ipu_ipv6)

#endif /* SK_ENABLE_IPV6 */


/* Define an address structure that knows the version of IP address */
typedef struct skipaddr_st {
    ipUnion     ip_ip;
#if SK_ENABLE_IPV6
    unsigned    ip_is_v6 :1;
#endif
} skipaddr_t;


/* Determine whether the skipaddr_t has a V6 address */
#if !SK_ENABLE_IPV6
#  define skipaddrIsV6(addr)   0
#else
#  define skipaddrIsV6(addr)   ((addr)->ip_is_v6)
#endif

/* Specify that the address is a V6 address */
#if !SK_ENABLE_IPV6
#  define skipaddrSetVersion(addr, version)
#else
#  define skipaddrSetVersion(addr, version)     \
    do { (addr)->ip_is_v6 = version; } while(0)
#endif


/* Copy the value from src to dest */
#if !SK_ENABLE_IPV6
#  define skipaddrCopy(dst, src)                                \
    do { skipaddrGetV4(dst) = skipaddrGetV4(src); } while(0)
#else
#  define skipaddrCopy(dst, src)   memcpy((dst), (src), sizeof(skipaddr_t))
#endif


/* Clear the value in the skipaddr_t */
#if !SK_ENABLE_IPV6
#  define skipaddrClear(addr)   do { skipaddrGetV4(addr) = 0; } while(0)
#else
#  define skipaddrClear(addr)   memset((addr), 0, sizeof(skipaddr_t))
#endif

/* Get and set the V4 address */
#define skipaddrGetV4(addr)    (ipUnionGetV4(&((addr)->ip_ip)))

#if !SK_ENABLE_IPV6
#  define skipaddrSetV4(addr, in_vp)            \
    ipUnionSetV4(&((addr)->ip_ip), in_vp)
#else
#define skipaddrSetV4(addr, in_vp)                                      \
    do {                                                                \
        skipaddrClear(addr);                                            \
        ipUnionSetV4(&((addr)->ip_ip), (in_vp));                        \
    } while(0)
#endif


#if SK_ENABLE_IPV6

/* Get and set the V6 address */

#  define skipaddrGetAsV6(addr, out_vp)                      \
    if (skipaddrIsV6(addr)) {                                \
        ipUnionGetV6(&((addr)->ip_ip), (out_vp));            \
    } else {                                                 \
        ipUnionGetV4AsV6(&((addr)->ip_ip), (out_vp));        \
    }

#  define skipaddrGetV6(addr, out_vp)           \
    ipUnionGetV6(&((addr)->ip_ip), (out_vp))

#  define skipaddrSetV6(addr, in_vp)                                    \
    do {                                                                \
        ipUnionSetV6(&((addr)->ip_ip), (in_vp));                        \
        (addr)->ip_is_v6 = 1;                                           \
    } while(0)

/* Convert a V4 address to a V6 address */
#define skipaddrV4toV6(srcaddr, dstaddr)                              \
    do {                                                              \
        ipUnion4to6(&((srcaddr)->ip_ip), &((dstaddr)->ip_ip));        \
        (dstaddr)->ip_is_v6 = 1;                                      \
    } while(0)

#endif /* SK_ENABLE_IPV6 */


/* What to do with IPv6 flows */
typedef enum ipv6policy {
    /* completely ignore IPv6 flows */
    SK_IPV6POLICY_IGNORE = -2,
    /* convert IPv6 flows to IPv4 if possible, else ignore */
    SK_IPV6POLICY_ASV4 = -1,
    /* mix IPv4 and IPv6 flows in the result--this is the default */
    SK_IPV6POLICY_MIX = 0,
    /* force IPv4 flows to be converted to IPv6 */
    SK_IPV6POLICY_FORCE = 1,
    /* only return IPv6 flows that were marked as IPv6 */
    SK_IPV6POLICY_ONLY = 2
} sk_ipv6policy_t;



/*
 *  sktime_t is milliseconds since the UNIX epoch.
 */
typedef int64_t sktime_t;


/*
 *    The type of message functions.  These should use the same
 *    semantics as printf.
 */
typedef int (*sk_msg_fn_t)(const char *, ...);


/*
 *    The type of message functions with the arguments expanded to a
 *    variable argument list.
 */
typedef int (*sk_msg_vargs_fn_t)(const char *, va_list);


/* Bit-swapping macros for changing endianness */
#if  IS_LITTLE_ENDIAN
#  define  BSWAP16(a)  (ntohs(a))
#  define  BSWAP32(a)  (ntohl(a))
#else
#  define BSWAP16(a) ((((uint16_t)(a)) >> 8) |    \
                      (((uint16_t)(a)) << 8))
#  define BSWAP32(a) (((((uint32_t)(a)) & 0x000000FF) << 24) |    \
                      ((((uint32_t)(a)) & 0x0000FF00) << 8)  |    \
                      ((((uint32_t)(a)) & 0x00FF0000) >> 8)  |    \
                      ((((uint32_t)(a)) >> 24) & 0x000000FF))
#endif /* IS_LITTLE_ENDIAN */
#define BSWAP64(a)                                              \
    ((((uint64_t)BSWAP32((uint32_t)((a) & 0xffffffff))) << 32)  \
     | BSWAP32((uint32_t)((a) >> 32)))


/* provide a network-to-host swapper for 64bit values */
#if   IS_LITTLE_ENDIAN
#  define ntoh64(a)  BSWAP64(a)
#else
#  define ntoh64(a)  (a)
#endif
#define hton64(a)  ntoh64(a)

#endif /* _SILK_H */

/*
** Local Variables:
** mode:c
** indent-tabs-mode:nil
** c-basic-offset:4
** End:
*/
