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