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(void *data, const SCTime_t ts)
131 {
132  HttpRangeContainerFile *cu = data;
133  // we only timeout if we have no flow referencing us
134  if (SCTIME_CMP_GTE(ts, cu->expire) || cu->error) {
135  DEBUG_VALIDATE_BUG_ON(cu->files == NULL);
136  return true;
137  }
138  return false;
139 }
140 
141 static void ContainerUrlRangeUpdate(HttpRangeContainerFile *cu, SCTime_t expire)
142 {
143  cu->expire = expire;
144 }
145 
146 #define HTTP_RANGE_DEFAULT_TIMEOUT 60
147 #define HTTP_RANGE_DEFAULT_MEMCAP 100 * 1024 * 1024
148 
150 {
151  SCLogDebug("containers start");
152  const char *str = NULL;
153  uint64_t memcap = HTTP_RANGE_DEFAULT_MEMCAP;
154  uint32_t timeout = HTTP_RANGE_DEFAULT_TIMEOUT;
155  if (ConfGet("app-layer.protocols.http.byterange.memcap", &str) == 1) {
156  if (ParseSizeStringU64(str, &memcap) < 0) {
157  SCLogWarning("memcap value cannot be deduced: %s,"
158  " resetting to default",
159  str);
160  memcap = 0;
161  }
162  }
163  if (ConfGet("app-layer.protocols.http.byterange.timeout", &str) == 1) {
164  size_t slen = strlen(str);
165  if (slen > UINT16_MAX || StringParseUint32(&timeout, 10, (uint16_t)slen, str) <= 0) {
166  SCLogWarning("timeout value cannot be deduced: %s,"
167  " resetting to default",
168  str);
169  timeout = 0;
170  }
171  }
172 
173  ContainerUrlRangeList.ht = THashInit("app-layer.protocols.http.byterange",
174  sizeof(HttpRangeContainerFile), ContainerUrlRangeSet, ContainerUrlRangeFree,
175  ContainerUrlRangeHash, ContainerUrlRangeCompare, ContainerValueRangeTimeout, NULL,
176  false, memcap, CONTAINER_URLRANGE_HASH_SIZE);
177  ContainerUrlRangeList.timeout = timeout;
178 
179  SCLogDebug("containers started");
180 }
181 
183 {
185 }
186 
188 {
190 }
191 
192 /**
193  * \returns locked data
194  */
195 static void *HttpRangeContainerUrlGet(const uint8_t *key, uint32_t keylen, const Flow *f)
196 {
197  const SCTime_t ts = f->lastts;
198  HttpRangeContainerFile lookup;
199  memset(&lookup, 0, sizeof(lookup));
200  // cast so as not to have const in the structure
201  lookup.key = (uint8_t *)key;
202  lookup.len = keylen;
204  if (res.data) {
205  // nothing more to do if (res.is_new)
206  ContainerUrlRangeUpdate(res.data->data, SCTIME_ADD_SECS(ts, ContainerUrlRangeList.timeout));
207  HttpRangeContainerFile *c = res.data->data;
208  c->hdata = res.data;
209  SCLogDebug("c %p", c);
210  return res.data->data;
211  }
212  return NULL;
213 }
214 
215 static HttpRangeContainerBlock *HttpRangeOpenFileAux(HttpRangeContainerFile *c, uint64_t start,
216  uint64_t end, uint64_t total, const StreamingBufferConfig *sbcfg, const uint8_t *name,
217  uint16_t name_len, uint16_t flags)
218 {
219  if (c->files != NULL && c->files->tail == NULL) {
220  /* this is the first request, we open a single file in the file container
221  * this could be part of ContainerUrlRangeSet if we could have
222  * all the arguments there
223  */
224  if (FileOpenFileWithId(c->files, sbcfg, 0, name, name_len, NULL, 0, flags) != 0) {
225  SCLogDebug("open file for range failed");
226  return NULL;
227  }
228  }
230  if (curf == NULL) {
231  c->error = true;
232  return NULL;
233  }
234  curf->files = NULL;
235  if (total > c->totalsize) {
236  // we grow to the maximum size indicated by different range requests
237  // we could add some warning/app-layer event in this case where
238  // different range requests indicate different total sizes
239  c->totalsize = total;
240  }
241  const uint64_t buflen = end - start + 1;
242 
243  /* The big part of this function is now to decide which kind of HttpRangeContainerBlock
244  * we will return :
245  * - skipping already processed data
246  * - storing out of order data for later use
247  * - directly appending to the file if we are at the right offset
248  */
249  if (start == c->lastsize && c->files != NULL) {
250  // easy case : append to current file
251  curf->container = c;
252  // If we see 2 duplicate range requests with the same range,
253  // the first one takes the ownership of the files container
254  // protected by the lock from caller HTPFileOpenWithRange
255  curf->files = c->files;
256  c->files = NULL;
257  return curf;
258  } else if (start < c->lastsize && c->lastsize - start >= buflen) {
259  // only overlap
260  // redundant to be explicit that this block is independent
261  curf->toskip = buflen;
262  return curf;
263  } else if (start < c->lastsize && c->lastsize - start < buflen && c->files != NULL) {
264  // some overlap, then some data to append to the file
265  curf->toskip = c->lastsize - start;
266  curf->files = c->files;
267  c->files = NULL;
268  curf->container = c;
269  return curf;
270  }
271  // Because we are not in the previous cases, we will store the data for later use
272 
273  // block/range to be inserted in ordered linked list
274  if (!(THASH_CHECK_MEMCAP(ContainerUrlRangeList.ht, buflen))) {
275  // skips this range
276  curf->toskip = buflen;
277  return curf;
278  }
279  curf->container = c;
280 
282  if (range == NULL) {
283  c->error = true;
284  SCFree(curf);
285  return NULL;
286  }
287 
288  (void)SC_ATOMIC_ADD(ContainerUrlRangeList.ht->memuse, buflen);
289  range->buffer = SCMalloc(buflen);
290  if (range->buffer == NULL) {
291  c->error = true;
292  SCFree(curf);
293  SCFree(range);
294  (void)SC_ATOMIC_SUB(ContainerUrlRangeList.ht->memuse, buflen);
295  return NULL;
296  }
297  range->buflen = buflen;
298  range->start = start;
299  range->offset = 0;
300  range->gap = 0;
301  curf->current = range;
302  return curf;
303 }
304 
305 static HttpRangeContainerBlock *HttpRangeOpenFile(HttpRangeContainerFile *c, uint64_t start,
306  uint64_t end, uint64_t total, const StreamingBufferConfig *sbcfg, const uint8_t *name,
307  uint16_t name_len, uint16_t flags, const uint8_t *data, uint32_t len)
308 {
310  HttpRangeOpenFileAux(c, start, end, total, sbcfg, name, name_len, flags);
311  if (r) {
312  if (HttpRangeAppendData(sbcfg, r, data, len) < 0) {
313  SCLogDebug("Failed to append data while opening");
314  }
315  }
316  return r;
317 }
318 
319 HttpRangeContainerBlock *HttpRangeContainerOpenFile(const uint8_t *key, uint32_t keylen,
320  const Flow *f, const HTTPContentRange *crparsed, const StreamingBufferConfig *sbcfg,
321  const uint8_t *name, uint16_t name_len, uint16_t flags, const uint8_t *data,
322  uint32_t data_len)
323 {
324  HttpRangeContainerFile *file_range_container = HttpRangeContainerUrlGet(key, keylen, f);
325  if (file_range_container == NULL) {
326  // probably reached memcap
327  return NULL;
328  }
329  file_range_container->sbcfg = sbcfg;
330 
331  HttpRangeContainerBlock *r = HttpRangeOpenFile(file_range_container, crparsed->start,
332  crparsed->end, crparsed->size, sbcfg, name, name_len, flags, data, data_len);
333  SCLogDebug("s->file_range == %p", r);
334  if (r == NULL) {
335  THashDecrUsecnt(file_range_container->hdata);
337  SC_ATOMIC_GET(file_range_container->hdata->use_cnt) > (uint32_t)INT_MAX);
338  THashDataUnlock(file_range_container->hdata);
339 
340  // probably reached memcap
341  return NULL;
342  /* in some cases we don't take a reference, so decr use cnt */
343  } else if (r->container == NULL) {
344  THashDecrUsecnt(file_range_container->hdata);
345  } else {
346  SCLogDebug("container %p use_cnt %u", r, SC_ATOMIC_GET(r->container->hdata->use_cnt));
347  DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(r->container->hdata->use_cnt) > (uint32_t)INT_MAX);
348  }
349 
350  /* we're done, so unlock. But since we have a reference in s->file_range keep use_cnt. */
351  THashDataUnlock(file_range_container->hdata);
352  return r;
353 }
354 
356  const uint8_t *data, uint32_t len)
357 {
358  if (len == 0) {
359  return 0;
360  }
361  // first check if we need to skip all bytes
362  if (c->toskip >= len) {
363  c->toskip -= len;
364  return 0;
365  }
366  // then if we need to skip only some bytes
367  if (c->toskip > 0) {
368  int r = 0;
369  if (c->files) {
370  if (data == NULL) {
371  // gap overlapping already known data
372  r = FileAppendData(c->files, sbcfg, NULL, (uint32_t)(len - c->toskip));
373  } else {
374  r = FileAppendData(c->files, sbcfg, data + c->toskip, (uint32_t)(len - c->toskip));
375  }
376  }
377  c->toskip = 0;
378  return r;
379  }
380  // If we are owning the file to append to it, let's do it
381  if (c->files) {
382  SCLogDebug("update files (FileAppendData)");
383  return FileAppendData(c->files, sbcfg, data, len);
384  }
385  // Maybe we were in the skipping case,
386  // but we get more data than expected and had set c->toskip = 0
387  // so we need to check for last case with something to do
388  if (c->current) {
389  // So we have a current allocated buffer to copy to
390  // in the case of an unordered range being handled
391  SCLogDebug("update current: adding %u bytes to block %p", len, c);
392  // GAP "data"
393  if (data == NULL) {
394  // just save the length of the gap
395  c->current->gap += len;
396  // data, but we're not yet complete
397  } else if (c->current->offset + len < c->current->buflen) {
398  memcpy(c->current->buffer + c->current->offset, data, len);
399  c->current->offset += len;
400  // data, we're complete
401  } else if (c->current->offset + len == c->current->buflen) {
402  memcpy(c->current->buffer + c->current->offset, data, len);
403  c->current->offset += len;
404  // data, more than expected
405  } else {
406  memcpy(c->current->buffer + c->current->offset, data,
407  c->current->buflen - c->current->offset);
408  c->current->offset = c->current->buflen;
409  }
410  }
411  return 0;
412 }
413 
414 static void HttpRangeFileClose(
415  const StreamingBufferConfig *sbcfg, HttpRangeContainerFile *c, uint16_t flags)
416 {
417  SCLogDebug("closing range %p flags %04x", c, flags);
418  DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(c->hdata->use_cnt) == 0);
419  // move ownership of file c->files->head to caller
420  FileCloseFile(c->files, sbcfg, NULL, 0, c->flags | flags);
421  c->files->head = NULL;
422  c->files->tail = NULL;
423 }
424 
425 /**
426  * \note if `f` is non-NULL, the ownership of the file is transferred to the caller.
427  */
429 {
430  SCLogDebug("c %p c->container %p c->current %p", c, c->container, c->current);
431 
432  DEBUG_VALIDATE_BUG_ON(c->container == NULL);
433 
434  /* we're processing an OOO chunk, won't be able to get us a full file just yet */
435  if (c->current) {
436  SCLogDebug("processing ooo chunk as c->current is set %p", c->current);
437  // some out-or-order range is finished
438  if (c->container->lastsize >= c->current->start + c->current->offset) {
439  // if the range has become obsolete because we received the data already
440  // we just free it
442  SCFree(c->current->buffer);
443  SCFree(c->current);
444  c->current = NULL;
445  SCLogDebug("c->current was obsolete");
446  return NULL;
447  } else {
448  /* otherwise insert in red and black tree. If res != NULL, the insert
449  failed because its a dup. */
451  HTTP_RANGES_RB_INSERT(&c->container->fragment_tree, c->current);
452  if (res) {
453  SCLogDebug("duplicate range fragment");
455  SCFree(c->current->buffer);
456  SCFree(c->current);
457  c->current = NULL;
458  return NULL;
459  }
460  SCLogDebug("inserted range fragment");
461  c->current = NULL;
462  if (c->container->files == NULL) {
463  // we have to wait for the flow owning the file
464  return NULL;
465  }
466  if (c->container->files->tail == NULL) {
467  // file has already been closed meanwhile
468  return NULL;
469  }
470  // keep on going, maybe this out of order chunk
471  // became the missing part between open and close
472  }
473  SCLogDebug("c->current was set, file incomplete so return NULL");
474  } else if (c->toskip > 0) {
475  // was only an overlapping range, truncated before new bytes
476  SCLogDebug("c->toskip %" PRIu64, c->toskip);
477  if (c->files) {
478  // if we expected new bytes after overlap
479  c->container->files = c->files;
480  c->files = NULL;
481  }
482  return NULL;
483  } else {
484  // we just finished an in-order block
485  DEBUG_VALIDATE_BUG_ON(c->files == NULL);
486  // move back the ownership of the file container to HttpRangeContainerFile
487  c->container->files = c->files;
488  c->files = NULL;
490  }
491 
492  File *f = c->container->files->tail;
493 
494  /* See if we can use our stored fragments to (partly) reconstruct the file */
495  HttpRangeContainerBuffer *range, *safe = NULL;
496  RB_FOREACH_SAFE (range, HTTP_RANGES, &c->container->fragment_tree, safe) {
497  if (f->size < range->start) {
498  // this next range is not reached yet
499  break;
500  }
501  if (f->size == range->start) {
502  // a new range just begins where we ended, append it
503  if (range->gap > 0) {
504  // if the range had a gap, begin by it
505  uint32_t gap = range->gap <= UINT32_MAX ? (uint32_t)range->gap : UINT32_MAX;
506  if (FileAppendData(c->container->files, sbcfg, NULL, gap) != 0) {
507  c->container->lastsize = f->size;
508  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
509  c->container->error = true;
510  return f;
511  }
512  }
513  if (range->offset > UINT32_MAX) {
514  c->container->lastsize = f->size;
515  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
516  c->container->error = true;
517  return f;
518  } else if (FileAppendData(c->container->files, sbcfg, range->buffer,
519  (uint32_t)range->offset) != 0) {
520  c->container->lastsize = f->size;
521  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
522  c->container->error = true;
523  return f;
524  }
525  } else {
526  // the range starts before where we ended
527  uint64_t overlap = f->size - range->start;
528  if (overlap < range->offset) {
529  if (range->gap > 0) {
530  // if the range had a gap, begin by it
531  uint32_t gap = range->gap <= UINT32_MAX ? (uint32_t)range->gap : UINT32_MAX;
532  if (FileAppendData(c->container->files, sbcfg, NULL, gap) != 0) {
533  c->container->lastsize = f->size;
534  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
535  c->container->error = true;
536  return f;
537  }
538  }
539  // And the range ends beyond where we ended
540  // in this case of overlap, only add the extra data
541  if (range->offset - overlap > UINT32_MAX) {
542  c->container->lastsize = f->size;
543  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
544  c->container->error = true;
545  return f;
546  } else if (FileAppendData(c->container->files, sbcfg, range->buffer + overlap,
547  (uint32_t)(range->offset - overlap)) != 0) {
548  c->container->lastsize = f->size;
549  HttpRangeFileClose(sbcfg, c->container, flags | FILE_TRUNCATED);
550  c->container->error = true;
551  return f;
552  }
553  }
554  }
555  /* Remove this range from the tree */
556  HTTP_RANGES_RB_REMOVE(&c->container->fragment_tree, range);
557  (void)SC_ATOMIC_SUB(ContainerUrlRangeList.ht->memuse, range->buflen);
558  SCFree(range->buffer);
559  SCFree(range);
560  }
561  // wait until we merged all the buffers to update known size
562  c->container->lastsize = f->size;
563 
564  if (f->size >= c->container->totalsize) {
565  // we finished the whole file
566  HttpRangeFileClose(sbcfg, c->container, flags);
567  } else {
568  // we are expecting more ranges
569  f = NULL;
570  SCLogDebug("expecting more use_cnt %u", SC_ATOMIC_GET(c->container->hdata->use_cnt));
571  }
572  SCLogDebug("returning f %p (c:%p container:%p)", f, c, c->container);
573  return f;
574 }
575 
576 static void HttpRangeBlockDerefContainer(HttpRangeContainerBlock *b)
577 {
578  if (b && b->container) {
581  b->container = NULL;
582  }
583 }
584 
586 {
587  if (b) {
588  BUG_ON(b->container == NULL && b->files != NULL);
589  const StreamingBufferConfig *sbcfg = b->container ? b->container->sbcfg : NULL;
590 
591  HttpRangeBlockDerefContainer(b);
592 
593  if (b->current) {
595  SCFree(b->current->buffer);
596  SCFree(b->current);
597  }
598  // we did not move ownership of the file container back to HttpRangeContainerFile
599  DEBUG_VALIDATE_BUG_ON(b->files != NULL);
600  if (b->files != NULL) {
601  FileContainerFree(b->files, sbcfg);
602  b->files = NULL;
603  }
604  SCFree(b);
605  }
606 }
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:191
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(*DataExpired)(void *, SCTime_t), uint32_t(*DataSize)(void *), bool reset_memcap, uint64_t memcap, uint32_t hashsize)
Definition: util-thash.c:302
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:190
HttpRangeContainerFile::files
FileContainer * files
Definition: app-layer-htp-range.h:76
FileContainerFree
void FileContainerFree(FileContainer *ffc, const StreamingBufferConfig *cfg)
Free a FileContainer.
Definition: util-file.c:533
Flow_
Flow data structure.
Definition: flow.h:360
HTTP_RANGE_DEFAULT_MEMCAP
#define HTTP_RANGE_DEFAULT_MEMCAP
Definition: app-layer-htp-range.c:147
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
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:319
HttpRangeAppendData
int HttpRangeAppendData(const StreamingBufferConfig *sbcfg, HttpRangeContainerBlock *c, const uint8_t *data, uint32_t len)
Definition: app-layer-htp-range.c:355
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
HttpRangeContainerFile
Definition: app-layer-htp-range.h:60
HttpRangeClose
File * HttpRangeClose(const StreamingBufferConfig *sbcfg, HttpRangeContainerBlock *c, uint16_t flags)
Definition: app-layer-htp-range.c:428
RB_INIT
#define RB_INIT(root)
Definition: tree.h:308
RB_GENERATE
RB_GENERATE(HTTP_RANGES, HttpRangeContainerBuffer, rb, HttpRangeContainerBufferCompare)
THashTableContext_
Definition: util-thash.h:141
HttpRangeContainerFile::lastsize
uint64_t lastsize
Definition: app-layer-htp-range.h:72
Flow_::lastts
SCTime_t lastts
Definition: flow.h:419
HttpRangeContainersInit
void HttpRangeContainersInit(void)
Definition: app-layer-htp-range.c:149
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
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:190
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:984
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:783
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:357
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
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
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:617
THashDecrUsecnt
#define THashDecrUsecnt(h)
Definition: util-thash.h:169
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:585
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:1080
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SCTIME_CMP_GTE
#define SCTIME_CMP_GTE(a, b)
Definition: util-time.h:103
src
uint16_t src
Definition: app-layer-dnp3.h:5
THashExpire
uint32_t THashExpire(THashTableContext *ctx, const SCTime_t ts)
expire data from the hash Walk the hash table and remove data that is exprired according to the DataE...
Definition: util-thash.c:426
HttpRangeContainersDestroy
void HttpRangeContainersDestroy(void)
Definition: app-layer-htp-range.c:182
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
SCTIME_ADD_SECS
#define SCTIME_ADD_SECS(ts, s)
Definition: util-time.h:64
HttpRangeContainerFile::expire
SCTime_t expire
Definition: app-layer-htp-range.h:66
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:164
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:102
HTTP_RANGE_DEFAULT_TIMEOUT
#define HTTP_RANGE_DEFAULT_TIMEOUT
Definition: app-layer-htp-range.c:146
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:187