Commit message: proto/detect: workaround dns misdetected as dcerpc

The DCERPC UDP detection would misfire on DNS with transaction
ID 0x0400. This would happen as the protocol detection engine
gives preference to pattern based detection over probing parsers for
performance reasons.

This hack/workaround fixes this specific case by still running the
probing parser if DCERPC has been detected on UDP. The probing
parser result will take precedence.

Bug #2736.
CVE: CVE-2019-1010251
CWE: CWE-20
Vulnerability description: Open Information Security Foundation Suricata prior to version 4.1.2 is affected by: Denial of Service - DNS detection bypass. The impact is: An attacker can evade a signature detection with a specialy formed network packet. The component is: app-layer-detect-proto.c, decode.c, decode-teredo.c and decode-ipv6.c (https://github.com/OISF/suricata/pull/3590/commits/11f3659f64a4e42e90cb3c09fcef66894205aefe, https://github.com/OISF/suricata/pull/3590/commits/8357ef3f8ffc7d99ef6571350724160de356158b). The attack vector is: An attacker can trigger the vulnerability by sending a specifically crafted network request. The fixed version is: 4.1.2.

Project: suricata
File: app-layer-detect-proto.c

int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto,
                                                 const char *alproto)
{
    SCEnter();

    BUG_ON(ipproto == NULL || alproto == NULL);

    int enabled = 1;
    char param[100];
    ConfNode *node;
    int r;

#ifdef AFLFUZZ_APPLAYER
    goto enabled;
#endif
    if (RunmodeIsUnittests())
        goto enabled;

    r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
                 alproto, ".enabled");
    if (r < 0) {
        SCLogError(SC_ERR_FATAL, "snprintf failure.");
        exit(EXIT_FAILURE);
    } else if (r > (int)sizeof(param)) {
        SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
        exit(EXIT_FAILURE);
    }

    node = ConfGetNode(param);
    if (node == NULL) {
        SCLogDebug("Entry for %s not found.", param);
        r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
                     alproto, ".", ipproto, ".enabled");
        if (r < 0) {
            SCLogError(SC_ERR_FATAL, "snprintf failure.");
            exit(EXIT_FAILURE);
        } else if (r > (int)sizeof(param)) {
            SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
            exit(EXIT_FAILURE);
        }

        node = ConfGetNode(param);
        if (node == NULL) {
            SCLogDebug("Entry for %s not found.", param);
            goto enabled;
        }
    }

    if (node->val) {
        if (ConfValIsTrue(node->val)) {
            goto enabled;
        } else if (ConfValIsFalse(node->val)) {
            goto disabled;
        } else if (strcasecmp(node->val, "detection-only") == 0) {
            goto enabled;
        }
    }

    /* Invalid or null value. */
    SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
    exit(EXIT_FAILURE);

 disabled:
    enabled = 0;
 enabled:
    SCReturnInt(enabled);
}

Project: suricata
File: app-layer-detect-proto.c

int AppLayerProtoDetectDeSetup(void)
{
    SCEnter();

    int ipproto_map = 0;
    int dir = 0;
    PatIntId id = 0;
    AppLayerProtoDetectPMCtx *pm_ctx = NULL;
    AppLayerProtoDetectPMSignature *sig = NULL;

    for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
        for (dir = 0; dir < 2; dir++) {
            pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
            mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
            for (id = 0; id < pm_ctx->max_sig_id; id++) {
                sig = pm_ctx->map[id];
                AppLayerProtoDetectPMFreeSignature(sig);
            }
        }
    }

    SpmDestroyGlobalThreadCtx(alpd_ctx.spm_global_thread_ctx);

    AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);

    SCReturnInt(0);
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx *alpd_tctx)
{
    SCEnter();

    MpmCtx *mpm_ctx;
    MpmThreadCtx *mpm_tctx;
    int ipproto_map, dir;

    for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
        for (dir = 0; dir < 2; dir++) {
            mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
            mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
            mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
        }
    }
    PmqFree(&alpd_tctx->pmq);
    if (alpd_tctx->spm_thread_ctx != NULL) {
        SpmDestroyThreadCtx(alpd_tctx->spm_thread_ctx);
    }
    SCFree(alpd_tctx);

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
{
    SCEnter();

    AppLayerProtoDetectProbingParser *tmp_pp = NULL;

    if (pp == NULL)
        goto end;

    while (pp != NULL) {
        tmp_pp = pp->next;
        AppLayerProtoDetectProbingParserFree(pp);
        pp = tmp_pp;
    }

 end:
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

AppLayerProtoDetectThreadCtx *AppLayerProtoDetectGetCtxThread(void)
{
    SCEnter();

    AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
    MpmCtx *mpm_ctx;
    MpmThreadCtx *mpm_tctx;
    int i, j;
    PatIntId max_pat_id = 0;

    for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
        for (j = 0; j < 2; j++) {
            if (max_pat_id == 0) {
                max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;

            } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
                    max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
            {
                max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
            }
        }
    }

    alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
    if (alpd_tctx == NULL)
        goto error;
    memset(alpd_tctx, 0, sizeof(*alpd_tctx));

    /* Get the max pat id for all the mpm ctxs. */
    if (PmqSetup(&alpd_tctx->pmq) < 0)
        goto error;

    for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
        for (j = 0; j < 2; j++) {
            mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
            mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
            mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx);
        }
    }

    alpd_tctx->spm_thread_ctx = SpmMakeThreadCtx(alpd_ctx.spm_global_thread_ctx);
    if (alpd_tctx->spm_thread_ctx == NULL) {
        goto error;
    }

    goto end;
 error:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    alpd_tctx = NULL;
 end:
    SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
}

Project: suricata
File: app-layer-detect-proto.c

static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser *pp,
                                                                                  uint8_t ipproto,
                                                                                  uint16_t port)
{
    AppLayerProtoDetectProbingParserPort *pp_port = NULL;

    while (pp != NULL) {
        if (pp->ipproto == ipproto)
            break;

        pp = pp->next;
    }

    if (pp == NULL)
        goto end;

    pp_port = pp->port;
    while (pp_port != NULL) {
        if (pp_port->port == port || pp_port->port == 0) {
            break;
        }
        pp_port = pp_port->next;
    }

 end:
    SCReturnPtr(pp_port, "AppLayerProtoDetectProbingParserPort *");
}

Project: suricata
File: app-layer-detect-proto.c

AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
{
    SCEnter();

    AppProto a;
    for (a = 0; a < ALPROTO_MAX; a++) {
        if (alpd_ctx.alproto_names[a] != NULL &&
            strlen(alpd_ctx.alproto_names[a]) == strlen(alproto_name) &&
            (SCMemcmp(alpd_ctx.alproto_names[a], alproto_name, strlen(alproto_name)) == 0))
        {
            SCReturnCT(a, "AppProto");
        }
    }

    SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
}

Project: suricata
File: app-layer-detect-proto.c

const char *AppLayerProtoDetectGetProtoName(AppProto alproto)
{
    return alpd_ctx.alproto_names[alproto];
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
                                                             uint8_t ipproto,
                                                             uint16_t port,
                                                             AppProto alproto,
                                                             uint16_t min_depth, uint16_t max_depth,
                                                             uint8_t direction,
                                                             ProbingParserFPtr ProbingParser1,
                                                             ProbingParserFPtr ProbingParser2)
{
    SCEnter();

    /* get the top level ipproto pp */
    AppLayerProtoDetectProbingParser *curr_pp = *pp;
    while (curr_pp != NULL) {
        if (curr_pp->ipproto == ipproto)
            break;
        curr_pp = curr_pp->next;
    }
    if (curr_pp == NULL) {
        AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
        new_pp->ipproto = ipproto;
        AppLayerProtoDetectProbingParserAppend(pp, new_pp);
        curr_pp = new_pp;
    }

    /* get the top level port pp */
    AppLayerProtoDetectProbingParserPort *curr_port = curr_pp->port;
    while (curr_port != NULL) {
        if (curr_port->port == port)
            break;
        curr_port = curr_port->next;
    }
    if (curr_port == NULL) {
        AppLayerProtoDetectProbingParserPort *new_port = AppLayerProtoDetectProbingParserPortAlloc();
        new_port->port = port;
        AppLayerProtoDetectProbingParserPortAppend(&curr_pp->port, new_port);
        curr_port = new_port;
        if (direction & STREAM_TOSERVER) {
            curr_port->dp_max_depth = max_depth;
        } else {
            curr_port->sp_max_depth = max_depth;
        }

        AppLayerProtoDetectProbingParserPort *zero_port;

        zero_port = curr_pp->port;
        while (zero_port != NULL && zero_port->port != 0) {
            zero_port = zero_port->next;
        }
        if (zero_port != NULL) {
            AppLayerProtoDetectProbingParserElement *zero_pe;

            zero_pe = zero_port->dp;
            for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
                if (curr_port->dp == NULL)
                    curr_port->dp_max_depth = zero_pe->max_depth;
                if (zero_pe->max_depth == 0)
                    curr_port->dp_max_depth = zero_pe->max_depth;
                if (curr_port->dp_max_depth != 0 &&
                    curr_port->dp_max_depth < zero_pe->max_depth) {
                    curr_port->dp_max_depth = zero_pe->max_depth;
                }

                AppLayerProtoDetectProbingParserElement *dup_pe =
                    AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
                AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
                curr_port->alproto_mask |= dup_pe->alproto_mask;
            }

            zero_pe = zero_port->sp;
            for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
                if (curr_port->sp == NULL)
                    curr_port->sp_max_depth = zero_pe->max_depth;
                if (zero_pe->max_depth == 0)
                    curr_port->sp_max_depth = zero_pe->max_depth;
                if (curr_port->sp_max_depth != 0 &&
                    curr_port->sp_max_depth < zero_pe->max_depth) {
                    curr_port->sp_max_depth = zero_pe->max_depth;
                }

                AppLayerProtoDetectProbingParserElement *dup_pe =
                    AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
                AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
                curr_port->alproto_mask |= dup_pe->alproto_mask;
            }
        } /* if (zero_port != NULL) */
    } /* if (curr_port == NULL) */

    /* insert the pe_pp */
    AppLayerProtoDetectProbingParserElement *curr_pe;
    if (direction & STREAM_TOSERVER)
        curr_pe = curr_port->dp;
    else
        curr_pe = curr_port->sp;
    while (curr_pe != NULL) {
        if (curr_pe->alproto == alproto) {
            SCLogError(SC_ERR_ALPARSER, "Duplicate pp registered - "
                       "ipproto - %"PRIu8" Port - %"PRIu16" "
                       "App Protocol - NULL, App Protocol(ID) - "
                       "%"PRIu16" min_depth - %"PRIu16" "
                       "max_dept - %"PRIu16".",
                       ipproto, port, alproto,
                       min_depth, max_depth);
            goto error;
        }
        curr_pe = curr_pe->next;
    }
    /* Get a new parser element */
    AppLayerProtoDetectProbingParserElement *new_pe =
        AppLayerProtoDetectProbingParserElementCreate(alproto,
                                                      curr_port->port,
                                                      min_depth, max_depth);
    if (new_pe == NULL)
        goto error;
    curr_pe = new_pe;
    AppLayerProtoDetectProbingParserElement **head_pe;
    if (direction & STREAM_TOSERVER) {
        curr_pe->ProbingParserTs = ProbingParser1;
        curr_pe->ProbingParserTc = ProbingParser2;
        if (curr_port->dp == NULL)
            curr_port->dp_max_depth = new_pe->max_depth;
        if (new_pe->max_depth == 0)
            curr_port->dp_max_depth = new_pe->max_depth;
        if (curr_port->dp_max_depth != 0 &&
            curr_port->dp_max_depth < new_pe->max_depth) {
            curr_port->dp_max_depth = new_pe->max_depth;
        }
        curr_port->alproto_mask |= new_pe->alproto_mask;
        head_pe = &curr_port->dp;
    } else {
        curr_pe->ProbingParserTs = ProbingParser2;
        curr_pe->ProbingParserTc = ProbingParser1;
        if (curr_port->sp == NULL)
            curr_port->sp_max_depth = new_pe->max_depth;
        if (new_pe->max_depth == 0)
            curr_port->sp_max_depth = new_pe->max_depth;
        if (curr_port->sp_max_depth != 0 &&
            curr_port->sp_max_depth < new_pe->max_depth) {
            curr_port->sp_max_depth = new_pe->max_depth;
        }
        curr_port->alproto_mask |= new_pe->alproto_mask;
        head_pe = &curr_port->sp;
    }
    AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);

    if (curr_port->port == 0) {
        AppLayerProtoDetectProbingParserPort *temp_port = curr_pp->port;
        while (temp_port != NULL && temp_port->port != 0) {
            if (direction & STREAM_TOSERVER) {
                if (temp_port->dp == NULL)
                    temp_port->dp_max_depth = curr_pe->max_depth;
                if (curr_pe->max_depth == 0)
                    temp_port->dp_max_depth = curr_pe->max_depth;
                if (temp_port->dp_max_depth != 0 &&
                    temp_port->dp_max_depth < curr_pe->max_depth) {
                    temp_port->dp_max_depth = curr_pe->max_depth;
                }
                AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
                                                              AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
                temp_port->alproto_mask |= curr_pe->alproto_mask;
            } else {
                if (temp_port->sp == NULL)
                    temp_port->sp_max_depth = curr_pe->max_depth;
                if (curr_pe->max_depth == 0)
                    temp_port->sp_max_depth = curr_pe->max_depth;
                if (temp_port->sp_max_depth != 0 &&
                    temp_port->sp_max_depth < curr_pe->max_depth) {
                    temp_port->sp_max_depth = curr_pe->max_depth;
                }
                AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
                                                              AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
                temp_port->alproto_mask |= curr_pe->alproto_mask;
            }
            temp_port = temp_port->next;
        } /* while */
    } /* if */

 error:
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
                                             uint8_t *ipprotos)
{
    if (expectation_proto[alproto] == IPPROTO_TCP) {
        ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
    }
    if (expectation_proto[alproto] == IPPROTO_UDP) {
        ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
    }
}

Project: suricata
File: app-layer-detect-proto.c

static AppProto AppLayerProtoDetectPEGetProto(Flow *f, uint8_t ipproto,
                                              uint8_t direction)
{
    AppProto alproto = ALPROTO_UNKNOWN;

    SCLogDebug("expectation check for %p (dir %d)", f, direction);
    FLOW_SET_PE_DONE(f, direction);

    alproto = AppLayerExpectationHandle(f, direction);

    return alproto;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx *ctx, DetectContentData *cd,
                                             AppProto alproto)
{
    SCEnter();

    int ret = 0;
    AppLayerProtoDetectPMSignature *s = SCMalloc(sizeof(*s));
    if (unlikely(s == NULL))
        goto error;
    memset(s, 0, sizeof(*s));

    s->alproto = alproto;
    s->cd = cd;

    /* prepend to the list */
    s->next = ctx->head;
    ctx->head = s;

    goto end;
 error:
    ret = -1;
 end:
    SCReturnInt(ret);
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
{
    SCEnter();
    if (sig == NULL)
        SCReturn;
    if (sig->cd)
        DetectContentFree(sig->cd);
    SCFree(sig);
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static AppProto AppLayerProtoDetectPMGetProto(AppLayerProtoDetectThreadCtx *tctx,
                                              Flow *f,
                                              uint8_t *buf, uint16_t buflen,
                                              uint8_t direction,
                                              uint8_t ipproto,
                                              AppProto *pm_results)
{
    SCEnter();

    pm_results[0] = ALPROTO_UNKNOWN;

    AppLayerProtoDetectPMCtx *pm_ctx;
    MpmThreadCtx *mpm_tctx;
    uint16_t pm_matches = 0;
    uint8_t cnt;
    uint16_t searchlen;

    if (f->protomap >= FLOW_PROTO_DEFAULT)
        return ALPROTO_UNKNOWN;

    if (direction & STREAM_TOSERVER) {
        pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
        mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
    } else {
        pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
        mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
    }
    if (pm_ctx->mpm_ctx.pattern_cnt == 0)
        goto end;

    searchlen = buflen;
    if (searchlen > pm_ctx->max_len)
        searchlen = pm_ctx->max_len;

    uint32_t search_cnt = 0;

    /* do the mpm search */
    search_cnt = mpm_table[pm_ctx->mpm_ctx.mpm_type].Search(&pm_ctx->mpm_ctx,
                                                            mpm_tctx,
                                                            &tctx->pmq,
                                                            buf, searchlen);
    if (search_cnt == 0)
        goto end;

    /* alproto bit field */
    uint8_t pm_results_bf[(ALPROTO_MAX / 8) + 1];
    memset(pm_results_bf, 0, sizeof(pm_results_bf));

    /* loop through unique pattern id's. Can't use search_cnt here,
     * as that contains all matches, tctx->pmq.pattern_id_array_cnt
     * contains only *unique* matches. */
    for (cnt = 0; cnt < tctx->pmq.rule_id_array_cnt; cnt++) {
        const AppLayerProtoDetectPMSignature *s = pm_ctx->map[tctx->pmq.rule_id_array[cnt]];
        while (s != NULL) {
            AppProto proto = AppLayerProtoDetectPMMatchSignature(s,
                    tctx, buf, searchlen, ipproto);

            /* store each unique proto once */
            if (proto != ALPROTO_UNKNOWN &&
                !(pm_results_bf[proto / 8] & (1 << (proto % 8))) )
            {
                pm_results[pm_matches++] = proto;
                pm_results_bf[proto / 8] |= 1 << (proto % 8);
            }
            s = s->next;
        }
    }

 end:
    PmqReset(&tctx->pmq);
    if (buflen >= pm_ctx->max_len)
        FLOW_SET_PM_DONE(f, direction);
    SCReturnUInt(pm_matches);
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
{
    SCEnter();

    int ret = 0;
    AppLayerProtoDetectPMSignature *s, *next_s;
    int mpm_ret;
    SigIntId id = 0;

    ctx->map = SCMalloc(ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
    if (ctx->map == NULL)
        goto error;
    memset(ctx->map, 0, ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));

    /* add an array indexed by rule id to look up the sig */
    for (s = ctx->head; s != NULL; ) {
        next_s = s->next;
        s->id = id++;
        SCLogDebug("s->id %u", s->id);

        if (s->cd->flags & DETECT_CONTENT_NOCASE) {
            mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
                                      s->cd->content, s->cd->content_len,
                                      0, 0, s->cd->id, s->id, 0);
            if (mpm_ret < 0)
                goto error;
        } else {
            mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
                                      s->cd->content, s->cd->content_len,
                                      0, 0, s->cd->id, s->id, 0);
            if (mpm_ret < 0)
                goto error;
        }

        ctx->map[s->id] = s;
        s->next = NULL;
        s = next_s;
    }
    ctx->head = NULL;

    goto end;
 error:
    ret = -1;
 end:
    SCReturnInt(ret);
}

Project: suricata
File: app-layer-detect-proto.c

static AppProto AppLayerProtoDetectPMMatchSignature(const AppLayerProtoDetectPMSignature *s,
                                                    AppLayerProtoDetectThreadCtx *tctx,
                                                    uint8_t *buf, uint16_t buflen,
                                                    uint8_t ipproto)
{
    SCEnter();
    AppProto proto = ALPROTO_UNKNOWN;
    uint8_t *found = NULL;

    if (s->cd->offset > buflen) {
        SCLogDebug("s->co->offset (%"PRIu16") > buflen (%"PRIu16")",
                   s->cd->offset, buflen);
        goto end;
    }

    if (s->cd->depth > buflen) {
        SCLogDebug("s->co->depth (%"PRIu16") > buflen (%"PRIu16")",
                   s->cd->depth, buflen);
        goto end;
    }

    uint8_t *sbuf = buf + s->cd->offset;
    uint16_t sbuflen = s->cd->depth - s->cd->offset;
    SCLogDebug("s->co->offset (%"PRIu16") s->cd->depth (%"PRIu16")",
               s->cd->offset, s->cd->depth);

    found = SpmScan(s->cd->spm_ctx, tctx->spm_thread_ctx, sbuf, sbuflen);
    if (found != NULL)
        proto = s->alproto;

 end:
    SCReturnUInt(proto);
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
                                                const char *pattern,
                                                uint16_t depth, uint16_t offset,
                                                uint8_t direction,
                                                uint8_t is_cs)
{
    SCEnter();

    AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
    AppLayerProtoDetectPMCtx *ctx_pm = NULL;
    DetectContentData *cd;
    int ret = 0;

    cd = DetectContentParseEncloseQuotes(alpd_ctx.spm_global_thread_ctx,
                                         pattern);
    if (cd == NULL)
        goto error;
    cd->depth = depth;
    cd->offset = offset;
    if (!is_cs) {
        /* Rebuild as nocase */
        SpmDestroyCtx(cd->spm_ctx);
        cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1,
                                 alpd_ctx.spm_global_thread_ctx);
        if (cd->spm_ctx == NULL) {
            goto error;
        }
        cd->flags |= DETECT_CONTENT_NOCASE;
    }
    if (depth < cd->content_len)
        goto error;

    if (direction & STREAM_TOSERVER)
        ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
    else
        ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];

    if (depth > ctx_pm->max_len)
        ctx_pm->max_len = depth;
    if (depth < ctx_pm->min_len)
        ctx_pm->min_len = depth;

    /* Finally turn it into a signature and add to the ctx. */
    AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto);

    goto end;
 error:
    ret = -1;
 end:
    SCReturnInt(ret);
}

Project: suricata
File: app-layer-detect-proto.c

int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto,
                                           const char *pattern,
                                           uint16_t depth, uint16_t offset,
                                           uint8_t direction)
{
    SCEnter();
    int r = 0;
    r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
                                                     pattern,
                                                     depth, offset,
                                                     direction,
                                                     0 /* !case-sensitive */);
    SCReturnInt(r);
}

Project: suricata
File: app-layer-detect-proto.c

int AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto, AppProto alproto,
                                           const char *pattern,
                                           uint16_t depth, uint16_t offset,
                                           uint8_t direction)
{
    SCEnter();
    int r = 0;
    r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
                                                     pattern,
                                                     depth, offset,
                                                     direction,
                                                     1 /* case-sensitive */);
    SCReturnInt(r);
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
{
    SCEnter();

    typedef struct TempContainer_ {
        PatIntId id;
        uint16_t content_len;
        uint8_t *content;
    } TempContainer;

    AppLayerProtoDetectPMSignature *s = NULL;
    uint32_t struct_total_size = 0;
    uint32_t content_total_size = 0;
    /* array hash buffer */
    uint8_t *ahb = NULL;
    uint8_t *content = NULL;
    uint8_t content_len = 0;
    PatIntId max_id = 0;
    TempContainer *struct_offset = NULL;
    uint8_t *content_offset = NULL;
    int ret = 0;

    if (ctx->head == NULL)
        goto end;

    for (s = ctx->head; s != NULL; s = s->next) {
        struct_total_size += sizeof(TempContainer);
        content_total_size += s->cd->content_len;
        ctx->max_sig_id++;
    }

    ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
    if (unlikely(ahb == NULL))
        goto error;

    struct_offset = (TempContainer *)ahb;
    content_offset = ahb + struct_total_size;
    for (s = ctx->head; s != NULL; s = s->next) {
        TempContainer *tcdup = (TempContainer *)ahb;
        content = s->cd->content;
        content_len = s->cd->content_len;

        for (; tcdup != struct_offset; tcdup++) {
            if (tcdup->content_len != content_len ||
                SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
            {
                continue;
            }
            break;
        }

        if (tcdup != struct_offset) {
            s->cd->id = tcdup->id;
            continue;
        }

        struct_offset->content_len = content_len;
        struct_offset->content = content_offset;
        content_offset += content_len;
        memcpy(struct_offset->content, content, content_len);
        struct_offset->id = max_id++;
        s->cd->id = struct_offset->id;

        struct_offset++;
    }

    ctx->max_pat_id = max_id;

    goto end;
 error:
    ret = -1;
 end:
    if (ahb != NULL)
        SCFree(ahb);
    SCReturnInt(ret);
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectPPGetIpprotos(AppProto alproto,
                                             uint8_t *ipprotos)
{
    SCEnter();

    const AppLayerProtoDetectProbingParser *pp;
    const AppLayerProtoDetectProbingParserPort *pp_port;
    const AppLayerProtoDetectProbingParserElement *pp_pe;

    for (pp = alpd_ctx.ctx_pp; pp != NULL; pp = pp->next) {
        for (pp_port = pp->port; pp_port != NULL; pp_port = pp_port->next) {
            for (pp_pe = pp_port->dp; pp_pe != NULL; pp_pe = pp_pe->next) {
                if (alproto == pp_pe->alproto)
                    ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
            }
            for (pp_pe = pp_port->sp; pp_pe != NULL; pp_pe = pp_pe->next) {
                if (alproto == pp_pe->alproto)
                    ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
            }
        }
    }

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static AppProto AppLayerProtoDetectPPGetProto(Flow *f,
                                              uint8_t *buf, uint32_t buflen,
                                              uint8_t ipproto, uint8_t direction)
{
    const AppLayerProtoDetectProbingParserPort *pp_port_dp = NULL;
    const AppLayerProtoDetectProbingParserPort *pp_port_sp = NULL;
    const AppLayerProtoDetectProbingParserElement *pe = NULL;
    const AppLayerProtoDetectProbingParserElement *pe1 = NULL;
    const AppLayerProtoDetectProbingParserElement *pe2 = NULL;
    AppProto alproto = ALPROTO_UNKNOWN;
    uint32_t *alproto_masks;
    uint32_t mask = 0;

    const uint16_t dp = f->protodetect_dp ? f->protodetect_dp : f->dp;
    const uint16_t sp = f->sp;

    if (direction & STREAM_TOSERVER) {
        /* first try the destination port */
        pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
        alproto_masks = &f->probing_parser_toserver_alproto_masks;
        if (pp_port_dp != NULL) {
            SCLogDebug("toserver - Probing parser found for destination port %"PRIu16, dp);

            /* found based on destination port, so use dp registration */
            pe1 = pp_port_dp->dp;
        } else {
            SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16, dp);
        }

        pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
        if (pp_port_sp != NULL) {
            SCLogDebug("toserver - Probing parser found for source port %"PRIu16, sp);

            /* found based on source port, so use sp registration */
            pe2 = pp_port_sp->sp;
        } else {
            SCLogDebug("toserver - No probing parser registered for source port %"PRIu16, sp);
        }
    } else {
        /* first try the destination port */
        pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
        alproto_masks = &f->probing_parser_toclient_alproto_masks;
        if (pp_port_dp != NULL) {
            SCLogDebug("toclient - Probing parser found for destination port %"PRIu16, dp);

            /* found based on destination port, so use dp registration */
            pe1 = pp_port_dp->dp;
        } else {
            SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16, dp);
        }

        pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
        if (pp_port_sp != NULL) {
            SCLogDebug("toclient - Probing parser found for source port %"PRIu16, sp);

            pe2 = pp_port_sp->sp;
        } else {
            SCLogDebug("toclient - No probing parser registered for source port %"PRIu16, sp);
        }
    }

    if (pe1 == NULL && pe2 == NULL) {
        SCLogDebug("%s - No probing parsers found for either port",
                (direction & STREAM_TOSERVER) ? "toserver":"toclient");
        FLOW_SET_PP_DONE(f, direction);
        goto end;
    }

    /* run the parser(s) */
    pe = pe1;
    while (pe != NULL) {
        if ((buflen < pe->min_depth)  ||
            (alproto_masks[0] & pe->alproto_mask)) {
            pe = pe->next;
            continue;
        }

        if (direction & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
            alproto = pe->ProbingParserTs(f, buf, buflen);
        } else if (pe->ProbingParserTc != NULL) {
            alproto = pe->ProbingParserTc(f, buf, buflen);
        }
        if (alproto != ALPROTO_UNKNOWN && alproto != ALPROTO_FAILED)
            goto end;
        if (alproto == ALPROTO_FAILED ||
            (pe->max_depth != 0 && buflen > pe->max_depth)) {
            alproto_masks[0] |= pe->alproto_mask;
        }
        pe = pe->next;
    }
    pe = pe2;
    while (pe != NULL) {
        if ((buflen < pe->min_depth)  ||
            (alproto_masks[0] & pe->alproto_mask)) {
            pe = pe->next;
            continue;
        }

        if (direction & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
            alproto = pe->ProbingParserTs(f, buf, buflen);
        } else if (pe->ProbingParserTc != NULL) {
            alproto = pe->ProbingParserTc(f, buf, buflen);
        }
        if (alproto != ALPROTO_UNKNOWN && alproto != ALPROTO_FAILED)
            goto end;
        if (alproto == ALPROTO_FAILED ||
            (pe->max_depth != 0 && buflen > pe->max_depth)) {
            alproto_masks[0] |= pe->alproto_mask;
        }
        pe = pe->next;
    }

    /* get the mask we need for this direction */
    if (pp_port_dp && pp_port_sp)
        mask = pp_port_dp->alproto_mask|pp_port_sp->alproto_mask;
    else if (pp_port_dp)
        mask = pp_port_dp->alproto_mask;
    else if (pp_port_sp)
        mask = pp_port_sp->alproto_mask;

    if (alproto_masks[0] == mask) {
        FLOW_SET_PP_DONE(f, direction);
        SCLogDebug("%s, mask is now %08x, needed %08x, so done",
                (direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0], mask);
    } else {
        SCLogDebug("%s, mask is now %08x, need %08x",
                (direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0], mask);
    }

 end:
    SCLogDebug("%s, mask is now %08x",
            (direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
    SCReturnUInt(alproto);
}

Project: suricata
File: app-layer-detect-proto.c

int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
                                         uint8_t ipproto,
                                         const char *alproto_name,
                                         AppProto alproto,
                                         uint16_t min_depth, uint16_t max_depth,
                                         ProbingParserFPtr ProbingParserTs,
                                         ProbingParserFPtr ProbingParserTc)
{
    SCEnter();

    char param[100];
    int r;
    ConfNode *node;
    ConfNode *port_node = NULL;
    int config = 0;

    r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
                 alproto_name, ".detection-ports");
    if (r < 0) {
        SCLogError(SC_ERR_FATAL, "snprintf failure.");
        exit(EXIT_FAILURE);
    } else if (r > (int)sizeof(param)) {
        SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
        exit(EXIT_FAILURE);
    }
    node = ConfGetNode(param);
    if (node == NULL) {
        SCLogDebug("Entry for %s not found.", param);
        r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
                     alproto_name, ".", ipproto_name, ".detection-ports");
        if (r < 0) {
            SCLogError(SC_ERR_FATAL, "snprintf failure.");
            exit(EXIT_FAILURE);
        } else if (r > (int)sizeof(param)) {
            SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
            exit(EXIT_FAILURE);
        }
        node = ConfGetNode(param);
        if (node == NULL)
            goto end;
    }

    /* detect by destination port of the flow (e.g. port 53 for DNS) */
    port_node = ConfNodeLookupChild(node, "dp");
    if (port_node == NULL)
        port_node = ConfNodeLookupChild(node, "toserver");

    if (port_node != NULL && port_node->val != NULL) {
        AppLayerProtoDetectPPRegister(ipproto,
                                      port_node->val,
                                      alproto,
                                      min_depth, max_depth,
                                      STREAM_TOSERVER, /* to indicate dp */
                                      ProbingParserTs, ProbingParserTc);
    }

    /* detect by source port of flow */
    port_node = ConfNodeLookupChild(node, "sp");
    if (port_node == NULL)
        port_node = ConfNodeLookupChild(node, "toclient");

    if (port_node != NULL && port_node->val != NULL) {
        AppLayerProtoDetectPPRegister(ipproto,
                                      port_node->val,
                                      alproto,
                                      min_depth, max_depth,
                                      STREAM_TOCLIENT, /* to indicate sp */
                                      ProbingParserTc, ProbingParserTs);

    }

    config = 1;
 end:
    SCReturnInt(config);
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectPPRegister(uint8_t ipproto,
                                   const char *portstr,
                                   AppProto alproto,
                                   uint16_t min_depth, uint16_t max_depth,
                                   uint8_t direction,
                                   ProbingParserFPtr ProbingParser1,
                                   ProbingParserFPtr ProbingParser2)
{
    SCEnter();

    DetectPort *head = NULL;
    DetectPortParse(NULL,&head, portstr);
    DetectPort *temp_dp = head;
    while (temp_dp != NULL) {
        uint32_t port = temp_dp->port;
        if (port == 0 && temp_dp->port2 != 0)
            port++;
        for ( ; port <= temp_dp->port2; port++) {
            AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
                                                      ipproto,
                                                      port,
                                                      alproto,
                                                      min_depth, max_depth,
                                                      direction,
                                                      ProbingParser1,
                                                      ProbingParser2);
        }
        temp_dp = temp_dp->next;
    }
    DetectPortCleanupList(NULL,head);

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
                                         AppLayerProtoDetectPPTestDataIPProto *ip_proto,
                                         int no_of_ip_proto)
{
    int result = 0;
    int i = -1, j = -1 , k = -1;
#ifdef DEBUG
    int dir = 0;
#endif
    for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
        if (pp->ipproto != ip_proto[i].ipproto)
            goto end;

        AppLayerProtoDetectProbingParserPort *pp_port = pp->port;
        for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
            if (pp_port->port != ip_proto[i].port[k].port)
                goto end;
            if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
                goto end;
            if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
                goto end;
            if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
                goto end;
            if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
                goto end;

            AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
#ifdef DEBUG
            dir = 0;
#endif
            for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
                 j++, pp_element = pp_element->next) {

                if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
                    goto end;
                }
                if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
                    goto end;
                }
                if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
                    goto end;
                }
                if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
                    goto end;
                }
                if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
                    goto end;
                }
            } /* for */
            if (pp_element != NULL)
                goto end;

            pp_element = pp_port->sp;
#ifdef DEBUG
            dir = 1;
#endif
            for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
                if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
                    goto end;
                }
                if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
                    goto end;
                }
                if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
                    goto end;
                }
                if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
                    goto end;
                }
                if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
                    goto end;
                }
            } /* for */
            if (pp_element != NULL)
                goto end;
        }
        if (pp_port != NULL)
            goto end;
    }
    if (pp != NULL)
        goto end;

    result = 1;
 end:
#ifdef DEBUG
    printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
#endif
    return result;
}

Project: suricata
File: app-layer-detect-proto.c

int AppLayerProtoDetectPrepareState(void)
{
    SCEnter();

    AppLayerProtoDetectPMCtx *ctx_pm;
    int i, j;
    int ret = 0;

    for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
        for (j = 0; j < 2; j++) {
            ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];

            if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
                goto error;

            if (ctx_pm->max_sig_id == 0)
                continue;

            if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
                goto error;
            if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
                goto error;
        }
    }

#ifdef DEBUG
    if (SCLogDebugEnabled()) {
        AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
    }
#endif

    goto end;
 error:
    ret = -1;
 end:
    SCReturnInt(ret);
}

Project: suricata
File: app-layer-detect-proto.c

static AppLayerProtoDetectProbingParser *AppLayerProtoDetectProbingParserAlloc(void)
{
    SCEnter();

    AppLayerProtoDetectProbingParser *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParser));
    if (unlikely(p == NULL)) {
        exit(EXIT_FAILURE);
    }
    memset(p, 0, sizeof(AppLayerProtoDetectProbingParser));

    SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
                                                   AppLayerProtoDetectProbingParser *new_pp)
{
    SCEnter();

    if (*head_pp == NULL) {
        *head_pp = new_pp;
        goto end;
    }

    AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
    while (temp_pp->next != NULL)
        temp_pp = temp_pp->next;
    temp_pp->next = new_pp;

 end:
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectProbingParserElementAlloc(void)
{
    SCEnter();

    AppLayerProtoDetectProbingParserElement *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserElement));
    if (unlikely(p == NULL)) {
        exit(EXIT_FAILURE);
    }
    memset(p, 0, sizeof(AppLayerProtoDetectProbingParserElement));

    SCReturnPtr(p, "AppLayerProtoDetectProbingParserElement");
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
                                                          AppLayerProtoDetectProbingParserElement *new_pe)
{
    SCEnter();

    if (*head_pe == NULL) {
        *head_pe = new_pe;
        goto end;
    }

    if ((*head_pe)->port == 0) {
        if (new_pe->port != 0) {
            new_pe->next = *head_pe;
            *head_pe = new_pe;
        } else {
            AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
            while (temp_pe->next != NULL)
                temp_pe = temp_pe->next;
            temp_pe->next = new_pe;
        }
    } else {
        AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
        if (new_pe->port == 0) {
            while (temp_pe->next != NULL)
                temp_pe = temp_pe->next;
            temp_pe->next = new_pe;
        } else {
            while (temp_pe->next != NULL && temp_pe->next->port != 0)
                temp_pe = temp_pe->next;
            new_pe->next = temp_pe->next;
            temp_pe->next = new_pe;

        }
    }

 end:
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
                                              uint16_t port,
                                              uint16_t min_depth,
                                              uint16_t max_depth)
{
    AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();

    pe->alproto = alproto;
    pe->port = port;
    pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
    pe->min_depth = min_depth;
    pe->max_depth = max_depth;
    pe->next = NULL;

    if (max_depth != 0 && min_depth >= max_depth) {
        SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to "
                   "register the probing parser.  min_depth >= max_depth");
        goto error;
    }
    if (alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_MAX) {
        SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to register "
                   "the probing parser.  Invalid alproto - %d", alproto);
        goto error;
    }

    SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
 error:
    AppLayerProtoDetectProbingParserElementFree(pe);
    SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
}

Project: suricata
File: app-layer-detect-proto.c

AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement *pe)
{
    SCEnter();

    AppLayerProtoDetectProbingParserElement *new_pe = AppLayerProtoDetectProbingParserElementAlloc();

    new_pe->alproto = pe->alproto;
    new_pe->port = pe->port;
    new_pe->alproto_mask = pe->alproto_mask;
    new_pe->min_depth = pe->min_depth;
    new_pe->max_depth = pe->max_depth;
    new_pe->ProbingParserTs = pe->ProbingParserTs;
    new_pe->ProbingParserTc = pe->ProbingParserTc;
    new_pe->next = NULL;

    SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement *p)
{
    SCEnter();
    SCFree(p);
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser *p)
{
    SCEnter();

    AppLayerProtoDetectProbingParserPort *pt = p->port;
    while (pt != NULL) {
        AppLayerProtoDetectProbingParserPort *pt_next = pt->next;
        AppLayerProtoDetectProbingParserPortFree(pt);
        pt = pt_next;
    }

    SCFree(p);

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static uint32_t AppLayerProtoDetectProbingParserGetMask(AppProto alproto)
{
    SCEnter();

    if (!(alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_FAILED)) {
        SCLogError(SC_ERR_ALPARSER, "Unknown protocol detected - %"PRIu16,
                   alproto);
        exit(EXIT_FAILURE);
    }

    SCReturnUInt(1 << alproto);
}

Project: suricata
File: app-layer-detect-proto.c

static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectProbingParserPortAlloc(void)
{
    SCEnter();

    AppLayerProtoDetectProbingParserPort *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserPort));
    if (unlikely(p == NULL)) {
        exit(EXIT_FAILURE);
    }
    memset(p, 0, sizeof(AppLayerProtoDetectProbingParserPort));

    SCReturnPtr(p, "AppLayerProtoDetectProbingParserPort");
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
                                                       AppLayerProtoDetectProbingParserPort *new_port)
{
    SCEnter();

    if (*head_port == NULL) {
        *head_port = new_port;
        goto end;
    }

    if ((*head_port)->port == 0) {
        new_port->next = *head_port;
        *head_port = new_port;
    } else {
        AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
        while (temp_port->next != NULL && temp_port->next->port != 0) {
            temp_port = temp_port->next;
        }
        new_port->next = temp_port->next;
        temp_port->next = new_port;
    }

 end:
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static void AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort *p)
{
    SCEnter();

    AppLayerProtoDetectProbingParserElement *e;

    e = p->dp;
    while (e != NULL) {
        AppLayerProtoDetectProbingParserElement *e_next = e->next;
        AppLayerProtoDetectProbingParserElementFree(e);
        e = e_next;
    }

    e = p->sp;
    while (e != NULL) {
        AppLayerProtoDetectProbingParserElement *e_next = e->next;
        AppLayerProtoDetectProbingParserElementFree(e);
        e = e_next;
    }

    SCFree(p);

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
{
    SCEnter();

    if (alpd_ctx.alproto_names[alproto] == NULL)
        alpd_ctx.alproto_names[alproto] = alproto_name;

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectReset(Flow *f)
{
    FlowUnsetChangeProtoFlag(f);
    FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
    FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
    FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
    FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
    FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
    FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
    f->probing_parser_toserver_alproto_masks = 0;
    f->probing_parser_toclient_alproto_masks = 0;

    AppLayerParserStateCleanup(f, f->alstate, f->alparser);
    f->alstate = NULL;
    f->alparser = NULL;
    f->alproto    = ALPROTO_UNKNOWN;
    f->alproto_ts = ALPROTO_UNKNOWN;
    f->alproto_tc = ALPROTO_UNKNOWN;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
{
    SCEnter();

    memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));

    int alproto;

    for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
        if (alpd_ctx.alproto_names[alproto] != NULL)
            alprotos[alproto] = 1;
    }

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
{
    SCEnter();

    AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
    AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
    AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest02(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    int r = 0;

    const char *buf = "HTTP";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
    buf = "ftp";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_FTP\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1].alproto != ALPROTO_HTTP\n");
        goto end;
    }

    r = 1;

 end:
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest03(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
    const char *buf;
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    memset(pm_results, 0, sizeof(pm_results));

    buf = "HTTP";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
    buf = "220 ";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_FTP\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1].alproto != ALPROTO_HTTP\n");
        goto end;
    }

    uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                                 &f,
                                                 l7data, sizeof(l7data),
                                                 STREAM_TOCLIENT,
                                                 IPPROTO_TCP,
                                                 pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
        printf("cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest04(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
    const char *buf;
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    memset(pm_results, 0, sizeof(pm_results));

    buf = "200 ";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 13, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_HTTP\n");
        goto end;
    }

    uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                                 &f,
                                                 l7data, sizeof(l7data),
                                                 STREAM_TOCLIENT,
                                                 IPPROTO_TCP,
                                                 pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
        printf("cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest06(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
    const char *buf;
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    buf = "HTTP";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
    buf = "220 ";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_FTP\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1].alproto != ALPROTO_HTTP\n");
        goto end;
    }

    uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                                 &f,
                                                 l7data, sizeof(l7data),
                                                 STREAM_TOCLIENT,
                                                 IPPROTO_TCP,
                                                 pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_FTP) {
        printf("cnt != 1 && pm_results[0] != AlPROTO_FTP\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest07(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
    const char *buf;
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    memset(pm_results, 0, sizeof(pm_results));

    buf = "HTTP";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_HTTP\n");
        goto end;
    }

    uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                                 &f,
                                                 l7data, sizeof(l7data),
                                                 STREAM_TOCLIENT,
                                                 IPPROTO_TCP,
                                                 pm_results);
    if (cnt != 0) {
        printf("cnt != 0\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest08(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = {
        0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
        0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
        0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
        0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
        0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
        0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
        0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
        0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
        0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
        0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
        0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
        0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
        0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
        0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
        0x00
    };
    const char *buf;
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    memset(pm_results, 0, sizeof(pm_results));

    buf = "|ff|SMB";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_SMB) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_SMB\n");
        goto end;
    }

    uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                                 &f,
                                                 l7data, sizeof(l7data),
                                                 STREAM_TOCLIENT,
                                                 IPPROTO_TCP,
                                                 pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_SMB) {
        printf("cnt != 1 && pm_results[0] != AlPROTO_SMB\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest09(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = {
        0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
        0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x02, 0x02
    };
    const char *buf;
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    memset(pm_results, 0, sizeof(pm_results));

    buf = "|fe|SMB";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB2, buf, 8, 4, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_SMB2) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_SMB2\n");
        goto end;
    }

    uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                                 &f,
                                                 l7data, sizeof(l7data),
                                                 STREAM_TOCLIENT,
                                                 IPPROTO_TCP,
                                                 pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_SMB2) {
        printf("cnt != 1 && pm_results[0] != AlPROTO_SMB2\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest10(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = {
        0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
        0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
        0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
        0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
        0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
        0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
        0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
    };
    const char *buf;
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    memset(pm_results, 0, sizeof(pm_results));

    buf = "|05 00|";
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_DCERPC) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_DCERPC\n");
        goto end;
    }

    uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                                 &f,
                                                 l7data, sizeof(l7data),
                                                 STREAM_TOCLIENT,
                                                 IPPROTO_TCP,
                                                 pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_DCERPC) {
        printf("cnt != 1 && pm_results[0] != AlPROTO_DCERPC\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest11(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
    uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    memset(pm_results, 0, sizeof(pm_results));

    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP)
        {
            printf("failure 1\n");
            goto end;
        }

    memset(pm_results, 0, sizeof(pm_results));
    uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                                 &f,
                                                 l7data, sizeof(l7data),
                                                 STREAM_TOSERVER,
                                                 IPPROTO_TCP,
                                                 pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
        printf("l7data - cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
        goto end;
    }

    memset(pm_results, 0, sizeof(pm_results));
    cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                        &f,
                                        l7data_resp, sizeof(l7data_resp),
                                        STREAM_TOCLIENT,
                                        IPPROTO_TCP,
                                        pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
        printf("l7data_resp - cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest12(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    int r = 0;

    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
    {
        printf("failure 1\n");
        goto end;
    }

    AppLayerProtoDetectPrepareState();
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
        printf("failure 2\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
    {
        printf("failure 3\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP) {
        printf("failure 4\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
        printf("failure 5\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
        printf("failure 6\n");
        goto end;
    }

    r = 1;

 end:
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest13(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
    uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;
    uint32_t cnt;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_TCP);

    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP)
        {
            printf("failure 1\n");
            goto end;
        }

    memset(pm_results, 0, sizeof(pm_results));
    cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                        &f,
                                        l7data, sizeof(l7data),
                                        STREAM_TOSERVER,
                                        IPPROTO_TCP,
                                        pm_results);
    if (cnt != 0) {
        printf("l7data - cnt != 0\n");
        goto end;
    }

    memset(pm_results, 0, sizeof(pm_results));
    cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                        &f,
                                        l7data_resp, sizeof(l7data_resp),
                                        STREAM_TOCLIENT,
                                        IPPROTO_TCP,
                                        pm_results);
    if (cnt != 0) {
        printf("l7data_resp - cnt != 0\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest14(void)
{
    AppLayerProtoDetectUnittestCtxBackup();
    AppLayerProtoDetectSetup();

    uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
    uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
    int r = 0;
    Flow f;
    AppProto pm_results[ALPROTO_MAX];
    AppLayerProtoDetectThreadCtx *alpd_tctx;
    uint32_t cnt;

    memset(&f, 0x00, sizeof(f));
    f.protomap = FlowGetProtoMapping(IPPROTO_UDP);

    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
    AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);

    AppLayerProtoDetectPrepareState();
    /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
     * it sets internal structures which depends on the above function. */
    alpd_tctx = AppLayerProtoDetectGetCtxThread();

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7\n");
        goto end;
    }
    if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1) {
        printf("alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1\n");
        goto end;
    }

    if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP ||
        alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP)
        {
            printf("failure 1\n");
            goto end;
        }

    memset(pm_results, 0, sizeof(pm_results));
    cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                        &f,
                                        l7data, sizeof(l7data),
                                        STREAM_TOSERVER,
                                        IPPROTO_UDP,
                                        pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
        printf("l7data - cnt != 0\n");
        goto end;
    }

    memset(pm_results, 0, sizeof(pm_results));
    cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
                                        &f,
                                        l7data_resp, sizeof(l7data_resp),
                                        STREAM_TOCLIENT,
                                        IPPROTO_UDP,
                                        pm_results);
    if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
        printf("l7data_resp - cnt != 0\n");
        goto end;
    }

    r = 1;

 end:
    if (alpd_tctx != NULL)
        AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
    AppLayerProtoDetectDeSetup();
    AppLayerProtoDetectUnittestCtxRestore();
    return r;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest16(void)
{
    int result = 0;
    Flow *f = NULL;
    HtpState *http_state = NULL;
    uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
        "User-Agent: Mozilla/1.0\r\n"
        "Cookie: hellocatch\r\n\r\n";
    uint32_t http_buf1_len = sizeof(http_buf1) - 1;
    TcpSession ssn;
    Packet *p = NULL;
    Signature *s = NULL;
    ThreadVars tv;
    DetectEngineThreadCtx *det_ctx = NULL;
    DetectEngineCtx *de_ctx = NULL;
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();

    memset(&tv, 0, sizeof(ThreadVars));
    memset(&ssn, 0, sizeof(TcpSession));

    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
    if (p == NULL) {
        printf("packet setup failed: ");
        goto end;
    }

    f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
    if (f == NULL) {
        printf("flow setup failed: ");
        goto end;
    }
    f->protoctx = &ssn;
    f->proto = IPPROTO_TCP;
    p->flow = f;

    p->flowflags |= FLOW_PKT_TOSERVER;
    p->flowflags |= FLOW_PKT_ESTABLISHED;
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;

    f->alproto = ALPROTO_HTTP;

    StreamTcpInitConfig(TRUE);

    de_ctx = DetectEngineCtxInit();
    if (de_ctx == NULL) {
        goto end;
    }
    de_ctx->flags |= DE_QUIET;

    s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
                                   "(msg:\"Test content option\"; "
                                   "sid:1;)");
    if (s == NULL) {
        goto end;
    }

    SigGroupBuild(de_ctx);
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);

    FLOWLOCK_WRLOCK(f);
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
                                STREAM_TOSERVER, http_buf1, http_buf1_len);
    if (r != 0) {
        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
        FLOWLOCK_UNLOCK(f);
        goto end;
    }
    FLOWLOCK_UNLOCK(f);

    http_state = f->alstate;
    if (http_state == NULL) {
        printf("no http state: ");
        goto end;
    }

    /* do detect */
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);

    if (!PacketAlertCheck(p, 1)) {
        printf("sig 1 didn't alert, but it should: ");
        goto end;
    }
    result = 1;
 end:
    if (alp_tctx != NULL)
        AppLayerParserThreadCtxFree(alp_tctx);
    if (det_ctx != NULL)
        DetectEngineThreadCtxDeinit(&tv, det_ctx);
    if (de_ctx != NULL)
        SigGroupCleanup(de_ctx);
    if (de_ctx != NULL)
        DetectEngineCtxFree(de_ctx);

    StreamTcpFreeConfig(TRUE);

    UTHFreePackets(&p, 1);
    UTHFreeFlow(f);
    return result;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest17(void)
{
    int result = 0;
    Flow *f = NULL;
    HtpState *http_state = NULL;
    uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
        "User-Agent: Mozilla/1.0\r\n"
        "Cookie: hellocatch\r\n\r\n";
    uint32_t http_buf1_len = sizeof(http_buf1) - 1;
    TcpSession ssn;
    Packet *p = NULL;
    Signature *s = NULL;
    ThreadVars tv;
    DetectEngineThreadCtx *det_ctx = NULL;
    DetectEngineCtx *de_ctx = NULL;
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();

    memset(&tv, 0, sizeof(ThreadVars));
    memset(&ssn, 0, sizeof(TcpSession));

    p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);

    f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
    if (f == NULL)
        goto end;
    f->protoctx = &ssn;
    f->proto = IPPROTO_TCP;
    p->flow = f;
    p->flowflags |= FLOW_PKT_TOSERVER;
    p->flowflags |= FLOW_PKT_ESTABLISHED;
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
    f->alproto = ALPROTO_HTTP;

    StreamTcpInitConfig(TRUE);

    de_ctx = DetectEngineCtxInit();
    if (de_ctx == NULL) {
        goto end;
    }
    de_ctx->flags |= DE_QUIET;

    s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
                                   "(msg:\"http over non standar port\"; "
                                   "sid:1;)");
    if (s == NULL) {
        goto end;
    }

    SigGroupBuild(de_ctx);
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);

    FLOWLOCK_WRLOCK(f);
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
                                STREAM_TOSERVER, http_buf1, http_buf1_len);
    if (r != 0) {
        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
        FLOWLOCK_UNLOCK(f);
        goto end;
    }
    FLOWLOCK_UNLOCK(f);

    http_state = f->alstate;
    if (http_state == NULL) {
        printf("no http state: ");
        goto end;
    }

    /* do detect */
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);

    if (!PacketAlertCheck(p, 1)) {
        printf("sig 1 didn't alert, but it should: ");
        goto end;
    }

    result = 1;

 end:
    if (alp_tctx != NULL)
        AppLayerParserThreadCtxFree(alp_tctx);
    if (det_ctx != NULL)
        DetectEngineThreadCtxDeinit(&tv, det_ctx);
    if (de_ctx != NULL)
        SigGroupCleanup(de_ctx);
    if (de_ctx != NULL)
        DetectEngineCtxFree(de_ctx);

    StreamTcpFreeConfig(TRUE);

    UTHFreePackets(&p, 1);
    UTHFreeFlow(f);
    return result;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest18(void)
{
    int result = 0;
    Flow *f = NULL;
    HtpState *http_state = NULL;
    uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
        "User-Agent: Mozilla/1.0\r\n"
        "Cookie: hellocatch\r\n\r\n";
    uint32_t http_buf1_len = sizeof(http_buf1) - 1;
    TcpSession ssn;
    Packet *p = NULL;
    Signature *s = NULL;
    ThreadVars tv;
    DetectEngineThreadCtx *det_ctx = NULL;
    DetectEngineCtx *de_ctx = NULL;
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();

    memset(&tv, 0, sizeof(ThreadVars));
    memset(&ssn, 0, sizeof(TcpSession));

    p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);

    f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
    if (f == NULL)
        goto end;
    f->protoctx = &ssn;
    f->proto = IPPROTO_TCP;
    p->flow = f;
    p->flowflags |= FLOW_PKT_TOSERVER;
    p->flowflags |= FLOW_PKT_ESTABLISHED;
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
    f->alproto = ALPROTO_HTTP;

    StreamTcpInitConfig(TRUE);

    de_ctx = DetectEngineCtxInit();
    if (de_ctx == NULL) {
        goto end;
    }
    de_ctx->flags |= DE_QUIET;

    s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
                                   "(msg:\"Test content option\"; "
                                   "sid:1;)");
    if (s == NULL) {
        goto end;
    }

    SigGroupBuild(de_ctx);
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);

    FLOWLOCK_WRLOCK(f);
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
                                STREAM_TOSERVER, http_buf1, http_buf1_len);
    if (r != 0) {
        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
        FLOWLOCK_UNLOCK(f);
        goto end;
    }
    FLOWLOCK_UNLOCK(f);

    http_state = f->alstate;
    if (http_state == NULL) {
        printf("no http state: ");
        goto end;
    }

    /* do detect */
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);

    if (PacketAlertCheck(p, 1)) {
        printf("sig 1 alerted, but it should not (it's not ftp): ");
        goto end;
    }

    result = 1;
 end:
    if (alp_tctx != NULL)
        AppLayerParserThreadCtxFree(alp_tctx);
    if (det_ctx != NULL)
        DetectEngineThreadCtxDeinit(&tv, det_ctx);
    if (de_ctx != NULL)
        SigGroupCleanup(de_ctx);
    if (de_ctx != NULL)
        DetectEngineCtxFree(de_ctx);

    StreamTcpFreeConfig(TRUE);

    UTHFreePackets(&p, 1);
    UTHFreeFlow(f);
    return result;
}

Project: suricata
File: app-layer-detect-proto.c

static int AppLayerProtoDetectTest19(void)
{
    int result = 0;
    Flow *f = NULL;
    uint8_t http_buf1[] = "MPUT one\r\n";
    uint32_t http_buf1_len = sizeof(http_buf1) - 1;
    TcpSession ssn;
    Packet *p = NULL;
    Signature *s = NULL;
    ThreadVars tv;
    DetectEngineThreadCtx *det_ctx = NULL;
    DetectEngineCtx *de_ctx = NULL;
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();

    memset(&tv, 0, sizeof(ThreadVars));
    memset(&ssn, 0, sizeof(TcpSession));

    p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);

    f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
    if (f == NULL)
        goto end;
    f->protoctx = &ssn;
    f->proto = IPPROTO_TCP;
    p->flow = f;
    p->flowflags |= FLOW_PKT_TOSERVER;
    p->flowflags |= FLOW_PKT_ESTABLISHED;
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
    f->alproto = ALPROTO_FTP;

    StreamTcpInitConfig(TRUE);

    de_ctx = DetectEngineCtxInit();
    if (de_ctx == NULL) {
        goto end;
    }
    de_ctx->flags |= DE_QUIET;

    s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
                                   "(msg:\"http over non standar port\"; "
                                   "sid:1;)");
    if (s == NULL) {
        goto end;
    }

    SigGroupBuild(de_ctx);
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);

    FLOWLOCK_WRLOCK(f);
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
                                STREAM_TOSERVER, http_buf1, http_buf1_len);
    if (r != 0) {
        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
        FLOWLOCK_UNLOCK(f);
        goto end;
    }
    FLOWLOCK_UNLOCK(f);

    /* do detect */
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);

    if (PacketAlertCheck(p, 1)) {
        printf("sig 1 alerted, but it should not (it's ftp): ");
        goto end;
    }

    result = 1;

 end:
    if (alp_tctx != NULL)
        AppLayerParserThreadCtxFree(alp_tctx);
    if (det_ctx != NULL)
        DetectEngineThreadCtxDeinit(&tv, det_ctx);
    if (de_ctx != NULL)
        SigGroupCleanup(de_ctx);
    if (de_ctx != NULL)
        DetectEngineCtxFree(de_ctx);

    StreamTcpFreeConfig(TRUE);
    UTHFreePackets(&p, 1);
    UTHFreeFlow(f);
    return result;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectUnittestCtxBackup(void)
{
    SCEnter();
    alpd_ctx_ut = alpd_ctx;
    memset(&alpd_ctx, 0, sizeof(alpd_ctx));
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectUnittestCtxRestore(void)
{
    SCEnter();
    alpd_ctx = alpd_ctx_ut;
    memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerProtoDetectUnittestsRegister(void)
{
    SCEnter();

    UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
    UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
    UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
    UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
    UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
    UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
    UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
    UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
    UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
    UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
    UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
    UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
    UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
    UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
    UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
    UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
    UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
    UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
    UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);

    SCReturn;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
{
    if (expectation_proto[alproto]) {
        if (proto != expectation_proto[alproto]) {
            SCLogError(SC_ERR_NOT_SUPPORTED,
                       "Expectation on 2 IP protocols are not supported");
        }
    }
    expectation_proto[alproto] = proto;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
{
    FlowSetChangeProtoFlag(f);
    f->protodetect_dp = dp;
    f->alproto_expect = expect_proto;
}

Project: suricata
File: app-layer-detect-proto.c

void AppLayerRequestProtocolTLSUpgrade(Flow *f)
{
    AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS);
}

Project: suricata
File: app-layer-detect-proto.c

static uint16_t ProbingParserDummyForTesting(Flow *f,
                                             uint8_t *input,
                                             uint32_t input_len)
{
    return 0;
}