added support for string type
[govpp.git] / vendor / github.com / google / gopacket / examples / httpassembly / main.go
1 // Copyright 2012 Google, Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree.
6
7 // This binary provides sample code for using the gopacket TCP assembler and TCP
8 // stream reader.  It reads packets off the wire and reconstructs HTTP requests
9 // it sees, logging them.
10 package main
11
12 import (
13         "bufio"
14         "flag"
15         "io"
16         "log"
17         "net/http"
18         "time"
19
20         "github.com/google/gopacket"
21         "github.com/google/gopacket/examples/util"
22         "github.com/google/gopacket/layers"
23         "github.com/google/gopacket/pcap"
24         "github.com/google/gopacket/tcpassembly"
25         "github.com/google/gopacket/tcpassembly/tcpreader"
26 )
27
28 var iface = flag.String("i", "eth0", "Interface to get packets from")
29 var fname = flag.String("r", "", "Filename to read from, overrides -i")
30 var snaplen = flag.Int("s", 1600, "SnapLen for pcap packet capture")
31 var filter = flag.String("f", "tcp and dst port 80", "BPF filter for pcap")
32 var logAllPackets = flag.Bool("v", false, "Logs every packet in great detail")
33
34 // Build a simple HTTP request parser using tcpassembly.StreamFactory and tcpassembly.Stream interfaces
35
36 // httpStreamFactory implements tcpassembly.StreamFactory
37 type httpStreamFactory struct{}
38
39 // httpStream will handle the actual decoding of http requests.
40 type httpStream struct {
41         net, transport gopacket.Flow
42         r              tcpreader.ReaderStream
43 }
44
45 func (h *httpStreamFactory) New(net, transport gopacket.Flow) tcpassembly.Stream {
46         hstream := &httpStream{
47                 net:       net,
48                 transport: transport,
49                 r:         tcpreader.NewReaderStream(),
50         }
51         go hstream.run() // Important... we must guarantee that data from the reader stream is read.
52
53         // ReaderStream implements tcpassembly.Stream, so we can return a pointer to it.
54         return &hstream.r
55 }
56
57 func (h *httpStream) run() {
58         buf := bufio.NewReader(&h.r)
59         for {
60                 req, err := http.ReadRequest(buf)
61                 if err == io.EOF {
62                         // We must read until we see an EOF... very important!
63                         return
64                 } else if err != nil {
65                         log.Println("Error reading stream", h.net, h.transport, ":", err)
66                 } else {
67                         bodyBytes := tcpreader.DiscardBytesToEOF(req.Body)
68                         req.Body.Close()
69                         log.Println("Received request from stream", h.net, h.transport, ":", req, "with", bodyBytes, "bytes in request body")
70                 }
71         }
72 }
73
74 func main() {
75         defer util.Run()()
76         var handle *pcap.Handle
77         var err error
78
79         // Set up pcap packet capture
80         if *fname != "" {
81                 log.Printf("Reading from pcap dump %q", *fname)
82                 handle, err = pcap.OpenOffline(*fname)
83         } else {
84                 log.Printf("Starting capture on interface %q", *iface)
85                 handle, err = pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever)
86         }
87         if err != nil {
88                 log.Fatal(err)
89         }
90
91         if err := handle.SetBPFFilter(*filter); err != nil {
92                 log.Fatal(err)
93         }
94
95         // Set up assembly
96         streamFactory := &httpStreamFactory{}
97         streamPool := tcpassembly.NewStreamPool(streamFactory)
98         assembler := tcpassembly.NewAssembler(streamPool)
99
100         log.Println("reading in packets")
101         // Read in packets, pass to assembler.
102         packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
103         packets := packetSource.Packets()
104         ticker := time.Tick(time.Minute)
105         for {
106                 select {
107                 case packet := <-packets:
108                         // A nil packet indicates the end of a pcap file.
109                         if packet == nil {
110                                 return
111                         }
112                         if *logAllPackets {
113                                 log.Println(packet)
114                         }
115                         if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP {
116                                 log.Println("Unusable packet")
117                                 continue
118                         }
119                         tcp := packet.TransportLayer().(*layers.TCP)
120                         assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp)
121
122                 case <-ticker:
123                         // Every minute, flush connections that haven't seen activity in the past 2 minutes.
124                         assembler.FlushOlderThan(time.Now().Add(time.Minute * -2))
125                 }
126         }
127 }