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); }
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; }
/* * 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; } }
/* * 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); }
/* * 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); }
/* * 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 !!?? */ }
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; } }
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; }
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); }
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; }
/* * 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 */ }
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); } }
/* 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; }
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; }
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; }
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); }
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); }
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; }
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 }
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; }
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); }
/* * 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); }
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); } } } }
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); }
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++; } }
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); }
/* * 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); }
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); }