suricata
ippair.c
Go to the documentation of this file.
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  * Information about ippairs.
24  */
25 
26 #include "suricata-common.h"
27 #include "conf.h"
28 
29 #include "util-debug.h"
30 #include "ippair.h"
31 #include "ippair-storage.h"
32 
33 #include "util-random.h"
34 #include "util-misc.h"
35 #include "util-byte.h"
36 
37 #include "ippair-queue.h"
38 
39 #include "detect-tag.h"
40 #include "detect-engine-tag.h"
42 
43 #include "util-hash-lookup3.h"
44 
45 static IPPair *IPPairGetUsedIPPair(void);
46 
47 /** ippair hash table */
48 IPPairHashRow *ippair_hash;
49 /** queue with spare ippairs */
50 static IPPairQueue ippair_spare_q;
52 SC_ATOMIC_DECLARE(uint64_t,ippair_memuse);
53 SC_ATOMIC_DECLARE(uint32_t,ippair_counter);
54 SC_ATOMIC_DECLARE(uint32_t,ippair_prune_idx);
55 
56 /** size of the ippair object. Maybe updated in IPPairInitConfig to include
57  * the storage APIs additions. */
58 static uint16_t g_ippair_size = sizeof(IPPair);
59 
60 /**
61  * \brief Update memcap value
62  *
63  * \param size new memcap value
64  */
65 int IPPairSetMemcap(uint64_t size)
66 {
67  if ((uint64_t)SC_ATOMIC_GET(ippair_memuse) < size) {
68  SC_ATOMIC_SET(ippair_config.memcap, size);
69  return 1;
70  }
71 
72  return 0;
73 }
74 
75 /**
76  * \brief Return memcap value
77  *
78  * \retval memcap value
79  */
80 uint64_t IPPairGetMemcap(void)
81 {
82  uint64_t memcapcopy = SC_ATOMIC_GET(ippair_config.memcap);
83  return memcapcopy;
84 }
85 
86 /**
87  * \brief Return memuse value
88  *
89  * \retval memuse value
90  */
91 uint64_t IPPairGetMemuse(void)
92 {
93  uint64_t memusecopy = SC_ATOMIC_GET(ippair_memuse);
94  return memusecopy;
95 }
96 
98 {
99  return IPPairQueueLen(&ippair_spare_q);
100 }
101 
103 {
104  IPPairEnqueue(&ippair_spare_q, h);
105  (void) SC_ATOMIC_SUB(ippair_counter, 1);
106 }
107 
109 {
110  if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
111  return NULL;
112  }
113 
114  (void) SC_ATOMIC_ADD(ippair_memuse, g_ippair_size);
115 
116  IPPair *h = SCMalloc(g_ippair_size);
117  if (unlikely(h == NULL))
118  goto error;
119 
120  memset(h, 0x00, g_ippair_size);
121 
122  SCMutexInit(&h->m, NULL);
123  SC_ATOMIC_INIT(h->use_cnt);
124  return h;
125 
126 error:
127  return NULL;
128 }
129 
131 {
132  if (h != NULL) {
134 
135  SC_ATOMIC_DESTROY(h->use_cnt);
136  SCMutexDestroy(&h->m);
137  SCFree(h);
138  (void) SC_ATOMIC_SUB(ippair_memuse, g_ippair_size);
139  }
140 }
141 
142 static IPPair *IPPairNew(Address *a, Address *b)
143 {
144  IPPair *p = IPPairAlloc();
145  if (p == NULL)
146  goto error;
147 
148  /* copy addresses */
149  COPY_ADDRESS(a, &p->a[0]);
150  COPY_ADDRESS(b, &p->a[1]);
151 
152  return p;
153 
154 error:
155  return NULL;
156 }
157 
159 {
160  if (IPPairStorageSize() > 0)
162 }
163 
164 #define IPPAIR_DEFAULT_HASHSIZE 4096
165 #define IPPAIR_DEFAULT_MEMCAP 16777216
166 #define IPPAIR_DEFAULT_PREALLOC 1000
167 
168 /** \brief initialize the configuration
169  * \warning Not thread safe */
170 void IPPairInitConfig(char quiet)
171 {
172  SCLogDebug("initializing ippair engine...");
173  if (IPPairStorageSize() > 0)
174  g_ippair_size = sizeof(IPPair) + IPPairStorageSize();
175 
176  memset(&ippair_config, 0, sizeof(ippair_config));
177  //SC_ATOMIC_INIT(flow_flags);
178  SC_ATOMIC_INIT(ippair_counter);
179  SC_ATOMIC_INIT(ippair_memuse);
180  SC_ATOMIC_INIT(ippair_prune_idx);
182  IPPairQueueInit(&ippair_spare_q);
183 
184  /* set defaults */
185  ippair_config.hash_rand = (uint32_t)RandomGet();
189 
190  /* Check if we have memcap and hash_size defined at config */
191  const char *conf_val;
192  uint32_t configval = 0;
193 
194  /** set config values for memcap, prealloc and hash_size */
195  uint64_t ippair_memcap;
196  if ((ConfGet("ippair.memcap", &conf_val)) == 1)
197  {
198  if (ParseSizeStringU64(conf_val, &ippair_memcap) < 0) {
199  SCLogError(SC_ERR_SIZE_PARSE, "Error parsing ippair.memcap "
200  "from conf file - %s. Killing engine",
201  conf_val);
202  exit(EXIT_FAILURE);
203  } else {
204  SC_ATOMIC_SET(ippair_config.memcap, ippair_memcap);
205  }
206  }
207  if ((ConfGet("ippair.hash-size", &conf_val)) == 1)
208  {
209  if (StringParseUint32(&configval, 10, strlen(conf_val),
210  conf_val) > 0) {
211  ippair_config.hash_size = configval;
212  }
213  }
214 
215  if ((ConfGet("ippair.prealloc", &conf_val)) == 1)
216  {
217  if (StringParseUint32(&configval, 10, strlen(conf_val),
218  conf_val) > 0) {
219  ippair_config.prealloc = configval;
220  } else {
221  WarnInvalidConfEntry("ippair.prealloc", "%"PRIu32, ippair_config.prealloc);
222  }
223  }
224  SCLogDebug("IPPair config from suricata.yaml: memcap: %"PRIu64", hash-size: "
225  "%"PRIu32", prealloc: %"PRIu32, SC_ATOMIC_GET(ippair_config.memcap),
227 
228  /* alloc hash memory */
229  uint64_t hash_size = ippair_config.hash_size * sizeof(IPPairHashRow);
230  if (!(IPPAIR_CHECK_MEMCAP(hash_size))) {
231  SCLogError(SC_ERR_IPPAIR_INIT, "allocating ippair hash failed: "
232  "max ippair memcap is smaller than projected hash size. "
233  "Memcap: %"PRIu64", Hash table size %"PRIu64". Calculate "
234  "total hash size by multiplying \"ippair.hash-size\" with %"PRIuMAX", "
235  "which is the hash bucket size.", SC_ATOMIC_GET(ippair_config.memcap), hash_size,
236  (uintmax_t)sizeof(IPPairHashRow));
237  exit(EXIT_FAILURE);
238  }
239  ippair_hash = SCMallocAligned(ippair_config.hash_size * sizeof(IPPairHashRow), CLS);
240  if (unlikely(ippair_hash == NULL)) {
241  SCLogError(SC_ERR_FATAL, "Fatal error encountered in IPPairInitConfig. Exiting...");
242  exit(EXIT_FAILURE);
243  }
244  memset(ippair_hash, 0, ippair_config.hash_size * sizeof(IPPairHashRow));
245 
246  uint32_t i = 0;
247  for (i = 0; i < ippair_config.hash_size; i++) {
249  }
250  (void) SC_ATOMIC_ADD(ippair_memuse, (ippair_config.hash_size * sizeof(IPPairHashRow)));
251 
252  if (quiet == FALSE) {
253  SCLogConfig("allocated %"PRIu64" bytes of memory for the ippair hash... "
254  "%" PRIu32 " buckets of size %" PRIuMAX "",
255  SC_ATOMIC_GET(ippair_memuse), ippair_config.hash_size,
256  (uintmax_t)sizeof(IPPairHashRow));
257  }
258 
259  /* pre allocate ippairs */
260  for (i = 0; i < ippair_config.prealloc; i++) {
261  if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
262  SCLogError(SC_ERR_IPPAIR_INIT, "preallocating ippairs failed: "
263  "max ippair memcap reached. Memcap %"PRIu64", "
264  "Memuse %"PRIu64".", SC_ATOMIC_GET(ippair_config.memcap),
265  ((uint64_t)SC_ATOMIC_GET(ippair_memuse) + g_ippair_size));
266  exit(EXIT_FAILURE);
267  }
268 
269  IPPair *h = IPPairAlloc();
270  if (h == NULL) {
271  SCLogError(SC_ERR_IPPAIR_INIT, "preallocating ippair failed: %s", strerror(errno));
272  exit(EXIT_FAILURE);
273  }
274  IPPairEnqueue(&ippair_spare_q,h);
275  }
276 
277  if (quiet == FALSE) {
278  SCLogConfig("preallocated %" PRIu32 " ippairs of size %" PRIu16 "",
279  ippair_spare_q.len, g_ippair_size);
280  SCLogConfig("ippair memory usage: %"PRIu64" bytes, maximum: %"PRIu64,
281  SC_ATOMIC_GET(ippair_memuse), SC_ATOMIC_GET(ippair_config.memcap));
282  }
283 
284  return;
285 }
286 
287 /** \brief print some ippair stats
288  * \warning Not thread safe */
289 void IPPairPrintStats (void)
290 {
291 #ifdef IPPAIRBITS_STATS
292  SCLogPerf("ippairbits added: %" PRIu32 ", removed: %" PRIu32 ", max memory usage: %" PRIu32 "",
293  ippairbits_added, ippairbits_removed, ippairbits_memuse_max);
294 #endif /* IPPAIRBITS_STATS */
295  SCLogPerf("ippair memory usage: %"PRIu64" bytes, maximum: %"PRIu64,
296  SC_ATOMIC_GET(ippair_memuse), SC_ATOMIC_GET(ippair_config.memcap));
297  return;
298 }
299 
300 /** \brief shutdown the flow engine
301  * \warning Not thread safe */
302 void IPPairShutdown(void)
303 {
304  IPPair *h;
305  uint32_t u;
306 
308 
309  /* free spare queue */
310  while((h = IPPairDequeue(&ippair_spare_q))) {
311  BUG_ON(SC_ATOMIC_GET(h->use_cnt) > 0);
312  IPPairFree(h);
313  }
314 
315  /* clear and free the hash */
316  if (ippair_hash != NULL) {
317  for (u = 0; u < ippair_config.hash_size; u++) {
318  h = ippair_hash[u].head;
319  while (h) {
320  IPPair *n = h->hnext;
321  IPPairFree(h);
322  h = n;
323  }
324 
326  }
328  ippair_hash = NULL;
329  }
330  (void) SC_ATOMIC_SUB(ippair_memuse, ippair_config.hash_size * sizeof(IPPairHashRow));
331  IPPairQueueDestroy(&ippair_spare_q);
332 
333  SC_ATOMIC_DESTROY(ippair_prune_idx);
334  SC_ATOMIC_DESTROY(ippair_memuse);
335  SC_ATOMIC_DESTROY(ippair_counter);
337  //SC_ATOMIC_DESTROY(flow_flags);
338  return;
339 }
340 
341 /** \brief Cleanup the ippair engine
342  *
343  * Cleanup the ippair engine from tag and threshold.
344  *
345  */
346 void IPPairCleanup(void)
347 {
348  IPPair *h;
349  uint32_t u;
350 
351  if (ippair_hash != NULL) {
352  for (u = 0; u < ippair_config.hash_size; u++) {
353  h = ippair_hash[u].head;
354  IPPairHashRow *hb = &ippair_hash[u];
355  HRLOCK_LOCK(hb);
356  while (h) {
357  if ((SC_ATOMIC_GET(h->use_cnt) > 0)) {
358  /* iprep is attached to ippair only clear local storage */
360  h = h->hnext;
361  } else {
362  IPPair *n = h->hnext;
363  /* remove from the hash */
364  if (h->hprev != NULL)
365  h->hprev->hnext = h->hnext;
366  if (h->hnext != NULL)
367  h->hnext->hprev = h->hprev;
368  if (hb->head == h)
369  hb->head = h->hnext;
370  if (hb->tail == h)
371  hb->tail = h->hprev;
372  h->hnext = NULL;
373  h->hprev = NULL;
376  h = n;
377  }
378  }
379  HRLOCK_UNLOCK(hb);
380  }
381  }
382 
383  return;
384 }
385 
386 /** \brief compare two raw ipv6 addrs
387  *
388  * \note we don't care about the real ipv6 ip's, this is just
389  * to consistently fill the FlowHashKey6 struct, without all
390  * the SCNtohl calls.
391  *
392  * \warning do not use elsewhere unless you know what you're doing.
393  * detect-engine-address-ipv6.c's AddressIPv6GtU32 is likely
394  * what you are looking for.
395  * Copied from FlowHashRawAddressIPv6GtU32
396  */
397 static inline int IPPairHashRawAddressIPv6GtU32(const uint32_t *a, const uint32_t *b)
398 {
399  int i;
400 
401  for (i = 0; i < 4; i++) {
402  if (a[i] > b[i])
403  return 1;
404  if (a[i] < b[i])
405  break;
406  }
407 
408  return 0;
409 }
410 
411 /* calculate the hash key for this packet
412  *
413  * we're using:
414  * hash_rand -- set at init time
415  * source address
416  */
417 static uint32_t IPPairGetKey(Address *a, Address *b)
418 {
419  uint32_t key;
420 
421  if (a->family == AF_INET) {
422  uint32_t addrs[2] = { MIN(a->addr_data32[0], b->addr_data32[0]),
423  MAX(a->addr_data32[0], b->addr_data32[0]) };
424  uint32_t hash = hashword(addrs, 2, ippair_config.hash_rand);
425  key = hash % ippair_config.hash_size;
426  } else if (a->family == AF_INET6) {
427  uint32_t addrs[8];
428  if (IPPairHashRawAddressIPv6GtU32(&a->addr_data32[0],&b->addr_data32[0])) {
429  addrs[0] = b->addr_data32[0];
430  addrs[1] = b->addr_data32[1];
431  addrs[2] = b->addr_data32[2];
432  addrs[3] = b->addr_data32[3];
433  addrs[4] = a->addr_data32[0];
434  addrs[5] = a->addr_data32[1];
435  addrs[6] = a->addr_data32[2];
436  addrs[7] = a->addr_data32[3];
437  } else {
438  addrs[0] = a->addr_data32[0];
439  addrs[1] = a->addr_data32[1];
440  addrs[2] = a->addr_data32[2];
441  addrs[3] = a->addr_data32[3];
442  addrs[4] = b->addr_data32[0];
443  addrs[5] = b->addr_data32[1];
444  addrs[6] = b->addr_data32[2];
445  addrs[7] = b->addr_data32[3];
446  }
447  uint32_t hash = hashword(addrs, 8, ippair_config.hash_rand);
448  key = hash % ippair_config.hash_size;
449  } else
450  key = 0;
451 
452  return key;
453 }
454 
455 /* Since two or more ippairs can have the same hash key, we need to compare
456  * the ippair with the current addresses. */
457 static inline int IPPairCompare(IPPair *p, Address *a, Address *b)
458 {
459  /* compare in both directions */
460  if ((CMP_ADDR(&p->a[0], a) && CMP_ADDR(&p->a[1], b)) ||
461  (CMP_ADDR(&p->a[0], b) && CMP_ADDR(&p->a[1], a)))
462  return 1;
463  return 0;
464 }
465 
466 /**
467  * \brief Get a new ippair
468  *
469  * Get a new ippair. We're checking memcap first and will try to make room
470  * if the memcap is reached.
471  *
472  * \retval h *LOCKED* ippair on succes, NULL on error.
473  */
474 static IPPair *IPPairGetNew(Address *a, Address *b)
475 {
476  IPPair *h = NULL;
477 
478  /* get a ippair from the spare queue */
479  h = IPPairDequeue(&ippair_spare_q);
480  if (h == NULL) {
481  /* If we reached the max memcap, we get a used ippair */
482  if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
483  /* declare state of emergency */
484  //if (!(SC_ATOMIC_GET(ippair_flags) & IPPAIR_EMERGENCY)) {
485  // SC_ATOMIC_OR(ippair_flags, IPPAIR_EMERGENCY);
486 
487  /* under high load, waking up the flow mgr each time leads
488  * to high cpu usage. Flows are not timed out much faster if
489  * we check a 1000 times a second. */
490  // FlowWakeupFlowManagerThread();
491  //}
492 
493  h = IPPairGetUsedIPPair();
494  if (h == NULL) {
495  return NULL;
496  }
497 
498  /* freed a ippair, but it's unlocked */
499  } else {
500  /* now see if we can alloc a new ippair */
501  h = IPPairNew(a,b);
502  if (h == NULL) {
503  return NULL;
504  }
505 
506  /* ippair is initialized but *unlocked* */
507  }
508  } else {
509  /* ippair has been recycled before it went into the spare queue */
510 
511  /* ippair is initialized (recylced) but *unlocked* */
512  }
513 
514  (void) SC_ATOMIC_ADD(ippair_counter, 1);
515  SCMutexLock(&h->m);
516  return h;
517 }
518 
519 static void IPPairInit(IPPair *h, Address *a, Address *b)
520 {
521  COPY_ADDRESS(a, &h->a[0]);
522  COPY_ADDRESS(b, &h->a[1]);
523  (void) IPPairIncrUsecnt(h);
524 }
525 
527 {
528  (void) IPPairDecrUsecnt(h);
529  SCMutexUnlock(&h->m);
530 }
531 
533 {
534  SCMutexLock(&h->m);
535 }
536 
538 {
539  SCMutexUnlock(&h->m);
540 }
541 
542 /* IPPairGetIPPairFromHash
543  *
544  * Hash retrieval function for ippairs. Looks up the hash bucket containing the
545  * ippair pointer. Then compares the packet with the found ippair to see if it is
546  * the ippair we need. If it isn't, walk the list until the right ippair is found.
547  *
548  * returns a *LOCKED* ippair or NULL
549  */
551 {
552  IPPair *h = NULL;
553 
554  /* get the key to our bucket */
555  uint32_t key = IPPairGetKey(a, b);
556  /* get our hash bucket and lock it */
557  IPPairHashRow *hb = &ippair_hash[key];
558  HRLOCK_LOCK(hb);
559 
560  /* see if the bucket already has a ippair */
561  if (hb->head == NULL) {
562  h = IPPairGetNew(a,b);
563  if (h == NULL) {
564  HRLOCK_UNLOCK(hb);
565  return NULL;
566  }
567 
568  /* ippair is locked */
569  hb->head = h;
570  hb->tail = h;
571 
572  /* got one, now lock, initialize and return */
573  IPPairInit(h,a,b);
574 
575  HRLOCK_UNLOCK(hb);
576  return h;
577  }
578 
579  /* ok, we have a ippair in the bucket. Let's find out if it is our ippair */
580  h = hb->head;
581 
582  /* see if this is the ippair we are looking for */
583  if (IPPairCompare(h, a, b) == 0) {
584  IPPair *ph = NULL; /* previous ippair */
585 
586  while (h) {
587  ph = h;
588  h = h->hnext;
589 
590  if (h == NULL) {
591  h = ph->hnext = IPPairGetNew(a,b);
592  if (h == NULL) {
593  HRLOCK_UNLOCK(hb);
594  return NULL;
595  }
596  hb->tail = h;
597 
598  /* ippair is locked */
599 
600  h->hprev = ph;
601 
602  /* initialize and return */
603  IPPairInit(h,a,b);
604 
605  HRLOCK_UNLOCK(hb);
606  return h;
607  }
608 
609  if (IPPairCompare(h, a, b) != 0) {
610  /* we found our ippair, lets put it on top of the
611  * hash list -- this rewards active ippairs */
612  if (h->hnext) {
613  h->hnext->hprev = h->hprev;
614  }
615  if (h->hprev) {
616  h->hprev->hnext = h->hnext;
617  }
618  if (h == hb->tail) {
619  hb->tail = h->hprev;
620  }
621 
622  h->hnext = hb->head;
623  h->hprev = NULL;
624  hb->head->hprev = h;
625  hb->head = h;
626 
627  /* found our ippair, lock & return */
628  SCMutexLock(&h->m);
629  (void) IPPairIncrUsecnt(h);
630  HRLOCK_UNLOCK(hb);
631  return h;
632  }
633  }
634  }
635 
636  /* lock & return */
637  SCMutexLock(&h->m);
638  (void) IPPairIncrUsecnt(h);
639  HRLOCK_UNLOCK(hb);
640  return h;
641 }
642 
643 /** \brief look up a ippair in the hash
644  *
645  * \param a address to look up
646  *
647  * \retval h *LOCKED* ippair or NULL
648  */
650 {
651  IPPair *h = NULL;
652 
653  /* get the key to our bucket */
654  uint32_t key = IPPairGetKey(a, b);
655  /* get our hash bucket and lock it */
656  IPPairHashRow *hb = &ippair_hash[key];
657  HRLOCK_LOCK(hb);
658 
659  /* see if the bucket already has a ippair */
660  if (hb->head == NULL) {
661  HRLOCK_UNLOCK(hb);
662  return h;
663  }
664 
665  /* ok, we have a ippair in the bucket. Let's find out if it is our ippair */
666  h = hb->head;
667 
668  /* see if this is the ippair we are looking for */
669  if (IPPairCompare(h, a, b) == 0) {
670  while (h) {
671  h = h->hnext;
672 
673  if (h == NULL) {
674  HRLOCK_UNLOCK(hb);
675  return h;
676  }
677 
678  if (IPPairCompare(h, a, b) != 0) {
679  /* we found our ippair, lets put it on top of the
680  * hash list -- this rewards active ippairs */
681  if (h->hnext) {
682  h->hnext->hprev = h->hprev;
683  }
684  if (h->hprev) {
685  h->hprev->hnext = h->hnext;
686  }
687  if (h == hb->tail) {
688  hb->tail = h->hprev;
689  }
690 
691  h->hnext = hb->head;
692  h->hprev = NULL;
693  hb->head->hprev = h;
694  hb->head = h;
695 
696  /* found our ippair, lock & return */
697  SCMutexLock(&h->m);
698  (void) IPPairIncrUsecnt(h);
699  HRLOCK_UNLOCK(hb);
700  return h;
701  }
702  }
703  }
704 
705  /* lock & return */
706  SCMutexLock(&h->m);
707  (void) IPPairIncrUsecnt(h);
708  HRLOCK_UNLOCK(hb);
709  return h;
710 }
711 
712 /** \internal
713  * \brief Get a ippair from the hash directly.
714  *
715  * Called in conditions where the spare queue is empty and memcap is reached.
716  *
717  * Walks the hash until a ippair can be freed. "ippair_prune_idx" atomic int makes
718  * sure we don't start at the top each time since that would clear the top of
719  * the hash leading to longer and longer search times under high pressure (observed).
720  *
721  * \retval h ippair or NULL
722  */
723 static IPPair *IPPairGetUsedIPPair(void)
724 {
725  uint32_t idx = SC_ATOMIC_GET(ippair_prune_idx) % ippair_config.hash_size;
726  uint32_t cnt = ippair_config.hash_size;
727 
728  while (cnt--) {
729  if (++idx >= ippair_config.hash_size)
730  idx = 0;
731 
732  IPPairHashRow *hb = &ippair_hash[idx];
733 
734  if (HRLOCK_TRYLOCK(hb) != 0)
735  continue;
736 
737  IPPair *h = hb->tail;
738  if (h == NULL) {
739  HRLOCK_UNLOCK(hb);
740  continue;
741  }
742 
743  if (SCMutexTrylock(&h->m) != 0) {
744  HRLOCK_UNLOCK(hb);
745  continue;
746  }
747 
748  /** never prune a ippair that is used by a packets
749  * we are currently processing in one of the threads */
750  if (SC_ATOMIC_GET(h->use_cnt) > 0) {
751  HRLOCK_UNLOCK(hb);
752  SCMutexUnlock(&h->m);
753  continue;
754  }
755 
756  /* remove from the hash */
757  if (h->hprev != NULL)
758  h->hprev->hnext = h->hnext;
759  if (h->hnext != NULL)
760  h->hnext->hprev = h->hprev;
761  if (hb->head == h)
762  hb->head = h->hnext;
763  if (hb->tail == h)
764  hb->tail = h->hprev;
765 
766  h->hnext = NULL;
767  h->hprev = NULL;
768  HRLOCK_UNLOCK(hb);
769 
770  IPPairClearMemory (h);
771 
772  SCMutexUnlock(&h->m);
773 
774  (void) SC_ATOMIC_ADD(ippair_prune_idx, (ippair_config.hash_size - cnt));
775  return h;
776  }
777 
778  return NULL;
779 }
780 
782 {
784 }
HRLOCK_DESTROY
#define HRLOCK_DESTROY(fb)
Definition: host.h:50
util-byte.h
SC_ERR_IPPAIR_INIT
@ SC_ERR_IPPAIR_INIT
Definition: util-error.h:298
ippair.h
IPPairQueue_::len
uint32_t len
Definition: ippair-queue.h:45
SC_ATOMIC_DESTROY
#define SC_ATOMIC_DESTROY(name)
Destroy the lock used to protect this variable.
Definition: util-atomic.h:97
hashword
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval)
Definition: util-hash-lookup3.c:174
IPPAIR_DEFAULT_HASHSIZE
#define IPPAIR_DEFAULT_HASHSIZE
Definition: ippair.c:164
IPPairQueueLen
uint32_t IPPairQueueLen(IPPairQueue *q)
Definition: ippair-queue.c:136
IPPair_::a
Address a[2]
Definition: ippair.h:63
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it's lock.
Definition: util-atomic.h:81
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(uint64_t, ippair_memuse)
IPPairRelease
void IPPairRelease(IPPair *h)
Definition: ippair.c:526
CLS
#define CLS
Definition: suricata-common.h:45
IPPAIR_DEFAULT_PREALLOC
#define IPPAIR_DEFAULT_PREALLOC
Definition: ippair.c:166
SCFree
#define SCFree(a)
Definition: util-mem.h:322
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:207
IPPairIncrUsecnt
#define IPPairIncrUsecnt(h)
Definition: ippair.h:109
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:335
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:203
SCFreeAligned
#define SCFreeAligned(a)
Free aligned memory.
Definition: util-mem.h:388
IPPairQueueInit
IPPairQueue * IPPairQueueInit(IPPairQueue *q)
Definition: ippair-queue.c:34
IPPairRegisterUnittests
void IPPairRegisterUnittests(void)
Definition: ippair.c:781
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:107
IPPAIR_CHECK_MEMCAP
#define IPPAIR_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
Definition: ippair.h:106
IPPairDecrUsecnt
#define IPPairDecrUsecnt(h)
Definition: ippair.h:111
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
MIN
#define MIN(x, y)
Definition: suricata-common.h:360
Address_
Definition: decode.h:111
IPPairDequeue
IPPair * IPPairDequeue(IPPairQueue *q)
remove a ippair from the queue
Definition: ippair-queue.c:103
RandomGet
long int RandomGet(void)
Definition: util-random.c:129
IPPairAlloc
IPPair * IPPairAlloc(void)
Definition: ippair.c:108
detect-tag.h
IPPairMoveToSpare
void IPPairMoveToSpare(IPPair *h)
Definition: ippair.c:102
MAX
#define MAX(x, y)
Definition: suricata-common.h:364
IPPairStorageSize
unsigned int IPPairStorageSize(void)
Definition: ippair-storage.c:30
IPPair_::m
SCMutex m
Definition: ippair.h:60
HRLOCK_LOCK
#define HRLOCK_LOCK(fb)
Definition: host.h:51
IPPairFree
void IPPairFree(IPPair *h)
Definition: ippair.c:130
IPPairShutdown
void IPPairShutdown(void)
shutdown the flow engine
Definition: ippair.c:302
IPPairConfig_::prealloc
uint32_t prealloc
Definition: ippair.h:96
SC_ERR_SIZE_PARSE
@ SC_ERR_SIZE_PARSE
Definition: util-error.h:230
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
HRLOCK_UNLOCK
#define HRLOCK_UNLOCK(fb)
Definition: host.h:53
util-debug.h
ippair_config
IPPairConfig ippair_config
Definition: ippair.c:51
IPPairCleanup
void IPPairCleanup(void)
Cleanup the ippair engine.
Definition: ippair.c:346
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
IPPairGetMemcap
uint64_t IPPairGetMemcap(void)
Return memcap value.
Definition: ippair.c:80
IPPairGetIPPairFromHash
IPPair * IPPairGetIPPairFromHash(Address *a, Address *b)
Definition: ippair.c:550
IPPairEnqueue
void IPPairEnqueue(IPPairQueue *q, IPPair *h)
add a ippair to a queue
Definition: ippair-queue.c:70
IPPairInitConfig
void IPPairInitConfig(char quiet)
initialize the configuration
Definition: ippair.c:170
SCMalloc
#define SCMalloc(a)
Definition: util-mem.h:222
IPPairLock
void IPPairLock(IPPair *h)
Definition: ippair.c:532
IPPairQueue_
Definition: ippair-queue.h:41
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:265
IPPAIR_DEFAULT_MEMCAP
#define IPPAIR_DEFAULT_MEMCAP
Definition: ippair.c:165
detect-engine-tag.h
IPPairUnlock
void IPPairUnlock(IPPair *h)
Definition: ippair.c:537
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:124
FALSE
#define FALSE
Definition: suricata-common.h:34
conf.h
HRLOCK_INIT
#define HRLOCK_INIT(fb)
Definition: host.h:49
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
WarnInvalidConfEntry
#define WarnInvalidConfEntry(param_name, format, value)
Generic API that can be used by all to log an invalid conf entry.
Definition: util-misc.h:37
IPPairSpareQueueGetSize
uint32_t IPPairSpareQueueGetSize(void)
Definition: ippair.c:97
StringParseUint32
int StringParseUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:304
CMP_ADDR
#define CMP_ADDR(a1, a2)
Definition: decode.h:240
suricata-common.h
RegisterIPPairStorageTests
void RegisterIPPairStorageTests(void)
Definition: ippair-storage.c:292
IPPair_
Definition: ippair.h:58
IPPairConfig_::hash_size
uint32_t hash_size
Definition: ippair.h:95
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:261
IPPairGetMemuse
uint64_t IPPairGetMemuse(void)
Return memuse value.
Definition: ippair.c:91
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
IPPairClearMemory
void IPPairClearMemory(IPPair *h)
Definition: ippair.c:158
util-hash-lookup3.h
IPPair_::hprev
struct IPPair_ * hprev
Definition: ippair.h:73
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
IPPairConfig_
Definition: ippair.h:92
IPPair_::hnext
struct IPPair_ * hnext
Definition: ippair.h:72
ippair-queue.h
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
SCMallocAligned
#define SCMallocAligned(a, b)
wrapper for allocing aligned mem
Definition: util-mem.h:363
util-random.h
HRLOCK_TRYLOCK
#define HRLOCK_TRYLOCK(fb)
Definition: host.h:52
IPPairQueueDestroy
void IPPairQueueDestroy(IPPairQueue *q)
Destroy a ippair queue.
Definition: ippair-queue.c:59
IPPairSetMemcap
int IPPairSetMemcap(uint64_t size)
Update memcap value.
Definition: ippair.c:65
Address_::family
char family
Definition: decode.h:112
IPPairLookupIPPairFromHash
IPPair * IPPairLookupIPPairFromHash(Address *a, Address *b)
look up a ippair in the hash
Definition: ippair.c:649
IPPairFreeStorage
void IPPairFreeStorage(IPPair *h)
Definition: ippair-storage.c:55
IPPair
struct IPPair_ IPPair
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:192
util-misc.h
COPY_ADDRESS
#define COPY_ADDRESS(a, b)
Definition: decode.h:126
IPPairConfig_::hash_rand
uint32_t hash_rand
Definition: ippair.h:94
ippair-storage.h
ippair_hash
IPPairHashRow * ippair_hash
Definition: ippair.c:48
SCMutexDestroy
#define SCMutexDestroy
Definition: threads-debug.h:120
IPPairPrintStats
void IPPairPrintStats(void)
print some ippair stats
Definition: ippair.c:289
SCMutexTrylock
#define SCMutexTrylock(mut)
Definition: threads-debug.h:118
detect-engine-threshold.h