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