suricata
app-layer-htp-range.c
Go to the documentation of this file.
1 /* Copyright (C) 2021 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 Philippe Antoine <p.antoine@catenacyber.fr>
22  */
23 
24 #include "suricata-common.h"
25 #include "app-layer-htp-range.h"
26 #include "util-misc.h" //ParseSizeStringU64
27 #include "util-thash.h" //HashTable
28 #include "util-memcmp.h" //SCBufferCmp
29 #include "util-hash-string.h" //StringHashDjb2
30 #include "util-validate.h" //DEBUG_VALIDATE_BUG_ON
31 #include "util-byte.h" //StringParseUint32
32 
33 typedef struct ContainerTHashTable {
35  uint32_t timeout;
37 
38 // globals
40 
41 static void HttpRangeBlockDerefContainer(HttpRangeContainerBlock *b);
42 
43 #define CONTAINER_URLRANGE_HASH_SIZE 256
44 
46 {
47  // lexical order : start, buflen, offset
48  if (a->start > b->start)
49  return 1;
50  if (a->start < b->start)
51  return -1;
52  if (a->buflen > b->buflen)
53  return 1;
54  if (a->buflen < b->buflen)
55  return -1;
56  if (a->offset > b->offset)
57  return 1;
58  if (a->offset < b->offset)
59  return -1;
60  return 0;
61 }
62 
64 
65 static int ContainerUrlRangeSet(void *dst, void *src)
66 {
67  HttpRangeContainerFile *src_s = src;
68  HttpRangeContainerFile *dst_s = dst;
69  dst_s->len = src_s->len;
70  dst_s->key = SCMalloc(dst_s->len);
71  if (dst_s->key == NULL)
72  return -1;
73  memcpy(dst_s->key, src_s->key, dst_s->len);
74  dst_s->files = FileContainerAlloc();
75  if (dst_s->files == NULL) {
76  SCFree(dst_s->key);
77  return -1;
78  }
79  RB_INIT(&dst_s->fragment_tree);
80  dst_s->flags = 0;
81  dst_s->lastsize = 0;
82  dst_s->totalsize = 0;
83  dst_s->hdata = NULL;
84  dst_s->error = false;
85  return 0;
86 }
87 
88 static bool ContainerUrlRangeCompare(void *a, void *b)
89 {
90  const HttpRangeContainerFile *as = a;
91  const HttpRangeContainerFile *bs = b;
92 
93  /* ranges in the error state should not be found so they can
94  * be evicted */
95  if (as->error || bs->error) {
96  return false;
97  }
98 
99  if (SCBufferCmp(as->key, as->len, bs->key, bs->len) == 0) {
100  return true;
101  }
102  return false;
103 }
104 
105 static uint32_t ContainerUrlRangeHash(void *s)
106 {
107  HttpRangeContainerFile *cur = s;
108  uint32_t h = StringHashDjb2(cur->key, cur->len);
109  return h;
110 }
111 
112 // base data stays in hash
113 static void ContainerUrlRangeFree(void *s)
114 {
115  HttpRangeContainerBuffer *range = NULL, *tmp = NULL;
116 
117  HttpRangeContainerFile *cu = s;
118  SCFree(cu->key);
119  cu->key = NULL;
120  FileContainerFree(cu->files, cu->sbcfg);
121  cu->files = NULL;
122  RB_FOREACH_SAFE (range, HTTP_RANGES, &cu->fragment_tree, tmp) {
123  RB_REMOVE(HTTP_RANGES, &cu->fragment_tree, range);
124  SCFree(range->buffer);
125  (void)SC_ATOMIC_SUB(ContainerUrlRangeList.ht->memuse, range->buflen);
126  SCFree(range);
127  }
128 }
129 
130 static inline bool ContainerValueRangeTimeout(HttpRangeContainerFile *cu, const SCTime_t ts)
131 {
132  // we only timeout if we have no flow referencing us
133  if ((uint32_t)SCTIME_SECS(ts) > cu->expire || cu->error) {
134  if (SC_ATOMIC_GET(cu->hdata->use_cnt) == 0) {
135  DEBUG_VALIDATE_BUG_ON(cu->files == NULL);
136  return true;
137  }
138  }
139  return false;
140 }
141 
142 static void ContainerUrlRangeUpdate(HttpRangeContainerFile *cu, uint32_t expire)
143 {
144  cu->expire = expire;
145 }
146 
147 #define HTTP_RANGE_DEFAULT_TIMEOUT 60
148 #define HTTP_RANGE_DEFAULT_MEMCAP 100 * 1024 * 1024
149 
151 {
152  SCLogDebug("containers start");
153  const char *str = NULL;
154  uint64_t memcap = HTTP_RANGE_DEFAULT_MEMCAP;
155  uint32_t timeout = HTTP_RANGE_DEFAULT_TIMEOUT;
156  if (ConfGet("app-layer.protocols.http.byterange.memcap", &str) == 1) {
157  if (ParseSizeStringU64(str, &memcap) < 0) {
158  SCLogWarning("memcap value cannot be deduced: %s,"
159  " resetting to default",
160  str);
161  memcap = 0;
162  }
163  }
164  if (ConfGet("app-layer.protocols.http.byterange.timeout", &str) == 1) {
165  size_t slen = strlen(str);
166  if (slen > UINT16_MAX || StringParseUint32(&timeout, 10, (uint16_t)slen, str) <= 0) {
167  SCLogWarning("timeout value cannot be deduced: %s,"
168  " resetting to default",
169  str);
170  timeout = 0;
171  }
172  }
173 
175  THashInit("app-layer.protocols.http.byterange", sizeof(HttpRangeContainerFile),
176  ContainerUrlRangeSet, ContainerUrlRangeFree, ContainerUrlRangeHash,
177  ContainerUrlRangeCompare, false, memcap, CONTAINER_URLRANGE_HASH_SIZE);
178  ContainerUrlRangeList.timeout = timeout;
179 
180  SCLogDebug("containers started");
181 }
182 
184 {
186 }
187 
189 {
190  SCLogDebug("timeout: starting");
191  uint32_t cnt = 0;
192 
193  for (uint32_t i = 0; i < ContainerUrlRangeList.ht->config.hash_size; i++) {
194  THashHashRow *hb = &ContainerUrlRangeList.ht->array[i];
195 
196  if (HRLOCK_TRYLOCK(hb) != 0)
197  continue;
198  /* hash bucket is now locked */
199  THashData *h = hb->head;
200  while (h) {
201  DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(h->use_cnt) > (uint32_t)INT_MAX);
202  THashData *n = h->next;
203  THashDataLock(h);
204  if (ContainerValueRangeTimeout(h->data, ts)) {
205  /* remove from the hash */
206  if (h->prev != NULL)
207  h->prev->next = h->next;
208  if (h->next != NULL)
209  h->next->prev = h->prev;
210  if (hb->head == h)
211  hb->head = h->next;
212  if (hb->tail == h)
213  hb->tail = h->prev;
214  h->next = NULL;
215  h->prev = NULL;
216  // we should log the timed out file somehow...
217  // but it does not belong to any flow...
218  SCLogDebug("timeout: removing range %p", h);
219  ContainerUrlRangeFree(h->data); // TODO do we need a "RECYCLE" func?
220  DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(h->use_cnt) > (uint32_t)INT_MAX);
221  THashDataUnlock(h);
223  } else {
224  THashDataUnlock(h);
225  }
226  h = n;
227  }
228  HRLOCK_UNLOCK(hb);
229  }
230 
231  SCLogDebug("timeout: ending");
232  return cnt;
233 }
234 
235 /**
236  * \returns locked data
237  */
238 static void *HttpRangeContainerUrlGet(const uint8_t *key, uint32_t keylen, const Flow *f)
239 {
240  const SCTime_t ts = f->lastts;
241  HttpRangeContainerFile lookup;
242  memset(&lookup, 0, sizeof(lookup));
243  // cast so as not to have const in the structure
244  lookup.key = (uint8_t *)key;
245  lookup.len = keylen;
247  if (res.data) {
248  // nothing more to do if (res.is_new)
249  ContainerUrlRangeUpdate(res.data->data, SCTIME_SECS(ts) + ContainerUrlRangeList.timeout);
250  HttpRangeContainerFile *c = res.data->data;
251  c->hdata = res.data;
252  SCLogDebug("c %p", c);
253  return res.data->data;
254  }
255  return NULL;
256 }
257 
258 static HttpRangeContainerBlock *HttpRangeOpenFileAux(HttpRangeContainerFile *c, uint64_t start,
259  uint64_t end, uint64_t total, const StreamingBufferConfig *sbcfg, const uint8_t *name,
260  uint16_t name_len, uint16_t flags)
261 {
262  if (c->files != NULL && c->files->tail == NULL) {
263  /* this is the first request, we open a single file in the file container
264  * this could be part of ContainerUrlRangeSet if we could have
265  * all the arguments there
266  */
267  if (FileOpenFileWithId(c->files, sbcfg, 0, name, name_len, NULL, 0, flags) != 0) {
268  SCLogDebug("open file for range failed");
269  return NULL;
270  }
271  }
273  if (curf == NULL) {
274  c->error = true;
275  return NULL;
276  }
277  curf->files = NULL;
278  if (total > c->totalsize) {
279  // we grow to the maximum size indicated by different range requests
280  // we could add some warning/app-layer event in this case where
281  // different range requests indicate different total sizes
282  c->totalsize = total;
283  }
284  const uint64_t buflen = end - start + 1;
285 
286  /* The big part of this function is now to decide which kind of HttpRangeContainerBlock
287  * we will return :
288  * - skipping already processed data
289  * - storing out of order data for later use
290  * - directly appending to the file if we are at the right offset
291  */
292  if (start == c->lastsize && c->files != NULL) {
293  // easy case : append to current file
294  curf->container = c;
295  // If we see 2 duplicate range requests with the same range,
296  // the first one takes the ownership of the files container
297  // protected by the lock from caller HTPFileOpenWithRange
298  curf->files = c->files;
299  c->files = NULL;
300  return curf;
301  } else if (start < c->lastsize && c->lastsize - start >= buflen) {
302  // only overlap
303  // redundant to be explicit that this block is independent
304  curf->toskip = buflen;
305  return curf;
306  } else if (start < c->lastsize && c->lastsize - start < buflen && c->files != NULL) {
307  // some overlap, then some data to append to the file
308  curf->toskip = c->lastsize - start;
309  curf->files = c->files;
310  c->files = NULL;
311  curf->container = c;
312  return curf;
313  }
314  // Because we are not in the previous cases, we will store the data for later use
315 
316  // block/range to be inserted in ordered linked list
317  if (!(THASH_CHECK_MEMCAP(ContainerUrlRangeList.ht, buflen))) {
318  // skips this range
319  curf->toskip = buflen;
320  return curf;
321  }
322  curf->container = c;
323 
325  if (range == NULL) {
326  c->error = true;
327  SCFree(curf);
328  return NULL;
329  }
330 
331  (void)SC_ATOMIC_ADD(ContainerUrlRangeList.ht->memuse, buflen);
332  range->buffer = SCMalloc(buflen);
333  if (range->buffer == NULL) {
334  c->error = true;
335  SCFree(curf);
336  SCFree(range);
337  (void)SC_ATOMIC_SUB(ContainerUrlRangeList.ht->memuse, buflen);
338  return NULL;
339  }
340  range->buflen = buflen;
341  range->start = start;
342  range->offset = 0;
343  range->gap = 0;
344  curf->current = range;
345  return curf;
346 }
347 
348 static HttpRangeContainerBlock *HttpRangeOpenFile(HttpRangeContainerFile *c, uint64_t start,
349  uint64_t end, uint64_t total, const StreamingBufferConfig *sbcfg, const uint8_t *name,
350  uint16_t name_len, uint16_t flags, const uint8_t *data, uint32_t len)
351 {
353  HttpRangeOpenFileAux(c, start, end, total, sbcfg, name, name_len, flags);
354  if (HttpRangeAppendData(sbcfg, r, data, len) < 0) {
355  SCLogDebug("Failed to append data while opening");
356  }
357  return r;
358 }
359 
360 HttpRangeContainerBlock *HttpRangeContainerOpenFile(const uint8_t *key, uint32_t keylen,
361  const Flow *f, const HTTPContentRange *crparsed, const StreamingBufferConfig *sbcfg,
362  const uint8_t *name, uint16_t name_len, uint16_t flags, const uint8_t *data,
363  uint32_t data_len)
364 {
365  HttpRangeContainerFile *file_range_container = HttpRangeContainerUrlGet(key, keylen, f);
366  if (file_range_container == NULL) {
367  // probably reached memcap
368  return NULL;
369  }
370  file_range_container->sbcfg = sbcfg;
371 
372  HttpRangeContainerBlock *r = HttpRangeOpenFile(file_range_container, crparsed->start,
373  crparsed->end, crparsed->size, sbcfg, name, name_len, flags, data, data_len);
374  SCLogDebug("s->file_range == %p", r);
375  if (r == NULL) {
376  THashDecrUsecnt(file_range_container->hdata);
378  SC_ATOMIC_GET(file_range_container->hdata->use_cnt) > (uint32_t)INT_MAX);
379  THashDataUnlock(file_range_container->hdata);
380 
381  // probably reached memcap
382  return NULL;
383  /* in some cases we don't take a reference, so decr use cnt */
384  } else if (r->container == NULL) {
385  THashDecrUsecnt(file_range_container->hdata);
386  } else {
387  SCLogDebug("container %p use_cnt %u", r, SC_ATOMIC_GET(r->container->hdata->use_cnt));
388  DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(r->container->hdata->use_cnt) > (uint32_t)INT_MAX);
389  }
390 
391  /* we're done, so unlock. But since we have a reference in s->file_range keep use_cnt. */
392  THashDataUnlock(file_range_container->hdata);
393  return r;
394 }
395 
397  const uint8_t *data, uint32_t len)
398 {
399  if (len == 0) {
400  return 0;
401  }
402  // first check if we need to skip all bytes
403  if (c->toskip >= len) {
404  c->toskip -= len;
405  return 0;
406  }
407  // then if we need to skip only some bytes
408  if (c->toskip > 0) {
409  int r = 0;
410  if (c->files) {
411  if (data == NULL) {
412  // gap overlapping already known data
413  r = FileAppendData(c->files, sbcfg, NULL, len - c->toskip);
414  } else {
415  r = FileAppendData(c->files, sbcfg, data + c->toskip, len - c->toskip);
416  }
417  }
418  c->toskip = 0;
419  return r;
420  }
421  // If we are owning the file to append to it, let's do it
422  if (c->files) {
423  SCLogDebug("update files (FileAppendData)");
424  return FileAppendData(c->files, sbcfg, data, len);
425  }
426  // Maybe we were in the skipping case,
427  // but we get more data than expected and had set c->toskip = 0
428  // so we need to check for last case with something to do
429  if (c->current) {
430  // So we have a current allocated buffer to copy to
431  // in the case of an unordered range being handled
432  SCLogDebug("update current: adding %u bytes to block %p", len, c);
433  // GAP "data"
434  if (data == NULL) {
435  // just save the length of the gap
436  c->current->gap += len;
437  // data, but we're not yet complete
438  } else if (c->current->offset + len < c->current->buflen) {
439  memcpy(c->current->buffer + c->current->offset, data, len);
440  c->current->offset += len;
441  // data, we're complete
442  } else if (c->current->offset + len == c->current->buflen) {
443  memcpy(c->current->buffer + c->current->offset, data, len);
444  c->current->offset += len;
445  // data, more than expected
446  } else {
447  memcpy(c->current->buffer + c->current->offset, data,
448  c->current->buflen - c->current->offset);
449  c->current->offset = c->current->buflen;
450  }
451  }
452  return 0;
453 }
454 
455 static void HttpRangeFileClose(
456  const StreamingBufferConfig *sbcfg, HttpRangeContainerFile *c, uint16_t flags)
457 {
458  SCLogDebug("closing range %p flags %04x", c, flags);
459  DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(c->hdata->use_cnt) == 0);
460  // move ownership of file c->files->head to caller
461  FileCloseFile(c->files, sbcfg, NULL, 0, c->flags | flags);
462  c->files->head = NULL;
463  c->files->tail = NULL;
464 }
465 
466 /**
467  * \note if `f` is non-NULL, the ownership of the file is transferred to the caller.
468  */
470 {
471  SCLogDebug("c %p c->container %p c->current %p", c, c->container, c->current);
472 
473  DEBUG_VALIDATE_BUG_ON(c->container == NULL);
474 
475  /* we're processing an OOO chunk, won't be able to get us a full file just yet */
476  if (c->current) {
477  SCLogDebug("processing ooo chunk as c->current is set %p", c->current);
478  // some out-or-order range is finished
479  if (c->container->lastsize >= c->current->start + c->current->offset) {
480  // if the range has become obsolete because we received the data already
481  // we just free it
483  SCFree(c->current->buffer);
484  SCFree(c->current);
485  c->current = NULL;
486  SCLogDebug("c->current was obsolete");
487  return NULL;
488  } else {
489  /* otherwise insert in red and black tree. If res != NULL, the insert
490  failed because its a dup. */
492  HTTP_RANGES_RB_INSERT(&c->container->fragment_tree, c->current);
493  if (res) {
494  SCLogDebug("duplicate range fragment");
496  SCFree(c->current->buffer);
497  SCFree(c->current);
498  c->current = NULL;
499  return NULL;
500  }
501  SCLogDebug("inserted range fragment");
502  c->current = NULL;
503  if (c->container->files == NULL) {
504  // we have to wait for the flow owning the file
505  return NULL;
506  }
507  if (c->container->files->tail == NULL) {
508  // file has already been closed meanwhile
509  return NULL;
510  }
511  // keep on going, maybe this out of order chunk
512  // became the missing part between open and close
513  }
514  SCLogDebug("c->current was set, file incomplete so return NULL");
515  } else if (c->toskip > 0) {
516  // was only an overlapping range, truncated before new bytes
517  SCLogDebug("c->toskip %" PRIu64, c->toskip);
518  if (c->files) {
519  // if we expected new bytes after overlap
520  c->container->files = c->files;
521  c->files = NULL;
522  }
523  return NULL;
524  } else {
525  // we just finished an in-order block
526  DEBUG_VALIDATE_BUG_ON(c->files == NULL);
527  // move back the ownership of the file container to HttpRangeContainerFile
528  c->container->files = c->files;
529  c->files = NULL;
531  }
532 
533  File *f = c->container->files->tail;
534 
535  /* See if we can use our stored fragments to (partly) reconstruct the file */
536  HttpRangeContainerBuffer *range, *safe = NULL;
537  RB_FOREACH_SAFE (range, HTTP_RANGES, &c->container->fragment_tree, safe) {
538  if (f->size < range->start) {
539  // this next range is not reached yet
540  break;
541  }
542  if (f->size == range->start) {
543  // a new range just begins where we ended, append it
544  if (range->gap > 0) {
545  // if the range had a gap, begin by it
546  if (FileAppendData(c->container->files, sbcfg, NULL, range->gap) != 0) {
547  c->container->lastsize = f->size;
548  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
549  c->container->error = true;
550  return f;
551  }
552  }
553  if (FileAppendData(c->container->files, sbcfg, range->buffer, range->offset) != 0) {
554  c->container->lastsize = f->size;
555  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
556  c->container->error = true;
557  return f;
558  }
559  } else {
560  // the range starts before where we ended
561  uint64_t overlap = f->size - range->start;
562  if (overlap < range->offset) {
563  if (range->gap > 0) {
564  // if the range had a gap, begin by it
565  if (FileAppendData(c->container->files, sbcfg, NULL, range->gap) != 0) {
566  c->container->lastsize = f->size;
567  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
568  c->container->error = true;
569  return f;
570  }
571  }
572  // And the range ends beyond where we ended
573  // in this case of overlap, only add the extra data
574  if (FileAppendData(c->container->files, sbcfg, range->buffer + overlap,
575  range->offset - overlap) != 0) {
576  c->container->lastsize = f->size;
577  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
578  c->container->error = true;
579  return f;
580  }
581  }
582  }
583  /* Remove this range from the tree */
584  HTTP_RANGES_RB_REMOVE(&c->container->fragment_tree, range);
585  (void)SC_ATOMIC_SUB(ContainerUrlRangeList.ht->memuse, range->buflen);
586  SCFree(range->buffer);
587  SCFree(range);
588  }
589  // wait until we merged all the buffers to update known size
590  c->container->lastsize = f->size;
591 
592  if (f->size >= c->container->totalsize) {
593  // we finished the whole file
594  HttpRangeFileClose(sbcfg, c->container, flags);
595  } else {
596  // we are expecting more ranges
597  f = NULL;
598  SCLogDebug("expecting more use_cnt %u", SC_ATOMIC_GET(c->container->hdata->use_cnt));
599  }
600  SCLogDebug("returning f %p (c:%p container:%p)", f, c, c->container);
601  return f;
602 }
603 
604 static void HttpRangeBlockDerefContainer(HttpRangeContainerBlock *b)
605 {
606  if (b && b->container) {
609  b->container = NULL;
610  }
611 }
612 
614 {
615  if (b) {
616  BUG_ON(b->container == NULL && b->files != NULL);
617  const StreamingBufferConfig *sbcfg = b->container ? b->container->sbcfg : NULL;
618 
619  HttpRangeBlockDerefContainer(b);
620 
621  if (b->current) {
623  SCFree(b->current->buffer);
624  SCFree(b->current);
625  }
626  // we did not move ownership of the file container back to HttpRangeContainerFile
627  DEBUG_VALIDATE_BUG_ON(b->files != NULL);
628  if (b->files != NULL) {
629  FileContainerFree(b->files, sbcfg);
630  b->files = NULL;
631  }
632  SCFree(b);
633  }
634 }
HttpRangeContainerBuffer::gap
uint64_t gap
Definition: app-layer-htp-range.h:43
util-byte.h
HttpRangeContainerBuffer::buffer
uint8_t * buffer
Definition: app-layer-htp-range.h:35
FILE_TRUNCATED
#define FILE_TRUNCATED
Definition: util-file.h:45
util-hash-string.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
ts
uint64_t ts
Definition: source-erf-file.c:55
app-layer-htp-range.h
HttpRangeContainerBuffer::buflen
uint64_t buflen
Definition: app-layer-htp-range.h:37
THashDataGetResult::data
THashData * data
Definition: util-thash.h:188
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
FileContainerAlloc
FileContainer * FileContainerAlloc(void)
allocate a FileContainer
Definition: util-file.c:497
RB_REMOVE
#define RB_REMOVE(name, x, y)
Definition: tree.h:773
File_::size
uint64_t size
Definition: util-file.h:102
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:198
HttpRangeContainerFile::files
FileContainer * files
Definition: app-layer-htp-range.h:76
THashData_::prev
struct THashData_ * prev
Definition: util-thash.h:95
FileContainerFree
void FileContainerFree(FileContainer *ffc, const StreamingBufferConfig *cfg)
Free a FileContainer.
Definition: util-file.c:533
Flow_
Flow data structure.
Definition: flow.h:351
HTTP_RANGE_DEFAULT_MEMCAP
#define HTTP_RANGE_DEFAULT_MEMCAP
Definition: app-layer-htp-range.c:148
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:332
HttpRangeContainerBuffer::start
uint64_t start
Definition: app-layer-htp-range.h:39
HttpRangeContainerFile::error
bool error
Definition: app-layer-htp-range.h:82
THashData_::next
struct THashData_ * next
Definition: util-thash.h:94
HttpRangeContainerOpenFile
HttpRangeContainerBlock * HttpRangeContainerOpenFile(const uint8_t *key, uint32_t keylen, const Flow *f, const HTTPContentRange *crparsed, const StreamingBufferConfig *sbcfg, const uint8_t *name, uint16_t name_len, uint16_t flags, const uint8_t *data, uint32_t data_len)
Definition: app-layer-htp-range.c:360
HttpRangeAppendData
int HttpRangeAppendData(const StreamingBufferConfig *sbcfg, HttpRangeContainerBlock *c, const uint8_t *data, uint32_t len)
Definition: app-layer-htp-range.c:396
FileContainer_::tail
File * tail
Definition: util-file.h:115
HttpRangeContainerBufferCompare
int HttpRangeContainerBufferCompare(HttpRangeContainerBuffer *a, HttpRangeContainerBuffer *b)
Definition: app-layer-htp-range.c:45
HttpRangeContainerBlock::toskip
uint64_t toskip
Definition: app-layer-htp-range.h:92
HttpRangeContainerFile::flags
uint16_t flags
Definition: app-layer-htp-range.h:80
util-memcmp.h
HttpRangeContainerBlock
Definition: app-layer-htp-range.h:90
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
HRLOCK_UNLOCK
#define HRLOCK_UNLOCK(fb)
Definition: host.h:53
HttpRangeContainerFile
Definition: app-layer-htp-range.h:60
THashDataConfig_::hash_size
uint32_t hash_size
Definition: util-thash.h:127
HttpRangeClose
File * HttpRangeClose(const StreamingBufferConfig *sbcfg, HttpRangeContainerBlock *c, uint16_t flags)
Definition: app-layer-htp-range.c:469
RB_INIT
#define RB_INIT(root)
Definition: tree.h:308
RB_GENERATE
RB_GENERATE(HTTP_RANGES, HttpRangeContainerBuffer, rb, HttpRangeContainerBufferCompare)
THashTableContext_
Definition: util-thash.h:139
HttpRangeContainerFile::lastsize
uint64_t lastsize
Definition: app-layer-htp-range.h:72
Flow_::lastts
SCTime_t lastts
Definition: flow.h:410
HttpRangeContainersInit
void HttpRangeContainersInit(void)
Definition: app-layer-htp-range.c:150
RB_FOREACH_SAFE
#define RB_FOREACH_SAFE(x, name, head, y)
Definition: tree.h:791
FileContainer_::head
File * head
Definition: util-file.h:114
HttpRangeContainerBlock::current
HttpRangeContainerBuffer * current
Definition: app-layer-htp-range.h:94
ContainerTHashTable
struct ContainerTHashTable ContainerTHashTable
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:313
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
THashInit
THashTableContext * THashInit(const char *cnf_prefix, size_t data_size, int(*DataSet)(void *, void *), void(*DataFree)(void *), uint32_t(*DataHash)(void *), bool(*DataCompare)(void *, void *), bool reset_memcap, uint64_t memcap, uint32_t hashsize)
Definition: util-thash.c:295
THashTableContext_::array
THashHashRow * array
Definition: util-thash.h:141
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:341
THashDataGetResult
Definition: util-thash.h:187
ContainerTHashTable
Definition: app-layer-htp-range.c:33
SCTime_t
Definition: util-time.h:40
FileOpenFileWithId
int FileOpenFileWithId(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id, const uint8_t *name, uint16_t name_len, const uint8_t *data, uint32_t data_len, uint16_t flags)
Open a new File.
Definition: util-file.c:981
HttpRangeContainerFile::expire
uint32_t expire
Definition: app-layer-htp-range.h:66
FileAppendData
int FileAppendData(FileContainer *ffc, const StreamingBufferConfig *sbcfg, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The last file in the FileContainer will be us...
Definition: util-file.c:780
THashDataMoveToSpare
void THashDataMoveToSpare(THashTableContext *ctx, THashData *h)
Definition: util-thash.c:41
HttpRangeContainerFile::key
uint8_t * key
Definition: app-layer-htp-range.h:62
HttpRangeContainerFile::hdata
THashData * hdata
Definition: app-layer-htp-range.h:68
THashShutdown
void THashShutdown(THashTableContext *ctx)
shutdown the flow engine
Definition: util-thash.c:347
HttpRangeContainerBlock::container
HttpRangeContainerFile * container
Definition: app-layer-htp-range.h:96
HttpRangeContainerBuffer::offset
uint64_t offset
Definition: app-layer-htp-range.h:41
File_
Definition: util-file.h:79
THashData_::data
void * data
Definition: util-thash.h:92
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
THashData_
Definition: util-thash.h:85
flags
uint8_t flags
Definition: decode-gre.h:0
ContainerTHashTable::timeout
uint32_t timeout
Definition: app-layer-htp-range.c:35
suricata-common.h
CONTAINER_URLRANGE_HASH_SIZE
#define CONTAINER_URLRANGE_HASH_SIZE
Definition: app-layer-htp-range.c:43
HttpRangeContainerFile::totalsize
uint64_t totalsize
Definition: app-layer-htp-range.h:70
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
HttpRangeContainerFile::len
uint32_t len
Definition: app-layer-htp-range.h:64
ContainerUrlRangeList
ContainerTHashTable ContainerUrlRangeList
Definition: app-layer-htp-range.c:39
THashGetFromHash
struct THashDataGetResult THashGetFromHash(THashTableContext *ctx, void *data)
Definition: util-thash.c:530
THashDecrUsecnt
#define THashDecrUsecnt(h)
Definition: util-thash.h:167
util-validate.h
StreamingBufferConfig_
Definition: util-streaming-buffer.h:65
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
HttpRangeFreeBlock
void HttpRangeFreeBlock(HttpRangeContainerBlock *b)
Definition: app-layer-htp-range.c:613
str
#define str(s)
Definition: suricata-common.h:291
FileCloseFile
int FileCloseFile(FileContainer *ffc, const StreamingBufferConfig *sbcfg, const uint8_t *data, uint32_t data_len, uint16_t flags)
Close a File.
Definition: util-file.c:1077
SCFree
#define SCFree(p)
Definition: util-mem.h:61
src
uint16_t src
Definition: app-layer-dnp3.h:5
HRLOCK_TRYLOCK
#define HRLOCK_TRYLOCK(fb)
Definition: host.h:52
HttpRangeContainersDestroy
void HttpRangeContainersDestroy(void)
Definition: app-layer-htp-range.c:183
HttpRangeContainerFile::fragment_tree
struct HTTP_RANGES fragment_tree
Definition: app-layer-htp-range.h:78
ContainerTHashTable::ht
THashTableContext * ht
Definition: app-layer-htp-range.c:34
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
dst
uint16_t dst
Definition: app-layer-dnp3.h:4
util-misc.h
util-thash.h
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
HttpRangeContainerFile::sbcfg
const StreamingBufferConfig * sbcfg
Definition: app-layer-htp-range.h:74
THASH_CHECK_MEMCAP
#define THASH_CHECK_MEMCAP(ctx, size)
check if a memory alloc would fit in the memcap
Definition: util-thash.h:162
HttpRangeContainerBlock::files
FileContainer * files
Definition: app-layer-htp-range.h:98
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:103
HTTP_RANGE_DEFAULT_TIMEOUT
#define HTTP_RANGE_DEFAULT_TIMEOUT
Definition: app-layer-htp-range.c:147
HttpRangeContainerBuffer
Definition: app-layer-htp-range.h:31
StringHashDjb2
uint32_t StringHashDjb2(const uint8_t *data, uint32_t datalen)
Definition: util-hash-string.c:22
HttpRangeContainersTimeoutHash
uint32_t HttpRangeContainersTimeoutHash(const SCTime_t ts)
Definition: app-layer-htp-range.c:188
THashTableContext_::config
THashConfig config
Definition: util-thash.h:149