netshovel

Network Archaeology library for Go
git clone https://git.woozle.org/neale/netshovel.git

commit
ba891c3
parent
dd6e485
author
Neale Pickett
date
2020-09-24 16:57:02 -0600 MDT
Handle unaligned headers
3 files changed,  +42, -36
M netshovel.go
+4, -3
 1@@ -10,15 +10,16 @@ package netshovel
 2 
 3 import (
 4 	"flag"
 5+	"log"
 6+
 7 	"github.com/google/gopacket"
 8 	"github.com/google/gopacket/layers"
 9 	"github.com/google/gopacket/pcap"
10 	"github.com/google/gopacket/tcpassembly"
11-	"log"
12 )
13 
14-// Mainloop to handle dispatching of PCAP files from command line
15-//
16+// Shovel handles dispatching of PCAP files from the command line.
17+// It's intended that you invoke this from your main function.
18 // This parses the command line arguments,
19 // and for each PCAP file specified on the command line,
20 // invokes a TCP assembler that sends streams to whatever is returned from factory.
M packet.go
+27, -23
  1@@ -4,12 +4,13 @@ import (
  2 	"encoding/binary"
  3 	"encoding/hex"
  4 	"fmt"
  5-	"github.com/dirtbags/netshovel/gapstring"
  6 	"strings"
  7 	"time"
  8+
  9+	"github.com/dirtbags/netshovel/gapstring"
 10 )
 11 
 12-// Error returned by convenience methods that are unable to get enough data
 13+// ShortError is returned by convenience methods that are unable to get enough data
 14 type ShortError struct {
 15 	Wanted    int // How many bytes you needed
 16 	Available int // How many bytes were available
 17@@ -19,7 +20,7 @@ func (e *ShortError) Error() string {
 18 	return fmt.Sprintf("Short read: wanted %d of %d available", e.Wanted, e.Available)
 19 }
 20 
 21-// Error returned by convenience methods that are unable to operate on gaps in data
 22+// MissingError is returned by convenience methods that are unable to operate on gaps in data
 23 type MissingError struct {
 24 }
 25 
 26@@ -58,7 +59,7 @@ type Packet struct {
 27 
 28 var never = time.Unix(0, 0)
 29 
 30-// Return a new packet
 31+// NewPacket returns a new packet
 32 func NewPacket() Packet {
 33 	return Packet{
 34 		Opcode:      -1,
 35@@ -70,7 +71,7 @@ func NewPacket() Packet {
 36 	}
 37 }
 38 
 39-// Return a string with timestamp, opcode, and description of this packet
 40+// DescribeType returns a string with timestamp, opcode, and description of this packet
 41 func (pkt *Packet) DescribeType() string {
 42 	return fmt.Sprintf(
 43 		"  %s Opcode %d: %s",
 44@@ -80,7 +81,7 @@ func (pkt *Packet) DescribeType() string {
 45 	)
 46 }
 47 
 48-// Return a multi-line string describing fields in this packet
 49+// DescribeFields returns a multi-line string describing fields in this packet
 50 func (pkt *Packet) DescribeFields() string {
 51 	out := new(strings.Builder)
 52 	for _, f := range pkt.fields {
 53@@ -96,11 +97,11 @@ func center(s string, w int) string {
 54 	return fmt.Sprintf("%*s", -w, fmt.Sprintf("%*s", (w+len(s))/2, s))
 55 }
 56 
 57-// Return a multi-line string describing this packet's header structure
 58+// DescribeHeader returns a multi-line string describing this packet's header structure
 59 func (pkt *Packet) DescribeHeader() string {
 60 	out := new(strings.Builder)
 61 	fmt.Fprintln(out, " 0                               1                            ")
 62-	fmt.Fprintln(out, " 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f")
 63+	fmt.Fprintln(out, " mo0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f")
 64 
 65 	bitOffset := 0
 66 	for _, f := range pkt.header {
 67@@ -128,11 +129,14 @@ func (pkt *Packet) DescribeHeader() string {
 68 			}
 69 		}
 70 	}
 71+	if bitOffset > 0 {
 72+		fmt.Fprintln(out, "|")
 73+	}
 74 	fmt.Fprintln(out, "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+")
 75 	return out.String()
 76 }
 77 
 78-// Return a multi-line string describing this packet
 79+// Describe returns a multi-line string describing this packet
 80 //
 81 // This shows the timestamp, opcode, description, and hex dump.
 82 // If you set any values, those are displayed in the order they were set.
 83@@ -157,32 +161,32 @@ func (pkt *Packet) Set(key, value string) {
 84 	pkt.fields = append(pkt.fields, namedField{key, value})
 85 }
 86 
 87-// Set a string value, displaying its Go string representation
 88+// SetString sets a string value, displaying its Go string representation
 89 func (pkt *Packet) SetString(key, value string) {
 90 	pkt.Set(key, fmt.Sprintf("%#v", value))
 91 }
 92 
 93-// Set an int value, displaying its decimal and hexadecimal representations
 94+// SetInt sets an int value, displaying its decimal and hexadecimal representations
 95 func (pkt *Packet) SetInt(key string, value int) {
 96 	pkt.Set(key, fmt.Sprintf("%d == 0x%x", value, value))
 97 }
 98 
 99-// Set an unsigned int value, displaying its decimal and hexadecimal representations
100+// SetUint sets an unsigned int value, displaying its decimal and hexadecimal representations
101 func (pkt *Packet) SetUint(key string, value uint) {
102 	pkt.Set(key, fmt.Sprintf("%d == 0x%x", value, value))
103 }
104 
105-// Set an Unt32 value, displaying its decimal and 0-padded hexadecimal representations
106+// SetUint32 sets an Unt32 value, displaying its decimal and 0-padded hexadecimal representations
107 func (pkt *Packet) SetUint32(key string, value uint32) {
108 	pkt.Set(key, fmt.Sprintf("%d == 0x%04x", value, value))
109 }
110 
111-// Set an []byte value, displaying the hex encoding of the bytes
112+// SetBytes sets a []byte value, displaying the hex encoding of the bytes
113 func (pkt *Packet) SetBytes(key string, value []byte) {
114 	pkt.Set(key, hex.EncodeToString(value))
115 }
116 
117-// Set a GapString value, displaying the hex encoding and runes encoding (like a hex dump)
118+// SetGapString sets a GapString value, displaying the hex encoding and runes encoding (like a hex dump)
119 func (pkt *Packet) SetGapString(key string, value gapstring.GapString) {
120 	pkt.Set(key, fmt.Sprintf("%s  %s", value.HexString(), value.Runes()))
121 }
122@@ -203,7 +207,7 @@ func (pkt *Packet) Peel(octets int) ([]byte, error) {
123 	return b, nil
124 }
125 
126-// Add a field to the header field description
127+// AddHeaderField adds a field to the header field description
128 func (pkt *Packet) AddHeaderField(order binary.ByteOrder, name string, bits int, value interface{}) {
129 	h := headerField{
130 		name:  name,
131@@ -247,7 +251,7 @@ func (pkt *Packet) readUint(order binary.ByteOrder, bits int, name string) (inte
132 	return value, nil
133 }
134 
135-// Peel off a uint64, little-endian
136+// Uint64LE peels off a uint64, little-endian
137 func (pkt *Packet) Uint64LE(name string) (uint64, error) {
138 	value, err := pkt.readUint(binary.LittleEndian, 64, name)
139 	if err != nil {
140@@ -256,7 +260,7 @@ func (pkt *Packet) Uint64LE(name string) (uint64, error) {
141 	return value.(uint64), err
142 }
143 
144-// Peel off a uint32, little-endian
145+// Uint32LE peels off a uint32, little-endian
146 func (pkt *Packet) Uint32LE(name string) (uint32, error) {
147 	value, err := pkt.readUint(binary.LittleEndian, 32, name)
148 	if err != nil {
149@@ -265,7 +269,7 @@ func (pkt *Packet) Uint32LE(name string) (uint32, error) {
150 	return value.(uint32), err
151 }
152 
153-// Peel off a uint16, little-endian
154+// Uint16LE peels off a uint16, little-endian
155 func (pkt *Packet) Uint16LE(name string) (uint16, error) {
156 	value, err := pkt.readUint(binary.LittleEndian, 16, name)
157 	if err != nil {
158@@ -274,7 +278,7 @@ func (pkt *Packet) Uint16LE(name string) (uint16, error) {
159 	return value.(uint16), err
160 }
161 
162-// Peel off a uint64, big-endian
163+// Uint64BE peels off a uint64, big-endian
164 func (pkt *Packet) Uint64BE(name string) (uint64, error) {
165 	value, err := pkt.readUint(binary.BigEndian, 64, name)
166 	if err != nil {
167@@ -283,7 +287,7 @@ func (pkt *Packet) Uint64BE(name string) (uint64, error) {
168 	return value.(uint64), err
169 }
170 
171-// Peel off a uint32, big-endian
172+// Uint32BE peels off a uint32, big-endian
173 func (pkt *Packet) Uint32BE(name string) (uint32, error) {
174 	value, err := pkt.readUint(binary.BigEndian, 32, name)
175 	if err != nil {
176@@ -292,7 +296,7 @@ func (pkt *Packet) Uint32BE(name string) (uint32, error) {
177 	return value.(uint32), err
178 }
179 
180-// Peel off a uint16, big-endian
181+// Uint16BE peels off a uint16, big-endian
182 func (pkt *Packet) Uint16BE(name string) (uint16, error) {
183 	value, err := pkt.readUint(binary.BigEndian, 16, name)
184 	if err != nil {
185@@ -301,7 +305,7 @@ func (pkt *Packet) Uint16BE(name string) (uint16, error) {
186 	return value.(uint16), err
187 }
188 
189-// Peel off a uint8 (aka byte)
190+// Uint8 peels off a uint8 (aka byte)
191 func (pkt *Packet) Uint8(name string) (uint8, error) {
192 	value, err := pkt.readUint(binary.BigEndian, 8, name)
193 	if err != nil {
M stream.go
+11, -10
 1@@ -2,23 +2,24 @@ package netshovel
 2 
 3 import (
 4 	"fmt"
 5-	"github.com/dirtbags/netshovel/gapstring"
 6-	"github.com/google/gopacket"
 7-	"github.com/google/gopacket/tcpassembly"
 8 	"io"
 9 	"net/url"
10 	"os"
11 	"strings"
12 	"time"
13+
14+	"github.com/dirtbags/netshovel/gapstring"
15+	"github.com/google/gopacket"
16+	"github.com/google/gopacket/tcpassembly"
17 )
18 
19-// A File and the path where it lives
20+// NamedFile stores a file and the path where it lives
21 type NamedFile struct {
22 	*os.File
23 	Name string
24 }
25 
26-// An atomic communication within a Stream
27+// Utterance is an atomic communication within a Stream
28 //
29 // Streams consist of a string of Utterances.
30 // Each utterance has associated data, and a time stamp.
31@@ -38,7 +39,7 @@ type Stream struct {
32 	pending        Utterance
33 }
34 
35-// Return a newly-built Stream
36+// NewStream returns a newly-built Stream
37 //
38 // You should embed Stream into your own Application protocol stream struct.
39 // Use this to initialize the internal stuff netshovel needs.
40@@ -50,7 +51,7 @@ func NewStream(net, transport gopacket.Flow) Stream {
41 	}
42 }
43 
44-// Called by the TCP assembler when an Utterance can be built
45+// Reassembled is called by the TCP assembler when an Utterance can be built
46 func (stream *Stream) Reassembled(rs []tcpassembly.Reassembly) {
47 	ret := Utterance{
48 		When: rs[0].Seen,
49@@ -68,7 +69,7 @@ func (stream *Stream) Reassembled(rs []tcpassembly.Reassembly) {
50 	}
51 }
52 
53-// Called by the TCP assemble when the Stream is closed
54+// ReassemblyComplete is called by the TCP assemble when the Stream is closed
55 func (stream *Stream) ReassemblyComplete() {
56 	close(stream.conversation)
57 }
58@@ -137,7 +138,7 @@ func (stream *Stream) Read(length int) (Utterance, error) {
59 	return ret, nil
60 }
61 
62-// Return a string description of a packet
63+// Describe returns a string description of a packet
64 //
65 // This just prefixes our source and dest IP:Port to pkt.Describe()
66 func (stream *Stream) Describe(pkt Packet) string {
67@@ -151,7 +152,7 @@ func (stream *Stream) Describe(pkt Packet) string {
68 	return out.String()
69 }
70 
71-// Return a newly-created, truncated file
72+// CreateFile returns a newly-created, truncated file
73 //
74 // This function creates consistently-named files,
75 // which include a timestamp,