#include <netinet/in.h>
#include <arpa/inet.h>
-#include <errno.h>
#endif /* WIN32 */
}
#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
-static int skf_ad_vlan_tag_present_supported(int bpf_extensions) {
- return bpf_extensions >= SKF_AD_VLAN_TAG_PRESENT;
-}
-
static struct block *
-gen_vlan_bpf_extensions(int vlan_num) {
+gen_vlan_bpf_extensions(int vlan_num)
+{
struct block *b0, *b1;
struct slist *s;
- int val = 0, len, r;
-
- len = sizeof(val);
- r = getsockopt(bpf_pcap->fd, SOL_SOCKET, SO_BPF_EXTENSIONS, &val, &len);
- if (r < 0)
- return NULL;
-
- if (!skf_ad_vlan_tag_present_supported(val))
- return NULL;
/* generate new filter code based on extracting packet
* metadata */
#endif
static struct block *
-gen_vlan_no_bpf_extensions(int vlan_num) {
+gen_vlan_no_bpf_extensions(int vlan_num)
+{
struct block *b0, *b1;
/* check for VLAN, including QinQ */
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
- if (!vlan_stack_depth) {
- b0 = gen_vlan_bpf_extensions(vlan_num);
- if (!b0)
- b0 = gen_vlan_no_bpf_extensions(vlan_num);
- }
- else
+ if (vlan_stack_depth == 0) {
+ /*
+ * Do we need special VLAN handling?
+ */
+ if (p->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
+ b0 = gen_vlan_bpf_extensions(vlan_num);
+ else
+ b0 = gen_vlan_no_bpf_extensions(vlan_num);
+ } else
#endif
- b0 = gen_vlan_no_bpf_extensions(vlan_num);
+ b0 = gen_vlan_no_bpf_extensions(vlan_num);
break;
default:
bpf_error("no VLAN support for data link type %d",
/* We're accepting only packets in this direction/these directions. */
pcap_direction_t direction;
+ /*
+ * Flags to affect BPF code generation.
+ */
+ int bpf_codegen_flags;
+
/*
* Placeholder for filter code if bpf not in kernel.
*/
cleanup_op_t cleanup_op;
};
+/*
+ * BPF code generation flags.
+ */
+#define BPF_SPECIAL_VLAN_HANDLING 0x00000001 /* special VLAN handling for Linux */
+
/*
* This is a timeval as stored in a savefile.
* It has to use the same types everywhere, independent of the actual
#endif
int err = 0;
struct packet_mreq mr;
+#ifdef SO_BPF_EXTENSIONS
+ int bpf_extensions, len;
+#endif
/*
* Open a socket with protocol family packet. If the
*/
handle->fd = sock_fd;
+#ifdef SO_BPF_EXTENSIONS
+ /*
+ * Can we generate special code for VLAN checks?
+ * (XXX - what if we need the special code but it's not supported
+ * by the OS? Is that possible?)
+ */
+ if (getsockopt(sock_fd, SOL_SOCKET, SO_BPF_EXTENSIONS,
+ &bpf_extensions, &len == 0) {
+ if (bpf_extensions >= SKF_AD_VLAN_TAG_PRESENT) {
+ /*
+ * Yes, we can. Request that we do so.
+ */
+ handle->bpf_codegen_flags |= BPF_SPECIAL_VLAN_HANDLING;
+ }
+ }
+#endif /* SO_BPF_EXTENSIONS */
+
return 1;
#else /* HAVE_PF_PACKET_SOCKETS */
strlcpy(ebuf,
p->opt.immediate = 0;
p->opt.tstamp_type = -1; /* default to not setting time stamp type */
p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
+
+ /*
+ * Start out with no BPF code generation flags set.
+ */
+ p->bpf_codegen_flags = 0;
+
return (p);
}
p->setmintocopy_op = pcap_setmintocopy_dead;
#endif
p->cleanup_op = pcap_cleanup_dead;
+
+ /*
+ * A "dead" pcap_t never requires special BPF code generation.
+ */
+ p->bpf_codegen_flags = 0;
+
p->activated = 1;
return (p);
}
*/
p->oneshot_callback = pcap_oneshot;
+ /*
+ * Savefiles never require special BPF code generation.
+ */
+ p->bpf_codegen_flags = 0;
+
p->activated = 1;
return (p);