/** * \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); } SCLogDebug("Read %d records from stream: %d, DAG: %s", pkts_read, dtv->dagstream, dtv->dagname); } SCReturnInt(TM_ECODE_OK); }
int pfring_dag_poll(pfring *ring, u_int wait_duration) { pfring_dag *d; if(ring->priv_data == NULL) return -1; d = (pfring_dag *) ring->priv_data; if ((d->top - d->bottom) >= dag_record_size) return 1; if ( (d->top = dag_advance_stream(d->fd, d->stream_num, (void * /* but it is void** */) &d->bottom)) == NULL) return -1; if ( (d->top - d->bottom) < dag_record_size ) return 0; return 1; }
/* * Read at most max_packets from the capture stream and call the callback * for each of them. Returns the number of packets handled, -1 if an * error occured, or -2 if we were told to break out of the loop. */ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { struct pcap_dag *pd = p->priv; unsigned int processed = 0; unsigned int nonblocking = pd->dag_flags & DAGF_NONBLOCK; unsigned int num_ext_hdr = 0; unsigned int ticks_per_second; /* Get the next bufferful of packets (if necessary). */ while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } /* dag_advance_stream() will block (unless nonblock is called) * until 64kB of data has accumulated. * If to_ms is set, it will timeout before 64kB has accumulated. * We wait for 64kB because processing a few packets at a time * can cause problems at high packet rates (>200kpps) due * to inefficiencies. * This does mean if to_ms is not specified the capture may 'hang' * for long periods if the data rate is extremely slow (<64kB/sec) * If non-block is specified it will return immediately. The user * is then responsible for efficiency. */ if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) { return -1; } if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size)) { /* Pcap is configured to process only available packets, and there aren't any, return immediately. */ return 0; } if(!nonblocking && pd->dag_timeout && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size)) { /* Blocking mode, but timeout set and no data has arrived, return anyway.*/ return 0; } } /* Process the packets. */ while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) { unsigned short packet_len = 0; int caplen = 0; struct pcap_pkthdr pcap_header; dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom); u_char *dp = ((u_char *)header); /* + dag_record_size; */ unsigned short rlen; /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } rlen = ntohs(header->rlen); if (rlen < dag_record_size) { strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE); return -1; } pd->dag_mem_bottom += rlen; /* Count lost packets. */ switch((header->type & 0x7f)) { /* in these types the color value overwrites the lctr */ case ERF_TYPE_COLOR_HDLC_POS: case ERF_TYPE_COLOR_ETH: case ERF_TYPE_DSM_COLOR_HDLC_POS: case ERF_TYPE_DSM_COLOR_ETH: case ERF_TYPE_COLOR_MC_HDLC_POS: case ERF_TYPE_COLOR_HASH_ETH: case ERF_TYPE_COLOR_HASH_POS: break; default: if ( (pd->drop_attr == kNullAttributeUuid) && (header->lctr) ) { pd->stat.ps_drop += ntohs(header->lctr); } } if ((header->type & 0x7f) == ERF_TYPE_PAD) { continue; } num_ext_hdr = dag_erf_ext_header_count(dp, rlen); /* ERF encapsulation */ /* The Extensible Record Format is not dropped for this kind of encapsulation, * and will be handled as a pseudo header by the decoding application. * The information carried in the ERF header and in the optional subheader (if present) * could be merged with the libpcap information, to offer a better decoding. * The packet length is * o the length of the packet on the link (header->wlen), * o plus the length of the ERF header (dag_record_size), as the length of the * pseudo header will be adjusted during the decoding, * o plus the length of the optional subheader (if present). * * The capture length is header.rlen and the byte stuffing for alignment will be dropped * if the capture length is greater than the packet length. */ if (p->linktype == DLT_ERF) { packet_len = ntohs(header->wlen) + dag_record_size; caplen = rlen; switch ((header->type & 0x7f)) { case ERF_TYPE_MC_AAL5: case ERF_TYPE_MC_ATM: case ERF_TYPE_MC_HDLC: case ERF_TYPE_MC_RAW_CHANNEL: case ERF_TYPE_MC_RAW: case ERF_TYPE_MC_AAL2: case ERF_TYPE_COLOR_MC_HDLC_POS: packet_len += 4; /* MC header */ break; case ERF_TYPE_COLOR_HASH_ETH: case ERF_TYPE_DSM_COLOR_ETH: case ERF_TYPE_COLOR_ETH: case ERF_TYPE_ETH: packet_len += 2; /* ETH header */ break; } /* switch type */ /* Include ERF extension headers */ packet_len += (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } } else { /* Other kind of encapsulation according to the header Type */ /* Skip over generic ERF header */ dp += dag_record_size; /* Skip over extension headers */ dp += 8 * num_ext_hdr; switch((header->type & 0x7f)) { case ERF_TYPE_ATM: case ERF_TYPE_AAL5: if ((header->type & 0x7f) == ERF_TYPE_AAL5) { packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size; } case ERF_TYPE_MC_ATM: if ((header->type & 0x7f) == ERF_TYPE_MC_ATM) { caplen = packet_len = ATM_CELL_SIZE; dp+=4; } case ERF_TYPE_MC_AAL5: if ((header->type & 0x7f) == ERF_TYPE_MC_AAL5) { packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size - 4; dp+=4; } /* Skip over extension headers */ caplen -= (8 * num_ext_hdr); if ((header->type & 0x7f) == ERF_TYPE_ATM) { caplen = packet_len = ATM_CELL_SIZE; } if (p->linktype == DLT_SUNATM) { struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp; unsigned long rawatm; rawatm = ntohl(*((unsigned long *)dp)); sunatm->vci = htons((rawatm >> 4) & 0xffff); sunatm->vpi = (rawatm >> 20) & 0x00ff; sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 : ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : ((dp[ATM_HDR_SIZE] == 0xaa && dp[ATM_HDR_SIZE+1] == 0xaa && dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1))); } else if (p->linktype == DLT_ATM_RFC1483) { packet_len -= ATM_HDR_SIZE; caplen -= ATM_HDR_SIZE; dp += ATM_HDR_SIZE; } else continue; break; case ERF_TYPE_COLOR_HASH_ETH: case ERF_TYPE_DSM_COLOR_ETH: case ERF_TYPE_COLOR_ETH: case ERF_TYPE_ETH: if ((p->linktype != DLT_EN10MB) && (p->linktype != DLT_DOCSIS)) continue; packet_len = ntohs(header->wlen); packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 2; /* Skip over extension headers */ caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } dp += 2; break; case ERF_TYPE_COLOR_HASH_POS: case ERF_TYPE_DSM_COLOR_HDLC_POS: case ERF_TYPE_COLOR_HDLC_POS: case ERF_TYPE_HDLC_POS: if ((p->linktype != DLT_CHDLC) && (p->linktype != DLT_PPP_SERIAL) && (p->linktype != DLT_FRELAY)) continue; packet_len = ntohs(header->wlen); packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size; /* Skip over extension headers */ caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } break; case ERF_TYPE_COLOR_MC_HDLC_POS: case ERF_TYPE_MC_HDLC: if ((p->linktype != DLT_CHDLC) && (p->linktype != DLT_PPP_SERIAL) && (p->linktype != DLT_FRELAY) && (p->linktype != DLT_MTP2) && (p->linktype != DLT_MTP2_WITH_PHDR) && (p->linktype != DLT_LAPD)) continue; packet_len = ntohs(header->wlen); packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 4; /* Skip over extension headers */ caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } /* jump the MC_HDLC_HEADER */ dp += 4; #ifdef DLT_MTP2_WITH_PHDR if (p->linktype == DLT_MTP2_WITH_PHDR) { /* Add the MTP2 Pseudo Header */ caplen += MTP2_HDR_LEN; packet_len += MTP2_HDR_LEN; TempPkt[MTP2_SENT_OFFSET] = 0; TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN; *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01); *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff); memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen); dp = TempPkt; } #endif break; case ERF_TYPE_IPV4: if ((p->linktype != DLT_RAW) && (p->linktype != DLT_IPV4)) continue; packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size; /* Skip over extension headers */ caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } break; case ERF_TYPE_IPV6: if ((p->linktype != DLT_RAW) && (p->linktype != DLT_IPV6)) continue; packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size; /* Skip over extension headers */ caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } break; /* These types have no matching 'native' DLT, but can be used with DLT_ERF above */ case ERF_TYPE_MC_RAW: case ERF_TYPE_MC_RAW_CHANNEL: case ERF_TYPE_IP_COUNTER: case ERF_TYPE_TCP_FLOW_COUNTER: case ERF_TYPE_INFINIBAND: case ERF_TYPE_RAW_LINK: case ERF_TYPE_INFINIBAND_LINK: default: /* Unhandled ERF type. * Ignore rather than generating error */ continue; } /* switch type */ } /* ERF encapsulation */
int pfring_dag_recv(pfring *ring, u_char** buffer, u_int buffer_len, struct pfring_pkthdr *hdr, u_int8_t wait_for_incoming_packet) { int caplen = 0; int skip; dag_record_t *erf_hdr; uint16_t rlen; u_char *payload; uint8_t *ext_hdr_type; uint32_t ext_hdr_num; uint32_t len; unsigned long long ts; int retval = 0; if(ring->priv_data == NULL) return -1; pfring_dag *d = (pfring_dag *) ring->priv_data; if(ring->reentrant) pthread_spin_lock(&ring->spinlock); check_and_poll: if (ring->break_recv_loop) goto exit; /* retval = 0 */ if ((d->top - d->bottom) < dag_record_size) { if ( (d->top = dag_advance_stream(d->fd, d->stream_num, (void * /* but it is void** */) &d->bottom)) == NULL) { retval = -1; goto exit; } if ( (d->top - d->bottom) < dag_record_size && !wait_for_incoming_packet ) goto exit; /* retval = 0 */ goto check_and_poll; } erf_hdr = (dag_record_t *) d->bottom; rlen = ntohs(erf_hdr->rlen); if (rlen < dag_record_size) { fprintf(stderr, "Error: wrong record size\n"); retval = -1; goto exit; } d->bottom += rlen; skip = 0; switch((erf_hdr->type & 0x7f)) { case TYPE_PAD: skip = 1; case TYPE_ETH: /* stats update */ if (erf_hdr->lctr) { if (d->stats_drop > (UINT_MAX - ntohs(erf_hdr->lctr))) d->stats_drop = UINT_MAX; else d->stats_drop += ntohs(erf_hdr->lctr); } break; default: break; } if (skip) goto check_and_poll; payload = (u_char *) erf_hdr; payload += dag_record_size; /* computing extension headers size */ ext_hdr_type = &erf_hdr->type; ext_hdr_num = 0; while ( (*ext_hdr_type & 0x80) && (rlen > (16 + ext_hdr_num * 8)) ) { ext_hdr_type += 8; ext_hdr_num++; } payload += 8 * ext_hdr_num; switch((erf_hdr->type & 0x7f)) { case TYPE_COLOR_HASH_ETH: case TYPE_DSM_COLOR_ETH: case TYPE_COLOR_ETH: case TYPE_ETH: len = ntohs(erf_hdr->wlen); if (d->strip_crc) len -= 4; caplen = rlen; caplen -= dag_record_size; caplen -= (8 * ext_hdr_num); caplen -= 2; if (caplen > ring->caplen) caplen = ring->caplen; if (caplen > len) caplen = len; if((buffer_len > 0) && (caplen > buffer_len)) caplen = buffer_len; payload += 2; break; default: #ifdef DAG_DEBUG printf("Warning: unhandled ERF type\n"); #endif goto check_and_poll; } if (buffer_len > 0){ if(*buffer != NULL && caplen > 0) memcpy(*buffer, payload, caplen); } else *buffer = payload; hdr->caplen = caplen; hdr->len = len; /* computing timestamp as from DAG docs */ ts = erf_hdr->ts; hdr->ts.tv_sec = ts >> 32; ts = (ts & 0xffffffffULL) * 1000000; ts += 0x80000000; hdr->ts.tv_usec = ts >> 32; if (hdr->ts.tv_usec >= 1000000) { hdr->ts.tv_usec -= 1000000; hdr->ts.tv_sec++; } #ifdef PFRING_DAG_PARSE_PKT parse_pkt(*buffer, hdr); #else hdr->extended_hdr.parsed_header_len = 0; #endif d->stats_recv++; retval = 1; exit: if(ring->reentrant) pthread_spin_unlock(&ring->spinlock); return retval; }
/* * Read at most max_packets from the capture stream and call the callback * for each of them. Returns the number of packets handled, -1 if an * error occured, or -2 if we were told to break out of the loop. */ static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { unsigned int processed = 0; int flags = p->md.dag_offset_flags; unsigned int nonblocking = flags & DAGF_NONBLOCK; /* Get the next bufferful of packets (if necessary). */ while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } #ifdef HAVE_DAG_STREAMS_API /* dag_advance_stream() will block (unless nonblock is called) * until 64kB of data has accumulated. * If to_ms is set, it will timeout before 64kB has accumulated. * We wait for 64kB because processing a few packets at a time * can cause problems at high packet rates (>200kpps) due * to inefficiencies. * This does mean if to_ms is not specified the capture may 'hang' * for long periods if the data rate is extremely slow (<64kB/sec) * If non-block is specified it will return immediately. The user * is then responsible for efficiency. */ p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom)); #else /* dag_offset does not support timeouts */ p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags); #endif /* HAVE_DAG_STREAMS_API */ if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) { /* Pcap is configured to process only available packets, and there aren't any, return immediately. */ return 0; } if(!nonblocking && p->md.dag_timeout && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) { /* Blocking mode, but timeout set and no data has arrived, return anyway.*/ return 0; } } /* Process the packets. */ while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) { unsigned short packet_len = 0; int caplen = 0; struct pcap_pkthdr pcap_header; #ifdef HAVE_DAG_STREAMS_API dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom); #else dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom); #endif /* HAVE_DAG_STREAMS_API */ u_char *dp = ((u_char *)header) + dag_record_size; unsigned short rlen; /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that * it has, and return -2 to indicate that * we were told to break out of the loop. */ p->break_loop = 0; return -2; } rlen = ntohs(header->rlen); if (rlen < dag_record_size) { strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE); return -1; } p->md.dag_mem_bottom += rlen; switch(header->type) { case TYPE_ATM: #ifdef TYPE_AAL5 case TYPE_AAL5: if (header->type == TYPE_AAL5) { packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size; } #endif #ifdef TYPE_MC_ATM case TYPE_MC_ATM: if (header->type == TYPE_MC_ATM) { caplen = packet_len = ATM_CELL_SIZE; dp+=4; } #endif #ifdef TYPE_MC_AAL5 case TYPE_MC_AAL5: if (header->type == TYPE_MC_AAL5) { packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size - 4; dp+=4; } #endif if (header->type == TYPE_ATM) { caplen = packet_len = ATM_CELL_SIZE; } if (p->linktype == DLT_SUNATM) { struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp; unsigned long rawatm; rawatm = ntohl(*((unsigned long *)dp)); sunatm->vci = htons((rawatm >> 4) & 0xffff); sunatm->vpi = (rawatm >> 20) & 0x00ff; sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 : ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : ((dp[ATM_HDR_SIZE] == 0xaa && dp[ATM_HDR_SIZE+1] == 0xaa && dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1))); } else { packet_len -= ATM_HDR_SIZE; caplen -= ATM_HDR_SIZE; dp += ATM_HDR_SIZE; } break; #ifdef TYPE_COLOR_ETH case TYPE_COLOR_ETH: #endif case TYPE_ETH: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 2; if (caplen > packet_len) { caplen = packet_len; } dp += 2; break; #ifdef TYPE_COLOR_HDLC_POS case TYPE_COLOR_HDLC_POS: #endif case TYPE_HDLC_POS: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size; if (caplen > packet_len) { caplen = packet_len; } break; #ifdef TYPE_MC_HDLC case TYPE_MC_HDLC: packet_len = ntohs(header->wlen); packet_len -= (p->md.dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 4; if (caplen > packet_len) { caplen = packet_len; } dp += 4; break; #endif } if (caplen > p->snapshot) caplen = p->snapshot; /* Count lost packets. */ switch(header->type) { #ifdef TYPE_COLOR_HDLC_POS /* in this type the color value overwrites the lctr */ case TYPE_COLOR_HDLC_POS: break; #endif #ifdef TYPE_COLOR_ETH /* in this type the color value overwrites the lctr */ case TYPE_COLOR_ETH: break; #endif default: if (header->lctr) { if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { p->md.stat.ps_drop = UINT_MAX; } else { p->md.stat.ps_drop += ntohs(header->lctr); } } } /* Run the packet filter if there is one. */ if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { /* convert between timestamp formats */ register unsigned long long ts; if (IS_BIGENDIAN()) { ts = SWAP_TS(header->ts); } else { ts = header->ts; } pcap_header.ts.tv_sec = ts >> 32; ts = (ts & 0xffffffffULL) * 1000000; ts += 0x80000000; /* rounding */ pcap_header.ts.tv_usec = ts >> 32; if (pcap_header.ts.tv_usec >= 1000000) { pcap_header.ts.tv_usec -= 1000000; pcap_header.ts.tv_sec++; } /* Fill in our own header data */ pcap_header.caplen = caplen; pcap_header.len = packet_len; /* Count the packet. */ p->md.stat.ps_recv++; /* Call the user supplied callback function */ callback(user, &pcap_header, dp); /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */ processed++; if (processed == cnt) { /* Reached the user-specified limit. */ return cnt; } } }
static int endace_daq_acquire(void *handle, int cnt, DAQ_Analysis_Func_t callback, void *user) { #elif DAQ_API_VERSION == 0x00010002 static int endace_daq_acquire(void *handle, int cnt, DAQ_Analysis_Func_t callback, DAQ_Meta_Func_t metaback, void *user) { #endif int packets = 0; DAQ_PktHdr_t hdr; DAQ_Verdict verdict; uint8_t *frame = NULL; uint8_t *cp = NULL; uint8_t *ep = NULL; uint64_t lts; dag_record_t *rec; size_t reclen; EndaceDAGCtx_t *ctx = (EndaceDAGCtx_t *) handle; if (!ctx) { return DAQ_ERROR; } ctx->analysis_func = callback; while (!ctx->breakloop && (packets < cnt || cnt <=0)) { if ((ep = dag_advance_stream(ctx->fd, ctx->stream, &cp)) == NULL) { snprintf(ctx->errbuf, ERROR_BUF_SIZE, "%s: failed advancing stream: %d on Endace adapter: %s!", __FUNCTION__, ctx->stream, ctx->name); return DAQ_ERROR; } if (ep-cp == 0) continue; while (cp < ep && (packets < cnt || cnt <=0)) { rec = (dag_record_t*)cp; reclen = ntohs(rec->rlen); /* Advance the stream if a short read is detected */ if ((ep-cp) < reclen) break; /* Advance the current pointer */ cp += reclen; if (rec->type != TYPE_ETH) continue; frame = &(rec->rec.eth.dst[0]); hdr.caplen = (((uint8_t *)rec + reclen) - frame); hdr.pktlen = hdr.caplen; lts = rec->ts; hdr.ts.tv_sec = lts >> 32; lts = ((lts & 0xffffffffULL) * 1000 * 1000); lts += (lts & 0x80000000ULL) << 1; hdr.ts.tv_usec = lts >> 32; if(hdr.ts.tv_usec >= 1000000) { hdr.ts.tv_sec += 1; hdr.ts.tv_usec -= 1000000; } #if DAQ_API_VERSION == 0x00010001 hdr.device_index = -1; #elif DAQ_API_VERSION == 0x00010002 hdr.ingress_index = -1; hdr.ingress_group = -1; hdr.egress_index = -1; hdr.egress_group = -1; #endif hdr.flags = 0; ctx->stats.packets_received++; verdict = ctx->analysis_func(user, &hdr, frame); if (verdict >= MAX_DAQ_VERDICT) { verdict = DAQ_VERDICT_PASS; } ctx->stats.verdicts[verdict]++; packets++; if(rec->lctr) ctx->stats.hw_packets_dropped += rec->lctr; } } return DAQ_SUCCESS; }
void do_packet_capture(void) { // int ret; static uint8_t *bottom = NULL; static uint8_t *top = NULL; ULONG total_read, buffer_len, read_size, diff; /* * The main Dag capture loop, wait for data and deliver. */ while( loop_continue ) { #if 0 top = dag_advance_stream(dag_fd, dag_devnum, &bottom); if(top == NULL) { dagutil_panic("dag_advance_stream %s:%u: %s\n", dagname, dag_devnum, strerror(errno)); log_print(LOGN_CRI, "%s: FAIL[dag_start_stream] [%s]", __FUNCTION__, strerror(errno)); close_device(); exit(errno); } #endif diff = top - bottom; if( diff > 0 ) { /* read multiple packets */ buffer_len = diff; total_read = 0; while( total_read < diff ) { read_size = read_one_packet(&bottom[total_read], buffer_len, 0 ); if( read_size < 0 ) { close_device(); exit(-1); } else if( read_size == 0 ) break; total_read += read_size; buffer_len -= read_size; } bottom += total_read; } else { #if 0 curTime = time(NULL); if(oldTime + 5 < curTime) { if(Send_Node_Cnt && Send_Node_Cnt == Diff_Node_Cnt) { /* Send Buffring Packet */ if((ret = Send_CAPD_Data(pstMEMSINFO, myqid, NULL, 0)) < 0) { log_print(LOGN_CRI, "[%s.%d] Send_CAPD_Data [%d][%s]", __FUNCTION__, __LINE__, ret, strerror(-ret)); } Collection_Cnt = 50; // COLLECTIONCNT_MIN 으로 설정 } Diff_Node_Cnt = Send_Node_Cnt; oldTime = curTime; } #endif usleep(0); } /* CHECK ACTIVE & STANDBY STATUS */ curTime = time(NULL); if( chkTime != curTime ) { if( stPortStatus[0].uiLastCnt == stPortStatus[0].uiCurrCnt ) { stPortStatus[0].uiRetryCnt++; if( stPortStatus[0].uiRetryCnt > 2 ) { fidb->mirrorsts[0] = CRITICAL; if( fidb->mirrorActsts[0] == DEF_ACTIVE && fidb->mirrorsts[1] != CRITICAL ) { fidb->mirrorActsts[0] = DEF_STANDBY; fidb->mirrorActsts[1] = DEF_ACTIVE; log_print( LOGN_CRI, "CHANGE ACTIVE 0 -> 1.."); } } } else { fidb->mirrorsts[0] = NORMAL; stPortStatus[0].uiRetryCnt = 0; stPortStatus[0].uiLastCnt = stPortStatus[0].uiCurrCnt; } if( stPortStatus[1].uiLastCnt == stPortStatus[1].uiCurrCnt ) { stPortStatus[1].uiRetryCnt++; if( stPortStatus[1].uiRetryCnt > 2 ) { fidb->mirrorsts[1] = CRITICAL; if( fidb->mirrorActsts[1] == DEF_ACTIVE && fidb->mirrorsts[0] != CRITICAL ) { fidb->mirrorActsts[1] = DEF_STANDBY; fidb->mirrorActsts[0] = DEF_ACTIVE; log_print( LOGN_CRI, "CHANGE ACTIVE 1 -> 0.."); } } } else { fidb->mirrorsts[1] = NORMAL; stPortStatus[1].uiRetryCnt = 0; stPortStatus[1].uiLastCnt = stPortStatus[1].uiCurrCnt; } chkTime = curTime; log_print( LOGN_DEBUG, "[0] STS:0X%02X ACT:%u [1] STS:0X%02X ACT:%u", fidb->mirrorsts[0], fidb->mirrorActsts[0], fidb->mirrorsts[1], fidb->mirrorActsts[1] ); } } }
static void dagcapture_fill_buffer(struct dag_context* cap){ cap->top = dag_advance_stream(cap->fd, RX_STREAM, &cap->bottom); }
/** * \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); }