Files
yoloyolo/capture/bpf.go
T
gurix 52c601019b feat(04-01): add BPF validation, pcap reading, Timestamp field, and filter support
- Add Timestamp time.Time field to ClassifiedPacket (classify/types.go)
- Create capture/bpf.go: ValidateBPFFilter and CompileSoftwareBPF
- Create capture/pcap_reader.go: ReadPcapFile with optional software BPF filter
- Update OpenCapture and StartCapture to accept filter string param
- Update cmd/netsynth/main.go to pass empty filter to StartCapture
- All new tests pass; existing tests unaffected
2026-03-26 14:33:29 +01:00

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)
}