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