internal/netlink: export generic connection
All checks were successful
Test / Create distribution (push) Successful in 1m26s
Test / Sandbox (push) Successful in 3m33s
Test / Hakurei (push) Successful in 4m53s
Test / ShareFS (push) Successful in 4m50s
Test / Sandbox (race detector) (push) Successful in 5m59s
Test / Hakurei (race detector) (push) Successful in 7m3s
Test / Flake checks (push) Successful in 1m25s
All checks were successful
Test / Create distribution (push) Successful in 1m26s
Test / Sandbox (push) Successful in 3m33s
Test / Hakurei (push) Successful in 4m53s
Test / ShareFS (push) Successful in 4m50s
Test / Sandbox (race detector) (push) Successful in 5m59s
Test / Hakurei (race detector) (push) Successful in 7m3s
Test / Flake checks (push) Successful in 1m25s
This enables abstractions around some families to be implemented in a separate package. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -18,8 +18,8 @@ const (
|
||||
stateOpen uint32 = 1 << iota
|
||||
)
|
||||
|
||||
// A conn represents resources associated to a netlink socket.
|
||||
type conn struct {
|
||||
// A Conn represents resources associated to a netlink socket.
|
||||
type Conn struct {
|
||||
// AF_NETLINK socket.
|
||||
f *os.File
|
||||
// For using runtime polling via f.
|
||||
@@ -44,9 +44,10 @@ type conn struct {
|
||||
t time.Time
|
||||
}
|
||||
|
||||
// dial returns the address of a newly connected conn of specified family.
|
||||
func dial(family int, groups uint32) (*conn, error) {
|
||||
var c conn
|
||||
// Dial returns the address of a newly connected generic netlink connection of
|
||||
// specified family and groups.
|
||||
func Dial(family int, groups uint32) (*Conn, error) {
|
||||
var c Conn
|
||||
if fd, err := syscall.Socket(
|
||||
syscall.AF_NETLINK,
|
||||
syscall.SOCK_RAW|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC,
|
||||
@@ -89,10 +90,10 @@ func dial(family int, groups uint32) (*conn, error) {
|
||||
}
|
||||
|
||||
// ok returns whether conn is still open.
|
||||
func (c *conn) ok() bool { return c.state&stateOpen != 0 }
|
||||
func (c *Conn) ok() bool { return c.state&stateOpen != 0 }
|
||||
|
||||
// Close closes the underlying socket.
|
||||
func (c *conn) Close() error {
|
||||
func (c *Conn) Close() error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
@@ -100,8 +101,8 @@ func (c *conn) Close() error {
|
||||
return c.f.Close()
|
||||
}
|
||||
|
||||
// recvfrom wraps recv(2) with nonblocking behaviour via the runtime network poller.
|
||||
func (c *conn) recvfrom(
|
||||
// Recvfrom wraps recv(2) with nonblocking behaviour via the runtime network poller.
|
||||
func (c *Conn) Recvfrom(
|
||||
ctx context.Context,
|
||||
p []byte,
|
||||
flags int,
|
||||
@@ -125,6 +126,7 @@ func (c *conn) recvfrom(
|
||||
} else {
|
||||
err = rcErr
|
||||
}
|
||||
return
|
||||
|
||||
case <-ctx.Done():
|
||||
cancelErr := c.f.SetReadDeadline(c.t)
|
||||
@@ -136,11 +138,10 @@ func (c *conn) recvfrom(
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// sendto wraps send(2) with nonblocking behaviour via the runtime network poller.
|
||||
func (c *conn) sendto(
|
||||
// Sendto wraps send(2) with nonblocking behaviour via the runtime network poller.
|
||||
func (c *Conn) sendto(
|
||||
ctx context.Context,
|
||||
p []byte,
|
||||
flags int,
|
||||
@@ -165,6 +166,7 @@ func (c *conn) sendto(
|
||||
} else {
|
||||
err = rcErr
|
||||
}
|
||||
return
|
||||
|
||||
case <-ctx.Done():
|
||||
cancelErr := c.f.SetWriteDeadline(c.t)
|
||||
@@ -176,7 +178,6 @@ func (c *conn) sendto(
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Msg is type constraint for types sent over the wire via netlink.
|
||||
@@ -198,7 +199,7 @@ func As[M Msg](data []byte) *M {
|
||||
}
|
||||
|
||||
// add queues a value to be sent by conn.
|
||||
func add[M Msg](c *conn, p *M) bool {
|
||||
func add[M Msg](c *Conn, p *M) bool {
|
||||
pos := c.pos
|
||||
c.pos += int(unsafe.Sizeof(*p))
|
||||
if c.pos > len(c.buf) {
|
||||
@@ -233,7 +234,7 @@ func (e *InconsistentError) Error() string {
|
||||
}
|
||||
|
||||
// checkReply checks the message header of a reply from the kernel.
|
||||
func (c *conn) checkReply(header *syscall.NlMsghdr) error {
|
||||
func (c *Conn) checkReply(header *syscall.NlMsghdr) error {
|
||||
if header.Seq != c.seq || header.Pid != c.port {
|
||||
return &InconsistentError{*header, c.seq, c.port}
|
||||
}
|
||||
@@ -241,7 +242,7 @@ func (c *conn) checkReply(header *syscall.NlMsghdr) error {
|
||||
}
|
||||
|
||||
// pending returns the valid slice of buf and initialises pos.
|
||||
func (c *conn) pending() []byte {
|
||||
func (c *Conn) pending() []byte {
|
||||
buf := c.buf[:c.pos]
|
||||
c.pos = syscall.NLMSG_HDRLEN
|
||||
|
||||
@@ -267,10 +268,10 @@ type HandlerFunc func(resp []syscall.NetlinkMessage) error
|
||||
|
||||
// receive receives from a socket with specified flags until a non-nil error is
|
||||
// returned by f. An error of type [Complete] is returned as nil.
|
||||
func (c *conn) receive(ctx context.Context, f HandlerFunc, flags int) error {
|
||||
func (c *Conn) receive(ctx context.Context, f HandlerFunc, flags int) error {
|
||||
for {
|
||||
buf := c.buf[:]
|
||||
if n, _, err := c.recvfrom(ctx, buf, flags); err != nil {
|
||||
if n, _, err := c.Recvfrom(ctx, buf, flags); err != nil {
|
||||
return err
|
||||
} else if n < syscall.NLMSG_HDRLEN {
|
||||
return syscall.EBADE
|
||||
@@ -293,7 +294,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 {
|
||||
func (c *Conn) Roundtrip(ctx context.Context, f HandlerFunc) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user