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