mirror of
https://github.com/danderson/netboot.git
synced 2025-10-17 02:21:20 +02:00
Implement a pcap writer.
This commit is contained in:
parent
67755cdc83
commit
7549f62395
BIN
pcap/pcap.test
BIN
pcap/pcap.test
Binary file not shown.
@ -73,7 +73,6 @@ func NewReader(r io.Reader) (*Reader, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Printf("%x\n", header.Magic)
|
|
||||||
switch header.Magic {
|
switch header.Magic {
|
||||||
case 0xa1b2c3d4:
|
case 0xa1b2c3d4:
|
||||||
// Timestamps are (sec, usec)
|
// Timestamps are (sec, usec)
|
74
pcap/writer.go
Normal file
74
pcap/writer.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package pcap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Writer serializes Packets to an io.Writer.
|
||||||
|
type Writer struct {
|
||||||
|
Writer io.Writer
|
||||||
|
LinkType LinkType
|
||||||
|
SnapLen uint32
|
||||||
|
ByteOrder binary.ByteOrder // defaults to binary.LittleEndian
|
||||||
|
|
||||||
|
headerWritten bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) order() binary.ByteOrder {
|
||||||
|
if w.ByteOrder != nil {
|
||||||
|
return w.ByteOrder
|
||||||
|
}
|
||||||
|
return binary.LittleEndian
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) header() error {
|
||||||
|
hdr := struct {
|
||||||
|
Magic uint32
|
||||||
|
Major uint16
|
||||||
|
Minor uint16
|
||||||
|
Ignored uint64
|
||||||
|
Snaplen uint32
|
||||||
|
Type uint32
|
||||||
|
}{
|
||||||
|
Magic: 0xa1b23c4d,
|
||||||
|
Major: 2,
|
||||||
|
Minor: 4,
|
||||||
|
Snaplen: w.SnapLen,
|
||||||
|
Type: uint32(w.LinkType),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(w.Writer, w.order(), hdr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.headerWritten = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put serializes pkt to w.Writer.
|
||||||
|
func (w *Writer) Put(pkt *Packet) error {
|
||||||
|
if !w.headerWritten {
|
||||||
|
if err := w.header(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hdr := struct {
|
||||||
|
Sec uint32
|
||||||
|
NSec uint32
|
||||||
|
Len uint32
|
||||||
|
OrigLen uint32
|
||||||
|
}{
|
||||||
|
Sec: uint32(pkt.Timestamp.Unix()),
|
||||||
|
NSec: uint32(pkt.Timestamp.Nanosecond()),
|
||||||
|
Len: uint32(len(pkt.Bytes)),
|
||||||
|
OrigLen: uint32(pkt.Length),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(w.Writer, w.order(), hdr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Writer.Write(pkt.Bytes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
86
pcap/writer_test.go
Normal file
86
pcap/writer_test.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package pcap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/kr/pretty"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReadback(t *testing.T) {
|
||||||
|
pkts := []*Packet{
|
||||||
|
{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
Length: 42,
|
||||||
|
Bytes: []byte{1, 2, 3, 4},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
Length: 30,
|
||||||
|
Bytes: []byte{2, 3, 4, 5},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
Length: 20,
|
||||||
|
Bytes: []byte{3, 4, 5, 6},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
Length: 10,
|
||||||
|
Bytes: []byte{4, 5, 6, 7},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
serializations := map[string]bool{}
|
||||||
|
for _, order := range []binary.ByteOrder{nil, binary.LittleEndian, binary.BigEndian} {
|
||||||
|
var b bytes.Buffer
|
||||||
|
w := &Writer{
|
||||||
|
Writer: &b,
|
||||||
|
LinkType: LinkEthernet,
|
||||||
|
SnapLen: 65535,
|
||||||
|
ByteOrder: order,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkt := range pkts {
|
||||||
|
if err := w.Put(pkt); err != nil {
|
||||||
|
t.Fatalf(pretty.Sprintf("Writing packet %# v: %s", pkt, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the binary form, to check how many different serializations we get.
|
||||||
|
serializations[b.String()] = true
|
||||||
|
|
||||||
|
readBack := []*Packet{}
|
||||||
|
r, err := NewReader(&b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Initializing reader for writer read-back: %s", err)
|
||||||
|
}
|
||||||
|
if r.LinkType != LinkEthernet {
|
||||||
|
t.Fatalf("Wrote link type %d, read back %d", LinkEthernet, r.LinkType)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadLoop:
|
||||||
|
for {
|
||||||
|
pkt, err := r.Next()
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break ReadLoop
|
||||||
|
}
|
||||||
|
t.Fatalf("Unexpected error reading packets: %s", err)
|
||||||
|
}
|
||||||
|
readBack = append(readBack, pkt)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(pkts, readBack) {
|
||||||
|
t.Fatalf("Packets were mutated by write-then-read")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(serializations) != 2 {
|
||||||
|
t.Fatalf("Expected 2 distinct serializations due to endianness, got %d", len(serializations))
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user