UINT EthGetPacketBpf(ETH *e, void **data) { struct bpf_hdr *hdr; if(e->Rest<=0){ e->Rest = read(e->Socket, e->Buffer, e->BufSize); if(e->Rest < 0){ *data = NULL; if(errno != EAGAIN){ // エラー return INFINITE; } // データなし return 0; } e->Next = e->Buffer; } // パケットの切り出し hdr = (struct bpf_hdr*)e->Next; *data = Malloc(hdr->bh_caplen); Copy(*data, e->Next+(hdr->bh_hdrlen), hdr->bh_caplen); // 次のパケットの頭出し e->Rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); e->Next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); return hdr->bh_caplen; }
UINT EthGetPacketBpf(ETH *e, void **data) { struct bpf_hdr *hdr; if(e->Rest<=0){ e->Rest = read(e->Socket, e->Buffer, e->BufSize); if(e->Rest < 0){ *data = NULL; if(errno != EAGAIN){ // Error return INFINITE; } // No packet return 0; } e->Next = e->Buffer; } // Cut out a packet hdr = (struct bpf_hdr*)e->Next; *data = Malloc(hdr->bh_caplen); Copy(*data, e->Next+(hdr->bh_hdrlen), hdr->bh_caplen); // Find the head of next packet e->Rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); e->Next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); return hdr->bh_caplen; }
int getpkt(int fd, uchar *buf, int sz) { register struct bpf_hdr *bh; register int pktlen, retlen; if (pktn <= 0) { if ((pktn = read(fd, pktbuf, pktbufsz)) < 0) { perror("read"); exit(1); } pktbp = pktbuf; } bh = (struct bpf_hdr *) pktbp; retlen = (int) bh->bh_caplen; /* This memcpy() is currently needed */ memcpy(buf, (void *)(pktbp + bh->bh_hdrlen), retlen > sz ? sz : retlen); pktlen = bh->bh_hdrlen + bh->bh_caplen; pktbp = pktbp + BPF_WORDALIGN(pktlen); pktn -= (int) BPF_WORDALIGN(pktlen); return retlen; }
// BPF でのパケットキャプチャの中継用スレッド void BpfThread(THREAD *thread, void *param) { ETH *e = (ETH*)param; int fd = e->Socket; int len; int rest; // バッファ中の残りバイト数 UCHAR *next; //バッファ中の次のパケットの先頭 struct CAPTUREBLOCK *block; // キューに追加するデータ UCHAR *data; struct bpf_hdr *hdr; // バッファを確保 UCHAR *buf = Malloc(e->BufSize); // 初期化完了を通知 NoticeThreadInit(thread); while(1){ // ループの脱出判定 if(e->Socket == INVALID_SOCKET){ break; } rest = read(fd, buf, e->BufSize); if(rest < 0 && errno != EAGAIN){ // エラー close(fd); e->Socket = INVALID_SOCKET; Free(buf); Cancel(e->Cancel); return; } next = buf; LockQueue(e->Queue); while(rest>0){ // パケットの切り出し hdr = (struct bpf_hdr*)next; // Queue中のパケットサイズが限界を超えたらパケットを破棄する if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){ data = Malloc(hdr->bh_caplen); Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen); block = NewCaptureBlock(data, hdr->bh_caplen); InsertQueue(e->Queue, block); e->QueueSize += hdr->bh_caplen; } // 次のパケットの頭出し rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); } UnlockQueue(e->Queue); Cancel(e->Cancel); } Free(buf); Cancel(e->Cancel); return; }
// Relay thread for captured packet (BPF) void BpfThread(THREAD *thread, void *param) { ETH *e = (ETH*)param; int fd = e->Socket; int len; int rest; // Rest size in buffer UCHAR *next; // Head of next packet in buffer struct CAPTUREBLOCK *block; // Data to enqueue UCHAR *data; struct bpf_hdr *hdr; // Allocate the buffer UCHAR *buf = Malloc(e->BufSize); // Notify initialize completed NoticeThreadInit(thread); while(1){ // Determining to exit loop if(e->Socket == INVALID_SOCKET){ break; } rest = read(fd, buf, e->BufSize); if(rest < 0 && errno != EAGAIN){ // Error close(fd); e->Socket = INVALID_SOCKET; Free(buf); Cancel(e->Cancel); return; } next = buf; LockQueue(e->Queue); while(rest>0){ // Cut out a packet hdr = (struct bpf_hdr*)next; // Discard arriving packet when queue filled if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){ data = Malloc(hdr->bh_caplen); Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen); block = NewCaptureBlock(data, hdr->bh_caplen); InsertQueue(e->Queue, block); e->QueueSize += hdr->bh_caplen; } // Find the head of next packet rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); } UnlockQueue(e->Queue); Cancel(e->Cancel); } Free(buf); Cancel(e->Cancel); return; }
/* ARGSUSED */ void logpkt_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { sa_family_t af; u_int8_t hdrlen; u_int32_t caplen = h->caplen; const struct ip *ip = NULL; const struct pfloghdr *hdr; char ipstraddr[40] = { '\0' }; uint8_t link_offset; if(use_pf){ hdr = (const struct pfloghdr *)sp; if (hdr->length < MIN_PFLOG_HDRLEN) { logmsg(LOG_WARNING, "invalid pflog header length (%u/%u). " "packet dropped.", hdr->length, MIN_PFLOG_HDRLEN); return; } hdrlen = BPF_WORDALIGN(hdr->length); if (caplen < hdrlen) { logmsg(LOG_WARNING, "pflog header larger than caplen (%u/%u). " "packet dropped.", hdrlen, caplen); return; } /* We're interested in passed packets */ if (hdr->action != PF_PASS) return; af = hdr->af; if (af == AF_INET) { ip = (const struct ip *)(sp + hdrlen); if (hdr->dir == PF_IN) inet_ntop(af, &ip->ip_src, ipstraddr, sizeof(ipstraddr)); else if (hdr->dir == PF_OUT && !flag_inbound) inet_ntop(af, &ip->ip_dst, ipstraddr, sizeof(ipstraddr)); } } else { /* IPFW code */ link_offset = 4; /* LOOPHDR_SIZE */ struct ip *ip4_pkt = (struct ip *) (sp + link_offset); if(ip4_pkt->ip_v!=4){ logmsg(LOG_WARNING, "Incorrect IP version: %d", ip4_pkt->ip_v); return; } inet_ntop(AF_INET, (const void *)&ip4_pkt->ip_src, ipstraddr, sizeof(ipstraddr)); } if (ipstraddr[0] != '\0') { if (!use_pf || hdr->dir == PF_IN) logmsg(LOG_DEBUG,"inbound %s", ipstraddr); else logmsg(LOG_DEBUG,"outbound %s", ipstraddr); dbupdate(PATH_SPAMD_DB, ipstraddr); } }
/* * Attach an interface to bpf. driverp is a pointer to a (struct bpf_if *) * in the driver's softc; dlt is the link layer type; hdrlen is the fixed * size of the link header (variable length headers not yet supported). */ void bpfattach(caddr_t *driverp, struct ifnet *ifp, u_int dlt, u_int hdrlen) { struct bpf_if *bp; bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT); if (bp == 0) panic("bpfattach"); bp->bif_dlist = 0; bp->bif_driverp = (struct bpf_if **)driverp; bp->bif_ifp = ifp; bp->bif_dlt = dlt; bp->bif_next = bpf_iflist; bpf_iflist = bp; *bp->bif_driverp = NULL; /* * Compute the length of the bpf header. This is not necessarily * equal to SIZEOF_BPF_HDR because we want to insert spacing such * that the network layer header begins on a longword boundary (for * performance reasons and to alleviate alignment restrictions). */ bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen; }
unsigned char * etherflow_receive_frame_C(int *lengthp) { struct frame_t *frame; struct bpf_hdr *bpf_packet; // Check if a new read is needed (a read from a bpf device can contains several bpf packets) if(bpf_ptr >= ((char*)(bpf_buf) + bpf_read_bytes)) { //New read memset(bpf_buf, 0, bpf_buf_len); bpf_read_bytes = read(bpf, bpf_buf, bpf_buf_len); if(bpf_read_bytes < 0) { (*lengthp) = 0; return recbuffer; } if(bpf_read_bytes == 0) { (*lengthp) = 0; return recbuffer; } bpf_ptr = (char*)bpf_buf; } bpf_packet = (struct bpf_hdr*)bpf_ptr; memcpy(recbuffer, (char*)bpf_packet + bpf_packet->bh_hdrlen, bpf_packet->bh_caplen); // Increment thr ptr message for the next read bpf_ptr += BPF_WORDALIGN(bpf_packet->bh_hdrlen + bpf_packet->bh_caplen); if (lengthp != NULL) (*lengthp) = bpf_packet->bh_caplen; return recbuffer; }
static void bpf_process_packets(struct bpf_thread_instance *instance, struct bpf_zbuf *bz, char *bufname) { struct pcap_pkthdr phd; int clen, hlen, i; u_char *b,*bp, *ep, *p, by; #define bhp ((struct bpf_hdr *)bp) b = bp = bz->bz_bufa; ep = bp + bz->bz_buflen; while (bp < ep) { instance->count++; #if 0 if (cflag > 0 && packet_count > cflag) exit(0); #endif if (pflag) { /* * XXXCSJP this prefetch method needs to be * re-visted */ __builtin_prefetch(bp + bhp->bh_datalen, 0, 3); } clen = bhp->bh_caplen; hlen = bhp->bh_hdrlen; p = (u_char *)bp + hlen; phd.ts.tv_sec = bhp->bh_tstamp.tv_sec; phd.ts.tv_usec = bhp->bh_tstamp.tv_usec; phd.caplen = phd.len = bhp->bh_datalen; if (Tflag) { for (i = 0; i < bhp->bh_datalen; i++) by = p[i]; bp += BPF_WORDALIGN(clen + hlen); continue; } if (wflag) { pcap_dump((u_char *)instance->dp, &phd, p); if (ferror((FILE *)instance->dp)) { perror("dump.pcap"); exit(-1); } fflush((FILE *)instance->dp); } instance->wrote += bhp->bh_caplen; bp += BPF_WORDALIGN(clen + hlen); } }
/** * Parses the work buffer to extract packets * * The work buffer should be filled in with a set of tuples (bh_hdrlen, frame, pad). * The pad extends each packet out to BPF_WORDALIGN. * * If the CCNxMessage PacketLength says it is larger than the read capture length (caplen), * then this is an invalid packet and it will be discarded. This error will result in a * ReadWorkBufferResult_TryAgain condition. * * struct bpf_hdr { * struct BPF_TIMEVAL bh_tstamp; // time stamp * bpf_u_int32 bh_caplen; // length of captured portion * bpf_u_int32 bh_datalen; // original length of packet * u_short bh_hdrlen; // length of bpf header (this struct plus alignment padding) * } * * @param [in] ether An allocated Darwin ethernet. * @param [in] readbuffer A user-provided read buffer. * * @retval ReadWorkBufferResult_Ok A frame was moved from workbuffer to readbuffer * @retval ReadWorkBufferResult_Empty There's not enough bytes in the workbuffer * @retval ReadWorkBufferResult_TryAgain (likely discard) caused this call to fail, but you should try again * * Example: * @code * <#example#> * @endcode */ static _ReadWorkBufferResult _darwinEthernet_ReadWorkBuffer(MetisGenericEther *ether, PARCEventBuffer *readbuffer) { _ReadWorkBufferResult result = ReadWorkBufferResult_Empty; // Make sure we have linear memory for the BPF header struct bpf_hdr *bpfHeader = (struct bpf_hdr *) parcEventBuffer_Pullup(ether->workBuffer, sizeof(struct bpf_hdr)); // make sure we have enough bytes to process the frame // bpfHeader may be NULL if there are not sizeof(struct bpf_hdr) bytes available. if (bpfHeader && parcEventBuffer_GetLength(ether->workBuffer) >= bpfHeader->bh_hdrlen + bpfHeader->bh_caplen) { // (0) Save the needed fields from the bpf header // (1) pop off the bpf header // (2) move the iovec from work buffer to readBuffer. // (3) remove any BPF_WORDALIGN padding to the start of the next packet // (0) Save the needed fields from the bpf header uint16_t hdrlen = bpfHeader->bh_hdrlen; uint32_t caplen = bpfHeader->bh_caplen; // (1) pop off the bpf header parcEventBuffer_Read(ether->workBuffer, NULL, hdrlen); // (1a) Determine the packet length from the fixed header and only transfer that many bytes uint16_t packetlen = _getFrameLengthFromWorkBuffer(ether); if (packetlen <= caplen) { // (2) move the iovec from work buffer to readBuffer. parcEventBuffer_ReadIntoBuffer(ether->workBuffer, readbuffer, packetlen); // (2a) drain off any trailer (i.e. FCS) parcEventBuffer_Read(ether->workBuffer, NULL, caplen - packetlen); result = ReadWorkBufferResult_Ok; } else { if (metisLogger_IsLoggable(ether->logger, MetisLoggerFacility_IO, PARCLogLevel_Warning)) { metisLogger_Log(ether->logger, MetisLoggerFacility_IO, PARCLogLevel_Warning, __func__, "%s reading fd %d discard packetlen %u greater than caplen %u", __func__, ether->etherSocket, packetlen, caplen); } // discard all of caplen parcEventBuffer_Read(ether->workBuffer, NULL, caplen); // tell the caller that this read failed, but they could try again. result = ReadWorkBufferResult_TryAgain; } // (3) remove any BPF_WORDALIGN padding to the start of the next packet size_t alignedLength = BPF_WORDALIGN(hdrlen + caplen); size_t pad = alignedLength - hdrlen - caplen; parcEventBuffer_Read(ether->workBuffer, NULL, pad); } return result; }
int main (int argc, char const * argv []) { char const* interface = "fxp0"; ethernet_frame * frame; ifreq bound_if; charar buf [11] = { 0 }; int buf_len = 1; int bpf = 0; bpf_hdr * bpf_buf = new bpf_hdr [buf_len]; bpf_hdr * bpf_packet; int i; for (i = 0; i < 99; i++) { sprintf (buf, "/dev/bpf%i", i); if ((bpf = open (buf, O_RDWR)) != -1) { break; } } strcpy (bound_if.ifr_name, interface); if (ioctl (bpf, BIOCSETIF, &bound_if) > 0) { return (-1); } if (ioctl (bpf, BIOCIMMEDIATE, &buf_len) == -1) { return (-1); } if (ioctl (bpf, BIOCGBLEN, &buf_len) == -1) { return (-1); } read (bpf, bpf_buf, bpf_len); frame = (ethernet_frame*) ((byte *) (bpf_buf) + bpf_buf->bh_hdrlen); while (run_loop) { memset (bpf_buf, 0, buf_len); if ((read_bytes = read (bpf, bpf_buf, buf_len)) > 0) { char* ptr = reinterpret_cast<char*>(bpf_buf); while (ptr < (reinterpret_cast<char*>(bpf_buf) + read_bytes)) { bpf_packet = reinterpret_cast<bpf_hdr*>(ptr); frame = (ethernet_frame*)((byte *) (bpf_packet) + bpf_packet->bh_hdrlen); ptr += BPF_WORDALIGN (bpf_packet->bh_hdrlen + bpf_packet->bh_caplen); } } } write (bpf, frame, bpf_buf->bh_caplen); return (0); }
static void dl_pflog(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { struct pfloghdr *pfh = (struct pfloghdr *)p; switch (pfh->af) { case AF_INET: case AF_INET6: collect(pfh->af, (struct ip *)(p + BPF_WORDALIGN(pfh->length))); break; } }
static void handle_pflog_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet) { register u_int length = pkthdr->len; u_int hdrlen; const struct pfloghdr *hdr; hdr = (struct pfloghdr *)packet; hdrlen = BPF_WORDALIGN(hdr->length); length -= hdrlen; packet += hdrlen; handle_ip_packet((struct ip*)packet, -1); }
static void packet_received(u_char *args, const struct pcap_pkthdr *h, const u_char *sp) { FW_handle_T handle = (FW_handle_T) args; struct fw_handle *fwh = handle->fwh; sa_family_t af; u_int8_t hdrlen; u_int32_t caplen = h->caplen; const struct ip *ip = NULL; const struct pfloghdr *hdr; char addr[INET6_ADDRSTRLEN] = { '\0' }; int track_outbound; track_outbound = Config_get_int(handle->config, "track_outbound", "firewall", TRACK_OUTBOUND); hdr = (const struct pfloghdr *)sp; if(hdr->length < MIN_PFLOG_HDRLEN) { i_warning("invalid pflog header length (%u/%u). " "packet dropped.", hdr->length, MIN_PFLOG_HDRLEN); return; } hdrlen = BPF_WORDALIGN(hdr->length); if(caplen < hdrlen) { i_warning("pflog header larger than caplen (%u/%u). " "packet dropped.", hdrlen, caplen); return; } /* We're interested in passed packets */ if(hdr->action != PF_PASS) return; af = hdr->af; if(af == AF_INET) { ip = (const struct ip *) (sp + hdrlen); if(hdr->dir == PF_IN) { inet_ntop(af, &ip->ip_src, addr, sizeof(addr)); } else if(hdr->dir == PF_OUT && track_outbound) { inet_ntop(af, &ip->ip_dst, addr, sizeof(addr)); } } if(addr[0] != '\0') { i_debug("packet received: direction = %s, addr = %s", (hdr->dir == PF_IN ? "in" : "out"), addr); List_insert_after(fwh->entries, strdup(addr)); } }
int ifbpf_phys_init(struct lldpd *cfg, struct lldpd_hardware *hardware) { struct bpf_buffer *buffer = NULL; int fd = -1; log_debug("interfaces", "initialize ethernet device %s", hardware->h_ifname); if ((fd = priv_iface_init(hardware->h_ifindex, hardware->h_ifname)) == -1) return -1; /* Allocate receive buffer */ hardware->h_data = buffer = malloc(ETHER_MAX_LEN + BPF_WORDALIGN(sizeof(struct bpf_hdr)) + sizeof(struct bpf_buffer)); if (buffer == NULL) { log_warn("interfaces", "unable to allocate buffer space for BPF on %s", hardware->h_ifname); goto end; } buffer->len = ETHER_MAX_LEN + BPF_WORDALIGN(sizeof(struct bpf_hdr)); /* Setup multicast */ interfaces_setup_multicast(cfg, hardware->h_ifname, 0); hardware->h_sendfd = fd; /* Send */ levent_hardware_add_fd(hardware, fd); /* Receive */ log_debug("interfaces", "interface %s initialized (fd=%d)", hardware->h_ifname, fd); return 0; end: if (fd >= 0) close(fd); free(buffer); hardware->h_data = NULL; return -1; }
void packet_loop() { int rv; int rlen = 0; struct pktbuf pkb; struct bpf_hdr *bh; byte_t *bpfbuf = emalloc(g_buflen); byte_t *bp; while (1) { if (rlen <= 0) { rlen = read(g_ifsock, bpfbuf, g_buflen); if (rlen <= 0) { if (rlen < 0) { rlen = 0; if (errno == EINTR) continue; errsys("error receiving packet: "); } break; } bp = bpfbuf; } bh = (struct bpf_hdr *)bp; setup_pkb(&pkb, bp + bh->bh_hdrlen, bh); rv = pkb_pack(&pkb); abort_unless(rv == 0); if (pkb_file_write(&pkb, g_outfile) < 0) errsys("pkb_file_write: "); bp += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen); rlen -= BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen); } }
/* BPF requires that we read the entire buffer. * So we pass the buffer in the API so we can loop on >1 packet. */ ssize_t if_readrawpacket(struct interface *ifp, int protocol, void *data, size_t len, int *flags) { int fd; struct bpf_hdr packet; ssize_t bytes; const unsigned char *payload; struct dhcp_state *state; state = D_STATE(ifp); if (protocol == ETHERTYPE_ARP) fd = state->arp_fd; else fd = state->raw_fd; *flags = 0; for (;;) { if (state->buffer_len == 0) { bytes = read(fd, state->buffer, state->buffer_size); if (bytes == -1 || bytes == 0) return bytes; state->buffer_len = (size_t)bytes; state->buffer_pos = 0; } bytes = -1; memcpy(&packet, state->buffer + state->buffer_pos, sizeof(packet)); if (packet.bh_caplen != packet.bh_datalen) goto next; /* Incomplete packet, drop. */ if (state->buffer_pos + packet.bh_caplen + packet.bh_hdrlen > state->buffer_len) goto next; /* Packet beyond buffer, drop. */ payload = state->buffer + state->buffer_pos + packet.bh_hdrlen + ETHER_HDR_LEN; bytes = (ssize_t)packet.bh_caplen - ETHER_HDR_LEN; if ((size_t)bytes > len) bytes = (ssize_t)len; memcpy(data, payload, (size_t)bytes); next: state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen + packet.bh_caplen); if (state->buffer_pos >= state->buffer_len) { state->buffer_len = state->buffer_pos = 0; *flags |= RAW_EOF; } if (bytes != -1) return bytes; } }
PARCBuffer * athenaEthernet_Receive(AthenaEthernet *athenaEthernet, int timeout, AthenaTransportLinkEvent *events) { // Allocate, and read, a new BPF buffer if no packets are currently pending in an old one if (athenaEthernet->bpfBuffer == NULL) { athenaEthernet->bpfBuffer = parcBuffer_Allocate(athenaEthernet->etherBufferLength); uint8_t *buffer = parcBuffer_Overlay(athenaEthernet->bpfBuffer, 0); athenaEthernet->readCount = read(athenaEthernet->fd, buffer, athenaEthernet->etherBufferLength); if (athenaEthernet->readCount == -1) { if ((errno == EAGAIN) || (errno == EINTR)) { parcLog_Info(athenaEthernet->log, "Ethernet read retry"); return NULL; } parcLog_Error(athenaEthernet->log, "recv: %s", strerror(errno)); *events = AthenaTransportLinkEvent_Error; parcBuffer_Release(&athenaEthernet->bpfBuffer); return NULL; } parcLog_Debug(athenaEthernet->log, "received bpf packet (size=%d)", athenaEthernet->readCount); } // Obtain the current position in the BPF buffer to return a message from size_t position = parcBuffer_Position(athenaEthernet->bpfBuffer); // Read the BPF header and seek past it struct bpf_hdr *bpfhdr = parcBuffer_Overlay(athenaEthernet->bpfBuffer, sizeof(struct bpf_hdr)); parcBuffer_SetLimit(athenaEthernet->bpfBuffer, position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen); parcBuffer_SetPosition(athenaEthernet->bpfBuffer, position + bpfhdr->bh_hdrlen); parcLog_Debug(athenaEthernet->log, "received message (size=%d)", bpfhdr->bh_datalen); // Slice a new PARCBuffer with the message to send up. PARCBuffer *wireFormatBuffer = parcBuffer_Slice(athenaEthernet->bpfBuffer); // If there's another packet in the buffer, position it and flag a receive event if ((athenaEthernet->readCount - (position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen)) != 0) { parcBuffer_SetLimit(athenaEthernet->bpfBuffer, athenaEthernet->readCount); parcBuffer_SetPosition(athenaEthernet->bpfBuffer, BPF_WORDALIGN(position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen)); // Mark a receive event for this packet *events = AthenaTransportLinkEvent_Receive; } else { parcBuffer_Release(&athenaEthernet->bpfBuffer); } return wireFormatBuffer; }
static int listen_loop (volatile int *term, void (*callback)(const u_char *, const int)) { struct packet_buffer_t *pbf; int len; int caplen, hdrlen; u_char *bp = NULL, *ep; int cc; while (! *term) { if ((cc = read (sockfd, buffer, bufsize)) < 0) { if (errno == EINTR) continue; fprintf (stderr, "bpf: %s\n", strerror (errno)); *term = 1; break; } bp = buffer; ep = bp + cc; while (bp < ep) { caplen = ((struct bpf_hdr *)bp)->bh_caplen; hdrlen = ((struct bpf_hdr *)bp)->bh_hdrlen; len = ((struct bpf_hdr *)bp)->bh_datalen; if ((pbf = pkbeng->request ()) != NULL) { pkts_received++; octets_received += len; pbf->len = len; // memcpy (pbf->buffer, bp + hdrlen, caplen); memcpy (pbf->pktbuff, bp + hdrlen, sizeof pbf->pktbuff); // pbf->buffer_ready = 1; pkbeng->ready (pbf); callback (pbf->pktbuff, pbf->len); } else { pkts_received++; octets_received += len; pkts_dropped++; octets_dropped += len; } bp += BPF_WORDALIGN(caplen + hdrlen); } } return 1; }
int Ethernet_receivePacket(EthernetSocket self, uint8_t* buffer, int bufferSize) { // If the actual buffer is empty, make a read call to the BSP device in order to get new data. if (self->bpfEnd - self->bpfPositon < 4) { // Position the read pointer to the start of the buffer. self->bpfPositon = self->bpfBuffer; // Read one or more frames from the BPF handle. int size = read(self->bpf, self->bpfBuffer, self->bpfBufferSize); // Set the end pointer to the end of the received data or to 0 if no data at all was received. if (size >= 0) self->bpfEnd = self->bpfBuffer + size; else self->bpfEnd = NULL; } // Do we actually have at least one ethernet frame received? if (self->bpfPositon < self->bpfEnd) { // BPF adds a header to each packet, so we have to interpret it. struct bpf_hdr *header = (struct bpf_hdr *)(self->bpfPositon); // Check if the target buffer is big enough to hold the received ethernet frame. if ((unsigned int) bufferSize >= header->bh_caplen) { // Copy the frame to the target buffer. memcpy(buffer, self->bpfPositon + header->bh_hdrlen, header->bh_caplen); // Move the read pointer to the next ethernet frame header WORD ALIGNED (Took me a while to find that out). self->bpfPositon += BPF_WORDALIGN(header->bh_hdrlen + header->bh_caplen); // Return the number of bytes copied to the target buffer. return header->bh_caplen; } else // The buffer is too small, return an error. // TODO: Would be there a standard error number to signal that the target buffer is too small? return -1; } else // We did not get any ethernet frames, so return 0. return 0; }
static unsigned char *get_80211(struct priv_fbsd *pf, int *plen, struct rx_info *ri) { struct bpf_hdr *bpfh; struct ieee80211_radiotap_header *rth; void *ptr; unsigned char **data; int *totlen; data = &pf->pf_next; totlen = &pf->pf_totlen; assert(*totlen); /* bpf hdr */ bpfh = (struct bpf_hdr*) (*data); assert(bpfh->bh_caplen == bpfh->bh_datalen); /* XXX */ *totlen -= bpfh->bh_hdrlen; /* check if more packets */ if ((int)bpfh->bh_caplen < *totlen) { int tot = bpfh->bh_hdrlen + bpfh->bh_caplen; int offset = BPF_WORDALIGN(tot); *data = (unsigned char*)bpfh + offset; *totlen -= offset - tot; /* take into account align bytes */ } else if ((int)bpfh->bh_caplen > *totlen) abort(); *plen = bpfh->bh_caplen; *totlen -= bpfh->bh_caplen; assert(*totlen >= 0); /* radiotap */ rth = (struct ieee80211_radiotap_header*) ((char*)bpfh + bpfh->bh_hdrlen); get_radiotap_info(pf, rth, plen, ri); *plen -= rth->it_len; assert(*plen > 0); /* data */ ptr = (char*)rth + rth->it_len; return ptr; }
int mypcap_read(pcap_t *pd, void *user) { static struct lnMinNode *node = NULL; int idx, cc, retval = 0; char *bp, *ep; pthread_mutex_lock(&mypcap_data.mpd_mutex); if (node != NULL) { lnAddHead(&mypcap_data.mpd_freelist, node); } while ((node = lnRemHead(&mypcap_data.mpd_buflist)) == NULL) { pthread_cond_wait(&mypcap_data.mpd_cond, &mypcap_data.mpd_mutex); } pthread_mutex_unlock(&mypcap_data.mpd_mutex); idx = node - mypcap_data.mpd_nodes; bp = mypcap_data.mpd_buffer[idx]; cc = mypcap_data.mpd_buflen[idx]; /* * Loop through each packet. */ #define bhp ((struct bpf_hdr *)bp) ep = bp + cc; while (bp < ep) { register int caplen, hdrlen; caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; /* * XXX A bpf_hdr matches a pcap_pkthdr. */ (*mypcap_data.mpd_callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); bp += BPF_WORDALIGN(caplen + hdrlen); } #undef bhp return retval; }
/* sorry, this function is really ugly */ void * bpfWalkNext(int *len) { struct bpf_hdr *b = bpfWalkCur; char *pkt; assert(NULL != bpfWalkCur); if (b->bh_hdrlen == 0) { bpfWalkStart = bpfWalkCur = NULL; return NULL; } bpfWalkCur += BPF_WORDALIGN(b->bh_hdrlen + b->bh_caplen); if (bpfWalkCur >= (bpfWalkStart + bpf_buflen)) { bpfWalkStart = bpfWalkCur = NULL; return NULL; } b = bpfWalkCur; if (b->bh_hdrlen == 0) { bpfWalkStart = bpfWalkCur = NULL; return NULL; } pkt = (void *) b + b->bh_hdrlen; *len = b->bh_caplen; return pkt; }
static int pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; int n = 0; register u_char *bp, *ep; cc = p->cc; if (p->cc == 0) { /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return -2 to indicate that we were * told to break out of the loop. */ p->break_loop = 0; return (-2); } /* capture the packets */ if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); return (-1); } cc = p->Packet->ulBytesReceived; bp = p->Packet->Buffer; } else bp = p->bp; /* * Loop through each packet. */ #define bhp ((struct bpf_hdr *)bp) ep = bp + cc; while (1) { register int caplen, hdrlen; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = bp; p->cc = ep - bp; return (n); } } if (bp >= ep) break; caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; /* * XXX A bpf_hdr matches a pcap_pkthdr. */ (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); bp += BPF_WORDALIGN(caplen + hdrlen); if (++n >= cnt && cnt > 0) { p->bp = bp; p->cc = ep - bp; return (n); } } #undef bhp p->cc = 0; return (n); }
int init_pcap(void) { struct bpf_program bpfp; char filter[PCAPFSIZ] = "ip and port 25 and action pass " "and tcp[13]&0x12=0x2"; #ifdef __FreeBSD__ if(!use_pf) { strncpy(filter, "ip and port 25 and tcp[13]&0x12=0x2", sizeof(filter)); } #endif if ((hpcap = pcap_open_live(pflogif, PCAPSNAP, 1, PCAPTIMO, errbuf)) == NULL) { logmsg(LOG_ERR, "Failed to initialize: %s", errbuf); return (-1); } #ifndef __FreeBSD__ if (pcap_datalink(hpcap) != DLT_PFLOG) { #else if ((use_pf && pcap_datalink(hpcap) != DLT_PFLOG) || (!use_pf && pcap_datalink(hpcap)!=DLT_NULL)) { #endif logmsg(LOG_ERR, "Invalid datalink type"); pcap_close(hpcap); hpcap = NULL; return (-1); } if (networkif != NULL) { strlcat(filter, " and on ", PCAPFSIZ); strlcat(filter, networkif, PCAPFSIZ); } if (pcap_compile(hpcap, &bpfp, filter, PCAPOPTZ, 0) == -1 || pcap_setfilter(hpcap, &bpfp) == -1) { logmsg(LOG_ERR, "%s", pcap_geterr(hpcap)); return (-1); } pcap_freecode(&bpfp); if (ioctl(pcap_fileno(hpcap), BIOCLOCK) < 0) { logmsg(LOG_ERR, "BIOCLOCK: %s", strerror(errno)); return (-1); } return (0); } /* ARGSUSED */ void logpkt_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { sa_family_t af; u_int8_t hdrlen; u_int32_t caplen = h->caplen; const struct ip *ip = NULL; const struct pfloghdr *hdr; char ipstraddr[40] = { '\0' }; uint8_t link_offset; hdr = (const struct pfloghdr *)sp; if(use_pf){ if (hdr->length < MIN_PFLOG_HDRLEN) { logmsg(LOG_WARNING, "invalid pflog header length (%u/%u). " "packet dropped.", hdr->length, MIN_PFLOG_HDRLEN); return; } hdrlen = BPF_WORDALIGN(hdr->length); if (caplen < hdrlen) { logmsg(LOG_WARNING, "pflog header larger than caplen (%u/%u). " "packet dropped.", hdrlen, caplen); return; } /* We're interested in passed packets */ if (hdr->action != PF_PASS) return; af = hdr->af; if (af == AF_INET) { ip = (const struct ip *)(sp + hdrlen); if (hdr->dir == PF_IN) inet_ntop(af, &ip->ip_src, ipstraddr, sizeof(ipstraddr)); else if (hdr->dir == PF_OUT && !flag_inbound) inet_ntop(af, &ip->ip_dst, ipstraddr, sizeof(ipstraddr)); } } else { /* IPFW code */ link_offset = 4; /* LOOPHDR_SIZE */ struct ip *ip4_pkt = (struct ip *) (sp + link_offset); if(ip4_pkt->ip_v!=4){ logmsg(LOG_WARNING, "Incorrect IP version: %d", ip4_pkt->ip_v); return; } inet_ntop(AF_INET, (const void *)&ip4_pkt->ip_src, ipstraddr, sizeof(ipstraddr)); } if (ipstraddr[0] != '\0') { if (!use_pf || hdr->dir == PF_IN) logmsg(LOG_DEBUG,"inbound %s", ipstraddr); else logmsg(LOG_DEBUG,"outbound %s", ipstraddr); dbupdate(PATH_SPAMD_DB, ipstraddr); } }
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); } } } }
/* * Loop indefinitely listening for RARP requests on the * interfaces in 'iflist'. */ void rarp_loop(void) { int cc, fd, numfd = 0, i; u_int bufsize; struct pollfd *pfd; u_char *buf, *bp, *ep; struct if_info *ii; if (iflist == 0) { error(FATAL, "no interfaces"); /* NOTREACHED */ } if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) { error(FATAL, "BIOCGBLEN: %s", strerror(errno)); /* NOTREACHED */ } arptab_init(); if (pledge("stdio rpath dns", NULL) == -1) error(FATAL, "pledge"); buf = malloc((size_t) bufsize); if (buf == 0) { error(FATAL, "malloc: %s", strerror(errno)); /* NOTREACHED */ } /* * Initialize the set of descriptors to listen to. */ for (ii = iflist; ii; ii = ii->ii_next) numfd++; pfd = reallocarray(NULL, numfd, sizeof(*pfd)); if (pfd == NULL) { error(FATAL, "reallocarray: %s", strerror(errno)); /* NOTREACHED */ } for (i = 0, ii = iflist; ii; ii = ii->ii_next, i++) { pfd[i].fd = ii->ii_fd; pfd[i].events = POLLIN; } while (1) { if (poll(pfd, numfd, -1) == -1) { if (errno == EINTR) continue; error(FATAL, "poll: %s", strerror(errno)); /* NOTREACHED */ } for (i = 0, ii = iflist; ii; ii = ii->ii_next, i++) { if (pfd[i].revents == 0) continue; fd = ii->ii_fd; again: cc = read(fd, (char *)buf, bufsize); /* Don't choke when we get ptraced */ if (cc < 0 && errno == EINTR) goto again; if (cc < 0) { error(FATAL, "read: %s", strerror(errno)); /* NOTREACHED */ } /* Loop through the packet(s) */ #define bhp ((struct bpf_hdr *)bp) bp = buf; ep = bp + cc; while (bp < ep) { int caplen, hdrlen; caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; if (rarp_check(bp + hdrlen, caplen)) rarp_process(ii, bp + hdrlen); bp += BPF_WORDALIGN(hdrlen + caplen); } } } free(pfd); }
int pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; int n = 0; register u_char *bp, *ep; again: /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return PCAP_ERROR_BREAK to indicate * that we were told to break out of the loop. */ p->break_loop = 0; return (PCAP_ERROR_BREAK); } cc = p->cc; if (p->cc == 0) { cc = read(p->fd, (char *)p->buffer, p->bufsize); if (cc < 0) { /* Don't choke when we get ptraced */ switch (errno) { case EINTR: goto again; case EWOULDBLOCK: return (0); case ENXIO: /* * The device on which we're capturing * went away. * * XXX - we should really return * PCAP_ERROR_IFACE_NOT_UP, but * pcap_dispatch() etc. aren't * defined to return that. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The interface went down"); return (PCAP_ERROR); #if defined(sun) && !defined(BSD) /* * Due to a SunOS bug, after 2^31 bytes, the kernel * file offset overflows and read fails with EINVAL. * The lseek() to 0 will fix things. */ case EINVAL: if (lseek(p->fd, 0L, SEEK_CUR) + p->bufsize < 0) { (void)lseek(p->fd, 0L, SEEK_SET); goto again; } /* FALLTHROUGH */ #endif } snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s", pcap_strerror(errno)); return (PCAP_ERROR); } bp = p->buffer; } else bp = p->bp; /* * Loop through each packet. */ #define bhp ((struct bpf_hdr *)bp) ep = bp + cc; while (bp < ep) { register int caplen, hdrlen; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return PCAP_ERROR_BREAK * to indicate that we were told to break out of the loop, * otherwise leave the flag set, so that the *next* call * will break out of the loop without having read any * packets, and return the number of packets we've * processed so far. */ if (p->break_loop) { p->bp = bp; p->cc = ep - bp; /* * ep is set based on the return value of read(), * but read() from a BPF device doesn't necessarily * return a value that's a multiple of the alignment * value for BPF_WORDALIGN(). However, whenever we * increment bp, we round up the increment value by * a value rounded up by BPF_WORDALIGN(), so we * could increment bp past ep after processing the * last packet in the buffer. * * We treat ep < bp as an indication that this * happened, and just set p->cc to 0. */ if (p->cc < 0) p->cc = 0; if (n == 0) { p->break_loop = 0; return (PCAP_ERROR_BREAK); } else return (n); } caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; /* * XXX A bpf_hdr matches a pcap_pkthdr. */ (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); bp += BPF_WORDALIGN(caplen + hdrlen); if (++n >= cnt && cnt > 0) { p->bp = bp; p->cc = ep - bp; return (n); } } #undef bhp p->cc = 0; return (n); }
static int pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { int cc; int n = 0; register u_char *bp, *ep; u_char *datap; struct bpf_insn *fcode; #ifdef PCAP_FDDIPAD register int pad; #endif fcode = p->md.use_bpf ? NULL : p->fcode.bf_insns; again: /* * Has "pcap_breakloop()" been called? */ if (p->break_loop) { /* * Yes - clear the flag that indicates that it * has, and return -2 to indicate that we were * told to break out of the loop. */ p->break_loop = 0; return (-2); } cc = p->cc; if (p->cc == 0) { cc = read(p->fd, (char *)p->buffer, p->bufsize); if (cc < 0) { /* Don't choke when we get ptraced */ switch (errno) { case EINTR: goto again; #ifdef _AIX case EFAULT: /* * Sigh. More AIX wonderfulness. * * For some unknown reason the uiomove() * operation in the bpf kernel extension * used to copy the buffer into user * space sometimes returns EFAULT. I have * no idea why this is the case given that * a kernel debugger shows the user buffer * is correct. This problem appears to * be mostly mitigated by the memset of * the buffer before it is first used. * Very strange.... Shaun Clowes * * In any case this means that we shouldn't * treat EFAULT as a fatal error; as we * don't have an API for returning * a "some packets were dropped since * the last packet you saw" indication, * we just ignore EFAULT and keep reading. */ goto again; #endif case EWOULDBLOCK: return (0); #if defined(sun) && !defined(BSD) /* * Due to a SunOS bug, after 2^31 bytes, the kernel * file offset overflows and read fails with EINVAL. * The lseek() to 0 will fix things. */ case EINVAL: if (lseek(p->fd, 0L, SEEK_CUR) + p->bufsize < 0) { (void)lseek(p->fd, 0L, SEEK_SET); goto again; } /* fall through */ #endif } snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s", pcap_strerror(errno)); return (-1); } bp = p->buffer; } else bp = p->bp; /* * Loop through each packet. */ #define bhp ((struct bpf_hdr *)bp) ep = bp + cc; #ifdef PCAP_FDDIPAD pad = p->fddipad; #endif while (bp < ep) { register int caplen, hdrlen; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else { p->bp = bp; p->cc = ep - bp; return (n); } } caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; datap = bp + hdrlen; /* * Short-circuit evaluation: if using BPF filter * in kernel, no need to do it now. * #ifdef PCAP_FDDIPAD * Note: the filter code was generated assuming * that p->fddipad was the amount of padding * before the header, as that's what's required * in the kernel, so we run the filter before * skipping that padding. #endif */ if (fcode == NULL || bpf_filter(fcode, datap, bhp->bh_datalen, caplen)) { struct pcap_pkthdr pkthdr; pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec; #ifdef _AIX /* * AIX's BPF returns seconds/nanoseconds time * stamps, not seconds/microseconds time stamps. */ pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000; #else pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec; #endif #ifdef PCAP_FDDIPAD if (caplen > pad) pkthdr.caplen = caplen - pad; else pkthdr.caplen = 0; if (bhp->bh_datalen > pad) pkthdr.len = bhp->bh_datalen - pad; else pkthdr.len = 0; datap += pad; #else pkthdr.caplen = caplen; pkthdr.len = bhp->bh_datalen; #endif (*callback)(user, &pkthdr, datap); bp += BPF_WORDALIGN(caplen + hdrlen); if (++n >= cnt && cnt > 0) { p->bp = bp; p->cc = ep - bp; return (n); } } else { /* * Skip this packet. */ bp += BPF_WORDALIGN(caplen + hdrlen); } } #undef bhp p->cc = 0; return (n); }
/*********************************************************************** *%FUNCTION: receivePacket *%ARGUMENTS: * sock -- socket to read from * pkt -- place to store the received packet * size -- set to size of packet in bytes *%RETURNS: * >= 0 if all OK; < 0 if error *%DESCRIPTION: * Receives a packet ***********************************************************************/ int receivePacket(int sock, PPPoEPacket *pkt, int *size) { #ifdef USE_BPF struct bpf_hdr hdr; int seglen, copylen; if (bpfSize <= 0) { bpfOffset = 0; if ((bpfSize = read(sock, bpfBuffer, bpfLength)) < 0) { sysErr("read (receivePacket)"); return -1; } } if (bpfSize < sizeof(hdr)) { syslog(LOG_ERR, "Truncated bpf packet header: len=%d", bpfSize); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } memcpy(&hdr, bpfBuffer + bpfOffset, sizeof(hdr)); if (hdr.bh_caplen != hdr.bh_datalen) { syslog(LOG_ERR, "Truncated bpf packet: caplen=%d, datalen=%d", hdr.bh_caplen, hdr.bh_datalen); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } seglen = hdr.bh_hdrlen + hdr.bh_caplen; if (seglen > bpfSize) { syslog(LOG_ERR, "Truncated bpf packet: seglen=%d, bpfSize=%d", seglen, bpfSize); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } seglen = BPF_WORDALIGN(seglen); *size = copylen = ((hdr.bh_caplen < sizeof(PPPoEPacket)) ? hdr.bh_caplen : sizeof(PPPoEPacket)); memcpy(pkt, bpfBuffer + bpfOffset + hdr.bh_hdrlen, copylen); if (seglen >= bpfSize) { bpfSize = bpfOffset = 0; } else { bpfSize -= seglen; bpfOffset += seglen; } #else #ifdef USE_DLPI struct strbuf data; int flags = 0; int retval; data.buf = (char *) pkt; data.maxlen = MAXDLBUF; data.len = 0; if ((retval = getmsg(sock, NULL, &data, &flags)) < 0) { sysErr("read (receivePacket)"); return -1; } *size = data.len; #else if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) { sysErr("recv (receivePacket)"); return -1; } #endif #endif return 0; }