forked from aregm/nff-go
/
handlers.go
140 lines (123 loc) · 3.24 KB
/
handlers.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"bytes"
"encoding/binary"
"fmt"
"hash/fnv"
"sync/atomic"
"github.com/bnordbo/nff-go/examples/dpi/pattern"
"github.com/bnordbo/nff-go/flow"
"github.com/bnordbo/nff-go/packet"
"github.com/bnordbo/nff-go/types"
)
type localCounters struct {
handlerID uint
allowedCounterPtr *uint64
readCounterPtr *uint64
blockedCounterPtr *uint64
}
// Create new counters for new handler
func (lc localCounters) Copy() interface{} {
var newlc localCounters
// Clones has the same id
id := lc.handlerID
newlc.handlerID = id
newlc.allowedCounterPtr = &allowedPktsCount[id]
newlc.readCounterPtr = &readPktsCount[id]
newlc.blockedCounterPtr = &blockedPktsCount[id]
return newlc
}
func (lc localCounters) Delete() {
}
func filterByRegexp(pkt *packet.Packet, context flow.UserContext) bool {
cnt := context.(localCounters)
numRead := cnt.readCounterPtr
numAllowed := cnt.allowedCounterPtr
numBlocked := cnt.blockedCounterPtr
atomic.AddUint64(numRead, 1)
data, ok := pkt.GetPacketPayload()
if !ok {
fmt.Println("WARNING: cannot get payload, drop packet")
return false
}
accept := false
block := false
for _, p := range patterns {
result := p.Re.Match(data)
if !result {
continue
}
if p.Allow {
accept = true
} else {
accept = false
block = true
}
}
if accept {
atomic.AddUint64(numAllowed, 1)
}
if !accept && block {
atomic.AddUint64(numBlocked, 1)
}
return accept
}
func splitBy5Tuple(pkt *packet.Packet, context flow.UserContext) uint {
hash := fnv.New64a()
ip4, ip6, _ := pkt.ParseAllKnownL3()
if ip4 != nil {
pkt.ParseL4ForIPv4()
} else if ip6 != nil {
pkt.ParseL4ForIPv6()
} else {
// Other protocols not supported
return pattern.TotalNumFlows - 1
}
if ip4 != nil {
if ip4.NextProtoID != types.TCPNumber && ip4.NextProtoID != types.UDPNumber {
return pattern.TotalNumFlows - 1
}
hash.Write([]byte{ip4.NextProtoID})
buf := new(bytes.Buffer)
flow.CheckFatal(binary.Write(buf, binary.LittleEndian, ip4.SrcAddr))
hash.Write(buf.Bytes())
flow.CheckFatal(binary.Write(buf, binary.LittleEndian, ip4.DstAddr))
hash.Write(buf.Bytes())
} else if ip6 != nil {
if ip6.Proto != types.TCPNumber && ip6.Proto != types.UDPNumber {
return pattern.TotalNumFlows - 1
}
flow.CheckFatal(binary.Write(hash, binary.BigEndian, ip6.Proto))
hash.Write(ip6.SrcAddr[:])
hash.Write(ip6.DstAddr[:])
}
binary.Write(hash, binary.BigEndian, pkt.GetTCPNoCheck().SrcPort)
binary.Write(hash, binary.BigEndian, pkt.GetTCPNoCheck().DstPort)
return uint(hash.Sum64()) % pattern.NumFlows
}
func onMatch(id uint, from, to uint64, flags uint, context interface{}) error {
isMatch := context.(*bool)
// Report outside that match was found
*isMatch = true
return nil
}
func filterByHS(pkt *packet.Packet, context flow.UserContext) bool {
cnt := context.(localCounters)
hid := cnt.handlerID
numRead := cnt.readCounterPtr
numAllowed := cnt.allowedCounterPtr
atomic.AddUint64(numRead, 1)
data, ok := pkt.GetPacketPayload()
if !ok {
fmt.Println("WARNING: cannot get payload, drop packet")
return false
}
result := new(bool)
if err := hsdb.Bdb.Scan(data, hsdb.Scratches[hid], onMatchCallback, result); err != nil {
return false
}
if *result {
atomic.AddUint64(numAllowed, 1)
}
return *result
}