package capture import ( "fmt" "strings" "golang.org/x/net/bpf" gpcapfilter "github.com/packetcap/go-pcap/filter" ) // ValidateBPFFilter checks if a BPF expression string is valid without needing a live socket. // Returns nil for empty strings (empty = no filter). Per CAPT-05. func ValidateBPFFilter(expr string) error { if strings.TrimSpace(expr) == "" { return nil } e := gpcapfilter.NewExpression(expr) if e == nil { return fmt.Errorf("invalid BPF filter expression: %q", expr) } f := e.Compile() if _, err := f.Compile(); err != nil { return fmt.Errorf("invalid BPF filter %q: %v", expr, err) } return nil } // CompileSoftwareBPF compiles a BPF expression into a VM for user-space packet matching. // Used for --read mode where kernel BPF is unavailable. Per D-04 (filter works with --read). func CompileSoftwareBPF(expr string) (*bpf.VM, error) { e := gpcapfilter.NewExpression(expr) if e == nil { return nil, fmt.Errorf("invalid BPF filter expression: %q", expr) } instructions, err := e.Compile().Compile() if err != nil { return nil, fmt.Errorf("BPF compile error for %q: %v", expr, err) } return bpf.NewVM(instructions) }