mirror of
https://github.com/aljazceru/kata-containers.git
synced 2026-01-09 01:14:20 +01:00
CCv0: Merge main into CCv0 branch
Merge remote-tracking branch 'upstream/main' into CCv0 Fixes: #3738 Signed-off-by: stevenhorsman <steven@uk.ibm.com>
This commit is contained in:
36
src/runtime/vendor/github.com/mdlayher/socket/CHANGELOG.md
generated
vendored
Normal file
36
src/runtime/vendor/github.com/mdlayher/socket/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.2.0
|
||||
|
||||
- [New API] [commit](https://github.com/mdlayher/socket/commit/6e912a68523c45e5fd899239f4b46c402dd856da):
|
||||
`socket.FileConn` can be used to create a `socket.Conn` from an existing
|
||||
`os.File`, which may be provided by systemd socket activation or another
|
||||
external mechanism.
|
||||
- [API change] [commit](https://github.com/mdlayher/socket/commit/66d61f565188c23fe02b24099ddc856d538bf1a7):
|
||||
`socket.Conn.Connect` now returns the `unix.Sockaddr` value provided by
|
||||
`getpeername(2)`, since we have to invoke that system call anyway to verify
|
||||
that a connection to a remote peer was successfully established.
|
||||
- [Bug Fix] [commit](https://github.com/mdlayher/socket/commit/b60b2dbe0ac3caff2338446a150083bde8c5c19c):
|
||||
check the correct error from `unix.GetsockoptInt` in the `socket.Conn.Connect`
|
||||
method. Thanks @vcabbage!
|
||||
|
||||
## v0.1.2
|
||||
|
||||
- [Bug Fix]: `socket.Conn.Connect` now properly checks the `SO_ERROR` socket
|
||||
option value after calling `connect(2)` to verify whether or not a connection
|
||||
could successfully be established. This means that `Connect` should now report
|
||||
an error for an `AF_INET` TCP connection refused or `AF_VSOCK` connection
|
||||
reset by peer.
|
||||
- [New API]: add `socket.Conn.Getpeername` for use in `Connect`, but also for
|
||||
use by external callers.
|
||||
|
||||
## v0.1.1
|
||||
|
||||
- [New API]: `socket.Conn` now has `CloseRead`, `CloseWrite`, and `Shutdown`
|
||||
methods.
|
||||
- [Improvement]: internal rework to more robustly handle various errors.
|
||||
|
||||
## v0.1.0
|
||||
|
||||
- Initial unstable release. Most functionality has been developed and ported
|
||||
from package [`netlink`](https://github.com/mdlayher/netlink).
|
||||
9
src/runtime/vendor/github.com/mdlayher/socket/LICENSE.md
generated
vendored
Normal file
9
src/runtime/vendor/github.com/mdlayher/socket/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# MIT License
|
||||
|
||||
Copyright (C) 2021 Matt Layher
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
14
src/runtime/vendor/github.com/mdlayher/socket/README.md
generated
vendored
Normal file
14
src/runtime/vendor/github.com/mdlayher/socket/README.md
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# socket [](https://github.com/mdlayher/socket/actions) [](https://pkg.go.dev/github.com/mdlayher/socket) [](https://goreportcard.com/report/github.com/mdlayher/socket)
|
||||
|
||||
Package `socket` provides a low-level network connection type which integrates
|
||||
with Go's runtime network poller to provide asynchronous I/O and deadline
|
||||
support. MIT Licensed.
|
||||
|
||||
This package focuses on UNIX-like operating systems which make use of BSD
|
||||
sockets system call APIs. It is meant to be used as a foundation for the
|
||||
creation of operating system-specific socket packages, for socket families such
|
||||
as Linux's `AF_NETLINK`, `AF_PACKET`, or `AF_VSOCK`. This package should not be
|
||||
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.
|
||||
23
src/runtime/vendor/github.com/mdlayher/socket/accept.go
generated
vendored
Normal file
23
src/runtime/vendor/github.com/mdlayher/socket/accept.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
//go:build !dragonfly && !freebsd && !illumos && !linux
|
||||
// +build !dragonfly,!freebsd,!illumos,!linux
|
||||
|
||||
package socket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const sysAccept = "accept"
|
||||
|
||||
// accept wraps accept(2).
|
||||
func accept(fd, flags int) (int, unix.Sockaddr, error) {
|
||||
if flags != 0 {
|
||||
// These operating systems have no support for flags to accept(2).
|
||||
return 0, nil, fmt.Errorf("socket: Conn.Accept flags are ineffective on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
return unix.Accept(fd)
|
||||
}
|
||||
15
src/runtime/vendor/github.com/mdlayher/socket/accept4.go
generated
vendored
Normal file
15
src/runtime/vendor/github.com/mdlayher/socket/accept4.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
//go:build dragonfly || freebsd || illumos || linux
|
||||
// +build dragonfly freebsd illumos linux
|
||||
|
||||
package socket
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const sysAccept = "accept4"
|
||||
|
||||
// accept wraps accept4(2).
|
||||
func accept(fd, flags int) (int, unix.Sockaddr, error) {
|
||||
return unix.Accept4(fd, flags)
|
||||
}
|
||||
675
src/runtime/vendor/github.com/mdlayher/socket/conn.go
generated
vendored
Normal file
675
src/runtime/vendor/github.com/mdlayher/socket/conn.go
generated
vendored
Normal file
@@ -0,0 +1,675 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// A Conn is a low-level network connection which integrates with Go's runtime
|
||||
// network poller to provide asynchronous I/O and deadline support.
|
||||
type Conn struct {
|
||||
// Indicates whether or not Conn.Close has been called. Must be accessed
|
||||
// atomically. Atomics definitions must come first in the Conn struct.
|
||||
closed uint32
|
||||
|
||||
// A unique name for the Conn which is also associated with derived file
|
||||
// descriptors such as those created by accept(2).
|
||||
name string
|
||||
|
||||
// Provides access to the underlying file registered with the runtime
|
||||
// network poller, and arbitrary raw I/O calls.
|
||||
fd *os.File
|
||||
rc syscall.RawConn
|
||||
}
|
||||
|
||||
// A Config contains options for a Conn.
|
||||
type Config struct {
|
||||
// NetNS specifies the Linux network namespace the Conn will operate in.
|
||||
// This option is unsupported on other operating systems.
|
||||
//
|
||||
// If set (non-zero), Conn will enter the specified network namespace and an
|
||||
// error will occur in Socket if the operation fails.
|
||||
//
|
||||
// If not set (zero), a best-effort attempt will be made to enter the
|
||||
// network namespace of the calling thread: this means that any changes made
|
||||
// to the calling thread's network namespace will also be reflected in Conn.
|
||||
// If this operation fails (due to lack of permissions or because network
|
||||
// namespaces are disabled by kernel configuration), Socket will not return
|
||||
// an error, and the Conn will operate in the default network namespace of
|
||||
// the process. This enables non-privileged use of Conn in applications
|
||||
// which do not require elevated privileges.
|
||||
//
|
||||
// Entering a network namespace is a privileged operation (root or
|
||||
// CAP_SYS_ADMIN are required), and most applications should leave this set
|
||||
// to 0.
|
||||
NetNS int
|
||||
}
|
||||
|
||||
// High-level methods which provide convenience over raw system calls.
|
||||
|
||||
// Close closes the underlying file descriptor for the Conn, which also causes
|
||||
// all in-flight I/O operations to immediately unblock and return errors. Any
|
||||
// subsequent uses of Conn will result in EBADF.
|
||||
func (c *Conn) Close() error {
|
||||
// The caller has expressed an intent to close the socket, so immediately
|
||||
// increment s.closed to force further calls to result in EBADF before also
|
||||
// closing the file descriptor to unblock any outstanding operations.
|
||||
//
|
||||
// Because other operations simply check for s.closed != 0, we will permit
|
||||
// double Close, which would increment s.closed beyond 1.
|
||||
if atomic.AddUint32(&c.closed, 1) != 1 {
|
||||
// Multiple Close calls.
|
||||
return nil
|
||||
}
|
||||
|
||||
return os.NewSyscallError("close", c.fd.Close())
|
||||
}
|
||||
|
||||
// CloseRead shuts down the reading side of the Conn. Most callers should just
|
||||
// use Close.
|
||||
func (c *Conn) CloseRead() error { return c.Shutdown(unix.SHUT_RD) }
|
||||
|
||||
// CloseWrite shuts down the writing side of the Conn. Most callers should just
|
||||
// use Close.
|
||||
func (c *Conn) CloseWrite() error { return c.Shutdown(unix.SHUT_WR) }
|
||||
|
||||
// Read implements io.Reader by reading directly from the underlying file
|
||||
// descriptor.
|
||||
func (c *Conn) Read(b []byte) (int, error) { return c.fd.Read(b) }
|
||||
|
||||
// Write implements io.Writer by writing directly to the underlying file
|
||||
// descriptor.
|
||||
func (c *Conn) Write(b []byte) (int, error) { return c.fd.Write(b) }
|
||||
|
||||
// SetDeadline sets both the read and write deadlines associated with the Conn.
|
||||
func (c *Conn) SetDeadline(t time.Time) error { return c.fd.SetDeadline(t) }
|
||||
|
||||
// SetReadDeadline sets the read deadline associated with the Conn.
|
||||
func (c *Conn) SetReadDeadline(t time.Time) error { return c.fd.SetReadDeadline(t) }
|
||||
|
||||
// SetWriteDeadline sets the write deadline associated with the Conn.
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error { return c.fd.SetWriteDeadline(t) }
|
||||
|
||||
// ReadBuffer gets the size of the operating system's receive buffer associated
|
||||
// with the Conn.
|
||||
func (c *Conn) ReadBuffer() (int, error) {
|
||||
return c.GetsockoptInt(unix.SOL_SOCKET, unix.SO_RCVBUF)
|
||||
}
|
||||
|
||||
// WriteBuffer gets the size of the operating system's transmit buffer
|
||||
// associated with the Conn.
|
||||
func (c *Conn) WriteBuffer() (int, error) {
|
||||
return c.GetsockoptInt(unix.SOL_SOCKET, unix.SO_SNDBUF)
|
||||
}
|
||||
|
||||
// SetReadBuffer sets the size of the operating system's receive buffer
|
||||
// associated with the Conn.
|
||||
//
|
||||
// When called with elevated privileges on Linux, the SO_RCVBUFFORCE option will
|
||||
// be used to override operating system limits. Otherwise SO_RCVBUF is used
|
||||
// (which obeys operating system limits).
|
||||
func (c *Conn) SetReadBuffer(bytes int) error { return c.setReadBuffer(bytes) }
|
||||
|
||||
// SetWriteBuffer sets the size of the operating system's transmit buffer
|
||||
// associated with the Conn.
|
||||
//
|
||||
// When called with elevated privileges on Linux, the SO_SNDBUFFORCE option will
|
||||
// be used to override operating system limits. Otherwise SO_SNDBUF is used
|
||||
// (which obeys operating system limits).
|
||||
func (c *Conn) SetWriteBuffer(bytes int) error { return c.setWriteBuffer(bytes) }
|
||||
|
||||
// SyscallConn returns a raw network connection. This implements the
|
||||
// syscall.Conn interface.
|
||||
//
|
||||
// SyscallConn is intended for advanced use cases, such as getting and setting
|
||||
// arbitrary socket options using the socket's file descriptor. If possible,
|
||||
// those operations should be performed using methods on Conn instead.
|
||||
//
|
||||
// Once invoked, it is the caller's responsibility to ensure that operations
|
||||
// performed using Conn and the syscall.RawConn do not conflict with each other.
|
||||
func (c *Conn) SyscallConn() (syscall.RawConn, error) {
|
||||
if atomic.LoadUint32(&c.closed) != 0 {
|
||||
return nil, os.NewSyscallError("syscallconn", unix.EBADF)
|
||||
}
|
||||
|
||||
// TODO(mdlayher): mutex or similar to enforce syscall.RawConn contract of
|
||||
// FD remaining valid for duration of calls?
|
||||
return c.rc, nil
|
||||
}
|
||||
|
||||
// Socket wraps the socket(2) system call to produce a Conn. domain, typ, and
|
||||
// proto are passed directly to socket(2), and name should be a unique name for
|
||||
// the socket type such as "netlink" or "vsock".
|
||||
//
|
||||
// The cfg parameter specifies optional configuration for the Conn. If nil, no
|
||||
// additional configuration will be applied.
|
||||
//
|
||||
// If the operating system supports SOCK_CLOEXEC and SOCK_NONBLOCK, they are
|
||||
// automatically applied to typ to mirror the standard library's socket flag
|
||||
// behaviors.
|
||||
func Socket(domain, typ, proto int, name string, cfg *Config) (*Conn, error) {
|
||||
if cfg == nil {
|
||||
cfg = &Config{}
|
||||
}
|
||||
|
||||
if cfg.NetNS == 0 {
|
||||
// Non-Linux or no network namespace.
|
||||
return socket(domain, typ, proto, name)
|
||||
}
|
||||
|
||||
// Linux only: create Conn in the specified network namespace.
|
||||
return withNetNS(cfg.NetNS, func() (*Conn, error) {
|
||||
return socket(domain, typ, proto, name)
|
||||
})
|
||||
}
|
||||
|
||||
// socket is the internal, cross-platform entry point for socket(2).
|
||||
func socket(domain, typ, proto int, name string) (*Conn, error) {
|
||||
var (
|
||||
fd int
|
||||
err error
|
||||
)
|
||||
|
||||
for {
|
||||
fd, err = unix.Socket(domain, typ|socketFlags, proto)
|
||||
switch {
|
||||
case err == nil:
|
||||
// Some OSes already set CLOEXEC with typ.
|
||||
if !flagCLOEXEC {
|
||||
unix.CloseOnExec(fd)
|
||||
}
|
||||
|
||||
// No error, prepare the Conn.
|
||||
return newConn(fd, name)
|
||||
case !ready(err):
|
||||
// System call interrupted or not ready, try again.
|
||||
continue
|
||||
case err == unix.EINVAL, err == unix.EPROTONOSUPPORT:
|
||||
// On Linux, SOCK_NONBLOCK and SOCK_CLOEXEC were introduced in
|
||||
// 2.6.27. On FreeBSD, both flags were introduced in FreeBSD 10.
|
||||
// EINVAL and EPROTONOSUPPORT check for earlier versions of these
|
||||
// OSes respectively.
|
||||
//
|
||||
// Mirror what the standard library does when creating file
|
||||
// descriptors: avoid racing a fork/exec with the creation of new
|
||||
// file descriptors, so that child processes do not inherit socket
|
||||
// file descriptors unexpectedly.
|
||||
//
|
||||
// For a more thorough explanation, see similar work in the Go tree:
|
||||
// func sysSocket in net/sock_cloexec.go, as well as the detailed
|
||||
// comment in syscall/exec_unix.go.
|
||||
syscall.ForkLock.RLock()
|
||||
fd, err = unix.Socket(domain, typ, proto)
|
||||
if err != nil {
|
||||
syscall.ForkLock.RUnlock()
|
||||
return nil, os.NewSyscallError("socket", err)
|
||||
}
|
||||
unix.CloseOnExec(fd)
|
||||
syscall.ForkLock.RUnlock()
|
||||
|
||||
return newConn(fd, name)
|
||||
default:
|
||||
// Unhandled error.
|
||||
return nil, os.NewSyscallError("socket", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FileConn returns a copy of the network connection corresponding to the open
|
||||
// file. It is the caller's responsibility to close the file when finished.
|
||||
// Closing the Conn does not affect the File, and closing the File does not
|
||||
// affect the Conn.
|
||||
func FileConn(f *os.File, name string) (*Conn, error) {
|
||||
// First we'll try to do fctnl(2) with F_DUPFD_CLOEXEC because we can dup
|
||||
// the file descriptor and set the flag in one syscall.
|
||||
fd, err := unix.FcntlInt(f.Fd(), unix.F_DUPFD_CLOEXEC, 0)
|
||||
switch err {
|
||||
case nil:
|
||||
// OK, ready to set up non-blocking I/O.
|
||||
return newConn(fd, name)
|
||||
case unix.EINVAL:
|
||||
// The kernel rejected our fcntl(2), fall back to separate dup(2) and
|
||||
// setting close on exec.
|
||||
//
|
||||
// Mirror what the standard library does when creating file descriptors:
|
||||
// avoid racing a fork/exec with the creation of new file descriptors,
|
||||
// so that child processes do not inherit socket file descriptors
|
||||
// unexpectedly.
|
||||
syscall.ForkLock.RLock()
|
||||
fd, err := unix.Dup(fd)
|
||||
if err != nil {
|
||||
syscall.ForkLock.RUnlock()
|
||||
return nil, os.NewSyscallError("dup", err)
|
||||
}
|
||||
unix.CloseOnExec(fd)
|
||||
syscall.ForkLock.RUnlock()
|
||||
|
||||
return newConn(fd, name)
|
||||
default:
|
||||
// Any other errors.
|
||||
return nil, os.NewSyscallError("fcntl", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(mdlayher): consider exporting newConn as New?
|
||||
|
||||
// newConn wraps an existing file descriptor to create a Conn. name should be a
|
||||
// unique name for the socket type such as "netlink" or "vsock".
|
||||
func newConn(fd int, name string) (*Conn, error) {
|
||||
// All Conn I/O is nonblocking for integration with Go's runtime network
|
||||
// poller. Depending on the OS this might already be set but it can't hurt
|
||||
// to set it again.
|
||||
if err := unix.SetNonblock(fd, true); err != nil {
|
||||
return nil, os.NewSyscallError("setnonblock", err)
|
||||
}
|
||||
|
||||
// os.NewFile registers the non-blocking file descriptor with the runtime
|
||||
// poller, which is then used for most subsequent operations except those
|
||||
// that require raw I/O via SyscallConn.
|
||||
//
|
||||
// See also: https://golang.org/pkg/os/#NewFile
|
||||
f := os.NewFile(uintptr(fd), name)
|
||||
rc, err := f.SyscallConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Conn{
|
||||
name: name,
|
||||
fd: f,
|
||||
rc: rc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Low-level methods which provide raw system call access.
|
||||
|
||||
// Accept wraps accept(2) or accept4(2) depending on the operating system, but
|
||||
// returns a Conn for the accepted connection rather than a raw file descriptor.
|
||||
//
|
||||
// If the operating system supports accept4(2) (which allows flags),
|
||||
// SOCK_CLOEXEC and SOCK_NONBLOCK are automatically applied to flags to mirror
|
||||
// the standard library's socket flag behaviors.
|
||||
//
|
||||
// If the operating system only supports accept(2) (which does not allow flags)
|
||||
// and flags is not zero, an error will be returned.
|
||||
func (c *Conn) Accept(flags int) (*Conn, unix.Sockaddr, error) {
|
||||
var (
|
||||
nfd int
|
||||
sa unix.Sockaddr
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.read(sysAccept, func(fd int) error {
|
||||
// Either accept(2) or accept4(2) depending on the OS.
|
||||
nfd, sa, err = accept(fd, flags|socketFlags)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return nil, nil, doErr
|
||||
}
|
||||
if err != nil {
|
||||
// sysAccept is either "accept" or "accept4" depending on the OS.
|
||||
return nil, nil, os.NewSyscallError(sysAccept, err)
|
||||
}
|
||||
|
||||
// Successfully accepted a connection, wrap it in a Conn for use by the
|
||||
// caller.
|
||||
ac, err := newConn(nfd, c.name)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return ac, sa, nil
|
||||
}
|
||||
|
||||
// Bind wraps bind(2).
|
||||
func (c *Conn) Bind(sa unix.Sockaddr) error {
|
||||
const op = "bind"
|
||||
|
||||
var err error
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
err = unix.Bind(fd, sa)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Connect wraps connect(2). In order to verify that the underlying socket is
|
||||
// connected to a remote peer, Connect calls getpeername(2) and returns the
|
||||
// unix.Sockaddr from that call.
|
||||
func (c *Conn) Connect(sa unix.Sockaddr) (unix.Sockaddr, error) {
|
||||
const op = "connect"
|
||||
|
||||
// TODO(mdlayher): it would seem that trying to connect to unbound vsock
|
||||
// listeners by calling Connect multiple times results in ECONNRESET for the
|
||||
// first and nil error for subsequent calls. Do we need to memoize the
|
||||
// error? Check what the stdlib behavior is.
|
||||
|
||||
var (
|
||||
// Track progress between invocations of the write closure. We don't
|
||||
// have an explicit WaitWrite call like internal/poll does, so we have
|
||||
// to wait until the runtime calls the closure again to indicate we can
|
||||
// write.
|
||||
progress uint32
|
||||
|
||||
// Capture closure sockaddr and error.
|
||||
rsa unix.Sockaddr
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.write(op, func(fd int) error {
|
||||
if atomic.AddUint32(&progress, 1) == 1 {
|
||||
// First call: initiate connect.
|
||||
return unix.Connect(fd, sa)
|
||||
}
|
||||
|
||||
// Subsequent calls: the runtime network poller indicates fd is
|
||||
// writable. Check for errno.
|
||||
errno, gerr := c.GetsockoptInt(unix.SOL_SOCKET, unix.SO_ERROR)
|
||||
if gerr != nil {
|
||||
return gerr
|
||||
}
|
||||
if errno != 0 {
|
||||
// Connection is still not ready or failed. If errno indicates
|
||||
// the socket is not ready, we will wait for the next write
|
||||
// event. Otherwise we propagate this errno back to the as a
|
||||
// permanent error.
|
||||
uerr := unix.Errno(errno)
|
||||
err = uerr
|
||||
return uerr
|
||||
}
|
||||
|
||||
// According to internal/poll, it's possible for the runtime network
|
||||
// poller to spuriously wake us and return errno 0 for SO_ERROR.
|
||||
// Make sure we are actually connected to a peer.
|
||||
peer, err := c.Getpeername()
|
||||
if err != nil {
|
||||
// internal/poll unconditionally goes back to WaitWrite.
|
||||
// Synthesize an error that will do the same for us.
|
||||
return unix.EAGAIN
|
||||
}
|
||||
|
||||
// Connection complete.
|
||||
rsa = peer
|
||||
return nil
|
||||
})
|
||||
if doErr != nil {
|
||||
return nil, doErr
|
||||
}
|
||||
|
||||
if err == unix.EISCONN {
|
||||
// TODO(mdlayher): is this block obsolete with the addition of the
|
||||
// getsockopt SO_ERROR check above?
|
||||
//
|
||||
// EISCONN is reported if the socket is already established and should
|
||||
// not be treated as an error.
|
||||
// - Darwin reports this for at least TCP sockets
|
||||
// - Linux reports this for at least AF_VSOCK sockets
|
||||
return rsa, nil
|
||||
}
|
||||
|
||||
return rsa, os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Getsockname wraps getsockname(2).
|
||||
func (c *Conn) Getsockname() (unix.Sockaddr, error) {
|
||||
const op = "getsockname"
|
||||
|
||||
var (
|
||||
sa unix.Sockaddr
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
sa, err = unix.Getsockname(fd)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return nil, doErr
|
||||
}
|
||||
|
||||
return sa, os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Getpeername wraps getpeername(2).
|
||||
func (c *Conn) Getpeername() (unix.Sockaddr, error) {
|
||||
const op = "getpeername"
|
||||
|
||||
var (
|
||||
sa unix.Sockaddr
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
sa, err = unix.Getpeername(fd)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return nil, doErr
|
||||
}
|
||||
|
||||
return sa, os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// GetsockoptInt wraps getsockopt(2) for integer values.
|
||||
func (c *Conn) GetsockoptInt(level, opt int) (int, error) {
|
||||
const op = "getsockopt"
|
||||
|
||||
var (
|
||||
value int
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
value, err = unix.GetsockoptInt(fd, level, opt)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return 0, doErr
|
||||
}
|
||||
|
||||
return value, os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Listen wraps listen(2).
|
||||
func (c *Conn) Listen(n int) error {
|
||||
const op = "listen"
|
||||
|
||||
var err error
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
err = unix.Listen(fd, n)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Recvmsg wraps recvmsg(2).
|
||||
func (c *Conn) Recvmsg(p, oob []byte, flags int) (int, int, int, unix.Sockaddr, error) {
|
||||
const op = "recvmsg"
|
||||
|
||||
var (
|
||||
n, oobn, recvflags int
|
||||
from unix.Sockaddr
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.read(op, func(fd int) error {
|
||||
n, oobn, recvflags, from, err = unix.Recvmsg(fd, p, oob, flags)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return 0, 0, 0, nil, doErr
|
||||
}
|
||||
|
||||
return n, oobn, recvflags, from, os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Recvfrom wraps recvfrom(2)
|
||||
func (c *Conn) Recvfrom(p []byte, flags int) (int, unix.Sockaddr, error) {
|
||||
const op = "recvfrom"
|
||||
|
||||
var (
|
||||
n int
|
||||
addr unix.Sockaddr
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.read(op, func(fd int) error {
|
||||
n, addr, err = unix.Recvfrom(fd, p, flags)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return 0, nil, doErr
|
||||
}
|
||||
|
||||
return n, addr, os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Sendmsg wraps sendmsg(2).
|
||||
func (c *Conn) Sendmsg(p, oob []byte, to unix.Sockaddr, flags int) error {
|
||||
const op = "sendmsg"
|
||||
|
||||
var err error
|
||||
doErr := c.write(op, func(fd int) error {
|
||||
err = unix.Sendmsg(fd, p, oob, to, flags)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Sendto wraps sendto(2).
|
||||
func (c *Conn) Sendto(b []byte, to unix.Sockaddr, flags int) error {
|
||||
const op = "sendto"
|
||||
|
||||
var err error
|
||||
doErr := c.write(op, func(fd int) error {
|
||||
err = unix.Sendto(fd, b, flags, to)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// SetsockoptInt wraps setsockopt(2) for integer values.
|
||||
func (c *Conn) SetsockoptInt(level, opt, value int) error {
|
||||
const op = "setsockopt"
|
||||
|
||||
var err error
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
err = unix.SetsockoptInt(fd, level, opt, value)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Shutdown wraps shutdown(2).
|
||||
func (c *Conn) Shutdown(how int) error {
|
||||
const op = "shutdown"
|
||||
|
||||
var err error
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
err = unix.Shutdown(fd, how)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// Conn low-level read/write/control functions. These functions mirror the
|
||||
// syscall.RawConn APIs but the input closures return errors rather than
|
||||
// booleans. Any syscalls invoked within f should return their error to allow
|
||||
// the Conn to check for readiness with the runtime network poller, or to retry
|
||||
// operations which may have been interrupted by EINTR or similar.
|
||||
//
|
||||
// Note that errors from the input closure functions are not propagated to the
|
||||
// error return values of read/write/control, and the caller is still
|
||||
// responsible for error handling.
|
||||
|
||||
// read executes f, a read function, against the associated file descriptor.
|
||||
// op is used to create an *os.SyscallError if the file descriptor is closed.
|
||||
func (c *Conn) read(op string, f func(fd int) error) error {
|
||||
if atomic.LoadUint32(&c.closed) != 0 {
|
||||
return os.NewSyscallError(op, unix.EBADF)
|
||||
}
|
||||
|
||||
return c.rc.Read(func(fd uintptr) bool {
|
||||
return ready(f(int(fd)))
|
||||
})
|
||||
}
|
||||
|
||||
// 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(op string, f func(fd int) error) error {
|
||||
if atomic.LoadUint32(&c.closed) != 0 {
|
||||
return os.NewSyscallError(op, unix.EBADF)
|
||||
}
|
||||
|
||||
return c.rc.Write(func(fd uintptr) bool {
|
||||
return ready(f(int(fd)))
|
||||
})
|
||||
}
|
||||
|
||||
// control executes f, a control function, against the associated file
|
||||
// descriptor. op is used to create an *os.SyscallError if the file descriptor
|
||||
// is closed.
|
||||
func (c *Conn) control(op string, f func(fd int) error) error {
|
||||
if atomic.LoadUint32(&c.closed) != 0 {
|
||||
return os.NewSyscallError(op, unix.EBADF)
|
||||
}
|
||||
|
||||
return c.rc.Control(func(fd uintptr) {
|
||||
// Repeatedly attempt the syscall(s) invoked by f until completion is
|
||||
// indicated by the return value of ready.
|
||||
for {
|
||||
if ready(f(int(fd))) {
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ready indicates readiness based on the value of err.
|
||||
func ready(err error) bool {
|
||||
// When a socket is in non-blocking mode, we might see a variety of errors:
|
||||
// - EAGAIN: most common case for a socket read not being ready
|
||||
// - EINPROGRESS: reported by some sockets when first calling connect
|
||||
// - EINTR: system call interrupted, more frequently occurs in Go 1.14+
|
||||
// because goroutines can be asynchronously preempted
|
||||
//
|
||||
// Return false to let the poller wait for readiness. See the source code
|
||||
// for internal/poll.FD.RawRead for more details.
|
||||
switch err {
|
||||
case unix.EAGAIN, unix.EINPROGRESS, unix.EINTR:
|
||||
// Not ready.
|
||||
return false
|
||||
default:
|
||||
// Ready regardless of whether there was an error or no error.
|
||||
return true
|
||||
}
|
||||
}
|
||||
88
src/runtime/vendor/github.com/mdlayher/socket/conn_linux.go
generated
vendored
Normal file
88
src/runtime/vendor/github.com/mdlayher/socket/conn_linux.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package socket
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// SetBPF attaches an assembled BPF program to a Conn.
|
||||
func (c *Conn) SetBPF(filter []bpf.RawInstruction) error {
|
||||
// We can't point to the first instruction in the array if no instructions
|
||||
// are present.
|
||||
if len(filter) == 0 {
|
||||
return os.NewSyscallError("setsockopt", unix.EINVAL)
|
||||
}
|
||||
|
||||
prog := unix.SockFprog{
|
||||
Len: uint16(len(filter)),
|
||||
Filter: (*unix.SockFilter)(unsafe.Pointer(&filter[0])),
|
||||
}
|
||||
|
||||
return c.SetsockoptSockFprog(unix.SOL_SOCKET, unix.SO_ATTACH_FILTER, &prog)
|
||||
}
|
||||
|
||||
// RemoveBPF removes a BPF filter from a Conn.
|
||||
func (c *Conn) RemoveBPF() error {
|
||||
// 0 argument is ignored.
|
||||
return c.SetsockoptInt(unix.SOL_SOCKET, unix.SO_DETACH_FILTER, 0)
|
||||
}
|
||||
|
||||
// SetsockoptSockFprog wraps setsockopt(2) for unix.SockFprog values.
|
||||
func (c *Conn) SetsockoptSockFprog(level, opt int, fprog *unix.SockFprog) error {
|
||||
const op = "setsockopt"
|
||||
|
||||
var err error
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
err = unix.SetsockoptSockFprog(fd, level, opt, fprog)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// GetSockoptTpacketStats wraps getsockopt(2) for getting TpacketStats
|
||||
func (c *Conn) GetSockoptTpacketStats(level, name int) (*unix.TpacketStats, error) {
|
||||
const op = "getsockopt"
|
||||
|
||||
var (
|
||||
stats *unix.TpacketStats
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
stats, err = unix.GetsockoptTpacketStats(fd, level, name)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return stats, doErr
|
||||
}
|
||||
return stats, os.NewSyscallError(op, err)
|
||||
}
|
||||
|
||||
// GetSockoptTpacketStatsV3 wraps getsockopt(2) for getting TpacketStatsV3
|
||||
func (c *Conn) GetSockoptTpacketStatsV3(level, name int) (*unix.TpacketStatsV3, error) {
|
||||
const op = "getsockopt"
|
||||
|
||||
var (
|
||||
stats *unix.TpacketStatsV3
|
||||
err error
|
||||
)
|
||||
|
||||
doErr := c.control(op, func(fd int) error {
|
||||
stats, err = unix.GetsockoptTpacketStatsV3(fd, level, name)
|
||||
return err
|
||||
})
|
||||
if doErr != nil {
|
||||
return stats, doErr
|
||||
}
|
||||
return stats, os.NewSyscallError(op, err)
|
||||
}
|
||||
13
src/runtime/vendor/github.com/mdlayher/socket/doc.go
generated
vendored
Normal file
13
src/runtime/vendor/github.com/mdlayher/socket/doc.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// Package socket provides a low-level network connection type which integrates
|
||||
// with Go's runtime network poller to provide asynchronous I/O and deadline
|
||||
// support.
|
||||
//
|
||||
// This package focuses on UNIX-like operating systems which make use of BSD
|
||||
// sockets system call APIs. It is meant to be used as a foundation for the
|
||||
// creation of operating system-specific socket packages, for socket families
|
||||
// such as Linux's AF_NETLINK, AF_PACKET, or AF_VSOCK. This package should not
|
||||
// be 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.
|
||||
package socket
|
||||
10
src/runtime/vendor/github.com/mdlayher/socket/go.mod
generated
vendored
Normal file
10
src/runtime/vendor/github.com/mdlayher/socket/go.mod
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
module github.com/mdlayher/socket
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/google/go-cmp v0.5.6
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6
|
||||
)
|
||||
13
src/runtime/vendor/github.com/mdlayher/socket/go.sum
generated
vendored
Normal file
13
src/runtime/vendor/github.com/mdlayher/socket/go.sum
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
150
src/runtime/vendor/github.com/mdlayher/socket/netns_linux.go
generated
vendored
Normal file
150
src/runtime/vendor/github.com/mdlayher/socket/netns_linux.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package socket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// errNetNSDisabled is returned when network namespaces are unavailable on
|
||||
// a given system.
|
||||
var errNetNSDisabled = errors.New("socket: Linux network namespaces are not enabled on this system")
|
||||
|
||||
// withNetNS invokes fn within the context of the network namespace specified by
|
||||
// fd, while also managing the logic required to safely do so by manipulating
|
||||
// thread-local state.
|
||||
func withNetNS(fd int, fn func() (*Conn, error)) (*Conn, error) {
|
||||
var (
|
||||
eg errgroup.Group
|
||||
conn *Conn
|
||||
)
|
||||
|
||||
eg.Go(func() error {
|
||||
// Retrieve and store the calling OS thread's network namespace so the
|
||||
// thread can be reassigned to it after creating a socket in another network
|
||||
// namespace.
|
||||
runtime.LockOSThread()
|
||||
|
||||
ns, err := threadNetNS()
|
||||
if err != nil {
|
||||
// No thread-local manipulation, unlock.
|
||||
runtime.UnlockOSThread()
|
||||
return err
|
||||
}
|
||||
defer ns.Close()
|
||||
|
||||
// Beyond this point, the thread's network namespace is poisoned. Do not
|
||||
// unlock the OS thread until all network namespace manipulation completes
|
||||
// to avoid returning to the caller with altered thread-local state.
|
||||
|
||||
// Assign the current OS thread the goroutine is locked to to the given
|
||||
// network namespace.
|
||||
if err := ns.Set(fd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Attempt Conn creation and unconditionally restore the original namespace.
|
||||
c, err := fn()
|
||||
if nerr := ns.Restore(); nerr != nil {
|
||||
// Failed to restore original namespace. Return an error and allow the
|
||||
// runtime to terminate the thread.
|
||||
if err == nil {
|
||||
_ = c.Close()
|
||||
}
|
||||
|
||||
return nerr
|
||||
}
|
||||
|
||||
// No more thread-local state manipulation; return the new Conn.
|
||||
runtime.UnlockOSThread()
|
||||
conn = c
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := eg.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// A netNS is a handle that can manipulate network namespaces.
|
||||
//
|
||||
// Operations performed on a netNS must use runtime.LockOSThread before
|
||||
// manipulating any network namespaces.
|
||||
type netNS struct {
|
||||
// The handle to a network namespace.
|
||||
f *os.File
|
||||
|
||||
// Indicates if network namespaces are disabled on this system, and thus
|
||||
// operations should become a no-op or return errors.
|
||||
disabled bool
|
||||
}
|
||||
|
||||
// threadNetNS constructs a netNS using the network namespace of the calling
|
||||
// thread. If the namespace is not the default namespace, runtime.LockOSThread
|
||||
// should be invoked first.
|
||||
func threadNetNS() (*netNS, error) {
|
||||
return fileNetNS(fmt.Sprintf("/proc/self/task/%d/ns/net", unix.Gettid()))
|
||||
}
|
||||
|
||||
// fileNetNS opens file and creates a netNS. fileNetNS should only be called
|
||||
// directly in tests.
|
||||
func fileNetNS(file string) (*netNS, error) {
|
||||
f, err := os.Open(file)
|
||||
switch {
|
||||
case err == nil:
|
||||
return &netNS{f: f}, nil
|
||||
case os.IsNotExist(err):
|
||||
// Network namespaces are not enabled on this system. Use this signal
|
||||
// to return errors elsewhere if the caller explicitly asks for a
|
||||
// network namespace to be set.
|
||||
return &netNS{disabled: true}, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Close releases the handle to a network namespace.
|
||||
func (n *netNS) Close() error {
|
||||
return n.do(func() error { return n.f.Close() })
|
||||
}
|
||||
|
||||
// FD returns a file descriptor which represents the network namespace.
|
||||
func (n *netNS) FD() int {
|
||||
if n.disabled {
|
||||
// No reasonable file descriptor value in this case, so specify a
|
||||
// non-existent one.
|
||||
return -1
|
||||
}
|
||||
|
||||
return int(n.f.Fd())
|
||||
}
|
||||
|
||||
// Restore restores the original network namespace for the calling thread.
|
||||
func (n *netNS) Restore() error {
|
||||
return n.do(func() error { return n.Set(n.FD()) })
|
||||
}
|
||||
|
||||
// Set sets a new network namespace for the current thread using fd.
|
||||
func (n *netNS) Set(fd int) error {
|
||||
return n.do(func() error {
|
||||
return os.NewSyscallError("setns", unix.Setns(fd, unix.CLONE_NEWNET))
|
||||
})
|
||||
}
|
||||
|
||||
// do runs fn if network namespaces are enabled on this system.
|
||||
func (n *netNS) do(fn func() error) error {
|
||||
if n.disabled {
|
||||
return errNetNSDisabled
|
||||
}
|
||||
|
||||
return fn()
|
||||
}
|
||||
14
src/runtime/vendor/github.com/mdlayher/socket/netns_others.go
generated
vendored
Normal file
14
src/runtime/vendor/github.com/mdlayher/socket/netns_others.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package socket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// withNetNS returns an error on non-Linux systems.
|
||||
func withNetNS(_ int, _ func() (*Conn, error)) (*Conn, error) {
|
||||
return nil, fmt.Errorf("socket: Linux network namespace support is not available on %s", runtime.GOOS)
|
||||
}
|
||||
24
src/runtime/vendor/github.com/mdlayher/socket/setbuffer_linux.go
generated
vendored
Normal file
24
src/runtime/vendor/github.com/mdlayher/socket/setbuffer_linux.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package socket
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
// setReadBuffer wraps the SO_RCVBUF{,FORCE} setsockopt(2) options.
|
||||
func (c *Conn) setReadBuffer(bytes int) error {
|
||||
err := c.SetsockoptInt(unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, bytes)
|
||||
if err != nil {
|
||||
err = c.SetsockoptInt(unix.SOL_SOCKET, unix.SO_RCVBUF, bytes)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// setWriteBuffer wraps the SO_SNDBUF{,FORCE} setsockopt(2) options.
|
||||
func (c *Conn) setWriteBuffer(bytes int) error {
|
||||
err := c.SetsockoptInt(unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, bytes)
|
||||
if err != nil {
|
||||
err = c.SetsockoptInt(unix.SOL_SOCKET, unix.SO_SNDBUF, bytes)
|
||||
}
|
||||
return err
|
||||
}
|
||||
16
src/runtime/vendor/github.com/mdlayher/socket/setbuffer_others.go
generated
vendored
Normal file
16
src/runtime/vendor/github.com/mdlayher/socket/setbuffer_others.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package socket
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
// setReadBuffer wraps the SO_RCVBUF setsockopt(2) option.
|
||||
func (c *Conn) setReadBuffer(bytes int) error {
|
||||
return c.SetsockoptInt(unix.SOL_SOCKET, unix.SO_RCVBUF, bytes)
|
||||
}
|
||||
|
||||
// setWriteBuffer wraps the SO_SNDBUF setsockopt(2) option.
|
||||
func (c *Conn) setWriteBuffer(bytes int) error {
|
||||
return c.SetsockoptInt(unix.SOL_SOCKET, unix.SO_SNDBUF, bytes)
|
||||
}
|
||||
12
src/runtime/vendor/github.com/mdlayher/socket/typ_cloexec_nonblock.go
generated
vendored
Normal file
12
src/runtime/vendor/github.com/mdlayher/socket/typ_cloexec_nonblock.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build !darwin
|
||||
// +build !darwin
|
||||
|
||||
package socket
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
const (
|
||||
// These operating systems support CLOEXEC and NONBLOCK socket options.
|
||||
flagCLOEXEC = true
|
||||
socketFlags = unix.SOCK_CLOEXEC | unix.SOCK_NONBLOCK
|
||||
)
|
||||
11
src/runtime/vendor/github.com/mdlayher/socket/typ_none.go
generated
vendored
Normal file
11
src/runtime/vendor/github.com/mdlayher/socket/typ_none.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package socket
|
||||
|
||||
const (
|
||||
// These operating systems do not support CLOEXEC and NONBLOCK socket
|
||||
// options.
|
||||
flagCLOEXEC = false
|
||||
socketFlags = 0
|
||||
)
|
||||
35
src/runtime/vendor/github.com/mdlayher/vsock/CHANGELOG.md
generated
vendored
Normal file
35
src/runtime/vendor/github.com/mdlayher/vsock/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# CHANGELOG
|
||||
|
||||
## Unreleased
|
||||
|
||||
## v1.1.0
|
||||
|
||||
- [New API] [commit](https://github.com/mdlayher/vsock/commit/44cd82dc5f7de644436f22236b111ab97fa9a14f):
|
||||
`vsock.FileListener` can be used to create a `vsock.Listener` from an existing
|
||||
`os.File`, which may be provided by systemd socket activation or another
|
||||
external mechanism.
|
||||
|
||||
## v1.0.1
|
||||
|
||||
- [Bug Fix] [commit](https://github.com/mdlayher/vsock/commit/99a6dccdebad21d1fa5f757d228d677ccb1412dc):
|
||||
upgrade `github.com/mdlayher/socket` to handle non-blocking `connect(2)`
|
||||
errors (called in `vsock.Dial`) properly by checking the `SO_ERROR` socket
|
||||
option. Lock in this behavior with a new test.
|
||||
- [Improvement] [commit](https://github.com/mdlayher/vsock/commit/375f3bbcc363500daf367ec511638a4655471719):
|
||||
downgrade the version of `golang.org/x/net` in use to support Go 1.12. We
|
||||
don't need the latest version for this package.
|
||||
|
||||
## v1.0.0
|
||||
|
||||
**This is the first release of package vsock that only supports Go 1.12+.
|
||||
Users on older versions of Go must use an unstable release.**
|
||||
|
||||
- Initial stable commit!
|
||||
- [API change]: the `vsock.Dial` and `vsock.Listen` constructors now accept an
|
||||
optional `*vsock.Config` parameter to enable future expansion in v1.x.x
|
||||
without prompting further breaking API changes. Because `vsock.Config` has no
|
||||
options as of this release, `nil` may be passed in all call sites to fix
|
||||
existing code upon upgrading to v1.0.0.
|
||||
- [New API]: the `vsock.ListenContextID` function can be used to create a
|
||||
`*vsock.Listener` which is bound to an explicit context ID address, rather
|
||||
than inferring one automatically as `vsock.Listen` does.
|
||||
5
src/runtime/vendor/github.com/mdlayher/vsock/LICENSE.md
generated
vendored
5
src/runtime/vendor/github.com/mdlayher/vsock/LICENSE.md
generated
vendored
@@ -1,7 +1,6 @@
|
||||
MIT License
|
||||
===========
|
||||
# MIT License
|
||||
|
||||
Copyright (C) 2017 Matt Layher
|
||||
Copyright (C) 2017-2022 Matt Layher
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
39
src/runtime/vendor/github.com/mdlayher/vsock/README.md
generated
vendored
39
src/runtime/vendor/github.com/mdlayher/vsock/README.md
generated
vendored
@@ -1,32 +1,30 @@
|
||||
# vsock [](https://builds.sr.ht/~mdlayher/vsock?) [](https://godoc.org/github.com/mdlayher/vsock) [](https://goreportcard.com/report/github.com/mdlayher/vsock)
|
||||
# vsock [](https://github.com/mdlayher/vsock/actions) [](https://pkg.go.dev/github.com/mdlayher/vsock) [](https://goreportcard.com/report/github.com/mdlayher/vsock)
|
||||
|
||||
Package `vsock` provides access to Linux VM sockets (`AF_VSOCK`) for
|
||||
communication between a hypervisor and its virtual machines. MIT Licensed.
|
||||
|
||||
For more information about VM sockets, check out my blog about
|
||||
[Linux VM sockets in Go](https://medium.com/@mdlayher/linux-vm-sockets-in-go-ea11768e9e67).
|
||||
|
||||
## Go version support
|
||||
|
||||
This package supports varying levels of functionality depending on the version
|
||||
of Go used during compilation. The `Listener` and `Conn` types produced by this
|
||||
package are backed by non-blocking I/O, in order to integrate with Go's runtime
|
||||
network poller in Go 1.11+. Additional functionality is available starting in Go
|
||||
1.12+. The older Go 1.10 is only supported in a blocking-only mode.
|
||||
|
||||
A comprehensive list of functionality for supported Go versions can be found on
|
||||
[package vsock's GoDoc page](https://godoc.org/github.com/mdlayher/vsock#hdr-Go_version_support).
|
||||
[Linux VM sockets in Go](https://mdlayher.com/blog/linux-vm-sockets-in-go/).
|
||||
|
||||
## Stability
|
||||
|
||||
At this time, package `vsock` is in a pre-v1.0.0 state. Changes are being made
|
||||
which may impact the exported API of this package and others in its ecosystem.
|
||||
See the [CHANGELOG](./CHANGELOG.md) file for a description of changes between
|
||||
releases.
|
||||
|
||||
**If you depend on this package in your application, please use Go modules when
|
||||
building your application.**
|
||||
This package has a stable v1 API and any future breaking changes will prompt
|
||||
the release of a new major version. Features and bug fixes will continue to
|
||||
occur in the v1.x.x series.
|
||||
|
||||
In order to reduce the maintenance burden, this package is only supported on
|
||||
Go 1.12+. Older versions of Go lack critical features and APIs which are
|
||||
necessary for this package to function correctly.
|
||||
|
||||
**If you depend on this package in your applications, please use Go modules.**
|
||||
|
||||
## Requirements
|
||||
|
||||
**It's possible these requirements are out of date. PRs are welcome.**
|
||||
|
||||
To make use of VM sockets with QEMU and virtio-vsock, you must have:
|
||||
|
||||
- a Linux hypervisor with kernel 4.8+
|
||||
@@ -53,10 +51,3 @@ Check out the
|
||||
[QEMU wiki page on virtio-vsock](http://wiki.qemu-project.org/Features/VirtioVsock)
|
||||
for more details. More detail on setting up this environment will be provided
|
||||
in the future.
|
||||
|
||||
## Usage
|
||||
|
||||
To try out VM sockets and see an example of how they work, see
|
||||
[cmd/vscp](https://github.com/mdlayher/vsock/tree/master/cmd/vscp).
|
||||
This command shows usage of the `vsock.ListenStream` and `vsock.DialStream`
|
||||
APIs, and allows users to easily test VM sockets on their systems.
|
||||
|
||||
83
src/runtime/vendor/github.com/mdlayher/vsock/conn_linux.go
generated
vendored
83
src/runtime/vendor/github.com/mdlayher/vsock/conn_linux.go
generated
vendored
@@ -1,72 +1,55 @@
|
||||
//+build linux
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package vsock
|
||||
|
||||
import (
|
||||
"github.com/mdlayher/socket"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// newConn creates a Conn using a connFD, immediately setting the connFD to
|
||||
// non-blocking mode for use with the runtime network poller.
|
||||
func newConn(cfd connFD, local, remote *Addr) (*Conn, error) {
|
||||
// Note: if any calls fail after this point, cfd.Close should be invoked
|
||||
// for cleanup because the socket is now non-blocking.
|
||||
if err := cfd.SetNonblocking(local.fileName()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Conn{
|
||||
fd: cfd,
|
||||
local: local,
|
||||
remote: remote,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// dial is the entry point for Dial on Linux.
|
||||
func dial(cid, port uint32) (*Conn, error) {
|
||||
cfd, err := newConnFD()
|
||||
func dial(cid, port uint32, _ *Config) (*Conn, error) {
|
||||
// TODO(mdlayher): Config default nil check and initialize. Pass options to
|
||||
// socket.Config where necessary.
|
||||
|
||||
c, err := socket.Socket(unix.AF_VSOCK, unix.SOCK_STREAM, 0, "vsock", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dialLinux(cfd, cid, port)
|
||||
}
|
||||
|
||||
// dialLinux is the entry point for tests on Linux.
|
||||
func dialLinux(cfd connFD, cid, port uint32) (c *Conn, err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
// If any system calls fail during setup, the socket must be closed
|
||||
// to avoid file descriptor leaks.
|
||||
_ = cfd.EarlyClose()
|
||||
}
|
||||
}()
|
||||
|
||||
rsa := &unix.SockaddrVM{
|
||||
CID: cid,
|
||||
Port: port,
|
||||
}
|
||||
|
||||
if err := cfd.Connect(rsa); err != nil {
|
||||
sa := &unix.SockaddrVM{CID: cid, Port: port}
|
||||
rsa, err := c.Connect(sa)
|
||||
if err != nil {
|
||||
_ = c.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lsa, err := cfd.Getsockname()
|
||||
// TODO(mdlayher): getpeername(2) appears to return nil in the GitHub CI
|
||||
// environment, so in the event of a nil sockaddr, fall back to the previous
|
||||
// method of synthesizing the remote address.
|
||||
if rsa == nil {
|
||||
rsa = sa
|
||||
}
|
||||
|
||||
lsa, err := c.Getsockname()
|
||||
if err != nil {
|
||||
_ = c.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lsavm := lsa.(*unix.SockaddrVM)
|
||||
rsavm := rsa.(*unix.SockaddrVM)
|
||||
|
||||
local := &Addr{
|
||||
ContextID: lsavm.CID,
|
||||
Port: lsavm.Port,
|
||||
}
|
||||
|
||||
remote := &Addr{
|
||||
ContextID: cid,
|
||||
Port: port,
|
||||
}
|
||||
|
||||
return newConn(cfd, local, remote)
|
||||
return &Conn{
|
||||
c: c,
|
||||
local: &Addr{
|
||||
ContextID: lsavm.CID,
|
||||
Port: lsavm.Port,
|
||||
},
|
||||
remote: &Addr{
|
||||
ContextID: rsavm.CID,
|
||||
Port: rsavm.Port,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
50
src/runtime/vendor/github.com/mdlayher/vsock/doc.go
generated
vendored
50
src/runtime/vendor/github.com/mdlayher/vsock/doc.go
generated
vendored
@@ -7,54 +7,4 @@
|
||||
// - *Addr implements net.Addr
|
||||
// - *Conn implements net.Conn
|
||||
// - *Listener implements net.Listener
|
||||
//
|
||||
// Go version support
|
||||
//
|
||||
// This package supports varying levels of functionality depending on the version
|
||||
// of Go used during compilation. The Listener and Conn types produced by this
|
||||
// package are backed by non-blocking I/O, in order to integrate with Go's
|
||||
// runtime network poller in Go 1.11+. Additional functionality is available
|
||||
// starting in Go 1.12+.
|
||||
//
|
||||
// Go 1.12+ (recommended):
|
||||
// - *Listener:
|
||||
// - Accept blocks until a connection is received
|
||||
// - Close can interrupt Accept and make it return a permanent error
|
||||
// - SetDeadline can set timeouts which can interrupt Accept and make it return a
|
||||
// temporary error
|
||||
// - *Conn:
|
||||
// - SetDeadline family of methods are fully supported
|
||||
// - CloseRead and CloseWrite can close the reading or writing sides of a
|
||||
// Conn, respectively
|
||||
// - SyscallConn provides access to raw network control/read/write functionality
|
||||
//
|
||||
// Go 1.11 (not recommended):
|
||||
// - *Listener:
|
||||
// - Accept is non-blocking and should be called in a loop, checking for
|
||||
// net.Error.Temporary() == true and sleeping for a short period to avoid wasteful
|
||||
// CPU cycle consumption
|
||||
// - Close makes Accept return a permanent error on the next loop iteration
|
||||
// - SetDeadline is not supported and will always return an error
|
||||
// - *Conn:
|
||||
// - SetDeadline family of methods are fully supported
|
||||
// - CloseRead and CloseWrite are not supported and will always return an error
|
||||
// - SyscallConn is not supported and will always return an error
|
||||
//
|
||||
// Go 1.10 (not recommended):
|
||||
// - *Listener:
|
||||
// - Accept blocks until a connection is received
|
||||
// - Close cannot unblock Accept
|
||||
// - SetDeadline is not supported and will always return an error
|
||||
// - *Conn:
|
||||
// - SetDeadline is not supported and will always return an error
|
||||
// - CloseRead and CloseWrite are not supported and will always return an error
|
||||
// - SyscallConn is not supported and will always return an error
|
||||
//
|
||||
// Stability
|
||||
//
|
||||
// At this time, package vsock is in a pre-v1.0.0 state. Changes are being made
|
||||
// which may impact the exported API of this package and others in its ecosystem.
|
||||
//
|
||||
// If you depend on this package in your application, please use Go modules when
|
||||
// building your application.
|
||||
package vsock
|
||||
|
||||
189
src/runtime/vendor/github.com/mdlayher/vsock/fd_linux.go
generated
vendored
189
src/runtime/vendor/github.com/mdlayher/vsock/fd_linux.go
generated
vendored
@@ -2,10 +2,7 @@ package vsock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
@@ -21,192 +18,6 @@ func contextID() (uint32, error) {
|
||||
return unix.IoctlGetUint32(int(f.Fd()), unix.IOCTL_VM_SOCKETS_GET_LOCAL_CID)
|
||||
}
|
||||
|
||||
// A listenFD is a type that wraps a file descriptor used to implement
|
||||
// net.Listener.
|
||||
type listenFD interface {
|
||||
io.Closer
|
||||
EarlyClose() error
|
||||
Accept4(flags int) (connFD, unix.Sockaddr, error)
|
||||
Bind(sa unix.Sockaddr) error
|
||||
Listen(n int) error
|
||||
Getsockname() (unix.Sockaddr, error)
|
||||
SetNonblocking(name string) error
|
||||
SetDeadline(t time.Time) error
|
||||
}
|
||||
|
||||
var _ listenFD = &sysListenFD{}
|
||||
|
||||
// A sysListenFD is the system call implementation of listenFD.
|
||||
type sysListenFD struct {
|
||||
// These fields should never be non-zero at the same time.
|
||||
fd int // Used in blocking mode.
|
||||
f *os.File // Used in non-blocking mode.
|
||||
}
|
||||
|
||||
// newListenFD creates a sysListenFD in its default blocking mode.
|
||||
func newListenFD() (*sysListenFD, error) {
|
||||
fd, err := socket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &sysListenFD{
|
||||
fd: fd,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Blocking mode methods.
|
||||
|
||||
func (lfd *sysListenFD) Bind(sa unix.Sockaddr) error { return unix.Bind(lfd.fd, sa) }
|
||||
func (lfd *sysListenFD) Getsockname() (unix.Sockaddr, error) { return unix.Getsockname(lfd.fd) }
|
||||
func (lfd *sysListenFD) Listen(n int) error { return unix.Listen(lfd.fd, n) }
|
||||
|
||||
func (lfd *sysListenFD) SetNonblocking(name string) error {
|
||||
return lfd.setNonblocking(name)
|
||||
}
|
||||
|
||||
// EarlyClose is a blocking version of Close, only used for cleanup before
|
||||
// entering non-blocking mode.
|
||||
func (lfd *sysListenFD) EarlyClose() error { return unix.Close(lfd.fd) }
|
||||
|
||||
// Non-blocking mode methods.
|
||||
|
||||
func (lfd *sysListenFD) Accept4(flags int) (connFD, unix.Sockaddr, error) {
|
||||
// Invoke Go version-specific logic for accept.
|
||||
newFD, sa, err := lfd.accept4(flags)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Create a non-blocking connFD which will be used to implement net.Conn.
|
||||
cfd := &sysConnFD{fd: newFD}
|
||||
return cfd, sa, nil
|
||||
}
|
||||
|
||||
func (lfd *sysListenFD) Close() error {
|
||||
// In Go 1.12+, *os.File.Close will also close the runtime network poller
|
||||
// file descriptor, so that net.Listener.Accept can stop blocking.
|
||||
return lfd.f.Close()
|
||||
}
|
||||
|
||||
func (lfd *sysListenFD) SetDeadline(t time.Time) error {
|
||||
// Invoke Go version-specific logic for setDeadline.
|
||||
return lfd.setDeadline(t)
|
||||
}
|
||||
|
||||
// A connFD is a type that wraps a file descriptor used to implement net.Conn.
|
||||
type connFD interface {
|
||||
io.ReadWriteCloser
|
||||
EarlyClose() error
|
||||
Connect(sa unix.Sockaddr) error
|
||||
Getsockname() (unix.Sockaddr, error)
|
||||
Shutdown(how int) error
|
||||
SetNonblocking(name string) error
|
||||
SetDeadline(t time.Time, typ deadlineType) error
|
||||
SyscallConn() (syscall.RawConn, error)
|
||||
}
|
||||
|
||||
var _ connFD = &sysConnFD{}
|
||||
|
||||
// newConnFD creates a sysConnFD in its default blocking mode.
|
||||
func newConnFD() (*sysConnFD, error) {
|
||||
fd, err := socket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &sysConnFD{
|
||||
fd: fd,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// A sysConnFD is the system call implementation of connFD.
|
||||
type sysConnFD struct {
|
||||
// These fields should never be non-zero at the same time.
|
||||
fd int // Used in blocking mode.
|
||||
f *os.File // Used in non-blocking mode.
|
||||
}
|
||||
|
||||
// Blocking mode methods.
|
||||
|
||||
func (cfd *sysConnFD) Connect(sa unix.Sockaddr) error { return unix.Connect(cfd.fd, sa) }
|
||||
func (cfd *sysConnFD) Getsockname() (unix.Sockaddr, error) { return unix.Getsockname(cfd.fd) }
|
||||
|
||||
// EarlyClose is a blocking version of Close, only used for cleanup before
|
||||
// entering non-blocking mode.
|
||||
func (cfd *sysConnFD) EarlyClose() error { return unix.Close(cfd.fd) }
|
||||
|
||||
func (cfd *sysConnFD) SetNonblocking(name string) error {
|
||||
return cfd.setNonblocking(name)
|
||||
}
|
||||
|
||||
// Non-blocking mode methods.
|
||||
|
||||
func (cfd *sysConnFD) Close() error {
|
||||
// *os.File.Close will also close the runtime network poller file descriptor,
|
||||
// so that read/write can stop blocking.
|
||||
return cfd.f.Close()
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) Read(b []byte) (int, error) { return cfd.f.Read(b) }
|
||||
func (cfd *sysConnFD) Write(b []byte) (int, error) { return cfd.f.Write(b) }
|
||||
|
||||
func (cfd *sysConnFD) Shutdown(how int) error {
|
||||
switch how {
|
||||
case unix.SHUT_RD, unix.SHUT_WR:
|
||||
return cfd.shutdown(how)
|
||||
default:
|
||||
panicf("vsock: sysConnFD.Shutdown method invoked with invalid how constant: %d", how)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) SetDeadline(t time.Time, typ deadlineType) error {
|
||||
return cfd.setDeadline(t, typ)
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) SyscallConn() (syscall.RawConn, error) { return cfd.syscallConn() }
|
||||
|
||||
// socket invokes unix.Socket with the correct arguments to produce a vsock
|
||||
// file descriptor.
|
||||
func socket() (int, error) {
|
||||
// "Mirror what the standard library does when creating file
|
||||
// descriptors: avoid racing a fork/exec with the creation
|
||||
// of new file descriptors, so that child processes do not
|
||||
// inherit [socket] file descriptors unexpectedly.
|
||||
//
|
||||
// On Linux, SOCK_CLOEXEC was introduced in 2.6.27. OTOH,
|
||||
// Go supports Linux 2.6.23 and above. If we get EINVAL on
|
||||
// the first try, it may be that we are running on a kernel
|
||||
// older than 2.6.27. In that case, take syscall.ForkLock
|
||||
// and try again without SOCK_CLOEXEC.
|
||||
//
|
||||
// For a more thorough explanation, see similar work in the
|
||||
// Go tree: func sysSocket in net/sock_cloexec.go, as well
|
||||
// as the detailed comment in syscall/exec_unix.go."
|
||||
//
|
||||
// Explanation copied from netlink, courtesy of acln:
|
||||
// https://github.com/mdlayher/netlink/pull/138.
|
||||
fd, err := unix.Socket(unix.AF_VSOCK, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
|
||||
switch err {
|
||||
case nil:
|
||||
return fd, nil
|
||||
case unix.EINVAL:
|
||||
syscall.ForkLock.RLock()
|
||||
defer syscall.ForkLock.RUnlock()
|
||||
|
||||
fd, err = unix.Socket(unix.AF_VSOCK, unix.SOCK_STREAM, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
unix.CloseOnExec(fd)
|
||||
|
||||
return fd, nil
|
||||
default:
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
// isErrno determines if an error a matches UNIX error number.
|
||||
func isErrno(err error, errno int) bool {
|
||||
switch errno {
|
||||
|
||||
63
src/runtime/vendor/github.com/mdlayher/vsock/fd_linux_1.10.go
generated
vendored
63
src/runtime/vendor/github.com/mdlayher/vsock/fd_linux_1.10.go
generated
vendored
@@ -1,63 +0,0 @@
|
||||
//+build go1.10,!go1.11,linux
|
||||
|
||||
package vsock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (lfd *sysListenFD) accept4(flags int) (int, unix.Sockaddr, error) {
|
||||
// In Go 1.11, accept on the raw file descriptor directly, because lfd.f
|
||||
// may be attached to the runtime network poller, forcing this call to block
|
||||
// even if Close is called.
|
||||
return unix.Accept4(lfd.fd, flags)
|
||||
}
|
||||
|
||||
func (lfd *sysListenFD) setNonblocking(name string) error {
|
||||
// Go 1.10 doesn't support non-blocking I/O.
|
||||
if err := unix.SetNonblock(lfd.fd, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lfd.f = os.NewFile(uintptr(lfd.fd), name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*sysListenFD) setDeadline(_ time.Time) error {
|
||||
// Listener deadlines won't work as expected in this version of Go, so
|
||||
// return an early error.
|
||||
return fmt.Errorf("vsock: listener deadlines not supported on %s", runtime.Version())
|
||||
}
|
||||
|
||||
func (*sysConnFD) shutdown(_ int) error {
|
||||
// Shutdown functionality is not available in this version on Go.
|
||||
return fmt.Errorf("vsock: close conn read/write not supported on %s", runtime.Version())
|
||||
}
|
||||
|
||||
func (*sysConnFD) syscallConn() (syscall.RawConn, error) {
|
||||
// SyscallConn functionality is not available in this version on Go.
|
||||
return nil, fmt.Errorf("vsock: syscall conn not supported on %s", runtime.Version())
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) setNonblocking(name string) error {
|
||||
// Go 1.10 doesn't support non-blocking I/O.
|
||||
if err := unix.SetNonblock(cfd.fd, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfd.f = os.NewFile(uintptr(cfd.fd), name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) setDeadline(t time.Time, typ deadlineType) error {
|
||||
// Deadline functionality is not available in this version on Go.
|
||||
return fmt.Errorf("vsock: connection deadlines not supported on %s", runtime.Version())
|
||||
}
|
||||
76
src/runtime/vendor/github.com/mdlayher/vsock/fd_linux_1.11.go
generated
vendored
76
src/runtime/vendor/github.com/mdlayher/vsock/fd_linux_1.11.go
generated
vendored
@@ -1,76 +0,0 @@
|
||||
//+build go1.11,!go1.12,linux
|
||||
|
||||
package vsock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (lfd *sysListenFD) accept4(flags int) (int, unix.Sockaddr, error) {
|
||||
// In Go 1.11, accept on the raw file descriptor directly, because lfd.f
|
||||
// may be attached to the runtime network poller, forcing this call to block
|
||||
// even if Close is called.
|
||||
return unix.Accept4(lfd.fd, flags)
|
||||
}
|
||||
|
||||
func (lfd *sysListenFD) setNonblocking(name string) error {
|
||||
// From now on, we must perform non-blocking I/O, so that our
|
||||
// net.Listener.Accept method can be interrupted by closing the socket.
|
||||
if err := unix.SetNonblock(lfd.fd, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Transition from blocking mode to non-blocking mode.
|
||||
lfd.f = os.NewFile(uintptr(lfd.fd), name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*sysListenFD) setDeadline(_ time.Time) error {
|
||||
// Listener deadlines won't work as expected in this version of Go, so
|
||||
// return an early error.
|
||||
return fmt.Errorf("vsock: listener deadlines not supported on %s", runtime.Version())
|
||||
}
|
||||
|
||||
func (*sysConnFD) shutdown(_ int) error {
|
||||
// Shutdown functionality is not available in this version on Go.
|
||||
return fmt.Errorf("vsock: close conn read/write not supported on %s", runtime.Version())
|
||||
}
|
||||
|
||||
func (*sysConnFD) syscallConn() (syscall.RawConn, error) {
|
||||
// SyscallConn functionality is not available in this version on Go.
|
||||
return nil, fmt.Errorf("vsock: syscall conn not supported on %s", runtime.Version())
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) setNonblocking(name string) error {
|
||||
// From now on, we must perform non-blocking I/O, so that our deadline
|
||||
// methods work, and the connection can be interrupted by net.Conn.Close.
|
||||
if err := unix.SetNonblock(cfd.fd, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Transition from blocking mode to non-blocking mode.
|
||||
cfd.f = os.NewFile(uintptr(cfd.fd), name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) setDeadline(t time.Time, typ deadlineType) error {
|
||||
switch typ {
|
||||
case deadline:
|
||||
return cfd.f.SetDeadline(t)
|
||||
case readDeadline:
|
||||
return cfd.f.SetReadDeadline(t)
|
||||
case writeDeadline:
|
||||
return cfd.f.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
panicf("vsock: sysConnFD.SetDeadline method invoked with invalid deadline type constant: %d", typ)
|
||||
return nil
|
||||
}
|
||||
112
src/runtime/vendor/github.com/mdlayher/vsock/fd_linux_gteq_1.12.go
generated
vendored
112
src/runtime/vendor/github.com/mdlayher/vsock/fd_linux_gteq_1.12.go
generated
vendored
@@ -1,112 +0,0 @@
|
||||
//+build go1.12,linux
|
||||
|
||||
package vsock
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (lfd *sysListenFD) accept4(flags int) (int, unix.Sockaddr, error) {
|
||||
// In Go 1.12+, we make use of runtime network poller integration to allow
|
||||
// net.Listener.Accept to be unblocked by a call to net.Listener.Close.
|
||||
rc, err := lfd.f.SyscallConn()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
newFD int
|
||||
sa unix.Sockaddr
|
||||
)
|
||||
|
||||
doErr := rc.Read(func(fd uintptr) bool {
|
||||
newFD, sa, err = unix.Accept4(int(fd), flags)
|
||||
|
||||
switch err {
|
||||
case unix.EAGAIN, unix.ECONNABORTED:
|
||||
// Return false to let the poller wait for readiness. See the
|
||||
// source code for internal/poll.FD.RawRead for more details.
|
||||
//
|
||||
// When the socket is in non-blocking mode, we might see EAGAIN if
|
||||
// the socket is not ready for reading.
|
||||
//
|
||||
// In addition, the network poller's accept implementation also
|
||||
// deals with ECONNABORTED, in case a socket is closed before it is
|
||||
// pulled from our listen queue.
|
||||
return false
|
||||
default:
|
||||
// No error or some unrecognized error, treat this Read operation
|
||||
// as completed.
|
||||
return true
|
||||
}
|
||||
})
|
||||
if doErr != nil {
|
||||
return 0, nil, doErr
|
||||
}
|
||||
|
||||
return newFD, sa, err
|
||||
}
|
||||
|
||||
func (lfd *sysListenFD) setDeadline(t time.Time) error { return lfd.f.SetDeadline(t) }
|
||||
|
||||
func (lfd *sysListenFD) setNonblocking(name string) error {
|
||||
// From now on, we must perform non-blocking I/O, so that our
|
||||
// net.Listener.Accept method can be interrupted by closing the socket.
|
||||
if err := unix.SetNonblock(lfd.fd, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Transition from blocking mode to non-blocking mode.
|
||||
lfd.f = os.NewFile(uintptr(lfd.fd), name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) shutdown(how int) error {
|
||||
rc, err := cfd.f.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
doErr := rc.Control(func(fd uintptr) {
|
||||
err = unix.Shutdown(int(fd), how)
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) syscallConn() (syscall.RawConn, error) { return cfd.f.SyscallConn() }
|
||||
|
||||
func (cfd *sysConnFD) setNonblocking(name string) error {
|
||||
// From now on, we must perform non-blocking I/O, so that our deadline
|
||||
// methods work, and the connection can be interrupted by net.Conn.Close.
|
||||
if err := unix.SetNonblock(cfd.fd, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Transition from blocking mode to non-blocking mode.
|
||||
cfd.f = os.NewFile(uintptr(cfd.fd), name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfd *sysConnFD) setDeadline(t time.Time, typ deadlineType) error {
|
||||
switch typ {
|
||||
case deadline:
|
||||
return cfd.f.SetDeadline(t)
|
||||
case readDeadline:
|
||||
return cfd.f.SetReadDeadline(t)
|
||||
case writeDeadline:
|
||||
return cfd.f.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
panicf("vsock: sysConnFD.SetDeadline method invoked with invalid deadline type constant: %d", typ)
|
||||
return nil
|
||||
}
|
||||
7
src/runtime/vendor/github.com/mdlayher/vsock/go.mod
generated
vendored
7
src/runtime/vendor/github.com/mdlayher/vsock/go.mod
generated
vendored
@@ -3,7 +3,8 @@ module github.com/mdlayher/vsock
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/google/go-cmp v0.3.1
|
||||
golang.org/x/net v0.0.0-20191108221443-4ba9e2ef068c
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd
|
||||
github.com/google/go-cmp v0.5.7
|
||||
github.com/mdlayher/socket v0.2.0
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c
|
||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a
|
||||
)
|
||||
|
||||
23
src/runtime/vendor/github.com/mdlayher/vsock/go.sum
generated
vendored
23
src/runtime/vendor/github.com/mdlayher/vsock/go.sum
generated
vendored
@@ -1,16 +1,17 @@
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/mdlayher/socket v0.2.0 h1:EY4YQd6hTAg2tcXF84p5DTHazShE50u5HeBzBaNgjkA=
|
||||
github.com/mdlayher/socket v0.2.0/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20191108221443-4ba9e2ef068c h1:SRpq/kuj/xNci/RdvEs+RSvpfxqvLAzTKuKGlzoGdZQ=
|
||||
golang.org/x/net v0.0.0-20191108221443-4ba9e2ef068c/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
|
||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII=
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a h1:ppl5mZgokTT8uPkmYOyEUmPTr3ypaKkg5eFOGrAmxxE=
|
||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
109
src/runtime/vendor/github.com/mdlayher/vsock/listener_linux.go
generated
vendored
109
src/runtime/vendor/github.com/mdlayher/vsock/listener_linux.go
generated
vendored
@@ -1,11 +1,14 @@
|
||||
//+build linux
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package vsock
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/mdlayher/socket"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -14,93 +17,107 @@ var _ net.Listener = &listener{}
|
||||
// A listener is the net.Listener implementation for connection-oriented
|
||||
// VM sockets.
|
||||
type listener struct {
|
||||
fd listenFD
|
||||
c *socket.Conn
|
||||
addr *Addr
|
||||
}
|
||||
|
||||
// Addr and Close implement the net.Listener interface for listener.
|
||||
func (l *listener) Addr() net.Addr { return l.addr }
|
||||
func (l *listener) Close() error { return l.fd.Close() }
|
||||
func (l *listener) SetDeadline(t time.Time) error { return l.fd.SetDeadline(t) }
|
||||
func (l *listener) Close() error { return l.c.Close() }
|
||||
func (l *listener) SetDeadline(t time.Time) error { return l.c.SetDeadline(t) }
|
||||
|
||||
// Accept accepts a single connection from the listener, and sets up
|
||||
// a net.Conn backed by conn.
|
||||
func (l *listener) Accept() (net.Conn, error) {
|
||||
// Mimic what internal/poll does and close on exec, but leave it up to
|
||||
// newConn to set non-blocking mode.
|
||||
// See: https://golang.org/src/internal/poll/sock_cloexec.go.
|
||||
//
|
||||
// TODO(mdlayher): acquire syscall.ForkLock.RLock here once the Go 1.11
|
||||
// code can be removed and we're fully using the runtime network poller in
|
||||
// non-blocking mode.
|
||||
cfd, sa, err := l.fd.Accept4(unix.SOCK_CLOEXEC)
|
||||
c, rsa, err := l.c.Accept(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
savm := sa.(*unix.SockaddrVM)
|
||||
savm := rsa.(*unix.SockaddrVM)
|
||||
remote := &Addr{
|
||||
ContextID: savm.CID,
|
||||
Port: savm.Port,
|
||||
}
|
||||
|
||||
return newConn(cfd, l.addr, remote)
|
||||
return &Conn{
|
||||
c: c,
|
||||
local: l.addr,
|
||||
remote: remote,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// name is the socket name passed to package socket.
|
||||
const name = "vsock"
|
||||
|
||||
// listen is the entry point for Listen on Linux.
|
||||
func listen(cid, port uint32) (*Listener, error) {
|
||||
lfd, err := newListenFD()
|
||||
func listen(cid, port uint32, _ *Config) (*Listener, error) {
|
||||
// TODO(mdlayher): Config default nil check and initialize. Pass options to
|
||||
// socket.Config where necessary.
|
||||
|
||||
c, err := socket.Socket(unix.AF_VSOCK, unix.SOCK_STREAM, 0, name, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return listenLinux(lfd, cid, port)
|
||||
}
|
||||
// Be sure to close the Conn if any of the system calls fail before we
|
||||
// return the Conn to the caller.
|
||||
|
||||
// listenLinux is the entry point for tests on Linux.
|
||||
func listenLinux(lfd listenFD, cid, port uint32) (l *Listener, err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
// If any system calls fail during setup, the socket must be closed
|
||||
// to avoid file descriptor leaks.
|
||||
_ = lfd.EarlyClose()
|
||||
}
|
||||
}()
|
||||
|
||||
// Zero-value for "any port" is friendlier in Go than a constant.
|
||||
if port == 0 {
|
||||
port = unix.VMADDR_PORT_ANY
|
||||
}
|
||||
|
||||
sa := &unix.SockaddrVM{
|
||||
CID: cid,
|
||||
Port: port,
|
||||
}
|
||||
|
||||
if err := lfd.Bind(sa); err != nil {
|
||||
if err := c.Bind(&unix.SockaddrVM{CID: cid, Port: port}); err != nil {
|
||||
_ = c.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := lfd.Listen(unix.SOMAXCONN); err != nil {
|
||||
if err := c.Listen(unix.SOMAXCONN); err != nil {
|
||||
_ = c.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lsa, err := lfd.Getsockname()
|
||||
l, err := newListener(c)
|
||||
if err != nil {
|
||||
_ = c.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// fileListener is the entry point for FileListener on Linux.
|
||||
func fileListener(f *os.File) (*Listener, error) {
|
||||
c, err := socket.FileConn(f, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Done with blocking mode setup, transition to non-blocking before the
|
||||
// caller has a chance to start calling things concurrently that might make
|
||||
// the locking situation tricky.
|
||||
//
|
||||
// Note: if any calls fail after this point, lfd.Close should be invoked
|
||||
// for cleanup because the socket is now non-blocking.
|
||||
if err := lfd.SetNonblocking("vsock-listen"); err != nil {
|
||||
l, err := newListener(c)
|
||||
if err != nil {
|
||||
_ = c.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lsavm := lsa.(*unix.SockaddrVM)
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// newListener creates a Listener from a raw socket.Conn.
|
||||
func newListener(c *socket.Conn) (*Listener, error) {
|
||||
lsa, err := c.Getsockname()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now that the library can also accept arbitrary os.Files, we have to
|
||||
// verify the address family so we don't accidentally create a
|
||||
// *vsock.Listener backed by TCP or some other socket type.
|
||||
lsavm, ok := lsa.(*unix.SockaddrVM)
|
||||
if !ok {
|
||||
// All errors should wrapped with os.SyscallError.
|
||||
return nil, os.NewSyscallError("listen", unix.EINVAL)
|
||||
}
|
||||
|
||||
addr := &Addr{
|
||||
ContextID: lsavm.CID,
|
||||
Port: lsavm.Port,
|
||||
@@ -108,7 +125,7 @@ func listenLinux(lfd listenFD, cid, port uint32) (l *Listener, err error) {
|
||||
|
||||
return &Listener{
|
||||
l: &listener{
|
||||
fd: lfd,
|
||||
c: c,
|
||||
addr: addr,
|
||||
},
|
||||
}, nil
|
||||
|
||||
154
src/runtime/vendor/github.com/mdlayher/vsock/vsock.go
generated
vendored
154
src/runtime/vendor/github.com/mdlayher/vsock/vsock.go
generated
vendored
@@ -9,26 +9,27 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/mdlayher/socket"
|
||||
)
|
||||
|
||||
const (
|
||||
// Hypervisor specifies that a socket should communicate with the hypervisor
|
||||
// process.
|
||||
// process. Note that this is _not_ the same as a socket owned by a process
|
||||
// running on the hypervisor. Most users should probably use Host instead.
|
||||
Hypervisor = 0x0
|
||||
|
||||
// Local specifies that a socket should communicate with a matching socket
|
||||
// on the same machine. This provides an alternative to UNIX sockets or
|
||||
// similar and may be useful in testing VM sockets applications.
|
||||
Local = 0x1
|
||||
|
||||
// Host specifies that a socket should communicate with processes other than
|
||||
// the hypervisor on the host machine.
|
||||
// the hypervisor on the host machine. This is the correct choice to
|
||||
// communicate with a process running on a hypervisor using a socket dialed
|
||||
// from a guest.
|
||||
Host = 0x2
|
||||
|
||||
// cidReserved is a reserved context ID that is no longer in use,
|
||||
// and cannot be used for socket communications.
|
||||
cidReserved = 0x1
|
||||
|
||||
// shutRd and shutWr are arguments for unix.Shutdown, copied here to avoid
|
||||
// importing x/sys/unix in cross-platform code.
|
||||
shutRd = 0 // unix.SHUT_RD
|
||||
shutWr = 1 // unix.SHUT_WR
|
||||
|
||||
// Error numbers we recognize, copied here to avoid importing x/sys/unix in
|
||||
// cross-platform code.
|
||||
ebadf = 9
|
||||
@@ -55,25 +56,47 @@ const (
|
||||
opWrite = "write"
|
||||
)
|
||||
|
||||
// TODO(mdlayher): plumb through socket.Config.NetNS if it makes sense.
|
||||
|
||||
// Config contains options for a Conn or Listener.
|
||||
type Config struct{}
|
||||
|
||||
// Listen opens a connection-oriented net.Listener for incoming VM sockets
|
||||
// connections. The port parameter specifies the port for the Listener.
|
||||
// connections. The port parameter specifies the port for the Listener. Config
|
||||
// specifies optional configuration for the Listener. If config is nil, a
|
||||
// default configuration will be used.
|
||||
//
|
||||
// To allow the server to assign a port automatically, specify 0 for port.
|
||||
// The address of the server can be retrieved using the Addr method.
|
||||
// To allow the server to assign a port automatically, specify 0 for port. The
|
||||
// address of the server can be retrieved using the Addr method.
|
||||
//
|
||||
// When the Listener is no longer needed, Close must be called to free resources.
|
||||
func Listen(port uint32) (*Listener, error) {
|
||||
// Listen automatically infers the appropriate context ID for this machine by
|
||||
// calling ContextID and passing that value to ListenContextID. Callers with
|
||||
// advanced use cases (such as using the Local context ID) may wish to use
|
||||
// ListenContextID directly.
|
||||
//
|
||||
// When the Listener is no longer needed, Close must be called to free
|
||||
// resources.
|
||||
func Listen(port uint32, cfg *Config) (*Listener, error) {
|
||||
cid, err := ContextID()
|
||||
if err != nil {
|
||||
// No addresses available.
|
||||
return nil, opError(opListen, err, nil, nil)
|
||||
}
|
||||
|
||||
l, err := listen(cid, port)
|
||||
return ListenContextID(cid, port, cfg)
|
||||
}
|
||||
|
||||
// ListenContextID is the same as Listen, but also accepts an explicit context
|
||||
// ID parameter. This function is intended for advanced use cases and most
|
||||
// callers should use Listen instead.
|
||||
//
|
||||
// See the documentation of Listen for more details.
|
||||
func ListenContextID(contextID, port uint32, cfg *Config) (*Listener, error) {
|
||||
l, err := listen(contextID, port, cfg)
|
||||
if err != nil {
|
||||
// No remote address available.
|
||||
return nil, opError(opListen, err, &Addr{
|
||||
ContextID: cid,
|
||||
ContextID: contextID,
|
||||
Port: port,
|
||||
}, nil)
|
||||
}
|
||||
@@ -81,6 +104,23 @@ func Listen(port uint32) (*Listener, error) {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// FileListener returns a copy of the network listener corresponding to an open
|
||||
// os.File. It is the caller's responsibility to close the Listener when
|
||||
// finished. Closing the Listener does not affect the os.File, and closing the
|
||||
// os.File does not affect the Listener.
|
||||
//
|
||||
// This function is intended for advanced use cases and most callers should use
|
||||
// Listen instead.
|
||||
func FileListener(f *os.File) (*Listener, error) {
|
||||
l, err := fileListener(f)
|
||||
if err != nil {
|
||||
// No addresses available.
|
||||
return nil, opError(opListen, err, nil, nil)
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
var _ net.Listener = &Listener{}
|
||||
|
||||
// A Listener is a VM sockets implementation of a net.Listener.
|
||||
@@ -112,8 +152,6 @@ func (l *Listener) Close() error {
|
||||
|
||||
// SetDeadline sets the deadline associated with the listener. A zero time value
|
||||
// disables the deadline.
|
||||
//
|
||||
// SetDeadline only works with Go 1.12+.
|
||||
func (l *Listener) SetDeadline(t time.Time) error {
|
||||
return l.opError(opSet, l.l.SetDeadline(t))
|
||||
}
|
||||
@@ -125,8 +163,10 @@ func (l *Listener) opError(op string, err error) error {
|
||||
return opError(op, err, l.Addr(), nil)
|
||||
}
|
||||
|
||||
// Dial dials a connection-oriented net.Conn to a VM sockets server.
|
||||
// The contextID and port parameters specify the address of the server.
|
||||
// Dial dials a connection-oriented net.Conn to a VM sockets listener. The
|
||||
// context ID and port parameters specify the address of the listener. Config
|
||||
// specifies optional configuration for the Conn. If config is nil, a default
|
||||
// configuration will be used.
|
||||
//
|
||||
// If dialing a connection from the hypervisor to a virtual machine, the VM's
|
||||
// context ID should be specified.
|
||||
@@ -135,9 +175,10 @@ func (l *Listener) opError(op string, err error) error {
|
||||
// communicate with the hypervisor process, or Host should be used to
|
||||
// communicate with other processes on the host machine.
|
||||
//
|
||||
// When the connection is no longer needed, Close must be called to free resources.
|
||||
func Dial(contextID, port uint32) (*Conn, error) {
|
||||
c, err := dial(contextID, port)
|
||||
// When the connection is no longer needed, Close must be called to free
|
||||
// resources.
|
||||
func Dial(contextID, port uint32, cfg *Config) (*Conn, error) {
|
||||
c, err := dial(contextID, port, cfg)
|
||||
if err != nil {
|
||||
// No local address, but we have a remote address we can return.
|
||||
return nil, opError(opDial, err, nil, &Addr{
|
||||
@@ -149,35 +190,33 @@ func Dial(contextID, port uint32) (*Conn, error) {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
var _ net.Conn = &Conn{}
|
||||
var _ syscall.Conn = &Conn{}
|
||||
var (
|
||||
_ net.Conn = &Conn{}
|
||||
_ syscall.Conn = &Conn{}
|
||||
)
|
||||
|
||||
// A Conn is a VM sockets implementation of a net.Conn.
|
||||
type Conn struct {
|
||||
fd connFD
|
||||
c *socket.Conn
|
||||
local *Addr
|
||||
remote *Addr
|
||||
}
|
||||
|
||||
// Close closes the connection.
|
||||
func (c *Conn) Close() error {
|
||||
return c.opError(opClose, c.fd.Close())
|
||||
return c.opError(opClose, c.c.Close())
|
||||
}
|
||||
|
||||
// CloseRead shuts down the reading side of the VM sockets connection. Most
|
||||
// callers should just use Close.
|
||||
//
|
||||
// CloseRead only works with Go 1.12+.
|
||||
func (c *Conn) CloseRead() error {
|
||||
return c.opError(opClose, c.fd.Shutdown(shutRd))
|
||||
return c.opError(opClose, c.c.CloseRead())
|
||||
}
|
||||
|
||||
// CloseWrite shuts down the writing side of the VM sockets connection. Most
|
||||
// callers should just use Close.
|
||||
//
|
||||
// CloseWrite only works with Go 1.12+.
|
||||
func (c *Conn) CloseWrite() error {
|
||||
return c.opError(opClose, c.fd.Shutdown(shutWr))
|
||||
return c.opError(opClose, c.c.CloseWrite())
|
||||
}
|
||||
|
||||
// LocalAddr returns the local network address. The Addr returned is shared by
|
||||
@@ -190,7 +229,7 @@ func (c *Conn) RemoteAddr() net.Addr { return c.remote }
|
||||
|
||||
// Read implements the net.Conn Read method.
|
||||
func (c *Conn) Read(b []byte) (int, error) {
|
||||
n, err := c.fd.Read(b)
|
||||
n, err := c.c.Read(b)
|
||||
if err != nil {
|
||||
return n, c.opError(opRead, err)
|
||||
}
|
||||
@@ -200,7 +239,7 @@ func (c *Conn) Read(b []byte) (int, error) {
|
||||
|
||||
// Write implements the net.Conn Write method.
|
||||
func (c *Conn) Write(b []byte) (int, error) {
|
||||
n, err := c.fd.Write(b)
|
||||
n, err := c.c.Write(b)
|
||||
if err != nil {
|
||||
return n, c.opError(opWrite, err)
|
||||
}
|
||||
@@ -208,35 +247,25 @@ func (c *Conn) Write(b []byte) (int, error) {
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// A deadlineType specifies the type of deadline to set for a Conn.
|
||||
type deadlineType int
|
||||
|
||||
// Possible deadlineType values.
|
||||
const (
|
||||
deadline deadlineType = iota
|
||||
readDeadline
|
||||
writeDeadline
|
||||
)
|
||||
|
||||
// SetDeadline implements the net.Conn SetDeadline method.
|
||||
func (c *Conn) SetDeadline(t time.Time) error {
|
||||
return c.opError(opSet, c.fd.SetDeadline(t, deadline))
|
||||
return c.opError(opSet, c.c.SetDeadline(t))
|
||||
}
|
||||
|
||||
// SetReadDeadline implements the net.Conn SetReadDeadline method.
|
||||
func (c *Conn) SetReadDeadline(t time.Time) error {
|
||||
return c.opError(opSet, c.fd.SetDeadline(t, readDeadline))
|
||||
return c.opError(opSet, c.c.SetReadDeadline(t))
|
||||
}
|
||||
|
||||
// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
return c.opError(opSet, c.fd.SetDeadline(t, writeDeadline))
|
||||
return c.opError(opSet, c.c.SetWriteDeadline(t))
|
||||
}
|
||||
|
||||
// SyscallConn returns a raw network connection. This implements the
|
||||
// syscall.Conn interface.
|
||||
func (c *Conn) SyscallConn() (syscall.RawConn, error) {
|
||||
rc, err := c.fd.SyscallConn()
|
||||
rc, err := c.c.SyscallConn()
|
||||
if err != nil {
|
||||
return nil, c.opError(opSyscallConn, err)
|
||||
}
|
||||
@@ -254,14 +283,17 @@ func (c *Conn) opError(op string, err error) error {
|
||||
return opError(op, err, c.local, c.remote)
|
||||
}
|
||||
|
||||
// TODO(mdlayher): see if we can port smarter net.OpError with local/remote
|
||||
// address error logic into socket.Conn's SyscallConn type to avoid the need for
|
||||
// this wrapper.
|
||||
|
||||
var _ syscall.RawConn = &rawConn{}
|
||||
|
||||
// A rawConn is a syscall.RawConn that wraps an internal syscall.RawConn in order
|
||||
// to produce net.OpError error values.
|
||||
type rawConn struct {
|
||||
rc syscall.RawConn
|
||||
local *Addr
|
||||
remote *Addr
|
||||
rc syscall.RawConn
|
||||
local, remote *Addr
|
||||
}
|
||||
|
||||
// Control implements the syscall.RawConn Control method.
|
||||
@@ -289,8 +321,7 @@ var _ net.Addr = &Addr{}
|
||||
|
||||
// An Addr is the address of a VM sockets endpoint.
|
||||
type Addr struct {
|
||||
ContextID uint32
|
||||
Port uint32
|
||||
ContextID, Port uint32
|
||||
}
|
||||
|
||||
// Network returns the address's network name, "vsock".
|
||||
@@ -304,8 +335,8 @@ func (a *Addr) String() string {
|
||||
switch a.ContextID {
|
||||
case Hypervisor:
|
||||
host = fmt.Sprintf("hypervisor(%d)", a.ContextID)
|
||||
case cidReserved:
|
||||
host = fmt.Sprintf("reserved(%d)", a.ContextID)
|
||||
case Local:
|
||||
host = fmt.Sprintf("local(%d)", a.ContextID)
|
||||
case Host:
|
||||
host = fmt.Sprintf("host(%d)", a.ContextID)
|
||||
default:
|
||||
@@ -338,6 +369,13 @@ func opError(op string, err error, local, remote net.Addr) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(mdlayher): this entire function is suspect and should probably be
|
||||
// looked at carefully, especially with Go 1.13+ error wrapping.
|
||||
//
|
||||
// Eventually this *net.OpError logic should probably be ported into
|
||||
// mdlayher/socket because similar checks are necessary to comply with
|
||||
// nettest.TestConn.
|
||||
|
||||
// Unwrap inner errors from error types.
|
||||
//
|
||||
// TODO(mdlayher): errors.Cause or similar in Go 1.13.
|
||||
|
||||
31
src/runtime/vendor/github.com/mdlayher/vsock/vsock_others.go
generated
vendored
31
src/runtime/vendor/github.com/mdlayher/vsock/vsock_others.go
generated
vendored
@@ -1,23 +1,23 @@
|
||||
//+build !linux
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package vsock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// errUnimplemented is returned by all functions on platforms that
|
||||
// cannot make use of VM sockets.
|
||||
errUnimplemented = fmt.Errorf("vsock: not implemented on %s/%s",
|
||||
runtime.GOOS, runtime.GOARCH)
|
||||
)
|
||||
// errUnimplemented is returned by all functions on platforms that
|
||||
// cannot make use of VM sockets.
|
||||
var errUnimplemented = fmt.Errorf("vsock: not implemented on %s/%s",
|
||||
runtime.GOOS, runtime.GOARCH)
|
||||
|
||||
func listen(_, _ uint32) (*Listener, error) { return nil, errUnimplemented }
|
||||
func fileListener(_ *os.File) (*Listener, error) { return nil, errUnimplemented }
|
||||
func listen(_, _ uint32, _ *Config) (*Listener, error) { return nil, errUnimplemented }
|
||||
|
||||
type listener struct{}
|
||||
|
||||
@@ -26,18 +26,7 @@ func (*listener) Addr() net.Addr { return nil }
|
||||
func (*listener) Close() error { return errUnimplemented }
|
||||
func (*listener) SetDeadline(_ time.Time) error { return errUnimplemented }
|
||||
|
||||
func dial(_, _ uint32) (*Conn, error) { return nil, errUnimplemented }
|
||||
|
||||
type connFD struct{}
|
||||
|
||||
func (*connFD) LocalAddr() net.Addr { return nil }
|
||||
func (*connFD) RemoteAddr() net.Addr { return nil }
|
||||
func (*connFD) SetDeadline(_ time.Time, _ deadlineType) error { return errUnimplemented }
|
||||
func (*connFD) Read(_ []byte) (int, error) { return 0, errUnimplemented }
|
||||
func (*connFD) Write(_ []byte) (int, error) { return 0, errUnimplemented }
|
||||
func (*connFD) Close() error { return errUnimplemented }
|
||||
func (*connFD) Shutdown(_ int) error { return errUnimplemented }
|
||||
func (*connFD) SyscallConn() (syscall.RawConn, error) { return nil, errUnimplemented }
|
||||
func dial(_, _ uint32, _ *Config) (*Conn, error) { return nil, errUnimplemented }
|
||||
|
||||
func contextID() (uint32, error) { return 0, errUnimplemented }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user