Add hex2pcap
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// Package pcap writes classic libpcap capture files.
|
||||
//
|
||||
// Format reference: https://www.ietf.org/archive/id/draft-ietf-opsawg-pcap-04.html
|
||||
package pcap
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultSnapLen is the snapshot length written to the file header.
|
||||
const DefaultSnapLen = 262144
|
||||
|
||||
const magicMicroseconds = 0xa1b2c3d4
|
||||
|
||||
// Common link-layer header types (LINKTYPE_* values from tcpdump.org).
|
||||
const (
|
||||
LinkTypeEthernet uint32 = 1
|
||||
LinkTypeRaw uint32 = 101
|
||||
LinkTypeIEEE80211 uint32 = 105
|
||||
LinkTypeLinuxSLL uint32 = 113
|
||||
LinkTypeLinuxSLL2 uint32 = 276
|
||||
)
|
||||
|
||||
// LinkTypeName returns a human readable name for well known link types.
|
||||
func LinkTypeName(lt uint32) string {
|
||||
switch lt {
|
||||
case LinkTypeEthernet:
|
||||
return "Ethernet"
|
||||
case LinkTypeRaw:
|
||||
return "Raw IP"
|
||||
case LinkTypeIEEE80211:
|
||||
return "IEEE 802.11"
|
||||
case LinkTypeLinuxSLL:
|
||||
return "Linux cooked (SLL)"
|
||||
case LinkTypeLinuxSLL2:
|
||||
return "Linux cooked v2 (SLL2)"
|
||||
}
|
||||
return fmt.Sprintf("LINKTYPE %d", lt)
|
||||
}
|
||||
|
||||
// Writer writes packets to a pcap file. The file header is written by NewWriter.
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
snapLen uint32
|
||||
}
|
||||
|
||||
// NewWriter writes a pcap file header (microsecond resolution, little endian)
|
||||
// for the given link type and returns a Writer for appending packets.
|
||||
func NewWriter(w io.Writer, linkType uint32) (*Writer, error) {
|
||||
var hdr [24]byte
|
||||
binary.LittleEndian.PutUint32(hdr[0:], magicMicroseconds)
|
||||
binary.LittleEndian.PutUint16(hdr[4:], 2) // version major
|
||||
binary.LittleEndian.PutUint16(hdr[6:], 4) // version minor
|
||||
// hdr[8:16]: thiszone and sigfigs, always zero
|
||||
binary.LittleEndian.PutUint32(hdr[16:], DefaultSnapLen)
|
||||
binary.LittleEndian.PutUint32(hdr[20:], linkType)
|
||||
if _, err := w.Write(hdr[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Writer{w: w, snapLen: DefaultSnapLen}, nil
|
||||
}
|
||||
|
||||
// WritePacket appends one packet record with the given timestamp.
|
||||
func (w *Writer) WritePacket(ts time.Time, data []byte) error {
|
||||
if len(data) > int(w.snapLen) {
|
||||
return fmt.Errorf("packet length %d exceeds snaplen %d", len(data), w.snapLen)
|
||||
}
|
||||
var hdr [16]byte
|
||||
binary.LittleEndian.PutUint32(hdr[0:], uint32(ts.Unix()))
|
||||
binary.LittleEndian.PutUint32(hdr[4:], uint32(ts.Nanosecond()/1000))
|
||||
binary.LittleEndian.PutUint32(hdr[8:], uint32(len(data))) // captured length
|
||||
binary.LittleEndian.PutUint32(hdr[12:], uint32(len(data))) // original length
|
||||
if _, err := w.w.Write(hdr[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := w.w.Write(data)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package pcap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestWriter(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
w, err := NewWriter(&buf, LinkTypeRaw)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ts := time.Unix(0x01020304, 5000)
|
||||
if err := w.WritePacket(ts, []byte{0xaa, 0xbb}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := "d4c3b2a1" + "0200" + "0400" + "00000000" + "00000000" + "00000400" + "65000000" +
|
||||
"04030201" + "05000000" + "02000000" + "02000000" + "aabb"
|
||||
if got := hex.EncodeToString(buf.Bytes()); got != want {
|
||||
t.Errorf("got %s\nwant %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriterRejectsOversizedPacket(t *testing.T) {
|
||||
w, err := NewWriter(&bytes.Buffer{}, LinkTypeEthernet)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := w.WritePacket(time.Now(), make([]byte, DefaultSnapLen+1)); err == nil {
|
||||
t.Error("expected error for oversized packet")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user