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