github.com/cilium/cilium@v1.16.2/pkg/hubble/recorder/pcap/pcap.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package pcap
     5  
     6  import (
     7  	"io"
     8  	"net"
     9  
    10  	"github.com/cilium/cilium/pkg/byteorder"
    11  	"github.com/cilium/cilium/pkg/time"
    12  )
    13  
    14  // Datalink defines the type of the first layer of the captured packet
    15  type Datalink uint32
    16  
    17  var (
    18  	Null     Datalink = 0
    19  	Ethernet Datalink = 1
    20  )
    21  
    22  const (
    23  	MagicNumber  = 0xa1b2c3d4
    24  	VersionMajor = 2
    25  	VersionMinor = 4
    26  
    27  	TimestampCorrection = 0
    28  	TimestampAccuracy   = 0
    29  
    30  	DefaultSnapLen = 65535
    31  )
    32  
    33  const (
    34  	GlobalHeaderByteLen = 24
    35  	RecordHeaderByteLen = 16
    36  )
    37  
    38  // Header contains the configurable parameters for the global pcap header
    39  type Header struct {
    40  	// SnapshotLength is the maximum length of captured packets
    41  	SnapshotLength uint32
    42  	// Datalink is the type of header at the beginning of the packet
    43  	Datalink Datalink
    44  }
    45  
    46  // Bytes returns the byte representation of the global pcap header
    47  func (h *Header) Bytes() []byte {
    48  	// https://wiki.wireshark.org/Development/LibpcapFileFormat#Global_Header
    49  	const (
    50  		offsetMagicNumber         = 0
    51  		offsetVersionMajor        = 4
    52  		offsetVersionMinor        = 6
    53  		offsetTimestampCorrection = 8
    54  		offsetTimestampAccuracy   = 12
    55  		offsetSnapshotLength      = 16
    56  		offsetDatalink            = 20
    57  	)
    58  
    59  	native := byteorder.Native
    60  	b := make([]byte, GlobalHeaderByteLen)
    61  
    62  	snapLen := h.SnapshotLength
    63  	if snapLen == 0 {
    64  		snapLen = DefaultSnapLen
    65  	}
    66  
    67  	native.PutUint32(b[offsetMagicNumber:], MagicNumber)
    68  	native.PutUint16(b[offsetVersionMajor:], VersionMajor)
    69  	native.PutUint16(b[offsetVersionMinor:], VersionMinor)
    70  	native.PutUint32(b[offsetTimestampCorrection:], TimestampCorrection)
    71  	native.PutUint32(b[offsetTimestampAccuracy:], TimestampAccuracy)
    72  	native.PutUint32(b[offsetSnapshotLength:], snapLen)
    73  	native.PutUint32(b[offsetDatalink:], uint32(h.Datalink))
    74  
    75  	return b
    76  }
    77  
    78  // Record contains the configurable parameters for a record header
    79  type Record struct {
    80  	// Timestamp is the time the packet was captured
    81  	Timestamp time.Time
    82  	// CaptureLength is the size of the captured packet
    83  	CaptureLength uint32
    84  	// OriginalLength is the size of the original packet
    85  	OriginalLength uint32
    86  }
    87  
    88  // Bytes returns the byte representation of the per-record pcap header
    89  func (r *Record) Bytes() []byte {
    90  	// https://wiki.wireshark.org/Development/LibpcapFileFormat#Record_.28Packet.29_Header
    91  	const (
    92  		offsetTimestampUnix   = 0
    93  		offsetTimestampMicros = 4
    94  		offsetCaptureLength   = 8
    95  		offsetOriginalLength  = 12
    96  	)
    97  
    98  	tsUnix := uint32(r.Timestamp.Unix())
    99  	tsMicros := uint32(r.Timestamp.Nanosecond() / 1000)
   100  
   101  	native := byteorder.Native
   102  	b := make([]byte, RecordHeaderByteLen)
   103  
   104  	native.PutUint32(b[offsetTimestampUnix:], tsUnix)
   105  	native.PutUint32(b[offsetTimestampMicros:], tsMicros)
   106  	native.PutUint32(b[offsetCaptureLength:], r.CaptureLength)
   107  	native.PutUint32(b[offsetOriginalLength:], r.OriginalLength)
   108  
   109  	return b
   110  }
   111  
   112  // RecordWriter defines the interface for pcap writers
   113  type RecordWriter interface {
   114  	// WriteHeader writes the global pcap header. This must be invoked before
   115  	// WriteRecord is called.
   116  	WriteHeader(header Header) error
   117  	// WriteRecord writes a pcap record to the underlying stream.
   118  	WriteRecord(record Record, packet []byte) error
   119  	io.Closer
   120  }
   121  
   122  var _ RecordWriter = (*Writer)(nil)
   123  
   124  // Writer wraps a io.WriteCloser to implement RecordWriter
   125  type Writer struct {
   126  	io.WriteCloser
   127  }
   128  
   129  // NewWriter wraps a io.WriteCloser
   130  func NewWriter(w io.WriteCloser) *Writer {
   131  	return &Writer{
   132  		WriteCloser: w,
   133  	}
   134  }
   135  
   136  // WriteHeader implements RecordWriter
   137  func (w *Writer) WriteHeader(header Header) error {
   138  	_, err := w.Write(header.Bytes())
   139  	return err
   140  }
   141  
   142  // WriteRecord implements RecordWriter
   143  func (w *Writer) WriteRecord(record Record, packet []byte) error {
   144  	ioVec := net.Buffers{record.Bytes(), packet}
   145  	_, err := ioVec.WriteTo(w)
   146  	return err
   147  }