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