예제 #1
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);
        }

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

    SCReturnInt(TM_ECODE_OK);
}
예제 #2
0
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;
}
예제 #3
0
파일: pcap-dag.c 프로젝트: 0mp/freebsd
/*
 *  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 */
예제 #4
0
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;
}
예제 #5
0
파일: pcap-dag.c 프로젝트: DonCN/haiku
/*
 *  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;
			}
		}
	}
예제 #6
0
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;
}
예제 #7
0
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] );
        }
    }
}
예제 #8
0
파일: dag.c 프로젝트: DPMI/mp
static void dagcapture_fill_buffer(struct dag_context* cap){
	cap->top = dag_advance_stream(cap->fd, RX_STREAM, &cap->bottom);
}
예제 #9
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);
}