- TCP streams beyond stream.reassembly.depth
- encrypted streams after the key exchange
+- If a ``bpf-filter`` is set, packets that don't match the filter will
+ not be logged
It is possible to do conditional pcap logging by using the `conditional`
option in the pcap-log section. By default the variable is set to `all`
mode: normal # "normal" or multi
conditional: alerts
+ # A BPF filter that will be applied to all packets being
+ # logged. If set, packets must match this filter otherwise they
+ # will not be logged.
+ #bpf-filter:
+
In ``normal`` mode a pcap file "filename" is created in the default-log-dir or as
specified by "dir". ``normal`` mode is generally not as performant as ``multi``
mode.
typedef struct PcapLogData_ {
int use_stream_depth; /**< use stream depth i.e. ignore packets that reach limit */
int honor_pass_rules; /**< don't log if pass rules have matched */
+ char *bpf_filter; /**< bpf filter to apply to output */
SCMutex plog_lock;
uint64_t pkt_cnt; /**< total number of packets */
struct pcap_pkthdr *h; /**< pcap header struct */
uint64_t size_limit; /**< file size limit */
pcap_t *pcap_dead_handle; /**< pcap_dumper_t needs a handle */
pcap_dumper_t *pcap_dumper; /**< actually writes the packets */
+ struct bpf_program *bpfp; /**< compiled bpf program */
uint64_t profile_data_size; /**< track in bytes how many bytes we wrote */
uint32_t file_cnt; /**< count of pcap files we currently have */
uint32_t max_files; /**< maximum files to use in ring buffer mode */
SCLogDebug("Error opening dead pcap handle");
return TM_ECODE_FAILED;
}
+
+ if (pl->bpfp == NULL && pl->bpf_filter) {
+ struct bpf_program bpfp;
+ if (pcap_compile(pl->pcap_dead_handle, &bpfp, pl->bpf_filter, 0,
+ PCAP_NETMASK_UNKNOWN) == PCAP_ERROR) {
+ FatalError("Failed to compile BPF filter, aborting: %s: %s", pl->bpf_filter,
+ pcap_geterr(pl->pcap_dead_handle));
+ } else {
+ pl->bpfp = SCCalloc(1, sizeof(*pl->bpfp));
+ *pl->bpfp = bpfp;
+ }
+ }
}
if (pl->pcap_dumper == NULL) {
{
struct timeval current_dump;
gettimeofday(¤t_dump, NULL);
+
+ if (pl->bpfp) {
+ if (pcap_offline_filter(pl->bpfp, pl->h, data) == 0) {
+ SCLogDebug("Packet doesn't match filter, will not be logged.");
+ return TM_ECODE_OK;
+ }
+ }
+
pcap_dump((u_char *)pl->pcap_dumper, pl->h, data);
if (pl->compression.format == PCAP_LOG_COMPRESSION_FORMAT_NONE) {
pl->size_current += len;
pcap_close(pl->pcap_dead_handle);
}
+ if (pl->bpfp) {
+ pcap_freecode(pl->bpfp);
+ SCFree(pl->bpfp);
+ }
+
#ifdef HAVE_LIBLZ4
if (pl->compression.format == PCAP_LOG_COMPRESSION_FORMAT_LZ4) {
SCFree(pl->compression.buffer);
}
}
+ pl->bpf_filter = conf == NULL ? NULL : (char *)SCConfNodeLookupChildValue(conf, "bpf-filter");
+
/* create the output ctx and send it back */
OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));