int OutputRegisterTxLogger(const char *name, AppProto alproto, TxLogger LogFunc,
                           OutputCtx *output_ctx, int tc_log_progress,
                           int ts_log_progress, TxLoggerCondition LogCondition)
{
    int module_id = TmModuleGetIdByName(name);
    if (module_id < 0)
        return -1;

    OutputTxLogger *op = SCMalloc(sizeof(*op));
    if (op == NULL)
        return -1;
    memset(op, 0x00, sizeof(*op));

    op->alproto = alproto;
    op->LogFunc = LogFunc;
    op->LogCondition = LogCondition;
    op->output_ctx = output_ctx;
    op->name = name;
    op->module_id = (TmmId) module_id;

    if (tc_log_progress) {
        op->tc_log_progress = tc_log_progress;
    } else {
        op->tc_log_progress =
            AppLayerParserGetStateProgressCompletionStatus(alproto,
                                                           STREAM_TOCLIENT);
    }

    if (ts_log_progress) {
        op->ts_log_progress = ts_log_progress;
    } else {
        op->ts_log_progress =
            AppLayerParserGetStateProgressCompletionStatus(alproto,
                                                           STREAM_TOSERVER);
    }

    if (list == NULL) {
        op->id = 1;
        list = op;
    } else {
        OutputTxLogger *t = list;
        while (t->next)
            t = t->next;
        if (t->id * 2 > UINT32_MAX) {
            SCLogError(SC_ERR_FATAL, "Too many loggers registered.");
            exit(EXIT_FAILURE);
        }
        op->id = t->id * 2;
        t->next = op;
    }

    SCLogDebug("OutputRegisterTxLogger happy");
    return 0;
}
void AppLayerParserSetTransactionInspectId(AppLayerParserState *pstate,
                                           uint8_t ipproto, AppProto alproto, void *alstate,
                                           uint8_t direction)
{
    SCEnter();

    uint8_t dir = (direction & STREAM_TOSERVER) ? 0 : 1;
    uint64_t total_txs = AppLayerParserGetTxCnt(ipproto, alproto, alstate);
    uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, direction);
    int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(ipproto, alproto, direction);
    void *tx;
    int state_progress;

    for (; idx < total_txs; idx++) {
        tx = AppLayerParserGetTx(ipproto, alproto, alstate, idx);
        if (tx == NULL)
            continue;
        state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, direction);
        if (state_progress >= state_done_progress)
            continue;
        else
            break;
    }
    pstate->inspect_id[dir] = idx;

    SCReturn;
}
Beispiel #3
0
/** \brief active TX retrieval for logging only: so NO detection
 *
 *  If the logger is enabled, we simply return the log_id here.
 *
 *  Otherwise, we go look for the tx id. There probably is no point
 *  in running this function in that case though. With no detection
 *  and no logging, why run a parser in the first place?
 **/
uint64_t AppLayerTransactionGetActiveLogOnly(Flow *f, uint8_t flags)
{
    AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][f->alproto];

    if (p->logger == TRUE) {
        uint64_t log_id = f->alparser->log_id;
        SCLogDebug("returning %"PRIu64, log_id);
        return log_id;
    }

    /* logger is disabled, return highest 'complete' tx id */
    uint64_t total_txs = AppLayerParserGetTxCnt(f->proto, f->alproto, f->alstate);
    uint64_t idx = AppLayerParserGetTransactionInspectId(f->alparser, flags);
    int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
    void *tx;
    int state_progress;

    for (; idx < total_txs; idx++) {
        tx = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, idx);
        if (tx == NULL)
            continue;
        state_progress = AppLayerParserGetStateProgress(f->proto, f->alproto, tx, flags);
        if (state_progress >= state_done_progress)
            continue;
        else
            break;
    }
    SCLogDebug("returning %"PRIu64, idx);
    return idx;
}
Beispiel #4
0
int OutputRegisterTxLogger(LoggerId id, const char *name, AppProto alproto,
                           TxLogger LogFunc,
                           OutputCtx *output_ctx, int tc_log_progress,
                           int ts_log_progress, TxLoggerCondition LogCondition,
                           ThreadInitFunc ThreadInit,
                           ThreadDeinitFunc ThreadDeinit,
                           void (*ThreadExitPrintStats)(ThreadVars *, void *))
{
    if (!(AppLayerParserIsTxAware(alproto))) {
        SCLogNotice("%s logger not enabled: protocol %s is disabled",
            name, AppProtoToString(alproto));
        return -1;
    }

    OutputTxLogger *op = SCMalloc(sizeof(*op));
    if (op == NULL)
        return -1;
    memset(op, 0x00, sizeof(*op));

    op->alproto = alproto;
    op->LogFunc = LogFunc;
    op->LogCondition = LogCondition;
    op->output_ctx = output_ctx;
    op->name = name;
    op->logger_id = id;
    op->ThreadInit = ThreadInit;
    op->ThreadDeinit = ThreadDeinit;
    op->ThreadExitPrintStats = ThreadExitPrintStats;

    if (tc_log_progress < 0) {
        op->tc_log_progress =
            AppLayerParserGetStateProgressCompletionStatus(alproto,
                                                           STREAM_TOCLIENT);
    } else {
        op->tc_log_progress = tc_log_progress;
    }

    if (ts_log_progress < 0) {
        op->ts_log_progress =
            AppLayerParserGetStateProgressCompletionStatus(alproto,
                                                           STREAM_TOSERVER);
    } else {
        op->ts_log_progress = ts_log_progress;
    }

    if (list == NULL) {
        op->id = 1;
        list = op;
    } else {
        OutputTxLogger *t = list;
        while (t->next)
            t = t->next;
        if (t->id * 2 > UINT32_MAX) {
            SCLogError(SC_ERR_FATAL, "Too many loggers registered.");
            exit(EXIT_FAILURE);
        }
        op->id = t->id * 2;
        t->next = op;
    }

    SCLogDebug("OutputRegisterTxLogger happy");
    return 0;
}
int HttpBodyIterator(Flow *f, int close, void *cbdata, uint8_t iflags)
{
    SCLogDebug("called with %p, %d, %p, %02x", f, close, cbdata, iflags);

    HtpState *s = f->alstate;
    if (s != NULL && s->conn != NULL) {
        int tx_progress_done_value_ts =
            AppLayerParserGetStateProgressCompletionStatus(IPPROTO_TCP,
                                                           ALPROTO_HTTP, STREAM_TOSERVER);
        int tx_progress_done_value_tc =
            AppLayerParserGetStateProgressCompletionStatus(IPPROTO_TCP,
                                                           ALPROTO_HTTP, STREAM_TOCLIENT);

        // for each tx
        uint64_t tx_id = 0;
        uint64_t total_txs = AppLayerParserGetTxCnt(f->proto, f->alproto, f->alstate);
        SCLogDebug("s->conn %p", s->conn);
        for (tx_id = 0; tx_id < total_txs; tx_id++) { // TODO optimization store log tx
            htp_tx_t *tx = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, tx_id);
            if (tx != NULL) {
                int tx_done = 0;
                int tx_logged = 0;

                int tx_progress_ts = AppLayerParserGetStateProgress(
                        IPPROTO_TCP, ALPROTO_HTTP, tx, FlowGetDisruptionFlags(f, STREAM_TOSERVER));
                if (tx_progress_ts >= tx_progress_done_value_ts) {
                    int tx_progress_tc = AppLayerParserGetStateProgress(
                            IPPROTO_TCP, ALPROTO_HTTP, tx, FlowGetDisruptionFlags(f, STREAM_TOCLIENT));
                    if (tx_progress_tc >= tx_progress_done_value_tc) {
                        tx_done = 1;
                    }
                }

                SCLogDebug("tx %p", tx);
                HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
                if (htud != NULL) {
                    SCLogDebug("htud %p", htud);
                    HtpBody *body = NULL;
                    if (iflags & OUTPUT_STREAMING_FLAG_TOCLIENT)
                        body = &htud->request_body;
                    else if (iflags & OUTPUT_STREAMING_FLAG_TOSERVER)
                        body = &htud->response_body;

                    if (body == NULL) {
                        SCLogDebug("no body");
                        goto next;
                    }
                    if (body->first == NULL) {
                        SCLogDebug("no body chunks");
                        goto next;
                    }
                    if (body->last->logged == 1) {
                        SCLogDebug("all logged already");
                        goto next;
                    }

                    // for each chunk
                    HtpBodyChunk *chunk = body->first;
                    for ( ; chunk != NULL; chunk = chunk->next) {
                        if (chunk->logged) {
                            SCLogDebug("logged %d", chunk->logged);
                            continue;
                        }

                        uint8_t flags = iflags | OUTPUT_STREAMING_FLAG_TRANSACTION;
                        if (chunk->stream_offset == 0)
                            flags |= OUTPUT_STREAMING_FLAG_OPEN;
                        /* if we need to close and we're at the last segment in the list
                         * we add the 'close' flag so the logger can close up. */
                        if ((tx_done || close) && chunk->next == NULL) {
                            flags |= OUTPUT_STREAMING_FLAG_CLOSE;
                        }

                        // invoke Streamer
                        Streamer(cbdata, f, chunk->data, (uint32_t)chunk->len, tx_id, flags);
                        //PrintRawDataFp(stdout, chunk->data, chunk->len);
                        chunk->logged = 1;
                        tx_logged = 1;
                    }

                  next:
                    /* if we need to close we need to invoke the Streamer for sure. If we
                     * logged no chunks, we call the Streamer with NULL data so it can
                     * close up. */
                    if (tx_logged == 0 && (close||tx_done)) {
                        Streamer(cbdata, f, NULL, 0, tx_id,
                                OUTPUT_STREAMING_FLAG_CLOSE|OUTPUT_STREAMING_FLAG_TRANSACTION);
                    }
                }
            }
        }
    }


    return 0;
}
Beispiel #6
0
static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data, PacketQueue *pq, PacketQueue *postpq)
{
    BUG_ON(thread_data == NULL);
    BUG_ON(list == NULL);

    OutputLoggerThreadData *op_thread_data = (OutputLoggerThreadData *)thread_data;
    OutputTxLogger *logger = list;
    OutputLoggerThreadStore *store = op_thread_data->store;

    BUG_ON(logger == NULL && store != NULL);
    BUG_ON(logger != NULL && store == NULL);
    BUG_ON(logger == NULL && store == NULL);

    if (p->flow == NULL)
        return TM_ECODE_OK;

    Flow * const f = p->flow;

    FLOWLOCK_WRLOCK(f); /* WRITE lock before we updated flow logged id */
    AppProto alproto = f->alproto;

    if (AppLayerParserProtocolIsTxAware(p->proto, alproto) == 0)
        goto end;
    if (AppLayerParserProtocolHasLogger(p->proto, alproto) == 0)
        goto end;

    void *alstate = f->alstate;
    if (alstate == NULL) {
        SCLogDebug("no alstate");
        goto end;
    }

    uint64_t total_txs = AppLayerParserGetTxCnt(p->proto, alproto, alstate);
    uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser);
    int tx_progress_done_value_ts =
        AppLayerParserGetStateProgressCompletionStatus(p->proto, alproto,
                                                       STREAM_TOSERVER);
    int tx_progress_done_value_tc =
        AppLayerParserGetStateProgressCompletionStatus(p->proto, alproto,
                                                       STREAM_TOCLIENT);
    for (; tx_id < total_txs; tx_id++)
    {
        int proto_logged = 0;

        void *tx = AppLayerParserGetTx(p->proto, alproto, alstate, tx_id);
        if (tx == NULL) {
            SCLogDebug("tx is NULL not logging");
            continue;
        }

        if (!(AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF)))
        {
            int tx_progress = AppLayerParserGetStateProgress(p->proto, alproto,
                                                             tx, FlowGetDisruptionFlags(f, STREAM_TOSERVER));
            if (tx_progress < tx_progress_done_value_ts) {
                SCLogDebug("progress not far enough, not logging");
                break;
            }

            tx_progress = AppLayerParserGetStateProgress(p->proto, alproto,
                                                         tx, FlowGetDisruptionFlags(f, STREAM_TOCLIENT));
            if (tx_progress < tx_progress_done_value_tc) {
                SCLogDebug("progress not far enough, not logging");
                break;
            }
        }

        // call each logger here (pseudo code)
        logger = list;
        store = op_thread_data->store;
        while (logger && store) {
            BUG_ON(logger->LogFunc == NULL);

            SCLogDebug("logger %p", logger);
            if (logger->alproto == alproto) {
                SCLogDebug("alproto match, logging tx_id %ju", tx_id);
                PACKET_PROFILING_TMM_START(p, logger->module_id);
                logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id);
                PACKET_PROFILING_TMM_END(p, logger->module_id);
                proto_logged = 1;
            }

            logger = logger->next;
            store = store->next;

            BUG_ON(logger == NULL && store != NULL);
            BUG_ON(logger != NULL && store == NULL);
        }

        if (proto_logged) {
            SCLogDebug("updating log tx_id %ju", tx_id);
            AppLayerParserSetTransactionLogId(f->alparser);
        }
    }

end:
    FLOWLOCK_UNLOCK(f);
    return TM_ECODE_OK;
}