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