...
1 package netlink
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 "os"
8 "syscall"
9
10 "github.com/vishvananda/netlink/nl"
11 "github.com/vishvananda/netns"
12 "golang.org/x/sys/unix"
13 )
14
15 const CN_IDX_PROC = 0x1
16
17 const (
18 PROC_EVENT_NONE = 0x00000000
19 PROC_EVENT_FORK = 0x00000001
20 PROC_EVENT_EXEC = 0x00000002
21 PROC_EVENT_UID = 0x00000004
22 PROC_EVENT_GID = 0x00000040
23 PROC_EVENT_SID = 0x00000080
24 PROC_EVENT_PTRACE = 0x00000100
25 PROC_EVENT_COMM = 0x00000200
26 PROC_EVENT_COREDUMP = 0x40000000
27 PROC_EVENT_EXIT = 0x80000000
28 )
29
30 const (
31 CN_VAL_PROC = 0x1
32 PROC_CN_MCAST_LISTEN = 0x1
33 )
34
35 type ProcEventMsg interface {
36 Pid() uint32
37 Tgid() uint32
38 }
39
40 type ProcEventHeader struct {
41 What uint32
42 CPU uint32
43 Timestamp uint64
44 }
45
46 type ProcEvent struct {
47 ProcEventHeader
48 Msg ProcEventMsg
49 }
50
51 func (pe *ProcEvent) setHeader(h ProcEventHeader) {
52 pe.What = h.What
53 pe.CPU = h.CPU
54 pe.Timestamp = h.Timestamp
55 }
56
57 type ExitProcEvent struct {
58 ProcessPid uint32
59 ProcessTgid uint32
60 ExitCode uint32
61 ExitSignal uint32
62 ParentPid uint32
63 ParentTgid uint32
64 }
65
66 func (e *ExitProcEvent) Pid() uint32 {
67 return e.ProcessPid
68 }
69
70 func (e *ExitProcEvent) Tgid() uint32 {
71 return e.ProcessTgid
72 }
73
74 type ExecProcEvent struct {
75 ProcessPid uint32
76 ProcessTgid uint32
77 }
78
79 func (e *ExecProcEvent) Pid() uint32 {
80 return e.ProcessPid
81 }
82
83 func (e *ExecProcEvent) Tgid() uint32 {
84 return e.ProcessTgid
85 }
86
87 type ForkProcEvent struct {
88 ParentPid uint32
89 ParentTgid uint32
90 ChildPid uint32
91 ChildTgid uint32
92 }
93
94 func (e *ForkProcEvent) Pid() uint32 {
95 return e.ParentPid
96 }
97
98 func (e *ForkProcEvent) Tgid() uint32 {
99 return e.ParentTgid
100 }
101
102 type CommProcEvent struct {
103 ProcessPid uint32
104 ProcessTgid uint32
105 Comm [16]byte
106 }
107
108 func (e *CommProcEvent) Pid() uint32 {
109 return e.ProcessPid
110 }
111
112 func (e *CommProcEvent) Tgid() uint32 {
113 return e.ProcessTgid
114 }
115
116 func ProcEventMonitor(ch chan<- ProcEvent, done <-chan struct{}, errorChan chan<- error) error {
117 h, err := NewHandle()
118 if err != nil {
119 return err
120 }
121 defer h.Delete()
122
123 s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_CONNECTOR, CN_IDX_PROC)
124 if err != nil {
125 return err
126 }
127
128 var nlmsg nl.NetlinkRequest
129
130 nlmsg.Pid = uint32(os.Getpid())
131 nlmsg.Type = unix.NLMSG_DONE
132 nlmsg.Len = uint32(unix.SizeofNlMsghdr)
133
134 cm := nl.NewCnMsg(CN_IDX_PROC, CN_VAL_PROC, PROC_CN_MCAST_LISTEN)
135 nlmsg.AddData(cm)
136
137 s.Send(&nlmsg)
138
139 if done != nil {
140 go func() {
141 <-done
142 s.Close()
143 }()
144 }
145
146 go func() {
147 defer close(ch)
148 for {
149 msgs, from, err := s.Receive()
150 if err != nil {
151 errorChan <- err
152 return
153 }
154 if from.Pid != nl.PidKernel {
155 errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
156 return
157 }
158
159 for _, m := range msgs {
160 e := parseNetlinkMessage(m)
161 if e != nil {
162 ch <- *e
163 }
164 }
165
166 }
167 }()
168
169 return nil
170 }
171
172 func parseNetlinkMessage(m syscall.NetlinkMessage) *ProcEvent {
173 if m.Header.Type == unix.NLMSG_DONE {
174 buf := bytes.NewBuffer(m.Data)
175 msg := &nl.CnMsg{}
176 hdr := &ProcEventHeader{}
177 binary.Read(buf, nl.NativeEndian(), msg)
178 binary.Read(buf, nl.NativeEndian(), hdr)
179
180 pe := &ProcEvent{}
181 pe.setHeader(*hdr)
182 switch hdr.What {
183 case PROC_EVENT_EXIT:
184 event := &ExitProcEvent{}
185 binary.Read(buf, nl.NativeEndian(), event)
186 pe.Msg = event
187 return pe
188 case PROC_EVENT_FORK:
189 event := &ForkProcEvent{}
190 binary.Read(buf, nl.NativeEndian(), event)
191 pe.Msg = event
192 return pe
193 case PROC_EVENT_EXEC:
194 event := &ExecProcEvent{}
195 binary.Read(buf, nl.NativeEndian(), event)
196 pe.Msg = event
197 return pe
198 case PROC_EVENT_COMM:
199 event := &CommProcEvent{}
200 binary.Read(buf, nl.NativeEndian(), event)
201 pe.Msg = event
202 return pe
203 }
204 return nil
205 }
206
207 return nil
208 }
209
View as plain text