]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
app-layer: validate registration
authorVictor Julien <victor@inliniac.net>
Thu, 15 Jun 2017 09:32:13 +0000 (11:32 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 16 Jun 2017 09:34:00 +0000 (11:34 +0200)
src/app-layer-parser.c

index cddf5c02e2e5fe23d197e21e400ea9c170b111b4..0cf921949cbc74cc0b39355a2b8aed6ee73ef417 100644 (file)
@@ -1271,6 +1271,96 @@ void AppLayerParserStateCleanup(const Flow *f, void *alstate,
     SCReturn;
 }
 
+static void ValidateParserProtoDump(AppProto alproto, uint8_t ipproto)
+{
+    uint8_t map = FlowGetProtoMapping(ipproto);
+    const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
+    const AppLayerParserProtoCtx *ctx_def = &alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto];
+    printf("ERROR: incomplete app-layer registration\n");
+    printf("AppLayer protocol %s ipproto %u\n", AppProtoToString(alproto), ipproto);
+    printf("- flags %"PRIx64"\n", ctx->flags);
+    printf("- first_data_dir %"PRIx8"\n", ctx->first_data_dir);
+    printf("Mandatory:\n");
+    printf("- Parser[0] %p Parser[1] %p\n", ctx->Parser[0], ctx->Parser[1]);
+    printf("- StateAlloc %p StateFree %p\n", ctx->StateAlloc, ctx->StateFree);
+    printf("- StateGetTx %p StateGetTxCnt %p StateTransactionFree %p\n",
+            ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree);
+    printf("- StateGetProgress %p StateGetProgressCompletionStatus %p\n", ctx->StateGetProgress, ctx_def->StateGetProgressCompletionStatus);
+    printf("Optional:\n");
+    printf("- LocalStorageAlloc %p LocalStorageFree %p\n", ctx->LocalStorageAlloc, ctx->LocalStorageFree);
+    printf("- StateGetTxLogged %p StateSetTxLogged %p\n", ctx->StateGetTxLogged, ctx->StateSetTxLogged);
+    printf("- SetTxMpmIDs %p GetTxMpmIDs %p\n", ctx->SetTxMpmIDs, ctx->GetTxMpmIDs);
+    printf("- GetTxDetectState %p SetTxDetectState %p StateHasTxDetectState %p\n", ctx->GetTxDetectState, ctx->SetTxDetectState, ctx->StateHasTxDetectState);
+    printf("- StateGetEvents %p StateHasEvents %p StateGetEventInfo %p\n", ctx->StateGetEvents, ctx->StateHasEvents, ctx->StateGetEventInfo);
+}
+
+#define BOTH_SET(a, b) ((a) != NULL && (b) != NULL)
+#define BOTH_SET_OR_BOTH_UNSET(a, b) (((a) == NULL && (b) == NULL) || ((a) != NULL && (b) != NULL))
+#define THREE_SET_OR_THREE_UNSET(a, b, c) (((a) == NULL && (b) == NULL && (c) == NULL) || ((a) != NULL && (b) != NULL && (c) != NULL))
+
+static void ValidateParserProto(AppProto alproto, uint8_t ipproto)
+{
+    uint8_t map = FlowGetProtoMapping(ipproto);
+    const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
+    const AppLayerParserProtoCtx *ctx_def = &alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto];
+
+    if (ctx->Parser[0] == NULL && ctx->Parser[1] == NULL)
+        return;
+
+    if (!(BOTH_SET(ctx->Parser[0], ctx->Parser[1]))) {
+        goto bad;
+    }
+    if (!(BOTH_SET(ctx->StateFree, ctx->StateAlloc))) {
+        goto bad;
+    }
+    if (!(THREE_SET_OR_THREE_UNSET(ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree))) {
+        goto bad;
+    }
+    /* special case: StateGetProgressCompletionStatus is used from 'default'. */
+    if (!(BOTH_SET(ctx->StateGetProgress, ctx_def->StateGetProgressCompletionStatus))) {
+        goto bad;
+    }
+    /* local storage is optional, but needs both set if used */
+    if (!(BOTH_SET_OR_BOTH_UNSET(ctx->LocalStorageAlloc, ctx->LocalStorageFree))) {
+        goto bad;
+    }
+    if (!(BOTH_SET_OR_BOTH_UNSET(ctx->StateGetTxLogged, ctx->StateSetTxLogged))) {
+        goto bad;
+    }
+    if (!(BOTH_SET_OR_BOTH_UNSET(ctx->SetTxMpmIDs, ctx->GetTxMpmIDs))) {
+        goto bad;
+    }
+    if (!(BOTH_SET_OR_BOTH_UNSET(ctx->GetTxDetectState, ctx->SetTxDetectState))) {
+        goto bad;
+    }
+/*  TODO: not yet mandatory to use StateHasTxDetectState
+    if (!(THREE_SET_OR_THREE_UNSET(ctx->GetTxDetectState, ctx->SetTxDetectState, ctx->StateHasTxDetectState))) {
+        goto bad;
+    }
+*/
+
+    return;
+bad:
+    ValidateParserProtoDump(alproto, ipproto);
+    exit(EXIT_FAILURE);
+}
+#undef BOTH_SET
+#undef BOTH_SET_OR_BOTH_UNSET
+#undef THREE_SET_OR_THREE_UNSET
+
+static void ValidateParser(AppProto alproto)
+{
+    ValidateParserProto(alproto, IPPROTO_TCP);
+    ValidateParserProto(alproto, IPPROTO_UDP);
+}
+
+static void ValidateParsers(void)
+{
+    AppProto p = 0;
+    for ( ; p < ALPROTO_MAX; p++) {
+        ValidateParser(p);
+    }
+}
 
 void AppLayerParserRegisterProtocolParsers(void)
 {
@@ -1323,6 +1413,7 @@ void AppLayerParserRegisterProtocolParsers(void)
                   "msn");
     }
 
+    ValidateParsers();
     return;
 }