// configureBPF configures a BPF device with the specified file descriptor to // use the specified network and interface and protocol. func configureBPF(fd int, ifi *net.Interface, proto Protocol) (int, error) { // Use specified interface with BPF device if err := syscall.SetBpfInterface(fd, ifi.Name); err != nil { return 0, err } // Inform BPF to send us its data immediately if err := syscall.SetBpfImmediate(fd, 1); err != nil { return 0, err } // Check buffer size of BPF device buflen, err := syscall.BpfBuflen(fd) if err != nil { return 0, err } // Do not automatically complete source address in ethernet headers if err := syscall.SetBpfHeadercmpl(fd, 0); err != nil { return 0, err } // Only retrieve incoming traffic using BPF device if err := setBPFDirection(fd, bpfDIn); err != nil { return 0, err } // Build and apply base BPF filter which checks for correct EtherType // on incoming packets prog, err := bpf.Assemble(baseInterfaceFilter(proto, ifi.MTU)) if err != nil { return 0, err } if err := syscall.SetBpf(fd, assembleBpfInsn(prog)); err != nil { return 0, err } // Flush any packets currently in the BPF device's buffer if err := syscall.FlushBpf(fd); err != nil { return 0, err } return buflen, nil }
func initialize(iface net.Interface) (err error) { verboseLog.Println("search available /dev/bpfX") for i := 0; i <= 10; i++ { bpfPath := fmt.Sprintf("/dev/bpf%d", i) bpf, err = os.OpenFile(bpfPath, os.O_RDWR, 0666) if err != nil { verboseLog.Printf(" open failed: %s - %s\n", bpfPath, err.Error()) } else { verboseLog.Printf(" open success: %s\n", bpfPath) break } } bpfFd = int(bpf.Fd()) if bpfFd == -1 { return errors.New("unable to open /dev/bpfX") } if err := syscall.SetBpfInterface(bpfFd, iface.Name); err != nil { return err } if err := syscall.SetBpfImmediate(bpfFd, 1); err != nil { return err } buflen, err = syscall.BpfBuflen(bpfFd) if err != nil { return err } if err := syscall.SetBpf(bpfFd, bpfArpFilter); err != nil { return err } if err := syscall.FlushBpf(bpfFd); err != nil { return err } return nil }
func prepareBPF(fd int, name string) (int, error) { if err := syscall.SetBpfInterface(fd, name); err != nil { return 0, err } if err := syscall.CheckBpfVersion(fd); err != nil { return 0, err } if err := syscall.SetBpfImmediate(fd, 1); err != nil { return 0, err } if err := syscall.SetBpfPromisc(fd, 1); err != nil { return 0, err } buflen, err := syscall.BpfBuflen(fd) if err != nil { return 0, err } if _, err = syscall.BpfHeadercmpl(fd); err != nil { return 0, err } if err := syscall.SetBpfHeadercmpl(fd, 0); err != nil { return 0, err } if _, err := syscall.BpfTimeout(fd); err != nil { return 0, err } tv := syscall.Timeval{Usec: 10} if err := syscall.SetBpfTimeout(fd, &tv); err != nil { return 0, err } if err := syscall.SetBpf(fd, ipv6OverEthernet); err != nil { return 0, nil } if err := syscall.FlushBpf(fd); err != nil { return 0, err } return buflen, nil }