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