示例#1
0
int RunModeSetIPSAutoFp(ConfigIPSParserFunc ConfigParser,
                        const char *recv_mod_name,
                        const char *verdict_mod_name,
                        const char *decode_mod_name)
{
    SCEnter();
    char tname[TM_THREAD_NAME_MAX];
    char qname[TM_QUEUE_NAME_MAX];
    TmModule *tm_module ;
    const char *cur_queue = NULL;
    char *queues = NULL;
    int thread;

    /* Available cpus */
    uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
    int nqueue = LiveGetDeviceCount();

    int thread_max = TmThreadGetNbThreads(WORKER_CPU_SET);
    /* always create at least one thread */
    if (thread_max == 0)
        thread_max = ncpus * threading_detect_ratio;
    if (thread_max < 1)
        thread_max = 1;

    queues = RunmodeAutoFpCreatePickupQueuesString(thread_max);
    if (queues == NULL) {
        SCLogError(SC_ERR_RUNMODE, "RunmodeAutoFpCreatePickupQueuesString failed");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < nqueue; i++) {
    /* create the threads */
        cur_queue = LiveGetDeviceName(i);
        if (cur_queue == NULL) {
            SCLogError(SC_ERR_RUNMODE, "invalid queue number");
            exit(EXIT_FAILURE);
        }
        memset(tname, 0, sizeof(tname));
        snprintf(tname, sizeof(tname), "%s-Q%s", thread_name_autofp, cur_queue);

        ThreadVars *tv_receive =
            TmThreadCreatePacketHandler(tname,
                    "packetpool", "packetpool",
                    queues, "flow", "pktacqloop");
        if (tv_receive == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
            exit(EXIT_FAILURE);
        }
        TmModule *tm_module = TmModuleGetByName(recv_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName failed for %s", recv_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receive, tm_module, (void *) ConfigParser(i));

        tm_module = TmModuleGetByName(decode_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName %s failed", decode_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receive, tm_module, NULL);

        TmThreadSetCPU(tv_receive, RECEIVE_CPU_SET);

        if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }

    }
    for (thread = 0; thread < thread_max; thread++) {
        snprintf(tname, sizeof(tname), "%s#%02d", thread_name_workers, thread+1);
        snprintf(qname, sizeof(qname), "pickup%d", thread+1);

        SCLogDebug("tname %s, qname %s", tname, qname);

        ThreadVars *tv_detect_ncpu =
            TmThreadCreatePacketHandler(tname,
                                        qname, "flow",
                                        "verdict-queue", "simple",
                                        "varslot");
        if (tv_detect_ncpu == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
            exit(EXIT_FAILURE);
        }

        TmModule *tm_module = TmModuleGetByName("FlowWorker");
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName for FlowWorker failed");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL);

        TmThreadSetCPU(tv_detect_ncpu, WORKER_CPU_SET);

        TmThreadSetGroupName(tv_detect_ncpu, "Detect");

        if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }
    }

    /* create the threads */
    for (int i = 0; i < nqueue; i++) {
        memset(tname, 0, sizeof(tname));
        snprintf(tname, sizeof(tname), "%s#%02d", thread_name_verdict, i);

        ThreadVars *tv_verdict =
            TmThreadCreatePacketHandler(tname,
                                        "verdict-queue", "simple",
                                        "packetpool", "packetpool",
                                        "varslot");
        if (tv_verdict == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName(verdict_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName %s failed", verdict_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_verdict, tm_module, (void *)ConfigParser(i));

        tm_module = TmModuleGetByName("RespondReject");
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName for RespondReject failed");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_verdict, tm_module, NULL);

        TmThreadSetCPU(tv_verdict, VERDICT_CPU_SET);

        if (TmThreadSpawn(tv_verdict) != TM_ECODE_OK) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }
    }

    SCFree(queues);
    return 0;
}
示例#2
0
/**
 * \brief Receives packets from a DAG interface.
 *
 * \param tv pointer to ThreadVars
 * \param data pointer to ErfDagThreadVars
 * \param slot slot containing task information
 *
 * \retval TM_ECODE_OK on success
 * \retval TM_ECODE_FAILED on failure
 */
TmEcode
ReceiveErfDagLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    ErfDagThreadVars *dtv = (ErfDagThreadVars *)data;
    uint32_t diff = 0;
    int      err;
    uint8_t  *top = NULL;
    uint32_t pkts_read = 0;
    TmSlot *s = (TmSlot *)slot;

    dtv->slot = s->slot_next;

    while (1) {
        if (suricata_ctl_flags & (SURICATA_STOP | SURICATA_KILL)) {
            SCReturnInt(TM_ECODE_OK);
        }

        top = dag_advance_stream(dtv->dagfd, dtv->dagstream, &(dtv->btm));
        if (top == NULL) {
            if (errno == EAGAIN) {
                if (dtv->dagstream & 0x1) {
                    usleep(10 * 1000);
                    dtv->btm = dtv->top;
                }
                continue;
            } else {
                SCLogError(SC_ERR_ERF_DAG_STREAM_READ_FAILED,
                    "Failed to read from stream: %d, DAG: %s when "
                    "using dag_advance_stream",
                    dtv->dagstream, dtv->dagname);
                SCReturnInt(TM_ECODE_FAILED);
            }
        }

        diff = top - dtv->btm;
        if (diff == 0) {
            continue;
        }

        assert(diff >= dag_record_size);

        err = ProcessErfDagRecords(dtv, top, &pkts_read);

        if (err == TM_ECODE_FAILED) {
            SCLogError(SC_ERR_ERF_DAG_STREAM_READ_FAILED,
                "Failed to read from stream: %d, DAG: %s",
                dtv->dagstream, dtv->dagname);
            ReceiveErfDagCloseStream(dtv->dagfd, dtv->dagstream);
            SCReturnInt(TM_ECODE_FAILED);
        }

        StatsSyncCountersIfSignalled(tv);

        SCLogDebug("Read %d records from stream: %d, DAG: %s",
            pkts_read, dtv->dagstream, dtv->dagname);
    }

    SCReturnInt(TM_ECODE_OK);
}
示例#3
0
/**
 * \brief   Process a DAG record into a TM packet buffer.
 * \param   prec pointer to a DAG record.
 * \param
 */
static inline TmEcode
ProcessErfDagRecord(ErfDagThreadVars *ewtn, char *prec)
{
    SCEnter();

    int wlen = 0;
    int rlen = 0;
    int hdr_num = 0;
    char hdr_type = 0;
    dag_record_t  *dr = (dag_record_t*)prec;
    erf_payload_t *pload;
    Packet *p;

    hdr_type = dr->type;
    wlen = ntohs(dr->wlen);
    rlen = ntohs(dr->rlen);

    /* count extension headers */
    while (hdr_type & 0x80) {
        if (rlen < (dag_record_size + (hdr_num * 8))) {
            SCLogError(SC_ERR_UNIMPLEMENTED,
                "Insufficient captured packet length.");
            SCReturnInt(TM_ECODE_FAILED);
        }
        hdr_type = prec[(dag_record_size + (hdr_num * 8))];
        hdr_num++;
    }

    /* Check that the whole frame was captured */
    if (rlen < (dag_record_size + (8 * hdr_num) + 2 + wlen)) {
        SCLogInfo("Incomplete frame captured.");
        SCReturnInt(TM_ECODE_OK);
    }

    /* skip over extension headers */
    pload = (erf_payload_t *)(prec + dag_record_size + (8 * hdr_num));

    p = PacketGetFromQueueOrAlloc();
    if (p == NULL) {
        SCLogError(SC_ERR_MEM_ALLOC,
            "Failed to allocate a Packet on stream: %d, DAG: %s",
            ewtn->dagstream, ewtn->dagname);
        SCReturnInt(TM_ECODE_FAILED);
    }
    PKT_SET_SRC(p, PKT_SRC_WIRE);

    SET_PKT_LEN(p, wlen);
    p->datalink = LINKTYPE_ETHERNET;

    /* Take into account for link type Ethernet ETH frame starts
     * after ther ERF header + pad.
     */
    if (unlikely(PacketCopyData(p, pload->eth.dst, GET_PKT_LEN(p)))) {
        TmqhOutputPacketpool(ewtn->tv, p);
        SCReturnInt(TM_ECODE_FAILED);
    }

    /* Convert ERF time to timeval - from libpcap. */
    uint64_t ts = dr->ts;
    p->ts.tv_sec = ts >> 32;
    ts = (ts & 0xffffffffULL) * 1000000;
    ts += 0x80000000; /* rounding */
    p->ts.tv_usec = ts >> 32;
    if (p->ts.tv_usec >= 1000000) {
        p->ts.tv_usec -= 1000000;
        p->ts.tv_sec++;
    }

    StatsIncr(tv, ewtn->packets);
    ewtn->bytes += wlen;

    if (TmThreadsSlotProcessPkt(ewtn->tv, ewtn->slot, p) != TM_ECODE_OK) {
        TmqhOutputPacketpool(ewtn->tv, p);
        SCReturnInt(TM_ECODE_FAILED);
    }

    SCReturnInt(TM_ECODE_OK);
}
static const uint8_t *DetectEngineSMTPGetBufferForTX(uint64_t tx_id,
                                               DetectEngineCtx *de_ctx,
                                               DetectEngineThreadCtx *det_ctx,
                                               Flow *f, File *curr_file,
                                               uint8_t flags,
                                               uint32_t *buffer_len,
                                               uint32_t *stream_start_offset)
{
    SCEnter();
    int index = 0;
    const uint8_t *buffer = NULL;
    *buffer_len = 0;
    *stream_start_offset = 0;
    uint64_t file_size = FileSize(curr_file);

    if (det_ctx->smtp_buffers_list_len == 0) {
        if (SMTPCreateSpace(det_ctx, 1) < 0)
            goto end;
        index = 0;

        if (det_ctx->smtp_buffers_list_len == 0) {
            det_ctx->smtp_start_tx_id = tx_id;
        }
        det_ctx->smtp_buffers_list_len++;
    } else {
        if ((tx_id - det_ctx->smtp_start_tx_id) < det_ctx->smtp_buffers_list_len) {
            if (det_ctx->smtp[(tx_id - det_ctx->smtp_start_tx_id)].buffer_len != 0) {
                *buffer_len = det_ctx->smtp[(tx_id - det_ctx->smtp_start_tx_id)].buffer_len;
                *stream_start_offset = det_ctx->smtp[(tx_id - det_ctx->smtp_start_tx_id)].offset;
                buffer = det_ctx->smtp[(tx_id - det_ctx->smtp_start_tx_id)].buffer;

                SCReturnPtr(buffer, "uint8_t");
            }
        } else {
            if (SMTPCreateSpace(det_ctx, (tx_id - det_ctx->smtp_start_tx_id) + 1) < 0)
                goto end;

            if (det_ctx->smtp_buffers_list_len == 0) {
                det_ctx->smtp_start_tx_id = tx_id;
            }
            det_ctx->smtp_buffers_list_len++;
        }
        index = (tx_id - det_ctx->smtp_start_tx_id);
    }

    SCLogDebug("smtp_config.content_limit %u, smtp_config.content_inspect_min_size %u",
                smtp_config.content_limit, smtp_config.content_inspect_min_size);

    SCLogDebug("file %p size %"PRIu64", state %d", curr_file, file_size, curr_file->state);

    /* no new data */
    if (curr_file->content_inspected == file_size) {
        SCLogDebug("no new data");
        goto end;
    }

    if (file_size == 0) {
        SCLogDebug("no data to inspect for this transaction");
        goto end;
    }

    if ((smtp_config.content_limit == 0 || file_size < smtp_config.content_limit) &&
        file_size < smtp_config.content_inspect_min_size &&
        !(flags & STREAM_EOF) && !(curr_file->state > FILE_STATE_OPENED)) {
        SCLogDebug("we still haven't seen the entire content. "
                   "Let's defer content inspection till we see the "
                   "entire content.");
        goto end;
    }

    StreamingBufferGetDataAtOffset(curr_file->sb,
            &det_ctx->smtp[index].buffer, &det_ctx->smtp[index].buffer_len,
            curr_file->content_inspected);

    det_ctx->smtp[index].offset = curr_file->content_inspected;

    /* updat inspected tracker */
    curr_file->content_inspected = FileSize(curr_file);

    SCLogDebug("content_inspected %u, offset %u", (uint)curr_file->content_inspected, (uint)det_ctx->smtp[index].offset);

    buffer = det_ctx->smtp[index].buffer;
    *buffer_len = det_ctx->smtp[index].buffer_len;
    *stream_start_offset = det_ctx->smtp[index].offset;

end:
    SCLogDebug("buffer %p, len %u", buffer, *buffer_len);
    SCReturnPtr(buffer, "uint8_t");
}
示例#5
0
/**
 * \brief This function is used to match ftpbounce attacks
 *
 * \param payload Payload of the PORT command
 * \param payload_len Length of the payload
 * \param ip_orig IP source to check the ftpbounce condition
 * \param offset offset to the arguments of the PORT command
 *
 * \retval 1 if ftpbounce detected, 0 if not
 */
int DetectFtpbounceMatchArgs(uint8_t *payload, uint16_t payload_len,
                             uint32_t ip_orig, uint16_t offset)
{
    SCEnter();
    SCLogDebug("Checking ftpbounce condition");
    char *c = NULL;
    uint16_t i = 0;
    int octet = 0;
    int octet_ascii_len = 0;
    int noctet = 0;
    uint32_t ip = 0;
    /* PrintRawDataFp(stdout, payload, payload_len); */

    if (payload_len < 7) {
        /* we need at least a differet ip address
         * in the format 1,2,3,4,x,y where x,y is the port
         * in two byte representation so let's look at
         * least for the IP octets in comma separated */
        return 0;
    }

    if (offset + 7 >= payload_len)
        return 0;

    c =(char*) payload;
    if (c == NULL) {
        SCLogDebug("No payload to check");
        return 0;
    }

    i = offset;
    /* Search for the first IP octect(Skips "PORT ") */
    while (i < payload_len && !isdigit((unsigned char)c[i])) i++;

    for (;i < payload_len && octet_ascii_len < 4 ;i++) {
        if (isdigit((unsigned char)c[i])) {
            octet =(c[i] - '0') + octet * 10;
            octet_ascii_len++;
        } else {
            if (octet > 256) {
                SCLogDebug("Octet not in ip format");
                return 0;
            }

            if (isspace((unsigned char)c[i]))
                while (i < payload_len && isspace((unsigned char)c[i]) ) i++;

            if (i < payload_len && c[i] == ',') { /* we have an octet */
                noctet++;
                octet_ascii_len = 0;
                ip =(ip << 8) + octet;
                octet = 0;
            } else {
                SCLogDebug("Unrecognized character '%c'", c[i]);
                return 0;
            }
            if (noctet == 4) {
                /* Different IP than src, ftp bounce scan */
                ip = SCByteSwap32(ip);

                if (ip != ip_orig) {
                    SCLogDebug("Different ip, so Matched ip:%d <-> ip_orig:%d",
                               ip, ip_orig);
                    return 1;
                }
                SCLogDebug("Same ip, so no match here");
                return 0;
            }
        }
    }
    SCLogDebug("No match");
    return 0;
}
示例#6
0
/**
 * \brief Initialize analyzer description
 *
 * \return 0 if ok
 */
static int SetupAnalyzer(idmef_analyzer_t *analyzer)
{
    int ret;
    prelude_string_t *string;

    SCEnter();

    ret = idmef_analyzer_new_model(analyzer, &string);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error creating analyzer model: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }
    ret = prelude_string_set_constant(string, ANALYZER_MODEL);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error setting analyzer model: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }

    ret = idmef_analyzer_new_class(analyzer, &string);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error creating analyzer class: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }
    ret = prelude_string_set_constant(string, ANALYZER_CLASS);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error setting analyzer class: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }

    ret = idmef_analyzer_new_manufacturer(analyzer, &string);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error creating analyzer manufacturer: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }
    ret = prelude_string_set_constant(string, ANALYZER_MANUFACTURER);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error setting analyzer manufacturer: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }

    ret = idmef_analyzer_new_version(analyzer, &string);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error creating analyzer version: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }
    ret = prelude_string_set_constant(string, VERSION);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error setting analyzer version: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }

    SCReturnInt(0);
}
示例#7
0
/**
 * \brief Add Source and Target fields to the IDMEF alert.
 * These objects contains IP addresses, source and destination
 * ports (see sections 4.2.4.3 and 4.2.4.4 of RFC 4765).
 *
 * \return 0 if ok
 */
static int EventToSourceTarget(const PacketAlert *pa, const Packet *p,
                               idmef_alert_t *alert)
{
    int ret;
    idmef_node_t *node;
    idmef_source_t *source;
    idmef_target_t *target;
    idmef_address_t *address;
    idmef_service_t *service;
    prelude_string_t *string;
    static char saddr[128], daddr[128];
    uint8_t ip_vers;
    uint8_t ip_proto;
    uint16_t sp, dp;
    uint8_t invert = 0;

    SCEnter();

    if ( !p )
        SCReturnInt(0);

    if ( ! IPH_IS_VALID(p) )
        SCReturnInt(0);

    if (pa->s->flags & SIG_FLAG_HAS_TARGET) {
        if (pa->s->flags & SIG_FLAG_SRC_IS_TARGET) {
            invert = 1;
        } else {
            invert = 0;
        }
    } else {
        invert = 0;
    }

    if (PKT_IS_IPV4(p)) {
        ip_vers = 4;
        ip_proto = IPV4_GET_RAW_IPPROTO(p->ip4h);
        if (invert) {
            PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), saddr, sizeof(saddr));
            PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), daddr, sizeof(daddr));
            sp = p->dp;
            dp = p->sp;
        } else {
            PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), saddr, sizeof(saddr));
            PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), daddr, sizeof(daddr));
            sp = p->sp;
            dp = p->dp;

        }
    } else if (PKT_IS_IPV6(p)) {
        ip_vers = 6;
        ip_proto = IPV6_GET_L4PROTO(p);
        if (invert) {
            PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), saddr, sizeof(saddr));
            PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), daddr, sizeof(daddr));
            sp = p->dp;
            dp = p->sp;
        } else {
            PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), saddr, sizeof(saddr));
            PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), daddr, sizeof(daddr));
            sp = p->sp;
            dp = p->dp;
        }
    } else
        SCReturnInt(0);

    ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    ret = idmef_source_new_service(source, &service);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    if ( p->tcph || p->udph )
        idmef_service_set_port(service, sp);

    idmef_service_set_ip_version(service, ip_vers);
    idmef_service_set_iana_protocol_number(service, ip_proto);

    ret = idmef_source_new_node(source, &node);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    ret = idmef_address_new_address(address, &string);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    prelude_string_set_ref(string, saddr);

    ret = idmef_alert_new_target(alert, &target, IDMEF_LIST_APPEND);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    ret = idmef_target_new_service(target, &service);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    if ( p->tcph || p->udph )
        idmef_service_set_port(service, dp);

    idmef_service_set_ip_version(service, ip_vers);
    idmef_service_set_iana_protocol_number(service, ip_proto);

    ret = idmef_target_new_node(target, &node);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    ret = idmef_address_new_address(address, &string);
    if (unlikely(ret < 0))
        SCReturnInt(ret);

    prelude_string_set_ref(string, daddr);

    SCReturnInt(0);
}
示例#8
0
/**
 * \brief Check the threshold of the sigs that match, set actions, break on pass action
 *        This function iterate the packet alerts array, removing those that didn't match
 *        the threshold, and those that match after a signature with the action "pass".
 *        The array is sorted by action priority/order
 * \param de_ctx detection engine context
 * \param det_ctx detection engine thread context
 * \param p pointer to the packet
 */
void PacketAlertFinalize(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p) {
    SCEnter();
    int i = 0;
    Signature *s = NULL;
    SigMatch *sm = NULL;

    while (i < p->alerts.cnt) {
        SCLogDebug("Sig->num: %"PRIu16, p->alerts.alerts[i].num);
        s = de_ctx->sig_array[p->alerts.alerts[i].num];

        int res = PacketAlertHandle(de_ctx, det_ctx, s, p, i);
        if (res > 0) {
            /* Now, if we have an alert, we have to check if we want
             * to tag this session or src/dst host */
            sm = s->sm_lists[DETECT_SM_LIST_TMATCH];
            while (sm) {
                /* tags are set only for alerts */
                sigmatch_table[sm->type].Match(NULL, det_ctx, p, s, sm);
                sm = sm->next;
            }

            if (s->flags & SIG_FLAG_IPONLY) {
                if ((p->flowflags & FLOW_PKT_TOSERVER && !(p->flowflags & FLOW_PKT_TOSERVER_IPONLY_SET)) ||
                    (p->flowflags & FLOW_PKT_TOCLIENT && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET))) {
                    SCLogDebug("testing against \"ip-only\" signatures");

                    if (p->flow != NULL) {
                        /* Update flow flags for iponly */
                        FLOWLOCK_WRLOCK(p->flow);
                        FlowSetIPOnlyFlagNoLock(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0);

                        if (s->action & ACTION_DROP)
                            p->flow->flags |= FLOW_ACTION_DROP;
                        if (s->action & ACTION_REJECT)
                            p->flow->flags |= FLOW_ACTION_DROP;
                        if (s->action & ACTION_REJECT_DST)
                            p->flow->flags |= FLOW_ACTION_DROP;
                        if (s->action & ACTION_REJECT_BOTH)
                            p->flow->flags |= FLOW_ACTION_DROP;
                        if (s->action & ACTION_PASS)
                            p->flow->flags |= FLOW_ACTION_PASS;
                        FLOWLOCK_UNLOCK(p->flow);
                    }
                }
            }

            /* set verdict on packet */
            p->action |= p->alerts.alerts[i].action;

            if (p->action & ACTION_PASS) {
                /* Ok, reset the alert cnt to end in the previous of pass
                 * so we ignore the rest with less prio */
                p->alerts.cnt = i;
                break;
            /* if the signature wants to drop, check if the
             * PACKET_ALERT_FLAG_DROP_FLOW flag is set. */
            } else if (p->action & ACTION_DROP &&
                    ((p->alerts.alerts[i].flags & PACKET_ALERT_FLAG_DROP_FLOW) ||
                         (s->flags & SIG_FLAG_APPLAYER))
                       && p->flow != NULL)
            {
                FLOWLOCK_WRLOCK(p->flow);
                /* This will apply only on IPS mode (check StreamTcpPacket) */
                p->flow->flags |= FLOW_ACTION_DROP;
                FLOWLOCK_UNLOCK(p->flow);
            }
        }

        /* Thresholding removes this alert */
        if (res == 0 || res == 2) {
            PacketAlertRemove(p, i);

            if (p->alerts.cnt == 0)
                break;
        } else {
            i++;
        }
    }

    /* At this point, we should have all the new alerts. Now check the tag
     * keyword context for sessions and hosts */
    TagHandlePacket(de_ctx, det_ctx, p);
}
示例#9
0
/*
 * \brief RunModeFilePcapAuto set up the following thread packet handlers:
 *        - Receive thread (from pcap file)
 *        - Decode thread
 *        - Stream thread
 *        - Detect: If we have only 1 cpu, it will setup one Detect thread
 *                  If we have more than one, it will setup num_cpus - 1
 *                  starting from the second cpu available.
 *        - Outputs thread
 *        By default the threads will use the first cpu available
 *        except the Detection threads if we have more than one cpu.
 *
 * \param de_ctx Pointer to the Detection Engine.
 *
 * \retval 0 If all goes well. (If any problem is detected the engine will
 *           exit()).
 */
int RunModeFilePcapAuto(DetectEngineCtx *de_ctx)
{
    SCEnter();
    char tname[16];
    uint16_t cpu = 0;
    TmModule *tm_module;
    int cuda = 0;
    RunModeInitialize();

    /* Available cpus */
    uint16_t ncpus = UtilCpuGetNumProcessorsOnline();

    char *file = NULL;
    if (ConfGet("pcap-file.file", &file) == 0) {
        SCLogError(SC_ERR_RUNMODE, "Failed retrieving pcap-file from Conf");
        exit(EXIT_FAILURE);
    }
    SCLogDebug("file %s", file);

    TimeModeSetOffline();

#if defined(__SC_CUDA_SUPPORT__)
    if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) {
        cuda = 1;
    }
#endif

    if (cuda == 0) {
        /* create the threads */
        ThreadVars *tv_receivepcap =
            TmThreadCreatePacketHandler("ReceivePcapFile",
                    "packetpool", "packetpool",
                    "detect-queue1", "simple",
                    "pktacqloop");
        if (tv_receivepcap == NULL) {
            printf("ERROR: TmThreadsCreate failed\n");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("ReceivePcapFile");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, file);

        TmThreadSetCPU(tv_receivepcap, RECEIVE_CPU_SET);

        tm_module = TmModuleGetByName("DecodePcapFile");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName DecodePcap failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, NULL);

        tm_module = TmModuleGetByName("StreamTcp");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName StreamTcp failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, (void *)de_ctx);

        TmThreadSetCPU(tv_receivepcap, DECODE_CPU_SET);

        if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }
#if defined(__SC_CUDA_SUPPORT__)
    } else {
        /* create the threads */
        ThreadVars *tv_receivepcap =
            TmThreadCreatePacketHandler("ReceivePcapFile",
                                        "packetpool", "packetpool",
                                        "cuda-pb", "simple",
                                        "pktacqloop");
        if (tv_receivepcap == NULL) {
            printf("ERROR: TmThreadsCreate failed\n");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("ReceivePcapFile");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, file);

        TmThreadSetCPU(tv_receivepcap, RECEIVE_CPU_SET);

        tm_module = TmModuleGetByName("DecodePcapFile");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName DecodePcap failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, NULL);

        TmThreadSetCPU(tv_receivepcap, DECODE_CPU_SET);

        if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }

        ThreadVars *tv_cuda_PB =
            TmThreadCreate("CUDA_PB",
                           "cuda-pb", "simple",
                           "detect-queue1", "simple",
                           "custom", SCCudaPBTmThreadsSlot1, 0);
        if (tv_cuda_PB == NULL) {
            printf("ERROR: TmThreadsCreate failed for CUDA_PB\n");
            exit(EXIT_FAILURE);
        }
        tv_cuda_PB->type = TVT_PPT;

        tm_module = TmModuleGetByName("CudaPacketBatcher");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName CudaPacketBatcher failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_cuda_PB, tm_module, de_ctx);

        tm_module = TmModuleGetByName("StreamTcp");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName StreamTcp failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_cuda_PB, tm_module, NULL);

        if (TmThreadSpawn(tv_cuda_PB) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }

#endif
    }

    /* start with cpu 1 so that if we're creating an odd number of detect
     * threads we're not creating the most on CPU0. */
    if (ncpus > 0)
        cpu = 1;

    /* always create at least one thread */
    int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET);
    if (thread_max == 0)
        thread_max = ncpus * threading_detect_ratio;
    if (thread_max < 1)
        thread_max = 1;

    int thread;
    for (thread = 0; thread < thread_max; thread++) {
        snprintf(tname, sizeof(tname), "Detect%"PRIu16, thread+1);

        char *thread_name = SCStrdup(tname);
        if (unlikely(thread_name == NULL)) {
            printf("ERROR: Can not strdup thread name\n");
            exit(EXIT_FAILURE);
        }
        SCLogDebug("Assigning %s affinity to cpu %u", thread_name, cpu);

        ThreadVars *tv_detect_ncpu =
            TmThreadCreatePacketHandler(thread_name,
                                        "detect-queue1", "simple",
                                        "alert-queue1", "simple",
                                        "1slot");
        if (tv_detect_ncpu == NULL) {
            printf("ERROR: TmThreadsCreate failed\n");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("Detect");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName Detect failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, (void *)de_ctx);

        TmThreadSetCPU(tv_detect_ncpu, DETECT_CPU_SET);

        char *thread_group_name = SCStrdup("Detect");
        if (unlikely(thread_group_name == NULL)) {
            printf("Error allocating memory\n");
            exit(EXIT_FAILURE);
        }
        tv_detect_ncpu->thread_group_name = thread_group_name;

        if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }

        if ((cpu + 1) == ncpus)
            cpu = 0;
        else
            cpu++;
    }

    ThreadVars *tv_outputs =
        TmThreadCreatePacketHandler("Outputs",
                                    "alert-queue1", "simple",
                                    "packetpool", "packetpool",
                                    "varslot");
    if (tv_outputs == NULL) {
        printf("ERROR: TmThreadCreatePacketHandler for Outputs failed\n");
        exit(EXIT_FAILURE);
    }

    SetupOutputs(tv_outputs);

    TmThreadSetCPU(tv_outputs, OUTPUT_CPU_SET);

    if (TmThreadSpawn(tv_outputs) != TM_ECODE_OK) {
        printf("ERROR: TmThreadSpawn failed\n");
        exit(EXIT_FAILURE);
    }

    return 0;
}
示例#10
0
/**
 * \brief   Thread entry function for reading ERF records from a DAG card.
 *
 *          Reads a new ERF record the DAG input buffer and copies it to
 *          an internal Suricata packet buffer -- similar to the way the
 *          pcap packet handler works.
 *
 *          We create new packet structures using PacketGetFromQueueOrAlloc
 *          for each packet between the top and btm pointers except for
 *          the first packet for which a Packet buffer is provided
 *          from the packetpool.
 *
 *          We always read up to dag_max_read_packets ERF packets from the
 *          DAG buffer, but we might read less. This differs from the
 *          ReceivePcap handler -- it will only read pkts up to a maximum
 *          of either the packetpool count or the pcap_max_read_packets.
 *
 * \param   tv pointer to ThreadVars
 * \param   p data pointer
 * \param   data
 * \param   pq pointer to the PacketQueue (not used here)
 * \param   postpq
 * \retval  TM_ECODE_FAILED on failure and TM_ECODE_OK on success.
 * \note    We also use the packetpool hack first used in the source-pcap
 *          handler so we don't keep producing packets without any dying.
 *          This implies that if we are in this situation we run the risk
 *          of dropping packets at the interface.
 */
TmEcode
ReceiveErfDag(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq,
               PacketQueue *postpq)
{
    SCEnter();

    uint16_t packet_q_len = 0;
    uint32_t diff = 0;
    int      err;
    uint8_t  *top = NULL;
    uint32_t pkts_read = 0;

    assert(p);
    assert(pq);
    assert(postpq);

    ErfDagThreadVars *ewtn = (ErfDagThreadVars *)data;

    /* NOTE/JNM: Hack copied from source-pcap.c
     *
     * Make sure we have at least one packet in the packet pool, to
     * prevent us from alloc'ing packets at line rate
     */
    while (packet_q_len == 0) {
        packet_q_len = PacketPoolSize();
        if (packet_q_len == 0) {
            PacketPoolWait();
        }
    }

    if (postpq == NULL) {
        ewtn->dag_max_read_packets = 1;
    }

    while(pkts_read == 0)
    {
	    if (suricata_ctl_flags != 0) {
            break;
        }

        /* NOTE/JNM: This might not work well if we start restricting the
	     * number of ERF records processed per call to a small number as
	     * the over head required here could exceed the time it takes to
	     * process a small number of ERF records.
	     *
	     * XXX/JNM: Possibly process the DAG stream buffer first if there
	     * are ERF packets or else call dag_advance_stream and then process
	     * the DAG stream buffer.
	     */
	    top = dag_advance_stream(ewtn->dagfd, ewtn->dagstream, &(ewtn->btm));

	    if (NULL == top)
	    {
	        if((ewtn->dagstream & 0x1) && (errno == EAGAIN)) {
	            usleep(10 * 1000);
	            ewtn->btm = ewtn->top;
                continue;
	        }
	        else {
	            SCLogError(SC_ERR_ERF_DAG_STREAM_READ_FAILED,
	                       "Failed to read from stream: %d, DAG: %s when using dag_advance_stream",
	                       ewtn->dagstream, ewtn->dagname);
	            SCReturnInt(TM_ECODE_FAILED);
	        }
	    }

	    diff = top - ewtn->btm;
	    if (diff == 0)
	    {
	        continue;
	    }

	    assert(diff >= dag_record_size);

	    err = ProcessErfDagRecords(ewtn, p, top, postpq, &pkts_read);

        if (err == TM_ECODE_FAILED) {
             SCLogError(SC_ERR_ERF_DAG_STREAM_READ_FAILED,
                   "Failed to read from stream: %d, DAG: %s",
                   ewtn->dagstream, ewtn->dagname);
            ReceiveErfDagCloseStream(ewtn->dagfd, ewtn->dagstream);
            SCReturnInt(err);
        }
    }

    SCLogDebug("Read %d records from stream: %d, DAG: %s",
        pkts_read, ewtn->dagstream, ewtn->dagname);

    if (suricata_ctl_flags != 0) {
        SCReturnInt(TM_ECODE_FAILED);
    }

    SCReturnInt(err);
}
示例#11
0
TmEcode ProcessErfDagRecords(ErfDagThreadVars *ewtn,
                             Packet *p,
                             uint8_t* top,
                             PacketQueue *postpq,
                             uint32_t *pkts_read)
{
    SCEnter();

    int     err = 0;
    dag_record_t* dr = NULL;
    char    *prec = NULL;
    int     rlen;

    *pkts_read = 0;

    while(((top-(ewtn->btm))>=dag_record_size) &&
          ((*pkts_read)<(ewtn->dag_max_read_packets)))
    {
        prec = (char*)ewtn->btm;
        dr = (dag_record_t*)prec;

        rlen = ntohs(dr->rlen);

        if (rlen == 20) {
            rlen = 28;
            SCLogWarning(SC_WARN_ERF_DAG_REC_LEN_CHANGED,
                "Warning, adjusted the length of ERF from 20 to 28 on stream: %d, DAG: %s",
                ewtn->dagstream, ewtn->dagname);
        }

        /* If we don't have enough data to finsih processing this ERF record
         * return and maybe next time we will.
         */
        if ((top-(ewtn->btm)) < rlen)
            SCReturnInt(TM_ECODE_OK);

        p = p ? p : PacketGetFromQueueOrAlloc();

        if (p == NULL) {
            SCLogError(SC_ERR_MEM_ALLOC,
                       "Failed to allocate a Packet on stream: %d, DAG: %s",
                       ewtn->dagstream, ewtn->dagname);
            SCReturnInt(TM_ECODE_FAILED);
        }

        err = ProcessErfDagRecord(ewtn, prec, p);

        if (err != TM_ECODE_OK)
            SCReturnInt(err);

        ewtn->btm += rlen;

        /* XXX/JNM: Hack to get around the fact that the first Packet from
         * Suricata is added explicitly by the Slot code and shouldn't go
         * onto the post queue -- else it is added twice to the next queue.
         */
        if (*pkts_read) {
            PacketEnqueue(postpq, p);
        }

        (*pkts_read)++;

        p = NULL;
    }

    SCReturnInt(TM_ECODE_OK);
}
static uint8_t *DetectEngineSMTPGetBufferForTX(uint64_t tx_id,
                                               DetectEngineCtx *de_ctx,
                                               DetectEngineThreadCtx *det_ctx,
                                               Flow *f, File *curr_file,
                                               uint8_t flags,
                                               uint32_t *buffer_len,
                                               uint32_t *stream_start_offset)
{
    SCEnter();
    int index = 0;
    uint8_t *buffer = NULL;
    *buffer_len = 0;
    *stream_start_offset = 0;
    FileData *curr_chunk = NULL;

    if (det_ctx->smtp_buffers_list_len == 0) {
        if (SMTPCreateSpace(det_ctx, 1) < 0)
            goto end;
        index = 0;

        if (det_ctx->smtp_buffers_list_len == 0) {
            det_ctx->smtp_start_tx_id = tx_id;
        }
        det_ctx->smtp_buffers_list_len++;
    } else {
        if ((tx_id - det_ctx->smtp_start_tx_id) < det_ctx->smtp_buffers_list_len) {
            if (det_ctx->smtp[(tx_id - det_ctx->smtp_start_tx_id)].buffer_len != 0) {
                *buffer_len = det_ctx->smtp[(tx_id - det_ctx->smtp_start_tx_id)].buffer_len;
                *stream_start_offset = det_ctx->smtp[(tx_id - det_ctx->smtp_start_tx_id)].offset;
                buffer = det_ctx->smtp[(tx_id - det_ctx->smtp_start_tx_id)].buffer;

                SCReturnPtr(buffer, "uint8_t");
            }
        } else {
            if (SMTPCreateSpace(det_ctx, (tx_id - det_ctx->smtp_start_tx_id) + 1) < 0)
                goto end;

            if (det_ctx->smtp_buffers_list_len == 0) {
                det_ctx->smtp_start_tx_id = tx_id;
            }
            det_ctx->smtp_buffers_list_len++;
        }
        index = (tx_id - det_ctx->smtp_start_tx_id);
    }

    SCLogDebug("smtp_config.content_limit %u, smtp_config.content_inspect_min_size %u",
                smtp_config.content_limit, smtp_config.content_inspect_min_size);

    SCLogDebug("file %p size %"PRIu64", state %d", curr_file, curr_file->content_len_so_far, curr_file->state);

    /* no new data */
    if (curr_file->content_inspected == curr_file->content_len_so_far) {
        SCLogDebug("no new data");
        goto end;
    }

    curr_chunk = curr_file->chunks_head;
    if (curr_chunk == NULL) {
        SCLogDebug("no data chunks to inspect for this transaction");
        goto end;
    }

    if ((smtp_config.content_limit == 0 ||
         curr_file->content_len_so_far < smtp_config.content_limit) &&
        curr_file->content_len_so_far < smtp_config.content_inspect_min_size &&
        !(flags & STREAM_EOF) && !(curr_file->state > FILE_STATE_OPENED)) {
        SCLogDebug("we still haven't seen the entire content. "
                   "Let's defer content inspection till we see the "
                   "entire content.");
        goto end;
    }

    int first = 1;
    curr_chunk = curr_file->chunks_head;
    while (curr_chunk != NULL) {
        /* see if we can filter out chunks */
        if (curr_file->content_inspected > 0) {
            if (curr_chunk->stream_offset < curr_file->content_inspected) {
                if ((curr_file->content_inspected - curr_chunk->stream_offset) > smtp_config.content_inspect_window) {
                    curr_chunk = curr_chunk->next;
                    continue;
                } else {
                    /* include this one */
                }
            } else {
                /* include this one */
            }
        }

        if (first) {
            det_ctx->smtp[index].offset = curr_chunk->stream_offset;
            first = 0;
        }

        /* see if we need to grow the buffer */
        if (det_ctx->smtp[index].buffer == NULL || (det_ctx->smtp[index].buffer_len + curr_chunk->len) > det_ctx->smtp[index].buffer_size) {
            void *ptmp;
            det_ctx->smtp[index].buffer_size += curr_chunk->len * 2;

            if ((ptmp = SCRealloc(det_ctx->smtp[index].buffer, det_ctx->smtp[index].buffer_size)) == NULL) {
                SCFree(det_ctx->smtp[index].buffer);
                det_ctx->smtp[index].buffer = NULL;
                det_ctx->smtp[index].buffer_size = 0;
                det_ctx->smtp[index].buffer_len = 0;
                goto end;
            }
            det_ctx->smtp[index].buffer = ptmp;
        }
        memcpy(det_ctx->smtp[index].buffer + det_ctx->smtp[index].buffer_len, curr_chunk->data, curr_chunk->len);
        det_ctx->smtp[index].buffer_len += curr_chunk->len;

        curr_chunk = curr_chunk->next;
    }

    /* updat inspected tracker */
    curr_file->content_inspected = curr_file->chunks_tail->stream_offset + curr_file->chunks_tail->len;
    SCLogDebug("curr_file->content_inspected now %"PRIu64, curr_file->content_inspected);

    buffer = det_ctx->smtp[index].buffer;
    *buffer_len = det_ctx->smtp[index].buffer_len;
    *stream_start_offset = det_ctx->smtp[index].offset;

end:
    SCLogDebug("buffer %p, len %u", buffer, *buffer_len);
    SCReturnPtr(buffer, "uint8_t");
}
示例#13
0
/**
 *  \brief Main Napatech reading Loop function
 */
TmEcode NapatechStreamLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    int32_t status;
    char errbuf[100];
    uint64_t pkt_ts;
    NtNetBuf_t packet_buffer;
    NapatechThreadVars *ntv = (NapatechThreadVars *)data;
    NtNetRx_t stat_cmd;

    SCLogInfo("Opening NAPATECH Stream: %lu for processing", ntv->stream_id);

    if ((status = NT_NetRxOpen(&(ntv->rx_stream), "SuricataStream", NT_NET_INTERFACE_PACKET, ntv->stream_id, ntv->hba)) != NT_SUCCESS) {
        NT_ExplainError(status, errbuf, sizeof(errbuf));
        SCLogError(SC_ERR_NAPATECH_OPEN_FAILED, "Failed to open NAPATECH Stream: %lu - %s", ntv->stream_id, errbuf);
        SCFree(ntv);
        SCReturnInt(TM_ECODE_FAILED);
    }

    stat_cmd.cmd = NT_NETRX_READ_CMD_STREAM_DROP;

    SCLogInfo("Napatech Packet Stream Loop Started for Stream ID: %lu", ntv->stream_id);

    TmSlot *s = (TmSlot *)slot;
    ntv->slot = s->slot_next;

    while (!(suricata_ctl_flags & (SURICATA_STOP | SURICATA_KILL))) {
        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        PacketPoolWait();

        /*
         * Napatech returns packets 1 at a time
         */
        status = NT_NetRxGet(ntv->rx_stream, &packet_buffer, 1000);
        if (unlikely(status == NT_STATUS_TIMEOUT || status == NT_STATUS_TRYAGAIN)) {
            /*
             * no frames currently available
             */
            continue;
        } else if (unlikely(status != NT_SUCCESS)) {
            SCLogError(SC_ERR_NAPATECH_STREAM_NEXT_FAILED,
                       "Failed to read from Napatech Stream: %lu",
                       ntv->stream_id);
            SCReturnInt(TM_ECODE_FAILED);
        }

        Packet *p = PacketGetFromQueueOrAlloc();
        if (unlikely(p == NULL)) {
            NT_NetRxRelease(ntv->rx_stream, packet_buffer);
            SCReturnInt(TM_ECODE_FAILED);
        }

        pkt_ts = NT_NET_GET_PKT_TIMESTAMP(packet_buffer);

        /*
         * Handle the different timestamp forms that the napatech cards could use
         *   - NT_TIMESTAMP_TYPE_NATIVE is not supported due to having an base of 0 as opposed to NATIVE_UNIX which has a base of 1/1/1970
         */
        switch(NT_NET_GET_PKT_TIMESTAMP_TYPE(packet_buffer)) {
            case NT_TIMESTAMP_TYPE_NATIVE_UNIX:
                p->ts.tv_sec = pkt_ts / 100000000;
                p->ts.tv_usec = ((pkt_ts % 100000000) / 100) + (pkt_ts % 100) > 50 ? 1 : 0;
                break;
            case NT_TIMESTAMP_TYPE_PCAP:
                p->ts.tv_sec = pkt_ts >> 32;
                p->ts.tv_usec = pkt_ts & 0xFFFFFFFF;
                break;
            case NT_TIMESTAMP_TYPE_PCAP_NANOTIME:
                p->ts.tv_sec = pkt_ts >> 32;
                p->ts.tv_usec = ((pkt_ts & 0xFFFFFFFF) / 1000) + (pkt_ts % 1000) > 500 ? 1 : 0;
                break;
            case NT_TIMESTAMP_TYPE_NATIVE_NDIS:
                /* number of seconds between 1/1/1601 and 1/1/1970 */
                p->ts.tv_sec = (pkt_ts / 100000000) - 11644473600;
                p->ts.tv_usec = ((pkt_ts % 100000000) / 100) + (pkt_ts % 100) > 50 ? 1 : 0;
                break;
            default:
                SCLogError(SC_ERR_NAPATECH_TIMESTAMP_TYPE_NOT_SUPPORTED,
                           "Packet from Napatech Stream: %lu does not have a supported timestamp format",
                           ntv->stream_id);
                NT_NetRxRelease(ntv->rx_stream, packet_buffer);
                SCReturnInt(TM_ECODE_FAILED);
        }

        SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
        p->datalink = LINKTYPE_ETHERNET;

        ntv->pkts++;
        ntv->bytes += NT_NET_GET_PKT_WIRE_LENGTH(packet_buffer);

        // Update drop counter
        if (unlikely((status = NT_NetRxRead(ntv->rx_stream, &stat_cmd)) != NT_SUCCESS))
        {
            NT_ExplainError(status, errbuf, sizeof(errbuf));
            SCLogWarning(SC_ERR_NAPATECH_STAT_DROPS_FAILED, "Couldn't retrieve drop statistics from the RX stream: %lu - %s", ntv->stream_id, errbuf);
        }
        else
        {
            ntv->drops += stat_cmd.u.streamDrop.pktsDropped;
        }

        if (unlikely(PacketCopyData(p, (uint8_t *)NT_NET_GET_PKT_L2_PTR(packet_buffer), NT_NET_GET_PKT_WIRE_LENGTH(packet_buffer)))) {
            TmqhOutputPacketpool(ntv->tv, p);
            NT_NetRxRelease(ntv->rx_stream, packet_buffer);
            SCReturnInt(TM_ECODE_FAILED);
        }

        if (unlikely(TmThreadsSlotProcessPkt(ntv->tv, ntv->slot, p) != TM_ECODE_OK)) {
            TmqhOutputPacketpool(ntv->tv, p);
            NT_NetRxRelease(ntv->rx_stream, packet_buffer);
            SCReturnInt(TM_ECODE_FAILED);
        }

        NT_NetRxRelease(ntv->rx_stream, packet_buffer);
        StatsSyncCountersIfSignalled(tv);
    }

    SCReturnInt(TM_ECODE_OK);
}
/**
 *  \internal
 *  \brief Apply the nocase keyword to the last pattern match, either content or uricontent
 *  \param det_ctx detection engine ctx
 *  \param s signature
 *  \param nullstr should be null
 *  \retval 0 ok
 *  \retval -1 failure
 */
static int DetectTransformCompressWhitespaceSetup (DetectEngineCtx *de_ctx, Signature *s, const char *nullstr)
{
    SCEnter();
    int r = DetectSignatureAddTransform(s, DETECT_TRANSFORM_COMPRESS_WHITESPACE);
    SCReturnInt(r);
}
示例#15
0
/**
 *  \param de_ctx detection engine, can be NULL
 */
int RunModeSetIPSAutoFp(DetectEngineCtx *de_ctx,
                        ConfigIPSParserFunc ConfigParser,
                        char *recv_mod_name,
                        char *verdict_mod_name,
                        char *decode_mod_name)
{
    SCEnter();
    char tname[TM_THREAD_NAME_MAX];
    char qname[TM_QUEUE_NAME_MAX];
    TmModule *tm_module ;
    char *cur_queue = NULL;
    char *queues = NULL;
    int thread;

    /* Available cpus */
    uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
    int nqueue = LiveGetDeviceCount();

    int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET);
    /* always create at least one thread */
    if (thread_max == 0)
        thread_max = ncpus * threading_detect_ratio;
    if (thread_max < 1)
        thread_max = 1;

    RunmodeSetFlowStreamAsync();

    queues = RunmodeAutoFpCreatePickupQueuesString(thread_max);
    if (queues == NULL) {
        SCLogError(SC_ERR_RUNMODE, "RunmodeAutoFpCreatePickupQueuesString failed");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < nqueue; i++) {
    /* create the threads */
        cur_queue = LiveGetDeviceName(i);
        if (cur_queue == NULL) {
            SCLogError(SC_ERR_RUNMODE, "invalid queue number");
            exit(EXIT_FAILURE);
        }
        memset(tname, 0, sizeof(tname));
        snprintf(tname, sizeof(tname), "Recv-Q%s", cur_queue);

        char *thread_name = SCStrdup(tname);
        if (unlikely(thread_name == NULL)) {
            SCLogError(SC_ERR_RUNMODE, "thread name creation failed");
            exit(EXIT_FAILURE);
        }
        ThreadVars *tv_receive =
            TmThreadCreatePacketHandler(thread_name,
                    "packetpool", "packetpool",
                    queues, "flow", "pktacqloop");
        if (tv_receive == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
            exit(EXIT_FAILURE);
        }
        TmModule *tm_module = TmModuleGetByName(recv_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName failed for %s", recv_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receive, tm_module, (void *) ConfigParser(i));

        tm_module = TmModuleGetByName(decode_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName %s failed", decode_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receive, tm_module, NULL);

        TmThreadSetCPU(tv_receive, RECEIVE_CPU_SET);

        if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }

    }
    for (thread = 0; thread < thread_max; thread++) {
        snprintf(tname, sizeof(tname), "Detect%"PRIu16, thread+1);
        snprintf(qname, sizeof(qname), "pickup%"PRIu16, thread+1);

        SCLogDebug("tname %s, qname %s", tname, qname);

        char *thread_name = SCStrdup(tname);
        if (unlikely(thread_name == NULL)) {
            SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate thread name");
            exit(EXIT_FAILURE);
        }
        ThreadVars *tv_detect_ncpu =
            TmThreadCreatePacketHandler(thread_name,
                                        qname, "flow",
                                        "verdict-queue", "simple",
                                        "varslot");
        if (tv_detect_ncpu == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
            exit(EXIT_FAILURE);
        }
        TmModule *tm_module = TmModuleGetByName("StreamTcp");
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName StreamTcp failed");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL);

        if (de_ctx != NULL) {
            tm_module = TmModuleGetByName("Detect");
            if (tm_module == NULL) {
                SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName Detect failed");
                exit(EXIT_FAILURE);
            }
            TmSlotSetFuncAppendDelayed(tv_detect_ncpu, tm_module,
                    (void *)de_ctx, de_ctx->delayed_detect);
        }

        TmThreadSetCPU(tv_detect_ncpu, DETECT_CPU_SET);

        SetupOutputs(tv_detect_ncpu);

        char *thread_group_name = SCStrdup("Detect");
        if (unlikely(thread_group_name == NULL)) {
            SCLogError(SC_ERR_RUNMODE, "Error allocating memory");
            exit(EXIT_FAILURE);
        }
        tv_detect_ncpu->thread_group_name = thread_group_name;

        if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }
    }

    /* create the threads */
    for (int i = 0; i < nqueue; i++) {
        memset(tname, 0, sizeof(tname));
        snprintf(tname, sizeof(tname), "Verdict%"PRIu16, i);

        char *thread_name = SCStrdup(tname);
        if (unlikely(thread_name == NULL)) {
            SCLogError(SC_ERR_RUNMODE, "Error allocating memory");
            exit(EXIT_FAILURE);
        }
        ThreadVars *tv_verdict =
            TmThreadCreatePacketHandler(thread_name,
                                        "verdict-queue", "simple",
                                        "packetpool", "packetpool",
                                        "varslot");
        if (tv_verdict == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName(verdict_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName %s failed", verdict_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_verdict, tm_module, (void *)ConfigParser(i));

        tm_module = TmModuleGetByName("RespondReject");
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName for RespondReject failed");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_verdict, tm_module, NULL);

        TmThreadSetCPU(tv_verdict, VERDICT_CPU_SET);

        if (TmThreadSpawn(tv_verdict) != TM_ECODE_OK) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }
    }

    SCFree(queues);
    return 0;
}
示例#16
0
/**
 * \brief RunModeFilePcapAuto set up the following thread packet handlers:
 *        - Receive thread (from pcap file)
 *        - Decode thread
 *        - Stream thread
 *        - Detect: If we have only 1 cpu, it will setup one Detect thread
 *                  If we have more than one, it will setup num_cpus - 1
 *                  starting from the second cpu available.
 *        - Outputs thread
 *        By default the threads will use the first cpu available
 *        except the Detection threads if we have more than one cpu.
 *
 * \param de_ctx Pointer to the Detection Engine
 *
 * \retval 0 If all goes well. (If any problem is detected the engine will
 *           exit()).
 */
int RunModeFilePcapAutoFp(DetectEngineCtx *de_ctx)
{
    SCEnter();
    char tname[12];
    char qname[12];
    uint16_t cpu = 0;
    char queues[2048] = "";

    RunModeInitialize();

    /* Available cpus */
    uint16_t ncpus = UtilCpuGetNumProcessorsOnline();

    /* start with cpu 1 so that if we're creating an odd number of detect
     * threads we're not creating the most on CPU0. */
    if (ncpus > 0)
        cpu = 1;

    /* always create at least one thread */
    int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET);
    if (thread_max == 0)
        thread_max = ncpus * threading_detect_ratio;
    if (thread_max < 1)
        thread_max = 1;

    int thread;
    for (thread = 0; thread < thread_max; thread++) {
        if (strlen(queues) > 0)
            strlcat(queues, ",", sizeof(queues));

        snprintf(qname, sizeof(qname), "pickup%"PRIu16, thread+1);
        strlcat(queues, qname, sizeof(queues));
    }
    SCLogDebug("queues %s", queues);

    char *file = NULL;
    if (ConfGet("pcap-file.file", &file) == 0) {
        SCLogError(SC_ERR_RUNMODE, "Failed retrieving pcap-file from Conf");
        exit(EXIT_FAILURE);
    }
    SCLogDebug("file %s", file);

    TimeModeSetOffline();

    /* create the threads */
    ThreadVars *tv_receivepcap =
        TmThreadCreatePacketHandler("ReceivePcapFile",
                                    "packetpool", "packetpool",
                                    queues, "flow",
                                    "pktacqloop");
    if (tv_receivepcap == NULL) {
        printf("ERROR: TmThreadsCreate failed\n");
        exit(EXIT_FAILURE);
    }
    TmModule *tm_module = TmModuleGetByName("ReceivePcapFile");
    if (tm_module == NULL) {
        printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
        exit(EXIT_FAILURE);
    }
    TmSlotSetFuncAppend(tv_receivepcap, tm_module, file);

    tm_module = TmModuleGetByName("DecodePcapFile");
    if (tm_module == NULL) {
        printf("ERROR: TmModuleGetByName DecodePcap failed\n");
        exit(EXIT_FAILURE);
    }
    TmSlotSetFuncAppend(tv_receivepcap, tm_module, NULL);

    if (threading_set_cpu_affinity) {
        TmThreadSetCPUAffinity(tv_receivepcap, 0);
        if (ncpus > 1)
            TmThreadSetThreadPriority(tv_receivepcap, PRIO_MEDIUM);
    }

    if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
        printf("ERROR: TmThreadSpawn failed\n");
        exit(EXIT_FAILURE);
    }

    for (thread = 0; thread < thread_max; thread++) {
        snprintf(tname, sizeof(tname), "Detect%"PRIu16, thread+1);
        snprintf(qname, sizeof(qname), "pickup%"PRIu16, thread+1);

        SCLogDebug("tname %s, qname %s", tname, qname);

        char *thread_name = SCStrdup(tname);
        if (unlikely(thread_name == NULL)) {
            printf("ERROR: Can not strdup thread name\n");
            exit(EXIT_FAILURE);
        }
        SCLogDebug("Assigning %s affinity to cpu %u", thread_name, cpu);

        ThreadVars *tv_detect_ncpu =
            TmThreadCreatePacketHandler(thread_name,
                                        qname, "flow",
                                        "packetpool", "packetpool",
                                        "varslot");
        if (tv_detect_ncpu == NULL) {
            printf("ERROR: TmThreadsCreate failed\n");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("StreamTcp");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName StreamTcp failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL);

        tm_module = TmModuleGetByName("Detect");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName Detect failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, (void *)de_ctx);

        if (threading_set_cpu_affinity) {
            TmThreadSetCPUAffinity(tv_detect_ncpu, (int)cpu);
            /* If we have more than one core/cpu, the first Detect thread
             * (at cpu 0) will have less priority (higher 'nice' value)
             * In this case we will set the thread priority to +10 (default is 0)
             */
            if (cpu == 0 && ncpus > 1) {
                TmThreadSetThreadPriority(tv_detect_ncpu, PRIO_LOW);
            } else if (ncpus > 1) {
                TmThreadSetThreadPriority(tv_detect_ncpu, PRIO_MEDIUM);
            }
        }

        char *thread_group_name = SCStrdup("Detect");
        if (unlikely(thread_group_name == NULL)) {
            printf("Error allocating memory\n");
            exit(EXIT_FAILURE);
        }
        tv_detect_ncpu->thread_group_name = thread_group_name;

        /* add outputs as well */
        SetupOutputs(tv_detect_ncpu);

        if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }

        if ((cpu + 1) == ncpus)
            cpu = 0;
        else
            cpu++;
    }

    return 0;
}
示例#17
0
static void
DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
    SCEnter();

    uint8_t *orig_pkt = pkt;
    uint8_t nh = 0; /* careful, 0 is actually a real type */
    uint16_t hdrextlen = 0;
    uint16_t plen;
    char dstopts = 0;
    char exthdr_fh_done = 0;
    int hh = 0;
    int rh = 0;
    int eh = 0;
    int ah = 0;

    nh = IPV6_GET_NH(p);
    plen = len;

    while(1)
    {
        /* No upper layer, but we do have data. Suspicious. */
        if (nh == IPPROTO_NONE && plen > 0) {
            ENGINE_SET_EVENT(p, IPV6_DATA_AFTER_NONE_HEADER);
            SCReturn;
        }

        if (plen < 2) { /* minimal needed in a hdr */
            SCReturn;
        }

        switch(nh)
        {
            case IPPROTO_TCP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeTCP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_UDP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeUDP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_ICMPV6:
                IPV6_SET_L4PROTO(p,nh);
                DecodeICMPV6(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_SCTP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeSCTP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_ROUTING:
                IPV6_SET_L4PROTO(p,nh);
                hdrextlen = 8 + (*(pkt+1) * 8);  /* 8 bytes + length in 8 octet units */

                SCLogDebug("hdrextlen %"PRIu8, hdrextlen);

                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if (rh) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_RH);
                    /* skip past this extension so we can continue parsing the rest
                     * of the packet */
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                rh = 1;
                IPV6_EXTHDR_SET_RH(p);

                uint8_t ip6rh_type = *(pkt + 2);
                if (ip6rh_type == 0) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_RH_TYPE_0);
                }
                p->ip6eh.rh_type = ip6rh_type;

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;

            case IPPROTO_HOPOPTS:
            case IPPROTO_DSTOPTS:
            {
                IPV6OptHAO hao_s, *hao = &hao_s;
                IPV6OptRA ra_s, *ra = &ra_s;
                IPV6OptJumbo jumbo_s, *jumbo = &jumbo_s;
                uint16_t optslen = 0;

                IPV6_SET_L4PROTO(p,nh);
                hdrextlen =  (*(pkt+1) + 1) << 3;
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                uint8_t *ptr = pkt + 2; /* +2 to go past nxthdr and len */

                /* point the pointers to right structures
                 * in Packet. */
                if (nh == IPPROTO_HOPOPTS) {
                    if (hh) {
                        ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_HH);
                        /* skip past this extension so we can continue parsing the rest
                         * of the packet */
                        nh = *pkt;
                        pkt += hdrextlen;
                        plen -= hdrextlen;
                        break;
                    }

                    hh = 1;

                    optslen = ((*(pkt + 1) + 1 ) << 3) - 2;
                }
                else if (nh == IPPROTO_DSTOPTS)
                {
                    if (dstopts == 0) {
                        optslen = ((*(pkt + 1) + 1 ) << 3) - 2;
                        dstopts = 1;
                    } else if (dstopts == 1) {
                        optslen = ((*(pkt + 1) + 1 ) << 3) - 2;
                        dstopts = 2;
                    } else {
                        ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_DH);
                        /* skip past this extension so we can continue parsing the rest
                         * of the packet */
                        nh = *pkt;
                        pkt += hdrextlen;
                        plen -= hdrextlen;
                        break;
                    }
                }

                if (optslen > plen) {
                    /* since the packet is long enough (we checked
                     * plen against hdrlen, the optlen must be malformed. */
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
                    /* skip past this extension so we can continue parsing the rest
                     * of the packet */
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }
/** \todo move into own function to loaded on demand */
                uint16_t padn_cnt = 0;
                uint16_t other_cnt = 0;
                uint16_t offset = 0;
                while(offset < optslen)
                {
                    if (*ptr == IPV6OPT_PAD1)
                    {
                        padn_cnt++;
                        offset++;
                        ptr++;
                        continue;
                    }

                    if (offset + 1 >= optslen) {
                        ENGINE_SET_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
                        break;
                    }

                    /* length field for each opt */
                    uint8_t ip6_optlen = *(ptr + 1);

                    /* see if the optlen from the packet fits the total optslen */
                    if ((offset + 1 + ip6_optlen) > optslen) {
                        ENGINE_SET_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
                        break;
                    }

                    if (*ptr == IPV6OPT_PADN) /* PadN */
                    {
                        //printf("PadN option\n");
                        padn_cnt++;

                        /* a zero padN len would be weird */
                        if (ip6_optlen == 0)
                            ENGINE_SET_EVENT(p, IPV6_EXTHDR_ZERO_LEN_PADN);
                    }
                    else if (*ptr == IPV6OPT_RA) /* RA */
                    {
                        ra->ip6ra_type = *(ptr);
                        ra->ip6ra_len  = ip6_optlen;

                        if (ip6_optlen < sizeof(ra->ip6ra_value)) {
                            ENGINE_SET_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
                            break;
                        }

                        memcpy(&ra->ip6ra_value, (ptr + 2), sizeof(ra->ip6ra_value));
                        ra->ip6ra_value = SCNtohs(ra->ip6ra_value);
                        //printf("RA option: type %" PRIu32 " len %" PRIu32 " value %" PRIu32 "\n",
                        //    ra->ip6ra_type, ra->ip6ra_len, ra->ip6ra_value);
                        other_cnt++;
                    }
                    else if (*ptr == IPV6OPT_JUMBO) /* Jumbo */
                    {
                        jumbo->ip6j_type = *(ptr);
                        jumbo->ip6j_len  = ip6_optlen;

                        if (ip6_optlen < sizeof(jumbo->ip6j_payload_len)) {
                            ENGINE_SET_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
                            break;
                        }

                        memcpy(&jumbo->ip6j_payload_len, (ptr+2), sizeof(jumbo->ip6j_payload_len));
                        jumbo->ip6j_payload_len = SCNtohl(jumbo->ip6j_payload_len);
                        //printf("Jumbo option: type %" PRIu32 " len %" PRIu32 " payload len %" PRIu32 "\n",
                        //    jumbo->ip6j_type, jumbo->ip6j_len, jumbo->ip6j_payload_len);
                    }
                    else if (*ptr == IPV6OPT_HAO) /* HAO */
                    {
                        hao->ip6hao_type = *(ptr);
                        hao->ip6hao_len  = ip6_optlen;

                        if (ip6_optlen < sizeof(hao->ip6hao_hoa)) {
                            ENGINE_SET_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
                            break;
                        }

                        memcpy(&hao->ip6hao_hoa, (ptr+2), sizeof(hao->ip6hao_hoa));
                        //printf("HAO option: type %" PRIu32 " len %" PRIu32 " ",
                        //    hao->ip6hao_type, hao->ip6hao_len);
                        //char addr_buf[46];
                        //PrintInet(AF_INET6, (char *)&(hao->ip6hao_hoa),
                        //    addr_buf,sizeof(addr_buf));
                        //printf("home addr %s\n", addr_buf);
                        other_cnt++;
                    } else {
                        if (nh == IPPROTO_HOPOPTS)
                            ENGINE_SET_EVENT(p, IPV6_HOPOPTS_UNKNOWN_OPT);
                        else
                            ENGINE_SET_EVENT(p, IPV6_DSTOPTS_UNKNOWN_OPT);

                        other_cnt++;
                    }
                    uint16_t optlen = (*(ptr + 1) + 2);
                    ptr += optlen; /* +2 for opt type and opt len fields */
                    offset += optlen;
                }
                /* flag packets that have only padding */
                if (padn_cnt > 0 && other_cnt == 0) {
                    if (nh == IPPROTO_HOPOPTS)
                        ENGINE_SET_EVENT(p, IPV6_HOPOPTS_ONLY_PADDING);
                    else
                        ENGINE_SET_EVENT(p, IPV6_DSTOPTS_ONLY_PADDING);
                }

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }

            case IPPROTO_FRAGMENT:
            {
                IPV6_SET_L4PROTO(p,nh);
                /* store the offset of this extension into the packet
                 * past the ipv6 header. We use it in defrag for creating
                 * a defragmented packet without the frag header */
                if (exthdr_fh_done == 0) {
                    p->ip6eh.fh_offset = pkt - orig_pkt;
                    exthdr_fh_done = 1;
                }

                uint16_t prev_hdrextlen = hdrextlen;
                hdrextlen = sizeof(IPV6FragHdr);
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                /* for the frag header, the length field is reserved */
                if (*(pkt + 1) != 0) {
                    ENGINE_SET_EVENT(p, IPV6_FH_NON_ZERO_RES_FIELD);
                    /* non fatal, lets try to continue */
                }

                if (IPV6_EXTHDR_ISSET_FH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_FH);
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                /* set the header flag first */
                IPV6_EXTHDR_SET_FH(p);

                /* parse the header and setup the vars */
                DecodeIPV6FragHeader(p, pkt, hdrextlen, plen, prev_hdrextlen);

                /* if FH has offset 0 and no more fragments are coming, we
                 * parse this packet further right away, no defrag will be
                 * needed. It is a useless FH then though, so we do set an
                 * decoder event. */
                if (p->ip6eh.fh_more_frags_set == 0 && p->ip6eh.fh_offset == 0) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_USELESS_FH);

                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                /* the rest is parsed upon reassembly */
                p->flags |= PKT_IS_FRAGMENT;
                SCReturn;
            }
            case IPPROTO_ESP:
            {
                IPV6_SET_L4PROTO(p,nh);
                hdrextlen = sizeof(IPV6EspHdr);
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if (eh) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_EH);
                    SCReturn;
                }

                eh = 1;

                nh = IPPROTO_NONE;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }
            case IPPROTO_AH:
            {
                IPV6_SET_L4PROTO(p,nh);
                /* we need the header as a minimum */
                hdrextlen = sizeof(IPV6AuthHdr);
                /* the payload len field is the number of extra 4 byte fields,
                 * IPV6AuthHdr already contains the first */
                if (*(pkt+1) > 0)
                    hdrextlen += ((*(pkt+1) - 1) * 4);

                SCLogDebug("hdrextlen %"PRIu8, hdrextlen);

                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                IPV6AuthHdr *ahhdr = (IPV6AuthHdr *)pkt;
                if (ahhdr->ip6ah_reserved != 0x0000) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_AH_RES_NOT_NULL);
                }

                if (ah) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_AH);
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                ah = 1;

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }
            case IPPROTO_IPIP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeIPv4inIPv6(tv, dtv, p, pkt, plen, pq);
                SCReturn;
            /* none, last header */
            case IPPROTO_NONE:
                IPV6_SET_L4PROTO(p,nh);
                SCReturn;
            case IPPROTO_ICMP:
                ENGINE_SET_EVENT(p,IPV6_WITH_ICMPV4);
                SCReturn;
            /* no parsing yet, just skip it */
            case IPPROTO_MH:
            case IPPROTO_HIP:
            case IPPROTO_SHIM6:
                hdrextlen = 8 + (*(pkt+1) * 8);  /* 8 bytes + length in 8 octet units */
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }
                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            default:
                ENGINE_SET_EVENT(p, IPV6_UNKNOWN_NEXT_HEADER);
                IPV6_SET_L4PROTO(p,nh);
                SCReturn;
        }
    }

    SCReturn;
}
示例#18
0
/**
 * \brief Recieves packets from an interface via libpfring.
 *
 *  This function recieves packets from an interface and passes
 *  the packet on to the pfring callback function.
 *
 * \param tv pointer to ThreadVars
 * \param data pointer that gets cast into PfringThreadVars for ptv
 * \param slot slot containing task information
 * \retval TM_ECODE_OK on success
 * \retval TM_ECODE_FAILED on failure
 */
TmEcode ReceivePfringLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    PfringThreadVars *ptv = (PfringThreadVars *)data;
    Packet *p = NULL;
    struct pfring_pkthdr hdr;
    TmSlot *s = (TmSlot *)slot;
    time_t last_dump = 0;
    struct timeval current_time;

    ptv->slot = s->slot_next;

    /* we have to enable the ring here as we need to do it after all
     * the threads have called pfring_set_cluster(). */
    int rc = pfring_enable_ring(ptv->pd);
    if (rc != 0) {
        SCLogError(SC_ERR_PF_RING_OPEN, "pfring_enable_ring failed returned %d ", rc);
        SCReturnInt(TM_ECODE_FAILED);
    }

    while(1) {
        if (suricata_ctl_flags & (SURICATA_STOP | SURICATA_KILL)) {
            SCReturnInt(TM_ECODE_OK);
        }

        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        PacketPoolWait();

        p = PacketGetFromQueueOrAlloc();
        if (p == NULL) {
            SCReturnInt(TM_ECODE_FAILED);
        }
        PKT_SET_SRC(p, PKT_SRC_WIRE);

        /* Some flavours of PF_RING may fail to set timestamp - see PF-RING-enabled libpcap code*/
        hdr.ts.tv_sec = hdr.ts.tv_usec = 0;

        /* Depending on what compile time options are used for pfring we either return 0 or -1 on error and always 1 for success */
        u_char *pkt_buffer = GET_PKT_DIRECT_DATA(p);
        u_int buffer_size = GET_PKT_DIRECT_MAX_SIZE(p);
        int r = pfring_recv(ptv->pd, &pkt_buffer,
                buffer_size,
                &hdr,
                LIBPFRING_WAIT_FOR_INCOMING);

        /* Check for Zero-copy if buffer size is zero */
        if (buffer_size == 0) {
            PacketSetData(p, pkt_buffer, hdr.caplen);
        }

        if (r == 1) {
            //printf("RecievePfring src %" PRIu32 " sport %" PRIu32 " dst %" PRIu32 " dstport %" PRIu32 "\n",
            //        hdr.parsed_pkt.ipv4_src,hdr.parsed_pkt.l4_src_port, hdr.parsed_pkt.ipv4_dst,hdr.parsed_pkt.l4_dst_port);

            PfringProcessPacket(ptv, &hdr, p);

            if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
                TmqhOutputPacketpool(ptv->tv, p);
                SCReturnInt(TM_ECODE_FAILED);
            }

            /* Trigger one dump of stats every second */
            TimeGet(&current_time);
            if (current_time.tv_sec != last_dump) {
                PfringDumpCounters(ptv);
                last_dump = current_time.tv_sec;
            }
        } else {
            SCLogError(SC_ERR_PF_RING_RECV,"pfring_recv error  %" PRId32 "", r);
            TmqhOutputPacketpool(ptv->tv, p);
            SCReturnInt(TM_ECODE_FAILED);
        }
        StatsSyncCountersIfSignalled(tv);
    }

    return TM_ECODE_OK;
}
示例#19
0
/**
 * \brief Create event impact description (see section
 * 4.2.6.1 of RFC 4765).
 * The impact contains the severity, completion (succeeded or failed)
 * and basic classification of the attack type.
 * Here, we don't set the completion since we don't know it (default
 * is unknown).
 *
 * \return 0 if ok
 */
static int EventToImpact(const PacketAlert *pa, const Packet *p, idmef_alert_t *alert)
{
    int ret;
    prelude_string_t *str;
    idmef_impact_t *impact;
    idmef_assessment_t *assessment;
    idmef_impact_severity_t severity;

    SCEnter();

    ret = idmef_alert_new_assessment(alert, &assessment);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error creating assessment: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }

    ret = idmef_assessment_new_impact(assessment, &impact);
    if (unlikely(ret < 0)) {
        SCLogDebug("%s: error creating assessment impact: %s.",
                prelude_strsource(ret), prelude_strerror(ret));
        SCReturnInt(ret);
    }

    if ( (unsigned int)pa->s->prio < mid_priority )
        severity = IDMEF_IMPACT_SEVERITY_HIGH;

    else if ( (unsigned int)pa->s->prio < low_priority )
        severity = IDMEF_IMPACT_SEVERITY_MEDIUM;

    else if ( (unsigned int)pa->s->prio < info_priority )
        severity = IDMEF_IMPACT_SEVERITY_LOW;

    else
        severity = IDMEF_IMPACT_SEVERITY_INFO;

    idmef_impact_set_severity(impact, severity);

    if (PACKET_TEST_ACTION(p, ACTION_DROP) ||
        PACKET_TEST_ACTION(p, ACTION_REJECT) ||
        PACKET_TEST_ACTION(p, ACTION_REJECT_DST) ||
        PACKET_TEST_ACTION(p, ACTION_REJECT_BOTH) ) {
        idmef_action_t *action;

        ret = idmef_action_new(&action);
        if (unlikely(ret < 0))
            SCReturnInt(ret);

        idmef_action_set_category(action, IDMEF_ACTION_CATEGORY_BLOCK_INSTALLED);
        idmef_assessment_set_action(assessment, action, 0);
    }

    if (pa->s->class_msg) {
        ret = idmef_impact_new_description(impact, &str);
        if (unlikely(ret < 0))
            SCReturnInt(ret);

        prelude_string_set_ref(str, pa->s->class_msg);
    }

    SCReturnInt(0);
}
示例#20
0
TmEcode ReceiveIPFWLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    IPFWThreadVars *ptv = (IPFWThreadVars *)data;
    IPFWQueueVars *nq = NULL;
    uint8_t pkt[IP_MAXPACKET];
    int pktlen=0;
    struct pollfd IPFWpoll;
    struct timeval IPFWts;
    Packet *p = NULL;
    uint16_t packet_q_len = 0;

    nq = IPFWGetQueue(ptv->ipfw_index);
    if (nq == NULL) {
        SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Can't get thread variable");
        SCReturnInt(TM_ECODE_FAILED);
    }

    SCLogInfo("Thread '%s' will run on port %d (item %d)",
              tv->name, nq->port_num, ptv->ipfw_index);
    while (1) {
        if (suricata_ctl_flags & (SURICATA_STOP || SURICATA_KILL)) {
            SCReturnInt(TM_ECODE_OK);
        }

        IPFWpoll.fd = nq->fd;
        IPFWpoll.events = POLLRDNORM;
        /* Poll the socket for status */
        if ( (poll(&IPFWpoll, 1, IPFW_SOCKET_POLL_MSEC)) > 0) {
            if (!(IPFWpoll.revents & (POLLRDNORM | POLLERR)))
                continue;
        }

        if ((pktlen = recvfrom(nq->fd, pkt, sizeof(pkt), 0,
                               (struct sockaddr *)&nq->ipfw_sin,
                               &nq->ipfw_sinlen)) == -1) {
            /* We received an error on socket read */
            if (errno == EINTR || errno == EWOULDBLOCK) {
                /* Nothing for us to process */
                continue;
            } else {
                SCLogWarning(SC_WARN_IPFW_RECV,
                             "Read from IPFW divert socket failed: %s",
                             strerror(errno));
                SCReturnInt(TM_ECODE_FAILED);
            }
        }
        /* We have a packet to process */
        memset (&IPFWts, 0, sizeof(struct timeval));
        gettimeofday(&IPFWts, NULL);

        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        do {
            packet_q_len = PacketPoolSize();
            if (unlikely(packet_q_len == 0)) {
                PacketPoolWait();
            }
        } while (packet_q_len == 0);

        p = PacketGetFromQueueOrAlloc();
        if (p == NULL) {
            SCReturnInt(TM_ECODE_FAILED);
        }
        PKT_SET_SRC(p, PKT_SRC_WIRE);

        SCLogDebug("Received Packet Len: %d", pktlen);

        p->ts.tv_sec = IPFWts.tv_sec;
        p->ts.tv_usec = IPFWts.tv_usec;

        ptv->pkts++;
        ptv->bytes += pktlen;

        p->datalink = ptv->datalink;

        p->ipfw_v.ipfw_index = ptv->ipfw_index;

        PacketCopyData(p, pkt, pktlen);
        SCLogDebug("Packet info: pkt_len: %" PRIu32 " (pkt %02x, pkt_data %02x)",
                   GET_PKT_LEN(p), *pkt, GET_PKT_DATA(p));

        if (TmThreadsSlotProcessPkt(tv, ((TmSlot *) slot)->slot_next, p)
                != TM_ECODE_OK) {
            TmqhOutputPacketpool(tv, p);
            SCReturnInt(TM_ECODE_FAILED);
        }

        SCPerfSyncCountersIfSignalled(tv, 0);
    }

    SCReturnInt(TM_ECODE_OK);
}
示例#21
0
/**
 * \brief Convert IP packet to an IDMEF alert (RFC 4765).
 * This function stores the alert SID (description and reference),
 * the payload of the packet, and pre-processed data.
 *
 * \return 0 if ok
 */
static int PacketToData(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert, AlertPreludeCtx *ctx)
{
    SCEnter();

    if (unlikely(p == NULL))
        SCReturnInt(0);

    AddIntData(alert, "snort_rule_sid", pa->s->id);
    AddIntData(alert, "snort_rule_rev", pa->s->rev);

    if (ctx->log_packet_header) {
        if ( PKT_IS_IPV4(p) )
            PacketToDataV4(p, pa, alert);

        else if ( PKT_IS_IPV6(p) )
            PacketToDataV6(p, pa, alert);

        if ( PKT_IS_TCP(p) ) {
            AddIntData(alert, "tcp_seq", TCP_GET_SEQ(p));
            AddIntData(alert, "tcp_ack", TCP_GET_ACK(p));

            AddIntData(alert, "tcp_off", TCP_GET_OFFSET(p));
            AddIntData(alert, "tcp_res", TCP_GET_X2(p));
            AddIntData(alert, "tcp_flags", TCP_GET_FLAGS(p));

            AddIntData(alert, "tcp_win", TCP_GET_WINDOW(p));
            AddIntData(alert, "tcp_sum", TCP_GET_SUM(p));
            AddIntData(alert, "tcp_urp", TCP_GET_URG_POINTER(p));
            if (p->tcpvars.ts_val != 0) {
                AddIntData(alert, "tcp_tsval", TCP_GET_TSVAL(p));
            }
            if (p->tcpvars.ts_ecr != 0) {
                AddIntData(alert, "tcp_tsecr", TCP_GET_TSECR(p));
            }
            if (p->tcph != NULL) {
                AddIntData(alert, "tcp_wscale", TCP_GET_WSCALE(p));
            }
            if (TCP_HAS_SACKOK(p)) {
                AddIntData(alert, "tcp_sackok", TCP_GET_SACKOK(p));
            }
            if (TCP_HAS_SACK(p)) {
                AddIntData(alert, "tcp_sack_cnt", TCP_GET_SACK_CNT(p));
            }
            AddIntData(alert, "tcp_hlen", TCP_GET_HLEN(p));
        }

        else if ( PKT_IS_UDP(p) ) {
            AddIntData(alert, "udp_len", UDP_GET_LEN(p));
            AddIntData(alert, "udp_sum", UDP_GET_SUM(p));
        }

        else if ( PKT_IS_ICMPV4(p) ) {
            AddIntData(alert, "icmp_type", ICMPV4_GET_TYPE(p));
            AddIntData(alert, "icmp_code", ICMPV4_GET_CODE(p));
            AddIntData(alert, "icmp_sum", ICMPV4_GET_RAW_CSUM(p));

        }

        else if ( PKT_IS_ICMPV6(p) ) {
            AddIntData(alert, "icmp_type", ICMPV6_GET_TYPE(p));
            AddIntData(alert, "icmp_code", ICMPV6_GET_CODE(p));
            AddIntData(alert, "icmp_csum", ICMPV6_GET_RAW_CSUM(p));
        }
    }

    if (ctx->log_packet_content)
        AddByteData(alert, "payload", p->payload, p->payload_len);

    SCReturnInt(0);
}
示例#22
0
/**
 * \brief This function sets the Verdict and processes the packet
 *
 *
 * \param tv pointer to ThreadVars
 * \param p pointer to the Packet
 */
TmEcode IPFWSetVerdict(ThreadVars *tv, IPFWThreadVars *ptv, Packet *p)
{
    uint32_t verdict;
    struct pollfd IPFWpoll;
    IPFWQueueVars *nq = NULL;

    SCEnter();

    if (p == NULL) {
        SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Packet is NULL");
        SCReturnInt(TM_ECODE_FAILED);
    }

    nq = IPFWGetQueue(p->ipfw_v.ipfw_index);
    if (nq == NULL) {
        SCLogWarning(SC_ERR_INVALID_ARGUMENT, "No thread found");
        SCReturnInt(TM_ECODE_FAILED);
    }

    IPFWpoll.fd = nq->fd;
    IPFWpoll.events = POLLWRNORM;

    if (p->action & ACTION_DROP) {
        verdict = IPFW_DROP;
    } else {
        verdict = IPFW_ACCEPT;
    }

    if (verdict == IPFW_ACCEPT) {
        SCLogDebug("IPFW Verdict is to Accept");
        ptv->accepted++;

        /* For divert sockets, accepting means writing the
         * packet back to the socket for ipfw to pick up
         */
        SCLogDebug("IPFWSetVerdict writing to socket %d, %p, %u", nq->fd, GET_PKT_DATA(p),GET_PKT_LEN(p));

#if 0
        while ((poll(&IPFWpoll,1,IPFW_SOCKET_POLL_MSEC)) < 1) {
            /* Did we receive a signal to shutdown */
            if (TmThreadsCheckFlag(tv, THV_KILL) || TmThreadsCheckFlag(tv, THV_PAUSE)) {
                SCLogInfo("Received ThreadShutdown: IPFW divert socket writing interrupted");
                SCReturnInt(TM_ECODE_OK);
            }
        }
#endif

        IPFWMutexLock(nq);
        if (sendto(nq->fd, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,(struct sockaddr *)&nq->ipfw_sin, nq->ipfw_sinlen) == -1) {
            int r = errno;
            switch (r) {
                default:
                    SCLogWarning(SC_WARN_IPFW_XMIT,"Write to ipfw divert socket failed: %s",strerror(r));
                    IPFWMutexUnlock(nq);
                    SCReturnInt(TM_ECODE_FAILED);
                case EHOSTDOWN:
                case ENETDOWN:
                    break;
            }
        }

        IPFWMutexUnlock(nq);

        SCLogDebug("Sent Packet back into IPFW Len: %d",GET_PKT_LEN(p));

    } /* end IPFW_ACCEPT */


    if (verdict == IPFW_DROP) {
        SCLogDebug("IPFW SetVerdict is to DROP");
        ptv->dropped++;

        /** \todo For divert sockets, dropping means not writing the packet back to the socket.
         * Need to see if there is some better way to free the packet from the queue */

    } /* end IPFW_DROP */

    SCReturnInt(TM_ECODE_OK);
}
示例#23
0
int LogStatsLogger(ThreadVars *tv, void *thread_data, const StatsTable *st)
{
    SCEnter();
    LogStatsLogThread *aft = (LogStatsLogThread *)thread_data;

    struct timeval tval;
    struct tm *tms;

    gettimeofday(&tval, NULL);
    struct tm local_tm;
    tms = SCLocalTime(tval.tv_sec, &local_tm);

    /* Calculate the Engine uptime */
    int up_time = (int)difftime(tval.tv_sec, st->start_time);
    int sec = up_time % 60;     // Seconds in a minute
    int in_min = up_time / 60;
    int min = in_min % 60;      // Minutes in a hour
    int in_hours = in_min / 60;
    int hours = in_hours % 24;  // Hours in a day
    int days = in_hours / 24;

    MemBufferWriteString(aft->buffer, "----------------------------------------------"
            "---------------------\n");
    MemBufferWriteString(aft->buffer, "Date: %" PRId32 "/%" PRId32 "/%04d -- "
            "%02d:%02d:%02d (uptime: %"PRId32"d, %02dh %02dm %02ds)\n",
            tms->tm_mon + 1, tms->tm_mday, tms->tm_year + 1900, tms->tm_hour,
            tms->tm_min, tms->tm_sec, days, hours, min, sec);
    MemBufferWriteString(aft->buffer, "----------------------------------------------"
            "---------------------\n");
    MemBufferWriteString(aft->buffer, "%-25s | %-25s | %-s\n", "Counter", "TM Name",
            "Value");
    MemBufferWriteString(aft->buffer, "----------------------------------------------"
            "---------------------\n");

    /* global stats */
    uint32_t u = 0;
    if (aft->statslog_ctx->flags & LOG_STATS_TOTALS) {
        for (u = 0; u < st->nstats; u++) {
            if (st->stats[u].name == NULL)
                continue;

            if (!(aft->statslog_ctx->flags & LOG_STATS_NULLS) && st->stats[u].value == 0)
                continue;

            char line[1024];
            size_t len = snprintf(line, sizeof(line), "%-25s | %-25s | %-" PRIu64 "\n",
                    st->stats[u].name, st->stats[u].tm_name, st->stats[u].value);

            /* since we can have many threads, the buffer might not be big enough.
             * Expand if necessary. */
            if (MEMBUFFER_OFFSET(aft->buffer) + len > MEMBUFFER_SIZE(aft->buffer)) {
                MemBufferExpand(&aft->buffer, OUTPUT_BUFFER_SIZE);
            }

            MemBufferWriteString(aft->buffer, "%s", line);
        }
    }

    /* per thread stats */
    if (st->tstats != NULL && aft->statslog_ctx->flags & LOG_STATS_THREADS) {
        /* for each thread (store) */
        uint32_t x;
        for (x = 0; x < st->ntstats; x++) {
            uint32_t offset = x * st->nstats;

            /* for each counter */
            for (u = offset; u < (offset + st->nstats); u++) {
                if (st->tstats[u].name == NULL)
                    continue;

                char line[1024];
                size_t len = snprintf(line, sizeof(line), "%-25s | %-25s | %-" PRIu64 "\n",
                        st->tstats[u].name, st->tstats[u].tm_name, st->tstats[u].value);

                /* since we can have many threads, the buffer might not be big enough.
                 * Expand if necessary. */
                if (MEMBUFFER_OFFSET(aft->buffer) + len > MEMBUFFER_SIZE(aft->buffer)) {
                    MemBufferExpand(&aft->buffer, OUTPUT_BUFFER_SIZE);
                }

                MemBufferWriteString(aft->buffer, "%s", line);
            }
        }
    }

    SCMutexLock(&aft->statslog_ctx->file_ctx->fp_mutex);
    aft->statslog_ctx->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer),
        MEMBUFFER_OFFSET(aft->buffer), aft->statslog_ctx->file_ctx);
    SCMutexUnlock(&aft->statslog_ctx->file_ctx->fp_mutex);

    MemBufferReset(aft->buffer);

    SCReturnInt(0);
}
示例#24
0
static void
DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
    SCEnter();

    uint8_t *orig_pkt = pkt;
    uint8_t nh;
    uint16_t hdrextlen;
    uint16_t plen;
    char dstopts = 0;
    char exthdr_fh_done = 0;

    nh = IPV6_GET_NH(p);
    plen = len;

    while(1)
    {
        if (plen < 2) { /* minimal needed in a hdr */
            SCReturn;
        }

        switch(nh)
        {
            case IPPROTO_TCP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeTCP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_UDP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeUDP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_ICMPV6:
                IPV6_SET_L4PROTO(p,nh);
                DecodeICMPV6(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_SCTP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeSCTP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_ROUTING:
                IPV6_SET_L4PROTO(p,nh);
                hdrextlen = 8 + (*(pkt+1) * 8);  /* 8 bytes + length in 8 octet units */

                SCLogDebug("hdrextlen %"PRIu8, hdrextlen);

                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if (p->IPV6_EH_CNT < IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                if (IPV6_EXTHDR_ISSET_RH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_RH);
                    /* skip past this extension so we can continue parsing the rest
                     * of the packet */
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                IPV6_EXTHDR_SET_RH(p, pkt);
                IPV6_EXTHDR_RH(p)->ip6rh_len = hdrextlen;
                /** \todo move into own function and load on demand */
                if (IPV6_EXTHDR_RH(p)->ip6rh_type == 0) {
                    uint8_t i;

                    uint8_t n = IPV6_EXTHDR_RH(p)->ip6rh_len / 2;

                    /* because we devide the header len by 2 (as rfc 2460 tells us to)
                     * we devide the result by 8 and not 16 as the header fields are
                     * sized */
                    for (i = 0; i < (n/8) && i < sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr)/sizeof(struct in6_addr); ++i) {
                        /* the address header fields are 16 bytes in size */
                        /** \todo do this without memcpy since it's expensive */
                        memcpy(&IPV6_EXTHDR_RH(p)->ip6rh0_addr[i], pkt+(i*16)+8, sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr[i]));
                    }
                    IPV6_EXTHDR_RH(p)->ip6rh0_num_addrs = i;
                }

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;

            case IPPROTO_HOPOPTS:
            case IPPROTO_DSTOPTS:
            {
                IPV6OptHAO *hao = NULL;
                IPV6OptRA *ra = NULL;
                IPV6OptJumbo *jumbo = NULL;
                uint8_t optslen = 0;

                IPV6_SET_L4PROTO(p,nh);
                hdrextlen =  (*(pkt+1) + 1) << 3;
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if (p->IPV6_EH_CNT < IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                uint8_t *ptr = pkt + 2; /* +2 to go past nxthdr and len */

                /* point the pointers to right structures
                 * in Packet. */
                if (nh == IPPROTO_HOPOPTS) {
                    if (IPV6_EXTHDR_ISSET_HH(p)) {
                        ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_HH);
                        /* skip past this extension so we can continue parsing the rest
                         * of the packet */
                        nh = *pkt;
                        pkt += hdrextlen;
                        plen -= hdrextlen;
                        break;
                    }

                    IPV6_EXTHDR_SET_HH(p, pkt);
                    hao = &IPV6_EXTHDR_HH_HAO(p);
                    ra = &IPV6_EXTHDR_HH_RA(p);
                    jumbo = &IPV6_EXTHDR_HH_JUMBO(p);

                    optslen = ((IPV6_EXTHDR_HH(p)->ip6hh_len+1)<<3)-2;
                }
                else if (nh == IPPROTO_DSTOPTS)
                {
                    if (dstopts == 0) {
                        IPV6_EXTHDR_SET_DH1(p, pkt);
                        hao = &IPV6_EXTHDR_DH1_HAO(p);
                        ra = &IPV6_EXTHDR_DH1_RA(p);
                        jumbo = &IPV6_EXTHDR_DH2_JUMBO(p);
                        optslen = ((IPV6_EXTHDR_DH1(p)->ip6dh_len+1)<<3)-2;
                        dstopts = 1;
                    } else if (dstopts == 1) {
                        IPV6_EXTHDR_SET_DH2(p, pkt);
                        hao = &IPV6_EXTHDR_DH2_HAO(p);
                        ra = &IPV6_EXTHDR_DH2_RA(p);
                        jumbo = &IPV6_EXTHDR_DH2_JUMBO(p);
                        optslen = ((IPV6_EXTHDR_DH2(p)->ip6dh_len+1)<<3)-2;
                        dstopts = 2;
                    } else {
                        ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_DH);
                        /* skip past this extension so we can continue parsing the rest
                         * of the packet */
                        nh = *pkt;
                        pkt += hdrextlen;
                        plen -= hdrextlen;
                        break;
                    }
                }

                if (optslen > plen) {
                    /* since the packet is long enough (we checked
                     * plen against hdrlen, the optlen must be malformed. */
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
                    /* skip past this extension so we can continue parsing the rest
                     * of the packet */
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }
/** \todo move into own function to loaded on demand */
                uint16_t padn_cnt = 0;
                uint16_t other_cnt = 0;
                uint16_t offset = 0;
                while(offset < optslen)
                {
                    if (*ptr == IPV6OPT_PADN) /* PadN */
                    {
                        //printf("PadN option\n");
                        padn_cnt++;
                    }
                    else if (*ptr == IPV6OPT_RA) /* RA */
                    {
                        ra->ip6ra_type = *(ptr);
                        ra->ip6ra_len  = *(ptr + 1);
                        memcpy(&ra->ip6ra_value, (ptr + 2), sizeof(ra->ip6ra_value));
                        ra->ip6ra_value = ntohs(ra->ip6ra_value);
                        //printf("RA option: type %" PRIu32 " len %" PRIu32 " value %" PRIu32 "\n",
                        //    ra->ip6ra_type, ra->ip6ra_len, ra->ip6ra_value);
                        other_cnt++;
                    }
                    else if (*ptr == IPV6OPT_JUMBO) /* Jumbo */
                    {
                        jumbo->ip6j_type = *(ptr);
                        jumbo->ip6j_len  = *(ptr+1);
                        memcpy(&jumbo->ip6j_payload_len, (ptr+2), sizeof(jumbo->ip6j_payload_len));
                        jumbo->ip6j_payload_len = ntohl(jumbo->ip6j_payload_len);
                        //printf("Jumbo option: type %" PRIu32 " len %" PRIu32 " payload len %" PRIu32 "\n",
                        //    jumbo->ip6j_type, jumbo->ip6j_len, jumbo->ip6j_payload_len);
                    }
                    else if (*ptr == IPV6OPT_HAO) /* HAO */
                    {
                        hao->ip6hao_type = *(ptr);
                        hao->ip6hao_len  = *(ptr+1);
                        memcpy(&hao->ip6hao_hoa, (ptr+2), sizeof(hao->ip6hao_hoa));
                        //printf("HAO option: type %" PRIu32 " len %" PRIu32 " ",
                        //    hao->ip6hao_type, hao->ip6hao_len);
                        //char addr_buf[46];
                        //PrintInet(AF_INET6, (char *)&(hao->ip6hao_hoa),
                        //    addr_buf,sizeof(addr_buf));
                        //printf("home addr %s\n", addr_buf);
                        other_cnt++;
                    } else {
                        if (nh == IPPROTO_HOPOPTS)
                            ENGINE_SET_EVENT(p, IPV6_HOPOPTS_UNKNOWN_OPT);
                        else
                            ENGINE_SET_EVENT(p, IPV6_DSTOPTS_UNKNOWN_OPT);

                        other_cnt++;
                    }
                    uint16_t optlen = (*(ptr + 1) + 2);
                    ptr += optlen; /* +2 for opt type and opt len fields */
                    offset += optlen;
                }
                /* flag packets that have only padding */
                if (padn_cnt > 0 && other_cnt == 0) {
                    if (nh == IPPROTO_HOPOPTS)
                        ENGINE_SET_EVENT(p, IPV6_HOPOPTS_ONLY_PADDING);
                    else
                        ENGINE_SET_EVENT(p, IPV6_DSTOPTS_ONLY_PADDING);
                }

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }

            case IPPROTO_FRAGMENT:
                IPV6_SET_L4PROTO(p,nh);
                /* store the offset of this extension into the packet
                 * past the ipv6 header. We use it in defrag for creating
                 * a defragmented packet without the frag header */
                if (exthdr_fh_done == 0) {
                    p->ip6eh.fh_offset = pkt - orig_pkt;
                    exthdr_fh_done = 1;
                }

                hdrextlen = sizeof(IPV6FragHdr);
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                if (IPV6_EXTHDR_ISSET_FH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_FH);
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                /* set the header ptr first */
                IPV6_EXTHDR_SET_FH(p, pkt);

                /* if FH has offset 0 and no more fragments are coming, we
                 * parse this packet further right away, no defrag will be
                 * needed. It is a useless FH then though, so we do set an
                 * decoder event. */
                if (IPV6_EXTHDR_GET_FH_FLAG(p) == 0 && IPV6_EXTHDR_GET_FH_OFFSET(p) == 0) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_USELESS_FH);

                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                /* the rest is parsed upon reassembly */
                p->flags |= PKT_IS_FRAGMENT;
                SCReturn;

            case IPPROTO_ESP:
            {
                IPV6_SET_L4PROTO(p,nh);
                hdrextlen = sizeof(IPV6EspHdr);
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = IPPROTO_NONE;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                if (IPV6_EXTHDR_ISSET_EH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_EH);
                    SCReturn;
                }

                IPV6_EXTHDR_SET_EH(p, pkt);

                nh = IPPROTO_NONE;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }
            case IPPROTO_AH:
            {
                IPV6_SET_L4PROTO(p,nh);
                /* we need the header as a minimum */
                hdrextlen = sizeof(IPV6AuthHdr);
                /* the payload len field is the number of extra 4 byte fields,
                 * IPV6AuthHdr already contains the first */
                if (*(pkt+1) > 0)
                    hdrextlen += ((*(pkt+1) - 1) * 4);

                SCLogDebug("hdrextlen %"PRIu8, hdrextlen);

                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                IPV6AuthHdr *ahhdr = (IPV6AuthHdr *)pkt;
                if (ahhdr->ip6ah_reserved != 0x0000) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_AH_RES_NOT_NULL);
                }

                if(p->IPV6_EH_CNT < IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                if (IPV6_EXTHDR_ISSET_AH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_AH);
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                IPV6_EXTHDR_SET_AH(p, pkt);

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }
            case IPPROTO_IPIP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeIPv4inIPv6(tv, dtv, p, pkt, plen, pq);
                SCReturn;
            case IPPROTO_NONE:
                IPV6_SET_L4PROTO(p,nh);
                SCReturn;
            case IPPROTO_ICMP:
                ENGINE_SET_EVENT(p,IPV6_WITH_ICMPV4);
                SCReturn;
            default:
                IPV6_SET_L4PROTO(p,nh);
                SCReturn;
        }
    }

    SCReturn;
}
示例#25
0
/**
 * \brief   Initialize the ERF receiver thread, generate a single
 *          ErfDagThreadVar structure for each thread, this will
 *          contain a DAG file descriptor which is read when the
 *          thread executes.
 *
 * \param tv        Thread variable to ThreadVars
 * \param initdata  Initial data to the interface passed from the user,
 *                  this is processed by the user.
 *
 *                  We assume that we have only a single name for the DAG
 *                  interface.
 *
 * \param data      data pointer gets populated with
 *
 */
TmEcode
ReceiveErfDagThreadInit(ThreadVars *tv, void *initdata, void **data)
{
    SCEnter();
    int stream_count = 0;

    if (initdata == NULL) {
        SCLogError(SC_ERR_INVALID_ARGUMENT,
            "Error: No DAG interface provided.");
        SCReturnInt(TM_ECODE_FAILED);
    }

    ErfDagThreadVars *ewtn = SCMalloc(sizeof(ErfDagThreadVars));
    if (unlikely(ewtn == NULL)) {
        SCLogError(SC_ERR_MEM_ALLOC,
            "Failed to allocate memory for ERF DAG thread vars.");
        exit(EXIT_FAILURE);
    }

    memset(ewtn, 0, sizeof(*ewtn));

    /* dag_parse_name will return a DAG device name and stream number
     * to open for this thread.
     */
    if (dag_parse_name(initdata, ewtn->dagname, DAGNAME_BUFSIZE,
            &ewtn->dagstream) < 0) {
        SCLogError(SC_ERR_INVALID_ARGUMENT,
            "Failed to parse DAG interface: %s",
            (char*)initdata);
        SCFree(ewtn);
        exit(EXIT_FAILURE);
    }

    ewtn->livedev = LiveGetDevice(initdata);
    if (ewtn->livedev == NULL) {
        SCLogError(SC_ERR_INVALID_VALUE, "Unable to get %s live device",
            (char *)initdata);
        SCFree(ewtn);
        SCReturnInt(TM_ECODE_FAILED);
    }

    SCLogInfo("Opening DAG: %s on stream: %d for processing",
        ewtn->dagname, ewtn->dagstream);

    if ((ewtn->dagfd = dag_open(ewtn->dagname)) < 0) {
        SCLogError(SC_ERR_ERF_DAG_OPEN_FAILED, "Failed to open DAG: %s",
            ewtn->dagname);
        SCFree(ewtn);
        SCReturnInt(TM_ECODE_FAILED);
    }

    /* Check to make sure the card has enough available streams to
     * support reading from the one specified.
     */
    if ((stream_count = dag_rx_get_stream_count(ewtn->dagfd)) < 0) {
        SCLogError(SC_ERR_ERF_DAG_OPEN_FAILED,
            "Failed to open stream: %d, DAG: %s, could not query stream count",
            ewtn->dagstream, ewtn->dagname);
        SCFree(ewtn);
        SCReturnInt(TM_ECODE_FAILED);
    }

    /* Check to make sure we have enough rx streams to open the stream
     * the user is asking for.
     */
    if (ewtn->dagstream > stream_count * 2) {
        SCLogError(SC_ERR_ERF_DAG_OPEN_FAILED,
            "Failed to open stream: %d, DAG: %s, insufficient streams: %d",
            ewtn->dagstream, ewtn->dagname, stream_count);
        SCFree(ewtn);
        SCReturnInt(TM_ECODE_FAILED);
    }

    /* If we are transmitting into a soft DAG card then set the stream
     * to act in reverse mode.
     */
    if (0 != (ewtn->dagstream & 0x01)) {
        /* Setting reverse mode for using with soft dag from daemon side */
        if (dag_set_mode(ewtn->dagfd, ewtn->dagstream, DAG_REVERSE_MODE)) {
            SCLogError(SC_ERR_ERF_DAG_STREAM_OPEN_FAILED,
                "Failed to set mode to DAG_REVERSE_MODE on stream: %d, DAG: %s",
                ewtn->dagstream, ewtn->dagname);
            SCFree(ewtn);
            SCReturnInt(TM_ECODE_FAILED);
        }
    }

    if (dag_attach_stream(ewtn->dagfd, ewtn->dagstream, 0, 0) < 0) {
        SCLogError(SC_ERR_ERF_DAG_STREAM_OPEN_FAILED,
            "Failed to open DAG stream: %d, DAG: %s",
            ewtn->dagstream, ewtn->dagname);
        SCFree(ewtn);
        SCReturnInt(TM_ECODE_FAILED);
    }

    if (dag_start_stream(ewtn->dagfd, ewtn->dagstream) < 0) {
        SCLogError(SC_ERR_ERF_DAG_STREAM_START_FAILED,
            "Failed to start DAG stream: %d, DAG: %s",
            ewtn->dagstream, ewtn->dagname);
        SCFree(ewtn);
        SCReturnInt(TM_ECODE_FAILED);
    }

    SCLogInfo("Attached and started stream: %d on DAG: %s",
        ewtn->dagstream, ewtn->dagname);

    /*
     * Initialise DAG Polling parameters.
     */
    timerclear(&ewtn->maxwait);
    ewtn->maxwait.tv_usec = MAXWAIT;
    timerclear(&ewtn->poll);
    ewtn->poll.tv_usec = POLL_INTERVAL;

    /* 32kB minimum data to return -- we still restrict the number of
     * pkts that are processed to a maximum of dag_max_read_packets.
     */
    if (dag_set_stream_poll(ewtn->dagfd, ewtn->dagstream, MINDATA,
            &(ewtn->maxwait), &(ewtn->poll)) < 0) {
        SCLogError(SC_ERR_ERF_DAG_STREAM_SET_FAILED,
            "Failed to set poll parameters for stream: %d, DAG: %s",
            ewtn->dagstream, ewtn->dagname);
        SCFree(ewtn);
        SCReturnInt(TM_ECODE_FAILED);
    }

    ewtn->packets = StatsRegisterCounter("capture.dag_packets", tv);
    ewtn->drops = StatsRegisterCounter("capture.dag_drops", tv);

    ewtn->tv = tv;
    *data = (void *)ewtn;

    SCLogInfo("Starting processing packets from stream: %d on DAG: %s",
        ewtn->dagstream, ewtn->dagname);

    SCReturnInt(TM_ECODE_OK);
}
示例#26
0
/**
 * \brief this function is used to parse filestore options
 * \brief into the current signature
 *
 * \param de_ctx pointer to the Detection Engine Context
 * \param s pointer to the Current Signature
 * \param str pointer to the user provided "filestore" option
 *
 * \retval 0 on Success
 * \retval -1 on Failure
 */
static int DetectFilestoreSetup (DetectEngineCtx *de_ctx, Signature *s, char *str)
{
    SCEnter();

    DetectFilestoreData *fd = NULL;
    SigMatch *sm = NULL;
    char *args[3] = {NULL,NULL,NULL};
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];

    sm = SigMatchAlloc();
    if (sm == NULL)
        goto error;

    sm->type = DETECT_FILESTORE;

    if (str != NULL && strlen(str) > 0) {
        SCLogDebug("str %s", str);

        ret = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0, ov, MAX_SUBSTRINGS);
        if (ret < 1 || ret > 4) {
            SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 ", string %s", ret, str);
            goto error;
        }

        if (ret > 1) {
            const char *str_ptr;
            res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
            if (res < 0) {
                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
                goto error;
            }
            args[0] = (char *)str_ptr;

            if (ret > 2) {
                res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 2, &str_ptr);
                if (res < 0) {
                    SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
                    goto error;
                }
                args[1] = (char *)str_ptr;
            }
            if (ret > 3) {
                res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 3, &str_ptr);
                if (res < 0) {
                    SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
                    goto error;
                }
                args[2] = (char *)str_ptr;
            }
        }

        fd = SCMalloc(sizeof(DetectFilestoreData));
        if (unlikely(fd == NULL))
            goto error;
        memset(fd, 0x00, sizeof(DetectFilestoreData));

        if (args[0] != NULL) {
            SCLogDebug("first arg %s", args[0]);

            if (strcasecmp(args[0], "request") == 0 ||
                    strcasecmp(args[0], "to_server") == 0)
            {
                fd->direction = FILESTORE_DIR_TOSERVER;
                fd->scope = FILESTORE_SCOPE_TX;
            }
            else if (strcasecmp(args[0], "response") == 0 ||
                    strcasecmp(args[0], "to_client") == 0)
            {
                fd->direction = FILESTORE_DIR_TOCLIENT;
                fd->scope = FILESTORE_SCOPE_TX;
            }
            else if (strcasecmp(args[0], "both") == 0)
            {
                fd->direction = FILESTORE_DIR_BOTH;
                fd->scope = FILESTORE_SCOPE_TX;
            }
        } else {
            fd->direction = FILESTORE_DIR_DEFAULT;
        }

        if (args[1] != NULL) {
            SCLogDebug("second arg %s", args[1]);

            if (strcasecmp(args[1], "file") == 0)
            {
                fd->scope = FILESTORE_SCOPE_DEFAULT;
            } else if (strcasecmp(args[1], "tx") == 0)
            {
                fd->scope = FILESTORE_SCOPE_TX;
            } else if (strcasecmp(args[1], "ssn") == 0 ||
                       strcasecmp(args[1], "flow") == 0)
            {
                fd->scope = FILESTORE_SCOPE_SSN;
            }
        } else {
            if (fd->scope == 0)
                fd->scope = FILESTORE_SCOPE_DEFAULT;
        }

        sm->ctx = fd;
    } else {
        sm->ctx = NULL;
    }

    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_FILEMATCH);
    s->filestore_sm = sm;

    if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP) {
        SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords.");
        goto error;
    }

    AppLayerHtpNeedFileInspection();

    s->alproto = ALPROTO_HTTP;

    s->flags |= SIG_FLAG_FILESTORE;
    return 0;

error:
    if (sm != NULL)
        SCFree(sm);
    return -1;
}
示例#27
0
/**
 * \brief Process a chunk of records read from a DAG interface.
 *
 * This function takes a pointer to buffer read from the DAG interface
 * and processes it individual records.
 */
static inline TmEcode
ProcessErfDagRecords(ErfDagThreadVars *ewtn, uint8_t *top, uint32_t *pkts_read)
{
    SCEnter();

    int err = 0;
    dag_record_t *dr = NULL;
    char *prec = NULL;
    int rlen;
    char hdr_type = 0;
    int processed = 0;

    *pkts_read = 0;

    while (((top - ewtn->btm) >= dag_record_size) &&
        ((processed + dag_record_size) < BYTES_PER_LOOP)) {

        /* Make sure we have at least one packet in the packet pool,
         * to prevent us from alloc'ing packets at line rate. */
        PacketPoolWait();

        prec = (char *)ewtn->btm;
        dr = (dag_record_t*)prec;
        rlen = ntohs(dr->rlen);
        hdr_type = dr->type;

        /* If we don't have enough data to finish processing this ERF
         * record return and maybe next time we will.
         */
        if ((top - ewtn->btm) < rlen)
            SCReturnInt(TM_ECODE_OK);

        ewtn->btm += rlen;
        processed += rlen;

        /* Only support ethernet at this time. */
        switch (hdr_type & 0x7f) {
        case TYPE_PAD:
            /* Skip. */
            continue;
        case TYPE_DSM_COLOR_ETH:
        case TYPE_COLOR_ETH:
        case TYPE_COLOR_HASH_ETH:
            /* In these types the color value overwrites the lctr
             * (drop count). */
            break;
        case TYPE_ETH:
            if (dr->lctr) {
                StatsAddUI64(tv, ewtn->drops, ntohs(dr->lctr));
            }
            break;
        default:
            SCLogError(SC_ERR_UNIMPLEMENTED,
                "Processing of DAG record type: %d not implemented.", dr->type);
            SCReturnInt(TM_ECODE_FAILED);
        }

        err = ProcessErfDagRecord(ewtn, prec);
        if (err != TM_ECODE_OK) {
            SCReturnInt(TM_ECODE_FAILED);
        }

        (*pkts_read)++;
    }

    SCReturnInt(TM_ECODE_OK);
}
示例#28
0
/** \brief Byte jump match function
 *  \param det_ctx thread detect engine ctx
 *  \param s signature
 *  \param m byte jump sigmatch
 *  \param payload ptr to the payload
 *  \param payload_len length of the payload
 *  \retval 1 match
 *  \retval 0 no match
 */
int DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s,
                          const SigMatchCtx *ctx, uint8_t *payload, uint32_t payload_len,
                          uint8_t flags, int32_t offset)
{
    SCEnter();

    const DetectBytejumpData *data = (const DetectBytejumpData *)ctx;
    uint8_t *ptr = NULL;
    uint8_t *jumpptr = NULL;
    int32_t len = 0;
    uint64_t val = 0;
    int extbytes;

    if (payload_len == 0) {
        SCReturnInt(0);
    }

    /* Calculate the ptr value for the bytejump and length remaining in
     * the packet from that point.
     */
    if (flags & DETECT_BYTEJUMP_RELATIVE) {
        ptr = payload + det_ctx->buffer_offset;
        len = payload_len - det_ctx->buffer_offset;

        ptr += offset;
        len -= offset;

        /* No match if there is no relative base */
        if (ptr == NULL || len <= 0) {
            SCReturnInt(0);
        }
    }
    else {
        ptr = payload + offset;
        len = payload_len - offset;
    }

    /* Verify the to-be-extracted data is within the packet */
    if (ptr < payload || data->nbytes > len) {
        SCLogDebug("Data not within payload "
               "pkt=%p, ptr=%p, len=%d, nbytes=%d",
               payload, ptr, len, data->nbytes);
        SCReturnInt(0);
    }

    /* Extract the byte data */
    if (flags & DETECT_BYTEJUMP_STRING) {
        extbytes = ByteExtractStringUint64(&val, data->base,
                                           data->nbytes, (const char *)ptr);
        if(extbytes <= 0) {
            SCLogDebug("error extracting %d bytes of string data: %d",
                    data->nbytes, extbytes);
            SCReturnInt(0);
        }
    }
    else {
        int endianness = (flags & DETECT_BYTEJUMP_LITTLE) ? BYTE_LITTLE_ENDIAN : BYTE_BIG_ENDIAN;
        extbytes = ByteExtractUint64(&val, endianness, data->nbytes, ptr);
        if (extbytes != data->nbytes) {
            SCLogDebug("error extracting %d bytes of numeric data: %d",
                    data->nbytes, extbytes);
            SCReturnInt(0);
        }
    }

    //printf("VAL: (%" PRIu64 " x %" PRIu32 ") + %d + %" PRId32 "\n", val, data->multiplier, extbytes, data->post_offset);

    /* Adjust the jump value based on flags */
    val *= data->multiplier;
    if (flags & DETECT_BYTEJUMP_ALIGN) {
        if ((val % 4) != 0) {
            val += 4 - (val % 4);
        }
    }
    val += data->post_offset;

    /* Calculate the jump location */
    if (flags & DETECT_BYTEJUMP_BEGIN) {
        jumpptr = payload + val;
        //printf("NEWVAL: payload %p + %ld = %p\n", p->payload, val, jumpptr);
    }
    else {
        val += extbytes;
        jumpptr = ptr + val;
        //printf("NEWVAL: ptr %p + %ld = %p\n", ptr, val, jumpptr);
    }


    /* Validate that the jump location is still in the packet
     * \todo Should this validate it is still in the *payload*?
     */
    if ((jumpptr < payload) || (jumpptr >= payload + payload_len)) {
        SCLogDebug("Jump location (%p) is not within "
               "payload (%p-%p)", jumpptr, payload, payload + payload_len - 1);
        SCReturnInt(0);
    }

#ifdef DEBUG
    if (SCLogDebugEnabled()) {
        uint8_t *sptr = (flags & DETECT_BYTEJUMP_BEGIN) ? payload : ptr;
        SCLogDebug("jumping %" PRId64 " bytes from %p (%08x) to %p (%08x)",
               val, sptr, (int)(sptr - payload),
               jumpptr, (int)(jumpptr - payload));
    }
#endif /* DEBUG */

    /* Adjust the detection context to the jump location. */
    det_ctx->buffer_offset = jumpptr - payload;

    SCReturnInt(1);
}
示例#29
0
/**
 *  \brief Main PCAP file reading Loop function
 */
TmEcode ReceivePcapFileLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    uint16_t packet_q_len = 0;
    PcapFileThreadVars *ptv = (PcapFileThreadVars *)data;
    int r;
    TmSlot *s = (TmSlot *)slot;

    ptv->slot = s->slot_next;
    ptv->cb_result = TM_ECODE_OK;

    while (1) {
        if (suricata_ctl_flags & (SURICATA_STOP | SURICATA_KILL)) {
            SCReturnInt(TM_ECODE_OK);
        }

        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        do {
            packet_q_len = PacketPoolSize();
            if (unlikely(packet_q_len == 0)) {
                PacketPoolWait();
            }
        } while (packet_q_len == 0);

        /* Right now we just support reading packets one at a time. */
        r = pcap_dispatch(pcap_g.pcap_handle, (int)packet_q_len,
                          (pcap_handler)PcapFileCallbackLoop, (u_char *)ptv);
        if (unlikely(r == -1)) {
            SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s",
                       r, pcap_geterr(pcap_g.pcap_handle));
            if (! RunModeUnixSocketIsActive()) {
                /* in the error state we just kill the engine */
                EngineKill();
                SCReturnInt(TM_ECODE_FAILED);
            } else {
                pcap_close(pcap_g.pcap_handle);
                pcap_g.pcap_handle = NULL;
                UnixSocketPcapFile(TM_ECODE_DONE);
                SCReturnInt(TM_ECODE_DONE);
            }
        } else if (unlikely(r == 0)) {
            SCLogInfo("pcap file end of file reached (pcap err code %" PRId32 ")", r);
            if (! RunModeUnixSocketIsActive()) {
                EngineStop();
            } else {
                pcap_close(pcap_g.pcap_handle);
                pcap_g.pcap_handle = NULL;
                UnixSocketPcapFile(TM_ECODE_DONE);
                SCReturnInt(TM_ECODE_DONE);
            }
            break;
        } else if (ptv->cb_result == TM_ECODE_FAILED) {
            SCLogError(SC_ERR_PCAP_DISPATCH, "Pcap callback PcapFileCallbackLoop failed");
            if (! RunModeUnixSocketIsActive()) {
                EngineKill();
                SCReturnInt(TM_ECODE_FAILED);
            } else {
                pcap_close(pcap_g.pcap_handle);
                pcap_g.pcap_handle = NULL;
                UnixSocketPcapFile(TM_ECODE_DONE);
                SCReturnInt(TM_ECODE_DONE);
            }
        }
        SCPerfSyncCountersIfSignalled(tv);
    }

    SCReturnInt(TM_ECODE_OK);
}
示例#30
0
static TmEcode LogFilestoreLogWrap(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq, int ipver)
{
    SCEnter();
    LogFilestoreLogThread *aft = (LogFilestoreLogThread *)data;
    uint8_t flags = 0;

    /* no flow, no htp state */
    if (p->flow == NULL) {
        SCReturnInt(TM_ECODE_OK);
    }

    if (p->flowflags & FLOW_PKT_TOCLIENT)
        flags |= STREAM_TOCLIENT;
    else
        flags |= STREAM_TOSERVER;

    int file_close = (p->flags & PKT_PSEUDO_STREAM_END) ? 1 : 0;
    int file_trunc = 0;

    FLOWLOCK_WRLOCK(p->flow);
    file_trunc = StreamTcpReassembleDepthReached(p);

    FileContainer *ffc = AppLayerGetFilesFromFlow(p->flow, flags);
    SCLogDebug("ffc %p", ffc);
    if (ffc != NULL) {
        File *ff;
        for (ff = ffc->head; ff != NULL; ff = ff->next) {
            int file_fd = -1;

            if (FileForceMagic() && ff->magic == NULL) {
                FilemagicLookup(ff);
            }

            SCLogDebug("ff %p", ff);
            if (ff->flags & FILE_STORED) {
                SCLogDebug("stored flag set");
                continue;
            }

            if (!(ff->flags & FILE_STORE)) {
                SCLogDebug("ff FILE_STORE not set");
                continue;
            }

            FileData *ffd;
            for (ffd = ff->chunks_head; ffd != NULL; ffd = ffd->next) {
                SCLogDebug("ffd %p", ffd);
                if (ffd->stored == 1) {
                    if (file_close == 1 && ffd->next == NULL) {
                        LogFilestoreLogCloseMetaFile(ff);
                        ff->flags |= FILE_STORED;
                    }
                    continue;
                }

                /* store */
                SCLogDebug("trying to open file");

                char filename[PATH_MAX] = "";

                if (ff->file_id == 0) {
                    ff->file_id = SC_ATOMIC_ADD(file_id, 1);

                    snprintf(filename, sizeof(filename), "%s/file.%u",
                            g_logfile_base_dir, ff->file_id);

                    file_fd = open(filename, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
                    if (file_fd == -1) {
                        SCLogDebug("failed to open file");
                        continue;
                    }

                    /* create a .meta file that contains time, src/dst/sp/dp/proto */
                    LogFilestoreLogCreateMetaFile(p, ff, filename, ipver);
                    aft->file_cnt++;
                } else {
                    snprintf(filename, sizeof(filename), "%s/file.%u",
                            g_logfile_base_dir, ff->file_id);

                    file_fd = open(filename, O_APPEND | O_NOFOLLOW | O_WRONLY);
                    if (file_fd == -1) {
                        SCLogDebug("failed to open file %s: %s", filename, strerror(errno));
                        continue;
                    }
                }

                ssize_t r = write(file_fd, (const void *)ffd->data, (size_t)ffd->len);
                if (r == -1) {
                    SCLogDebug("write failed: %s", strerror(errno));

                    close(file_fd);
                    continue;
                }

                close(file_fd);

                if (file_trunc && ff->state < FILE_STATE_CLOSED)
                    ff->state = FILE_STATE_TRUNCATED;

                if (ff->state == FILE_STATE_CLOSED ||
                    ff->state == FILE_STATE_TRUNCATED ||
                    ff->state == FILE_STATE_ERROR ||
                    (file_close == 1 && ff->state < FILE_STATE_CLOSED))
                {
                    if (ffd->next == NULL) {
                        LogFilestoreLogCloseMetaFile(ff);

                        ff->flags |= FILE_STORED;
                    }
                }

                ffd->stored = 1;
            }
        }

        FilePrune(ffc);
    }

    FLOWLOCK_UNLOCK(p->flow);
    SCReturnInt(TM_ECODE_OK);
}