aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/google/gopacket/examples/httpassembly/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/google/gopacket/examples/httpassembly/main.go')
-rw-r--r--vendor/github.com/google/gopacket/examples/httpassembly/main.go127
1 files changed, 127 insertions, 0 deletions
diff --git a/vendor/github.com/google/gopacket/examples/httpassembly/main.go b/vendor/github.com/google/gopacket/examples/httpassembly/main.go
new file mode 100644
index 0000000..02af21e
--- /dev/null
+++ b/vendor/github.com/google/gopacket/examples/httpassembly/main.go
@@ -0,0 +1,127 @@
+// Copyright 2012 Google, Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree.
+
+// This binary provides sample code for using the gopacket TCP assembler and TCP
+// stream reader. It reads packets off the wire and reconstructs HTTP requests
+// it sees, logging them.
+package main
+
+import (
+ "bufio"
+ "flag"
+ "io"
+ "log"
+ "net/http"
+ "time"
+
+ "github.com/google/gopacket"
+ "github.com/google/gopacket/examples/util"
+ "github.com/google/gopacket/layers"
+ "github.com/google/gopacket/pcap"
+ "github.com/google/gopacket/tcpassembly"
+ "github.com/google/gopacket/tcpassembly/tcpreader"
+)
+
+var iface = flag.String("i", "eth0", "Interface to get packets from")
+var fname = flag.String("r", "", "Filename to read from, overrides -i")
+var snaplen = flag.Int("s", 1600, "SnapLen for pcap packet capture")
+var filter = flag.String("f", "tcp and dst port 80", "BPF filter for pcap")
+var logAllPackets = flag.Bool("v", false, "Logs every packet in great detail")
+
+// Build a simple HTTP request parser using tcpassembly.StreamFactory and tcpassembly.Stream interfaces
+
+// httpStreamFactory implements tcpassembly.StreamFactory
+type httpStreamFactory struct{}
+
+// httpStream will handle the actual decoding of http requests.
+type httpStream struct {
+ net, transport gopacket.Flow
+ r tcpreader.ReaderStream
+}
+
+func (h *httpStreamFactory) New(net, transport gopacket.Flow) tcpassembly.Stream {
+ hstream := &httpStream{
+ net: net,
+ transport: transport,
+ r: tcpreader.NewReaderStream(),
+ }
+ go hstream.run() // Important... we must guarantee that data from the reader stream is read.
+
+ // ReaderStream implements tcpassembly.Stream, so we can return a pointer to it.
+ return &hstream.r
+}
+
+func (h *httpStream) run() {
+ buf := bufio.NewReader(&h.r)
+ for {
+ req, err := http.ReadRequest(buf)
+ if err == io.EOF {
+ // We must read until we see an EOF... very important!
+ return
+ } else if err != nil {
+ log.Println("Error reading stream", h.net, h.transport, ":", err)
+ } else {
+ bodyBytes := tcpreader.DiscardBytesToEOF(req.Body)
+ req.Body.Close()
+ log.Println("Received request from stream", h.net, h.transport, ":", req, "with", bodyBytes, "bytes in request body")
+ }
+ }
+}
+
+func main() {
+ defer util.Run()()
+ var handle *pcap.Handle
+ var err error
+
+ // Set up pcap packet capture
+ if *fname != "" {
+ log.Printf("Reading from pcap dump %q", *fname)
+ handle, err = pcap.OpenOffline(*fname)
+ } else {
+ log.Printf("Starting capture on interface %q", *iface)
+ handle, err = pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever)
+ }
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := handle.SetBPFFilter(*filter); err != nil {
+ log.Fatal(err)
+ }
+
+ // Set up assembly
+ streamFactory := &httpStreamFactory{}
+ streamPool := tcpassembly.NewStreamPool(streamFactory)
+ assembler := tcpassembly.NewAssembler(streamPool)
+
+ log.Println("reading in packets")
+ // Read in packets, pass to assembler.
+ packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
+ packets := packetSource.Packets()
+ ticker := time.Tick(time.Minute)
+ for {
+ select {
+ case packet := <-packets:
+ // A nil packet indicates the end of a pcap file.
+ if packet == nil {
+ return
+ }
+ if *logAllPackets {
+ log.Println(packet)
+ }
+ 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)
+
+ case <-ticker:
+ // Every minute, flush connections that haven't seen activity in the past 2 minutes.
+ assembler.FlushOlderThan(time.Now().Add(time.Minute * -2))
+ }
+ }
+}