代码拉取完成,页面将自动刷新
package pcapraw
import (
"net"
"time"
"gitee.com/sillyman/simpleUtil/network/ifaceutil"
"gitee.com/sillyman/simpleUtil/network/macaddr"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/mdlayher/raw"
"golang.org/x/net/bpf"
)
type linuxRaw struct {
rawConn *raw.Conn
pcapRecvPktsCh chan gopacket.Packet
readErrCh chan error
closed bool
}
// New 创建 PcapRaw 实例
func New(localIP net.IP, ethtype uint16, bpfExpr string) (*linuxRaw, error) {
bpfRawInstructions, err := compileBPFFilter(bpfExpr)
if err != nil {
return nil, err
}
ifi, err := ifaceutil.GetIfaceByIP(localIP)
if err != nil {
return nil, err
}
conn, err := raw.ListenPacket(ifi, ethtype, &raw.Config{Filter: bpfRawInstructions})
if err != nil {
return nil, err
}
lraw := &linuxRaw{rawConn: conn, pcapRecvPktsCh: make(chan gopacket.Packet, 1024)}
go lraw.packetsToChannel()
return lraw, nil
}
// ReadGoPkt 读取一个数据包,如果在n秒内没有读取到数据则返回nil
func (l *linuxRaw) ReadGoPkt(timeout time.Duration) (gopacket.Packet, error) {
select {
case err := <-l.readErrCh:
return nil, err
case <-time.After(timeout):
return nil, nil
case pkt := <-l.pcapRecvPktsCh:
return pkt, nil
}
}
// WriteLayers
func (l *linuxRaw) WriteLayers(layers []gopacket.SerializableLayer) error {
data, err := serializeLayers(layers)
if err != nil {
return err
}
return l.WriteRaw(data)
}
// WriteRaw 向 raw 句柄写入数据
func (l *linuxRaw) WriteRaw(data []byte) error {
_, err := l.rawConn.WriteTo(data, &raw.Addr{HardwareAddr: macaddr.Zero.HardwareAddr()})
return err
}
// Close 关闭
func (l *linuxRaw) Close() {
l.closed = true
l.rawConn.Close()
}
// packetsToChannel 将 rawConn 的数据读取到 channel
func (l *linuxRaw) packetsToChannel() {
defer close(l.pcapRecvPktsCh)
buf := make([]byte, 65535)
for !l.closed {
if err := l.rawConn.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
l.readErrCh <- err
return
}
n, _, err := l.rawConn.ReadFrom(buf)
if err != nil {
// Immediately retry for temporary network errors
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
continue
}
l.readErrCh <- err
return
}
pkt := gopacket.NewPacket(buf[:n], layers.LayerTypeEthernet, gopacket.Default)
l.pcapRecvPktsCh <- pkt
}
}
// compileBPFFilter 借助 gopacket/pcap 编译 bpfexpr
func compileBPFFilter(expr string) ([]bpf.RawInstruction, error) {
pcapBPFInstructions, err := pcap.CompileBPFFilter(layers.LinkTypeEthernet, 1024, expr)
if err != nil {
return nil, err
}
bpfRawInstructions := make([]bpf.RawInstruction, len(pcapBPFInstructions))
for _, pcapPbf := range pcapBPFInstructions {
bpfRawInstructions = append(bpfRawInstructions, bpf.RawInstruction{
Op: pcapPbf.Code,
Jt: pcapPbf.Jt,
Jf: pcapPbf.Jf,
K: pcapPbf.K,
})
}
return bpfRawInstructions, nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。