summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_tc.c2
-rw-r--r--sys/net/bpf.c263
-rw-r--r--sys/net/bpf.h112
-rw-r--r--sys/net/bpfdesc.h1
-rw-r--r--sys/sys/time.h1
5 files changed, 283 insertions, 96 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 48dc4f8..be2aacb 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -90,7 +90,7 @@ static struct timecounter *timecounters = &dummy_timecounter;
time_t time_second = 1;
time_t time_uptime = 1;
-static struct bintime boottimebin;
+struct bintime boottimebin;
struct timeval boottime;
static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS);
SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD,
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 16245c9..ab2ba1f 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -90,12 +90,16 @@ MALLOC_DEFINE(M_BPF, "BPF", "BPF data");
#define PRINET 26 /* interruptible */
+#define SIZEOF_BPF_HDR(type) \
+ (offsetof(type, bh_hdrlen) + sizeof(((type *)0)->bh_hdrlen))
+
#ifdef COMPAT_FREEBSD32
#include <sys/mount.h>
#include <compat/freebsd32/freebsd32.h>
#define BPF_ALIGNMENT32 sizeof(int32_t)
#define BPF_WORDALIGN32(x) (((x)+(BPF_ALIGNMENT32-1))&~(BPF_ALIGNMENT32-1))
+#ifndef BURN_BRIDGES
/*
* 32-bit version of structure prepended to each packet. We use this header
* instead of the standard one for 32-bit streams. We mark the a stream as
@@ -108,6 +112,7 @@ struct bpf_hdr32 {
uint16_t bh_hdrlen; /* length of bpf header (this struct
plus alignment padding) */
};
+#endif
struct bpf_program32 {
u_int bf_len;
@@ -120,11 +125,11 @@ struct bpf_dltlist32 {
};
#define BIOCSETF32 _IOW('B', 103, struct bpf_program32)
-#define BIOCSRTIMEOUT32 _IOW('B',109, struct timeval32)
-#define BIOCGRTIMEOUT32 _IOR('B',110, struct timeval32)
-#define BIOCGDLTLIST32 _IOWR('B',121, struct bpf_dltlist32)
-#define BIOCSETWF32 _IOW('B',123, struct bpf_program32)
-#define BIOCSETFNR32 _IOW('B',130, struct bpf_program32)
+#define BIOCSRTIMEOUT32 _IOW('B', 109, struct timeval32)
+#define BIOCGRTIMEOUT32 _IOR('B', 110, struct timeval32)
+#define BIOCGDLTLIST32 _IOWR('B', 121, struct bpf_dltlist32)
+#define BIOCSETWF32 _IOW('B', 123, struct bpf_program32)
+#define BIOCSETFNR32 _IOW('B', 130, struct bpf_program32)
#endif
/*
@@ -148,7 +153,7 @@ static __inline void
bpf_wakeup(struct bpf_d *);
static void catchpacket(struct bpf_d *, u_char *, u_int, u_int,
void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int),
- struct timeval *);
+ struct bintime *);
static void reset_d(struct bpf_d *);
static int bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
@@ -1007,6 +1012,8 @@ reset_d(struct bpf_d *d)
* BIOCSHDRCMPLT Set "header already complete" flag
* BIOCGDIRECTION Get packet direction flag
* BIOCSDIRECTION Set packet direction flag
+ * BIOCGTSTAMP Get time stamp format and resolution.
+ * BIOCSTSTAMP Set time stamp format and resolution.
* BIOCLOCK Set "locked" flag
* BIOCFEEDBACK Set packet feedback mode.
* BIOCSETZBUF Set current zero-copy buffer locations.
@@ -1055,6 +1062,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case BIOCVERSION:
case BIOCGRSIG:
case BIOCGHDRCMPLT:
+ case BIOCSTSTAMP:
case BIOCFEEDBACK:
case FIONREAD:
case BIOCLOCK:
@@ -1383,6 +1391,28 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
}
break;
+ /*
+ * Set packet timestamp format and resolution.
+ */
+ case BIOCGTSTAMP:
+ *(u_int *)addr = d->bd_tstamp;
+ break;
+
+ /*
+ * Set packet timestamp format and resolution.
+ */
+ case BIOCSTSTAMP:
+ {
+ u_int func;
+
+ func = *(u_int *)addr;
+ if (BPF_T_VALID(func))
+ d->bd_tstamp = func;
+ else
+ error = EINVAL;
+ }
+ break;
+
case BIOCFEEDBACK:
d->bd_feedback = *(u_int *)addr;
break;
@@ -1729,6 +1759,48 @@ filt_bpfread(struct knote *kn, long hint)
return (ready);
}
+#define BPF_TSTAMP_NONE 0
+#define BPF_TSTAMP_FAST 1
+#define BPF_TSTAMP_NORMAL 2
+#define BPF_TSTAMP_EXTERN 3
+
+static int
+bpf_ts_quality(int tstype)
+{
+
+ if (tstype == BPF_T_NONE)
+ return (BPF_TSTAMP_NONE);
+ if ((tstype & BPF_T_FAST) != 0)
+ return (BPF_TSTAMP_FAST);
+
+ return (BPF_TSTAMP_NORMAL);
+}
+
+static int
+bpf_gettime(struct bintime *bt, int tstype, struct mbuf *m)
+{
+ struct m_tag *tag;
+ int quality;
+
+ quality = bpf_ts_quality(tstype);
+ if (quality == BPF_TSTAMP_NONE)
+ return (quality);
+
+ if (m != NULL) {
+ tag = m_tag_locate(m, MTAG_BPF, MTAG_BPF_TIMESTAMP, NULL);
+ if (tag != NULL) {
+ *bt = *(struct bintime *)(tag + 1);
+ return (BPF_TSTAMP_EXTERN);
+ }
+ }
+ if (quality == BPF_TSTAMP_NORMAL)
+ binuptime(bt);
+ else
+ getbinuptime(bt);
+
+ return (quality);
+}
+
/*
* Incoming linkage from device drivers. Process the packet pkt, of length
* pktlen, which is stored in a contiguous buffer. The packet is parsed
@@ -1738,15 +1810,15 @@ filt_bpfread(struct knote *kn, long hint)
void
bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
{
+ struct bintime bt;
struct bpf_d *d;
#ifdef BPF_JITTER
bpf_jit_filter *bf;
#endif
u_int slen;
int gottime;
- struct timeval tv;
- gottime = 0;
+ gottime = BPF_TSTAMP_NONE;
BPFIF_LOCK(bp);
LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
BPFD_LOCK(d);
@@ -1766,15 +1838,13 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
slen = bpf_filter(d->bd_rfilter, pkt, pktlen, pktlen);
if (slen != 0) {
d->bd_fcount++;
- if (!gottime) {
- microtime(&tv);
- gottime = 1;
- }
+ if (gottime < bpf_ts_quality(d->bd_tstamp))
+ gottime = bpf_gettime(&bt, d->bd_tstamp, NULL);
#ifdef MAC
if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
#endif
catchpacket(d, pkt, pktlen, slen,
- bpf_append_bytes, &tv);
+ bpf_append_bytes, &bt);
}
BPFD_UNLOCK(d);
}
@@ -1791,13 +1861,13 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
void
bpf_mtap(struct bpf_if *bp, struct mbuf *m)
{
+ struct bintime bt;
struct bpf_d *d;
#ifdef BPF_JITTER
bpf_jit_filter *bf;
#endif
u_int pktlen, slen;
int gottime;
- struct timeval tv;
/* Skip outgoing duplicate packets. */
if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
@@ -1805,10 +1875,9 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m)
return;
}
- gottime = 0;
-
pktlen = m_length(m, NULL);
+ gottime = BPF_TSTAMP_NONE;
BPFIF_LOCK(bp);
LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp))
@@ -1825,15 +1894,13 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m)
slen = bpf_filter(d->bd_rfilter, (u_char *)m, pktlen, 0);
if (slen != 0) {
d->bd_fcount++;
- if (!gottime) {
- microtime(&tv);
- gottime = 1;
- }
+ if (gottime < bpf_ts_quality(d->bd_tstamp))
+ gottime = bpf_gettime(&bt, d->bd_tstamp, m);
#ifdef MAC
if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
#endif
catchpacket(d, (u_char *)m, pktlen, slen,
- bpf_append_mbuf, &tv);
+ bpf_append_mbuf, &bt);
}
BPFD_UNLOCK(d);
}
@@ -1847,11 +1914,11 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m)
void
bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
{
+ struct bintime bt;
struct mbuf mb;
struct bpf_d *d;
u_int pktlen, slen;
int gottime;
- struct timeval tv;
/* Skip outgoing duplicate packets. */
if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
@@ -1859,8 +1926,6 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
return;
}
- gottime = 0;
-
pktlen = m_length(m, NULL);
/*
* Craft on-stack mbuf suitable for passing to bpf_filter.
@@ -1872,6 +1937,7 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
mb.m_len = dlen;
pktlen += dlen;
+ gottime = BPF_TSTAMP_NONE;
BPFIF_LOCK(bp);
LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp))
@@ -1881,15 +1947,13 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
slen = bpf_filter(d->bd_rfilter, (u_char *)&mb, pktlen, 0);
if (slen != 0) {
d->bd_fcount++;
- if (!gottime) {
- microtime(&tv);
- gottime = 1;
- }
+ if (gottime < bpf_ts_quality(d->bd_tstamp))
+ gottime = bpf_gettime(&bt, d->bd_tstamp, m);
#ifdef MAC
if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
#endif
catchpacket(d, (u_char *)&mb, pktlen, slen,
- bpf_append_mbuf, &tv);
+ bpf_append_mbuf, &bt);
}
BPFD_UNLOCK(d);
}
@@ -1898,6 +1962,69 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
#undef BPF_CHECK_DIRECTION
+#undef BPF_TSTAMP_NONE
+#undef BPF_TSTAMP_FAST
+#undef BPF_TSTAMP_NORMAL
+#undef BPF_TSTAMP_EXTERN
+
+static int
+bpf_hdrlen(struct bpf_d *d)
+{
+ int hdrlen;
+
+ hdrlen = d->bd_bif->bif_hdrlen;
+#ifndef BURN_BRIDGES
+ if (d->bd_tstamp == BPF_T_NONE ||
+ BPF_T_FORMAT(d->bd_tstamp) == BPF_T_MICROTIME)
+#ifdef COMPAT_FREEBSD32
+ if (d->bd_compat32)
+ hdrlen += SIZEOF_BPF_HDR(struct bpf_hdr32);
+ else
+#endif
+ hdrlen += SIZEOF_BPF_HDR(struct bpf_hdr);
+ else
+#endif
+ hdrlen += SIZEOF_BPF_HDR(struct bpf_xhdr);
+#ifdef COMPAT_FREEBSD32
+ if (d->bd_compat32)
+ hdrlen = BPF_WORDALIGN32(hdrlen);
+ else
+#endif
+ hdrlen = BPF_WORDALIGN(hdrlen);
+
+ return (hdrlen - d->bd_bif->bif_hdrlen);
+}
+
+static void
+bpf_bintime2ts(struct bintime *bt, struct bpf_ts *ts, int tstype)
+{
+ struct bintime bt2;
+ struct timeval tsm;
+ struct timespec tsn;
+
+ if ((tstype & BPF_T_MONOTONIC) == 0) {
+ bt2 = *bt;
+ bintime_add(&bt2, &boottimebin);
+ bt = &bt2;
+ }
+ switch (BPF_T_FORMAT(tstype)) {
+ case BPF_T_MICROTIME:
+ bintime2timeval(bt, &tsm);
+ ts->bt_sec = tsm.tv_sec;
+ ts->bt_frac = tsm.tv_usec;
+ break;
+ case BPF_T_NANOTIME:
+ bintime2timespec(bt, &tsn);
+ ts->bt_sec = tsn.tv_sec;
+ ts->bt_frac = tsn.tv_nsec;
+ break;
+ case BPF_T_BINTIME:
+ ts->bt_sec = bt->sec;
+ ts->bt_frac = bt->frac;
+ break;
+ }
+}
+
/*
* Move the packet data from interface memory (pkt) into the
* store buffer. "cpfn" is the routine called to do the actual data
@@ -1908,15 +2035,19 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
static void
catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
void (*cpfn)(struct bpf_d *, caddr_t, u_int, void *, u_int),
- struct timeval *tv)
+ struct bintime *bt)
{
- struct bpf_hdr hdr;
+ struct bpf_xhdr hdr;
+#ifndef BURN_BRIDGES
+ struct bpf_hdr hdr_old;
#ifdef COMPAT_FREEBSD32
- struct bpf_hdr32 hdr32;
+ struct bpf_hdr32 hdr32_old;
#endif
- int totlen, curlen;
- int hdrlen = d->bd_bif->bif_hdrlen;
+#endif
+ int caplen, curlen, hdrlen, totlen;
int do_wakeup = 0;
+ int do_timestamp;
+ int tstype;
BPFD_LOCK_ASSERT(d);
@@ -1940,6 +2071,7 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
* much. Otherwise, transfer the whole packet (unless
* we hit the buffer size limit).
*/
+ hdrlen = bpf_hdrlen(d);
totlen = hdrlen + min(snaplen, pktlen);
if (totlen > d->bd_bufsize)
totlen = d->bd_bufsize;
@@ -1979,19 +2111,39 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
* reader should be woken up.
*/
do_wakeup = 1;
+ caplen = totlen - hdrlen;
+ tstype = d->bd_tstamp;
+ do_timestamp = tstype != BPF_T_NONE;
+#ifndef BURN_BRIDGES
+ if (tstype == BPF_T_NONE || BPF_T_FORMAT(tstype) == BPF_T_MICROTIME) {
+ struct bpf_ts ts;
+ if (do_timestamp)
+ bpf_bintime2ts(bt, &ts, tstype);
#ifdef COMPAT_FREEBSD32
- /*
- * If this is a 32-bit stream, then stick a 32-bit header at the
- * front and copy the data into the buffer.
- */
- if (d->bd_compat32) {
- bzero(&hdr32, sizeof(hdr32));
- hdr32.bh_tstamp.tv_sec = tv->tv_sec;
- hdr32.bh_tstamp.tv_usec = tv->tv_usec;
- hdr32.bh_datalen = pktlen;
- hdr32.bh_hdrlen = hdrlen;
- hdr.bh_caplen = hdr32.bh_caplen = totlen - hdrlen;
- bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr32, sizeof(hdr32));
+ if (d->bd_compat32) {
+ bzero(&hdr32_old, sizeof(hdr32_old));
+ if (do_timestamp) {
+ hdr32_old.bh_tstamp.tv_sec = ts.bt_sec;
+ hdr32_old.bh_tstamp.tv_usec = ts.bt_frac;
+ }
+ hdr32_old.bh_datalen = pktlen;
+ hdr32_old.bh_hdrlen = hdrlen;
+ hdr32_old.bh_caplen = caplen;
+ bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr32_old,
+ sizeof(hdr32_old));
+ goto copy;
+ }
+#endif
+ bzero(&hdr_old, sizeof(hdr_old));
+ if (do_timestamp) {
+ hdr_old.bh_tstamp.tv_sec = ts.bt_sec;
+ hdr_old.bh_tstamp.tv_usec = ts.bt_frac;
+ }
+ hdr_old.bh_datalen = pktlen;
+ hdr_old.bh_hdrlen = hdrlen;
+ hdr_old.bh_caplen = caplen;
+ bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr_old,
+ sizeof(hdr_old));
goto copy;
}
#endif
@@ -2001,19 +2153,20 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
* move forward the length of the header plus padding.
*/
bzero(&hdr, sizeof(hdr));
- hdr.bh_tstamp = *tv;
+ if (do_timestamp)
+ bpf_bintime2ts(bt, &hdr.bh_tstamp, tstype);
hdr.bh_datalen = pktlen;
hdr.bh_hdrlen = hdrlen;
- hdr.bh_caplen = totlen - hdrlen;
+ hdr.bh_caplen = caplen;
bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr, sizeof(hdr));
/*
* Copy the packet data into the store buffer and update its length.
*/
-#ifdef COMPAT_FREEBSD32
- copy:
+#ifndef BURN_BRIDGES
+copy:
#endif
- (*cpfn)(d, d->bd_sbuf, curlen + hdrlen, pkt, hdr.bh_caplen);
+ (*cpfn)(d, d->bd_sbuf, curlen + hdrlen, pkt, caplen);
d->bd_slen = curlen + totlen;
if (do_wakeup)
@@ -2083,13 +2236,7 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
LIST_INSERT_HEAD(&bpf_iflist, bp, bif_next);
mtx_unlock(&bpf_mtx);
- /*
- * 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;
+ bp->bif_hdrlen = hdrlen;
if (bootverbose)
if_printf(ifp, "bpf attached\n");
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index 726483a..b1aad51 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -45,6 +45,8 @@
typedef int32_t bpf_int32;
typedef u_int32_t bpf_u_int32;
+typedef int64_t bpf_int64;
+typedef u_int64_t bpf_u_int64;
/*
* Alignment macros. BPF_WORDALIGN rounds up to the next
@@ -113,36 +115,38 @@ struct bpf_zbuf {
size_t bz_buflen; /* Size of zero-copy buffers. */
};
-#define BIOCGBLEN _IOR('B',102, u_int)
-#define BIOCSBLEN _IOWR('B',102, u_int)
-#define BIOCSETF _IOW('B',103, struct bpf_program)
-#define BIOCFLUSH _IO('B',104)
-#define BIOCPROMISC _IO('B',105)
-#define BIOCGDLT _IOR('B',106, u_int)
-#define BIOCGETIF _IOR('B',107, struct ifreq)
-#define BIOCSETIF _IOW('B',108, struct ifreq)
-#define BIOCSRTIMEOUT _IOW('B',109, struct timeval)
-#define BIOCGRTIMEOUT _IOR('B',110, struct timeval)
-#define BIOCGSTATS _IOR('B',111, struct bpf_stat)
-#define BIOCIMMEDIATE _IOW('B',112, u_int)
-#define BIOCVERSION _IOR('B',113, struct bpf_version)
-#define BIOCGRSIG _IOR('B',114, u_int)
-#define BIOCSRSIG _IOW('B',115, u_int)
-#define BIOCGHDRCMPLT _IOR('B',116, u_int)
-#define BIOCSHDRCMPLT _IOW('B',117, u_int)
-#define BIOCGDIRECTION _IOR('B',118, u_int)
-#define BIOCSDIRECTION _IOW('B',119, u_int)
-#define BIOCSDLT _IOW('B',120, u_int)
-#define BIOCGDLTLIST _IOWR('B',121, struct bpf_dltlist)
+#define BIOCGBLEN _IOR('B', 102, u_int)
+#define BIOCSBLEN _IOWR('B', 102, u_int)
+#define BIOCSETF _IOW('B', 103, struct bpf_program)
+#define BIOCFLUSH _IO('B', 104)
+#define BIOCPROMISC _IO('B', 105)
+#define BIOCGDLT _IOR('B', 106, u_int)
+#define BIOCGETIF _IOR('B', 107, struct ifreq)
+#define BIOCSETIF _IOW('B', 108, struct ifreq)
+#define BIOCSRTIMEOUT _IOW('B', 109, struct timeval)
+#define BIOCGRTIMEOUT _IOR('B', 110, struct timeval)
+#define BIOCGSTATS _IOR('B', 111, struct bpf_stat)
+#define BIOCIMMEDIATE _IOW('B', 112, u_int)
+#define BIOCVERSION _IOR('B', 113, struct bpf_version)
+#define BIOCGRSIG _IOR('B', 114, u_int)
+#define BIOCSRSIG _IOW('B', 115, u_int)
+#define BIOCGHDRCMPLT _IOR('B', 116, u_int)
+#define BIOCSHDRCMPLT _IOW('B', 117, u_int)
+#define BIOCGDIRECTION _IOR('B', 118, u_int)
+#define BIOCSDIRECTION _IOW('B', 119, u_int)
+#define BIOCSDLT _IOW('B', 120, u_int)
+#define BIOCGDLTLIST _IOWR('B', 121, struct bpf_dltlist)
#define BIOCLOCK _IO('B', 122)
-#define BIOCSETWF _IOW('B',123, struct bpf_program)
-#define BIOCFEEDBACK _IOW('B',124, u_int)
-#define BIOCGETBUFMODE _IOR('B',125, u_int)
-#define BIOCSETBUFMODE _IOW('B',126, u_int)
-#define BIOCGETZMAX _IOR('B',127, size_t)
-#define BIOCROTZBUF _IOR('B',128, struct bpf_zbuf)
-#define BIOCSETZBUF _IOW('B',129, struct bpf_zbuf)
-#define BIOCSETFNR _IOW('B',130, struct bpf_program)
+#define BIOCSETWF _IOW('B', 123, struct bpf_program)
+#define BIOCFEEDBACK _IOW('B', 124, u_int)
+#define BIOCGETBUFMODE _IOR('B', 125, u_int)
+#define BIOCSETBUFMODE _IOW('B', 126, u_int)
+#define BIOCGETZMAX _IOR('B', 127, size_t)
+#define BIOCROTZBUF _IOR('B', 128, struct bpf_zbuf)
+#define BIOCSETZBUF _IOW('B', 129, struct bpf_zbuf)
+#define BIOCSETFNR _IOW('B', 130, struct bpf_program)
+#define BIOCGTSTAMP _IOR('B', 131, u_int)
+#define BIOCSTSTAMP _IOW('B', 132, u_int)
/* Obsolete */
#define BIOCGSEESENT BIOCGDIRECTION
@@ -155,9 +159,48 @@ enum bpf_direction {
BPF_D_OUT /* See outgoing packets */
};
+/* Time stamping functions */
+#define BPF_T_MICROTIME 0x0000
+#define BPF_T_NANOTIME 0x0001
+#define BPF_T_BINTIME 0x0002
+#define BPF_T_NONE 0x0003
+#define BPF_T_FORMAT_MASK 0x0003
+#define BPF_T_NORMAL 0x0000
+#define BPF_T_FAST 0x0100
+#define BPF_T_MONOTONIC 0x0200
+#define BPF_T_MONOTONIC_FAST (BPF_T_FAST | BPF_T_MONOTONIC)
+#define BPF_T_FLAG_MASK 0x0300
+#define BPF_T_FORMAT(t) ((t) & BPF_T_FORMAT_MASK)
+#define BPF_T_FLAG(t) ((t) & BPF_T_FLAG_MASK)
+#define BPF_T_VALID(t) \
+ ((t) == BPF_T_NONE || (BPF_T_FORMAT(t) != BPF_T_NONE && \
+ ((t) & ~(BPF_T_FORMAT_MASK | BPF_T_FLAG_MASK)) == 0))
+
+#define BPF_T_MICROTIME_FAST (BPF_T_MICROTIME | BPF_T_FAST)
+#define BPF_T_NANOTIME_FAST (BPF_T_NANOTIME | BPF_T_FAST)
+#define BPF_T_BINTIME_FAST (BPF_T_BINTIME | BPF_T_FAST)
+#define BPF_T_MICROTIME_MONOTONIC (BPF_T_MICROTIME | BPF_T_MONOTONIC)
+#define BPF_T_NANOTIME_MONOTONIC (BPF_T_NANOTIME | BPF_T_MONOTONIC)
+#define BPF_T_BINTIME_MONOTONIC (BPF_T_BINTIME | BPF_T_MONOTONIC)
+#define BPF_T_MICROTIME_MONOTONIC_FAST (BPF_T_MICROTIME | BPF_T_MONOTONIC_FAST)
+#define BPF_T_NANOTIME_MONOTONIC_FAST (BPF_T_NANOTIME | BPF_T_MONOTONIC_FAST)
+#define BPF_T_BINTIME_MONOTONIC_FAST (BPF_T_BINTIME | BPF_T_MONOTONIC_FAST)
+
/*
* Structure prepended to each packet.
*/
+struct bpf_ts {
+ bpf_int64 bt_sec; /* seconds */
+ bpf_u_int64 bt_frac; /* fraction */
+};
+struct bpf_xhdr {
+ struct bpf_ts 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) */
+};
+/* Obsolete */
struct bpf_hdr {
struct timeval bh_tstamp; /* time stamp */
bpf_u_int32 bh_caplen; /* length of captured portion */
@@ -165,14 +208,9 @@ struct bpf_hdr {
u_short bh_hdrlen; /* length of bpf header (this struct
plus alignment padding) */
};
-/*
- * Because the structure above is not a multiple of 4 bytes, some compilers
- * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
- * Only the kernel needs to know about it; applications use bh_hdrlen.
- */
#ifdef _KERNEL
-#define SIZEOF_BPF_HDR (sizeof(struct bpf_hdr) <= 20 ? 18 : \
- sizeof(struct bpf_hdr))
+#define MTAG_BPF 0x627066
+#define MTAG_BPF_TIMESTAMP 0
#endif
/*
@@ -922,7 +960,7 @@ struct bpf_if {
LIST_ENTRY(bpf_if) bif_next; /* list of all interfaces */
LIST_HEAD(, bpf_d) bif_dlist; /* descriptor list */
u_int bif_dlt; /* link layer type */
- u_int bif_hdrlen; /* length of header (with padding) */
+ u_int bif_hdrlen; /* length of link header */
struct ifnet *bif_ifp; /* corresponding interface */
struct mtx bif_mtx; /* mutex for interface */
};
diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h
index 03cb20d..14a895c 100644
--- a/sys/net/bpfdesc.h
+++ b/sys/net/bpfdesc.h
@@ -81,6 +81,7 @@ struct bpf_d {
u_char bd_immediate; /* true to return on packet arrival */
int bd_hdrcmplt; /* false to fill in src lladdr automatically */
int bd_direction; /* select packet direction */
+ int bd_tstamp; /* select time stamping function */
int bd_feedback; /* true to feed back sent packets */
int bd_async; /* non-zero if packet reception should generate signal */
int bd_sig; /* signal to send upon packet reception */
diff --git a/sys/sys/time.h b/sys/sys/time.h
index c2ed337..1039c22 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -264,6 +264,7 @@ void resettodr(void);
extern time_t time_second;
extern time_t time_uptime;
+extern struct bintime boottimebin;
extern struct timeval boottime;
/*
OpenPOWER on IntegriCloud