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 
1700 {
1701  if (alpd_ctx.alproto_names[ALPROTO_HTTP1] || alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
1702  printf("http\n");
1703  }
1704  for (size_t i = 0; i < alpd_ctx.alproto_names_len; i++) {
1705  if (alpd_ctx.alproto_names[i]) {
1706  if (i == ALPROTO_HTTP1) {
1707  printf("http1\n");
1708  } else {
1709  printf("%s\n", alpd_ctx.alproto_names[i]);
1710  }
1711  }
1712  }
1713 }
1714 
1715 /**
1716  * \todo incomplete. Need more work.
1717  */
1719 {
1720  SCEnter();
1721 
1722  int ipproto_map = 0;
1723  int dir = 0;
1724  PatIntId id = 0;
1725  AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1726  AppLayerProtoDetectPMSignature *sig = NULL;
1727 
1728  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1729  for (dir = 0; dir < 2; dir++) {
1730  pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1731  mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1732  for (id = 0; id < pm_ctx->max_sig_id; id++) {
1733  sig = pm_ctx->map[id];
1734  AppLayerProtoDetectPMFreeSignature(sig);
1735  }
1736  SCFree(pm_ctx->map);
1737  pm_ctx->map = NULL;
1738  }
1739  }
1740 
1741  SCFree(alpd_ctx.alproto_names);
1742  alpd_ctx.alproto_names = NULL;
1743  alpd_ctx.alproto_names_len = 0;
1744  SCFree(alpd_ctx.expectation_proto);
1745  alpd_ctx.expectation_proto = NULL;
1746  alpd_ctx.expectation_proto_len = 0;
1747 
1749 
1750  AppLayerProtoDetectFreeAliases();
1751 
1752  AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1753 
1754  SCReturnInt(0);
1755 }
1756 
1757 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1758 {
1759  SCEnter();
1760 
1761  if (alpd_ctx.alproto_names_len <= alproto && alproto < g_alproto_max) {
1762  void *tmp = SCRealloc(alpd_ctx.alproto_names, sizeof(char *) * g_alproto_max);
1763  if (unlikely(tmp == NULL)) {
1764  FatalError("Unable to realloc alproto_names.");
1765  }
1766  alpd_ctx.alproto_names = tmp;
1767  memset(&alpd_ctx.alproto_names[alpd_ctx.alproto_names_len], 0,
1768  sizeof(char *) * (g_alproto_max - alpd_ctx.alproto_names_len));
1769  alpd_ctx.alproto_names_len = g_alproto_max;
1770  }
1771  if (alpd_ctx.alproto_names[alproto] == NULL)
1772  alpd_ctx.alproto_names[alproto] = alproto_name;
1773 
1774  SCReturn;
1775 }
1776 
1777 void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_alias)
1778 {
1779  SCEnter();
1780 
1782  if (unlikely(new_alias == NULL)) {
1783  exit(EXIT_FAILURE);
1784  }
1785 
1786  new_alias->proto_name = proto_name;
1787  new_alias->proto_alias = proto_alias;
1788  new_alias->next = NULL;
1789 
1790  if (alpda_ctx == NULL) {
1791  alpda_ctx = new_alias;
1792  } else {
1793  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1794  while (cur_alias->next != NULL) {
1795  cur_alias = cur_alias->next;
1796  }
1797  cur_alias->next = new_alias;
1798  }
1799 
1800  SCReturn;
1801 }
1802 
1803 /** \brief request applayer to wrap up this protocol and rerun protocol
1804  * detection.
1805  *
1806  * When this is called, the old session is reset unconditionally. A
1807  * 'detect/log' flush packet is generated for both direction before
1808  * the reset, so allow for final detection and logging.
1809  *
1810  * \param f flow to act on
1811  * \param dp destination port to use in protocol detection. Set to 443
1812  * for start tls, set to the HTTP uri port for CONNECT and
1813  * set to 0 to not use it.
1814  * \param expect_proto expected protocol. AppLayer event will be set if
1815  * detected protocol differs from this.
1816  */
1817 bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1818 {
1819  if (FlowChangeProto(f)) {
1820  // If we are already changing protocols, from SMTP to TLS for instance,
1821  // and that we do not get TLS but HTTP1, which is requesting change to HTTP2,
1822  // we do not proceed the new protocol change
1823  return false;
1824  }
1826  f->protodetect_dp = dp;
1827  f->alproto_expect = expect_proto;
1829  f->alproto_orig = f->alproto;
1830  // If one side is unknown yet, set it to the other known side
1831  if (f->alproto_ts == ALPROTO_UNKNOWN) {
1832  f->alproto_ts = f->alproto;
1833  }
1834  if (f->alproto_tc == ALPROTO_UNKNOWN) {
1835  f->alproto_tc = f->alproto;
1836  }
1837  return true;
1838 }
1839 
1840 /** \brief request applayer to wrap up this protocol and rerun protocol
1841  * detection with expectation of TLS. Used by STARTTLS.
1842  *
1843  * Sets detection port to 443 to make port based TLS detection work for
1844  * SMTP, FTP etc as well.
1845  *
1846  * \param f flow to act on
1847  */
1849 {
1851 }
1852 
1853 /** \brief Forces a flow app-layer protocol change.
1854  * Happens for instance when a HTTP2 flow is seen as DOH2
1855  *
1856  * \param f flow to act on
1857  * \param new_proto new app-layer protocol
1858  */
1860 {
1861  if (new_proto != f->alproto) {
1862  f->alproto_orig = f->alproto;
1863  f->alproto = new_proto;
1864  f->alproto_ts = f->alproto;
1865  f->alproto_tc = f->alproto;
1866  }
1867 }
1868 
1870 {
1871  FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1872  FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
1873  FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1874  FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
1875  FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1876  FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
1879  // Does not free the structures for the parser
1880  // keeps f->alstate for new state creation
1881  f->alparser = NULL;
1882  f->alproto = ALPROTO_UNKNOWN;
1885 }
1886 
1888  const char *ipproto, const char *alproto, bool default_enabled)
1889 {
1890  SCEnter();
1891 
1892  BUG_ON(ipproto == NULL || alproto == NULL);
1893 
1894  int enabled = 1;
1895  char param[100];
1896  SCConfNode *node;
1897  int r;
1898 
1899  if (RunmodeIsUnittests())
1900  goto enabled;
1901 
1902 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1903  // so that fuzzig takes place for DNP3 and such
1904  default_enabled = true;
1905 #endif
1906 
1907  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1908  alproto, ".enabled");
1909  if (r < 0) {
1910  FatalError("snprintf failure.");
1911  } else if (r > (int)sizeof(param)) {
1912  FatalError("buffer not big enough to write param.");
1913  }
1914 
1915  node = SCConfGetNode(param);
1916  if (node == NULL) {
1917  SCLogDebug("Entry for %s not found.", param);
1918  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1919  alproto, ".", ipproto, ".enabled");
1920  if (r < 0) {
1921  FatalError("snprintf failure.");
1922  } else if (r > (int)sizeof(param)) {
1923  FatalError("buffer not big enough to write param.");
1924  }
1925 
1926  node = SCConfGetNode(param);
1927  if (node == NULL) {
1928  SCLogDebug("Entry for %s not found.", param);
1929  if (default_enabled) {
1930  goto enabled;
1931  } else {
1932  goto disabled;
1933  }
1934  }
1935  }
1936 
1937  if (node->val) {
1938  if (SCConfValIsTrue(node->val)) {
1939  goto enabled;
1940  } else if (SCConfValIsFalse(node->val)) {
1941  goto disabled;
1942  } else if (strcasecmp(node->val, "detection-only") == 0) {
1943  goto enabled;
1944  }
1945  }
1946 
1947  /* Invalid or null value. */
1948  SCLogError("Invalid value found for %s.", param);
1949  exit(EXIT_FAILURE);
1950 
1951  disabled:
1952  enabled = 0;
1953  enabled:
1954  SCReturnInt(enabled);
1955 }
1956 
1957 int SCAppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
1958 {
1959  return SCAppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
1960 }
1961 
1963 {
1964  SCEnter();
1965 
1967  MpmCtx *mpm_ctx;
1968  MpmThreadCtx *mpm_tctx;
1969  int i, j;
1970  PatIntId max_pat_id = 0;
1971 
1972  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1973  for (j = 0; j < 2; j++) {
1974  if (max_pat_id == 0) {
1975  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1976 
1977  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
1978  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
1979  {
1980  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1981  }
1982  }
1983  }
1984 
1985  alpd_tctx = SCCalloc(1, sizeof(*alpd_tctx));
1986  if (alpd_tctx == NULL)
1987  goto error;
1988 
1989  /* Get the max pat id for all the mpm ctxs. */
1990  if (PmqSetup(&alpd_tctx->pmq) < 0)
1991  goto error;
1992 
1993  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1994  for (j = 0; j < 2; j++) {
1995  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
1996  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
1997  MpmInitThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
1998  }
1999  }
2000 
2002  if (alpd_tctx->spm_thread_ctx == NULL) {
2003  goto error;
2004  }
2005 
2006  goto end;
2007  error:
2008  if (alpd_tctx != NULL)
2010  alpd_tctx = NULL;
2011  end:
2012  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2013 }
2014 
2016 {
2017  SCEnter();
2018 
2019  MpmCtx *mpm_ctx;
2020  MpmThreadCtx *mpm_tctx;
2021  int ipproto_map, dir;
2022 
2023  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2024  for (dir = 0; dir < 2; dir++) {
2025  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2026  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2027  MpmDestroyThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
2028  }
2029  }
2030  PmqFree(&alpd_tctx->pmq);
2031  if (alpd_tctx->spm_thread_ctx != NULL) {
2033  }
2034  SCFree(alpd_tctx);
2035 
2036  SCReturn;
2037 }
2038 
2039 /***** Utility *****/
2040 
2041 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2042 {
2043  SCEnter();
2044 
2045  // Custom case for only signature-only protocol so far
2046  if (alproto == ALPROTO_HTTP) {
2049  } else if (alproto == ALPROTO_DOH2) {
2050  // DOH2 is not detected, just HTTP2
2052  } else {
2053  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2054  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2055  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2056  }
2057 
2058  SCReturn;
2059 }
2060 
2062 {
2063  SCEnter();
2064 
2065  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2066  while (cur_alias != NULL) {
2067  if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2068  alproto_name = cur_alias->proto_name;
2069  }
2070 
2071  cur_alias = cur_alias->next;
2072  }
2073 
2074  AppProto a;
2075  AppProto b = StringToAppProto(alproto_name);
2076  for (a = 0; a < g_alproto_max; a++) {
2077  if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2078  // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2079  SCReturnCT(b, "AppProto");
2080  }
2081  }
2082 
2083  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2084 }
2085 
2087 {
2088  // Special case for http (any version) :
2089  // returns "http" if both versions are enabled
2090  // and returns "http1" or "http2" if only one version is enabled
2091  if (alproto == ALPROTO_HTTP) {
2092  if (alpd_ctx.alproto_names[ALPROTO_HTTP1]) {
2093  if (alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
2094  return "http";
2095  } // else
2096  return alpd_ctx.alproto_names[ALPROTO_HTTP1];
2097  } // else
2098  return alpd_ctx.alproto_names[ALPROTO_HTTP2];
2099  }
2100  return alpd_ctx.alproto_names[alproto];
2101 }
2102 
2104 {
2105  SCEnter();
2106 
2107  memset(alprotos, 0, g_alproto_max * sizeof(AppProto));
2108 
2109  int alproto;
2110 
2111  for (alproto = 0; alproto != g_alproto_max; alproto++) {
2112  if (alpd_ctx.alproto_names[alproto] != NULL)
2113  alprotos[alproto] = 1;
2114  }
2115 
2116  SCReturn;
2117 }
2118 
2119 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2120  uint8_t *ipprotos)
2121 {
2122  if (alproto >= alpd_ctx.expectation_proto_len) {
2123  return;
2124  }
2125  if (alpd_ctx.expectation_proto[alproto] == IPPROTO_TCP) {
2126  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2127  }
2128  if (alpd_ctx.expectation_proto[alproto] == IPPROTO_UDP) {
2129  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2130  }
2131 }
2132 
2134 {
2135  if (alpd_ctx.expectation_proto[alproto]) {
2136  if (proto != alpd_ctx.expectation_proto[alproto]) {
2137  SCLogError("Expectation on 2 IP protocols are not supported");
2138  }
2139  }
2140  alpd_ctx.expectation_proto[alproto] = proto;
2141 }
2142 
2143 /***** Unittests *****/
2144 
2145 #ifdef UNITTESTS
2146 
2147 #include "app-layer-htp.h"
2148 #include "detect-engine-alert.h"
2149 
2150 static AppLayerProtoDetectCtx alpd_ctx_ut;
2151 
2153 {
2154  SCEnter();
2155  alpd_ctx_ut = alpd_ctx;
2156  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2157  SCReturn;
2158 }
2159 
2161 {
2162  SCEnter();
2163  alpd_ctx = alpd_ctx_ut;
2164  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2165  SCReturn;
2166 }
2167 
2168 static int AppLayerProtoDetectTest01(void)
2169 {
2172 
2173  const char *buf = "HTTP";
2175  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2176  buf = "GET";
2178  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOSERVER);
2179 
2181  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2182  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2183 
2186  PASS;
2187 }
2188 
2189 static int AppLayerProtoDetectTest02(void)
2190 {
2193 
2194  const char *buf = "HTTP";
2196  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2197  buf = "ftp";
2198  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2199 
2201  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2202  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2203 
2204  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2205  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2206 
2209 
2212  PASS;
2213 }
2214 
2215 static int AppLayerProtoDetectTest03(void)
2216 {
2219 
2220  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2221  AppProto pm_results[g_alproto_max];
2222  memset(pm_results, 0, sizeof(pm_results));
2223  Flow f;
2224  memset(&f, 0x00, sizeof(f));
2225  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2226 
2227 
2228  const char *buf = "HTTP";
2230  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2231  buf = "220 ";
2232  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2233 
2235  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2236  * it sets internal structures which depends on the above function. */
2239 
2240  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2241  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2242  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2243  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2246 
2247  bool rflow = false;
2248  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2249  &f, l7data, sizeof(l7data),
2250  STREAM_TOCLIENT,
2251  pm_results, &rflow);
2252  FAIL_IF(cnt != 1);
2253  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2254 
2258  PASS;
2259 }
2260 
2261 static int AppLayerProtoDetectTest04(void)
2262 {
2265 
2266  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2267  Flow f;
2268  memset(&f, 0x00, sizeof(f));
2269  AppProto pm_results[g_alproto_max];
2270  memset(pm_results, 0, sizeof(pm_results));
2271  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2272 
2273  const char *buf = "200 ";
2275  IPPROTO_TCP, ALPROTO_HTTP1, buf, 13, 0, STREAM_TOCLIENT);
2276 
2278  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2279  * it sets internal structures which depends on the above function. */
2282 
2283  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2284  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2285  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2286  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2288 
2289  bool rdir = false;
2290  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2291  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2292  pm_results, &rdir);
2293  FAIL_IF(cnt != 1);
2294  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2295 
2299  PASS;
2300 }
2301 
2302 static int AppLayerProtoDetectTest05(void)
2303 {
2306 
2307  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2308  AppProto pm_results[g_alproto_max];
2309  memset(pm_results, 0, sizeof(pm_results));
2310  Flow f;
2311  memset(&f, 0x00, sizeof(f));
2312  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2313 
2314  const char *buf = "HTTP";
2316  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2317  buf = "220 ";
2318  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2319 
2321  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2322  * it sets internal structures which depends on the above function. */
2325 
2326  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2327  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2328  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2329  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2332 
2333  bool rdir = false;
2334  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2335  &f, l7data, sizeof(l7data),
2336  STREAM_TOCLIENT,
2337  pm_results, &rdir);
2338  FAIL_IF(cnt != 1);
2339  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2340 
2344  PASS;
2345 }
2346 
2347 static int AppLayerProtoDetectTest06(void)
2348 {
2351 
2352  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2353  AppProto pm_results[g_alproto_max];
2354  memset(pm_results, 0, sizeof(pm_results));
2355  Flow f;
2356  memset(&f, 0x00, sizeof(f));
2357  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2358 
2359  const char *buf = "HTTP";
2361  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2362  buf = "220 ";
2363  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2364 
2366  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2367  * it sets internal structures which depends on the above function. */
2370 
2371  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2372  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2373  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2374  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2377 
2378  bool rdir = false;
2379  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2380  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2381  pm_results, &rdir);
2382  FAIL_IF(cnt != 1);
2383  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2384 
2388  PASS;
2389 }
2390 
2391 static int AppLayerProtoDetectTest07(void)
2392 {
2395 
2396  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2397  Flow f;
2398  memset(&f, 0x00, sizeof(f));
2399  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2400  AppProto pm_results[g_alproto_max];
2401  memset(pm_results, 0, sizeof(pm_results));
2402 
2403  const char *buf = "HTTP";
2405  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2406 
2408  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2409  * it sets internal structures which depends on the above function. */
2411 
2412  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2413  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2414  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2415  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2417 
2418  bool rdir = false;
2419  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2420  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2421  pm_results, &rdir);
2422  FAIL_IF(cnt != 0);
2423 
2427  PASS;
2428 }
2429 
2430 static int AppLayerProtoDetectTest08(void)
2431 {
2434 
2435  uint8_t l7data[] = {
2436  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2437  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2438  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2439  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2440  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2441  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2442  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2443  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2444  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2445  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2446  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2447  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2448  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2449  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2450  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2451  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2452  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2453  0x00
2454  };
2455  AppProto pm_results[g_alproto_max];
2456  memset(pm_results, 0, sizeof(pm_results));
2457  Flow f;
2458  memset(&f, 0x00, sizeof(f));
2459  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2460 
2461  const char *buf = "|ff|SMB";
2462  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2463 
2465  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2466  * it sets internal structures which depends on the above function. */
2469 
2470  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2471  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2472  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2473  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2475 
2476  bool rdir = false;
2477  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2478  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2479  pm_results, &rdir);
2480  FAIL_IF(cnt != 1);
2481  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2482 
2486  PASS;
2487 }
2488 
2489 static int AppLayerProtoDetectTest09(void)
2490 {
2493 
2494  uint8_t l7data[] = {
2495  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2496  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2497  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2498  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2499  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2500  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2501  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2502  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2503  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2504  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2505  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2506  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2507  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2508  0x00, 0x02, 0x02
2509  };
2510  AppProto pm_results[g_alproto_max];
2511  memset(pm_results, 0, sizeof(pm_results));
2512  Flow f;
2513  memset(&f, 0x00, sizeof(f));
2514  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2515 
2516  const char *buf = "|fe|SMB";
2517  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2518 
2520  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2521  * it sets internal structures which depends on the above function. */
2524 
2525  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2526  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2527  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2528  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2530 
2531  bool rdir = false;
2532  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2533  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2534  pm_results, &rdir);
2535  FAIL_IF(cnt != 1);
2536  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2537 
2541  PASS;
2542 }
2543 
2544 static int AppLayerProtoDetectTest10(void)
2545 {
2548 
2549  uint8_t l7data[] = {
2550  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2551  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2552  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2553  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2554  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2555  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2556  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2557  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2558  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2559  };
2560  AppProto pm_results[g_alproto_max];
2561  memset(pm_results, 0, sizeof(pm_results));
2562  Flow f;
2563  memset(&f, 0x00, sizeof(f));
2564  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2565 
2566  const char *buf = "|05 00|";
2568  IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2569 
2571  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2572  * it sets internal structures which depends on the above function. */
2575 
2576  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2577  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2578  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2579  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2581 
2582  bool rdir = false;
2583  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2584  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2585  pm_results, &rdir);
2586  FAIL_IF(cnt != 1);
2587  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2588 
2592  PASS;
2593 }
2594 
2595 /**
2596  * \test Why we still get http for connect... obviously because
2597  * we also match on the reply, duh
2598  */
2599 static int AppLayerProtoDetectTest11(void)
2600 {
2603 
2604  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2605  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2606  AppProto pm_results[g_alproto_max];
2607  memset(pm_results, 0, sizeof(pm_results));
2608  Flow f;
2609  memset(&f, 0x00, sizeof(f));
2610  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2611 
2613  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2615  IPPROTO_TCP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2617  IPPROTO_TCP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2619  IPPROTO_TCP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2621  IPPROTO_TCP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2623  IPPROTO_TCP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2625  IPPROTO_TCP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2627  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2628 
2630  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2631  * it sets internal structures which depends on the above function. */
2634 
2635  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2636  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2637  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2638  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2639 
2648 
2649  bool rdir = false;
2650  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2651  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2652  pm_results, &rdir);
2653  FAIL_IF(cnt != 1);
2654  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2655 
2656  memset(pm_results, 0, sizeof(pm_results));
2657  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2658  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2659  pm_results, &rdir);
2660  FAIL_IF(cnt != 1);
2661  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2662 
2666  PASS;
2667 }
2668 
2669 /**
2670  * \test AlpProtoSignature test
2671  */
2672 static int AppLayerProtoDetectTest12(void)
2673 {
2676 
2677  int r = 0;
2678 
2680  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2681  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2682  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2683  {
2684  printf("failure 1\n");
2685  goto end;
2686  }
2687 
2689  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2690  printf("failure 2\n");
2691  goto end;
2692  }
2693  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2694  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2695  {
2696  printf("failure 3\n");
2697  goto end;
2698  }
2699  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2700  printf("failure 4\n");
2701  goto end;
2702  }
2703  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2704  printf("failure 5\n");
2705  goto end;
2706  }
2707  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2708  printf("failure 6\n");
2709  goto end;
2710  }
2711 
2712  r = 1;
2713 
2714  end:
2717  return r;
2718 }
2719 
2720 /**
2721  * \test What about if we add some sigs only for udp but call for tcp?
2722  * It should not detect any proto
2723  */
2724 static int AppLayerProtoDetectTest13(void)
2725 {
2728 
2729  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2730  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2731  AppProto pm_results[g_alproto_max];
2732 
2733  Flow f;
2734  memset(&f, 0x00, sizeof(f));
2735  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2736 
2738  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2740  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2742  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2744  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2746  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2748  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2750  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2752  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2753 
2755  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2756  * it sets internal structures which depends on the above function. */
2758 
2759  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2760  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2761 
2770 
2771  memset(pm_results, 0, sizeof(pm_results));
2772  bool rdir = false;
2773  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2774  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2775  pm_results, &rdir);
2776  FAIL_IF(cnt != 0);
2777 
2778  memset(pm_results, 0, sizeof(pm_results));
2779  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2780  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2781  pm_results, &rdir);
2782  FAIL_IF(cnt != 0);
2783 
2787  PASS;
2788 }
2789 
2790 /**
2791  * \test What about if we add some sigs only for udp calling it for UDP?
2792  * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2793  * to ensure that TCP/UDP differences work correctly.
2794  */
2795 static int AppLayerProtoDetectTest14(void)
2796 {
2799 
2800  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2801  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2802  AppProto pm_results[g_alproto_max];
2803  uint32_t cnt;
2804  Flow f;
2805  memset(&f, 0x00, sizeof(f));
2806  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2807 
2809  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2811  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2813  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2815  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2817  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2819  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2821  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2823  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2824 
2826  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2827  * it sets internal structures which depends on the above function. */
2830 
2831  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2832  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2833 
2842 
2843  memset(pm_results, 0, sizeof(pm_results));
2844  bool rdir = false;
2845  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2846  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2847  pm_results, &rdir);
2848  FAIL_IF(cnt != 1);
2849  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2850 
2851  memset(pm_results, 0, sizeof(pm_results));
2852  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2853  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2854  pm_results, &rdir);
2855  FAIL_IF(cnt != 1);
2856  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2857 
2861  PASS;
2862 }
2863 
2865  const char *alproto_name;
2867  uint16_t port;
2868  uint32_t min_depth;
2869  uint32_t max_depth;
2871 
2873  uint16_t port;
2874  uint16_t dp_max_depth;
2875  uint16_t sp_max_depth;
2876 
2882 
2883 
2885  uint8_t ipproto;
2886 
2890 
2891 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2893  int no_of_ip_proto)
2894 {
2895  int result = 0;
2896  int i = -1, j = -1 , k = -1;
2897 #ifdef DEBUG
2898  int dir = 0;
2899 #endif
2900  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2901  if (pp->ipproto != ip_proto[i].ipproto)
2902  goto end;
2903 
2905  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2906  if (pp_port->port != ip_proto[i].port[k].port)
2907  goto end;
2908  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2909  goto end;
2910  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2911  goto end;
2912 
2913  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2914 #ifdef DEBUG
2915  dir = 0;
2916 #endif
2917  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2918  j++, pp_element = pp_element->next) {
2919 
2920  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2921  goto end;
2922  }
2923  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2924  goto end;
2925  }
2926  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2927  goto end;
2928  }
2929  } /* for */
2930  if (pp_element != NULL)
2931  goto end;
2932 
2933  pp_element = pp_port->sp;
2934 #ifdef DEBUG
2935  dir = 1;
2936 #endif
2937  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2938  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2939  goto end;
2940  }
2941  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2942  goto end;
2943  }
2944  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2945  goto end;
2946  }
2947  } /* for */
2948  if (pp_element != NULL)
2949  goto end;
2950  }
2951  if (pp_port != NULL)
2952  goto end;
2953  }
2954  if (pp != NULL)
2955  goto end;
2956 
2957  result = 1;
2958  end:
2959 #ifdef DEBUG
2960  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2961 #endif
2962  return result;
2963 }
2964 
2965 static uint16_t ProbingParserDummyForTesting(
2966  const Flow *f, uint8_t direction, const uint8_t *input, uint32_t input_len, uint8_t *rdir)
2967 {
2968  return 0;
2969 }
2970 
2971 static int AppLayerProtoDetectTest15(void)
2972 {
2975 
2976  int result = 0;
2977 
2978  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOSERVER,
2979  ProbingParserDummyForTesting, NULL);
2980  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_SMB, 5, 6, STREAM_TOSERVER,
2981  ProbingParserDummyForTesting, NULL);
2982  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_FTP, 7, 10, STREAM_TOSERVER,
2983  ProbingParserDummyForTesting, NULL);
2984 
2985  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_DCERPC, 9, 10, STREAM_TOSERVER,
2986  ProbingParserDummyForTesting, NULL);
2987  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_FTP, 7, 15, STREAM_TOSERVER,
2988  ProbingParserDummyForTesting, NULL);
2989  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_SMTP, 12, 0, STREAM_TOSERVER,
2990  ProbingParserDummyForTesting, NULL);
2991  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_TLS, 12, 18, STREAM_TOSERVER,
2992  ProbingParserDummyForTesting, NULL);
2993 
2994  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_DCERPC, 9, 10, STREAM_TOSERVER,
2995  ProbingParserDummyForTesting, NULL);
2996  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_FTP, 7, 15, STREAM_TOSERVER,
2997  ProbingParserDummyForTesting, NULL);
2998  result = 1;
2999 
3000  SCAppLayerProtoDetectPPRegister(IPPROTO_UDP, "85", ALPROTO_IMAP, 12, 23, STREAM_TOSERVER,
3001  ProbingParserDummyForTesting, NULL);
3002 
3003  /* toclient */
3004  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_JABBER, 12, 23, STREAM_TOCLIENT,
3005  ProbingParserDummyForTesting, NULL);
3006  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_IRC, 12, 14, STREAM_TOCLIENT,
3007  ProbingParserDummyForTesting, NULL);
3008 
3009  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_DCERPC, 9, 10, STREAM_TOCLIENT,
3010  ProbingParserDummyForTesting, NULL);
3011  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_FTP, 7, 15, STREAM_TOCLIENT,
3012  ProbingParserDummyForTesting, NULL);
3013  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_TLS, 12, 18, STREAM_TOCLIENT,
3014  ProbingParserDummyForTesting, NULL);
3015  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOCLIENT,
3016  ProbingParserDummyForTesting, NULL);
3017  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_DCERPC, 9, 10, STREAM_TOCLIENT,
3018  ProbingParserDummyForTesting, NULL);
3019  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "90", ALPROTO_FTP, 7, 15, STREAM_TOCLIENT,
3020  ProbingParserDummyForTesting, NULL);
3021  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_SMB, 5, 6, STREAM_TOCLIENT,
3022  ProbingParserDummyForTesting, NULL);
3023  SCAppLayerProtoDetectPPRegister(IPPROTO_UDP, "85", ALPROTO_IMAP, 12, 23, STREAM_TOCLIENT,
3024  ProbingParserDummyForTesting, NULL);
3025  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_SMTP, 12, 17, STREAM_TOCLIENT,
3026  ProbingParserDummyForTesting, NULL);
3027  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_FTP, 7, 10, STREAM_TOCLIENT,
3028  ProbingParserDummyForTesting, NULL);
3029 
3030  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3031  { "http", ALPROTO_HTTP1, 80, 5, 8 },
3032  { "smb", ALPROTO_SMB, 80, 5, 6 },
3033  { "ftp", ALPROTO_FTP, 80, 7, 10 },
3034  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3035  { "tls", ALPROTO_TLS, 0, 12, 18 },
3036  { "irc", ALPROTO_IRC, 0, 12, 25 },
3037  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3038  };
3039  AppLayerProtoDetectPPTestDataElement element_tc_80[] = { { "http", ALPROTO_HTTP1, 80, 5, 8 },
3040  { "smb", ALPROTO_SMB, 80, 5, 6 }, { "ftp", ALPROTO_FTP, 80, 7, 10 },
3041  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3042  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3043 
3044  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3045  { "dcerpc", ALPROTO_DCERPC, 81, 9, 10 },
3046  { "ftp", ALPROTO_FTP, 81, 7, 15 },
3047  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3048  { "tls", ALPROTO_TLS, 0, 12, 18 },
3049  { "irc", ALPROTO_IRC, 0, 12, 25 },
3050  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3051  };
3052  AppLayerProtoDetectPPTestDataElement element_tc_81[] = { { "ftp", ALPROTO_FTP, 81, 7, 15 },
3053  { "dcerpc", ALPROTO_DCERPC, 81, 9, 10 }, { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3054  { "irc", ALPROTO_IRC, 0, 12, 14 }, { "tls", ALPROTO_TLS, 0, 12, 18 },
3055  { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3056 
3057  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3058  { "dcerpc", ALPROTO_DCERPC, 85, 9, 10 },
3059  { "ftp", ALPROTO_FTP, 85, 7, 15 },
3060  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3061  { "tls", ALPROTO_TLS, 0, 12, 18 },
3062  { "irc", ALPROTO_IRC, 0, 12, 25 },
3063  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3064  };
3065  AppLayerProtoDetectPPTestDataElement element_tc_85[] = { { "dcerpc", ALPROTO_DCERPC, 85, 9,
3066  10 },
3067  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3068  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3069 
3070  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3071  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3072  { "tls", ALPROTO_TLS, 0, 12, 18 },
3073  { "irc", ALPROTO_IRC, 0, 12, 25 },
3074  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3075  };
3076  AppLayerProtoDetectPPTestDataElement element_tc_90[] = { { "ftp", ALPROTO_FTP, 90, 7, 15 },
3077  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3078  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3079 
3080  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3081  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3082  { "tls", ALPROTO_TLS, 0, 12, 18 },
3083  { "irc", ALPROTO_IRC, 0, 12, 25 },
3084  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3085  };
3086  AppLayerProtoDetectPPTestDataElement element_tc_0[] = { { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3087  { "irc", ALPROTO_IRC, 0, 12, 14 }, { "tls", ALPROTO_TLS, 0, 12, 18 },
3088  { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3089 
3090  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3091  { "imap", ALPROTO_IMAP, 85, 12, 23 },
3092  };
3093  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3094  { "imap", ALPROTO_IMAP, 85, 12, 23 },
3095  };
3096 
3097  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3098  {
3099  80,
3100  23,
3101  23,
3102  element_ts_80,
3103  element_tc_80,
3104  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3105  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3106  },
3107  {
3108  81,
3109  23,
3110  23,
3111  element_ts_81,
3112  element_tc_81,
3113  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3114  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3115  },
3116  { 85, 23, 23, element_ts_85, element_tc_85,
3117  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3118  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3119  { 90, 23, 23, element_ts_90, element_tc_90,
3120  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3121  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3122  { 0, 23, 23, element_ts_0, element_tc_0,
3123  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3124  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement) }
3125  };
3126 
3127  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3128  {
3129  85,
3130  23,
3131  23,
3132  element_ts_85_udp,
3133  element_tc_85_udp,
3134  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3135  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3136  },
3137  };
3138 
3140  { IPPROTO_TCP,
3141  ports_tcp,
3142  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3143  },
3144  { IPPROTO_UDP,
3145  ports_udp,
3146  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3147  },
3148  };
3149 
3150 
3151  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3152  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3153  goto end;
3154  }
3155  result = 1;
3156 
3157  end:
3160  return result;
3161 }
3162 
3163 
3164 /** \test test if the engine detect the proto and match with it */
3165 static int AppLayerProtoDetectTest16(void)
3166 {
3167  int result = 0;
3168  Flow *f = NULL;
3169  HtpState *http_state = NULL;
3170  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3171  "User-Agent: Mozilla/1.0\r\n"
3172  "Cookie: hellocatch\r\n\r\n";
3173  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3174  TcpSession ssn;
3175  Packet *p = NULL;
3176  Signature *s = NULL;
3177  ThreadVars tv;
3178  DetectEngineThreadCtx *det_ctx = NULL;
3179  DetectEngineCtx *de_ctx = NULL;
3181 
3182  memset(&tv, 0, sizeof(ThreadVars));
3184  memset(&ssn, 0, sizeof(TcpSession));
3185 
3186  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3187  if (p == NULL) {
3188  printf("packet setup failed: ");
3189  goto end;
3190  }
3191 
3192  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3193  if (f == NULL) {
3194  printf("flow setup failed: ");
3195  goto end;
3196  }
3197  f->protoctx = &ssn;
3198  f->proto = IPPROTO_TCP;
3199  p->flow = f;
3200 
3204 
3205  f->alproto = ALPROTO_HTTP1;
3206 
3207  StreamTcpInitConfig(true);
3208 
3210  if (de_ctx == NULL) {
3211  goto end;
3212  }
3213  de_ctx->flags |= DE_QUIET;
3214 
3215  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3216  "(msg:\"Test content option\"; "
3217  "sid:1;)");
3218  if (s == NULL) {
3219  goto end;
3220  }
3221 
3223  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3224 
3225  int r = AppLayerParserParse(
3226  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3227  if (r != 0) {
3228  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3229  goto end;
3230  }
3231 
3232  http_state = f->alstate;
3233  if (http_state == NULL) {
3234  printf("no http state: ");
3235  goto end;
3236  }
3237 
3238  /* do detect */
3239  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3240 
3241  if (!PacketAlertCheck(p, 1)) {
3242  printf("sig 1 didn't alert, but it should: ");
3243  goto end;
3244  }
3245  result = 1;
3246  end:
3247  UTHFreePackets(&p, 1);
3248  UTHFreeFlow(f);
3249  if (alp_tctx != NULL)
3251  if (det_ctx != NULL)
3252  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3253  if (de_ctx != NULL)
3255  StreamTcpFreeConfig(true);
3257  return result;
3258 }
3259 
3260 /** \test test if the engine detect the proto on a non standar port
3261  * and match with it */
3262 static int AppLayerProtoDetectTest17(void)
3263 {
3264  int result = 0;
3265  Flow *f = NULL;
3266  HtpState *http_state = NULL;
3267  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3268  "User-Agent: Mozilla/1.0\r\n"
3269  "Cookie: hellocatch\r\n\r\n";
3270  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3271  TcpSession ssn;
3272  Packet *p = NULL;
3273  Signature *s = NULL;
3274  ThreadVars tv;
3275  DetectEngineThreadCtx *det_ctx = NULL;
3276  DetectEngineCtx *de_ctx = NULL;
3278 
3279  memset(&tv, 0, sizeof(ThreadVars));
3281  memset(&ssn, 0, sizeof(TcpSession));
3282 
3283  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3284 
3285  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3286  if (f == NULL)
3287  goto end;
3288  f->protoctx = &ssn;
3289  f->proto = IPPROTO_TCP;
3290  p->flow = f;
3294  f->alproto = ALPROTO_HTTP1;
3295 
3296  StreamTcpInitConfig(true);
3297 
3299  if (de_ctx == NULL) {
3300  goto end;
3301  }
3302  de_ctx->flags |= DE_QUIET;
3303 
3304  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3305  "(msg:\"http over non standar port\"; "
3306  "sid:1;)");
3307  if (s == NULL) {
3308  goto end;
3309  }
3310 
3312  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3313 
3314  int r = AppLayerParserParse(
3315  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3316  if (r != 0) {
3317  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3318  goto end;
3319  }
3320 
3321  http_state = f->alstate;
3322  if (http_state == NULL) {
3323  printf("no http state: ");
3324  goto end;
3325  }
3326 
3327  /* do detect */
3328  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3329 
3330  if (!PacketAlertCheck(p, 1)) {
3331  printf("sig 1 didn't alert, but it should: ");
3332  goto end;
3333  }
3334 
3335  result = 1;
3336 
3337  end:
3338  UTHFreePackets(&p, 1);
3339  UTHFreeFlow(f);
3340  if (alp_tctx != NULL)
3342  if (det_ctx != NULL)
3343  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3344  if (de_ctx != NULL)
3346  StreamTcpFreeConfig(true);
3348  return result;
3349 }
3350 
3351 /** \test test if the engine detect the proto and doesn't match
3352  * because the sig expects another proto (ex ftp)*/
3353 static int AppLayerProtoDetectTest18(void)
3354 {
3355  int result = 0;
3356  Flow *f = NULL;
3357  HtpState *http_state = NULL;
3358  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3359  "User-Agent: Mozilla/1.0\r\n"
3360  "Cookie: hellocatch\r\n\r\n";
3361  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3362  TcpSession ssn;
3363  Packet *p = NULL;
3364  Signature *s = NULL;
3365  ThreadVars tv;
3366  DetectEngineThreadCtx *det_ctx = NULL;
3367  DetectEngineCtx *de_ctx = NULL;
3369 
3370  memset(&tv, 0, sizeof(ThreadVars));
3372  memset(&ssn, 0, sizeof(TcpSession));
3373 
3374  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3375 
3376  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3377  if (f == NULL)
3378  goto end;
3379  f->protoctx = &ssn;
3380  f->proto = IPPROTO_TCP;
3381  p->flow = f;
3385  f->alproto = ALPROTO_HTTP1;
3386 
3387  StreamTcpInitConfig(true);
3388 
3390  if (de_ctx == NULL) {
3391  goto end;
3392  }
3393  de_ctx->flags |= DE_QUIET;
3394 
3395  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3396  "(msg:\"Test content option\"; "
3397  "sid:1;)");
3398  if (s == NULL) {
3399  goto end;
3400  }
3401 
3403  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3404 
3405  int r = AppLayerParserParse(
3406  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3407  if (r != 0) {
3408  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3409  goto end;
3410  }
3411 
3412  http_state = f->alstate;
3413  if (http_state == NULL) {
3414  printf("no http state: ");
3415  goto end;
3416  }
3417 
3418  /* do detect */
3419  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3420 
3421  if (PacketAlertCheck(p, 1)) {
3422  printf("sig 1 alerted, but it should not (it's not ftp): ");
3423  goto end;
3424  }
3425 
3426  result = 1;
3427  end:
3428  UTHFreePackets(&p, 1);
3429  UTHFreeFlow(f);
3430  if (alp_tctx != NULL)
3432  if (det_ctx != NULL)
3433  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3434  if (de_ctx != NULL)
3436  StreamTcpFreeConfig(true);
3438  return result;
3439 }
3440 
3441 /** \test test if the engine detect the proto and doesn't match
3442  * because the packet has another proto (ex ftp) */
3443 static int AppLayerProtoDetectTest19(void)
3444 {
3445  int result = 0;
3446  Flow *f = NULL;
3447  uint8_t http_buf1[] = "MPUT one\r\n";
3448  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3449  TcpSession ssn;
3450  Packet *p = NULL;
3451  Signature *s = NULL;
3452  ThreadVars tv;
3453  DetectEngineThreadCtx *det_ctx = NULL;
3454  DetectEngineCtx *de_ctx = NULL;
3456 
3457  memset(&tv, 0, sizeof(ThreadVars));
3459  memset(&ssn, 0, sizeof(TcpSession));
3460 
3461  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3462 
3463  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3464  if (f == NULL)
3465  goto end;
3466  f->protoctx = &ssn;
3467  f->proto = IPPROTO_TCP;
3468  p->flow = f;
3472  f->alproto = ALPROTO_FTP;
3473 
3474  StreamTcpInitConfig(true);
3475 
3477  if (de_ctx == NULL) {
3478  goto end;
3479  }
3480  de_ctx->flags |= DE_QUIET;
3481 
3482  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3483  "(msg:\"http over non standar port\"; "
3484  "sid:1;)");
3485  if (s == NULL) {
3486  goto end;
3487  }
3488 
3490  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3491 
3492  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3493  STREAM_TOSERVER, http_buf1, http_buf1_len);
3494  if (r != 0) {
3495  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3496  goto end;
3497  }
3498 
3499  /* do detect */
3500  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3501 
3502  if (PacketAlertCheck(p, 1)) {
3503  printf("sig 1 alerted, but it should not (it's ftp): ");
3504  goto end;
3505  }
3506 
3507  result = 1;
3508 
3509  end:
3510  UTHFreePackets(&p, 1);
3511  UTHFreeFlow(f);
3512  if (alp_tctx != NULL)
3514  if (det_ctx != NULL)
3515  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3516  if (de_ctx != NULL)
3518  StreamTcpFreeConfig(true);
3520  return result;
3521 }
3522 
3524 {
3525  SCEnter();
3526 
3527  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3528  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3529  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3530  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3531  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3532  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3533  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3534  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3535  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3536  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3537  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3538  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3539  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3540  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3541  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3542  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3543  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3544  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3545  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3546 
3547  SCReturn;
3548 }
3549 
3550 #endif /* UNITTESTS */
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:195
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2872
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:2160
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
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:282
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:2152
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2865
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:41
ctx
struct Thresholds ctx
ALPROTO_IRC
@ ALPROTO_IRC
Definition: app-layer-protos.h:45
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:933
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:2634
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2041
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:1817
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
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:66
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:2868
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:2866
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:2418
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:1859
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:532
stream_config
TcpStreamCnf stream_config
Definition: stream-tcp.c:227
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:367
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:2884
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:1957
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:496
UTHBuildFlow
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Definition: util-unittest-helper.c:497
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
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:69
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:19
AppLayerProtoDetectProbingParserElement_::ProbingParserTs
ProbingParserFPtr ProbingParserTs
Definition: app-layer-detect-proto.c:76
g_alproto_max
AppProto g_alproto_max
Definition: app-layer-protos.c:30
FLOW_IS_PP_DONE
#define FLOW_IS_PP_DONE(f, dir)
Definition: flow.h:271
DetectEngineThreadCtx_
Definition: detect.h:1245
BIT_U32
#define BIT_U32(n)
Definition: suricata-common.h:417
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:38
AppProtoDetectListNames
void AppProtoDetectListNames(void)
Definition: app-layer-detect-proto.c:1699
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:24
StringToAppProto
AppProto StringToAppProto(const char *proto_name)
Maps a string to its ALPROTO_* equivalent.
Definition: app-layer-protos.c:61
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:284
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:3364
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:1869
detect-engine-port.h
AppLayerProtoDetectPPTestDataPort_::toserver_element
AppLayerProtoDetectPPTestDataElement * toserver_element
Definition: app-layer-detect-proto.c:2877
alpd_tctx
AppLayerProtoDetectThreadCtx * alpd_tctx
Definition: fuzz_applayerprotodetectgetproto.c:23
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:3105
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:2888
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
SigIntId
#define SigIntId
Definition: detect-engine-state.h:38
SCReturn
#define SCReturn
Definition: util-debug.h:286
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:2878
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:290
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:2133
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2880
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:300
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:1757
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:2874
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:2873
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:274
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:2194
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:410
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1249
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:502
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:867
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:1277
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:2885
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:1718
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:3601
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:517
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:942
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:1848
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:33
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:2103
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:3523
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:2869
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:1962
FLOW_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:67
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2061
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:274
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:2595
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
SCReturnCT
#define SCReturnCT(x, type)
Definition: util-debug.h:298
AppLayerProtoDetectRegisterAlias
void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_alias)
Definition: app-layer-detect-proto.c:1777
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:1887
AppLayerProtoDetectPPTestDataPort_::ts_no_of_element
int ts_no_of_element
Definition: app-layer-detect-proto.c:2879
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:2015
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:944
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:935
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:60
DetectContentParseEncloseQuotes
DetectContentData * DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr)
Definition: detect-content.c:248
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
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:121
AppLayerProtoDetectPPTestDataElement_::port
uint16_t port
Definition: app-layer-detect-proto.c:2867
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
SCConfNode_
Definition: conf.h:37
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1345
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:2875
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:768
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:2887
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2086
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:2864