/*
** Copyright (C) 2001-2011 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.227.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 FA8721-05-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/silk_config.h>

#include <stdio.h>
#ifdef    SK_HAVE_SYS_TYPES_H
#  include <sys/types.h>
#endif
#ifdef    SK_HAVE_SYS_STAT_H
#  include <sys/stat.h>
#endif
#ifdef    SK_STDC_HEADERS
#  include <stdlib.h>
#  include <stddef.h>
#else
#  ifdef  SK_HAVE_STDLIB_H
#    include <stdlib.h>
#  endif
#  ifdef  SK_HAVE_MALLOC_H
#    include <malloc.h>
#  endif
#endif
#ifdef    SK_HAVE_STRING_H
#  if     !defined SK_STDC_HEADERS && defined SK_HAVE_MEMORY_H
#    include <memory.h>
#  endif
#  include <string.h>
#endif
#ifdef    SK_HAVE_STRINGS_H
#  include <strings.h>
#endif
#ifdef    SK_HAVE_INTTYPES_H
#  include <inttypes.h>
#endif
#ifdef    SK_HAVE_STDINT_H
#  include <stdint.h>
#endif
#ifdef    SK_HAVE_UNISTD_H
#  include <unistd.h>
#endif

#ifdef    SK_HAVE_ASSERT_H
#  include <assert.h>
#endif
#ifdef    SK_HAVE_CTYPE_H
#  include <ctype.h>
#endif
#ifdef    SK_HAVE_ERRNO_H
#  include <errno.h>
#endif
#ifdef    SK_HAVE_FCNTL_H
#  include <fcntl.h>
#endif
#ifdef    SK_HAVE_FLOAT_H
#  include <float.h>
#endif
#ifdef    SK_HAVE_LIMITS_H
#  include <limits.h>
#endif
#ifdef    SK_HAVE_MATH_H
#  include <math.h>
#endif
#ifdef    SK_HAVE_NETDB_H
#  include <netdb.h>
#endif
#ifdef    SK_HAVE_PTHREAD_H
#  include <pthread.h>
#endif
#ifdef    SK_HAVE_REGEX_H
#  include <regex.h>
#endif
#ifdef    SK_HAVE_SIGNAL_H
#  include <signal.h>
#endif
#ifdef    SK_HAVE_STDARG_H
#  include <stdarg.h>
#endif
#ifdef    SK_HAVE_SYS_SELECT_H
#  include <sys/select.h>
#endif
#ifdef    SK_HAVE_SYS_SOCKET_H
#  include <sys/socket.h>
#endif
#ifdef    SK_HAVE_NETINET_IN_H
#  include <netinet/in.h>
#endif
#ifdef    SK_HAVE_NETINET_TCP_H
#  include <netinet/tcp.h>
#endif
#ifdef    SK_HAVE_ARPA_INET_H
#  include <arpa/inet.h>
#endif

#ifdef    SK_TIME_WITH_SYS_TIME
#  include <sys/time.h>
#  include <time.h>
#else
#  ifdef  SK_HAVE_SYS_TIME_H
#    include <sys/time.h>
#  else
#    include <time.h>
#  endif
#endif

#ifdef    SK_HAVE_DIRENT_H
#  include <dirent.h>
#else
#  define dirent direct
#  ifdef  SK_HAVE_SYS_NDIR_H
#    include <sys/ndir.h>
#  endif
#  ifdef  SK_HAVE_SYS_DIR_H
#    include <sys/dir.h>
#  endif
#  ifdef  SK_HAVE_NDIR_H
#    include <ndir.h>
#  endif
#endif

#ifdef    SK_HAVE_SYS_MMAN_H
#  include <sys/mman.h>
#endif
#ifdef    SK_HAVE_SYS_RESOURCE_H
#  include <sys/resource.h>
#endif
#ifdef    SK_HAVE_SYS_WAIT_H
#  include <sys/wait.h>
#endif
#ifdef    SK_HAVE_SYS_UIO_H
#  include <sys/uio.h>
#endif


/* make old endian macros generate errors */
#define IS_LITTLE_ENDIAN "Change IS_LITTLE_ENDIAN " "to SK_LITTLE_ENDIAN"
#define IS_BIG_ENDIAN    "Change IS_BIG_ENDIAN "    "to SK_BIG_ENDIAN"


/* Add appropriate suffix to constants */
#if !defined(INT32_C)
/* Assume we either get them all or get none of them. */
#  define  INT8_C(v)      (v)
#  define  INT16_C(v)     (v)
#  define  INT32_C(v)     (v)

#  define UINT8_C(v)      (v ## U)
#  define UINT16_C(v)     (v ## U)
#  define UINT32_C(v)     (v ## U)

#  if (SK_SIZEOF_LONG >= 8)
#    define  INT64_C(v)   (v ## L)
#    define UINT64_C(v)   (v ## UL)
#  elif (SK_SIZEOF_UNSIGNED_LONG_LONG >= 8)
#    define  INT64_C(v)   (v ## LL)
#    define UINT64_C(v)   (v ## ULL)
#  endif
#endif


/* Maxima */
#if !defined(INT8_MAX)
#  define  INT8_MAX          127
#endif
#if !defined(UINT8_MAX)
#  define UINT8_MAX          255U
#endif
#if !defined(INT16_MAX)
#  define  INT16_MAX       32767
#endif
#if !defined(UINT16_MAX)
#  define UINT16_MAX       65535U
#endif
#if !defined(INT32_MAX)
#  define  INT32_MAX   2147483647
#endif
#if !defined(UINT32_MAX)
#  define UINT32_MAX   4294967295U
#endif
#if !defined(INT64_MAX)
#  define  INT64_MAX    INT64_C(9223372036854775807)
#endif
#if !defined(UINT64_MAX)
#  define UINT64_MAX   UINT64_C(18446744073709551615)
#endif

#if !defined(ULLONG_MAX)
#  if (SK_SIZEOF_UNSIGNED_LONG_LONG == 8)
#    define ULLONG_MAX UINT64_MAX
#  endif
#endif
#if !defined(SIZE_MAX)
#  if (SK_SIZEOF_SIZE_T >= 8)
#    define SIZE_MAX   UINT64_MAX
#  else
#    define SIZE_MAX   UINT32_MAX
#  endif
#endif
#if !defined(SSIZE_MAX)
#  if (SK_SIZEOF_SSIZE_T >= 8)
#    define SSIZE_MAX  INT64_MAX
#  else
#    define SSIZE_MAX  INT32_MAX
#  endif
#endif

/* PRI* macros for printing */
#if !defined(PRIu32)
/* Assume we either get them all or get none of them. */
#  define PRId32 "d"
#  define PRIi32 "i"
#  define PRIo32 "o"
#  define PRIu32 "u"
#  define PRIx32 "x"
#  define PRIX32 "X"

#  define PRId16 PRId32
#  define PRIi16 PRIi32
#  define PRIo16 PRIo32
#  define PRIu16 PRIu32
#  define PRIx16 PRIx32
#  define PRIX16 PRIX32

#  define PRId8  PRId32
#  define PRIi8  PRIi32
#  define PRIo8  PRIo32
#  define PRIu8  PRIu32
#  define PRIx8  PRIx32
#  define PRIX8  PRIX32
#endif /* !defined(PRIU32) */
#if !defined(PRIu64)
#  if (SK_SIZEOF_LONG >= 8)
#    define PRId64 "l" PRId32
#    define PRIi64 "l" PRIi32
#    define PRIo64 "l" PRIo32
#    define PRIu64 "l" PRIu32
#    define PRIx64 "l" PRIx32
#    define PRIX64 "l" PRIX32
#  else
#    define PRId64 "ll" PRId32
#    define PRIi64 "ll" PRIi32
#    define PRIo64 "ll" PRIo32
#    define PRIu64 "ll" PRIu32
#    define PRIx64 "ll" PRIx32
#    define PRIX64 "ll" PRIX32
#  endif
#endif /* !defined(PRIu64) */


/* Functions and types from C99 that we require */
#ifndef SK_HAVE_INTMAX_T
#  define intmax_t sk_intmax_t
#endif
#ifndef SK_HAVE_IMAXDIV_T
#  define imaxdiv_t sk_imaxdiv_t
#endif
#ifndef SK_HAVE_IMAXDIV
#  define imaxdiv sk_imaxdiv
#endif
#ifndef SK_HAVE_MEMCCPY
#  define memccpy sk_memccpy
#endif
#ifndef SK_HAVE_SETENV
#  define setenv sk_setenv
#endif
#ifndef SK_HAVE_STRSEP
#  define strsep sk_strsep
#endif
#ifndef SK_HAVE_TIMEGM
#  define timegm sk_timegm
#endif


/* various IP protocols */
#ifndef IPPROTO_ICMP
#  define IPPROTO_ICMP    1
#endif
#ifndef IPPROTO_TCP
#  define IPPROTO_TCP     6
#endif
#ifndef IPPROTO_UDP
#  define IPPROTO_UDP    17
#endif
#ifndef IPPROTO_ICMPV6
#  define IPPROTO_ICMPV6 58
#endif


/* Wrap UNUSED() around unused parameters to silence gcc -W */
#ifdef __GNUC__
#define UNUSED(var) /*@unused@*/ var __attribute__((__unused__))
#define SK_CHECK_PRINTF(fmt_pos, argv1_pos)                        \
    __attribute__((format (printf, fmt_pos, argv1_pos)))
#else
#define UNUSED(var) /*@unused@*/ var
#define SK_CHECK_PRINTF(fmt_pos, argv1)
#endif

/*
 *  Create a variable for magic RCS variables: Define 'var' to be the
 *  string in 'id'.  Can be used in header, keep 'var's unique.  Use:
 *  RCSIDENTVAR(myheader, "$Magic RCS Var$");
 */
#ifndef SK_HAVE_COMP_ATTRIBUTE_USED
#define RCSIDENTVAR(var, id) \
    static const char /*@observer@*/ UNUSED(* var) = (id)
#else
/*
 *  Have RCSIDENTVAR() mark the variables as "used" so GCC doesn't
 *  strip them.
 */
#define RCSIDENTVAR(var, id) \
    static const char /*@observer@*/ /*@unused@*/ * var __attribute__((__used__)) = (id)
#endif /* SK_HAVE_COMP_ATTRIBUTE_USED */

/*
 *  As above, except for C files since 'var' can be fixed.
 */
#define RCSIDENT(id) RCSIDENTVAR(_rcsID, (id))


RCSIDENTVAR(rcsID_SILK_H, "$SiLK: silk.h 16700 2011-02-10 18:34:03Z 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/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.  Do not deference directly, use the
 * macros specified in skipaddr.h to get/set the value. */
typedef union ipUnion_un {
    uint32_t    ipu_ipv4;
#if SK_ENABLE_IPV6
    uint8_t     ipu_ipv6[16];
#endif
} ipUnion;

/* Define an address structure that knows the version of IP address.
 * Do not deference directly, use the macros specified in skipaddr.h
 * to get/set the value */
typedef struct skipaddr_st {
    ipUnion     ip_ip;
#if SK_ENABLE_IPV6
    unsigned    ip_is_v6 :1;
#endif
} skipaddr_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);


/*
 *    Functions declared in utils.h, defined in sku-app.c, that print
 *    messages to the stderr.
 */
void skAppPrintAbortMsg(
    const char *func_name,
    const char *file_name,
    int         line_number);
void skAppPrintBadCaseMsg(
    const char *func_name,
    const char *file_name,
    int         line_number,
    int64_t     value,
    const char *value_expr);

/* include abort() in macro definition so compiler knows function exits */
#ifdef SK_HAVE_C99___FUNC__
#define skAbort()                                               \
    do {                                                        \
        skAppPrintAbortMsg(__func__, __FILE__, __LINE__);       \
        abort();                                                \
    } while(0)
#define skAbortBadCase(abc_expr)                                \
    do {                                                        \
        skAppPrintBadCaseMsg(__func__, __FILE__, __LINE__,      \
                             (int64_t)(abc_expr), #abc_expr);   \
        abort();                                                \
    } while(0)
#else
#define skAbort()                                       \
    do {                                                \
        skAppPrintAbortMsg(NULL, __FILE__, __LINE__);   \
        abort();                                        \
    } while(0)
#define skAbortBadCase(abc_expr)                                \
    do {                                                        \
        skAppPrintBadCaseMsg(NULL, __FILE__, __LINE__,          \
                             (int64_t)(abc_expr), #abc_expr);   \
        abort();                                                \
    } while(0)
#endif


/* Bit-swapping macros for changing endianness */
#if  SK_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 /* SK_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   SK_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:
*/
