Current-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: /dev/tap and tcpdump don't go together very well?
On Wed 04 Nov 2009 at 20:37:14 -0500, Greg Troxel wrote:
>
> Rhialto <rhialto%falu.nl@localhost> writes:
>
> > On Sun 08 Apr 2007 at 16:21:48 +0200, Rhialto wrote:
> >> BPF sees packets that come in from the wire and optionally (default
> >> on; BIOCSSEESENT; apparently undocumented) the packets that the host
> >> sends to the wire.
> >
> > This seems to be documented now in bpf(4).
>
> This flag applies to packets injected via BPF, or is it also about bpf
> seeing normal outgoing packets? The man page (5-stable) is not really
> clear.
I looked back at the original context, and at the kernel source. It
seems it is *only* about normal outgoing packets, not those injected via
BPF. I have included some hopefully clearer wording in the patch below.
> >> Packets injected into BPF are sent to the wire only, not to the host.
> >
> > FreeBSD now apparently has an ioctl for this:
> >
> > BIOCFEEDBACK (u_int) Set packet feedback mode. This allows injected
> > packets to be fed back as input to the interface when
> > output via the interface is successful. When
> > BPF_D_INOUT
> > direction is set, injected outgoing packet is not
> > returned by BPF to avoid duplication. This flag is ini-
> > tialized to zero by default.
>
> Is this separate from the bpf-ought-to-work-on-tap notion, and about how
> writes to bpf can be made to interoperate with the local host? If so,
> do we need to port BIOCFEEDBACK to NetBSD's bpf implementation?
It is separate, and about the latter. I just came across the old thread
again and somehow looked at FreeBSD :-) I thought it is a good idea to
copy BIOCFEEDBACK into NetBSD, and so I include a patch.
(Since I'm also trying out git and crossbuilding from FreeBSD at the
same time, it is not even compile-tested, but the spirit should be
there).
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 9e1b9c8..f68af76 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -403,6 +403,7 @@ bpfopen(dev_t dev, int flag, int mode, struct lwp *l)
d = malloc(sizeof(*d), M_DEVBUF, M_WAITOK|M_ZERO);
d->bd_bufsize = bpf_bufsize;
d->bd_seesent = 1;
+ d->bd_feedback = 0;
d->bd_pid = l->l_proc->p_pid;
getnanotime(&d->bd_btime);
d->bd_atime = d->bd_mtime = d->bd_btime;
@@ -618,7 +619,7 @@ bpf_write(struct file *fp, off_t *offp, struct uio *uio,
{
struct bpf_d *d = fp->f_data;
struct ifnet *ifp;
- struct mbuf *m;
+ struct mbuf *m, *mc;
int error, s;
static struct sockaddr_storage dst;
@@ -655,8 +656,25 @@ bpf_write(struct file *fp, off_t *offp, struct uio *uio,
if (d->bd_hdrcmplt)
dst.ss_family = pseudo_AF_HDRCMPLT;
+ if (d->bd_feedback) {
+ mc = m_dup(m, 0, M_COPYALL, M_NOWAIT);
+ if (mc != NULL)
+ mc->m_pkthdr.rcvif = ifp;
+ /* Set M_PROMISC for outgoing packets to be discarded. */
+ if (1 /*d->bd_direction == BPF_D_INOUT*/)
+ m->m_flags |= M_PROMISC;
+ } else
+ mc = NULL;
+
s = splsoftnet();
error = (*ifp->if_output)(ifp, m, (struct sockaddr *) &dst, NULL);
+
+ if (mc != NULL) {
+ if (error == 0)
+ (*ifp->if_input)(ifp, mc);
+ else
+ m_freem(mc);
+ }
splx(s);
KERNEL_UNLOCK_ONE(NULL);
/*
@@ -700,6 +718,10 @@ reset_d(struct bpf_d *d)
* BIOCVERSION Get filter language version.
* BIOCGHDRCMPLT Get "header already complete" flag.
* BIOCSHDRCMPLT Set "header already complete" flag.
+ * BIOCFEEDBACK Set packet feedback mode.
+ * BIOCGFEEDBACK Get packet feedback mode.
+ * BIOCGSEESENT Get "see sent packets" mode.
+ * BIOCSSEESENT Set "see sent packets" mode.
*/
/* ARGSUSED */
static int
@@ -971,6 +993,20 @@ bpf_ioctl(struct file *fp, u_long cmd, void *addr)
d->bd_seesent = *(u_int *)addr;
break;
+ /*
+ * Set "feed packets from bpf back to input" mode
+ */
+ case BIOCSFEEDBACK:
+ d->bd_feedback = *(u_int *)addr;
+ break;
+
+ /*
+ * Get "feed packets from bpf back to input" mode
+ */
+ case BIOCGFEEDBACK:
+ *(u_int *)addr = d->bd_feedback;
+ break;
+
case FIONBIO: /* Non-blocking I/O */
/*
* No need to do anything special as we use IO_NDELAY in
@@ -1355,9 +1391,15 @@ bpf_mtap2(void *arg, void *data, u_int dlen, struct mbuf
*m)
u_int pktlen;
struct mbuf mb;
+ /* Skip outgoing duplicate packets. */
+ if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
+ m->m_flags &= ~M_PROMISC;
+ return;
+ }
+
pktlen = m_length(m) + dlen;
- /*
+ /*
* Craft on-stack mbuf suitable for passing to bpf_filter.
* Note that we cut corners here; we only setup what's
* absolutely needed--this mbuf should never go anywhere else.
@@ -1381,6 +1423,12 @@ bpf_mtap(void *arg, struct mbuf *m)
u_int pktlen, buflen;
void *marg;
+ /* Skip outgoing duplicate packets. */
+ if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
+ m->m_flags &= ~M_PROMISC;
+ return;
+ }
+
pktlen = m_length(m);
if (pktlen == m->m_len) {
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index cb0d585..a280b67 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -139,6 +139,9 @@ struct bpf_version {
#define BIOCSSEESENT _IOW('B',121, u_int)
#define BIOCSRTIMEOUT _IOW('B',122, struct timeval)
#define BIOCGRTIMEOUT _IOR('B',123, struct timeval)
+#define BIOCGFEEDBACK _IOR('B',124, u_int)
+#define BIOCSFEEDBACK _IOW('B',125, u_int)
+#define BIOCFEEDBACK BIOCSFEEDBACK /* FreeBSD name */
/*
* Structure prepended to each packet. This is "wire" format, so we
diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h
index 7cc01ca..97729e5 100644
--- a/sys/net/bpfdesc.h
+++ b/sys/net/bpfdesc.h
@@ -79,6 +79,7 @@ struct bpf_d {
u_char bd_immediate; /* true to return on packet arrival */
int bd_hdrcmplt; /* false to fill in src lladdr */
int bd_seesent; /* true if bpf should see sent packets
*/
+ int bd_feedback; /* true to feed back sent packets */
int bd_async; /* non-zero if packet reception should
generate signal */
pid_t bd_pgid; /* process or group id for signal */
#if BSD < 199103
diff --git a/share/man/man4/bpf.4 b/share/man/man4/bpf.4
index 9507cf9..3f5ac41 100644
--- a/share/man/man4/bpf.4
+++ b/share/man/man4/bpf.4
@@ -297,8 +297,23 @@ By default, the flag is disabled (value is 0).
Enable/disable or get the
.Dq see sent
flag status.
-If enabled, packets sent will be passed to the filter.
+If enabled, packets sent by the host (not from
+.Nm )
+will be passed to the filter.
By default, the flag is enabled (value is 1).
+.It Dv BIOCFEEDBACK BIOCSFEEDBACK BIOCGFEEDBACK (u_int)
+Set (or get)
+.Dq packet feedback mode .
+This allows injected packets to be fed back as input to the interface when
+output via the interface is successful.
+The first name is meant for FreeBSD compatibility, the two others follow
+the Get/Set convention.
+.\"When
+.\".Dv BPF_D_INOUT
+.\"direction is set, injected
+Injected
+outgoing packets are not returned by BPF to avoid
+duplication. This flag is initialized to zero by default.
.El
.Sh STANDARD IOCTLS
.Nm
-Olaf.
--
___ Olaf 'Rhialto' Seibert -- You author it, and I'll reader it.
\X/ rhialto/at/xs4all.nl -- Cetero censeo "authored" delendum esse.
Home |
Main Index |
Thread Index |
Old Index