Repository navigation
Expand file tree
/
Copy pathmain.go
More file actions
120 lines (99 loc) · 2.68 KB
/
Copy pathmain.go
File metadata and controls
120 lines (99 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package main
import (
"flag"
"fmt"
"os"
"strings"
"sync"
"github.com/golang/glog"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/tcpassembly"
)
var (
pcapFile = flag.String("f", "", "pcap file from tcpdump")
pcapInterface = flag.String("i", "all", "interface to read packets from (\"en4\", \"eth0\", ..)")
snapLen = flag.Int("s", 65535, "interface snap length")
promiscOff = flag.Bool("p", false, "disable promiscuous mode")
)
const usageMessage = `
Usage: rtmp_debug [-i <interface>] [<bpf expression>]
Display decoded RTMP commands from pcap wire data.
Options:
`
func usage() {
fmt.Fprintf(os.Stderr, usageMessage)
flag.PrintDefaults()
}
func printResults(done chan struct{}, results chan string) {
for x := range results {
if len(x) > 0 {
fmt.Printf("%v\n", x)
}
}
close(done)
}
func openPcap() (h *pcap.Handle, err error) {
if len(*pcapFile) > 0 {
h, err = pcap.OpenOffline(*pcapFile)
if err != nil {
glog.Errorf("unable to open \"%s\"", *pcapFile)
}
return
}
h, err = pcap.OpenLive(*pcapInterface,
int32(*snapLen),
!*promiscOff,
pcap.BlockForever)
if err != nil {
glog.Errorf("unable to open interface \"%s\"", *pcapInterface)
}
return
}
func main() {
flag.Usage = usage
flag.Parse()
pcapfile, err := openPcap()
if err != nil {
glog.Fatalf("%v", err)
}
bpf := strings.Join(flag.Args(), " ")
if err = pcapfile.SetBPFFilter(bpf); err != nil {
glog.Fatalf("unable to set BPF: %v", err)
}
// "Pass this stream factory to an tcpassembly.StreamPool ,
// start up an tcpassembly.Assembler, and you're good to go!"
done := make(chan struct{})
results := make(chan string)
go printResults(done, results)
wg := &sync.WaitGroup{}
rtmp := &rtmpStreamWrapper{wg, results}
pool := tcpassembly.NewStreamPool(rtmp)
asm := tcpassembly.NewAssembler(pool)
asm.MaxBufferedPagesTotal = 4096 // limit gopacket memory allocation
source := gopacket.NewPacketSource(pcapfile, pcapfile.LinkType())
var pkt gopacket.Packet
for {
pkt, err = source.NextPacket()
if pkt == nil || err != nil {
break
}
if tcp := pkt.Layer(layers.LayerTypeTCP); tcp != nil {
asm.AssembleWithTimestamp(
pkt.TransportLayer().TransportFlow(),
tcp.(*layers.TCP),
pkt.Metadata().Timestamp)
}
}
if err != nil && !errIsEOF(err) {
glog.Errorf("packet: %v", err)
if err = pcapfile.Error(); err != nil {
glog.Errorf("pcap: %v", err)
}
}
asm.FlushAll() // abort any in progress tcp connections
wg.Wait() // tcp streams have finished processing
close(results) // no more results will be generated by tcp streams
<-done // printResults has finished
}