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  SCLogError(SC_ERR_ALPARSER, "Unknown protocol detected - %"PRIu16,
649  alproto);
650  exit(EXIT_FAILURE);
651  }
652 
653  SCReturnUInt(1 << alproto);
654 }
655 
656 static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectProbingParserElementAlloc(void)
657 {
658  SCEnter();
659 
661  if (unlikely(p == NULL)) {
662  exit(EXIT_FAILURE);
663  }
664  memset(p, 0, sizeof(AppLayerProtoDetectProbingParserElement));
665 
666  SCReturnPtr(p, "AppLayerProtoDetectProbingParserElement");
667 }
668 
669 
670 static void AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement *p)
671 {
672  SCEnter();
673  SCFree(p);
674  SCReturn;
675 }
676 
677 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectProbingParserPortAlloc(void)
678 {
679  SCEnter();
680 
682  if (unlikely(p == NULL)) {
683  exit(EXIT_FAILURE);
684  }
685  memset(p, 0, sizeof(AppLayerProtoDetectProbingParserPort));
686 
687  SCReturnPtr(p, "AppLayerProtoDetectProbingParserPort");
688 }
689 
690 static void AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort *p)
691 {
692  SCEnter();
693 
695 
696  e = p->dp;
697  while (e != NULL) {
699  AppLayerProtoDetectProbingParserElementFree(e);
700  e = e_next;
701  }
702 
703  e = p->sp;
704  while (e != NULL) {
706  AppLayerProtoDetectProbingParserElementFree(e);
707  e = e_next;
708  }
709 
710  SCFree(p);
711 
712  SCReturn;
713 }
714 
715 static AppLayerProtoDetectProbingParser *AppLayerProtoDetectProbingParserAlloc(void)
716 {
717  SCEnter();
718 
720  if (unlikely(p == NULL)) {
721  exit(EXIT_FAILURE);
722  }
723  memset(p, 0, sizeof(AppLayerProtoDetectProbingParser));
724 
725  SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
726 }
727 
728 static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser *p)
729 {
730  SCEnter();
731 
733  while (pt != NULL) {
735  AppLayerProtoDetectProbingParserPortFree(pt);
736  pt = pt_next;
737  }
738 
739  SCFree(p);
740 
741  SCReturn;
742 }
743 
745 AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
746  uint16_t port,
747  uint16_t min_depth,
748  uint16_t max_depth)
749 {
750  AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
751 
752  pe->alproto = alproto;
753  pe->port = port;
754  pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
755  pe->min_depth = min_depth;
756  pe->max_depth = max_depth;
757  pe->next = NULL;
758 
759  if (max_depth != 0 && min_depth >= max_depth) {
760  SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to "
761  "register the probing parser. min_depth >= max_depth");
762  goto error;
763  }
764  if (alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_MAX) {
765  SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to register "
766  "the probing parser. Invalid alproto - %d", alproto);
767  goto error;
768  }
769 
770  SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
771  error:
772  AppLayerProtoDetectProbingParserElementFree(pe);
773  SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
774 }
775 
777 AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement *pe)
778 {
779  SCEnter();
780 
781  AppLayerProtoDetectProbingParserElement *new_pe = AppLayerProtoDetectProbingParserElementAlloc();
782 
783  new_pe->alproto = pe->alproto;
784  new_pe->port = pe->port;
785  new_pe->alproto_mask = pe->alproto_mask;
786  new_pe->min_depth = pe->min_depth;
787  new_pe->max_depth = pe->max_depth;
788  new_pe->ProbingParserTs = pe->ProbingParserTs;
789  new_pe->ProbingParserTc = pe->ProbingParserTc;
790  new_pe->next = NULL;
791 
792  SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
793 }
794 
795 #ifdef DEBUG
796 static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser *pp)
797 {
798  SCEnter();
799 
800  AppLayerProtoDetectProbingParserPort *pp_port = NULL;
802 
803  printf("\nProtocol Detection Configuration\n");
804 
805  for ( ; pp != NULL; pp = pp->next) {
806  /* print ip protocol */
807  if (pp->ipproto == IPPROTO_TCP)
808  printf("IPProto: TCP\n");
809  else if (pp->ipproto == IPPROTO_UDP)
810  printf("IPProto: UDP\n");
811  else
812  printf("IPProto: %"PRIu8"\n", pp->ipproto);
813 
814  pp_port = pp->port;
815  for ( ; pp_port != NULL; pp_port = pp_port->next) {
816  if (pp_port->dp != NULL) {
817  printf(" Port: %"PRIu16 "\n", pp_port->port);
818 
819  printf(" Destination port: (max-depth: %"PRIu16 ", "
820  "mask - %"PRIu32")\n",
821  pp_port->dp_max_depth,
822  pp_port->alproto_mask);
823  pp_pe = pp_port->dp;
824  for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
825 
826  if (pp_pe->alproto == ALPROTO_HTTP)
827  printf(" alproto: ALPROTO_HTTP\n");
828  else if (pp_pe->alproto == ALPROTO_FTP)
829  printf(" alproto: ALPROTO_FTP\n");
830  else if (pp_pe->alproto == ALPROTO_FTPDATA)
831  printf(" alproto: ALPROTO_FTPDATA\n");
832  else if (pp_pe->alproto == ALPROTO_SMTP)
833  printf(" alproto: ALPROTO_SMTP\n");
834  else if (pp_pe->alproto == ALPROTO_TLS)
835  printf(" alproto: ALPROTO_TLS\n");
836  else if (pp_pe->alproto == ALPROTO_SSH)
837  printf(" alproto: ALPROTO_SSH\n");
838  else if (pp_pe->alproto == ALPROTO_IMAP)
839  printf(" alproto: ALPROTO_IMAP\n");
840  else if (pp_pe->alproto == ALPROTO_JABBER)
841  printf(" alproto: ALPROTO_JABBER\n");
842  else if (pp_pe->alproto == ALPROTO_SMB)
843  printf(" alproto: ALPROTO_SMB\n");
844  else if (pp_pe->alproto == ALPROTO_DCERPC)
845  printf(" alproto: ALPROTO_DCERPC\n");
846  else if (pp_pe->alproto == ALPROTO_IRC)
847  printf(" alproto: ALPROTO_IRC\n");
848  else if (pp_pe->alproto == ALPROTO_DNS)
849  printf(" alproto: ALPROTO_DNS\n");
850  else if (pp_pe->alproto == ALPROTO_MODBUS)
851  printf(" alproto: ALPROTO_MODBUS\n");
852  else if (pp_pe->alproto == ALPROTO_ENIP)
853  printf(" alproto: ALPROTO_ENIP\n");
854  else if (pp_pe->alproto == ALPROTO_NFS)
855  printf(" alproto: ALPROTO_NFS\n");
856  else if (pp_pe->alproto == ALPROTO_NTP)
857  printf(" alproto: ALPROTO_NTP\n");
858  else if (pp_pe->alproto == ALPROTO_TFTP)
859  printf(" alproto: ALPROTO_TFTP\n");
860  else if (pp_pe->alproto == ALPROTO_IKEV2)
861  printf(" alproto: ALPROTO_IKEV2\n");
862  else if (pp_pe->alproto == ALPROTO_KRB5)
863  printf(" alproto: ALPROTO_KRB5\n");
864  else if (pp_pe->alproto == ALPROTO_DHCP)
865  printf(" alproto: ALPROTO_DHCP\n");
866  else if (pp_pe->alproto == ALPROTO_SNMP)
867  printf(" alproto: ALPROTO_SNMP\n");
868  else if (pp_pe->alproto == ALPROTO_SIP)
869  printf(" alproto: ALPROTO_SIP\n");
870  else if (pp_pe->alproto == ALPROTO_TEMPLATE_RUST)
871  printf(" alproto: ALPROTO_TEMPLATE_RUST\n");
872  else if (pp_pe->alproto == ALPROTO_RFB)
873  printf(" alproto: ALPROTO_RFB\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_TEMPLATE)
950  printf(" alproto: ALPROTO_TEMPLATE\n");
951  else if (pp_pe->alproto == ALPROTO_DNP3)
952  printf(" alproto: ALPROTO_DNP3\n");
953  else
954  printf("impossible\n");
955 
956  printf(" port: %"PRIu16 "\n", pp_pe->port);
957  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
958  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
959  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
960 
961  printf("\n");
962  }
963  }
964  }
965 
966  SCReturn;
967 }
968 #endif
969 
970 static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
972 {
973  SCEnter();
974 
975  if (*head_pe == NULL) {
976  *head_pe = new_pe;
977  goto end;
978  }
979 
980  if ((*head_pe)->port == 0) {
981  if (new_pe->port != 0) {
982  new_pe->next = *head_pe;
983  *head_pe = new_pe;
984  } else {
985  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
986  while (temp_pe->next != NULL)
987  temp_pe = temp_pe->next;
988  temp_pe->next = new_pe;
989  }
990  } else {
991  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
992  if (new_pe->port == 0) {
993  while (temp_pe->next != NULL)
994  temp_pe = temp_pe->next;
995  temp_pe->next = new_pe;
996  } else {
997  while (temp_pe->next != NULL && temp_pe->next->port != 0)
998  temp_pe = temp_pe->next;
999  new_pe->next = temp_pe->next;
1000  temp_pe->next = new_pe;
1001 
1002  }
1003  }
1004 
1005  end:
1006  SCReturn;
1007 }
1008 
1009 static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
1011 {
1012  SCEnter();
1013 
1014  if (*head_pp == NULL) {
1015  *head_pp = new_pp;
1016  goto end;
1017  }
1018 
1019  AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
1020  while (temp_pp->next != NULL)
1021  temp_pp = temp_pp->next;
1022  temp_pp->next = new_pp;
1023 
1024  end:
1025  SCReturn;
1026 }
1027 
1028 static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
1030 {
1031  SCEnter();
1032 
1033  if (*head_port == NULL) {
1034  *head_port = new_port;
1035  goto end;
1036  }
1037 
1038  if ((*head_port)->port == 0) {
1039  new_port->next = *head_port;
1040  *head_port = new_port;
1041  } else {
1042  AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
1043  while (temp_port->next != NULL && temp_port->next->port != 0) {
1044  temp_port = temp_port->next;
1045  }
1046  new_port->next = temp_port->next;
1047  temp_port->next = new_port;
1048  }
1049 
1050  end:
1051  SCReturn;
1052 }
1053 
1054 static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
1055  uint8_t ipproto,
1056  uint16_t port,
1057  AppProto alproto,
1058  uint16_t min_depth, uint16_t max_depth,
1059  uint8_t direction,
1060  ProbingParserFPtr ProbingParser1,
1061  ProbingParserFPtr ProbingParser2)
1062 {
1063  SCEnter();
1064 
1065  /* get the top level ipproto pp */
1066  AppLayerProtoDetectProbingParser *curr_pp = *pp;
1067  while (curr_pp != NULL) {
1068  if (curr_pp->ipproto == ipproto)
1069  break;
1070  curr_pp = curr_pp->next;
1071  }
1072  if (curr_pp == NULL) {
1073  AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
1074  new_pp->ipproto = ipproto;
1075  AppLayerProtoDetectProbingParserAppend(pp, new_pp);
1076  curr_pp = new_pp;
1077  }
1078 
1079  /* get the top level port pp */
1080  AppLayerProtoDetectProbingParserPort *curr_port = curr_pp->port;
1081  while (curr_port != NULL) {
1082  if (curr_port->port == port)
1083  break;
1084  curr_port = curr_port->next;
1085  }
1086  if (curr_port == NULL) {
1087  AppLayerProtoDetectProbingParserPort *new_port = AppLayerProtoDetectProbingParserPortAlloc();
1088  new_port->port = port;
1089  AppLayerProtoDetectProbingParserPortAppend(&curr_pp->port, new_port);
1090  curr_port = new_port;
1091  if (direction & STREAM_TOSERVER) {
1092  curr_port->dp_max_depth = max_depth;
1093  } else {
1094  curr_port->sp_max_depth = max_depth;
1095  }
1096 
1098 
1099  zero_port = curr_pp->port;
1100  while (zero_port != NULL && zero_port->port != 0) {
1101  zero_port = zero_port->next;
1102  }
1103  if (zero_port != NULL) {
1105 
1106  zero_pe = zero_port->dp;
1107  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1108  if (curr_port->dp == NULL)
1109  curr_port->dp_max_depth = zero_pe->max_depth;
1110  if (zero_pe->max_depth == 0)
1111  curr_port->dp_max_depth = zero_pe->max_depth;
1112  if (curr_port->dp_max_depth != 0 &&
1113  curr_port->dp_max_depth < zero_pe->max_depth) {
1114  curr_port->dp_max_depth = zero_pe->max_depth;
1115  }
1116 
1118  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1119  AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
1120  curr_port->alproto_mask |= dup_pe->alproto_mask;
1121  }
1122 
1123  zero_pe = zero_port->sp;
1124  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1125  if (curr_port->sp == NULL)
1126  curr_port->sp_max_depth = zero_pe->max_depth;
1127  if (zero_pe->max_depth == 0)
1128  curr_port->sp_max_depth = zero_pe->max_depth;
1129  if (curr_port->sp_max_depth != 0 &&
1130  curr_port->sp_max_depth < zero_pe->max_depth) {
1131  curr_port->sp_max_depth = zero_pe->max_depth;
1132  }
1133 
1135  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1136  AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
1137  curr_port->alproto_mask |= dup_pe->alproto_mask;
1138  }
1139  } /* if (zero_port != NULL) */
1140  } /* if (curr_port == NULL) */
1141 
1142  /* insert the pe_pp */
1144  if (direction & STREAM_TOSERVER)
1145  curr_pe = curr_port->dp;
1146  else
1147  curr_pe = curr_port->sp;
1148  while (curr_pe != NULL) {
1149  if (curr_pe->alproto == alproto) {
1150  SCLogError(SC_ERR_ALPARSER, "Duplicate pp registered - "
1151  "ipproto - %"PRIu8" Port - %"PRIu16" "
1152  "App Protocol - NULL, App Protocol(ID) - "
1153  "%"PRIu16" min_depth - %"PRIu16" "
1154  "max_dept - %"PRIu16".",
1155  ipproto, port, alproto,
1156  min_depth, max_depth);
1157  goto error;
1158  }
1159  curr_pe = curr_pe->next;
1160  }
1161  /* Get a new parser element */
1163  AppLayerProtoDetectProbingParserElementCreate(alproto,
1164  curr_port->port,
1165  min_depth, max_depth);
1166  if (new_pe == NULL)
1167  goto error;
1168  curr_pe = new_pe;
1170  if (direction & STREAM_TOSERVER) {
1171  curr_pe->ProbingParserTs = ProbingParser1;
1172  curr_pe->ProbingParserTc = ProbingParser2;
1173  if (curr_port->dp == NULL)
1174  curr_port->dp_max_depth = new_pe->max_depth;
1175  if (new_pe->max_depth == 0)
1176  curr_port->dp_max_depth = new_pe->max_depth;
1177  if (curr_port->dp_max_depth != 0 &&
1178  curr_port->dp_max_depth < new_pe->max_depth) {
1179  curr_port->dp_max_depth = new_pe->max_depth;
1180  }
1181  curr_port->alproto_mask |= new_pe->alproto_mask;
1182  head_pe = &curr_port->dp;
1183  } else {
1184  curr_pe->ProbingParserTs = ProbingParser2;
1185  curr_pe->ProbingParserTc = ProbingParser1;
1186  if (curr_port->sp == NULL)
1187  curr_port->sp_max_depth = new_pe->max_depth;
1188  if (new_pe->max_depth == 0)
1189  curr_port->sp_max_depth = new_pe->max_depth;
1190  if (curr_port->sp_max_depth != 0 &&
1191  curr_port->sp_max_depth < new_pe->max_depth) {
1192  curr_port->sp_max_depth = new_pe->max_depth;
1193  }
1194  curr_port->alproto_mask |= new_pe->alproto_mask;
1195  head_pe = &curr_port->sp;
1196  }
1197  AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);
1198 
1199  if (curr_port->port == 0) {
1200  AppLayerProtoDetectProbingParserPort *temp_port = curr_pp->port;
1201  while (temp_port != NULL && temp_port->port != 0) {
1202  if (direction & STREAM_TOSERVER) {
1203  if (temp_port->dp == NULL)
1204  temp_port->dp_max_depth = curr_pe->max_depth;
1205  if (curr_pe->max_depth == 0)
1206  temp_port->dp_max_depth = curr_pe->max_depth;
1207  if (temp_port->dp_max_depth != 0 &&
1208  temp_port->dp_max_depth < curr_pe->max_depth) {
1209  temp_port->dp_max_depth = curr_pe->max_depth;
1210  }
1211  AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
1212  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1213  temp_port->alproto_mask |= curr_pe->alproto_mask;
1214  } else {
1215  if (temp_port->sp == NULL)
1216  temp_port->sp_max_depth = curr_pe->max_depth;
1217  if (curr_pe->max_depth == 0)
1218  temp_port->sp_max_depth = curr_pe->max_depth;
1219  if (temp_port->sp_max_depth != 0 &&
1220  temp_port->sp_max_depth < curr_pe->max_depth) {
1221  temp_port->sp_max_depth = curr_pe->max_depth;
1222  }
1223  AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
1224  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1225  temp_port->alproto_mask |= curr_pe->alproto_mask;
1226  }
1227  temp_port = temp_port->next;
1228  } /* while */
1229  } /* if */
1230 
1231  error:
1232  SCReturn;
1233 }
1234 
1235 /***** Static Internal Calls: PM registration *****/
1236 
1237 static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto,
1238  uint8_t *ipprotos)
1239 {
1240  SCEnter();
1241 
1242  for (int i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1243  uint8_t ipproto = FlowGetReverseProtoMapping(i);
1244  for (int j = 0; j < 2; j++) {
1245  AppLayerProtoDetectPMCtx *pm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1246 
1247  for (SigIntId x = 0; x < pm_ctx->max_sig_id; x++) {
1248  const AppLayerProtoDetectPMSignature *s = pm_ctx->map[x];
1249  if (s->alproto == alproto)
1250  ipprotos[ipproto / 8] |= 1 << (ipproto % 8);
1251  }
1252  }
1253  }
1254 
1255  SCReturn;
1256 }
1257 
1258 static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
1259 {
1260  SCEnter();
1261 
1262  typedef struct TempContainer_ {
1263  PatIntId id;
1264  uint16_t content_len;
1265  uint8_t *content;
1266  } TempContainer;
1267 
1269  uint32_t struct_total_size = 0;
1270  uint32_t content_total_size = 0;
1271  /* array hash buffer */
1272  uint8_t *ahb = NULL;
1273  uint8_t *content = NULL;
1274  uint8_t content_len = 0;
1275  PatIntId max_id = 0;
1276  TempContainer *struct_offset = NULL;
1277  uint8_t *content_offset = NULL;
1278  int ret = 0;
1279 
1280  if (ctx->head == NULL)
1281  goto end;
1282 
1283  for (s = ctx->head; s != NULL; s = s->next) {
1284  struct_total_size += sizeof(TempContainer);
1285  content_total_size += s->cd->content_len;
1286  ctx->max_sig_id++;
1287  }
1288 
1289  ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1290  if (unlikely(ahb == NULL))
1291  goto error;
1292 
1293  struct_offset = (TempContainer *)ahb;
1294  content_offset = ahb + struct_total_size;
1295  for (s = ctx->head; s != NULL; s = s->next) {
1296  TempContainer *tcdup = (TempContainer *)ahb;
1297  content = s->cd->content;
1298  content_len = s->cd->content_len;
1299 
1300  for (; tcdup != struct_offset; tcdup++) {
1301  if (tcdup->content_len != content_len ||
1302  SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
1303  {
1304  continue;
1305  }
1306  break;
1307  }
1308 
1309  if (tcdup != struct_offset) {
1310  s->cd->id = tcdup->id;
1311  continue;
1312  }
1313 
1314  struct_offset->content_len = content_len;
1315  struct_offset->content = content_offset;
1316  content_offset += content_len;
1317  memcpy(struct_offset->content, content, content_len);
1318  struct_offset->id = max_id++;
1319  s->cd->id = struct_offset->id;
1320 
1321  struct_offset++;
1322  }
1323 
1324  ctx->max_pat_id = max_id;
1325 
1326  goto end;
1327  error:
1328  ret = -1;
1329  end:
1330  if (ahb != NULL)
1331  SCFree(ahb);
1332  SCReturnInt(ret);
1333 }
1334 
1335 static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
1336 {
1337  SCEnter();
1338 
1339  int ret = 0;
1340  AppLayerProtoDetectPMSignature *s, *next_s;
1341  int mpm_ret;
1342  SigIntId id = 0;
1343 
1344  ctx->map = SCMalloc(ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1345  if (ctx->map == NULL)
1346  goto error;
1347  memset(ctx->map, 0, ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1348 
1349  /* add an array indexed by rule id to look up the sig */
1350  for (s = ctx->head; s != NULL; ) {
1351  next_s = s->next;
1352  s->id = id++;
1353  SCLogDebug("s->id %u offset %u depth %u",
1354  s->id, s->cd->offset, s->cd->depth);
1355 
1356  if (s->cd->flags & DETECT_CONTENT_NOCASE) {
1357  mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
1358  s->cd->content, s->cd->content_len,
1359  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1360  if (mpm_ret < 0)
1361  goto error;
1362  } else {
1363  mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
1364  s->cd->content, s->cd->content_len,
1365  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1366  if (mpm_ret < 0)
1367  goto error;
1368  }
1369 
1370  ctx->map[s->id] = s;
1371  s->next = NULL;
1372  s = next_s;
1373  }
1374  ctx->head = NULL;
1375 
1376  goto end;
1377  error:
1378  ret = -1;
1379  end:
1380  SCReturnInt(ret);
1381 }
1382 
1383 static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
1384 {
1385  SCEnter();
1386 
1387  int ret = 0;
1388  MpmCtx *mpm_ctx = &ctx->mpm_ctx;
1389 
1390  if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
1391  goto error;
1392 
1393  goto end;
1394  error:
1395  ret = -1;
1396  end:
1397  SCReturnInt(ret);
1398 }
1399 
1400 static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
1401 {
1402  SCEnter();
1403  if (sig == NULL)
1404  SCReturn;
1405  if (sig->cd)
1406  DetectContentFree(sig->cd);
1407  SCFree(sig);
1408  SCReturn;
1409 }
1410 
1411 static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx *ctx, DetectContentData *cd,
1412  AppProto alproto, uint8_t direction,
1413  ProbingParserFPtr PPFunc,
1414  uint16_t pp_min_depth, uint16_t pp_max_depth)
1415 {
1416  SCEnter();
1417 
1418  AppLayerProtoDetectPMSignature *s = SCCalloc(1, sizeof(*s));
1419  if (unlikely(s == NULL))
1420  SCReturnInt(-1);
1421 
1422  s->alproto = alproto;
1423  s->direction = direction;
1424  s->cd = cd;
1425  s->PPFunc = PPFunc;
1426  s->pp_min_depth = pp_min_depth;
1427  s->pp_max_depth = pp_max_depth;
1428 
1429  /* prepend to the list */
1430  s->next = ctx->head;
1431  ctx->head = s;
1432 
1433  SCReturnInt(0);
1434 }
1435 
1436 static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
1437  const char *pattern,
1438  uint16_t depth, uint16_t offset,
1439  uint8_t direction,
1440  uint8_t is_cs,
1441  ProbingParserFPtr PPFunc,
1442  uint16_t pp_min_depth, uint16_t pp_max_depth)
1443 {
1444  SCEnter();
1445 
1446  AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
1447  AppLayerProtoDetectPMCtx *ctx_pm = NULL;
1448  int ret = 0;
1449 
1451  alpd_ctx.spm_global_thread_ctx, pattern);
1452  if (cd == NULL)
1453  goto error;
1454  cd->depth = depth;
1455  cd->offset = offset;
1456  if (!is_cs) {
1457  /* Rebuild as nocase */
1458  SpmDestroyCtx(cd->spm_ctx);
1459  cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1,
1460  alpd_ctx.spm_global_thread_ctx);
1461  if (cd->spm_ctx == NULL) {
1462  goto error;
1463  }
1465  }
1466  if (depth < cd->content_len)
1467  goto error;
1468 
1469  if (direction & STREAM_TOSERVER)
1470  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
1471  else
1472  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
1473 
1474  if (pp_max_depth > ctx_pm->pp_max_len)
1475  ctx_pm->pp_max_len = pp_max_depth;
1476  if (depth < ctx_pm->min_len)
1477  ctx_pm->min_len = depth;
1478 
1479  /* Finally turn it into a signature and add to the ctx. */
1480  AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto, direction,
1481  PPFunc, pp_min_depth, pp_max_depth);
1482 
1483  goto end;
1484  error:
1485  DetectContentFree(cd);
1486  ret = -1;
1487  end:
1488  SCReturnInt(ret);
1489 }
1490 
1491 /***** Protocol Retrieval *****/
1492 
1494  Flow *f,
1495  const uint8_t *buf, uint32_t buflen,
1496  uint8_t ipproto, uint8_t direction,
1497  bool *reverse_flow)
1498 {
1499  SCEnter();
1500  SCLogDebug("buflen %u for %s direction", buflen,
1501  (direction & STREAM_TOSERVER) ? "toserver" : "toclient");
1502 
1503  AppProto alproto = ALPROTO_UNKNOWN;
1504  AppProto pm_alproto = ALPROTO_UNKNOWN;
1505 
1506  if (!FLOW_IS_PM_DONE(f, direction)) {
1507  AppProto pm_results[ALPROTO_MAX];
1508  uint16_t pm_matches = AppLayerProtoDetectPMGetProto(tctx, f,
1509  buf, buflen, direction, pm_results, reverse_flow);
1510  if (pm_matches > 0) {
1511  alproto = pm_results[0];
1512 
1513  /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1514  * to avoid misdetecting DNS as DCERPC. */
1515  if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1516  goto end;
1517 
1518  pm_alproto = alproto;
1519 
1520  /* fall through */
1521  }
1522  }
1523 
1524  if (!FLOW_IS_PP_DONE(f, direction)) {
1525  bool rflow = false;
1526  alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto,
1527  direction & (STREAM_TOSERVER|STREAM_TOCLIENT), &rflow);
1528  if (AppProtoIsValid(alproto)) {
1529  if (rflow) {
1530  *reverse_flow = true;
1531  }
1532  goto end;
1533  }
1534  }
1535 
1536  /* Look if flow can be found in expectation list */
1537  if (!FLOW_IS_PE_DONE(f, direction)) {
1538  alproto = AppLayerProtoDetectPEGetProto(f, ipproto, direction);
1539  }
1540 
1541  end:
1542  if (!AppProtoIsValid(alproto))
1543  alproto = pm_alproto;
1544 
1545  SCReturnUInt(alproto);
1546 }
1547 
1548 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1549 {
1550  SCEnter();
1551 
1552  AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1553 
1554  if (pp == NULL)
1555  goto end;
1556 
1557  while (pp != NULL) {
1558  tmp_pp = pp->next;
1559  AppLayerProtoDetectProbingParserFree(pp);
1560  pp = tmp_pp;
1561  }
1562 
1563  end:
1564  SCReturn;
1565 }
1566 
1567 /***** State Preparation *****/
1568 
1570 {
1571  SCEnter();
1572 
1573  AppLayerProtoDetectPMCtx *ctx_pm;
1574  int i, j;
1575  int ret = 0;
1576 
1577  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1578  for (j = 0; j < 2; j++) {
1579  ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1580 
1581  if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1582  goto error;
1583 
1584  if (ctx_pm->max_sig_id == 0)
1585  continue;
1586 
1587  if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1588  goto error;
1589  if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1590  goto error;
1591  }
1592  }
1593 
1594 #ifdef DEBUG
1595  if (SCLogDebugEnabled()) {
1596  AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1597  }
1598 #endif
1599 
1600  goto end;
1601  error:
1602  ret = -1;
1603  end:
1604  SCReturnInt(ret);
1605 }
1606 
1607 /***** PP registration *****/
1608 
1609 /** \brief register parser at a port
1610  *
1611  * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1612  */
1613 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1614  const char *portstr,
1615  AppProto alproto,
1616  uint16_t min_depth, uint16_t max_depth,
1617  uint8_t direction,
1618  ProbingParserFPtr ProbingParser1,
1619  ProbingParserFPtr ProbingParser2)
1620 {
1621  SCEnter();
1622 
1623  DetectPort *head = NULL;
1624  DetectPortParse(NULL,&head, portstr);
1625  DetectPort *temp_dp = head;
1626  while (temp_dp != NULL) {
1627  uint32_t port = temp_dp->port;
1628  if (port == 0 && temp_dp->port2 != 0)
1629  port++;
1630  for ( ; port <= temp_dp->port2; port++) {
1631  AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
1632  ipproto,
1633  port,
1634  alproto,
1635  min_depth, max_depth,
1636  direction,
1637  ProbingParser1,
1638  ProbingParser2);
1639  }
1640  temp_dp = temp_dp->next;
1641  }
1643 
1644  SCReturn;
1645 }
1646 
1647 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1648  uint8_t ipproto,
1649  const char *alproto_name,
1650  AppProto alproto,
1651  uint16_t min_depth, uint16_t max_depth,
1652  ProbingParserFPtr ProbingParserTs,
1653  ProbingParserFPtr ProbingParserTc)
1654 {
1655  SCEnter();
1656 
1657  char param[100];
1658  int r;
1659  ConfNode *node;
1660  ConfNode *port_node = NULL;
1661  int config = 0;
1662 
1663  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1664  alproto_name, ".detection-ports");
1665  if (r < 0) {
1666  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1667  exit(EXIT_FAILURE);
1668  } else if (r > (int)sizeof(param)) {
1669  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1670  exit(EXIT_FAILURE);
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  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1679  exit(EXIT_FAILURE);
1680  } else if (r > (int)sizeof(param)) {
1681  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1682  exit(EXIT_FAILURE);
1683  }
1684  node = ConfGetNode(param);
1685  if (node == NULL)
1686  goto end;
1687  }
1688 
1689  /* detect by destination port of the flow (e.g. port 53 for DNS) */
1690  port_node = ConfNodeLookupChild(node, "dp");
1691  if (port_node == NULL)
1692  port_node = ConfNodeLookupChild(node, "toserver");
1693 
1694  if (port_node != NULL && port_node->val != NULL) {
1696  port_node->val,
1697  alproto,
1698  min_depth, max_depth,
1699  STREAM_TOSERVER, /* to indicate dp */
1700  ProbingParserTs, ProbingParserTc);
1701  }
1702 
1703  /* detect by source port of flow */
1704  port_node = ConfNodeLookupChild(node, "sp");
1705  if (port_node == NULL)
1706  port_node = ConfNodeLookupChild(node, "toclient");
1707 
1708  if (port_node != NULL && port_node->val != NULL) {
1710  port_node->val,
1711  alproto,
1712  min_depth, max_depth,
1713  STREAM_TOCLIENT, /* to indicate sp */
1714  ProbingParserTc, ProbingParserTs);
1715 
1716  }
1717 
1718  config = 1;
1719  end:
1720  SCReturnInt(config);
1721 }
1722 
1723 /***** PM registration *****/
1724 
1726  const char *pattern,
1727  uint16_t depth, uint16_t offset,
1728  uint8_t direction)
1729 {
1730  SCEnter();
1731  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1732  pattern, depth, offset,
1733  direction, 1 /* case-sensitive */,
1734  NULL, 0, 0);
1735  SCReturnInt(r);
1736 }
1737 
1739  const char *pattern, uint16_t depth, uint16_t offset,
1740  uint8_t direction,
1741  ProbingParserFPtr PPFunc,
1742  uint16_t pp_min_depth, uint16_t pp_max_depth)
1743 {
1744  SCEnter();
1745  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1746  pattern, depth, offset,
1747  direction, 1 /* case-sensitive */,
1748  PPFunc, pp_min_depth, pp_max_depth);
1749  SCReturnInt(r);
1750 }
1751 
1753  const char *pattern,
1754  uint16_t depth, uint16_t offset,
1755  uint8_t direction)
1756 {
1757  SCEnter();
1758  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1759  pattern, depth, offset,
1760  direction, 0 /* !case-sensitive */,
1761  NULL, 0, 0);
1762  SCReturnInt(r);
1763 }
1764 
1765 /***** Setup/General Registration *****/
1766 
1768 {
1769  SCEnter();
1770 
1771  int i, j;
1772 
1773  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1774 
1775  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1776  uint16_t mpm_matcher = PatternMatchDefaultMatcher();
1777 
1778  alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1779  if (alpd_ctx.spm_global_thread_ctx == NULL) {
1780  SCLogError(SC_ERR_FATAL, "Unable to alloc SpmGlobalThreadCtx.");
1781  exit(EXIT_FAILURE);
1782  }
1783 
1784  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1785  for (j = 0; j < 2; j++) {
1786  MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, mpm_matcher);
1787  }
1788  }
1789 
1791 
1792  SCReturnInt(0);
1793 }
1794 
1795 /**
1796  * \todo incomplete. Need more work.
1797  */
1799 {
1800  SCEnter();
1801 
1802  int ipproto_map = 0;
1803  int dir = 0;
1804  PatIntId id = 0;
1805  AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1806  AppLayerProtoDetectPMSignature *sig = NULL;
1807 
1808  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1809  for (dir = 0; dir < 2; dir++) {
1810  pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1811  mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1812  for (id = 0; id < pm_ctx->max_sig_id; id++) {
1813  sig = pm_ctx->map[id];
1814  AppLayerProtoDetectPMFreeSignature(sig);
1815  }
1816  SCFree(pm_ctx->map);
1817  pm_ctx->map = NULL;
1818  }
1819  }
1820 
1822 
1823  AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1824 
1825  SCReturnInt(0);
1826 }
1827 
1828 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1829 {
1830  SCEnter();
1831 
1832  if (alpd_ctx.alproto_names[alproto] == NULL)
1833  alpd_ctx.alproto_names[alproto] = alproto_name;
1834 
1835  SCReturn;
1836 }
1837 
1838 /** \brief request applayer to wrap up this protocol and rerun protocol
1839  * detection.
1840  *
1841  * When this is called, the old session is reset unconditionally. A
1842  * 'detect/log' flush packet is generated for both direction before
1843  * the reset, so allow for final detection and logging.
1844  *
1845  * \param f flow to act on
1846  * \param dp destination port to use in protocol detection. Set to 443
1847  * for start tls, set to the HTTP uri port for CONNECT and
1848  * set to 0 to not use it.
1849  * \param expect_proto expected protocol. AppLayer event will be set if
1850  * detected protocol differs from this.
1851  */
1852 void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1853 {
1855  f->protodetect_dp = dp;
1856  f->alproto_expect = expect_proto;
1857 }
1858 
1859 /** \brief request applayer to wrap up this protocol and rerun protocol
1860  * detection with expectation of TLS. Used by STARTTLS.
1861  *
1862  * Sets detection port to 443 to make port based TLS detection work for
1863  * SMTP, FTP etc as well.
1864  *
1865  * \param f flow to act on
1866  */
1868 {
1870 }
1871 
1873 {
1883 
1885  f->alstate = NULL;
1886  f->alparser = NULL;
1887  f->alproto = ALPROTO_UNKNOWN;
1890 }
1891 
1893  const char *alproto)
1894 {
1895  SCEnter();
1896 
1897  BUG_ON(ipproto == NULL || alproto == NULL);
1898 
1899  int enabled = 1;
1900  char param[100];
1901  ConfNode *node;
1902  int r;
1903 
1904  if (RunmodeIsUnittests())
1905  goto enabled;
1906 
1907  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1908  alproto, ".enabled");
1909  if (r < 0) {
1910  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1911  exit(EXIT_FAILURE);
1912  } else if (r > (int)sizeof(param)) {
1913  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1914  exit(EXIT_FAILURE);
1915  }
1916 
1917  node = ConfGetNode(param);
1918  if (node == NULL) {
1919  SCLogDebug("Entry for %s not found.", param);
1920  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1921  alproto, ".", ipproto, ".enabled");
1922  if (r < 0) {
1923  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1924  exit(EXIT_FAILURE);
1925  } else if (r > (int)sizeof(param)) {
1926  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1927  exit(EXIT_FAILURE);
1928  }
1929 
1930  node = ConfGetNode(param);
1931  if (node == NULL) {
1932  SCLogDebug("Entry for %s not found.", param);
1933  goto enabled;
1934  }
1935  }
1936 
1937  if (node->val) {
1938  if (ConfValIsTrue(node->val)) {
1939  goto enabled;
1940  } else if (ConfValIsFalse(node->val)) {
1941  goto disabled;
1942  } else if (strcasecmp(node->val, "detection-only") == 0) {
1943  goto enabled;
1944  }
1945  }
1946 
1947  /* Invalid or null value. */
1948  SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
1949  exit(EXIT_FAILURE);
1950 
1951  disabled:
1952  enabled = 0;
1953  enabled:
1954  SCReturnInt(enabled);
1955 }
1956 
1958 {
1959  SCEnter();
1960 
1962  MpmCtx *mpm_ctx;
1963  MpmThreadCtx *mpm_tctx;
1964  int i, j;
1965  PatIntId max_pat_id = 0;
1966 
1967  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1968  for (j = 0; j < 2; j++) {
1969  if (max_pat_id == 0) {
1970  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1971 
1972  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
1973  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
1974  {
1975  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1976  }
1977  }
1978  }
1979 
1980  alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
1981  if (alpd_tctx == NULL)
1982  goto error;
1983  memset(alpd_tctx, 0, sizeof(*alpd_tctx));
1984 
1985  /* Get the max pat id for all the mpm ctxs. */
1986  if (PmqSetup(&alpd_tctx->pmq) < 0)
1987  goto error;
1988 
1989  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1990  for (j = 0; j < 2; j++) {
1991  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
1992  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
1993  mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx);
1994  }
1995  }
1996 
1998  if (alpd_tctx->spm_thread_ctx == NULL) {
1999  goto error;
2000  }
2001 
2002  goto end;
2003  error:
2004  if (alpd_tctx != NULL)
2006  alpd_tctx = NULL;
2007  end:
2008  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2009 }
2010 
2012 {
2013  SCEnter();
2014 
2015  MpmCtx *mpm_ctx;
2016  MpmThreadCtx *mpm_tctx;
2017  int ipproto_map, dir;
2018 
2019  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2020  for (dir = 0; dir < 2; dir++) {
2021  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2022  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2023  mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
2024  }
2025  }
2026  PmqFree(&alpd_tctx->pmq);
2027  if (alpd_tctx->spm_thread_ctx != NULL) {
2029  }
2030  SCFree(alpd_tctx);
2031 
2032  SCReturn;
2033 }
2034 
2035 /***** Utility *****/
2036 
2037 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2038 {
2039  SCEnter();
2040 
2041  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2042  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2043  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2044 
2045  SCReturn;
2046 }
2047 
2049 {
2050  SCEnter();
2051 
2052  AppProto a;
2053  for (a = 0; a < ALPROTO_MAX; a++) {
2054  if (alpd_ctx.alproto_names[a] != NULL &&
2055  strlen(alpd_ctx.alproto_names[a]) == strlen(alproto_name) &&
2056  (SCMemcmp(alpd_ctx.alproto_names[a], alproto_name, strlen(alproto_name)) == 0))
2057  {
2058  SCReturnCT(a, "AppProto");
2059  }
2060  }
2061 
2062  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2063 }
2064 
2066 {
2067  return alpd_ctx.alproto_names[alproto];
2068 }
2069 
2071 {
2072  SCEnter();
2073 
2074  memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2075 
2076  int alproto;
2077 
2078  for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2079  if (alpd_ctx.alproto_names[alproto] != NULL)
2080  alprotos[alproto] = 1;
2081  }
2082 
2083  SCReturn;
2084 }
2085 
2087 
2088 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2089  uint8_t *ipprotos)
2090 {
2091  if (expectation_proto[alproto] == IPPROTO_TCP) {
2092  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2093  }
2094  if (expectation_proto[alproto] == IPPROTO_UDP) {
2095  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2096  }
2097 }
2098 
2100 {
2101  if (expectation_proto[alproto]) {
2102  if (proto != expectation_proto[alproto]) {
2104  "Expectation on 2 IP protocols are not supported");
2105  }
2106  }
2107  expectation_proto[alproto] = proto;
2108 }
2109 
2110 /***** Unittests *****/
2111 
2112 #ifdef UNITTESTS
2113 
2114 #include "app-layer-htp.h"
2115 
2116 static AppLayerProtoDetectCtx alpd_ctx_ut;
2117 
2119 {
2120  SCEnter();
2121  alpd_ctx_ut = alpd_ctx;
2122  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2123  SCReturn;
2124 }
2125 
2127 {
2128  SCEnter();
2129  alpd_ctx = alpd_ctx_ut;
2130  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2131  SCReturn;
2132 }
2133 
2134 static int AppLayerProtoDetectTest01(void)
2135 {
2138 
2139  const char *buf = "HTTP";
2141  buf = "GET";
2143 
2145  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2146  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2147 
2150  PASS;
2151 }
2152 
2153 static int AppLayerProtoDetectTest02(void)
2154 {
2157 
2158  const char *buf = "HTTP";
2160  buf = "ftp";
2162 
2164  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2165  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2166 
2167  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2168  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2169 
2172 
2175  PASS;
2176 }
2177 
2178 static int AppLayerProtoDetectTest03(void)
2179 {
2182 
2183  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2184  AppProto pm_results[ALPROTO_MAX];
2185  memset(pm_results, 0, sizeof(pm_results));
2186  Flow f;
2187  memset(&f, 0x00, sizeof(f));
2188  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2189 
2190 
2191  const char *buf = "HTTP";
2193  buf = "220 ";
2195 
2197  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2198  * it sets internal structures which depends on the above function. */
2201 
2202  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2203  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2204  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2205  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2208 
2209  bool rflow = false;
2210  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2211  &f, l7data, sizeof(l7data),
2213  pm_results, &rflow);
2214  FAIL_IF(cnt != 1);
2215  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2216 
2220  PASS;
2221 }
2222 
2223 static int AppLayerProtoDetectTest04(void)
2224 {
2227 
2228  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2229  Flow f;
2230  memset(&f, 0x00, sizeof(f));
2231  AppProto pm_results[ALPROTO_MAX];
2232  memset(pm_results, 0, sizeof(pm_results));
2233  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2234 
2235  const char *buf = "200 ";
2237 
2239  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2240  * it sets internal structures which depends on the above function. */
2243 
2244  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2245  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2246  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2247  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2249 
2250  bool rdir = false;
2251  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2252  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2253  pm_results, &rdir);
2254  FAIL_IF(cnt != 1);
2255  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2256 
2260  PASS;
2261 }
2262 
2263 static int AppLayerProtoDetectTest05(void)
2264 {
2267 
2268  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2269  AppProto pm_results[ALPROTO_MAX];
2270  memset(pm_results, 0, sizeof(pm_results));
2271  Flow f;
2272  memset(&f, 0x00, sizeof(f));
2273  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2274 
2275  const char *buf = "HTTP";
2277  buf = "220 ";
2279 
2281  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2282  * it sets internal structures which depends on the above function. */
2285 
2286  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2287  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2288  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2289  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2292 
2293  bool rdir = false;
2294  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2295  &f, l7data, sizeof(l7data),
2297  pm_results, &rdir);
2298  FAIL_IF(cnt != 1);
2299  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2300 
2304  PASS;
2305 }
2306 
2307 static int AppLayerProtoDetectTest06(void)
2308 {
2311 
2312  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2313  AppProto pm_results[ALPROTO_MAX];
2314  memset(pm_results, 0, sizeof(pm_results));
2315  Flow f;
2316  memset(&f, 0x00, sizeof(f));
2317  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2318 
2319  const char *buf = "HTTP";
2321  buf = "220 ";
2323 
2325  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2326  * it sets internal structures which depends on the above function. */
2329 
2330  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2331  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2332  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2333  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2336 
2337  bool rdir = false;
2338  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2339  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2340  pm_results, &rdir);
2341  FAIL_IF(cnt != 1);
2342  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2343 
2347  PASS;
2348 }
2349 
2350 static int AppLayerProtoDetectTest07(void)
2351 {
2354 
2355  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2356  Flow f;
2357  memset(&f, 0x00, sizeof(f));
2358  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2359  AppProto pm_results[ALPROTO_MAX];
2360  memset(pm_results, 0, sizeof(pm_results));
2361 
2362  const char *buf = "HTTP";
2364 
2366  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2367  * it sets internal structures which depends on the above function. */
2369 
2370  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2371  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2372  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2373  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2375 
2376  bool rdir = false;
2377  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2378  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2379  pm_results, &rdir);
2380  FAIL_IF(cnt != 0);
2381 
2385  PASS;
2386 }
2387 
2388 static int AppLayerProtoDetectTest08(void)
2389 {
2392 
2393  uint8_t l7data[] = {
2394  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2395  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2396  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2397  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2398  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2399  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2400  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2401  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2402  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2403  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2404  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2405  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2406  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2407  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2408  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2409  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2410  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2411  0x00
2412  };
2413  AppProto pm_results[ALPROTO_MAX];
2414  memset(pm_results, 0, sizeof(pm_results));
2415  Flow f;
2416  memset(&f, 0x00, sizeof(f));
2417  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2418 
2419  const char *buf = "|ff|SMB";
2421 
2423  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2424  * it sets internal structures which depends on the above function. */
2427 
2428  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2429  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2430  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2431  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2433 
2434  bool rdir = false;
2435  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2436  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2437  pm_results, &rdir);
2438  FAIL_IF(cnt != 1);
2439  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2440 
2444  PASS;
2445 }
2446 
2447 static int AppLayerProtoDetectTest09(void)
2448 {
2451 
2452  uint8_t l7data[] = {
2453  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2454  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2455  0x00, 0x00, 0x3f, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2459  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2460  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2461  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2462  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2463  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2464  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2465  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2466  0x00, 0x02, 0x02
2467  };
2468  AppProto pm_results[ALPROTO_MAX];
2469  memset(pm_results, 0, sizeof(pm_results));
2470  Flow f;
2471  memset(&f, 0x00, sizeof(f));
2472  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2473 
2474  const char *buf = "|fe|SMB";
2476 
2478  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2479  * it sets internal structures which depends on the above function. */
2482 
2483  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2484  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2485  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2486  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2488 
2489  bool rdir = false;
2490  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2491  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2492  pm_results, &rdir);
2493  FAIL_IF(cnt != 1);
2494  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2495 
2499  PASS;
2500 }
2501 
2502 static int AppLayerProtoDetectTest10(void)
2503 {
2506 
2507  uint8_t l7data[] = {
2508  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2509  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2510  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2511  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2512  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2513  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2514  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2515  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2516  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2517  };
2518  AppProto pm_results[ALPROTO_MAX];
2519  memset(pm_results, 0, sizeof(pm_results));
2520  Flow f;
2521  memset(&f, 0x00, sizeof(f));
2522  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2523 
2524  const char *buf = "|05 00|";
2526 
2528  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2529  * it sets internal structures which depends on the above function. */
2532 
2533  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2534  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2535  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2536  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2538 
2539  bool rdir = false;
2540  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2541  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2542  pm_results, &rdir);
2543  FAIL_IF(cnt != 1);
2544  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2545 
2549  PASS;
2550 }
2551 
2552 /**
2553  * \test Why we still get http for connect... obviously because
2554  * we also match on the reply, duh
2555  */
2556 static int AppLayerProtoDetectTest11(void)
2557 {
2560 
2561  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2562  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2563  AppProto pm_results[ALPROTO_MAX];
2564  memset(pm_results, 0, sizeof(pm_results));
2565  Flow f;
2566  memset(&f, 0x00, sizeof(f));
2567  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2568 
2577 
2579  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2580  * it sets internal structures which depends on the above function. */
2583 
2584  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2585  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2586  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2587  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2588 
2597 
2598  bool rdir = false;
2599  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2600  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2601  pm_results, &rdir);
2602  FAIL_IF(cnt != 1);
2603  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2604 
2605  memset(pm_results, 0, sizeof(pm_results));
2606  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2607  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2608  pm_results, &rdir);
2609  FAIL_IF(cnt != 1);
2610  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2611 
2615  PASS;
2616 }
2617 
2618 /**
2619  * \test AlpProtoSignature test
2620  */
2621 static int AppLayerProtoDetectTest12(void)
2622 {
2625 
2626  int r = 0;
2627 
2629  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2630  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2631  {
2632  printf("failure 1\n");
2633  goto end;
2634  }
2635 
2637  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2638  printf("failure 2\n");
2639  goto end;
2640  }
2641  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2642  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2643  {
2644  printf("failure 3\n");
2645  goto end;
2646  }
2647  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP) {
2648  printf("failure 4\n");
2649  goto end;
2650  }
2651  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2652  printf("failure 5\n");
2653  goto end;
2654  }
2655  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2656  printf("failure 6\n");
2657  goto end;
2658  }
2659 
2660  r = 1;
2661 
2662  end:
2665  return r;
2666 }
2667 
2668 /**
2669  * \test What about if we add some sigs only for udp but call for tcp?
2670  * It should not detect any proto
2671  */
2672 static int AppLayerProtoDetectTest13(void)
2673 {
2676 
2677  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2678  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2679  AppProto pm_results[ALPROTO_MAX];
2680 
2681  Flow f;
2682  memset(&f, 0x00, sizeof(f));
2683  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2684 
2693 
2695  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2696  * it sets internal structures which depends on the above function. */
2698 
2699  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2700  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2701 
2710 
2711  memset(pm_results, 0, sizeof(pm_results));
2712  bool rdir = false;
2713  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2714  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2715  pm_results, &rdir);
2716  FAIL_IF(cnt != 0);
2717 
2718  memset(pm_results, 0, sizeof(pm_results));
2719  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2720  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2721  pm_results, &rdir);
2722  FAIL_IF(cnt != 0);
2723 
2727  PASS;
2728 }
2729 
2730 /**
2731  * \test What about if we add some sigs only for udp calling it for UDP?
2732  * It should detect ALPROTO_HTTP (over udp). This is just a check
2733  * to ensure that TCP/UDP differences work correctly.
2734  */
2735 static int AppLayerProtoDetectTest14(void)
2736 {
2739 
2740  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2741  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2742  AppProto pm_results[ALPROTO_MAX];
2743  uint32_t cnt;
2744  Flow f;
2745  memset(&f, 0x00, sizeof(f));
2746  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2747 
2756 
2758  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2759  * it sets internal structures which depends on the above function. */
2762 
2763  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2764  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2765 
2774 
2775  memset(pm_results, 0, sizeof(pm_results));
2776  bool rdir = false;
2777  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2778  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2779  pm_results, &rdir);
2780  FAIL_IF(cnt != 1);
2781  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2782 
2783  memset(pm_results, 0, sizeof(pm_results));
2784  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2785  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2786  pm_results, &rdir);
2787  FAIL_IF(cnt != 1);
2788  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2789 
2793  PASS;
2794 }
2795 
2797  const char *alproto_name;
2799  uint16_t port;
2800  uint32_t alproto_mask;
2801  uint32_t min_depth;
2802  uint32_t max_depth;
2804 
2806  uint16_t port;
2807  uint32_t alproto_mask;
2808  uint16_t dp_max_depth;
2809  uint16_t sp_max_depth;
2810 
2816 
2817 
2819  uint8_t ipproto;
2820 
2824 
2825 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2827  int no_of_ip_proto)
2828 {
2829  int result = 0;
2830  int i = -1, j = -1 , k = -1;
2831 #ifdef DEBUG
2832  int dir = 0;
2833 #endif
2834  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2835  if (pp->ipproto != ip_proto[i].ipproto)
2836  goto end;
2837 
2839  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2840  if (pp_port->port != ip_proto[i].port[k].port)
2841  goto end;
2842  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2843  goto end;
2844  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2845  goto end;
2846  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2847  goto end;
2848  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2849  goto end;
2850 
2851  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2852 #ifdef DEBUG
2853  dir = 0;
2854 #endif
2855  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2856  j++, pp_element = pp_element->next) {
2857 
2858  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2859  goto end;
2860  }
2861  if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
2862  goto end;
2863  }
2864  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
2865  goto end;
2866  }
2867  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2868  goto end;
2869  }
2870  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2871  goto end;
2872  }
2873  } /* for */
2874  if (pp_element != NULL)
2875  goto end;
2876 
2877  pp_element = pp_port->sp;
2878 #ifdef DEBUG
2879  dir = 1;
2880 #endif
2881  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2882  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2883  goto end;
2884  }
2885  if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
2886  goto end;
2887  }
2888  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
2889  goto end;
2890  }
2891  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2892  goto end;
2893  }
2894  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2895  goto end;
2896  }
2897  } /* for */
2898  if (pp_element != NULL)
2899  goto end;
2900  }
2901  if (pp_port != NULL)
2902  goto end;
2903  }
2904  if (pp != NULL)
2905  goto end;
2906 
2907  result = 1;
2908  end:
2909 #ifdef DEBUG
2910  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2911 #endif
2912  return result;
2913 }
2914 
2915 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
2916  const uint8_t *input,
2917  uint32_t input_len, uint8_t *rdir)
2918 {
2919  return 0;
2920 }
2921 
2922 static int AppLayerProtoDetectTest15(void)
2923 {
2926 
2927  int result = 0;
2928 
2929  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2930  "80",
2931  ALPROTO_HTTP,
2932  5, 8,
2934  ProbingParserDummyForTesting, NULL);
2935  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2936  "80",
2937  ALPROTO_SMB,
2938  5, 6,
2940  ProbingParserDummyForTesting, NULL);
2941  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2942  "80",
2943  ALPROTO_FTP,
2944  7, 10,
2946  ProbingParserDummyForTesting, NULL);
2947 
2948  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2949  "81",
2951  9, 10,
2953  ProbingParserDummyForTesting, NULL);
2954  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2955  "81",
2956  ALPROTO_FTP,
2957  7, 15,
2959  ProbingParserDummyForTesting, NULL);
2960  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2961  "0",
2962  ALPROTO_SMTP,
2963  12, 0,
2965  ProbingParserDummyForTesting, NULL);
2966  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2967  "0",
2968  ALPROTO_TLS,
2969  12, 18,
2971  ProbingParserDummyForTesting, NULL);
2972 
2973  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2974  "85",
2976  9, 10,
2978  ProbingParserDummyForTesting, NULL);
2979  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2980  "85",
2981  ALPROTO_FTP,
2982  7, 15,
2984  ProbingParserDummyForTesting, NULL);
2985  result = 1;
2986 
2987  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
2988  "85",
2989  ALPROTO_IMAP,
2990  12, 23,
2992  ProbingParserDummyForTesting, NULL);
2993 
2994  /* toclient */
2995  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2996  "0",
2998  12, 23,
3000  ProbingParserDummyForTesting, NULL);
3001  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3002  "0",
3003  ALPROTO_IRC,
3004  12, 14,
3006  ProbingParserDummyForTesting, NULL);
3007 
3008  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3009  "85",
3011  9, 10,
3013  ProbingParserDummyForTesting, NULL);
3014  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3015  "81",
3016  ALPROTO_FTP,
3017  7, 15,
3019  ProbingParserDummyForTesting, NULL);
3020  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3021  "0",
3022  ALPROTO_TLS,
3023  12, 18,
3025  ProbingParserDummyForTesting, NULL);
3026  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3027  "80",
3028  ALPROTO_HTTP,
3029  5, 8,
3031  ProbingParserDummyForTesting, NULL);
3032  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3033  "81",
3035  9, 10,
3037  ProbingParserDummyForTesting, NULL);
3038  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3039  "90",
3040  ALPROTO_FTP,
3041  7, 15,
3043  ProbingParserDummyForTesting, NULL);
3044  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3045  "80",
3046  ALPROTO_SMB,
3047  5, 6,
3049  ProbingParserDummyForTesting, NULL);
3050  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3051  "85",
3052  ALPROTO_IMAP,
3053  12, 23,
3055  ProbingParserDummyForTesting, NULL);
3056  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3057  "0",
3058  ALPROTO_SMTP,
3059  12, 17,
3061  ProbingParserDummyForTesting, NULL);
3062  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3063  "80",
3064  ALPROTO_FTP,
3065  7, 10,
3067  ProbingParserDummyForTesting, NULL);
3068 
3069  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3070  { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3071  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3072  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3073  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3074  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3075  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3076  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3077  };
3078  AppLayerProtoDetectPPTestDataElement element_tc_80[] = {
3079  { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3080  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3081  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3082  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3083  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3084  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3085  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3086  };
3087 
3088  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3089  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3090  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3091  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3092  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3093  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3094  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3095  };
3096  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3097  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3098  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3099  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3100  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3101  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3102  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3103  };
3104 
3105  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3106  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3107  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3108  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3109  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3110  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3111  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3112  };
3113  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3114  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3115  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3116  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3117  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3118  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3119  };
3120 
3121  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3122  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3123  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3124  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3125  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3126  };
3127  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3128  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3129  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3130  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3131  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3132  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3133  };
3134 
3135  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3136  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3137  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3138  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3139  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3140  };
3141  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3142  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3143  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3144  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3145  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3146  };
3147 
3148 
3149  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3150  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3151  };
3152  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3153  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3154  };
3155 
3156  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3157  { 80,
3158  ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3159  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3160  ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3161  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3162  23,
3163  element_ts_80, element_tc_80,
3164  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3165  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3166  },
3167  { 81,
3168  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3169  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3170  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) |
3171  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3172  23,
3173  element_ts_81, element_tc_81,
3174  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3175  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3176  },
3177  { 85,
3178  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3179  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3180  ((1 << ALPROTO_DCERPC) |
3181  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3182  23,
3183  element_ts_85, element_tc_85,
3184  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3185  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement)
3186  },
3187  { 90,
3188  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3189  ((1 << ALPROTO_FTP) |
3190  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3191  23,
3192  element_ts_90, element_tc_90,
3193  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3194  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement)
3195  },
3196  { 0,
3197  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3198  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3199  23,
3200  element_ts_0, element_tc_0,
3201  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3202  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement)
3203  }
3204  };
3205 
3206  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3207  { 85,
3208  (1 << ALPROTO_IMAP),
3209  (1 << ALPROTO_IMAP),
3210  23,
3211  element_ts_85_udp, element_tc_85_udp,
3212  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3213  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3214  },
3215  };
3216 
3218  { IPPROTO_TCP,
3219  ports_tcp,
3220  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3221  },
3222  { IPPROTO_UDP,
3223  ports_udp,
3224  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3225  },
3226  };
3227 
3228 
3229  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3230  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3231  goto end;
3232  }
3233  result = 1;
3234 
3235  end:
3238  return result;
3239 }
3240 
3241 
3242 /** \test test if the engine detect the proto and match with it */
3243 static int AppLayerProtoDetectTest16(void)
3244 {
3245  int result = 0;
3246  Flow *f = NULL;
3247  HtpState *http_state = NULL;
3248  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3249  "User-Agent: Mozilla/1.0\r\n"
3250  "Cookie: hellocatch\r\n\r\n";
3251  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3252  TcpSession ssn;
3253  Packet *p = NULL;
3254  Signature *s = NULL;
3255  ThreadVars tv;
3256  DetectEngineThreadCtx *det_ctx = NULL;
3257  DetectEngineCtx *de_ctx = NULL;
3259 
3260  memset(&tv, 0, sizeof(ThreadVars));
3261  memset(&ssn, 0, sizeof(TcpSession));
3262 
3263  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3264  if (p == NULL) {
3265  printf("packet setup failed: ");
3266  goto end;
3267  }
3268 
3269  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3270  if (f == NULL) {
3271  printf("flow setup failed: ");
3272  goto end;
3273  }
3274  f->protoctx = &ssn;
3275  f->proto = IPPROTO_TCP;
3276  p->flow = f;
3277 
3281 
3282  f->alproto = ALPROTO_HTTP;
3283 
3285 
3287  if (de_ctx == NULL) {
3288  goto end;
3289  }
3290  de_ctx->flags |= DE_QUIET;
3291 
3292  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3293  "(msg:\"Test content option\"; "
3294  "sid:1;)");
3295  if (s == NULL) {
3296  goto end;
3297  }
3298 
3300  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3301 
3302  FLOWLOCK_WRLOCK(f);
3303  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3304  STREAM_TOSERVER, http_buf1, http_buf1_len);
3305  if (r != 0) {
3306  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3307  FLOWLOCK_UNLOCK(f);
3308  goto end;
3309  }
3310  FLOWLOCK_UNLOCK(f);
3311 
3312  http_state = f->alstate;
3313  if (http_state == NULL) {
3314  printf("no http state: ");
3315  goto end;
3316  }
3317 
3318  /* do detect */
3319  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3320 
3321  if (!PacketAlertCheck(p, 1)) {
3322  printf("sig 1 didn't alert, but it should: ");
3323  goto end;
3324  }
3325  result = 1;
3326  end:
3327  if (alp_tctx != NULL)
3329  if (det_ctx != NULL)
3330  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3331  if (de_ctx != NULL)
3333  if (de_ctx != NULL)
3335 
3337 
3338  UTHFreePackets(&p, 1);
3339  UTHFreeFlow(f);
3340  return result;
3341 }
3342 
3343 /** \test test if the engine detect the proto on a non standar port
3344  * and match with it */
3345 static int AppLayerProtoDetectTest17(void)
3346 {
3347  int result = 0;
3348  Flow *f = NULL;
3349  HtpState *http_state = NULL;
3350  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3351  "User-Agent: Mozilla/1.0\r\n"
3352  "Cookie: hellocatch\r\n\r\n";
3353  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3354  TcpSession ssn;
3355  Packet *p = NULL;
3356  Signature *s = NULL;
3357  ThreadVars tv;
3358  DetectEngineThreadCtx *det_ctx = NULL;
3359  DetectEngineCtx *de_ctx = NULL;
3361 
3362  memset(&tv, 0, sizeof(ThreadVars));
3363  memset(&ssn, 0, sizeof(TcpSession));
3364 
3365  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3366 
3367  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3368  if (f == NULL)
3369  goto end;
3370  f->protoctx = &ssn;
3371  f->proto = IPPROTO_TCP;
3372  p->flow = f;
3376  f->alproto = ALPROTO_HTTP;
3377 
3379 
3381  if (de_ctx == NULL) {
3382  goto end;
3383  }
3384  de_ctx->flags |= DE_QUIET;
3385 
3386  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3387  "(msg:\"http over non standar port\"; "
3388  "sid:1;)");
3389  if (s == NULL) {
3390  goto end;
3391  }
3392 
3394  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3395 
3396  FLOWLOCK_WRLOCK(f);
3397  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3398  STREAM_TOSERVER, http_buf1, http_buf1_len);
3399  if (r != 0) {
3400  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3401  FLOWLOCK_UNLOCK(f);
3402  goto end;
3403  }
3404  FLOWLOCK_UNLOCK(f);
3405 
3406  http_state = f->alstate;
3407  if (http_state == NULL) {
3408  printf("no http state: ");
3409  goto end;
3410  }
3411 
3412  /* do detect */
3413  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3414 
3415  if (!PacketAlertCheck(p, 1)) {
3416  printf("sig 1 didn't alert, but it should: ");
3417  goto end;
3418  }
3419 
3420  result = 1;
3421 
3422  end:
3423  if (alp_tctx != NULL)
3425  if (det_ctx != NULL)
3426  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3427  if (de_ctx != NULL)
3429  if (de_ctx != NULL)
3431 
3433 
3434  UTHFreePackets(&p, 1);
3435  UTHFreeFlow(f);
3436  return result;
3437 }
3438 
3439 /** \test test if the engine detect the proto and doesn't match
3440  * because the sig expects another proto (ex ftp)*/
3441 static int AppLayerProtoDetectTest18(void)
3442 {
3443  int result = 0;
3444  Flow *f = NULL;
3445  HtpState *http_state = NULL;
3446  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3447  "User-Agent: Mozilla/1.0\r\n"
3448  "Cookie: hellocatch\r\n\r\n";
3449  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3450  TcpSession ssn;
3451  Packet *p = NULL;
3452  Signature *s = NULL;
3453  ThreadVars tv;
3454  DetectEngineThreadCtx *det_ctx = NULL;
3455  DetectEngineCtx *de_ctx = NULL;
3457 
3458  memset(&tv, 0, sizeof(ThreadVars));
3459  memset(&ssn, 0, sizeof(TcpSession));
3460 
3461  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3462 
3463  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3464  if (f == NULL)
3465  goto end;
3466  f->protoctx = &ssn;
3467  f->proto = IPPROTO_TCP;
3468  p->flow = f;
3472  f->alproto = ALPROTO_HTTP;
3473 
3475 
3477  if (de_ctx == NULL) {
3478  goto end;
3479  }
3480  de_ctx->flags |= DE_QUIET;
3481 
3482  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3483  "(msg:\"Test content option\"; "
3484  "sid:1;)");
3485  if (s == NULL) {
3486  goto end;
3487  }
3488 
3490  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3491 
3492  FLOWLOCK_WRLOCK(f);
3493  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3494  STREAM_TOSERVER, http_buf1, http_buf1_len);
3495  if (r != 0) {
3496  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3497  FLOWLOCK_UNLOCK(f);
3498  goto end;
3499  }
3500  FLOWLOCK_UNLOCK(f);
3501 
3502  http_state = f->alstate;
3503  if (http_state == NULL) {
3504  printf("no http state: ");
3505  goto end;
3506  }
3507 
3508  /* do detect */
3509  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3510 
3511  if (PacketAlertCheck(p, 1)) {
3512  printf("sig 1 alerted, but it should not (it's not ftp): ");
3513  goto end;
3514  }
3515 
3516  result = 1;
3517  end:
3518  if (alp_tctx != NULL)
3520  if (det_ctx != NULL)
3521  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3522  if (de_ctx != NULL)
3524  if (de_ctx != NULL)
3526 
3528 
3529  UTHFreePackets(&p, 1);
3530  UTHFreeFlow(f);
3531  return result;
3532 }
3533 
3534 /** \test test if the engine detect the proto and doesn't match
3535  * because the packet has another proto (ex ftp) */
3536 static int AppLayerProtoDetectTest19(void)
3537 {
3538  int result = 0;
3539  Flow *f = NULL;
3540  uint8_t http_buf1[] = "MPUT one\r\n";
3541  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3542  TcpSession ssn;
3543  Packet *p = NULL;
3544  Signature *s = NULL;
3545  ThreadVars tv;
3546  DetectEngineThreadCtx *det_ctx = NULL;
3547  DetectEngineCtx *de_ctx = NULL;
3549 
3550  memset(&tv, 0, sizeof(ThreadVars));
3551  memset(&ssn, 0, sizeof(TcpSession));
3552 
3553  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3554 
3555  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3556  if (f == NULL)
3557  goto end;
3558  f->protoctx = &ssn;
3559  f->proto = IPPROTO_TCP;
3560  p->flow = f;
3564  f->alproto = ALPROTO_FTP;
3565 
3567 
3569  if (de_ctx == NULL) {
3570  goto end;
3571  }
3572  de_ctx->flags |= DE_QUIET;
3573 
3574  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3575  "(msg:\"http over non standar port\"; "
3576  "sid:1;)");
3577  if (s == NULL) {
3578  goto end;
3579  }
3580 
3582  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3583 
3584  FLOWLOCK_WRLOCK(f);
3585  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3586  STREAM_TOSERVER, http_buf1, http_buf1_len);
3587  if (r != 0) {
3588  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3589  FLOWLOCK_UNLOCK(f);
3590  goto end;
3591  }
3592  FLOWLOCK_UNLOCK(f);
3593 
3594  /* do detect */
3595  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3596 
3597  if (PacketAlertCheck(p, 1)) {
3598  printf("sig 1 alerted, but it should not (it's ftp): ");
3599  goto end;
3600  }
3601 
3602  result = 1;
3603 
3604  end:
3605  if (alp_tctx != NULL)
3607  if (det_ctx != NULL)
3608  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3609  if (de_ctx != NULL)
3611  if (de_ctx != NULL)
3613 
3615  UTHFreePackets(&p, 1);
3616  UTHFreeFlow(f);
3617  return result;
3618 }
3619 
3621 {
3622  SCEnter();
3623 
3624  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3625  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3626  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3627  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3628  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3629  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3630  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3631  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3632  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3633  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3634  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3635  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3636  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3637  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3638  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3639  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3640  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3641  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3642  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3643 
3644  SCReturn;
3645 }
3646 
3647 #endif /* UNITTESTS */
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2805
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:272
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:2126
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:100
ALPROTO_IKEV2
@ ALPROTO_IKEV2
Definition: app-layer-protos.h:49
FlowUnsetChangeProtoFlag
void FlowUnsetChangeProtoFlag(Flow *f)
Unset flag to indicate to change proto for the flow.
Definition: flow.c:244
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:1647
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:1767
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:235
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:1752
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1077
offset
uint64_t offset
Definition: util-streaming-buffer.h:2
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:265
flow-util.h
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
AppLayerExpectationSetup
void AppLayerExpectationSetup(void)
Definition: app-layer-expectation.c:124
DetectContentFree
void DetectContentFree(void *ptr)
this function will SCFree memory associated with DetectContentData
Definition: detect-content.c:359
FLOW_SET_PM_DONE
#define FLOW_SET_PM_DONE(f, dir)
Definition: flow.h:267
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:272
SCFree
#define SCFree(a)
Definition: util-mem.h:322
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:335
DetectPort_::port
uint16_t port
Definition: detect.h:192
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint16_t matcher)
Definition: util-mpm.c:264
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:359
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:71
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:444
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
threads.h
ALPROTO_JABBER
@ ALPROTO_JABBER
Definition: app-layer-protos.h:36
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:340
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2023
AppLayerProtoDetectUnittestCtxBackup
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
Definition: app-layer-detect-proto.c:2118
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2797
Flow_::protomap
uint8_t protomap
Definition: flow.h:418
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:761
AppLayerProtoDetectPPTestDataElement
struct AppLayerProtoDetectPPTestDataElement_ AppLayerProtoDetectPPTestDataElement
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2030
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2037
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:279
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:216
MIN
#define MIN(x, y)
Definition: suricata-common.h:360
AppLayerProtoDetectPMCtx
struct AppLayerProtoDetectPMCtx_ AppLayerProtoDetectPMCtx
DE_QUIET
#define DE_QUIET
Definition: detect.h:292
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:2801
PatIntId
#define PatIntId
Definition: suricata-common.h:283
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:262
AppLayerProtoDetectPPTestDataElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:2798
AppLayerProtoDetectProbingParserElement
struct AppLayerProtoDetectProbingParserElement_ AppLayerProtoDetectProbingParserElement
proto
uint8_t proto
Definition: decode-template.h:2
m
SCMutex m
Definition: flow-hash.h:5
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:379
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:440
ALPROTO_MAX
@ ALPROTO_MAX
Definition: app-layer-protos.h:66
Flow_::protoctx
void * protoctx
Definition: flow.h:414
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
AppLayerProtoDetectPPTestDataElement_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:2800
util-unittest.h
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:111
HtpState_
Definition: app-layer-htp.h:245
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
FLOW_SET_PP_DONE
#define FLOW_SET_PP_DONE(f, dir)
Definition: flow.h:268
util-unittest-helper.h
FLOWLOCK_UNLOCK
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:258
AppLayerProtoDetectPPTestDataIPProto_
Definition: app-layer-detect-proto.c:2818
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:263
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:1613
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:451
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:446
expectation_proto
uint8_t expectation_proto[ALPROTO_MAX]
Definition: app-layer-detect-proto.c:2086
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:1231
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:400
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:16
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:264
DetectEngineThreadCtx_
Definition: detect.h:1004
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:255
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:337
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
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:1872
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:1738
detect-engine-port.h
AppLayerProtoDetectPPTestDataPort_::toserver_element
AppLayerProtoDetectPPTestDataElement * toserver_element
Definition: app-layer-detect-proto.c:2811
alpd_tctx
AppLayerProtoDetectThreadCtx * alpd_tctx
Definition: fuzz_applayerprotodetectgetproto.c:20
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
AppLayerParserStateCleanup
void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
Definition: app-layer-parser.c:1451
TRUE
#define TRUE
Definition: suricata-common.h:33
AppLayerProtoDetectPPTestDataIPProto_::no_of_port
int no_of_port
Definition: app-layer-detect-proto.c:2822
SCMalloc
#define SCMalloc(a)
Definition: util-mem.h:222
AppLayerProtoDetectCtx_
The app layer protocol detection context.
Definition: app-layer-detect-proto.c:147
stream_config
TcpStreamCnf stream_config
Definition: stream-tcp.c:119
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:265
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:1665
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:1947
SCReturn
#define SCReturn
Definition: util-debug.h:339
FLOW_RESET_PM_DONE
#define FLOW_RESET_PM_DONE(f, dir)
Definition: flow.h:271
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:188
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:2812
Packet_
Definition: decode.h:408
FLOW_GET_DP
#define FLOW_GET_DP(f)
Definition: flow.h:156
SCCalloc
#define SCCalloc(nm, a)
Definition: util-mem.h:253
StreamTcpFreeConfig
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
ALPROTO_IMAP
@ ALPROTO_IMAP
Definition: app-layer-protos.h:35
FLOW_GET_SP
#define FLOW_GET_SP(f)
Definition: flow.h:154
stream-tcp-private.h
SCReturnUInt
#define SCReturnUInt(x)
Definition: util-debug.h:343
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:2099
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:72
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2814
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:1852
SpmMakeThreadCtx
SpmThreadCtx * SpmMakeThreadCtx(const SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:148
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:353
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:1828
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:2808
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:392
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:2806
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:305
Flow_::alproto_expect
AppProto alproto_expect
Definition: flow.h:432
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:139
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1876
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:391
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:497
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:253
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:815
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:1867
Packet_::flow
struct Flow_ * flow
Definition: decode.h:446
SpmDestroyThreadCtx
void SpmDestroyThreadCtx(SpmThreadCtx *thread_ctx)
Definition: util-spm.c:158
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:2726
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:2807
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:1181
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:2934
AppLayerProtoDetectPPTestDataIPProto_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:2819
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:273
AppLayerProtoDetectDeSetup
int AppLayerProtoDetectDeSetup(void)
Cleans up the app layer protocol detection phase.
Definition: app-layer-detect-proto.c:1798
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:389
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:294
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
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:767
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
AppLayerProtoDetectProbingParserElement_::next
struct AppLayerProtoDetectProbingParserElement_ * next
Definition: app-layer-detect-proto.c:85
threadvars.h
FLOW_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:69
SpmGlobalThreadCtx_
Definition: util-spm.h:49
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:68
DetectContentData_::spm_ctx
SpmCtx * spm_ctx
Definition: detect-content.h:104
AppLayerProtoDetectSupportedAppProtocols
void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
Definition: app-layer-detect-proto.c:2070
AppLayerProtoDetectUnittestsRegister
void AppLayerProtoDetectUnittestsRegister(void)
Register unittests for app layer proto detection module.
Definition: app-layer-detect-proto.c:3620
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:2802
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:1957
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2048
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:145
head
Flow * head
Definition: flow-hash.h:2
Flow_::alproto_ts
AppProto alproto_ts
Definition: flow.h:424
ConfNode_
Definition: conf.h:32
Flow_::alstate
void * alstate
Definition: flow.h:452
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:522
ConfValIsFalse
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:591
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:61
ALPROTO_TEMPLATE
@ ALPROTO_TEMPLATE
Definition: app-layer-protos.h:55
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:218
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:1985
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:48
SCReturnCT
#define SCReturnCT(x, type)
Definition: util-debug.h:351
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:2813
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:2011
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:762
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:146
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:85
DetectContentParseEncloseQuotes
DetectContentData * DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr)
Definition: detect-content.c:243
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:1725
SpmInitGlobalThreadCtx
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint16_t matcher)
Definition: util-spm.c:133
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:1493
MpmCtx_
Definition: util-mpm.h:88
TcpSession_
Definition: stream-tcp-private.h:260
AppLayerProtoDetectProbingParser
struct AppLayerProtoDetectProbingParser_ AppLayerProtoDetectProbingParser
flow.h
SigIntId
#define SigIntId
Definition: suricata-common.h:280
Flow_::alproto_tc
AppProto alproto_tc
Definition: flow.h:425
SpmDestroyCtx
void SpmDestroyCtx(SpmCtx *ctx)
Definition: util-spm.c:178
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:1569
FLOW_SET_PE_DONE
#define FLOW_SET_PE_DONE(f, dir)
Definition: flow.h:269
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:423
AppLayerProtoDetectCtx_::ctx_pp
AppLayerProtoDetectProbingParser * ctx_pp
Definition: app-layer-detect-proto.c:156
util-pool.h
AppLayerProtoDetectPPTestDataElement_::port
uint16_t port
Definition: app-layer-detect-proto.c:2799
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:341
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:314
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:1892
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:2809
SpmInitCtx
SpmCtx * SpmInitCtx(const uint8_t *needle, uint16_t needle_len, int nocase, SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:168
DetectPortCleanupList
void DetectPortCleanupList(const DetectEngineCtx *de_ctx, DetectPort *head)
Free a DetectPort list and each of its members.
Definition: detect-engine-port.c:120
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:624
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:1075
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2821
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2065
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:56
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:393
AppLayerProtoDetectPPTestDataElement_
Definition: app-layer-detect-proto.c:2796