-
Notifications
You must be signed in to change notification settings - Fork 0
/
tcpacct.go
115 lines (99 loc) · 2.22 KB
/
tcpacct.go
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
package main
import (
"fmt"
"log"
"net"
"os"
"os/signal"
"strings"
"syscall"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
type Tally struct {
SrcIP net.IP
DstIP net.IP
Packets uint64
Bytes uint64
}
func main() {
termCh := make(chan struct{})
go func(termCh chan<- struct{}) {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs
close(termCh)
}(termCh)
// A map of flows to Tally struct pointers.
flows := make(map[gopacket.Flow]*Tally)
// The first arg is the capture device.
handle, err := pcap.OpenLive(os.Args[1], 1600, true, pcap.BlockForever)
if err != nil {
log.Fatal(err)
}
// Set default BPF filter to "ip" (IPv4), but override with command args.
bpfFilter := "ip"
if len(os.Args) > 2 {
bpfFilter = strings.Join(os.Args[2:], " ")
}
log.Printf("BPF filter: %s", bpfFilter)
if err := handle.SetBPFFilter(bpfFilter); err != nil {
log.Fatal(err)
}
// Set up the packet source and channel.
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
packetCh := packetSource.Packets()
OuterLoop:
for {
select {
case <-termCh:
log.Print("exiting due to termination signal")
break OuterLoop
case packet := <-packetCh:
ip4Layer := packet.NetworkLayer()
if ip4Layer == nil {
break
}
if ip4Layer.LayerType() != layers.LayerTypeIPv4 {
break
}
ip4Packet := ip4Layer.(*layers.IPv4)
nFlow := ip4Layer.NetworkFlow()
if v, found := flows[nFlow]; found {
v.Packets++
v.Bytes += uint64(ip4Packet.Length)
} else {
flows[nFlow] = &Tally{
SrcIP: ip4Packet.SrcIP,
DstIP: ip4Packet.DstIP,
Packets: 1,
Bytes: uint64(ip4Packet.Length),
}
}
}
}
// Totals for packet and byte counters.
totalPackets := uint64(0)
totalBytes := uint64(0)
fmt.Printf("src_ip\tdst_ip\tpackets\tbytes\n")
for _, flow := range flows {
fmt.Printf(
"%s\t%s\t%d\t%d\n",
flow.SrcIP.String(),
flow.DstIP.String(),
flow.Packets,
flow.Bytes,
)
totalPackets += flow.Packets
totalBytes += flow.Bytes
}
// Print the totals as well.
fmt.Printf(
"%s\t%s\t%d\t%d\n",
"0.0.0.0",
"0.0.0.0",
totalPackets,
totalBytes,
)
}