diff --git a/go.mod b/go.mod index 5dc25ad309..6ebf8462e0 100644 --- a/go.mod +++ b/go.mod @@ -60,7 +60,7 @@ require ( github.com/hashicorp/memberlist v0.7.0 github.com/in-toto/in-toto-golang v0.11.0 github.com/ishidawataru/sctp v0.0.0-20251114114122-19ddcbc6aae2 - github.com/mdlayher/socket v0.7.0 + github.com/mdlayher/socket v0.8.0 github.com/miekg/dns v1.1.73 github.com/mistifyio/go-zfs/v4 v4.0.0 github.com/mitchellh/copystructure v1.2.0 diff --git a/go.sum b/go.sum index d20c4324db..54502c0772 100644 --- a/go.sum +++ b/go.sum @@ -451,8 +451,8 @@ github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= -github.com/mdlayher/socket v0.7.0 h1:qVREPVwtUMg17pwvveQxpurq0PVisMxi3FGgpsorMYQ= -github.com/mdlayher/socket v0.7.0/go.mod h1:f7iKql2EK/rfsWYDKofKjk2Ig7I+6HQWdMIdn1tO4A4= +github.com/mdlayher/socket v0.8.0 h1:1lIVvHAs3sT623kPkPDa+I0nLVusskwnpWzp6ZUcNyc= +github.com/mdlayher/socket v0.8.0/go.mod h1:EhNb63aXqexVoTJDblxvDOSuIGIJinC4H5ZktnaJ6Rk= github.com/mdlayher/vsock v1.3.0 h1:bqQfZ1OznI03y6YiXp2sze05RVdzLn/zsfjnjd4+ivI= github.com/mdlayher/vsock v1.3.0/go.mod h1:WsuksavOvwCnV5UqGHUkvAvCy+Dqy81y4goKQTzxxNY= github.com/miekg/dns v1.1.73 h1:uhT8nJxmTrPJYClxVxTCX+CVn6qnzSiybRk72Z6DgrE= diff --git a/vendor/github.com/mdlayher/socket/CHANGELOG.md b/vendor/github.com/mdlayher/socket/CHANGELOG.md index b3b322e7c6..e80fa37a4d 100644 --- a/vendor/github.com/mdlayher/socket/CHANGELOG.md +++ b/vendor/github.com/mdlayher/socket/CHANGELOG.md @@ -1,5 +1,16 @@ # CHANGELOG +## v0.8.0 + +- [New API]: add `Conn.ReadFunc` and `Conn.WriteFunc` to execute an arbitrary + system call against the underlying file descriptor with runtime network + poller integration, context cancelation, and deadline support. These are the + building blocks used by the other `Conn` read and write methods, exported for + system calls which have no wrapper in this package or in `x/sys/unix`. +- [New API]: add `Conn.Ioctl` to wrap `ioctl(2)` for arbitrary requests with a + pointer argument. +- [Improvement]: update dependencies. + ## v0.7.0 **This is the first release of package socket that only supports Go 1.26+.** diff --git a/vendor/github.com/mdlayher/socket/CLAUDE.md b/vendor/github.com/mdlayher/socket/CLAUDE.md new file mode 100644 index 0000000000..ec8590e504 --- /dev/null +++ b/vendor/github.com/mdlayher/socket/CLAUDE.md @@ -0,0 +1,121 @@ +# CLAUDE.md + +Guidance for AI agents working in this repository. + +## Verification + +Run these on every Go change, alongside `go build ./...` and +`go test -race ./...`: + +- `gofumpt -l .` (keep stderr visible so a bad path can't look like a clean + run) +- `go vet ./...` +- `GOOS=darwin go vet ./...` (CI tests on macOS as well as Linux; any file + without a `//go:build linux` constraint must build there) +- `staticcheck ./...` (if the system binary is too old for the toolchain, + use `go run honnef.co/go/tools/cmd/staticcheck@latest ./...`) +- `gopls check -severity=hint ` (catches unusedfunc, + modernize, typeargs, and other hint-level findings vet and staticcheck + miss) + +This is a single Go module, so `./...` from the repository root covers +everything including `internal/sockettest`. + +CI builds on the two most recent Go releases, mirroring Go's own release +policy. Do not use language or library features newer than the minimum +version in `go.mod`. + +## Platforms + +- Cross-platform code lives in unsuffixed files such as `conn.go` and must + build on Linux, macOS, and the BSDs. Prefer this location for a new API + when the underlying system call exists everywhere. +- Linux-only code lives in `*_linux.go` files with a `//go:build linux` + constraint. When a feature needs a stub elsewhere, pair it with a + `*_others.go` file (see `netns_linux.go` and `netns_others.go`). +- Prefer the typed wrappers in `golang.org/x/sys/unix`. When one does not + exist, call `unix.Syscall` or `unix.Syscall6` directly and keep any + `unsafe.Pointer` to `uintptr` conversion inside the call expression so + `go vet` accepts it. + +## Code style + +Blank lines: + +- Leave an empty line after a closing brace and after a `var (` / `const (` + block when another statement or declaration follows at the same indent + level. Keep `}`, `)`, `case`, `default:`, and `else` continuations tight + against what precedes them. +- Break dense bodies, especially tests, with blank lines at logical seams: + between one actor's cluster of steps and the next, before final verdict + assertions, and between constructing a fixture and the next setup + statement. +- A single multi-line struct literal is one logical unit: never split it + mid-literal. + +Declaration layout: + +- A type and all of its methods stay contiguous. Supporting enums and codes + go before the type that uses them. +- `Conn` system call wrappers are one method per system call, named after + it, ordered roughly alphabetically within their file. Typed variants share + a prefix such as `GetsockoptInt` and `GetsockoptString`. +- Every `Conn` method that touches the file descriptor goes through + `control`/`controlT` for non-blocking calls or `ReadFunc`/`WriteFunc` + (and the generic `readT`/`writeT`) for calls that must wait on the + runtime network poller. Never call `c.rc` directly from a new method, and + never duplicate the retry, deadline, or cancelation logic in `rwT`. +- Closures passed to these helpers return the raw error from the system + call. The helper decides readiness via `ready` and wraps the result with + `os.NewSyscallError(op, err)`; callers must not wrap twice. +- Paired values described by one doc comment share one declaration. A doc + comment attaches to the declaration, so separate lines leave every name + after the first undocumented in go doc and IDE hover. +- Keep groups of one-line method stubs compact and aligned, with no blank + lines between them. + +Exported doc comments: + +- Open with "X wraps y(2)" for a plain system call wrapper. For anything + with more behavior, state the contract directly and self-contained: what + the closure receives, what it must return, when it may be called again, + and how errors are wrapped. +- Plain prose: short sentences, no em dashes. Prefer separate sentences, a + colon, or "such as X or Y" over parenthetical asides. Internal comments + are exempt. + +Markdown documents: + +- Wrap prose at 80 columns for terminal splits. Table rows and lines that + carry a URL are exempt: they cannot wrap. + +## Tests + +- Never sleep in tests. Every awaited condition must be signaled; poll + loops with sleep intervals count as sleeping. To prove a retry happened, + have the closure signal a channel on its first attempt and wait on it + before acting on the peer. +- Tests live in the external `socket_test` package. Use + `internal/sockettest` for TCP fixtures backed by `*socket.Conn`, and + `unix.Socketpair` wrapped by `socket.New` when a test only needs two + connected descriptors. +- Independent scenarios are individual top-level Test functions. `t.Run` + is for a table's cases and for subtests sharing a fixture built by the + parent. +- Test scenarios, not coverage. Cover paths a plausible real-world scenario + hits, framed on behavior; 100% coverage is not a goal. For blocking + operations that means success, readiness retry, context cancel, context + deadline plus its disarm for the next call, and `EBADF` after `Close`. +- Linux-only tests go in `*_linux_test.go`. Skip, rather than fail, when a + test needs privileges the environment lacks, such as a network namespace. +- Test helpers, rig types, and shared fixtures go at the end of test files, + after every Test/Fuzz/Benchmark/Example function. Shared consts may stay + at the top. + +## Changelog and releases + +- Every user-visible change gets a bullet in `CHANGELOG.md` under an + `## Unreleased` heading at the top, tagged `[New API]`, `[Bug Fix]`, or + `[Improvement]`, with a PR link when one exists. +- Do not bump versions or create tags as part of a change; releases are cut + separately. diff --git a/vendor/github.com/mdlayher/socket/README.md b/vendor/github.com/mdlayher/socket/README.md index 9cf7445a36..18453adbd7 100644 --- a/vendor/github.com/mdlayher/socket/README.md +++ b/vendor/github.com/mdlayher/socket/README.md @@ -13,6 +13,96 @@ used directly in end user applications. Any use of package socket should be guarded by build tags, as one would also use when importing the `syscall` or `golang.org/x/sys` packages. +## Ecosystem + +Over time, an ecosystem of Go packages has developed around package `socket`. +Many of these packages provide access to a specific socket family, such as +`AF_NETLINK` or `AF_PACKET`, and act as building blocks for further packages. + +To have your package included in this diagram, please send a pull request! + +```mermaid +flowchart LR + socket["github.com/mdlayher/socket"] + click socket "https://github.com/mdlayher/socket" + + subgraph af_inet["AF_INET and AF_INET6"] + direction LR + + go-rosenpass["cunicu.li/go-rosenpass"] + click go-rosenpass "https://codeberg.org/cunicu/go-rosenpass" + + icmpx["github.com/mdlayher/icmpx"] + click icmpx "https://github.com/mdlayher/icmpx" + + kquic["github.com/mdlayher/kquic"] + click kquic "https://github.com/mdlayher/kquic" + + netbird["github.com/netbirdio/netbird"] + click netbird "https://github.com/netbirdio/netbird" + + wsoding["github.com/shadowy-pycoder/wsoding"] + click wsoding "https://github.com/shadowy-pycoder/wsoding" + end + + subgraph "AF_KCM" + direction LR + + kcm["github.com/mdlayher/kcm"] + click kcm "https://github.com/mdlayher/kcm" + end + + subgraph "AF_NETLINK" + direction LR + + netlink["github.com/mdlayher/netlink"] + click netlink "https://github.com/mdlayher/netlink" + + ebpf-nftrace["github.com/Morwran/ebpf-nftrace"] + click ebpf-nftrace "https://github.com/Morwran/ebpf-nftrace" + end + + subgraph "AF_PACKET" + direction LR + + packet["github.com/mdlayher/packet"] + click packet "https://github.com/mdlayher/packet" + + fast_afpacket["github.com/subspace-com/fast_afpacket"] + click fast_afpacket "https://github.com/subspace-com/fast_afpacket" + + ndn-dpdk["github.com/usnistgov/ndn-dpdk"] + click ndn-dpdk "https://github.com/usnistgov/ndn-dpdk" + + ovn-kubernetes["github.com/ovn-kubernetes/ovn-kubernetes"] + click ovn-kubernetes "https://github.com/ovn-kubernetes/ovn-kubernetes" + + tailscale["tailscale.com"] + click tailscale "https://github.com/tailscale/tailscale" + end + + subgraph "AF_VSOCK" + direction LR + + vsock["github.com/mdlayher/vsock"] + click vsock "https://github.com/mdlayher/vsock" + end + + subgraph fds["Process file descriptors"] + direction LR + + pidfd["github.com/mdlayher/pidfd"] + click pidfd "https://github.com/mdlayher/pidfd" + end + + af_inet --> socket + AF_KCM --> socket + AF_NETLINK --> socket + AF_PACKET --> socket + AF_VSOCK --> socket + fds --> socket +``` + ## Stability See the [CHANGELOG](./CHANGELOG.md) file for a description of changes between diff --git a/vendor/github.com/mdlayher/socket/conn.go b/vendor/github.com/mdlayher/socket/conn.go index 68f9c52b8d..38151f5cc0 100644 --- a/vendor/github.com/mdlayher/socket/conn.go +++ b/vendor/github.com/mdlayher/socket/conn.go @@ -9,6 +9,7 @@ import ( "sync/atomic" "syscall" "time" + "unsafe" "golang.org/x/sys/unix" ) @@ -141,7 +142,7 @@ func (c *Conn) WriteContext(ctx context.Context, b []byte) (int, error) { err error ) - doErr := c.write(ctx, "write", func(fd int) error { + doErr := c.WriteFunc(ctx, "write", func(fd int) error { lenb := len(b) if c.facts.isStream && lenb-nn > maxRW { lenb = nn + maxRW @@ -471,7 +472,7 @@ func (c *Conn) Connect(ctx context.Context, sa unix.Sockaddr) (unix.Sockaddr, er err error ) - doErr := c.write(ctx, op, func(fd int) error { + doErr := c.WriteFunc(ctx, op, func(fd int) error { if progress.Add(1) == 1 { // First call: initiate connect. return unix.Connect(fd, sa) @@ -557,6 +558,29 @@ func (c *Conn) GetsockoptString(level, opt int) (string, error) { }) } +// Ioctl wraps ioctl(2) for an arbitrary request req with a pointer argument +// arg, which is passed to the kernel verbatim. It is intended for requests +// which have no typed wrapper in this package or in package +// golang.org/x/sys/unix. arg may be nil for requests which take no argument. +// +// The caller is responsible for ensuring that arg points to memory of the +// size and layout expected by the kernel for req. +func (c *Conn) Ioctl(req uint, arg unsafe.Pointer) error { + return c.control("ioctl", func(fd int) error { + _, _, errno := unix.Syscall( + unix.SYS_IOCTL, + uintptr(fd), + uintptr(req), + uintptr(arg), + ) + if errno != 0 { + return errno + } + + return nil + }) +} + // Listen wraps listen(2). func (c *Conn) Listen(n int) error { return c.control("listen", func(fd int) error { return unix.Listen(fd, n) }) @@ -614,7 +638,7 @@ func (c *Conn) SendmsgBuffers(ctx context.Context, buffers [][]byte, oob []byte, // Sendto wraps sendto(2). func (c *Conn) Sendto(ctx context.Context, p []byte, flags int, to unix.Sockaddr) error { - return c.write(ctx, "sendto", func(fd int) error { + return c.WriteFunc(ctx, "sendto", func(fd int) error { return unix.Sendto(fd, p, flags, to) }) } @@ -649,18 +673,52 @@ func (c *Conn) Shutdown(how int) error { // syscall.RawConn APIs but the input closures return errors rather than // booleans. -// read wraps readT to execute a function and capture its error result. This is -// a convenience wrapper for functions which don't return any extra values. -func (c *Conn) read(ctx context.Context, op string, f func(fd int) error) error { +// ReadFunc executes f, a read function, against the underlying file descriptor +// with integration into Go's runtime network poller. It is the raw building +// block used by the Conn read methods such as ReadContext and Recvmsg and is +// intended for system calls which have no wrapper in this package or in +// package golang.org/x/sys/unix. +// +// f is invoked with the file descriptor while the runtime network poller holds +// it, and must return the raw error from the system call it performs: nil on +// success or a unix.Errno on failure. If f returns unix.EAGAIN, unix.EINTR, or +// unix.EINPROGRESS, ReadFunc waits for the file descriptor to become readable +// and invokes f again. Any other error or nil completes the operation, so f +// may be called more than once and must be safe to retry. +// +// op is the name of the operation used in errors. The error returned by f is +// wrapped as os.NewSyscallError(op, err). If ctx is canceled or its deadline +// is reached before f completes, the context error is wrapped in the same way. +// A context deadline is applied to the Conn's read deadline for the duration +// of the call and is cleared before ReadFunc returns. If the Conn is closed, +// ReadFunc returns os.NewSyscallError(op, unix.EBADF). +func (c *Conn) ReadFunc(ctx context.Context, op string, f func(fd int) error) error { _, err := readT(ctx, c, op, func(fd int) (struct{}, error) { return struct{}{}, f(fd) }) return err } -// write executes f, a write function, against the associated file descriptor. -// op is used to create an *os.SyscallError if the file descriptor is closed. -func (c *Conn) write(ctx context.Context, op string, f func(fd int) error) error { +// WriteFunc executes f, a write function, against the underlying file +// descriptor with integration into Go's runtime network poller. It is the raw +// building block used by the Conn write methods such as WriteContext and +// Sendmsg and is intended for system calls which have no wrapper in this +// package or in package golang.org/x/sys/unix. +// +// f is invoked with the file descriptor while the runtime network poller holds +// it, and must return the raw error from the system call it performs: nil on +// success or a unix.Errno on failure. If f returns unix.EAGAIN, unix.EINTR, or +// unix.EINPROGRESS, WriteFunc waits for the file descriptor to become writable +// and invokes f again. Any other error or nil completes the operation, so f +// may be called more than once and must be safe to retry. +// +// op is the name of the operation used in errors. The error returned by f is +// wrapped as os.NewSyscallError(op, err). If ctx is canceled or its deadline +// is reached before f completes, the context error is wrapped in the same way. +// A context deadline is applied to the Conn's write deadline for the duration +// of the call and is cleared before WriteFunc returns. If the Conn is closed, +// WriteFunc returns os.NewSyscallError(op, unix.EBADF). +func (c *Conn) WriteFunc(ctx context.Context, op string, f func(fd int) error) error { _, err := writeT(ctx, c, op, func(fd int) (struct{}, error) { return struct{}{}, f(fd) }) diff --git a/vendor/github.com/mdlayher/socket/conn_linux.go b/vendor/github.com/mdlayher/socket/conn_linux.go index 9746e21c77..d2ca17e2b0 100644 --- a/vendor/github.com/mdlayher/socket/conn_linux.go +++ b/vendor/github.com/mdlayher/socket/conn_linux.go @@ -173,7 +173,7 @@ func (c *Conn) GetsockoptTpacketStatsV3(level, name int) (*unix.TpacketStatsV3, // Waitid wraps waitid(2). func (c *Conn) Waitid(idType int, info *unix.Siginfo, options int, rusage *unix.Rusage) error { - return c.read(context.Background(), "waitid", func(fd int) error { + return c.ReadFunc(context.Background(), "waitid", func(fd int) error { return unix.Waitid(idType, fd, info, options, rusage) }) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 836f03c87a..cabe5c2713 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1055,7 +1055,7 @@ github.com/klauspost/compress/zstd/internal/xxhash # github.com/knqyf263/go-plugin v0.9.0 ## explicit; go 1.24.0 github.com/knqyf263/go-plugin/wasm -# github.com/mdlayher/socket v0.7.0 +# github.com/mdlayher/socket v0.8.0 ## explicit; go 1.26.0 github.com/mdlayher/socket # github.com/mdlayher/vsock v1.3.0