suricata
app-layer-parser.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Generic App-layer parsing functions.
24  */
25 
26 #include "suricata-common.h"
27 #include "debug.h"
28 #include "util-unittest.h"
29 #include "decode.h"
30 #include "threads.h"
31 
32 #include "util-print.h"
33 #include "util-pool.h"
34 
35 #include "flow-util.h"
36 #include "flow-private.h"
37 
38 #include "detect-engine-state.h"
39 #include "detect-engine-port.h"
40 
41 #include "stream-tcp.h"
42 #include "stream-tcp-private.h"
43 #include "stream.h"
44 #include "stream-tcp-reassemble.h"
45 
46 #include "app-layer.h"
47 #include "app-layer-protos.h"
48 #include "app-layer-parser.h"
49 #include "app-layer-dcerpc.h"
50 #include "app-layer-dcerpc-udp.h"
51 #include "app-layer-smb.h"
52 #include "app-layer-htp.h"
53 #include "app-layer-ftp.h"
54 #include "app-layer-ssl.h"
55 #include "app-layer-ssh.h"
56 #include "app-layer-smtp.h"
57 #include "app-layer-dns-udp.h"
58 #include "app-layer-dns-tcp.h"
59 #include "app-layer-modbus.h"
60 #include "app-layer-enip.h"
61 #include "app-layer-dnp3.h"
62 #include "app-layer-nfs-tcp.h"
63 #include "app-layer-nfs-udp.h"
64 #include "app-layer-ntp.h"
65 #include "app-layer-tftp.h"
66 #include "app-layer-ikev2.h"
67 #include "app-layer-krb5.h"
68 #include "app-layer-dhcp.h"
69 #include "app-layer-template.h"
71 
72 #include "conf.h"
73 #include "util-spm.h"
74 
75 #include "util-debug.h"
76 #include "decode-events.h"
77 #include "util-unittest-helper.h"
78 #include "util-validate.h"
79 
80 #include "runmodes.h"
81 
84 };
85 
86 
87 /**
88  * \brief App layer protocol parser context.
89  */
91 {
92  /* 0 - to_server, 1 - to_client. */
93  AppLayerParserFPtr Parser[2];
94  bool logger;
95  uint32_t logger_bits; /**< registered loggers for this proto */
96 
97  void *(*StateAlloc)(void);
98  void (*StateFree)(void *);
99  void (*StateTransactionFree)(void *, uint64_t);
100  void *(*LocalStorageAlloc)(void);
101  void (*LocalStorageFree)(void *);
102 
103  void (*Truncate)(void *, uint8_t);
104  FileContainer *(*StateGetFiles)(void *, uint8_t);
105  AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t);
106 
107  int (*StateGetProgress)(void *alstate, uint8_t direction);
108  uint64_t (*StateGetTxCnt)(void *alstate);
109  void *(*StateGetTx)(void *alstate, uint64_t tx_id);
111  int (*StateGetProgressCompletionStatus)(uint8_t direction);
112  int (*StateGetEventInfo)(const char *event_name,
113  int *event_id, AppLayerEventType *event_type);
114 
115  LoggerId (*StateGetTxLogged)(void *alstate, void *tx);
116  void (*StateSetTxLogged)(void *alstate, void *tx, LoggerId logger);
117 
118  DetectEngineState *(*GetTxDetectState)(void *tx);
119  int (*SetTxDetectState)(void *tx, DetectEngineState *);
120 
121  uint64_t (*GetTxDetectFlags)(void *tx, uint8_t dir);
122  void (*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t);
123 
124  /* each app-layer has its own value */
125  uint32_t stream_depth;
126 
127  /* Indicates the direction the parser is ready to see the data
128  * the first time for a flow. Values accepted -
129  * STREAM_TOSERVER, STREAM_TOCLIENT */
130  uint8_t first_data_dir;
131 
132  /* Option flags such as supporting gaps or not. */
133  uint32_t option_flags;
134  /* coccinelle: AppLayerParserProtoCtx:option_flags:APP_LAYER_PARSER_OPT_ */
135 
136  uint32_t internal_flags;
137  /* coccinelle: AppLayerParserProtoCtx:internal_flags:APP_LAYER_PARSER_INT_ */
138 
139 #ifdef UNITTESTS
140  void (*RegisterUnittests)(void);
141 #endif
143 
144 typedef struct AppLayerParserCtx_ {
147 
149  /* coccinelle: AppLayerParserState:flags:APP_LAYER_PARSER_ */
150  uint8_t flags;
151 
152  /* Indicates the current transaction that is being inspected.
153  * We have a var per direction. */
154  uint64_t inspect_id[2];
155  /* Indicates the current transaction being logged. Unlike inspect_id,
156  * we don't need a var per direction since we don't log a transaction
157  * unless we have the entire transaction. */
158  uint64_t log_id;
159 
160  uint64_t min_id;
161 
162  /* Used to store decoder events. */
164 };
165 
166 #ifdef UNITTESTS
167 void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
168 {
169  struct AppLayerParserState_ *s = ptr;
170  *i1 = s->inspect_id[0];
171  *i2 = s->inspect_id[1];
172  *log = s->log_id;
173  *min = s->min_id;
174 }
175 #endif
176 
177 /* Static global version of the parser context.
178  * Post 2.0 let's look at changing this to move it out to app-layer.c. */
179 static AppLayerParserCtx alp_ctx;
180 
181 int AppLayerParserProtoIsRegistered(uint8_t ipproto, AppProto alproto)
182 {
183  uint8_t ipproto_map = FlowGetProtoMapping(ipproto);
184 
185  return (alp_ctx.ctxs[ipproto_map][alproto].StateAlloc != NULL) ? 1 : 0;
186 }
187 
189 {
190  SCEnter();
191 
192  AppLayerParserState *pstate = (AppLayerParserState *)SCMalloc(sizeof(*pstate));
193  if (pstate == NULL)
194  goto end;
195  memset(pstate, 0, sizeof(*pstate));
196 
197  end:
198  SCReturnPtr(pstate, "AppLayerParserState");
199 }
200 
202 {
203  SCEnter();
204 
205  if (pstate->decoder_events != NULL)
207  SCFree(pstate);
208 
209  SCReturn;
210 }
211 
213 {
214  SCEnter();
215  memset(&alp_ctx, 0, sizeof(alp_ctx));
216  SCReturnInt(0);
217 }
218 
220 {
221  AppProto alproto = 0;
222  int flow_proto = 0;
223 
224  /* lets set a default value for stream_depth */
225  for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
226  for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
227  if (!(alp_ctx.ctxs[flow_proto][alproto].internal_flags &
229  alp_ctx.ctxs[flow_proto][alproto].stream_depth =
231  }
232  }
233  }
234 }
235 
237 {
238  SCEnter();
239 
241 
242  SCReturnInt(0);
243 }
244 
246 {
247  SCEnter();
248 
249  AppProto alproto = 0;
250  int flow_proto = 0;
252 
253  tctx = SCMalloc(sizeof(*tctx));
254  if (tctx == NULL)
255  goto end;
256  memset(tctx, 0, sizeof(*tctx));
257 
258  for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
259  for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
260  uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
261 
262  tctx->alproto_local_storage[flow_proto][alproto] =
264  }
265  }
266 
267  end:
268  SCReturnPtr(tctx, "void *");
269 }
270 
272 {
273  SCEnter();
274 
275  AppProto alproto = 0;
276  int flow_proto = 0;
277 
278  for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
279  for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
280  uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
281 
283  tctx->alproto_local_storage[flow_proto][alproto]);
284  }
285  }
286 
287  SCFree(tctx);
288  SCReturn;
289 }
290 
291 /** \brief check if a parser is enabled in the config
292  * Returns enabled always if: were running unittests and
293  * when compiled with --enable-afl
294  */
295 int AppLayerParserConfParserEnabled(const char *ipproto,
296  const char *alproto_name)
297 {
298  SCEnter();
299 
300  int enabled = 1;
301  char param[100];
302  ConfNode *node;
303  int r;
304 
305 #ifdef AFLFUZZ_APPLAYER
306  goto enabled;
307 #endif
308  if (RunmodeIsUnittests())
309  goto enabled;
310 
311  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
312  alproto_name, ".enabled");
313  if (r < 0) {
314  SCLogError(SC_ERR_FATAL, "snprintf failure.");
315  exit(EXIT_FAILURE);
316  } else if (r > (int)sizeof(param)) {
317  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
318  exit(EXIT_FAILURE);
319  }
320 
321  node = ConfGetNode(param);
322  if (node == NULL) {
323  SCLogDebug("Entry for %s not found.", param);
324  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
325  alproto_name, ".", ipproto, ".enabled");
326  if (r < 0) {
327  SCLogError(SC_ERR_FATAL, "snprintf failure.");
328  exit(EXIT_FAILURE);
329  } else if (r > (int)sizeof(param)) {
330  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
331  exit(EXIT_FAILURE);
332  }
333 
334  node = ConfGetNode(param);
335  if (node == NULL) {
336  SCLogDebug("Entry for %s not found.", param);
337  goto enabled;
338  }
339  }
340 
341  if (ConfValIsTrue(node->val)) {
342  goto enabled;
343  } else if (ConfValIsFalse(node->val)) {
344  goto disabled;
345  } else if (strcasecmp(node->val, "detection-only") == 0) {
346  goto disabled;
347  } else {
348  SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
349  exit(EXIT_FAILURE);
350  }
351 
352  disabled:
353  enabled = 0;
354  enabled:
355  SCReturnInt(enabled);
356 }
357 
358 /***** Parser related registration *****/
359 
360 int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto,
361  uint8_t direction,
362  AppLayerParserFPtr Parser)
363 {
364  SCEnter();
365 
366  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
367  Parser[(direction & STREAM_TOSERVER) ? 0 : 1] = Parser;
368 
369  SCReturnInt(0);
370 }
371 
373  uint8_t direction)
374 {
375  SCEnter();
376 
377  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].first_data_dir |=
378  (direction & (STREAM_TOSERVER | STREAM_TOCLIENT));
379 
380  SCReturn;
381 }
382 
383 void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto,
384  uint32_t flags)
385 {
386  SCEnter();
387 
388  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].option_flags |= flags;
389 
390  SCReturn;
391 }
392 
393 void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto,
394  void *(*StateAlloc)(void),
395  void (*StateFree)(void *))
396 {
397  SCEnter();
398 
399  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateAlloc =
400  StateAlloc;
401  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateFree =
402  StateFree;
403 
404  SCReturn;
405 }
406 
407 void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto,
408  void *(*LocalStorageAlloc)(void),
409  void (*LocalStorageFree)(void *))
410 {
411  SCEnter();
412 
413  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageAlloc =
414  LocalStorageAlloc;
415  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageFree =
416  LocalStorageFree;
417 
418  SCReturn;
419 }
420 
421 void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto,
422  FileContainer *(*StateGetFiles)(void *, uint8_t))
423 {
424  SCEnter();
425 
426  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles =
427  StateGetFiles;
428 
429  SCReturn;
430 }
431 
432 void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto,
433  AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
434 {
435  SCEnter();
436 
437  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetEvents =
438  StateGetEvents;
439 
440  SCReturn;
441 }
442 
443 void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto,
444  LoggerId (*StateGetTxLogged)(void *, void *),
445  void (*StateSetTxLogged)(void *, void *, LoggerId))
446 {
447  SCEnter();
448 
449  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxLogged =
450  StateGetTxLogged;
451 
452  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateSetTxLogged =
453  StateSetTxLogged;
454 
455  SCReturn;
456 }
457 
458 void AppLayerParserRegisterLoggerBits(uint8_t ipproto, AppProto alproto, LoggerId bits)
459 {
460  SCEnter();
461 
462  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger_bits = bits;
463 
464  SCReturn;
465 }
466 
467 void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
468 {
469  SCEnter();
470 
471  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger = true;
472 
473  SCReturn;
474 }
475 
476 void AppLayerParserRegisterTruncateFunc(uint8_t ipproto, AppProto alproto,
477  void (*Truncate)(void *, uint8_t))
478 {
479  SCEnter();
480 
481  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate = Truncate;
482 
483  SCReturn;
484 }
485 
487  int (*StateGetProgress)(void *alstate, uint8_t direction))
488 {
489  SCEnter();
490 
491  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
492  StateGetProgress = StateGetProgress;
493 
494  SCReturn;
495 }
496 
497 void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto,
498  void (*StateTransactionFree)(void *, uint64_t))
499 {
500  SCEnter();
501 
502  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
503  StateTransactionFree = StateTransactionFree;
504 
505  SCReturn;
506 }
507 
508 void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto,
509  uint64_t (*StateGetTxCnt)(void *alstate))
510 {
511  SCEnter();
512 
513  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
514  StateGetTxCnt = StateGetTxCnt;
515 
516  SCReturn;
517 }
518 
519 void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto,
520  void *(StateGetTx)(void *alstate, uint64_t tx_id))
521 {
522  SCEnter();
523 
524  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
525  StateGetTx = StateGetTx;
526 
527  SCReturn;
528 }
529 
530 void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto,
532 {
533  SCEnter();
534  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxIterator = Func;
535  SCReturn;
536 }
537 
539  int (*StateGetProgressCompletionStatus)(uint8_t direction))
540 {
541  SCEnter();
542 
543  alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].
544  StateGetProgressCompletionStatus = StateGetProgressCompletionStatus;
545 
546  SCReturn;
547 }
548 
549 void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
550  int (*StateGetEventInfo)(const char *event_name, int *event_id,
552 {
553  SCEnter();
554 
555  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
556  StateGetEventInfo = StateGetEventInfo;
557 
558  SCReturn;
559 }
560 
561 void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto,
562  DetectEngineState *(*GetTxDetectState)(void *tx),
563  int (*SetTxDetectState)(void *tx, DetectEngineState *))
564 {
565  SCEnter();
566 
567  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState = GetTxDetectState;
568  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectState = SetTxDetectState;
569 
570  SCReturn;
571 }
572 
573 void AppLayerParserRegisterDetectFlagsFuncs(uint8_t ipproto, AppProto alproto,
574  uint64_t(*GetTxDetectFlags)(void *tx, uint8_t dir),
575  void (*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t))
576 {
577  SCEnter();
578 
579  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectFlags = GetTxDetectFlags;
580  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectFlags = SetTxDetectFlags;
581 
582  SCReturn;
583 }
584 
585 void AppLayerParserRegisterMpmIDsFuncs(uint8_t ipproto, AppProto alproto,
586  uint64_t(*GetTxMpmIDs)(void *tx),
587  int (*SetTxMpmIDs)(void *tx, uint64_t))
588 {
589  SCEnter();
590  SCLogWarning(SC_WARN_DEPRECATED, "%u/%s: GetTxMpmIDs/SetTxMpmIDs is no longer used",
591  ipproto, AppProtoToString(alproto));
592  SCReturn;
593 }
594 
595 /***** Get and transaction functions *****/
596 
598 {
599  SCEnter();
600  void * r = NULL;
601 
602  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
603  LocalStorageAlloc != NULL)
604  {
605  r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
606  LocalStorageAlloc();
607  }
608 
609  SCReturnPtr(r, "void *");
610 }
611 
613  void *local_data)
614 {
615  SCEnter();
616 
617  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
618  LocalStorageFree != NULL)
619  {
620  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
621  LocalStorageFree(local_data);
622  }
623 
624  SCReturn;
625 }
626 
627 /** \brief default tx iterator
628  *
629  * Used if the app layer parser doesn't register its own iterator.
630  * Simply walks the tx_id space until it finds a tx. Uses 'state' to
631  * keep track of where it left off.
632  *
633  * \retval txptr or NULL if no more txs in list
634  */
635 static AppLayerGetTxIterTuple AppLayerDefaultGetTxIterator(
636  const uint8_t ipproto, const AppProto alproto,
637  void *alstate, uint64_t min_tx_id, uint64_t max_tx_id,
638  AppLayerGetTxIterState *state)
639 {
640  uint64_t ustate = *(uint64_t *)state;
641  uint64_t tx_id = MAX(min_tx_id, ustate);
642  for ( ; tx_id < max_tx_id; tx_id++) {
643  void *tx_ptr = AppLayerParserGetTx(ipproto, alproto, alstate, tx_id);
644  if (tx_ptr != NULL) {
645  ustate = tx_id + 1;
646  *state = *(AppLayerGetTxIterState *)&ustate;
647  AppLayerGetTxIterTuple tuple = {
648  .tx_ptr = tx_ptr,
649  .tx_id = tx_id,
650  .has_next = (tx_id + 1 < max_tx_id),
651  };
652  SCLogDebug("tulpe: %p/%"PRIu64"/%s", tuple.tx_ptr, tuple.tx_id,
653  tuple.has_next ? "true" : "false");
654  return tuple;
655  }
656  }
657 
658  AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
659  return no_tuple;
660 }
661 
663  const AppProto alproto)
664 {
666  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxIterator;
667  return Func ? Func : AppLayerDefaultGetTxIterator;
668 }
669 
670 void AppLayerParserSetTxLogged(uint8_t ipproto, AppProto alproto,
671  void *alstate, void *tx, LoggerId logger)
672 {
673  SCEnter();
674 
675  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
676  StateSetTxLogged != NULL) {
677  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
678  StateSetTxLogged(alstate, tx, logger);
679  }
680 
681  SCReturn;
682 }
683 
685  void *alstate, void *tx)
686 {
687  SCEnter();
688 
689  LoggerId r = 0;
690  if (alp_ctx.ctxs[f->protomap][f->alproto].StateGetTxLogged != NULL) {
691  r = alp_ctx.ctxs[f->protomap][f->alproto].
692  StateGetTxLogged(alstate, tx);
693  }
694 
695  SCReturnUInt(r);
696 }
697 
699 {
700  SCEnter();
701 
702  SCReturnCT((pstate == NULL) ? 0 : pstate->log_id, "uint64_t");
703 }
704 
706 {
707  SCEnter();
708 
709  if (pstate != NULL)
710  pstate->log_id = tx_id;
711 
712  SCReturn;
713 }
714 
715 uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
716 {
717  SCEnter();
718 
719  if (pstate == NULL)
720  SCReturnCT(0ULL, "uint64_t");
721 
722  SCReturnCT(pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1], "uint64_t");
723 }
724 
726  void *alstate, const uint8_t flags,
727  bool tag_txs_as_inspected)
728 {
729  SCEnter();
730 
731  const int direction = (flags & STREAM_TOSERVER) ? 0 : 1;
732  const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
733  uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, flags);
734  const int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
735  const uint8_t ipproto = f->proto;
736  const AppProto alproto = f->alproto;
737 
738  AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
740  memset(&state, 0, sizeof(state));
741 
742  SCLogDebug("called: %s, tag_txs_as_inspected %s",direction==0?"toserver":"toclient",
743  tag_txs_as_inspected?"true":"false");
744 
745  /* mark all txs as inspected if the applayer progress is
746  * at the 'end state'. */
747  while (1) {
748  AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
749  if (ires.tx_ptr == NULL)
750  break;
751 
752  void *tx = ires.tx_ptr;
753  idx = ires.tx_id;
754 
755  int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
756  if (state_progress < state_done_progress)
757  break;
758 
759  if (tag_txs_as_inspected) {
760  uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, flags);
761  if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
762  detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
763  AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags);
764  SCLogDebug("%p/%"PRIu64" in-order tx is done for direction %s. Flag %016"PRIx64,
765  tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
766  }
767  }
768  if (!ires.has_next)
769  break;
770  idx++;
771  }
772  pstate->inspect_id[direction] = idx;
773  SCLogDebug("inspect_id now %"PRIu64, pstate->inspect_id[direction]);
774 
775  /* if necessary we flag all txs that are complete as 'inspected'
776  * also move inspect_id forward. */
777  if (tag_txs_as_inspected) {
778  /* continue at idx */
779  while (1) {
780  AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
781  if (ires.tx_ptr == NULL)
782  break;
783 
784  void *tx = ires.tx_ptr;
785  /* if we got a higher id than the minimum we requested, we
786  * skipped a bunch of 'null-txs'. Lets see if we can up the
787  * inspect tracker */
788  if (ires.tx_id > idx && pstate->inspect_id[direction] == idx) {
789  pstate->inspect_id[direction] = ires.tx_id;
790  }
791  idx = ires.tx_id;
792 
793  const int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
794  if (state_progress < state_done_progress)
795  break;
796 
797  uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, flags);
798  if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
799  detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
800  AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags);
801  SCLogDebug("%p/%"PRIu64" out of order tx is done for direction %s. Flag %016"PRIx64,
802  tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
803 
804  SCLogDebug("%p/%"PRIu64" out of order tx. Update inspect_id? %"PRIu64,
805  tx, idx, pstate->inspect_id[direction]);
806  if (pstate->inspect_id[direction]+1 == idx)
807  pstate->inspect_id[direction] = idx;
808  }
809  if (!ires.has_next)
810  break;
811  idx++;
812  }
813  }
814 
815  SCReturn;
816 }
817 
819 {
820  SCEnter();
821 
822  SCReturnPtr(pstate->decoder_events,
823  "AppLayerDecoderEvents *");
824 }
825 
827 {
828  pstate->decoder_events = devents;
829 }
830 
832  void *alstate, uint64_t tx_id)
833 {
834  SCEnter();
835 
836  AppLayerDecoderEvents *ptr = NULL;
837 
838  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
839  StateGetEvents != NULL)
840  {
841  ptr = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
842  StateGetEvents(alstate, tx_id);
843  }
844 
845  SCReturnPtr(ptr, "AppLayerDecoderEvents *");
846 }
847 
849  void *alstate, uint8_t direction)
850 {
851  SCEnter();
852 
853  FileContainer *ptr = NULL;
854 
855  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
856  StateGetFiles != NULL)
857  {
858  ptr = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
859  StateGetFiles(alstate, direction);
860  }
861 
862  SCReturnPtr(ptr, "FileContainer *");
863 }
864 
865 /**
866  * \brief remove obsolete (inspected and logged) transactions
867  */
869 {
870  SCEnter();
872 
873  AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][f->alproto];
874  if (unlikely(p->StateTransactionFree == NULL))
875  SCReturn;
876 
877  const uint8_t ipproto = f->proto;
878  const AppProto alproto = f->alproto;
879  void * const alstate = f->alstate;
880  AppLayerParserState * const alparser = f->alparser;
881 
882  if (alstate == NULL || alparser == NULL)
883  SCReturn;
884 
885  const uint64_t min = alparser->min_id;
886  const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
887  const LoggerId logger_expectation = AppLayerParserProtocolGetLoggerBits(ipproto, alproto);
888  const int tx_end_state_ts = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOSERVER);
889  const int tx_end_state_tc = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOCLIENT);
890 
891  AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
893  memset(&state, 0, sizeof(state));
894  uint64_t i = min;
895  uint64_t new_min = min;
896  SCLogDebug("start min %"PRIu64, min);
897  bool skipped = false;
898 
899  while (1) {
900  AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, i, total_txs, &state);
901  if (ires.tx_ptr == NULL)
902  break;
903 
904  void *tx = ires.tx_ptr;
905  i = ires.tx_id; // actual tx id for the tx the IterFunc returned
906 
907  SCLogDebug("%p/%"PRIu64" checking", tx, i);
908 
909  const int tx_progress_tc = AppLayerParserGetStateProgress(ipproto, alproto, tx, STREAM_TOCLIENT);
910  if (tx_progress_tc < tx_end_state_tc) {
911  SCLogDebug("%p/%"PRIu64" skipping: tc parser not done", tx, i);
912  skipped = true;
913  goto next;
914  }
915  const int tx_progress_ts = AppLayerParserGetStateProgress(ipproto, alproto, tx, STREAM_TOSERVER);
916  if (tx_progress_ts < tx_end_state_ts) {
917  SCLogDebug("%p/%"PRIu64" skipping: ts parser not done", tx, i);
918  skipped = true;
919  goto next;
920  }
921  if (f->sgh_toserver != NULL) {
922  uint64_t detect_flags_ts = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, STREAM_TOSERVER);
923  if (!(detect_flags_ts & APP_LAYER_TX_INSPECTED_FLAG)) {
924  SCLogDebug("%p/%"PRIu64" skipping: TS inspect not done: ts:%"PRIx64,
925  tx, i, detect_flags_ts);
926  skipped = true;
927  goto next;
928  }
929  }
930  if (f->sgh_toclient != NULL) {
931  uint64_t detect_flags_tc = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, STREAM_TOCLIENT);
932  if (!(detect_flags_tc & APP_LAYER_TX_INSPECTED_FLAG)) {
933  SCLogDebug("%p/%"PRIu64" skipping: TC inspect not done: tc:%"PRIx64,
934  tx, i, detect_flags_tc);
935  skipped = true;
936  goto next;
937  }
938  }
939  if (logger_expectation != 0) {
940  LoggerId tx_logged = AppLayerParserGetTxLogged(f, alstate, tx);
941  if (tx_logged != logger_expectation) {
942  SCLogDebug("%p/%"PRIu64" skipping: logging not done: want:%"PRIx32", have:%"PRIx32,
943  tx, i, logger_expectation, tx_logged);
944  skipped = true;
945  goto next;
946  }
947  }
948 
949  /* if we are here, the tx can be freed. */
950  p->StateTransactionFree(alstate, i);
951  SCLogDebug("%p/%"PRIu64" freed", tx, i);
952 
953  /* if we didn't skip any tx so far, up the minimum */
954  SCLogDebug("skipped? %s i %"PRIu64", new_min %"PRIu64, skipped ? "true" : "false", i, new_min);
955  if (!skipped)
956  new_min = i + 1;
957  SCLogDebug("final i %"PRIu64", new_min %"PRIu64, i, new_min);
958 
959 next:
960  if (!ires.has_next) {
961  /* this was the last tx. See if we skipped any. If not
962  * we removed all and can update the minimum to the max
963  * id. */
964  SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64, i, total_txs);
965  if (!skipped) {
966  new_min = total_txs;
967  SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64": "
968  "new_min updated to %"PRIu64, i, total_txs, new_min);
969  }
970  break;
971  }
972  i++;
973  }
974 
975  /* see if we need to bring all trackers up to date. */
976  SCLogDebug("update f->alparser->min_id? %"PRIu64" vs %"PRIu64, new_min, alparser->min_id);
977  if (new_min > alparser->min_id) {
978  const uint64_t next_id = new_min;
979  alparser->min_id = next_id;
980  alparser->inspect_id[0] = MAX(alparser->inspect_id[0], next_id);
981  alparser->inspect_id[1] = MAX(alparser->inspect_id[1], next_id);
982  alparser->log_id = MAX(alparser->log_id, next_id);
983  SCLogDebug("updated f->alparser->min_id %"PRIu64, alparser->min_id);
984  }
985  SCReturn;
986 }
987 
988 #define IS_DISRUPTED(flags) \
989  ((flags) & (STREAM_DEPTH|STREAM_GAP))
990 
991 /**
992  * \brief get the progress value for a tx/protocol
993  *
994  * If the stream is disrupted, we return the 'completion' value.
995  */
996 int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto,
997  void *alstate, uint8_t flags)
998 {
999  SCEnter();
1000  int r = 0;
1001  if (unlikely(IS_DISRUPTED(flags))) {
1002  r = alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].
1003  StateGetProgressCompletionStatus(flags);
1004  } else {
1005  r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1006  StateGetProgress(alstate, flags);
1007  }
1008  SCReturnInt(r);
1009 }
1010 
1011 uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
1012 {
1013  SCEnter();
1014  uint64_t r = 0;
1015  r = alp_ctx.ctxs[f->protomap][f->alproto].
1016  StateGetTxCnt(alstate);
1017  SCReturnCT(r, "uint64_t");
1018 }
1019 
1020 void *AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
1021 {
1022  SCEnter();
1023  void * r = NULL;
1024  r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1025  StateGetTx(alstate, tx_id);
1026  SCReturnPtr(r, "void *");
1027 }
1028 
1030  uint8_t direction)
1031 {
1032  SCEnter();
1033  int r = 0;
1034  r = alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].
1035  StateGetProgressCompletionStatus(direction);
1036  SCReturnInt(r);
1037 }
1038 
1039 int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name,
1040  int *event_id, AppLayerEventType *event_type)
1041 {
1042  SCEnter();
1043  int ipproto_map = FlowGetProtoMapping(ipproto);
1044  int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo == NULL) ?
1045  -1 : alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo(event_name, event_id, event_type);
1046  SCReturnInt(r);
1047 }
1048 
1049 uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
1050 {
1051  SCEnter();
1052  uint8_t r = 0;
1053  r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1054  first_data_dir;
1055  SCReturnCT(r, "uint8_t");
1056 }
1057 
1059  AppLayerParserState *pstate, uint8_t direction)
1060 {
1061  SCEnter();
1062 
1063  uint64_t active_id;
1064 
1065  uint64_t log_id = pstate->log_id;
1066  uint64_t inspect_id = pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1];
1067  if (alp_ctx.ctxs[f->protomap][f->alproto].logger == true) {
1068  active_id = (log_id < inspect_id) ? log_id : inspect_id;
1069  } else {
1070  active_id = inspect_id;
1071  }
1072 
1073  SCReturnCT(active_id, "uint64_t");
1074 }
1075 
1076 int AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
1077 {
1078  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles != NULL)
1079  return TRUE;
1080  return FALSE;
1081 }
1082 
1083 int AppLayerParserSupportsTxDetectState(uint8_t ipproto, AppProto alproto)
1084 {
1085  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState != NULL)
1086  return TRUE;
1087  return FALSE;
1088 }
1089 
1090 DetectEngineState *AppLayerParserGetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx)
1091 {
1092  SCEnter();
1093  DetectEngineState *s;
1094  s = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState(tx);
1095  SCReturnPtr(s, "DetectEngineState");
1096 }
1097 
1099  void *tx, DetectEngineState *s)
1100 {
1101  int r;
1102  SCEnter();
1103  if ((alp_ctx.ctxs[f->protomap][f->alproto].GetTxDetectState(tx) != NULL))
1104  SCReturnInt(-EBUSY);
1105  r = alp_ctx.ctxs[f->protomap][f->alproto].SetTxDetectState(tx, s);
1106  SCReturnInt(r);
1107 }
1108 
1109 uint64_t AppLayerParserGetTxDetectFlags(uint8_t ipproto, AppProto alproto, void *tx, uint8_t dir)
1110 {
1111  SCEnter();
1112  uint64_t flags = 0;
1113  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectFlags != NULL) {
1114  flags = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectFlags(tx, dir);
1115  }
1116  SCReturnUInt(flags);
1117 }
1118 
1119 void AppLayerParserSetTxDetectFlags(uint8_t ipproto, AppProto alproto, void *tx, uint8_t dir, uint64_t flags)
1120 {
1121  SCEnter();
1122  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectFlags != NULL) {
1123  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectFlags(tx, dir, flags);
1124  }
1125  SCReturn;
1126 }
1127 
1128 /***** General *****/
1129 
1131  uint8_t flags, uint8_t *input, uint32_t input_len)
1132 {
1133  SCEnter();
1134 #ifdef DEBUG_VALIDATION
1136 #endif
1137  AppLayerParserState *pstate = NULL;
1138  AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][alproto];
1139  void *alstate = NULL;
1140  uint64_t p_tx_cnt = 0;
1141 
1142  /* we don't have the parser registered for this protocol */
1143  if (p->StateAlloc == NULL)
1144  goto end;
1145 
1146  if (flags & STREAM_GAP) {
1148  SCLogDebug("app-layer parser does not accept gaps");
1149  if (f->alstate != NULL) {
1151  flags);
1152  }
1153  goto error;
1154  }
1155  }
1156 
1157  /* Get the parser state (if any) */
1158  pstate = f->alparser;
1159  if (pstate == NULL) {
1160  f->alparser = pstate = AppLayerParserStateAlloc();
1161  if (pstate == NULL)
1162  goto error;
1163  }
1164 
1165  if (flags & STREAM_EOF)
1167 
1168  alstate = f->alstate;
1169  if (alstate == NULL) {
1170  f->alstate = alstate = p->StateAlloc();
1171  if (alstate == NULL)
1172  goto error;
1173  SCLogDebug("alloced new app layer state %p (name %s)",
1174  alstate, AppLayerGetProtoName(f->alproto));
1175  } else {
1176  SCLogDebug("using existing app layer state %p (name %s))",
1177  alstate, AppLayerGetProtoName(f->alproto));
1178  }
1179 
1180  if (AppLayerParserProtocolIsTxAware(f->proto, alproto)) {
1181  p_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
1182  }
1183 
1184  /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
1185  if (input_len > 0 || (flags & STREAM_EOF)) {
1186  /* invoke the parser */
1187  if (p->Parser[(flags & STREAM_TOSERVER) ? 0 : 1](f, alstate, pstate,
1188  input, input_len,
1189  alp_tctx->alproto_local_storage[f->protomap][alproto],
1190  flags) < 0)
1191  {
1192  goto error;
1193  }
1194  }
1195 
1196  /* set the packets to no inspection and reassembly if required */
1197  if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) {
1198  AppLayerParserSetEOF(pstate);
1199  FlowSetNoPayloadInspectionFlag(f);
1200 
1201  if (f->proto == IPPROTO_TCP) {
1203 
1204  /* Set the no reassembly flag for both the stream in this TcpSession */
1205  if (pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) {
1206  /* Used only if it's TCP */
1207  TcpSession *ssn = f->protoctx;
1208  if (ssn != NULL) {
1210  flags & STREAM_TOCLIENT ? 1 : 0);
1212  flags & STREAM_TOSERVER ? 1 : 0);
1213  }
1214  }
1215  /* Set the bypass flag for both the stream in this TcpSession */
1216  if (pstate->flags & APP_LAYER_PARSER_BYPASS_READY) {
1217  /* Used only if it's TCP */
1218  TcpSession *ssn = f->protoctx;
1219  if (ssn != NULL) {
1221  }
1222  }
1223  }
1224  }
1225 
1226  /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */
1228  FlowSetNoPayloadInspectionFlag(f);
1229  /* Set the no reassembly flag for both the stream in this TcpSession */
1230  if (f->proto == IPPROTO_TCP) {
1231  /* Used only if it's TCP */
1232  TcpSession *ssn = f->protoctx;
1233  if (ssn != NULL) {
1236  }
1237  }
1238  }
1239 
1240  if (AppLayerParserProtocolIsTxAware(f->proto, alproto)) {
1241  if (likely(tv)) {
1242  uint64_t cur_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
1243  if (cur_tx_cnt > p_tx_cnt) {
1244  AppLayerIncTxCounter(tv, f, cur_tx_cnt - p_tx_cnt);
1245  }
1246  }
1247  }
1248 
1249  /* stream truncated, inform app layer */
1250  if (flags & STREAM_DEPTH)
1251  AppLayerParserStreamTruncated(f->proto, alproto, alstate, flags);
1252 
1253  end:
1254  SCReturnInt(0);
1255  error:
1256  /* Set the no app layer inspection flag for both
1257  * the stream in this Flow */
1258  if (f->proto == IPPROTO_TCP) {
1260  }
1261  AppLayerParserSetEOF(pstate);
1262  SCReturnInt(-1);
1263 }
1264 
1266 {
1267  SCEnter();
1268 
1269  if (pstate == NULL)
1270  goto end;
1271 
1273 
1274  end:
1275  SCReturn;
1276 }
1277 
1278 /* return true if there are app parser decoder events. These are
1279  * only the ones that are set during protocol detection. */
1281 {
1282  SCEnter();
1283 
1284  if (pstate == NULL)
1285  return false;
1286 
1288  if (decoder_events && decoder_events->cnt)
1289  return true;
1290 
1291  /* if we have reached here, we don't have events */
1292  return false;
1293 }
1294 
1295 /** \brief simpler way to globally test if a alproto is registered
1296  * and fully enabled in the configuration.
1297  */
1299 {
1300  return (alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto]
1302 }
1303 
1304 int AppLayerParserProtocolIsTxAware(uint8_t ipproto, AppProto alproto)
1305 {
1306  SCEnter();
1307  int ipproto_map = FlowGetProtoMapping(ipproto);
1308  int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetTx == NULL) ? 0 : 1;
1309  SCReturnInt(r);
1310 }
1311 
1312 int AppLayerParserProtocolIsTxEventAware(uint8_t ipproto, AppProto alproto)
1313 {
1314  SCEnter();
1315  int ipproto_map = FlowGetProtoMapping(ipproto);
1316  int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEvents == NULL) ? 0 : 1;
1317  SCReturnInt(r);
1318 }
1319 
1320 int AppLayerParserProtocolSupportsTxs(uint8_t ipproto, AppProto alproto)
1321 {
1322  SCEnter();
1323  int ipproto_map = FlowGetProtoMapping(ipproto);
1324  int r = (alp_ctx.ctxs[ipproto_map][alproto].StateTransactionFree == NULL) ? 0 : 1;
1325  SCReturnInt(r);
1326 }
1327 
1328 int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto)
1329 {
1330  SCEnter();
1331  int ipproto_map = FlowGetProtoMapping(ipproto);
1332  int r = (alp_ctx.ctxs[ipproto_map][alproto].logger == false) ? 0 : 1;
1333  SCReturnInt(r);
1334 }
1335 
1337 {
1338  SCEnter();
1339  const int ipproto_map = FlowGetProtoMapping(ipproto);
1340  LoggerId r = alp_ctx.ctxs[ipproto_map][alproto].logger_bits;
1341  SCReturnUInt(r);
1342 }
1343 
1345 {
1346  SCEnter();
1347 
1348  SCLogDebug("f %p tcp %p direction %d", f, f ? f->protoctx : NULL, direction);
1349  if (f != NULL && f->protoctx != NULL)
1351 
1352  SCReturn;
1353 }
1354 
1355 void AppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
1356 {
1357  SCEnter();
1358 
1359  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].stream_depth = stream_depth;
1360  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].internal_flags |=
1362 
1363  SCReturn;
1364 }
1365 
1367 {
1368  SCReturnInt(alp_ctx.ctxs[f->protomap][f->alproto].stream_depth);
1369 }
1370 
1371 /***** Cleanup *****/
1372 
1373 void AppLayerParserStateCleanup(const Flow *f, void *alstate,
1374  AppLayerParserState *pstate)
1375 {
1376  SCEnter();
1377 
1378  AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[f->protomap][f->alproto];
1379 
1380  if (ctx->StateFree != NULL && alstate != NULL)
1381  ctx->StateFree(alstate);
1382 
1383  /* free the app layer parser api state */
1384  if (pstate != NULL)
1385  AppLayerParserStateFree(pstate);
1386 
1387  SCReturn;
1388 }
1389 
1390 static void ValidateParserProtoDump(AppProto alproto, uint8_t ipproto)
1391 {
1392  uint8_t map = FlowGetProtoMapping(ipproto);
1393  const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
1394  const AppLayerParserProtoCtx *ctx_def = &alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto];
1395  printf("ERROR: incomplete app-layer registration\n");
1396  printf("AppLayer protocol %s ipproto %u\n", AppProtoToString(alproto), ipproto);
1397  printf("- option flags %"PRIx32"\n", ctx->option_flags);
1398  printf("- first_data_dir %"PRIx8"\n", ctx->first_data_dir);
1399  printf("Mandatory:\n");
1400  printf("- Parser[0] %p Parser[1] %p\n", ctx->Parser[0], ctx->Parser[1]);
1401  printf("- StateAlloc %p StateFree %p\n", ctx->StateAlloc, ctx->StateFree);
1402  printf("- StateGetTx %p StateGetTxCnt %p StateTransactionFree %p\n",
1403  ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree);
1404  printf("- StateGetProgress %p StateGetProgressCompletionStatus %p\n", ctx->StateGetProgress, ctx_def->StateGetProgressCompletionStatus);
1405  printf("- GetTxDetectState %p SetTxDetectState %p\n", ctx->GetTxDetectState, ctx->SetTxDetectState);
1406  printf("Optional:\n");
1407  printf("- LocalStorageAlloc %p LocalStorageFree %p\n", ctx->LocalStorageAlloc, ctx->LocalStorageFree);
1408  printf("- StateGetTxLogged %p StateSetTxLogged %p\n", ctx->StateGetTxLogged, ctx->StateSetTxLogged);
1409  printf("- StateGetEvents %p StateGetEventInfo %p\n", ctx->StateGetEvents, ctx->StateGetEventInfo);
1410 }
1411 
1412 #define BOTH_SET(a, b) ((a) != NULL && (b) != NULL)
1413 #define BOTH_SET_OR_BOTH_UNSET(a, b) (((a) == NULL && (b) == NULL) || ((a) != NULL && (b) != NULL))
1414 #define THREE_SET_OR_THREE_UNSET(a, b, c) (((a) == NULL && (b) == NULL && (c) == NULL) || ((a) != NULL && (b) != NULL && (c) != NULL))
1415 
1416 static void ValidateParserProto(AppProto alproto, uint8_t ipproto)
1417 {
1418  uint8_t map = FlowGetProtoMapping(ipproto);
1419  const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
1420  const AppLayerParserProtoCtx *ctx_def = &alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto];
1421 
1422  if (ctx->Parser[0] == NULL && ctx->Parser[1] == NULL)
1423  return;
1424 
1425  if (!(BOTH_SET(ctx->Parser[0], ctx->Parser[1]))) {
1426  goto bad;
1427  }
1428  if (!(BOTH_SET(ctx->StateFree, ctx->StateAlloc))) {
1429  goto bad;
1430  }
1432  goto bad;
1433  }
1434  /* special case: StateGetProgressCompletionStatus is used from 'default'. */
1436  goto bad;
1437  }
1438  /* local storage is optional, but needs both set if used */
1440  goto bad;
1441  }
1443  goto bad;
1444  }
1445  if (!(BOTH_SET(ctx->GetTxDetectState, ctx->SetTxDetectState))) {
1446  goto bad;
1447  }
1448 /* TODO: not yet mandatory to use StateHasTxDetectState
1449  if (!(THREE_SET_OR_THREE_UNSET(ctx->GetTxDetectState, ctx->SetTxDetectState, ctx->StateHasTxDetectState))) {
1450  goto bad;
1451  }
1452 */
1453 
1454  return;
1455 bad:
1456  ValidateParserProtoDump(alproto, ipproto);
1457  exit(EXIT_FAILURE);
1458 }
1459 #undef BOTH_SET
1460 #undef BOTH_SET_OR_BOTH_UNSET
1461 #undef THREE_SET_OR_THREE_UNSET
1462 
1463 static void ValidateParser(AppProto alproto)
1464 {
1465  ValidateParserProto(alproto, IPPROTO_TCP);
1466  ValidateParserProto(alproto, IPPROTO_UDP);
1467 }
1468 
1469 static void ValidateParsers(void)
1470 {
1471  AppProto p = 0;
1472  for ( ; p < ALPROTO_MAX; p++) {
1473  ValidateParser(p);
1474  }
1475 }
1476 
1478 {
1479  SCEnter();
1480 
1504 
1505  /** IMAP */
1507  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "imap")) {
1509  "1|20|capability", 12, 0, STREAM_TOSERVER) < 0)
1510  {
1511  SCLogInfo("imap proto registration failure\n");
1512  exit(EXIT_FAILURE);
1513  }
1514  } else {
1515  SCLogInfo("Protocol detection and parser disabled for %s protocol.",
1516  "imap");
1517  }
1518 
1519  /** MSN Messenger */
1523  "msn", 10, 6, STREAM_TOSERVER) < 0)
1524  {
1525  SCLogInfo("msn proto registration failure\n");
1526  exit(EXIT_FAILURE);
1527  }
1528  } else {
1529  SCLogInfo("Protocol detection and parser disabled for %s protocol.",
1530  "msn");
1531  }
1532 
1533  ValidateParsers();
1534  return;
1535 }
1536 
1537 
1539 {
1540  SCEnter();
1541  pstate->flags |= flag;
1542  SCReturn;
1543 }
1544 
1546 {
1547  SCEnter();
1548  SCReturnInt(pstate->flags & flag);
1549 }
1550 
1551 
1552 void AppLayerParserStreamTruncated(uint8_t ipproto, AppProto alproto, void *alstate,
1553  uint8_t direction)
1554 {
1555  SCEnter();
1556 
1557 
1558  if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate != NULL)
1559  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate(alstate, direction);
1560 
1561  SCReturn;
1562 }
1563 
1564 #ifdef DEBUG
1565 void AppLayerParserStatePrintDetails(AppLayerParserState *pstate)
1566 {
1567  SCEnter();
1568 
1569  if (pstate == NULL)
1570  SCReturn;
1571 
1572  AppLayerParserState *p = pstate;
1573  SCLogDebug("AppLayerParser parser state information for parser state p(%p). "
1574  "p->inspect_id[0](%"PRIu64"), "
1575  "p->inspect_id[1](%"PRIu64"), "
1576  "p->log_id(%"PRIu64"), "
1577  "p->decoder_events(%p).",
1578  pstate, p->inspect_id[0], p->inspect_id[1], p->log_id,
1579  p->decoder_events);
1580 
1581  SCReturn;
1582 }
1583 #endif
1584 
1585 #ifdef AFLFUZZ_APPLAYER
1586 int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filename)
1587 {
1588  bool do_dump = (getenv("SC_AFL_DUMP_FILES") != NULL);
1589  struct timeval ts;
1590  memset(&ts, 0, sizeof(ts));
1591  gettimeofday(&ts, NULL);
1592 
1593  int result = 1;
1594  Flow *f = NULL;
1595  TcpSession ssn;
1597 
1598  memset(&ssn, 0, sizeof(ssn));
1599 
1600  f = SCCalloc(1, sizeof(Flow));
1601  if (f == NULL)
1602  goto end;
1603  FLOW_INITIALIZE(f);
1604 
1605  f->flags |= FLOW_IPV4;
1606  f->src.addr_data32[0] = 0x01020304;
1607  f->dst.addr_data32[0] = 0x05060708;
1608  f->sp = 10000;
1609  f->dp = 80;
1610  f->protoctx = &ssn;
1611  f->proto = ipproto;
1613  f->alproto = alproto;
1614 
1615  uint8_t buffer[65536];
1616  uint32_t cnt = 0;
1617 
1618 #ifdef AFLFUZZ_PERSISTANT_MODE
1619  while (__AFL_LOOP(1000)) {
1620  /* reset state */
1621  memset(buffer, 0, sizeof(buffer));
1622 #endif /* AFLFUZZ_PERSISTANT_MODE */
1623 
1624  FILE *fp = fopen(filename, "r");
1625  BUG_ON(fp == NULL);
1626 
1627  int start = 1;
1628  while (1) {
1629  int done = 0;
1630  size_t size = fread(&buffer, 1, sizeof(buffer), fp);
1631  if (size < sizeof(buffer))
1632  done = 1;
1633 
1634  if (do_dump) {
1635  char outfilename[256];
1636  snprintf(outfilename, sizeof(outfilename), "dump/%u-%u.%u",
1637  (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, cnt);
1638  FILE *out_fp = fopen(outfilename, "w");
1639  BUG_ON(out_fp == NULL);
1640  (void)fwrite(buffer, size, 1, out_fp);
1641  fclose(out_fp);
1642  }
1643  //SCLogInfo("result %u done %d start %d", (uint)result, done, start);
1644 
1645  uint8_t flags = STREAM_TOSERVER;
1646  if (start--) {
1647  flags |= STREAM_START;
1648  }
1649  if (done) {
1650  flags |= STREAM_EOF;
1651  }
1652  //PrintRawDataFp(stdout, buffer, result);
1653 
1654  (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
1655  buffer, size);
1656  cnt++;
1657 
1658  if (done)
1659  break;
1660  }
1661 
1662  fclose(fp);
1663 
1664 #ifdef AFLFUZZ_PERSISTANT_MODE
1665  }
1666 #endif /* AFLFUZZ_PERSISTANT_MODE */
1667 
1668  if (do_dump) {
1669  /* if we get here there was no crash, so we can remove our files */
1670  uint32_t x = 0;
1671  for (x = 0; x < cnt; x++) {
1672  char rmfilename[256];
1673  snprintf(rmfilename, sizeof(rmfilename), "dump/%u-%u.%u",
1674  (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, x);
1675  unlink(rmfilename);
1676  }
1677  }
1678 
1679  result = 0;
1680 
1681 end:
1682  if (alp_tctx != NULL)
1683  AppLayerParserThreadCtxFree(alp_tctx);
1684  if (f != NULL) {
1685  FlowFree(f);
1686  }
1687  return result;
1688 }
1689 
1690 /* load a serie of files generated by DecoderParseDataFromFile() in
1691  * the same order as it was produced. */
1692 int AppLayerParserRequestFromFileSerie(uint8_t ipproto, AppProto alproto, char *fileprefix)
1693 {
1694  uint32_t cnt = 0;
1695  int start = 1;
1696  int result = 1;
1697  Flow *f = NULL;
1698  TcpSession ssn;
1700 
1701  memset(&ssn, 0, sizeof(ssn));
1702 
1703  f = SCCalloc(1, sizeof(Flow));
1704  if (f == NULL)
1705  goto end;
1706  FLOW_INITIALIZE(f);
1707 
1708  f->flags |= FLOW_IPV4;
1709  f->src.addr_data32[0] = 0x01020304;
1710  f->dst.addr_data32[0] = 0x05060708;
1711  f->sp = 10000;
1712  f->dp = 80;
1713  f->protoctx = &ssn;
1714  f->proto = ipproto;
1716  f->alproto = alproto;
1717 
1718  uint8_t buffer[65536];
1719 
1720  char filename[256];
1721  snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
1722  FILE *fp;
1723  while ((fp = fopen(filename, "r")) != NULL)
1724  {
1725  memset(buffer, 0, sizeof(buffer));
1726 
1727  size_t size = fread(&buffer, 1, sizeof(buffer), fp);
1728 
1729  uint8_t flags = STREAM_TOSERVER;
1730  if (start--) {
1731  flags |= STREAM_START;
1732  }
1733 
1734  (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
1735  buffer, size);
1736 
1737  fclose(fp);
1738  cnt++;
1739 
1740  snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
1741  }
1742 
1743  result = 0;
1744 
1745 end:
1746  if (alp_tctx != NULL)
1747  AppLayerParserThreadCtxFree(alp_tctx);
1748  if (f != NULL) {
1749  FlowFree(f);
1750  }
1751  return result;
1752 }
1753 
1754 int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename)
1755 {
1756  bool do_dump = (getenv("SC_AFL_DUMP_FILES") != NULL);
1757  struct timeval ts;
1758  memset(&ts, 0, sizeof(ts));
1759  gettimeofday(&ts, NULL);
1760 
1761  int result = 1;
1762  Flow *f = NULL;
1763  TcpSession ssn;
1765 
1766  memset(&ssn, 0, sizeof(ssn));
1767 
1768  f = SCCalloc(1, sizeof(Flow));
1769  if (f == NULL)
1770  goto end;
1771  FLOW_INITIALIZE(f);
1772 
1773  f->flags |= FLOW_IPV4;
1774  f->src.addr_data32[0] = 0x01020304;
1775  f->dst.addr_data32[0] = 0x05060708;
1776  f->sp = 10000;
1777  f->dp = 80;
1778  f->protoctx = &ssn;
1779  f->proto = ipproto;
1781  f->alproto = alproto;
1782 
1783  uint8_t buffer[65536];
1784  uint32_t cnt = 0;
1785 
1786 #ifdef AFLFUZZ_PERSISTANT_MODE
1787  while (__AFL_LOOP(1000)) {
1788  /* reset state */
1789  memset(buffer, 0, sizeof(buffer));
1790 #endif /* AFLFUZZ_PERSISTANT_MODE */
1791 
1792  FILE *fp = fopen(filename, "r");
1793  BUG_ON(fp == NULL);
1794 
1795  int start = 1;
1796  int flip = 0;
1797  while (1) {
1798  int done = 0;
1799  size_t size = fread(&buffer, 1, sizeof(buffer), fp);
1800  if (size < sizeof(buffer))
1801  done = 1;
1802  if (do_dump) {
1803  char outfilename[256];
1804  snprintf(outfilename, sizeof(outfilename), "dump/%u-%u.%u",
1805  (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, cnt);
1806  FILE *out_fp = fopen(outfilename, "w");
1807  BUG_ON(out_fp == NULL);
1808  (void)fwrite(buffer, size, 1, out_fp);
1809  fclose(out_fp);
1810  }
1811  //SCLogInfo("result %u done %d start %d", (uint)result, done, start);
1812 
1813  uint8_t flags = 0;
1814  if (flip) {
1815  flags = STREAM_TOCLIENT;
1816  flip = 0;
1817  } else {
1818  flags = STREAM_TOSERVER;
1819  flip = 1;
1820  }
1821 
1822  if (start--) {
1823  flags |= STREAM_START;
1824  }
1825  if (done) {
1826  flags |= STREAM_EOF;
1827  }
1828  //PrintRawDataFp(stdout, buffer, result);
1829 
1830  (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
1831  buffer, size);
1832 
1833  cnt++;
1834 
1835  if (done)
1836  break;
1837  }
1838 
1839  fclose(fp);
1840 
1841 #ifdef AFLFUZZ_PERSISTANT_MODE
1842  }
1843 #endif /* AFLFUZZ_PERSISTANT_MODE */
1844 
1845  if (do_dump) {
1846  /* if we get here there was no crash, so we can remove our files */
1847  uint32_t x = 0;
1848  for (x = 0; x < cnt; x++) {
1849  char rmfilename[256];
1850  snprintf(rmfilename, sizeof(rmfilename), "dump/%u-%u.%u",
1851  (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, x);
1852  unlink(rmfilename);
1853  }
1854  }
1855 
1856  result = 0;
1857 end:
1858  if (alp_tctx != NULL)
1859  AppLayerParserThreadCtxFree(alp_tctx);
1860  if (f != NULL) {
1861  FlowFree(f);
1862  }
1863  return result;
1864 }
1865 
1866 /* load a serie of files generated by DecoderParseDataFromFile() in
1867  * the same order as it was produced. */
1868 int AppLayerParserFromFileSerie(uint8_t ipproto, AppProto alproto, char *fileprefix)
1869 {
1870  uint32_t cnt = 0;
1871  int start = 1;
1872  int result = 1;
1873  Flow *f = NULL;
1874  TcpSession ssn;
1876 
1877  memset(&ssn, 0, sizeof(ssn));
1878 
1879  f = SCCalloc(1, sizeof(Flow));
1880  if (f == NULL)
1881  goto end;
1882  FLOW_INITIALIZE(f);
1883 
1884  f->flags |= FLOW_IPV4;
1885  f->src.addr_data32[0] = 0x01020304;
1886  f->dst.addr_data32[0] = 0x05060708;
1887  f->sp = 10000;
1888  f->dp = 80;
1889  f->protoctx = &ssn;
1890  f->proto = ipproto;
1892  f->alproto = alproto;
1893 
1894  uint8_t buffer[65536];
1895  int flip = 0;
1896  char filename[256];
1897  snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
1898  FILE *fp;
1899  while ((fp = fopen(filename, "r")) != NULL)
1900  {
1901  memset(buffer, 0, sizeof(buffer));
1902 
1903  size_t size = fread(&buffer, 1, sizeof(buffer), fp);
1904 
1905  uint8_t flags = 0;
1906  if (flip) {
1907  flags = STREAM_TOCLIENT;
1908  flip = 0;
1909  } else {
1910  flags = STREAM_TOSERVER;
1911  flip = 1;
1912  }
1913 
1914  if (start--) {
1915  flags |= STREAM_START;
1916  }
1917 
1918  (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
1919  buffer, size);
1920 
1921  fclose(fp);
1922  cnt++;
1923 
1924  snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
1925  }
1926 
1927  result = 0;
1928 
1929 end:
1930  if (alp_tctx != NULL)
1931  AppLayerParserThreadCtxFree(alp_tctx);
1932  if (f != NULL) {
1933  FlowFree(f);
1934  }
1935  return result;
1936 }
1937 
1938 #endif /* AFLFUZZ_APPLAYER */
1939 
1940 /***** Unittests *****/
1941 
1942 #ifdef UNITTESTS
1943 
1944 static AppLayerParserCtx alp_ctx_backup_unittest;
1945 
1946 typedef struct TestState_ {
1947  uint8_t test;
1948 } TestState;
1949 
1950 /**
1951  * \brief Test parser function to test the memory deallocation of app layer
1952  * parser of occurence of an error.
1953  */
1954 static int TestProtocolParser(Flow *f, void *test_state, AppLayerParserState *pstate,
1955  uint8_t *input, uint32_t input_len,
1956  void *local_data, const uint8_t flags)
1957 {
1958  SCEnter();
1959  SCReturnInt(-1);
1960 }
1961 
1962 /** \brief Function to allocates the Test protocol state memory
1963  */
1964 static void *TestProtocolStateAlloc(void)
1965 {
1966  SCEnter();
1967  void *s = SCMalloc(sizeof(TestState));
1968  if (unlikely(s == NULL))
1969  goto end;
1970  memset(s, 0, sizeof(TestState));
1971  end:
1972  SCReturnPtr(s, "TestState");
1973 }
1974 
1975 /** \brief Function to free the Test Protocol state memory
1976  */
1977 static void TestProtocolStateFree(void *s)
1978 {
1979  SCFree(s);
1980 }
1981 
1983  void (*RegisterUnittests)(void))
1984 {
1985  SCEnter();
1986  alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1987  RegisterUnittests = RegisterUnittests;
1988  SCReturn;
1989 }
1990 
1992 {
1993  SCEnter();
1994  alp_ctx_backup_unittest = alp_ctx;
1995  memset(&alp_ctx, 0, sizeof(alp_ctx));
1996  SCReturn;
1997 }
1998 
2000 {
2001  SCEnter();
2002  alp_ctx = alp_ctx_backup_unittest;
2003  memset(&alp_ctx_backup_unittest, 0, sizeof(alp_ctx_backup_unittest));
2004  SCReturn;
2005 }
2006 
2007 /**
2008  * \test Test the deallocation of app layer parser memory on occurance of
2009  * error in the parsing process.
2010  */
2011 static int AppLayerParserTest01(void)
2012 {
2014 
2015  int result = 0;
2016  Flow *f = NULL;
2017  uint8_t testbuf[] = { 0x11 };
2018  uint32_t testlen = sizeof(testbuf);
2019  TcpSession ssn;
2021 
2022  memset(&ssn, 0, sizeof(ssn));
2023 
2024  /* Register the Test protocol state and parser functions */
2026  TestProtocolParser);
2028  TestProtocolStateAlloc, TestProtocolStateFree);
2029 
2030  f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
2031  if (f == NULL)
2032  goto end;
2033  f->protoctx = &ssn;
2034  f->alproto = ALPROTO_TEST;
2035  f->proto = IPPROTO_TCP;
2036 
2038 
2039  FLOWLOCK_WRLOCK(f);
2040  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_TEST,
2041  STREAM_TOSERVER | STREAM_EOF, testbuf,
2042  testlen);
2043  if (r != -1) {
2044  printf("returned %" PRId32 ", expected -1: ", r);
2045  FLOWLOCK_UNLOCK(f);
2046  goto end;
2047  }
2048  FLOWLOCK_UNLOCK(f);
2049 
2051  printf("flag should have been set, but is not: ");
2052  goto end;
2053  }
2054 
2055  result = 1;
2056  end:
2059 
2060  UTHFreeFlow(f);
2061  return result;
2062 }
2063 
2064 /**
2065  * \test Test the deallocation of app layer parser memory on occurance of
2066  * error in the parsing process for UDP.
2067  */
2068 static int AppLayerParserTest02(void)
2069 {
2071 
2072  int result = 1;
2073  Flow *f = NULL;
2074  uint8_t testbuf[] = { 0x11 };
2075  uint32_t testlen = sizeof(testbuf);
2077 
2078  /* Register the Test protocol state and parser functions */
2080  TestProtocolParser);
2082  TestProtocolStateAlloc, TestProtocolStateFree);
2083 
2084  f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
2085  if (f == NULL)
2086  goto end;
2087  f->alproto = ALPROTO_TEST;
2088  f->proto = IPPROTO_UDP;
2090 
2092 
2093  FLOWLOCK_WRLOCK(f);
2094  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_TEST,
2095  STREAM_TOSERVER | STREAM_EOF, testbuf,
2096  testlen);
2097  if (r != -1) {
2098  printf("returned %" PRId32 ", expected -1: \n", r);
2099  result = 0;
2100  FLOWLOCK_UNLOCK(f);
2101  goto end;
2102  }
2103  FLOWLOCK_UNLOCK(f);
2104 
2105  end:
2108  UTHFreeFlow(f);
2109  return result;
2110 }
2111 
2112 
2114 {
2115  SCEnter();
2116 
2117  int ip;
2118  AppProto alproto;
2120 
2121  for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
2122  for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
2123  ctx = &alp_ctx.ctxs[ip][alproto];
2124  if (ctx->RegisterUnittests == NULL)
2125  continue;
2126  ctx->RegisterUnittests();
2127  }
2128  }
2129 
2130  UtRegisterTest("AppLayerParserTest01", AppLayerParserTest01);
2131  UtRegisterTest("AppLayerParserTest02", AppLayerParserTest02);
2132 
2133  SCReturn;
2134 }
2135 
2136 #endif
void RegisterSMBParsers(void)
void AppLayerParserPostStreamSetup(void)
AppLayerDecoderEvents * AppLayerParserGetDecoderEvents(AppLayerParserState *pstate)
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate, void *alstate, const uint8_t flags, bool tag_txs_as_inspected)
void AppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
void RegisterTFTPParsers(void)
enum AppLayerEventType_ AppLayerEventType
void * AppLayerParserGetProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto)
uint16_t flags
void StreamTcpSetSessionNoReassemblyFlag(TcpSession *, char)
disable reassembly
Definition: stream-tcp.c:5785
LoggerId AppLayerParserGetTxLogged(const Flow *f, void *alstate, void *tx)
void RegisterSMTPParsers(void)
Register the SMTP Protocol parser.
#define SCLogDebug(...)
Definition: util-debug.h:335
#define MAX(x, y)
void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto, uint32_t flags)
int(* AppLayerParserFPtr)(Flow *f, void *protocol_state, AppLayerParserState *pstate, uint8_t *buf, uint32_t buf_len, void *local_storage, const uint8_t flags)
Prototype for parsing functions.
struct HtpBodyChunk_ * next
void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto, void *(*LocalStorageAlloc)(void), void(*LocalStorageFree)(void *))
void * alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX]
int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto)
const struct SigGroupHead_ * sgh_toclient
Definition: flow.h:437
void RegisterNFSTCPParsers(void)
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
TcpStreamCnf stream_config
Definition: stream-tcp.h:106
#define BUG_ON(x)
void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate, uint64_t tx_id)
uint32_t event_type
uint8_t proto
Definition: flow.h:343
DetectEngineState *(* GetTxDetectState)(void *tx)
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
int AppLayerParserIsTxAware(AppProto alproto)
simpler way to globally test if a alproto is registered and fully enabled in the configuration.
LoggerId(* StateGetTxLogged)(void *alstate, void *tx)
#define FALSE
void RegisterDHCPParsers(void)
void(* SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t)
LoggerId
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:242
Port sp
Definition: flow.h:330
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
#define unlikely(expr)
Definition: util-optimize.h:35
int AppLayerParserDeSetup(void)
#define BOTH_SET(a, b)
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
void AppLayerParserRegisterDetectFlagsFuncs(uint8_t ipproto, AppProto alproto, uint64_t(*GetTxDetectFlags)(void *tx, uint8_t dir), void(*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t))
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
void FlowFree(Flow *f)
cleanup & free the memory of a flow
Definition: flow-util.c:80
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
void RegisterSSHParsers(void)
Function to register the SSH protocol parsers and other functions.
void RegisterNFSUDPParsers(void)
void(* Truncate)(void *, uint8_t)
int AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
void RegisterNTPParsers(void)
Definition: app-layer-ntp.c:62
void StreamTcpDisableAppLayer(Flow *f)
void AppLayerParserRegisterTruncateFunc(uint8_t ipproto, AppProto alproto, void(*Truncate)(void *, uint8_t))
#define STREAMTCP_FLAG_APP_LAYER_DISABLED
#define APP_LAYER_PARSER_BYPASS_READY
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
void StreamTcpReassembleTriggerRawReassembly(TcpSession *ssn, int direction)
Trigger RAW stream reassembly.
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:95
void RegisterDNSTCPParsers(void)
#define SCReturnUInt(x)
Definition: util-debug.h:343
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:239
#define THREE_SET_OR_THREE_UNSET(a, b, c)
AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto, const AppProto alproto)
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
uint16_t AppProto
char * val
Definition: conf.h:34
void AppLayerParserBackupParserTable(void)
void RegisterTemplateParsers(void)
#define TRUE
#define SCReturnCT(x, type)
Definition: util-debug.h:351
void * protoctx
Definition: flow.h:395
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
FlowAddress dst
Definition: flow.h:328
#define STREAM_DEPTH
Definition: stream.h:34
void AppLayerParserRegisterProtocolParsers(void)
void AppLayerParserStreamTruncated(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t direction)
void RegisterDCERPCUDPParsers(void)
int AppLayerParserSupportsTxDetectState(uint8_t ipproto, AppProto alproto)
void * alstate
Definition: flow.h:433
#define APP_LAYER_TX_INSPECTED_FLAG
#define APP_LAYER_PARSER_NO_REASSEMBLY
int AppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests and when...
void AppLayerParserTriggerRawStreamReassembly(Flow *f, int direction)
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
struct AppLayerParserProtoCtx_ AppLayerParserProtoCtx
App layer protocol parser context.
void RegisterENIPUDPParsers(void)
Function to register the ENIP protocol parsers and other functions.
void AppLayerParserRegisterLoggerBits(uint8_t ipproto, AppProto alproto, LoggerId bits)
#define SCCalloc(nm, a)
Definition: util-mem.h:197
AppLayerDecoderEvents * AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Data structure to store app layer decoder events.
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
#define STREAM_GAP
Definition: stream.h:33
uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate)
int AppLayerParserProtocolIsTxEventAware(uint8_t ipproto, AppProto alproto)
int(* StateGetProgress)(void *alstate, uint8_t direction)
void(* StateFree)(void *)
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
void AppLayerParserStateFree(AppLayerParserState *pstate)
void *(* LocalStorageAlloc)(void)
void AppLayerParserRestoreParserTable(void)
void(* StateSetTxLogged)(void *alstate, void *tx, LoggerId logger)
void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto, FileContainer *(*StateGetFiles)(void *, uint8_t))
void StreamTcpSetSessionBypassFlag(TcpSession *)
enable bypass
Definition: stream-tcp.c:5812
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
#define BOTH_SET_OR_BOTH_UNSET(a, b)
Data structures and function prototypes for keeping state for the detection engine.
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, int *event_id, AppLayerEventType *event_type))
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:111
void AppLayerParserSetDecoderEvents(AppLayerParserState *pstate, AppLayerDecoderEvents *devents)
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_NOPAYLOAD_INSPECTION
Definition: flow.h:60
void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
#define IS_DISRUPTED(flags)
#define STREAM_EOF
Definition: stream.h:30
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void AppLayerParserSetEOF(AppLayerParserState *pstate)
void RegisterFTPParsers(void)
#define DEBUG_ASSERT_FLOW_LOCKED(f)
#define APP_LAYER_PARSER_NO_INSPECTION
uint64_t AppLayerParserGetTransactionActive(const Flow *f, AppLayerParserState *pstate, uint8_t direction)
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
void *(* StateAlloc)(void)
void StreamTcpSetDisableRawReassemblyFlag(TcpSession *ssn, char direction)
Set the No reassembly flag for the given direction in given TCP session.
Definition: stream-tcp.c:5801
void RegisterHTPParsers(void)
Register the HTTP protocol and state handling functions to APP layer of the engine.
void *(* StateGetTx)(void *alstate, uint64_t tx_id)
void AppLayerParserRegisterUnittests(void)
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:591
uint32_t AppLayerParserGetStreamDepth(const Flow *f)
AppLayerParserProtoCtx ctxs[FLOW_PROTO_MAX][ALPROTO_MAX]
#define STREAM_TOCLIENT
Definition: stream.h:32
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
void RegisterIKEV2Parsers(void)
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
App layer protocol parser context.
FileContainer *(* StateGetFiles)(void *, uint8_t)
void(* LocalStorageFree)(void *)
int RunmodeIsUnittests(void)
Definition: suricata.c:259
void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
#define SCReturnInt(x)
Definition: util-debug.h:341
uint64_t(* GetTxDetectFlags)(void *tx, uint8_t dir)
void(* RegisterUnittests)(void)
int AppLayerParserSetup(void)
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
uint32_t reassembly_depth
Definition: stream-tcp.h:60
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
AppLayerParserState * AppLayerParserStateAlloc(void)
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
void RegisterENIPTCPParsers(void)
Function to register the ENIP protocol parsers and other functions.
Definition: conf.h:32
#define SCMalloc(a)
Definition: util-mem.h:166
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
void AppLayerParserTransactionsCleanup(Flow *f)
remove obsolete (inspected and logged) transactions
uint64_t(* StateGetTxCnt)(void *alstate)
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step)
Definition: app-layer.c:113
#define SCFree(a)
Definition: util-mem.h:228
int(* StateGetProgressCompletionStatus)(uint8_t direction)
Port dp
Definition: flow.h:337
int AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction)
Registers a case-sensitive pattern for protocol detection.
uint16_t tx_id
struct AppLayerParserCtx_ AppLayerParserCtx
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
void RegisterSSLParsers(void)
Function to register the SSL protocol parser and other functions.
void SMTPParserCleanup(void)
Free memory allocated for global SMTP parser state.
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
AppLayerDecoderEvents *(* StateGetEvents)(void *, uint64_t)
const struct SigGroupHead_ * sgh_toserver
Definition: flow.h:440
#define STREAM_START
Definition: stream.h:29
void RegisterModbusParsers(void)
Function to register the Modbus protocol parsers and other functions.
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
AppLayerParserFPtr Parser[2]
#define STREAM_TOSERVER
Definition: stream.h:31
#define APP_LAYER_PARSER_OPT_ACCEPT_GAPS
#define APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD
#define SCReturnPtr(x, type)
Definition: util-debug.h:353
void RegisterKRB5Parsers(void)
void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto, AppLayerGetTxIteratorFunc Func)
void RegisterTemplateRustParsers(void)
void AppLayerParserSetTxLogged(uint8_t ipproto, AppProto alproto, void *alstate, void *tx, LoggerId logger)
#define APP_LAYER_PARSER_EOF
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
AppLayerDecoderEvents * decoder_events
FlowAddress src
Definition: flow.h:328
void RegisterDCERPCParsers(void)
void RegisterDNP3Parsers(void)
Register the DNP3 application protocol parser.
int(* SetTxDetectState)(void *tx, DetectEngineState *)
const char * AppLayerGetProtoName(AppProto alproto)
Given the internal protocol id, returns a string representation of the protocol.
Definition: app-layer.c:749
void AppLayerParserDestroyProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto, void *local_data)
struct TestState_ TestState
#define SCReturn
Definition: util-debug.h:339
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
Per thread variable structure.
Definition: threadvars.h:57
AppProto alproto
application level protocol
Definition: flow.h:404
void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
void RegisterDNSUDPParsers(void)
LoggerId AppLayerParserProtocolGetLoggerBits(uint8_t ipproto, AppProto alproto)
FileContainer * AppLayerParserGetFiles(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t direction)
DetectEngineState * AppLayerParserGetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx)
void AppLayerParserSetTxDetectFlags(uint8_t ipproto, AppProto alproto, void *tx, uint8_t dir, uint64_t flags)
#define likely(expr)
Definition: util-optimize.h:32
bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
AppLayerGetTxIteratorFunc StateGetTxIterator
int AppLayerParserProtocolIsTxAware(uint8_t ipproto, AppProto alproto)
int(* StateGetEventInfo)(const char *event_name, int *event_id, AppLayerEventType *event_type)
uint8_t protomap
Definition: flow.h:399
Flow data structure.
Definition: flow.h:324
#define FLOW_IPV4
Definition: flow.h:93
void AppLayerParserStateSetFlag(AppLayerParserState *pstate, uint8_t flag)
void(* StateTransactionFree)(void *, uint64_t)
uint32_t flags
Definition: flow.h:374
int AppLayerParserProtocolSupportsTxs(uint8_t ipproto, AppProto alproto)
int AppLayerParserSetTxDetectState(const Flow *f, void *tx, DetectEngineState *s)
#define APP_LAYER_PARSER_INT_STREAM_DEPTH_SET
int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name, int *event_id, AppLayerEventType *event_type)
AppLayerParserState * alparser
Definition: flow.h:432
uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
void UTHFreeFlow(Flow *flow)
int AppLayerParserProtoIsRegistered(uint8_t ipproto, AppProto alproto)
uint64_t AppLayerParserGetTxDetectFlags(uint8_t ipproto, AppProto alproto, void *tx, uint8_t dir)
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
void AppLayerParserRegisterMpmIDsFuncs(uint8_t ipproto, AppProto alproto, uint64_t(*GetTxMpmIDs)(void *tx), int(*SetTxMpmIDs)(void *tx, uint64_t))
AppLayerGetTxIterTuple(* AppLayerGetTxIteratorFunc)(const uint8_t ipproto, const AppProto alproto, void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *state)
tx iterator prototype