airpcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
struct pcap_airpcap *pa = p->priv;
- int cc;
+ u_int cc;
int n;
register u_char *bp, *ep;
UINT bytes_read;
p_AirpcapGetLastError(pa->adapter));
return (-1);
}
+
+ /*
+ * At this point, read_ret is guaranteed to be
+ * >= 0 and < p->bufsize; p->bufsize is a u_int,
+ * so its value is guaranteed to fit in cc, which
+ * is also a u_int.
+ */
cc = bytes_read;
bp = p->buffer;
} else
ep = bp + cc;
for (;;) {
register u_int caplen, hdrlen;
+ size_t packet_bytes;
/*
* Has "pcap_breakloop()" been called?
return (PCAP_ERROR_BREAK);
} else {
p->bp = bp;
- p->cc = (int) (ep - bp);
+ p->cc = (u_int) (ep - bp);
return (n);
}
}
caplen = bhp->Caplen;
hdrlen = bhp->Hdrlen;
datap = bp + hdrlen;
+
+ /*
+ * Compute the number of bytes for this packet in
+ * the buffer.
+ *
+ * That's the sum of the header length and the packet
+ * data length plus, if this is not the last packet,
+ * the padding required to align the next packet on
+ * the appropriate boundary.
+ *
+ * That means that it should be the minimum of the
+ * number of bytes left in the buffer and the
+ * rounded-up sum of the header and packet data lengths.
+ */
+ packet_bytes = min((u_int)(ep - bp), AIRPCAP_WORDALIGN(caplen + hdrlen));
+
/*
* Short-circuit evaluation: if using BPF filter
* in the AirPcap adapter, no need to do it now -
pkthdr.caplen = caplen;
pkthdr.len = bhp->Originallen;
(*callback)(user, &pkthdr, datap);
- bp += AIRPCAP_WORDALIGN(caplen + hdrlen);
+ bp += packet_bytes;
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
p->bp = bp;
- p->cc = (int)(ep - bp);
+ p->cc = (u_int)(ep - bp);
return (n);
}
} else {
/*
* Skip this packet.
*/
- bp += AIRPCAP_WORDALIGN(caplen + hdrlen);
+ bp += packet_bytes;
}
}
#undef bhp
* buffer filled for a fresh BPF session.
*/
static int
-pcap_next_zbuf_shm(pcap_t *p, ssize_t *cc)
+pcap_next_zbuf_shm(pcap_t *p, u_int *cc)
{
struct pcap_bpf *pb = p->priv;
struct bpf_zbuf_header *bzh;
* work.
*/
static int
-pcap_next_zbuf(pcap_t *p, ssize_t *cc)
+pcap_next_zbuf(pcap_t *p, u_int *cc)
{
struct pcap_bpf *pb = p->priv;
struct bpf_zbuf bz;
pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
struct pcap_bpf *pb = p->priv;
- ssize_t cc;
+ u_int cc;
int n = 0;
register u_char *bp, *ep;
u_char *datap;
#ifdef PCAP_FDDIPAD
register u_int pad;
#endif
-#ifdef HAVE_ZEROCOPY_BPF
- int i;
-#endif
again:
/*
*/
#ifdef HAVE_ZEROCOPY_BPF
if (pb->zerocopy) {
+ int next_zbuf_ret;
+
if (p->buffer != NULL)
pcap_ack_zbuf(p);
- i = pcap_next_zbuf(p, &cc);
- if (i == 0)
+ next_zbuf_ret = pcap_next_zbuf(p, &cc);
+ if (next_zbuf_ret == 0)
goto again;
- if (i < 0)
- return (PCAP_ERROR);
+ if (next_zbuf_ret < 0)
+ return (next_zbuf_ret);
} else
#endif
{
- cc = read(p->fd, p->buffer, p->bufsize);
- if (cc < 0) {
+ ssize_t read_ret;
+
+ read_ret = read(p->fd, p->buffer, p->bufsize);
+ if (read_ret < 0) {
/* Don't choke when we get ptraced */
switch (errno) {
errno, "read");
return (PCAP_ERROR);
}
+
+ /*
+ * At this point, read_ret is guaranteed to be
+ * >= 0 and < p->bufsize; p->bufsize is a u_int,
+ * so its value is guaranteed to fit in cc, which
+ * is also a u_int.
+ */
+ cc = (u_int)read_ret;
}
bp = p->buffer;
} else
#endif
while (bp < ep) {
register u_int caplen, hdrlen;
+ size_t packet_bytes;
/*
* Has "pcap_breakloop()" been called?
*/
if (p->break_loop) {
p->bp = bp;
- p->cc = (int)(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;
+ p->cc = (u_int)(ep - bp);
if (n == 0) {
p->break_loop = 0;
return (PCAP_ERROR_BREAK);
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;
datap = bp + hdrlen;
+
+ /*
+ * Compute the number of bytes for this packet in
+ * the buffer.
+ *
+ * That's the sum of the header length and the packet
+ * data length plus, if this is not the last packet,
+ * the padding required to align the next packet on
+ * the appropriate boundary.
+ *
+ * That means that it should be the minimum of the
+ * number of bytes left in the buffer (ep - bp) and the
+ * rounded-up sum of the header and packet data lengths.
+ */
+ packet_bytes = min((u_int)(ep - bp), BPF_WORDALIGN(caplen + hdrlen));
+
/*
* Short-circuit evaluation: if using BPF filter
* in kernel, no need to do it now - we already know
pkthdr.len = bhp->bh_datalen;
#endif
(*callback)(user, &pkthdr, datap);
- bp += BPF_WORDALIGN(caplen + hdrlen);
+ bp += packet_bytes;
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
p->bp = bp;
- p->cc = (int)(ep - bp);
- /*
- * See comment above about p->cc < 0.
- */
- if (p->cc < 0)
- p->cc = 0;
+ p->cc = (u_int)(ep - bp);
return (n);
}
} else {
/*
* Skip this packet.
*/
- bp += BPF_WORDALIGN(caplen + hdrlen);
+ bp += packet_bytes;
}
}
#undef bhp
u_int bufsize;
u_char *buffer;
u_char *bp;
- int cc;
+ u_int cc;
sig_atomic_t break_loop; /* flag set to force break from packet-reading loop */
int snapshot;
int linktype; /* Network linktype */
int linktype_ext; /* Extended information stored in the linktype field of a file */
- int offset; /* offset for proper alignment */
+ u_int offset; /* offset for proper alignment */
int activated; /* true if the capture is really started */
int oldstyle; /* if we're opening with pcap_open_live() */
char *device; /* device name */
int filter_in_userland; /* must filter in userland */
- int blocks_to_filter_in_userland;
+ u_int blocks_to_filter_in_userland;
int must_do_on_close; /* stuff we must do when we close */
int timeout; /* timeout for buffering */
int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */
* Get the status field of the ring buffer frame at a specified offset.
*/
static inline u_int
-pcap_get_ring_frame_status(pcap_t *handle, int offset)
+pcap_get_ring_frame_status(pcap_t *handle, u_int offset)
{
struct pcap_linux *handlep = handle->priv;
union thdr h;
* the one we've just processed.
*/
packet_mmap_release(h.h2);
- if (handlep->blocks_to_filter_in_userland > 0) {
+ if (handlep->blocks_to_filter_in_userland != 0) {
handlep->blocks_to_filter_in_userland--;
if (handlep->blocks_to_filter_in_userland == 0) {
/*
* just processed.
*/
packet_mmap_v3_release(h.h3);
- if (handlep->blocks_to_filter_in_userland > 0) {
+ if (handlep->blocks_to_filter_in_userland != 0) {
handlep->blocks_to_filter_in_userland--;
if (handlep->blocks_to_filter_in_userland == 0) {
/*
struct sock_fprog fcode;
int can_filter_in_kernel;
int err = 0;
- int n, offset;
+ u_int n, offset;
if (!handle)
return -1;
* walk the ring backward and count the free blocks.
*/
offset = handle->offset;
- if (--offset < 0)
- offset = handle->cc - 1;
+ if (offset == 0)
+ offset = handle->cc;
+ offset--;
for (n=0; n < handle->cc; ++n) {
- if (--offset < 0)
- offset = handle->cc - 1;
+ if (offset == 0)
+ offset = handle->cc;
+ offset--;
if (pcap_get_ring_frame_status(handle, offset) != TP_STATUS_KERNEL)
break;
}
struct pcap_netfilter *handlep = handle->priv;
register u_char *bp, *ep;
int count = 0;
- ssize_t len;
+ u_int cc;
/*
* Has "pcap_breakloop()" been called?
handle->break_loop = 0;
return PCAP_ERROR_BREAK;
}
- len = handle->cc;
- if (len == 0) {
+ cc = handle->cc;
+ if (cc == 0) {
/*
* The buffer is empty; refill it.
*
* to set handle->break_loop (we ignore it on other
* platforms as well).
*/
+ ssize_t read_ret;
+
do {
- len = recv(handle->fd, handle->buffer, handle->bufsize, 0);
+ read_ret = recv(handle->fd, handle->buffer, handle->bufsize, 0);
if (handle->break_loop) {
handle->break_loop = 0;
return PCAP_ERROR_BREAK;
}
- if (len == -1 && errno == ENOBUFS)
+ if (read_ret == -1 && errno == ENOBUFS)
handlep->packets_nobufs++;
- } while ((len == -1) && (errno == EINTR || errno == ENOBUFS));
+ } while ((read_ret == -1) && (errno == EINTR || errno == ENOBUFS));
- if (len < 0) {
+ if (read_ret < 0) {
pcapint_fmt_errmsg_for_errno(handle->errbuf,
PCAP_ERRBUF_SIZE, errno, "Can't receive packet");
return PCAP_ERROR;
}
+ /*
+ * At this point, read_ret is guaranteed to be
+ * >= 0 and < p->bufsize; p->bufsize is a u_int,
+ * so its value is guaranteed to fit in cc, which
+ * is also a u_int.
+ */
+ cc = (u_int)read_ret;
bp = (unsigned char *)handle->buffer;
} else
bp = handle->bp;
* This assumes that a single buffer of message will have
* <= INT_MAX packets, so the message count doesn't overflow.
*/
- ep = bp + len;
+ ep = bp + cc;
while (bp < ep) {
const struct nlmsghdr *nlh = (const struct nlmsghdr *) bp;
uint32_t msg_len;
*/
if (handle->break_loop) {
handle->bp = bp;
- handle->cc = (int)(ep - bp);
+ handle->cc = (u_int)(ep - bp);
if (count == 0) {
handle->break_loop = 0;
return PCAP_ERROR_BREAK;
break;
}
- if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || (u_int)len < nlh->nlmsg_len) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %zd) (nlmsg_len: %u)", len, nlh->nlmsg_len);
+ if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || cc < nlh->nlmsg_len) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %u) (nlmsg_len: %u)", cc, nlh->nlmsg_len);
return -1;
}
bp += msg_len;
if (count >= max_packets && !PACKET_COUNT_IS_UNLIMITED(max_packets)) {
handle->bp = bp;
- handle->cc = (int)(ep - bp);
- if (handle->cc < 0)
- handle->cc = 0;
+ handle->cc = (u_int)(ep - bp);
return count;
}
}
pcap_read_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
PACKET Packet;
- int cc;
+ u_int cc;
int n;
register u_char *bp, *ep;
u_char *datap;
ep = bp + cc;
for (;;) {
register u_int caplen, hdrlen;
+ size_t packet_bytes;
/*
* Has "pcap_breakloop()" been called?
return (PCAP_ERROR_BREAK);
} else {
p->bp = bp;
- p->cc = (int) (ep - bp);
+ p->cc = (u_int) (ep - bp);
return (n);
}
}
hdrlen = bhp->bh_hdrlen;
datap = bp + hdrlen;
+ /*
+ * Compute the number of bytes for this packet in
+ * the buffer.
+ *
+ * That's the sum of the header length and the packet
+ * data length plus, if this is not the last packet,
+ * the padding required to align the next packet on
+ * the appropriate boundary.
+ *
+ * That means that it should be the minimum of the
+ * number of bytes left in the buffer and the
+ * rounded-up sum of the header and packet data lengths.
+ */
+ packet_bytes = min((u_int)(ep - bp), Packet_WORDALIGN(caplen + hdrlen));
+
/*
* Short-circuit evaluation: if using BPF filter
* in kernel, no need to do it now - we already know
/* Discard all packets that are not '1 out of N' */
if (pw->samp_npkt != 0) {
- bp += Packet_WORDALIGN(caplen + hdrlen);
+ bp += packet_bytes;
continue;
}
break;
*/
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);
+ bp += packet_bytes;
continue;
}
* XXX A bpf_hdr matches a pcap_pkthdr.
*/
(*callback)(user, (struct pcap_pkthdr*)bp, datap);
- bp += Packet_WORDALIGN(caplen + hdrlen);
+ bp += packet_bytes;
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
p->bp = bp;
- p->cc = (int) (ep - bp);
+ p->cc = (u_int) (ep - bp);
return (n);
}
} else {
/*
* Skip this packet.
*/
- bp += Packet_WORDALIGN(caplen + hdrlen);
+ bp += packet_bytes;
}
}
#undef bhp
static int rpcap_read_packet_msg(struct pcap_rpcap const *rp, pcap_t *p, size_t size)
{
u_char *bp;
- int cc;
+ u_int cc;
int bytes_read;
bp = p->bp;
* Loop until we have the amount of data requested or we get
* an error or interrupt.
*/
- while ((size_t)cc < size)
+ while (cc < size)
{
/*
* We haven't read all of the packet header yet.