コード例 #1
0
ファイル: BridgeUnix.c プロジェクト: falcon8823/utvpn
UINT EthGetPacketBpf(ETH *e, void **data)
{
	struct bpf_hdr *hdr;
	
	if(e->Rest<=0){
		e->Rest = read(e->Socket, e->Buffer, e->BufSize);
		if(e->Rest < 0){
			*data = NULL;
			if(errno != EAGAIN){
				// エラー
				return INFINITE;
			}
			// データなし
			return 0;
		}
		e->Next = e->Buffer;
	}
	// パケットの切り出し
	hdr = (struct bpf_hdr*)e->Next;
	*data = Malloc(hdr->bh_caplen);
	Copy(*data, e->Next+(hdr->bh_hdrlen), hdr->bh_caplen);

	// 次のパケットの頭出し
	e->Rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
	e->Next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
	
	return hdr->bh_caplen;
}
コード例 #2
0
UINT EthGetPacketBpf(ETH *e, void **data)
{
	struct bpf_hdr *hdr;
	
	if(e->Rest<=0){
		e->Rest = read(e->Socket, e->Buffer, e->BufSize);
		if(e->Rest < 0){
			*data = NULL;
			if(errno != EAGAIN){
				// Error
				return INFINITE;
			}
			// No packet
			return 0;
		}
		e->Next = e->Buffer;
	}
	// Cut out a packet
	hdr = (struct bpf_hdr*)e->Next;
	*data = Malloc(hdr->bh_caplen);
	Copy(*data, e->Next+(hdr->bh_hdrlen), hdr->bh_caplen);

	// Find the head of next packet
	e->Rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
	e->Next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
	
	return hdr->bh_caplen;
}
コード例 #3
0
ファイル: freebsd.c プロジェクト: andrewbasterfield/vblade
int
getpkt(int fd, uchar *buf, int sz)
{
	register struct bpf_hdr *bh;
	register int pktlen, retlen;
	
	if (pktn <= 0) { 
		if ((pktn = read(fd, pktbuf, pktbufsz)) < 0) {
			perror("read");
			exit(1);
		}
		pktbp = pktbuf;
	}

	bh = (struct bpf_hdr *) pktbp;
	retlen = (int) bh->bh_caplen;
	/* This memcpy() is currently needed */ 
	memcpy(buf, (void *)(pktbp + bh->bh_hdrlen),
		retlen > sz ? sz : retlen);
	pktlen = bh->bh_hdrlen + bh->bh_caplen; 
	
	pktbp = pktbp + BPF_WORDALIGN(pktlen);
	pktn  -= (int) BPF_WORDALIGN(pktlen);

	return retlen; 
}
コード例 #4
0
ファイル: BridgeUnix.c プロジェクト: falcon8823/utvpn
// BPF でのパケットキャプチャの中継用スレッド
void BpfThread(THREAD *thread, void *param)
{
	ETH *e = (ETH*)param;
	int fd = e->Socket;
	int len;
	int rest;	// バッファ中の残りバイト数
	UCHAR *next;	//バッファ中の次のパケットの先頭
	struct CAPTUREBLOCK *block;	// キューに追加するデータ
	UCHAR *data;
	struct bpf_hdr *hdr;

	// バッファを確保
	UCHAR *buf = Malloc(e->BufSize);
	
	// 初期化完了を通知
	NoticeThreadInit(thread);

	while(1){
		// ループの脱出判定
		if(e->Socket == INVALID_SOCKET){
			break;
		}
		
		rest = read(fd, buf, e->BufSize);
		if(rest < 0 && errno != EAGAIN){
			// エラー
			close(fd);
			e->Socket = INVALID_SOCKET;
			Free(buf);
			Cancel(e->Cancel);
			return;
		}
		next = buf;
		LockQueue(e->Queue);
		while(rest>0){
			// パケットの切り出し
			hdr = (struct bpf_hdr*)next;

			// Queue中のパケットサイズが限界を超えたらパケットを破棄する
			if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
				data = Malloc(hdr->bh_caplen);
				Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen);
				block = NewCaptureBlock(data, hdr->bh_caplen);
				InsertQueue(e->Queue, block);
				e->QueueSize += hdr->bh_caplen;
			}

			// 次のパケットの頭出し
			rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
			next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
		}
		UnlockQueue(e->Queue);
		Cancel(e->Cancel);
	}
	Free(buf);
	Cancel(e->Cancel);
	return;
}
コード例 #5
0
// Relay thread for captured packet (BPF)
void BpfThread(THREAD *thread, void *param)
{
	ETH *e = (ETH*)param;
	int fd = e->Socket;
	int len;
	int rest;	// Rest size in buffer
	UCHAR *next;	// Head of next packet in buffer
	struct CAPTUREBLOCK *block;	// Data to enqueue
	UCHAR *data;
	struct bpf_hdr *hdr;

	// Allocate the buffer
	UCHAR *buf = Malloc(e->BufSize);
	
	// Notify initialize completed
	NoticeThreadInit(thread);

	while(1){
		// Determining to exit loop
		if(e->Socket == INVALID_SOCKET){
			break;
		}
		
		rest = read(fd, buf, e->BufSize);
		if(rest < 0 && errno != EAGAIN){
			// Error
			close(fd);
			e->Socket = INVALID_SOCKET;
			Free(buf);
			Cancel(e->Cancel);
			return;
		}
		next = buf;
		LockQueue(e->Queue);
		while(rest>0){
			// Cut out a packet
			hdr = (struct bpf_hdr*)next;

			// Discard arriving packet when queue filled
			if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
				data = Malloc(hdr->bh_caplen);
				Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen);
				block = NewCaptureBlock(data, hdr->bh_caplen);
				InsertQueue(e->Queue, block);
				e->QueueSize += hdr->bh_caplen;
			}

			// Find the head of next packet
			rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
			next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
		}
		UnlockQueue(e->Queue);
		Cancel(e->Cancel);
	}
	Free(buf);
	Cancel(e->Cancel);
	return;
}
コード例 #6
0
/* ARGSUSED */
void
logpkt_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
{
	sa_family_t		 af;
	u_int8_t		 hdrlen;
	u_int32_t		 caplen = h->caplen;
	const struct ip		*ip = NULL;
	const struct pfloghdr	*hdr;
	char			 ipstraddr[40] = { '\0' };
	uint8_t link_offset;

	if(use_pf){
		hdr = (const struct pfloghdr *)sp;
		if (hdr->length < MIN_PFLOG_HDRLEN) {
			logmsg(LOG_WARNING, "invalid pflog header length (%u/%u). "
			"packet dropped.", hdr->length, MIN_PFLOG_HDRLEN);
			return;
		}
		
		hdrlen = BPF_WORDALIGN(hdr->length);
		
		if (caplen < hdrlen) {
			logmsg(LOG_WARNING, "pflog header larger than caplen (%u/%u). "
			"packet dropped.", hdrlen, caplen);
			return;
		}
		
		/* We're interested in passed packets */
		if (hdr->action != PF_PASS)
			return;
		
		af = hdr->af;
		if (af == AF_INET) {
			ip = (const struct ip *)(sp + hdrlen);
			if (hdr->dir == PF_IN)
				inet_ntop(af, &ip->ip_src, ipstraddr,
			sizeof(ipstraddr));
			else if (hdr->dir == PF_OUT && !flag_inbound)
				inet_ntop(af, &ip->ip_dst, ipstraddr,
			sizeof(ipstraddr));
		}
	}
	else { /* IPFW code */
		link_offset = 4; /* LOOPHDR_SIZE */
		struct ip      *ip4_pkt = (struct ip *)    (sp + link_offset);
		if(ip4_pkt->ip_v!=4){
			logmsg(LOG_WARNING, "Incorrect IP version: %d", ip4_pkt->ip_v);
			return;
		}
		inet_ntop(AF_INET, (const void *)&ip4_pkt->ip_src, ipstraddr, sizeof(ipstraddr));
	}

	if (ipstraddr[0] != '\0') {
		if (!use_pf || hdr->dir == PF_IN)
			logmsg(LOG_DEBUG,"inbound %s", ipstraddr);
		else 
			logmsg(LOG_DEBUG,"outbound %s", ipstraddr);
		dbupdate(PATH_SPAMD_DB, ipstraddr);
	}
}
コード例 #7
0
ファイル: bpf.c プロジェクト: repos-holder/openbsd-patches
/*
 * Attach an interface to bpf.  driverp is a pointer to a (struct bpf_if *)
 * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
 * size of the link header (variable length headers not yet supported).
 */
void
bpfattach(caddr_t *driverp, struct ifnet *ifp, u_int dlt, u_int hdrlen)
{
    struct bpf_if *bp;
    bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);

    if (bp == 0)
        panic("bpfattach");

    bp->bif_dlist = 0;
    bp->bif_driverp = (struct bpf_if **)driverp;
    bp->bif_ifp = ifp;
    bp->bif_dlt = dlt;

    bp->bif_next = bpf_iflist;
    bpf_iflist = bp;

    *bp->bif_driverp = NULL;

    /*
     * Compute the length of the bpf header.  This is not necessarily
     * equal to SIZEOF_BPF_HDR because we want to insert spacing such
     * that the network layer header begins on a longword boundary (for
     * performance reasons and to alleviate alignment restrictions).
     */
    bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
}
コード例 #8
0
ファイル: etherflow.c プロジェクト: clementfarabet/neuflow
unsigned char * etherflow_receive_frame_C(int *lengthp) {
  struct frame_t *frame;
  struct bpf_hdr *bpf_packet;
  // Check if a new read is needed (a read from a bpf device can contains several bpf packets)
  if(bpf_ptr >= ((char*)(bpf_buf) + bpf_read_bytes))
  {
    //New read
    memset(bpf_buf, 0, bpf_buf_len);
    bpf_read_bytes = read(bpf, bpf_buf, bpf_buf_len);
    if(bpf_read_bytes < 0)
    {
        (*lengthp) = 0;
      return recbuffer;
    }
    if(bpf_read_bytes == 0)
    {
        (*lengthp) = 0;
      return recbuffer;
    }
    bpf_ptr = (char*)bpf_buf;
  }
  bpf_packet = (struct bpf_hdr*)bpf_ptr;
  memcpy(recbuffer, (char*)bpf_packet + bpf_packet->bh_hdrlen, bpf_packet->bh_caplen);
  // Increment thr ptr message for the next read
  bpf_ptr += BPF_WORDALIGN(bpf_packet->bh_hdrlen + bpf_packet->bh_caplen);
  if (lengthp != NULL) (*lengthp) = bpf_packet->bh_caplen;
  return recbuffer;
}
コード例 #9
0
ファイル: test_mqbpf.c プロジェクト: syuu1228/mq_bpf_test
static void
bpf_process_packets(struct bpf_thread_instance *instance, struct bpf_zbuf *bz, char *bufname)
{
	struct pcap_pkthdr phd;
	int clen, hlen, i;
	u_char *b,*bp, *ep, *p, by;
#define bhp ((struct bpf_hdr *)bp)

	b = bp = bz->bz_bufa;
	ep = bp + bz->bz_buflen;
	while (bp < ep) {
		instance->count++;
#if 0
		if (cflag > 0 && packet_count > cflag)
			exit(0);
#endif
		if (pflag) {
			/*
			 * XXXCSJP this prefetch method needs to be
			 * re-visted
			 */
			__builtin_prefetch(bp + bhp->bh_datalen, 0, 3);
		}
		clen = bhp->bh_caplen;
		hlen = bhp->bh_hdrlen;
		p = (u_char *)bp + hlen;
		phd.ts.tv_sec = bhp->bh_tstamp.tv_sec;
		phd.ts.tv_usec = bhp->bh_tstamp.tv_usec;
		phd.caplen = phd.len = bhp->bh_datalen;
		if (Tflag) {
			for (i = 0; i < bhp->bh_datalen; i++)
				by = p[i];
			bp += BPF_WORDALIGN(clen + hlen);
			continue;
		}
		if (wflag) {
			pcap_dump((u_char *)instance->dp, &phd, p);
			if (ferror((FILE *)instance->dp)) {
				perror("dump.pcap");
				exit(-1);
			}
			fflush((FILE *)instance->dp);
		}
		instance->wrote += bhp->bh_caplen;
		bp += BPF_WORDALIGN(clen + hlen);
	}
}
コード例 #10
0
ファイル: metis_GenericEther.c プロジェクト: isolis/Metis
/**
 * Parses the work buffer to extract packets
 *
 * The work buffer should be filled in with a set of tuples (bh_hdrlen, frame, pad).
 * The pad extends each packet out to BPF_WORDALIGN.
 *
 * If the CCNxMessage PacketLength says it is larger than the read capture length (caplen),
 * then this is an invalid packet and it will be discarded.  This error will result in a
 * ReadWorkBufferResult_TryAgain condition.
 *
 * struct bpf_hdr {
 *    struct BPF_TIMEVAL bh_tstamp;	 // time stamp
 *    bpf_u_int32        bh_caplen;	 // length of captured portion
 *    bpf_u_int32        bh_datalen; // original length of packet
 *    u_short		     bh_hdrlen;	 // length of bpf header (this struct plus alignment padding)
 * }
 *
 * @param [in] ether An allocated Darwin ethernet.
 * @param [in] readbuffer A user-provided read buffer.
 *
 * @retval ReadWorkBufferResult_Ok A frame was moved from workbuffer to readbuffer
 * @retval ReadWorkBufferResult_Empty There's not enough bytes in the workbuffer
 * @retval ReadWorkBufferResult_TryAgain (likely discard) caused this call to fail, but you should try again
 *
 * Example:
 * @code
 * <#example#>
 * @endcode
 */
static _ReadWorkBufferResult
_darwinEthernet_ReadWorkBuffer(MetisGenericEther *ether, PARCEventBuffer *readbuffer)
{
    _ReadWorkBufferResult result = ReadWorkBufferResult_Empty;

    // Make sure we have linear memory for the BPF header
    struct bpf_hdr *bpfHeader = (struct bpf_hdr *) parcEventBuffer_Pullup(ether->workBuffer, sizeof(struct bpf_hdr));

    // make sure we have enough bytes to process the frame
    // bpfHeader may be NULL if there are not sizeof(struct bpf_hdr) bytes available.
    if (bpfHeader && parcEventBuffer_GetLength(ether->workBuffer) >= bpfHeader->bh_hdrlen + bpfHeader->bh_caplen) {
        // (0) Save the needed fields from the bpf header
        // (1) pop off the bpf header
        // (2) move the iovec from work buffer to readBuffer.
        // (3) remove any BPF_WORDALIGN padding to the start of the next packet

        // (0) Save the needed fields from the bpf header
        uint16_t hdrlen = bpfHeader->bh_hdrlen;
        uint32_t caplen = bpfHeader->bh_caplen;

        // (1) pop off the bpf header
        parcEventBuffer_Read(ether->workBuffer, NULL, hdrlen);

        // (1a) Determine the packet length from the fixed header and only transfer that many bytes
        uint16_t packetlen = _getFrameLengthFromWorkBuffer(ether);

        if (packetlen <= caplen) {
            // (2) move the iovec from work buffer to readBuffer.
            parcEventBuffer_ReadIntoBuffer(ether->workBuffer, readbuffer, packetlen);

            // (2a) drain off any trailer (i.e. FCS)
            parcEventBuffer_Read(ether->workBuffer, NULL, caplen - packetlen);

            result = ReadWorkBufferResult_Ok;
        } else {
            if (metisLogger_IsLoggable(ether->logger, MetisLoggerFacility_IO, PARCLogLevel_Warning)) {
                metisLogger_Log(ether->logger, MetisLoggerFacility_IO, PARCLogLevel_Warning, __func__,
                                "%s reading fd %d discard packetlen %u greater than caplen %u",
                                __func__, ether->etherSocket, packetlen, caplen);
            }

            // discard all of caplen
            parcEventBuffer_Read(ether->workBuffer, NULL, caplen);

            // tell the caller that this read failed, but they could try again.
            result = ReadWorkBufferResult_TryAgain;
        }

        // (3) remove any BPF_WORDALIGN padding to the start of the next packet
        size_t alignedLength = BPF_WORDALIGN(hdrlen + caplen);
        size_t pad = alignedLength - hdrlen - caplen;
        parcEventBuffer_Read(ether->workBuffer, NULL, pad);
    }
    return result;
}
コード例 #11
0
ファイル: bpf.c プロジェクト: razzlefratz/MotleyTools
int main (int argc, char const * argv []) 

{
	char const* interface = "fxp0";
	ethernet_frame * frame;
	ifreq bound_if;
	charar buf [11] = 
	{
		0
	};
	int buf_len = 1;
	int bpf = 0;
	bpf_hdr * bpf_buf = new bpf_hdr [buf_len];
	bpf_hdr * bpf_packet;
	int i;
	for (i = 0; i < 99; i++) 
	{
		sprintf (buf, "/dev/bpf%i", i);
		if ((bpf = open (buf, O_RDWR)) != -1) 
		{
			break;
		}
	}
	strcpy (bound_if.ifr_name, interface);
	if (ioctl (bpf, BIOCSETIF, &bound_if) > 0) 
	{
		return (-1);
	}
	if (ioctl (bpf, BIOCIMMEDIATE, &buf_len) == -1) 
	{
		return (-1);
	}
	if (ioctl (bpf, BIOCGBLEN, &buf_len) == -1) 
	{
		return (-1);
	}
	read (bpf, bpf_buf, bpf_len);
	frame = (ethernet_frame*) ((byte *) (bpf_buf) + bpf_buf->bh_hdrlen);
	while (run_loop) 
	{
		memset (bpf_buf, 0, buf_len);
		if ((read_bytes = read (bpf, bpf_buf, buf_len)) > 0) 
		{
			char* ptr = reinterpret_cast<char*>(bpf_buf);
			while (ptr < (reinterpret_cast<char*>(bpf_buf) + read_bytes)) 
			{
				bpf_packet = reinterpret_cast<bpf_hdr*>(ptr);
				frame = (ethernet_frame*)((byte *) (bpf_packet) + bpf_packet->bh_hdrlen);
				ptr += BPF_WORDALIGN (bpf_packet->bh_hdrlen + bpf_packet->bh_caplen);
			}
		}
	}
	write (bpf, frame, bpf_buf->bh_caplen);
	return (0);
}
コード例 #12
0
static void
dl_pflog(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
	struct pfloghdr *pfh = (struct pfloghdr *)p;

	switch (pfh->af) {
	case AF_INET:
	case AF_INET6:
		collect(pfh->af, (struct ip *)(p + BPF_WORDALIGN(pfh->length)));
		break;
	}
}
コード例 #13
0
ファイル: iftop.c プロジェクト: dove0rz/iftop-android
static void handle_pflog_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
{
	register u_int length = pkthdr->len;
	u_int hdrlen;
	const struct pfloghdr *hdr;
	
	hdr = (struct pfloghdr *)packet;
	hdrlen = BPF_WORDALIGN(hdr->length);
	length -= hdrlen;
	packet += hdrlen;
	handle_ip_packet((struct ip*)packet, -1);
}
コード例 #14
0
ファイル: pf.c プロジェクト: FluentDevelopment/greyd
static void
packet_received(u_char *args, const struct pcap_pkthdr *h, const u_char *sp)
{
    FW_handle_T handle = (FW_handle_T) args;
    struct fw_handle *fwh = handle->fwh;
    sa_family_t af;
    u_int8_t hdrlen;
    u_int32_t caplen = h->caplen;
    const struct ip *ip = NULL;
    const struct pfloghdr *hdr;
    char addr[INET6_ADDRSTRLEN] = { '\0' };
    int track_outbound;

    track_outbound = Config_get_int(handle->config, "track_outbound",
                                    "firewall", TRACK_OUTBOUND);

    hdr = (const struct pfloghdr *)sp;
    if(hdr->length < MIN_PFLOG_HDRLEN) {
        i_warning("invalid pflog header length (%u/%u). "
            "packet dropped.", hdr->length, MIN_PFLOG_HDRLEN);
        return;
    }
    hdrlen = BPF_WORDALIGN(hdr->length);

    if(caplen < hdrlen) {
        i_warning("pflog header larger than caplen (%u/%u). "
            "packet dropped.", hdrlen, caplen);
        return;
    }

    /* We're interested in passed packets */
    if(hdr->action != PF_PASS)
        return;

    af = hdr->af;
    if(af == AF_INET) {
        ip = (const struct ip *) (sp + hdrlen);
        if(hdr->dir == PF_IN) {
            inet_ntop(af, &ip->ip_src, addr,
                      sizeof(addr));
        }
        else if(hdr->dir == PF_OUT && track_outbound) {
            inet_ntop(af, &ip->ip_dst, addr,
                      sizeof(addr));
        }
    }

    if(addr[0] != '\0') {
        i_debug("packet received: direction = %s, addr = %s",
                (hdr->dir == PF_IN ? "in" : "out"), addr);
        List_insert_after(fwh->entries, strdup(addr));
    }
}
コード例 #15
0
ファイル: interfaces-bpf.c プロジェクト: AngieB/devops_quiz
int
ifbpf_phys_init(struct lldpd *cfg,
    struct lldpd_hardware *hardware)
{
	struct bpf_buffer *buffer = NULL;
	int fd = -1;

	log_debug("interfaces", "initialize ethernet device %s",
	    hardware->h_ifname);
	if ((fd = priv_iface_init(hardware->h_ifindex, hardware->h_ifname)) == -1)
		return -1;

	/* Allocate receive buffer */
	hardware->h_data = buffer =
	    malloc(ETHER_MAX_LEN + BPF_WORDALIGN(sizeof(struct bpf_hdr)) + sizeof(struct bpf_buffer));
	if (buffer == NULL) {
		log_warn("interfaces",
		    "unable to allocate buffer space for BPF on %s",
		    hardware->h_ifname);
		goto end;
	}
	buffer->len = ETHER_MAX_LEN + BPF_WORDALIGN(sizeof(struct bpf_hdr));

	/* Setup multicast */
	interfaces_setup_multicast(cfg, hardware->h_ifname, 0);

	hardware->h_sendfd = fd; /* Send */

	levent_hardware_add_fd(hardware, fd); /* Receive */
	log_debug("interfaces", "interface %s initialized (fd=%d)", hardware->h_ifname,
	    fd);
	return 0;

end:
	if (fd >= 0) close(fd);
	free(buffer);
	hardware->h_data = NULL;
	return -1;
}
コード例 #16
0
ファイル: pktin-bsd.c プロジェクト: ctelfer/onics
void packet_loop()
{
	int rv;
	int rlen = 0;
	struct pktbuf pkb;
	struct bpf_hdr *bh;
	byte_t *bpfbuf = emalloc(g_buflen);
	byte_t *bp;

	while (1) {
		if (rlen <= 0) {
			rlen = read(g_ifsock, bpfbuf, g_buflen);
			if (rlen <= 0) {
				if (rlen < 0) {
					rlen = 0;
					if (errno == EINTR)
						continue;
					errsys("error receiving packet: ");
				}
				break;
			}

			bp = bpfbuf;
		}

		bh = (struct bpf_hdr *)bp;
		setup_pkb(&pkb, bp + bh->bh_hdrlen, bh);

		rv = pkb_pack(&pkb);
		abort_unless(rv == 0);

		if (pkb_file_write(&pkb, g_outfile) < 0)
			errsys("pkb_file_write: ");

		bp += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
		rlen -= BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
	}
}
コード例 #17
0
ファイル: if-bsd.c プロジェクト: RsrchBoy/dpkg-dhcpcd5
/* BPF requires that we read the entire buffer.
 * So we pass the buffer in the API so we can loop on >1 packet. */
ssize_t
if_readrawpacket(struct interface *ifp, int protocol,
    void *data, size_t len, int *flags)
{
	int fd;
	struct bpf_hdr packet;
	ssize_t bytes;
	const unsigned char *payload;
	struct dhcp_state *state;

	state = D_STATE(ifp);
	if (protocol == ETHERTYPE_ARP)
		fd = state->arp_fd;
	else
		fd = state->raw_fd;

	*flags = 0;
	for (;;) {
		if (state->buffer_len == 0) {
			bytes = read(fd, state->buffer, state->buffer_size);
			if (bytes == -1 || bytes == 0)
				return bytes;
			state->buffer_len = (size_t)bytes;
			state->buffer_pos = 0;
		}
		bytes = -1;
		memcpy(&packet, state->buffer + state->buffer_pos,
		    sizeof(packet));
		if (packet.bh_caplen != packet.bh_datalen)
			goto next; /* Incomplete packet, drop. */
		if (state->buffer_pos + packet.bh_caplen + packet.bh_hdrlen >
		    state->buffer_len)
			goto next; /* Packet beyond buffer, drop. */
		payload = state->buffer + state->buffer_pos +
		    packet.bh_hdrlen + ETHER_HDR_LEN;
		bytes = (ssize_t)packet.bh_caplen - ETHER_HDR_LEN;
		if ((size_t)bytes > len)
			bytes = (ssize_t)len;
		memcpy(data, payload, (size_t)bytes);
next:
		state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
		    packet.bh_caplen);
		if (state->buffer_pos >= state->buffer_len) {
			state->buffer_len = state->buffer_pos = 0;
			*flags |= RAW_EOF;
		}
		if (bytes != -1)
			return bytes;
	}
}
コード例 #18
0
ファイル: athena_Ethernet.c プロジェクト: chris-wood/ghost
PARCBuffer *
athenaEthernet_Receive(AthenaEthernet *athenaEthernet, int timeout, AthenaTransportLinkEvent *events)
{
    // Allocate, and read, a new BPF buffer if no packets are currently pending in an old one
    if (athenaEthernet->bpfBuffer == NULL) {
        athenaEthernet->bpfBuffer = parcBuffer_Allocate(athenaEthernet->etherBufferLength);
        uint8_t *buffer = parcBuffer_Overlay(athenaEthernet->bpfBuffer, 0);

        athenaEthernet->readCount = read(athenaEthernet->fd, buffer, athenaEthernet->etherBufferLength);
        if (athenaEthernet->readCount == -1) {
            if ((errno == EAGAIN) || (errno == EINTR)) {
                parcLog_Info(athenaEthernet->log, "Ethernet read retry");
                return NULL;
            }
            parcLog_Error(athenaEthernet->log, "recv: %s", strerror(errno));
            *events = AthenaTransportLinkEvent_Error;
            parcBuffer_Release(&athenaEthernet->bpfBuffer);
            return NULL;
        }
        parcLog_Debug(athenaEthernet->log, "received bpf packet (size=%d)", athenaEthernet->readCount);
    }

    // Obtain the current position in the BPF buffer to return a message from
    size_t position = parcBuffer_Position(athenaEthernet->bpfBuffer);

    // Read the BPF header and seek past it
    struct bpf_hdr *bpfhdr = parcBuffer_Overlay(athenaEthernet->bpfBuffer, sizeof(struct bpf_hdr));
    parcBuffer_SetLimit(athenaEthernet->bpfBuffer, position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen);
    parcBuffer_SetPosition(athenaEthernet->bpfBuffer, position + bpfhdr->bh_hdrlen);
    parcLog_Debug(athenaEthernet->log, "received message (size=%d)", bpfhdr->bh_datalen);

    // Slice a new PARCBuffer with the message to send up.
    PARCBuffer *wireFormatBuffer = parcBuffer_Slice(athenaEthernet->bpfBuffer);

    // If there's another packet in the buffer, position it and flag a receive event
    if ((athenaEthernet->readCount - (position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen)) != 0) {
        parcBuffer_SetLimit(athenaEthernet->bpfBuffer, athenaEthernet->readCount);
        parcBuffer_SetPosition(athenaEthernet->bpfBuffer,
                               BPF_WORDALIGN(position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen));
        // Mark a receive event for this packet
        *events = AthenaTransportLinkEvent_Receive;
    } else {
        parcBuffer_Release(&athenaEthernet->bpfBuffer);
    }

    return wireFormatBuffer;
}
コード例 #19
0
ファイル: bpf.c プロジェクト: blue-saber/NetflowExporter
static int listen_loop (volatile int *term,
				void (*callback)(const u_char *, const int)) {
	struct packet_buffer_t	*pbf;
	int			len;
	int			caplen, hdrlen;
	u_char			*bp = NULL, *ep;
	int			cc;

	while (! *term) {
		if ((cc = read (sockfd, buffer, bufsize)) < 0) {
			if (errno == EINTR) continue;
			fprintf (stderr, "bpf: %s\n", strerror (errno));
			*term = 1;
			break;
		}

		bp = buffer;
		ep = bp + cc;

		while (bp < ep) {
			caplen = ((struct bpf_hdr *)bp)->bh_caplen;
			hdrlen = ((struct bpf_hdr *)bp)->bh_hdrlen;
			len    = ((struct bpf_hdr *)bp)->bh_datalen;

			if ((pbf = pkbeng->request ()) != NULL) {
				pkts_received++;
				octets_received += len;
				pbf->len = len;
				// memcpy (pbf->buffer, bp + hdrlen, caplen);
				memcpy (pbf->pktbuff,
					bp + hdrlen, sizeof pbf->pktbuff);
				// pbf->buffer_ready = 1;
				pkbeng->ready (pbf);
				callback (pbf->pktbuff, pbf->len);
			} else {
				pkts_received++;
				octets_received += len;
				pkts_dropped++;
				octets_dropped  += len;
			}

			bp += BPF_WORDALIGN(caplen + hdrlen);
		}
	}
	return 1;
}
コード例 #20
0
ファイル: ethernet_bsd.c プロジェクト: feuvan/libiec61850
int Ethernet_receivePacket(EthernetSocket self, uint8_t* buffer, int bufferSize)
{
    // If the actual buffer is empty, make a read call to the BSP device in order to get new data.
    if (self->bpfEnd - self->bpfPositon < 4)
    {
        // Position the read pointer to the start of the buffer.
        self->bpfPositon = self->bpfBuffer;

        // Read one or more frames from the BPF handle.
        int size = read(self->bpf, self->bpfBuffer, self->bpfBufferSize);

        // Set the end pointer to the end of the received data or to 0 if no data at all was received.
        if (size >= 0)
            self->bpfEnd = self->bpfBuffer + size;
        else
            self->bpfEnd = NULL;
    }

    // Do we actually have at least one ethernet frame received?
    if (self->bpfPositon < self->bpfEnd)
    {
        // BPF adds a header to each packet, so we have to interpret it.
        struct bpf_hdr *header = (struct bpf_hdr *)(self->bpfPositon);

        // Check if the target buffer is big enough to hold the received ethernet frame.
        if ((unsigned int) bufferSize >= header->bh_caplen)
        {
            // Copy the frame to the target buffer.
            memcpy(buffer, self->bpfPositon + header->bh_hdrlen, header->bh_caplen);

            // Move the read pointer to the next ethernet frame header WORD ALIGNED (Took me a while to find that out).
            self->bpfPositon += BPF_WORDALIGN(header->bh_hdrlen + header->bh_caplen);

            // Return the number of bytes copied to the target buffer.
            return header->bh_caplen;
        }
        else
            // The buffer is too small, return an error.
            // TODO: Would be there a standard error number to signal that the target buffer is too small?
            return -1;
    }
    else
        // We did not get any ethernet frames, so return 0.
        return 0;
}
コード例 #21
0
ファイル: freebsd.c プロジェクト: 0x0d/lrc
static unsigned char *get_80211(struct priv_fbsd *pf, int *plen,
				struct rx_info *ri)
{
        struct bpf_hdr *bpfh;
        struct ieee80211_radiotap_header *rth;
        void *ptr;
        unsigned char **data;
	int *totlen;

	data = &pf->pf_next;
	totlen = &pf->pf_totlen;
	assert(*totlen);

        /* bpf hdr */
        bpfh = (struct bpf_hdr*) (*data);
        assert(bpfh->bh_caplen == bpfh->bh_datalen); /* XXX */
        *totlen -= bpfh->bh_hdrlen;

        /* check if more packets */
        if ((int)bpfh->bh_caplen < *totlen) {
		int tot = bpfh->bh_hdrlen + bpfh->bh_caplen;
		int offset = BPF_WORDALIGN(tot);

                *data = (unsigned char*)bpfh + offset;
		*totlen -= offset - tot; /* take into account align bytes */
	} else if ((int)bpfh->bh_caplen > *totlen)
		abort();

        *plen = bpfh->bh_caplen;
	*totlen -= bpfh->bh_caplen;
	assert(*totlen >= 0);

        /* radiotap */
        rth = (struct ieee80211_radiotap_header*)
              ((char*)bpfh + bpfh->bh_hdrlen);
	get_radiotap_info(pf, rth, plen, ri);
        *plen -= rth->it_len;
	assert(*plen > 0);

       	/* data */
	ptr = (char*)rth + rth->it_len;

        return ptr;
}
コード例 #22
0
ファイル: mypcap.c プロジェクト: senseisimple/emulab-stable
int mypcap_read(pcap_t *pd, void *user)
{
    static struct lnMinNode *node = NULL;
    int idx, cc, retval = 0;
    char *bp, *ep;

    pthread_mutex_lock(&mypcap_data.mpd_mutex);
    if (node != NULL) {
        lnAddHead(&mypcap_data.mpd_freelist, node);
    }
    while ((node = lnRemHead(&mypcap_data.mpd_buflist)) == NULL) {
        pthread_cond_wait(&mypcap_data.mpd_cond,
                          &mypcap_data.mpd_mutex);
    }
    pthread_mutex_unlock(&mypcap_data.mpd_mutex);

    idx = node - mypcap_data.mpd_nodes;
    bp = mypcap_data.mpd_buffer[idx];
    cc = mypcap_data.mpd_buflen[idx];
    /*
     * Loop through each packet.
     */
#define bhp ((struct bpf_hdr *)bp)
    ep = bp + cc;
    while (bp < ep) {
        register int caplen, hdrlen;
        caplen = bhp->bh_caplen;
        hdrlen = bhp->bh_hdrlen;
        /*
         * XXX A bpf_hdr matches a pcap_pkthdr.
         */
        (*mypcap_data.mpd_callback)(user,
                                    (struct pcap_pkthdr*)bp,
                                    bp + hdrlen);
        bp += BPF_WORDALIGN(caplen + hdrlen);
    }
#undef bhp

    return retval;
}
コード例 #23
0
ファイル: msl_test_bsd.c プロジェクト: albertok/web-polygraph
/* sorry, this function is really ugly */
void *
bpfWalkNext(int *len)
{
    struct bpf_hdr *b = bpfWalkCur;
    char *pkt;
    assert(NULL != bpfWalkCur);
    if (b->bh_hdrlen == 0) {
	bpfWalkStart = bpfWalkCur = NULL;
	return NULL;
    }
    bpfWalkCur += BPF_WORDALIGN(b->bh_hdrlen + b->bh_caplen);
    if (bpfWalkCur >= (bpfWalkStart + bpf_buflen)) {
	bpfWalkStart = bpfWalkCur = NULL;
	return NULL;
    }
    b = bpfWalkCur;
    if (b->bh_hdrlen == 0) {
	bpfWalkStart = bpfWalkCur = NULL;
	return NULL;
    }
    pkt = (void *) b + b->bh_hdrlen;
    *len = b->bh_caplen;
    return pkt;
}
コード例 #24
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 += BPF_WORDALIGN(caplen + hdrlen);
		if (++n >= cnt && cnt > 0) {
			p->bp = bp;
			p->cc = ep - bp;
			return (n);
		}
	}
#undef bhp
	p->cc = 0;
	return (n);
}
コード例 #25
0
int
init_pcap(void)
{
	struct bpf_program	bpfp;
	char	filter[PCAPFSIZ] = "ip and port 25 and action pass "
		    "and tcp[13]&0x12=0x2";

#ifdef __FreeBSD__
	if(!use_pf) {
		strncpy(filter, "ip and port 25 and tcp[13]&0x12=0x2", sizeof(filter));
	}
#endif

	if ((hpcap = pcap_open_live(pflogif, PCAPSNAP, 1, PCAPTIMO,
	    errbuf)) == NULL) {
		logmsg(LOG_ERR, "Failed to initialize: %s", errbuf);
		return (-1);
	}

#ifndef __FreeBSD__
	if (pcap_datalink(hpcap) != DLT_PFLOG) {
#else
	if ((use_pf && pcap_datalink(hpcap) != DLT_PFLOG) || (!use_pf && pcap_datalink(hpcap)!=DLT_NULL)) {
#endif
		logmsg(LOG_ERR, "Invalid datalink type");
		pcap_close(hpcap);
		hpcap = NULL;
		return (-1);
	}

	if (networkif != NULL) {
		strlcat(filter, " and on ", PCAPFSIZ);
		strlcat(filter, networkif, PCAPFSIZ);
	}

	if (pcap_compile(hpcap, &bpfp, filter, PCAPOPTZ, 0) == -1 ||
	    pcap_setfilter(hpcap, &bpfp) == -1) {
		logmsg(LOG_ERR, "%s", pcap_geterr(hpcap));
		return (-1);
	}

	pcap_freecode(&bpfp);

	if (ioctl(pcap_fileno(hpcap), BIOCLOCK) < 0) {
		logmsg(LOG_ERR, "BIOCLOCK: %s", strerror(errno));
		return (-1);
	}

	return (0);
}

/* ARGSUSED */
void
logpkt_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
{
	sa_family_t		 af;
	u_int8_t		 hdrlen;
	u_int32_t		 caplen = h->caplen;
	const struct ip		*ip = NULL;
	const struct pfloghdr	*hdr;
	char			 ipstraddr[40] = { '\0' };
	uint8_t link_offset;

	hdr = (const struct pfloghdr *)sp;
	if(use_pf){
		if (hdr->length < MIN_PFLOG_HDRLEN) {
			logmsg(LOG_WARNING, "invalid pflog header length (%u/%u). "
			"packet dropped.", hdr->length, MIN_PFLOG_HDRLEN);
			return;
		}

		hdrlen = BPF_WORDALIGN(hdr->length);

		if (caplen < hdrlen) {
			logmsg(LOG_WARNING, "pflog header larger than caplen (%u/%u). "
			"packet dropped.", hdrlen, caplen);
			return;
		}

		/* We're interested in passed packets */
		if (hdr->action != PF_PASS)
			return;

		af = hdr->af;
		if (af == AF_INET) {
			ip = (const struct ip *)(sp + hdrlen);
			if (hdr->dir == PF_IN)
				inet_ntop(af, &ip->ip_src, ipstraddr,
			sizeof(ipstraddr));
			else if (hdr->dir == PF_OUT && !flag_inbound)
				inet_ntop(af, &ip->ip_dst, ipstraddr,
			sizeof(ipstraddr));
		}
	}
	else { /* IPFW code */
		link_offset = 4; /* LOOPHDR_SIZE */
		struct ip      *ip4_pkt = (struct ip *)    (sp + link_offset);
		if(ip4_pkt->ip_v!=4){
			logmsg(LOG_WARNING, "Incorrect IP version: %d", ip4_pkt->ip_v);
			return;
		}
		inet_ntop(AF_INET, (const void *)&ip4_pkt->ip_src, ipstraddr, sizeof(ipstraddr));
	}

	if (ipstraddr[0] != '\0') {
		if (!use_pf || hdr->dir == PF_IN)
			logmsg(LOG_DEBUG,"inbound %s", ipstraddr);
		else
			logmsg(LOG_DEBUG,"outbound %s", ipstraddr);
		dbupdate(PATH_SPAMD_DB, ipstraddr);
	}
}
コード例 #26
0
ファイル: Win32-Extensions.c プロジェクト: 52M/npcap
int 
pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data)
{
	/* Check the capture type */

#ifdef HAVE_REMOTE
	if (p->rmt_clientside)
	{
		/* We are on an remote capture */
		if (!p->rmt_capstarted)
		{
			// if the capture has not started yet, please start it
			if (pcap_startcapture_remote(p) )
				return -1;
			p->rmt_capstarted= 1;
		}
		return pcap_next_ex_remote(p, pkt_header, pkt_data);
	}
#endif

	if (p->adapter!=NULL)
	{
		/* We are on a live capture */
		int cc;
		int n = 0;
		register u_char *bp, *ep;
		
		cc = p->cc;
		if (p->cc == 0) 
		{
			/* capture the packets */
			if(PacketReceivePacket(p->adapter, p->Packet, TRUE) == FALSE)
			{
				sprintf(p->errbuf, "read error: PacketReceivePacket failed");
				return (-1);
			}
			
			cc = p->Packet->ulBytesReceived;
			
			bp = p->Packet->Buffer;
		} 
		else
			bp = p->bp;
		
		/*
		 * Loop through each packet.
		 */
		ep = bp + cc;
		if (bp < ep) 
		{
			register int caplen, hdrlen;
			caplen = ((struct bpf_hdr *)bp)->bh_caplen;
			hdrlen = ((struct bpf_hdr *)bp)->bh_hdrlen;
			
			/*
			 * XXX A bpf_hdr matches a pcap_pkthdr.
			 */
			*pkt_header = (struct pcap_pkthdr*)bp;
			*pkt_data = bp + hdrlen;
			bp += BPF_WORDALIGN(caplen + hdrlen);
			
			p->bp = bp;
			p->cc = ep - bp;
			return (1);
		}
		else{
			p->cc = 0;
			return (0);
		}
	}	
	else
	{
		/* We are on an offline capture */
		struct bpf_insn *fcode = p->fcode.bf_insns;
		int status;
		int n = 0;
		
		struct pcap_pkthdr *h=(struct pcap_pkthdr*)(p->buffer+p->bufsize-sizeof(struct pcap_pkthdr));
		
		while (1)
		{
			status = sf_next_packet(p, h, p->buffer, p->bufsize);
			if (status==1)
				/* EOF */
				return (-2);
			if (status==-1)
				/* Error */
				return (-1);
			
			if (fcode == NULL ||
				bpf_filter(fcode, p->buffer, h->len, h->caplen)) 
			{
				*pkt_header = h;
				*pkt_data = p->buffer;
				return (1);
			}			
			
		}
	}
}
コード例 #27
0
ファイル: rarpd.c プロジェクト: mosconi/openbsd
/*
 * Loop indefinitely listening for RARP requests on the
 * interfaces in 'iflist'.
 */
void
rarp_loop(void)
{
	int	cc, fd, numfd = 0, i;
	u_int	bufsize;
	struct pollfd *pfd;
	u_char	*buf, *bp, *ep;
	struct if_info *ii;

	if (iflist == 0) {
		error(FATAL, "no interfaces");
		/* NOTREACHED */
	}
	if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) {
		error(FATAL, "BIOCGBLEN: %s", strerror(errno));
		/* NOTREACHED */
	}

	arptab_init();

	if (pledge("stdio rpath dns", NULL) == -1)
		error(FATAL, "pledge");

	buf = malloc((size_t) bufsize);
	if (buf == 0) {
		error(FATAL, "malloc: %s", strerror(errno));
		/* NOTREACHED */
	}
	/*
	 * Initialize the set of descriptors to listen to.
	 */
	for (ii = iflist; ii; ii = ii->ii_next)
		numfd++;
	pfd = reallocarray(NULL, numfd, sizeof(*pfd));
	if (pfd == NULL) {
		error(FATAL, "reallocarray: %s", strerror(errno));
		/* NOTREACHED */
	}
	for (i = 0, ii = iflist; ii; ii = ii->ii_next, i++) {
		pfd[i].fd = ii->ii_fd;
		pfd[i].events = POLLIN;
	}

	while (1) {
		if (poll(pfd, numfd, -1) == -1) {
			if (errno == EINTR)
				continue;
			error(FATAL, "poll: %s", strerror(errno));
			/* NOTREACHED */
		}
		for (i = 0, ii = iflist; ii; ii = ii->ii_next, i++) {
			if (pfd[i].revents == 0)
				continue;
			fd = ii->ii_fd;
		again:
			cc = read(fd, (char *)buf, bufsize);
			/* Don't choke when we get ptraced */
			if (cc < 0 && errno == EINTR)
				goto again;
			if (cc < 0) {
				error(FATAL, "read: %s", strerror(errno));
				/* NOTREACHED */
			}
			/* Loop through the packet(s) */
#define bhp ((struct bpf_hdr *)bp)
			bp = buf;
			ep = bp + cc;
			while (bp < ep) {
				int caplen, hdrlen;

				caplen = bhp->bh_caplen;
				hdrlen = bhp->bh_hdrlen;
				if (rarp_check(bp + hdrlen, caplen))
					rarp_process(ii, bp + hdrlen);
				bp += BPF_WORDALIGN(hdrlen + caplen);
			}
		}
	}
	free(pfd);
}
コード例 #28
0
ファイル: pcap-bpf.c プロジェクト: enukane/openbsd-work
int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	int cc;
	int n = 0;
	register u_char *bp, *ep;

 again:
	/*
	 * 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);
	}

	cc = p->cc;
	if (p->cc == 0) {
		cc = read(p->fd, (char *)p->buffer, p->bufsize);
		if (cc < 0) {
			/* Don't choke when we get ptraced */
			switch (errno) {

			case EINTR:
				goto again;

			case EWOULDBLOCK:
				return (0);

			case ENXIO:
				/*
				 * The device on which we're capturing
				 * went away.
				 *
				 * XXX - we should really return
				 * PCAP_ERROR_IFACE_NOT_UP, but
				 * pcap_dispatch() etc. aren't
				 * defined to return that.
				 */
				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
				    "The interface went down");
				return (PCAP_ERROR);

#if defined(sun) && !defined(BSD)
			/*
			 * Due to a SunOS bug, after 2^31 bytes, the kernel
			 * file offset overflows and read fails with EINVAL.
			 * The lseek() to 0 will fix things.
			 */
			case EINVAL:
				if (lseek(p->fd, 0L, SEEK_CUR) +
				    p->bufsize < 0) {
					(void)lseek(p->fd, 0L, SEEK_SET);
					goto again;
				}
				/* FALLTHROUGH */
#endif
			}
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
			    pcap_strerror(errno));
			return (PCAP_ERROR);
		}
		bp = p->buffer;
	} else
		bp = p->bp;

	/*
	 * Loop through each packet.
	 */
#define bhp ((struct bpf_hdr *)bp)
	ep = bp + cc;
	while (bp < ep) {
		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) {
			p->bp = bp;
			p->cc = ep - bp;
			/*
			 * ep is set based on the return value of read(),
			 * but read() from a BPF device doesn't necessarily
			 * return a value that's a multiple of the alignment
			 * value for BPF_WORDALIGN().  However, whenever we
			 * increment bp, we round up the increment value by
			 * a value rounded up by BPF_WORDALIGN(), so we
			 * could increment bp past ep after processing the
			 * last packet in the buffer.
			 *
			 * We treat ep < bp as an indication that this
			 * happened, and just set p->cc to 0.
			 */
			if (p->cc < 0)
				p->cc = 0;
			if (n == 0) {
				p->break_loop = 0;
				return (PCAP_ERROR_BREAK);
			} else
				return (n);
		}

		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 += BPF_WORDALIGN(caplen + hdrlen);
		if (++n >= cnt && cnt > 0) {
			p->bp = bp;
			p->cc = ep - bp;
			return (n);
		}
	}
#undef bhp
	p->cc = 0;
	return (n);
}
コード例 #29
0
static int
pcap_read_bpf(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 bpf_insn *fcode;
#ifdef PCAP_FDDIPAD
	register int pad;
#endif

	fcode = p->md.use_bpf ? NULL : p->fcode.bf_insns;
 again:
	/*
	 * 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);
	}
	cc = p->cc;
	if (p->cc == 0) {
		cc = read(p->fd, (char *)p->buffer, p->bufsize);
		if (cc < 0) {
			/* Don't choke when we get ptraced */
			switch (errno) {

			case EINTR:
				goto again;

#ifdef _AIX
			case EFAULT:
				/*
				 * Sigh.  More AIX wonderfulness.
				 *
				 * For some unknown reason the uiomove()
				 * operation in the bpf kernel extension
				 * used to copy the buffer into user 
				 * space sometimes returns EFAULT. I have
				 * no idea why this is the case given that
				 * a kernel debugger shows the user buffer 
				 * is correct. This problem appears to 
				 * be mostly mitigated by the memset of 
				 * the buffer before it is first used. 
				 * Very strange.... Shaun Clowes
				 *
				 * In any case this means that we shouldn't 
				 * treat EFAULT as a fatal error; as we
				 * don't have an API for returning
				 * a "some packets were dropped since
				 * the last packet you saw" indication,
				 * we just ignore EFAULT and keep reading.
				 */
				goto again;
#endif 
  
			case EWOULDBLOCK:
				return (0);
#if defined(sun) && !defined(BSD)
			/*
			 * Due to a SunOS bug, after 2^31 bytes, the kernel
			 * file offset overflows and read fails with EINVAL.
			 * The lseek() to 0 will fix things.
			 */
			case EINVAL:
				if (lseek(p->fd, 0L, SEEK_CUR) +
				    p->bufsize < 0) {
					(void)lseek(p->fd, 0L, SEEK_SET);
					goto again;
				}
				/* fall through */
#endif
			}
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
			    pcap_strerror(errno));
			return (-1);
		}
		bp = p->buffer;
	} else
		bp = p->bp;

	/*
	 * Loop through each packet.
	 */
#define bhp ((struct bpf_hdr *)bp)
	ep = bp + cc;
#ifdef PCAP_FDDIPAD
	pad = p->fddipad;
#endif
	while (bp < ep) {
		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);
			}
		}

		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.
		 *
#ifdef PCAP_FDDIPAD
		 * Note: the filter code was generated assuming
		 * that p->fddipad was the amount of padding
		 * before the header, as that's what's required
		 * in the kernel, so we run the filter before
		 * skipping that padding.
#endif
		 */
		if (fcode == NULL ||
		    bpf_filter(fcode, datap, bhp->bh_datalen, caplen)) {
			struct pcap_pkthdr pkthdr;

			pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;
#ifdef _AIX
			/*
			 * AIX's BPF returns seconds/nanoseconds time
			 * stamps, not seconds/microseconds time stamps.
			 */
			pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000;
#else
			pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec;
#endif
#ifdef PCAP_FDDIPAD
			if (caplen > pad)
				pkthdr.caplen = caplen - pad;
			else
				pkthdr.caplen = 0;
			if (bhp->bh_datalen > pad)
				pkthdr.len = bhp->bh_datalen - pad;
			else
				pkthdr.len = 0;
			datap += pad;
#else
			pkthdr.caplen = caplen;
			pkthdr.len = bhp->bh_datalen;
#endif
			(*callback)(user, &pkthdr, datap);
			bp += BPF_WORDALIGN(caplen + hdrlen);
			if (++n >= cnt && cnt > 0) {
				p->bp = bp;
				p->cc = ep - bp;
				return (n);
			}
		} else {
			/*
			 * Skip this packet.
			 */
			bp += BPF_WORDALIGN(caplen + hdrlen);
		}
	}
#undef bhp
	p->cc = 0;
	return (n);
}
コード例 #30
0
ファイル: if.c プロジェクト: BackupTheBerlios/wl530g-svn
/***********************************************************************
*%FUNCTION: receivePacket
*%ARGUMENTS:
* sock -- socket to read from
* pkt -- place to store the received packet
* size -- set to size of packet in bytes
*%RETURNS:
* >= 0 if all OK; < 0 if error
*%DESCRIPTION:
* Receives a packet
***********************************************************************/
int
receivePacket(int sock, PPPoEPacket *pkt, int *size)
{
#ifdef USE_BPF
    struct bpf_hdr hdr;
    int seglen, copylen;

    if (bpfSize <= 0) {
	bpfOffset = 0;
	if ((bpfSize = read(sock, bpfBuffer, bpfLength)) < 0) {
	    sysErr("read (receivePacket)");
	    return -1;
	}
    }
    if (bpfSize < sizeof(hdr)) {
	syslog(LOG_ERR, "Truncated bpf packet header: len=%d", bpfSize);
	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
	return 0;
    }
    memcpy(&hdr, bpfBuffer + bpfOffset, sizeof(hdr));
    if (hdr.bh_caplen != hdr.bh_datalen) {
	syslog(LOG_ERR, "Truncated bpf packet: caplen=%d, datalen=%d",
	       hdr.bh_caplen, hdr.bh_datalen);
	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
	return 0;
    }
    seglen = hdr.bh_hdrlen + hdr.bh_caplen;
    if (seglen > bpfSize) {
	syslog(LOG_ERR, "Truncated bpf packet: seglen=%d, bpfSize=%d",
	       seglen, bpfSize);
	clearPacketHeader(pkt);		/* resets bpfSize and bpfOffset */
	return 0;
    }
    seglen = BPF_WORDALIGN(seglen);
    *size = copylen = ((hdr.bh_caplen < sizeof(PPPoEPacket)) ?
			hdr.bh_caplen : sizeof(PPPoEPacket));
    memcpy(pkt, bpfBuffer + bpfOffset + hdr.bh_hdrlen, copylen);
    if (seglen >= bpfSize) {
	bpfSize = bpfOffset = 0;
    } else {
	bpfSize -= seglen;
	bpfOffset += seglen;
    }
#else
#ifdef USE_DLPI
	struct strbuf data; 
	int flags = 0; 	
	int retval; 

	data.buf = (char *) pkt; 
	data.maxlen = MAXDLBUF; 
	data.len = 0; 
	
	if ((retval = getmsg(sock, NULL, &data, &flags)) < 0) {
	    sysErr("read (receivePacket)");
	    return -1;
	}

	*size = data.len; 

#else
    if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
	sysErr("recv (receivePacket)");
	return -1;
    }
#endif
#endif
    return 0;
}