/** * The idle state is invoked before and after every transaction. Consequently, * it will start a new transaction when data is available and finalise a transaction * which has been processed. * * @param connp * @returns HTP_OK on state change, HTTP_ERROR on error, or HTP_DATA when more data is needed. */ int htp_connp_REQ_IDLE(htp_connp_t * connp) { // If we're here and a transaction object exists that // means we've just completed parsing a request. We need // to run the final hook and start over. if (connp->in_tx != NULL) { // Run hook REQUEST int rc = hook_run_all(connp->cfg->hook_request, connp); if (rc != HOOK_OK) { htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Request callback returned error (%d)", rc); return HTP_ERROR; } // Start afresh connp->in_tx = NULL; } // We want to start parsing the next request (and change // the state from IDLE) only if there's at least one // byte of data available. Otherwise we could be creating // new structures even if there's no more data on the // connection. IN_TEST_NEXT_BYTE_OR_RETURN(connp); // Detect pipelining if (list_size(connp->conn->transactions) > connp->out_next_tx_index) { connp->conn->flags |= PIPELINED_CONNECTION; } // Parsing a new request connp->in_tx = htp_tx_create(connp->cfg, CFG_SHARED, connp->conn); if (connp->in_tx == NULL) return HTP_ERROR; connp->in_tx->connp = connp; list_add(connp->conn->transactions, connp->in_tx); connp->in_content_length = -1; connp->in_body_data_left = -1; connp->in_header_line_index = -1; connp->in_header_line_counter = 0; connp->in_chunk_request_index = connp->in_chunk_count; // Run hook TRANSACTION_START int rc = hook_run_all(connp->cfg->hook_transaction_start, connp); if (rc != HOOK_OK) { htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Transaction start callback returned error (%d)", rc); return HTP_ERROR; } // Change state into request line parsing connp->in_state = htp_connp_REQ_LINE; connp->in_tx->progress[0] = TX_PROGRESS_REQ_LINE; return HTP_OK; }
/** * The idle state is where the parser will end up after a transaction is processed. * If there is more data available, a new request will be started. * * @param[in] connp * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed. */ htp_status_t htp_connp_REQ_IDLE(htp_connp_t * connp) { // We want to start parsing the next request (and change // the state from IDLE) only if there's at least one // byte of data available. Otherwise we could be creating // new structures even if there's no more data on the // connection. IN_TEST_NEXT_BYTE_OR_RETURN(connp); connp->in_tx = htp_connp_tx_create(connp); if (connp->in_tx == NULL) return HTP_ERROR; // Change state to TRANSACTION_START htp_tx_state_request_start(connp->in_tx); return HTP_OK; }