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