-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathsuricata.go
108 lines (97 loc) · 2.67 KB
/
suricata.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
package main
import (
"time"
"net"
"io"
"encoding/json"
"errors"
)
const SURICATA = "suricata"
func init() {
parser.Add(SURICATA, "/usr/local/var/run/suricata/suricata-command.socket", "dump Suricata's performance counters")
}
type Suricata struct {
SocketName string
}
func (self *Suricata) Prefix() string {
return SURICATA
}
func (self *Suricata) Collect(c *MetricsCollection) (e error) {
name := "testTag"
tags := map[string]string{"name": name}
c.AddWithTags("suricata.test", 1024, tags)
r,e := getCountersFromSocket(self.SocketName)
if e != nil {
return
}
for k,v := range r {
for kk,vv := range v {
// add thread name as tag
if k != "Detect" && k != "FlowManagerThread" {
tags := map[string]string{"thread": k}
c.AddWithTags(kk, vv, tags)
} else {
c.Add(kk, vv)
}
}
}
return
}
type Response struct {
ReturnCode string `json:"return"`
Message map[string]map[string]int64 `json:"message"`
}
func getCountersFromSocket(socketName string) (counts map[string]map[string]int64, err error) {
conn, err := net.Dial("unix", socketName)
if err != nil {
return nil, err
}
defer conn.Close()
// see https://github.com/inliniac/suricata/blob/94571c5dd28858ff68c44b648fd41c5d87c0e28d/src/unix-manager.c#L288
_, err = conn.Write([]byte("{\"version\": \"0.1\"}"))
if err != nil {
return nil, errors.New("can not send version :: "+err.Error())
}
time.Sleep(100 * time.Millisecond)
var buf [128]byte
_, err = conn.Read(buf[0:])
if err != nil {
// see https://github.com/inliniac/suricata/blob/94571c5dd28858ff68c44b648fd41c5d87c0e28d/src/unix-manager.c#L319
return nil, errors.New("got kick on version :: "+err.Error())
}
_, err = conn.Write([]byte("{\"command\": \"dump-counters\"}"))
if err != nil {
return nil, errors.New("can not send command :: "+err.Error())
}
time.Sleep(100 * time.Millisecond)
data := ""
// read anser for command
// see https://github.com/inliniac/suricata/blob/672049632431bb695f56798c9c5f196afcf2fb27/scripts/suricatasc/src/suricatasc.py#L83
for i := 0; i < 16; i++ {
var buf2 [4096]byte
result2, err := conn.Read(buf2[0:])
if err != nil {
if err != io.EOF {
return nil, err
}
}
data = data + string(buf2[:result2])
var isJson Response
jerr := json.Unmarshal([]byte(data), &isJson)
if jerr == nil {
if isJson.ReturnCode == "OK" {
return isJson.Message, nil
} else {
return nil, errors.New(isJson.ReturnCode)
}
} else {
expect := "unexpected end of JSON input"
if jerr.Error() != expect {
// is json but not our counters
return nil, errors.New(data)
}
}
time.Sleep(10 * time.Millisecond)
}
return nil, errors.New("max limit for loop")
}