Beispiel #1
0
void
readloop(int cnt, int if_fd, struct bpf_program *fp, printfunc printit)
{
#ifdef	IBMRTPC
	register struct packet_header *ph;
	register u_char *bp;
	register int inc;
#else	/* !IBMRTPC */
	static struct timeval tv = { 0 };
#endif	/* IBMRTPC */
	register int cc, caplen;
	register struct bpf_insn *fcode = fp->bf_insns;
	union {
		struct packet_header hdr;
		u_char	p[BUFSPACE];
		u_short	s;
	} buf;

	while (1) {
		if ((cc = read(if_fd, (char *)buf.p, sizeof(buf))) < 0)
			efReadError(if_fd, "reader");

#ifdef	IBMRTPC
		/*
		 * Loop through each packet.
		 */
		bp = buf.p;
		while (cc > 0) {
			ph = (struct packet_header *)bp;
			caplen = ph->tap.th_wirelen > snaplen ? snaplen : ph->tap
.th_wirelen ;
			if (bpf_filter(fcode, (char *)ph->packet,
						ph->tap.th_wirelen, caplen)) {
				if (cnt >= 0 && --cnt < 0)
					goto out;
				(*printit)((char *)ph->packet,
					(struct timeval *)ph->tap.th_timestamp,
					ph->tap.th_wirelen, caplen);
			}
			inc = ph->length.PacketOffset;
			cc -= inc;
			bp += inc;
		}
#else	/* !IBMRTPC */
		caplen = cc > snaplen ? snaplen : cc ;
		if (bpf_filter(fcode, buf.hdr.packet, cc, caplen)) {
			if (cnt >= 0 && --cnt < 0)
				goto out;
			(*printit)(buf.hdr.packet, &tv, cc, caplen);
		}
#endif	/* IBMRTPC */
	}
 out:
	wrapup(if_fd);
}
Beispiel #2
0
static int pfring_zc_daq_acquire_best_effort(void *handle, int cnt, DAQ_Analysis_Func_t callback,
#if (DAQ_API_VERSION >= 0x00010002)
        DAQ_Meta_Func_t metaback,
#endif
        void *user) {
    Pfring_Context_t *context = (Pfring_Context_t *) handle;
    int ret = 0, c = 0;
    u_int32_t rx_ring_idx = context->num_devices - 1, rx_ring_idx_clone;
    u_int32_t mask = 0;
    u_char *pkt_buffer;

    context->analysis_func = callback;
    context->breakloop = 0;

    while (!context->breakloop && (cnt <= 0 || c < cnt)) {

#ifdef SIG_RELOAD
        if (pfring_zc_daq_reload_requested)
            pfring_zc_daq_reload(context);
#endif

        while (pfring_zc_daq_in_packets(context, &rx_ring_idx) && !context->breakloop) {

            pfring_zc_recv_pkt(context->rx_queues[rx_ring_idx], &context->buffer, 0);

            context->buffer->hash = context->ifindexes[rx_ring_idx];

            pkt_buffer = pfring_zc_pkt_buff_data(context->buffer, context->rx_queues[rx_ring_idx]);

#ifdef ENABLE_BPF
            if (!context->bpf_filter || bpf_filter(context->filter.bf_insns, pkt_buffer, context->buffer->len /* caplen */, context->buffer->len) != 0) { /* accept */
#endif
                /* enqueueing pkt (and don't care of no room available) */
                mask = 1 << (context->num_devices);
#ifdef ENABLE_BPF
            } else {
                context->stats.packets_received++;
                context->stats.verdicts[DAQ_VERDICT_PASS]++;
            }
#endif
            mask |= 1 << (rx_ring_idx ^ 0x1);
            pfring_zc_send_pkt_multi(context->mq, &context->buffer, mask, 0);
        }

        rx_ring_idx_clone = rx_ring_idx;
        while (!(ret = pfring_zc_daq_in_packets(context, &rx_ring_idx_clone)) && !pfring_zc_queue_is_empty(context->q) && !context->breakloop) {
            ret = pfring_zc_recv_pkt(context->q, &context->buffer, 0);
            pfring_zc_daq_process(context, context->buffer, user);
            c++;
        }

        if (!ret) {
            if (usleep(1) == -1)
                if (errno == EINTR)
                    break;
        }
    }

    return 0;
}
Beispiel #3
0
/*
 * Incoming linkage from device drivers, when packet is in an mbuf chain.
 */
void
bpf_mtap(caddr_t arg, struct mbuf *m, u_int direction)
{
    struct bpf_if *bp = (struct bpf_if *)arg;
    struct bpf_d *d;
    size_t pktlen, slen;
    struct mbuf *m0;

    if (m == NULL)
        return;

    pktlen = 0;
    for (m0 = m; m0 != 0; m0 = m0->m_next)
        pktlen += m0->m_len;

    for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
        ++d->bd_rcount;
        if ((direction & d->bd_dirfilt) != 0)
            slen = 0;
        else
            slen = bpf_filter(d->bd_rfilter, (u_char *)m,
                              pktlen, 0);

        if (slen == 0)
            continue;

        bpf_catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
        if (d->bd_fildrop)
            m->m_flags |= M_FILDROP;
    }
}
Beispiel #4
0
/*
 * Incoming linkage from device drivers.  Process the packet pkt, of length
 * pktlen, which is stored in a contiguous buffer.  The packet is parsed
 * by each process' filter, and if accepted, stashed into the corresponding
 * buffer.
 */
int
bpf_tap(caddr_t arg, u_char *pkt, u_int pktlen, u_int direction)
{
    struct bpf_if *bp;
    struct bpf_d *d;
    size_t slen;
    int drop = 0;

    /*
     * Note that the ipl does not have to be raised at this point.
     * The only problem that could arise here is that if two different
     * interfaces shared any data.  This is not the case.
     */
    bp = (struct bpf_if *)arg;
    for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
        ++d->bd_rcount;
        if ((direction & d->bd_dirfilt) != 0)
            slen = 0;
        else
            slen = bpf_filter(d->bd_rfilter, pkt, pktlen, pktlen);
        if (slen != 0) {
            bpf_catchpacket(d, pkt, pktlen, slen, bcopy);
            if (d->bd_fildrop)
                drop++;
        }
    }

    return (drop);
}
Beispiel #5
0
/*
 * Print out packets stored in the file initialized by sf_read_init().
 * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
 */
int
pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	struct bpf_insn *fcode = p->fcode.bf_insns;
	int status = 0;
	int n = 0;

	while (status == 0) {
		struct pcap_pkthdr h;

		status = sf_next_packet(p, &h, p->buffer, p->bufsize);
		if (status) {
			if (status == 1)
				return (0);
			return (status);
		}

		if (fcode == NULL ||
		    bpf_filter(fcode, p->buffer, h.len, h.caplen)) {
			(*callback)(user, &h, p->buffer);
			if (++n >= cnt && cnt > 0)
				break;
		}
	}
	/*XXX this breaks semantics tcpslice expects */
	return (n);
}
Beispiel #6
0
/*
 * Scan a packet to decide whether it is an "active" packet,
 * that is, whether it is worth bringing up the link for.
 */
static int
active_packet(unsigned char *p, int len)
{
    int proto, i;
    struct protent *protp;

    if (len < PPP_HDRLEN)
	return 0;
    proto = PPP_PROTOCOL(p);
#ifdef PPP_FILTER
    if (active_filter.bf_len != 0
	&& bpf_filter(active_filter.bf_insns, frame, len, len) == 0)
	return 0;
#endif
    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
	if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
	    if (!protp->enabled_flag)
		return 0;
	    if (protp->active_pkt == NULL)
		return 1;
	    return (*protp->active_pkt)(p, len);
	}
    }
    return 0;			/* not a supported protocol !!?? */
}
Beispiel #7
0
int bsf_filter(bsf_t *bsf_desc, in_addr_t clt_ip, in_port_t clt_port, in_addr_t svr_ip, in_port_t svr_port)
{
	unsigned char dummy_packet[BSF_SNAP_LEN];
	
	
	populate_packet(dummy_packet, clt_ip, clt_port, svr_ip, svr_port);
	//validate the bpf program
	if (bsf_desc->flags && BSF_FLAG_VALIDATE == BSF_FLAG_VALIDATE)
	{
		//validate the BPF:
		if (bpf_validate(bsf_desc->bpf_prog->bf_insns, bsf_desc->bpf_prog->bf_len) == 0)
		{
			//validation failed
			return BSF_RESULT_ERROR;
		} 	
	}
	
	if (bpf_filter(bsf_desc->bpf_prog->bf_insns, dummy_packet, BSF_SNAP_LEN, BSF_SNAP_LEN) == BSF_SNAP_LEN)
	{
		return BSF_RESULT_PASS;
	} else
	{
		return BSF_RESULT_FAIL;
	}
	
	
}
Beispiel #8
0
static int
pcap_read_haiku(pcap_t* handle, int maxPackets, pcap_handler callback,
	u_char* userdata)
{
	// Receive a single packet

	u_char* buffer = handle->buffer + handle->offset;
	struct sockaddr_dl from;
	ssize_t bytesReceived;
	do {
		if (handle->break_loop) {
			// Clear the break loop flag, and return -2 to indicate our
			// reasoning
			handle->break_loop = 0;
			return -2;
		}

		socklen_t fromLength = sizeof(from);
		bytesReceived = recvfrom(handle->fd, buffer, handle->bufsize, MSG_TRUNC,
			(struct sockaddr *) &from, &fromLength);
	} while (bytesReceived < 0 && errno == B_INTERRUPTED);

	if (bytesReceived < 0) {
		if (errno == B_WOULD_BLOCK) {
			// there is no packet for us
			return 0;
		}

		snprintf(handle->errbuf, sizeof(handle->errbuf),
			"recvfrom: %s", strerror(errno));
		return -1;
	}

	int32 captureLength = bytesReceived;
	if (captureLength > handle->snapshot)
		captureLength = handle->snapshot;

	// run the packet filter
	if (!handle->md.use_bpf && handle->fcode.bf_insns) {
		if (bpf_filter(handle->fcode.bf_insns, buffer, bytesReceived,
				captureLength) == 0) {
			// packet got rejected
			return 0;
		}
	}

	// fill in pcap_header

	pcap_pkthdr header;
	header.caplen = captureLength;
	header.len = bytesReceived;
	header.ts.tv_usec = system_time() % 1000000;
	header.ts.tv_sec = system_time() / 1000000;
		// TODO: get timing from packet!!!

	/* Call the user supplied callback function */
	callback(userdata, &header, buffer);
	return 1;
}
Beispiel #9
0
static void
pcap_netmap_filter(u_char *arg, struct pcap_pkthdr *h, const u_char *buf)
{
	pcap_t *p = (pcap_t *)arg;
	struct pcap_netmap *pn = p->priv;
	const struct bpf_insn *pc = p->fcode.bf_insns;

	++pn->rx_pkts;
	if (pc == NULL || bpf_filter(pc, buf, h->len, h->caplen))
		pn->cb(pn->cb_arg, h, buf);
}
Beispiel #10
0
int reader_pfring_should_filter(const MolochPacket_t *UNUSED(packet))
{
    int i;
    for (i = 0; i < config.dontSaveBPFsNum; i++) {
        if (bpf_filter(bpf_programs[i].bf_insns, packet->pkt, packet->pktlen, packet->pktlen)) {
            return i;
            break;
        }
    }
    return -1;
}
Beispiel #11
0
/*
 * see <linux-kernel-source>/Documentation/usb/usbmon.txt and 
 * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
 */
static int
usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
	struct pcap_usb_linux *handlep = handle->private;
	struct mon_bin_get info;
	int ret;
	struct pcap_pkthdr pkth;
	int clen = handle->snapshot - sizeof(pcap_usb_header);

	/* the usb header is going to be part of 'packet' data*/
	info.hdr = (pcap_usb_header*) handle->buffer;
	info.data = handle->buffer + sizeof(pcap_usb_header);
	info.data_len = clen;

	/* ignore interrupt system call errors */
	do {
		ret = ioctl(handle->fd, MON_IOCX_GET, &info);
		if (handle->break_loop)
		{
			handle->break_loop = 0;
			return -2;
		}
	} while ((ret == -1) && (errno == EINTR));
	if (ret < 0)
	{
		if (errno == EAGAIN)
			return 0;	/* no data there */

		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
		    "Can't read from fd %d: %s", handle->fd, strerror(errno));
		return -1;
	}

	/* we can get less that than really captured from kernel, depending on
	 * snaplen, so adjust header accordingly */
	if (info.hdr->data_len < clen)
		clen = info.hdr->data_len;
	info.hdr->data_len = clen;
	pkth.caplen = clen + sizeof(pcap_usb_header);
	pkth.len = info.hdr->data_len + sizeof(pcap_usb_header);
	pkth.ts.tv_sec = info.hdr->ts_sec;
	pkth.ts.tv_usec = info.hdr->ts_usec;

	if (handle->fcode.bf_insns == NULL ||
	    bpf_filter(handle->fcode.bf_insns, handle->buffer,
	      pkth.len, pkth.caplen)) {
		handlep->packets_read++;
		callback(user, &pkth, handle->buffer);
		return 1;
	}

	return 0;	/* didn't pass filter */
}
Beispiel #12
0
bool
nmsg_pcap_filter(nmsg_pcap_t pcap, const uint8_t *pkt, size_t len) {
	struct bpf_insn *fcode;

	fcode = pcap->userbpf.bf_insns;

	if (fcode != NULL) {
		return (bpf_filter(fcode, (u_char *) pkt, len, len) != 0);
	} else {
		return (true);
	}
}
Beispiel #13
0
/* return value:
   TRUE: We want it!
   FALSE: Discard it!
*/
int evaluate_filters(struct aggregate_filter *filter, char *pkt, struct pcap_pkthdr *pkthdr)
{
  int index;

  if (*filter->num == 0) return TRUE;  /* no entries in the filter array: aggregate filtering disabled */

  for (index = 0; index < *filter->num; index++) {
    if (bpf_filter(filter->table[index]->bf_insns, pkt, pkthdr->len, pkthdr->caplen)) return TRUE; 
  }

  return FALSE;
}
Beispiel #14
0
static int
dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
	struct pcap_dbus *handlep = handle->priv;

	struct pcap_pkthdr pkth;
	DBusMessage *message;

	char *raw_msg;
	int raw_msg_len;

	int count = 0;

	message = dbus_connection_pop_message(handlep->conn);

	while (!message) {
		/* XXX handle->opt.timeout = timeout_ms; */
		if (!dbus_connection_read_write(handlep->conn, 100)) {
			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
			return -1;
		}

		if (handle->break_loop) {
			handle->break_loop = 0;
			return -2;
		}

		message = dbus_connection_pop_message(handlep->conn);
	}

	if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
		return -1;
	}

	if (dbus_message_marshal(message, &raw_msg, &raw_msg_len)) {
		pkth.caplen = pkth.len = raw_msg_len;
		/* pkth.caplen = min (payload_len, handle->snapshot); */

		gettimeofday(&pkth.ts, NULL);
		if (handle->fcode.bf_insns == NULL ||
		    bpf_filter(handle->fcode.bf_insns, (u_char *)raw_msg, pkth.len, pkth.caplen)) {
			handlep->packets_read++;
			callback(user, &pkth, (u_char *)raw_msg);
			count++;
		}

		dbus_free(raw_msg);
	}
	return count;
}
Beispiel #15
0
int reader_libpcapfile_should_filter(const MolochPacket_t *packet, enum MolochFilterType *type, int *index)
{
    int t, i;
    for (t = 0; t < MOLOCH_FILTER_MAX; t++) {
        for (i = 0; i < config.bpfsNum[t]; i++) {
            if (bpf_filter(bpf_programs[t][i].bf_insns, packet->pkt, packet->pktlen, packet->pktlen)) {
                *type = t;
                *index = i;
                return 1;
            }
        }
    }
    return 0;
}
Beispiel #16
0
void
test_bpf_filter(size_t counter, size_t dummy)
{
	size_t i;
	unsigned int ret = 0;

	for (i = 0; i < counter; i++) {
		ret += bpf_filter(insns, test_pkt,
		    sizeof(test_pkt), sizeof(test_pkt));
	}

	if (counter == dummy)
		printf("bpf_filter returned %u\n", ret);
}
Beispiel #17
0
int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	int cc;
	register struct snoopheader *sh;
	register int datalen;
	register int caplen;
	register u_char *cp;

again:
	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);			/* XXX */
		}
		sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
		return (-1);
	}
	sh = (struct snoopheader *)p->buffer;
	datalen = sh->snoop_packetlen;
	caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
	cp = (u_char *)(sh + 1) + p->offset;		/* XXX */

	if (p->fcode.bf_insns == NULL ||
	    bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
		struct pcap_pkthdr h;
		++p->md.stat.ps_recv;
		h.ts = sh->snoop_timestamp;
		h.len = datalen;
		h.caplen = caplen;
		(*callback)(user, &h, cp);
		return (1);
	}
	return (0);
}
Beispiel #18
0
int pfring_recv(pfring *ring, u_char** buffer, u_int buffer_len,
		struct pfring_pkthdr *hdr,
		u_int8_t wait_for_incoming_packet) {
  if (likely(ring
	     && ring->enabled
	     && ring->recv
	     && ring->mode != send_only_mode)) {
    int rc;

    /* Reentrancy is not compatible with zero copy */
    if (unlikely(buffer_len == 0 && ring->reentrant))
      return PF_RING_ERROR_INVALID_ARGUMENT;

    ring->break_recv_loop = 0;

#ifdef ENABLE_BPF
recv_next:
#endif

    rc = ring->recv(ring, buffer, buffer_len, hdr, wait_for_incoming_packet);
    hdr->caplen = min_val(hdr->caplen, ring->caplen), hdr->extended_hdr.if_index = ring->device_id;

    if(unlikely(ring->ixia_timestamp_enabled))
      pfring_handle_ixia_hw_timestamp(*buffer, hdr);

#ifdef ENABLE_BPF
    if (unlikely(rc > 0 && ring->userspace_bpf && bpf_filter(ring->userspace_bpf_filter.bf_insns, *buffer, hdr->caplen, hdr->len) == 0))
      goto recv_next; /* rejected */
#endif

    if (unlikely(rc > 0 && ring->reflector_socket != NULL))
        pfring_send(ring->reflector_socket, (char *) *buffer, hdr->caplen, 0 /* flush */);

    return rc;
  }

  if (!ring->enabled)
    return PF_RING_ERROR_RING_NOT_ENABLED;

  return PF_RING_ERROR_NOT_SUPPORTED;
}
Beispiel #19
0
void
bpf_mtap_pflog(caddr_t arg, caddr_t data, struct mbuf *m)
{
#if NPFLOG > 0
	struct m_hdr mh;
	struct bpf_if *bp = (struct bpf_if *)arg;
	struct bpf_d *d;
	size_t pktlen, slen;
	struct mbuf *m0;

	if (m == NULL)
		return;

	mh.mh_flags = 0;
	mh.mh_next = m;
	mh.mh_len = PFLOG_HDRLEN;
	mh.mh_data = data;

	pktlen = mh.mh_len;
	for (m0 = m; m0 != 0; m0 = m0->m_next)
		pktlen += m0->m_len;

	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
		++d->bd_rcount;
		if ((BPF_DIRECTION_OUT & d->bd_dirfilt) != 0)
			slen = 0;
		else
			slen = bpf_filter(d->bd_rfilter, (u_char *)&mh,
			    pktlen, 0);

		if (slen == 0)
		    continue;

		bpf_catchpacket(d, (u_char *)&mh, pktlen, slen, pflog_bpfcopy);
	}
#endif
}
Beispiel #20
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);
}
static int
netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
	struct pcap_netfilter *handlep = handle->priv;
	const unsigned char *buf;
	int count = 0;
	int len;

	/* ignore interrupt system call error */
	do {
		len = recv(handle->fd, handle->buffer, handle->bufsize, 0);
		if (handle->break_loop) {
			handle->break_loop = 0;
			return -2;
		}
	} while ((len == -1) && (errno == EINTR));

	if (len < 0) {
		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s", errno, pcap_strerror(errno));
		return -1;
	}

	buf = handle->buffer;
	while (len >= NLMSG_SPACE(0)) {
		const struct nlmsghdr *nlh = (const struct nlmsghdr *) buf;
		u_int32_t msg_len;
		nftype_t type = OTHER;

		if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || len < nlh->nlmsg_len) {
			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
			return -1;
		}

		if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG && 
			NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET) 
				type = NFLOG;

		if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE && 
			NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET)
				type = NFQUEUE;

		if (type != OTHER) {
			const unsigned char *payload = NULL;
			struct pcap_pkthdr pkth;

			const struct nfgenmsg *nfg;
			int id = 0;

			if (handle->linktype != DLT_NFLOG) {
				const struct nfattr *payload_attr = NULL;

				if (nlh->nlmsg_len < HDR_LENGTH) {
					snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
					return -1;
				}

				nfg = NLMSG_DATA(nlh);
				if (nlh->nlmsg_len > HDR_LENGTH) {
					struct nfattr *attr = NFM_NFA(nfg);
					int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH);

					while (NFA_OK(attr, attr_len)) {
						if (type == NFQUEUE) {
							switch (NFA_TYPE(attr)) {
								case NFQA_PACKET_HDR:
									{
										const struct nfqnl_msg_packet_hdr *pkt_hdr = (const struct nfqnl_msg_packet_hdr *) NFA_DATA(attr);

										id = ntohl(pkt_hdr->packet_id);
										break;
									}
								case NFQA_PAYLOAD:
									payload_attr = attr;
									break;
							}

						} else if (type == NFLOG) {
							switch (NFA_TYPE(attr)) {
								case NFULA_PAYLOAD:
									payload_attr = attr;
									break;
							}
						}
						attr = NFA_NEXT(attr, attr_len);
					}
				}

				if (payload_attr) {
					payload = NFA_DATA(payload_attr);
					pkth.len = pkth.caplen = NFA_PAYLOAD(payload_attr);
				}

			} else {
				payload = NLMSG_DATA(nlh);
				pkth.caplen = pkth.len = nlh->nlmsg_len-NLMSG_ALIGN(sizeof(struct nlmsghdr));
			}

			if (payload) {
				/* pkth.caplen = min (payload_len, handle->snapshot); */

				gettimeofday(&pkth.ts, NULL);
				if (handle->fcode.bf_insns == NULL ||
						bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen)) 
				{
					handlep->packets_read++;
					callback(user, &pkth, payload);
					count++;
				}
			}

			if (type == NFQUEUE) {
				/* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */
				nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT);
			}
		}

		msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
		if (msg_len > len)
			msg_len = len;

		len -= msg_len;
		buf += msg_len;
	}
	return count;
}
Beispiel #22
0
int pfring_loop(pfring *ring, pfringProcesssPacket looper,
		const u_char *user_bytes, u_int8_t wait_for_packet) {
  int rc = 0;
  struct pfring_pkthdr hdr;

  memset(&hdr, 0, sizeof(hdr));
  ring->break_recv_loop = 0;

  if((! ring)
     || ring->is_shutting_down
     || (! ring->recv)
     || ring->mode == send_only_mode)
    return -1;

  if(!ring->chunk_mode_enabled) {
    /* Packet (non chunk) mode */
    u_char *buffer = NULL;

    while(!ring->break_recv_loop) {
      rc = ring->recv(ring, &buffer, 0, &hdr, wait_for_packet);

      if(rc < 0)
	break;
      else if(rc > 0) {
	hdr.caplen = min_val(hdr.caplen, ring->caplen);

#ifdef ENABLE_BPF
        if (unlikely(ring->userspace_bpf && bpf_filter(ring->userspace_bpf_filter.bf_insns, buffer, hdr.caplen, hdr.len) == 0))
          continue; /* rejected */
#endif
        if(unlikely(ring->ixia_timestamp_enabled))
          pfring_handle_ixia_hw_timestamp(buffer, &hdr);

	looper(&hdr, buffer, user_bytes);
      } else {
	/* if(!wait_for_packet) usleep(1); */
      }
    }
  } else {
    /* Chunk mode */
    void *chunk;

    if(!ring->recv_chunk) return(-2);

    /* All set to zero as the header is meaningless */
    memset(&hdr, 0, sizeof(hdr));

    while(!ring->break_recv_loop) {
      rc = ring->recv_chunk(ring, &chunk, &hdr.len, wait_for_packet);

      if(rc < 0)
	break;
      else if(rc > 0) {
	hdr.caplen = min_val(hdr.len, ring->caplen);

	looper(&hdr, chunk, user_bytes);
      } else {
	/* if(!wait_for_packet) usleep(1); */
      }
    }
  }

  return(rc);
}
Beispiel #23
0
/*
 * Loop through the packets and call the callback for each packet.
 * Return the number of packets read.
 */
int
pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
                  int count, u_char *bufp, int len)
{
    struct pcap_dlpi *pd = p->priv;
    int n, caplen, origlen;
    u_char *ep, *pk;
    struct pcap_pkthdr pkthdr;
#ifdef HAVE_SYS_BUFMOD_H
    struct sb_hdr *sbp;
#ifdef LBL_ALIGN
    struct sb_hdr sbhdr;
#endif
#endif

    /* Loop through packets */
    ep = bufp + len;
    n = 0;

#ifdef HAVE_SYS_BUFMOD_H
    while (bufp < ep) {
        /*
         * 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 = bufp;
                p->cc = ep - bufp;
                return (n);
            }
        }
#ifdef LBL_ALIGN
        if ((long)bufp & 3) {
            sbp = &sbhdr;
            memcpy(sbp, bufp, sizeof(*sbp));
        } else
#endif
            sbp = (struct sb_hdr *)bufp;
        pd->stat.ps_drop = sbp->sbh_drops;
        pk = bufp + sizeof(*sbp);
        bufp += sbp->sbh_totlen;
        origlen = sbp->sbh_origlen;
        caplen = sbp->sbh_msglen;
#else
    origlen = len;
    caplen = min(p->snapshot, len);
    pk = bufp;
    bufp += caplen;
#endif
        ++pd->stat.ps_recv;
        if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
#ifdef HAVE_SYS_BUFMOD_H
            pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
            pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
#else
            (void) gettimeofday(&pkthdr.ts, NULL);
#endif
            pkthdr.len = origlen;
            pkthdr.caplen = caplen;
            /* Insure caplen does not exceed snapshot */
            if (pkthdr.caplen > p->snapshot)
                pkthdr.caplen = p->snapshot;
            (*callback)(user, &pkthdr, pk);
            if (++n >= count && !PACKET_COUNT_IS_UNLIMITED(count)) {
                p->cc = ep - bufp;
                p->bp = bufp;
                return (n);
            }
        }
#ifdef HAVE_SYS_BUFMOD_H
    }
#endif
    p->cc = 0;
    return (n);
}
Beispiel #24
0
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);
			}			
			
		}
	}
}
Beispiel #25
0
static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	TC_STATUS status;
	int n = 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);
	}

	if (p->TcPacketsBuffer == NULL)
	{
		status = g_TcFunctions.InstanceReceivePackets(p->TcInstance, &p->TcPacketsBuffer);
		if (status != TC_SUCCESS)
		{
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcInstanceReceivePackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
			return (-1);
		}
	}

	while (TRUE) 
	{
		struct pcap_pkthdr hdr;
		TC_PACKET_HEADER tcHeader;
		PVOID data;
		ULONG filterResult;

		/*
		 * 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 
			{
				return (n);
			}
		}

		if (p->TcPacketsBuffer == NULL)
		{
			break;
		}
		
		status = g_TcFunctions.PacketsBufferQueryNextPacket(p->TcPacketsBuffer, &tcHeader, &data);

		if (status == TC_ERROR_END_OF_BUFFER)
		{
			g_TcFunctions.PacketsBufferDestroy(p->TcPacketsBuffer);
			p->TcPacketsBuffer = NULL;
			break;
		}

		if (status != TC_SUCCESS)
		{
			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcPacketsBufferQueryNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
			return (-1);
		}

		/* No underlaying filtering system. We need to filter on our own */
		if (p->fcode.bf_insns) 
		{
			filterResult = bpf_filter(p->fcode.bf_insns, data, tcHeader.Length, tcHeader.CapturedLength);
			
			if (filterResult == 0)
			{
				continue;
			}
			
			if (filterResult > tcHeader.CapturedLength)
			{
				filterResult = tcHeader.CapturedLength;
			}
		}
		else
		{
			filterResult = tcHeader.CapturedLength;
		}
		
		p->TcAcceptedCount ++;
		
		hdr.ts.tv_sec = (bpf_u_int32)(tcHeader.Timestamp / (ULONGLONG)(1000  * 1000 * 1000));
		hdr.ts.tv_usec = (bpf_u_int32)((tcHeader.Timestamp % (ULONGLONG)(1000  * 1000 * 1000)) / 1000);

		if (p->linktype == DLT_EN10MB)
		{
			hdr.caplen = filterResult;
			hdr.len = tcHeader.Length;
			(*callback)(user, &hdr, data);
		}
		else
		{
			PPPI_HEADER pPpiHeader = (PPPI_HEADER)p->PpiPacket;
			PVOID data2 = pPpiHeader + 1;

			pPpiHeader->AggregationField.InterfaceId = TC_PH_FLAGS_RX_PORT_ID(tcHeader.Flags);
			pPpiHeader->Dot3Field.Errors = tcHeader.Errors;
			if (tcHeader.Flags & TC_PH_FLAGS_CHECKSUM)
			{
				pPpiHeader->Dot3Field.Flags = PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT;
			}
			else
			{
				pPpiHeader->Dot3Field.Flags = 0;
			}

			if (filterResult <= MAX_TC_PACKET_SIZE)
			{
				memcpy(data2, data, filterResult);
				hdr.caplen = sizeof(PPI_HEADER) + filterResult;
				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
			}
			else
			{
				memcpy(data2, data, MAX_TC_PACKET_SIZE);
				hdr.caplen = sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE;
				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
			}

			(*callback)(user, &hdr, p->PpiPacket);

		}

		if (++n >= cnt && cnt > 0) 
		{
			return (n);
		}
	}

	return (n);
}
Beispiel #26
0
static int
pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	struct pcap_win *pw = p->priv;
	PACKET Packet;
	u_char *dp = NULL;
	int	packet_len = 0, caplen = 0;
	struct pcap_pkthdr	pcap_header;
	u_char *endofbuf;
	int n = 0;
	dag_record_t *header;
	unsigned erf_record_len;
	ULONGLONG ts;
	int cc;
	unsigned swt;
	unsigned dfp = pw->adapter->DagFastProcess;

	cc = p->cc;
	if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
	{
		/*
		 * Get new packets from the network.
		 *
		 * 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 (-1);
		}

		cc = Packet.ulBytesReceived;
		if(cc == 0)
			/* The timeout has expired but we no packets arrived */
			return (0);
		header = (dag_record_t*)pw->adapter->DagBuffer;
	}
	else
		header = (dag_record_t*)p->bp;

	endofbuf = (char*)header + cc;

	/*
	 * Cycle through the packets
	 */
	do
	{
		erf_record_len = SWAPS(header->rlen);
		if((char*)header + erf_record_len > endofbuf)
			break;

		/* Increase the number of captured packets */
		p->stat.ps_recv++;

		/* Find the beginning of the packet */
		dp = ((u_char *)header) + dag_record_size;

		/* Determine actual packet len */
		switch(header->type)
		{
		case TYPE_ATM:
			packet_len = ATM_SNAPLEN;
			caplen = ATM_SNAPLEN;
			dp += 4;

			break;

		case TYPE_ETH:
			swt = SWAPS(header->wlen);
			packet_len = swt - (pw->dag_fcs_bits);
			caplen = erf_record_len - dag_record_size - 2;
			if (caplen > packet_len)
			{
				caplen = packet_len;
			}
			dp += 2;

			break;

		case TYPE_HDLC_POS:
			swt = SWAPS(header->wlen);
			packet_len = swt - (pw->dag_fcs_bits);
			caplen = erf_record_len - dag_record_size;
			if (caplen > packet_len)
			{
				caplen = packet_len;
			}

			break;
		}

		if(caplen > p->snapshot)
			caplen = p->snapshot;

		/*
		 * 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 = (char*)header;
				p->cc = endofbuf - (char*)header;
				return (n);
			}
		}

		if(!dfp)
		{
			/* convert between timestamp formats */
			ts = header->ts;
			pcap_header.ts.tv_sec = (int)(ts >> 32);
			ts = (ts & 0xffffffffi64) * 1000000;
			ts += 0x80000000; /* rounding */
			pcap_header.ts.tv_usec = (int)(ts >> 32);
			if (pcap_header.ts.tv_usec >= 1000000) {
				pcap_header.ts.tv_usec -= 1000000;
				pcap_header.ts.tv_sec++;
			}
		}

		/* No underlaying filtering system. We need to filter on our own */
		if (p->fcode.bf_insns)
		{
			if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
			{
				/* Move to next packet */
				header = (dag_record_t*)((char*)header + erf_record_len);
				continue;
			}
		}

		/* Fill the header for the user suppplied callback function */
		pcap_header.caplen = caplen;
		pcap_header.len = packet_len;

		/* Call the callback function */
		(*callback)(user, &pcap_header, dp);

		/* Move to next packet */
		header = (dag_record_t*)((char*)header + erf_record_len);

		/* Stop if the number of packets requested by user has been reached*/
		if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
		{
			p->bp = (char*)header;
			p->cc = endofbuf - (char*)header;
			return (n);
		}
	}
/* ARGSUSED */
static void
pfp_packet(void *arg, mac_resource_handle_t mrh, mblk_t *mp, boolean_t flag)
{
	struct T_unitdata_ind *tunit;
	struct sockaddr_ll *sll;
	struct sockaddr_ll *sol;
	mac_header_info_t hdr;
	struct pfpsock *ps;
	size_t tusz;
	mblk_t *mp0;
	int error;

	if (mp == NULL)
		return;

	ps = arg;
	if (ps->ps_flow_ctrld) {
		ps->ps_flow_ctrl_drops++;
		ps->ps_stats.tp_drops++;
		ks_stats.kp_recv_flow_cntrld.value.ui64++;
		freemsg(mp);
		return;
	}

	if (mac_header_info(ps->ps_mh, mp, &hdr) != 0) {
		/*
		 * Can't decode the packet header information so drop it.
		 */
		ps->ps_stats.tp_drops++;
		ks_stats.kp_recv_mac_hdr_fail.value.ui64++;
		freemsg(mp);
		return;
	}

	if (mac_type(ps->ps_mh) == DL_ETHER &&
	    hdr.mhi_bindsap == ETHERTYPE_VLAN) {
		struct ether_vlan_header *evhp;
		struct ether_vlan_header evh;

		hdr.mhi_hdrsize = sizeof (struct ether_vlan_header);
		hdr.mhi_istagged = B_TRUE;

		if (MBLKL(mp) >= sizeof (*evhp)) {
			evhp = (struct ether_vlan_header *)mp->b_rptr;
		} else {
			int sz = sizeof (*evhp);
			char *s = (char *)&evh;
			mblk_t *tmp;
			int len;

			for (tmp = mp; sz > 0 && tmp != NULL;
			    tmp = tmp->b_cont) {
				len = min(sz, MBLKL(tmp));
				bcopy(tmp->b_rptr, s, len);
				sz -= len;
			}
			evhp = &evh;
		}
		hdr.mhi_tci = ntohs(evhp->ether_tci);
		hdr.mhi_bindsap = ntohs(evhp->ether_type);
	}

	if ((ps->ps_proto != 0) && (ps->ps_proto != hdr.mhi_bindsap)) {
		/*
		 * The packet is not of interest to this socket so
		 * drop it on the floor. Here the SAP is being used
		 * as a very course filter.
		 */
		ps->ps_stats.tp_drops++;
		ks_stats.kp_recv_bad_proto.value.ui64++;
		freemsg(mp);
		return;
	}

	/*
	 * This field is not often set, even for ethernet,
	 * by mac_header_info, so compute it if it is 0.
	 */
	if (hdr.mhi_pktsize == 0)
		hdr.mhi_pktsize = msgdsize(mp);

	/*
	 * If a BPF filter is present, pass the raw packet into that.
	 * A failed match will result in zero being returned, indicating
	 * that this socket is not interested in the packet.
	 */
	if (ps->ps_bpf.bf_len != 0) {
		uchar_t *buffer;
		int buflen;

		buflen = MBLKL(mp);
		if (hdr.mhi_pktsize == buflen) {
			buffer = mp->b_rptr;
		} else {
			buflen = 0;
			buffer = (uchar_t *)mp;
		}
		rw_enter(&ps->ps_bpflock, RW_READER);
		if (bpf_filter(ps->ps_bpf.bf_insns, buffer,
		    hdr.mhi_pktsize, buflen) == 0) {
			rw_exit(&ps->ps_bpflock);
			ps->ps_stats.tp_drops++;
			ks_stats.kp_recv_filtered.value.ui64++;
			freemsg(mp);
			return;
		}
		rw_exit(&ps->ps_bpflock);
	}

	if (ps->ps_type == SOCK_DGRAM) {
		/*
		 * SOCK_DGRAM socket expect a "layer 3" packet, so advance
		 * past the link layer header.
		 */
		mp->b_rptr += hdr.mhi_hdrsize;
		hdr.mhi_pktsize -= hdr.mhi_hdrsize;
	}

	tusz = sizeof (struct T_unitdata_ind) + sizeof (struct sockaddr_ll);
	if (ps->ps_auxdata) {
		tusz += _TPI_ALIGN_TOPT(sizeof (struct tpacket_auxdata));
		tusz += _TPI_ALIGN_TOPT(sizeof (struct T_opthdr));
	}

	/*
	 * It is tempting to think that this could be optimised by having
	 * the base mblk_t allocated and hung off the pfpsock structure,
	 * except that then another one would need to be allocated for the
	 * sockaddr_ll that is included. Even creating a template to copy
	 * from is of questionable value, as read-write from one structure
	 * to the other is going to be slower than all of the initialisation.
	 */
	mp0 = allocb(tusz, BPRI_HI);
	if (mp0 == NULL) {
		ps->ps_stats.tp_drops++;
		ks_stats.kp_recv_alloc_fail.value.ui64++;
		freemsg(mp);
		return;
	}

	(void) memset(mp0->b_rptr, 0, tusz);

	mp0->b_datap->db_type = M_PROTO;
	mp0->b_wptr = mp0->b_rptr + tusz;

	tunit = (struct T_unitdata_ind *)mp0->b_rptr;
	tunit->PRIM_type = T_UNITDATA_IND;
	tunit->SRC_length = sizeof (struct sockaddr);
	tunit->SRC_offset = sizeof (*tunit);

	sol = (struct sockaddr_ll *)&ps->ps_sock;
	sll = (struct sockaddr_ll *)(mp0->b_rptr + sizeof (*tunit));
	sll->sll_ifindex = sol->sll_ifindex;
	sll->sll_hatype = (uint16_t)hdr.mhi_origsap;
	sll->sll_halen = sol->sll_halen;
	if (hdr.mhi_saddr != NULL)
		(void) memcpy(sll->sll_addr, hdr.mhi_saddr, sll->sll_halen);

	switch (hdr.mhi_dsttype) {
	case MAC_ADDRTYPE_MULTICAST :
		sll->sll_pkttype = PACKET_MULTICAST;
		break;
	case MAC_ADDRTYPE_BROADCAST :
		sll->sll_pkttype = PACKET_BROADCAST;
		break;
	case MAC_ADDRTYPE_UNICAST :
		if (memcmp(sol->sll_addr, hdr.mhi_daddr, sol->sll_halen) == 0)
			sll->sll_pkttype = PACKET_HOST;
		else
			sll->sll_pkttype = PACKET_OTHERHOST;
		break;
	}

	if (ps->ps_auxdata) {
		struct tpacket_auxdata *aux;
		struct T_opthdr *topt;

		tunit->OPT_offset = _TPI_ALIGN_TOPT(tunit->SRC_offset +
		    sizeof (struct sockaddr_ll));
		tunit->OPT_length = _TPI_ALIGN_TOPT(sizeof (struct T_opthdr)) +
		    _TPI_ALIGN_TOPT(sizeof (struct tpacket_auxdata));

		topt = (struct T_opthdr *)(mp0->b_rptr + tunit->OPT_offset);
		aux = (struct tpacket_auxdata *)
		    ((char *)topt + _TPI_ALIGN_TOPT(sizeof (*topt)));

		topt->len = tunit->OPT_length;
		topt->level = SOL_PACKET;
		topt->name = PACKET_AUXDATA;
		topt->status = 0;
		/*
		 * libpcap doesn't seem to use any other field,
		 * so it isn't clear how they should be filled in.
		 */
		aux->tp_vlan_vci = hdr.mhi_tci;
	}

	linkb(mp0, mp);

	ps->ps_upcalls->su_recv(ps->ps_upper, mp0, hdr.mhi_pktsize, 0,
	    &error, NULL);

	if (error == 0) {
		ps->ps_stats.tp_packets++;
		ks_stats.kp_recv_ok.value.ui64++;
	} else {
		mutex_enter(&ps->ps_lock);
		if (error == ENOSPC) {
			ps->ps_upcalls->su_recv(ps->ps_upper, NULL, 0, 0,
			    &error, NULL);
			if (error == ENOSPC)
				ps->ps_flow_ctrld = B_TRUE;
		}
		mutex_exit(&ps->ps_lock);
		ps->ps_stats.tp_drops++;
		ks_stats.kp_recv_fail.value.ui64++;
	}
}
Beispiel #28
0
static int
pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
{
	struct pcap_pf *pf = pc->priv;
	register u_char *p, *bp;
	register int cc, n, buflen, inc;
	register struct enstamp *sp;
#ifdef LBL_ALIGN
	struct enstamp stamp;
#endif
	register int pad;

 again:
	cc = pc->cc;
	if (cc == 0) {
		cc = read(pc->fd, (char *)pc->buffer + pc->offset, pc->bufsize);
		if (cc < 0) {
			if (errno == EWOULDBLOCK)
				return (0);
			if (errno == EINVAL &&
			    lseek(pc->fd, 0L, SEEK_CUR) + pc->bufsize < 0) {
				/*
				 * Due to a kernel bug, after 2^31 bytes,
				 * the kernel file offset overflows and
				 * read fails with EINVAL. The lseek()
				 * to 0 will fix things.
				 */
				(void)lseek(pc->fd, 0L, SEEK_SET);
				goto again;
			}
			snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s",
				pcap_strerror(errno));
			return (-1);
		}
		bp = (u_char *)pc->buffer + pc->offset;
	} else
		bp = pc->bp;
	/*
	 * Loop through each packet.
	 */
	n = 0;
	pad = pc->fddipad;
	while (cc > 0) {
		/*
		 * 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 (pc->break_loop) {
			if (n == 0) {
				pc->break_loop = 0;
				return (-2);
			} else {
				pc->cc = cc;
				pc->bp = bp;
				return (n);
			}
		}
		if (cc < sizeof(*sp)) {
			snprintf(pc->errbuf, sizeof(pc->errbuf),
			    "pf short read (%d)", cc);
			return (-1);
		}
#ifdef LBL_ALIGN
		if ((long)bp & 3) {
			sp = &stamp;
			memcpy((char *)sp, (char *)bp, sizeof(*sp));
		} else
#endif
			sp = (struct enstamp *)bp;
		if (sp->ens_stamplen != sizeof(*sp)) {
			snprintf(pc->errbuf, sizeof(pc->errbuf),
			    "pf short stamplen (%d)",
			    sp->ens_stamplen);
			return (-1);
		}

		p = bp + sp->ens_stamplen;
		buflen = sp->ens_count;
		if (buflen > pc->snapshot)
			buflen = pc->snapshot;

		/* Calculate inc before possible pad update */
		inc = ENALIGN(buflen + sp->ens_stamplen);
		cc -= inc;
		bp += inc;
		pf->TotPkts++;
		pf->TotDrops += sp->ens_dropped;
		pf->TotMissed = sp->ens_ifoverflows;
		if (pf->OrigMissed < 0)
			pf->OrigMissed = pf->TotMissed;

		/*
		 * Short-circuit evaluation: if using BPF filter
		 * in kernel, no need to do it now - we already know
		 * the packet passed the filter.
		 *
		 * Note: the filter code was generated assuming
		 * that pc->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.
		 */
		if (pf->filtering_in_kernel ||
		    bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
			struct pcap_pkthdr h;
			pf->TotAccepted++;
			h.ts = sp->ens_tstamp;
			h.len = sp->ens_count - pad;
			p += pad;
			buflen -= pad;
			h.caplen = buflen;
			(*callback)(user, &h, p);
			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
				pc->cc = cc;
				pc->bp = bp;
				return (n);
			}
		}
	}
	pc->cc = 0;
	return (n);
}
Beispiel #29
0
/*
 * Queue a packet.  Start transmission if not active.
 * Packet is placed in Information field of PPP frame.
 * Called at splnet as the if->if_output handler.
 * Called at splnet from pppwrite().
 */
static int
pppoutput_serialized(struct ifnet *ifp, struct ifaltq_subque *ifsq,
    struct mbuf *m0, struct sockaddr *dst, struct rtentry *rtp)
{
    struct ppp_softc *sc = &ppp_softc[ifp->if_dunit];
    int protocol, address, control;
    u_char *cp;
    int error;
#ifdef INET
    struct ip *ip;
#endif
    struct ifqueue *ifq;
    enum NPmode mode;
    int len;
    struct mbuf *m;
    struct altq_pktattr pktattr;

    if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
	|| ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
	error = ENETDOWN;	/* sort of */
	goto bad;
    }

    ifq_classify(&ifp->if_snd, m0, dst->sa_family, &pktattr);

    /*
     * Compute PPP header.
     */
    m0->m_flags &= ~M_HIGHPRI;
    switch (dst->sa_family) {
#ifdef INET
    case AF_INET:
	address = PPP_ALLSTATIONS;
	control = PPP_UI;
	protocol = PPP_IP;
	mode = sc->sc_npmode[NP_IP];

	/*
	 * If this packet has the "low delay" bit set in the IP header,
	 * put it on the fastq instead.
	 */
	ip = mtod(m0, struct ip *);
	if (ip->ip_tos & IPTOS_LOWDELAY)
	    m0->m_flags |= M_HIGHPRI;
	break;
#endif
#ifdef IPX
    case AF_IPX:
	/*
	 * This is pretty bogus.. We dont have an ipxcp module in pppd
	 * yet to configure the link parameters.  Sigh. I guess a
	 * manual ifconfig would do....  -Peter
	 */
	address = PPP_ALLSTATIONS;
	control = PPP_UI;
	protocol = PPP_IPX;
	mode = NPMODE_PASS;
	break;
#endif
    case AF_UNSPEC:
	address = PPP_ADDRESS(dst->sa_data);
	control = PPP_CONTROL(dst->sa_data);
	protocol = PPP_PROTOCOL(dst->sa_data);
	mode = NPMODE_PASS;
	break;
    default:
	kprintf("%s: af%d not supported\n", ifp->if_xname, dst->sa_family);
	error = EAFNOSUPPORT;
	goto bad;
    }

    /*
     * Drop this packet, or return an error, if necessary.
     */
    if (mode == NPMODE_ERROR) {
	error = ENETDOWN;
	goto bad;
    }
    if (mode == NPMODE_DROP) {
	error = 0;
	goto bad;
    }

    /*
     * Add PPP header.  If no space in first mbuf, allocate another.
     * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
     */
    if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
	m0 = m_prepend(m0, PPP_HDRLEN, MB_DONTWAIT);
	if (m0 == NULL) {
	    error = ENOBUFS;
	    goto bad;
	}
	m0->m_len = 0;
    } else
	m0->m_data -= PPP_HDRLEN;

    cp = mtod(m0, u_char *);
    *cp++ = address;
    *cp++ = control;
    *cp++ = protocol >> 8;
    *cp++ = protocol & 0xff;
    m0->m_len += PPP_HDRLEN;

    len = 0;
    for (m = m0; m != NULL; m = m->m_next)
	len += m->m_len;

    if (sc->sc_flags & SC_LOG_OUTPKT) {
	kprintf("%s output: ", ifp->if_xname);
	pppdumpm(m0);
    }

    if ((protocol & 0x8000) == 0) {
#ifdef PPP_FILTER
	/*
	 * Apply the pass and active filters to the packet,
	 * but only if it is a data packet.
	 */
	*mtod(m0, u_char *) = 1;	/* indicates outbound */
	if (sc->sc_pass_filt.bf_insns != NULL
	    && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m0,
			  len, 0) == 0) {
	    error = 0;		/* drop this packet */
	    goto bad;
	}

	/*
	 * Update the time we sent the most recent packet.
	 */
	if (sc->sc_active_filt.bf_insns == NULL
	    || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m0, len, 0))
	    sc->sc_last_sent = time_uptime;

	*mtod(m0, u_char *) = address;
#else
	/*
	 * Update the time we sent the most recent data packet.
	 */
	sc->sc_last_sent = time_uptime;
#endif /* PPP_FILTER */
    }

    BPF_MTAP(ifp, m0);

    /*
     * Put the packet on the appropriate queue.
     */
    crit_enter();
    if (mode == NPMODE_QUEUE) {
	/* XXX we should limit the number of packets on this queue */
	*sc->sc_npqtail = m0;
	m0->m_nextpkt = NULL;
	sc->sc_npqtail = &m0->m_nextpkt;
    } else {
	/* fastq and if_snd are emptied at spl[soft]net now */
	if ((m0->m_flags & M_HIGHPRI) && !ifq_is_enabled(&sc->sc_if.if_snd)) {
	    ifq = &sc->sc_fastq;
	    if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
	        IF_DROP(ifq);
	        m_freem(m0);
	        error = ENOBUFS;
	    } else {
	        IF_ENQUEUE(ifq, m0);
	        error = 0;
	    }
	} else {
	    ASSERT_ALTQ_SQ_SERIALIZED_HW(ifsq);
	    error = ifsq_enqueue(ifsq, m0, &pktattr);
	}
	if (error) {
	    crit_exit();
	    IFNET_STAT_INC(&sc->sc_if, oerrors, 1);
	    sc->sc_stats.ppp_oerrors++;
	    return (error);
	}
	(*sc->sc_start)(sc);
    }
    getmicrotime(&ifp->if_lastchange);
    IFNET_STAT_INC(ifp, opackets, 1);
    IFNET_STAT_INC(ifp, obytes, len);

    crit_exit();
    return (0);

bad:
    m_freem(m0);
    return (error);
}
Beispiel #30
0
static int
pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	struct pcap_nit *pn = p->priv;
	register int cc, n;
	register u_char *bp, *cp, *ep;
	register struct nit_hdr *nh;
	register int caplen;

	cc = p->cc;
	if (cc == 0) {
		cc = read(p->fd, (char *)p->buffer, p->bufsize);
		if (cc < 0) {
			if (errno == EWOULDBLOCK)
				return (0);
			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
			    errno, "pcap_read");
			return (-1);
		}
		bp = (u_char *)p->buffer;
	} else
		bp = p->bp;

	/*
	 * Loop through each packet.  The increment expression
	 * rounds up to the next int boundary past the end of
	 * the previous packet.
	 */
	n = 0;
	ep = bp + cc;
	while (bp < ep) {
		/*
		 * 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->cc = ep - bp;
				p->bp = bp;
				return (n);
			}
		}

		nh = (struct nit_hdr *)bp;
		cp = bp + sizeof(*nh);

		switch (nh->nh_state) {

		case NIT_CATCH:
			break;

		case NIT_NOMBUF:
		case NIT_NOCLUSTER:
		case NIT_NOSPACE:
			pn->stat.ps_drop = nh->nh_dropped;
			continue;

		case NIT_SEQNO:
			continue;

		default:
			pcap_snprintf(p->errbuf, sizeof(p->errbuf),
			    "bad nit state %d", nh->nh_state);
			return (-1);
		}
		++pn->stat.ps_recv;
		bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
		    sizeof(int) - 1) & ~(sizeof(int) - 1));

		caplen = nh->nh_wirelen;
		if (caplen > p->snapshot)
			caplen = p->snapshot;
		if (bpf_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) {
			struct pcap_pkthdr h;
			h.ts = nh->nh_timestamp;
			h.len = nh->nh_wirelen;
			h.caplen = caplen;
			(*callback)(user, &h, cp);
			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
				p->cc = ep - bp;
				p->bp = bp;
				return (n);
			}
		}
	}
	p->cc = 0;
	return (n);
}