42 lines
1.1 KiB
Go
42 lines
1.1 KiB
Go
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)
|
||
|
|
}
|