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