Beispiel #1
0
static int daq_nfq_callback(
    struct nfq_q_handle* qh,
    struct nfgenmsg* nfmsg,
    struct nfq_data* nfad,
    void* data)
{
    NfqImpl *impl = (NfqImpl*)data;
    struct nfqnl_msg_packet_hdr* ph = nfq_get_msg_packet_hdr(nfad);

    DAQ_Verdict verdict;
    DAQ_PktHdr_t hdr;
    uint8_t* pkt;
    int nf_verdict;
    uint32_t data_len;

    if ( impl->state != DAQ_STATE_STARTED )
        return -1;

    if ( !ph || SetPktHdr(impl, nfad, &hdr, &pkt) )
    {
        DPE(impl->error, "%s: can't setup packet header",
            __FUNCTION__);
        return -1;
    }

    if (
        impl->fcode.bf_insns &&
        sfbpf_filter(impl->fcode.bf_insns, pkt, hdr.caplen, hdr.caplen) == 0
    ) {
        verdict = DAQ_VERDICT_PASS;
        impl->stats.packets_filtered++;
    }
    else
    {
        verdict = impl->user_func(impl->user_data, &hdr, pkt);

        if ( verdict >= MAX_DAQ_VERDICT )
            verdict = DAQ_VERDICT_BLOCK;

        impl->stats.verdicts[verdict]++;
        impl->stats.packets_received++;
    }
    nf_verdict = ( impl->passive || s_fwd[verdict] ) ? NF_ACCEPT : NF_DROP;
    data_len = ( verdict == DAQ_VERDICT_REPLACE ) ? hdr.caplen : 0;

    nfq_set_verdict(
        impl->nf_queue, ntohl(ph->packet_id),
        nf_verdict, data_len, pkt);

    return 0;
}
Beispiel #2
0
int
main()
{
	struct sfbpf_program fcode;
	const char *filter = "tcp";
	char data[1514];
	int len = 1514;

	memset(data, 0, sizeof(data));

	if (sfbpf_compile(1514, DLT_EN10MB, &fcode, filter, 1, 0) < 0) {
		fprintf(stderr, "%s: BPF state machine compilation failed!", __FUNCTION__);
		return EXIT_FAILURE;
	}
	
	if (fcode.bf_insns && sfbpf_filter(fcode.bf_insns, data, len, len) == 0) {
		fprintf(stderr, "Packet ignored!\n");
	}
	
	sfbpf_freecode(&fcode);

	return EXIT_SUCCESS;
}
Beispiel #3
0
static int ipq_daq_acquire (
    void* handle, int cnt, DAQ_Analysis_Func_t callback, void* user)
{
    IpqImpl* impl = (IpqImpl*)handle;

    int n = 0;
    DAQ_PktHdr_t hdr;

    // If cnt is <= 0, don't limit the packets acquired.  However,
    // impl->count = 0 has a special meaning, so interpret accordingly.
    impl->count = (cnt == 0) ? -1 : cnt;
    hdr.device_index = 0;
    hdr.flags = 0;

    while ( impl->count < 0 || n < impl->count )
    {
        int ipqt, status = ipq_read(
            impl->ipqh, impl->buf, MSG_BUF_SIZE, impl->timeout);

        if ( status <= 0 )
        {
            if ( status < 0 )
            {
                DPE(impl->error, "%s: ipq_read=%d error %s",
                    __FUNCTION__, status, ipq_errstr());
                return DAQ_ERROR;
            }
            return 0;
        }

        ipqt = ipq_message_type(impl->buf);

        if ( ipqt == IPQM_PACKET )
        {
            DAQ_Verdict verdict;
            ipq_packet_msg_t* ipqm = ipq_get_packet(impl->buf);
            SetPktHdr(impl, ipqm, &hdr);
            impl->stats.hw_packets_received++;

            if (
                impl->fcode.bf_insns &&
                sfbpf_filter(impl->fcode.bf_insns, ipqm->payload,
                    hdr.caplen, hdr.caplen) == 0
            ) {
                verdict = DAQ_VERDICT_PASS;
                impl->stats.packets_filtered++;
            }
            else
            {
                verdict = callback(user, &hdr, (uint8_t*)ipqm->payload);
                impl->stats.verdicts[verdict]++;
                impl->stats.packets_received++;
            }
            if ( impl->passive ) verdict = DAQ_VERDICT_PASS;

            switch ( verdict ) {
            case DAQ_VERDICT_BLOCK:
            case DAQ_VERDICT_BLACKLIST:
                status = ipq_set_verdict(
                    impl->ipqh, ipqm->packet_id, NF_DROP, 0, NULL);
                break;

            case DAQ_VERDICT_REPLACE:
                status = ipq_set_verdict(
                    impl->ipqh, ipqm->packet_id, NF_ACCEPT,
                    hdr.pktlen, ipqm->payload);
                break;

            case DAQ_VERDICT_PASS:
            case DAQ_VERDICT_WHITELIST:
            case DAQ_VERDICT_IGNORE:
            default:
                status = ipq_set_verdict(
                    impl->ipqh, ipqm->packet_id, NF_ACCEPT, 0, NULL);
                break;
            }
            if ( status < 0 )
            {
                DPE(impl->error, "%s: ipq_set_verdict=%d error %s",
                    __FUNCTION__, status, ipq_errstr());
                return DAQ_ERROR;
            }
            n++;
        }
        else
        {
            // NLMSG_ERROR is supposed to be the only other valid type
            status = ipq_get_msgerr(impl->buf);
            DPE(impl->error, "%s: ipq_message_type=%d error=%d %s",
                __FUNCTION__, ipqt, status, ipq_errstr());
            // ipq_message_type=2 error=1 Timeout
            // keep looping upon timeout or other errors
        }
    }
    return 0;
}
Beispiel #4
0
static int afpacket_daq_acquire(void *handle, int cnt, DAQ_Analysis_Func_t callback, void *user)
{
    AFPacket_Context_t *afpc = (AFPacket_Context_t *) handle;
    AFPacketInstance *instance;
    DAQ_PktHdr_t daqhdr;
    DAQ_Verdict verdict;
    union thdr hdr;
    struct pollfd pfd[AF_PACKET_MAX_INTERFACES];
    const uint8_t *data;
    uint32_t i;
    int got_one, ignored_one;
    int result, c = 0;
    struct sockaddr_ll *sll;
    const struct ethhdr *eth;
    unsigned int tp_len, tp_mac, tp_snaplen, tp_sec, tp_usec;

    while (cnt <= 0 || c < cnt)
    {
        got_one = 0;
        ignored_one = 0;
        for (instance = afpc->instances; instance; instance = instance->next)
        {
            /* Has breakloop() been called? */
            if (afpc->break_loop)
            {
                afpc->break_loop = 0;
                return 0;
            }

            hdr = instance->entry->hdr;
            if ((instance->tp_version == TPACKET_V1 && hdr.h1->tp_status)
#ifdef HAVE_TPACKET2
                    || (instance->tp_version == TPACKET_V2 && hdr.h2->tp_status)
#endif
               )
            {
                switch (instance->tp_version)
                {
                case TPACKET_V1:
                    tp_len = hdr.h1->tp_len;
                    tp_mac = hdr.h1->tp_mac;
                    tp_snaplen = hdr.h1->tp_snaplen;
                    tp_sec = hdr.h1->tp_sec;
                    tp_usec = hdr.h1->tp_usec;
                    break;
#ifdef HAVE_TPACKET2
                case TPACKET_V2:
                    tp_len = hdr.h2->tp_len;
                    tp_mac = hdr.h2->tp_mac;
                    tp_snaplen = hdr.h2->tp_snaplen;
                    tp_sec = hdr.h2->tp_sec;
                    tp_usec = hdr.h2->tp_nsec / 1000;
                    break;
#endif
                default:
                    DPE(afpc->errbuf, "%s: Unknown TPACKET version: %u!", __FUNCTION__, instance->tp_version);
                    return DAQ_ERROR;
                }
                data = instance->entry->begin + tp_mac;

                verdict = DAQ_VERDICT_PASS;
                if (afpc->fcode.bf_insns && sfbpf_filter(afpc->fcode.bf_insns, data, tp_len, tp_snaplen) == 0)
                {
                    ignored_one = 1;
                    afpc->stats.packets_filtered++;
                    goto send_packet;
                }
                got_one = 1;

                daqhdr.caplen = tp_snaplen;
                daqhdr.pktlen = tp_len;
                daqhdr.ts.tv_sec = tp_sec;
                daqhdr.ts.tv_usec = tp_usec;
                daqhdr.device_index = instance->index;
                daqhdr.flags = 0;

                if (callback)
                {
                    verdict = callback(user, &daqhdr, data);
                    if (verdict >= MAX_DAQ_VERDICT)
                        verdict = DAQ_VERDICT_PASS;
                    afpc->stats.verdicts[verdict]++;
                    verdict = verdict_translation_table[verdict];
                }
                afpc->stats.packets_received++;
                c++;
send_packet:
                if (verdict == DAQ_VERDICT_PASS && instance->peer)
                {
                    eth = (const struct ethhdr *)data;
                    sll = &instance->peer->sll;
                    sll->sll_protocol = eth->h_proto;
                    sendto(instance->peer->fd, data, tp_snaplen, 0, (struct sockaddr *) sll, sizeof(*sll));
                }
                switch (instance->tp_version)
                {
                case TPACKET_V1:
                    hdr.h1->tp_status = TP_STATUS_KERNEL;
                    break;
#ifdef HAVE_TPACKET2
                case TPACKET_V2:
                    hdr.h2->tp_status = TP_STATUS_KERNEL;
                    break;
#endif
                }
                instance->entry = instance->entry->next;
            }
        }
        if (!got_one && !ignored_one)
        {
            for (i = 0, instance = afpc->instances; instance; i++, instance = instance->next)
            {
                pfd[i].fd = instance->fd;
                pfd[i].revents = 0;
                pfd[i].events = POLLIN;
            }
            result = poll(pfd, afpc->intf_count, afpc->timeout);
            if (result < 0)
            {
                /* If we were interrupted by a signal, just return without error. */
                if (errno == EINTR)
                    break;
                DPE(afpc->errbuf, "%s: Poll failed: %s (%d)", __FUNCTION__, strerror(errno), errno);
                return DAQ_ERROR;
            }
            else if (result == 0)
                break;
        }
    }
    return 0;
}
Beispiel #5
0
static int
afpacket_daq_acquire(void *handle, int cnt,
        DAQ_Analysis_Func_t callback, DAQ_Meta_Func_t metaback, void *user)
{
    AFPacket_Context_t *afpc = (AFPacket_Context_t *) handle;
    AFPacketInstance *instance;
    DAQ_PktHdr_t daqhdr;
    DAQ_Verdict verdict;
    union thdr hdr;
    struct pollfd pfd[AF_PACKET_MAX_INTERFACES];
    const uint8_t *data;
    uint32_t i;
    int got_one, ignored_one;
    int ret, c = 0;
    unsigned int tp_len, tp_mac, tp_snaplen, tp_sec, tp_usec;

    while (c < cnt || cnt <= 0)
    {
        got_one = 0;
        ignored_one = 0;
        for (instance = afpc->instances; instance; instance = instance->next)
        {
            /* Has breakloop() been called? */
            if (afpc->break_loop)
            {
                afpc->break_loop = 0;
                return 0;
            }

            hdr = instance->rx_ring.cursor->hdr;
            if (instance->tp_version == TPACKET_V2 && (hdr.h2->tp_status & TP_STATUS_USER))
            {
                switch (instance->tp_version)
                {
                    case TPACKET_V2:
                        tp_len = hdr.h2->tp_len;
                        tp_mac = hdr.h2->tp_mac;
                        tp_snaplen = hdr.h2->tp_snaplen;
                        tp_sec = hdr.h2->tp_sec;
                        tp_usec = hdr.h2->tp_nsec / 1000;
                        break;

                    default:
                        DPE(afpc->errbuf, "%s: Unknown TPACKET version: %u!", __FUNCTION__, instance->tp_version);
                        return DAQ_ERROR;
                }
                if (tp_mac + tp_snaplen > instance->rx_ring.layout.tp_frame_size)
                {
                    DPE(afpc->errbuf, "%s: Corrupted frame on kernel ring (MAC offset %u + CapLen %u > FrameSize %d)",
                        __FUNCTION__, tp_mac, tp_snaplen, instance->rx_ring.layout.tp_frame_size);
                    return DAQ_ERROR;
                }
                data = instance->rx_ring.cursor->hdr.raw + tp_mac;

                /* Make a valiant attempt at reconstructing the VLAN tag if it has been stripped.  This really sucks. :( */
                if ((instance->tp_version == TPACKET_V2) &&
#if defined(TP_STATUS_VLAN_VALID)
                    (hdr.h2->tp_vlan_tci || (hdr.h2->tp_status & TP_STATUS_VLAN_VALID)) &&
#else
                    hdr.h2->tp_vlan_tci &&
#endif
                    tp_snaplen >= (unsigned int) vlan_offset)
                {
                    struct vlan_tag *tag;

                    data -= VLAN_TAG_LEN;
                    memmove((void *) data, data + VLAN_TAG_LEN, vlan_offset);

                    tag = (struct vlan_tag *) (data + vlan_offset);
                    tag->vlan_tpid = htons(ETH_P_8021Q);
                    tag->vlan_tci = htons(hdr.h2->tp_vlan_tci);

                    tp_snaplen += VLAN_TAG_LEN;
                    tp_len += VLAN_TAG_LEN;
                }

                verdict = DAQ_VERDICT_PASS;
                if (afpc->fcode.bf_insns && sfbpf_filter(afpc->fcode.bf_insns, data, tp_len, tp_snaplen) == 0)
                {
                    ignored_one = 1;
                    afpc->stats.packets_filtered++;
                    goto send_packet;
                }
                got_one = 1;

                daqhdr.ts.tv_sec = tp_sec;
                daqhdr.ts.tv_usec = tp_usec;
                daqhdr.caplen = tp_snaplen;
                daqhdr.pktlen = tp_len;
                daqhdr.ingress_index = instance->index;
                daqhdr.egress_index = instance->peer ? instance->peer->index : DAQ_PKTHDR_UNKNOWN;
                daqhdr.ingress_group = DAQ_PKTHDR_UNKNOWN;
                daqhdr.egress_group = DAQ_PKTHDR_UNKNOWN;
                daqhdr.flags = 0;
                daqhdr.opaque = 0;
                daqhdr.priv_ptr = NULL;
                daqhdr.address_space_id = 0;

                if (callback)
                {
                    verdict = callback(user, &daqhdr, data);
                    if (verdict >= MAX_DAQ_VERDICT)
                        verdict = DAQ_VERDICT_PASS;
                    afpc->stats.verdicts[verdict]++;
                    verdict = verdict_translation_table[verdict];
                }
                afpc->stats.packets_received++;
                c++;
send_packet:
                if (verdict == DAQ_VERDICT_PASS && instance->peer)
                {
                    AFPacketEntry *entry = instance->peer->tx_ring.cursor;
                    int rc;

                    if (entry->hdr.h2->tp_status == TP_STATUS_AVAILABLE)
                    {
                        memcpy(entry->hdr.raw + TPACKET_ALIGN(instance->peer->tp_hdrlen), data, tp_snaplen);
                        entry->hdr.h2->tp_len = tp_snaplen;
                        entry->hdr.h2->tp_status = TP_STATUS_SEND_REQUEST;
                        rc = send(instance->peer->fd, NULL, 0, 0);
                        instance->peer->tx_ring.cursor = entry->next;
                    }
                    /* Else, don't forward the packet... */
                }
                /* Release the TPACKET buffer back to the kernel. */
                switch (instance->tp_version)
                {
                    case TPACKET_V2:
                        hdr.h2->tp_status = TP_STATUS_KERNEL;
                        break;
                }
                instance->rx_ring.cursor = instance->rx_ring.cursor->next;
            }
        }
        if (!got_one && !ignored_one)
        {
            for (i = 0, instance = afpc->instances; instance; i++, instance = instance->next)
            {
                pfd[i].fd = instance->fd;
                pfd[i].revents = 0;
                pfd[i].events = POLLIN;
            }
            ret = poll(pfd, afpc->intf_count, afpc->timeout);
            /* If we were interrupted by a signal, start the loop over.  The user should call daq_breakloop to actually exit. */
            if (ret < 0 && errno != EINTR)
            {
                DPE(afpc->errbuf, "%s: Poll failed: %s (%d)", __FUNCTION__, strerror(errno), errno);
                return DAQ_ERROR;
            }
            /* If the poll times out, return control to the caller. */
            if (ret == 0)
                break;
            /* If some number of of sockets have events returned, check them all for badness. */
            if (ret > 0)
            {
                for (i = 0; i < afpc->intf_count; i++)
                {
                    if (pfd[i].revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL))
                    {
                        if (pfd[i].revents & (POLLHUP | POLLRDHUP))
                            DPE(afpc->errbuf, "%s: Hang-up on a packet socket", __FUNCTION__);
                        else if (pfd[i].revents & POLLERR)
                            DPE(afpc->errbuf, "%s: Encountered error condition on a packet socket", __FUNCTION__);
                        else if (pfd[i].revents & POLLNVAL)
                            DPE(afpc->errbuf, "%s: Invalid polling request on a packet socket", __FUNCTION__);
                        return DAQ_ERROR;
                    }
                }
            }
        }
    }
    return 0;
}