suricata
app-layer-detect-proto.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 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  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23  */
24 
25 #include "suricata-common.h"
26 #include "debug.h"
27 #include "decode.h"
28 #include "threads.h"
29 #include "threadvars.h"
30 #include "tm-threads.h"
31 
32 #include "detect.h"
33 #include "detect-engine-port.h"
34 #include "detect-parse.h"
35 #include "detect-engine.h"
36 #include "detect-content.h"
37 #include "detect-engine-mpm.h"
38 #include "detect-engine-state.h"
39 
40 #include "util-print.h"
41 #include "util-pool.h"
42 #include "util-unittest.h"
43 #include "util-unittest-helper.h"
44 
45 #include "flow.h"
46 #include "flow-util.h"
47 #include "flow-private.h"
48 
49 #include "stream-tcp-private.h"
50 #include "stream-tcp-reassemble.h"
51 #include "stream-tcp.h"
52 #include "stream.h"
53 
54 #include "app-layer.h"
55 #include "app-layer-protos.h"
56 #include "app-layer-parser.h"
57 #include "app-layer-detect-proto.h"
58 #include "app-layer-expectation.h"
59 
60 #include "conf.h"
61 #include "util-memcmp.h"
62 #include "util-spm.h"
63 #include "util-debug.h"
64 
65 #include "runmodes.h"
66 
69  /* \todo don't really need it. See if you can get rid of it */
70  uint16_t port;
71  /* \todo calculate at runtime and get rid of this var */
72  uint32_t alproto_mask;
73  /* \todo check if we can reduce the bottom 2 vars to uint16_t */
74  /* the min length of data that has to be supplied to invoke the parser */
75  uint32_t min_depth;
76  /* the max length of data after which this parser won't be invoked */
77  uint32_t max_depth;
78 
79  /* the to_server probing parser function */
81 
82  /* the to_client probing parser function */
84 
87 
89  /* the port no for which probing parser(s) are invoked */
90  uint16_t port;
91 
92  uint32_t alproto_mask;
93 
94  /* the max depth for all the probing parsers registered for this port */
95  uint16_t dp_max_depth;
96  uint16_t sp_max_depth;
97 
100 
103 
105  uint8_t ipproto;
107 
110 
113  uint8_t direction; /**< direction for midstream */
115  /* \todo Change this into a non-pointer */
117  uint16_t pp_min_depth;
118  uint16_t pp_max_depth;
122 
124  uint16_t pp_max_len;
125  uint16_t min_len;
127 
128  /** Mapping between pattern id and signature. As each signature has a
129  * unique pattern with a unique id, we can lookup the signature by
130  * the pattern id. */
133 
134  /* \todo we don't need this except at setup time. Get rid of it. */
138 
140  /* 0 - toserver, 1 - toclient */
143 
144 /**
145  * \brief The app layer protocol detection context.
146  */
147 typedef struct AppLayerProtoDetectCtx_ {
148  /* Context per ip_proto.
149  * \todo Modify ctx_ipp to hold for only tcp and udp. The rest can be
150  * implemented if needed. Waste of space otherwise. */
152 
153  /* Global SPM thread context prototype. */
155 
157 
158  /* Indicates the protocols that have registered themselves
159  * for protocol detection. This table is independent of the
160  * ipproto. */
163 
164 /**
165  * \brief The app layer protocol detection thread context.
166  */
169  /* The value 2 is for direction(0 - toserver, 1 - toclient). */
172 };
173 
174 /* The global app layer proto detection context. */
175 static AppLayerProtoDetectCtx alpd_ctx;
176 
177 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
178  uint8_t *ipprotos);
179 
180 /***** Static Internal Calls: Protocol Retrieval *****/
181 
182 /** \internal
183  * \brief Handle SPM search for Signature
184  * \param buflen full size of the input buffer
185  * \param searchlen pattern matching portion of buffer */
186 static AppProto AppLayerProtoDetectPMMatchSignature(
189  Flow *f, uint8_t direction,
190  const uint8_t *buf, uint16_t buflen, uint16_t searchlen,
191  bool *rflow)
192 {
193  SCEnter();
194 
195  if (s->cd->offset > searchlen) {
196  SCLogDebug("s->co->offset (%"PRIu16") > searchlen (%"PRIu16")",
197  s->cd->offset, searchlen);
199  }
200  if (s->cd->depth > searchlen) {
201  SCLogDebug("s->co->depth (%"PRIu16") > searchlen (%"PRIu16")",
202  s->cd->depth, searchlen);
204  }
205 
206  const uint8_t *sbuf = buf + s->cd->offset;
207  uint16_t ssearchlen = s->cd->depth - s->cd->offset;
208  SCLogDebug("s->co->offset (%"PRIu16") s->cd->depth (%"PRIu16")",
209  s->cd->offset, s->cd->depth);
210 
211  uint8_t *found = SpmScan(s->cd->spm_ctx, tctx->spm_thread_ctx,
212  sbuf, ssearchlen);
213  if (found == NULL) {
215  }
216 
217  SCLogDebug("matching, s->direction %s, our dir %s",
218  (s->direction & STREAM_TOSERVER) ? "toserver" : "toclient",
219  (direction & STREAM_TOSERVER) ? "toserver" : "toclient");
220  if (s->PPFunc == NULL) {
221  if ((direction & (STREAM_TOSERVER|STREAM_TOCLIENT)) == s->direction) {
222  SCLogDebug("direction is correct");
223  } else {
224  SCLogDebug("direction is wrong, rflow = true");
225  *rflow = true;
226  }
227  /* validate using Probing Parser */
228  } else {
229  if (s->pp_min_depth > buflen) {
230  SCLogDebug("PP can't be run yet as pp_min_depth %u > buflen %u",
231  s->pp_min_depth, buflen);
233  }
234 
235  uint8_t rdir = 0;
236  AppProto r = s->PPFunc(f, direction, buf, buflen, &rdir);
237  if (r == s->alproto) {
238  SCLogDebug("found %s/%u, rdir %02x reverse_flow? %s",
239  AppProtoToString(r), r, rdir,
240  (rdir && direction != rdir) ? "true" : "false");
241  *rflow = (rdir && direction != rdir);
242  SCReturnUInt(s->alproto);
243  } else if (r == ALPROTO_FAILED) {
245  } else {
246  /* unknown: lets see if we will try again later */
247  if (s->pp_max_depth < buflen) {
248  SCLogDebug("depth reached and answer inconclusive: fail");
250  }
252  }
253  }
254  SCReturnUInt(s->alproto);
255 }
256 
257 /**
258  * \retval 0 no matches
259  * \retval -1 no matches, mpm depth reached
260  */
261 static inline int PMGetProtoInspect(
263  AppLayerProtoDetectPMCtx *pm_ctx,
264  MpmThreadCtx *mpm_tctx,
265  Flow *f, const uint8_t *buf, uint16_t buflen,
266  uint8_t direction, AppProto *pm_results, bool *rflow)
267 {
268  int pm_matches = 0;
269 
270  uint16_t searchlen = MIN(buflen, pm_ctx->mpm_ctx.maxdepth);
271  SCLogDebug("searchlen %u buflen %u", searchlen, buflen);
272 
273  /* do the mpm search */
274  uint32_t search_cnt = mpm_table[pm_ctx->mpm_ctx.mpm_type].Search(
275  &pm_ctx->mpm_ctx, mpm_tctx, &tctx->pmq,
276  buf, searchlen);
277  if (search_cnt == 0) {
278  if (buflen >= pm_ctx->mpm_ctx.maxdepth)
279  return -1;
280  return 0;
281  }
282 
283  /* alproto bit field */
284  uint8_t pm_results_bf[(ALPROTO_MAX / 8) + 1];
285  memset(pm_results_bf, 0, sizeof(pm_results_bf));
286 
287  /* loop through unique pattern id's. Can't use search_cnt here,
288  * as that contains all matches, tctx->pmq.pattern_id_array_cnt
289  * contains only *unique* matches. */
290  for (uint32_t cnt = 0; cnt < tctx->pmq.rule_id_array_cnt; cnt++) {
291  const AppLayerProtoDetectPMSignature *s = pm_ctx->map[tctx->pmq.rule_id_array[cnt]];
292  while (s != NULL) {
293  AppProto proto = AppLayerProtoDetectPMMatchSignature(s,
294  tctx, f, direction, buf, buflen, searchlen, rflow);
295 
296  /* store each unique proto once */
297  if (AppProtoIsValid(proto) &&
298  !(pm_results_bf[proto / 8] & (1 << (proto % 8))) )
299  {
300  pm_results[pm_matches++] = proto;
301  pm_results_bf[proto / 8] |= 1 << (proto % 8);
302  }
303  s = s->next;
304  }
305  }
306  if (pm_matches == 0 && buflen >= pm_ctx->pp_max_len) {
307  pm_matches = -2;
308  }
309  PmqReset(&tctx->pmq);
310  return pm_matches;
311 }
312 
313 /** \internal
314  * \brief Run Pattern Sigs against buffer
315  * \param direction direction for the patterns
316  * \param pm_results[out] AppProto array of size ALPROTO_MAX */
317 static AppProto AppLayerProtoDetectPMGetProto(
319  Flow *f, const uint8_t *buf, uint16_t buflen,
320  uint8_t direction, AppProto *pm_results, bool *rflow)
321 {
322  SCEnter();
323 
324  pm_results[0] = ALPROTO_UNKNOWN;
325 
326  AppLayerProtoDetectPMCtx *pm_ctx;
327  MpmThreadCtx *mpm_tctx;
328  int m = -1;
329 
330  if (f->protomap >= FLOW_PROTO_DEFAULT)
331  return ALPROTO_FAILED;
332 
333  if (direction & STREAM_TOSERVER) {
334  pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
335  mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
336  } else {
337  pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
338  mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
339  }
340  if (likely(pm_ctx->mpm_ctx.pattern_cnt > 0)) {
341  m = PMGetProtoInspect(tctx,
342  pm_ctx, mpm_tctx,
343  f, buf, buflen, direction,
344  pm_results, rflow);
345 
346  }
347  /* pattern found, yay */
348  if (m > 0) {
349  FLOW_SET_PM_DONE(f, direction);
350  SCReturnUInt((uint16_t)m);
351 
352  /* handle non-found in non-midstream case */
353  } else if (!stream_config.midstream) {
354  /* we can give up if mpm gave no results and its search depth
355  * was reached. */
356  if (m < 0) {
357  FLOW_SET_PM_DONE(f, direction);
358  SCReturnUInt(0);
359  } else if (m == 0) {
360  SCReturnUInt(0);
361  }
362  SCReturnUInt((uint16_t)m);
363 
364  /* handle non-found in midstream case */
365  } else if (m <= 0) {
366  if (direction & STREAM_TOSERVER) {
367  pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
368  mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
369  } else {
370  pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
371  mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
372  }
373  SCLogDebug("no matches and in midstream mode, lets try the "
374  "*patterns for the other side");
375 
376  int om = -1;
377  if (likely(pm_ctx->mpm_ctx.pattern_cnt > 0)) {
378  om = PMGetProtoInspect(tctx,
379  pm_ctx, mpm_tctx,
380  f, buf, buflen, direction,
381  pm_results, rflow);
382  }
383  /* found! */
384  if (om > 0) {
385  FLOW_SET_PM_DONE(f, direction);
386  SCReturnUInt((uint16_t)om);
387 
388  /* both sides failed */
389  } else if (om < 0 && m && m < 0) {
390  FLOW_SET_PM_DONE(f, direction);
391  SCReturnUInt(0);
392 
393  /* one side still uncertain */
394  } else if (om == 0 || m == 0) {
395  SCReturnUInt(0);
396  }
397  }
398  SCReturnUInt(0);
399 }
400 
401 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser *pp,
402  uint8_t ipproto,
403  uint16_t port)
404 {
405  AppLayerProtoDetectProbingParserPort *pp_port = NULL;
406 
407  while (pp != NULL) {
408  if (pp->ipproto == ipproto)
409  break;
410 
411  pp = pp->next;
412  }
413 
414  if (pp == NULL)
415  goto end;
416 
417  pp_port = pp->port;
418  while (pp_port != NULL) {
419  if (pp_port->port == port || pp_port->port == 0) {
420  break;
421  }
422  pp_port = pp_port->next;
423  }
424 
425  end:
426  SCReturnPtr(pp_port, "AppLayerProtoDetectProbingParserPort *");
427 }
428 
429 
430 /**
431  * \brief Call the probing expectation to see if there is some for this flow.
432  *
433  */
434 static AppProto AppLayerProtoDetectPEGetProto(Flow *f, uint8_t ipproto,
435  uint8_t direction)
436 {
437  AppProto alproto = ALPROTO_UNKNOWN;
438 
439  SCLogDebug("expectation check for %p (dir %d)", f, direction);
440  FLOW_SET_PE_DONE(f, direction);
441 
442  alproto = AppLayerExpectationHandle(f, direction);
443 
444  return alproto;
445 }
446 
447 static inline AppProto PPGetProto(
449  Flow *f, uint8_t direction,
450  const uint8_t *buf, uint32_t buflen,
451  uint32_t *alproto_masks, uint8_t *rdir
452 )
453 {
454  while (pe != NULL) {
455  if ((buflen < pe->min_depth) ||
456  (alproto_masks[0] & pe->alproto_mask)) {
457  pe = pe->next;
458  continue;
459  }
460 
461  AppProto alproto = ALPROTO_UNKNOWN;
462  if (direction & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
463  alproto = pe->ProbingParserTs(f, direction, buf, buflen, rdir);
464  } else if (pe->ProbingParserTc != NULL) {
465  alproto = pe->ProbingParserTc(f, direction, buf, buflen, rdir);
466  }
467  if (AppProtoIsValid(alproto)) {
468  SCReturnUInt(alproto);
469  }
470  if (alproto == ALPROTO_FAILED ||
471  (pe->max_depth != 0 && buflen > pe->max_depth)) {
472  alproto_masks[0] |= pe->alproto_mask;
473  }
474  pe = pe->next;
475  }
476 
478 }
479 
480 /**
481  * \brief Call the probing parser if it exists for this flow.
482  *
483  * First we check the flow's dp as it's most likely to match. If that didn't
484  * lead to a PP, we try the sp.
485  *
486  */
487 static AppProto AppLayerProtoDetectPPGetProto(Flow *f,
488  const uint8_t *buf, uint32_t buflen,
489  uint8_t ipproto, const uint8_t idir,
490  bool *reverse_flow)
491 {
492  const AppLayerProtoDetectProbingParserPort *pp_port_dp = NULL;
493  const AppLayerProtoDetectProbingParserPort *pp_port_sp = NULL;
494  const AppLayerProtoDetectProbingParserElement *pe1 = NULL;
495  const AppLayerProtoDetectProbingParserElement *pe2 = NULL;
496  AppProto alproto = ALPROTO_UNKNOWN;
497  uint32_t *alproto_masks;
498  uint32_t mask = 0;
499  uint8_t dir = idir;
500  uint16_t dp = f->protodetect_dp ? f->protodetect_dp : FLOW_GET_DP(f);
501  uint16_t sp = FLOW_GET_SP(f);
502 
503 again_midstream:
504  if (idir != dir) {
505  SWAP_VARS(uint16_t, dp, sp); /* look up parsers in rev dir */
506  }
507  SCLogDebug("%u->%u %s", sp, dp,
508  (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
509 
510  if (dir == STREAM_TOSERVER) {
511  /* first try the destination port */
512  pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
513  alproto_masks = &f->probing_parser_toserver_alproto_masks;
514  if (pp_port_dp != NULL) {
515  SCLogDebug("toserver - Probing parser found for destination port %"PRIu16, dp);
516 
517  /* found based on destination port, so use dp registration */
518  pe1 = pp_port_dp->dp;
519  } else {
520  SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16, dp);
521  }
522 
523  pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
524  if (pp_port_sp != NULL) {
525  SCLogDebug("toserver - Probing parser found for source port %"PRIu16, sp);
526 
527  /* found based on source port, so use sp registration */
528  pe2 = pp_port_sp->sp;
529  } else {
530  SCLogDebug("toserver - No probing parser registered for source port %"PRIu16, sp);
531  }
532  } else {
533  /* first try the destination port */
534  pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
535  alproto_masks = &f->probing_parser_toclient_alproto_masks;
536  if (pp_port_dp != NULL) {
537  SCLogDebug("toclient - Probing parser found for destination port %"PRIu16, dp);
538 
539  /* found based on destination port, so use dp registration */
540  pe1 = pp_port_dp->dp;
541  } else {
542  SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16, dp);
543  }
544 
545  pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
546  if (pp_port_sp != NULL) {
547  SCLogDebug("toclient - Probing parser found for source port %"PRIu16, sp);
548 
549  pe2 = pp_port_sp->sp;
550  } else {
551  SCLogDebug("toclient - No probing parser registered for source port %"PRIu16, sp);
552  }
553  }
554 
555  if (pe1 == NULL && pe2 == NULL) {
556  SCLogDebug("%s - No probing parsers found for either port",
557  (dir == STREAM_TOSERVER) ? "toserver":"toclient");
558  if (dir == idir)
559  FLOW_SET_PP_DONE(f, dir);
560  goto noparsers;
561  }
562 
563  /* run the parser(s): always call with original direction */
564  uint8_t rdir = 0;
565  alproto = PPGetProto(pe1, f, idir, buf, buflen, alproto_masks, &rdir);
566  if (AppProtoIsValid(alproto))
567  goto end;
568  alproto = PPGetProto(pe2, f, idir, buf, buflen, alproto_masks, &rdir);
569  if (AppProtoIsValid(alproto))
570  goto end;
571 
572  /* get the mask we need for this direction */
573  if (dir == idir) {
574  if (pp_port_dp && pp_port_sp)
575  mask = pp_port_dp->alproto_mask|pp_port_sp->alproto_mask;
576  else if (pp_port_dp)
577  mask = pp_port_dp->alproto_mask;
578  else if (pp_port_sp)
579  mask = pp_port_sp->alproto_mask;
580 
581  if (alproto_masks[0] == mask) {
582  FLOW_SET_PP_DONE(f, dir);
583  SCLogDebug("%s, mask is now %08x, needed %08x, so done",
584  (dir == STREAM_TOSERVER) ? "toserver":"toclient",
585  alproto_masks[0], mask);
586  } else {
587  SCLogDebug("%s, mask is now %08x, need %08x",
588  (dir == STREAM_TOSERVER) ? "toserver":"toclient",
589  alproto_masks[0], mask);
590  }
591  }
592 
593  noparsers:
594  if (stream_config.midstream == true && idir == dir) {
595  if (idir == STREAM_TOSERVER) {
596  dir = STREAM_TOCLIENT;
597  } else {
598  dir = STREAM_TOSERVER;
599  }
600  SCLogDebug("no match + midstream, retry the other direction %s",
601  (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
602  goto again_midstream;
603  }
604 
605  end:
606  if (AppProtoIsValid(alproto) && rdir != 0 && rdir != idir) {
607  SCLogDebug("PP found %u, is reverse flow", alproto);
608  *reverse_flow = true;
609  }
610 
611  SCLogDebug("%s, mask is now %08x",
612  (idir == STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
613  SCReturnUInt(alproto);
614 }
615 
616 /***** Static Internal Calls: PP registration *****/
617 
618 static void AppLayerProtoDetectPPGetIpprotos(AppProto alproto,
619  uint8_t *ipprotos)
620 {
621  SCEnter();
622 
626 
627  for (pp = alpd_ctx.ctx_pp; pp != NULL; pp = pp->next) {
628  for (pp_port = pp->port; pp_port != NULL; pp_port = pp_port->next) {
629  for (pp_pe = pp_port->dp; pp_pe != NULL; pp_pe = pp_pe->next) {
630  if (alproto == pp_pe->alproto)
631  ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
632  }
633  for (pp_pe = pp_port->sp; pp_pe != NULL; pp_pe = pp_pe->next) {
634  if (alproto == pp_pe->alproto)
635  ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
636  }
637  }
638  }
639 
640  SCReturn;
641 }
642 
643 static uint32_t AppLayerProtoDetectProbingParserGetMask(AppProto alproto)
644 {
645  SCEnter();
646 
647  if (!(alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_FAILED)) {
648  FatalError(SC_ERR_ALPARSER, "Unknown protocol detected - %u", alproto);
649  }
650 
651  SCReturnUInt(1UL << (uint32_t)alproto);
652 }
653 
654 static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectProbingParserElementAlloc(void)
655 {
656  SCEnter();
657 
659  if (unlikely(p == NULL)) {
660  exit(EXIT_FAILURE);
661  }
662  memset(p, 0, sizeof(AppLayerProtoDetectProbingParserElement));
663 
664  SCReturnPtr(p, "AppLayerProtoDetectProbingParserElement");
665 }
666 
667 
668 static void AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement *p)
669 {
670  SCEnter();
671  SCFree(p);
672  SCReturn;
673 }
674 
675 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectProbingParserPortAlloc(void)
676 {
677  SCEnter();
678 
680  if (unlikely(p == NULL)) {
681  exit(EXIT_FAILURE);
682  }
683  memset(p, 0, sizeof(AppLayerProtoDetectProbingParserPort));
684 
685  SCReturnPtr(p, "AppLayerProtoDetectProbingParserPort");
686 }
687 
688 static void AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort *p)
689 {
690  SCEnter();
691 
693 
694  e = p->dp;
695  while (e != NULL) {
697  AppLayerProtoDetectProbingParserElementFree(e);
698  e = e_next;
699  }
700 
701  e = p->sp;
702  while (e != NULL) {
704  AppLayerProtoDetectProbingParserElementFree(e);
705  e = e_next;
706  }
707 
708  SCFree(p);
709 
710  SCReturn;
711 }
712 
713 static AppLayerProtoDetectProbingParser *AppLayerProtoDetectProbingParserAlloc(void)
714 {
715  SCEnter();
716 
718  if (unlikely(p == NULL)) {
719  exit(EXIT_FAILURE);
720  }
721  memset(p, 0, sizeof(AppLayerProtoDetectProbingParser));
722 
723  SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
724 }
725 
726 static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser *p)
727 {
728  SCEnter();
729 
731  while (pt != NULL) {
733  AppLayerProtoDetectProbingParserPortFree(pt);
734  pt = pt_next;
735  }
736 
737  SCFree(p);
738 
739  SCReturn;
740 }
741 
743 AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
744  uint16_t port,
745  uint16_t min_depth,
746  uint16_t max_depth)
747 {
748  AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
749 
750  pe->alproto = alproto;
751  pe->port = port;
752  pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
753  pe->min_depth = min_depth;
754  pe->max_depth = max_depth;
755  pe->next = NULL;
756 
757  if (max_depth != 0 && min_depth >= max_depth) {
758  SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to "
759  "register the probing parser. min_depth >= max_depth");
760  goto error;
761  }
762  if (alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_MAX) {
763  SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to register "
764  "the probing parser. Invalid alproto - %d", alproto);
765  goto error;
766  }
767 
768  SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
769  error:
770  AppLayerProtoDetectProbingParserElementFree(pe);
771  SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
772 }
773 
775 AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement *pe)
776 {
777  SCEnter();
778 
779  AppLayerProtoDetectProbingParserElement *new_pe = AppLayerProtoDetectProbingParserElementAlloc();
780 
781  new_pe->alproto = pe->alproto;
782  new_pe->port = pe->port;
783  new_pe->alproto_mask = pe->alproto_mask;
784  new_pe->min_depth = pe->min_depth;
785  new_pe->max_depth = pe->max_depth;
786  new_pe->ProbingParserTs = pe->ProbingParserTs;
787  new_pe->ProbingParserTc = pe->ProbingParserTc;
788  new_pe->next = NULL;
789 
790  SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
791 }
792 
793 #ifdef DEBUG
794 static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser *pp)
795 {
796  SCEnter();
797 
798  AppLayerProtoDetectProbingParserPort *pp_port = NULL;
800 
801  printf("\nProtocol Detection Configuration\n");
802 
803  for ( ; pp != NULL; pp = pp->next) {
804  /* print ip protocol */
805  if (pp->ipproto == IPPROTO_TCP)
806  printf("IPProto: TCP\n");
807  else if (pp->ipproto == IPPROTO_UDP)
808  printf("IPProto: UDP\n");
809  else
810  printf("IPProto: %"PRIu8"\n", pp->ipproto);
811 
812  pp_port = pp->port;
813  for ( ; pp_port != NULL; pp_port = pp_port->next) {
814  if (pp_port->dp != NULL) {
815  printf(" Port: %"PRIu16 "\n", pp_port->port);
816 
817  printf(" Destination port: (max-depth: %"PRIu16 ", "
818  "mask - %"PRIu32")\n",
819  pp_port->dp_max_depth,
820  pp_port->alproto_mask);
821  pp_pe = pp_port->dp;
822  for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
823 
824  if (pp_pe->alproto == ALPROTO_HTTP)
825  printf(" alproto: ALPROTO_HTTP\n");
826  else if (pp_pe->alproto == ALPROTO_FTP)
827  printf(" alproto: ALPROTO_FTP\n");
828  else if (pp_pe->alproto == ALPROTO_FTPDATA)
829  printf(" alproto: ALPROTO_FTPDATA\n");
830  else if (pp_pe->alproto == ALPROTO_SMTP)
831  printf(" alproto: ALPROTO_SMTP\n");
832  else if (pp_pe->alproto == ALPROTO_TLS)
833  printf(" alproto: ALPROTO_TLS\n");
834  else if (pp_pe->alproto == ALPROTO_SSH)
835  printf(" alproto: ALPROTO_SSH\n");
836  else if (pp_pe->alproto == ALPROTO_IMAP)
837  printf(" alproto: ALPROTO_IMAP\n");
838  else if (pp_pe->alproto == ALPROTO_JABBER)
839  printf(" alproto: ALPROTO_JABBER\n");
840  else if (pp_pe->alproto == ALPROTO_SMB)
841  printf(" alproto: ALPROTO_SMB\n");
842  else if (pp_pe->alproto == ALPROTO_DCERPC)
843  printf(" alproto: ALPROTO_DCERPC\n");
844  else if (pp_pe->alproto == ALPROTO_IRC)
845  printf(" alproto: ALPROTO_IRC\n");
846  else if (pp_pe->alproto == ALPROTO_DNS)
847  printf(" alproto: ALPROTO_DNS\n");
848  else if (pp_pe->alproto == ALPROTO_MODBUS)
849  printf(" alproto: ALPROTO_MODBUS\n");
850  else if (pp_pe->alproto == ALPROTO_ENIP)
851  printf(" alproto: ALPROTO_ENIP\n");
852  else if (pp_pe->alproto == ALPROTO_NFS)
853  printf(" alproto: ALPROTO_NFS\n");
854  else if (pp_pe->alproto == ALPROTO_NTP)
855  printf(" alproto: ALPROTO_NTP\n");
856  else if (pp_pe->alproto == ALPROTO_TFTP)
857  printf(" alproto: ALPROTO_TFTP\n");
858  else if (pp_pe->alproto == ALPROTO_IKEV2)
859  printf(" alproto: ALPROTO_IKEV2\n");
860  else if (pp_pe->alproto == ALPROTO_KRB5)
861  printf(" alproto: ALPROTO_KRB5\n");
862  else if (pp_pe->alproto == ALPROTO_DHCP)
863  printf(" alproto: ALPROTO_DHCP\n");
864  else if (pp_pe->alproto == ALPROTO_SNMP)
865  printf(" alproto: ALPROTO_SNMP\n");
866  else if (pp_pe->alproto == ALPROTO_SIP)
867  printf(" alproto: ALPROTO_SIP\n");
868  else if (pp_pe->alproto == ALPROTO_TEMPLATE_RUST)
869  printf(" alproto: ALPROTO_TEMPLATE_RUST\n");
870  else if (pp_pe->alproto == ALPROTO_RFB)
871  printf(" alproto: ALPROTO_RFB\n");
872  else if (pp_pe->alproto == ALPROTO_MQTT)
873  printf(" alproto: ALPROTO_MQTT\n");
874  else if (pp_pe->alproto == ALPROTO_TEMPLATE)
875  printf(" alproto: ALPROTO_TEMPLATE\n");
876  else if (pp_pe->alproto == ALPROTO_DNP3)
877  printf(" alproto: ALPROTO_DNP3\n");
878  else
879  printf("impossible\n");
880 
881  printf(" port: %"PRIu16 "\n", pp_pe->port);
882  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
883  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
884  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
885 
886  printf("\n");
887  }
888  }
889 
890  if (pp_port->sp == NULL) {
891  continue;
892  }
893 
894  printf(" Source port: (max-depth: %"PRIu16 ", "
895  "mask - %"PRIu32")\n",
896  pp_port->sp_max_depth,
897  pp_port->alproto_mask);
898  pp_pe = pp_port->sp;
899  for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
900 
901  if (pp_pe->alproto == ALPROTO_HTTP)
902  printf(" alproto: ALPROTO_HTTP\n");
903  else if (pp_pe->alproto == ALPROTO_FTP)
904  printf(" alproto: ALPROTO_FTP\n");
905  else if (pp_pe->alproto == ALPROTO_FTPDATA)
906  printf(" alproto: ALPROTO_FTPDATA\n");
907  else if (pp_pe->alproto == ALPROTO_SMTP)
908  printf(" alproto: ALPROTO_SMTP\n");
909  else if (pp_pe->alproto == ALPROTO_TLS)
910  printf(" alproto: ALPROTO_TLS\n");
911  else if (pp_pe->alproto == ALPROTO_SSH)
912  printf(" alproto: ALPROTO_SSH\n");
913  else if (pp_pe->alproto == ALPROTO_IMAP)
914  printf(" alproto: ALPROTO_IMAP\n");
915  else if (pp_pe->alproto == ALPROTO_JABBER)
916  printf(" alproto: ALPROTO_JABBER\n");
917  else if (pp_pe->alproto == ALPROTO_SMB)
918  printf(" alproto: ALPROTO_SMB\n");
919  else if (pp_pe->alproto == ALPROTO_DCERPC)
920  printf(" alproto: ALPROTO_DCERPC\n");
921  else if (pp_pe->alproto == ALPROTO_IRC)
922  printf(" alproto: ALPROTO_IRC\n");
923  else if (pp_pe->alproto == ALPROTO_DNS)
924  printf(" alproto: ALPROTO_DNS\n");
925  else if (pp_pe->alproto == ALPROTO_MODBUS)
926  printf(" alproto: ALPROTO_MODBUS\n");
927  else if (pp_pe->alproto == ALPROTO_ENIP)
928  printf(" alproto: ALPROTO_ENIP\n");
929  else if (pp_pe->alproto == ALPROTO_NFS)
930  printf(" alproto: ALPROTO_NFS\n");
931  else if (pp_pe->alproto == ALPROTO_NTP)
932  printf(" alproto: ALPROTO_NTP\n");
933  else if (pp_pe->alproto == ALPROTO_TFTP)
934  printf(" alproto: ALPROTO_TFTP\n");
935  else if (pp_pe->alproto == ALPROTO_IKEV2)
936  printf(" alproto: ALPROTO_IKEV2\n");
937  else if (pp_pe->alproto == ALPROTO_KRB5)
938  printf(" alproto: ALPROTO_KRB5\n");
939  else if (pp_pe->alproto == ALPROTO_DHCP)
940  printf(" alproto: ALPROTO_DHCP\n");
941  else if (pp_pe->alproto == ALPROTO_SNMP)
942  printf(" alproto: ALPROTO_SNMP\n");
943  else if (pp_pe->alproto == ALPROTO_SIP)
944  printf(" alproto: ALPROTO_SIP\n");
945  else if (pp_pe->alproto == ALPROTO_TEMPLATE_RUST)
946  printf(" alproto: ALPROTO_TEMPLATE_RUST\n");
947  else if (pp_pe->alproto == ALPROTO_RFB)
948  printf(" alproto: ALPROTO_RFB\n");
949  else if (pp_pe->alproto == ALPROTO_MQTT)
950  printf(" alproto: ALPROTO_MQTT\n");
951  else if (pp_pe->alproto == ALPROTO_TEMPLATE)
952  printf(" alproto: ALPROTO_TEMPLATE\n");
953  else if (pp_pe->alproto == ALPROTO_DNP3)
954  printf(" alproto: ALPROTO_DNP3\n");
955  else
956  printf("impossible\n");
957 
958  printf(" port: %"PRIu16 "\n", pp_pe->port);
959  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
960  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
961  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
962 
963  printf("\n");
964  }
965  }
966  }
967 
968  SCReturn;
969 }
970 #endif
971 
972 static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
974 {
975  SCEnter();
976 
977  if (*head_pe == NULL) {
978  *head_pe = new_pe;
979  goto end;
980  }
981 
982  if ((*head_pe)->port == 0) {
983  if (new_pe->port != 0) {
984  new_pe->next = *head_pe;
985  *head_pe = new_pe;
986  } else {
987  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
988  while (temp_pe->next != NULL)
989  temp_pe = temp_pe->next;
990  temp_pe->next = new_pe;
991  }
992  } else {
993  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
994  if (new_pe->port == 0) {
995  while (temp_pe->next != NULL)
996  temp_pe = temp_pe->next;
997  temp_pe->next = new_pe;
998  } else {
999  while (temp_pe->next != NULL && temp_pe->next->port != 0)
1000  temp_pe = temp_pe->next;
1001  new_pe->next = temp_pe->next;
1002  temp_pe->next = new_pe;
1003 
1004  }
1005  }
1006 
1007  end:
1008  SCReturn;
1009 }
1010 
1011 static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
1013 {
1014  SCEnter();
1015 
1016  if (*head_pp == NULL) {
1017  *head_pp = new_pp;
1018  goto end;
1019  }
1020 
1021  AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
1022  while (temp_pp->next != NULL)
1023  temp_pp = temp_pp->next;
1024  temp_pp->next = new_pp;
1025 
1026  end:
1027  SCReturn;
1028 }
1029 
1030 static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
1032 {
1033  SCEnter();
1034 
1035  if (*head_port == NULL) {
1036  *head_port = new_port;
1037  goto end;
1038  }
1039 
1040  if ((*head_port)->port == 0) {
1041  new_port->next = *head_port;
1042  *head_port = new_port;
1043  } else {
1044  AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
1045  while (temp_port->next != NULL && temp_port->next->port != 0) {
1046  temp_port = temp_port->next;
1047  }
1048  new_port->next = temp_port->next;
1049  temp_port->next = new_port;
1050  }
1051 
1052  end:
1053  SCReturn;
1054 }
1055 
1056 static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
1057  uint8_t ipproto,
1058  uint16_t port,
1059  AppProto alproto,
1060  uint16_t min_depth, uint16_t max_depth,
1061  uint8_t direction,
1062  ProbingParserFPtr ProbingParser1,
1063  ProbingParserFPtr ProbingParser2)
1064 {
1065  SCEnter();
1066 
1067  /* get the top level ipproto pp */
1068  AppLayerProtoDetectProbingParser *curr_pp = *pp;
1069  while (curr_pp != NULL) {
1070  if (curr_pp->ipproto == ipproto)
1071  break;
1072  curr_pp = curr_pp->next;
1073  }
1074  if (curr_pp == NULL) {
1075  AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
1076  new_pp->ipproto = ipproto;
1077  AppLayerProtoDetectProbingParserAppend(pp, new_pp);
1078  curr_pp = new_pp;
1079  }
1080 
1081  /* get the top level port pp */
1082  AppLayerProtoDetectProbingParserPort *curr_port = curr_pp->port;
1083  while (curr_port != NULL) {
1084  if (curr_port->port == port)
1085  break;
1086  curr_port = curr_port->next;
1087  }
1088  if (curr_port == NULL) {
1089  AppLayerProtoDetectProbingParserPort *new_port = AppLayerProtoDetectProbingParserPortAlloc();
1090  new_port->port = port;
1091  AppLayerProtoDetectProbingParserPortAppend(&curr_pp->port, new_port);
1092  curr_port = new_port;
1093  if (direction & STREAM_TOSERVER) {
1094  curr_port->dp_max_depth = max_depth;
1095  } else {
1096  curr_port->sp_max_depth = max_depth;
1097  }
1098 
1100 
1101  zero_port = curr_pp->port;
1102  while (zero_port != NULL && zero_port->port != 0) {
1103  zero_port = zero_port->next;
1104  }
1105  if (zero_port != NULL) {
1107 
1108  zero_pe = zero_port->dp;
1109  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1110  if (curr_port->dp == NULL)
1111  curr_port->dp_max_depth = zero_pe->max_depth;
1112  if (zero_pe->max_depth == 0)
1113  curr_port->dp_max_depth = zero_pe->max_depth;
1114  if (curr_port->dp_max_depth != 0 &&
1115  curr_port->dp_max_depth < zero_pe->max_depth) {
1116  curr_port->dp_max_depth = zero_pe->max_depth;
1117  }
1118 
1120  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1121  AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
1122  curr_port->alproto_mask |= dup_pe->alproto_mask;
1123  }
1124 
1125  zero_pe = zero_port->sp;
1126  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1127  if (curr_port->sp == NULL)
1128  curr_port->sp_max_depth = zero_pe->max_depth;
1129  if (zero_pe->max_depth == 0)
1130  curr_port->sp_max_depth = zero_pe->max_depth;
1131  if (curr_port->sp_max_depth != 0 &&
1132  curr_port->sp_max_depth < zero_pe->max_depth) {
1133  curr_port->sp_max_depth = zero_pe->max_depth;
1134  }
1135 
1137  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1138  AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
1139  curr_port->alproto_mask |= dup_pe->alproto_mask;
1140  }
1141  } /* if (zero_port != NULL) */
1142  } /* if (curr_port == NULL) */
1143 
1144  /* insert the pe_pp */
1146  if (direction & STREAM_TOSERVER)
1147  curr_pe = curr_port->dp;
1148  else
1149  curr_pe = curr_port->sp;
1150  while (curr_pe != NULL) {
1151  if (curr_pe->alproto == alproto) {
1152  SCLogError(SC_ERR_ALPARSER, "Duplicate pp registered - "
1153  "ipproto - %"PRIu8" Port - %"PRIu16" "
1154  "App Protocol - NULL, App Protocol(ID) - "
1155  "%"PRIu16" min_depth - %"PRIu16" "
1156  "max_dept - %"PRIu16".",
1157  ipproto, port, alproto,
1158  min_depth, max_depth);
1159  goto error;
1160  }
1161  curr_pe = curr_pe->next;
1162  }
1163  /* Get a new parser element */
1165  AppLayerProtoDetectProbingParserElementCreate(alproto,
1166  curr_port->port,
1167  min_depth, max_depth);
1168  if (new_pe == NULL)
1169  goto error;
1170  curr_pe = new_pe;
1172  if (direction & STREAM_TOSERVER) {
1173  curr_pe->ProbingParserTs = ProbingParser1;
1174  curr_pe->ProbingParserTc = ProbingParser2;
1175  if (curr_port->dp == NULL)
1176  curr_port->dp_max_depth = new_pe->max_depth;
1177  if (new_pe->max_depth == 0)
1178  curr_port->dp_max_depth = new_pe->max_depth;
1179  if (curr_port->dp_max_depth != 0 &&
1180  curr_port->dp_max_depth < new_pe->max_depth) {
1181  curr_port->dp_max_depth = new_pe->max_depth;
1182  }
1183  curr_port->alproto_mask |= new_pe->alproto_mask;
1184  head_pe = &curr_port->dp;
1185  } else {
1186  curr_pe->ProbingParserTs = ProbingParser2;
1187  curr_pe->ProbingParserTc = ProbingParser1;
1188  if (curr_port->sp == NULL)
1189  curr_port->sp_max_depth = new_pe->max_depth;
1190  if (new_pe->max_depth == 0)
1191  curr_port->sp_max_depth = new_pe->max_depth;
1192  if (curr_port->sp_max_depth != 0 &&
1193  curr_port->sp_max_depth < new_pe->max_depth) {
1194  curr_port->sp_max_depth = new_pe->max_depth;
1195  }
1196  curr_port->alproto_mask |= new_pe->alproto_mask;
1197  head_pe = &curr_port->sp;
1198  }
1199  AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);
1200 
1201  if (curr_port->port == 0) {
1202  AppLayerProtoDetectProbingParserPort *temp_port = curr_pp->port;
1203  while (temp_port != NULL && temp_port->port != 0) {
1204  if (direction & STREAM_TOSERVER) {
1205  if (temp_port->dp == NULL)
1206  temp_port->dp_max_depth = curr_pe->max_depth;
1207  if (curr_pe->max_depth == 0)
1208  temp_port->dp_max_depth = curr_pe->max_depth;
1209  if (temp_port->dp_max_depth != 0 &&
1210  temp_port->dp_max_depth < curr_pe->max_depth) {
1211  temp_port->dp_max_depth = curr_pe->max_depth;
1212  }
1213  AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
1214  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1215  temp_port->alproto_mask |= curr_pe->alproto_mask;
1216  } else {
1217  if (temp_port->sp == NULL)
1218  temp_port->sp_max_depth = curr_pe->max_depth;
1219  if (curr_pe->max_depth == 0)
1220  temp_port->sp_max_depth = curr_pe->max_depth;
1221  if (temp_port->sp_max_depth != 0 &&
1222  temp_port->sp_max_depth < curr_pe->max_depth) {
1223  temp_port->sp_max_depth = curr_pe->max_depth;
1224  }
1225  AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
1226  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1227  temp_port->alproto_mask |= curr_pe->alproto_mask;
1228  }
1229  temp_port = temp_port->next;
1230  } /* while */
1231  } /* if */
1232 
1233  error:
1234  SCReturn;
1235 }
1236 
1237 /***** Static Internal Calls: PM registration *****/
1238 
1239 static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto,
1240  uint8_t *ipprotos)
1241 {
1242  SCEnter();
1243 
1244  for (int i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1245  uint8_t ipproto = FlowGetReverseProtoMapping(i);
1246  for (int j = 0; j < 2; j++) {
1247  AppLayerProtoDetectPMCtx *pm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1248 
1249  for (SigIntId x = 0; x < pm_ctx->max_sig_id; x++) {
1250  const AppLayerProtoDetectPMSignature *s = pm_ctx->map[x];
1251  if (s->alproto == alproto)
1252  ipprotos[ipproto / 8] |= 1 << (ipproto % 8);
1253  }
1254  }
1255  }
1256 
1257  SCReturn;
1258 }
1259 
1260 static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
1261 {
1262  SCEnter();
1263 
1264  typedef struct TempContainer_ {
1265  PatIntId id;
1266  uint16_t content_len;
1267  uint8_t *content;
1268  } TempContainer;
1269 
1271  uint32_t struct_total_size = 0;
1272  uint32_t content_total_size = 0;
1273  /* array hash buffer */
1274  uint8_t *ahb = NULL;
1275  uint8_t *content = NULL;
1276  uint8_t content_len = 0;
1277  PatIntId max_id = 0;
1278  TempContainer *struct_offset = NULL;
1279  uint8_t *content_offset = NULL;
1280  int ret = 0;
1281 
1282  if (ctx->head == NULL)
1283  goto end;
1284 
1285  for (s = ctx->head; s != NULL; s = s->next) {
1286  struct_total_size += sizeof(TempContainer);
1287  content_total_size += s->cd->content_len;
1288  ctx->max_sig_id++;
1289  }
1290 
1291  ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1292  if (unlikely(ahb == NULL))
1293  goto error;
1294 
1295  struct_offset = (TempContainer *)ahb;
1296  content_offset = ahb + struct_total_size;
1297  for (s = ctx->head; s != NULL; s = s->next) {
1298  TempContainer *tcdup = (TempContainer *)ahb;
1299  content = s->cd->content;
1300  content_len = s->cd->content_len;
1301 
1302  for (; tcdup != struct_offset; tcdup++) {
1303  if (tcdup->content_len != content_len ||
1304  SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
1305  {
1306  continue;
1307  }
1308  break;
1309  }
1310 
1311  if (tcdup != struct_offset) {
1312  s->cd->id = tcdup->id;
1313  continue;
1314  }
1315 
1316  struct_offset->content_len = content_len;
1317  struct_offset->content = content_offset;
1318  content_offset += content_len;
1319  memcpy(struct_offset->content, content, content_len);
1320  struct_offset->id = max_id++;
1321  s->cd->id = struct_offset->id;
1322 
1323  struct_offset++;
1324  }
1325 
1326  ctx->max_pat_id = max_id;
1327 
1328  goto end;
1329  error:
1330  ret = -1;
1331  end:
1332  if (ahb != NULL)
1333  SCFree(ahb);
1334  SCReturnInt(ret);
1335 }
1336 
1337 static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
1338 {
1339  SCEnter();
1340 
1341  int ret = 0;
1342  AppLayerProtoDetectPMSignature *s, *next_s;
1343  int mpm_ret;
1344  SigIntId id = 0;
1345 
1346  ctx->map = SCMalloc(ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1347  if (ctx->map == NULL)
1348  goto error;
1349  memset(ctx->map, 0, ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1350 
1351  /* add an array indexed by rule id to look up the sig */
1352  for (s = ctx->head; s != NULL; ) {
1353  next_s = s->next;
1354  s->id = id++;
1355  SCLogDebug("s->id %u offset %u depth %u",
1356  s->id, s->cd->offset, s->cd->depth);
1357 
1358  if (s->cd->flags & DETECT_CONTENT_NOCASE) {
1359  mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
1360  s->cd->content, s->cd->content_len,
1361  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1362  if (mpm_ret < 0)
1363  goto error;
1364  } else {
1365  mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
1366  s->cd->content, s->cd->content_len,
1367  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1368  if (mpm_ret < 0)
1369  goto error;
1370  }
1371 
1372  ctx->map[s->id] = s;
1373  s->next = NULL;
1374  s = next_s;
1375  }
1376  ctx->head = NULL;
1377 
1378  goto end;
1379  error:
1380  ret = -1;
1381  end:
1382  SCReturnInt(ret);
1383 }
1384 
1385 static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
1386 {
1387  SCEnter();
1388 
1389  int ret = 0;
1390  MpmCtx *mpm_ctx = &ctx->mpm_ctx;
1391 
1392  if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
1393  goto error;
1394 
1395  goto end;
1396  error:
1397  ret = -1;
1398  end:
1399  SCReturnInt(ret);
1400 }
1401 
1402 static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
1403 {
1404  SCEnter();
1405  if (sig == NULL)
1406  SCReturn;
1407  if (sig->cd)
1408  DetectContentFree(NULL, sig->cd);
1409  SCFree(sig);
1410  SCReturn;
1411 }
1412 
1413 static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx *ctx, DetectContentData *cd,
1414  AppProto alproto, uint8_t direction,
1415  ProbingParserFPtr PPFunc,
1416  uint16_t pp_min_depth, uint16_t pp_max_depth)
1417 {
1418  SCEnter();
1419 
1420  AppLayerProtoDetectPMSignature *s = SCCalloc(1, sizeof(*s));
1421  if (unlikely(s == NULL))
1422  SCReturnInt(-1);
1423 
1424  s->alproto = alproto;
1425  s->direction = direction;
1426  s->cd = cd;
1427  s->PPFunc = PPFunc;
1428  s->pp_min_depth = pp_min_depth;
1429  s->pp_max_depth = pp_max_depth;
1430 
1431  /* prepend to the list */
1432  s->next = ctx->head;
1433  ctx->head = s;
1434 
1435  SCReturnInt(0);
1436 }
1437 
1438 static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
1439  const char *pattern,
1440  uint16_t depth, uint16_t offset,
1441  uint8_t direction,
1442  uint8_t is_cs,
1443  ProbingParserFPtr PPFunc,
1444  uint16_t pp_min_depth, uint16_t pp_max_depth)
1445 {
1446  SCEnter();
1447 
1448  AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
1449  AppLayerProtoDetectPMCtx *ctx_pm = NULL;
1450  int ret = 0;
1451 
1453  alpd_ctx.spm_global_thread_ctx, pattern);
1454  if (cd == NULL)
1455  goto error;
1456  cd->depth = depth;
1457  cd->offset = offset;
1458  if (!is_cs) {
1459  /* Rebuild as nocase */
1460  SpmDestroyCtx(cd->spm_ctx);
1461  cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1,
1462  alpd_ctx.spm_global_thread_ctx);
1463  if (cd->spm_ctx == NULL) {
1464  goto error;
1465  }
1467  }
1468  if (depth < cd->content_len)
1469  goto error;
1470 
1471  if (direction & STREAM_TOSERVER)
1472  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
1473  else
1474  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
1475 
1476  if (pp_max_depth > ctx_pm->pp_max_len)
1477  ctx_pm->pp_max_len = pp_max_depth;
1478  if (depth < ctx_pm->min_len)
1479  ctx_pm->min_len = depth;
1480 
1481  /* Finally turn it into a signature and add to the ctx. */
1482  AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto, direction,
1483  PPFunc, pp_min_depth, pp_max_depth);
1484 
1485  goto end;
1486  error:
1487  DetectContentFree(NULL, cd);
1488  ret = -1;
1489  end:
1490  SCReturnInt(ret);
1491 }
1492 
1493 /***** Protocol Retrieval *****/
1494 
1496  Flow *f,
1497  const uint8_t *buf, uint32_t buflen,
1498  uint8_t ipproto, uint8_t direction,
1499  bool *reverse_flow)
1500 {
1501  SCEnter();
1502  SCLogDebug("buflen %u for %s direction", buflen,
1503  (direction & STREAM_TOSERVER) ? "toserver" : "toclient");
1504 
1505  AppProto alproto = ALPROTO_UNKNOWN;
1506  AppProto pm_alproto = ALPROTO_UNKNOWN;
1507 
1508  if (!FLOW_IS_PM_DONE(f, direction)) {
1509  AppProto pm_results[ALPROTO_MAX];
1510  uint16_t pm_matches = AppLayerProtoDetectPMGetProto(tctx, f,
1511  buf, buflen, direction, pm_results, reverse_flow);
1512  if (pm_matches > 0) {
1513  alproto = pm_results[0];
1514 
1515  /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1516  * to avoid misdetecting DNS as DCERPC. */
1517  if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1518  goto end;
1519 
1520  pm_alproto = alproto;
1521 
1522  /* fall through */
1523  }
1524  }
1525 
1526  if (!FLOW_IS_PP_DONE(f, direction)) {
1527  bool rflow = false;
1528  alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto,
1529  direction & (STREAM_TOSERVER|STREAM_TOCLIENT), &rflow);
1530  if (AppProtoIsValid(alproto)) {
1531  if (rflow) {
1532  *reverse_flow = true;
1533  }
1534  goto end;
1535  }
1536  }
1537 
1538  /* Look if flow can be found in expectation list */
1539  if (!FLOW_IS_PE_DONE(f, direction)) {
1540  alproto = AppLayerProtoDetectPEGetProto(f, ipproto, direction);
1541  }
1542 
1543  end:
1544  if (!AppProtoIsValid(alproto))
1545  alproto = pm_alproto;
1546 
1547  SCReturnUInt(alproto);
1548 }
1549 
1550 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1551 {
1552  SCEnter();
1553 
1554  AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1555 
1556  if (pp == NULL)
1557  goto end;
1558 
1559  while (pp != NULL) {
1560  tmp_pp = pp->next;
1561  AppLayerProtoDetectProbingParserFree(pp);
1562  pp = tmp_pp;
1563  }
1564 
1565  end:
1566  SCReturn;
1567 }
1568 
1569 /***** State Preparation *****/
1570 
1572 {
1573  SCEnter();
1574 
1575  AppLayerProtoDetectPMCtx *ctx_pm;
1576  int i, j;
1577  int ret = 0;
1578 
1579  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1580  for (j = 0; j < 2; j++) {
1581  ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1582 
1583  if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1584  goto error;
1585 
1586  if (ctx_pm->max_sig_id == 0)
1587  continue;
1588 
1589  if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1590  goto error;
1591  if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1592  goto error;
1593  }
1594  }
1595 
1596 #ifdef DEBUG
1597  if (SCLogDebugEnabled()) {
1598  AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1599  }
1600 #endif
1601 
1602  goto end;
1603  error:
1604  ret = -1;
1605  end:
1606  SCReturnInt(ret);
1607 }
1608 
1609 /***** PP registration *****/
1610 
1611 /** \brief register parser at a port
1612  *
1613  * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1614  */
1615 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1616  const char *portstr,
1617  AppProto alproto,
1618  uint16_t min_depth, uint16_t max_depth,
1619  uint8_t direction,
1620  ProbingParserFPtr ProbingParser1,
1621  ProbingParserFPtr ProbingParser2)
1622 {
1623  SCEnter();
1624 
1625  DetectPort *head = NULL;
1626  DetectPortParse(NULL,&head, portstr);
1627  DetectPort *temp_dp = head;
1628  while (temp_dp != NULL) {
1629  uint32_t port = temp_dp->port;
1630  if (port == 0 && temp_dp->port2 != 0)
1631  port++;
1632  for ( ; port <= temp_dp->port2; port++) {
1633  AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
1634  ipproto,
1635  port,
1636  alproto,
1637  min_depth, max_depth,
1638  direction,
1639  ProbingParser1,
1640  ProbingParser2);
1641  }
1642  temp_dp = temp_dp->next;
1643  }
1645 
1646  SCReturn;
1647 }
1648 
1649 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1650  uint8_t ipproto,
1651  const char *alproto_name,
1652  AppProto alproto,
1653  uint16_t min_depth, uint16_t max_depth,
1654  ProbingParserFPtr ProbingParserTs,
1655  ProbingParserFPtr ProbingParserTc)
1656 {
1657  SCEnter();
1658 
1659  char param[100];
1660  int r;
1661  ConfNode *node;
1662  ConfNode *port_node = NULL;
1663  int config = 0;
1664 
1665  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1666  alproto_name, ".detection-ports");
1667  if (r < 0) {
1668  FatalError(SC_ERR_FATAL, "snprintf failure.");
1669  } else if (r > (int)sizeof(param)) {
1670  FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
1671  }
1672  node = ConfGetNode(param);
1673  if (node == NULL) {
1674  SCLogDebug("Entry for %s not found.", param);
1675  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1676  alproto_name, ".", ipproto_name, ".detection-ports");
1677  if (r < 0) {
1678  FatalError(SC_ERR_FATAL, "snprintf failure.");
1679  } else if (r > (int)sizeof(param)) {
1680  FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
1681  }
1682  node = ConfGetNode(param);
1683  if (node == NULL)
1684  goto end;
1685  }
1686 
1687  /* detect by destination port of the flow (e.g. port 53 for DNS) */
1688  port_node = ConfNodeLookupChild(node, "dp");
1689  if (port_node == NULL)
1690  port_node = ConfNodeLookupChild(node, "toserver");
1691 
1692  if (port_node != NULL && port_node->val != NULL) {
1694  port_node->val,
1695  alproto,
1696  min_depth, max_depth,
1697  STREAM_TOSERVER, /* to indicate dp */
1698  ProbingParserTs, ProbingParserTc);
1699  }
1700 
1701  /* detect by source port of flow */
1702  port_node = ConfNodeLookupChild(node, "sp");
1703  if (port_node == NULL)
1704  port_node = ConfNodeLookupChild(node, "toclient");
1705 
1706  if (port_node != NULL && port_node->val != NULL) {
1708  port_node->val,
1709  alproto,
1710  min_depth, max_depth,
1711  STREAM_TOCLIENT, /* to indicate sp */
1712  ProbingParserTc, ProbingParserTs);
1713 
1714  }
1715 
1716  config = 1;
1717  end:
1718  SCReturnInt(config);
1719 }
1720 
1721 /***** PM registration *****/
1722 
1724  const char *pattern,
1725  uint16_t depth, uint16_t offset,
1726  uint8_t direction)
1727 {
1728  SCEnter();
1729  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1730  pattern, depth, offset,
1731  direction, 1 /* case-sensitive */,
1732  NULL, 0, 0);
1733  SCReturnInt(r);
1734 }
1735 
1737  const char *pattern, uint16_t depth, uint16_t offset,
1738  uint8_t direction,
1739  ProbingParserFPtr PPFunc,
1740  uint16_t pp_min_depth, uint16_t pp_max_depth)
1741 {
1742  SCEnter();
1743  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1744  pattern, depth, offset,
1745  direction, 1 /* case-sensitive */,
1746  PPFunc, pp_min_depth, pp_max_depth);
1747  SCReturnInt(r);
1748 }
1749 
1751  const char *pattern,
1752  uint16_t depth, uint16_t offset,
1753  uint8_t direction)
1754 {
1755  SCEnter();
1756  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1757  pattern, depth, offset,
1758  direction, 0 /* !case-sensitive */,
1759  NULL, 0, 0);
1760  SCReturnInt(r);
1761 }
1762 
1763 /***** Setup/General Registration *****/
1764 
1766 {
1767  SCEnter();
1768 
1769  int i, j;
1770 
1771  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1772 
1773  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1774  uint16_t mpm_matcher = PatternMatchDefaultMatcher();
1775 
1776  alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1777  if (alpd_ctx.spm_global_thread_ctx == NULL) {
1778  FatalError(SC_ERR_FATAL, "Unable to alloc SpmGlobalThreadCtx.");
1779  }
1780 
1781  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1782  for (j = 0; j < 2; j++) {
1783  MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, mpm_matcher);
1784  }
1785  }
1786 
1788 
1789  SCReturnInt(0);
1790 }
1791 
1792 /**
1793  * \todo incomplete. Need more work.
1794  */
1796 {
1797  SCEnter();
1798 
1799  int ipproto_map = 0;
1800  int dir = 0;
1801  PatIntId id = 0;
1802  AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1803  AppLayerProtoDetectPMSignature *sig = NULL;
1804 
1805  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1806  for (dir = 0; dir < 2; dir++) {
1807  pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1808  mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1809  for (id = 0; id < pm_ctx->max_sig_id; id++) {
1810  sig = pm_ctx->map[id];
1811  AppLayerProtoDetectPMFreeSignature(sig);
1812  }
1813  SCFree(pm_ctx->map);
1814  pm_ctx->map = NULL;
1815  }
1816  }
1817 
1819 
1820  AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1821 
1822  SCReturnInt(0);
1823 }
1824 
1825 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1826 {
1827  SCEnter();
1828 
1829  if (alpd_ctx.alproto_names[alproto] == NULL)
1830  alpd_ctx.alproto_names[alproto] = alproto_name;
1831 
1832  SCReturn;
1833 }
1834 
1835 /** \brief request applayer to wrap up this protocol and rerun protocol
1836  * detection.
1837  *
1838  * When this is called, the old session is reset unconditionally. A
1839  * 'detect/log' flush packet is generated for both direction before
1840  * the reset, so allow for final detection and logging.
1841  *
1842  * \param f flow to act on
1843  * \param dp destination port to use in protocol detection. Set to 443
1844  * for start tls, set to the HTTP uri port for CONNECT and
1845  * set to 0 to not use it.
1846  * \param expect_proto expected protocol. AppLayer event will be set if
1847  * detected protocol differs from this.
1848  */
1849 void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1850 {
1852  f->protodetect_dp = dp;
1853  f->alproto_expect = expect_proto;
1854 }
1855 
1856 /** \brief request applayer to wrap up this protocol and rerun protocol
1857  * detection with expectation of TLS. Used by STARTTLS.
1858  *
1859  * Sets detection port to 443 to make port based TLS detection work for
1860  * SMTP, FTP etc as well.
1861  *
1862  * \param f flow to act on
1863  */
1865 {
1867 }
1868 
1870 {
1879 
1880  // Does not free the structures for the parser
1881  // keeps f->alstate for new state creation
1882  f->alparser = NULL;
1883  f->alproto = ALPROTO_UNKNOWN;
1886 }
1887 
1889  const char *alproto)
1890 {
1891  SCEnter();
1892 
1893  BUG_ON(ipproto == NULL || alproto == NULL);
1894 
1895  int enabled = 1;
1896  char param[100];
1897  ConfNode *node;
1898  int r;
1899 
1900  if (RunmodeIsUnittests())
1901  goto enabled;
1902 
1903  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1904  alproto, ".enabled");
1905  if (r < 0) {
1906  FatalError(SC_ERR_FATAL, "snprintf failure.");
1907  } else if (r > (int)sizeof(param)) {
1908  FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
1909  }
1910 
1911  node = ConfGetNode(param);
1912  if (node == NULL) {
1913  SCLogDebug("Entry for %s not found.", param);
1914  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1915  alproto, ".", ipproto, ".enabled");
1916  if (r < 0) {
1917  FatalError(SC_ERR_FATAL, "snprintf failure.");
1918  } else if (r > (int)sizeof(param)) {
1919  FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
1920  }
1921 
1922  node = ConfGetNode(param);
1923  if (node == NULL) {
1924  SCLogDebug("Entry for %s not found.", param);
1925  goto enabled;
1926  }
1927  }
1928 
1929  if (node->val) {
1930  if (ConfValIsTrue(node->val)) {
1931  goto enabled;
1932  } else if (ConfValIsFalse(node->val)) {
1933  goto disabled;
1934  } else if (strcasecmp(node->val, "detection-only") == 0) {
1935  goto enabled;
1936  }
1937  }
1938 
1939  /* Invalid or null value. */
1940  SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
1941  exit(EXIT_FAILURE);
1942 
1943  disabled:
1944  enabled = 0;
1945  enabled:
1946  SCReturnInt(enabled);
1947 }
1948 
1950 {
1951  SCEnter();
1952 
1954  MpmCtx *mpm_ctx;
1955  MpmThreadCtx *mpm_tctx;
1956  int i, j;
1957  PatIntId max_pat_id = 0;
1958 
1959  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1960  for (j = 0; j < 2; j++) {
1961  if (max_pat_id == 0) {
1962  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1963 
1964  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
1965  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
1966  {
1967  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1968  }
1969  }
1970  }
1971 
1972  alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
1973  if (alpd_tctx == NULL)
1974  goto error;
1975  memset(alpd_tctx, 0, sizeof(*alpd_tctx));
1976 
1977  /* Get the max pat id for all the mpm ctxs. */
1978  if (PmqSetup(&alpd_tctx->pmq) < 0)
1979  goto error;
1980 
1981  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1982  for (j = 0; j < 2; j++) {
1983  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
1984  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
1985  mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx);
1986  }
1987  }
1988 
1990  if (alpd_tctx->spm_thread_ctx == NULL) {
1991  goto error;
1992  }
1993 
1994  goto end;
1995  error:
1996  if (alpd_tctx != NULL)
1998  alpd_tctx = NULL;
1999  end:
2000  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2001 }
2002 
2004 {
2005  SCEnter();
2006 
2007  MpmCtx *mpm_ctx;
2008  MpmThreadCtx *mpm_tctx;
2009  int ipproto_map, dir;
2010 
2011  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2012  for (dir = 0; dir < 2; dir++) {
2013  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2014  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2015  mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
2016  }
2017  }
2018  PmqFree(&alpd_tctx->pmq);
2019  if (alpd_tctx->spm_thread_ctx != NULL) {
2021  }
2022  SCFree(alpd_tctx);
2023 
2024  SCReturn;
2025 }
2026 
2027 /***** Utility *****/
2028 
2029 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2030 {
2031  SCEnter();
2032 
2033  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2034  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2035  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2036 
2037  SCReturn;
2038 }
2039 
2041 {
2042  SCEnter();
2043 
2044  AppProto a;
2045  for (a = 0; a < ALPROTO_MAX; a++) {
2046  if (alpd_ctx.alproto_names[a] != NULL &&
2047  strlen(alpd_ctx.alproto_names[a]) == strlen(alproto_name) &&
2048  (SCMemcmp(alpd_ctx.alproto_names[a], alproto_name, strlen(alproto_name)) == 0))
2049  {
2050  SCReturnCT(a, "AppProto");
2051  }
2052  }
2053 
2054  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2055 }
2056 
2058 {
2059  return alpd_ctx.alproto_names[alproto];
2060 }
2061 
2063 {
2064  SCEnter();
2065 
2066  memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2067 
2068  int alproto;
2069 
2070  for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2071  if (alpd_ctx.alproto_names[alproto] != NULL)
2072  alprotos[alproto] = 1;
2073  }
2074 
2075  SCReturn;
2076 }
2077 
2079 
2080 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2081  uint8_t *ipprotos)
2082 {
2083  if (expectation_proto[alproto] == IPPROTO_TCP) {
2084  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2085  }
2086  if (expectation_proto[alproto] == IPPROTO_UDP) {
2087  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2088  }
2089 }
2090 
2092 {
2093  if (expectation_proto[alproto]) {
2094  if (proto != expectation_proto[alproto]) {
2096  "Expectation on 2 IP protocols are not supported");
2097  }
2098  }
2099  expectation_proto[alproto] = proto;
2100 }
2101 
2102 /***** Unittests *****/
2103 
2104 #ifdef UNITTESTS
2105 
2106 #include "app-layer-htp.h"
2107 
2108 static AppLayerProtoDetectCtx alpd_ctx_ut;
2109 
2111 {
2112  SCEnter();
2113  alpd_ctx_ut = alpd_ctx;
2114  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2115  SCReturn;
2116 }
2117 
2119 {
2120  SCEnter();
2121  alpd_ctx = alpd_ctx_ut;
2122  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2123  SCReturn;
2124 }
2125 
2126 static int AppLayerProtoDetectTest01(void)
2127 {
2130 
2131  const char *buf = "HTTP";
2133  buf = "GET";
2135 
2137  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2138  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2139 
2142  PASS;
2143 }
2144 
2145 static int AppLayerProtoDetectTest02(void)
2146 {
2149 
2150  const char *buf = "HTTP";
2152  buf = "ftp";
2154 
2156  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2157  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2158 
2159  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2160  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2161 
2164 
2167  PASS;
2168 }
2169 
2170 static int AppLayerProtoDetectTest03(void)
2171 {
2174 
2175  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2176  AppProto pm_results[ALPROTO_MAX];
2177  memset(pm_results, 0, sizeof(pm_results));
2178  Flow f;
2179  memset(&f, 0x00, sizeof(f));
2180  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2181 
2182 
2183  const char *buf = "HTTP";
2185  buf = "220 ";
2187 
2189  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2190  * it sets internal structures which depends on the above function. */
2193 
2194  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2195  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2196  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2197  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2200 
2201  bool rflow = false;
2202  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2203  &f, l7data, sizeof(l7data),
2205  pm_results, &rflow);
2206  FAIL_IF(cnt != 1);
2207  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2208 
2212  PASS;
2213 }
2214 
2215 static int AppLayerProtoDetectTest04(void)
2216 {
2219 
2220  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2221  Flow f;
2222  memset(&f, 0x00, sizeof(f));
2223  AppProto pm_results[ALPROTO_MAX];
2224  memset(pm_results, 0, sizeof(pm_results));
2225  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2226 
2227  const char *buf = "200 ";
2229 
2231  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2232  * it sets internal structures which depends on the above function. */
2235 
2236  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2237  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2238  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2239  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2241 
2242  bool rdir = false;
2243  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2244  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2245  pm_results, &rdir);
2246  FAIL_IF(cnt != 1);
2247  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2248 
2252  PASS;
2253 }
2254 
2255 static int AppLayerProtoDetectTest05(void)
2256 {
2259 
2260  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2261  AppProto pm_results[ALPROTO_MAX];
2262  memset(pm_results, 0, sizeof(pm_results));
2263  Flow f;
2264  memset(&f, 0x00, sizeof(f));
2265  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2266 
2267  const char *buf = "HTTP";
2269  buf = "220 ";
2271 
2273  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2274  * it sets internal structures which depends on the above function. */
2277 
2278  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2279  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2280  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2281  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2284 
2285  bool rdir = false;
2286  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2287  &f, l7data, sizeof(l7data),
2289  pm_results, &rdir);
2290  FAIL_IF(cnt != 1);
2291  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2292 
2296  PASS;
2297 }
2298 
2299 static int AppLayerProtoDetectTest06(void)
2300 {
2303 
2304  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2305  AppProto pm_results[ALPROTO_MAX];
2306  memset(pm_results, 0, sizeof(pm_results));
2307  Flow f;
2308  memset(&f, 0x00, sizeof(f));
2309  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2310 
2311  const char *buf = "HTTP";
2313  buf = "220 ";
2315 
2317  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2318  * it sets internal structures which depends on the above function. */
2321 
2322  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2323  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2324  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2325  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2328 
2329  bool rdir = false;
2330  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2331  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2332  pm_results, &rdir);
2333  FAIL_IF(cnt != 1);
2334  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2335 
2339  PASS;
2340 }
2341 
2342 static int AppLayerProtoDetectTest07(void)
2343 {
2346 
2347  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2348  Flow f;
2349  memset(&f, 0x00, sizeof(f));
2350  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2351  AppProto pm_results[ALPROTO_MAX];
2352  memset(pm_results, 0, sizeof(pm_results));
2353 
2354  const char *buf = "HTTP";
2356 
2358  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2359  * it sets internal structures which depends on the above function. */
2361 
2362  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2363  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2364  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2365  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2367 
2368  bool rdir = false;
2369  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2370  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2371  pm_results, &rdir);
2372  FAIL_IF(cnt != 0);
2373 
2377  PASS;
2378 }
2379 
2380 static int AppLayerProtoDetectTest08(void)
2381 {
2384 
2385  uint8_t l7data[] = {
2386  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2387  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2388  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2389  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2390  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2391  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2392  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2393  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2394  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2395  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2396  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2397  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2398  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2399  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2400  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2401  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2402  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2403  0x00
2404  };
2405  AppProto pm_results[ALPROTO_MAX];
2406  memset(pm_results, 0, sizeof(pm_results));
2407  Flow f;
2408  memset(&f, 0x00, sizeof(f));
2409  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2410 
2411  const char *buf = "|ff|SMB";
2413 
2415  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2416  * it sets internal structures which depends on the above function. */
2419 
2420  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2421  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2422  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2423  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2425 
2426  bool rdir = false;
2427  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2428  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2429  pm_results, &rdir);
2430  FAIL_IF(cnt != 1);
2431  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2432 
2436  PASS;
2437 }
2438 
2439 static int AppLayerProtoDetectTest09(void)
2440 {
2443 
2444  uint8_t l7data[] = {
2445  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2446  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2447  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2448  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2449  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2450  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2451  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2452  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2453  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2454  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2455  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2456  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2457  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2458  0x00, 0x02, 0x02
2459  };
2460  AppProto pm_results[ALPROTO_MAX];
2461  memset(pm_results, 0, sizeof(pm_results));
2462  Flow f;
2463  memset(&f, 0x00, sizeof(f));
2464  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2465 
2466  const char *buf = "|fe|SMB";
2468 
2470  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2471  * it sets internal structures which depends on the above function. */
2474 
2475  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2476  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2477  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2478  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2480 
2481  bool rdir = false;
2482  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2483  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2484  pm_results, &rdir);
2485  FAIL_IF(cnt != 1);
2486  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2487 
2491  PASS;
2492 }
2493 
2494 static int AppLayerProtoDetectTest10(void)
2495 {
2498 
2499  uint8_t l7data[] = {
2500  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2501  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2502  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2503  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2504  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2505  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2506  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2507  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2508  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2509  };
2510  AppProto pm_results[ALPROTO_MAX];
2511  memset(pm_results, 0, sizeof(pm_results));
2512  Flow f;
2513  memset(&f, 0x00, sizeof(f));
2514  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2515 
2516  const char *buf = "|05 00|";
2518 
2520  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2521  * it sets internal structures which depends on the above function. */
2524 
2525  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2526  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2527  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2528  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2530 
2531  bool rdir = false;
2532  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2533  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2534  pm_results, &rdir);
2535  FAIL_IF(cnt != 1);
2536  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2537 
2541  PASS;
2542 }
2543 
2544 /**
2545  * \test Why we still get http for connect... obviously because
2546  * we also match on the reply, duh
2547  */
2548 static int AppLayerProtoDetectTest11(void)
2549 {
2552 
2553  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2554  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2555  AppProto pm_results[ALPROTO_MAX];
2556  memset(pm_results, 0, sizeof(pm_results));
2557  Flow f;
2558  memset(&f, 0x00, sizeof(f));
2559  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2560 
2569 
2571  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2572  * it sets internal structures which depends on the above function. */
2575 
2576  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2577  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2578  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2579  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2580 
2589 
2590  bool rdir = false;
2591  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2592  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2593  pm_results, &rdir);
2594  FAIL_IF(cnt != 1);
2595  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2596 
2597  memset(pm_results, 0, sizeof(pm_results));
2598  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2599  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2600  pm_results, &rdir);
2601  FAIL_IF(cnt != 1);
2602  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2603 
2607  PASS;
2608 }
2609 
2610 /**
2611  * \test AlpProtoSignature test
2612  */
2613 static int AppLayerProtoDetectTest12(void)
2614 {
2617 
2618  int r = 0;
2619 
2621  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2622  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2623  {
2624  printf("failure 1\n");
2625  goto end;
2626  }
2627 
2629  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2630  printf("failure 2\n");
2631  goto end;
2632  }
2633  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2634  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2635  {
2636  printf("failure 3\n");
2637  goto end;
2638  }
2639  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP) {
2640  printf("failure 4\n");
2641  goto end;
2642  }
2643  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2644  printf("failure 5\n");
2645  goto end;
2646  }
2647  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2648  printf("failure 6\n");
2649  goto end;
2650  }
2651 
2652  r = 1;
2653 
2654  end:
2657  return r;
2658 }
2659 
2660 /**
2661  * \test What about if we add some sigs only for udp but call for tcp?
2662  * It should not detect any proto
2663  */
2664 static int AppLayerProtoDetectTest13(void)
2665 {
2668 
2669  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2670  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2671  AppProto pm_results[ALPROTO_MAX];
2672 
2673  Flow f;
2674  memset(&f, 0x00, sizeof(f));
2675  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2676 
2685 
2687  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2688  * it sets internal structures which depends on the above function. */
2690 
2691  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2692  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2693 
2702 
2703  memset(pm_results, 0, sizeof(pm_results));
2704  bool rdir = false;
2705  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2706  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2707  pm_results, &rdir);
2708  FAIL_IF(cnt != 0);
2709 
2710  memset(pm_results, 0, sizeof(pm_results));
2711  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2712  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2713  pm_results, &rdir);
2714  FAIL_IF(cnt != 0);
2715 
2719  PASS;
2720 }
2721 
2722 /**
2723  * \test What about if we add some sigs only for udp calling it for UDP?
2724  * It should detect ALPROTO_HTTP (over udp). This is just a check
2725  * to ensure that TCP/UDP differences work correctly.
2726  */
2727 static int AppLayerProtoDetectTest14(void)
2728 {
2731 
2732  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2733  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2734  AppProto pm_results[ALPROTO_MAX];
2735  uint32_t cnt;
2736  Flow f;
2737  memset(&f, 0x00, sizeof(f));
2738  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2739 
2748 
2750  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2751  * it sets internal structures which depends on the above function. */
2754 
2755  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2756  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2757 
2766 
2767  memset(pm_results, 0, sizeof(pm_results));
2768  bool rdir = false;
2769  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2770  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2771  pm_results, &rdir);
2772  FAIL_IF(cnt != 1);
2773  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2774 
2775  memset(pm_results, 0, sizeof(pm_results));
2776  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2777  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2778  pm_results, &rdir);
2779  FAIL_IF(cnt != 1);
2780  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2781 
2785  PASS;
2786 }
2787 
2789  const char *alproto_name;
2791  uint16_t port;
2792  uint32_t alproto_mask;
2793  uint32_t min_depth;
2794  uint32_t max_depth;
2796 
2798  uint16_t port;
2799  uint32_t alproto_mask;
2800  uint16_t dp_max_depth;
2801  uint16_t sp_max_depth;
2802 
2808 
2809 
2811  uint8_t ipproto;
2812 
2816 
2817 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2819  int no_of_ip_proto)
2820 {
2821  int result = 0;
2822  int i = -1, j = -1 , k = -1;
2823 #ifdef DEBUG
2824  int dir = 0;
2825 #endif
2826  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2827  if (pp->ipproto != ip_proto[i].ipproto)
2828  goto end;
2829 
2831  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2832  if (pp_port->port != ip_proto[i].port[k].port)
2833  goto end;
2834  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2835  goto end;
2836  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2837  goto end;
2838  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2839  goto end;
2840  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2841  goto end;
2842 
2843  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2844 #ifdef DEBUG
2845  dir = 0;
2846 #endif
2847  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2848  j++, pp_element = pp_element->next) {
2849 
2850  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2851  goto end;
2852  }
2853  if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
2854  goto end;
2855  }
2856  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
2857  goto end;
2858  }
2859  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2860  goto end;
2861  }
2862  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2863  goto end;
2864  }
2865  } /* for */
2866  if (pp_element != NULL)
2867  goto end;
2868 
2869  pp_element = pp_port->sp;
2870 #ifdef DEBUG
2871  dir = 1;
2872 #endif
2873  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2874  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2875  goto end;
2876  }
2877  if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
2878  goto end;
2879  }
2880  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
2881  goto end;
2882  }
2883  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2884  goto end;
2885  }
2886  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2887  goto end;
2888  }
2889  } /* for */
2890  if (pp_element != NULL)
2891  goto end;
2892  }
2893  if (pp_port != NULL)
2894  goto end;
2895  }
2896  if (pp != NULL)
2897  goto end;
2898 
2899  result = 1;
2900  end:
2901 #ifdef DEBUG
2902  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2903 #endif
2904  return result;
2905 }
2906 
2907 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
2908  const uint8_t *input,
2909  uint32_t input_len, uint8_t *rdir)
2910 {
2911  return 0;
2912 }
2913 
2914 static int AppLayerProtoDetectTest15(void)
2915 {
2918 
2919  int result = 0;
2920 
2921  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2922  "80",
2923  ALPROTO_HTTP,
2924  5, 8,
2926  ProbingParserDummyForTesting, NULL);
2927  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2928  "80",
2929  ALPROTO_SMB,
2930  5, 6,
2932  ProbingParserDummyForTesting, NULL);
2933  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2934  "80",
2935  ALPROTO_FTP,
2936  7, 10,
2938  ProbingParserDummyForTesting, NULL);
2939 
2940  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2941  "81",
2943  9, 10,
2945  ProbingParserDummyForTesting, NULL);
2946  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2947  "81",
2948  ALPROTO_FTP,
2949  7, 15,
2951  ProbingParserDummyForTesting, NULL);
2952  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2953  "0",
2954  ALPROTO_SMTP,
2955  12, 0,
2957  ProbingParserDummyForTesting, NULL);
2958  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2959  "0",
2960  ALPROTO_TLS,
2961  12, 18,
2963  ProbingParserDummyForTesting, NULL);
2964 
2965  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2966  "85",
2968  9, 10,
2970  ProbingParserDummyForTesting, NULL);
2971  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2972  "85",
2973  ALPROTO_FTP,
2974  7, 15,
2976  ProbingParserDummyForTesting, NULL);
2977  result = 1;
2978 
2979  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
2980  "85",
2981  ALPROTO_IMAP,
2982  12, 23,
2984  ProbingParserDummyForTesting, NULL);
2985 
2986  /* toclient */
2987  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2988  "0",
2990  12, 23,
2992  ProbingParserDummyForTesting, NULL);
2993  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2994  "0",
2995  ALPROTO_IRC,
2996  12, 14,
2998  ProbingParserDummyForTesting, NULL);
2999 
3000  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3001  "85",
3003  9, 10,
3005  ProbingParserDummyForTesting, NULL);
3006  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3007  "81",
3008  ALPROTO_FTP,
3009  7, 15,
3011  ProbingParserDummyForTesting, NULL);
3012  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3013  "0",
3014  ALPROTO_TLS,
3015  12, 18,
3017  ProbingParserDummyForTesting, NULL);
3018  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3019  "80",
3020  ALPROTO_HTTP,
3021  5, 8,
3023  ProbingParserDummyForTesting, NULL);
3024  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3025  "81",
3027  9, 10,
3029  ProbingParserDummyForTesting, NULL);
3030  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3031  "90",
3032  ALPROTO_FTP,
3033  7, 15,
3035  ProbingParserDummyForTesting, NULL);
3036  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3037  "80",
3038  ALPROTO_SMB,
3039  5, 6,
3041  ProbingParserDummyForTesting, NULL);
3042  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3043  "85",
3044  ALPROTO_IMAP,
3045  12, 23,
3047  ProbingParserDummyForTesting, NULL);
3048  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3049  "0",
3050  ALPROTO_SMTP,
3051  12, 17,
3053  ProbingParserDummyForTesting, NULL);
3054  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3055  "80",
3056  ALPROTO_FTP,
3057  7, 10,
3059  ProbingParserDummyForTesting, NULL);
3060 
3061  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3062  { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3063  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3064  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3065  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3066  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3067  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3068  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3069  };
3070  AppLayerProtoDetectPPTestDataElement element_tc_80[] = {
3071  { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3072  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3073  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3074  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3075  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3076  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3077  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3078  };
3079 
3080  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3081  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3082  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3083  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3084  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3085  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3086  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3087  };
3088  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3089  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3090  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3091  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3092  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3093  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3094  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3095  };
3096 
3097  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3098  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3099  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3100  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3101  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3102  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3103  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3104  };
3105  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3106  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3107  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3108  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3109  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3110  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3111  };
3112 
3113  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3114  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3115  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3116  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3117  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3118  };
3119  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3120  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3121  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3122  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3123  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3124  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3125  };
3126 
3127  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3128  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3129  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3130  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3131  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3132  };
3133  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3134  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3135  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3136  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3137  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3138  };
3139 
3140 
3141  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3142  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3143  };
3144  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3145  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3146  };
3147 
3148  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3149  { 80,
3150  ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3151  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3152  ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3153  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3154  23,
3155  element_ts_80, element_tc_80,
3156  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3157  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3158  },
3159  { 81,
3160  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3161  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3162  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) |
3163  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3164  23,
3165  element_ts_81, element_tc_81,
3166  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3167  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3168  },
3169  { 85,
3170  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3171  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3172  ((1 << ALPROTO_DCERPC) |
3173  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3174  23,
3175  element_ts_85, element_tc_85,
3176  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3177  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement)
3178  },
3179  { 90,
3180  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3181  ((1 << ALPROTO_FTP) |
3182  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3183  23,
3184  element_ts_90, element_tc_90,
3185  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3186  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement)
3187  },
3188  { 0,
3189  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3190  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3191  23,
3192  element_ts_0, element_tc_0,
3193  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3194  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement)
3195  }
3196  };
3197 
3198  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3199  { 85,
3200  (1 << ALPROTO_IMAP),
3201  (1 << ALPROTO_IMAP),
3202  23,
3203  element_ts_85_udp, element_tc_85_udp,
3204  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3205  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3206  },
3207  };
3208 
3210  { IPPROTO_TCP,
3211  ports_tcp,
3212  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3213  },
3214  { IPPROTO_UDP,
3215  ports_udp,
3216  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3217  },
3218  };
3219 
3220 
3221  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3222  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3223  goto end;
3224  }
3225  result = 1;
3226 
3227  end:
3230  return result;
3231 }
3232 
3233 
3234 /** \test test if the engine detect the proto and match with it */
3235 static int AppLayerProtoDetectTest16(void)
3236 {
3237  int result = 0;
3238  Flow *f = NULL;
3239  HtpState *http_state = NULL;
3240  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3241  "User-Agent: Mozilla/1.0\r\n"
3242  "Cookie: hellocatch\r\n\r\n";
3243  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3244  TcpSession ssn;
3245  Packet *p = NULL;
3246  Signature *s = NULL;
3247  ThreadVars tv;
3248  DetectEngineThreadCtx *det_ctx = NULL;
3249  DetectEngineCtx *de_ctx = NULL;
3251 
3252  memset(&tv, 0, sizeof(ThreadVars));
3253  memset(&ssn, 0, sizeof(TcpSession));
3254 
3255  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3256  if (p == NULL) {
3257  printf("packet setup failed: ");
3258  goto end;
3259  }
3260 
3261  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3262  if (f == NULL) {
3263  printf("flow setup failed: ");
3264  goto end;
3265  }
3266  f->protoctx = &ssn;
3267  f->proto = IPPROTO_TCP;
3268  p->flow = f;
3269 
3273 
3274  f->alproto = ALPROTO_HTTP;
3275 
3277 
3279  if (de_ctx == NULL) {
3280  goto end;
3281  }
3282  de_ctx->flags |= DE_QUIET;
3283 
3284  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3285  "(msg:\"Test content option\"; "
3286  "sid:1;)");
3287  if (s == NULL) {
3288  goto end;
3289  }
3290 
3292  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3293 
3294  FLOWLOCK_WRLOCK(f);
3295  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3296  STREAM_TOSERVER, http_buf1, http_buf1_len);
3297  if (r != 0) {
3298  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3299  FLOWLOCK_UNLOCK(f);
3300  goto end;
3301  }
3302  FLOWLOCK_UNLOCK(f);
3303 
3304  http_state = f->alstate;
3305  if (http_state == NULL) {
3306  printf("no http state: ");
3307  goto end;
3308  }
3309 
3310  /* do detect */
3311  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3312 
3313  if (!PacketAlertCheck(p, 1)) {
3314  printf("sig 1 didn't alert, but it should: ");
3315  goto end;
3316  }
3317  result = 1;
3318  end:
3319  if (alp_tctx != NULL)
3321  if (det_ctx != NULL)
3322  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3323  if (de_ctx != NULL)
3325  if (de_ctx != NULL)
3327 
3329 
3330  UTHFreePackets(&p, 1);
3331  UTHFreeFlow(f);
3332  return result;
3333 }
3334 
3335 /** \test test if the engine detect the proto on a non standar port
3336  * and match with it */
3337 static int AppLayerProtoDetectTest17(void)
3338 {
3339  int result = 0;
3340  Flow *f = NULL;
3341  HtpState *http_state = NULL;
3342  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3343  "User-Agent: Mozilla/1.0\r\n"
3344  "Cookie: hellocatch\r\n\r\n";
3345  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3346  TcpSession ssn;
3347  Packet *p = NULL;
3348  Signature *s = NULL;
3349  ThreadVars tv;
3350  DetectEngineThreadCtx *det_ctx = NULL;
3351  DetectEngineCtx *de_ctx = NULL;
3353 
3354  memset(&tv, 0, sizeof(ThreadVars));
3355  memset(&ssn, 0, sizeof(TcpSession));
3356 
3357  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3358 
3359  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3360  if (f == NULL)
3361  goto end;
3362  f->protoctx = &ssn;
3363  f->proto = IPPROTO_TCP;
3364  p->flow = f;
3368  f->alproto = ALPROTO_HTTP;
3369 
3371 
3373  if (de_ctx == NULL) {
3374  goto end;
3375  }
3376  de_ctx->flags |= DE_QUIET;
3377 
3378  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3379  "(msg:\"http over non standar port\"; "
3380  "sid:1;)");
3381  if (s == NULL) {
3382  goto end;
3383  }
3384 
3386  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3387 
3388  FLOWLOCK_WRLOCK(f);
3389  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3390  STREAM_TOSERVER, http_buf1, http_buf1_len);
3391  if (r != 0) {
3392  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3393  FLOWLOCK_UNLOCK(f);
3394  goto end;
3395  }
3396  FLOWLOCK_UNLOCK(f);
3397 
3398  http_state = f->alstate;
3399  if (http_state == NULL) {
3400  printf("no http state: ");
3401  goto end;
3402  }
3403 
3404  /* do detect */
3405  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3406 
3407  if (!PacketAlertCheck(p, 1)) {
3408  printf("sig 1 didn't alert, but it should: ");
3409  goto end;
3410  }
3411 
3412  result = 1;
3413 
3414  end:
3415  if (alp_tctx != NULL)
3417  if (det_ctx != NULL)
3418  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3419  if (de_ctx != NULL)
3421  if (de_ctx != NULL)
3423 
3425 
3426  UTHFreePackets(&p, 1);
3427  UTHFreeFlow(f);
3428  return result;
3429 }
3430 
3431 /** \test test if the engine detect the proto and doesn't match
3432  * because the sig expects another proto (ex ftp)*/
3433 static int AppLayerProtoDetectTest18(void)
3434 {
3435  int result = 0;
3436  Flow *f = NULL;
3437  HtpState *http_state = NULL;
3438  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3439  "User-Agent: Mozilla/1.0\r\n"
3440  "Cookie: hellocatch\r\n\r\n";
3441  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3442  TcpSession ssn;
3443  Packet *p = NULL;
3444  Signature *s = NULL;
3445  ThreadVars tv;
3446  DetectEngineThreadCtx *det_ctx = NULL;
3447  DetectEngineCtx *de_ctx = NULL;
3449 
3450  memset(&tv, 0, sizeof(ThreadVars));
3451  memset(&ssn, 0, sizeof(TcpSession));
3452 
3453  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3454 
3455  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3456  if (f == NULL)
3457  goto end;
3458  f->protoctx = &ssn;
3459  f->proto = IPPROTO_TCP;
3460  p->flow = f;
3464  f->alproto = ALPROTO_HTTP;
3465 
3467 
3469  if (de_ctx == NULL) {
3470  goto end;
3471  }
3472  de_ctx->flags |= DE_QUIET;
3473 
3474  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3475  "(msg:\"Test content option\"; "
3476  "sid:1;)");
3477  if (s == NULL) {
3478  goto end;
3479  }
3480 
3482  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3483 
3484  FLOWLOCK_WRLOCK(f);
3485  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3486  STREAM_TOSERVER, http_buf1, http_buf1_len);
3487  if (r != 0) {
3488  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3489  FLOWLOCK_UNLOCK(f);
3490  goto end;
3491  }
3492  FLOWLOCK_UNLOCK(f);
3493 
3494  http_state = f->alstate;
3495  if (http_state == NULL) {
3496  printf("no http state: ");
3497  goto end;
3498  }
3499 
3500  /* do detect */
3501  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3502 
3503  if (PacketAlertCheck(p, 1)) {
3504  printf("sig 1 alerted, but it should not (it's not ftp): ");
3505  goto end;
3506  }
3507 
3508  result = 1;
3509  end:
3510  if (alp_tctx != NULL)
3512  if (det_ctx != NULL)
3513  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3514  if (de_ctx != NULL)
3516  if (de_ctx != NULL)
3518 
3520 
3521  UTHFreePackets(&p, 1);
3522  UTHFreeFlow(f);
3523  return result;
3524 }
3525 
3526 /** \test test if the engine detect the proto and doesn't match
3527  * because the packet has another proto (ex ftp) */
3528 static int AppLayerProtoDetectTest19(void)
3529 {
3530  int result = 0;
3531  Flow *f = NULL;
3532  uint8_t http_buf1[] = "MPUT one\r\n";
3533  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3534  TcpSession ssn;
3535  Packet *p = NULL;
3536  Signature *s = NULL;
3537  ThreadVars tv;
3538  DetectEngineThreadCtx *det_ctx = NULL;
3539  DetectEngineCtx *de_ctx = NULL;
3541 
3542  memset(&tv, 0, sizeof(ThreadVars));
3543  memset(&ssn, 0, sizeof(TcpSession));
3544 
3545  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3546 
3547  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3548  if (f == NULL)
3549  goto end;
3550  f->protoctx = &ssn;
3551  f->proto = IPPROTO_TCP;
3552  p->flow = f;
3556  f->alproto = ALPROTO_FTP;
3557 
3559 
3561  if (de_ctx == NULL) {
3562  goto end;
3563  }
3564  de_ctx->flags |= DE_QUIET;
3565 
3566  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3567  "(msg:\"http over non standar port\"; "
3568  "sid:1;)");
3569  if (s == NULL) {
3570  goto end;
3571  }
3572 
3574  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3575 
3576  FLOWLOCK_WRLOCK(f);
3577  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3578  STREAM_TOSERVER, http_buf1, http_buf1_len);
3579  if (r != 0) {
3580  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3581  FLOWLOCK_UNLOCK(f);
3582  goto end;
3583  }
3584  FLOWLOCK_UNLOCK(f);
3585 
3586  /* do detect */
3587  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3588 
3589  if (PacketAlertCheck(p, 1)) {
3590  printf("sig 1 alerted, but it should not (it's ftp): ");
3591  goto end;
3592  }
3593 
3594  result = 1;
3595 
3596  end:
3597  if (alp_tctx != NULL)
3599  if (det_ctx != NULL)
3600  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3601  if (de_ctx != NULL)
3603  if (de_ctx != NULL)
3605 
3607  UTHFreePackets(&p, 1);
3608  UTHFreeFlow(f);
3609  return result;
3610 }
3611 
3613 {
3614  SCEnter();
3615 
3616  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3617  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3618  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3619  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3620  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3621  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3622  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3623  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3624  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3625  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3626  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3627  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3628  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3629  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3630  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3631  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3632  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3633  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3634  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3635 
3636  SCReturn;
3637 }
3638 
3639 #endif /* UNITTESTS */
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2797
DETECT_CONTENT_NOCASE
#define DETECT_CONTENT_NOCASE
Definition: detect-content.h:29
AppLayerProtoDetectPMCtx_
Definition: app-layer-detect-proto.c:123
AppLayerProtoDetectProbingParserElement_
Definition: app-layer-detect-proto.c:67
AppLayerProtoDetectThreadCtx_::mpm_tctx
MpmThreadCtx mpm_tctx[FLOW_PROTO_DEFAULT][2]
Definition: app-layer-detect-proto.c:170
FLOW_RESET_PP_DONE
#define FLOW_RESET_PP_DONE(f, dir)
Definition: flow.h:278
AppLayerProtoDetectUnittestCtxRestore
void AppLayerProtoDetectUnittestCtxRestore(void)
Restores back the internal context used by the app layer proto detection module, that was previously ...
Definition: app-layer-detect-proto.c:2118
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:100
ALPROTO_IKEV2
@ ALPROTO_IKEV2
Definition: app-layer-protos.h:49
AppLayerProtoDetectPMSignature_::cd
DetectContentData * cd
Definition: app-layer-detect-proto.c:116
AppLayerProtoDetectPMCtx_::max_pat_id
PatIntId max_pat_id
Definition: app-layer-detect-proto.c:135
tm-threads.h
AppLayerProtoDetectPMSignature_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:112
AppLayerProtoDetectPPParseConfPorts
int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
Definition: app-layer-detect-proto.c:1649
detect-content.h
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:90
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
AppLayerProtoDetectSetup
int AppLayerProtoDetectSetup(void)
The first function to be called. This initializes a global protocol detection context.
Definition: app-layer-detect-proto.c:1765
AppLayerProtoDetectProbingParser_::next
struct AppLayerProtoDetectProbingParser_ * next
Definition: app-layer-detect-proto.c:108
FlowSetChangeProtoFlag
void FlowSetChangeProtoFlag(Flow *f)
Set flag to indicate to change proto for the flow.
Definition: flow.c:193
AppLayerProtoDetectPMRegisterPatternCI
int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction)
Registers a case-insensitive pattern for protocol detection.
Definition: app-layer-detect-proto.c:1750
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:73
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1109
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
ALPROTO_DCERPC
@ ALPROTO_DCERPC
Definition: app-layer-protos.h:38
MpmTableElmt_::InitThreadCtx
void(* InitThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:144
FLOW_IS_PE_DONE
#define FLOW_IS_PE_DONE(f, dir)
Definition: flow.h:271
flow-util.h
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
AppLayerExpectationSetup
void AppLayerExpectationSetup(void)
Definition: app-layer-expectation.c:147
FLOW_SET_PM_DONE
#define FLOW_SET_PM_DONE(f, dir)
Definition: flow.h:273
MpmThreadCtx_
Definition: util-mpm.h:46
ConfNode_::val
char * val
Definition: conf.h:34
stream-tcp.h
PrefilterRuleStore_::rule_id_array_cnt
uint32_t rule_id_array_cnt
Definition: util-prefilter.h:38
ALPROTO_ENIP
@ ALPROTO_ENIP
Definition: app-layer-protos.h:43
AppLayerExpectationHandle
AppProto AppLayerExpectationHandle(Flow *f, int direction)
Definition: app-layer-expectation.c:302
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
ALPROTO_TLS
@ ALPROTO_TLS
Definition: app-layer-protos.h:33
PrefilterRuleStore_
structure for storing potential rule matches
Definition: util-prefilter.h:32
AppLayerProtoDetectPMCtx_::map
AppLayerProtoDetectPMSignature ** map
Definition: app-layer-detect-proto.c:131
AppLayerProtoDetectProbingParserElement_::max_depth
uint32_t max_depth
Definition: app-layer-detect-proto.c:77
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
DetectPort_::port
uint16_t port
Definition: detect.h:192
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint16_t matcher)
Definition: util-mpm.c:254
AppLayerProtoDetectProbingParserPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:90
ALPROTO_MODBUS
@ ALPROTO_MODBUS
Definition: app-layer-protos.h:42
Flow_::proto
uint8_t proto
Definition: flow.h:365
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:73
TcpStreamCnf_::midstream
int midstream
Definition: stream-tcp.h:58
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:138
AppLayerProtoDetectProbingParserElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:68
SC_ERR_NOT_SUPPORTED
@ SC_ERR_NOT_SUPPORTED
Definition: util-error.h:257
Packet_::flags
uint32_t flags
Definition: decode.h:449
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:175
threads.h
ALPROTO_JABBER
@ ALPROTO_JABBER
Definition: app-layer-protos.h:36
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:347
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2051
AppLayerProtoDetectUnittestCtxBackup
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
Definition: app-layer-detect-proto.c:2110
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2789
Flow_::protomap
uint8_t protomap
Definition: flow.h:445
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:30
ALPROTO_IRC
@ ALPROTO_IRC
Definition: app-layer-protos.h:39
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:767
AppLayerProtoDetectPPTestDataElement
struct AppLayerProtoDetectPPTestDataElement_ AppLayerProtoDetectPPTestDataElement
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2093
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2029
ALPROTO_SIP
@ ALPROTO_SIP
Definition: app-layer-protos.h:53
AppLayerProtoDetectProbingParserPort_::sp
AppLayerProtoDetectProbingParserElement * sp
Definition: app-layer-detect-proto.c:99
AppLayerProtoDetectCtx_::ctx_ipp
AppLayerProtoDetectCtxIpproto ctx_ipp[FLOW_PROTO_DEFAULT]
Definition: app-layer-detect-proto.c:151
AppLayerProtoDetectPMSignature_::PPFunc
ProbingParserFPtr PPFunc
Definition: app-layer-detect-proto.c:119
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:278
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:219
MIN
#define MIN(x, y)
Definition: suricata-common.h:377
AppLayerProtoDetectPMCtx
struct AppLayerProtoDetectPMCtx_ AppLayerProtoDetectPMCtx
DE_QUIET
#define DE_QUIET
Definition: detect.h:294
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:205
ALPROTO_FTP
@ ALPROTO_FTP
Definition: app-layer-protos.h:31
AppLayerProtoDetectPPTestDataElement_::min_depth
uint32_t min_depth
Definition: app-layer-detect-proto.c:2793
PatIntId
#define PatIntId
Definition: suricata-common.h:300
stream-tcp-reassemble.h
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:337
AppLayerProtoDetectPPTestDataElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:2790
AppLayerProtoDetectProbingParserElement
struct AppLayerProtoDetectProbingParserElement_ AppLayerProtoDetectProbingParserElement
proto
uint8_t proto
Definition: decode-template.h:0
m
SCMutex m
Definition: flow-hash.h:6
DetectContentData_
Definition: detect-content.h:86
UTHBuildPacketSrcDstPorts
Packet * UTHBuildPacketSrcDstPorts(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, uint16_t sport, uint16_t dport)
UTHBuildPacketSrcDstPorts is a wrapper that build packets specifying src and dst ports and defaulting...
Definition: util-unittest-helper.c:454
AppLayerProtoDetectPMSignature_
Definition: app-layer-detect-proto.c:111
MpmCtx_::maxdepth
uint16_t maxdepth
Definition: util-mpm.h:94
ALPROTO_SSH
@ ALPROTO_SSH
Definition: app-layer-protos.h:34
ALPROTO_DHCP
@ ALPROTO_DHCP
Definition: app-layer-protos.h:51
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:445
stream_config
TcpStreamCnf stream_config
Definition: stream-tcp.c:119
ALPROTO_MAX
@ ALPROTO_MAX
Definition: app-layer-protos.h:68
Flow_::protoctx
void * protoctx
Definition: flow.h:441
AppLayerProtoDetectProbingParser_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:105
AppLayerProtoDetectProbingParserPort_::sp_max_depth
uint16_t sp_max_depth
Definition: app-layer-detect-proto.c:96
DetectPort_::port2
uint16_t port2
Definition: detect.h:193
DetectContentFree
void DetectContentFree(DetectEngineCtx *de_ctx, void *ptr)
this function will SCFree memory associated with DetectContentData
Definition: detect-content.c:374
AppLayerProtoDetectPPTestDataElement_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:2792
util-unittest.h
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:109
HtpState_
Definition: app-layer-htp.h:243
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:565
FLOW_SET_PP_DONE
#define FLOW_SET_PP_DONE(f, dir)
Definition: flow.h:274
util-unittest-helper.h
FLOWLOCK_UNLOCK
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:264
AppLayerProtoDetectPPTestDataIPProto_
Definition: app-layer-detect-proto.c:2810
ALPROTO_KRB5
@ ALPROTO_KRB5
Definition: app-layer-protos.h:50
ALPROTO_SNMP
@ ALPROTO_SNMP
Definition: app-layer-protos.h:52
util-memcmp.h
FLOW_IS_PM_DONE
#define FLOW_IS_PM_DONE(f, dir)
Definition: flow.h:269
AppLayerProtoDetectPPRegister
void AppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
Definition: app-layer-detect-proto.c:1615
AppLayerProtoDetectCtx_::spm_global_thread_ctx
SpmGlobalThreadCtx * spm_global_thread_ctx
Definition: app-layer-detect-proto.c:154
AppLayerProtoDetectProbingParserPort_::dp
AppLayerProtoDetectProbingParserElement * dp
Definition: app-layer-detect-proto.c:98
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:475
app-layer-expectation.h
app-layer-detect-proto.h
UTHBuildFlow
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Definition: util-unittest-helper.c:521
expectation_proto
uint8_t expectation_proto[ALPROTO_MAX]
Definition: app-layer-detect-proto.c:2078
app-layer-htp.h
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1243
AppLayerProtoDetectThreadCtx_
The app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:167
Flow_::protodetect_dp
uint16_t protodetect_dp
Definition: flow.h:427
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
AppLayerProtoDetectProbingParserElement_::ProbingParserTs
ProbingParserFPtr ProbingParserTs
Definition: app-layer-detect-proto.c:80
FLOW_IS_PP_DONE
#define FLOW_IS_PP_DONE(f, dir)
Definition: flow.h:270
DetectEngineThreadCtx_
Definition: detect.h:1010
ALPROTO_DNP3
@ ALPROTO_DNP3
Definition: app-layer-protos.h:44
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:32
STREAM_TOSERVER
#define STREAM_TOSERVER
Definition: stream.h:31
AppLayerProtoDetectProbingParserPort
struct AppLayerProtoDetectProbingParserPort_ AppLayerProtoDetectProbingParserPort
AppLayerProtoDetectProbingParserPort_::dp_max_depth
uint16_t dp_max_depth
Definition: app-layer-detect-proto.c:95
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:19
FLOWLOCK_WRLOCK
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:261
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
AppLayerProtoDetectProbingParserPort_::next
struct AppLayerProtoDetectProbingParserPort_ * next
Definition: app-layer-detect-proto.c:101
AppLayerProtoDetectReset
void AppLayerProtoDetectReset(Flow *f)
Reset proto detect for flow.
Definition: app-layer-detect-proto.c:1869
AppLayerProtoDetectPMRegisterPatternCSwPP
int AppLayerProtoDetectPMRegisterPatternCSwPP(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction, ProbingParserFPtr PPFunc, uint16_t pp_min_depth, uint16_t pp_max_depth)
Definition: app-layer-detect-proto.c:1736
detect-engine-port.h
AppLayerProtoDetectPPTestDataPort_::toserver_element
AppLayerProtoDetectPPTestDataElement * toserver_element
Definition: app-layer-detect-proto.c:2803
alpd_tctx
AppLayerProtoDetectThreadCtx * alpd_tctx
Definition: fuzz_applayerprotodetectgetproto.c:22
DetectPort_
Port structure for detection engine.
Definition: detect.h:191
AppLayerProtoDetectProbingParserPort_
Definition: app-layer-detect-proto.c:88
DetectContentData_::id
PatIntId id
Definition: detect-content.h:98
app-layer-parser.h
TRUE
#define TRUE
Definition: suricata-common.h:33
AppLayerProtoDetectPPTestDataIPProto_::no_of_port
int no_of_port
Definition: app-layer-detect-proto.c:2814
AppLayerProtoDetectCtx_
The app layer protocol detection context.
Definition: app-layer-detect-proto.c:147
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:282
AppLayerProtoDetectProbingParserElement_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:72
SigMatchSignatures
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1688
PmqReset
void PmqReset(PrefilterRuleStore *)
Reset a Pmq for reusage. Meant to be called after a single search.
Definition: util-prefilter.c:101
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1949
SCReturn
#define SCReturn
Definition: util-debug.h:302
FLOW_RESET_PM_DONE
#define FLOW_RESET_PM_DONE(f, dir)
Definition: flow.h:277
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:99
stream.h
SpmScan
uint8_t * SpmScan(const SpmCtx *ctx, SpmThreadCtx *thread_ctx, const uint8_t *haystack, uint32_t haystack_len)
Definition: util-spm.c:194
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:95
AppLayerProtoDetectPPTestDataPort_::toclient_element
AppLayerProtoDetectPPTestDataElement * toclient_element
Definition: app-layer-detect-proto.c:2804
Packet_
Definition: decode.h:414
FLOW_GET_DP
#define FLOW_GET_DP(f)
Definition: flow.h:159
StreamTcpFreeConfig
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:668
ALPROTO_IMAP
@ ALPROTO_IMAP
Definition: app-layer-protos.h:35
FLOW_GET_SP
#define FLOW_GET_SP(f)
Definition: flow.h:157
stream-tcp-private.h
SCReturnUInt
#define SCReturnUInt(x)
Definition: util-debug.h:306
conf.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:97
AppLayerProtoDetectPMCtx_::head
AppLayerProtoDetectPMSignature * head
Definition: app-layer-detect-proto.c:132
SinglePatternMatchDefaultMatcher
uint16_t SinglePatternMatchDefaultMatcher(void)
Returns the single pattern matcher algorithm to be used, based on the spm-algo setting in yaml.
Definition: util-spm.c:68
AppLayerRegisterExpectationProto
void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
Definition: app-layer-detect-proto.c:2091
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2806
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:161
AppLayerRequestProtocolChange
void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
request applayer to wrap up this protocol and rerun protocol detection.
Definition: app-layer-detect-proto.c:1849
SpmMakeThreadCtx
SpmThreadCtx * SpmMakeThreadCtx(const SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:154
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:316
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1825
AppLayerProtoDetectPMSignature_::pp_min_depth
uint16_t pp_min_depth
Definition: app-layer-detect-proto.c:117
AppLayerProtoDetectPMCtx_::max_sig_id
SigIntId max_sig_id
Definition: app-layer-detect-proto.c:136
ProbingParserFPtr
AppProto(* ProbingParserFPtr)(Flow *f, uint8_t dir, const uint8_t *input, uint32_t input_len, uint8_t *rdir)
Definition: app-layer-detect-proto.h:30
ALPROTO_TFTP
@ ALPROTO_TFTP
Definition: app-layer-protos.h:48
AppLayerProtoDetectPPTestDataPort_::dp_max_depth
uint16_t dp_max_depth
Definition: app-layer-detect-proto.c:2800
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:419
AppLayerProtoDetectPMSignature_::pp_max_depth
uint16_t pp_max_depth
Definition: app-layer-detect-proto.c:118
AppLayerProtoDetectPPTestDataPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:2798
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:162
AppLayerProtoDetectPMCtx_::mpm_ctx
MpmCtx mpm_ctx
Definition: app-layer-detect-proto.c:126
MpmAddPatternCS
int MpmAddPatternCS(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:295
Flow_::alproto_expect
AppProto alproto_expect
Definition: flow.h:459
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:264
AppLayerProtoDetectThreadCtx_::spm_thread_ctx
SpmThreadCtx * spm_thread_ctx
Definition: app-layer-detect-proto.c:171
AppLayerProtoDetectCtx
struct AppLayerProtoDetectCtx_ AppLayerProtoDetectCtx
The app layer protocol detection context.
AppLayerProtoDetectProbingParserElement_::min_depth
uint32_t min_depth
Definition: app-layer-detect-proto.c:75
SpmDestroyGlobalThreadCtx
void SpmDestroyGlobalThreadCtx(SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:145
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1884
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:418
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:526
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:252
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:814
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:70
AppLayerRequestProtocolTLSUpgrade
void AppLayerRequestProtocolTLSUpgrade(Flow *f)
request applayer to wrap up this protocol and rerun protocol detection with expectation of TLS....
Definition: app-layer-detect-proto.c:1864
Packet_::flow
struct Flow_ * flow
Definition: decode.h:451
SpmDestroyThreadCtx
void SpmDestroyThreadCtx(SpmThreadCtx *thread_ctx)
Definition: util-spm.c:164
AppLayerProtoDetectPMSignature_::direction
uint8_t direction
Definition: app-layer-detect-proto.c:113
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2797
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
AppLayerProtoDetectPPTestDataPort_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:2799
AppLayerProtoDetectPMSignature_::next
struct AppLayerProtoDetectPMSignature_ * next
Definition: app-layer-detect-proto.c:120
AppLayerProtoDetectPPTestDataIPProto
struct AppLayerProtoDetectPPTestDataIPProto_ AppLayerProtoDetectPPTestDataIPProto
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1178
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3005
AppLayerProtoDetectPPTestDataIPProto_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:2811
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:97
AppLayerProtoDetectPMSignature
struct AppLayerProtoDetectPMSignature_ AppLayerProtoDetectPMSignature
FLOW_RESET_PE_DONE
#define FLOW_RESET_PE_DONE(f, dir)
Definition: flow.h:279
AppLayerProtoDetectDeSetup
int AppLayerProtoDetectDeSetup(void)
Cleans up the app layer protocol detection phase.
Definition: app-layer-detect-proto.c:1795
PatternMatchDefaultMatcher
uint16_t PatternMatchDefaultMatcher(void)
Function to return the multi pattern matcher algorithm to be used by the engine, based on the mpm-alg...
Definition: detect-engine-mpm.c:615
SWAP_VARS
#define SWAP_VARS(type, a, b)
Definition: suricata-common.h:412
AppLayerProtoDetectPMSignature_::id
SigIntId id
Definition: app-layer-detect-proto.c:114
util-spm.h
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:87
STREAM_TOCLIENT
#define STREAM_TOCLIENT
Definition: stream.h:32
PmqFree
void PmqFree(PrefilterRuleStore *)
Cleanup and free a Pmq.
Definition: util-prefilter.c:126
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
ALPROTO_FTPDATA
@ ALPROTO_FTPDATA
Definition: app-layer-protos.h:47
AppLayerProtoDetectCtx_::alproto_names
const char * alproto_names[ALPROTO_MAX]
Definition: app-layer-detect-proto.c:161
FatalError
#define FatalError(x,...)
Definition: util-debug.h:532
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:773
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
AppLayerProtoDetectProbingParserElement_::next
struct AppLayerProtoDetectProbingParserElement_ * next
Definition: app-layer-detect-proto.c:85
threadvars.h
SpmGlobalThreadCtx_
Definition: util-spm.h:49
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DetectContentData_::spm_ctx
SpmCtx * spm_ctx
Definition: detect-content.h:104
AppLayerProtoDetectSupportedAppProtocols
void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
Definition: app-layer-detect-proto.c:2062
AppLayerProtoDetectUnittestsRegister
void AppLayerProtoDetectUnittestsRegister(void)
Register unittests for app layer proto detection module.
Definition: app-layer-detect-proto.c:3612
AppLayerProtoDetectCtxIpproto_::ctx_pm
AppLayerProtoDetectPMCtx ctx_pm[2]
Definition: app-layer-detect-proto.c:141
AppLayerProtoDetectPPTestDataElement_::max_depth
uint32_t max_depth
Definition: app-layer-detect-proto.c:2794
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:1949
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2040
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:145
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alproto_ts
AppProto alproto_ts
Definition: flow.h:451
ConfNode_
Definition: conf.h:32
Flow_::alstate
void * alstate
Definition: flow.h:476
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
AppLayerProtoDetectCtxIpproto_
Definition: app-layer-detect-proto.c:139
AppLayerProtoDetectPMCtx_::pp_max_len
uint16_t pp_max_len
Definition: app-layer-detect-proto.c:124
PmqSetup
int PmqSetup(PrefilterRuleStore *)
Setup a pmq.
Definition: util-prefilter.c:36
detect-parse.h
Signature_
Signature container.
Definition: detect.h:528
ALPROTO_MQTT
@ ALPROTO_MQTT
Definition: app-layer-protos.h:55
ConfValIsFalse
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:590
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:30
AppLayerProtoDetectProbingParserElement_::ProbingParserTc
ProbingParserFPtr ProbingParserTc
Definition: app-layer-detect-proto.c:83
StreamTcpInitConfig
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:63
ALPROTO_TEMPLATE
@ ALPROTO_TEMPLATE
Definition: app-layer-protos.h:56
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:221
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2048
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:48
SCReturnCT
#define SCReturnCT(x, type)
Definition: util-debug.h:314
AppLayerProtoDetectThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: app-layer-detect-proto.c:168
app-layer-protos.h
AppLayerProtoDetectProbingParser_
Definition: app-layer-detect-proto.c:104
ALPROTO_RFB
@ ALPROTO_RFB
Definition: app-layer-protos.h:54
AppLayerProtoDetectPPTestDataPort_::ts_no_of_element
int ts_no_of_element
Definition: app-layer-detect-proto.c:2805
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:88
AppLayerProtoDetectPPTestDataPort
struct AppLayerProtoDetectPPTestDataPort_ AppLayerProtoDetectPPTestDataPort
AppLayerProtoDetectDestroyCtxThread
void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx *alpd_tctx)
Destroys the app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:2003
AppLayerProtoDetectProbingParserElement_::port
uint16_t port
Definition: app-layer-detect-proto.c:70
ALPROTO_NTP
@ ALPROTO_NTP
Definition: app-layer-protos.h:46
ALPROTO_SMB
@ ALPROTO_SMB
Definition: app-layer-protos.h:37
likely
#define likely(expr)
Definition: util-optimize.h:32
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:768
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:146
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:87
DetectContentParseEncloseQuotes
DetectContentData * DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr)
Definition: detect-content.c:247
AppLayerProtoDetectPMRegisterPatternCS
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.
Definition: app-layer-detect-proto.c:1723
SpmInitGlobalThreadCtx
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint16_t matcher)
Definition: util-spm.c:139
AppLayerProtoDetectGetProto
AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f, const uint8_t *buf, uint32_t buflen, uint8_t ipproto, uint8_t direction, bool *reverse_flow)
Returns the app layer protocol given a buffer.
Definition: app-layer-detect-proto.c:1495
MpmCtx_
Definition: util-mpm.h:88
TcpSession_
Definition: stream-tcp-private.h:261
AppLayerProtoDetectProbingParser
struct AppLayerProtoDetectProbingParser_ AppLayerProtoDetectProbingParser
FLOW_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:71
flow.h
SigIntId
#define SigIntId
Definition: suricata-common.h:297
Flow_::alproto_tc
AppProto alproto_tc
Definition: flow.h:452
SpmDestroyCtx
void SpmDestroyCtx(SpmCtx *ctx)
Definition: util-spm.c:184
AppLayerProtoDetectPMCtx_::min_len
uint16_t min_len
Definition: app-layer-detect-proto.c:125
AppLayerProtoDetectPrepareState
int AppLayerProtoDetectPrepareState(void)
Prepares the internal state for protocol detection. This needs to be called once all the patterns and...
Definition: app-layer-detect-proto.c:1571
FLOW_SET_PE_DONE
#define FLOW_SET_PE_DONE(f, dir)
Definition: flow.h:275
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
AppLayerProtoDetectCtx_::ctx_pp
AppLayerProtoDetectProbingParser * ctx_pp
Definition: app-layer-detect-proto.c:156
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-pool.h
AppLayerProtoDetectPPTestDataElement_::port
uint16_t port
Definition: app-layer-detect-proto.c:2791
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
MpmAddPatternCI
int MpmAddPatternCI(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:304
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:369
AppLayerProtoDetectConfProtoDetectionEnabled
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:1888
SC_ERR_ALPARSER
@ SC_ERR_ALPARSER
Definition: util-error.h:89
AppLayerProtoDetectPPTestDataPort_::sp_max_depth
uint16_t sp_max_depth
Definition: app-layer-detect-proto.c:2801
SpmInitCtx
SpmCtx * SpmInitCtx(const uint8_t *needle, uint16_t needle_len, int nocase, SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:174
DetectPortCleanupList
void DetectPortCleanupList(const DetectEngineCtx *de_ctx, DetectPort *head)
Free a DetectPort list and each of its members.
Definition: detect-engine-port.c:121
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:662
ALPROTO_NFS
@ ALPROTO_NFS
Definition: app-layer-protos.h:45
debug.h
AppLayerProtoDetectProbingParser_::port
AppLayerProtoDetectProbingParserPort * port
Definition: app-layer-detect-proto.c:106
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1107
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2813
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2057
AppLayerProtoDetectProbingParserPort_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:92
app-layer.h
ALPROTO_TEMPLATE_RUST
@ ALPROTO_TEMPLATE_RUST
Definition: app-layer-protos.h:57
AppLayerProtoDetectCtxIpproto
struct AppLayerProtoDetectCtxIpproto_ AppLayerProtoDetectCtxIpproto
PrefilterRuleStore_::rule_id_array
SigIntId * rule_id_array
Definition: util-prefilter.h:36
SpmThreadCtx_
Definition: util-spm.h:56
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:468
AppLayerProtoDetectPPTestDataElement_
Definition: app-layer-detect-proto.c:2788