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