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