1 /* Copyright (C) 2007-2012 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Defrag tracker queue handler functions
24  */
25 
26 #include "suricata-common.h"
27 #include "threads.h"
28 #include "debug.h"
29 #include "defrag-queue.h"
30 #include "util-error.h"
31 #include "util-debug.h"
32 #include "util-print.h"
33 
DefragTrackerQueueInit(DefragTrackerQueue * q)34 DefragTrackerQueue *DefragTrackerQueueInit (DefragTrackerQueue *q)
35 {
36     if (q != NULL) {
37         memset(q, 0, sizeof(DefragTrackerQueue));
38         DQLOCK_INIT(q);
39     }
40     return q;
41 }
42 
DefragTrackerQueueNew()43 DefragTrackerQueue *DefragTrackerQueueNew()
44 {
45     DefragTrackerQueue *q = (DefragTrackerQueue *)SCMalloc(sizeof(DefragTrackerQueue));
46     if (q == NULL) {
47         SCLogError(SC_ERR_FATAL, "Fatal error encountered in DefragTrackerQueueNew. Exiting...");
48         exit(EXIT_SUCCESS);
49     }
50     q = DefragTrackerQueueInit(q);
51     return q;
52 }
53 
54 /**
55  *  \brief Destroy a tracker queue
56  *
57  *  \param q the tracker queue to destroy
58  */
DefragTrackerQueueDestroy(DefragTrackerQueue * q)59 void DefragTrackerQueueDestroy (DefragTrackerQueue *q)
60 {
61     DQLOCK_DESTROY(q);
62 }
63 
64 /**
65  *  \brief add a tracker to a queue
66  *
67  *  \param q queue
68  *  \param dt tracker
69  */
DefragTrackerEnqueue(DefragTrackerQueue * q,DefragTracker * dt)70 void DefragTrackerEnqueue (DefragTrackerQueue *q, DefragTracker *dt)
71 {
72 #ifdef DEBUG
73     BUG_ON(q == NULL || dt == NULL);
74 #endif
75 
76     DQLOCK_LOCK(q);
77 
78     /* more trackers in queue */
79     if (q->top != NULL) {
80         dt->lnext = q->top;
81         q->top->lprev = dt;
82         q->top = dt;
83     /* only tracker */
84     } else {
85         q->top = dt;
86         q->bot = dt;
87     }
88     q->len++;
89 #ifdef DBG_PERF
90     if (q->len > q->dbg_maxlen)
91         q->dbg_maxlen = q->len;
92 #endif /* DBG_PERF */
93     DQLOCK_UNLOCK(q);
94 }
95 
96 /**
97  *  \brief remove a tracker from the queue
98  *
99  *  \param q queue
100  *
101  *  \retval dt tracker or NULL if empty list.
102  */
DefragTrackerDequeue(DefragTrackerQueue * q)103 DefragTracker *DefragTrackerDequeue (DefragTrackerQueue *q)
104 {
105     DQLOCK_LOCK(q);
106 
107     DefragTracker *dt = q->bot;
108     if (dt == NULL) {
109         DQLOCK_UNLOCK(q);
110         return NULL;
111     }
112 
113     /* more packets in queue */
114     if (q->bot->lprev != NULL) {
115         q->bot = q->bot->lprev;
116         q->bot->lnext = NULL;
117     /* just the one we remove, so now empty */
118     } else {
119         q->top = NULL;
120         q->bot = NULL;
121     }
122 
123 #ifdef DEBUG
124     BUG_ON(q->len == 0);
125 #endif
126     if (q->len > 0)
127         q->len--;
128 
129     dt->lnext = NULL;
130     dt->lprev = NULL;
131 
132     DQLOCK_UNLOCK(q);
133     return dt;
134 }
135 
DefragTrackerQueueLen(DefragTrackerQueue * q)136 uint32_t DefragTrackerQueueLen(DefragTrackerQueue *q)
137 {
138     uint32_t len;
139     DQLOCK_LOCK(q);
140     len = q->len;
141     DQLOCK_UNLOCK(q);
142     return len;
143 }
144 
145