Exemple #1
0
int archEthRecvPacket(UInt8** buffer, UInt32* length) 
{
    static UInt8 buf[65536];

    if (ethIf.pcapHandle == NULL) {
        return 0;
    }

    if (ethIf.packetOffset >= ethIf.packetLenth) {
        ethIf.packetOffset = 0;
        ethIf.packetLenth = 0;

        pcapPacketInitPacket(ethIf.pkRecv, (char*)buf, sizeof(buf));
        if (pcapPacketReceivePacket(ethIf.pcapHandle, ethIf.pkRecv, TRUE)) {
            ethIf.packetLenth = ethIf.pkRecv->ulBytesReceived;
        }
    }

    if (ethIf.packetOffset < ethIf.packetLenth) {
        UInt8* packetStart = (UInt8*)ethIf.pkRecv->Buffer + ethIf.packetOffset;
        struct bpf_hdr* hdr = (struct bpf_hdr*)packetStart;
        *buffer = packetStart + hdr->bh_hdrlen;
        *length = hdr->bh_caplen;
        ethIf.packetOffset += Packet_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
        return 1;
    }

    return 0;
}
Exemple #2
0
int _recvPacket(void *pData) {
	struct bpf_hdr *hdr;
	u8 *data;
	int ret=0;
	int size;

	while (lbytes > 0) {
		hdr = (struct bpf_hdr *)buf;
//		DEV9_LOG("hdr %d,%d,%d\n", hdr->bh_hdrlen, hdr->bh_caplen, hdr->bh_datalen);
//		DEV9_LOG("lbytes %d\n", lbytes);
		data = buf+hdr->bh_hdrlen;
		size = Packet_WORDALIGN(hdr->bh_hdrlen+hdr->bh_datalen);
		buf+= size; lbytes-= size;
		if (_filterPacket(data)) {
			struct bpf_stat stat;

			ret = hdr->bh_datalen;
			memcpy(pData, data, ret);
			if(PacketGetStats(lpAdapter,&stat)==FALSE){
				printf("Warning: unable to get stats from the kernel!\n");
			}
//			printf("_recvPacket %d (tbytes=%d, packets=%d, lost=%d, time=%d)\n", ret, tbytes, stat.bs_recv,stat.bs_drop, timeGetTime());
//			printf("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", data[5], data[4], data[3], data[2], data[1], data[0]);
			break;
		}
	}

	return ret;
}
Exemple #3
0
void checkpackets() // check for and process packets
{

	PacketReceivePacket(lpAdapter,lpPacket,TRUE);	


	char *data;
	data = (char *)lpPacket->Buffer;
	int tbytes;
	tbytes = lpPacket->ulBytesReceived;
	int reader = 0;
	while(reader < tbytes)
	{
		bpf_hdr *header;
		header=(struct bpf_hdr *)(data+reader);
		int datalength = header->bh_datalen;
		int totallength = header->bh_caplen;
		reader = reader + header->bh_hdrlen;
		char *readme;
		readme = data+reader;
		printpacket((unsigned char *)readme, datalength);
		reader = Packet_WORDALIGN(reader+datalength);
	}



}
Exemple #4
0
void PrintPackets(LPPACKET lpPacket)
{

	ULONG	i, j, ulLines, ulen, ulBytesReceived;
	char	*pChar, *pLine, *base;
	char	*buf;
	u_int off=0;
	u_int tlen,tlen1;
	struct bpf_hdr *hdr;
	
		ulBytesReceived = lpPacket->ulBytesReceived;


		buf = lpPacket->Buffer;

		off=0;

		while(off<ulBytesReceived){	
			if(kbhit())return;
		hdr=(struct bpf_hdr *)(buf+off);
		tlen1=hdr->bh_datalen;
		tlen=hdr->bh_caplen;
		printf("Packet length, captured portion: %ld, %ld\n", tlen1, tlen);
		off+=hdr->bh_hdrlen;

		ulLines = (tlen + 15) / 16;

		pChar =(char*)(buf+off);
		base=pChar;
		off=Packet_WORDALIGN(off+tlen);
		
		for ( i=0; i<ulLines; i++ )
		{

			pLine =pChar;

			printf( "%08lx : ", pChar-base );

			ulen=tlen;
			ulen = ( ulen > 16 ) ? 16 : ulen;
			tlen -= ulen;

			for ( j=0; j<ulen; j++ )
				printf( "%02x ", *(BYTE *)pChar++ );

			if ( ulen < 16 )
				printf( "%*s", (16-ulen)*3, " " );

			pChar = pLine;

			for ( j=0; j<ulen; j++, pChar++ )
				printf( "%c", isprint( (unsigned char)*pChar ) ? *pChar : '.' );

			printf( "\n" );
		} 

		printf( "\n" );
		}
} 
//抓包处理函数,解析出单个Packet
void NetworkInterface::SplitPackets(LPPACKET &lpPacket)
{
	ULONG   ulBytesReceived;
	char	*pChar;
	char	*buf;
	u_int   off = 0;

	//caplen为捕获的数据长度,datalen为原始数据长度
	//caplen可能小于datalen
	u_int   caplen, datalen;	
	struct  bpf_hdr *hdr;
	
	//收到的字节数
	ulBytesReceived = lpPacket->ulBytesReceived;

	//缓冲区首地址
	buf = (char*)lpPacket->Buffer;

	//初始化偏移量为0
	off = 0;
	
	while (off < ulBytesReceived)
	{	
		hdr = (struct bpf_hdr *)(buf + off);
		datalen = hdr->bh_datalen;
		caplen  = hdr->bh_caplen;

		//校验捕获的包是否完整,对于不完整的包不做处理
		if(caplen != datalen)
			break;
		off += hdr->bh_hdrlen;

		//单包数据段首地址
		pChar = (char*)(buf + off);

		//跳到下一个包的首地址(可能不存在)
		off = Packet_WORDALIGN(off + caplen);

		//对于自己的Packet不做响应
		if(memcmp((pChar + 6), srcMAC, 6) == 0)
			continue;
		/*在此处处理每个数据包,首地址为pChar,长度为caplen*/
		//在此处调用外部函数处理数据包
		//PrintPacket((u_char*)pChar, caplen, 0);
        if(p != NULL)
		    p->HandlePacket((u_char*)pChar, caplen);	
	}
}
Exemple #6
0
void bx_win32_pktmover_c::rx_timer(void)
{
    // Recieve Packet ????
    char           *pBuf;
    unsigned char  *pPacket;
    unsigned int   iOffset = 0;
    struct bpf_hdr *hdr;
    int pktlen;

    PacketInitPacket(pkRecv, (char *)buffer, 256000);
    if (WaitForSingleObject(lpAdapter->ReadEvent,0) == WAIT_OBJECT_0 || IsNT) {
        PacketReceivePacket(lpAdapter, pkRecv, TRUE);
        pBuf = (char *)pkRecv->Buffer;
        iOffset = 0;
        while(iOffset < pkRecv->ulBytesReceived)
        {
            hdr = (struct bpf_hdr *)(pBuf + iOffset);
            pPacket = (unsigned char *)(pBuf + iOffset + hdr->bh_hdrlen);
            if (memcmp(pPacket + 6, cMacAddr, 6) != 0) // src field != ours
            {
                if(memcmp(pPacket, cMacAddr, 6) == 0 || memcmp(pPacket, broadcast_macaddr, 6) == 0)
                {
                    pktlen = hdr->bh_caplen;
                    if (pktlen < 60) pktlen = 60;
#if BX_ETH_WIN32_LOGGING
                    fprintf (pktlog_txt, "a packet from host to guest, length %u\n", pktlen);
                    Bit8u *charbuf = (Bit8u *)pPacket;
                    int n;
                    for (n=0; n<pktlen; n++) {
                        if (((n % 16) == 0) && n>0)
                            fprintf (pktlog_txt, "\n");
                        fprintf (pktlog_txt, "%02x ", (unsigned)charbuf[n]);
                    }
                    fprintf (pktlog_txt, "\n--\n");
                    fflush (pktlog_txt);
#endif
                    (*rx_handler)(rx_Arg, pPacket, pktlen);
                }
            }
            iOffset = Packet_WORDALIGN(iOffset + (hdr->bh_hdrlen + hdr->bh_caplen));
        }
    }
}
Exemple #7
0
/**
 * Process a packet buffer (which can hold multiple packets) and feed
 * every packet to process_input().
 *
 * @param adapter adapter handle received by a call to init_adapter
 * @param lpPacket the packet buffer to process
 */
static void
ProcessPackets(void *adapter, LPPACKET lpPacket)
{
  struct packet_adapter *pa = (struct packet_adapter*)adapter;
  ULONG  ulLines, ulBytesReceived;
  char  *base;
  char  *buf;
  u_int off = 0;
  u_int tlen, tlen1;
  struct bpf_hdr *hdr;
  void *cur_packet;
  int cur_length;

  if (pa == NULL) {
    return;
  }

  ulBytesReceived = lpPacket->ulBytesReceived;

  buf = (char*)lpPacket->Buffer;

  off=0;

  while (off < ulBytesReceived) {
    hdr = (struct bpf_hdr *)(buf + off);
    tlen1 = hdr->bh_datalen;
    cur_length = tlen1;
    tlen = hdr->bh_caplen;
    off += hdr->bh_hdrlen;

    ulLines = (tlen + 15) / 16;
    if (ulLines > 5) {
      ulLines = 5;
    }

    base =(char*)(buf + off);
    cur_packet = base;
    off = Packet_WORDALIGN(off + tlen);

    pa->input(pa->input_fn_arg, cur_packet, cur_length);
  }
}
void SniffPacketThread::Run()
{
	u_int tlen = 0, offset = 0;
	struct bpf_hdr *hdr = NULL;
		
	while(1)
	{
		if(m_stop_flag) break;

		try
		{
			if(PacketReceivePacket(m_lpa, m_lpp, TRUE) == FALSE)
				continue;
		}
		catch(...)
		{
			TRACE0("Exception in packet receive thread");
			return;
		}
		
		// Grab total length
		tlen = m_lpp->ulBytesReceived;

		// Process all the packets we've been handed
		offset = 0;
		while(offset < tlen)
		{
			hdr = (struct bpf_hdr *)(m_pbuf + offset);
			offset += hdr->bh_hdrlen;
			unsigned char *pkt = (unsigned char *)(m_pbuf + offset);
			u_int len = hdr->bh_caplen;
			
			// Adjust offset to next pkt w/ alignment
			offset = Packet_WORDALIGN(offset + hdr->bh_caplen);
						
			// we don't need to free the packet since it's static
			// for this loop
			m_parent->ProcessSniffedPacket( pkt, len );
		}
		Sleep(1);
	}
}
Exemple #9
0
static int
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	PACKET Packet;
	int cc;
	int n = 0;
	register u_char *bp, *ep;
	u_char *datap;
	struct pcap_win *pw = p->priv;

	cc = p->cc;
	if (p->cc == 0) {
		/*
		 * Has "pcap_breakloop()" been called?
		 */
		if (p->break_loop) {
			/*
			 * Yes - clear the flag that indicates that it
			 * has, and return PCAP_ERROR_BREAK to indicate
			 * that we were told to break out of the loop.
			 */
			p->break_loop = 0;
			return (PCAP_ERROR_BREAK);
		}

		/*
		 * Capture the packets.
		 *
		 * The PACKET structure had a bunch of extra stuff for
		 * Windows 9x/Me, but the only interesting data in it
		 * in the versions of Windows that we support is just
		 * a copy of p->buffer, a copy of p->buflen, and the
		 * actual number of bytes read returned from
		 * PacketReceivePacket(), none of which has to be
		 * retained from call to call, so we just keep one on
		 * the stack.
		 */
		PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
		if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) {
			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
			return (PCAP_ERROR);
		}

		cc = Packet.ulBytesReceived;

		bp = p->buffer;
	}
	else
		bp = p->bp;

	/*
	 * Loop through each packet.
	 */
#define bhp ((struct bpf_hdr *)bp)
	ep = bp + cc;
	for (;;) {
		register int caplen, hdrlen;

		/*
		 * Has "pcap_breakloop()" been called?
		 * If so, return immediately - if we haven't read any
		 * packets, clear the flag and return PCAP_ERROR_BREAK
		 * to indicate that we were told to break out of the loop,
		 * otherwise leave the flag set, so that the *next* call
		 * will break out of the loop without having read any
		 * packets, and return the number of packets we've
		 * processed so far.
		 */
		if (p->break_loop) {
			if (n == 0) {
				p->break_loop = 0;
				return (PCAP_ERROR_BREAK);
			} else {
				p->bp = bp;
				p->cc = (int) (ep - bp);
				return (n);
			}
		}
		if (bp >= ep)
			break;

		caplen = bhp->bh_caplen;
		hdrlen = bhp->bh_hdrlen;
		datap = bp + hdrlen;

		/*
		 * Short-circuit evaluation: if using BPF filter
		 * in kernel, no need to do it now - we already know
		 * the packet passed the filter.
		 *
		 * XXX - bpf_filter() should always return TRUE if
		 * handed a null pointer for the program, but it might
		 * just try to "run" the filter, so we check here.
		 */
		if (pw->filtering_in_kernel ||
		    p->fcode.bf_insns == NULL ||
		    bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
#ifdef ENABLE_REMOTE
			switch (p->rmt_samp.method) {

			case PCAP_SAMP_1_EVERY_N:
				pw->samp_npkt = (pw->samp_npkt + 1) % p->rmt_samp.value;

				/* Discard all packets that are not '1 out of N' */
				if (pw->samp_npkt != 0) {
					bp += Packet_WORDALIGN(caplen + hdrlen);
					continue;
				}
				break;

			case PCAP_SAMP_FIRST_AFTER_N_MS:
			    {
				struct pcap_pkthdr *pkt_header = (struct pcap_pkthdr*) bp;

				/*
				 * Check if the timestamp of the arrived
				 * packet is smaller than our target time.
				 */
				if (pkt_header->ts.tv_sec < pw->samp_time.tv_sec ||
				   (pkt_header->ts.tv_sec == pw->samp_time.tv_sec && pkt_header->ts.tv_usec < pw->samp_time.tv_usec)) {
					bp += Packet_WORDALIGN(caplen + hdrlen);
					continue;
				}

				/*
				 * The arrived packet is suitable for being
				 * delivered to our caller, so let's update
				 * the target time.
				 */
				pw->samp_time.tv_usec = pkt_header->ts.tv_usec + p->rmt_samp.value * 1000;
				if (pw->samp_time.tv_usec > 1000000) {
					pw->samp_time.tv_sec = pkt_header->ts.tv_sec + pw->samp_time.tv_usec / 1000000;
					pw->samp_time.tv_usec = pw->samp_time.tv_usec % 1000000;
				}
			    }
			}
#endif	/* ENABLE_REMOTE */

			/*
			 * XXX A bpf_hdr matches a pcap_pkthdr.
			 */
			(*callback)(user, (struct pcap_pkthdr*)bp, datap);
			bp += Packet_WORDALIGN(caplen + hdrlen);
			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
				p->bp = bp;
				p->cc = (int) (ep - bp);
				return (n);
			}
		} else {
			/*
			 * Skip this packet.
			 */
			bp += Packet_WORDALIGN(caplen + hdrlen);
		}
	}
#undef bhp
	p->cc = 0;
	return (n);
}
// Read next packet
UINT EthGetPacket(ETH *e, void **data)
{
	BLOCK *b;
	bool flag = false;
	// Validate arguments
	if (e == NULL || data == NULL)
	{
		return INFINITE;
	}
	if (e->HasFatalError)
	{
		return INFINITE;
	}

	if (e->SuAdapter != NULL)
	{
		// Read packet with SeLow
		UINT size;
		if (SuGetNextPacket(e->SuAdapter, data, &size) == false)
		{
			// Error occurred
			e->HasFatalError = true;
			return INFINITE;
		}

		return size;
	}

RETRY:
	// Check the presence of the packet in queue
	b = GetNext(e->PacketQueue);
	if (b != NULL)
	{
		UINT size;
		size = b->Size;
		*data = b->Buf;
		Free(b);

		if (e->PacketQueue->num_item == 0)
		{
			e->Empty = true;
		}

		return size;
	}

	if (e->Empty)
	{
		e->Empty = false;
		return 0;
	}

	if (flag == false)
	{
		// Try to get next packet
		PROBE_STR("EthGetPacket: PacketInitPacket");
		wp->PacketInitPacket(e->Packet, e->Buffer, e->BufferSize);
		PROBE_STR("EthGetPacket: PacketReceivePacket");
		if (wp->PacketReceivePacket(e->Adapter, e->Packet, false) == false)
		{
			// Failed
			return INFINITE;
		}
		else
		{
			UCHAR *buf;
			UINT total;
			UINT offset;

			buf = (UCHAR *)e->Packet->Buffer;
			total = e->Packet->ulBytesReceived;
			offset = 0;

			while (offset < total)
			{
				struct bpf_hdr *header;
				UINT packet_size;
				UCHAR *packet_data;

				header = (struct bpf_hdr *)(buf + offset);
				packet_size = header->bh_caplen;
				offset += header->bh_hdrlen;
				packet_data = buf + offset;
				offset = Packet_WORDALIGN(offset + packet_size);

				if (packet_size >= 14)
				{
					UCHAR *tmp;
					BLOCK *b;

					PROBE_DATA2("EthGetPacket: NewBlock", packet_data, packet_size);
					
					tmp = MallocFast(packet_size);

					Copy(tmp, packet_data, packet_size);
					b = NewBlock(tmp, packet_size, 0);
					InsertQueue(e->PacketQueue, b);
				}
			}

			flag = true;
			goto RETRY;
		}
	}

	// No more packet
	return 0;
}
Exemple #11
0
/**
 * Our low-level capture thread.
 *
 * Loop waiting for packet(s) in PacketReceivePacket(). In
 * _pkt_release() the receive event-handle (adapter->Readvent) is
 * set. This causes WaitForSingleObject() in PacketReceivePacket()
 * to return. It is vital that the ADAPTER object isn't deallocated
 * before PacketReceivePacket() returns.
 *
 * The return-value is > 0 if thread exited on it's own. Otherwise
 * it is 0  (from  GetExitCodeThread).
 */
DWORD __stdcall pkt_recv_thread (void *arg)
{
  int rc = 0;

  while (1)
  {
    const  ADAPTER *adapter;
    const  BYTE *pkt, *pkt_end;
    size_t cap_len, hdr_len;
    int    total_len, chunk;
    PACKET npf_pkt;

    if (!_pkt_inf || _pkt_inf->stop_thread)  /* signals closure */
    {
      rc = 1;
      break;
    }

    adapter  = (const ADAPTER*) _pkt_inf->adapter;
    npf_pkt.Length = _pkt_inf->npf_buf_size;
    npf_pkt.Buffer = _pkt_inf->npf_buf;

    if (!PacketReceivePacket(adapter, &npf_pkt, TRUE))
    {
      rc = 2;
      break;
    }
    total_len = npf_pkt.ulBytesReceived;

    ENTER_CRIT();

    for (pkt = npf_pkt.Buffer, pkt_end = (BYTE*)npf_pkt.Buffer + total_len, chunk = 1;
         pkt < pkt_end;
         pkt += Packet_WORDALIGN(cap_len+hdr_len), chunk++)
    {
      struct pkt_ringbuf    *q;
      struct pkt_rx_element *head;
      struct bpf_hdr        *bp;

      q  = &_pkt_inf->pkt_queue;
      bp = (struct bpf_hdr*) pkt;

      cap_len = bp->bh_caplen;
      hdr_len = bp->bh_hdrlen;

      num_rx_bytes += bp->bh_datalen;

      TCP_CONSOLE_MSG (2, ("pkt_recv_thread(): total_len %d, "
                           "chunk %d, cap_len %d, in-idx %d\n",
                       total_len, chunk, cap_len, q->in_index));

      if (cap_len > ETH_MAX)
      {
        _pkt_inf->error = "Large size";
        STAT (macstats.num_too_large++);
      }
      else
      if (pktq_in_index(q) == q->out_index)  /* queue is full, drop it */
         q->num_drop++;
      else
      {
        int pad_len, buf_max;

        head = (struct pkt_rx_element*) pktq_in_buf (q);
        memcpy (head->rx_buf, pkt + hdr_len, cap_len);
        head->tstamp_put = bp->bh_tstamp;
        head->rx_length  = cap_len;

        /* zero-pad up to ETH_MAX (don't destroy marker at end)
         */
        buf_max = q->buf_size - RX_ELEMENT_HEAD_SIZE - 4;
        pad_len = min (ETH_MAX, buf_max - cap_len);
        if (pad_len > 0)
           memset (&head->rx_buf[cap_len], 0, pad_len);
        pktq_inc_in (q);
      }
    }
    LEAVE_CRIT();
  }

  TCP_CONSOLE_MSG (2, ("pkt_recv_thread(): rc %d\n", rc));
  fflush (stdout);
  ARGSUSED (arg);
  thr_stopped = TRUE;
  return (rc);
}
Exemple #12
0
static int
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	int cc;
	int n = 0;
	register u_char *bp, *ep;

	cc = p->cc;
	if (p->cc == 0) {
		/*
		 * 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);
		}

	    /* capture the packets */
		if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
			return (-1);
		}
			
		cc = p->Packet->ulBytesReceived;

		bp = p->Packet->Buffer;
	} 
	else
		bp = p->bp;

	/*
	 * Loop through each packet.
	 */
#define bhp ((struct bpf_hdr *)bp)
	ep = bp + cc;
	while (1) {
		register int caplen, hdrlen;

		/*
		 * Has "pcap_breakloop()" been called?
		 * If so, return immediately - if we haven't read any
		 * packets, clear the flag and return -2 to indicate
		 * that we were told to break out of the loop, otherwise
		 * leave the flag set, so that the *next* call will break
		 * out of the loop without having read any packets, and
		 * return the number of packets we've processed so far.
		 */
		if (p->break_loop) {
			if (n == 0) {
				p->break_loop = 0;
				return (-2);
			} else {
				p->bp = bp;
				p->cc = ep - bp;
				return (n);
			}
		}
		if (bp >= ep)
			break;

		caplen = bhp->bh_caplen;
		hdrlen = bhp->bh_hdrlen;

		/*
		 * XXX A bpf_hdr matches a pcap_pkthdr.
		 */
		(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
		bp += Packet_WORDALIGN(caplen + hdrlen);
		if (++n >= cnt && cnt > 0) {
			p->bp = bp;
			p->cc = ep - bp;
			return (n);
		}
	}
#undef bhp
	p->cc = 0;
	return (n);
}
Exemple #13
0
static int
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	int cc;
	int n = 0;
	register u_char *bp, *ep;
	u_char *datap;
	struct pcap_win *pw = p->priv;

	cc = p->cc;
	if (p->cc == 0) {
		/*
		 * Has "pcap_breakloop()" been called?
		 */
		if (p->break_loop) {
			/*
			 * Yes - clear the flag that indicates that it
			 * has, and return PCAP_ERROR_BREAK to indicate
			 * that we were told to break out of the loop.
			 */
			p->break_loop = 0;
			return (PCAP_ERROR_BREAK);
		}

	    /* capture the packets */
		if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
			return (PCAP_ERROR);
		}

		cc = p->Packet->ulBytesReceived;

		bp = p->Packet->Buffer;
	}
	else
		bp = p->bp;

	/*
	 * Loop through each packet.
	 */
#define bhp ((struct bpf_hdr *)bp)
	ep = bp + cc;
	while (1) {
		register int caplen, hdrlen;

		/*
		 * Has "pcap_breakloop()" been called?
		 * If so, return immediately - if we haven't read any
		 * packets, clear the flag and return PCAP_ERROR_BREAK
		 * to indicate that we were told to break out of the loop,
		 * otherwise leave the flag set, so that the *next* call
		 * will break out of the loop without having read any
		 * packets, and return the number of packets we've
		 * processed so far.
		 */
		if (p->break_loop) {
			if (n == 0) {
				p->break_loop = 0;
				return (PCAP_ERROR_BREAK);
			} else {
				p->bp = bp;
				p->cc = ep - bp;
				return (n);
			}
		}
		if (bp >= ep)
			break;

		caplen = bhp->bh_caplen;
		hdrlen = bhp->bh_hdrlen;
		datap = bp + hdrlen;

		/*
		 * Short-circuit evaluation: if using BPF filter
		 * in kernel, no need to do it now - we already know
		 * the packet passed the filter.
		 *
		 * XXX - bpf_filter() should always return TRUE if
		 * handed a null pointer for the program, but it might
		 * just try to "run" the filter, so we check here.
		 */
		if (pw->filtering_in_kernel ||
		    p->fcode.bf_insns == NULL ||
		    bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
			/*
			 * XXX A bpf_hdr matches a pcap_pkthdr.
			 */
			(*callback)(user, (struct pcap_pkthdr*)bp, datap);
			bp += Packet_WORDALIGN(caplen + hdrlen);
			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
				p->bp = bp;
				p->cc = ep - bp;
				return (n);
			}
		} else {
			/*
			 * Skip this packet.
			 */
			bp += Packet_WORDALIGN(caplen + hdrlen);
		}
	}
#undef bhp
	p->cc = 0;
	return (n);
}