forked from bisrael8191/sniffer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
afpacket.go
80 lines (66 loc) · 2 KB
/
afpacket.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
package main
import (
"fmt"
"os"
"github.com/google/gopacket"
"github.com/google/gopacket/afpacket"
)
// afpacket version of the gopacket library
type AfpacketSniffer struct {
handle *afpacket.TPacket
}
// Computes the block_size and the num_blocks in such a way that the
// allocated mmap buffer is close to but smaller than target_size_mb.
// The restriction is that the block_size must be divisible by both the
// frame size and page size. From PacketBeat.
func afpacketComputeSize(target_size_mb int, snaplen int, page_size int) (
frame_size int, block_size int, num_blocks int, err error) {
if snaplen < page_size {
frame_size = page_size / (page_size / snaplen)
} else {
frame_size = (snaplen/page_size + 1) * page_size
}
// 128 is the default from the gopacket library so just use that
block_size = frame_size * 128
num_blocks = (target_size_mb * 1024 * 1024) / block_size
if num_blocks == 0 {
return 0, 0, 0, fmt.Errorf("Buffer size too small")
}
return frame_size, block_size, num_blocks, nil
}
func (s *AfpacketSniffer) Open(config *Config) error {
// Capture settings
const (
// MMap buffer size
buffer_mb int = 24
// Max packet length
snaplen int = 65536
// Set the interface in promiscuous mode
promisc bool = true
)
frame_size, block_size, num_blocks, err := afpacketComputeSize(
buffer_mb,
snaplen,
os.Getpagesize())
if err != nil {
return fmt.Errorf("Error calculating afpacket size: %s", err)
}
// Configure the afpacket ring and bind it to the interface
var tPacket *afpacket.TPacket
tPacket, err = afpacket.NewTPacket(
afpacket.OptInterface(*iface),
afpacket.OptFrameSize(frame_size),
afpacket.OptBlockSize(block_size),
afpacket.OptNumBlocks(num_blocks))
if err != nil {
fmt.Errorf("Error opening afpacket interface: %s", err)
}
s.handle = tPacket
return nil
}
func (s *AfpacketSniffer) Close() {
s.handle.Close()
}
func (s *AfpacketSniffer) ReadPacket() (data []byte, ci gopacket.CaptureInfo, err error) {
return s.handle.ZeroCopyReadPacketData()
}