]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
queue.h: wrap the system sys/queue.h 6455/head
authorJason Ish <jason.ish@oisf.net>
Wed, 6 Oct 2021 16:53:46 +0000 (10:53 -0600)
committerJason Ish <jason.ish@oisf.net>
Wed, 6 Oct 2021 21:39:07 +0000 (15:39 -0600)
Instead of using local implementations for the queue.h macro,
wrap the system provided queue.h and then adding missing
features as needed.

The idea is that Suricata when integrated with another library
that includes sys/queue.h can look at the same source of truth
for these macros.

But not all operating systems include a queue.h with the same
features, and some don't include it at all, like Windows. So
on Windows this will be a full implementation of all the queue.h
features Suricata needs.

configure.ac
src/queue.h

index 743c2323c846b55d6e5c53c0e19e665314463dd6..59ccafada6708f08b7bc621a2e30a742c24813fb 100644 (file)
     AC_CHECK_HEADERS([libgen.h])
     AC_CHECK_HEADERS([mach/mach.h])
     AC_CHECK_HEADERS([stdatomic.h])
+    AC_CHECK_HEADERS([sys/queue.h])
 
     AC_CHECK_HEADERS([sys/socket.h net/if.h sys/mman.h linux/if_arp.h], [], [],
     [[#ifdef HAVE_SYS_SOCKET_H
index d5fb32f11a7bb4e84f732c1939e0a3064f08851c..153d02ab4990fbec28efb74efdf8e35574d2daf1 100644 (file)
  *     @(#)queue.h     8.5 (Berkeley) 8/20/94
  */
 
-#ifndef        _SYS_QUEUE_H_
-#define        _SYS_QUEUE_H_
-
-/*
- * This file defines five types of data structures: singly-linked lists,
- * lists, simple queues, tail queues, and circular queues.
- *
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction.  Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A simple queue is headed by a pair of pointers, one the head of the
- * list and the other to the tail of the list. The elements are singly
- * linked to save space, so elements can only be removed from the
- * head of the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the
- * list. A simple queue may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- *
- * For details on the use of these macros, see the queue(3) manual page.
+// Disable clang-formatting as these implementations are copied from other
+// sources.
+//
+// clang-format off
+
+#ifndef SURICATA_QUEUE_H
+#define SURICATA_QUEUE_H
+
+/**
+ * This file started as a copy of sys/queue.h from OpenBSD and then had
+ * various changes made over time. Now we include the system sys/queue.h
+ * and then add missing behavior. On Windows this means we basically add
+ * everything. This allows for Suricata builds that integrate with other
+ * libraries that make use of sys/queue.h to use the exact same definitions
+ * from queue.h instead the Suricata copy.
  */
 
-#if defined(__clang_analyzer__) || defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
-#define _Q_INVALIDATE(a) ((a) = ((void *)-1))
-#else
-#define _Q_INVALIDATE(a)
-#endif
+#include "autoconf.h"
 
-#if defined(__clang_analyzer__)
-#define _Q_ASSERT(a) assert((a))
-#else
-#define _Q_ASSERT(a)
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
 #endif
 
-/*
- * Singly-linked List definitions.
- */
-
-/*
- * The following macros are not used and are in conflict with Win32 API
- */
-
-#if 0
-
-#define SLIST_HEAD(name, type)                                         \
-struct name {                                                          \
-       struct type *slh_first; /* first element */                     \
-}
-
-#define        SLIST_HEAD_INITIALIZER(head)                                    \
-       { NULL }
-
-#define SLIST_ENTRY(type)                                              \
-struct {                                                               \
-       struct type *sle_next;  /* next element */                      \
-}
-
-/*
- * Singly-linked List access methods.
- */
-#define        SLIST_FIRST(head)       ((head)->slh_first)
-#define        SLIST_END(head)         NULL
-#define        SLIST_EMPTY(head)       (SLIST_FIRST(head) == SLIST_END(head))
-#define        SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
-
-#define        SLIST_FOREACH(var, head, field)                                 \
-       for((var) = SLIST_FIRST(head);                                  \
-           (var) != SLIST_END(head);                                   \
-           (var) = SLIST_NEXT(var, field))
-
-#define        SLIST_FOREACH_PREVPTR(var, varp, head, field)                   \
-       for ((varp) = &SLIST_FIRST((head));                             \
-           ((var) = *(varp)) != SLIST_END(head);                       \
-           (varp) = &SLIST_NEXT((var), field))
-
-/*
- * Singly-linked List functions.
- */
-#define        SLIST_INIT(head) {                                              \
-       SLIST_FIRST(head) = SLIST_END(head);                            \
-}
-
-#define        SLIST_INSERT_AFTER(slistelm, elm, field) do {                   \
-       (elm)->field.sle_next = (slistelm)->field.sle_next;             \
-       (slistelm)->field.sle_next = (elm);                             \
-} while (0)
-
-#define        SLIST_INSERT_HEAD(head, elm, field) do {                        \
-       (elm)->field.sle_next = (head)->slh_first;                      \
-       (head)->slh_first = (elm);                                      \
-} while (0)
-
-#define        SLIST_REMOVE_NEXT(head, elm, field) do {                        \
-       (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
-} while (0)
-
-#define        SLIST_REMOVE_HEAD(head, field) do {                             \
-       (head)->slh_first = (head)->slh_first->field.sle_next;          \
-} while (0)
-
-#define SLIST_REMOVE(head, elm, type, field) do {                      \
-       if ((head)->slh_first == (elm)) {                               \
-               SLIST_REMOVE_HEAD((head), field);                       \
-       } else {                                                        \
-               struct type *curelm = (head)->slh_first;                \
-                                                                       \
-               while (curelm->field.sle_next != (elm))                 \
-                       curelm = curelm->field.sle_next;                \
-               curelm->field.sle_next =                                \
-                   curelm->field.sle_next->field.sle_next;             \
-               _Q_INVALIDATE((elm)->field.sle_next);                   \
-       }                                                               \
-} while (0)
-
-#endif /* 0 */
-
-/*
- * List definitions.
- */
-#define LIST_HEAD(name, type)                                          \
-struct name {                                                          \
-       struct type *lh_first;  /* first element */                     \
-}
-
-#define LIST_HEAD_INITIALIZER(head)                                    \
-       { NULL }
-
-#define LIST_ENTRY(type)                                               \
-struct {                                                               \
-       struct type *le_next;   /* next element */                      \
-       struct type **le_prev;  /* address of previous next element */  \
-}
-
-/*
- * List access methods
- */
-#define        LIST_FIRST(head)                ((head)->lh_first)
-#define        LIST_END(head)                  NULL
-#define        LIST_EMPTY(head)                (LIST_FIRST(head) == LIST_END(head))
-#define        LIST_NEXT(elm, field)           ((elm)->field.le_next)
-
-#define LIST_FOREACH(var, head, field)                                 \
-       for((var) = LIST_FIRST(head);                                   \
-           (var)!= LIST_END(head);                                     \
-           (var) = LIST_NEXT(var, field))
-
-/*
- * List functions.
- */
-#define        LIST_INIT(head) do {                                            \
-       LIST_FIRST(head) = LIST_END(head);                              \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do {                    \
-       if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
-               (listelm)->field.le_next->field.le_prev =               \
-                   &(elm)->field.le_next;                              \
-       (listelm)->field.le_next = (elm);                               \
-       (elm)->field.le_prev = &(listelm)->field.le_next;               \
-} while (0)
-
-#define        LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
-       (elm)->field.le_prev = (listelm)->field.le_prev;                \
-       (elm)->field.le_next = (listelm);                               \
-       *(listelm)->field.le_prev = (elm);                              \
-       (listelm)->field.le_prev = &(elm)->field.le_next;               \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do {                                \
-       if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
-               (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
-       (head)->lh_first = (elm);                                       \
-       (elm)->field.le_prev = &(head)->lh_first;                       \
-} while (0)
-
-#define LIST_REMOVE(elm, field) do {                                   \
-       if ((elm)->field.le_next != NULL)                               \
-               (elm)->field.le_next->field.le_prev =                   \
-                   (elm)->field.le_prev;                               \
-       *(elm)->field.le_prev = (elm)->field.le_next;                   \
-       _Q_INVALIDATE((elm)->field.le_prev);                            \
-       _Q_INVALIDATE((elm)->field.le_next);                            \
-} while (0)
-
-#define LIST_REPLACE(elm, elm2, field) do {                            \
-       if (((elm2)->field.le_next = (elm)->field.le_next) != NULL)     \
-               (elm2)->field.le_next->field.le_prev =                  \
-                   &(elm2)->field.le_next;                             \
-       (elm2)->field.le_prev = (elm)->field.le_prev;                   \
-       *(elm2)->field.le_prev = (elm2);                                \
-       _Q_INVALIDATE((elm)->field.le_prev);                            \
-       _Q_INVALIDATE((elm)->field.le_next);                            \
-} while (0)
-
-/*
- * Simple queue definitions.
- */
-#define SIMPLEQ_HEAD(name, type)                                       \
-struct name {                                                          \
-       struct type *sqh_first; /* first element */                     \
-       struct type **sqh_last; /* addr of last next element */         \
-}
-
-#define SIMPLEQ_HEAD_INITIALIZER(head)                                 \
-       { NULL, &(head).sqh_first }
-
-#define SIMPLEQ_ENTRY(type)                                            \
-struct {                                                               \
-       struct type *sqe_next;  /* next element */                      \
-}
-
-/*
- * Simple queue access methods.
- */
-#define        SIMPLEQ_FIRST(head)         ((head)->sqh_first)
-#define        SIMPLEQ_END(head)           NULL
-#define        SIMPLEQ_EMPTY(head)         (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
-#define        SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
-
-#define SIMPLEQ_FOREACH(var, head, field)                              \
-       for((var) = SIMPLEQ_FIRST(head);                                \
-           (var) != SIMPLEQ_END(head);                                 \
-           (var) = SIMPLEQ_NEXT(var, field))
-
-/*
- * Simple queue functions.
- */
-#define        SIMPLEQ_INIT(head) do {                                         \
-       (head)->sqh_first = NULL;                                       \
-       (head)->sqh_last = &(head)->sqh_first;                          \
-} while (0)
-
-#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {                     \
-       if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)        \
-               (head)->sqh_last = &(elm)->field.sqe_next;              \
-       (head)->sqh_first = (elm);                                      \
-} while (0)
-
-#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {                     \
-       (elm)->field.sqe_next = NULL;                                   \
-       *(head)->sqh_last = (elm);                                      \
-       (head)->sqh_last = &(elm)->field.sqe_next;                      \
-} while (0)
-
-#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {           \
-       if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
-               (head)->sqh_last = &(elm)->field.sqe_next;              \
-       (listelm)->field.sqe_next = (elm);                              \
-} while (0)
-
-#define SIMPLEQ_REMOVE_HEAD(head, field) do {                  \
-       if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
-               (head)->sqh_last = &(head)->sqh_first;                  \
-} while (0)
-
-/*
- * Tail queue definitions.
- */
-#define TAILQ_HEAD(name, type)                                         \
-struct name {                                                          \
-       struct type *tqh_first; /* first element */                     \
-       struct type **tqh_last; /* addr of last next element */         \
-}
-
-#define TAILQ_HEAD_INITIALIZER(head)                                   \
-       { NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type)                                              \
-struct {                                                               \
-       struct type *tqe_next;  /* next element */                      \
-       struct type **tqe_prev; /* address of previous next element */  \
-}
-
-/*
- * tail queue access methods
+/* Not included in Linux, but are in FreeBSD and friends.
+ *
+ * This implementation from FreeBSD's sys/queue.h.
  */
-#define        TAILQ_FIRST(head)               ((head)->tqh_first)
-#define        TAILQ_END(head)                 NULL
-#define        TAILQ_NEXT(elm, field)          ((elm)->field.tqe_next)
-#define TAILQ_LAST(head, headname)                                     \
-       (*(((struct headname *)((head)->tqh_last))->tqh_last))
-/* XXX */
-#define TAILQ_PREV(elm, headname, field)                               \
-       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-#define        TAILQ_EMPTY(head)                                               \
-       (TAILQ_FIRST(head) == TAILQ_END(head))
-
-#define TAILQ_FOREACH(var, head, field)                                        \
-       for((var) = TAILQ_FIRST(head);                                  \
-           (var) != TAILQ_END(head);                                   \
-           (var) = TAILQ_NEXT(var, field))
-
-/* removal safe iterator using a temprary element has last param */
-#define TAILQ_FOREACH_SAFE(var, head, field, tvar)                                     \
-       for((var) = TAILQ_FIRST(head), \
-        (tvar) = TAILQ_FIRST(head) ? TAILQ_NEXT(TAILQ_FIRST(head), field): NULL ; \
-           (var) != TAILQ_END(head);                                   \
-           (var = tvar), (tvar) = var ? TAILQ_NEXT(var, field): NULL)
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field)              \
-       for((var) = TAILQ_LAST(head, headname);                         \
-           (var) != TAILQ_END(head);                                   \
-           (var) = TAILQ_PREV(var, headname, field))
+#ifndef TAILQ_FOREACH_SAFE
+#define        TAILQ_FOREACH_SAFE(var, head, field, tvar)                      \
+       for ((var) = TAILQ_FIRST((head));                               \
+           (var) && ((tvar) = TAILQ_NEXT((var), field), 1);            \
+           (var) = (tvar))
+#endif
 
-/*
- * Tail queue functions.
+/* The BSDs have removed CIRCLEQ but it still exists in Linux.
+ *
+ * This implementation from OpenBSD sys/queue.h v1.40 as it still has
+ * CIRCLEQ and includes the safe variations.
+ * - _Q_INVALIDATE for some extra debugging has been removed as its
+ *   not available on the Linux version of CIRCLEQ.
  */
-#define        TAILQ_INIT(head) do {                                           \
-       (head)->tqh_first = NULL;                                       \
-       (head)->tqh_last = &(head)->tqh_first;                          \
-} while (0)
 
-#define TAILQ_INSERT_HEAD(head, elm, field) do {                       \
-       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
-               (head)->tqh_first->field.tqe_prev =                     \
-                   &(elm)->field.tqe_next;                             \
-       else                                                            \
-               (head)->tqh_last = &(elm)->field.tqe_next;              \
-       (head)->tqh_first = (elm);                                      \
-       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do {                       \
-       _Q_ASSERT((elm));                                               \
-       _Q_ASSERT((head));                                              \
-       (elm)->field.tqe_next = NULL;                                   \
-       (elm)->field.tqe_prev = (head)->tqh_last;                       \
-       *(head)->tqh_last = (elm);                                      \
-       _Q_ASSERT(*(head)->tqh_last);                                   \
-       (head)->tqh_last = &(elm)->field.tqe_next;                      \
-} while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {             \
-       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
-               (elm)->field.tqe_next->field.tqe_prev =                 \
-                   &(elm)->field.tqe_next;                             \
-       else                                                            \
-               (head)->tqh_last = &(elm)->field.tqe_next;              \
-       (listelm)->field.tqe_next = (elm);                              \
-       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
-} while (0)
-
-#define        TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
-       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
-       (elm)->field.tqe_next = (listelm);                              \
-       *(listelm)->field.tqe_prev = (elm);                             \
-       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
-} while (0)
-
-#define TAILQ_REMOVE(head, elm, field) do {                            \
-       if (((elm)->field.tqe_next) != NULL)                            \
-               (elm)->field.tqe_next->field.tqe_prev =                 \
-                   (elm)->field.tqe_prev;                              \
-       else                                                            \
-               (head)->tqh_last = (elm)->field.tqe_prev;               \
-       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
-       _Q_ASSERT((head)->tqh_first != (elm));                          \
-       _Q_INVALIDATE((elm)->field.tqe_prev);                           \
-       _Q_INVALIDATE((elm)->field.tqe_next);                           \
-} while (0)
-
-#define TAILQ_REPLACE(head, elm, elm2, field) do {                     \
-       if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   \
-               (elm2)->field.tqe_next->field.tqe_prev =                \
-                   &(elm2)->field.tqe_next;                            \
-       else                                                            \
-               (head)->tqh_last = &(elm2)->field.tqe_next;             \
-       (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 \
-       *(elm2)->field.tqe_prev = (elm2);                               \
-       _Q_INVALIDATE((elm)->field.tqe_prev);                           \
-       _Q_INVALIDATE((elm)->field.tqe_next);                           \
-} while (0)
+#ifndef CIRCLEQ_HEAD
 
 /*
  * Circular queue definitions.
@@ -456,7 +99,6 @@ struct {                                                             \
  */
 #define        CIRCLEQ_FIRST(head)             ((head)->cqh_first)
 #define        CIRCLEQ_LAST(head)              ((head)->cqh_last)
-#define        CIRCLEQ_END(head)               ((void *)(head))
 #define        CIRCLEQ_NEXT(elm, field)        ((elm)->field.cqe_next)
 #define        CIRCLEQ_PREV(elm, field)        ((elm)->field.cqe_prev)
 #define        CIRCLEQ_EMPTY(head)                                             \
@@ -467,11 +109,23 @@ struct {                                                          \
            (var) != CIRCLEQ_END(head);                                 \
            (var) = CIRCLEQ_NEXT(var, field))
 
+#define        CIRCLEQ_FOREACH_SAFE(var, head, field, tvar)                    \
+       for ((var) = CIRCLEQ_FIRST(head);                               \
+           (var) != CIRCLEQ_END(head) &&                               \
+           ((tvar) = CIRCLEQ_NEXT(var, field), 1);                     \
+           (var) = (tvar))
+
 #define CIRCLEQ_FOREACH_REVERSE(var, head, field)                      \
        for((var) = CIRCLEQ_LAST(head);                                 \
            (var) != CIRCLEQ_END(head);                                 \
            (var) = CIRCLEQ_PREV(var, field))
 
+#define        CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)  \
+       for ((var) = CIRCLEQ_LAST(head, headname);                      \
+           (var) != CIRCLEQ_END(head) &&                               \
+           ((tvar) = CIRCLEQ_PREV(var, headname, field), 1);           \
+           (var) = (tvar))
+
 /*
  * Circular queue functions.
  */
@@ -531,35 +185,141 @@ struct {                                                         \
        else                                                            \
                (elm)->field.cqe_prev->field.cqe_next =                 \
                    (elm)->field.cqe_next;                              \
-       _Q_INVALIDATE((elm)->field.cqe_prev);                           \
-       _Q_INVALIDATE((elm)->field.cqe_next);                           \
 } while (0)
 
 #define CIRCLEQ_REPLACE(head, elm, elm2, field) do {                   \
        if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==         \
            CIRCLEQ_END(head))                                          \
-               (head).cqh_last = (elm2);                               \
+               (head)->cqh_last = (elm2);                              \
        else                                                            \
                (elm2)->field.cqe_next->field.cqe_prev = (elm2);        \
        if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==         \
            CIRCLEQ_END(head))                                          \
-               (head).cqh_first = (elm2);                              \
+               (head)->cqh_first = (elm2);                             \
        else                                                            \
                (elm2)->field.cqe_prev->field.cqe_next = (elm2);        \
-       _Q_INVALIDATE((elm)->field.cqe_prev);                           \
-       _Q_INVALIDATE((elm)->field.cqe_next);                           \
 } while (0)
 
+#endif /* !CIRCLEQ_HEAD */
+
+/* Required by local implementation as well as _SAFE variations. */
+#ifndef CIRCLEQ_END
+#define CIRCLEQ_END(head)       ((void *)(head))
+#endif /* !CIRCLEQ_END */
+
+#ifndef CIRCLEQ_FOREACH_SAFE
 #define        CIRCLEQ_FOREACH_SAFE(var, head, field, tvar)                    \
-    for ((var) = CIRCLEQ_FIRST(head);                          \
-        (var) != CIRCLEQ_END(head) &&                          \
-        ((tvar) = CIRCLEQ_NEXT(var, field), 1);                        \
-        (var) = (tvar))
+       for ((var) = CIRCLEQ_FIRST(head);                               \
+           (var) != CIRCLEQ_END(head) &&                               \
+           ((tvar) = CIRCLEQ_NEXT(var, field), 1);                     \
+           (var) = (tvar))
 
 #define        CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)  \
-    for ((var) = CIRCLEQ_LAST(head, headname);                 \
-        (var) != CIRCLEQ_END(head) &&                          \
-        ((tvar) = CIRCLEQ_PREV(var, headname, field), 1);              \
-        (var) = (tvar))
+       for ((var) = CIRCLEQ_LAST(head, headname);                      \
+           (var) != CIRCLEQ_END(head) &&                               \
+           ((tvar) = CIRCLEQ_PREV(var, headname, field), 1);           \
+           (var) = (tvar))
+#endif /* !CIRCLEQ_FOREACH_SAFE */
+
+/*
+ * Complete TAILQ implementation as sys/queue.h is not available on Windows
+ * and used by Suricata.
+ *
+ * This implementation copied from FreeBSD sys/queue.h.
+ */
+#ifndef TAILQ_HEAD
+
+/*
+ * Tail queue declarations.
+ */
+#define        TAILQ_HEAD(name, type)                                          \
+struct name {                                                          \
+       struct type *tqh_first; /* first element */                     \
+       struct type **tqh_last; /* addr of last next element */         \
+}
+
+#define        TAILQ_HEAD_INITIALIZER(head)                                    \
+       { NULL, &(head).tqh_first }
+
+#define        TAILQ_ENTRY(type)                                               \
+struct {                                                               \
+       struct type *tqe_next;  /* next element */                      \
+       struct type **tqe_prev; /* address of previous next element */  \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define        TAILQ_EMPTY(head)       ((head)->tqh_first == NULL)
+
+#define        TAILQ_FIRST(head)       ((head)->tqh_first)
+
+#define        TAILQ_FOREACH(var, head, field)                                 \
+       for ((var) = TAILQ_FIRST((head));                               \
+           (var);                                                      \
+           (var) = TAILQ_NEXT((var), field))
+
+#define        TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
+       for ((var) = TAILQ_LAST((head), headname);                      \
+           (var);                                                      \
+           (var) = TAILQ_PREV((var), headname, field))
+
+#define        TAILQ_INIT(head) do {                                           \
+       TAILQ_FIRST((head)) = NULL;                                     \
+       (head)->tqh_last = &TAILQ_FIRST((head));                        \
+} while (0)
+
+#define        TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
+       if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+               TAILQ_NEXT((elm), field)->field.tqe_prev =              \
+                   &TAILQ_NEXT((elm), field);                          \
+       else                                                            \
+               (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
+       TAILQ_NEXT((listelm), field) = (elm);                           \
+       (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);          \
+} while (0)
+
+#define        TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
+       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
+       TAILQ_NEXT((elm), field) = (listelm);                           \
+       *(listelm)->field.tqe_prev = (elm);                             \
+       (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);          \
+} while (0)
+
+#define        TAILQ_INSERT_HEAD(head, elm, field) do {                        \
+       if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)   \
+               TAILQ_FIRST((head))->field.tqe_prev =                   \
+                   &TAILQ_NEXT((elm), field);                          \
+       else                                                            \
+               (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
+       TAILQ_FIRST((head)) = (elm);                                    \
+       (elm)->field.tqe_prev = &TAILQ_FIRST((head));                   \
+} while (0)
+
+#define        TAILQ_INSERT_TAIL(head, elm, field) do {                        \
+       TAILQ_NEXT((elm), field) = NULL;                                \
+       (elm)->field.tqe_prev = (head)->tqh_last;                       \
+       *(head)->tqh_last = (elm);                                      \
+       (head)->tqh_last = &TAILQ_NEXT((elm), field);                   \
+} while (0)
+
+#define        TAILQ_LAST(head, headname)                                      \
+       (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define        TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define        TAILQ_PREV(elm, headname, field)                                \
+       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define        TAILQ_REMOVE(head, elm, field) do {                             \
+       if ((TAILQ_NEXT((elm), field)) != NULL)                         \
+               TAILQ_NEXT((elm), field)->field.tqe_prev =              \
+                   (elm)->field.tqe_prev;                              \
+       else                                                            \
+               (head)->tqh_last = (elm)->field.tqe_prev;               \
+       *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);              \
+} while (0)
+
+#endif /* !TAILQ_HEAD */
 
-#endif /* !_SYS_QUEUE_H_ */
+#endif /* !SURICATA_QUEUE_H */