forked from dropbox/goebpf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprogram_socket_filter.go
102 lines (81 loc) · 2.38 KB
/
program_socket_filter.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
// Copyright (c) 2019 Dropbox, Inc.
// Full license can be found in the LICENSE file.
package goebpf
//#include "bpf_helpers.h"
import "C"
import (
"fmt"
"golang.org/x/sys/unix"
)
// SocketFilterResult is eBPF program return code enum
type SocketFilterResult int
type SocketFilterAttachType int
const (
SocketFilterDeny SocketFilterResult = C.SOCKET_FILTER_DENY
SocketFilterAllow SocketFilterResult = C.SOCKET_FILTER_ALLOW
SocketAttachTypeFilter SocketFilterAttachType = SO_ATTACH_BPF
SocketAttachTypeReusePort SocketFilterAttachType = SO_ATTACH_REUSEPORT_EBPF
// Constants from Linux kernel, they dont' present in "golang.org/x/sys/unix"
SO_ATTACH_BPF = 50
SO_ATTACH_REUSEPORT_EBPF = 52
SO_DETACH_FILTER = 27
)
// SocketFilterAttachParams is accepted as argument to Program.Attach()
type SocketFilterAttachParams struct {
// SocketFd is socket file descriptor returned by unix.Socket(...)
SocketFd int
// AttachType is one of SocketAttachTypeFilter / SocketAttachTypeReusePort
// depending on use case
AttachType SocketFilterAttachType
}
func (t SocketFilterResult) String() string {
switch t {
case SocketFilterDeny:
return "Deny"
case SocketFilterAllow:
return "Allow"
}
return "UNKNOWN"
}
func (t SocketFilterAttachType) String() string {
switch t {
case SocketAttachTypeFilter:
return "AttachTypeFilter"
case SocketAttachTypeReusePort:
return "AttachTypeReusePort"
}
return "UNKNOWN"
}
type socketFilterProgram struct {
BaseProgram
sockFd int
}
func newSocketFilterProgram(name, license string, bytecode []byte) Program {
return &socketFilterProgram{
BaseProgram: BaseProgram{
name: name,
license: license,
bytecode: bytecode,
programType: ProgramTypeSocketFilter,
},
}
}
func (p *socketFilterProgram) Attach(data interface{}) error {
params, ok := data.(SocketFilterAttachParams)
if !ok {
return fmt.Errorf("SocketFilterAttachParams expected, got %T", data)
}
p.sockFd = params.SocketFd
err := unix.SetsockoptInt(p.sockFd, unix.SOL_SOCKET, int(params.AttachType), p.GetFd())
if err != nil {
return fmt.Errorf("SetSockOpt with %v failed: %v", params.AttachType, err)
}
return nil
}
func (p *socketFilterProgram) Detach() error {
err := unix.SetsockoptInt(p.sockFd, unix.SOL_SOCKET, SO_DETACH_FILTER, 0)
if err != nil {
return fmt.Errorf("SetSockOpt with SO_DETACH_FILTER failed: %v", err)
}
return nil
}