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