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; }
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; }