mirror of
https://github.com/zr-hebo/sniffer-agent.git
synced 2025-08-09 20:46:27 +08:00
优化抓包性能
This commit is contained in:
171
vendor/github.com/google/gopacket/pcapgo/snoop.go
generated
vendored
Normal file
171
vendor/github.com/google/gopacket/pcapgo/snoop.go
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright 2019 The GoPacket Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
package pcapgo
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
const snoopMagic uint64 = 0x736e6f6f70000000 //8 byte in big endian
|
||||
const snoopVersion uint32 = 2
|
||||
const defaultBufLen uint32 = 150
|
||||
const maxCaptureLen int = 4096
|
||||
|
||||
// Errors
|
||||
const unknownMagic = "Unknown Snoop Magic Bytes"
|
||||
const unknownVersion = "Unknown Snoop Format Version"
|
||||
const unkownLinkType = "Unknown Link Type"
|
||||
const originalLenExceeded = "Capture length exceeds original packet length"
|
||||
const captureLenExceeded = "Capture length exceeds max capture length"
|
||||
|
||||
type snoopHeader struct {
|
||||
Version uint32
|
||||
linkType uint32
|
||||
}
|
||||
|
||||
// SnoopReader wraps an underlying io.SnoopReader to read packet data in SNOOP
|
||||
// format. See https://tools.ietf.org/html/rfc1761
|
||||
// for information on the file format.
|
||||
// We currenty read v2 file format and convert microsecond to nanoseconds
|
||||
// byte order in big-endian encoding.
|
||||
type SnoopReader struct {
|
||||
r io.Reader
|
||||
header snoopHeader
|
||||
//reuseable
|
||||
pad int
|
||||
packetBuf []byte
|
||||
buf [24]byte
|
||||
}
|
||||
|
||||
var (
|
||||
layerTypes = map[uint32]layers.LinkType{
|
||||
0: layers.LinkTypeEthernet, // IEEE 802.3
|
||||
2: layers.LinkTypeTokenRing, // IEEE 802.5 Token Ring
|
||||
4: layers.LinkTypeEthernet, // Ethernet
|
||||
5: layers.LinkTypeC_HDLC, // HDLC
|
||||
8: layers.LinkTypeFDDI, // FDDI
|
||||
/*
|
||||
10 - 4294967295 Unassigned
|
||||
not supported:
|
||||
1 - IEEE 802.4 Token Bus
|
||||
3 - IEEE 802.6 Metro Net
|
||||
6 - Character Synchronous
|
||||
7 - IBM Channel-to-Channel
|
||||
9 - Other
|
||||
*/
|
||||
}
|
||||
)
|
||||
|
||||
// LinkType return the mapped gopacket LinkType
|
||||
func (r *SnoopReader) LinkType() (*layers.LinkType, error) {
|
||||
if _, ok := layerTypes[r.header.linkType]; ok {
|
||||
lt := layerTypes[r.header.linkType]
|
||||
return <, nil
|
||||
}
|
||||
return nil, fmt.Errorf("%s, Code:%d", unkownLinkType, r.header.linkType)
|
||||
|
||||
}
|
||||
|
||||
// NewSnoopReader returns a new SnoopReader object, for reading packet data from
|
||||
// the given SnoopReader. The SnoopReader must be open and header data is
|
||||
// read from it at this point.
|
||||
// If the file format is not supported an error is returned
|
||||
func NewSnoopReader(r io.Reader) (*SnoopReader, error) {
|
||||
ret := SnoopReader{r: r}
|
||||
|
||||
if err := ret.readHeader(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
|
||||
func (r *SnoopReader) readHeader() error {
|
||||
buf := make([]byte, 16)
|
||||
|
||||
if n, err := io.ReadFull(r.r, buf); err != nil {
|
||||
return err
|
||||
} else if n < 16 {
|
||||
return errors.New("Not enough data for read")
|
||||
}
|
||||
|
||||
if magic := binary.BigEndian.Uint64(buf[0:8]); magic != snoopMagic {
|
||||
return fmt.Errorf("%s: %x", unknownMagic, magic)
|
||||
}
|
||||
|
||||
if r.header.Version = binary.BigEndian.Uint32(buf[8:12]); r.header.Version != snoopVersion {
|
||||
return fmt.Errorf("%s: %d", unknownVersion, r.header.Version)
|
||||
}
|
||||
|
||||
if r.header.linkType = binary.BigEndian.Uint32(buf[12:16]); r.header.linkType > 10 {
|
||||
return fmt.Errorf("%s, Code:%d", unkownLinkType, r.header.linkType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SnoopReader) readPacketHeader() (ci gopacket.CaptureInfo, err error) {
|
||||
|
||||
if _, err = io.ReadFull(r.r, r.buf[:]); err != nil {
|
||||
return
|
||||
}
|
||||
// OriginalLength uint32 4
|
||||
// IncludedLength uint32 8
|
||||
// PacketRecordLength uint32 12
|
||||
// CumulativeDrops uint32 16
|
||||
// TimestampSeconds uint32 20
|
||||
// TimestampMicroseconds uint32 24
|
||||
|
||||
ci.Timestamp = time.Unix(int64(binary.BigEndian.Uint32(r.buf[16:20])), int64(binary.BigEndian.Uint32(r.buf[20:24])*1000)).UTC()
|
||||
ci.Length = int(binary.BigEndian.Uint32(r.buf[0:4]))
|
||||
ci.CaptureLength = int(binary.BigEndian.Uint32(r.buf[4:8]))
|
||||
r.pad = int(binary.BigEndian.Uint32(r.buf[8:12])) - (24 + ci.Length)
|
||||
|
||||
if ci.CaptureLength > ci.Length {
|
||||
err = errors.New(originalLenExceeded)
|
||||
return
|
||||
}
|
||||
|
||||
if ci.CaptureLength > maxCaptureLen {
|
||||
err = errors.New(captureLenExceeded)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ReadPacketData reads next packet data.
|
||||
func (r *SnoopReader) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
|
||||
if ci, err = r.readPacketHeader(); err != nil {
|
||||
return
|
||||
}
|
||||
data = make([]byte, ci.CaptureLength+r.pad)
|
||||
_, err = io.ReadFull(r.r, data)
|
||||
return data[:ci.CaptureLength], ci, err
|
||||
|
||||
}
|
||||
|
||||
// ZeroCopyReadPacketData reads next packet data. The data buffer is owned by the SnoopReader,
|
||||
// and each call to ZeroCopyReadPacketData invalidates data returned by the previous one.
|
||||
//
|
||||
// It is not true zero copy, as data is still copied from the underlying SnoopReader. However,
|
||||
// this method avoids allocating heap memory for every packet.
|
||||
func (r *SnoopReader) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
|
||||
if ci, err = r.readPacketHeader(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if cap(r.packetBuf) < ci.CaptureLength+r.pad {
|
||||
r.packetBuf = make([]byte, ci.CaptureLength+r.pad)
|
||||
}
|
||||
_, err = io.ReadFull(r.r, r.packetBuf[:ci.CaptureLength+r.pad])
|
||||
return r.packetBuf[:ci.CaptureLength], ci, err
|
||||
}
|
Reference in New Issue
Block a user