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