/* Option-converting functions */
static int ConvertPreprocessorOption(Rule *rule, int index, OptTreeNode *otn)
{
    PreprocessorOption *preprocOpt = rule->options[index]->option_u.preprocOpt;
    PreprocessorOptionInfo *preprocOptInfo = SnortAlloc(sizeof(PreprocessorOptionInfo));
    OptFpList *fpl;
    void *option_dup;

    preprocOptInfo->optionInit = preprocOpt->optionInit;
    preprocOptInfo->optionEval = preprocOpt->optionEval;
    preprocOptInfo->optionFpFunc = preprocOpt->optionFpFunc;
    preprocOptInfo->data = preprocOpt->dataPtr;

    /* FreeOneRule() already calls the cleanup function. Left NULL here
       to avoid a double-free. */
    preprocOptInfo->optionCleanup = NULL;

    preprocOptInfo->optionHash = NULL;
    preprocOptInfo->optionKeyCompare = NULL;
    preprocOptInfo->otnHandler = NULL;

    //  Add to option chain with generic callback
    fpl = AddOptFuncToList(PreprocessorOptionFunc, otn);

    /*
     * attach custom info to the context node so that we can call each instance
     * individually
     */
    fpl->context = (void *) preprocOptInfo;

    if (add_detection_option(RULE_OPTION_TYPE_PREPROCESSOR,
                             (void *)preprocOptInfo, &option_dup) == DETECTION_OPTION_EQUAL)
    {
        PreprocessorRuleOptionsFreeFunc(preprocOptInfo);
        fpl->context = preprocOptInfo = option_dup;
    }
    fpl->type = RULE_OPTION_TYPE_PREPROCESSOR;

    return 1;
}
int detection_hash_free_func(void *option_key, void *data)
{
    detection_option_key_t *key = (detection_option_key_t*)option_key;

    switch (key->option_type)
    {
        /* Call free function specific to the key type */
        case RULE_OPTION_TYPE_ASN1:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_BYTE_TEST:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_BYTE_JUMP:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_FLOW:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_CVS:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_DSIZE:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_FLOWBIT:
            FlowBitsFree(key->option_data);
            break;
        case RULE_OPTION_TYPE_FTPBOUNCE:
            /* Data is NULL, nothing to free */
            break;
        case RULE_OPTION_TYPE_ICMP_CODE:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_ICMP_ID:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_ICMP_SEQ:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_ICMP_TYPE:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_IP_FRAGBITS:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_IP_FRAG_OFFSET:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_IP_ID:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_IP_OPTION:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_IP_PROTO:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_IP_SAME:
            /* Data is NULL, nothing to free */
            break;
        case RULE_OPTION_TYPE_IP_TOS:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_IS_DATA_AT:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_CONTENT:
        case RULE_OPTION_TYPE_CONTENT_URI:
            PatternMatchFree(key->option_data);
            break;
        case RULE_OPTION_TYPE_PCRE:
            PcreFree(key->option_data);
            break;
#ifdef ENABLE_REACT
        case RULE_OPTION_TYPE_REACT:
            ReactFree(key->option_data);
            break;
#endif
#ifdef ENABLE_RESPOND
        case RULE_OPTION_TYPE_RESPOND:
            free(key->option_data);
            break;
#endif
        case RULE_OPTION_TYPE_RPC_CHECK:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_SESSION:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_TCP_ACK:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_TCP_FLAG:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_TCP_SEQ:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_TCP_WIN:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_TTL:
            free(key->option_data);
            break;
        case RULE_OPTION_TYPE_URILEN:
            free(key->option_data);
            break;
#ifdef DYNAMIC_PLUGIN
        case RULE_OPTION_TYPE_HDR_OPT_CHECK:
            break;
        case RULE_OPTION_TYPE_PREPROCESSOR:
            PreprocessorRuleOptionsFreeFunc(key->option_data);
            break;
        case RULE_OPTION_TYPE_DYNAMIC:
            fpDynamicDataFree(key->option_data);
            break;
#endif
        case RULE_OPTION_TYPE_LEAF_NODE:
            break;
    }
    return 0;
}