package libpcap import ( "context" "fmt" "github.com/google/gopacket" "github.com/google/gopacket/pcap" ) type NetCatch struct { eth string host string sentence string fn func(gopacket.Packet) *pcap.Handle ctx context.Context stopFn context.CancelFunc } func (n *NetCatch) Recall() func(gopacket.Packet) { return n.fn } func (n *NetCatch) SetRecall(fn func(p gopacket.Packet)) { n.fn = fn } func (n *NetCatch) Stop() { n.stopFn() } func FindAllDevs() ([]pcap.Interface, error) { return pcap.FindAllDevs() } func NewCatch(host string, sentence string) (*NetCatch, error) { ifs, err := pcap.FindAllDevs() if err != nil { return nil, err } eth := "" for _, v := range ifs { if host == "127.0.0.1" && v.Name == "\\Device\\NPF_Loopback" { eth = v.Name } for _, addr := range v.Addresses { if addr.IP.String() == host { eth = v.Name } } } if len(eth) == 0 { return nil, fmt.Errorf("cannot found eth") } nc := new(NetCatch) nc.host = host nc.eth = eth nc.sentence = sentence nc.ctx, nc.stopFn = context.WithCancel(context.Background()) return nc, nil } func NewCatchEth(eth string, sentence string) (*NetCatch, error) { nc := new(NetCatch) nc.eth = eth nc.sentence = sentence nc.ctx, nc.stopFn = context.WithCancel(context.Background()) return nc, nil } func (n *NetCatch) Run() error { if n.eth == "" { return fmt.Errorf("no pcap device") } handle, err := pcap.OpenLive(n.eth, 65535, true, pcap.BlockForever) if err != nil { return err } n.Handle = handle if err = handle.SetBPFFilter(n.sentence); err != nil { return err } pks := gopacket.NewPacketSource(handle, handle.LinkType()) for { select { case packet := <-pks.Packets(): if n.fn != nil { n.fn(packet) } case <-n.ctx.Done(): return nil } } }