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