aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-03-25 17:11:57 +0900
committerOphestra <cat@gensokyo.uk>2026-03-25 17:18:56 +0900
commitd62516ed1ee148c58eed60c4fa38c5dc2c3b9622 (patch)
tree2200fe0ff4451761deb5e44e9aa272dc6b368021 /internal
parentd2b635eb555d9c208028ea862604591c0973f268 (diff)
internal/netlink: enlarge recvfrom buffer
This also uses an array type for the buffer since its size now uses the hardcoded value found in the kernel. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal')
-rw-r--r--internal/netlink/netlink.go19
-rw-r--r--internal/netlink/netlink_test.go6
2 files changed, 13 insertions, 12 deletions
diff --git a/internal/netlink/netlink.go b/internal/netlink/netlink.go
index 406f567b..89f692a5 100644
--- a/internal/netlink/netlink.go
+++ b/internal/netlink/netlink.go
@@ -23,6 +23,9 @@ func getpid() uint32 {
return nlPid
}
+// net/netlink/af_netlink.c
+const maxRecvmsgLen = 32768
+
// A conn represents resources associated to a netlink socket.
type conn struct {
// AF_NETLINK socket.
@@ -37,8 +40,8 @@ type conn struct {
typ, flags uint16
// Outgoing position in buf.
pos int
- // A page holding incoming and outgoing messages.
- buf []byte
+ // Pages holding incoming and outgoing messages.
+ buf [maxRecvmsgLen]byte
// An instant some time after conn was established, but before the first
// I/O operation on f through raw. This serves as a cached deadline to
// cancel blocking I/O.
@@ -70,17 +73,19 @@ func dial(family int) (*conn, error) {
}
c.pos = syscall.NLMSG_HDRLEN
- c.buf = make([]byte, os.Getpagesize())
c.t = time.Now().UTC()
return &c, nil
}
+// ok returns whether conn is still open.
+func (c *conn) ok() bool { return c.family >= 0 }
+
// Close closes the underlying socket.
func (c *conn) Close() error {
- if c.buf == nil {
+ if !c.ok() {
return syscall.EINVAL
}
- c.buf = nil
+ c.family = -1
return c.f.Close()
}
@@ -245,7 +250,7 @@ type HandlerFunc func(resp []syscall.NetlinkMessage) error
// returned by f. An error of type [Complete] is returned as nil.
func (c *conn) receive(ctx context.Context, f HandlerFunc, flags int) error {
for {
- buf := c.buf
+ buf := c.buf[:]
if n, _, err := c.recvfrom(ctx, buf, flags); err != nil {
return err
} else if n < syscall.NLMSG_HDRLEN {
@@ -276,7 +281,7 @@ func (c *conn) receive(ctx context.Context, f HandlerFunc, flags int) error {
// Roundtrip sends the pending message and handles the reply.
func (c *conn) Roundtrip(ctx context.Context, f HandlerFunc) error {
- if c.buf == nil {
+ if !c.ok() {
return syscall.EINVAL
}
defer func() { c.seq++ }()
diff --git a/internal/netlink/netlink_test.go b/internal/netlink/netlink_test.go
index 0926e3bd..0b7df0f1 100644
--- a/internal/netlink/netlink_test.go
+++ b/internal/netlink/netlink_test.go
@@ -1,7 +1,6 @@
package netlink
import (
- "os"
"syscall"
"testing"
)
@@ -23,10 +22,7 @@ func checkPayload(t *testing.T, testCases []payloadTestCase) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
- c := conn{
- pos: syscall.NLMSG_HDRLEN,
- buf: make([]byte, os.Getpagesize()),
- }
+ c := conn{pos: syscall.NLMSG_HDRLEN}
tc.f(&c)
if got := c.pending(); string(got) != string(tc.want) {
t.Errorf("pending: %#v, want %#v", got, tc.want)