runtime: use github.com/mdlayher/vsock@v1.1.0

Fixes #3625
Signed-off-by: Matt Layher <mdlayher@gmail.com>
This commit is contained in:
Matt Layher 2022-02-04 20:06:12 -05:00
parent 88a70d32ba
commit c1ce67d905
No known key found for this signature in database
GPG Key ID: 77BFE531397EDE94
141 changed files with 6339 additions and 1877 deletions

View File

@ -28,7 +28,7 @@ require (
github.com/gogo/protobuf v1.3.2
github.com/hashicorp/go-multierror v1.0.0
github.com/intel-go/cpuid v0.0.0-20210602155658-5747e5cec0d9
github.com/mdlayher/vsock v0.0.0-20191108225356-d9c65923cb8f
github.com/mdlayher/vsock v1.1.0
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/runc v1.0.3
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
@ -49,9 +49,9 @@ require (
go.opentelemetry.io/otel/exporters/jaeger v1.0.0
go.opentelemetry.io/otel/sdk v1.0.1
go.opentelemetry.io/otel/trace v1.0.1
golang.org/x/net v0.0.0-20210825183410-e898025ed96a
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/grpc v1.41.0
k8s.io/apimachinery v0.22.0

View File

@ -479,8 +479,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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=
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/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
@ -617,8 +618,10 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/mdlayher/vsock v0.0.0-20191108225356-d9c65923cb8f h1:t9bhAC/9+wqdIb49Jamux+Sxqa7MhkyuTtsHkmVg6tk=
github.com/mdlayher/vsock v0.0.0-20191108225356-d9c65923cb8f/go.mod h1:4GtNxrXX+cNil8xnCdz0zGYemDZDDHSsXbopCRZrRRw=
github.com/mdlayher/socket v0.2.0 h1:EY4YQd6hTAg2tcXF84p5DTHazShE50u5HeBzBaNgjkA=
github.com/mdlayher/socket v0.2.0/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
github.com/mdlayher/vsock v1.1.0 h1:2k9udP/hUkLUOboGxXMHOk4f0GWWZwS3IuE3Ee/YYfk=
github.com/mdlayher/vsock v1.1.0/go.mod h1:nsVhPsVuBBwAKh6i6PzdNoke6/TNYTjkxoRKAp/+pXs=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
@ -988,7 +991,6 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191108221443-4ba9e2ef068c/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -1014,8 +1016,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1066,7 +1069,6 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1116,22 +1118,28 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/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/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View 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).

View 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.

View File

@ -0,0 +1,14 @@
# socket [![Test Status](https://github.com/mdlayher/socket/workflows/Test/badge.svg)](https://github.com/mdlayher/socket/actions) [![Go Reference](https://pkg.go.dev/badge/github.com/mdlayher/socket.svg)](https://pkg.go.dev/github.com/mdlayher/socket) [![Go Report Card](https://goreportcard.com/badge/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.

View 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)
}

View 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
View 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
}
}

View 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
View 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
View 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
View 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=

View 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()
}

View 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)
}

View 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
}

View 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)
}

View 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
)

View 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
)

View 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.

View File

@ -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:

View File

@ -1,32 +1,30 @@
# vsock [![builds.sr.ht status](https://builds.sr.ht/~mdlayher/vsock.svg)](https://builds.sr.ht/~mdlayher/vsock?) [![GoDoc](https://godoc.org/github.com/mdlayher/vsock?status.svg)](https://godoc.org/github.com/mdlayher/vsock) [![Go Report Card](https://goreportcard.com/badge/github.com/mdlayher/vsock)](https://goreportcard.com/report/github.com/mdlayher/vsock)
# vsock [![Test Status](https://github.com/mdlayher/vsock/workflows/Linux%20Test/badge.svg)](https://github.com/mdlayher/vsock/actions) [![Go Reference](https://pkg.go.dev/badge/github.com/mdlayher/vsock.svg)](https://pkg.go.dev/github.com/mdlayher/vsock) [![Go Report Card](https://goreportcard.com/badge/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.

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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())
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
)

View File

@ -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=

View File

@ -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

View File

@ -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.

View File

@ -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 }

41
src/runtime/vendor/golang.org/x/net/bpf/asm.go generated vendored Normal file
View File

@ -0,0 +1,41 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
import "fmt"
// Assemble converts insts into raw instructions suitable for loading
// into a BPF virtual machine.
//
// Currently, no optimization is attempted, the assembled program flow
// is exactly as provided.
func Assemble(insts []Instruction) ([]RawInstruction, error) {
ret := make([]RawInstruction, len(insts))
var err error
for i, inst := range insts {
ret[i], err = inst.Assemble()
if err != nil {
return nil, fmt.Errorf("assembling instruction %d: %s", i+1, err)
}
}
return ret, nil
}
// Disassemble attempts to parse raw back into
// Instructions. Unrecognized RawInstructions are assumed to be an
// extension not implemented by this package, and are passed through
// unchanged to the output. The allDecoded value reports whether insts
// contains no RawInstructions.
func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded bool) {
insts = make([]Instruction, len(raw))
allDecoded = true
for i, r := range raw {
insts[i] = r.Disassemble()
if _, ok := insts[i].(RawInstruction); ok {
allDecoded = false
}
}
return insts, allDecoded
}

222
src/runtime/vendor/golang.org/x/net/bpf/constants.go generated vendored Normal file
View File

@ -0,0 +1,222 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
// A Register is a register of the BPF virtual machine.
type Register uint16
const (
// RegA is the accumulator register. RegA is always the
// destination register of ALU operations.
RegA Register = iota
// RegX is the indirection register, used by LoadIndirect
// operations.
RegX
)
// An ALUOp is an arithmetic or logic operation.
type ALUOp uint16
// ALU binary operation types.
const (
ALUOpAdd ALUOp = iota << 4
ALUOpSub
ALUOpMul
ALUOpDiv
ALUOpOr
ALUOpAnd
ALUOpShiftLeft
ALUOpShiftRight
aluOpNeg // Not exported because it's the only unary ALU operation, and gets its own instruction type.
ALUOpMod
ALUOpXor
)
// A JumpTest is a comparison operator used in conditional jumps.
type JumpTest uint16
// Supported operators for conditional jumps.
// K can be RegX for JumpIfX
const (
// K == A
JumpEqual JumpTest = iota
// K != A
JumpNotEqual
// K > A
JumpGreaterThan
// K < A
JumpLessThan
// K >= A
JumpGreaterOrEqual
// K <= A
JumpLessOrEqual
// K & A != 0
JumpBitsSet
// K & A == 0
JumpBitsNotSet
)
// An Extension is a function call provided by the kernel that
// performs advanced operations that are expensive or impossible
// within the BPF virtual machine.
//
// Extensions are only implemented by the Linux kernel.
//
// TODO: should we prune this list? Some of these extensions seem
// either broken or near-impossible to use correctly, whereas other
// (len, random, ifindex) are quite useful.
type Extension int
// Extension functions available in the Linux kernel.
const (
// extOffset is the negative maximum number of instructions used
// to load instructions by overloading the K argument.
extOffset = -0x1000
// ExtLen returns the length of the packet.
ExtLen Extension = 1
// ExtProto returns the packet's L3 protocol type.
ExtProto Extension = 0
// ExtType returns the packet's type (skb->pkt_type in the kernel)
//
// TODO: better documentation. How nice an API do we want to
// provide for these esoteric extensions?
ExtType Extension = 4
// ExtPayloadOffset returns the offset of the packet payload, or
// the first protocol header that the kernel does not know how to
// parse.
ExtPayloadOffset Extension = 52
// ExtInterfaceIndex returns the index of the interface on which
// the packet was received.
ExtInterfaceIndex Extension = 8
// ExtNetlinkAttr returns the netlink attribute of type X at
// offset A.
ExtNetlinkAttr Extension = 12
// ExtNetlinkAttrNested returns the nested netlink attribute of
// type X at offset A.
ExtNetlinkAttrNested Extension = 16
// ExtMark returns the packet's mark value.
ExtMark Extension = 20
// ExtQueue returns the packet's assigned hardware queue.
ExtQueue Extension = 24
// ExtLinkLayerType returns the packet's hardware address type
// (e.g. Ethernet, Infiniband).
ExtLinkLayerType Extension = 28
// ExtRXHash returns the packets receive hash.
//
// TODO: figure out what this rxhash actually is.
ExtRXHash Extension = 32
// ExtCPUID returns the ID of the CPU processing the current
// packet.
ExtCPUID Extension = 36
// ExtVLANTag returns the packet's VLAN tag.
ExtVLANTag Extension = 44
// ExtVLANTagPresent returns non-zero if the packet has a VLAN
// tag.
//
// TODO: I think this might be a lie: it reads bit 0x1000 of the
// VLAN header, which changed meaning in recent revisions of the
// spec - this extension may now return meaningless information.
ExtVLANTagPresent Extension = 48
// ExtVLANProto returns 0x8100 if the frame has a VLAN header,
// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
// other value if no VLAN information is present.
ExtVLANProto Extension = 60
// ExtRand returns a uniformly random uint32.
ExtRand Extension = 56
)
// The following gives names to various bit patterns used in opcode construction.
const (
opMaskCls uint16 = 0x7
// opClsLoad masks
opMaskLoadDest = 0x01
opMaskLoadWidth = 0x18
opMaskLoadMode = 0xe0
// opClsALU & opClsJump
opMaskOperand = 0x08
opMaskOperator = 0xf0
)
const (
// +---------------+-----------------+---+---+---+
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 0 |
// +---------------+-----------------+---+---+---+
opClsLoadA uint16 = iota
// +---------------+-----------------+---+---+---+
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 1 |
// +---------------+-----------------+---+---+---+
opClsLoadX
// +---+---+---+---+---+---+---+---+
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
// +---+---+---+---+---+---+---+---+
opClsStoreA
// +---+---+---+---+---+---+---+---+
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
// +---+---+---+---+---+---+---+---+
opClsStoreX
// +---------------+-----------------+---+---+---+
// | Operator (4b) | OperandSrc (1b) | 1 | 0 | 0 |
// +---------------+-----------------+---+---+---+
opClsALU
// +-----------------------------+---+---+---+---+
// | TestOperator (4b) | 0 | 1 | 0 | 1 |
// +-----------------------------+---+---+---+---+
opClsJump
// +---+-------------------------+---+---+---+---+
// | 0 | 0 | 0 | RetSrc (1b) | 0 | 1 | 1 | 0 |
// +---+-------------------------+---+---+---+---+
opClsReturn
// +---+-------------------------+---+---+---+---+
// | 0 | 0 | 0 | TXAorTAX (1b) | 0 | 1 | 1 | 1 |
// +---+-------------------------+---+---+---+---+
opClsMisc
)
const (
opAddrModeImmediate uint16 = iota << 5
opAddrModeAbsolute
opAddrModeIndirect
opAddrModeScratch
opAddrModePacketLen // actually an extension, not an addressing mode.
opAddrModeMemShift
)
const (
opLoadWidth4 uint16 = iota << 3
opLoadWidth2
opLoadWidth1
)
// Operand for ALU and Jump instructions
type opOperand uint16
// Supported operand sources.
const (
opOperandConstant opOperand = iota << 3
opOperandX
)
// An jumpOp is a conditional jump condition.
type jumpOp uint16
// Supported jump conditions.
const (
opJumpAlways jumpOp = iota << 4
opJumpEqual
opJumpGT
opJumpGE
opJumpSet
)
const (
opRetSrcConstant uint16 = iota << 4
opRetSrcA
)
const (
opMiscTAX = 0x00
opMiscTXA = 0x80
)

82
src/runtime/vendor/golang.org/x/net/bpf/doc.go generated vendored Normal file
View File

@ -0,0 +1,82 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package bpf implements marshaling and unmarshaling of programs for the
Berkeley Packet Filter virtual machine, and provides a Go implementation
of the virtual machine.
BPF's main use is to specify a packet filter for network taps, so that
the kernel doesn't have to expensively copy every packet it sees to
userspace. However, it's been repurposed to other areas where running
user code in-kernel is needed. For example, Linux's seccomp uses BPF
to apply security policies to system calls. For simplicity, this
documentation refers only to packets, but other uses of BPF have their
own data payloads.
BPF programs run in a restricted virtual machine. It has almost no
access to kernel functions, and while conditional branches are
allowed, they can only jump forwards, to guarantee that there are no
infinite loops.
The virtual machine
The BPF VM is an accumulator machine. Its main register, called
register A, is an implicit source and destination in all arithmetic
and logic operations. The machine also has 16 scratch registers for
temporary storage, and an indirection register (register X) for
indirect memory access. All registers are 32 bits wide.
Each run of a BPF program is given one packet, which is placed in the
VM's read-only "main memory". LoadAbsolute and LoadIndirect
instructions can fetch up to 32 bits at a time into register A for
examination.
The goal of a BPF program is to produce and return a verdict (uint32),
which tells the kernel what to do with the packet. In the context of
packet filtering, the returned value is the number of bytes of the
packet to forward to userspace, or 0 to ignore the packet. Other
contexts like seccomp define their own return values.
In order to simplify programs, attempts to read past the end of the
packet terminate the program execution with a verdict of 0 (ignore
packet). This means that the vast majority of BPF programs don't need
to do any explicit bounds checking.
In addition to the bytes of the packet, some BPF programs have access
to extensions, which are essentially calls to kernel utility
functions. Currently, the only extensions supported by this package
are the Linux packet filter extensions.
Examples
This packet filter selects all ARP packets.
bpf.Assemble([]bpf.Instruction{
// Load "EtherType" field from the ethernet header.
bpf.LoadAbsolute{Off: 12, Size: 2},
// Skip over the next instruction if EtherType is not ARP.
bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: 0x0806, SkipTrue: 1},
// Verdict is "send up to 4k of the packet to userspace."
bpf.RetConstant{Val: 4096},
// Verdict is "ignore packet."
bpf.RetConstant{Val: 0},
})
This packet filter captures a random 1% sample of traffic.
bpf.Assemble([]bpf.Instruction{
// Get a 32-bit random number from the Linux kernel.
bpf.LoadExtension{Num: bpf.ExtRand},
// 1% dice roll?
bpf.JumpIf{Cond: bpf.JumpLessThan, Val: 2^32/100, SkipFalse: 1},
// Capture.
bpf.RetConstant{Val: 4096},
// Ignore.
bpf.RetConstant{Val: 0},
})
*/
package bpf // import "golang.org/x/net/bpf"

726
src/runtime/vendor/golang.org/x/net/bpf/instructions.go generated vendored Normal file
View File

@ -0,0 +1,726 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
import "fmt"
// An Instruction is one instruction executed by the BPF virtual
// machine.
type Instruction interface {
// Assemble assembles the Instruction into a RawInstruction.
Assemble() (RawInstruction, error)
}
// A RawInstruction is a raw BPF virtual machine instruction.
type RawInstruction struct {
// Operation to execute.
Op uint16
// For conditional jump instructions, the number of instructions
// to skip if the condition is true/false.
Jt uint8
Jf uint8
// Constant parameter. The meaning depends on the Op.
K uint32
}
// Assemble implements the Instruction Assemble method.
func (ri RawInstruction) Assemble() (RawInstruction, error) { return ri, nil }
// Disassemble parses ri into an Instruction and returns it. If ri is
// not recognized by this package, ri itself is returned.
func (ri RawInstruction) Disassemble() Instruction {
switch ri.Op & opMaskCls {
case opClsLoadA, opClsLoadX:
reg := Register(ri.Op & opMaskLoadDest)
sz := 0
switch ri.Op & opMaskLoadWidth {
case opLoadWidth4:
sz = 4
case opLoadWidth2:
sz = 2
case opLoadWidth1:
sz = 1
default:
return ri
}
switch ri.Op & opMaskLoadMode {
case opAddrModeImmediate:
if sz != 4 {
return ri
}
return LoadConstant{Dst: reg, Val: ri.K}
case opAddrModeScratch:
if sz != 4 || ri.K > 15 {
return ri
}
return LoadScratch{Dst: reg, N: int(ri.K)}
case opAddrModeAbsolute:
if ri.K > extOffset+0xffffffff {
return LoadExtension{Num: Extension(-extOffset + ri.K)}
}
return LoadAbsolute{Size: sz, Off: ri.K}
case opAddrModeIndirect:
return LoadIndirect{Size: sz, Off: ri.K}
case opAddrModePacketLen:
if sz != 4 {
return ri
}
return LoadExtension{Num: ExtLen}
case opAddrModeMemShift:
return LoadMemShift{Off: ri.K}
default:
return ri
}
case opClsStoreA:
if ri.Op != opClsStoreA || ri.K > 15 {
return ri
}
return StoreScratch{Src: RegA, N: int(ri.K)}
case opClsStoreX:
if ri.Op != opClsStoreX || ri.K > 15 {
return ri
}
return StoreScratch{Src: RegX, N: int(ri.K)}
case opClsALU:
switch op := ALUOp(ri.Op & opMaskOperator); op {
case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
switch operand := opOperand(ri.Op & opMaskOperand); operand {
case opOperandX:
return ALUOpX{Op: op}
case opOperandConstant:
return ALUOpConstant{Op: op, Val: ri.K}
default:
return ri
}
case aluOpNeg:
return NegateA{}
default:
return ri
}
case opClsJump:
switch op := jumpOp(ri.Op & opMaskOperator); op {
case opJumpAlways:
return Jump{Skip: ri.K}
case opJumpEqual, opJumpGT, opJumpGE, opJumpSet:
cond, skipTrue, skipFalse := jumpOpToTest(op, ri.Jt, ri.Jf)
switch operand := opOperand(ri.Op & opMaskOperand); operand {
case opOperandX:
return JumpIfX{Cond: cond, SkipTrue: skipTrue, SkipFalse: skipFalse}
case opOperandConstant:
return JumpIf{Cond: cond, Val: ri.K, SkipTrue: skipTrue, SkipFalse: skipFalse}
default:
return ri
}
default:
return ri
}
case opClsReturn:
switch ri.Op {
case opClsReturn | opRetSrcA:
return RetA{}
case opClsReturn | opRetSrcConstant:
return RetConstant{Val: ri.K}
default:
return ri
}
case opClsMisc:
switch ri.Op {
case opClsMisc | opMiscTAX:
return TAX{}
case opClsMisc | opMiscTXA:
return TXA{}
default:
return ri
}
default:
panic("unreachable") // switch is exhaustive on the bit pattern
}
}
func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest, uint8, uint8) {
var test JumpTest
// Decode "fake" jump conditions that don't appear in machine code
// Ensures the Assemble -> Disassemble stage recreates the same instructions
// See https://github.com/golang/go/issues/18470
if skipTrue == 0 {
switch op {
case opJumpEqual:
test = JumpNotEqual
case opJumpGT:
test = JumpLessOrEqual
case opJumpGE:
test = JumpLessThan
case opJumpSet:
test = JumpBitsNotSet
}
return test, skipFalse, 0
}
switch op {
case opJumpEqual:
test = JumpEqual
case opJumpGT:
test = JumpGreaterThan
case opJumpGE:
test = JumpGreaterOrEqual
case opJumpSet:
test = JumpBitsSet
}
return test, skipTrue, skipFalse
}
// LoadConstant loads Val into register Dst.
type LoadConstant struct {
Dst Register
Val uint32
}
// Assemble implements the Instruction Assemble method.
func (a LoadConstant) Assemble() (RawInstruction, error) {
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
}
// String returns the instruction in assembler notation.
func (a LoadConstant) String() string {
switch a.Dst {
case RegA:
return fmt.Sprintf("ld #%d", a.Val)
case RegX:
return fmt.Sprintf("ldx #%d", a.Val)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadScratch loads scratch[N] into register Dst.
type LoadScratch struct {
Dst Register
N int // 0-15
}
// Assemble implements the Instruction Assemble method.
func (a LoadScratch) Assemble() (RawInstruction, error) {
if a.N < 0 || a.N > 15 {
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
}
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
}
// String returns the instruction in assembler notation.
func (a LoadScratch) String() string {
switch a.Dst {
case RegA:
return fmt.Sprintf("ld M[%d]", a.N)
case RegX:
return fmt.Sprintf("ldx M[%d]", a.N)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
// register A.
type LoadAbsolute struct {
Off uint32
Size int // 1, 2 or 4
}
// Assemble implements the Instruction Assemble method.
func (a LoadAbsolute) Assemble() (RawInstruction, error) {
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadAbsolute) String() string {
switch a.Size {
case 1: // byte
return fmt.Sprintf("ldb [%d]", a.Off)
case 2: // half word
return fmt.Sprintf("ldh [%d]", a.Off)
case 4: // word
if a.Off > extOffset+0xffffffff {
return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
}
return fmt.Sprintf("ld [%d]", a.Off)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
// into register A.
type LoadIndirect struct {
Off uint32
Size int // 1, 2 or 4
}
// Assemble implements the Instruction Assemble method.
func (a LoadIndirect) Assemble() (RawInstruction, error) {
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadIndirect) String() string {
switch a.Size {
case 1: // byte
return fmt.Sprintf("ldb [x + %d]", a.Off)
case 2: // half word
return fmt.Sprintf("ldh [x + %d]", a.Off)
case 4: // word
return fmt.Sprintf("ld [x + %d]", a.Off)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
// by 4 and stores the result in register X.
//
// This instruction is mainly useful to load into X the length of an
// IPv4 packet header in a single instruction, rather than have to do
// the arithmetic on the header's first byte by hand.
type LoadMemShift struct {
Off uint32
}
// Assemble implements the Instruction Assemble method.
func (a LoadMemShift) Assemble() (RawInstruction, error) {
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
}
// String returns the instruction in assembler notation.
func (a LoadMemShift) String() string {
return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
}
// LoadExtension invokes a linux-specific extension and stores the
// result in register A.
type LoadExtension struct {
Num Extension
}
// Assemble implements the Instruction Assemble method.
func (a LoadExtension) Assemble() (RawInstruction, error) {
if a.Num == ExtLen {
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
}
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
}
// String returns the instruction in assembler notation.
func (a LoadExtension) String() string {
switch a.Num {
case ExtLen:
return "ld #len"
case ExtProto:
return "ld #proto"
case ExtType:
return "ld #type"
case ExtPayloadOffset:
return "ld #poff"
case ExtInterfaceIndex:
return "ld #ifidx"
case ExtNetlinkAttr:
return "ld #nla"
case ExtNetlinkAttrNested:
return "ld #nlan"
case ExtMark:
return "ld #mark"
case ExtQueue:
return "ld #queue"
case ExtLinkLayerType:
return "ld #hatype"
case ExtRXHash:
return "ld #rxhash"
case ExtCPUID:
return "ld #cpu"
case ExtVLANTag:
return "ld #vlan_tci"
case ExtVLANTagPresent:
return "ld #vlan_avail"
case ExtVLANProto:
return "ld #vlan_tpid"
case ExtRand:
return "ld #rand"
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// StoreScratch stores register Src into scratch[N].
type StoreScratch struct {
Src Register
N int // 0-15
}
// Assemble implements the Instruction Assemble method.
func (a StoreScratch) Assemble() (RawInstruction, error) {
if a.N < 0 || a.N > 15 {
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
}
var op uint16
switch a.Src {
case RegA:
op = opClsStoreA
case RegX:
op = opClsStoreX
default:
return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src)
}
return RawInstruction{
Op: op,
K: uint32(a.N),
}, nil
}
// String returns the instruction in assembler notation.
func (a StoreScratch) String() string {
switch a.Src {
case RegA:
return fmt.Sprintf("st M[%d]", a.N)
case RegX:
return fmt.Sprintf("stx M[%d]", a.N)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// ALUOpConstant executes A = A <Op> Val.
type ALUOpConstant struct {
Op ALUOp
Val uint32
}
// Assemble implements the Instruction Assemble method.
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | uint16(opOperandConstant) | uint16(a.Op),
K: a.Val,
}, nil
}
// String returns the instruction in assembler notation.
func (a ALUOpConstant) String() string {
switch a.Op {
case ALUOpAdd:
return fmt.Sprintf("add #%d", a.Val)
case ALUOpSub:
return fmt.Sprintf("sub #%d", a.Val)
case ALUOpMul:
return fmt.Sprintf("mul #%d", a.Val)
case ALUOpDiv:
return fmt.Sprintf("div #%d", a.Val)
case ALUOpMod:
return fmt.Sprintf("mod #%d", a.Val)
case ALUOpAnd:
return fmt.Sprintf("and #%d", a.Val)
case ALUOpOr:
return fmt.Sprintf("or #%d", a.Val)
case ALUOpXor:
return fmt.Sprintf("xor #%d", a.Val)
case ALUOpShiftLeft:
return fmt.Sprintf("lsh #%d", a.Val)
case ALUOpShiftRight:
return fmt.Sprintf("rsh #%d", a.Val)
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// ALUOpX executes A = A <Op> X
type ALUOpX struct {
Op ALUOp
}
// Assemble implements the Instruction Assemble method.
func (a ALUOpX) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | uint16(opOperandX) | uint16(a.Op),
}, nil
}
// String returns the instruction in assembler notation.
func (a ALUOpX) String() string {
switch a.Op {
case ALUOpAdd:
return "add x"
case ALUOpSub:
return "sub x"
case ALUOpMul:
return "mul x"
case ALUOpDiv:
return "div x"
case ALUOpMod:
return "mod x"
case ALUOpAnd:
return "and x"
case ALUOpOr:
return "or x"
case ALUOpXor:
return "xor x"
case ALUOpShiftLeft:
return "lsh x"
case ALUOpShiftRight:
return "rsh x"
default:
return fmt.Sprintf("unknown instruction: %#v", a)
}
}
// NegateA executes A = -A.
type NegateA struct{}
// Assemble implements the Instruction Assemble method.
func (a NegateA) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsALU | uint16(aluOpNeg),
}, nil
}
// String returns the instruction in assembler notation.
func (a NegateA) String() string {
return fmt.Sprintf("neg")
}
// Jump skips the following Skip instructions in the program.
type Jump struct {
Skip uint32
}
// Assemble implements the Instruction Assemble method.
func (a Jump) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsJump | uint16(opJumpAlways),
K: a.Skip,
}, nil
}
// String returns the instruction in assembler notation.
func (a Jump) String() string {
return fmt.Sprintf("ja %d", a.Skip)
}
// JumpIf skips the following Skip instructions in the program if A
// <Cond> Val is true.
type JumpIf struct {
Cond JumpTest
Val uint32
SkipTrue uint8
SkipFalse uint8
}
// Assemble implements the Instruction Assemble method.
func (a JumpIf) Assemble() (RawInstruction, error) {
return jumpToRaw(a.Cond, opOperandConstant, a.Val, a.SkipTrue, a.SkipFalse)
}
// String returns the instruction in assembler notation.
func (a JumpIf) String() string {
return jumpToString(a.Cond, fmt.Sprintf("#%d", a.Val), a.SkipTrue, a.SkipFalse)
}
// JumpIfX skips the following Skip instructions in the program if A
// <Cond> X is true.
type JumpIfX struct {
Cond JumpTest
SkipTrue uint8
SkipFalse uint8
}
// Assemble implements the Instruction Assemble method.
func (a JumpIfX) Assemble() (RawInstruction, error) {
return jumpToRaw(a.Cond, opOperandX, 0, a.SkipTrue, a.SkipFalse)
}
// String returns the instruction in assembler notation.
func (a JumpIfX) String() string {
return jumpToString(a.Cond, "x", a.SkipTrue, a.SkipFalse)
}
// jumpToRaw assembles a jump instruction into a RawInstruction
func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, skipFalse uint8) (RawInstruction, error) {
var (
cond jumpOp
flip bool
)
switch test {
case JumpEqual:
cond = opJumpEqual
case JumpNotEqual:
cond, flip = opJumpEqual, true
case JumpGreaterThan:
cond = opJumpGT
case JumpLessThan:
cond, flip = opJumpGE, true
case JumpGreaterOrEqual:
cond = opJumpGE
case JumpLessOrEqual:
cond, flip = opJumpGT, true
case JumpBitsSet:
cond = opJumpSet
case JumpBitsNotSet:
cond, flip = opJumpSet, true
default:
return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", test)
}
jt, jf := skipTrue, skipFalse
if flip {
jt, jf = jf, jt
}
return RawInstruction{
Op: opClsJump | uint16(cond) | uint16(operand),
Jt: jt,
Jf: jf,
K: k,
}, nil
}
// jumpToString converts a jump instruction to assembler notation
func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uint8) string {
switch cond {
// K == A
case JumpEqual:
return conditionalJump(operand, skipTrue, skipFalse, "jeq", "jneq")
// K != A
case JumpNotEqual:
return fmt.Sprintf("jneq %s,%d", operand, skipTrue)
// K > A
case JumpGreaterThan:
return conditionalJump(operand, skipTrue, skipFalse, "jgt", "jle")
// K < A
case JumpLessThan:
return fmt.Sprintf("jlt %s,%d", operand, skipTrue)
// K >= A
case JumpGreaterOrEqual:
return conditionalJump(operand, skipTrue, skipFalse, "jge", "jlt")
// K <= A
case JumpLessOrEqual:
return fmt.Sprintf("jle %s,%d", operand, skipTrue)
// K & A != 0
case JumpBitsSet:
if skipFalse > 0 {
return fmt.Sprintf("jset %s,%d,%d", operand, skipTrue, skipFalse)
}
return fmt.Sprintf("jset %s,%d", operand, skipTrue)
// K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips
case JumpBitsNotSet:
return jumpToString(JumpBitsSet, operand, skipFalse, skipTrue)
default:
return fmt.Sprintf("unknown JumpTest %#v", cond)
}
}
func conditionalJump(operand string, skipTrue, skipFalse uint8, positiveJump, negativeJump string) string {
if skipTrue > 0 {
if skipFalse > 0 {
return fmt.Sprintf("%s %s,%d,%d", positiveJump, operand, skipTrue, skipFalse)
}
return fmt.Sprintf("%s %s,%d", positiveJump, operand, skipTrue)
}
return fmt.Sprintf("%s %s,%d", negativeJump, operand, skipFalse)
}
// RetA exits the BPF program, returning the value of register A.
type RetA struct{}
// Assemble implements the Instruction Assemble method.
func (a RetA) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsReturn | opRetSrcA,
}, nil
}
// String returns the instruction in assembler notation.
func (a RetA) String() string {
return fmt.Sprintf("ret a")
}
// RetConstant exits the BPF program, returning a constant value.
type RetConstant struct {
Val uint32
}
// Assemble implements the Instruction Assemble method.
func (a RetConstant) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsReturn | opRetSrcConstant,
K: a.Val,
}, nil
}
// String returns the instruction in assembler notation.
func (a RetConstant) String() string {
return fmt.Sprintf("ret #%d", a.Val)
}
// TXA copies the value of register X to register A.
type TXA struct{}
// Assemble implements the Instruction Assemble method.
func (a TXA) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsMisc | opMiscTXA,
}, nil
}
// String returns the instruction in assembler notation.
func (a TXA) String() string {
return fmt.Sprintf("txa")
}
// TAX copies the value of register A to register X.
type TAX struct{}
// Assemble implements the Instruction Assemble method.
func (a TAX) Assemble() (RawInstruction, error) {
return RawInstruction{
Op: opClsMisc | opMiscTAX,
}, nil
}
// String returns the instruction in assembler notation.
func (a TAX) String() string {
return fmt.Sprintf("tax")
}
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
var (
cls uint16
sz uint16
)
switch dst {
case RegA:
cls = opClsLoadA
case RegX:
cls = opClsLoadX
default:
return RawInstruction{}, fmt.Errorf("invalid target register %v", dst)
}
switch loadSize {
case 1:
sz = opLoadWidth1
case 2:
sz = opLoadWidth2
case 4:
sz = opLoadWidth4
default:
return RawInstruction{}, fmt.Errorf("invalid load byte length %d", sz)
}
return RawInstruction{
Op: cls | sz | mode,
K: k,
}, nil
}

10
src/runtime/vendor/golang.org/x/net/bpf/setter.go generated vendored Normal file
View File

@ -0,0 +1,10 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
// A Setter is a type which can attach a compiled BPF filter to itself.
type Setter interface {
SetBPF(filter []RawInstruction) error
}

150
src/runtime/vendor/golang.org/x/net/bpf/vm.go generated vendored Normal file
View File

@ -0,0 +1,150 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
import (
"errors"
"fmt"
)
// A VM is an emulated BPF virtual machine.
type VM struct {
filter []Instruction
}
// NewVM returns a new VM using the input BPF program.
func NewVM(filter []Instruction) (*VM, error) {
if len(filter) == 0 {
return nil, errors.New("one or more Instructions must be specified")
}
for i, ins := range filter {
check := len(filter) - (i + 1)
switch ins := ins.(type) {
// Check for out-of-bounds jumps in instructions
case Jump:
if check <= int(ins.Skip) {
return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip)
}
case JumpIf:
if check <= int(ins.SkipTrue) {
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
}
if check <= int(ins.SkipFalse) {
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
}
case JumpIfX:
if check <= int(ins.SkipTrue) {
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
}
if check <= int(ins.SkipFalse) {
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
}
// Check for division or modulus by zero
case ALUOpConstant:
if ins.Val != 0 {
break
}
switch ins.Op {
case ALUOpDiv, ALUOpMod:
return nil, errors.New("cannot divide by zero using ALUOpConstant")
}
// Check for unknown extensions
case LoadExtension:
switch ins.Num {
case ExtLen:
default:
return nil, fmt.Errorf("extension %d not implemented", ins.Num)
}
}
}
// Make sure last instruction is a return instruction
switch filter[len(filter)-1].(type) {
case RetA, RetConstant:
default:
return nil, errors.New("BPF program must end with RetA or RetConstant")
}
// Though our VM works using disassembled instructions, we
// attempt to assemble the input filter anyway to ensure it is compatible
// with an operating system VM.
_, err := Assemble(filter)
return &VM{
filter: filter,
}, err
}
// Run runs the VM's BPF program against the input bytes.
// Run returns the number of bytes accepted by the BPF program, and any errors
// which occurred while processing the program.
func (v *VM) Run(in []byte) (int, error) {
var (
// Registers of the virtual machine
regA uint32
regX uint32
regScratch [16]uint32
// OK is true if the program should continue processing the next
// instruction, or false if not, causing the loop to break
ok = true
)
// TODO(mdlayher): implement:
// - NegateA:
// - would require a change from uint32 registers to int32
// registers
// TODO(mdlayher): add interop tests that check signedness of ALU
// operations against kernel implementation, and make sure Go
// implementation matches behavior
for i := 0; i < len(v.filter) && ok; i++ {
ins := v.filter[i]
switch ins := ins.(type) {
case ALUOpConstant:
regA = aluOpConstant(ins, regA)
case ALUOpX:
regA, ok = aluOpX(ins, regA, regX)
case Jump:
i += int(ins.Skip)
case JumpIf:
jump := jumpIf(ins, regA)
i += jump
case JumpIfX:
jump := jumpIfX(ins, regA, regX)
i += jump
case LoadAbsolute:
regA, ok = loadAbsolute(ins, in)
case LoadConstant:
regA, regX = loadConstant(ins, regA, regX)
case LoadExtension:
regA = loadExtension(ins, in)
case LoadIndirect:
regA, ok = loadIndirect(ins, in, regX)
case LoadMemShift:
regX, ok = loadMemShift(ins, in)
case LoadScratch:
regA, regX = loadScratch(ins, regScratch, regA, regX)
case RetA:
return int(regA), nil
case RetConstant:
return int(ins.Val), nil
case StoreScratch:
regScratch = storeScratch(ins, regScratch, regA, regX)
case TAX:
regX = regA
case TXA:
regA = regX
default:
return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins)
}
}
return 0, nil
}

View File

@ -0,0 +1,182 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bpf
import (
"encoding/binary"
"fmt"
)
func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
return aluOpCommon(ins.Op, regA, ins.Val)
}
func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
// Guard against division or modulus by zero by terminating
// the program, as the OS BPF VM does
if regX == 0 {
switch ins.Op {
case ALUOpDiv, ALUOpMod:
return 0, false
}
}
return aluOpCommon(ins.Op, regA, regX), true
}
func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
switch op {
case ALUOpAdd:
return regA + value
case ALUOpSub:
return regA - value
case ALUOpMul:
return regA * value
case ALUOpDiv:
// Division by zero not permitted by NewVM and aluOpX checks
return regA / value
case ALUOpOr:
return regA | value
case ALUOpAnd:
return regA & value
case ALUOpShiftLeft:
return regA << value
case ALUOpShiftRight:
return regA >> value
case ALUOpMod:
// Modulus by zero not permitted by NewVM and aluOpX checks
return regA % value
case ALUOpXor:
return regA ^ value
default:
return regA
}
}
func jumpIf(ins JumpIf, regA uint32) int {
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val)
}
func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int {
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX)
}
func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int {
var ok bool
switch cond {
case JumpEqual:
ok = regA == value
case JumpNotEqual:
ok = regA != value
case JumpGreaterThan:
ok = regA > value
case JumpLessThan:
ok = regA < value
case JumpGreaterOrEqual:
ok = regA >= value
case JumpLessOrEqual:
ok = regA <= value
case JumpBitsSet:
ok = (regA & value) != 0
case JumpBitsNotSet:
ok = (regA & value) == 0
}
if ok {
return int(skipTrue)
}
return int(skipFalse)
}
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
offset := int(ins.Off)
size := int(ins.Size)
return loadCommon(in, offset, size)
}
func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
switch ins.Dst {
case RegA:
regA = ins.Val
case RegX:
regX = ins.Val
}
return regA, regX
}
func loadExtension(ins LoadExtension, in []byte) uint32 {
switch ins.Num {
case ExtLen:
return uint32(len(in))
default:
panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
}
}
func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
offset := int(ins.Off) + int(regX)
size := int(ins.Size)
return loadCommon(in, offset, size)
}
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
offset := int(ins.Off)
// Size of LoadMemShift is always 1 byte
if !inBounds(len(in), offset, 1) {
return 0, false
}
// Mask off high 4 bits and multiply low 4 bits by 4
return uint32(in[offset]&0x0f) * 4, true
}
func inBounds(inLen int, offset int, size int) bool {
return offset+size <= inLen
}
func loadCommon(in []byte, offset int, size int) (uint32, bool) {
if !inBounds(len(in), offset, size) {
return 0, false
}
switch size {
case 1:
return uint32(in[offset]), true
case 2:
return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
case 4:
return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
default:
panic(fmt.Sprintf("invalid load size: %d", size))
}
}
func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
switch ins.Dst {
case RegA:
regA = regScratch[ins.N]
case RegX:
regX = regScratch[ins.N]
}
return regA, regX
}
func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
switch ins.Src {
case RegA:
regScratch[ins.N] = regA
case RegX:
regScratch[ins.N] = regX
}
return regScratch
}

View File

@ -16,6 +16,12 @@ import (
// ClientConnPool manages a pool of HTTP/2 client connections.
type ClientConnPool interface {
// GetClientConn returns a specific HTTP/2 connection (usually
// a TLS-TCP connection) to an HTTP/2 server. On success, the
// returned ClientConn accounts for the upcoming RoundTrip
// call, so the caller should not omit it. If the caller needs
// to, ClientConn.RoundTrip can be called with a bogus
// new(http.Request) to release the stream reservation.
GetClientConn(req *http.Request, addr string) (*ClientConn, error)
MarkDead(*ClientConn)
}
@ -42,7 +48,7 @@ type clientConnPool struct {
conns map[string][]*ClientConn // key is host:port
dialing map[string]*dialCall // currently in-flight dials
keys map[*ClientConn][]string
addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls
addConnCalls map[string]*addConnCall // in-flight addConnIfNeeded calls
}
func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
@ -54,28 +60,8 @@ const (
noDialOnMiss = false
)
// shouldTraceGetConn reports whether getClientConn should call any
// ClientTrace.GetConn hook associated with the http.Request.
//
// This complexity is needed to avoid double calls of the GetConn hook
// during the back-and-forth between net/http and x/net/http2 (when the
// net/http.Transport is upgraded to also speak http2), as well as support
// the case where x/net/http2 is being used directly.
func (p *clientConnPool) shouldTraceGetConn(st clientConnIdleState) bool {
// If our Transport wasn't made via ConfigureTransport, always
// trace the GetConn hook if provided, because that means the
// http2 package is being used directly and it's the one
// dialing, as opposed to net/http.
if _, ok := p.t.ConnPool.(noDialClientConnPool); !ok {
return true
}
// Otherwise, only use the GetConn hook if this connection has
// been used previously for other requests. For fresh
// connections, the net/http package does the dialing.
return !st.freshConn
}
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
// TODO(dneil): Dial a new connection when t.DisableKeepAlives is set?
if isConnectionCloseRequest(req) && dialOnMiss {
// It gets its own connection.
traceGetConn(req, addr)
@ -89,10 +75,14 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
for {
p.mu.Lock()
for _, cc := range p.conns[addr] {
if st := cc.idleState(); st.canTakeNewRequest {
if p.shouldTraceGetConn(st) {
if cc.ReserveNewRequest() {
// When a connection is presented to us by the net/http package,
// the GetConn hook has already been called.
// Don't call it a second time here.
if !cc.getConnCalled {
traceGetConn(req, addr)
}
cc.getConnCalled = false
p.mu.Unlock()
return cc, nil
}
@ -108,7 +98,13 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
if shouldRetryDial(call, req) {
continue
}
return call.res, call.err
cc, err := call.res, call.err
if err != nil {
return nil, err
}
if cc.ReserveNewRequest() {
return cc, nil
}
}
}
@ -205,6 +201,7 @@ func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
if err != nil {
c.err = err
} else {
cc.getConnCalled = true // already called by the net/http package
p.addConnLocked(key, cc)
}
delete(p.addConnCalls, key)

View File

@ -53,6 +53,13 @@ func (e ErrCode) String() string {
return fmt.Sprintf("unknown error code 0x%x", uint32(e))
}
func (e ErrCode) stringToken() string {
if s, ok := errCodeName[e]; ok {
return s
}
return fmt.Sprintf("ERR_UNKNOWN_%d", uint32(e))
}
// ConnectionError is an error that results in the termination of the
// entire connection.
type ConnectionError ErrCode
@ -67,6 +74,11 @@ type StreamError struct {
Cause error // optional additional detail
}
// errFromPeer is a sentinel error value for StreamError.Cause to
// indicate that the StreamError was sent from the peer over the wire
// and wasn't locally generated in the Transport.
var errFromPeer = errors.New("received from peer")
func streamError(id uint32, code ErrCode) StreamError {
return StreamError{StreamID: id, Code: code}
}

View File

@ -122,7 +122,7 @@ var flagName = map[FrameType]map[Flags]string{
// a frameParser parses a frame given its FrameHeader and payload
// bytes. The length of payload will always equal fh.Length (which
// might be 0).
type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error)
type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error)
var frameParsers = map[FrameType]frameParser{
FrameData: parseDataFrame,
@ -267,6 +267,11 @@ type Framer struct {
lastFrame Frame
errDetail error
// countError is a non-nil func that's called on a frame parse
// error with some unique error path token. It's initialized
// from Transport.CountError or Server.CountError.
countError func(errToken string)
// lastHeaderStream is non-zero if the last frame was an
// unfinished HEADERS/CONTINUATION.
lastHeaderStream uint32
@ -426,6 +431,7 @@ func NewFramer(w io.Writer, r io.Reader) *Framer {
fr := &Framer{
w: w,
r: r,
countError: func(string) {},
logReads: logFrameReads,
logWrites: logFrameWrites,
debugReadLoggerf: log.Printf,
@ -500,7 +506,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
if _, err := io.ReadFull(fr.r, payload); err != nil {
return nil, err
}
f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, fr.countError, payload)
if err != nil {
if ce, ok := err.(connError); ok {
return nil, fr.connError(ce.Code, ce.Reason)
@ -588,13 +594,14 @@ func (f *DataFrame) Data() []byte {
return f.data
}
func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
func parseDataFrame(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
if fh.StreamID == 0 {
// DATA frames MUST be associated with a stream. If a
// DATA frame is received whose stream identifier
// field is 0x0, the recipient MUST respond with a
// connection error (Section 5.4.1) of type
// PROTOCOL_ERROR.
countError("frame_data_stream_0")
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
}
f := fc.getDataFrame()
@ -605,6 +612,7 @@ func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, erro
var err error
payload, padSize, err = readByte(payload)
if err != nil {
countError("frame_data_pad_byte_short")
return nil, err
}
}
@ -613,6 +621,7 @@ func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, erro
// length of the frame payload, the recipient MUST
// treat this as a connection error.
// Filed: https://github.com/http2/http2-spec/issues/610
countError("frame_data_pad_too_big")
return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
}
f.data = payload[:len(payload)-int(padSize)]
@ -695,7 +704,7 @@ type SettingsFrame struct {
p []byte
}
func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
func parseSettingsFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
// When this (ACK 0x1) bit is set, the payload of the
// SETTINGS frame MUST be empty. Receipt of a
@ -703,6 +712,7 @@ func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error)
// field value other than 0 MUST be treated as a
// connection error (Section 5.4.1) of type
// FRAME_SIZE_ERROR.
countError("frame_settings_ack_with_length")
return nil, ConnectionError(ErrCodeFrameSize)
}
if fh.StreamID != 0 {
@ -713,14 +723,17 @@ func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error)
// field is anything other than 0x0, the endpoint MUST
// respond with a connection error (Section 5.4.1) of
// type PROTOCOL_ERROR.
countError("frame_settings_has_stream")
return nil, ConnectionError(ErrCodeProtocol)
}
if len(p)%6 != 0 {
countError("frame_settings_mod_6")
// Expecting even number of 6 byte settings.
return nil, ConnectionError(ErrCodeFrameSize)
}
f := &SettingsFrame{FrameHeader: fh, p: p}
if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
countError("frame_settings_window_size_too_big")
// Values above the maximum flow control window size of 2^31 - 1 MUST
// be treated as a connection error (Section 5.4.1) of type
// FLOW_CONTROL_ERROR.
@ -832,11 +845,13 @@ type PingFrame struct {
func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
func parsePingFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
if len(payload) != 8 {
countError("frame_ping_length")
return nil, ConnectionError(ErrCodeFrameSize)
}
if fh.StreamID != 0 {
countError("frame_ping_has_stream")
return nil, ConnectionError(ErrCodeProtocol)
}
f := &PingFrame{FrameHeader: fh}
@ -872,11 +887,13 @@ func (f *GoAwayFrame) DebugData() []byte {
return f.debugData
}
func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
func parseGoAwayFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if fh.StreamID != 0 {
countError("frame_goaway_has_stream")
return nil, ConnectionError(ErrCodeProtocol)
}
if len(p) < 8 {
countError("frame_goaway_short")
return nil, ConnectionError(ErrCodeFrameSize)
}
return &GoAwayFrame{
@ -912,7 +929,7 @@ func (f *UnknownFrame) Payload() []byte {
return f.p
}
func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
func parseUnknownFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
return &UnknownFrame{fh, p}, nil
}
@ -923,8 +940,9 @@ type WindowUpdateFrame struct {
Increment uint32 // never read with high bit set
}
func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if len(p) != 4 {
countError("frame_windowupdate_bad_len")
return nil, ConnectionError(ErrCodeFrameSize)
}
inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
@ -936,8 +954,10 @@ func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, err
// control window MUST be treated as a connection
// error (Section 5.4.1).
if fh.StreamID == 0 {
countError("frame_windowupdate_zero_inc_conn")
return nil, ConnectionError(ErrCodeProtocol)
}
countError("frame_windowupdate_zero_inc_stream")
return nil, streamError(fh.StreamID, ErrCodeProtocol)
}
return &WindowUpdateFrame{
@ -988,7 +1008,7 @@ func (f *HeadersFrame) HasPriority() bool {
return f.FrameHeader.Flags.Has(FlagHeadersPriority)
}
func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
func parseHeadersFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
hf := &HeadersFrame{
FrameHeader: fh,
}
@ -997,11 +1017,13 @@ func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err er
// is received whose stream identifier field is 0x0, the recipient MUST
// respond with a connection error (Section 5.4.1) of type
// PROTOCOL_ERROR.
countError("frame_headers_zero_stream")
return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
}
var padLength uint8
if fh.Flags.Has(FlagHeadersPadded) {
if p, padLength, err = readByte(p); err != nil {
countError("frame_headers_pad_short")
return
}
}
@ -1009,16 +1031,19 @@ func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err er
var v uint32
p, v, err = readUint32(p)
if err != nil {
countError("frame_headers_prio_short")
return nil, err
}
hf.Priority.StreamDep = v & 0x7fffffff
hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
p, hf.Priority.Weight, err = readByte(p)
if err != nil {
countError("frame_headers_prio_weight_short")
return nil, err
}
}
if len(p)-int(padLength) <= 0 {
if len(p)-int(padLength) < 0 {
countError("frame_headers_pad_too_big")
return nil, streamError(fh.StreamID, ErrCodeProtocol)
}
hf.headerFragBuf = p[:len(p)-int(padLength)]
@ -1125,11 +1150,13 @@ func (p PriorityParam) IsZero() bool {
return p == PriorityParam{}
}
func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
func parsePriorityFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
if fh.StreamID == 0 {
countError("frame_priority_zero_stream")
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
}
if len(payload) != 5 {
countError("frame_priority_bad_length")
return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
}
v := binary.BigEndian.Uint32(payload[:4])
@ -1172,11 +1199,13 @@ type RSTStreamFrame struct {
ErrCode ErrCode
}
func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if len(p) != 4 {
countError("frame_rststream_bad_len")
return nil, ConnectionError(ErrCodeFrameSize)
}
if fh.StreamID == 0 {
countError("frame_rststream_zero_stream")
return nil, ConnectionError(ErrCodeProtocol)
}
return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
@ -1202,8 +1231,9 @@ type ContinuationFrame struct {
headerFragBuf []byte
}
func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
func parseContinuationFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
if fh.StreamID == 0 {
countError("frame_continuation_zero_stream")
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
}
return &ContinuationFrame{fh, p}, nil
@ -1252,7 +1282,7 @@ func (f *PushPromiseFrame) HeadersEnded() bool {
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
}
func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
func parsePushPromise(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
pp := &PushPromiseFrame{
FrameHeader: fh,
}
@ -1263,6 +1293,7 @@ func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err err
// with. If the stream identifier field specifies the value
// 0x0, a recipient MUST respond with a connection error
// (Section 5.4.1) of type PROTOCOL_ERROR.
countError("frame_pushpromise_zero_stream")
return nil, ConnectionError(ErrCodeProtocol)
}
// The PUSH_PROMISE frame includes optional padding.
@ -1270,18 +1301,21 @@ func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err err
var padLength uint8
if fh.Flags.Has(FlagPushPromisePadded) {
if p, padLength, err = readByte(p); err != nil {
countError("frame_pushpromise_pad_short")
return
}
}
p, pp.PromiseID, err = readUint32(p)
if err != nil {
countError("frame_pushpromise_promiseid_short")
return
}
pp.PromiseID = pp.PromiseID & (1<<31 - 1)
if int(padLength) > len(p) {
// like the DATA frame, error out if padding is longer than the body.
countError("frame_pushpromise_pad_too_big")
return nil, ConnectionError(ErrCodeProtocol)
}
pp.headerFragBuf = p[:len(p)-int(padLength)]

View File

@ -140,25 +140,29 @@ func buildRootHuffmanNode() {
panic("unexpected size")
}
lazyRootHuffmanNode = newInternalNode()
for i, code := range huffmanCodes {
addDecoderNode(byte(i), code, huffmanCodeLen[i])
}
}
// allocate a leaf node for each of the 256 symbols
leaves := new([256]node)
func addDecoderNode(sym byte, code uint32, codeLen uint8) {
cur := lazyRootHuffmanNode
for codeLen > 8 {
codeLen -= 8
i := uint8(code >> codeLen)
if cur.children[i] == nil {
cur.children[i] = newInternalNode()
for sym, code := range huffmanCodes {
codeLen := huffmanCodeLen[sym]
cur := lazyRootHuffmanNode
for codeLen > 8 {
codeLen -= 8
i := uint8(code >> codeLen)
if cur.children[i] == nil {
cur.children[i] = newInternalNode()
}
cur = cur.children[i]
}
shift := 8 - codeLen
start, end := int(uint8(code<<shift)), int(1<<shift)
leaves[sym].sym = byte(sym)
leaves[sym].codeLen = codeLen
for i := start; i < start+end; i++ {
cur.children[i] = &leaves[sym]
}
cur = cur.children[i]
}
shift := 8 - codeLen
start, end := int(uint8(code<<shift)), int(1<<shift)
for i := start; i < start+end; i++ {
cur.children[i] = &node{sym: sym, codeLen: codeLen}
}
}

View File

@ -30,6 +30,17 @@ type pipeBuffer interface {
io.Reader
}
// setBuffer initializes the pipe buffer.
// It has no effect if the pipe is already closed.
func (p *pipe) setBuffer(b pipeBuffer) {
p.mu.Lock()
defer p.mu.Unlock()
if p.err != nil || p.breakErr != nil {
return
}
p.b = b
}
func (p *pipe) Len() int {
p.mu.Lock()
defer p.mu.Unlock()

View File

@ -130,6 +130,12 @@ type Server struct {
// If nil, a default scheduler is chosen.
NewWriteScheduler func() WriteScheduler
// CountError, if non-nil, is called on HTTP/2 server errors.
// It's intended to increment a metric for monitoring, such
// as an expvar or Prometheus metric.
// The errType consists of only ASCII word characters.
CountError func(errType string)
// Internal state. This is a pointer (rather than embedded directly)
// so that we don't embed a Mutex in this struct, which will make the
// struct non-copyable, which might break some callers.
@ -405,6 +411,9 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
fr := NewFramer(sc.bw, c)
if s.CountError != nil {
fr.countError = s.CountError
}
fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
fr.MaxHeaderListSize = sc.maxHeaderListSize()
fr.SetMaxReadFrameSize(s.maxReadFrameSize())
@ -710,7 +719,15 @@ func (sc *serverConn) canonicalHeader(v string) string {
sc.canonHeader = make(map[string]string)
}
cv = http.CanonicalHeaderKey(v)
sc.canonHeader[v] = cv
// maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
// entries in the canonHeader cache. This should be larger than the number
// of unique, uncommon header keys likely to be sent by the peer, while not
// so high as to permit unreasonable memory usage if the peer sends an unbounded
// number of unique header keys.
const maxCachedCanonicalHeaders = 32
if len(sc.canonHeader) < maxCachedCanonicalHeaders {
sc.canonHeader[v] = cv
}
return cv
}
@ -1399,7 +1416,7 @@ func (sc *serverConn) processFrame(f Frame) error {
// First frame received must be SETTINGS.
if !sc.sawFirstSettings {
if _, ok := f.(*SettingsFrame); !ok {
return ConnectionError(ErrCodeProtocol)
return sc.countError("first_settings", ConnectionError(ErrCodeProtocol))
}
sc.sawFirstSettings = true
}
@ -1424,7 +1441,7 @@ func (sc *serverConn) processFrame(f Frame) error {
case *PushPromiseFrame:
// A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
// frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
return ConnectionError(ErrCodeProtocol)
return sc.countError("push_promise", ConnectionError(ErrCodeProtocol))
default:
sc.vlogf("http2: server ignoring frame: %v", f.Header())
return nil
@ -1444,7 +1461,7 @@ func (sc *serverConn) processPing(f *PingFrame) error {
// identifier field value other than 0x0, the recipient MUST
// respond with a connection error (Section 5.4.1) of type
// PROTOCOL_ERROR."
return ConnectionError(ErrCodeProtocol)
return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))
}
if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
return nil
@ -1463,7 +1480,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
// or PRIORITY on a stream in this state MUST be
// treated as a connection error (Section 5.4.1) of
// type PROTOCOL_ERROR."
return ConnectionError(ErrCodeProtocol)
return sc.countError("stream_idle", ConnectionError(ErrCodeProtocol))
}
if st == nil {
// "WINDOW_UPDATE can be sent by a peer that has sent a
@ -1474,7 +1491,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
return nil
}
if !st.flow.add(int32(f.Increment)) {
return streamError(f.StreamID, ErrCodeFlowControl)
return sc.countError("bad_flow", streamError(f.StreamID, ErrCodeFlowControl))
}
default: // connection-level flow control
if !sc.flow.add(int32(f.Increment)) {
@ -1495,7 +1512,7 @@ func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
// identifying an idle stream is received, the
// recipient MUST treat this as a connection error
// (Section 5.4.1) of type PROTOCOL_ERROR.
return ConnectionError(ErrCodeProtocol)
return sc.countError("reset_idle_stream", ConnectionError(ErrCodeProtocol))
}
if st != nil {
st.cancelCtx()
@ -1547,7 +1564,7 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
// Why is the peer ACKing settings we never sent?
// The spec doesn't mention this case, but
// hang up on them anyway.
return ConnectionError(ErrCodeProtocol)
return sc.countError("ack_mystery", ConnectionError(ErrCodeProtocol))
}
return nil
}
@ -1555,7 +1572,7 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
// This isn't actually in the spec, but hang up on
// suspiciously large settings frames or those with
// duplicate entries.
return ConnectionError(ErrCodeProtocol)
return sc.countError("settings_big_or_dups", ConnectionError(ErrCodeProtocol))
}
if err := f.ForeachSetting(sc.processSetting); err != nil {
return err
@ -1622,7 +1639,7 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
// control window to exceed the maximum size as a
// connection error (Section 5.4.1) of type
// FLOW_CONTROL_ERROR."
return ConnectionError(ErrCodeFlowControl)
return sc.countError("setting_win_size", ConnectionError(ErrCodeFlowControl))
}
}
return nil
@ -1655,7 +1672,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
// or PRIORITY on a stream in this state MUST be
// treated as a connection error (Section 5.4.1) of
// type PROTOCOL_ERROR."
return ConnectionError(ErrCodeProtocol)
return sc.countError("data_on_idle", ConnectionError(ErrCodeProtocol))
}
// "If a DATA frame is received whose stream is not in "open"
@ -1672,7 +1689,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
// and return any flow control bytes since we're not going
// to consume them.
if sc.inflow.available() < int32(f.Length) {
return streamError(id, ErrCodeFlowControl)
return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
}
// Deduct the flow control from inflow, since we're
// going to immediately add it back in
@ -1685,7 +1702,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
// Already have a stream error in flight. Don't send another.
return nil
}
return streamError(id, ErrCodeStreamClosed)
return sc.countError("closed", streamError(id, ErrCodeStreamClosed))
}
if st.body == nil {
panic("internal error: should have a body in this state")
@ -1697,12 +1714,12 @@ func (sc *serverConn) processData(f *DataFrame) error {
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
// value of a content-length header field does not equal the sum of the
// DATA frame payload lengths that form the body.
return streamError(id, ErrCodeProtocol)
return sc.countError("send_too_much", streamError(id, ErrCodeProtocol))
}
if f.Length > 0 {
// Check whether the client has flow control quota.
if st.inflow.available() < int32(f.Length) {
return streamError(id, ErrCodeFlowControl)
return sc.countError("flow_on_data_length", streamError(id, ErrCodeFlowControl))
}
st.inflow.take(int32(f.Length))
@ -1710,7 +1727,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
wrote, err := st.body.Write(data)
if err != nil {
sc.sendWindowUpdate(nil, int(f.Length)-wrote)
return streamError(id, ErrCodeStreamClosed)
return sc.countError("body_write_err", streamError(id, ErrCodeStreamClosed))
}
if wrote != len(data) {
panic("internal error: bad Writer")
@ -1796,7 +1813,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// stream identifier MUST respond with a connection error
// (Section 5.4.1) of type PROTOCOL_ERROR.
if id%2 != 1 {
return ConnectionError(ErrCodeProtocol)
return sc.countError("headers_even", ConnectionError(ErrCodeProtocol))
}
// A HEADERS frame can be used to create a new stream or
// send a trailer for an open one. If we already have a stream
@ -1813,7 +1830,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// this state, it MUST respond with a stream error (Section 5.4.2) of
// type STREAM_CLOSED.
if st.state == stateHalfClosedRemote {
return streamError(id, ErrCodeStreamClosed)
return sc.countError("headers_half_closed", streamError(id, ErrCodeStreamClosed))
}
return st.processTrailerHeaders(f)
}
@ -1824,7 +1841,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// receives an unexpected stream identifier MUST respond with
// a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
if id <= sc.maxClientStreamID {
return ConnectionError(ErrCodeProtocol)
return sc.countError("stream_went_down", ConnectionError(ErrCodeProtocol))
}
sc.maxClientStreamID = id
@ -1841,14 +1858,14 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
if sc.curClientStreams+1 > sc.advMaxStreams {
if sc.unackedSettings == 0 {
// They should know better.
return streamError(id, ErrCodeProtocol)
return sc.countError("over_max_streams", streamError(id, ErrCodeProtocol))
}
// Assume it's a network race, where they just haven't
// received our last SETTINGS update. But actually
// this can't happen yet, because we don't yet provide
// a way for users to adjust server parameters at
// runtime.
return streamError(id, ErrCodeRefusedStream)
return sc.countError("over_max_streams_race", streamError(id, ErrCodeRefusedStream))
}
initialState := stateOpen
@ -1858,7 +1875,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
st := sc.newStream(id, 0, initialState)
if f.HasPriority() {
if err := checkPriority(f.StreamID, f.Priority); err != nil {
if err := sc.checkPriority(f.StreamID, f.Priority); err != nil {
return err
}
sc.writeSched.AdjustStream(st.id, f.Priority)
@ -1902,15 +1919,15 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
sc := st.sc
sc.serveG.check()
if st.gotTrailerHeader {
return ConnectionError(ErrCodeProtocol)
return sc.countError("dup_trailers", ConnectionError(ErrCodeProtocol))
}
st.gotTrailerHeader = true
if !f.StreamEnded() {
return streamError(st.id, ErrCodeProtocol)
return sc.countError("trailers_not_ended", streamError(st.id, ErrCodeProtocol))
}
if len(f.PseudoFields()) > 0 {
return streamError(st.id, ErrCodeProtocol)
return sc.countError("trailers_pseudo", streamError(st.id, ErrCodeProtocol))
}
if st.trailer != nil {
for _, hf := range f.RegularFields() {
@ -1919,7 +1936,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
// TODO: send more details to the peer somehow. But http2 has
// no way to send debug data at a stream level. Discuss with
// HTTP folk.
return streamError(st.id, ErrCodeProtocol)
return sc.countError("trailers_bogus", streamError(st.id, ErrCodeProtocol))
}
st.trailer[key] = append(st.trailer[key], hf.Value)
}
@ -1928,13 +1945,13 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
return nil
}
func checkPriority(streamID uint32, p PriorityParam) error {
func (sc *serverConn) checkPriority(streamID uint32, p PriorityParam) error {
if streamID == p.StreamDep {
// Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
// Section 5.3.3 says that a stream can depend on one of its dependencies,
// so it's only self-dependencies that are forbidden.
return streamError(streamID, ErrCodeProtocol)
return sc.countError("priority", streamError(streamID, ErrCodeProtocol))
}
return nil
}
@ -1943,7 +1960,7 @@ func (sc *serverConn) processPriority(f *PriorityFrame) error {
if sc.inGoAway {
return nil
}
if err := checkPriority(f.StreamID, f.PriorityParam); err != nil {
if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
return err
}
sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
@ -2000,7 +2017,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
isConnect := rp.method == "CONNECT"
if isConnect {
if rp.path != "" || rp.scheme != "" || rp.authority == "" {
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol))
}
} else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
// See 8.1.2.6 Malformed Requests and Responses:
@ -2013,13 +2030,13 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
// "All HTTP/2 requests MUST include exactly one valid
// value for the :method, :scheme, and :path
// pseudo-header fields"
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
}
bodyOpen := !f.StreamEnded()
if rp.method == "HEAD" && bodyOpen {
// HEAD requests can't have bodies
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
return nil, nil, sc.countError("head_body", streamError(f.StreamID, ErrCodeProtocol))
}
rp.header = make(http.Header)
@ -2102,7 +2119,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
var err error
url_, err = url.ParseRequestURI(rp.path)
if err != nil {
return nil, nil, streamError(st.id, ErrCodeProtocol)
return nil, nil, sc.countError("bad_path", streamError(st.id, ErrCodeProtocol))
}
requestURI = rp.path
}
@ -2985,3 +3002,31 @@ func h1ServerKeepAlivesDisabled(hs *http.Server) bool {
}
return false
}
func (sc *serverConn) countError(name string, err error) error {
if sc == nil || sc.srv == nil {
return err
}
f := sc.srv.CountError
if f == nil {
return err
}
var typ string
var code ErrCode
switch e := err.(type) {
case ConnectionError:
typ = "conn"
code = ErrCode(e)
case StreamError:
typ = "stream"
code = ErrCode(e.Code)
default:
return err
}
codeStr := errCodeName[code]
if codeStr == "" {
codeStr = strconv.Itoa(int(code))
}
f(fmt.Sprintf("%s_%s_%s", typ, codeStr, name))
return err
}

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,8 @@ type WriteScheduler interface {
// Pop dequeues the next frame to write. Returns false if no frames can
// be written. Frames with a given wr.StreamID() are Pop'd in the same
// order they are Push'd. No frames should be discarded except by CloseStream.
// order they are Push'd, except RST_STREAM frames. No frames should be
// discarded except by CloseStream.
Pop() (wr FrameWriteRequest, ok bool)
}
@ -52,6 +53,7 @@ type FrameWriteRequest struct {
// stream is the stream on which this frame will be written.
// nil for non-stream frames like PING and SETTINGS.
// nil for RST_STREAM streams, which use the StreamError.StreamID field instead.
stream *stream
// done, if non-nil, must be a buffered channel with space for

View File

@ -45,11 +45,11 @@ func (ws *randomWriteScheduler) AdjustStream(streamID uint32, priority PriorityP
}
func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
id := wr.StreamID()
if id == 0 {
if wr.isControl() {
ws.zero.push(wr)
return
}
id := wr.StreamID()
q, ok := ws.sq[id]
if !ok {
q = ws.queuePool.get()
@ -59,7 +59,7 @@ func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
}
func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) {
// Control frames first.
// Control and RST_STREAM frames first.
if !ws.zero.empty() {
return ws.zero.shift(), true
}

14
src/runtime/vendor/golang.org/x/net/idna/go118.go generated vendored Normal file
View File

@ -0,0 +1,14 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package idna
// Transitional processing is disabled by default in Go 1.18.
// https://golang.org/issue/47510
const transitionalLookup = false

View File

@ -59,10 +59,10 @@ type Option func(*options)
// Transitional sets a Profile to use the Transitional mapping as defined in UTS
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
// transitional mapping provides a compromise between IDNA2003 and IDNA2008
// compatibility. It is used by most browsers when resolving domain names. This
// compatibility. It is used by some browsers when resolving domain names. This
// option is only meaningful if combined with MapForLookup.
func Transitional(transitional bool) Option {
return func(o *options) { o.transitional = true }
return func(o *options) { o.transitional = transitional }
}
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
@ -284,7 +284,7 @@ var (
punycode = &Profile{}
lookup = &Profile{options{
transitional: true,
transitional: transitionalLookup,
useSTD3Rules: true,
checkHyphens: true,
checkJoiners: true,

View File

@ -58,10 +58,10 @@ type Option func(*options)
// Transitional sets a Profile to use the Transitional mapping as defined in UTS
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
// transitional mapping provides a compromise between IDNA2003 and IDNA2008
// compatibility. It is used by most browsers when resolving domain names. This
// compatibility. It is used by some browsers when resolving domain names. This
// option is only meaningful if combined with MapForLookup.
func Transitional(transitional bool) Option {
return func(o *options) { o.transitional = true }
return func(o *options) { o.transitional = transitional }
}
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts

12
src/runtime/vendor/golang.org/x/net/idna/pre_go118.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.18
// +build !go1.18
package idna
const transitionalLookup = true

View File

@ -49,6 +49,7 @@ func decode(encoded string) (string, error) {
}
}
i, n, bias := int32(0), initialN, initialBias
overflow := false
for pos < len(encoded) {
oldI, w := i, int32(1)
for k := base; ; k += base {
@ -60,29 +61,32 @@ func decode(encoded string) (string, error) {
return "", punyError(encoded)
}
pos++
i += digit * w
if i < 0 {
i, overflow = madd(i, digit, w)
if overflow {
return "", punyError(encoded)
}
t := k - bias
if t < tmin {
if k <= bias {
t = tmin
} else if t > tmax {
} else if k >= bias+tmax {
t = tmax
}
if digit < t {
break
}
w *= base - t
if w >= math.MaxInt32/base {
w, overflow = madd(0, w, base-t)
if overflow {
return "", punyError(encoded)
}
}
if len(output) >= 1024 {
return "", punyError(encoded)
}
x := int32(len(output) + 1)
bias = adapt(i-oldI, x, oldI == 0)
n += i / x
i %= x
if n > utf8.MaxRune || len(output) >= 1024 {
if n < 0 || n > utf8.MaxRune {
return "", punyError(encoded)
}
output = append(output, 0)
@ -115,6 +119,7 @@ func encode(prefix, s string) (string, error) {
if b > 0 {
output = append(output, '-')
}
overflow := false
for remaining != 0 {
m := int32(0x7fffffff)
for _, r := range s {
@ -122,8 +127,8 @@ func encode(prefix, s string) (string, error) {
m = r
}
}
delta += (m - n) * (h + 1)
if delta < 0 {
delta, overflow = madd(delta, m-n, h+1)
if overflow {
return "", punyError(s)
}
n = m
@ -141,9 +146,9 @@ func encode(prefix, s string) (string, error) {
q := delta
for k := base; ; k += base {
t := k - bias
if t < tmin {
if k <= bias {
t = tmin
} else if t > tmax {
} else if k >= bias+tmax {
t = tmax
}
if q < t {
@ -164,6 +169,15 @@ func encode(prefix, s string) (string, error) {
return string(output), nil
}
// madd computes a + (b * c), detecting overflow.
func madd(a, b, c int32) (next int32, overflow bool) {
p := int64(b) * int64(c)
if p > math.MaxInt32-int64(a) {
return 0, true
}
return a + int32(p), false
}
func decodeDigit(x byte) (digit int32, ok bool) {
switch {
case '0' <= x && x <= '9':

View File

@ -149,7 +149,7 @@ To add a constant, add the header that includes it to the appropriate variable.
Then, edit the regex (if necessary) to match the desired constant. Avoid making
the regex too broad to avoid matching unintended constants.
### mkmerge.go
### internal/mkmerge
This program is used to extract duplicate const, func, and type declarations
from the generated architecture-specific files listed below, and merge these

View File

@ -50,7 +50,7 @@ if [[ "$GOOS" = "linux" ]]; then
# Use the Docker-based build system
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
$cmd docker build --tag generate:$GOOS $GOOS
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")" && /bin/pwd):/build generate:$GOOS
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && /bin/pwd):/build generate:$GOOS
exit
fi

View File

@ -239,6 +239,7 @@ struct ltchars {
#include <linux/magic.h>
#include <linux/memfd.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netlink.h>
#include <linux/net_namespace.h>
@ -260,6 +261,7 @@ struct ltchars {
#include <linux/vm_sockets.h>
#include <linux/wait.h>
#include <linux/watchdog.h>
#include <linux/wireguard.h>
#include <mtd/ubi-user.h>
#include <mtd/mtd-user.h>
@ -520,7 +522,7 @@ ccflags="$@"
$2 ~ /^HW_MACHINE$/ ||
$2 ~ /^SYSCTL_VERS/ ||
$2 !~ "MNT_BITS" &&
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
$2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ ||
$2 ~ /^NS_GET_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||
@ -605,6 +607,7 @@ ccflags="$@"
$2 ~ /^MTD/ ||
$2 ~ /^OTP/ ||
$2 ~ /^MEM/ ||
$2 ~ /^WG/ ||
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
$2 ~ /^__WCOREFLAG$/ {next}
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}

View File

@ -67,9 +67,7 @@ func ParseOrigDstAddr(m *SocketControlMessage) (Sockaddr, error) {
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
case m.Header.Level == SOL_IPV6 && m.Header.Type == IPV6_ORIGDSTADDR:
@ -78,9 +76,7 @@ func ParseOrigDstAddr(m *SocketControlMessage) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
default:

View File

@ -70,9 +70,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
}
@ -85,9 +83,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
}
@ -261,9 +257,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
case AF_INET6:
@ -272,9 +266,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
}
return nil, EAFNOSUPPORT
@ -385,6 +377,11 @@ func (w WaitStatus) TrapCause() int { return -1 }
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
//sys fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range
func Fsync(fd int) error {
return fsyncRange(fd, O_SYNC, 0, 0)
}
/*
* Direct access
*/
@ -401,7 +398,6 @@ func (w WaitStatus) TrapCause() int { return -1 }
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
//sys Fdatasync(fd int) (err error)
//sys Fsync(fd int) (err error)
// readdir_r
//sysnb Getpgid(pid int) (pgid int, err error)
@ -523,8 +519,10 @@ func Pipe(p []int) (err error) {
}
var pp [2]_C_int
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return
}

View File

@ -163,9 +163,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
}
@ -179,9 +177,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
}
@ -210,9 +206,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Nlen = sa.Nlen
sa.raw.Alen = sa.Alen
sa.raw.Slen = sa.Slen
for i := 0; i < len(sa.raw.Data); i++ {
sa.raw.Data[i] = sa.Data[i]
}
sa.raw.Data = sa.Data
return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil
}
@ -228,9 +222,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Nlen = pp.Nlen
sa.Alen = pp.Alen
sa.Slen = pp.Slen
for i := 0; i < len(sa.Data); i++ {
sa.Data[i] = pp.Data[i]
}
sa.Data = pp.Data
return sa, nil
case AF_UNIX:
@ -262,9 +254,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
case AF_INET6:
@ -273,9 +263,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
}
return anyToSockaddrGOOS(fd, rsa)

View File

@ -159,8 +159,10 @@ func Pipe(p []int) (err error) {
}
var x [2]int32
err = pipe(&x)
p[0] = int(x[0])
p[1] = int(x[1])
if err == nil {
p[0] = int(x[0])
p[1] = int(x[1])
}
return
}
@ -430,8 +432,25 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
return x, err
}
func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) {
mib, err := sysctlmib(name)
func SysctlKinfoProc(name string, args ...int) (*KinfoProc, error) {
mib, err := sysctlmib(name, args...)
if err != nil {
return nil, err
}
var kinfo KinfoProc
n := uintptr(SizeofKinfoProc)
if err := sysctl(mib, (*byte)(unsafe.Pointer(&kinfo)), &n, nil, 0); err != nil {
return nil, err
}
if n != SizeofKinfoProc {
return nil, EIO
}
return &kinfo, nil
}
func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
mib, err := sysctlmib(name, args...)
if err != nil {
return nil, err
}

View File

@ -101,7 +101,10 @@ func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
p[0], p[1], err = pipe()
r, w, err := pipe()
if err == nil {
p[0], p[1] = r, w
}
return
}
@ -114,7 +117,10 @@ func Pipe2(p []int, flags int) (err error) {
var pp [2]_C_int
// pipe2 on dragonfly takes an fds array as an argument, but still
// returns the file descriptors.
p[0], p[1], err = pipe2(&pp, flags)
r, w, err := pipe2(&pp, flags)
if err == nil {
p[0], p[1] = r, w
}
return err
}

View File

@ -110,8 +110,10 @@ func Pipe2(p []int, flags int) error {
}
var pp [2]_C_int
err := pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err
}

View File

@ -131,8 +131,10 @@ func Pipe2(p []int, flags int) error {
}
var pp [2]_C_int
err := pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err
}
@ -372,9 +374,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
}
@ -387,9 +387,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
}
@ -438,9 +436,7 @@ func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Hatype = sa.Hatype
sa.raw.Pkttype = sa.Pkttype
sa.raw.Halen = sa.Halen
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil
}
@ -855,12 +851,10 @@ func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) {
if sa.Addr == nil {
return nil, 0, EINVAL
}
sa.raw.Family = AF_TIPC
sa.raw.Scope = int8(sa.Scope)
sa.raw.Addrtype = sa.Addr.tipcAddrtype()
sa.raw.Addr = sa.Addr.tipcAddr()
return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil
}
@ -874,9 +868,7 @@ type SockaddrL2TPIP struct {
func (sa *SockaddrL2TPIP) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_INET
sa.raw.Conn_id = sa.ConnId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP, nil
}
@ -892,9 +884,7 @@ func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_INET6
sa.raw.Conn_id = sa.ConnId
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil
}
@ -990,9 +980,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Hatype = pp.Hatype
sa.Pkttype = pp.Pkttype
sa.Halen = pp.Halen
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
case AF_UNIX:
@ -1031,18 +1019,14 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
pp := (*RawSockaddrL2TPIP)(unsafe.Pointer(rsa))
sa := new(SockaddrL2TPIP)
sa.ConnId = pp.Conn_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
default:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
}
@ -1058,9 +1042,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrL2TPIP6)
sa.ConnId = pp.Conn_id
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
default:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
@ -1068,9 +1050,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
}
@ -1797,6 +1777,16 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
return mount(source, target, fstype, flags, datap)
}
//sys mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) = SYS_MOUNT_SETATTR
// MountSetattr is a wrapper for mount_setattr(2).
// https://man7.org/linux/man-pages/man2/mount_setattr.2.html
//
// Requires kernel >= 5.12.
func MountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr) error {
return mountSetattr(dirfd, pathname, flags, attr, unsafe.Sizeof(*attr))
}
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync))

View File

@ -110,14 +110,8 @@ func direntNamlen(buf []byte) (uint64, bool) {
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}
//sysnb pipe() (fd1 int, fd2 int, err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
p[0], p[1], err = pipe()
return
return Pipe2(p, 0)
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
@ -128,8 +122,10 @@ func Pipe2(p []int, flags int) error {
}
var pp [2]_C_int
err := pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err
}

View File

@ -87,8 +87,10 @@ func Pipe2(p []int, flags int) error {
}
var pp [2]_C_int
err := pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err
}

View File

@ -66,8 +66,10 @@ func Pipe(p []int) (err error) {
if n != 0 {
return err
}
p[0] = int(pp[0])
p[1] = int(pp[1])
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return nil
}
@ -79,8 +81,10 @@ func Pipe2(p []int, flags int) error {
}
var pp [2]_C_int
err := pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err
}
@ -92,9 +96,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
}
@ -107,9 +109,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
}
@ -417,9 +417,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
case AF_INET6:
@ -428,9 +426,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
}
return nil, EAFNOSUPPORT

View File

@ -67,9 +67,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
}
@ -83,9 +81,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
sa.raw.Addr = sa.Addr
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
}
@ -144,9 +140,7 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
case AF_INET6:
@ -155,9 +149,7 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
sa.Addr = pp.Addr
return sa, nil
}
return nil, EAFNOSUPPORT
@ -587,8 +579,10 @@ func Pipe(p []int) (err error) {
}
var pp [2]_C_int
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
if err == nil {
p[0] = int(pp[0])
p[1] = int(pp[1])
}
return
}

View File

@ -1,4 +1,4 @@
// Code generated by mkmerge.go; DO NOT EDIT.
// Code generated by mkmerge; DO NOT EDIT.
//go:build linux
// +build linux
@ -38,7 +38,8 @@ const (
AF_KEY = 0xf
AF_LLC = 0x1a
AF_LOCAL = 0x1
AF_MAX = 0x2d
AF_MAX = 0x2e
AF_MCTP = 0x2d
AF_MPLS = 0x1c
AF_NETBEUI = 0xd
AF_NETLINK = 0x10
@ -116,6 +117,7 @@ const (
ARPHRD_LAPB = 0x204
ARPHRD_LOCALTLK = 0x305
ARPHRD_LOOPBACK = 0x304
ARPHRD_MCTP = 0x122
ARPHRD_METRICOM = 0x17
ARPHRD_NETLINK = 0x338
ARPHRD_NETROM = 0x0
@ -472,6 +474,7 @@ const (
DM_DEV_WAIT = 0xc138fd08
DM_DIR = "mapper"
DM_GET_TARGET_VERSION = 0xc138fd11
DM_IMA_MEASUREMENT_FLAG = 0x80000
DM_INACTIVE_PRESENT_FLAG = 0x40
DM_INTERNAL_SUSPEND_FLAG = 0x40000
DM_IOCTL = 0xfd
@ -716,6 +719,7 @@ const (
ETH_P_LOOPBACK = 0x9000
ETH_P_MACSEC = 0x88e5
ETH_P_MAP = 0xf9
ETH_P_MCTP = 0xfa
ETH_P_MOBITEX = 0x15
ETH_P_MPLS_MC = 0x8848
ETH_P_MPLS_UC = 0x8847
@ -738,6 +742,7 @@ const (
ETH_P_QINQ2 = 0x9200
ETH_P_QINQ3 = 0x9300
ETH_P_RARP = 0x8035
ETH_P_REALTEK = 0x8899
ETH_P_SCA = 0x6007
ETH_P_SLOW = 0x8809
ETH_P_SNAP = 0x5
@ -751,6 +756,21 @@ const (
ETH_P_WCCP = 0x883e
ETH_P_X25 = 0x805
ETH_P_XDSA = 0xf8
EV_ABS = 0x3
EV_CNT = 0x20
EV_FF = 0x15
EV_FF_STATUS = 0x17
EV_KEY = 0x1
EV_LED = 0x11
EV_MAX = 0x1f
EV_MSC = 0x4
EV_PWR = 0x16
EV_REL = 0x2
EV_REP = 0x14
EV_SND = 0x12
EV_SW = 0x5
EV_SYN = 0x0
EV_VERSION = 0x10001
EXABYTE_ENABLE_NEST = 0xf0
EXT2_SUPER_MAGIC = 0xef53
EXT3_SUPER_MAGIC = 0xef53
@ -789,11 +809,15 @@ const (
FAN_DELETE_SELF = 0x400
FAN_DENY = 0x2
FAN_ENABLE_AUDIT = 0x40
FAN_EPIDFD = -0x2
FAN_EVENT_INFO_TYPE_DFID = 0x3
FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2
FAN_EVENT_INFO_TYPE_ERROR = 0x5
FAN_EVENT_INFO_TYPE_FID = 0x1
FAN_EVENT_INFO_TYPE_PIDFD = 0x4
FAN_EVENT_METADATA_LEN = 0x18
FAN_EVENT_ON_CHILD = 0x8000000
FAN_FS_ERROR = 0x8000
FAN_MARK_ADD = 0x1
FAN_MARK_DONT_FOLLOW = 0x4
FAN_MARK_FILESYSTEM = 0x100
@ -811,6 +835,7 @@ const (
FAN_MOVE_SELF = 0x800
FAN_NOFD = -0x1
FAN_NONBLOCK = 0x2
FAN_NOPIDFD = -0x1
FAN_ONDIR = 0x40000000
FAN_OPEN = 0x20
FAN_OPEN_EXEC = 0x1000
@ -821,6 +846,7 @@ const (
FAN_REPORT_DIR_FID = 0x400
FAN_REPORT_FID = 0x200
FAN_REPORT_NAME = 0x800
FAN_REPORT_PIDFD = 0x80
FAN_REPORT_TID = 0x100
FAN_UNLIMITED_MARKS = 0x20
FAN_UNLIMITED_QUEUE = 0x10
@ -1454,6 +1480,18 @@ const (
MNT_FORCE = 0x1
MODULE_INIT_IGNORE_MODVERSIONS = 0x1
MODULE_INIT_IGNORE_VERMAGIC = 0x2
MOUNT_ATTR_IDMAP = 0x100000
MOUNT_ATTR_NOATIME = 0x10
MOUNT_ATTR_NODEV = 0x4
MOUNT_ATTR_NODIRATIME = 0x80
MOUNT_ATTR_NOEXEC = 0x8
MOUNT_ATTR_NOSUID = 0x2
MOUNT_ATTR_NOSYMFOLLOW = 0x200000
MOUNT_ATTR_RDONLY = 0x1
MOUNT_ATTR_RELATIME = 0x0
MOUNT_ATTR_SIZE_VER0 = 0x20
MOUNT_ATTR_STRICTATIME = 0x20
MOUNT_ATTR__ATIME = 0x70
MSDOS_SUPER_MAGIC = 0x4d44
MSG_BATCH = 0x40000
MSG_CMSG_CLOEXEC = 0x40000000
@ -1793,6 +1831,8 @@ const (
PERF_MEM_BLK_DATA = 0x2
PERF_MEM_BLK_NA = 0x1
PERF_MEM_BLK_SHIFT = 0x28
PERF_MEM_HOPS_0 = 0x1
PERF_MEM_HOPS_SHIFT = 0x2b
PERF_MEM_LOCK_LOCKED = 0x2
PERF_MEM_LOCK_NA = 0x1
PERF_MEM_LOCK_SHIFT = 0x18
@ -1952,6 +1992,9 @@ const (
PR_SCHED_CORE_CREATE = 0x1
PR_SCHED_CORE_GET = 0x0
PR_SCHED_CORE_MAX = 0x4
PR_SCHED_CORE_SCOPE_PROCESS_GROUP = 0x2
PR_SCHED_CORE_SCOPE_THREAD = 0x0
PR_SCHED_CORE_SCOPE_THREAD_GROUP = 0x1
PR_SCHED_CORE_SHARE_FROM = 0x3
PR_SCHED_CORE_SHARE_TO = 0x2
PR_SET_CHILD_SUBREAPER = 0x24
@ -1997,6 +2040,7 @@ const (
PR_SPEC_ENABLE = 0x2
PR_SPEC_FORCE_DISABLE = 0x8
PR_SPEC_INDIRECT_BRANCH = 0x1
PR_SPEC_L1D_FLUSH = 0x2
PR_SPEC_NOT_AFFECTED = 0x0
PR_SPEC_PRCTL = 0x1
PR_SPEC_STORE_BYPASS = 0x0
@ -2132,12 +2176,23 @@ const (
RTCF_NAT = 0x800000
RTCF_VALVE = 0x200000
RTC_AF = 0x20
RTC_BSM_DIRECT = 0x1
RTC_BSM_DISABLED = 0x0
RTC_BSM_LEVEL = 0x2
RTC_BSM_STANDBY = 0x3
RTC_FEATURE_ALARM = 0x0
RTC_FEATURE_ALARM_RES_2S = 0x3
RTC_FEATURE_ALARM_RES_MINUTE = 0x1
RTC_FEATURE_CNT = 0x3
RTC_FEATURE_BACKUP_SWITCH_MODE = 0x6
RTC_FEATURE_CNT = 0x7
RTC_FEATURE_CORRECTION = 0x5
RTC_FEATURE_NEED_WEEK_DAY = 0x2
RTC_FEATURE_UPDATE_INTERRUPT = 0x4
RTC_IRQF = 0x80
RTC_MAX_FREQ = 0x2000
RTC_PARAM_BACKUP_SWITCH_MODE = 0x2
RTC_PARAM_CORRECTION = 0x1
RTC_PARAM_FEATURES = 0x0
RTC_PF = 0x40
RTC_UF = 0x10
RTF_ADDRCLASSMASK = 0xf8000000
@ -2432,12 +2487,15 @@ const (
SMART_WRITE_THRESHOLDS = 0xd7
SMB_SUPER_MAGIC = 0x517b
SOCKFS_MAGIC = 0x534f434b
SOCK_BUF_LOCK_MASK = 0x3
SOCK_DCCP = 0x6
SOCK_IOC_TYPE = 0x89
SOCK_PACKET = 0xa
SOCK_RAW = 0x3
SOCK_RCVBUF_LOCK = 0x2
SOCK_RDM = 0x4
SOCK_SEQPACKET = 0x5
SOCK_SNDBUF_LOCK = 0x1
SOL_AAL = 0x109
SOL_ALG = 0x117
SOL_ATM = 0x108
@ -2494,6 +2552,8 @@ const (
SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1
SO_VM_SOCKETS_BUFFER_SIZE = 0x0
SO_VM_SOCKETS_CONNECT_TIMEOUT = 0x6
SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW = 0x8
SO_VM_SOCKETS_CONNECT_TIMEOUT_OLD = 0x6
SO_VM_SOCKETS_NONBLOCK_TXRX = 0x7
SO_VM_SOCKETS_PEER_HOST_VM_ID = 0x3
SO_VM_SOCKETS_TRUSTED = 0x5
@ -2788,6 +2848,13 @@ const (
WDIOS_TEMPPANIC = 0x4
WDIOS_UNKNOWN = -0x1
WEXITED = 0x4
WGALLOWEDIP_A_MAX = 0x3
WGDEVICE_A_MAX = 0x8
WGPEER_A_MAX = 0xa
WG_CMD_MAX = 0x1
WG_GENL_NAME = "wireguard"
WG_GENL_VERSION = 0x1
WG_KEY_LEN = 0x20
WIN_ACKMEDIACHANGE = 0xdb
WIN_CHECKPOWERMODE1 = 0xe5
WIN_CHECKPOWERMODE2 = 0x98

View File

@ -5,7 +5,7 @@
// +build 386,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/_const.go
package unix
@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x4004700e
RTC_IRQP_READ = 0x8004700b
RTC_IRQP_SET = 0x4004700c
RTC_PARAM_GET = 0x40187013
RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x801c7011
@ -293,6 +295,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -326,6 +329,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build amd64,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/_const.go
package unix
@ -251,6 +251,8 @@ const (
RTC_EPOCH_SET = 0x4008700e
RTC_IRQP_READ = 0x8008700b
RTC_IRQP_SET = 0x4008700c
RTC_PARAM_GET = 0x40187013
RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x80207011
@ -294,6 +296,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -327,6 +330,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build arm,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -257,6 +257,8 @@ const (
RTC_EPOCH_SET = 0x4004700e
RTC_IRQP_READ = 0x8004700b
RTC_IRQP_SET = 0x4004700c
RTC_PARAM_GET = 0x40187013
RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x801c7011
@ -300,6 +302,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -333,6 +336,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build arm64,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go
package unix
@ -247,6 +247,8 @@ const (
RTC_EPOCH_SET = 0x4008700e
RTC_IRQP_READ = 0x8008700b
RTC_IRQP_SET = 0x4008700c
RTC_PARAM_GET = 0x40187013
RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x80207011
@ -290,6 +292,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -323,6 +326,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build mips,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x8004700e
RTC_IRQP_READ = 0x4004700b
RTC_IRQP_SET = 0x8004700c
RTC_PARAM_GET = 0x80187013
RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x401c7011
@ -293,6 +295,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x20
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -326,6 +329,7 @@ const (
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build mips64,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
RTC_PARAM_GET = 0x80187013
RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@ -293,6 +295,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x20
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -326,6 +329,7 @@ const (
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build mips64le,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
RTC_PARAM_GET = 0x80187013
RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@ -293,6 +295,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x20
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -326,6 +329,7 @@ const (
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build mipsle,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x8004700e
RTC_IRQP_READ = 0x4004700b
RTC_IRQP_SET = 0x8004700c
RTC_PARAM_GET = 0x80187013
RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x401c7011
@ -293,6 +295,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x20
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -326,6 +329,7 @@ const (
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build ppc,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -305,6 +305,8 @@ const (
RTC_EPOCH_SET = 0x8004700e
RTC_IRQP_READ = 0x4004700b
RTC_IRQP_SET = 0x8004700c
RTC_PARAM_GET = 0x80187013
RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x401c7011
@ -348,6 +350,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -381,6 +384,7 @@ const (
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build ppc64,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -309,6 +309,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
RTC_PARAM_GET = 0x80187013
RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@ -352,6 +354,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -385,6 +388,7 @@ const (
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build ppc64le,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -309,6 +309,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
RTC_PARAM_GET = 0x80187013
RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@ -352,6 +354,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -385,6 +388,7 @@ const (
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build riscv64,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -238,6 +238,8 @@ const (
RTC_EPOCH_SET = 0x4008700e
RTC_IRQP_READ = 0x8008700b
RTC_IRQP_SET = 0x4008700c
RTC_PARAM_GET = 0x40187013
RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x80207011
@ -281,6 +283,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -314,6 +317,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build s390x,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go
package unix
@ -313,6 +313,8 @@ const (
RTC_EPOCH_SET = 0x4008700e
RTC_IRQP_READ = 0x8008700b
RTC_IRQP_SET = 0x4008700c
RTC_PARAM_GET = 0x40187013
RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x80207011
@ -356,6 +358,7 @@ const (
SO_BPF_EXTENSIONS = 0x30
SO_BROADCAST = 0x6
SO_BSDCOMPAT = 0xe
SO_BUF_LOCK = 0x48
SO_BUSY_POLL = 0x2e
SO_BUSY_POLL_BUDGET = 0x46
SO_CNX_ADVICE = 0x35
@ -389,6 +392,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28

View File

@ -5,7 +5,7 @@
// +build sparc64,linux
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
package unix
@ -304,6 +304,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
RTC_PARAM_GET = 0x80187013
RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@ -347,6 +349,7 @@ const (
SO_BPF_EXTENSIONS = 0x32
SO_BROADCAST = 0x20
SO_BSDCOMPAT = 0x400
SO_BUF_LOCK = 0x51
SO_BUSY_POLL = 0x30
SO_BUSY_POLL_BUDGET = 0x49
SO_CNX_ADVICE = 0x37
@ -380,6 +383,7 @@ const (
SO_RCVTIMEO = 0x2000
SO_RCVTIMEO_NEW = 0x44
SO_RCVTIMEO_OLD = 0x2000
SO_RESERVE_MEM = 0x52
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x24

View File

@ -17,6 +17,7 @@ int getdirent(int, uintptr_t, size_t);
int wait4(int, uintptr_t, int, uintptr_t);
int ioctl(int, int, uintptr_t);
int fcntl(uintptr_t, int, uintptr_t);
int fsync_range(int, int, long long, long long);
int acct(uintptr_t);
int chdir(uintptr_t);
int chroot(uintptr_t);
@ -29,7 +30,6 @@ int fchmod(int, unsigned int);
int fchmodat(int, uintptr_t, unsigned int, int);
int fchownat(int, uintptr_t, int, int, int);
int fdatasync(int);
int fsync(int);
int getpgid(int);
int getpgrp();
int getpid();
@ -255,6 +255,16 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fsyncRange(fd int, how int, start int64, length int64) (err error) {
r0, er := C.fsync_range(C.int(fd), C.int(how), C.longlong(start), C.longlong(length))
if r0 == -1 && er != nil {
err = er
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Acct(path string) (err error) {
_p0 := uintptr(unsafe.Pointer(C.CString(path)))
r0, er := C.acct(C.uintptr_t(_p0))
@ -379,16 +389,6 @@ func Fdatasync(fd int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fsync(fd int) (err error) {
r0, er := C.fsync(C.int(fd))
if r0 == -1 && er != nil {
err = er
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getpgid(pid int) (pgid int, err error) {
r0, er := C.getpgid(C.int(pid))
pgid = int(r0)

View File

@ -135,6 +135,16 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fsyncRange(fd int, how int, start int64, length int64) (err error) {
_, e1 := callfsync_range(fd, how, start, length)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Acct(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
@ -283,16 +293,6 @@ func Fdatasync(fd int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fsync(fd int) (err error) {
_, e1 := callfsync(fd)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getpgid(pid int) (pgid int, err error) {
r0, e1 := callgetpgid(pid)
pgid = int(r0)

View File

@ -18,6 +18,7 @@ import (
//go:cgo_import_dynamic libc_wait4 wait4 "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fsync_range fsync_range "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_acct acct "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o"
@ -30,7 +31,6 @@ import (
//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fchownat fchownat "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fdatasync fdatasync "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_fsync fsync "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_getpgid getpgid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_getpid getpid "libc.a/shr_64.o"
@ -136,6 +136,7 @@ import (
//go:linkname libc_wait4 libc_wait4
//go:linkname libc_ioctl libc_ioctl
//go:linkname libc_fcntl libc_fcntl
//go:linkname libc_fsync_range libc_fsync_range
//go:linkname libc_acct libc_acct
//go:linkname libc_chdir libc_chdir
//go:linkname libc_chroot libc_chroot
@ -148,7 +149,6 @@ import (
//go:linkname libc_fchmodat libc_fchmodat
//go:linkname libc_fchownat libc_fchownat
//go:linkname libc_fdatasync libc_fdatasync
//go:linkname libc_fsync libc_fsync
//go:linkname libc_getpgid libc_getpgid
//go:linkname libc_getpgrp libc_getpgrp
//go:linkname libc_getpid libc_getpid
@ -257,6 +257,7 @@ var (
libc_wait4,
libc_ioctl,
libc_fcntl,
libc_fsync_range,
libc_acct,
libc_chdir,
libc_chroot,
@ -269,7 +270,6 @@ var (
libc_fchmodat,
libc_fchownat,
libc_fdatasync,
libc_fsync,
libc_getpgid,
libc_getpgrp,
libc_getpid,
@ -430,6 +430,13 @@ func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callfsync_range(fd int, how int, start int64, length int64) (r1 uintptr, e1 Errno) {
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync_range)), 4, uintptr(fd), uintptr(how), uintptr(start), uintptr(length), 0, 0)
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) {
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_acct)), 1, _p0, 0, 0, 0, 0, 0)
return
@ -514,13 +521,6 @@ func callfdatasync(fd int) (r1 uintptr, e1 Errno) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callfsync(fd int) (r1 uintptr, e1 Errno) {
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync)), 1, uintptr(fd), 0, 0, 0, 0, 0)
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callgetpgid(pid int) (r1 uintptr, e1 Errno) {
r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getpgid)), 1, uintptr(pid), 0, 0, 0, 0, 0)
return

View File

@ -16,6 +16,7 @@ int getdirent(int, uintptr_t, size_t);
int wait4(int, uintptr_t, int, uintptr_t);
int ioctl(int, int, uintptr_t);
int fcntl(uintptr_t, int, uintptr_t);
int fsync_range(int, int, long long, long long);
int acct(uintptr_t);
int chdir(uintptr_t);
int chroot(uintptr_t);
@ -28,7 +29,6 @@ int fchmod(int, unsigned int);
int fchmodat(int, uintptr_t, unsigned int, int);
int fchownat(int, uintptr_t, int, int, int);
int fdatasync(int);
int fsync(int);
int getpgid(int);
int getpgrp();
int getpid();
@ -199,6 +199,14 @@ func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callfsync_range(fd int, how int, start int64, length int64) (r1 uintptr, e1 Errno) {
r1 = uintptr(C.fsync_range(C.int(fd), C.int(how), C.longlong(start), C.longlong(length)))
e1 = syscall.GetErrno()
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) {
r1 = uintptr(C.acct(C.uintptr_t(_p0)))
e1 = syscall.GetErrno()
@ -295,14 +303,6 @@ func callfdatasync(fd int) (r1 uintptr, e1 Errno) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callfsync(fd int) (r1 uintptr, e1 Errno) {
r1 = uintptr(C.fsync(C.int(fd)))
e1 = syscall.GetErrno()
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callgetpgid(pid int) (r1 uintptr, e1 Errno) {
r1 = uintptr(C.getpgid(C.int(pid)))
e1 = syscall.GetErrno()

View File

@ -1,4 +1,4 @@
// Code generated by mkmerge.go; DO NOT EDIT.
// Code generated by mkmerge; DO NOT EDIT.
//go:build linux
// +build linux
@ -409,6 +409,21 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(pathname)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_MOUNT_SETATTR, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(unsafe.Pointer(attr)), uintptr(size), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Acct(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)

View File

@ -351,18 +351,6 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe() (fd1 int, fd2 int, err error) {
r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
fd1 = int(r0)
fd2 = int(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {

View File

@ -351,18 +351,6 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe() (fd1 int, fd2 int, err error) {
r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
fd1 = int(r0)
fd2 = int(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {

View File

@ -351,18 +351,6 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe() (fd1 int, fd2 int, err error) {
r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
fd1 = int(r0)
fd2 = int(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {

View File

@ -351,18 +351,6 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe() (fd1 int, fd2 int, err error) {
r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
fd1 = int(r0)
fd2 = int(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {

View File

@ -444,4 +444,6 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
)

View File

@ -366,4 +366,6 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
)

View File

@ -7,6 +7,7 @@
package unix
const (
SYS_SYSCALL_MASK = 0
SYS_RESTART_SYSCALL = 0
SYS_EXIT = 1
SYS_FORK = 2
@ -407,4 +408,6 @@ const (
SYS_LANDLOCK_CREATE_RULESET = 444
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
)

View File

@ -311,4 +311,6 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
)

View File

@ -428,4 +428,6 @@ const (
SYS_LANDLOCK_CREATE_RULESET = 4444
SYS_LANDLOCK_ADD_RULE = 4445
SYS_LANDLOCK_RESTRICT_SELF = 4446
SYS_PROCESS_MRELEASE = 4448
SYS_FUTEX_WAITV = 4449
)

View File

@ -358,4 +358,6 @@ const (
SYS_LANDLOCK_CREATE_RULESET = 5444
SYS_LANDLOCK_ADD_RULE = 5445
SYS_LANDLOCK_RESTRICT_SELF = 5446
SYS_PROCESS_MRELEASE = 5448
SYS_FUTEX_WAITV = 5449
)

View File

@ -358,4 +358,6 @@ const (
SYS_LANDLOCK_CREATE_RULESET = 5444
SYS_LANDLOCK_ADD_RULE = 5445
SYS_LANDLOCK_RESTRICT_SELF = 5446
SYS_PROCESS_MRELEASE = 5448
SYS_FUTEX_WAITV = 5449
)

View File

@ -428,4 +428,6 @@ const (
SYS_LANDLOCK_CREATE_RULESET = 4444
SYS_LANDLOCK_ADD_RULE = 4445
SYS_LANDLOCK_RESTRICT_SELF = 4446
SYS_PROCESS_MRELEASE = 4448
SYS_FUTEX_WAITV = 4449
)

View File

@ -435,4 +435,6 @@ const (
SYS_LANDLOCK_CREATE_RULESET = 444
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
)

Some files were not shown because too many files have changed in this diff Show More