#include "pcap/sll.h"
#include "pcap/ipnet.h"
#include "arcnet.h"
+ #if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+ #include <linux/types.h>
+ #include <linux/if_packet.h>
+ #include <linux/filter.h>
+ #endif
#ifdef HAVE_NET_PFVAR_H
#include <sys/socket.h>
#include <net/if.h>
-#include <net/pfvar.h>
-#include <net/if_pflog.h>
+#include <net/pf/pfvar.h>
+#include <net/pf/if_pflog.h>
#endif
#ifndef offsetof
#define offsetof(s, e) ((size_t)&((s *)0)->e)
{
extern int n_errors;
const char * volatile xbuf = buf;
- int len;
+ u_int len;
no_optimize = 0;
n_errors = 0;
off_nl_nosnap = -1;
return;
- #ifdef DLT_PFSYNC
case DLT_PFSYNC:
off_linktype = -1;
off_macpl = 4;
off_nl = 0;
off_nl_nosnap = 0;
return;
- #endif
case DLT_AX25_KISS:
/*
case DLT_ERF:
bpf_error("ERF link-layer type filtering not implemented");
- #ifdef DLT_PFSYNC
case DLT_PFSYNC:
bpf_error("PFSYNC link-layer type filtering not implemented");
- #endif
case DLT_LINUX_LAPD:
bpf_error("LAPD link-layer type filtering not implemented");
int dir;
{
struct block *b0, *b1;
+ #ifdef INET6
+ #ifndef CHASE_CHAIN
+ struct block *b2;
+ #endif
+ #endif
if (dir != Q_DEFAULT)
bpf_error("direction applied to 'proto'");
case Q_IPV6:
b0 = gen_linktype(ETHERTYPE_IPV6);
#ifndef CHASE_CHAIN
- b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+ /*
+ * Also check for a fragment header before the final
+ * header.
+ */
+ b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT);
+ b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v);
+ gen_and(b2, b1);
+ b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+ gen_or(b2, b1);
#else
b1 = gen_protochain(v, Q_IPV6);
#endif
}
/*
- * generate command for inbound/outbound. It's here so we can
- * make it link-type specific. 'dir' = 0 implies "inbound",
- * = 1 implies "outbound".
+ * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
+ * Outbound traffic is sent by this machine, while inbound traffic is
+ * sent by a remote machine (and may include packets destined for a
+ * unicast or multicast link-layer address we are not subscribing to).
+ * These are the same definitions implemented by pcap_setdirection().
+ * Capturing only unicast traffic destined for this host is probably
+ * better accomplished using a higher-layer filter.
*/
struct block *
gen_inbound(dir)
break;
case DLT_LINUX_SLL:
- if (dir) {
- /*
- * Match packets sent by this machine.
- */
- b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
- } else {
- /*
- * Match packets sent to this machine.
- * (No broadcast or multicast packets, or
- * packets sent to some other machine and
- * received promiscuously.)
- *
- * XXX - packets sent to other machines probably
- * shouldn't be matched, but what about broadcast
- * or multicast packets we received?
- */
- b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST);
+ /* match outgoing packets */
+ b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
+ if (!dir) {
+ /* to filter on inbound traffic, invert the match */
+ gen_not(b0);
}
break;
break;
default:
+ /*
+ * If we have packet meta-data indicating a direction,
+ * check it, otherwise give up as this link-layer type
+ * has nothing in the packet data.
+ */
+ #if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+ /*
+ * We infer that this is Linux with PF_PACKET support.
+ * If this is a *live* capture, we can look at
+ * special meta-data in the filter expression;
+ * if it's a savefile, we can't.
+ */
+ if (bpf_pcap->sf.rfile != NULL) {
+ /* We have a FILE *, so this is a savefile */
+ bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
+ linktype);
+ b0 = NULL;
+ /* NOTREACHED */
+ }
+ /* match outgoing packets */
+ b0 = gen_cmp(OR_LINK, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
+ PACKET_OUTGOING);
+ if (!dir) {
+ /* to filter on inbound traffic, invert the match */
+ gen_not(b0);
+ }
+ #else /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
bpf_error("inbound/outbound not supported on linktype %d",
linktype);
b0 = NULL;
/* NOTREACHED */
+ #endif /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
}
return (b0);
}