File: netfilter.go

package info (click to toggle)
golang-github-cilium-ebpf 0.17.3%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 4,684 kB
  • sloc: ansic: 1,259; makefile: 127; python: 113; awk: 29; sh: 24
file content (90 lines) | stat: -rw-r--r-- 2,127 bytes parent folder | download
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
package link

import (
	"fmt"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/internal/sys"
)

const NetfilterIPDefrag NetfilterAttachFlags = 0 // Enable IP packet defragmentation

type NetfilterAttachFlags uint32

type NetfilterOptions struct {
	// Program must be a netfilter BPF program.
	Program *ebpf.Program
	// The protocol family.
	ProtocolFamily uint32
	// The number of the hook you are interested in.
	HookNumber uint32
	// Priority within hook
	Priority int32
	// Extra link flags
	Flags uint32
	// Netfilter flags
	NetfilterFlags NetfilterAttachFlags
}

type netfilterLink struct {
	RawLink
}

// AttachNetfilter links a netfilter BPF program to a netfilter hook.
func AttachNetfilter(opts NetfilterOptions) (Link, error) {
	if opts.Program == nil {
		return nil, fmt.Errorf("netfilter program is nil")
	}

	if t := opts.Program.Type(); t != ebpf.Netfilter {
		return nil, fmt.Errorf("invalid program type %s, expected netfilter", t)
	}

	progFd := opts.Program.FD()
	if progFd < 0 {
		return nil, fmt.Errorf("invalid program: %s", sys.ErrClosedFd)
	}

	attr := sys.LinkCreateNetfilterAttr{
		ProgFd:         uint32(opts.Program.FD()),
		AttachType:     sys.BPF_NETFILTER,
		Flags:          opts.Flags,
		Pf:             uint32(opts.ProtocolFamily),
		Hooknum:        uint32(opts.HookNumber),
		Priority:       opts.Priority,
		NetfilterFlags: uint32(opts.NetfilterFlags),
	}

	fd, err := sys.LinkCreateNetfilter(&attr)
	if err != nil {
		return nil, fmt.Errorf("attach netfilter link: %w", err)
	}

	return &netfilterLink{RawLink{fd, ""}}, nil
}

func (*netfilterLink) Update(_ *ebpf.Program) error {
	return fmt.Errorf("netfilter update: %w", ErrNotSupported)
}

func (nf *netfilterLink) Info() (*Info, error) {
	var info sys.NetfilterLinkInfo
	if err := sys.ObjInfo(nf.fd, &info); err != nil {
		return nil, fmt.Errorf("netfilter link info: %s", err)
	}
	extra := &NetfilterInfo{
		Pf:       info.Pf,
		Hooknum:  info.Hooknum,
		Priority: info.Priority,
		Flags:    info.Flags,
	}

	return &Info{
		info.Type,
		info.Id,
		ebpf.ProgramID(info.ProgId),
		extra,
	}, nil
}

var _ Link = (*netfilterLink)(nil)