示例#1
0
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
}
示例#2
0
// NewBPFSniffer is used to create BSD-only BPF ethernet sniffer
// iface is the network interface device name that you wish to sniff
// options can set to nil in order to utilize default values for everything.
// Each field of Options also have a default setting if left unspecified by
// the user's custome Options struct.
func NewBPFSniffer(iface string, options *Options) (*BPFSniffer, error) {
	var err error
	enable := 1
	sniffer := BPFSniffer{
		sniffDeviceName: iface,
	}
	if options == nil {
		sniffer.options = &defaultOptions
	} else {
		sniffer.options = options
	}

	if sniffer.options.BPFDeviceName == "" {
		sniffer.pickBpfDevice()
	}

	// setup our read buffer
	if sniffer.options.ReadBufLen == 0 {
		sniffer.options.ReadBufLen, err = syscall.BpfBuflen(sniffer.fd)
		if err != nil {
			return nil, err
		}
	} else {
		sniffer.options.ReadBufLen, err = syscall.SetBpfBuflen(sniffer.fd, sniffer.options.ReadBufLen)
		if err != nil {
			return nil, err
		}
	}
	sniffer.readBuffer = make([]byte, sniffer.options.ReadBufLen)

	err = syscall.SetBpfInterface(sniffer.fd, sniffer.sniffDeviceName)
	if err != nil {
		return nil, err
	}

	if sniffer.options.Immediate {
		// turn immediate mode on. This makes the snffer non-blocking.
		err = syscall.SetBpfImmediate(sniffer.fd, enable)
		if err != nil {
			return nil, err
		}
	}

	// the above call to syscall.SetBpfImmediate needs to be made
	// before setting a timer otherwise the reads will block for the
	// entire timer duration even if there are packets to return.
	if sniffer.options.Timeout != nil {
		err = syscall.SetBpfTimeout(sniffer.fd, sniffer.options.Timeout)
		if err != nil {
			return nil, err
		}
	}

	if sniffer.options.PreserveLinkAddr {
		// preserves the link level source address...
		// higher level protocol analyzers will not need this
		err = syscall.SetBpfHeadercmpl(sniffer.fd, enable)
		if err != nil {
			return nil, err
		}
	}

	if sniffer.options.Promisc {
		// forces the interface into promiscuous mode
		err = syscall.SetBpfPromisc(sniffer.fd, enable)
		if err != nil {
			return nil, err
		}
	}

	return &sniffer, nil
}