Start trying to make it a library
This commit is contained in:
parent
22929176dd
commit
0da5aa7d09
|
@ -0,0 +1,26 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/dirtbags/netshovel"
|
||||||
|
)
|
||||||
|
|
||||||
|
struct SimpleStreamFactory {
|
||||||
|
netshovel.Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SimpleStream {
|
||||||
|
netshovel.Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *SimpleStreamFactory) New(net, transport gopacket.Flow) tcpassembly.Stream {
|
||||||
|
ret = SimpleStream{}
|
||||||
|
ret.Stream = f.Factory.New(net, transport)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SimplePacket {
|
||||||
|
netshovel.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
netshovel.Shovel(SimpleFactory)
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
"github.com/dirtbags/netshovel/gapstring"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/google/gopacket/pcap"
|
||||||
|
"github.com/google/gopacket/tcpassembly"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func Shovel(factory tcpassembly.StreamFactory) {
|
||||||
|
verbose := flag.Bool("verbose", false, "Write lots of information out")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
streamPool := tcpassembly.NewStreamPool(factory)
|
||||||
|
assembler := tcpassembly.NewAssembler(streamPool)
|
||||||
|
|
||||||
|
for _, fn := range flag.Args() {
|
||||||
|
handle, err := pcap.OpenOffline(fn)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
|
||||||
|
packets := packetSource.Packets()
|
||||||
|
npackets := 0
|
||||||
|
for packet := range packets {
|
||||||
|
if packet == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP {
|
||||||
|
log.Println("Unusable packet")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tcp := packet.TransportLayer().(*layers.TCP)
|
||||||
|
assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp)
|
||||||
|
npackets += 1
|
||||||
|
}
|
||||||
|
log.Println("npackets", npackets)
|
||||||
|
}
|
||||||
|
assembler.FlushAll()
|
||||||
|
goRoutines.Wait()
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
"github.com/dirtbags/netshovel/gapstring"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/google/gopacket/pcap"
|
||||||
|
"github.com/google/gopacket/tcpassembly"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Packet struct {
|
||||||
|
Opcode int
|
||||||
|
Description string
|
||||||
|
When time.Time
|
||||||
|
Payload gapstring.GapString
|
||||||
|
Fields map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
var never = time.Unix(0, 0)
|
||||||
|
|
||||||
|
func NewPacket() Packet {
|
||||||
|
return Packet{
|
||||||
|
Opcode: -1,
|
||||||
|
Description: "Undefined",
|
||||||
|
When: never,
|
||||||
|
Payload: gapstring.GapString{},
|
||||||
|
Fields: map[string]string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pkt *Packet) Name() string {
|
||||||
|
return "Generic"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pkt *Packet) Describe() string {
|
||||||
|
out := new(strings.Builder)
|
||||||
|
|
||||||
|
fmt.Fprintf(out, "%s %s %d: %s\n",
|
||||||
|
pkt.When.UTC().Format(tim.RFC3339Nano),
|
||||||
|
pkt.Name(),
|
||||||
|
pkt.Opcode,
|
||||||
|
pkt.Description,
|
||||||
|
)
|
||||||
|
for _, k := range pkt.Keys() {
|
||||||
|
fmt.Fprintf(out, " %s: %s\n", k, pkt.Fields[k])
|
||||||
|
}
|
||||||
|
fmt.Fprint(out, pkt.Payload.Hexdump())
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pkt *Packet) Set(key, value string) {
|
||||||
|
pkt.Fileds[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pkt *Packet) Keys() {
|
||||||
|
keys := make([]string, len(pkt.Fields))
|
||||||
|
i := 0
|
||||||
|
for k := range(pkt.Fields) {
|
||||||
|
keys[i] = k
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
|
}
|
|
@ -16,9 +16,7 @@ import (
|
||||||
"github.com/google/gopacket/tcpassembly"
|
"github.com/google/gopacket/tcpassembly"
|
||||||
)
|
)
|
||||||
|
|
||||||
var verbose = flag.Bool("verbose", false, "Write lots of information out")
|
var StreamWG sync.WaitGroup
|
||||||
|
|
||||||
var goRoutines sync.WaitGroup
|
|
||||||
|
|
||||||
type WriteAtCloser interface {
|
type WriteAtCloser interface {
|
||||||
io.WriterAt
|
io.WriterAt
|
||||||
|
@ -39,34 +37,14 @@ type Stream struct {
|
||||||
pending Utterance
|
pending Utterance
|
||||||
}
|
}
|
||||||
|
|
||||||
type Packet struct {
|
|
||||||
Opcode int
|
|
||||||
Description string
|
|
||||||
When time.Time
|
|
||||||
Payload gapstring.GapString
|
|
||||||
Fields map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
var noTime = time.Unix(0, 0)
|
|
||||||
|
|
||||||
func NewPacket() Packet {
|
|
||||||
return Packet{
|
|
||||||
Opcode: -1,
|
|
||||||
Description: "Undefined",
|
|
||||||
When: noTime,
|
|
||||||
Payload: gapstring.GapString{},
|
|
||||||
Fields: map[string]string{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *StreamFactory) New(net, transport gopacket.Flow) tcpassembly.Stream {
|
func (f *StreamFactory) New(net, transport gopacket.Flow) tcpassembly.Stream {
|
||||||
stream := &Stream{
|
stream := &Stream{
|
||||||
Net: net,
|
Net: net,
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
conversation: make(chan Utterance, 100),
|
conversation: make(chan Utterance, 100),
|
||||||
}
|
}
|
||||||
goRoutines.Add(1)
|
StreamWG.Add(1)
|
||||||
go stream.run()
|
go stream.Run(StreamWG)
|
||||||
|
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
|
@ -140,29 +118,18 @@ func (stream *Stream) Read(length int) (Utterance, error) {
|
||||||
func (stream *Stream) Describe(pkt Packet) string {
|
func (stream *Stream) Describe(pkt Packet) string {
|
||||||
out := new(strings.Builder)
|
out := new(strings.Builder)
|
||||||
|
|
||||||
fmt.Fprintf(out, "Opcode %d: %s\n", pkt.Opcode, pkt.Description)
|
fmt.Fprintf(out, "%v:%v → %v:%v\n",
|
||||||
fmt.Fprintf(out, " %v:%v → %v:%v (%s)\n",
|
|
||||||
stream.Net.Src().String(), stream.Transport.Src().String(),
|
stream.Net.Src().String(), stream.Transport.Src().String(),
|
||||||
stream.Net.Dst().String(), stream.Transport.Dst().String(),
|
stream.Net.Dst().String(), stream.Transport.Dst().String()
|
||||||
pkt.When.UTC().Format(time.RFC3339Nano))
|
)
|
||||||
keys := make([]string, len(pkt.Fields))
|
out.writeString(pkt.Describe())
|
||||||
i := 0
|
|
||||||
for k := range(pkt.Fields) {
|
|
||||||
keys[i] = k
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
for _, k := range keys {
|
|
||||||
fmt.Fprintf(out, " %s: %s\n", k, pkt.Fields[k])
|
|
||||||
}
|
|
||||||
fmt.Fprint(out, pkt.Payload.Hexdump())
|
|
||||||
return out.String()
|
return out.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stream *Stream) run() {
|
func (stream *Stream) Run(wg sync.WaitGroup) {
|
||||||
defer goRoutines.Done()
|
defer wg.Done()
|
||||||
for {
|
for {
|
||||||
pkt, err := stream.buildPacket()
|
pkt, err := stream.BuildPacket()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
@ -174,7 +141,7 @@ func (stream *Stream) run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stream *Stream) buildPacket() (Packet, error) {
|
func (stream *Stream) BuildPacket() (Packet, error) {
|
||||||
pkt := NewPacket()
|
pkt := NewPacket()
|
||||||
|
|
||||||
utterance, err := stream.Read(-1)
|
utterance, err := stream.Read(-1)
|
||||||
|
@ -186,37 +153,3 @@ func (stream *Stream) buildPacket() (Packet, error) {
|
||||||
pkt.When = utterance.When
|
pkt.When = utterance.When
|
||||||
return pkt, nil
|
return pkt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
streamFactory := &StreamFactory{}
|
|
||||||
streamPool := tcpassembly.NewStreamPool(streamFactory)
|
|
||||||
assembler := tcpassembly.NewAssembler(streamPool)
|
|
||||||
|
|
||||||
for _, fn := range flag.Args() {
|
|
||||||
handle, err := pcap.OpenOffline(fn)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
|
|
||||||
packets := packetSource.Packets()
|
|
||||||
npackets := 0
|
|
||||||
for packet := range packets {
|
|
||||||
if packet == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP {
|
|
||||||
log.Println("Unusable packet")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tcp := packet.TransportLayer().(*layers.TCP)
|
|
||||||
assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp)
|
|
||||||
npackets += 1
|
|
||||||
}
|
|
||||||
log.Println("npackets", npackets)
|
|
||||||
}
|
|
||||||
assembler.FlushAll()
|
|
||||||
goRoutines.Wait()
|
|
||||||
}
|
|
Loading…
Reference in New Issue