-
Notifications
You must be signed in to change notification settings - Fork 53
/
godpi.go
128 lines (117 loc) · 4.07 KB
/
godpi.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
// Package godpi provides the main API interface for utilizing the go-dpi library.
package godpi
import (
"time"
"github.com/google/gopacket"
"github.com/mushorg/go-dpi/modules/classifiers"
"github.com/mushorg/go-dpi/modules/ml"
"github.com/mushorg/go-dpi/modules/wrappers"
"github.com/mushorg/go-dpi/types"
)
var activatedModules []types.Module
var moduleList = []types.Module{
classifiers.NewClassifierModule(),
wrappers.NewWrapperModule(),
ml.NewLinearSVCModule(),
}
var cacheExpiration = 5 * time.Minute
// Initialize initializes the library and the selected modules.
func Initialize(opts ...Options) (errs []error) {
// apply all options to all modules
// check if the option will be applied in appropriate module inside Apply func
for _, opt := range opts {
if opt == nil {
continue
}
for _, m := range moduleList {
opt.Apply(m)
}
}
types.InitCache(cacheExpiration)
for _, module := range moduleList {
activated := false
for _, activeModule := range activatedModules {
if activeModule == module {
activated = true
break
}
}
if !activated {
err := module.Initialize()
if err == nil {
activatedModules = append(activatedModules, module)
} else {
errs = append(errs, err)
}
}
}
return
}
// Destroy frees all allocated resources and deactivates the active modules.
func Destroy() (errs []error) {
types.DestroyCache()
newActivatedModules := make([]types.Module, 0)
for _, module := range activatedModules {
err := module.Destroy()
if err != nil {
newActivatedModules = append(newActivatedModules, module)
errs = append(errs, err)
}
}
activatedModules = newActivatedModules
return
}
// SetModules selects the modules to be used by the library and their order.
// After calling this method, Initialize should be called, in order to
// initialize any new modules. If Initialize has already been called before,
// Destroy should be called as well before Initialize.
func SetModules(modules []types.Module) {
moduleList = make([]types.Module, len(modules))
copy(moduleList, modules)
}
// SetCacheExpiration sets how long after being inactive flows should be
// discarded from the flow tracker. If a negative value is passed, flows
// will never expire. By default, this value is 5 minutes.
// After calling this method, Initialize should be called, in order to
// initialize the cache. If Initialize has already been called before,
// Destroy should be called as well before Initialize.
func SetCacheExpiration(expiration time.Duration) {
cacheExpiration = expiration
}
// GetPacketFlow returns a Flow for the given packet. If another packet has
// been processed before that was part of the same communication flow, the same
// Flow will be returned, with the new packet added. Otherwise, a new Flow
// will be created with only this packet.
// The function also returns whether the returned Flow is a new one, and not
// one that already existed.
func GetPacketFlow(packet gopacket.Packet) (*types.Flow, bool) {
return types.GetFlowForPacket(packet)
}
// ClassifyFlow takes a Flow and tries to classify it with all of the activated
// modules in order, until one of them manages to classify it. It returns
// the detected protocol as well as the source that made the classification.
// If no classification is made, the protocol Unknown is returned.
func ClassifyFlow(flow *types.Flow) (result types.ClassificationResult) {
for _, module := range activatedModules {
resultTmp := module.ClassifyFlow(flow)
if resultTmp.Protocol != types.Unknown {
result = resultTmp
return
}
}
return
}
// ClassifyFlowAllModules takes a Flow and tries to classify it with all of the
// activated modules. However, as opposed to ClassifyFlow, it will return all
// of the results returned from the modules, not only the first successful one.
func ClassifyFlowAllModules(flow *types.Flow) (results []types.ClassificationResult) {
for _, module := range activatedModules {
resultsTmp := module.ClassifyFlowAll(flow)
for _, resultTmp := range resultsTmp {
if resultTmp.Protocol != types.Unknown {
results = append(results, resultTmp)
}
}
}
return
}