// Matches returns true if the given packet data matches this filter. func (b *BPF) Matches(ci gopacket.CaptureInfo, data []byte) bool { var hdr C.struct_pcap_pkthdr hdr.ts.tv_sec = C.gopacket_time_secs_t(ci.Timestamp.Unix()) hdr.ts.tv_usec = C.gopacket_time_usecs_t(ci.Timestamp.Nanosecond() / 1000) hdr.caplen = C.bpf_u_int32(len(data)) // Trust actual length over ci.Length. hdr.len = C.bpf_u_int32(ci.Length) dataptr := (*C.u_char)(unsafe.Pointer(&data[0])) return C.pcap_offline_filter(&b.bpf, &hdr, dataptr) != 0 }
// compileBPFFilter always returns an allocated _Ctype_struct_bpf_program // It is the callers responsibility to free the memory again, e.g. // // C.pcap_freecode(&bpf) // func (p *Handle) compileBPFFilter(expr string) (_Ctype_struct_bpf_program, error) { errorBuf := (*C.char)(C.calloc(errorBufferSize, 1)) defer C.free(unsafe.Pointer(errorBuf)) var netp uint32 var maskp uint32 // Only do the lookup on network interfaces. // No device indicates we're handling a pcap file. if len(p.device) > 0 { dev := C.CString(p.device) defer C.free(unsafe.Pointer(dev)) if -1 == C.pcap_lookupnet( dev, (*C.bpf_u_int32)(unsafe.Pointer(&netp)), (*C.bpf_u_int32)(unsafe.Pointer(&maskp)), errorBuf, ) { // We can't lookup the network, but that could be because the interface // doesn't have an IPv4. } } var bpf _Ctype_struct_bpf_program cexpr := C.CString(expr) defer C.free(unsafe.Pointer(cexpr)) if -1 == C.pcap_compile(p.cptr, &bpf, cexpr, 1, C.bpf_u_int32(maskp)) { return bpf, p.Error() } return bpf, nil }
// Generate and return the Filter associated with the Builder. func (b *Builder) Build() *Filter { prog := (*C.struct_bpf_program)(b.filter.Program()) flen := int(C.bpf_get_len(prog)) for i := 0; i < flen; i++ { insn := C.bpf_get_insn(prog, C.int(i)) if lbl, ok := b.jumps_k[i]; ok { addr := b.labels[lbl] if addr != 0 { insn.k = C.bpf_u_int32(addr - i - 1) } } if lbl, ok := b.jumps_jt[i]; ok { addr := b.labels[lbl] if addr != 0 { insn.jt = C.u_char(addr - i - 1) } } if lbl, ok := b.jumps_jf[i]; ok { addr := b.labels[lbl] if addr != 0 { insn.jf = C.u_char(addr - i - 1) } } } return b.filter }
// Writes a packet to the file. The return values of ReadPacketData // can be passed to this function as arguments. func (d *Dumper) WritePacketData(data []byte, ci gopacket.CaptureInfo) (err error) { var pkthdr _Ctype_struct_pcap_pkthdr pkthdr.caplen = C.bpf_u_int32(ci.CaptureLength) pkthdr.len = C.bpf_u_int32(ci.Length) pkthdr.ts.tv_sec = C.gopacket_time_secs_t(ci.Timestamp.Unix()) pkthdr.ts.tv_usec = C.gopacket_time_usecs_t(ci.Timestamp.Nanosecond() / 1000) // pcap_dump takes a u_char pointer to the dumper as first argument dumper_ptr := (*C.u_char)(unsafe.Pointer(d.cptr)) // trick to get a pointer to the underling slice ptr := (*C.u_char)(unsafe.Pointer(&data[0])) _, err = C.pcap_dump(dumper_ptr, &pkthdr, ptr) return }