mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
@@ -12,21 +12,25 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/ultravioletrs/cocosvm/agent"
|
||||
"github.com/ultravioletrs/cocosvm/agent/api"
|
||||
agenthttpapi "github.com/ultravioletrs/cocosvm/agent/api/agent/http"
|
||||
"github.com/ultravioletrs/cocosvm/manager"
|
||||
"github.com/ultravioletrs/cocosvm/manager/api"
|
||||
managerhttpapi "github.com/ultravioletrs/cocosvm/manager/api/manager/http"
|
||||
|
||||
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
jconfig "github.com/uber/jaeger-client-go/config"
|
||||
|
||||
"github.com/digitalocean/go-libvirt"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -37,11 +41,11 @@ const (
|
||||
defServerKey = ""
|
||||
defSecret = "secret"
|
||||
|
||||
envLogLevel = "CC_AGENT_LOG_LEVEL"
|
||||
envHTTPPort = "CC_AGENT_HTTP_PORT"
|
||||
envServerCert = "CC_AGENT_SERVER_CERT"
|
||||
envServerKey = "CC_AGENT_SERVER_KEY"
|
||||
envSecret = "CC_AGENT_SECRET"
|
||||
envLogLevel = "CC_MANAGER_LOG_LEVEL"
|
||||
envHTTPPort = "CC_MANAGER_HTTP_PORT"
|
||||
envServerCert = "CC_MANAGER_SERVER_CERT"
|
||||
envServerKey = "CC_MANAGER_SERVER_KEY"
|
||||
envSecret = "CC_MANAGER_SECRET"
|
||||
envJaegerURL = "CC_JAEGER_URL"
|
||||
)
|
||||
|
||||
@@ -64,13 +68,16 @@ func main() {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
agentTracer, agentCloser := initJaeger("agent", cfg.jaegerURL, logger)
|
||||
defer agentCloser.Close()
|
||||
managerTracer, managerCloser := initJaeger("manager", cfg.jaegerURL, logger)
|
||||
defer managerCloser.Close()
|
||||
|
||||
libvirtConn := initLibvirt(logger)
|
||||
defer libvirtConn.Disconnect()
|
||||
|
||||
svc := newService(cfg.secret, libvirtConn, logger)
|
||||
|
||||
svc := newService(cfg.secret, logger)
|
||||
errs := make(chan error, 2)
|
||||
|
||||
go startHTTPServer(agenthttpapi.MakeHandler(agentTracer, svc), cfg.httpPort, cfg, logger, errs)
|
||||
go startHTTPServer(managerhttpapi.MakeHandler(managerTracer, svc), cfg.httpPort, cfg, logger, errs)
|
||||
|
||||
go func() {
|
||||
c := make(chan os.Signal)
|
||||
@@ -79,7 +86,7 @@ func main() {
|
||||
}()
|
||||
|
||||
err = <-errs
|
||||
logger.Error(fmt.Sprintf("Agent service terminated: %s", err))
|
||||
logger.Error(fmt.Sprintf("Manager service terminated: %s", err))
|
||||
}
|
||||
|
||||
func loadConfig() config {
|
||||
@@ -117,20 +124,20 @@ func initJaeger(svcName, url string, logger logger.Logger) (opentracing.Tracer,
|
||||
return tracer, closer
|
||||
}
|
||||
|
||||
func newService(secret string, logger logger.Logger) agent.Service {
|
||||
svc := agent.New(secret)
|
||||
func newService(secret string, libvirtConn *libvirt.Libvirt, logger logger.Logger) manager.Service {
|
||||
svc := manager.New(secret, libvirtConn)
|
||||
|
||||
svc = api.LoggingMiddleware(svc, logger)
|
||||
svc = api.MetricsMiddleware(
|
||||
svc,
|
||||
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
|
||||
Namespace: "agent",
|
||||
Namespace: "manager",
|
||||
Subsystem: "api",
|
||||
Name: "request_count",
|
||||
Help: "Number of requests received.",
|
||||
}, []string{"method"}),
|
||||
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
|
||||
Namespace: "agent",
|
||||
Namespace: "manager",
|
||||
Subsystem: "api",
|
||||
Name: "request_latency_microseconds",
|
||||
Help: "Total duration of requests in microseconds.",
|
||||
@@ -143,11 +150,44 @@ func newService(secret string, logger logger.Logger) agent.Service {
|
||||
func startHTTPServer(handler http.Handler, port string, cfg config, logger logger.Logger, errs chan error) {
|
||||
p := fmt.Sprintf(":%s", port)
|
||||
if cfg.serverCert != "" || cfg.serverKey != "" {
|
||||
logger.Info(fmt.Sprintf("Agent service started using https on port %s with cert %s key %s",
|
||||
logger.Info(fmt.Sprintf("Manager service started using https on port %s with cert %s key %s",
|
||||
port, cfg.serverCert, cfg.serverKey))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, handler)
|
||||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Agent service started using http on port %s", cfg.httpPort))
|
||||
logger.Info(fmt.Sprintf("Manager service started using http on port %s", cfg.httpPort))
|
||||
errs <- http.ListenAndServe(p, handler)
|
||||
}
|
||||
|
||||
func initLibvirt(logger logger.Logger) *libvirt.Libvirt {
|
||||
// This dials libvirt on the local machine, but you can substitute the first
|
||||
// two parameters with "tcp", "<ip address>:<port>" to connect to libvirt on
|
||||
// a remote machine.
|
||||
c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", 2*time.Second)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to dial libvirt: %v", err)
|
||||
}
|
||||
|
||||
l := libvirt.New(c)
|
||||
if err := l.Connect(); err != nil {
|
||||
log.Fatalf("failed to connect: %v", err)
|
||||
}
|
||||
|
||||
v, err := l.Version()
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to retrieve libvirt version: %v", err))
|
||||
}
|
||||
fmt.Println("Version:", v)
|
||||
|
||||
domains, err := l.Domains()
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to retrieve domains: %v", err))
|
||||
}
|
||||
fmt.Println("ID\tName\t\tUUID")
|
||||
fmt.Printf("--------------------------------------------------------\n")
|
||||
for _, d := range domains {
|
||||
fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
# Docker: Environment variables in Compose
|
||||
|
||||
## Agent
|
||||
CC_AGENT_LOG_LEVEL=debug
|
||||
CC_AGENT_HTTP_PORT=9021
|
||||
CC_AGENT_SECRET=secret
|
||||
CC_AGENT_SERVER_CERT=""
|
||||
CC_AGENT_SERVER_KEY=""
|
||||
## Manager
|
||||
CC_MANAGER_LOG_LEVEL=debug
|
||||
CC_MANAGER_HTTP_PORT=9021
|
||||
CC_MANAGER_SECRET=secret
|
||||
CC_MANAGER_SERVER_CERT=""
|
||||
CC_MANAGER_SERVER_KEY=""
|
||||
CC_JAEGER_URL="jaeger:6831"
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
FROM golang:1.16-alpine AS builder
|
||||
|
||||
WORKDIR /go/src/github.com/mainflux/agent
|
||||
WORKDIR /go/src/github.com/mainflux/manager
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 GOARCH=amd64 \
|
||||
go build -mod=vendor -ldflags "-s -w" -o build/mainflux-agent cmd/agent/main.go \
|
||||
&& mv build/mainflux-agent /exe
|
||||
go build -mod=vendor -ldflags "-s -w" -o build/mainflux-manager cmd/manager/main.go \
|
||||
&& mv build/mainflux-manager /exe
|
||||
|
||||
FROM scratch
|
||||
COPY --from=builder /exe /
|
||||
|
||||
@@ -13,18 +13,18 @@ networks:
|
||||
external: true
|
||||
|
||||
services:
|
||||
agent:
|
||||
image: mainflux/agent:latest
|
||||
container_name: mainflux-agent
|
||||
manager:
|
||||
image: mainflux/manager:latest
|
||||
container_name: mainflux-manager
|
||||
restart: on-failure
|
||||
environment:
|
||||
CC_AGENT_LOG_LEVEL: ${CC_AGENT_LOG_LEVEL}
|
||||
CC_AGENT_HTTP_PORT: ${CC_AGENT_HTTP_PORT}
|
||||
CC_AGENT_SERVER_CERT: ${CC_AGENT_SERVER_CERT}
|
||||
CC_AGENT_SERVER_KEY: ${CC_AGENT_SERVER_KEY}
|
||||
CC_MANAGER_LOG_LEVEL: ${CC_MANAGER_LOG_LEVEL}
|
||||
CC_MANAGER_HTTP_PORT: ${CC_MANAGER_HTTP_PORT}
|
||||
CC_MANAGER_SERVER_CERT: ${CC_MANAGER_SERVER_CERT}
|
||||
CC_MANAGER_SERVER_KEY: ${CC_MANAGER_SERVER_KEY}
|
||||
CC_JAEGER_URL: ${CC_JAEGER_URL}
|
||||
CC_AGENT_SECRET: ${CC_AGENT_SECRET}
|
||||
CC_MANAGER_SECRET: ${CC_MANAGER_SECRET}
|
||||
ports:
|
||||
- ${CC_AGENT_HTTP_PORT}:${CC_AGENT_HTTP_PORT}
|
||||
- ${CC_MANAGER_HTTP_PORT}:${CC_MANAGER_HTTP_PORT}
|
||||
networks:
|
||||
- docker_mainflux-base-net
|
||||
|
||||
@@ -3,6 +3,7 @@ module github.com/ultravioletrs/cocosvm
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/digitalocean/go-libvirt v0.0.0-20221205150000-2939327a8519
|
||||
github.com/go-kit/kit v0.12.0
|
||||
github.com/go-zoo/bone v1.3.0
|
||||
github.com/mainflux/mainflux v0.12.0
|
||||
@@ -25,8 +26,8 @@ require (
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/uber/jaeger-lib v2.0.0+incompatible // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 // indirect
|
||||
google.golang.org/grpc v1.40.0 // indirect
|
||||
|
||||
@@ -128,6 +128,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xb
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/digitalocean/go-libvirt v0.0.0-20221205150000-2939327a8519 h1:OpkN/n40cmKenDQS+IOAeW9DLhYy4DADSeZnouCEV/E=
|
||||
github.com/digitalocean/go-libvirt v0.0.0-20221205150000-2939327a8519/go.mod h1:WyJJyfmJ0gWJvjV+ZH4DOgtOYZc1KOvYyBXWCLKxsUU=
|
||||
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
@@ -663,16 +665,21 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
@@ -708,6 +715,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
@@ -756,6 +764,7 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -792,6 +801,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -830,11 +840,13 @@ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
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=
|
||||
@@ -853,6 +865,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -916,8 +929,9 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/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=
|
||||
@@ -996,6 +1010,7 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1146,8 +1161,9 @@ gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Agent
|
||||
# Manager
|
||||
|
||||
Agent service provides a barebones HTTP API and Service interface implementation for development of a core Mainflux service.
|
||||
Manager service provides a barebones HTTP API and Service interface implementation for development of a core Mainflux service.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -8,12 +8,12 @@ The service is configured using the environment variables from the following tab
|
||||
|
||||
| Variable | Description | Default |
|
||||
|-----------------------|---------------------------------------------------------|---------|
|
||||
| CC_AGENT_LOG_LEVEL | Log level for agent service (debug, info, warn, error) | error |
|
||||
| CC_AGENT_HTTP_PORT | Agent service HTTP port | 9021 |
|
||||
| CC_AGENT_SERVER_CERT | Path to server certificate in pem format | |
|
||||
| CC_AGENT_SERVER_KEY | Path to server key in pem format | |
|
||||
| CC_MANAGER_LOG_LEVEL | Log level for manager service (debug, info, warn, error) | error |
|
||||
| CC_MANAGER_HTTP_PORT | Manager service HTTP port | 9021 |
|
||||
| CC_MANAGER_SERVER_CERT | Path to server certificate in pem format | |
|
||||
| CC_MANAGER_SERVER_KEY | Path to server key in pem format | |
|
||||
| CC_JAEGER_URL | Jaeger server URL | |
|
||||
| CC_AGENT_SECRET | Agent service secret | secret |
|
||||
| CC_MANAGER_SECRET | Manager service secret | secret |
|
||||
|
||||
## Deployment
|
||||
|
||||
@@ -22,17 +22,17 @@ The service is distributed as a Docker container. The following snippet provides
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
agent:
|
||||
image: mainflux/agent:[version]
|
||||
manager:
|
||||
image: mainflux/manager:[version]
|
||||
container_name: [instance name]
|
||||
ports:
|
||||
- [host machine port]:[configured HTTP port]
|
||||
environment:
|
||||
CC_AGENT_LOG_LEVEL: [Kit log level]
|
||||
CC_AGENT_HTTP_PORT: [Service HTTP port]
|
||||
CC_AGENT_SERVER_CERT: [String path to server cert in pem format]
|
||||
CC_AGENT_SERVER_KEY: [String path to server key in pem format]
|
||||
CC_AGENT_SECRET: [Agent service secret]
|
||||
CC_MANAGER_LOG_LEVEL: [Kit log level]
|
||||
CC_MANAGER_HTTP_PORT: [Service HTTP port]
|
||||
CC_MANAGER_SERVER_CERT: [String path to server cert in pem format]
|
||||
CC_MANAGER_SERVER_KEY: [String path to server key in pem format]
|
||||
CC_MANAGER_SECRET: [Manager service secret]
|
||||
CC_JAEGER_URL: [Jaeger server URL]
|
||||
```
|
||||
|
||||
@@ -44,14 +44,14 @@ go get github.com/mainflux/mainflux
|
||||
|
||||
cd $GOPATH/src/github.com/mainflux/mainflux
|
||||
|
||||
# compile the agent
|
||||
make agent
|
||||
# compile the manager
|
||||
make manager
|
||||
|
||||
# copy binary to bin
|
||||
make install
|
||||
|
||||
# set the environment variables and run the service
|
||||
CC_AGENT_LOG_LEVEL=[Kit log level] CC_AGENT_HTTP_PORT=[Service HTTP port] CC_AGENT_SERVER_CERT: [String path to server cert in pem format] CC_AGENT_SERVER_KEY: [String path to server key in pem format] CC_JAEGER_URL=[Jaeger server URL] CC_AGENT_SECRET: [Agent service secret] $GOBIN/mainflux-kit
|
||||
CC_MANAGER_LOG_LEVEL=[Kit log level] CC_MANAGER_HTTP_PORT=[Service HTTP port] CC_MANAGER_SERVER_CERT: [String path to server cert in pem format] CC_MANAGER_SERVER_KEY: [String path to server key in pem format] CC_JAEGER_URL=[Jaeger server URL] CC_MANAGER_SECRET: [Manager service secret] $GOBIN/mainflux-kit
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -11,18 +11,18 @@ import (
|
||||
"time"
|
||||
|
||||
log "github.com/mainflux/mainflux/logger"
|
||||
"github.com/ultravioletrs/cocosvm/agent"
|
||||
"github.com/ultravioletrs/cocosvm/manager"
|
||||
)
|
||||
|
||||
var _ agent.Service = (*loggingMiddleware)(nil)
|
||||
var _ manager.Service = (*loggingMiddleware)(nil)
|
||||
|
||||
type loggingMiddleware struct {
|
||||
logger log.Logger
|
||||
svc agent.Service
|
||||
svc manager.Service
|
||||
}
|
||||
|
||||
// LoggingMiddleware adds logging facilities to the core service.
|
||||
func LoggingMiddleware(svc agent.Service, logger log.Logger) agent.Service {
|
||||
func LoggingMiddleware(svc manager.Service, logger log.Logger) manager.Service {
|
||||
return &loggingMiddleware{logger, svc}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/ultravioletrs/cocosvm/agent"
|
||||
"github.com/ultravioletrs/cocosvm/manager"
|
||||
)
|
||||
|
||||
func pingEndpoint(svc agent.Service) endpoint.Endpoint {
|
||||
func pingEndpoint(svc manager.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(pingReq)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
package http
|
||||
|
||||
import "github.com/ultravioletrs/cocosvm/agent"
|
||||
import "github.com/ultravioletrs/cocosvm/manager"
|
||||
|
||||
type apiReq interface {
|
||||
validate() error
|
||||
@@ -15,7 +15,7 @@ type pingReq struct {
|
||||
|
||||
func (req pingReq) validate() error {
|
||||
if req.Secret == "" {
|
||||
return agent.ErrMalformedEntity
|
||||
return manager.ErrMalformedEntity
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"github.com/mainflux/mainflux"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/ultravioletrs/cocosvm/agent"
|
||||
"github.com/ultravioletrs/cocosvm/manager"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -31,7 +31,7 @@ var (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(tracer opentracing.Tracer, svc agent.Service) http.Handler {
|
||||
func MakeHandler(tracer opentracing.Tracer, svc manager.Service) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
}
|
||||
@@ -86,9 +86,9 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
|
||||
switch err {
|
||||
case agent.ErrMalformedEntity:
|
||||
case manager.ErrMalformedEntity:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case agent.ErrUnauthorizedAccess:
|
||||
case manager.ErrUnauthorizedAccess:
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
case errUnsupportedContentType:
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
@@ -10,20 +10,20 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/metrics"
|
||||
"github.com/ultravioletrs/cocosvm/agent"
|
||||
"github.com/ultravioletrs/cocosvm/manager"
|
||||
)
|
||||
|
||||
var _ agent.Service = (*metricsMiddleware)(nil)
|
||||
var _ manager.Service = (*metricsMiddleware)(nil)
|
||||
|
||||
type metricsMiddleware struct {
|
||||
counter metrics.Counter
|
||||
latency metrics.Histogram
|
||||
svc agent.Service
|
||||
svc manager.Service
|
||||
}
|
||||
|
||||
// MetricsMiddleware instruments core service by tracking request count and
|
||||
// latency.
|
||||
func MetricsMiddleware(svc agent.Service, counter metrics.Counter, latency metrics.Histogram) agent.Service {
|
||||
func MetricsMiddleware(svc manager.Service, counter metrics.Counter, latency metrics.Histogram) manager.Service {
|
||||
return &metricsMiddleware{
|
||||
counter: counter,
|
||||
latency: latency,
|
||||
@@ -2,6 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package things contains the domain concept definitions needed to support
|
||||
// Mainflux agent service functionality.
|
||||
// Mainflux manager service functionality.
|
||||
|
||||
package agent
|
||||
package manager
|
||||
@@ -1,10 +1,12 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package agent
|
||||
package manager
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/digitalocean/go-libvirt"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -24,22 +26,38 @@ type Service interface {
|
||||
Ping(string) (string, error)
|
||||
}
|
||||
|
||||
type agentService struct {
|
||||
secret string
|
||||
type managerService struct {
|
||||
secret string
|
||||
libvirt *libvirt.Libvirt
|
||||
}
|
||||
|
||||
var _ Service = (*agentService)(nil)
|
||||
var _ Service = (*managerService)(nil)
|
||||
|
||||
// New instantiates the agent service implementation.
|
||||
func New(secret string) Service {
|
||||
return &agentService{
|
||||
secret: secret,
|
||||
// New instantiates the manager service implementation.
|
||||
func New(secret string, libvirtConn *libvirt.Libvirt) Service {
|
||||
return &managerService{
|
||||
secret: secret,
|
||||
libvirt: libvirtConn,
|
||||
}
|
||||
}
|
||||
|
||||
func (ks *agentService) Ping(secret string) (string, error) {
|
||||
func (ks *managerService) Ping(secret string) (string, error) {
|
||||
if ks.secret != secret {
|
||||
return "", ErrUnauthorizedAccess
|
||||
}
|
||||
return "Hello World :)", nil
|
||||
}
|
||||
|
||||
func (ks *managerService) CreateDomain(XML string) (libvirt.Domain, error) {
|
||||
dom, err := ks.libvirt.DomainDefineXMLFlags(XML, 0)
|
||||
if err != nil {
|
||||
return libvirt.Domain{}, err
|
||||
}
|
||||
|
||||
err = ks.libvirt.DomainCreate(dom)
|
||||
if err != nil {
|
||||
return libvirt.Domain{}, err
|
||||
}
|
||||
|
||||
return dom, nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.idea/
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
Maintainer
|
||||
----------
|
||||
DigitalOcean, Inc
|
||||
|
||||
Original Authors
|
||||
----------------
|
||||
Ben LeMasurier <blemasurier@digitalocean.com>
|
||||
Matt Layher <mlayher@digitalocean.com>
|
||||
|
||||
Contributors
|
||||
------------
|
||||
Justin Kim <justin@digitalocean.com>
|
||||
Ricky Medina <rm@do.co>
|
||||
Charlie Drage <charlie@charliedrage.com>
|
||||
Michael Koppmann <me@mkoppmann.at>
|
||||
Simarpreet Singh <simar@linux.com>
|
||||
Alexander Polyakov <apolyakov@beget.com>
|
||||
Amanda Andrade <amanda.andrade@serpro.gov.br>
|
||||
Geoff Hickey <ghickey@digitalocean.com>
|
||||
Yuriy Taraday <yorik.sar@gmail.com>
|
||||
Sylvain Baubeau <sbaubeau@redhat.com>
|
||||
David Schneider <dsbrng25b@gmail.com>
|
||||
Alec Hothan <ahothan@gmail.com>
|
||||
Akos Varga <vrgakos@gmail.com>
|
||||
Peter Kurfer <peter.kurfer@gmail.com>
|
||||
Sam Roberts <sroberts@digitalocean.com>
|
||||
Moritz Wanzenböck <moritz.wanzenboeck@linbit.com>
|
||||
Jenni Griesmann <jgriesmann@digitalocean.com>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
The `go-libvirt` project makes use of the [GitHub Flow](https://guides.github.com/introduction/flow/)
|
||||
for contributions.
|
||||
|
||||
If you'd like to contribute to the project, please
|
||||
[open an issue](https://github.com/digitalocean/go-libvirt/issues/new) or find an
|
||||
[existing issue](https://github.com/digitalocean/go-libvirt/issues) that you'd like
|
||||
to take on. This ensures that efforts are not duplicated, and that a new feature
|
||||
aligns with the focus of the rest of the repository.
|
||||
|
||||
Once your suggestion has been submitted and discussed, please be sure that your
|
||||
code meets the following criteria:
|
||||
- code is completely `gofmt`'d
|
||||
- new features or codepaths have appropriate test coverage
|
||||
- `go test ./...` passes
|
||||
- `go vet ./...` passes
|
||||
- `golint ./...` returns no warnings, including documentation comment warnings
|
||||
|
||||
In addition, if this is your first time contributing to the `go-libvirt` project,
|
||||
add your name and email address to the
|
||||
[AUTHORS](https://github.com/digitalocean/go-libvirt/blob/master/AUTHORS) file
|
||||
under the "Contributors" section using the format:
|
||||
`First Last <email@example.com>`.
|
||||
|
||||
Finally, submit a pull request for review!
|
||||
|
||||
Feel free to join us in [`#go-libvirt` on libera chat](https://web.libera.chat/)
|
||||
if you'd like to discuss the project.
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
Apache License
|
||||
==============
|
||||
|
||||
_Version 2.0, January 2004_
|
||||
_<<http://www.apache.org/licenses/>>_
|
||||
|
||||
### Terms and Conditions for use, reproduction, and distribution
|
||||
|
||||
#### 1. Definitions
|
||||
|
||||
“License” shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
“Licensor” shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
“Legal Entity” shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, “control” means **(i)** the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or **(iii)** beneficial ownership of such entity.
|
||||
|
||||
“You” (or “Your”) shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
“Source” form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
“Object” form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
“Work” shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
“Derivative Works” shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
“Contribution” shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
“submitted” means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as “Not a Contribution.”
|
||||
|
||||
“Contributor” shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
#### 2. Grant of Copyright License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
#### 3. Grant of Patent License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
#### 4. Redistribution
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
* **(a)** You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
* **(b)** You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
* **(c)** You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
#### 5. Submission of Contributions
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
#### 6. Trademarks
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
#### 7. Disclaimer of Warranty
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
#### 8. Limitation of Liability
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
#### 9. Accepting Warranty or Additional Liability
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
_END OF TERMS AND CONDITIONS_
|
||||
|
||||
### APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets `[]` replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same “printed page” as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
+283
@@ -0,0 +1,283 @@
|
||||
libvirt
|
||||
[](http://godoc.org/github.com/digitalocean/go-libvirt)
|
||||
[](https://github.com/digitalocean/go-libvirt/actions/)
|
||||
[](https://goreportcard.com/report/github.com/digitalocean/go-libvirt)
|
||||
====
|
||||
|
||||
Package `go-libvirt` provides a pure Go interface for interacting with libvirt.
|
||||
|
||||
Rather than using libvirt's C bindings, this package makes use of
|
||||
libvirt's RPC interface, as documented [here](https://libvirt.org/kbase/internals/rpc.html).
|
||||
Connections to the libvirt server may be local, or remote. RPC packets are encoded
|
||||
using the XDR standard as defined by [RFC 4506](https://tools.ietf.org/html/rfc4506.html).
|
||||
|
||||
libvirt's RPC interface is quite extensive, and changes from one version to the
|
||||
next, so this project uses a pair of code generators to build the go bindings.
|
||||
The code generators should be run whenever you want to build go-libvirt for a
|
||||
new version of libvirt. See the next section for directions on re-generating
|
||||
go-libvirt.
|
||||
|
||||
[Pull requests are welcome](https://github.com/digitalocean/go-libvirt/blob/master/CONTRIBUTING.md)!
|
||||
|
||||
Feel free to join us in [`#go-libvirt` on libera chat](https://web.libera.chat/)
|
||||
if you'd like to discuss the project.
|
||||
|
||||
Running the Code Generators
|
||||
---------------------------
|
||||
|
||||
The code generator doesn't run automatically when you build go-libvirt. It's
|
||||
meant to be run manually any time you change the version of libvirt you're
|
||||
using. When you download go-libvirt it will come with generated files
|
||||
corresponding to a particular version of libvirt. You can use the library as-is,
|
||||
but the generated code may be missing libvirt functions, if you're using a newer
|
||||
version of libvirt, or it may have extra functions that will return
|
||||
'unimplemented' errors if you try to call them. If this is a problem, you should
|
||||
re-run the code generator. To do this, follow these steps:
|
||||
|
||||
- First, download a copy of the libvirt sources corresponding to the version you
|
||||
want to use.
|
||||
- Change directories into where you've unpacked your distribution of libvirt.
|
||||
- The second step depends on the version of libvirt you'd like to build against.
|
||||
It's not necessary to actually build libvirt, but it is necessary to run libvirt's
|
||||
"configure" step because it generates required files.
|
||||
- For libvirt < v6.7.0:
|
||||
- `$ mkdir build; cd build`
|
||||
- `$ ../autogen.sh`
|
||||
- For libvirt >= v6.7.0:
|
||||
- `$ meson setup build`
|
||||
- Finally, set the environment variable `LIBVIRT_SOURCE` to the directory you
|
||||
put libvirt into, and run `go generate ./...` from the go-libvirt directory.
|
||||
This runs both of the go-libvirt's code generators.
|
||||
|
||||
How to Use This Library
|
||||
-----------------------
|
||||
|
||||
Once you've vendored go-libvirt into your project, you'll probably want to call
|
||||
some libvirt functions. There's some example code below showing how to connect
|
||||
to libvirt and make one such call, but once you get past the introduction you'll
|
||||
next want to call some other libvirt functions. How do you find them?
|
||||
|
||||
Start with the [libvirt API reference](https://libvirt.org/html/index.html).
|
||||
Let's say you want to gracefully shutdown a VM, and after reading through the
|
||||
libvirt docs you determine that virDomainShutdown() is the function you want to
|
||||
call to do that. Where's that function in go-libvirt? We transform the names
|
||||
slightly when building the go bindings. There's no need for a global prefix like
|
||||
"vir" in Go, since all our functions are inside the package namespace, so we
|
||||
drop it. That means the Go function for `virDomainShutdown()` is just `DomainShutdown()`,
|
||||
and sure enough, you can find the Go function `DomainShutdown()` in libvirt.gen.go,
|
||||
with parameters and return values equivalent to those documented in the API
|
||||
reference.
|
||||
|
||||
Suppose you then decide you need more control over your shutdown, so you switch
|
||||
over to `virDomainShutdownFlags()`. As its name suggests, this function takes a
|
||||
flag parameter which has possible values specified in an enum called
|
||||
`virDomainShutdownFlagValues`. Flag types like this are a little tricky for the
|
||||
code generator, because the C functions just take an integer type - only the
|
||||
libvirt documentation actually ties the flags to the enum types. In most cases
|
||||
though we're able to generate a wrapper function with a distinct flag type,
|
||||
making it easier for Go tooling to suggest possible flag values while you're
|
||||
working. Checking the documentation for this function:
|
||||
|
||||
`godoc github.com/digitalocean/go-libvirt DomainShutdownFlags`
|
||||
|
||||
returns this:
|
||||
|
||||
`func (l *Libvirt) DomainShutdownFlags(Dom Domain, Flags DomainShutdownFlagValues) (err error)`
|
||||
|
||||
If you want to see the possible flag values, `godoc` can help again:
|
||||
|
||||
```
|
||||
$ godoc github.com/digitalocean/go-libvirt DomainShutdownFlagValues
|
||||
|
||||
type DomainShutdownFlagValues int32
|
||||
DomainShutdownFlagValues as declared in libvirt/libvirt-domain.h:1121
|
||||
|
||||
const (
|
||||
DomainShutdownDefault DomainShutdownFlagValues = iota
|
||||
DomainShutdownAcpiPowerBtn DomainShutdownFlagValues = 1
|
||||
DomainShutdownGuestAgent DomainShutdownFlagValues = 2
|
||||
DomainShutdownInitctl DomainShutdownFlagValues = 4
|
||||
DomainShutdownSignal DomainShutdownFlagValues = 8
|
||||
DomainShutdownParavirt DomainShutdownFlagValues = 16
|
||||
)
|
||||
DomainShutdownFlagValues enumeration from libvirt/libvirt-domain.h:1121
|
||||
```
|
||||
|
||||
One other suggestion: most of the code in go-libvirt is now generated, but a few
|
||||
hand-written routines still exist in libvirt.go, and wrap calls to the generated
|
||||
code with slightly different parameters or return values. We suggest avoiding
|
||||
these hand-written routines and calling the generated routines in libvirt.gen.go
|
||||
instead. Over time these handwritten routines will be removed from go-libvirt.
|
||||
|
||||
Warning
|
||||
-------
|
||||
|
||||
While these package are reasonably well-tested and have seen some use inside of
|
||||
DigitalOcean, there may be subtle bugs which could cause the packages to act
|
||||
in unexpected ways. Use at your own risk!
|
||||
|
||||
In addition, the API is not considered stable at this time. If you would like
|
||||
to include package `libvirt` in a project, we highly recommend vendoring it into
|
||||
your project.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/digitalocean/go-libvirt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// This dials libvirt on the local machine, but you can substitute the first
|
||||
// two parameters with "tcp", "<ip address>:<port>" to connect to libvirt on
|
||||
// a remote machine.
|
||||
c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", 2*time.Second)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to dial libvirt: %v", err)
|
||||
}
|
||||
|
||||
l := libvirt.New(c)
|
||||
if err := l.Connect(); err != nil {
|
||||
log.Fatalf("failed to connect: %v", err)
|
||||
}
|
||||
|
||||
v, err := l.Version()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to retrieve libvirt version: %v", err)
|
||||
}
|
||||
fmt.Println("Version:", v)
|
||||
|
||||
domains, err := l.Domains()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to retrieve domains: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("ID\tName\t\tUUID")
|
||||
fmt.Printf("--------------------------------------------------------\n")
|
||||
for _, d := range domains {
|
||||
fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
||||
}
|
||||
|
||||
if err := l.Disconnect(); err != nil {
|
||||
log.Fatalf("failed to disconnect: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
Version: 1.3.4
|
||||
ID Name UUID
|
||||
--------------------------------------------------------
|
||||
1 Test-1 dc329f87d4de47198cfd2e21c6105b01
|
||||
2 Test-2 dc229f87d4de47198cfd2e21c6105b01
|
||||
```
|
||||
|
||||
Example (Connect to libvirt via TLS over TCP)
|
||||
-------
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/digitalocean/go-libvirt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// This dials libvirt on the local machine
|
||||
// It connects to libvirt via TLS over TCP
|
||||
// To connect to a remote machine, you need to have the ca/cert/key of it.
|
||||
keyFileXML, err := ioutil.ReadFile("/etc/pki/libvirt/private/clientkey.pem")
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
certFileXML, err := ioutil.ReadFile("/etc/pki/libvirt/clientcert.pem")
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
caFileXML, err := ioutil.ReadFile("/etc/pki/CA/cacert.pem")
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
}
|
||||
cert, err := tls.X509KeyPair([]byte(certFileXML), []byte(keyFileXML))
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
roots := x509.NewCertPool()
|
||||
roots.AppendCertsFromPEM([]byte(caFileXML))
|
||||
|
||||
config := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: roots,
|
||||
}
|
||||
|
||||
// Use host name or IP which is valid in certificate
|
||||
addr := "10.10.10.10"
|
||||
port := "16514"
|
||||
c, err := tls.Dial("tcp", addr + ":" + port, config)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to dial libvirt: %v", err)
|
||||
}
|
||||
|
||||
// Drop a byte before libvirt.New(c)
|
||||
// More details at https://github.com/digitalocean/go-libvirt/issues/89
|
||||
// Remove this line if the issue does not exist any more
|
||||
c.Read(make([]byte, 1))
|
||||
|
||||
l := libvirt.New(c)
|
||||
if err := l.Connect(); err != nil {
|
||||
log.Fatalf("failed to connect: %v", err)
|
||||
}
|
||||
|
||||
v, err := l.Version()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to retrieve libvirt version: %v", err)
|
||||
}
|
||||
fmt.Println("Version:", v)
|
||||
|
||||
// Return both running and stopped VMs
|
||||
flags := libvirt.ConnectListDomainsActive | libvirt.ConnectListDomainsInactive
|
||||
domains, _, err := l.ConnectListAllDomains(1, flags)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to retrieve domains: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("ID\tName\t\tUUID")
|
||||
fmt.Println("--------------------------------------------------------")
|
||||
for _, d := range domains {
|
||||
fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
||||
}
|
||||
|
||||
if err := l.Disconnect(); err != nil {
|
||||
log.Fatalf("failed to disconnect: %v", err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Running the Integration Tests
|
||||
-----------------------------
|
||||
|
||||
GitHub actions workflows are defined in [.github/workflows](.github/workflows)
|
||||
and can be triggered manually in the GitHub UI after pushing a branch. There
|
||||
are not currently convenient scripts for setting up and running integration tests
|
||||
locally, but installing libvirt and defining only the artifacts described by the
|
||||
files in testdata should be sufficient to be able to run the integration test file
|
||||
against.
|
||||
+2500
File diff suppressed because it is too large
Load Diff
+70
@@ -0,0 +1,70 @@
|
||||
// Copyright 2016 The go-libvirt Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package libvirt is a pure Go interface to libvirt.
|
||||
//
|
||||
// Rather than using Libvirt's C bindings, this package makes use of Libvirt's
|
||||
// RPC interface, as documented here: https://libvirt.org/internals/rpc.html.
|
||||
// Connections to the libvirt server may be local, or remote. RPC packets are
|
||||
// encoded using the XDR standard as defined by RFC 4506.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import (
|
||||
// "fmt"
|
||||
// "log"
|
||||
// "net"
|
||||
// "time"
|
||||
//
|
||||
// "github.com/digitalocean/go-libvirt"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// // This dials libvirt on the local machine, but you can substitute the first
|
||||
// // two parameters with "tcp", "<ip address>:<port>" to connect to libvirt on
|
||||
// // a remote machine.
|
||||
// c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", 2*time.Second)
|
||||
// if err != nil {
|
||||
// log.Fatalf("failed to dial libvirt: %v", err)
|
||||
// }
|
||||
//
|
||||
// l := libvirt.New(c)
|
||||
// if err := l.Connect(); err != nil {
|
||||
// log.Fatalf("failed to connect: %v", err)
|
||||
// }
|
||||
//
|
||||
// v, err := l.Version()
|
||||
// if err != nil {
|
||||
// log.Fatalf("failed to retrieve libvirt version: %v", err)
|
||||
// }
|
||||
// fmt.Println("Version:", v)
|
||||
//
|
||||
// domains, err := l.Domains()
|
||||
// if err != nil {
|
||||
// log.Fatalf("failed to retrieve domains: %v", err)
|
||||
// }
|
||||
//
|
||||
// fmt.Println("ID\tName\t\tUUID")
|
||||
// fmt.Printf("--------------------------------------------------------\n")
|
||||
// for _, d := range domains {
|
||||
// fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
||||
// }
|
||||
//
|
||||
// if err := l.Disconnect(); err != nil {
|
||||
// log.Fatalf("failed to disconnect: %v", err)
|
||||
// }
|
||||
// }
|
||||
package libvirt
|
||||
Generated
Vendored
+47
@@ -0,0 +1,47 @@
|
||||
// Copyright 2018 The go-libvirt Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//
|
||||
// Code generated by internal/lvgen/generate.go. DO NOT EDIT.
|
||||
//
|
||||
// To regenerate, run 'go generate' in internal/lvgen.
|
||||
//
|
||||
|
||||
package constants
|
||||
|
||||
// These are libvirt procedure numbers which correspond to each respective
|
||||
// API call between remote_internal driver and libvirtd. Each procedure is
|
||||
// identified by a unique number.
|
||||
const (
|
||||
// From enums:
|
||||
// QEMUProcDomainMonitorCommand is libvirt's QEMU_PROC_DOMAIN_MONITOR_COMMAND
|
||||
QEMUProcDomainMonitorCommand = 1
|
||||
// QEMUProcDomainAttach is libvirt's QEMU_PROC_DOMAIN_ATTACH
|
||||
QEMUProcDomainAttach = 2
|
||||
// QEMUProcDomainAgentCommand is libvirt's QEMU_PROC_DOMAIN_AGENT_COMMAND
|
||||
QEMUProcDomainAgentCommand = 3
|
||||
// QEMUProcConnectDomainMonitorEventRegister is libvirt's QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_REGISTER
|
||||
QEMUProcConnectDomainMonitorEventRegister = 4
|
||||
// QEMUProcConnectDomainMonitorEventDeregister is libvirt's QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER
|
||||
QEMUProcConnectDomainMonitorEventDeregister = 5
|
||||
// QEMUProcDomainMonitorEvent is libvirt's QEMU_PROC_DOMAIN_MONITOR_EVENT
|
||||
QEMUProcDomainMonitorEvent = 6
|
||||
|
||||
|
||||
// From consts:
|
||||
// QEMUProgram is libvirt's QEMU_PROGRAM
|
||||
QEMUProgram = 0x20008087
|
||||
// QEMUProtocolVersion is libvirt's QEMU_PROTOCOL_VERSION
|
||||
QEMUProtocolVersion = 1
|
||||
)
|
||||
Generated
Vendored
+1023
File diff suppressed because it is too large
Load Diff
+20
@@ -0,0 +1,20 @@
|
||||
// Copyright 2020 The go-libvirt Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package event
|
||||
|
||||
// Event represents an internal Event.
|
||||
type Event interface {
|
||||
GetCallbackID() int32
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
// Copyright 2020 The go-libvirt Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package event
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// emptyEvent is used as a zero-value. Clients will never receive one of these;
|
||||
// they are only here to satisfy the compiler. See the comments in process() for
|
||||
// more information.
|
||||
type emptyEvent struct{}
|
||||
|
||||
func (emptyEvent) GetCallbackID() int32 { return 0 }
|
||||
|
||||
// Stream is an unbounded buffered event channel. The implementation
|
||||
// consists of a pair of unbuffered channels and a goroutine to manage them.
|
||||
// Client behavior will not cause incoming events to block.
|
||||
type Stream struct {
|
||||
// Program specifies the source of the events - libvirt or QEMU.
|
||||
Program uint32
|
||||
|
||||
// CallbackID is returned by the event registration call.
|
||||
CallbackID int32
|
||||
|
||||
// manage unbounded channel behavior.
|
||||
queue []Event
|
||||
qlen chan (chan int)
|
||||
in, out chan Event
|
||||
|
||||
// terminates processing
|
||||
shutdown context.CancelFunc
|
||||
}
|
||||
|
||||
// NewStream configures a new Event Stream. Incoming events are appended to a
|
||||
// queue, which is then relayed to the listening client. Client behavior will
|
||||
// not cause incoming events to block. It is the responsibility of the caller
|
||||
// to terminate the Stream via Shutdown() when no longer in use.
|
||||
func NewStream(program uint32, cbID int32) *Stream {
|
||||
s := &Stream{
|
||||
Program: program,
|
||||
CallbackID: cbID,
|
||||
in: make(chan Event),
|
||||
out: make(chan Event),
|
||||
qlen: make(chan (chan int)),
|
||||
}
|
||||
|
||||
// Start the processing loop, which will return a routine we can use to
|
||||
// shut the queue down later.
|
||||
s.shutdown = s.start()
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Len will return the current count of events in the internal queue for a
|
||||
// stream. It does this by sending a message to the stream's process() loop,
|
||||
// which will then write the current length to the channel contained in that
|
||||
// message.
|
||||
func (s *Stream) Len() int {
|
||||
// Send a request to the process() loop to get the current length of the
|
||||
// queue
|
||||
ch := make(chan int)
|
||||
s.qlen <- ch
|
||||
return <-ch
|
||||
}
|
||||
|
||||
// Recv returns the next available event from the Stream's queue.
|
||||
func (s *Stream) Recv() chan Event {
|
||||
return s.out
|
||||
}
|
||||
|
||||
// Push appends a new event to the queue.
|
||||
func (s *Stream) Push(e Event) {
|
||||
s.in <- e
|
||||
}
|
||||
|
||||
// Shutdown gracefully terminates Stream processing, releasing all internal
|
||||
// resources. Events which have not yet been received by the client will be
|
||||
// dropped. Subsequent calls to Shutdown() are idempotent.
|
||||
func (s *Stream) Shutdown() {
|
||||
if s.shutdown != nil {
|
||||
s.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
// start starts the event processing loop, which will continue to run until
|
||||
// terminated by the returned context.CancelFunc.
|
||||
func (s *Stream) start() context.CancelFunc {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
go s.process(ctx)
|
||||
|
||||
return cancel
|
||||
}
|
||||
|
||||
// process manages an Stream's lifecycle until canceled by the provided context.
|
||||
// Incoming events are appended to a queue which is then relayed to the
|
||||
// listening client. New events pushed onto the queue will not block if the
|
||||
// client is not actively polling for them; the stream will buffer them
|
||||
// internally.
|
||||
func (s *Stream) process(ctx context.Context) {
|
||||
// Close the output channel so that clients know this stream is finished.
|
||||
// We don't close s.in to avoid creating a race with the stream's Push()
|
||||
// function.
|
||||
defer close(s.out)
|
||||
|
||||
// This function is used to retrieve the next event from the queue, to be
|
||||
// sent to the client. If there are no more events to send, it returns a nil
|
||||
// channel and a zero-value event.
|
||||
nextEvent := func() (chan Event, Event) {
|
||||
sendCh := chan Event(nil)
|
||||
next := Event(emptyEvent{})
|
||||
if len(s.queue) > 0 {
|
||||
sendCh = s.out
|
||||
next = s.queue[0]
|
||||
}
|
||||
return sendCh, next
|
||||
}
|
||||
|
||||
// The select statement in this loop relies on the fact that a send to a nil
|
||||
// channel will block forever. If we have no entries in the queue, the
|
||||
// sendCh variable will be nil, so the clause that attempts to send an event
|
||||
// to the client will never complete. Clients will never receive an
|
||||
// emptyEvent.
|
||||
for {
|
||||
sendCh, nextEvt := nextEvent()
|
||||
|
||||
select {
|
||||
// new event received, append to queue
|
||||
case e := <-s.in:
|
||||
s.queue = append(s.queue, e)
|
||||
|
||||
case lenCh := <-s.qlen:
|
||||
lenCh <- len(s.queue)
|
||||
|
||||
// client received an event, pop from queue
|
||||
case sendCh <- nextEvt:
|
||||
s.queue = s.queue[1:]
|
||||
|
||||
// shutdown requested
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+896
@@ -0,0 +1,896 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package xdr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
errMaxSlice = "data exceeds max slice limit"
|
||||
errIODecode = "%s while decoding %d bytes"
|
||||
)
|
||||
|
||||
/*
|
||||
Unmarshal parses XDR-encoded data into the value pointed to by v reading from
|
||||
reader r and returning the total number of bytes read. An addressable pointer
|
||||
must be provided since Unmarshal needs to both store the result of the decode as
|
||||
well as obtain target type information. Unmarhsal traverses v recursively and
|
||||
automatically indirects pointers through arbitrary depth, allocating them as
|
||||
necessary, to decode the data into the underlying value pointed to.
|
||||
|
||||
Unmarshal uses reflection to determine the type of the concrete value contained
|
||||
by v and performs a mapping of underlying XDR types to Go types as follows:
|
||||
|
||||
Go Type <- XDR Type
|
||||
--------------------
|
||||
int8, int16, int32, int <- XDR Integer
|
||||
uint8, uint16, uint32, uint <- XDR Unsigned Integer
|
||||
int64 <- XDR Hyper Integer
|
||||
uint64 <- XDR Unsigned Hyper Integer
|
||||
bool <- XDR Boolean
|
||||
float32 <- XDR Floating-Point
|
||||
float64 <- XDR Double-Precision Floating-Point
|
||||
string <- XDR String
|
||||
byte <- XDR Integer
|
||||
[]byte <- XDR Variable-Length Opaque Data
|
||||
[#]byte <- XDR Fixed-Length Opaque Data
|
||||
[]<type> <- XDR Variable-Length Array
|
||||
[#]<type> <- XDR Fixed-Length Array
|
||||
struct <- XDR Structure
|
||||
map <- XDR Variable-Length Array of two-element XDR Structures
|
||||
time.Time <- XDR String encoded with RFC3339 nanosecond precision
|
||||
|
||||
Notes and Limitations:
|
||||
|
||||
* Automatic unmarshalling of variable and fixed-length arrays of uint8s
|
||||
requires a special struct tag `xdropaque:"false"` since byte slices
|
||||
and byte arrays are assumed to be opaque data and byte is a Go alias
|
||||
for uint8 thus indistinguishable under reflection
|
||||
* Cyclic data structures are not supported and will result in infinite
|
||||
loops
|
||||
|
||||
If any issues are encountered during the unmarshalling process, an
|
||||
UnmarshalError is returned with a human readable description as well as
|
||||
an ErrorCode value for further inspection from sophisticated callers. Some
|
||||
potential issues are unsupported Go types, attempting to decode a value which is
|
||||
too large to fit into a specified Go type, and exceeding max slice limitations.
|
||||
*/
|
||||
func Unmarshal(r io.Reader, v interface{}) (int, error) {
|
||||
d := Decoder{r: r}
|
||||
return d.Decode(v)
|
||||
}
|
||||
|
||||
// UnmarshalLimited is identical to Unmarshal but it sets maxReadSize in order
|
||||
// to cap reads.
|
||||
func UnmarshalLimited(r io.Reader, v interface{}, maxSize uint) (int, error) {
|
||||
d := Decoder{r: r, maxReadSize: maxSize}
|
||||
return d.Decode(v)
|
||||
}
|
||||
|
||||
// TypeDecoder lets a caller provide a custom decode routine for a custom type.
|
||||
type TypeDecoder interface {
|
||||
Decode(*Decoder, reflect.Value) (int, error)
|
||||
}
|
||||
|
||||
// A Decoder wraps an io.Reader that is expected to provide an XDR-encoded byte
|
||||
// stream and provides several exposed methods to manually decode various XDR
|
||||
// primitives without relying on reflection. The NewDecoder function can be
|
||||
// used to get a new Decoder directly.
|
||||
//
|
||||
// Typically, Unmarshal should be used instead of manual decoding. A Decoder
|
||||
// is exposed so it is possible to perform manual decoding should it be
|
||||
// necessary in complex scenarios where automatic reflection-based decoding
|
||||
// won't work.
|
||||
type Decoder struct {
|
||||
r io.Reader
|
||||
|
||||
// maxReadSize is the default maximum bytes an element can contain. 0
|
||||
// is unlimited and provides backwards compatability. Setting it to a
|
||||
// non-zero value caps reads.
|
||||
maxReadSize uint
|
||||
|
||||
// customTypes is a map allowing the caller to provide decoder routines for
|
||||
// custom types known only to itself.
|
||||
customTypes map[string]TypeDecoder
|
||||
}
|
||||
|
||||
// DecodeInt treats the next 4 bytes as an XDR encoded integer and returns the
|
||||
// result as an int32 along with the number of bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.1 - Integer
|
||||
// 32-bit big-endian signed integer in range [-2147483648, 2147483647]
|
||||
func (d *Decoder) DecodeInt() (int32, int, error) {
|
||||
var buf [4]byte
|
||||
n, err := io.ReadFull(d.r, buf[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIODecode, err.Error(), 4)
|
||||
err := unmarshalError("DecodeInt", ErrIO, msg, buf[:n], err)
|
||||
return 0, n, err
|
||||
}
|
||||
|
||||
rv := int32(buf[3]) | int32(buf[2])<<8 |
|
||||
int32(buf[1])<<16 | int32(buf[0])<<24
|
||||
return rv, n, nil
|
||||
}
|
||||
|
||||
// DecodeUint treats the next 4 bytes as an XDR encoded unsigned integer and
|
||||
// returns the result as a uint32 along with the number of bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.2 - Unsigned Integer
|
||||
// 32-bit big-endian unsigned integer in range [0, 4294967295]
|
||||
func (d *Decoder) DecodeUint() (uint32, int, error) {
|
||||
var buf [4]byte
|
||||
n, err := io.ReadFull(d.r, buf[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIODecode, err.Error(), 4)
|
||||
err := unmarshalError("DecodeUint", ErrIO, msg, buf[:n], err)
|
||||
return 0, n, err
|
||||
}
|
||||
|
||||
rv := uint32(buf[3]) | uint32(buf[2])<<8 |
|
||||
uint32(buf[1])<<16 | uint32(buf[0])<<24
|
||||
return rv, n, nil
|
||||
}
|
||||
|
||||
// DecodeEnum treats the next 4 bytes as an XDR encoded enumeration value and
|
||||
// returns the result as an int32 after verifying that the value is in the
|
||||
// provided map of valid values. It also returns the number of bytes actually
|
||||
// read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining or
|
||||
// the parsed enumeration value is not one of the provided valid values.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.3 - Enumeration
|
||||
// Represented as an XDR encoded signed integer
|
||||
func (d *Decoder) DecodeEnum(validEnums map[int32]bool) (int32, int, error) {
|
||||
val, n, err := d.DecodeInt()
|
||||
if err != nil {
|
||||
return 0, n, err
|
||||
}
|
||||
|
||||
if !validEnums[val] {
|
||||
err := unmarshalError("DecodeEnum", ErrBadEnumValue,
|
||||
"invalid enum", val, nil)
|
||||
return 0, n, err
|
||||
}
|
||||
return val, n, nil
|
||||
}
|
||||
|
||||
// DecodeBool treats the next 4 bytes as an XDR encoded boolean value and
|
||||
// returns the result as a bool along with the number of bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining or
|
||||
// the parsed value is not a 0 or 1.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.4 - Boolean
|
||||
// Represented as an XDR encoded enumeration where 0 is false and 1 is true
|
||||
func (d *Decoder) DecodeBool() (bool, int, error) {
|
||||
val, n, err := d.DecodeInt()
|
||||
if err != nil {
|
||||
return false, n, err
|
||||
}
|
||||
switch val {
|
||||
case 0:
|
||||
return false, n, nil
|
||||
case 1:
|
||||
return true, n, nil
|
||||
}
|
||||
|
||||
err = unmarshalError("DecodeBool", ErrBadEnumValue, "bool not 0 or 1",
|
||||
val, nil)
|
||||
return false, n, err
|
||||
}
|
||||
|
||||
// DecodeHyper treats the next 8 bytes as an XDR encoded hyper value and
|
||||
// returns the result as an int64 along with the number of bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.5 - Hyper Integer
|
||||
// 64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
|
||||
func (d *Decoder) DecodeHyper() (int64, int, error) {
|
||||
var buf [8]byte
|
||||
n, err := io.ReadFull(d.r, buf[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIODecode, err.Error(), 8)
|
||||
err := unmarshalError("DecodeHyper", ErrIO, msg, buf[:n], err)
|
||||
return 0, n, err
|
||||
}
|
||||
|
||||
rv := int64(buf[7]) | int64(buf[6])<<8 |
|
||||
int64(buf[5])<<16 | int64(buf[4])<<24 |
|
||||
int64(buf[3])<<32 | int64(buf[2])<<40 |
|
||||
int64(buf[1])<<48 | int64(buf[0])<<56
|
||||
return rv, n, err
|
||||
}
|
||||
|
||||
// DecodeUhyper treats the next 8 bytes as an XDR encoded unsigned hyper value
|
||||
// and returns the result as a uint64 along with the number of bytes actually
|
||||
// read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.5 - Unsigned Hyper Integer
|
||||
// 64-bit big-endian unsigned integer in range [0, 18446744073709551615]
|
||||
func (d *Decoder) DecodeUhyper() (uint64, int, error) {
|
||||
var buf [8]byte
|
||||
n, err := io.ReadFull(d.r, buf[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIODecode, err.Error(), 8)
|
||||
err := unmarshalError("DecodeUhyper", ErrIO, msg, buf[:n], err)
|
||||
return 0, n, err
|
||||
}
|
||||
|
||||
rv := uint64(buf[7]) | uint64(buf[6])<<8 |
|
||||
uint64(buf[5])<<16 | uint64(buf[4])<<24 |
|
||||
uint64(buf[3])<<32 | uint64(buf[2])<<40 |
|
||||
uint64(buf[1])<<48 | uint64(buf[0])<<56
|
||||
return rv, n, nil
|
||||
}
|
||||
|
||||
// DecodeFloat treats the next 4 bytes as an XDR encoded floating point and
|
||||
// returns the result as a float32 along with the number of bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.6 - Floating Point
|
||||
// 32-bit single-precision IEEE 754 floating point
|
||||
func (d *Decoder) DecodeFloat() (float32, int, error) {
|
||||
var buf [4]byte
|
||||
n, err := io.ReadFull(d.r, buf[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIODecode, err.Error(), 4)
|
||||
err := unmarshalError("DecodeFloat", ErrIO, msg, buf[:n], err)
|
||||
return 0, n, err
|
||||
}
|
||||
|
||||
val := uint32(buf[3]) | uint32(buf[2])<<8 |
|
||||
uint32(buf[1])<<16 | uint32(buf[0])<<24
|
||||
return math.Float32frombits(val), n, nil
|
||||
}
|
||||
|
||||
// DecodeDouble treats the next 8 bytes as an XDR encoded double-precision
|
||||
// floating point and returns the result as a float64 along with the number of
|
||||
// bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.7 - Double-Precision Floating Point
|
||||
// 64-bit double-precision IEEE 754 floating point
|
||||
func (d *Decoder) DecodeDouble() (float64, int, error) {
|
||||
var buf [8]byte
|
||||
n, err := io.ReadFull(d.r, buf[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIODecode, err.Error(), 8)
|
||||
err := unmarshalError("DecodeDouble", ErrIO, msg, buf[:n], err)
|
||||
return 0, n, err
|
||||
}
|
||||
|
||||
val := uint64(buf[7]) | uint64(buf[6])<<8 |
|
||||
uint64(buf[5])<<16 | uint64(buf[4])<<24 |
|
||||
uint64(buf[3])<<32 | uint64(buf[2])<<40 |
|
||||
uint64(buf[1])<<48 | uint64(buf[0])<<56
|
||||
return math.Float64frombits(val), n, nil
|
||||
}
|
||||
|
||||
// RFC Section 4.8 - Quadruple-Precision Floating Point
|
||||
// 128-bit quadruple-precision floating point
|
||||
// Not Implemented
|
||||
|
||||
// DecodeFixedOpaque treats the next 'size' bytes as XDR encoded opaque data and
|
||||
// returns the result as a byte slice along with the number of bytes actually
|
||||
// read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining to
|
||||
// satisfy the passed size, including the necessary padding to make it a
|
||||
// multiple of 4.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.9 - Fixed-Length Opaque Data
|
||||
// Fixed-length uninterpreted data zero-padded to a multiple of four
|
||||
func (d *Decoder) DecodeFixedOpaque(size int32) ([]byte, int, error) {
|
||||
// Nothing to do if size is 0.
|
||||
if size == 0 {
|
||||
return nil, 0, nil
|
||||
}
|
||||
|
||||
pad := (4 - (size % 4)) % 4
|
||||
paddedSize := size + pad
|
||||
if uint(paddedSize) > uint(math.MaxInt32) {
|
||||
err := unmarshalError("DecodeFixedOpaque", ErrOverflow,
|
||||
errMaxSlice, paddedSize, nil)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
buf := make([]byte, paddedSize)
|
||||
n, err := io.ReadFull(d.r, buf)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIODecode, err.Error(), paddedSize)
|
||||
err := unmarshalError("DecodeFixedOpaque", ErrIO, msg, buf[:n],
|
||||
err)
|
||||
return nil, n, err
|
||||
}
|
||||
return buf[0:size], n, nil
|
||||
}
|
||||
|
||||
// DecodeOpaque treats the next bytes as variable length XDR encoded opaque
|
||||
// data and returns the result as a byte slice along with the number of bytes
|
||||
// actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining or
|
||||
// the opaque data is larger than the max length of a Go slice.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.10 - Variable-Length Opaque Data
|
||||
// Unsigned integer length followed by fixed opaque data of that length
|
||||
func (d *Decoder) DecodeOpaque() ([]byte, int, error) {
|
||||
dataLen, n, err := d.DecodeUint()
|
||||
if err != nil {
|
||||
return nil, n, err
|
||||
}
|
||||
if uint(dataLen) > uint(math.MaxInt32) ||
|
||||
(d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
|
||||
err := unmarshalError("DecodeOpaque", ErrOverflow, errMaxSlice,
|
||||
dataLen, nil)
|
||||
return nil, n, err
|
||||
}
|
||||
|
||||
rv, n2, err := d.DecodeFixedOpaque(int32(dataLen))
|
||||
n += n2
|
||||
if err != nil {
|
||||
return nil, n, err
|
||||
}
|
||||
return rv, n, nil
|
||||
}
|
||||
|
||||
// DecodeString treats the next bytes as a variable length XDR encoded string
|
||||
// and returns the result as a string along with the number of bytes actually
|
||||
// read. Character encoding is assumed to be UTF-8 and therefore ASCII
|
||||
// compatible. If the underlying character encoding is not compatibile with
|
||||
// this assumption, the data can instead be read as variable-length opaque data
|
||||
// (DecodeOpaque) and manually converted as needed.
|
||||
//
|
||||
// An UnmarshalError is returned if there are insufficient bytes remaining or
|
||||
// the string data is larger than the max length of a Go slice.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.11 - String
|
||||
// Unsigned integer length followed by bytes zero-padded to a multiple of
|
||||
// four
|
||||
func (d *Decoder) DecodeString() (string, int, error) {
|
||||
dataLen, n, err := d.DecodeUint()
|
||||
if err != nil {
|
||||
return "", n, err
|
||||
}
|
||||
if uint(dataLen) > uint(math.MaxInt32) ||
|
||||
(d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
|
||||
err = unmarshalError("DecodeString", ErrOverflow, errMaxSlice,
|
||||
dataLen, nil)
|
||||
return "", n, err
|
||||
}
|
||||
|
||||
opaque, n2, err := d.DecodeFixedOpaque(int32(dataLen))
|
||||
n += n2
|
||||
if err != nil {
|
||||
return "", n, err
|
||||
}
|
||||
return string(opaque), n, nil
|
||||
}
|
||||
|
||||
// decodeFixedArray treats the next bytes as a series of XDR encoded elements
|
||||
// of the same type as the array represented by the reflection value and decodes
|
||||
// each element into the passed array. The ignoreOpaque flag controls whether
|
||||
// or not uint8 (byte) elements should be decoded individually or as a fixed
|
||||
// sequence of opaque data. It returns the the number of bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if any issues are encountered while decoding
|
||||
// the array elements.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.12 - Fixed-Length Array
|
||||
// Individually XDR encoded array elements
|
||||
func (d *Decoder) decodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
|
||||
// Treat [#]byte (byte is alias for uint8) as opaque data unless
|
||||
// ignored.
|
||||
if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
|
||||
data, n, err := d.DecodeFixedOpaque(int32(v.Len()))
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
reflect.Copy(v, reflect.ValueOf(data))
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Decode each array element.
|
||||
var n int
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
n2, err := d.decode(v.Index(i))
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// decodeArray treats the next bytes as a variable length series of XDR encoded
|
||||
// elements of the same type as the array represented by the reflection value.
|
||||
// The number of elements is obtained by first decoding the unsigned integer
|
||||
// element count. Then each element is decoded into the passed array. The
|
||||
// ignoreOpaque flag controls whether or not uint8 (byte) elements should be
|
||||
// decoded individually or as a variable sequence of opaque data. It returns
|
||||
// the number of bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if any issues are encountered while decoding
|
||||
// the array elements.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.13 - Variable-Length Array
|
||||
// Unsigned integer length followed by individually XDR encoded array
|
||||
// elements
|
||||
func (d *Decoder) decodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
|
||||
dataLen, n, err := d.DecodeUint()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if uint(dataLen) > uint(math.MaxInt32) ||
|
||||
(d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
|
||||
err := unmarshalError("decodeArray", ErrOverflow, errMaxSlice,
|
||||
dataLen, nil)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Allocate storage for the slice elements (the underlying array) if
|
||||
// existing slice does not have enough capacity.
|
||||
sliceLen := int(dataLen)
|
||||
if v.Cap() < sliceLen {
|
||||
v.Set(reflect.MakeSlice(v.Type(), sliceLen, sliceLen))
|
||||
}
|
||||
if v.Len() < sliceLen {
|
||||
v.SetLen(sliceLen)
|
||||
}
|
||||
|
||||
// Treat []byte (byte is alias for uint8) as opaque data unless ignored.
|
||||
if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
|
||||
data, n2, err := d.DecodeFixedOpaque(int32(sliceLen))
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
v.SetBytes(data)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Decode each slice element.
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
n2, err := d.decode(v.Index(i))
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// decodeStruct treats the next bytes as a series of XDR encoded elements
|
||||
// of the same type as the exported fields of the struct represented by the
|
||||
// passed reflection value. Pointers are automatically indirected and
|
||||
// allocated as necessary. It returns the the number of bytes actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if any issues are encountered while decoding
|
||||
// the elements.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.14 - Structure
|
||||
// XDR encoded elements in the order of their declaration in the struct
|
||||
func (d *Decoder) decodeStruct(v reflect.Value) (int, error) {
|
||||
var n int
|
||||
vt := v.Type()
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
// Skip unexported fields.
|
||||
vtf := vt.Field(i)
|
||||
if vtf.PkgPath != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Indirect through pointers allocating them as needed and
|
||||
// ensure the field is settable.
|
||||
vf := v.Field(i)
|
||||
vf, err := d.indirect(vf)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if !vf.CanSet() {
|
||||
msg := fmt.Sprintf("can't decode to unsettable '%v'",
|
||||
vf.Type().String())
|
||||
err := unmarshalError("decodeStruct", ErrNotSettable,
|
||||
msg, nil, nil)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Handle non-opaque data to []uint8 and [#]uint8 based on
|
||||
// struct tag.
|
||||
tag := vtf.Tag.Get("xdropaque")
|
||||
if tag == "false" {
|
||||
switch vf.Kind() {
|
||||
case reflect.Slice:
|
||||
n2, err := d.decodeArray(vf, true)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
continue
|
||||
|
||||
case reflect.Array:
|
||||
n2, err := d.decodeFixedArray(vf, true)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Decode each struct field.
|
||||
n2, err := d.decode(vf)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// RFC Section 4.15 - Discriminated Union
|
||||
// RFC Section 4.16 - Void
|
||||
// RFC Section 4.17 - Constant
|
||||
// RFC Section 4.18 - Typedef
|
||||
// RFC Section 4.19 - Optional data
|
||||
// RFC Sections 4.15 though 4.19 only apply to the data specification language
|
||||
// which is not implemented by this package. In the case of discriminated
|
||||
// unions, struct tags are used to perform a similar function.
|
||||
|
||||
// decodeMap treats the next bytes as an XDR encoded variable array of 2-element
|
||||
// structures whose fields are of the same type as the map keys and elements
|
||||
// represented by the passed reflection value. Pointers are automatically
|
||||
// indirected and allocated as necessary. It returns the the number of bytes
|
||||
// actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if any issues are encountered while decoding
|
||||
// the elements.
|
||||
func (d *Decoder) decodeMap(v reflect.Value) (int, error) {
|
||||
dataLen, n, err := d.DecodeUint()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Allocate storage for the underlying map if needed.
|
||||
vt := v.Type()
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.MakeMap(vt))
|
||||
}
|
||||
|
||||
// Decode each key and value according to their type.
|
||||
keyType := vt.Key()
|
||||
elemType := vt.Elem()
|
||||
for i := uint32(0); i < dataLen; i++ {
|
||||
key := reflect.New(keyType).Elem()
|
||||
n2, err := d.decode(key)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
val := reflect.New(elemType).Elem()
|
||||
n2, err = d.decode(val)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
v.SetMapIndex(key, val)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// decodeInterface examines the interface represented by the passed reflection
|
||||
// value to detect whether it is an interface that can be decoded into and
|
||||
// if it is, extracts the underlying value to pass back into the decode function
|
||||
// for decoding according to its type. It returns the the number of bytes
|
||||
// actually read.
|
||||
//
|
||||
// An UnmarshalError is returned if any issues are encountered while decoding
|
||||
// the interface.
|
||||
func (d *Decoder) decodeInterface(v reflect.Value) (int, error) {
|
||||
if v.IsNil() || !v.CanInterface() {
|
||||
msg := fmt.Sprintf("can't decode to nil interface")
|
||||
err := unmarshalError("decodeInterface", ErrNilInterface, msg,
|
||||
nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Extract underlying value from the interface and indirect through
|
||||
// pointers allocating them as needed.
|
||||
ve := reflect.ValueOf(v.Interface())
|
||||
ve, err := d.indirect(ve)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if !ve.CanSet() {
|
||||
msg := fmt.Sprintf("can't decode to unsettable '%v'",
|
||||
ve.Type().String())
|
||||
err := unmarshalError("decodeInterface", ErrNotSettable, msg,
|
||||
nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
return d.decode(ve)
|
||||
}
|
||||
|
||||
// decode is the main workhorse for unmarshalling via reflection. It uses
|
||||
// the passed reflection value to choose the XDR primitives to decode from
|
||||
// the encapsulated reader. It is a recursive function,
|
||||
// so cyclic data structures are not supported and will result in an infinite
|
||||
// loop. It returns the the number of bytes actually read.
|
||||
func (d *Decoder) decode(v reflect.Value) (int, error) {
|
||||
if !v.IsValid() {
|
||||
msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
|
||||
err := unmarshalError("decode", ErrUnsupportedType, msg, nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Indirect through pointers allocating them as needed.
|
||||
ve, err := d.indirect(v)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Handle time.Time values by decoding them as an RFC3339 formatted
|
||||
// string with nanosecond precision. Check the type string rather
|
||||
// than doing a full blown conversion to interface and type assertion
|
||||
// since checking a string is much quicker.
|
||||
switch ve.Type().String() {
|
||||
case "time.Time":
|
||||
// Read the value as a string and parse it.
|
||||
timeString, n, err := d.DecodeString()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
ttv, err := time.Parse(time.RFC3339, timeString)
|
||||
if err != nil {
|
||||
err := unmarshalError("decode", ErrParseTime,
|
||||
err.Error(), timeString, err)
|
||||
return n, err
|
||||
}
|
||||
ve.Set(reflect.ValueOf(ttv))
|
||||
return n, nil
|
||||
}
|
||||
// If this type is in our custom types map, call the decode routine set up
|
||||
// for it.
|
||||
if dt, ok := d.customTypes[ve.Type().String()]; ok {
|
||||
return dt.Decode(d, v)
|
||||
}
|
||||
|
||||
// Handle native Go types.
|
||||
switch ve.Kind() {
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
|
||||
i, n, err := d.DecodeInt()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if ve.OverflowInt(int64(i)) {
|
||||
msg := fmt.Sprintf("signed integer too large to fit '%s'",
|
||||
ve.Kind().String())
|
||||
err = unmarshalError("decode", ErrOverflow, msg, i, nil)
|
||||
return n, err
|
||||
}
|
||||
ve.SetInt(int64(i))
|
||||
return n, nil
|
||||
|
||||
case reflect.Int64:
|
||||
i, n, err := d.DecodeHyper()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
ve.SetInt(i)
|
||||
return n, nil
|
||||
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
|
||||
ui, n, err := d.DecodeUint()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if ve.OverflowUint(uint64(ui)) {
|
||||
msg := fmt.Sprintf("unsigned integer too large to fit '%s'",
|
||||
ve.Kind().String())
|
||||
err = unmarshalError("decode", ErrOverflow, msg, ui, nil)
|
||||
return n, err
|
||||
}
|
||||
ve.SetUint(uint64(ui))
|
||||
return n, nil
|
||||
|
||||
case reflect.Uint64:
|
||||
ui, n, err := d.DecodeUhyper()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
ve.SetUint(ui)
|
||||
return n, nil
|
||||
|
||||
case reflect.Bool:
|
||||
b, n, err := d.DecodeBool()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
ve.SetBool(b)
|
||||
return n, nil
|
||||
|
||||
case reflect.Float32:
|
||||
f, n, err := d.DecodeFloat()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
ve.SetFloat(float64(f))
|
||||
return n, nil
|
||||
|
||||
case reflect.Float64:
|
||||
f, n, err := d.DecodeDouble()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
ve.SetFloat(f)
|
||||
return n, nil
|
||||
|
||||
case reflect.String:
|
||||
s, n, err := d.DecodeString()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
ve.SetString(s)
|
||||
return n, nil
|
||||
|
||||
case reflect.Array:
|
||||
n, err := d.decodeFixedArray(ve, false)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
|
||||
case reflect.Slice:
|
||||
n, err := d.decodeArray(ve, false)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
|
||||
case reflect.Struct:
|
||||
n, err := d.decodeStruct(ve)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
|
||||
case reflect.Map:
|
||||
n, err := d.decodeMap(ve)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
|
||||
case reflect.Interface:
|
||||
n, err := d.decodeInterface(ve)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// The only unhandled types left are unsupported. At the time of this
|
||||
// writing the only remaining unsupported types that exist are
|
||||
// reflect.Uintptr and reflect.UnsafePointer.
|
||||
msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
|
||||
err = unmarshalError("decode", ErrUnsupportedType, msg, nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// indirect dereferences pointers allocating them as needed until it reaches
|
||||
// a non-pointer. This allows transparent decoding through arbitrary levels
|
||||
// of indirection.
|
||||
func (d *Decoder) indirect(v reflect.Value) (reflect.Value, error) {
|
||||
rv := v
|
||||
for rv.Kind() == reflect.Ptr {
|
||||
// Allocate pointer if needed.
|
||||
isNil := rv.IsNil()
|
||||
if isNil && !rv.CanSet() {
|
||||
msg := fmt.Sprintf("unable to allocate pointer for '%v'",
|
||||
rv.Type().String())
|
||||
err := unmarshalError("indirect", ErrNotSettable, msg,
|
||||
nil, nil)
|
||||
return rv, err
|
||||
}
|
||||
if isNil {
|
||||
rv.Set(reflect.New(rv.Type().Elem()))
|
||||
}
|
||||
rv = rv.Elem()
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
// Decode operates identically to the Unmarshal function with the exception of
|
||||
// using the reader associated with the Decoder as the source of XDR-encoded
|
||||
// data instead of a user-supplied reader. See the Unmarhsal documentation for
|
||||
// specifics.
|
||||
func (d *Decoder) Decode(v interface{}) (int, error) {
|
||||
if v == nil {
|
||||
msg := "can't unmarshal to nil interface"
|
||||
return 0, unmarshalError("Unmarshal", ErrNilInterface, msg, nil,
|
||||
nil)
|
||||
}
|
||||
|
||||
vv := reflect.ValueOf(v)
|
||||
if vv.Kind() != reflect.Ptr {
|
||||
msg := fmt.Sprintf("can't unmarshal to non-pointer '%v' - use "+
|
||||
"& operator", vv.Type().String())
|
||||
err := unmarshalError("Unmarshal", ErrBadArguments, msg, nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
if vv.IsNil() && !vv.CanSet() {
|
||||
msg := fmt.Sprintf("can't unmarshal to unsettable '%v' - use "+
|
||||
"& operator", vv.Type().String())
|
||||
err := unmarshalError("Unmarshal", ErrNotSettable, msg, nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return d.decode(vv)
|
||||
}
|
||||
|
||||
// NewDecoder returns a Decoder that can be used to manually decode XDR data
|
||||
// from a provided reader. Typically, Unmarshal should be used instead of
|
||||
// manually creating a Decoder.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{r: r}
|
||||
}
|
||||
|
||||
// NewDecoderLimited is identical to NewDecoder but it sets maxReadSize in
|
||||
// order to cap reads.
|
||||
func NewDecoderLimited(r io.Reader, maxSize uint) *Decoder {
|
||||
return &Decoder{r: r, maxReadSize: maxSize}
|
||||
}
|
||||
|
||||
// NewDecoderCustomTypes returns a decoder with support for custom types known
|
||||
// to the caller. The second parameter is a map of the type name to the decoder
|
||||
// routine. When the decoder finds a type matching one of the entries in the map
|
||||
// it will call the custom routine for that type.
|
||||
func NewDecoderCustomTypes(r io.Reader, maxSize uint, ct map[string]TypeDecoder) *Decoder {
|
||||
return &Decoder{r: r, maxReadSize: maxSize, customTypes: ct}
|
||||
}
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package xdr implements the data representation portion of the External Data
|
||||
Representation (XDR) standard protocol as specified in RFC 4506 (obsoletes
|
||||
RFC 1832 and RFC 1014).
|
||||
|
||||
The XDR RFC defines both a data specification language and a data
|
||||
representation standard. This package implements methods to encode and decode
|
||||
XDR data per the data representation standard with the exception of 128-bit
|
||||
quadruple-precision floating points. It does not currently implement parsing of
|
||||
the data specification language. In other words, the ability to automatically
|
||||
generate Go code by parsing an XDR data specification file (typically .x
|
||||
extension) is not supported. In practice, this limitation of the package is
|
||||
fairly minor since it is largely unnecessary due to the reflection capabilities
|
||||
of Go as described below.
|
||||
|
||||
This package provides two approaches for encoding and decoding XDR data:
|
||||
|
||||
1) Marshal/Unmarshal functions which automatically map between XDR and Go types
|
||||
2) Individual Encoder/Decoder objects to manually work with XDR primitives
|
||||
|
||||
For the Marshal/Unmarshal functions, Go reflection capabilities are used to
|
||||
choose the type of the underlying XDR data based upon the Go type to encode or
|
||||
the target Go type to decode into. A description of how each type is mapped is
|
||||
provided below, however one important type worth reviewing is Go structs. In
|
||||
the case of structs, each exported field (first letter capitalized) is reflected
|
||||
and mapped in order. As a result, this means a Go struct with exported fields
|
||||
of the appropriate types listed in the expected order can be used to
|
||||
automatically encode / decode the XDR data thereby eliminating the need to write
|
||||
a lot of boilerplate code to encode/decode and error check each piece of XDR
|
||||
data as is typically required with C based XDR libraries.
|
||||
|
||||
Go Type to XDR Type Mappings
|
||||
|
||||
The following chart shows an overview of how Go types are mapped to XDR types
|
||||
for automatic marshalling and unmarshalling. The documentation for the Marshal
|
||||
and Unmarshal functions has specific details of how the mapping proceeds.
|
||||
|
||||
Go Type <-> XDR Type
|
||||
--------------------
|
||||
int8, int16, int32, int <-> XDR Integer
|
||||
uint8, uint16, uint32, uint <-> XDR Unsigned Integer
|
||||
int64 <-> XDR Hyper Integer
|
||||
uint64 <-> XDR Unsigned Hyper Integer
|
||||
bool <-> XDR Boolean
|
||||
float32 <-> XDR Floating-Point
|
||||
float64 <-> XDR Double-Precision Floating-Point
|
||||
string <-> XDR String
|
||||
byte <-> XDR Integer
|
||||
[]byte <-> XDR Variable-Length Opaque Data
|
||||
[#]byte <-> XDR Fixed-Length Opaque Data
|
||||
[]<type> <-> XDR Variable-Length Array
|
||||
[#]<type> <-> XDR Fixed-Length Array
|
||||
struct <-> XDR Structure
|
||||
map <-> XDR Variable-Length Array of two-element XDR Structures
|
||||
time.Time <-> XDR String encoded with RFC3339 nanosecond precision
|
||||
|
||||
Notes and Limitations:
|
||||
|
||||
* Automatic marshalling and unmarshalling of variable and fixed-length
|
||||
arrays of uint8s require a special struct tag `xdropaque:"false"`
|
||||
since byte slices and byte arrays are assumed to be opaque data and
|
||||
byte is a Go alias for uint8 thus indistinguishable under reflection
|
||||
* Channel, complex, and function types cannot be encoded
|
||||
* Interfaces without a concrete value cannot be encoded
|
||||
* Cyclic data structures are not supported and will result in infinite
|
||||
loops
|
||||
* Strings are marshalled and unmarshalled with UTF-8 character encoding
|
||||
which differs from the XDR specification of ASCII, however UTF-8 is
|
||||
backwards compatible with ASCII so this should rarely cause issues
|
||||
|
||||
|
||||
Encoding
|
||||
|
||||
To encode XDR data, use the Marshal function.
|
||||
func Marshal(w io.Writer, v interface{}) (int, error)
|
||||
|
||||
For example, given the following code snippet:
|
||||
|
||||
type ImageHeader struct {
|
||||
Signature [3]byte
|
||||
Version uint32
|
||||
IsGrayscale bool
|
||||
NumSections uint32
|
||||
}
|
||||
h := ImageHeader{[3]byte{0xAB, 0xCD, 0xEF}, 2, true, 10}
|
||||
|
||||
var w bytes.Buffer
|
||||
bytesWritten, err := xdr.Marshal(&w, &h)
|
||||
// Error check elided
|
||||
|
||||
The result, encodedData, will then contain the following XDR encoded byte
|
||||
sequence:
|
||||
|
||||
0xAB, 0xCD, 0xEF, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x0A
|
||||
|
||||
|
||||
In addition, while the automatic marshalling discussed above will work for the
|
||||
vast majority of cases, an Encoder object is provided that can be used to
|
||||
manually encode XDR primitives for complex scenarios where automatic
|
||||
reflection-based encoding won't work. The included examples provide a sample of
|
||||
manual usage via an Encoder.
|
||||
|
||||
|
||||
Decoding
|
||||
|
||||
To decode XDR data, use the Unmarshal function.
|
||||
func Unmarshal(r io.Reader, v interface{}) (int, error)
|
||||
|
||||
For example, given the following code snippet:
|
||||
|
||||
type ImageHeader struct {
|
||||
Signature [3]byte
|
||||
Version uint32
|
||||
IsGrayscale bool
|
||||
NumSections uint32
|
||||
}
|
||||
|
||||
// Using output from the Encoding section above.
|
||||
encodedData := []byte{
|
||||
0xAB, 0xCD, 0xEF, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x0A,
|
||||
}
|
||||
|
||||
var h ImageHeader
|
||||
bytesRead, err := xdr.Unmarshal(bytes.NewReader(encodedData), &h)
|
||||
// Error check elided
|
||||
|
||||
The struct instance, h, will then contain the following values:
|
||||
|
||||
h.Signature = [3]byte{0xAB, 0xCD, 0xEF}
|
||||
h.Version = 2
|
||||
h.IsGrayscale = true
|
||||
h.NumSections = 10
|
||||
|
||||
In addition, while the automatic unmarshalling discussed above will work for the
|
||||
vast majority of cases, a Decoder object is provided that can be used to
|
||||
manually decode XDR primitives for complex scenarios where automatic
|
||||
reflection-based decoding won't work. The included examples provide a sample of
|
||||
manual usage via a Decoder.
|
||||
|
||||
Errors
|
||||
|
||||
All errors are either of type UnmarshalError or MarshalError. Both provide
|
||||
human-readable output as well as an ErrorCode field which can be inspected by
|
||||
sophisticated callers if necessary.
|
||||
|
||||
See the documentation of UnmarshalError, MarshalError, and ErrorCode for further
|
||||
details.
|
||||
*/
|
||||
package xdr
|
||||
+669
@@ -0,0 +1,669 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package xdr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
var errIOEncode = "%s while encoding %d bytes"
|
||||
|
||||
/*
|
||||
Marshal writes the XDR encoding of v to writer w and returns the number of bytes
|
||||
written. It traverses v recursively and automatically indirects pointers
|
||||
through arbitrary depth to encode the actual value pointed to.
|
||||
|
||||
Marshal uses reflection to determine the type of the concrete value contained by
|
||||
v and performs a mapping of Go types to the underlying XDR types as follows:
|
||||
|
||||
Go Type -> XDR Type
|
||||
--------------------
|
||||
int8, int16, int32, int -> XDR Integer
|
||||
uint8, uint16, uint32, uint -> XDR Unsigned Integer
|
||||
int64 -> XDR Hyper Integer
|
||||
uint64 -> XDR Unsigned Hyper Integer
|
||||
bool -> XDR Boolean
|
||||
float32 -> XDR Floating-Point
|
||||
float64 -> XDR Double-Precision Floating-Point
|
||||
string -> XDR String
|
||||
byte -> XDR Integer
|
||||
[]byte -> XDR Variable-Length Opaque Data
|
||||
[#]byte -> XDR Fixed-Length Opaque Data
|
||||
[]<type> -> XDR Variable-Length Array
|
||||
[#]<type> -> XDR Fixed-Length Array
|
||||
struct -> XDR Structure
|
||||
map -> XDR Variable-Length Array of two-element XDR Structures
|
||||
time.Time -> XDR String encoded with RFC3339 nanosecond precision
|
||||
|
||||
Notes and Limitations:
|
||||
|
||||
* Automatic marshalling of variable and fixed-length arrays of uint8s
|
||||
requires a special struct tag `xdropaque:"false"` since byte slices and
|
||||
byte arrays are assumed to be opaque data and byte is a Go alias for uint8
|
||||
thus indistinguishable under reflection
|
||||
* Channel, complex, and function types cannot be encoded
|
||||
* Interfaces without a concrete value cannot be encoded
|
||||
* Cyclic data structures are not supported and will result in infinite loops
|
||||
* Strings are marshalled with UTF-8 character encoding which differs from
|
||||
the XDR specification of ASCII, however UTF-8 is backwards compatible with
|
||||
ASCII so this should rarely cause issues
|
||||
|
||||
If any issues are encountered during the marshalling process, a MarshalError is
|
||||
returned with a human readable description as well as an ErrorCode value for
|
||||
further inspection from sophisticated callers. Some potential issues are
|
||||
unsupported Go types, attempting to encode more opaque data than can be
|
||||
represented by a single opaque XDR entry, and exceeding max slice limitations.
|
||||
*/
|
||||
func Marshal(w io.Writer, v interface{}) (int, error) {
|
||||
enc := Encoder{w: w}
|
||||
return enc.Encode(v)
|
||||
}
|
||||
|
||||
// An Encoder wraps an io.Writer that will receive the XDR encoded byte stream.
|
||||
// See NewEncoder.
|
||||
type Encoder struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
// EncodeInt writes the XDR encoded representation of the passed 32-bit signed
|
||||
// integer to the encapsulated writer and returns the number of bytes written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.1 - Integer
|
||||
// 32-bit big-endian signed integer in range [-2147483648, 2147483647]
|
||||
func (enc *Encoder) EncodeInt(v int32) (int, error) {
|
||||
var b [4]byte
|
||||
b[0] = byte(v >> 24)
|
||||
b[1] = byte(v >> 16)
|
||||
b[2] = byte(v >> 8)
|
||||
b[3] = byte(v)
|
||||
|
||||
n, err := enc.w.Write(b[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
|
||||
err := marshalError("EncodeInt", ErrIO, msg, b[:n], err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// EncodeUint writes the XDR encoded representation of the passed 32-bit
|
||||
// unsigned integer to the encapsulated writer and returns the number of bytes
|
||||
// written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.2 - Unsigned Integer
|
||||
// 32-bit big-endian unsigned integer in range [0, 4294967295]
|
||||
func (enc *Encoder) EncodeUint(v uint32) (int, error) {
|
||||
var b [4]byte
|
||||
b[0] = byte(v >> 24)
|
||||
b[1] = byte(v >> 16)
|
||||
b[2] = byte(v >> 8)
|
||||
b[3] = byte(v)
|
||||
|
||||
n, err := enc.w.Write(b[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
|
||||
err := marshalError("EncodeUint", ErrIO, msg, b[:n], err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// EncodeEnum treats the passed 32-bit signed integer as an enumeration value
|
||||
// and, if it is in the list of passed valid enumeration values, writes the XDR
|
||||
// encoded representation of it to the encapsulated writer. It returns the
|
||||
// number of bytes written.
|
||||
//
|
||||
// A MarshalError is returned if the enumeration value is not one of the
|
||||
// provided valid values or if writing the data fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.3 - Enumeration
|
||||
// Represented as an XDR encoded signed integer
|
||||
func (enc *Encoder) EncodeEnum(v int32, validEnums map[int32]bool) (int, error) {
|
||||
if !validEnums[v] {
|
||||
err := marshalError("EncodeEnum", ErrBadEnumValue,
|
||||
"invalid enum", v, nil)
|
||||
return 0, err
|
||||
}
|
||||
return enc.EncodeInt(v)
|
||||
}
|
||||
|
||||
// EncodeBool writes the XDR encoded representation of the passed boolean to the
|
||||
// encapsulated writer and returns the number of bytes written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.4 - Boolean
|
||||
// Represented as an XDR encoded enumeration where 0 is false and 1 is true
|
||||
func (enc *Encoder) EncodeBool(v bool) (int, error) {
|
||||
i := int32(0)
|
||||
if v == true {
|
||||
i = 1
|
||||
}
|
||||
return enc.EncodeInt(i)
|
||||
}
|
||||
|
||||
// EncodeHyper writes the XDR encoded representation of the passed 64-bit
|
||||
// signed integer to the encapsulated writer and returns the number of bytes
|
||||
// written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.5 - Hyper Integer
|
||||
// 64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
|
||||
func (enc *Encoder) EncodeHyper(v int64) (int, error) {
|
||||
var b [8]byte
|
||||
b[0] = byte(v >> 56)
|
||||
b[1] = byte(v >> 48)
|
||||
b[2] = byte(v >> 40)
|
||||
b[3] = byte(v >> 32)
|
||||
b[4] = byte(v >> 24)
|
||||
b[5] = byte(v >> 16)
|
||||
b[6] = byte(v >> 8)
|
||||
b[7] = byte(v)
|
||||
|
||||
n, err := enc.w.Write(b[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
|
||||
err := marshalError("EncodeHyper", ErrIO, msg, b[:n], err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// EncodeUhyper writes the XDR encoded representation of the passed 64-bit
|
||||
// unsigned integer to the encapsulated writer and returns the number of bytes
|
||||
// written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.5 - Unsigned Hyper Integer
|
||||
// 64-bit big-endian unsigned integer in range [0, 18446744073709551615]
|
||||
func (enc *Encoder) EncodeUhyper(v uint64) (int, error) {
|
||||
var b [8]byte
|
||||
b[0] = byte(v >> 56)
|
||||
b[1] = byte(v >> 48)
|
||||
b[2] = byte(v >> 40)
|
||||
b[3] = byte(v >> 32)
|
||||
b[4] = byte(v >> 24)
|
||||
b[5] = byte(v >> 16)
|
||||
b[6] = byte(v >> 8)
|
||||
b[7] = byte(v)
|
||||
|
||||
n, err := enc.w.Write(b[:])
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
|
||||
err := marshalError("EncodeUhyper", ErrIO, msg, b[:n], err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// EncodeFloat writes the XDR encoded representation of the passed 32-bit
|
||||
// (single-precision) floating point to the encapsulated writer and returns the
|
||||
// number of bytes written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.6 - Floating Point
|
||||
// 32-bit single-precision IEEE 754 floating point
|
||||
func (enc *Encoder) EncodeFloat(v float32) (int, error) {
|
||||
ui := math.Float32bits(v)
|
||||
return enc.EncodeUint(ui)
|
||||
}
|
||||
|
||||
// EncodeDouble writes the XDR encoded representation of the passed 64-bit
|
||||
// (double-precision) floating point to the encapsulated writer and returns the
|
||||
// number of bytes written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.7 - Double-Precision Floating Point
|
||||
// 64-bit double-precision IEEE 754 floating point
|
||||
func (enc *Encoder) EncodeDouble(v float64) (int, error) {
|
||||
ui := math.Float64bits(v)
|
||||
return enc.EncodeUhyper(ui)
|
||||
}
|
||||
|
||||
// RFC Section 4.8 - Quadruple-Precision Floating Point
|
||||
// 128-bit quadruple-precision floating point
|
||||
// Not Implemented
|
||||
|
||||
// EncodeFixedOpaque treats the passed byte slice as opaque data of a fixed
|
||||
// size and writes the XDR encoded representation of it to the encapsulated
|
||||
// writer. It returns the number of bytes written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.9 - Fixed-Length Opaque Data
|
||||
// Fixed-length uninterpreted data zero-padded to a multiple of four
|
||||
func (enc *Encoder) EncodeFixedOpaque(v []byte) (int, error) {
|
||||
l := len(v)
|
||||
pad := (4 - (l % 4)) % 4
|
||||
|
||||
// Write the actual bytes.
|
||||
n, err := enc.w.Write(v)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf(errIOEncode, err.Error(), len(v))
|
||||
err := marshalError("EncodeFixedOpaque", ErrIO, msg, v[:n], err)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Write any padding if needed.
|
||||
if pad > 0 {
|
||||
b := make([]byte, pad)
|
||||
n2, err := enc.w.Write(b)
|
||||
n += n2
|
||||
if err != nil {
|
||||
written := make([]byte, l+n2)
|
||||
copy(written, v)
|
||||
copy(written[l:], b[:n2])
|
||||
msg := fmt.Sprintf(errIOEncode, err.Error(), l+pad)
|
||||
err := marshalError("EncodeFixedOpaque", ErrIO, msg,
|
||||
written, err)
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// EncodeOpaque treats the passed byte slice as opaque data of a variable
|
||||
// size and writes the XDR encoded representation of it to the encapsulated
|
||||
// writer. It returns the number of bytes written.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.10 - Variable-Length Opaque Data
|
||||
// Unsigned integer length followed by fixed opaque data of that length
|
||||
func (enc *Encoder) EncodeOpaque(v []byte) (int, error) {
|
||||
// Length of opaque data.
|
||||
n, err := enc.EncodeUint(uint32(len(v)))
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
n2, err := enc.EncodeFixedOpaque(v)
|
||||
n += n2
|
||||
return n, err
|
||||
}
|
||||
|
||||
// EncodeString writes the XDR encoded representation of the passed string
|
||||
// to the encapsulated writer and returns the number of bytes written.
|
||||
// Character encoding is assumed to be UTF-8 and therefore ASCII compatible. If
|
||||
// the underlying character encoding is not compatible with this assumption, the
|
||||
// data can instead be written as variable-length opaque data (EncodeOpaque) and
|
||||
// manually converted as needed.
|
||||
//
|
||||
// A MarshalError with an error code of ErrIO is returned if writing the data
|
||||
// fails.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.11 - String
|
||||
// Unsigned integer length followed by bytes zero-padded to a multiple of four
|
||||
func (enc *Encoder) EncodeString(v string) (int, error) {
|
||||
// Length of string.
|
||||
n, err := enc.EncodeUint(uint32(len(v)))
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
n2, err := enc.EncodeFixedOpaque([]byte(v))
|
||||
n += n2
|
||||
return n, err
|
||||
}
|
||||
|
||||
// encodeFixedArray writes the XDR encoded representation of each element
|
||||
// in the passed array represented by the reflection value to the encapsulated
|
||||
// writer and returns the number of bytes written. The ignoreOpaque flag
|
||||
// controls whether or not uint8 (byte) elements should be encoded individually
|
||||
// or as a fixed sequence of opaque data.
|
||||
//
|
||||
// A MarshalError is returned if any issues are encountered while encoding
|
||||
// the array elements.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.12 - Fixed-Length Array
|
||||
// Individually XDR encoded array elements
|
||||
func (enc *Encoder) encodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
|
||||
// Treat [#]byte (byte is alias for uint8) as opaque data unless ignored.
|
||||
if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
|
||||
// Create a slice of the underlying array for better efficiency
|
||||
// when possible. Can't create a slice of an unaddressable
|
||||
// value.
|
||||
if v.CanAddr() {
|
||||
return enc.EncodeFixedOpaque(v.Slice(0, v.Len()).Bytes())
|
||||
}
|
||||
|
||||
// When the underlying array isn't addressable fall back to
|
||||
// copying the array into a new slice. This is rather ugly, but
|
||||
// the inability to create a constant slice from an
|
||||
// unaddressable array is a limitation of Go.
|
||||
slice := make([]byte, v.Len(), v.Len())
|
||||
reflect.Copy(reflect.ValueOf(slice), v)
|
||||
return enc.EncodeFixedOpaque(slice)
|
||||
}
|
||||
|
||||
// Encode each array element.
|
||||
var n int
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
n2, err := enc.encode(v.Index(i))
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// encodeArray writes an XDR encoded integer representing the number of
|
||||
// elements in the passed slice represented by the reflection value followed by
|
||||
// the XDR encoded representation of each element in slice to the encapsulated
|
||||
// writer and returns the number of bytes written. The ignoreOpaque flag
|
||||
// controls whether or not uint8 (byte) elements should be encoded individually
|
||||
// or as a variable sequence of opaque data.
|
||||
//
|
||||
// A MarshalError is returned if any issues are encountered while encoding
|
||||
// the array elements.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.13 - Variable-Length Array
|
||||
// Unsigned integer length followed by individually XDR encoded array elements
|
||||
func (enc *Encoder) encodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
|
||||
numItems := uint32(v.Len())
|
||||
n, err := enc.EncodeUint(numItems)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
n2, err := enc.encodeFixedArray(v, ignoreOpaque)
|
||||
n += n2
|
||||
return n, err
|
||||
}
|
||||
|
||||
// encodeStruct writes an XDR encoded representation of each value in the
|
||||
// exported fields of the struct represented by the passed reflection value to
|
||||
// the encapsulated writer and returns the number of bytes written. Pointers
|
||||
// are automatically indirected through arbitrary depth to encode the actual
|
||||
// value pointed to.
|
||||
//
|
||||
// A MarshalError is returned if any issues are encountered while encoding
|
||||
// the elements.
|
||||
//
|
||||
// Reference:
|
||||
// RFC Section 4.14 - Structure
|
||||
// XDR encoded elements in the order of their declaration in the struct
|
||||
func (enc *Encoder) encodeStruct(v reflect.Value) (int, error) {
|
||||
var n int
|
||||
vt := v.Type()
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
// Skip unexported fields and indirect through pointers.
|
||||
vtf := vt.Field(i)
|
||||
if vtf.PkgPath != "" {
|
||||
continue
|
||||
}
|
||||
vf := v.Field(i)
|
||||
vf = enc.indirect(vf)
|
||||
|
||||
// Handle non-opaque data to []uint8 and [#]uint8 based on struct tag.
|
||||
tag := vtf.Tag.Get("xdropaque")
|
||||
if tag == "false" {
|
||||
switch vf.Kind() {
|
||||
case reflect.Slice:
|
||||
n2, err := enc.encodeArray(vf, true)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
continue
|
||||
|
||||
case reflect.Array:
|
||||
n2, err := enc.encodeFixedArray(vf, true)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Encode each struct field.
|
||||
n2, err := enc.encode(vf)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// RFC Section 4.15 - Discriminated Union
|
||||
// RFC Section 4.16 - Void
|
||||
// RFC Section 4.17 - Constant
|
||||
// RFC Section 4.18 - Typedef
|
||||
// RFC Section 4.19 - Optional data
|
||||
// RFC Sections 4.15 though 4.19 only apply to the data specification language
|
||||
// which is not implemented by this package. In the case of discriminated
|
||||
// unions, struct tags are used to perform a similar function.
|
||||
|
||||
// encodeMap treats the map represented by the passed reflection value as a
|
||||
// variable-length array of 2-element structures whose fields are of the same
|
||||
// type as the map keys and elements and writes its XDR encoded representation
|
||||
// to the encapsulated writer. It returns the number of bytes written.
|
||||
//
|
||||
// A MarshalError is returned if any issues are encountered while encoding
|
||||
// the elements.
|
||||
func (enc *Encoder) encodeMap(v reflect.Value) (int, error) {
|
||||
// Number of elements.
|
||||
n, err := enc.EncodeUint(uint32(v.Len()))
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Encode each key and value according to their type.
|
||||
for _, key := range v.MapKeys() {
|
||||
n2, err := enc.encode(key)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
n2, err = enc.encode(v.MapIndex(key))
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// encodeInterface examines the interface represented by the passed reflection
|
||||
// value to detect whether it is an interface that can be encoded if it is,
|
||||
// extracts the underlying value to pass back into the encode function for
|
||||
// encoding according to its type.
|
||||
//
|
||||
// A MarshalError is returned if any issues are encountered while encoding
|
||||
// the interface.
|
||||
func (enc *Encoder) encodeInterface(v reflect.Value) (int, error) {
|
||||
if v.IsNil() || !v.CanInterface() {
|
||||
msg := fmt.Sprintf("can't encode nil interface")
|
||||
err := marshalError("encodeInterface", ErrNilInterface, msg,
|
||||
nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Extract underlying value from the interface and indirect through pointers.
|
||||
ve := reflect.ValueOf(v.Interface())
|
||||
ve = enc.indirect(ve)
|
||||
return enc.encode(ve)
|
||||
}
|
||||
|
||||
// encode is the main workhorse for marshalling via reflection. It uses
|
||||
// the passed reflection value to choose the XDR primitives to encode into
|
||||
// the encapsulated writer and returns the number of bytes written. It is a
|
||||
// recursive function, so cyclic data structures are not supported and will
|
||||
// result in an infinite loop.
|
||||
func (enc *Encoder) encode(v reflect.Value) (int, error) {
|
||||
if !v.IsValid() {
|
||||
msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
|
||||
err := marshalError("encode", ErrUnsupportedType, msg, nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Indirect through pointers to get at the concrete value.
|
||||
ve := enc.indirect(v)
|
||||
|
||||
// Handle time.Time values by encoding them as an RFC3339 formatted
|
||||
// string with nanosecond precision. Check the type string before
|
||||
// doing a full blown conversion to interface and type assertion since
|
||||
// checking a string is much quicker.
|
||||
if ve.Type().String() == "time.Time" && ve.CanInterface() {
|
||||
viface := ve.Interface()
|
||||
if tv, ok := viface.(time.Time); ok {
|
||||
return enc.EncodeString(tv.Format(time.RFC3339Nano))
|
||||
}
|
||||
}
|
||||
|
||||
// Handle native Go types.
|
||||
switch ve.Kind() {
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
|
||||
return enc.EncodeInt(int32(ve.Int()))
|
||||
|
||||
case reflect.Int64:
|
||||
return enc.EncodeHyper(ve.Int())
|
||||
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
|
||||
return enc.EncodeUint(uint32(ve.Uint()))
|
||||
|
||||
case reflect.Uint64:
|
||||
return enc.EncodeUhyper(ve.Uint())
|
||||
|
||||
case reflect.Bool:
|
||||
return enc.EncodeBool(ve.Bool())
|
||||
|
||||
case reflect.Float32:
|
||||
return enc.EncodeFloat(float32(ve.Float()))
|
||||
|
||||
case reflect.Float64:
|
||||
return enc.EncodeDouble(ve.Float())
|
||||
|
||||
case reflect.String:
|
||||
return enc.EncodeString(ve.String())
|
||||
|
||||
case reflect.Array:
|
||||
return enc.encodeFixedArray(ve, false)
|
||||
|
||||
case reflect.Slice:
|
||||
return enc.encodeArray(ve, false)
|
||||
|
||||
case reflect.Struct:
|
||||
return enc.encodeStruct(ve)
|
||||
|
||||
case reflect.Map:
|
||||
return enc.encodeMap(ve)
|
||||
|
||||
case reflect.Interface:
|
||||
return enc.encodeInterface(ve)
|
||||
}
|
||||
|
||||
// The only unhandled types left are unsupported. At the time of this
|
||||
// writing the only remaining unsupported types that exist are
|
||||
// reflect.Uintptr and reflect.UnsafePointer.
|
||||
msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
|
||||
err := marshalError("encode", ErrUnsupportedType, msg, nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// indirect dereferences pointers until it reaches a non-pointer. This allows
|
||||
// transparent encoding through arbitrary levels of indirection.
|
||||
func (enc *Encoder) indirect(v reflect.Value) reflect.Value {
|
||||
rv := v
|
||||
for rv.Kind() == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
// Encode operates identically to the Marshal function with the exception of
|
||||
// using the writer associated with the Encoder for the destination of the
|
||||
// XDR-encoded data instead of a user-supplied writer. See the Marshal
|
||||
// documentation for specifics.
|
||||
func (enc *Encoder) Encode(v interface{}) (int, error) {
|
||||
if v == nil {
|
||||
msg := "can't marshal nil interface"
|
||||
err := marshalError("Marshal", ErrNilInterface, msg, nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
vv := reflect.ValueOf(v)
|
||||
vve := vv
|
||||
for vve.Kind() == reflect.Ptr {
|
||||
if vve.IsNil() {
|
||||
msg := fmt.Sprintf("can't marshal nil pointer '%v'",
|
||||
vv.Type().String())
|
||||
err := marshalError("Marshal", ErrBadArguments, msg,
|
||||
nil, nil)
|
||||
return 0, err
|
||||
}
|
||||
vve = vve.Elem()
|
||||
}
|
||||
|
||||
return enc.encode(vve)
|
||||
}
|
||||
|
||||
// NewEncoder returns an object that can be used to manually choose fields to
|
||||
// XDR encode to the passed writer w. Typically, Marshal should be used instead
|
||||
// of manually creating an Encoder. An Encoder, along with several of its
|
||||
// methods to encode XDR primitives, is exposed so it is possible to perform
|
||||
// manual encoding of data without relying on reflection should it be necessary
|
||||
// in complex scenarios where automatic reflection-based encoding won't work.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w}
|
||||
}
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package xdr
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ErrorCode identifies a kind of error.
|
||||
type ErrorCode int
|
||||
|
||||
const (
|
||||
// ErrBadArguments indicates arguments passed to the function are not
|
||||
// what was expected.
|
||||
ErrBadArguments ErrorCode = iota
|
||||
|
||||
// ErrUnsupportedType indicates the Go type is not a supported type for
|
||||
// marshalling and unmarshalling XDR data.
|
||||
ErrUnsupportedType
|
||||
|
||||
// ErrBadEnumValue indicates an enumeration value is not in the list of
|
||||
// valid values.
|
||||
ErrBadEnumValue
|
||||
|
||||
// ErrNotSettable indicates an interface value cannot be written to.
|
||||
// This usually means the interface value was not passed with the &
|
||||
// operator, but it can also happen if automatic pointer allocation
|
||||
// fails.
|
||||
ErrNotSettable
|
||||
|
||||
// ErrOverflow indicates that the data in question is too large to fit
|
||||
// into the corresponding Go or XDR data type. For example, an integer
|
||||
// decoded from XDR that is too large to fit into a target type of int8,
|
||||
// or opaque data that exceeds the max length of a Go slice.
|
||||
ErrOverflow
|
||||
|
||||
// ErrNilInterface indicates an interface with no concrete type
|
||||
// information was encountered. Type information is necessary to
|
||||
// perform mapping between XDR and Go types.
|
||||
ErrNilInterface
|
||||
|
||||
// ErrIO indicates an error was encountered while reading or writing to
|
||||
// an io.Reader or io.Writer, respectively. The actual underlying error
|
||||
// will be available via the Err field of the MarshalError or
|
||||
// UnmarshalError struct.
|
||||
ErrIO
|
||||
|
||||
// ErrParseTime indicates an error was encountered while parsing an
|
||||
// RFC3339 formatted time value. The actual underlying error will be
|
||||
// available via the Err field of the UnmarshalError struct.
|
||||
ErrParseTime
|
||||
)
|
||||
|
||||
// Map of ErrorCode values back to their constant names for pretty printing.
|
||||
var errorCodeStrings = map[ErrorCode]string{
|
||||
ErrBadArguments: "ErrBadArguments",
|
||||
ErrUnsupportedType: "ErrUnsupportedType",
|
||||
ErrBadEnumValue: "ErrBadEnumValue",
|
||||
ErrNotSettable: "ErrNotSettable",
|
||||
ErrOverflow: "ErrOverflow",
|
||||
ErrNilInterface: "ErrNilInterface",
|
||||
ErrIO: "ErrIO",
|
||||
ErrParseTime: "ErrParseTime",
|
||||
}
|
||||
|
||||
// String returns the ErrorCode as a human-readable name.
|
||||
func (e ErrorCode) String() string {
|
||||
if s := errorCodeStrings[e]; s != "" {
|
||||
return s
|
||||
}
|
||||
return fmt.Sprintf("Unknown ErrorCode (%d)", e)
|
||||
}
|
||||
|
||||
// UnmarshalError describes a problem encountered while unmarshaling data.
|
||||
// Some potential issues are unsupported Go types, attempting to decode a value
|
||||
// which is too large to fit into a specified Go type, and exceeding max slice
|
||||
// limitations.
|
||||
type UnmarshalError struct {
|
||||
ErrorCode ErrorCode // Describes the kind of error
|
||||
Func string // Function name
|
||||
Value interface{} // Value actually parsed where appropriate
|
||||
Description string // Human readable description of the issue
|
||||
Err error // The underlying error for IO errors
|
||||
}
|
||||
|
||||
// Error satisfies the error interface and prints human-readable errors.
|
||||
func (e *UnmarshalError) Error() string {
|
||||
switch e.ErrorCode {
|
||||
case ErrBadEnumValue, ErrOverflow, ErrIO, ErrParseTime:
|
||||
return fmt.Sprintf("xdr:%s: %s - read: '%v'", e.Func,
|
||||
e.Description, e.Value)
|
||||
}
|
||||
return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description)
|
||||
}
|
||||
|
||||
// unmarshalError creates an error given a set of arguments and will copy byte
|
||||
// slices into the Value field since they might otherwise be changed from from
|
||||
// the original value.
|
||||
func unmarshalError(f string, c ErrorCode, desc string, v interface{}, err error) *UnmarshalError {
|
||||
e := &UnmarshalError{ErrorCode: c, Func: f, Description: desc, Err: err}
|
||||
switch t := v.(type) {
|
||||
case []byte:
|
||||
slice := make([]byte, len(t))
|
||||
copy(slice, t)
|
||||
e.Value = slice
|
||||
default:
|
||||
e.Value = v
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
// IsIO returns a boolean indicating whether the error is known to report that
|
||||
// the underlying reader or writer encountered an ErrIO.
|
||||
func IsIO(err error) bool {
|
||||
switch e := err.(type) {
|
||||
case *UnmarshalError:
|
||||
return e.ErrorCode == ErrIO
|
||||
case *MarshalError:
|
||||
return e.ErrorCode == ErrIO
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MarshalError describes a problem encountered while marshaling data.
|
||||
// Some potential issues are unsupported Go types, attempting to encode more
|
||||
// opaque data than can be represented by a single opaque XDR entry, and
|
||||
// exceeding max slice limitations.
|
||||
type MarshalError struct {
|
||||
ErrorCode ErrorCode // Describes the kind of error
|
||||
Func string // Function name
|
||||
Value interface{} // Value actually parsed where appropriate
|
||||
Description string // Human readable description of the issue
|
||||
Err error // The underlying error for IO errors
|
||||
}
|
||||
|
||||
// Error satisfies the error interface and prints human-readable errors.
|
||||
func (e *MarshalError) Error() string {
|
||||
switch e.ErrorCode {
|
||||
case ErrIO:
|
||||
return fmt.Sprintf("xdr:%s: %s - wrote: '%v'", e.Func,
|
||||
e.Description, e.Value)
|
||||
case ErrBadEnumValue:
|
||||
return fmt.Sprintf("xdr:%s: %s - value: '%v'", e.Func,
|
||||
e.Description, e.Value)
|
||||
}
|
||||
return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description)
|
||||
}
|
||||
|
||||
// marshalError creates an error given a set of arguments and will copy byte
|
||||
// slices into the Value field since they might otherwise be changed from from
|
||||
// the original value.
|
||||
func marshalError(f string, c ErrorCode, desc string, v interface{}, err error) *MarshalError {
|
||||
e := &MarshalError{ErrorCode: c, Func: f, Description: desc, Err: err}
|
||||
switch t := v.(type) {
|
||||
case []byte:
|
||||
slice := make([]byte, len(t))
|
||||
copy(slice, t)
|
||||
e.Value = slice
|
||||
default:
|
||||
e.Value = v
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
+890
@@ -0,0 +1,890 @@
|
||||
// Copyright 2018 The go-libvirt Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package libvirt
|
||||
|
||||
// We'll use c-for-go to extract the consts and typedefs from the libvirt
|
||||
// sources so we don't have to duplicate them here.
|
||||
//go:generate scripts/gen-consts.sh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||
"github.com/digitalocean/go-libvirt/internal/event"
|
||||
xdr "github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2"
|
||||
"github.com/digitalocean/go-libvirt/socket"
|
||||
"github.com/digitalocean/go-libvirt/socket/dialers"
|
||||
)
|
||||
|
||||
// ErrEventsNotSupported is returned by Events() if event streams
|
||||
// are unsupported by either QEMU or libvirt.
|
||||
var ErrEventsNotSupported = errors.New("event monitor is not supported")
|
||||
|
||||
// ConnectURI defines a type for driver URIs for libvirt
|
||||
// the defined constants are *not* exhaustive as there are also options
|
||||
// e.g. to connect remote via SSH
|
||||
type ConnectURI string
|
||||
|
||||
const (
|
||||
// QEMUSystem connects to a QEMU system mode daemon
|
||||
QEMUSystem ConnectURI = "qemu:///system"
|
||||
// QEMUSession connects to a QEMU session mode daemon (unprivileged)
|
||||
QEMUSession ConnectURI = "qemu:///session"
|
||||
// XenSystem connects to a Xen system mode daemon
|
||||
XenSystem ConnectURI = "xen:///system"
|
||||
//TestDefault connect to default mock driver
|
||||
TestDefault ConnectURI = "test:///default"
|
||||
|
||||
// disconnectedTimeout is how long to wait for disconnect cleanup to
|
||||
// complete
|
||||
disconnectTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
// Libvirt implements libvirt's remote procedure call protocol.
|
||||
type Libvirt struct {
|
||||
// socket connection
|
||||
socket *socket.Socket
|
||||
// closed after cleanup complete following the underlying connection to
|
||||
// libvirt being disconnected.
|
||||
disconnected chan struct{}
|
||||
|
||||
// method callbacks
|
||||
cmux sync.RWMutex
|
||||
callbacks map[int32]chan response
|
||||
|
||||
// event listeners
|
||||
emux sync.RWMutex
|
||||
events map[int32]*event.Stream
|
||||
|
||||
// next request serial number
|
||||
s int32
|
||||
}
|
||||
|
||||
// DomainEvent represents a libvirt domain event.
|
||||
type DomainEvent struct {
|
||||
CallbackID int32
|
||||
Domain Domain
|
||||
Event string
|
||||
Seconds uint64
|
||||
Microseconds uint32
|
||||
Padding uint8
|
||||
Details []byte
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID of a QEMU domain event.
|
||||
func (de DomainEvent) GetCallbackID() int32 {
|
||||
return de.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID of a libvirt lifecycle event.
|
||||
func (m DomainEventCallbackLifecycleMsg) GetCallbackID() int32 {
|
||||
return m.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackRebootMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackRtcChangeMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackWatchdogMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackIOErrorMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackIOErrorReasonMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackGraphicsMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackBlockJobMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackDiskChangeMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackTrayChangeMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackPmwakeupMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackPmsuspendMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackBalloonChangeMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackPmsuspendDiskMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackControlErrorMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackDeviceRemovedMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackTunableMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackDeviceAddedMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackAgentLifecycleMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackMigrationIterationMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackJobCompletedMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackDeviceRemovalFailedMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// GetCallbackID returns the callback ID.
|
||||
func (e *DomainEventCallbackMetadataChangeMsg) GetCallbackID() int32 {
|
||||
return e.CallbackID
|
||||
}
|
||||
|
||||
// qemuError represents a QEMU process error.
|
||||
type qemuError struct {
|
||||
Error struct {
|
||||
Class string `json:"class"`
|
||||
Description string `json:"desc"`
|
||||
} `json:"error"`
|
||||
}
|
||||
|
||||
// Capabilities returns an XML document describing the host's capabilties.
|
||||
func (l *Libvirt) Capabilities() ([]byte, error) {
|
||||
caps, err := l.ConnectGetCapabilities()
|
||||
return []byte(caps), err
|
||||
}
|
||||
|
||||
// called at connection time, authenticating with all supported auth types
|
||||
func (l *Libvirt) authenticate() error {
|
||||
// libvirt requires that we call auth-list prior to connecting,
|
||||
// even when no authentication is used.
|
||||
resp, err := l.AuthList()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, auth := range resp {
|
||||
switch auth {
|
||||
case constants.AuthNone:
|
||||
case constants.AuthPolkit:
|
||||
_, err := l.AuthPolkit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Libvirt) initLibvirtComms(uri ConnectURI) error {
|
||||
payload := struct {
|
||||
Padding [3]byte
|
||||
Name string
|
||||
Flags uint32
|
||||
}{
|
||||
Padding: [3]byte{0x1, 0x0, 0x0},
|
||||
Name: string(uri),
|
||||
Flags: 0,
|
||||
}
|
||||
|
||||
buf, err := encode(&payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = l.authenticate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = l.request(constants.ProcConnectOpen, constants.Program, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConnectToURI establishes communication with the specified libvirt driver
|
||||
// The underlying libvirt socket connection will be created via the dialer.
|
||||
// Since the connection can be lost, the Disconnected function can be used
|
||||
// to monitor for a lost connection.
|
||||
func (l *Libvirt) ConnectToURI(uri ConnectURI) error {
|
||||
err := l.socket.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Start watching the underlying socket connection immediately.
|
||||
// If we don't, and Libvirt goes away partway through initLibvirtComms,
|
||||
// then the callbacks that initLibvirtComms has registered will never
|
||||
// be closed, and therefore it will be stuck waiting for data from a
|
||||
// channel that will never arrive.
|
||||
go l.waitAndDisconnect()
|
||||
|
||||
err = l.initLibvirtComms(uri)
|
||||
if err != nil {
|
||||
l.socket.Disconnect()
|
||||
return err
|
||||
}
|
||||
|
||||
l.disconnected = make(chan struct{})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Connect establishes communication with the libvirt server.
|
||||
// The underlying libvirt socket connection will be created via the dialer.
|
||||
// Since the connection can be lost, the Disconnected function can be used
|
||||
// to monitor for a lost connection.
|
||||
func (l *Libvirt) Connect() error {
|
||||
return l.ConnectToURI(QEMUSystem)
|
||||
}
|
||||
|
||||
// Disconnect shuts down communication with the libvirt server and closes the
|
||||
// underlying net.Conn.
|
||||
func (l *Libvirt) Disconnect() error {
|
||||
// Ordering is important here. We want to make sure the connection is closed
|
||||
// before unsubscribing and deregistering the events and requests, to
|
||||
// prevent new requests from racing.
|
||||
_, err := l.request(constants.ProcConnectClose, constants.Program, nil)
|
||||
|
||||
// syscall.EINVAL is returned by the socket pkg when things have already
|
||||
// been disconnected.
|
||||
if err != nil && err != syscall.EINVAL {
|
||||
return err
|
||||
}
|
||||
err = l.socket.Disconnect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait for the listen goroutine to detect the lost connection and clean up
|
||||
// to happen once it returns. Safeguard with a timeout.
|
||||
// Things not fully cleaned up is better than a deadlock.
|
||||
select {
|
||||
case <-l.disconnected:
|
||||
case <-time.After(disconnectTimeout):
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Disconnected allows callers to detect if the underlying connection
|
||||
// to libvirt has been closed. If the returned channel is closed, then
|
||||
// the connection to libvirt has been lost (or disconnected intentionally).
|
||||
func (l *Libvirt) Disconnected() <-chan struct{} {
|
||||
return l.disconnected
|
||||
}
|
||||
|
||||
// IsConnected indicates whether or not there is currently a connection to
|
||||
// libvirtd.
|
||||
func (l *Libvirt) IsConnected() bool {
|
||||
select {
|
||||
case <-l.Disconnected():
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Domains returns a list of all domains managed by libvirt.
|
||||
//
|
||||
// Deprecated: use ConnectListAllDomains instead.
|
||||
func (l *Libvirt) Domains() ([]Domain, error) {
|
||||
// these are the flags as passed by `virsh list --all`
|
||||
flags := ConnectListDomainsActive | ConnectListDomainsInactive
|
||||
domains, _, err := l.ConnectListAllDomains(1, flags)
|
||||
return domains, err
|
||||
}
|
||||
|
||||
// DomainState returns state of the domain managed by libvirt.
|
||||
//
|
||||
// Deprecated: use DomainGetState instead.
|
||||
func (l *Libvirt) DomainState(dom string) (DomainState, error) {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return DomainNostate, err
|
||||
}
|
||||
|
||||
state, _, err := l.DomainGetState(d, 0)
|
||||
return DomainState(state), err
|
||||
}
|
||||
|
||||
// SubscribeQEMUEvents streams domain events until the provided context is
|
||||
// cancelled. If a problem is encountered setting up the event monitor
|
||||
// connection an error will be returned. Errors encountered during streaming
|
||||
// will cause the returned event channel to be closed. QEMU domain events.
|
||||
func (l *Libvirt) SubscribeQEMUEvents(ctx context.Context, dom string) (<-chan DomainEvent, error) {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
callbackID, err := l.QEMUConnectDomainMonitorEventRegister([]Domain{d}, nil, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stream := event.NewStream(constants.QEMUProgram, callbackID)
|
||||
l.addStream(stream)
|
||||
ch := make(chan DomainEvent)
|
||||
go func() {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
defer l.unsubscribeQEMUEvents(stream)
|
||||
defer stream.Shutdown()
|
||||
defer close(ch)
|
||||
|
||||
for {
|
||||
select {
|
||||
case ev, ok := <-stream.Recv():
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ch <- *ev.(*DomainEvent)
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// unsubscribeQEMUEvents stops the flow of events from QEMU through libvirt.
|
||||
func (l *Libvirt) unsubscribeQEMUEvents(stream *event.Stream) error {
|
||||
err := l.QEMUConnectDomainMonitorEventDeregister(stream.CallbackID)
|
||||
l.removeStream(stream.CallbackID)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SubscribeEvents allows the caller to subscribe to any of the event types
|
||||
// supported by libvirt. The events will continue to be streamed until the
|
||||
// caller cancels the provided context. After canceling the context, callers
|
||||
// should wait until the channel is closed to be sure they're collected all the
|
||||
// events.
|
||||
func (l *Libvirt) SubscribeEvents(ctx context.Context, eventID DomainEventID,
|
||||
dom OptDomain) (<-chan interface{}, error) {
|
||||
|
||||
callbackID, err := l.ConnectDomainEventCallbackRegisterAny(int32(eventID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stream := event.NewStream(constants.QEMUProgram, callbackID)
|
||||
l.addStream(stream)
|
||||
|
||||
ch := make(chan interface{})
|
||||
go func() {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
defer l.unsubscribeEvents(stream)
|
||||
defer stream.Shutdown()
|
||||
defer func() { close(ch) }()
|
||||
|
||||
for {
|
||||
select {
|
||||
case ev, ok := <-stream.Recv():
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ch <- ev
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// unsubscribeEvents stops the flow of the specified events from libvirt. There
|
||||
// are two steps to this process: a call to libvirt to deregister our callback,
|
||||
// and then removing the callback from the list used by the `Route` function. If
|
||||
// the deregister call fails, we'll return the error, but still remove the
|
||||
// callback from the list. That's ok; if any events arrive after this point, the
|
||||
// Route function will drop them when it finds no registered handler.
|
||||
func (l *Libvirt) unsubscribeEvents(stream *event.Stream) error {
|
||||
err := l.ConnectDomainEventCallbackDeregisterAny(stream.CallbackID)
|
||||
l.removeStream(stream.CallbackID)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// LifecycleEvents streams lifecycle events until the provided context is
|
||||
// cancelled. If a problem is encountered setting up the event monitor
|
||||
// connection, an error will be returned. Errors encountered during streaming
|
||||
// will cause the returned event channel to be closed.
|
||||
func (l *Libvirt) LifecycleEvents(ctx context.Context) (<-chan DomainEventLifecycleMsg, error) {
|
||||
callbackID, err := l.ConnectDomainEventCallbackRegisterAny(int32(DomainEventIDLifecycle), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stream := event.NewStream(constants.Program, callbackID)
|
||||
l.addStream(stream)
|
||||
|
||||
ch := make(chan DomainEventLifecycleMsg)
|
||||
|
||||
go func() {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
defer l.unsubscribeEvents(stream)
|
||||
defer stream.Shutdown()
|
||||
defer func() { close(ch) }()
|
||||
|
||||
for {
|
||||
select {
|
||||
case ev, ok := <-stream.Recv():
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ch <- ev.(*DomainEventCallbackLifecycleMsg).Msg
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// Run executes the given QAPI command against a domain's QEMU instance.
|
||||
// For a list of available QAPI commands, see:
|
||||
// http://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD
|
||||
func (l *Libvirt) Run(dom string, cmd []byte) ([]byte, error) {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payload := struct {
|
||||
Domain Domain
|
||||
Command []byte
|
||||
Flags uint32
|
||||
}{
|
||||
Domain: d,
|
||||
Command: cmd,
|
||||
Flags: 0,
|
||||
}
|
||||
|
||||
buf, err := encode(&payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := l.request(constants.QEMUProcDomainMonitorCommand, constants.QEMUProgram, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check for QEMU process errors
|
||||
if err = getQEMUError(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := bytes.NewReader(res.Payload)
|
||||
dec := xdr.NewDecoder(r)
|
||||
data, _, err := dec.DecodeFixedOpaque(int32(r.Len()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// drop QMP control characters from start of line, and drop
|
||||
// any trailing NULL characters from the end
|
||||
return bytes.TrimRight(data[4:], "\x00"), nil
|
||||
}
|
||||
|
||||
// Secrets returns all secrets managed by the libvirt daemon.
|
||||
//
|
||||
// Deprecated: use ConnectListAllSecrets instead.
|
||||
func (l *Libvirt) Secrets() ([]Secret, error) {
|
||||
secrets, _, err := l.ConnectListAllSecrets(1, 0)
|
||||
return secrets, err
|
||||
}
|
||||
|
||||
// StoragePool returns the storage pool associated with the provided name.
|
||||
// An error is returned if the requested storage pool is not found.
|
||||
//
|
||||
// Deprecated: use StoragePoolLookupByName instead.
|
||||
func (l *Libvirt) StoragePool(name string) (StoragePool, error) {
|
||||
return l.StoragePoolLookupByName(name)
|
||||
}
|
||||
|
||||
// StoragePools returns a list of defined storage pools. Pools are filtered by
|
||||
// the provided flags. See StoragePools*.
|
||||
//
|
||||
// Deprecated: use ConnectListAllStoragePools instead.
|
||||
func (l *Libvirt) StoragePools(flags ConnectListAllStoragePoolsFlags) ([]StoragePool, error) {
|
||||
pools, _, err := l.ConnectListAllStoragePools(1, flags)
|
||||
return pools, err
|
||||
}
|
||||
|
||||
// Undefine undefines the domain specified by dom, e.g., 'prod-lb-01'.
|
||||
// The flags argument allows additional options to be specified such as
|
||||
// cleaning up snapshot metadata. For more information on available
|
||||
// flags, see DomainUndefine*.
|
||||
//
|
||||
// Deprecated: use DomainUndefineFlags instead.
|
||||
func (l *Libvirt) Undefine(dom string, flags DomainUndefineFlagsValues) error {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return l.DomainUndefineFlags(d, flags)
|
||||
}
|
||||
|
||||
// Destroy destroys the domain specified by dom, e.g., 'prod-lb-01'.
|
||||
// The flags argument allows additional options to be specified such as
|
||||
// allowing a graceful shutdown with SIGTERM than SIGKILL.
|
||||
// For more information on available flags, see DomainDestroy*.
|
||||
//
|
||||
// Deprecated: use DomainDestroyFlags instead.
|
||||
func (l *Libvirt) Destroy(dom string, flags DomainDestroyFlagsValues) error {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return l.DomainDestroyFlags(d, flags)
|
||||
}
|
||||
|
||||
// XML returns a domain's raw XML definition, akin to `virsh dumpxml <domain>`.
|
||||
// See DomainXMLFlag* for optional flags.
|
||||
//
|
||||
// Deprecated: use DomainGetXMLDesc instead.
|
||||
func (l *Libvirt) XML(dom string, flags DomainXMLFlags) ([]byte, error) {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
xml, err := l.DomainGetXMLDesc(d, flags)
|
||||
return []byte(xml), err
|
||||
}
|
||||
|
||||
// DefineXML defines a domain, but does not start it.
|
||||
//
|
||||
// Deprecated: use DomainDefineXMLFlags instead.
|
||||
func (l *Libvirt) DefineXML(x []byte, flags DomainDefineFlags) error {
|
||||
_, err := l.DomainDefineXMLFlags(string(x), flags)
|
||||
return err
|
||||
}
|
||||
|
||||
// Version returns the version of the libvirt daemon.
|
||||
//
|
||||
// Deprecated: use ConnectGetLibVersion instead.
|
||||
func (l *Libvirt) Version() (string, error) {
|
||||
ver, err := l.ConnectGetLibVersion()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// The version is provided as an int following this formula:
|
||||
// version * 1,000,000 + minor * 1000 + micro
|
||||
// See src/libvirt-host.c # virConnectGetLibVersion
|
||||
major := ver / 1000000
|
||||
ver %= 1000000
|
||||
minor := ver / 1000
|
||||
ver %= 1000
|
||||
micro := ver
|
||||
|
||||
versionString := fmt.Sprintf("%d.%d.%d", major, minor, micro)
|
||||
return versionString, nil
|
||||
}
|
||||
|
||||
// Shutdown shuts down a domain. Note that the guest OS may ignore the request.
|
||||
// If flags is set to 0 then the hypervisor will choose the method of shutdown it considers best.
|
||||
//
|
||||
// Deprecated: use DomainShutdownFlags instead.
|
||||
func (l *Libvirt) Shutdown(dom string, flags DomainShutdownFlagValues) error {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return l.DomainShutdownFlags(d, flags)
|
||||
}
|
||||
|
||||
// Reboot reboots the domain. Note that the guest OS may ignore the request.
|
||||
// If flags is set to zero, then the hypervisor will choose the method of shutdown it considers best.
|
||||
//
|
||||
// Deprecated: use DomainReboot instead.
|
||||
func (l *Libvirt) Reboot(dom string, flags DomainRebootFlagValues) error {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return l.DomainReboot(d, flags)
|
||||
}
|
||||
|
||||
// Reset resets domain immediately without any guest OS shutdown
|
||||
//
|
||||
// Deprecated: use DomainReset instead.
|
||||
func (l *Libvirt) Reset(dom string) error {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return l.DomainReset(d, 0)
|
||||
}
|
||||
|
||||
// BlockLimit contains a name and value pair for a Get/SetBlockIOTune limit. The
|
||||
// Name field is the name of the limit (to see a list of the limits that can be
|
||||
// applied, execute the 'blkdeviotune' command on a VM in virsh). Callers can
|
||||
// use the QEMUBlockIO... constants below for the Name value. The Value field is
|
||||
// the limit to apply.
|
||||
type BlockLimit struct {
|
||||
Name string
|
||||
Value uint64
|
||||
}
|
||||
|
||||
// SetBlockIOTune changes the per-device block I/O tunables within a guest.
|
||||
// Parameters are the name of the VM, the name of the disk device to which the
|
||||
// limits should be applied, and 1 or more BlockLimit structs containing the
|
||||
// actual limits.
|
||||
//
|
||||
// The limits which can be applied here are enumerated in the QEMUBlockIO...
|
||||
// constants above, and you can also see the full list by executing the
|
||||
// 'blkdeviotune' command on a VM in virsh.
|
||||
//
|
||||
// Example usage:
|
||||
// SetBlockIOTune("vm-name", "vda", BlockLimit{libvirt.QEMUBlockIOWriteBytesSec, 1000000})
|
||||
//
|
||||
// Deprecated: use DomainSetBlockIOTune instead.
|
||||
func (l *Libvirt) SetBlockIOTune(dom string, disk string, limits ...BlockLimit) error {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params := make([]TypedParam, len(limits))
|
||||
for ix, limit := range limits {
|
||||
tpval := NewTypedParamValueUllong(limit.Value)
|
||||
params[ix] = TypedParam{Field: limit.Name, Value: *tpval}
|
||||
}
|
||||
|
||||
return l.DomainSetBlockIOTune(d, disk, params, uint32(DomainAffectLive))
|
||||
}
|
||||
|
||||
// GetBlockIOTune returns a slice containing the current block I/O tunables for
|
||||
// a disk.
|
||||
//
|
||||
// Deprecated: use DomainGetBlockIOTune instead.
|
||||
func (l *Libvirt) GetBlockIOTune(dom string, disk string) ([]BlockLimit, error) {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lims, _, err := l.DomainGetBlockIOTune(d, []string{disk}, 32, uint32(TypedParamStringOkay))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var limits []BlockLimit
|
||||
|
||||
// now decode each of the returned TypedParams. To do this we read the field
|
||||
// name and type, then use the type information to decode the value.
|
||||
for _, lim := range lims {
|
||||
var l BlockLimit
|
||||
name := lim.Field
|
||||
switch lim.Value.I.(type) {
|
||||
case uint64:
|
||||
l = BlockLimit{Name: name, Value: lim.Value.I.(uint64)}
|
||||
}
|
||||
limits = append(limits, l)
|
||||
}
|
||||
|
||||
return limits, nil
|
||||
}
|
||||
|
||||
// lookup returns a domain as seen by libvirt.
|
||||
func (l *Libvirt) lookup(name string) (Domain, error) {
|
||||
return l.DomainLookupByName(name)
|
||||
}
|
||||
|
||||
// getQEMUError checks the provided response for QEMU process errors.
|
||||
// If an error is found, it is extracted an returned, otherwise nil.
|
||||
func getQEMUError(r response) error {
|
||||
pl := bytes.NewReader(r.Payload)
|
||||
dec := xdr.NewDecoder(pl)
|
||||
|
||||
s, _, err := dec.DecodeString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var e qemuError
|
||||
if err = json.Unmarshal([]byte(s), &e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.Error.Description != "" {
|
||||
return errors.New(e.Error.Description)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Libvirt) waitAndDisconnect() {
|
||||
// wait for the socket to indicate if/when it's been disconnected
|
||||
<-l.socket.Disconnected()
|
||||
|
||||
// close event streams
|
||||
l.removeAllStreams()
|
||||
|
||||
// Deregister all callbacks to prevent blocking on clients with
|
||||
// outstanding requests
|
||||
l.deregisterAll()
|
||||
|
||||
select {
|
||||
case <-l.disconnected:
|
||||
// l.disconnected is already closed, i.e., Libvirt.ConnectToURI
|
||||
// was unable to complete all phases of its connection and
|
||||
// so this hadn't been assigned to an open channel yet (it
|
||||
// is set to a closed channel in Libvirt.New*)
|
||||
//
|
||||
// Just return to avoid closing an already-closed channel.
|
||||
return
|
||||
default:
|
||||
// if we make it here then reading from l.disconnected is blocking,
|
||||
// which suggests that it is open and must be closed.
|
||||
}
|
||||
|
||||
close(l.disconnected)
|
||||
}
|
||||
|
||||
// NewWithDialer configures a new Libvirt object that can be used to perform
|
||||
// RPCs via libvirt's socket. The actual connection will not be established
|
||||
// until Connect is called. The same Libvirt object may be used to re-connect
|
||||
// multiple times.
|
||||
func NewWithDialer(dialer socket.Dialer) *Libvirt {
|
||||
l := &Libvirt{
|
||||
s: 0,
|
||||
disconnected: make(chan struct{}),
|
||||
callbacks: make(map[int32]chan response),
|
||||
events: make(map[int32]*event.Stream),
|
||||
}
|
||||
|
||||
l.socket = socket.New(dialer, l)
|
||||
|
||||
// we start with a closed channel since that indicates no connection
|
||||
close(l.disconnected)
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// New configures a new Libvirt RPC connection.
|
||||
// This function only remains to retain backwards compatability.
|
||||
// When Libvirt's Connect function is called, the Dial will simply return the
|
||||
// connection passed in here and start a goroutine listening/reading from it.
|
||||
// If at any point the Disconnect function is called, any subsequent Connect
|
||||
// call will simply return an already closed connection.
|
||||
//
|
||||
// Deprecated: Please use NewWithDialer.
|
||||
func New(conn net.Conn) *Libvirt {
|
||||
return NewWithDialer(dialers.NewAlreadyConnected(conn))
|
||||
}
|
||||
|
||||
// NetworkUpdateCompat is a wrapper over NetworkUpdate which swaps `Command` and `Section` when needed.
|
||||
// This function must be used instead of NetworkUpdate to be sure that the
|
||||
// NetworkUpdate call works both with older and newer libvirtd connections.
|
||||
//
|
||||
// libvirt on-wire protocol had a bug for a long time where Command and Section
|
||||
// were reversed. It's been fixed in newer libvirt versions, and backported to
|
||||
// some older versions. This helper detects what argument order libvirtd expects
|
||||
// and makes the correct NetworkUpdate call.
|
||||
func (l *Libvirt) NetworkUpdateCompat(Net Network, Command NetworkUpdateCommand, Section NetworkUpdateSection, ParentIndex int32, XML string, Flags NetworkUpdateFlags) (err error) {
|
||||
// This is defined in libvirt/src/libvirt_internal.h and thus not available in go-libvirt autogenerated code
|
||||
const virDrvFeatureNetworkUpdateHasCorrectOrder = 16
|
||||
hasCorrectOrder, err := l.ConnectSupportsFeature(virDrvFeatureNetworkUpdateHasCorrectOrder)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to confirm argument order for NetworkUpdate: %w", err)
|
||||
}
|
||||
|
||||
// https://gitlab.com/libvirt/libvirt/-/commit/b0f78d626a18bcecae3a4d165540ab88bfbfc9ee
|
||||
if hasCorrectOrder == 0 {
|
||||
return l.NetworkUpdate(Net, uint32(Section), uint32(Command), ParentIndex, XML, Flags)
|
||||
}
|
||||
return l.NetworkUpdate(Net, uint32(Command), uint32(Section), ParentIndex, XML, Flags)
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
# Configuration file for c-for-go, which go-libvirt uses to translate the const
|
||||
# and type definitions from the C-language sources in the libvirt project into
|
||||
# Go. This file is used by the c-for-go binary (github.com/xlab/c-for-go), which
|
||||
# is called when 'go generate' is run. See libvirt.go for the command line used.
|
||||
---
|
||||
GENERATOR:
|
||||
PackageName: libvirt
|
||||
PackageLicense: |
|
||||
Copyright 2018 The go-libvirt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
Includes: []
|
||||
|
||||
PARSER:
|
||||
# We can't use environment variables here, but we don't want to process the
|
||||
# libvirt version installed in the system folders (if any). Instead we'll
|
||||
# rely on our caller to link the libvirt source directory to lv_source/, and
|
||||
# run on that code. This isn't ideal, but changes to c-for-go are needed to
|
||||
# fix it.
|
||||
IncludePaths: [./lv_source/include, ./lv_source/build/include]
|
||||
SourcesPaths:
|
||||
- libvirt/libvirt.h
|
||||
- libvirt/virterror.h
|
||||
|
||||
TRANSLATOR:
|
||||
ConstRules:
|
||||
defines: eval
|
||||
Rules:
|
||||
global:
|
||||
- {action: accept, from: "^vir"}
|
||||
post-global:
|
||||
- {action: replace, from: "^vir"}
|
||||
- {load: snakecase}
|
||||
# Follow golint's capitalization conventions.
|
||||
- {action: replace, from: "Api([A-Z]|$)", to: "API$1"}
|
||||
- {action: replace, from: "Cpu([A-Z]|$)", to: "CPU$1"}
|
||||
- {action: replace, from: "Dns([A-Z]|$)", to: "DNS$1"}
|
||||
- {action: replace, from: "Eof([A-Z]|$)", to: "EOF$1"}
|
||||
- {action: replace, from: "Id([A-Z]|$)", to: "ID$1"}
|
||||
- {action: replace, from: "Ip([A-Z]|$)", to: "IP$1"}
|
||||
- {action: replace, from: "Tls([A-Z]|$)", to: "TLS$1"}
|
||||
- {action: replace, from: "Uuid([A-Z]|$)", to: "UUID$1"}
|
||||
- {action: replace, from: "Uri([A-Z]|$)", to: "URI$1"}
|
||||
- {action: replace, from: "Vcpu([A-Z]|$)", to: "VCPU$1"}
|
||||
- {action: replace, from: "Xml([A-Z]|$)", to: "XML$1"}
|
||||
- {action: replace, from: "Rpc([A-Z]|$)", to: "RPC$1"}
|
||||
- {action: replace, from: "Ssh([A-Z]|$)", to: "SSH$1"}
|
||||
- {action: replace, from: "Http([A-Z]|$)", to: "HTTP$1"}
|
||||
- {transform: unexport, from: "^From"}
|
||||
const:
|
||||
- {action: accept, from: "^VIR_"}
|
||||
# Special case to prevent a collision with a type:
|
||||
- {action: replace, from: "^VIR_DOMAIN_JOB_OPERATION", to: "VIR_DOMAIN_JOB_OPERATION_STR"}
|
||||
- {transform: lower}
|
||||
+292
@@ -0,0 +1,292 @@
|
||||
// Copyright 2018 The go-libvirt Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//
|
||||
// Code generated by internal/lvgen/generate.go. DO NOT EDIT.
|
||||
//
|
||||
// To regenerate, run 'go generate' in internal/lvgen.
|
||||
//
|
||||
|
||||
package libvirt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||
"github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2"
|
||||
)
|
||||
|
||||
// References to prevent "imported and not used" errors.
|
||||
var (
|
||||
_ = bytes.Buffer{}
|
||||
_ = io.Copy
|
||||
_ = constants.Program
|
||||
_ = xdr.Unmarshal
|
||||
)
|
||||
|
||||
//
|
||||
// Typedefs:
|
||||
//
|
||||
|
||||
//
|
||||
// Enums:
|
||||
//
|
||||
// QEMUProcedure is libvirt's qemu_procedure
|
||||
type QEMUProcedure int32
|
||||
|
||||
//
|
||||
// Structs:
|
||||
//
|
||||
// QEMUDomainMonitorCommandArgs is libvirt's qemu_domain_monitor_command_args
|
||||
type QEMUDomainMonitorCommandArgs struct {
|
||||
Dom Domain
|
||||
Cmd string
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// QEMUDomainMonitorCommandRet is libvirt's qemu_domain_monitor_command_ret
|
||||
type QEMUDomainMonitorCommandRet struct {
|
||||
Result string
|
||||
}
|
||||
|
||||
// QEMUDomainAttachArgs is libvirt's qemu_domain_attach_args
|
||||
type QEMUDomainAttachArgs struct {
|
||||
PidValue uint32
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// QEMUDomainAttachRet is libvirt's qemu_domain_attach_ret
|
||||
type QEMUDomainAttachRet struct {
|
||||
Dom Domain
|
||||
}
|
||||
|
||||
// QEMUDomainAgentCommandArgs is libvirt's qemu_domain_agent_command_args
|
||||
type QEMUDomainAgentCommandArgs struct {
|
||||
Dom Domain
|
||||
Cmd string
|
||||
Timeout int32
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// QEMUDomainAgentCommandRet is libvirt's qemu_domain_agent_command_ret
|
||||
type QEMUDomainAgentCommandRet struct {
|
||||
Result OptString
|
||||
}
|
||||
|
||||
// QEMUConnectDomainMonitorEventRegisterArgs is libvirt's qemu_connect_domain_monitor_event_register_args
|
||||
type QEMUConnectDomainMonitorEventRegisterArgs struct {
|
||||
Dom OptDomain
|
||||
Event OptString
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// QEMUConnectDomainMonitorEventRegisterRet is libvirt's qemu_connect_domain_monitor_event_register_ret
|
||||
type QEMUConnectDomainMonitorEventRegisterRet struct {
|
||||
CallbackID int32
|
||||
}
|
||||
|
||||
// QEMUConnectDomainMonitorEventDeregisterArgs is libvirt's qemu_connect_domain_monitor_event_deregister_args
|
||||
type QEMUConnectDomainMonitorEventDeregisterArgs struct {
|
||||
CallbackID int32
|
||||
}
|
||||
|
||||
// QEMUDomainMonitorEventMsg is libvirt's qemu_domain_monitor_event_msg
|
||||
type QEMUDomainMonitorEventMsg struct {
|
||||
CallbackID int32
|
||||
Dom Domain
|
||||
Event string
|
||||
Seconds int64
|
||||
Micros uint32
|
||||
Details OptString
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// QEMUDomainMonitorCommand is the go wrapper for QEMU_PROC_DOMAIN_MONITOR_COMMAND.
|
||||
func (l *Libvirt) QEMUDomainMonitorCommand(Dom Domain, Cmd string, Flags uint32) (rResult string, err error) {
|
||||
var buf []byte
|
||||
|
||||
args := QEMUDomainMonitorCommandArgs {
|
||||
Dom: Dom,
|
||||
Cmd: Cmd,
|
||||
Flags: Flags,
|
||||
}
|
||||
|
||||
buf, err = encode(&args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var r response
|
||||
r, err = l.requestStream(1, constants.QEMUProgram, buf, nil, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Return value unmarshaling
|
||||
tpd := typedParamDecoder{}
|
||||
ct := map[string]xdr.TypeDecoder{"libvirt.TypedParam": tpd}
|
||||
rdr := bytes.NewReader(r.Payload)
|
||||
dec := xdr.NewDecoderCustomTypes(rdr, 0, ct)
|
||||
// Result: string
|
||||
_, err = dec.Decode(&rResult)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// QEMUDomainAttach is the go wrapper for QEMU_PROC_DOMAIN_ATTACH.
|
||||
func (l *Libvirt) QEMUDomainAttach(PidValue uint32, Flags uint32) (rDom Domain, err error) {
|
||||
var buf []byte
|
||||
|
||||
args := QEMUDomainAttachArgs {
|
||||
PidValue: PidValue,
|
||||
Flags: Flags,
|
||||
}
|
||||
|
||||
buf, err = encode(&args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var r response
|
||||
r, err = l.requestStream(2, constants.QEMUProgram, buf, nil, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Return value unmarshaling
|
||||
tpd := typedParamDecoder{}
|
||||
ct := map[string]xdr.TypeDecoder{"libvirt.TypedParam": tpd}
|
||||
rdr := bytes.NewReader(r.Payload)
|
||||
dec := xdr.NewDecoderCustomTypes(rdr, 0, ct)
|
||||
// Dom: Domain
|
||||
_, err = dec.Decode(&rDom)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// QEMUDomainAgentCommand is the go wrapper for QEMU_PROC_DOMAIN_AGENT_COMMAND.
|
||||
func (l *Libvirt) QEMUDomainAgentCommand(Dom Domain, Cmd string, Timeout int32, Flags uint32) (rResult OptString, err error) {
|
||||
var buf []byte
|
||||
|
||||
args := QEMUDomainAgentCommandArgs {
|
||||
Dom: Dom,
|
||||
Cmd: Cmd,
|
||||
Timeout: Timeout,
|
||||
Flags: Flags,
|
||||
}
|
||||
|
||||
buf, err = encode(&args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var r response
|
||||
r, err = l.requestStream(3, constants.QEMUProgram, buf, nil, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Return value unmarshaling
|
||||
tpd := typedParamDecoder{}
|
||||
ct := map[string]xdr.TypeDecoder{"libvirt.TypedParam": tpd}
|
||||
rdr := bytes.NewReader(r.Payload)
|
||||
dec := xdr.NewDecoderCustomTypes(rdr, 0, ct)
|
||||
// Result: OptString
|
||||
_, err = dec.Decode(&rResult)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// QEMUConnectDomainMonitorEventRegister is the go wrapper for QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_REGISTER.
|
||||
func (l *Libvirt) QEMUConnectDomainMonitorEventRegister(Dom OptDomain, Event OptString, Flags uint32) (rCallbackID int32, err error) {
|
||||
var buf []byte
|
||||
|
||||
args := QEMUConnectDomainMonitorEventRegisterArgs {
|
||||
Dom: Dom,
|
||||
Event: Event,
|
||||
Flags: Flags,
|
||||
}
|
||||
|
||||
buf, err = encode(&args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var r response
|
||||
r, err = l.requestStream(4, constants.QEMUProgram, buf, nil, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Return value unmarshaling
|
||||
tpd := typedParamDecoder{}
|
||||
ct := map[string]xdr.TypeDecoder{"libvirt.TypedParam": tpd}
|
||||
rdr := bytes.NewReader(r.Payload)
|
||||
dec := xdr.NewDecoderCustomTypes(rdr, 0, ct)
|
||||
// CallbackID: int32
|
||||
_, err = dec.Decode(&rCallbackID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// QEMUConnectDomainMonitorEventDeregister is the go wrapper for QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER.
|
||||
func (l *Libvirt) QEMUConnectDomainMonitorEventDeregister(CallbackID int32) (err error) {
|
||||
var buf []byte
|
||||
|
||||
args := QEMUConnectDomainMonitorEventDeregisterArgs {
|
||||
CallbackID: CallbackID,
|
||||
}
|
||||
|
||||
buf, err = encode(&args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
_, err = l.requestStream(5, constants.QEMUProgram, buf, nil, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// QEMUDomainMonitorEvent is the go wrapper for QEMU_PROC_DOMAIN_MONITOR_EVENT.
|
||||
func (l *Libvirt) QEMUDomainMonitorEvent() (err error) {
|
||||
var buf []byte
|
||||
|
||||
|
||||
_, err = l.requestStream(6, constants.QEMUProgram, buf, nil, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
+16494
File diff suppressed because it is too large
Load Diff
+481
@@ -0,0 +1,481 @@
|
||||
// Copyright 2018 The go-libvirt Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package libvirt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||
"github.com/digitalocean/go-libvirt/internal/event"
|
||||
xdr "github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2"
|
||||
"github.com/digitalocean/go-libvirt/socket"
|
||||
)
|
||||
|
||||
// ErrUnsupported is returned if a procedure is not supported by libvirt
|
||||
var ErrUnsupported = errors.New("unsupported procedure requested")
|
||||
|
||||
// ErrInterrupted is returned if the socket is closed while waiting for the
|
||||
// result of a procedure call.
|
||||
var ErrInterrupted = errors.New("procedure interrupted while awaiting response")
|
||||
|
||||
// internal rpc response
|
||||
type response struct {
|
||||
Payload []byte
|
||||
Status uint32
|
||||
}
|
||||
|
||||
// Error reponse from libvirt
|
||||
type Error struct {
|
||||
Code uint32
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e Error) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
// checkError is used to check whether an error is a libvirtError, and if it is,
|
||||
// whether its error code matches the one passed in. It will return false if
|
||||
// these conditions are not met.
|
||||
func checkError(err error, expectedError ErrorNumber) bool {
|
||||
for err != nil {
|
||||
e, ok := err.(Error)
|
||||
if ok {
|
||||
return e.Code == uint32(expectedError)
|
||||
}
|
||||
err = errors.Unwrap(err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsNotFound detects libvirt's ERR_NO_DOMAIN.
|
||||
func IsNotFound(err error) bool {
|
||||
return checkError(err, ErrNoDomain)
|
||||
}
|
||||
|
||||
// callback sends RPC responses to respective callers.
|
||||
func (l *Libvirt) callback(id int32, res response) {
|
||||
l.cmux.Lock()
|
||||
defer l.cmux.Unlock()
|
||||
|
||||
c, ok := l.callbacks[id]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c <- res
|
||||
}
|
||||
|
||||
// Route sends incoming packets to their listeners.
|
||||
func (l *Libvirt) Route(h *socket.Header, buf []byte) {
|
||||
// Route events to their respective listener
|
||||
var event event.Event
|
||||
|
||||
switch h.Program {
|
||||
case constants.QEMUProgram:
|
||||
if h.Procedure != constants.QEMUProcDomainMonitorEvent {
|
||||
break
|
||||
}
|
||||
event = &DomainEvent{}
|
||||
case constants.Program:
|
||||
event = eventFromProcedureID(h.Procedure)
|
||||
}
|
||||
|
||||
if event != nil {
|
||||
err := eventDecoder(buf, event)
|
||||
if err != nil { // event was malformed, drop.
|
||||
return
|
||||
}
|
||||
|
||||
l.stream(event)
|
||||
return
|
||||
}
|
||||
|
||||
// send response to caller
|
||||
l.callback(h.Serial, response{Payload: buf, Status: h.Status})
|
||||
}
|
||||
|
||||
func eventFromProcedureID(procID uint32) event.Event {
|
||||
switch procID {
|
||||
case constants.ProcDomainEventCallbackLifecycle:
|
||||
return &DomainEventCallbackLifecycleMsg{}
|
||||
case constants.ProcDomainEventCallbackReboot:
|
||||
return &DomainEventCallbackRebootMsg{}
|
||||
case constants.ProcDomainEventCallbackRtcChange:
|
||||
return &DomainEventCallbackRtcChangeMsg{}
|
||||
case constants.ProcDomainEventCallbackWatchdog:
|
||||
return &DomainEventCallbackWatchdogMsg{}
|
||||
case constants.ProcDomainEventCallbackIOError:
|
||||
return &DomainEventCallbackIOErrorMsg{}
|
||||
case constants.ProcDomainEventCallbackIOErrorReason:
|
||||
return &DomainEventCallbackIOErrorReasonMsg{}
|
||||
case constants.ProcDomainEventCallbackGraphics:
|
||||
return &DomainEventCallbackGraphicsMsg{}
|
||||
case constants.ProcDomainEventCallbackBlockJob:
|
||||
return &DomainEventCallbackBlockJobMsg{}
|
||||
case constants.ProcDomainEventCallbackDiskChange:
|
||||
return &DomainEventCallbackDiskChangeMsg{}
|
||||
case constants.ProcDomainEventCallbackTrayChange:
|
||||
return &DomainEventCallbackTrayChangeMsg{}
|
||||
case constants.ProcDomainEventCallbackPmwakeup:
|
||||
return &DomainEventCallbackPmwakeupMsg{}
|
||||
case constants.ProcDomainEventCallbackPmsuspend:
|
||||
return &DomainEventCallbackPmsuspendMsg{}
|
||||
case constants.ProcDomainEventCallbackBalloonChange:
|
||||
return &DomainEventCallbackBalloonChangeMsg{}
|
||||
case constants.ProcDomainEventCallbackPmsuspendDisk:
|
||||
return &DomainEventCallbackPmsuspendDiskMsg{}
|
||||
case constants.ProcDomainEventCallbackControlError:
|
||||
return &DomainEventCallbackControlErrorMsg{}
|
||||
case constants.ProcDomainEventCallbackDeviceRemoved:
|
||||
return &DomainEventCallbackDeviceRemovedMsg{}
|
||||
case constants.ProcDomainEventCallbackTunable:
|
||||
return &DomainEventCallbackTunableMsg{}
|
||||
case constants.ProcDomainEventCallbackDeviceAdded:
|
||||
return &DomainEventCallbackDeviceAddedMsg{}
|
||||
case constants.ProcDomainEventCallbackAgentLifecycle:
|
||||
return &DomainEventCallbackAgentLifecycleMsg{}
|
||||
case constants.ProcDomainEventCallbackMigrationIteration:
|
||||
return &DomainEventCallbackMigrationIterationMsg{}
|
||||
case constants.ProcDomainEventCallbackJobCompleted:
|
||||
return &DomainEventCallbackJobCompletedMsg{}
|
||||
case constants.ProcDomainEventCallbackDeviceRemovalFailed:
|
||||
return &DomainEventCallbackDeviceRemovalFailedMsg{}
|
||||
case constants.ProcDomainEventCallbackMetadataChange:
|
||||
return &DomainEventCallbackMetadataChangeMsg{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// serial provides atomic access to the next sequential request serial number.
|
||||
func (l *Libvirt) serial() int32 {
|
||||
return atomic.AddInt32(&l.s, 1)
|
||||
}
|
||||
|
||||
// stream decodes and relays domain events to their respective listener.
|
||||
func (l *Libvirt) stream(e event.Event) {
|
||||
l.emux.RLock()
|
||||
defer l.emux.RUnlock()
|
||||
|
||||
q, ok := l.events[e.GetCallbackID()]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
q.Push(e)
|
||||
}
|
||||
|
||||
// addStream configures the routing for an event stream.
|
||||
func (l *Libvirt) addStream(s *event.Stream) {
|
||||
l.emux.Lock()
|
||||
defer l.emux.Unlock()
|
||||
|
||||
l.events[s.CallbackID] = s
|
||||
}
|
||||
|
||||
// removeStream deletes an event stream. The caller should first notify libvirt
|
||||
// to stop sending events for this stream. Subsequent calls to removeStream are
|
||||
// idempotent and return nil.
|
||||
func (l *Libvirt) removeStream(id int32) error {
|
||||
l.emux.Lock()
|
||||
defer l.emux.Unlock()
|
||||
|
||||
// if the event is already removed, just return nil
|
||||
q, ok := l.events[id]
|
||||
if ok {
|
||||
delete(l.events, id)
|
||||
q.Shutdown()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// removeAllStreams deletes all event streams. This is meant to be used to
|
||||
// clean up only once the underlying connection to libvirt is disconnected and
|
||||
// thus does not attempt to notify libvirt to stop sending events.
|
||||
func (l *Libvirt) removeAllStreams() {
|
||||
l.emux.Lock()
|
||||
defer l.emux.Unlock()
|
||||
|
||||
for _, ev := range l.events {
|
||||
ev.Shutdown()
|
||||
delete(l.events, ev.CallbackID)
|
||||
}
|
||||
}
|
||||
|
||||
// register configures a method response callback
|
||||
func (l *Libvirt) register(id int32, c chan response) {
|
||||
l.cmux.Lock()
|
||||
defer l.cmux.Unlock()
|
||||
|
||||
l.callbacks[id] = c
|
||||
}
|
||||
|
||||
// deregister destroys a method response callback. It is the responsibility of
|
||||
// the caller to manage locking (l.cmux) during this call.
|
||||
func (l *Libvirt) deregister(id int32) {
|
||||
_, ok := l.callbacks[id]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
close(l.callbacks[id])
|
||||
delete(l.callbacks, id)
|
||||
}
|
||||
|
||||
// deregisterAll closes all waiting callback channels. This is used to clean up
|
||||
// if the connection to libvirt is lost. Callers waiting for responses will
|
||||
// return an error when the response channel is closed, rather than just
|
||||
// hanging.
|
||||
func (l *Libvirt) deregisterAll() {
|
||||
l.cmux.Lock()
|
||||
defer l.cmux.Unlock()
|
||||
|
||||
for id := range l.callbacks {
|
||||
l.deregister(id)
|
||||
}
|
||||
}
|
||||
|
||||
// request performs a libvirt RPC request.
|
||||
// returns response returned by server.
|
||||
// if response is not OK, decodes error from it and returns it.
|
||||
func (l *Libvirt) request(proc uint32, program uint32, payload []byte) (response, error) {
|
||||
return l.requestStream(proc, program, payload, nil, nil)
|
||||
}
|
||||
|
||||
// requestStream performs a libvirt RPC request. The `out` and `in` parameters
|
||||
// are optional, and should be nil when RPC endpoints don't return a stream.
|
||||
func (l *Libvirt) requestStream(proc uint32, program uint32, payload []byte,
|
||||
out io.Reader, in io.Writer) (response, error) {
|
||||
serial := l.serial()
|
||||
c := make(chan response)
|
||||
|
||||
l.register(serial, c)
|
||||
defer func() {
|
||||
l.cmux.Lock()
|
||||
defer l.cmux.Unlock()
|
||||
|
||||
l.deregister(serial)
|
||||
}()
|
||||
|
||||
err := l.socket.SendPacket(serial, proc, program, payload, socket.Call,
|
||||
socket.StatusOK)
|
||||
if err != nil {
|
||||
return response{}, err
|
||||
}
|
||||
|
||||
resp, err := l.getResponse(c)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
if out != nil {
|
||||
abort := make(chan bool)
|
||||
outErr := make(chan error)
|
||||
go func() {
|
||||
outErr <- l.socket.SendStream(serial, proc, program, out, abort)
|
||||
}()
|
||||
|
||||
// Even without incoming stream server sends confirmation once all data is received
|
||||
resp, err = l.processIncomingStream(c, in)
|
||||
if err != nil {
|
||||
abort <- true
|
||||
return resp, err
|
||||
}
|
||||
|
||||
err = <-outErr
|
||||
if err != nil {
|
||||
return response{}, err
|
||||
}
|
||||
}
|
||||
|
||||
switch in {
|
||||
case nil:
|
||||
return resp, nil
|
||||
default:
|
||||
return l.processIncomingStream(c, in)
|
||||
}
|
||||
}
|
||||
|
||||
// processIncomingStream is called once we've successfully sent a request to
|
||||
// libvirt. It writes the responses back to the stream passed by the caller
|
||||
// until libvirt sends a packet with statusOK or an error.
|
||||
func (l *Libvirt) processIncomingStream(c chan response, inStream io.Writer) (response, error) {
|
||||
for {
|
||||
resp, err := l.getResponse(c)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// StatusOK indicates end of stream
|
||||
if resp.Status == socket.StatusOK {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// FIXME: this smells.
|
||||
// StatusError is handled in getResponse, so this must be StatusContinue
|
||||
// StatusContinue is only valid here for stream packets
|
||||
// libvirtd breaks protocol and returns StatusContinue with an
|
||||
// empty response Payload when the stream finishes
|
||||
if len(resp.Payload) == 0 {
|
||||
return resp, nil
|
||||
}
|
||||
if inStream != nil {
|
||||
_, err = inStream.Write(resp.Payload)
|
||||
if err != nil {
|
||||
return response{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Libvirt) getResponse(c chan response) (response, error) {
|
||||
resp, ok := <-c
|
||||
|
||||
if !ok {
|
||||
// The channel was closed before a response was received. This means
|
||||
// that the socket was unexpectedly closed during the RPC call. In
|
||||
// this case, we must assume the worst, such as libvirt crashed while
|
||||
// attempting to execute the call.
|
||||
return resp, ErrInterrupted
|
||||
}
|
||||
|
||||
if resp.Status == socket.StatusError {
|
||||
return resp, decodeError(resp.Payload)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// encode XDR encodes the provided data.
|
||||
func encode(data interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
_, err := xdr.Marshal(&buf, data)
|
||||
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
// decodeError extracts an error message from the provider buffer.
|
||||
func decodeError(buf []byte) error {
|
||||
dec := xdr.NewDecoder(bytes.NewReader(buf))
|
||||
|
||||
e := struct {
|
||||
Code uint32
|
||||
DomainID uint32
|
||||
Padding uint8
|
||||
Message string
|
||||
Level uint32
|
||||
}{}
|
||||
_, err := dec.Decode(&e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.Contains(e.Message, "unknown procedure") {
|
||||
return ErrUnsupported
|
||||
}
|
||||
|
||||
// if libvirt returns ERR_OK, ignore the error
|
||||
if ErrorNumber(e.Code) == ErrOk {
|
||||
return nil
|
||||
}
|
||||
|
||||
return Error{Code: uint32(e.Code), Message: e.Message}
|
||||
}
|
||||
|
||||
// eventDecoder decodes an event from a xdr buffer.
|
||||
func eventDecoder(buf []byte, e interface{}) error {
|
||||
dec := xdr.NewDecoder(bytes.NewReader(buf))
|
||||
_, err := dec.Decode(e)
|
||||
return err
|
||||
}
|
||||
|
||||
type typedParamDecoder struct{}
|
||||
|
||||
// Decode decodes a TypedParam. These are part of the libvirt spec, and not xdr
|
||||
// proper. TypedParams contain a name, which is called Field for some reason,
|
||||
// and a Value, which itself has a "discriminant" - an integer enum encoding the
|
||||
// actual type, and a value, the length of which varies based on the actual
|
||||
// type.
|
||||
func (tpd typedParamDecoder) Decode(d *xdr.Decoder, v reflect.Value) (int, error) {
|
||||
// Get the name of the typed param first
|
||||
name, n, err := d.DecodeString()
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
val, n2, err := tpd.decodeTypedParamValue(d)
|
||||
n += n2
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
tp := &TypedParam{Field: name, Value: *val}
|
||||
v.Set(reflect.ValueOf(*tp))
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// decodeTypedParamValue decodes the Value part of a TypedParam.
|
||||
func (typedParamDecoder) decodeTypedParamValue(d *xdr.Decoder) (*TypedParamValue, int, error) {
|
||||
// All TypedParamValues begin with a uint32 discriminant that tells us what
|
||||
// type they are.
|
||||
discriminant, n, err := d.DecodeUint()
|
||||
if err != nil {
|
||||
return nil, n, err
|
||||
}
|
||||
var n2 int
|
||||
var tpv *TypedParamValue
|
||||
switch discriminant {
|
||||
case 1:
|
||||
var val int32
|
||||
n2, err = d.Decode(&val)
|
||||
tpv = &TypedParamValue{D: discriminant, I: val}
|
||||
case 2:
|
||||
var val uint32
|
||||
n2, err = d.Decode(&val)
|
||||
tpv = &TypedParamValue{D: discriminant, I: val}
|
||||
case 3:
|
||||
var val int64
|
||||
n2, err = d.Decode(&val)
|
||||
tpv = &TypedParamValue{D: discriminant, I: val}
|
||||
case 4:
|
||||
var val uint64
|
||||
n2, err = d.Decode(&val)
|
||||
tpv = &TypedParamValue{D: discriminant, I: val}
|
||||
case 5:
|
||||
var val float64
|
||||
n2, err = d.Decode(&val)
|
||||
tpv = &TypedParamValue{D: discriminant, I: val}
|
||||
case 6:
|
||||
var val int32
|
||||
n2, err = d.Decode(&val)
|
||||
tpv = &TypedParamValue{D: discriminant, I: val}
|
||||
case 7:
|
||||
var val string
|
||||
n2, err = d.Decode(&val)
|
||||
tpv = &TypedParamValue{D: discriminant, I: val}
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("invalid parameter type %v", discriminant)
|
||||
}
|
||||
n += n2
|
||||
|
||||
return tpv, n, err
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package dialers
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// AlreadyConnected implements a dialer interface for a connection that was
|
||||
// established prior to initializing the socket object. This exists solely
|
||||
// for backwards compatability with the previous implementation of Libvirt
|
||||
// that took an already established connection.
|
||||
type AlreadyConnected struct {
|
||||
c net.Conn
|
||||
}
|
||||
|
||||
// NewAlreadyConnected is a noop dialer to simply use a connection previously
|
||||
// established. This means any re-dial attempts simply won't work.
|
||||
func NewAlreadyConnected(c net.Conn) AlreadyConnected {
|
||||
return AlreadyConnected{c}
|
||||
}
|
||||
|
||||
// Dial just returns the connection previously established.
|
||||
// If at some point it is disconnected by the client, this obviously does *not*
|
||||
// re-dial and will simply return the already closed connection.
|
||||
func (a AlreadyConnected) Dial() (net.Conn, error) {
|
||||
return a.c, nil
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package dialers
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultSocket specifies the default path to the libvirt unix socket.
|
||||
defaultSocket = "/var/run/libvirt/libvirt-sock"
|
||||
|
||||
// defaultLocalTimeout specifies the default libvirt dial timeout.
|
||||
defaultLocalTimeout = 15 * time.Second
|
||||
)
|
||||
|
||||
// Local implements connecting to a local libvirtd over the unix socket.
|
||||
type Local struct {
|
||||
timeout time.Duration
|
||||
socket string
|
||||
}
|
||||
|
||||
// LocalOption is a function for setting local socket options.
|
||||
type LocalOption func(*Local)
|
||||
|
||||
// WithLocalTimeout sets the dial timeout.
|
||||
func WithLocalTimeout(timeout time.Duration) LocalOption {
|
||||
return func(l *Local) {
|
||||
l.timeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// WithSocket sets the path to the local libvirt socket.
|
||||
func WithSocket(socket string) LocalOption {
|
||||
return func(l *Local) {
|
||||
l.socket = socket
|
||||
}
|
||||
}
|
||||
|
||||
// NewLocal is a default dialer to simply connect to a locally running libvirt's
|
||||
// socket.
|
||||
func NewLocal(opts ...LocalOption) *Local {
|
||||
l := &Local{
|
||||
timeout: defaultLocalTimeout,
|
||||
socket: defaultSocket,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(l)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// Dial connects to a local socket
|
||||
func (l *Local) Dial() (net.Conn, error) {
|
||||
return net.DialTimeout("unix", l.socket, l.timeout)
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package dialers
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultRemotePort specifies the default libvirtd port.
|
||||
defaultRemotePort = "16509"
|
||||
|
||||
// defaultRemoteTimeout specifies the default libvirt dial timeout.
|
||||
defaultRemoteTimeout = 20 * time.Second
|
||||
)
|
||||
|
||||
// Remote implements connecting to a remote server's libvirt using tcp
|
||||
type Remote struct {
|
||||
timeout time.Duration
|
||||
host, port string
|
||||
}
|
||||
|
||||
// RemoteOption is a function for setting remote dialer options.
|
||||
type RemoteOption func(*Remote)
|
||||
|
||||
// WithRemoteTimeout sets the dial timeout.
|
||||
func WithRemoteTimeout(timeout time.Duration) RemoteOption {
|
||||
return func(r *Remote) {
|
||||
r.timeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// UsePort sets the port to dial for libirt on the target host server.
|
||||
func UsePort(port string) RemoteOption {
|
||||
return func(r *Remote) {
|
||||
r.port = port
|
||||
}
|
||||
}
|
||||
|
||||
// NewRemote is a dialer for connecting to libvirt running on another server.
|
||||
func NewRemote(hostAddr string, opts ...RemoteOption) *Remote {
|
||||
r := &Remote{
|
||||
timeout: defaultRemoteTimeout,
|
||||
host: hostAddr,
|
||||
port: defaultRemotePort,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(r)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// Dial connects to libvirt running on another server.
|
||||
func (r *Remote) Dial() (net.Conn, error) {
|
||||
return net.DialTimeout(
|
||||
"tcp",
|
||||
net.JoinHostPort(r.host, r.port),
|
||||
r.timeout,
|
||||
)
|
||||
}
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||
)
|
||||
|
||||
const disconnectTimeout = 5 * time.Second
|
||||
|
||||
// request and response statuses
|
||||
const (
|
||||
// StatusOK is always set for method calls or events.
|
||||
// For replies it indicates successful completion of the method.
|
||||
// For streams it indicates confirmation of the end of file on the stream.
|
||||
StatusOK = iota
|
||||
|
||||
// StatusError for replies indicates that the method call failed
|
||||
// and error information is being returned. For streams this indicates
|
||||
// that not all data was sent and the stream has aborted.
|
||||
StatusError
|
||||
|
||||
// StatusContinue is only used for streams.
|
||||
// This indicates that further data packets will be following.
|
||||
StatusContinue
|
||||
)
|
||||
|
||||
// request and response types
|
||||
const (
|
||||
// Call is used when making calls to the remote server.
|
||||
Call = iota
|
||||
|
||||
// Reply indicates a server reply.
|
||||
Reply
|
||||
|
||||
// Message is an asynchronous notification.
|
||||
Message
|
||||
|
||||
// Stream represents a stream data packet.
|
||||
Stream
|
||||
|
||||
// CallWithFDs is used by a client to indicate the request has
|
||||
// arguments with file descriptors.
|
||||
CallWithFDs
|
||||
|
||||
// ReplyWithFDs is used by a server to indicate the request has
|
||||
// arguments with file descriptors.
|
||||
ReplyWithFDs
|
||||
)
|
||||
|
||||
// Dialer is an interface for connecting to libvirt's underlying socket.
|
||||
type Dialer interface {
|
||||
Dial() (net.Conn, error)
|
||||
}
|
||||
|
||||
// Router is an interface used to route packets to the appropriate clients.
|
||||
type Router interface {
|
||||
Route(*Header, []byte)
|
||||
}
|
||||
|
||||
// Socket represents a libvirt Socket and its connection state
|
||||
type Socket struct {
|
||||
dialer Dialer
|
||||
router Router
|
||||
|
||||
conn net.Conn
|
||||
reader *bufio.Reader
|
||||
writer *bufio.Writer
|
||||
// used to serialize any Socket writes and any updates to conn, r, or w
|
||||
mu *sync.Mutex
|
||||
|
||||
// disconnected is closed when the listen goroutine associated with a
|
||||
// Socket connection has returned.
|
||||
disconnected chan struct{}
|
||||
}
|
||||
|
||||
// packet represents a RPC request or response.
|
||||
type packet struct {
|
||||
// Size of packet, in bytes, including length.
|
||||
// Len + Header + Payload
|
||||
Len uint32
|
||||
Header Header
|
||||
}
|
||||
|
||||
// Global packet instance, for use with unsafe.Sizeof()
|
||||
var _p packet
|
||||
|
||||
// Header is a libvirt rpc packet header
|
||||
type Header struct {
|
||||
// Program identifier
|
||||
Program uint32
|
||||
|
||||
// Program version
|
||||
Version uint32
|
||||
|
||||
// Remote procedure identifier
|
||||
Procedure uint32
|
||||
|
||||
// Call type, e.g., Reply
|
||||
Type uint32
|
||||
|
||||
// Call serial number
|
||||
Serial int32
|
||||
|
||||
// Request status, e.g., StatusOK
|
||||
Status uint32
|
||||
}
|
||||
|
||||
// New initializes a new type for managing the Socket.
|
||||
func New(dialer Dialer, router Router) *Socket {
|
||||
s := &Socket{
|
||||
dialer: dialer,
|
||||
router: router,
|
||||
disconnected: make(chan struct{}),
|
||||
mu: &sync.Mutex{},
|
||||
}
|
||||
|
||||
// we start with a closed channel since that indicates no connection
|
||||
close(s.disconnected)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Connect uses the dialer provided on creation to establish
|
||||
// underlying physical connection to the desired libvirt.
|
||||
func (s *Socket) Connect() error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if !s.isDisconnected() {
|
||||
return errors.New("already connected to socket")
|
||||
}
|
||||
conn, err := s.dialer.Dial()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.conn = conn
|
||||
s.reader = bufio.NewReader(conn)
|
||||
s.writer = bufio.NewWriter(conn)
|
||||
s.disconnected = make(chan struct{})
|
||||
|
||||
go s.listenAndRoute()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Disconnect closes the Socket connection to libvirt and waits for the reader
|
||||
// gorouting to shut down.
|
||||
func (s *Socket) Disconnect() error {
|
||||
// just return if we're already disconnected
|
||||
if s.isDisconnected() {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := s.conn.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// now we wait for the reader to return so as not to avoid it nil
|
||||
// referencing
|
||||
// Put this in a select,
|
||||
// and have it only nil out the conn value if it doesn't fail
|
||||
select {
|
||||
case <-s.disconnected:
|
||||
case <-time.After(disconnectTimeout):
|
||||
return errors.New("timed out waiting for Disconnect cleanup")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Disconnected returns a channel that will be closed once the current
|
||||
// connection is closed. This can happen due to an explicit call to Disconnect
|
||||
// from the client, or due to non-temporary Read or Write errors encountered.
|
||||
func (s *Socket) Disconnected() <-chan struct{} {
|
||||
return s.disconnected
|
||||
}
|
||||
|
||||
// isDisconnected is a non-blocking function to query whether a connection
|
||||
// is disconnected or not.
|
||||
func (s *Socket) isDisconnected() bool {
|
||||
select {
|
||||
case <-s.disconnected:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// listenAndRoute reads packets from the Socket and calls the provided
|
||||
// Router function to route them
|
||||
func (s *Socket) listenAndRoute() {
|
||||
// only returns once it detects a non-temporary error related to the
|
||||
// underlying connection
|
||||
listen(s.reader, s.router)
|
||||
|
||||
// signal any clients listening that the connection has been disconnected
|
||||
close(s.disconnected)
|
||||
}
|
||||
|
||||
// listen processes incoming data and routes
|
||||
// responses to their respective callback handler.
|
||||
func listen(s io.Reader, router Router) {
|
||||
for {
|
||||
// response packet length
|
||||
length, err := pktlen(s)
|
||||
if err != nil {
|
||||
if isTemporary(err) {
|
||||
continue
|
||||
}
|
||||
// connection is no longer valid, so shutdown
|
||||
return
|
||||
}
|
||||
|
||||
// response header
|
||||
h, err := extractHeader(s)
|
||||
if err != nil {
|
||||
// invalid packet
|
||||
continue
|
||||
}
|
||||
|
||||
// payload: packet length minus what was previously read
|
||||
size := int(length) - int(unsafe.Sizeof(_p))
|
||||
buf := make([]byte, size)
|
||||
_, err = io.ReadFull(s, buf)
|
||||
if err != nil {
|
||||
// invalid packet
|
||||
continue
|
||||
}
|
||||
|
||||
// route response to caller
|
||||
router.Route(h, buf)
|
||||
}
|
||||
}
|
||||
|
||||
// isTemporary returns true if the error returned from a read is transient.
|
||||
// If the error type is an OpError, check whether the net connection
|
||||
// error condition is temporary (which means we can keep using the
|
||||
// connection).
|
||||
// Errors not of the net.OpError type tend to be things like io.EOF,
|
||||
// syscall.EINVAL, or io.ErrClosedPipe (i.e. all things that
|
||||
// indicate the connection in use is no longer valid.)
|
||||
func isTemporary(err error) bool {
|
||||
opErr, ok := err.(*net.OpError)
|
||||
if ok {
|
||||
return opErr.Temporary()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// pktlen returns the length of an incoming RPC packet. Read errors will
|
||||
// result in a returned response length of 0 and a non-nil error.
|
||||
func pktlen(r io.Reader) (uint32, error) {
|
||||
buf := make([]byte, unsafe.Sizeof(_p.Len))
|
||||
|
||||
// extract the packet's length from the header
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return binary.BigEndian.Uint32(buf), nil
|
||||
}
|
||||
|
||||
// extractHeader returns the decoded header from an incoming response.
|
||||
func extractHeader(r io.Reader) (*Header, error) {
|
||||
buf := make([]byte, unsafe.Sizeof(_p.Header))
|
||||
|
||||
// extract the packet's header from r
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Header{
|
||||
Program: binary.BigEndian.Uint32(buf[0:4]),
|
||||
Version: binary.BigEndian.Uint32(buf[4:8]),
|
||||
Procedure: binary.BigEndian.Uint32(buf[8:12]),
|
||||
Type: binary.BigEndian.Uint32(buf[12:16]),
|
||||
Serial: int32(binary.BigEndian.Uint32(buf[16:20])),
|
||||
Status: binary.BigEndian.Uint32(buf[20:24]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SendPacket sends a packet to libvirt on the socket connection.
|
||||
func (s *Socket) SendPacket(
|
||||
serial int32,
|
||||
proc uint32,
|
||||
program uint32,
|
||||
payload []byte,
|
||||
typ uint32,
|
||||
status uint32,
|
||||
) error {
|
||||
p := packet{
|
||||
Header: Header{
|
||||
Program: program,
|
||||
Version: constants.ProtocolVersion,
|
||||
Procedure: proc,
|
||||
Type: typ,
|
||||
Serial: serial,
|
||||
Status: status,
|
||||
},
|
||||
}
|
||||
|
||||
size := int(unsafe.Sizeof(p.Len)) + int(unsafe.Sizeof(p.Header))
|
||||
if payload != nil {
|
||||
size += len(payload)
|
||||
}
|
||||
p.Len = uint32(size)
|
||||
|
||||
if s.isDisconnected() {
|
||||
// this mirrors what a lot of net code return on use of a no
|
||||
// longer valid connection
|
||||
return syscall.EINVAL
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
err := binary.Write(s.writer, binary.BigEndian, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// write payload
|
||||
if payload != nil {
|
||||
err = binary.Write(s.writer, binary.BigEndian, payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return s.writer.Flush()
|
||||
}
|
||||
|
||||
// SendStream sends a stream of packets to libvirt on the socket connection.
|
||||
func (s *Socket) SendStream(serial int32, proc uint32, program uint32,
|
||||
stream io.Reader, abort chan bool) error {
|
||||
// Keep total packet length under 4 MiB to follow possible limitation in libvirt server code
|
||||
buf := make([]byte, 4*MiB-unsafe.Sizeof(_p))
|
||||
for {
|
||||
select {
|
||||
case <-abort:
|
||||
return s.SendPacket(serial, proc, program, nil, Stream, StatusError)
|
||||
default:
|
||||
}
|
||||
n, err := stream.Read(buf)
|
||||
if n > 0 {
|
||||
err2 := s.SendPacket(serial, proc, program, buf[:n], Stream, StatusContinue)
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return s.SendPacket(serial, proc, program, nil, Stream, StatusOK)
|
||||
}
|
||||
// keep original error
|
||||
err2 := s.SendPacket(serial, proc, program, nil, Stream, StatusError)
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// Copyright 2016 The go-libvirt Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This module provides different units of measurement to make other
|
||||
// code more readable.
|
||||
|
||||
package socket
|
||||
|
||||
const (
|
||||
// B - byte
|
||||
B = 1
|
||||
// KiB - kibibyte
|
||||
KiB = 1024 * B
|
||||
// MiB - mebibyte
|
||||
MiB = 1024 * KiB
|
||||
)
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/AUTHORS.
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
||||
+29
-25
@@ -173,13 +173,15 @@ func tokenEqual(t1, t2 string) bool {
|
||||
|
||||
// isLWS reports whether b is linear white space, according
|
||||
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
||||
// LWS = [CRLF] 1*( SP | HT )
|
||||
//
|
||||
// LWS = [CRLF] 1*( SP | HT )
|
||||
func isLWS(b byte) bool { return b == ' ' || b == '\t' }
|
||||
|
||||
// isCTL reports whether b is a control byte, according
|
||||
// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
|
||||
// CTL = <any US-ASCII control character
|
||||
// (octets 0 - 31) and DEL (127)>
|
||||
//
|
||||
// CTL = <any US-ASCII control character
|
||||
// (octets 0 - 31) and DEL (127)>
|
||||
func isCTL(b byte) bool {
|
||||
const del = 0x7f // a CTL
|
||||
return b < ' ' || b == del
|
||||
@@ -189,12 +191,13 @@ func isCTL(b byte) bool {
|
||||
// HTTP/2 imposes the additional restriction that uppercase ASCII
|
||||
// letters are not allowed.
|
||||
//
|
||||
// RFC 7230 says:
|
||||
// header-field = field-name ":" OWS field-value OWS
|
||||
// field-name = token
|
||||
// token = 1*tchar
|
||||
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
|
||||
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
|
||||
// RFC 7230 says:
|
||||
//
|
||||
// header-field = field-name ":" OWS field-value OWS
|
||||
// field-name = token
|
||||
// token = 1*tchar
|
||||
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
|
||||
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
|
||||
func ValidHeaderFieldName(v string) bool {
|
||||
if len(v) == 0 {
|
||||
return false
|
||||
@@ -267,27 +270,28 @@ var validHostByte = [256]bool{
|
||||
// ValidHeaderFieldValue reports whether v is a valid "field-value" according to
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
|
||||
//
|
||||
// message-header = field-name ":" [ field-value ]
|
||||
// field-value = *( field-content | LWS )
|
||||
// field-content = <the OCTETs making up the field-value
|
||||
// and consisting of either *TEXT or combinations
|
||||
// of token, separators, and quoted-string>
|
||||
// message-header = field-name ":" [ field-value ]
|
||||
// field-value = *( field-content | LWS )
|
||||
// field-content = <the OCTETs making up the field-value
|
||||
// and consisting of either *TEXT or combinations
|
||||
// of token, separators, and quoted-string>
|
||||
//
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
|
||||
//
|
||||
// TEXT = <any OCTET except CTLs,
|
||||
// but including LWS>
|
||||
// LWS = [CRLF] 1*( SP | HT )
|
||||
// CTL = <any US-ASCII control character
|
||||
// (octets 0 - 31) and DEL (127)>
|
||||
// TEXT = <any OCTET except CTLs,
|
||||
// but including LWS>
|
||||
// LWS = [CRLF] 1*( SP | HT )
|
||||
// CTL = <any US-ASCII control character
|
||||
// (octets 0 - 31) and DEL (127)>
|
||||
//
|
||||
// RFC 7230 says:
|
||||
// field-value = *( field-content / obs-fold )
|
||||
// obj-fold = N/A to http2, and deprecated
|
||||
// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||
// field-vchar = VCHAR / obs-text
|
||||
// obs-text = %x80-FF
|
||||
// VCHAR = "any visible [USASCII] character"
|
||||
//
|
||||
// field-value = *( field-content / obs-fold )
|
||||
// obj-fold = N/A to http2, and deprecated
|
||||
// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||
// field-vchar = VCHAR / obs-text
|
||||
// obs-text = %x80-FF
|
||||
// VCHAR = "any visible [USASCII] character"
|
||||
//
|
||||
// http2 further says: "Similarly, HTTP/2 allows header field values
|
||||
// that are not valid. While most of the values that can be encoded
|
||||
|
||||
+2
-1
@@ -139,7 +139,6 @@ func (p *clientConnPool) getStartDialLocked(ctx context.Context, addr string) *d
|
||||
func (c *dialCall) dial(ctx context.Context, addr string) {
|
||||
const singleUse = false // shared conn
|
||||
c.res, c.err = c.p.t.dialClientConn(ctx, addr, singleUse)
|
||||
close(c.done)
|
||||
|
||||
c.p.mu.Lock()
|
||||
delete(c.p.dialing, addr)
|
||||
@@ -147,6 +146,8 @@ func (c *dialCall) dial(ctx context.Context, addr string) {
|
||||
c.p.addConnLocked(addr, c.res)
|
||||
}
|
||||
c.p.mu.Unlock()
|
||||
|
||||
close(c.done)
|
||||
}
|
||||
|
||||
// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ func (e headerFieldNameError) Error() string {
|
||||
type headerFieldValueError string
|
||||
|
||||
func (e headerFieldValueError) Error() string {
|
||||
return fmt.Sprintf("invalid header field value %q", string(e))
|
||||
return fmt.Sprintf("invalid header field value for %q", string(e))
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
+2
-1
@@ -1532,7 +1532,8 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
||||
fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
|
||||
}
|
||||
if !httpguts.ValidHeaderFieldValue(hf.Value) {
|
||||
invalid = headerFieldValueError(hf.Value)
|
||||
// Don't include the value in the error, because it may be sensitive.
|
||||
invalid = headerFieldValueError(hf.Name)
|
||||
}
|
||||
isPseudo := strings.HasPrefix(hf.Name, ":")
|
||||
if isPseudo {
|
||||
|
||||
+40
-47
@@ -169,25 +169,50 @@ func buildRootHuffmanNode() {
|
||||
// AppendHuffmanString appends s, as encoded in Huffman codes, to dst
|
||||
// and returns the extended buffer.
|
||||
func AppendHuffmanString(dst []byte, s string) []byte {
|
||||
rembits := uint8(8)
|
||||
|
||||
// This relies on the maximum huffman code length being 30 (See tables.go huffmanCodeLen array)
|
||||
// So if a uint64 buffer has less than 32 valid bits can always accommodate another huffmanCode.
|
||||
var (
|
||||
x uint64 // buffer
|
||||
n uint // number valid of bits present in x
|
||||
)
|
||||
for i := 0; i < len(s); i++ {
|
||||
if rembits == 8 {
|
||||
dst = append(dst, 0)
|
||||
c := s[i]
|
||||
n += uint(huffmanCodeLen[c])
|
||||
x <<= huffmanCodeLen[c] % 64
|
||||
x |= uint64(huffmanCodes[c])
|
||||
if n >= 32 {
|
||||
n %= 32 // Normally would be -= 32 but %= 32 informs compiler 0 <= n <= 31 for upcoming shift
|
||||
y := uint32(x >> n) // Compiler doesn't combine memory writes if y isn't uint32
|
||||
dst = append(dst, byte(y>>24), byte(y>>16), byte(y>>8), byte(y))
|
||||
}
|
||||
dst, rembits = appendByteToHuffmanCode(dst, rembits, s[i])
|
||||
}
|
||||
|
||||
if rembits < 8 {
|
||||
// special EOS symbol
|
||||
code := uint32(0x3fffffff)
|
||||
nbits := uint8(30)
|
||||
|
||||
t := uint8(code >> (nbits - rembits))
|
||||
dst[len(dst)-1] |= t
|
||||
// Add padding bits if necessary
|
||||
if over := n % 8; over > 0 {
|
||||
const (
|
||||
eosCode = 0x3fffffff
|
||||
eosNBits = 30
|
||||
eosPadByte = eosCode >> (eosNBits - 8)
|
||||
)
|
||||
pad := 8 - over
|
||||
x = (x << pad) | (eosPadByte >> over)
|
||||
n += pad // 8 now divides into n exactly
|
||||
}
|
||||
|
||||
return dst
|
||||
// n in (0, 8, 16, 24, 32)
|
||||
switch n / 8 {
|
||||
case 0:
|
||||
return dst
|
||||
case 1:
|
||||
return append(dst, byte(x))
|
||||
case 2:
|
||||
y := uint16(x)
|
||||
return append(dst, byte(y>>8), byte(y))
|
||||
case 3:
|
||||
y := uint16(x >> 8)
|
||||
return append(dst, byte(y>>8), byte(y), byte(x))
|
||||
}
|
||||
// case 4:
|
||||
y := uint32(x)
|
||||
return append(dst, byte(y>>24), byte(y>>16), byte(y>>8), byte(y))
|
||||
}
|
||||
|
||||
// HuffmanEncodeLength returns the number of bytes required to encode
|
||||
@@ -199,35 +224,3 @@ func HuffmanEncodeLength(s string) uint64 {
|
||||
}
|
||||
return (n + 7) / 8
|
||||
}
|
||||
|
||||
// appendByteToHuffmanCode appends Huffman code for c to dst and
|
||||
// returns the extended buffer and the remaining bits in the last
|
||||
// element. The appending is not byte aligned and the remaining bits
|
||||
// in the last element of dst is given in rembits.
|
||||
func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte, uint8) {
|
||||
code := huffmanCodes[c]
|
||||
nbits := huffmanCodeLen[c]
|
||||
|
||||
for {
|
||||
if rembits > nbits {
|
||||
t := uint8(code << (rembits - nbits))
|
||||
dst[len(dst)-1] |= t
|
||||
rembits -= nbits
|
||||
break
|
||||
}
|
||||
|
||||
t := uint8(code >> (nbits - rembits))
|
||||
dst[len(dst)-1] |= t
|
||||
|
||||
nbits -= rembits
|
||||
rembits = 8
|
||||
|
||||
if nbits == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
dst = append(dst, 0)
|
||||
}
|
||||
|
||||
return dst, rembits
|
||||
}
|
||||
|
||||
+7
-7
@@ -13,7 +13,6 @@
|
||||
// See https://http2.github.io/ for more information on HTTP/2.
|
||||
//
|
||||
// See https://http2.golang.org/ for a test server running this code.
|
||||
//
|
||||
package http2 // import "golang.org/x/net/http2"
|
||||
|
||||
import (
|
||||
@@ -176,10 +175,11 @@ func (s SettingID) String() string {
|
||||
// name (key). See httpguts.ValidHeaderName for the base rules.
|
||||
//
|
||||
// Further, http2 says:
|
||||
// "Just as in HTTP/1.x, header field names are strings of ASCII
|
||||
// characters that are compared in a case-insensitive
|
||||
// fashion. However, header field names MUST be converted to
|
||||
// lowercase prior to their encoding in HTTP/2. "
|
||||
//
|
||||
// "Just as in HTTP/1.x, header field names are strings of ASCII
|
||||
// characters that are compared in a case-insensitive
|
||||
// fashion. However, header field names MUST be converted to
|
||||
// lowercase prior to their encoding in HTTP/2. "
|
||||
func validWireHeaderFieldName(v string) bool {
|
||||
if len(v) == 0 {
|
||||
return false
|
||||
@@ -365,8 +365,8 @@ func (s *sorter) SortStrings(ss []string) {
|
||||
// validPseudoPath reports whether v is a valid :path pseudo-header
|
||||
// value. It must be either:
|
||||
//
|
||||
// *) a non-empty string starting with '/'
|
||||
// *) the string '*', for OPTIONS requests.
|
||||
// - a non-empty string starting with '/'
|
||||
// - the string '*', for OPTIONS requests.
|
||||
//
|
||||
// For now this is only used a quick check for deciding when to clean
|
||||
// up Opaque URLs before sending requests from the Transport.
|
||||
|
||||
+111
-24
@@ -315,6 +315,20 @@ type ServeConnOpts struct {
|
||||
// requests. If nil, BaseConfig.Handler is used. If BaseConfig
|
||||
// or BaseConfig.Handler is nil, http.DefaultServeMux is used.
|
||||
Handler http.Handler
|
||||
|
||||
// UpgradeRequest is an initial request received on a connection
|
||||
// undergoing an h2c upgrade. The request body must have been
|
||||
// completely read from the connection before calling ServeConn,
|
||||
// and the 101 Switching Protocols response written.
|
||||
UpgradeRequest *http.Request
|
||||
|
||||
// Settings is the decoded contents of the HTTP2-Settings header
|
||||
// in an h2c upgrade request.
|
||||
Settings []byte
|
||||
|
||||
// SawClientPreface is set if the HTTP/2 connection preface
|
||||
// has already been read from the connection.
|
||||
SawClientPreface bool
|
||||
}
|
||||
|
||||
func (o *ServeConnOpts) context() context.Context {
|
||||
@@ -383,6 +397,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||
headerTableSize: initialHeaderTableSize,
|
||||
serveG: newGoroutineLock(),
|
||||
pushEnabled: true,
|
||||
sawClientPreface: opts.SawClientPreface,
|
||||
}
|
||||
|
||||
s.state.registerConn(sc)
|
||||
@@ -400,7 +415,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||
if s.NewWriteScheduler != nil {
|
||||
sc.writeSched = s.NewWriteScheduler()
|
||||
} else {
|
||||
sc.writeSched = NewRandomWriteScheduler()
|
||||
sc.writeSched = NewPriorityWriteScheduler(nil)
|
||||
}
|
||||
|
||||
// These start at the RFC-specified defaults. If there is a higher
|
||||
@@ -465,9 +480,27 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Settings != nil {
|
||||
fr := &SettingsFrame{
|
||||
FrameHeader: FrameHeader{valid: true},
|
||||
p: opts.Settings,
|
||||
}
|
||||
if err := fr.ForeachSetting(sc.processSetting); err != nil {
|
||||
sc.rejectConn(ErrCodeProtocol, "invalid settings")
|
||||
return
|
||||
}
|
||||
opts.Settings = nil
|
||||
}
|
||||
|
||||
if hook := testHookGetServerConn; hook != nil {
|
||||
hook(sc)
|
||||
}
|
||||
|
||||
if opts.UpgradeRequest != nil {
|
||||
sc.upgradeRequest(opts.UpgradeRequest)
|
||||
opts.UpgradeRequest = nil
|
||||
}
|
||||
|
||||
sc.serve()
|
||||
}
|
||||
|
||||
@@ -512,6 +545,7 @@ type serverConn struct {
|
||||
// Everything following is owned by the serve loop; use serveG.check():
|
||||
serveG goroutineLock // used to verify funcs are on serve()
|
||||
pushEnabled bool
|
||||
sawClientPreface bool // preface has already been read, used in h2c upgrade
|
||||
sawFirstSettings bool // got the initial SETTINGS frame after the preface
|
||||
needToSendSettingsAck bool
|
||||
unackedSettings int // how many SETTINGS have we sent without ACKs?
|
||||
@@ -974,6 +1008,9 @@ var errPrefaceTimeout = errors.New("timeout waiting for client preface")
|
||||
// returns errPrefaceTimeout on timeout, or an error if the greeting
|
||||
// is invalid.
|
||||
func (sc *serverConn) readPreface() error {
|
||||
if sc.sawClientPreface {
|
||||
return nil
|
||||
}
|
||||
errc := make(chan error, 1)
|
||||
go func() {
|
||||
// Read the client preface
|
||||
@@ -1915,6 +1952,26 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sc *serverConn) upgradeRequest(req *http.Request) {
|
||||
sc.serveG.check()
|
||||
id := uint32(1)
|
||||
sc.maxClientStreamID = id
|
||||
st := sc.newStream(id, 0, stateHalfClosedRemote)
|
||||
st.reqTrailer = req.Trailer
|
||||
if st.reqTrailer != nil {
|
||||
st.trailer = make(http.Header)
|
||||
}
|
||||
rw := sc.newResponseWriter(st, req)
|
||||
|
||||
// Disable any read deadline set by the net/http package
|
||||
// prior to the upgrade.
|
||||
if sc.hs.ReadTimeout != 0 {
|
||||
sc.conn.SetReadDeadline(time.Time{})
|
||||
}
|
||||
|
||||
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
|
||||
}
|
||||
|
||||
func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
||||
sc := st.sc
|
||||
sc.serveG.check()
|
||||
@@ -2145,6 +2202,11 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
|
||||
}
|
||||
req = req.WithContext(st.ctx)
|
||||
|
||||
rw := sc.newResponseWriter(st, req)
|
||||
return rw, req, nil
|
||||
}
|
||||
|
||||
func (sc *serverConn) newResponseWriter(st *stream, req *http.Request) *responseWriter {
|
||||
rws := responseWriterStatePool.Get().(*responseWriterState)
|
||||
bwSave := rws.bw
|
||||
*rws = responseWriterState{} // zero all the fields
|
||||
@@ -2153,10 +2215,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
|
||||
rws.bw.Reset(chunkWriter{rws})
|
||||
rws.stream = st
|
||||
rws.req = req
|
||||
rws.body = body
|
||||
|
||||
rw := &responseWriter{rws: rws}
|
||||
return rw, req, nil
|
||||
return &responseWriter{rws: rws}
|
||||
}
|
||||
|
||||
// Run on its own goroutine.
|
||||
@@ -2316,17 +2375,18 @@ type requestBody struct {
|
||||
_ incomparable
|
||||
stream *stream
|
||||
conn *serverConn
|
||||
closed bool // for use by Close only
|
||||
sawEOF bool // for use by Read only
|
||||
pipe *pipe // non-nil if we have a HTTP entity message body
|
||||
needsContinue bool // need to send a 100-continue
|
||||
closeOnce sync.Once // for use by Close only
|
||||
sawEOF bool // for use by Read only
|
||||
pipe *pipe // non-nil if we have a HTTP entity message body
|
||||
needsContinue bool // need to send a 100-continue
|
||||
}
|
||||
|
||||
func (b *requestBody) Close() error {
|
||||
if b.pipe != nil && !b.closed {
|
||||
b.pipe.BreakWithError(errClosedBody)
|
||||
}
|
||||
b.closed = true
|
||||
b.closeOnce.Do(func() {
|
||||
if b.pipe != nil {
|
||||
b.pipe.BreakWithError(errClosedBody)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2370,7 +2430,6 @@ type responseWriterState struct {
|
||||
// immutable within a request:
|
||||
stream *stream
|
||||
req *http.Request
|
||||
body *requestBody // to close at end of request, if DATA frames didn't
|
||||
conn *serverConn
|
||||
|
||||
// TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
|
||||
@@ -2546,8 +2605,9 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||
// prior to the headers being written. If the set of trailers is fixed
|
||||
// or known before the header is written, the normal Go trailers mechanism
|
||||
// is preferred:
|
||||
// https://golang.org/pkg/net/http/#ResponseWriter
|
||||
// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
|
||||
//
|
||||
// https://golang.org/pkg/net/http/#ResponseWriter
|
||||
// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
|
||||
const TrailerPrefix = "Trailer:"
|
||||
|
||||
// promoteUndeclaredTrailers permits http.Handlers to set trailers
|
||||
@@ -2643,8 +2703,7 @@ func checkWriteHeaderCode(code int) {
|
||||
// Issue 22880: require valid WriteHeader status codes.
|
||||
// For now we only enforce that it's three digits.
|
||||
// In the future we might block things over 599 (600 and above aren't defined
|
||||
// at http://httpwg.org/specs/rfc7231.html#status.codes)
|
||||
// and we might block under 200 (once we have more mature 1xx support).
|
||||
// at http://httpwg.org/specs/rfc7231.html#status.codes).
|
||||
// But for now any three digits.
|
||||
//
|
||||
// We used to send "HTTP/1.1 000 0" on the wire in responses but there's
|
||||
@@ -2665,13 +2724,41 @@ func (w *responseWriter) WriteHeader(code int) {
|
||||
}
|
||||
|
||||
func (rws *responseWriterState) writeHeader(code int) {
|
||||
if !rws.wroteHeader {
|
||||
checkWriteHeaderCode(code)
|
||||
rws.wroteHeader = true
|
||||
rws.status = code
|
||||
if len(rws.handlerHeader) > 0 {
|
||||
rws.snapHeader = cloneHeader(rws.handlerHeader)
|
||||
if rws.wroteHeader {
|
||||
return
|
||||
}
|
||||
|
||||
checkWriteHeaderCode(code)
|
||||
|
||||
// Handle informational headers
|
||||
if code >= 100 && code <= 199 {
|
||||
// Per RFC 8297 we must not clear the current header map
|
||||
h := rws.handlerHeader
|
||||
|
||||
_, cl := h["Content-Length"]
|
||||
_, te := h["Transfer-Encoding"]
|
||||
if cl || te {
|
||||
h = h.Clone()
|
||||
h.Del("Content-Length")
|
||||
h.Del("Transfer-Encoding")
|
||||
}
|
||||
|
||||
if rws.conn.writeHeaders(rws.stream, &writeResHeaders{
|
||||
streamID: rws.stream.id,
|
||||
httpResCode: code,
|
||||
h: h,
|
||||
endStream: rws.handlerDone && !rws.hasTrailers(),
|
||||
}) != nil {
|
||||
rws.dirty = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
rws.wroteHeader = true
|
||||
rws.status = code
|
||||
if len(rws.handlerHeader) > 0 {
|
||||
rws.snapHeader = cloneHeader(rws.handlerHeader)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-4
@@ -16,7 +16,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math"
|
||||
mathrand "math/rand"
|
||||
@@ -501,12 +500,14 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
||||
if req, err = shouldRetryRequest(req, err); err == nil {
|
||||
// After the first retry, do exponential backoff with 10% jitter.
|
||||
if retry == 0 {
|
||||
t.vlogf("RoundTrip retrying after failure: %v", err)
|
||||
continue
|
||||
}
|
||||
backoff := float64(uint(1) << (uint(retry) - 1))
|
||||
backoff += backoff * (0.1 * mathrand.Float64())
|
||||
select {
|
||||
case <-time.After(time.Second * time.Duration(backoff)):
|
||||
t.vlogf("RoundTrip retrying after failure: %v", err)
|
||||
continue
|
||||
case <-req.Context().Done():
|
||||
err = req.Context().Err()
|
||||
@@ -732,10 +733,13 @@ func (cc *ClientConn) healthCheck() {
|
||||
// trigger the healthCheck again if there is no frame received.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
|
||||
defer cancel()
|
||||
cc.vlogf("http2: Transport sending health check")
|
||||
err := cc.Ping(ctx)
|
||||
if err != nil {
|
||||
cc.vlogf("http2: Transport health check failure: %v", err)
|
||||
cc.closeForLostPing()
|
||||
return
|
||||
} else {
|
||||
cc.vlogf("http2: Transport health check success")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1765,7 +1769,8 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
||||
}
|
||||
for _, v := range vv {
|
||||
if !httpguts.ValidHeaderFieldValue(v) {
|
||||
return nil, fmt.Errorf("invalid HTTP header value %q for header %q", v, k)
|
||||
// Don't include the value in the error, because it may be sensitive.
|
||||
return nil, fmt.Errorf("invalid HTTP header value for header %q", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2898,7 +2903,12 @@ func (t *Transport) logf(format string, args ...interface{}) {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
|
||||
var noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil))
|
||||
var noBody io.ReadCloser = noBodyReader{}
|
||||
|
||||
type noBodyReader struct{}
|
||||
|
||||
func (noBodyReader) Close() error { return nil }
|
||||
func (noBodyReader) Read([]byte) (int, error) { return 0, io.EOF }
|
||||
|
||||
type missingBody struct{}
|
||||
|
||||
|
||||
+4
-5
@@ -383,16 +383,15 @@ func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority Priorit
|
||||
|
||||
func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
|
||||
var n *priorityNode
|
||||
if id := wr.StreamID(); id == 0 {
|
||||
if wr.isControl() {
|
||||
n = &ws.root
|
||||
} else {
|
||||
id := wr.StreamID()
|
||||
n = ws.nodes[id]
|
||||
if n == nil {
|
||||
// id is an idle or closed stream. wr should not be a HEADERS or
|
||||
// DATA frame. However, wr can be a RST_STREAM. In this case, we
|
||||
// push wr onto the root, rather than creating a new priorityNode,
|
||||
// since RST_STREAM is tiny and the stream's priority is unknown
|
||||
// anyway. See issue #17919.
|
||||
// DATA frame. In other case, we push wr onto the root, rather
|
||||
// than creating a new priorityNode.
|
||||
if wr.DataSize() > 0 {
|
||||
panic("add DATA on non-open stream")
|
||||
}
|
||||
|
||||
+17
-17
@@ -17,23 +17,23 @@ package idna
|
||||
//
|
||||
// The per-rune values have the following format:
|
||||
//
|
||||
// if mapped {
|
||||
// if inlinedXOR {
|
||||
// 15..13 inline XOR marker
|
||||
// 12..11 unused
|
||||
// 10..3 inline XOR mask
|
||||
// } else {
|
||||
// 15..3 index into xor or mapping table
|
||||
// }
|
||||
// } else {
|
||||
// 15..14 unused
|
||||
// 13 mayNeedNorm
|
||||
// 12..11 attributes
|
||||
// 10..8 joining type
|
||||
// 7..3 category type
|
||||
// }
|
||||
// 2 use xor pattern
|
||||
// 1..0 mapped category
|
||||
// if mapped {
|
||||
// if inlinedXOR {
|
||||
// 15..13 inline XOR marker
|
||||
// 12..11 unused
|
||||
// 10..3 inline XOR mask
|
||||
// } else {
|
||||
// 15..3 index into xor or mapping table
|
||||
// }
|
||||
// } else {
|
||||
// 15..14 unused
|
||||
// 13 mayNeedNorm
|
||||
// 12..11 attributes
|
||||
// 10..8 joining type
|
||||
// 7..3 category type
|
||||
// }
|
||||
// 2 use xor pattern
|
||||
// 1..0 mapped category
|
||||
//
|
||||
// See the definitions below for a more detailed description of the various
|
||||
// bits.
|
||||
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/AUTHORS.
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// 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 (darwin || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// System call support for RISCV64 BSD
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
+2
-2
@@ -30,7 +30,7 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||
MOVV trap+0(FP), R11 // syscall entry
|
||||
SYSCALL
|
||||
MOVV R4, r1+32(FP)
|
||||
MOVV R5, r2+40(FP)
|
||||
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0
|
||||
JAL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
@@ -50,5 +50,5 @@ TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||
MOVV trap+0(FP), R11 // syscall entry
|
||||
SYSCALL
|
||||
MOVV R4, r1+32(FP)
|
||||
MOVV R5, r2+40(FP)
|
||||
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0
|
||||
RET
|
||||
|
||||
-233
@@ -1,233 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
|
||||
// them here for backwards compatibility.
|
||||
|
||||
package unix
|
||||
|
||||
const (
|
||||
DLT_HHDLC = 0x79
|
||||
IFF_SMART = 0x20
|
||||
IFT_1822 = 0x2
|
||||
IFT_A12MPPSWITCH = 0x82
|
||||
IFT_AAL2 = 0xbb
|
||||
IFT_AAL5 = 0x31
|
||||
IFT_ADSL = 0x5e
|
||||
IFT_AFLANE8023 = 0x3b
|
||||
IFT_AFLANE8025 = 0x3c
|
||||
IFT_ARAP = 0x58
|
||||
IFT_ARCNET = 0x23
|
||||
IFT_ARCNETPLUS = 0x24
|
||||
IFT_ASYNC = 0x54
|
||||
IFT_ATM = 0x25
|
||||
IFT_ATMDXI = 0x69
|
||||
IFT_ATMFUNI = 0x6a
|
||||
IFT_ATMIMA = 0x6b
|
||||
IFT_ATMLOGICAL = 0x50
|
||||
IFT_ATMRADIO = 0xbd
|
||||
IFT_ATMSUBINTERFACE = 0x86
|
||||
IFT_ATMVCIENDPT = 0xc2
|
||||
IFT_ATMVIRTUAL = 0x95
|
||||
IFT_BGPPOLICYACCOUNTING = 0xa2
|
||||
IFT_BSC = 0x53
|
||||
IFT_CCTEMUL = 0x3d
|
||||
IFT_CEPT = 0x13
|
||||
IFT_CES = 0x85
|
||||
IFT_CHANNEL = 0x46
|
||||
IFT_CNR = 0x55
|
||||
IFT_COFFEE = 0x84
|
||||
IFT_COMPOSITELINK = 0x9b
|
||||
IFT_DCN = 0x8d
|
||||
IFT_DIGITALPOWERLINE = 0x8a
|
||||
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
|
||||
IFT_DLSW = 0x4a
|
||||
IFT_DOCSCABLEDOWNSTREAM = 0x80
|
||||
IFT_DOCSCABLEMACLAYER = 0x7f
|
||||
IFT_DOCSCABLEUPSTREAM = 0x81
|
||||
IFT_DS0 = 0x51
|
||||
IFT_DS0BUNDLE = 0x52
|
||||
IFT_DS1FDL = 0xaa
|
||||
IFT_DS3 = 0x1e
|
||||
IFT_DTM = 0x8c
|
||||
IFT_DVBASILN = 0xac
|
||||
IFT_DVBASIOUT = 0xad
|
||||
IFT_DVBRCCDOWNSTREAM = 0x93
|
||||
IFT_DVBRCCMACLAYER = 0x92
|
||||
IFT_DVBRCCUPSTREAM = 0x94
|
||||
IFT_ENC = 0xf4
|
||||
IFT_EON = 0x19
|
||||
IFT_EPLRS = 0x57
|
||||
IFT_ESCON = 0x49
|
||||
IFT_ETHER = 0x6
|
||||
IFT_FAITH = 0xf2
|
||||
IFT_FAST = 0x7d
|
||||
IFT_FASTETHER = 0x3e
|
||||
IFT_FASTETHERFX = 0x45
|
||||
IFT_FDDI = 0xf
|
||||
IFT_FIBRECHANNEL = 0x38
|
||||
IFT_FRAMERELAYINTERCONNECT = 0x3a
|
||||
IFT_FRAMERELAYMPI = 0x5c
|
||||
IFT_FRDLCIENDPT = 0xc1
|
||||
IFT_FRELAY = 0x20
|
||||
IFT_FRELAYDCE = 0x2c
|
||||
IFT_FRF16MFRBUNDLE = 0xa3
|
||||
IFT_FRFORWARD = 0x9e
|
||||
IFT_G703AT2MB = 0x43
|
||||
IFT_G703AT64K = 0x42
|
||||
IFT_GIF = 0xf0
|
||||
IFT_GIGABITETHERNET = 0x75
|
||||
IFT_GR303IDT = 0xb2
|
||||
IFT_GR303RDT = 0xb1
|
||||
IFT_H323GATEKEEPER = 0xa4
|
||||
IFT_H323PROXY = 0xa5
|
||||
IFT_HDH1822 = 0x3
|
||||
IFT_HDLC = 0x76
|
||||
IFT_HDSL2 = 0xa8
|
||||
IFT_HIPERLAN2 = 0xb7
|
||||
IFT_HIPPI = 0x2f
|
||||
IFT_HIPPIINTERFACE = 0x39
|
||||
IFT_HOSTPAD = 0x5a
|
||||
IFT_HSSI = 0x2e
|
||||
IFT_HY = 0xe
|
||||
IFT_IBM370PARCHAN = 0x48
|
||||
IFT_IDSL = 0x9a
|
||||
IFT_IEEE80211 = 0x47
|
||||
IFT_IEEE80212 = 0x37
|
||||
IFT_IEEE8023ADLAG = 0xa1
|
||||
IFT_IFGSN = 0x91
|
||||
IFT_IMT = 0xbe
|
||||
IFT_INTERLEAVE = 0x7c
|
||||
IFT_IP = 0x7e
|
||||
IFT_IPFORWARD = 0x8e
|
||||
IFT_IPOVERATM = 0x72
|
||||
IFT_IPOVERCDLC = 0x6d
|
||||
IFT_IPOVERCLAW = 0x6e
|
||||
IFT_IPSWITCH = 0x4e
|
||||
IFT_IPXIP = 0xf9
|
||||
IFT_ISDN = 0x3f
|
||||
IFT_ISDNBASIC = 0x14
|
||||
IFT_ISDNPRIMARY = 0x15
|
||||
IFT_ISDNS = 0x4b
|
||||
IFT_ISDNU = 0x4c
|
||||
IFT_ISO88022LLC = 0x29
|
||||
IFT_ISO88023 = 0x7
|
||||
IFT_ISO88024 = 0x8
|
||||
IFT_ISO88025 = 0x9
|
||||
IFT_ISO88025CRFPINT = 0x62
|
||||
IFT_ISO88025DTR = 0x56
|
||||
IFT_ISO88025FIBER = 0x73
|
||||
IFT_ISO88026 = 0xa
|
||||
IFT_ISUP = 0xb3
|
||||
IFT_L3IPXVLAN = 0x89
|
||||
IFT_LAPB = 0x10
|
||||
IFT_LAPD = 0x4d
|
||||
IFT_LAPF = 0x77
|
||||
IFT_LOCALTALK = 0x2a
|
||||
IFT_LOOP = 0x18
|
||||
IFT_MEDIAMAILOVERIP = 0x8b
|
||||
IFT_MFSIGLINK = 0xa7
|
||||
IFT_MIOX25 = 0x26
|
||||
IFT_MODEM = 0x30
|
||||
IFT_MPC = 0x71
|
||||
IFT_MPLS = 0xa6
|
||||
IFT_MPLSTUNNEL = 0x96
|
||||
IFT_MSDSL = 0x8f
|
||||
IFT_MVL = 0xbf
|
||||
IFT_MYRINET = 0x63
|
||||
IFT_NFAS = 0xaf
|
||||
IFT_NSIP = 0x1b
|
||||
IFT_OPTICALCHANNEL = 0xc3
|
||||
IFT_OPTICALTRANSPORT = 0xc4
|
||||
IFT_OTHER = 0x1
|
||||
IFT_P10 = 0xc
|
||||
IFT_P80 = 0xd
|
||||
IFT_PARA = 0x22
|
||||
IFT_PFLOG = 0xf6
|
||||
IFT_PFSYNC = 0xf7
|
||||
IFT_PLC = 0xae
|
||||
IFT_POS = 0xab
|
||||
IFT_PPPMULTILINKBUNDLE = 0x6c
|
||||
IFT_PROPBWAP2MP = 0xb8
|
||||
IFT_PROPCNLS = 0x59
|
||||
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
|
||||
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
|
||||
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
|
||||
IFT_PROPMUX = 0x36
|
||||
IFT_PROPWIRELESSP2P = 0x9d
|
||||
IFT_PTPSERIAL = 0x16
|
||||
IFT_PVC = 0xf1
|
||||
IFT_QLLC = 0x44
|
||||
IFT_RADIOMAC = 0xbc
|
||||
IFT_RADSL = 0x5f
|
||||
IFT_REACHDSL = 0xc0
|
||||
IFT_RFC1483 = 0x9f
|
||||
IFT_RS232 = 0x21
|
||||
IFT_RSRB = 0x4f
|
||||
IFT_SDLC = 0x11
|
||||
IFT_SDSL = 0x60
|
||||
IFT_SHDSL = 0xa9
|
||||
IFT_SIP = 0x1f
|
||||
IFT_SLIP = 0x1c
|
||||
IFT_SMDSDXI = 0x2b
|
||||
IFT_SMDSICIP = 0x34
|
||||
IFT_SONET = 0x27
|
||||
IFT_SONETOVERHEADCHANNEL = 0xb9
|
||||
IFT_SONETPATH = 0x32
|
||||
IFT_SONETVT = 0x33
|
||||
IFT_SRP = 0x97
|
||||
IFT_SS7SIGLINK = 0x9c
|
||||
IFT_STACKTOSTACK = 0x6f
|
||||
IFT_STARLAN = 0xb
|
||||
IFT_STF = 0xd7
|
||||
IFT_T1 = 0x12
|
||||
IFT_TDLC = 0x74
|
||||
IFT_TERMPAD = 0x5b
|
||||
IFT_TR008 = 0xb0
|
||||
IFT_TRANSPHDLC = 0x7b
|
||||
IFT_TUNNEL = 0x83
|
||||
IFT_ULTRA = 0x1d
|
||||
IFT_USB = 0xa0
|
||||
IFT_V11 = 0x40
|
||||
IFT_V35 = 0x2d
|
||||
IFT_V36 = 0x41
|
||||
IFT_V37 = 0x78
|
||||
IFT_VDSL = 0x61
|
||||
IFT_VIRTUALIPADDRESS = 0x70
|
||||
IFT_VOICEEM = 0x64
|
||||
IFT_VOICEENCAP = 0x67
|
||||
IFT_VOICEFXO = 0x65
|
||||
IFT_VOICEFXS = 0x66
|
||||
IFT_VOICEOVERATM = 0x98
|
||||
IFT_VOICEOVERFRAMERELAY = 0x99
|
||||
IFT_VOICEOVERIP = 0x68
|
||||
IFT_X213 = 0x5d
|
||||
IFT_X25 = 0x5
|
||||
IFT_X25DDN = 0x4
|
||||
IFT_X25HUNTGROUP = 0x7a
|
||||
IFT_X25MLP = 0x79
|
||||
IFT_X25PLE = 0x28
|
||||
IFT_XETHER = 0x1a
|
||||
IPPROTO_MAXID = 0x34
|
||||
IPV6_FAITH = 0x1d
|
||||
IPV6_MIN_MEMBERSHIPS = 0x1f
|
||||
IP_FAITH = 0x16
|
||||
IP_MAX_SOURCE_FILTER = 0x400
|
||||
IP_MIN_MEMBERSHIPS = 0x1f
|
||||
MAP_NORESERVE = 0x40
|
||||
MAP_RENAME = 0x20
|
||||
NET_RT_MAXID = 0x6
|
||||
RTF_PRCLONING = 0x10000
|
||||
RTM_OLDADD = 0x9
|
||||
RTM_OLDDEL = 0xa
|
||||
RT_CACHING_CONTEXT = 0x1
|
||||
RT_NORTREF = 0x2
|
||||
SIOCADDRT = 0x8030720a
|
||||
SIOCALIFADDR = 0x8118691b
|
||||
SIOCDELRT = 0x8030720b
|
||||
SIOCDLIFADDR = 0x8118691d
|
||||
SIOCGLIFADDR = 0xc118691c
|
||||
SIOCGLIFPHYADDR = 0xc118694b
|
||||
SIOCSLIFPHYADDR = 0x8118694a
|
||||
)
|
||||
-233
@@ -1,233 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
|
||||
// them here for backwards compatibility.
|
||||
|
||||
package unix
|
||||
|
||||
const (
|
||||
DLT_HHDLC = 0x79
|
||||
IFF_SMART = 0x20
|
||||
IFT_1822 = 0x2
|
||||
IFT_A12MPPSWITCH = 0x82
|
||||
IFT_AAL2 = 0xbb
|
||||
IFT_AAL5 = 0x31
|
||||
IFT_ADSL = 0x5e
|
||||
IFT_AFLANE8023 = 0x3b
|
||||
IFT_AFLANE8025 = 0x3c
|
||||
IFT_ARAP = 0x58
|
||||
IFT_ARCNET = 0x23
|
||||
IFT_ARCNETPLUS = 0x24
|
||||
IFT_ASYNC = 0x54
|
||||
IFT_ATM = 0x25
|
||||
IFT_ATMDXI = 0x69
|
||||
IFT_ATMFUNI = 0x6a
|
||||
IFT_ATMIMA = 0x6b
|
||||
IFT_ATMLOGICAL = 0x50
|
||||
IFT_ATMRADIO = 0xbd
|
||||
IFT_ATMSUBINTERFACE = 0x86
|
||||
IFT_ATMVCIENDPT = 0xc2
|
||||
IFT_ATMVIRTUAL = 0x95
|
||||
IFT_BGPPOLICYACCOUNTING = 0xa2
|
||||
IFT_BSC = 0x53
|
||||
IFT_CCTEMUL = 0x3d
|
||||
IFT_CEPT = 0x13
|
||||
IFT_CES = 0x85
|
||||
IFT_CHANNEL = 0x46
|
||||
IFT_CNR = 0x55
|
||||
IFT_COFFEE = 0x84
|
||||
IFT_COMPOSITELINK = 0x9b
|
||||
IFT_DCN = 0x8d
|
||||
IFT_DIGITALPOWERLINE = 0x8a
|
||||
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
|
||||
IFT_DLSW = 0x4a
|
||||
IFT_DOCSCABLEDOWNSTREAM = 0x80
|
||||
IFT_DOCSCABLEMACLAYER = 0x7f
|
||||
IFT_DOCSCABLEUPSTREAM = 0x81
|
||||
IFT_DS0 = 0x51
|
||||
IFT_DS0BUNDLE = 0x52
|
||||
IFT_DS1FDL = 0xaa
|
||||
IFT_DS3 = 0x1e
|
||||
IFT_DTM = 0x8c
|
||||
IFT_DVBASILN = 0xac
|
||||
IFT_DVBASIOUT = 0xad
|
||||
IFT_DVBRCCDOWNSTREAM = 0x93
|
||||
IFT_DVBRCCMACLAYER = 0x92
|
||||
IFT_DVBRCCUPSTREAM = 0x94
|
||||
IFT_ENC = 0xf4
|
||||
IFT_EON = 0x19
|
||||
IFT_EPLRS = 0x57
|
||||
IFT_ESCON = 0x49
|
||||
IFT_ETHER = 0x6
|
||||
IFT_FAITH = 0xf2
|
||||
IFT_FAST = 0x7d
|
||||
IFT_FASTETHER = 0x3e
|
||||
IFT_FASTETHERFX = 0x45
|
||||
IFT_FDDI = 0xf
|
||||
IFT_FIBRECHANNEL = 0x38
|
||||
IFT_FRAMERELAYINTERCONNECT = 0x3a
|
||||
IFT_FRAMERELAYMPI = 0x5c
|
||||
IFT_FRDLCIENDPT = 0xc1
|
||||
IFT_FRELAY = 0x20
|
||||
IFT_FRELAYDCE = 0x2c
|
||||
IFT_FRF16MFRBUNDLE = 0xa3
|
||||
IFT_FRFORWARD = 0x9e
|
||||
IFT_G703AT2MB = 0x43
|
||||
IFT_G703AT64K = 0x42
|
||||
IFT_GIF = 0xf0
|
||||
IFT_GIGABITETHERNET = 0x75
|
||||
IFT_GR303IDT = 0xb2
|
||||
IFT_GR303RDT = 0xb1
|
||||
IFT_H323GATEKEEPER = 0xa4
|
||||
IFT_H323PROXY = 0xa5
|
||||
IFT_HDH1822 = 0x3
|
||||
IFT_HDLC = 0x76
|
||||
IFT_HDSL2 = 0xa8
|
||||
IFT_HIPERLAN2 = 0xb7
|
||||
IFT_HIPPI = 0x2f
|
||||
IFT_HIPPIINTERFACE = 0x39
|
||||
IFT_HOSTPAD = 0x5a
|
||||
IFT_HSSI = 0x2e
|
||||
IFT_HY = 0xe
|
||||
IFT_IBM370PARCHAN = 0x48
|
||||
IFT_IDSL = 0x9a
|
||||
IFT_IEEE80211 = 0x47
|
||||
IFT_IEEE80212 = 0x37
|
||||
IFT_IEEE8023ADLAG = 0xa1
|
||||
IFT_IFGSN = 0x91
|
||||
IFT_IMT = 0xbe
|
||||
IFT_INTERLEAVE = 0x7c
|
||||
IFT_IP = 0x7e
|
||||
IFT_IPFORWARD = 0x8e
|
||||
IFT_IPOVERATM = 0x72
|
||||
IFT_IPOVERCDLC = 0x6d
|
||||
IFT_IPOVERCLAW = 0x6e
|
||||
IFT_IPSWITCH = 0x4e
|
||||
IFT_IPXIP = 0xf9
|
||||
IFT_ISDN = 0x3f
|
||||
IFT_ISDNBASIC = 0x14
|
||||
IFT_ISDNPRIMARY = 0x15
|
||||
IFT_ISDNS = 0x4b
|
||||
IFT_ISDNU = 0x4c
|
||||
IFT_ISO88022LLC = 0x29
|
||||
IFT_ISO88023 = 0x7
|
||||
IFT_ISO88024 = 0x8
|
||||
IFT_ISO88025 = 0x9
|
||||
IFT_ISO88025CRFPINT = 0x62
|
||||
IFT_ISO88025DTR = 0x56
|
||||
IFT_ISO88025FIBER = 0x73
|
||||
IFT_ISO88026 = 0xa
|
||||
IFT_ISUP = 0xb3
|
||||
IFT_L3IPXVLAN = 0x89
|
||||
IFT_LAPB = 0x10
|
||||
IFT_LAPD = 0x4d
|
||||
IFT_LAPF = 0x77
|
||||
IFT_LOCALTALK = 0x2a
|
||||
IFT_LOOP = 0x18
|
||||
IFT_MEDIAMAILOVERIP = 0x8b
|
||||
IFT_MFSIGLINK = 0xa7
|
||||
IFT_MIOX25 = 0x26
|
||||
IFT_MODEM = 0x30
|
||||
IFT_MPC = 0x71
|
||||
IFT_MPLS = 0xa6
|
||||
IFT_MPLSTUNNEL = 0x96
|
||||
IFT_MSDSL = 0x8f
|
||||
IFT_MVL = 0xbf
|
||||
IFT_MYRINET = 0x63
|
||||
IFT_NFAS = 0xaf
|
||||
IFT_NSIP = 0x1b
|
||||
IFT_OPTICALCHANNEL = 0xc3
|
||||
IFT_OPTICALTRANSPORT = 0xc4
|
||||
IFT_OTHER = 0x1
|
||||
IFT_P10 = 0xc
|
||||
IFT_P80 = 0xd
|
||||
IFT_PARA = 0x22
|
||||
IFT_PFLOG = 0xf6
|
||||
IFT_PFSYNC = 0xf7
|
||||
IFT_PLC = 0xae
|
||||
IFT_POS = 0xab
|
||||
IFT_PPPMULTILINKBUNDLE = 0x6c
|
||||
IFT_PROPBWAP2MP = 0xb8
|
||||
IFT_PROPCNLS = 0x59
|
||||
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
|
||||
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
|
||||
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
|
||||
IFT_PROPMUX = 0x36
|
||||
IFT_PROPWIRELESSP2P = 0x9d
|
||||
IFT_PTPSERIAL = 0x16
|
||||
IFT_PVC = 0xf1
|
||||
IFT_QLLC = 0x44
|
||||
IFT_RADIOMAC = 0xbc
|
||||
IFT_RADSL = 0x5f
|
||||
IFT_REACHDSL = 0xc0
|
||||
IFT_RFC1483 = 0x9f
|
||||
IFT_RS232 = 0x21
|
||||
IFT_RSRB = 0x4f
|
||||
IFT_SDLC = 0x11
|
||||
IFT_SDSL = 0x60
|
||||
IFT_SHDSL = 0xa9
|
||||
IFT_SIP = 0x1f
|
||||
IFT_SLIP = 0x1c
|
||||
IFT_SMDSDXI = 0x2b
|
||||
IFT_SMDSICIP = 0x34
|
||||
IFT_SONET = 0x27
|
||||
IFT_SONETOVERHEADCHANNEL = 0xb9
|
||||
IFT_SONETPATH = 0x32
|
||||
IFT_SONETVT = 0x33
|
||||
IFT_SRP = 0x97
|
||||
IFT_SS7SIGLINK = 0x9c
|
||||
IFT_STACKTOSTACK = 0x6f
|
||||
IFT_STARLAN = 0xb
|
||||
IFT_STF = 0xd7
|
||||
IFT_T1 = 0x12
|
||||
IFT_TDLC = 0x74
|
||||
IFT_TERMPAD = 0x5b
|
||||
IFT_TR008 = 0xb0
|
||||
IFT_TRANSPHDLC = 0x7b
|
||||
IFT_TUNNEL = 0x83
|
||||
IFT_ULTRA = 0x1d
|
||||
IFT_USB = 0xa0
|
||||
IFT_V11 = 0x40
|
||||
IFT_V35 = 0x2d
|
||||
IFT_V36 = 0x41
|
||||
IFT_V37 = 0x78
|
||||
IFT_VDSL = 0x61
|
||||
IFT_VIRTUALIPADDRESS = 0x70
|
||||
IFT_VOICEEM = 0x64
|
||||
IFT_VOICEENCAP = 0x67
|
||||
IFT_VOICEFXO = 0x65
|
||||
IFT_VOICEFXS = 0x66
|
||||
IFT_VOICEOVERATM = 0x98
|
||||
IFT_VOICEOVERFRAMERELAY = 0x99
|
||||
IFT_VOICEOVERIP = 0x68
|
||||
IFT_X213 = 0x5d
|
||||
IFT_X25 = 0x5
|
||||
IFT_X25DDN = 0x4
|
||||
IFT_X25HUNTGROUP = 0x7a
|
||||
IFT_X25MLP = 0x79
|
||||
IFT_X25PLE = 0x28
|
||||
IFT_XETHER = 0x1a
|
||||
IPPROTO_MAXID = 0x34
|
||||
IPV6_FAITH = 0x1d
|
||||
IPV6_MIN_MEMBERSHIPS = 0x1f
|
||||
IP_FAITH = 0x16
|
||||
IP_MAX_SOURCE_FILTER = 0x400
|
||||
IP_MIN_MEMBERSHIPS = 0x1f
|
||||
MAP_NORESERVE = 0x40
|
||||
MAP_RENAME = 0x20
|
||||
NET_RT_MAXID = 0x6
|
||||
RTF_PRCLONING = 0x10000
|
||||
RTM_OLDADD = 0x9
|
||||
RTM_OLDDEL = 0xa
|
||||
RT_CACHING_CONTEXT = 0x1
|
||||
RT_NORTREF = 0x2
|
||||
SIOCADDRT = 0x8040720a
|
||||
SIOCALIFADDR = 0x8118691b
|
||||
SIOCDELRT = 0x8040720b
|
||||
SIOCDLIFADDR = 0x8118691d
|
||||
SIOCGLIFADDR = 0xc118691c
|
||||
SIOCGLIFPHYADDR = 0xc118694b
|
||||
SIOCSLIFPHYADDR = 0x8118694a
|
||||
)
|
||||
-226
@@ -1,226 +0,0 @@
|
||||
// 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 unix
|
||||
|
||||
const (
|
||||
IFT_1822 = 0x2
|
||||
IFT_A12MPPSWITCH = 0x82
|
||||
IFT_AAL2 = 0xbb
|
||||
IFT_AAL5 = 0x31
|
||||
IFT_ADSL = 0x5e
|
||||
IFT_AFLANE8023 = 0x3b
|
||||
IFT_AFLANE8025 = 0x3c
|
||||
IFT_ARAP = 0x58
|
||||
IFT_ARCNET = 0x23
|
||||
IFT_ARCNETPLUS = 0x24
|
||||
IFT_ASYNC = 0x54
|
||||
IFT_ATM = 0x25
|
||||
IFT_ATMDXI = 0x69
|
||||
IFT_ATMFUNI = 0x6a
|
||||
IFT_ATMIMA = 0x6b
|
||||
IFT_ATMLOGICAL = 0x50
|
||||
IFT_ATMRADIO = 0xbd
|
||||
IFT_ATMSUBINTERFACE = 0x86
|
||||
IFT_ATMVCIENDPT = 0xc2
|
||||
IFT_ATMVIRTUAL = 0x95
|
||||
IFT_BGPPOLICYACCOUNTING = 0xa2
|
||||
IFT_BSC = 0x53
|
||||
IFT_CCTEMUL = 0x3d
|
||||
IFT_CEPT = 0x13
|
||||
IFT_CES = 0x85
|
||||
IFT_CHANNEL = 0x46
|
||||
IFT_CNR = 0x55
|
||||
IFT_COFFEE = 0x84
|
||||
IFT_COMPOSITELINK = 0x9b
|
||||
IFT_DCN = 0x8d
|
||||
IFT_DIGITALPOWERLINE = 0x8a
|
||||
IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
|
||||
IFT_DLSW = 0x4a
|
||||
IFT_DOCSCABLEDOWNSTREAM = 0x80
|
||||
IFT_DOCSCABLEMACLAYER = 0x7f
|
||||
IFT_DOCSCABLEUPSTREAM = 0x81
|
||||
IFT_DS0 = 0x51
|
||||
IFT_DS0BUNDLE = 0x52
|
||||
IFT_DS1FDL = 0xaa
|
||||
IFT_DS3 = 0x1e
|
||||
IFT_DTM = 0x8c
|
||||
IFT_DVBASILN = 0xac
|
||||
IFT_DVBASIOUT = 0xad
|
||||
IFT_DVBRCCDOWNSTREAM = 0x93
|
||||
IFT_DVBRCCMACLAYER = 0x92
|
||||
IFT_DVBRCCUPSTREAM = 0x94
|
||||
IFT_ENC = 0xf4
|
||||
IFT_EON = 0x19
|
||||
IFT_EPLRS = 0x57
|
||||
IFT_ESCON = 0x49
|
||||
IFT_ETHER = 0x6
|
||||
IFT_FAST = 0x7d
|
||||
IFT_FASTETHER = 0x3e
|
||||
IFT_FASTETHERFX = 0x45
|
||||
IFT_FDDI = 0xf
|
||||
IFT_FIBRECHANNEL = 0x38
|
||||
IFT_FRAMERELAYINTERCONNECT = 0x3a
|
||||
IFT_FRAMERELAYMPI = 0x5c
|
||||
IFT_FRDLCIENDPT = 0xc1
|
||||
IFT_FRELAY = 0x20
|
||||
IFT_FRELAYDCE = 0x2c
|
||||
IFT_FRF16MFRBUNDLE = 0xa3
|
||||
IFT_FRFORWARD = 0x9e
|
||||
IFT_G703AT2MB = 0x43
|
||||
IFT_G703AT64K = 0x42
|
||||
IFT_GIF = 0xf0
|
||||
IFT_GIGABITETHERNET = 0x75
|
||||
IFT_GR303IDT = 0xb2
|
||||
IFT_GR303RDT = 0xb1
|
||||
IFT_H323GATEKEEPER = 0xa4
|
||||
IFT_H323PROXY = 0xa5
|
||||
IFT_HDH1822 = 0x3
|
||||
IFT_HDLC = 0x76
|
||||
IFT_HDSL2 = 0xa8
|
||||
IFT_HIPERLAN2 = 0xb7
|
||||
IFT_HIPPI = 0x2f
|
||||
IFT_HIPPIINTERFACE = 0x39
|
||||
IFT_HOSTPAD = 0x5a
|
||||
IFT_HSSI = 0x2e
|
||||
IFT_HY = 0xe
|
||||
IFT_IBM370PARCHAN = 0x48
|
||||
IFT_IDSL = 0x9a
|
||||
IFT_IEEE80211 = 0x47
|
||||
IFT_IEEE80212 = 0x37
|
||||
IFT_IEEE8023ADLAG = 0xa1
|
||||
IFT_IFGSN = 0x91
|
||||
IFT_IMT = 0xbe
|
||||
IFT_INTERLEAVE = 0x7c
|
||||
IFT_IP = 0x7e
|
||||
IFT_IPFORWARD = 0x8e
|
||||
IFT_IPOVERATM = 0x72
|
||||
IFT_IPOVERCDLC = 0x6d
|
||||
IFT_IPOVERCLAW = 0x6e
|
||||
IFT_IPSWITCH = 0x4e
|
||||
IFT_ISDN = 0x3f
|
||||
IFT_ISDNBASIC = 0x14
|
||||
IFT_ISDNPRIMARY = 0x15
|
||||
IFT_ISDNS = 0x4b
|
||||
IFT_ISDNU = 0x4c
|
||||
IFT_ISO88022LLC = 0x29
|
||||
IFT_ISO88023 = 0x7
|
||||
IFT_ISO88024 = 0x8
|
||||
IFT_ISO88025 = 0x9
|
||||
IFT_ISO88025CRFPINT = 0x62
|
||||
IFT_ISO88025DTR = 0x56
|
||||
IFT_ISO88025FIBER = 0x73
|
||||
IFT_ISO88026 = 0xa
|
||||
IFT_ISUP = 0xb3
|
||||
IFT_L3IPXVLAN = 0x89
|
||||
IFT_LAPB = 0x10
|
||||
IFT_LAPD = 0x4d
|
||||
IFT_LAPF = 0x77
|
||||
IFT_LOCALTALK = 0x2a
|
||||
IFT_LOOP = 0x18
|
||||
IFT_MEDIAMAILOVERIP = 0x8b
|
||||
IFT_MFSIGLINK = 0xa7
|
||||
IFT_MIOX25 = 0x26
|
||||
IFT_MODEM = 0x30
|
||||
IFT_MPC = 0x71
|
||||
IFT_MPLS = 0xa6
|
||||
IFT_MPLSTUNNEL = 0x96
|
||||
IFT_MSDSL = 0x8f
|
||||
IFT_MVL = 0xbf
|
||||
IFT_MYRINET = 0x63
|
||||
IFT_NFAS = 0xaf
|
||||
IFT_NSIP = 0x1b
|
||||
IFT_OPTICALCHANNEL = 0xc3
|
||||
IFT_OPTICALTRANSPORT = 0xc4
|
||||
IFT_OTHER = 0x1
|
||||
IFT_P10 = 0xc
|
||||
IFT_P80 = 0xd
|
||||
IFT_PARA = 0x22
|
||||
IFT_PFLOG = 0xf6
|
||||
IFT_PFSYNC = 0xf7
|
||||
IFT_PLC = 0xae
|
||||
IFT_POS = 0xab
|
||||
IFT_PPPMULTILINKBUNDLE = 0x6c
|
||||
IFT_PROPBWAP2MP = 0xb8
|
||||
IFT_PROPCNLS = 0x59
|
||||
IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
|
||||
IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
|
||||
IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
|
||||
IFT_PROPMUX = 0x36
|
||||
IFT_PROPWIRELESSP2P = 0x9d
|
||||
IFT_PTPSERIAL = 0x16
|
||||
IFT_PVC = 0xf1
|
||||
IFT_QLLC = 0x44
|
||||
IFT_RADIOMAC = 0xbc
|
||||
IFT_RADSL = 0x5f
|
||||
IFT_REACHDSL = 0xc0
|
||||
IFT_RFC1483 = 0x9f
|
||||
IFT_RS232 = 0x21
|
||||
IFT_RSRB = 0x4f
|
||||
IFT_SDLC = 0x11
|
||||
IFT_SDSL = 0x60
|
||||
IFT_SHDSL = 0xa9
|
||||
IFT_SIP = 0x1f
|
||||
IFT_SLIP = 0x1c
|
||||
IFT_SMDSDXI = 0x2b
|
||||
IFT_SMDSICIP = 0x34
|
||||
IFT_SONET = 0x27
|
||||
IFT_SONETOVERHEADCHANNEL = 0xb9
|
||||
IFT_SONETPATH = 0x32
|
||||
IFT_SONETVT = 0x33
|
||||
IFT_SRP = 0x97
|
||||
IFT_SS7SIGLINK = 0x9c
|
||||
IFT_STACKTOSTACK = 0x6f
|
||||
IFT_STARLAN = 0xb
|
||||
IFT_STF = 0xd7
|
||||
IFT_T1 = 0x12
|
||||
IFT_TDLC = 0x74
|
||||
IFT_TERMPAD = 0x5b
|
||||
IFT_TR008 = 0xb0
|
||||
IFT_TRANSPHDLC = 0x7b
|
||||
IFT_TUNNEL = 0x83
|
||||
IFT_ULTRA = 0x1d
|
||||
IFT_USB = 0xa0
|
||||
IFT_V11 = 0x40
|
||||
IFT_V35 = 0x2d
|
||||
IFT_V36 = 0x41
|
||||
IFT_V37 = 0x78
|
||||
IFT_VDSL = 0x61
|
||||
IFT_VIRTUALIPADDRESS = 0x70
|
||||
IFT_VOICEEM = 0x64
|
||||
IFT_VOICEENCAP = 0x67
|
||||
IFT_VOICEFXO = 0x65
|
||||
IFT_VOICEFXS = 0x66
|
||||
IFT_VOICEOVERATM = 0x98
|
||||
IFT_VOICEOVERFRAMERELAY = 0x99
|
||||
IFT_VOICEOVERIP = 0x68
|
||||
IFT_X213 = 0x5d
|
||||
IFT_X25 = 0x5
|
||||
IFT_X25DDN = 0x4
|
||||
IFT_X25HUNTGROUP = 0x7a
|
||||
IFT_X25MLP = 0x79
|
||||
IFT_X25PLE = 0x28
|
||||
IFT_XETHER = 0x1a
|
||||
|
||||
// missing constants on FreeBSD-11.1-RELEASE, copied from old values in ztypes_freebsd_arm.go
|
||||
IFF_SMART = 0x20
|
||||
IFT_FAITH = 0xf2
|
||||
IFT_IPXIP = 0xf9
|
||||
IPPROTO_MAXID = 0x34
|
||||
IPV6_FAITH = 0x1d
|
||||
IP_FAITH = 0x16
|
||||
MAP_NORESERVE = 0x40
|
||||
MAP_RENAME = 0x20
|
||||
NET_RT_MAXID = 0x6
|
||||
RTF_PRCLONING = 0x10000
|
||||
RTM_OLDADD = 0x9
|
||||
RTM_OLDDEL = 0xa
|
||||
SIOCADDRT = 0x8030720a
|
||||
SIOCALIFADDR = 0x8118691b
|
||||
SIOCDELRT = 0x8030720b
|
||||
SIOCDLIFADDR = 0x8118691d
|
||||
SIOCGLIFADDR = 0xc118691c
|
||||
SIOCGLIFPHYADDR = 0xc118694b
|
||||
SIOCSLIFPHYADDR = 0x8118694a
|
||||
)
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
|
||||
// them here for backwards compatibility.
|
||||
|
||||
package unix
|
||||
|
||||
const (
|
||||
DLT_HHDLC = 0x79
|
||||
IPV6_MIN_MEMBERSHIPS = 0x1f
|
||||
IP_MAX_SOURCE_FILTER = 0x400
|
||||
IP_MIN_MEMBERSHIPS = 0x1f
|
||||
RT_CACHING_CONTEXT = 0x1
|
||||
RT_NORTREF = 0x2
|
||||
)
|
||||
+9
-4
@@ -89,25 +89,30 @@ dragonfly_amd64)
|
||||
freebsd_386)
|
||||
mkerrors="$mkerrors -m32"
|
||||
mksyscall="go run mksyscall.go -l32"
|
||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
|
||||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
freebsd_amd64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
|
||||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
freebsd_arm)
|
||||
mkerrors="$mkerrors"
|
||||
mksyscall="go run mksyscall.go -l32 -arm"
|
||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
|
||||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||
# Let the type of C char be signed for making the bare syscall
|
||||
# API consistent across platforms.
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
freebsd_arm64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
|
||||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
freebsd_riscv64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
netbsd_386)
|
||||
|
||||
+8
-2
@@ -128,6 +128,7 @@ includes_FreeBSD='
|
||||
#include <sys/mount.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
@@ -202,6 +203,7 @@ struct ltchars {
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/error.h>
|
||||
@@ -295,6 +297,10 @@ struct ltchars {
|
||||
#define SOL_NETLINK 270
|
||||
#endif
|
||||
|
||||
#ifndef SOL_SMC
|
||||
#define SOL_SMC 286
|
||||
#endif
|
||||
|
||||
#ifdef SOL_BLUETOOTH
|
||||
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
|
||||
// but it is already in bluetooth_linux.go
|
||||
@@ -529,7 +535,7 @@ ccflags="$@"
|
||||
$2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ ||
|
||||
$2 ~ /^NS_GET_/ ||
|
||||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
||||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||
|
||||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|PIOD|TFD)_/ ||
|
||||
$2 ~ /^KEXEC_/ ||
|
||||
$2 ~ /^LINUX_REBOOT_CMD_/ ||
|
||||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
|
||||
@@ -553,6 +559,7 @@ ccflags="$@"
|
||||
$2 ~ /^CLONE_[A-Z_]+/ ||
|
||||
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
|
||||
$2 ~ /^(BPF|DLT)_/ ||
|
||||
$2 ~ /^AUDIT_/ ||
|
||||
$2 ~ /^(CLOCK|TIMER)_/ ||
|
||||
$2 ~ /^CAN_/ ||
|
||||
$2 ~ /^CAP_/ ||
|
||||
@@ -575,7 +582,6 @@ ccflags="$@"
|
||||
$2 ~ /^SEEK_/ ||
|
||||
$2 ~ /^SPLICE_/ ||
|
||||
$2 ~ /^SYNC_FILE_RANGE_/ ||
|
||||
$2 !~ /^AUDIT_RECORD_MAGIC/ &&
|
||||
$2 !~ /IOC_MAGIC/ &&
|
||||
$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ ||
|
||||
$2 ~ /^(VM|VMADDR)_/ ||
|
||||
|
||||
+2
-2
@@ -217,12 +217,12 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||
// Recvmsg not implemented on AIX
|
||||
return -1, -1, -1, ENOSYS
|
||||
}
|
||||
|
||||
func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||
// SendmsgN not implemented on AIX
|
||||
return -1, ENOSYS
|
||||
}
|
||||
|
||||
+23
-23
@@ -325,27 +325,26 @@ func GetsockoptString(fd, level, opt int) (string, error) {
|
||||
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
||||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
|
||||
func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||
var msg Msghdr
|
||||
msg.Name = (*byte)(unsafe.Pointer(rsa))
|
||||
msg.Namelen = uint32(SizeofSockaddrAny)
|
||||
var iov Iovec
|
||||
if len(p) > 0 {
|
||||
iov.Base = (*byte)(unsafe.Pointer(&p[0]))
|
||||
iov.SetLen(len(p))
|
||||
}
|
||||
var dummy byte
|
||||
if len(oob) > 0 {
|
||||
// receive at least one normal byte
|
||||
if len(p) == 0 {
|
||||
iov.Base = &dummy
|
||||
iov.SetLen(1)
|
||||
if emptyIovecs(iov) {
|
||||
var iova [1]Iovec
|
||||
iova[0].Base = &dummy
|
||||
iova[0].SetLen(1)
|
||||
iov = iova[:]
|
||||
}
|
||||
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
|
||||
msg.SetControllen(len(oob))
|
||||
}
|
||||
msg.Iov = &iov
|
||||
msg.Iovlen = 1
|
||||
if len(iov) > 0 {
|
||||
msg.Iov = &iov[0]
|
||||
msg.SetIovlen(len(iov))
|
||||
}
|
||||
if n, err = recvmsg(fd, &msg, flags); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -356,31 +355,32 @@ func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn
|
||||
|
||||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
|
||||
func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||
var msg Msghdr
|
||||
msg.Name = (*byte)(unsafe.Pointer(ptr))
|
||||
msg.Namelen = uint32(salen)
|
||||
var iov Iovec
|
||||
if len(p) > 0 {
|
||||
iov.Base = (*byte)(unsafe.Pointer(&p[0]))
|
||||
iov.SetLen(len(p))
|
||||
}
|
||||
var dummy byte
|
||||
var empty bool
|
||||
if len(oob) > 0 {
|
||||
// send at least one normal byte
|
||||
if len(p) == 0 {
|
||||
iov.Base = &dummy
|
||||
iov.SetLen(1)
|
||||
empty := emptyIovecs(iov)
|
||||
if empty {
|
||||
var iova [1]Iovec
|
||||
iova[0].Base = &dummy
|
||||
iova[0].SetLen(1)
|
||||
iov = iova[:]
|
||||
}
|
||||
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
|
||||
msg.SetControllen(len(oob))
|
||||
}
|
||||
msg.Iov = &iov
|
||||
msg.Iovlen = 1
|
||||
if len(iov) > 0 {
|
||||
msg.Iov = &iov[0]
|
||||
msg.SetIovlen(len(iov))
|
||||
}
|
||||
if n, err = sendmsg(fd, &msg, flags); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(oob) > 0 && len(p) == 0 {
|
||||
if len(oob) > 0 && empty {
|
||||
n = 0
|
||||
}
|
||||
return n, nil
|
||||
|
||||
+7
@@ -393,6 +393,13 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
|
||||
return x, err
|
||||
}
|
||||
|
||||
func GetsockoptTCPConnectionInfo(fd, level, opt int) (*TCPConnectionInfo, error) {
|
||||
var value TCPConnectionInfo
|
||||
vallen := _Socklen(SizeofTCPConnectionInfo)
|
||||
err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func SysctlKinfoProc(name string, args ...int) (*KinfoProc, error) {
|
||||
mib, err := sysctlmib(name, args...)
|
||||
if err != nil {
|
||||
|
||||
+35
-290
@@ -17,25 +17,12 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
SYS_FSTAT_FREEBSD12 = 551 // { int fstat(int fd, _Out_ struct stat *sb); }
|
||||
SYS_FSTATAT_FREEBSD12 = 552 // { int fstatat(int fd, _In_z_ char *path, \
|
||||
SYS_GETDIRENTRIES_FREEBSD12 = 554 // { ssize_t getdirentries(int fd, \
|
||||
SYS_STATFS_FREEBSD12 = 555 // { int statfs(_In_z_ char *path, \
|
||||
SYS_FSTATFS_FREEBSD12 = 556 // { int fstatfs(int fd, \
|
||||
SYS_GETFSSTAT_FREEBSD12 = 557 // { int getfsstat( \
|
||||
SYS_MKNODAT_FREEBSD12 = 559 // { int mknodat(int fd, _In_z_ char *path, \
|
||||
)
|
||||
|
||||
// See https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions.html.
|
||||
var (
|
||||
osreldateOnce sync.Once
|
||||
osreldate uint32
|
||||
)
|
||||
|
||||
// INO64_FIRST from /usr/src/lib/libc/sys/compat-ino64.h
|
||||
const _ino64First = 1200031
|
||||
|
||||
func supportsABI(ver uint32) bool {
|
||||
osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") })
|
||||
return osreldate >= ver
|
||||
@@ -159,38 +146,18 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
|
||||
|
||||
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||
var (
|
||||
_p0 unsafe.Pointer
|
||||
bufsize uintptr
|
||||
oldBuf []statfs_freebsd11_t
|
||||
needsConvert bool
|
||||
_p0 unsafe.Pointer
|
||||
bufsize uintptr
|
||||
)
|
||||
|
||||
if len(buf) > 0 {
|
||||
if supportsABI(_ino64First) {
|
||||
_p0 = unsafe.Pointer(&buf[0])
|
||||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
} else {
|
||||
n := len(buf)
|
||||
oldBuf = make([]statfs_freebsd11_t, n)
|
||||
_p0 = unsafe.Pointer(&oldBuf[0])
|
||||
bufsize = unsafe.Sizeof(statfs_freebsd11_t{}) * uintptr(n)
|
||||
needsConvert = true
|
||||
}
|
||||
_p0 = unsafe.Pointer(&buf[0])
|
||||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
||||
}
|
||||
var sysno uintptr = SYS_GETFSSTAT
|
||||
if supportsABI(_ino64First) {
|
||||
sysno = SYS_GETFSSTAT_FREEBSD12
|
||||
}
|
||||
r0, _, e1 := Syscall(sysno, uintptr(_p0), bufsize, uintptr(flags))
|
||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||
n = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
if e1 == 0 && needsConvert {
|
||||
for i := range oldBuf {
|
||||
buf[i].convertFrom(&oldBuf[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -245,87 +212,11 @@ func Uname(uname *Utsname) error {
|
||||
}
|
||||
|
||||
func Stat(path string, st *Stat_t) (err error) {
|
||||
var oldStat stat_freebsd11_t
|
||||
if supportsABI(_ino64First) {
|
||||
return fstatat_freebsd12(AT_FDCWD, path, st, 0)
|
||||
}
|
||||
err = stat(path, &oldStat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.convertFrom(&oldStat)
|
||||
return nil
|
||||
return Fstatat(AT_FDCWD, path, st, 0)
|
||||
}
|
||||
|
||||
func Lstat(path string, st *Stat_t) (err error) {
|
||||
var oldStat stat_freebsd11_t
|
||||
if supportsABI(_ino64First) {
|
||||
return fstatat_freebsd12(AT_FDCWD, path, st, AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
err = lstat(path, &oldStat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.convertFrom(&oldStat)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Fstat(fd int, st *Stat_t) (err error) {
|
||||
var oldStat stat_freebsd11_t
|
||||
if supportsABI(_ino64First) {
|
||||
return fstat_freebsd12(fd, st)
|
||||
}
|
||||
err = fstat(fd, &oldStat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.convertFrom(&oldStat)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Fstatat(fd int, path string, st *Stat_t, flags int) (err error) {
|
||||
var oldStat stat_freebsd11_t
|
||||
if supportsABI(_ino64First) {
|
||||
return fstatat_freebsd12(fd, path, st, flags)
|
||||
}
|
||||
err = fstatat(fd, path, &oldStat, flags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.convertFrom(&oldStat)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Statfs(path string, st *Statfs_t) (err error) {
|
||||
var oldStatfs statfs_freebsd11_t
|
||||
if supportsABI(_ino64First) {
|
||||
return statfs_freebsd12(path, st)
|
||||
}
|
||||
err = statfs(path, &oldStatfs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.convertFrom(&oldStatfs)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Fstatfs(fd int, st *Statfs_t) (err error) {
|
||||
var oldStatfs statfs_freebsd11_t
|
||||
if supportsABI(_ino64First) {
|
||||
return fstatfs_freebsd12(fd, st)
|
||||
}
|
||||
err = fstatfs(fd, &oldStatfs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.convertFrom(&oldStatfs)
|
||||
return nil
|
||||
return Fstatat(AT_FDCWD, path, st, AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
|
||||
func Getdents(fd int, buf []byte) (n int, err error) {
|
||||
@@ -333,162 +224,25 @@ func Getdents(fd int, buf []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||
if supportsABI(_ino64First) {
|
||||
if basep == nil || unsafe.Sizeof(*basep) == 8 {
|
||||
return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep)))
|
||||
}
|
||||
// The freebsd12 syscall needs a 64-bit base. On 32-bit machines
|
||||
// we can't just use the basep passed in. See #32498.
|
||||
var base uint64 = uint64(*basep)
|
||||
n, err = getdirentries_freebsd12(fd, buf, &base)
|
||||
*basep = uintptr(base)
|
||||
if base>>32 != 0 {
|
||||
// We can't stuff the base back into a uintptr, so any
|
||||
// future calls would be suspect. Generate an error.
|
||||
// EIO is allowed by getdirentries.
|
||||
err = EIO
|
||||
}
|
||||
return
|
||||
if basep == nil || unsafe.Sizeof(*basep) == 8 {
|
||||
return getdirentries(fd, buf, (*uint64)(unsafe.Pointer(basep)))
|
||||
}
|
||||
|
||||
// The old syscall entries are smaller than the new. Use 1/4 of the original
|
||||
// buffer size rounded up to DIRBLKSIZ (see /usr/src/lib/libc/sys/getdirentries.c).
|
||||
oldBufLen := roundup(len(buf)/4, _dirblksiz)
|
||||
oldBuf := make([]byte, oldBufLen)
|
||||
n, err = getdirentries(fd, oldBuf, basep)
|
||||
if err == nil && n > 0 {
|
||||
n = convertFromDirents11(buf, oldBuf[:n])
|
||||
// The syscall needs a 64-bit base. On 32-bit machines
|
||||
// we can't just use the basep passed in. See #32498.
|
||||
var base uint64 = uint64(*basep)
|
||||
n, err = getdirentries(fd, buf, &base)
|
||||
*basep = uintptr(base)
|
||||
if base>>32 != 0 {
|
||||
// We can't stuff the base back into a uintptr, so any
|
||||
// future calls would be suspect. Generate an error.
|
||||
// EIO is allowed by getdirentries.
|
||||
err = EIO
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Mknod(path string, mode uint32, dev uint64) (err error) {
|
||||
var oldDev int
|
||||
if supportsABI(_ino64First) {
|
||||
return mknodat_freebsd12(AT_FDCWD, path, mode, dev)
|
||||
}
|
||||
oldDev = int(dev)
|
||||
return mknod(path, mode, oldDev)
|
||||
}
|
||||
|
||||
func Mknodat(fd int, path string, mode uint32, dev uint64) (err error) {
|
||||
var oldDev int
|
||||
if supportsABI(_ino64First) {
|
||||
return mknodat_freebsd12(fd, path, mode, dev)
|
||||
}
|
||||
oldDev = int(dev)
|
||||
return mknodat(fd, path, mode, oldDev)
|
||||
}
|
||||
|
||||
// round x to the nearest multiple of y, larger or equal to x.
|
||||
//
|
||||
// from /usr/include/sys/param.h Macros for counting and rounding.
|
||||
// #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
|
||||
func roundup(x, y int) int {
|
||||
return ((x + y - 1) / y) * y
|
||||
}
|
||||
|
||||
func (s *Stat_t) convertFrom(old *stat_freebsd11_t) {
|
||||
*s = Stat_t{
|
||||
Dev: uint64(old.Dev),
|
||||
Ino: uint64(old.Ino),
|
||||
Nlink: uint64(old.Nlink),
|
||||
Mode: old.Mode,
|
||||
Uid: old.Uid,
|
||||
Gid: old.Gid,
|
||||
Rdev: uint64(old.Rdev),
|
||||
Atim: old.Atim,
|
||||
Mtim: old.Mtim,
|
||||
Ctim: old.Ctim,
|
||||
Btim: old.Btim,
|
||||
Size: old.Size,
|
||||
Blocks: old.Blocks,
|
||||
Blksize: old.Blksize,
|
||||
Flags: old.Flags,
|
||||
Gen: uint64(old.Gen),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Statfs_t) convertFrom(old *statfs_freebsd11_t) {
|
||||
*s = Statfs_t{
|
||||
Version: _statfsVersion,
|
||||
Type: old.Type,
|
||||
Flags: old.Flags,
|
||||
Bsize: old.Bsize,
|
||||
Iosize: old.Iosize,
|
||||
Blocks: old.Blocks,
|
||||
Bfree: old.Bfree,
|
||||
Bavail: old.Bavail,
|
||||
Files: old.Files,
|
||||
Ffree: old.Ffree,
|
||||
Syncwrites: old.Syncwrites,
|
||||
Asyncwrites: old.Asyncwrites,
|
||||
Syncreads: old.Syncreads,
|
||||
Asyncreads: old.Asyncreads,
|
||||
// Spare
|
||||
Namemax: old.Namemax,
|
||||
Owner: old.Owner,
|
||||
Fsid: old.Fsid,
|
||||
// Charspare
|
||||
// Fstypename
|
||||
// Mntfromname
|
||||
// Mntonname
|
||||
}
|
||||
|
||||
sl := old.Fstypename[:]
|
||||
n := clen(*(*[]byte)(unsafe.Pointer(&sl)))
|
||||
copy(s.Fstypename[:], old.Fstypename[:n])
|
||||
|
||||
sl = old.Mntfromname[:]
|
||||
n = clen(*(*[]byte)(unsafe.Pointer(&sl)))
|
||||
copy(s.Mntfromname[:], old.Mntfromname[:n])
|
||||
|
||||
sl = old.Mntonname[:]
|
||||
n = clen(*(*[]byte)(unsafe.Pointer(&sl)))
|
||||
copy(s.Mntonname[:], old.Mntonname[:n])
|
||||
}
|
||||
|
||||
func convertFromDirents11(buf []byte, old []byte) int {
|
||||
const (
|
||||
fixedSize = int(unsafe.Offsetof(Dirent{}.Name))
|
||||
oldFixedSize = int(unsafe.Offsetof(dirent_freebsd11{}.Name))
|
||||
)
|
||||
|
||||
dstPos := 0
|
||||
srcPos := 0
|
||||
for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) {
|
||||
var dstDirent Dirent
|
||||
var srcDirent dirent_freebsd11
|
||||
|
||||
// If multiple direntries are written, sometimes when we reach the final one,
|
||||
// we may have cap of old less than size of dirent_freebsd11.
|
||||
copy((*[unsafe.Sizeof(srcDirent)]byte)(unsafe.Pointer(&srcDirent))[:], old[srcPos:])
|
||||
|
||||
reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8)
|
||||
if dstPos+reclen > len(buf) {
|
||||
break
|
||||
}
|
||||
|
||||
dstDirent.Fileno = uint64(srcDirent.Fileno)
|
||||
dstDirent.Off = 0
|
||||
dstDirent.Reclen = uint16(reclen)
|
||||
dstDirent.Type = srcDirent.Type
|
||||
dstDirent.Pad0 = 0
|
||||
dstDirent.Namlen = uint16(srcDirent.Namlen)
|
||||
dstDirent.Pad1 = 0
|
||||
|
||||
copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen])
|
||||
copy(buf[dstPos:], (*[unsafe.Sizeof(dstDirent)]byte)(unsafe.Pointer(&dstDirent))[:])
|
||||
padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen]
|
||||
for i := range padding {
|
||||
padding[i] = 0
|
||||
}
|
||||
|
||||
dstPos += int(dstDirent.Reclen)
|
||||
srcPos += int(srcDirent.Reclen)
|
||||
}
|
||||
|
||||
return dstPos
|
||||
return Mknodat(AT_FDCWD, path, mode, dev)
|
||||
}
|
||||
|
||||
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
|
||||
@@ -501,31 +255,31 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
//sys ptrace(request int, pid int, addr uintptr, data int) (err error)
|
||||
|
||||
func PtraceAttach(pid int) (err error) {
|
||||
return ptrace(PTRACE_ATTACH, pid, 0, 0)
|
||||
return ptrace(PT_ATTACH, pid, 0, 0)
|
||||
}
|
||||
|
||||
func PtraceCont(pid int, signal int) (err error) {
|
||||
return ptrace(PTRACE_CONT, pid, 1, signal)
|
||||
return ptrace(PT_CONTINUE, pid, 1, signal)
|
||||
}
|
||||
|
||||
func PtraceDetach(pid int) (err error) {
|
||||
return ptrace(PTRACE_DETACH, pid, 1, 0)
|
||||
return ptrace(PT_DETACH, pid, 1, 0)
|
||||
}
|
||||
|
||||
func PtraceGetFpRegs(pid int, fpregsout *FpReg) (err error) {
|
||||
return ptrace(PTRACE_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0)
|
||||
return ptrace(PT_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0)
|
||||
}
|
||||
|
||||
func PtraceGetRegs(pid int, regsout *Reg) (err error) {
|
||||
return ptrace(PTRACE_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0)
|
||||
return ptrace(PT_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0)
|
||||
}
|
||||
|
||||
func PtraceLwpEvents(pid int, enable int) (err error) {
|
||||
return ptrace(PTRACE_LWPEVENTS, pid, 0, enable)
|
||||
return ptrace(PT_LWP_EVENTS, pid, 0, enable)
|
||||
}
|
||||
|
||||
func PtraceLwpInfo(pid int, info uintptr) (err error) {
|
||||
return ptrace(PTRACE_LWPINFO, pid, info, int(unsafe.Sizeof(PtraceLwpInfoStruct{})))
|
||||
return ptrace(PT_LWPINFO, pid, info, int(unsafe.Sizeof(PtraceLwpInfoStruct{})))
|
||||
}
|
||||
|
||||
func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
|
||||
@@ -545,11 +299,11 @@ func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
|
||||
}
|
||||
|
||||
func PtraceSetRegs(pid int, regs *Reg) (err error) {
|
||||
return ptrace(PTRACE_SETREGS, pid, uintptr(unsafe.Pointer(regs)), 0)
|
||||
return ptrace(PT_SETREGS, pid, uintptr(unsafe.Pointer(regs)), 0)
|
||||
}
|
||||
|
||||
func PtraceSingleStep(pid int) (err error) {
|
||||
return ptrace(PTRACE_SINGLESTEP, pid, 1, 0)
|
||||
return ptrace(PT_STEP, pid, 1, 0)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -591,16 +345,12 @@ func PtraceSingleStep(pid int) (err error) {
|
||||
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
|
||||
//sys Flock(fd int, how int) (err error)
|
||||
//sys Fpathconf(fd int, name int) (val int, err error)
|
||||
//sys fstat(fd int, stat *stat_freebsd11_t) (err error)
|
||||
//sys fstat_freebsd12(fd int, stat *Stat_t) (err error)
|
||||
//sys fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error)
|
||||
//sys fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error)
|
||||
//sys fstatfs(fd int, stat *statfs_freebsd11_t) (err error)
|
||||
//sys fstatfs_freebsd12(fd int, stat *Statfs_t) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
|
||||
//sys Fstatfs(fd int, stat *Statfs_t) (err error)
|
||||
//sys Fsync(fd int) (err error)
|
||||
//sys Ftruncate(fd int, length int64) (err error)
|
||||
//sys getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
|
||||
//sys getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error)
|
||||
//sys getdirentries(fd int, buf []byte, basep *uint64) (n int, err error)
|
||||
//sys Getdtablesize() (size int)
|
||||
//sysnb Getegid() (egid int)
|
||||
//sysnb Geteuid() (uid int)
|
||||
@@ -622,13 +372,10 @@ func PtraceSingleStep(pid int) (err error) {
|
||||
//sys Link(path string, link string) (err error)
|
||||
//sys Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error)
|
||||
//sys Listen(s int, backlog int) (err error)
|
||||
//sys lstat(path string, stat *stat_freebsd11_t) (err error)
|
||||
//sys Mkdir(path string, mode uint32) (err error)
|
||||
//sys Mkdirat(dirfd int, path string, mode uint32) (err error)
|
||||
//sys Mkfifo(path string, mode uint32) (err error)
|
||||
//sys mknod(path string, mode uint32, dev int) (err error)
|
||||
//sys mknodat(fd int, path string, mode uint32, dev int) (err error)
|
||||
//sys mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error)
|
||||
//sys Mknodat(fd int, path string, mode uint32, dev uint64) (err error)
|
||||
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
|
||||
//sys Open(path string, mode int, perm uint32) (fd int, err error)
|
||||
//sys Openat(fdat int, path string, mode int, perm uint32) (fd int, err error)
|
||||
@@ -658,9 +405,7 @@ func PtraceSingleStep(pid int) (err error) {
|
||||
//sysnb Setsid() (pid int, err error)
|
||||
//sysnb Settimeofday(tp *Timeval) (err error)
|
||||
//sysnb Setuid(uid int) (err error)
|
||||
//sys stat(path string, stat *stat_freebsd11_t) (err error)
|
||||
//sys statfs(path string, stat *statfs_freebsd11_t) (err error)
|
||||
//sys statfs_freebsd12(path string, stat *Statfs_t) (err error)
|
||||
//sys Statfs(path string, stat *Statfs_t) (err error)
|
||||
//sys Symlink(path string, link string) (err error)
|
||||
//sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error)
|
||||
//sys Sync() (err error)
|
||||
|
||||
+2
-2
@@ -57,11 +57,11 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
||||
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||
return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||
}
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
||||
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
||||
+2
-2
@@ -57,11 +57,11 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
||||
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||
return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||
}
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
||||
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
||||
+1
-1
@@ -58,6 +58,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
||||
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
||||
+1
-1
@@ -58,6 +58,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
||||
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
// Copyright 2022 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 riscv64 && freebsd
|
||||
// +build riscv64,freebsd
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: sec, Nsec: nsec}
|
||||
}
|
||||
|
||||
func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: sec, Usec: usec}
|
||||
}
|
||||
|
||||
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
||||
k.Ident = uint64(fd)
|
||||
k.Filter = int16(mode)
|
||||
k.Flags = uint16(flags)
|
||||
}
|
||||
|
||||
func (iov *Iovec) SetLen(length int) {
|
||||
iov.Len = uint64(length)
|
||||
}
|
||||
|
||||
func (msghdr *Msghdr) SetControllen(length int) {
|
||||
msghdr.Controllen = uint32(length)
|
||||
}
|
||||
|
||||
func (msghdr *Msghdr) SetIovlen(length int) {
|
||||
msghdr.Iovlen = int32(length)
|
||||
}
|
||||
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint32(length)
|
||||
}
|
||||
|
||||
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
|
||||
var writtenOut uint64 = 0
|
||||
_, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0, 0)
|
||||
|
||||
written = int(writtenOut)
|
||||
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||
return int(ioDesc.Len), err
|
||||
}
|
||||
+2
-3
@@ -20,10 +20,9 @@ func bytes2iovec(bs [][]byte) []Iovec {
|
||||
for i, b := range bs {
|
||||
iovecs[i].SetLen(len(b))
|
||||
if len(b) > 0 {
|
||||
// somehow Iovec.Base on illumos is (*int8), not (*byte)
|
||||
iovecs[i].Base = (*int8)(unsafe.Pointer(&b[0]))
|
||||
iovecs[i].Base = &b[0]
|
||||
} else {
|
||||
iovecs[i].Base = (*int8)(unsafe.Pointer(&_zero))
|
||||
iovecs[i].Base = (*byte)(unsafe.Pointer(&_zero))
|
||||
}
|
||||
}
|
||||
return iovecs
|
||||
|
||||
+22
-23
@@ -1499,18 +1499,13 @@ func KeyctlRestrictKeyring(ringid int, keyType string, restriction string) error
|
||||
//sys keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) = SYS_KEYCTL
|
||||
//sys keyctlRestrictKeyring(cmd int, arg2 int) (err error) = SYS_KEYCTL
|
||||
|
||||
func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||
var msg Msghdr
|
||||
msg.Name = (*byte)(unsafe.Pointer(rsa))
|
||||
msg.Namelen = uint32(SizeofSockaddrAny)
|
||||
var iov Iovec
|
||||
if len(p) > 0 {
|
||||
iov.Base = &p[0]
|
||||
iov.SetLen(len(p))
|
||||
}
|
||||
var dummy byte
|
||||
if len(oob) > 0 {
|
||||
if len(p) == 0 {
|
||||
if emptyIovecs(iov) {
|
||||
var sockType int
|
||||
sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
|
||||
if err != nil {
|
||||
@@ -1518,15 +1513,19 @@ func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn
|
||||
}
|
||||
// receive at least one normal byte
|
||||
if sockType != SOCK_DGRAM {
|
||||
iov.Base = &dummy
|
||||
iov.SetLen(1)
|
||||
var iova [1]Iovec
|
||||
iova[0].Base = &dummy
|
||||
iova[0].SetLen(1)
|
||||
iov = iova[:]
|
||||
}
|
||||
}
|
||||
msg.Control = &oob[0]
|
||||
msg.SetControllen(len(oob))
|
||||
}
|
||||
msg.Iov = &iov
|
||||
msg.Iovlen = 1
|
||||
if len(iov) > 0 {
|
||||
msg.Iov = &iov[0]
|
||||
msg.SetIovlen(len(iov))
|
||||
}
|
||||
if n, err = recvmsg(fd, &msg, flags); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -1535,18 +1534,15 @@ func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn
|
||||
return
|
||||
}
|
||||
|
||||
func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||
var msg Msghdr
|
||||
msg.Name = (*byte)(ptr)
|
||||
msg.Namelen = uint32(salen)
|
||||
var iov Iovec
|
||||
if len(p) > 0 {
|
||||
iov.Base = &p[0]
|
||||
iov.SetLen(len(p))
|
||||
}
|
||||
var dummy byte
|
||||
var empty bool
|
||||
if len(oob) > 0 {
|
||||
if len(p) == 0 {
|
||||
empty := emptyIovecs(iov)
|
||||
if empty {
|
||||
var sockType int
|
||||
sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
|
||||
if err != nil {
|
||||
@@ -1554,19 +1550,22 @@ func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags i
|
||||
}
|
||||
// send at least one normal byte
|
||||
if sockType != SOCK_DGRAM {
|
||||
iov.Base = &dummy
|
||||
iov.SetLen(1)
|
||||
var iova [1]Iovec
|
||||
iova[0].Base = &dummy
|
||||
iova[0].SetLen(1)
|
||||
}
|
||||
}
|
||||
msg.Control = &oob[0]
|
||||
msg.SetControllen(len(oob))
|
||||
}
|
||||
msg.Iov = &iov
|
||||
msg.Iovlen = 1
|
||||
if len(iov) > 0 {
|
||||
msg.Iov = &iov[0]
|
||||
msg.SetIovlen(len(iov))
|
||||
}
|
||||
if n, err = sendmsg(fd, &msg, flags); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(oob) > 0 && len(p) == 0 {
|
||||
if len(oob) > 0 && empty {
|
||||
n = 0
|
||||
}
|
||||
return n, nil
|
||||
|
||||
+37
-2
@@ -12,8 +12,6 @@ import "unsafe"
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
|
||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||
//sys Ftruncate(fd int, length int64) (err error)
|
||||
//sysnb Getegid() (egid int)
|
||||
@@ -43,6 +41,43 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
|
||||
//sys Shutdown(fd int, how int) (err error)
|
||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||
|
||||
func timespecFromStatxTimestamp(x StatxTimestamp) Timespec {
|
||||
return Timespec{
|
||||
Sec: x.Sec,
|
||||
Nsec: int64(x.Nsec),
|
||||
}
|
||||
}
|
||||
|
||||
func Fstatat(fd int, path string, stat *Stat_t, flags int) error {
|
||||
var r Statx_t
|
||||
// Do it the glibc way, add AT_NO_AUTOMOUNT.
|
||||
if err := Statx(fd, path, AT_NO_AUTOMOUNT|flags, STATX_BASIC_STATS, &r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stat.Dev = Mkdev(r.Dev_major, r.Dev_minor)
|
||||
stat.Ino = r.Ino
|
||||
stat.Mode = uint32(r.Mode)
|
||||
stat.Nlink = r.Nlink
|
||||
stat.Uid = r.Uid
|
||||
stat.Gid = r.Gid
|
||||
stat.Rdev = Mkdev(r.Rdev_major, r.Rdev_minor)
|
||||
// hope we don't get to process files so large to overflow these size
|
||||
// fields...
|
||||
stat.Size = int64(r.Size)
|
||||
stat.Blksize = int32(r.Blksize)
|
||||
stat.Blocks = int64(r.Blocks)
|
||||
stat.Atim = timespecFromStatxTimestamp(r.Atime)
|
||||
stat.Mtim = timespecFromStatxTimestamp(r.Mtime)
|
||||
stat.Ctim = timespecFromStatxTimestamp(r.Ctime)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Fstat(fd int, stat *Stat_t) (err error) {
|
||||
return Fstatat(fd, "", stat, AT_EMPTY_PATH)
|
||||
}
|
||||
|
||||
func Stat(path string, stat *Stat_t) (err error) {
|
||||
return Fstatat(AT_FDCWD, path, stat, 0)
|
||||
}
|
||||
|
||||
+1
@@ -22,6 +22,7 @@ import "unsafe"
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sys Listen(s int, n int) (err error)
|
||||
//sys MemfdSecret(flags int) (fd int, err error)
|
||||
//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
|
||||
//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
|
||||
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
|
||||
|
||||
+4
@@ -26,6 +26,10 @@ func (msghdr *Msghdr) SetControllen(length int) {
|
||||
msghdr.Controllen = uint32(length)
|
||||
}
|
||||
|
||||
func (msghdr *Msghdr) SetIovlen(length int) {
|
||||
msghdr.Iovlen = uint32(length)
|
||||
}
|
||||
|
||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
cmsg.Len = uint32(length)
|
||||
}
|
||||
|
||||
+26
-25
@@ -451,26 +451,25 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
|
||||
|
||||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
|
||||
|
||||
func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||
var msg Msghdr
|
||||
msg.Name = (*byte)(unsafe.Pointer(rsa))
|
||||
msg.Namelen = uint32(SizeofSockaddrAny)
|
||||
var iov Iovec
|
||||
if len(p) > 0 {
|
||||
iov.Base = (*int8)(unsafe.Pointer(&p[0]))
|
||||
iov.SetLen(len(p))
|
||||
}
|
||||
var dummy int8
|
||||
var dummy byte
|
||||
if len(oob) > 0 {
|
||||
// receive at least one normal byte
|
||||
if len(p) == 0 {
|
||||
iov.Base = &dummy
|
||||
iov.SetLen(1)
|
||||
if emptyIovecs(iov) {
|
||||
var iova [1]Iovec
|
||||
iova[0].Base = &dummy
|
||||
iova[0].SetLen(1)
|
||||
iov = iova[:]
|
||||
}
|
||||
msg.Accrightslen = int32(len(oob))
|
||||
}
|
||||
msg.Iov = &iov
|
||||
msg.Iovlen = 1
|
||||
if len(iov) > 0 {
|
||||
msg.Iov = &iov[0]
|
||||
msg.SetIovlen(len(iov))
|
||||
}
|
||||
if n, err = recvmsg(fd, &msg, flags); n == -1 {
|
||||
return
|
||||
}
|
||||
@@ -480,30 +479,31 @@ func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn
|
||||
|
||||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
|
||||
|
||||
func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||
var msg Msghdr
|
||||
msg.Name = (*byte)(unsafe.Pointer(ptr))
|
||||
msg.Namelen = uint32(salen)
|
||||
var iov Iovec
|
||||
if len(p) > 0 {
|
||||
iov.Base = (*int8)(unsafe.Pointer(&p[0]))
|
||||
iov.SetLen(len(p))
|
||||
}
|
||||
var dummy int8
|
||||
var dummy byte
|
||||
var empty bool
|
||||
if len(oob) > 0 {
|
||||
// send at least one normal byte
|
||||
if len(p) == 0 {
|
||||
iov.Base = &dummy
|
||||
iov.SetLen(1)
|
||||
empty = emptyIovecs(iov)
|
||||
if empty {
|
||||
var iova [1]Iovec
|
||||
iova[0].Base = &dummy
|
||||
iova[0].SetLen(1)
|
||||
iov = iova[:]
|
||||
}
|
||||
msg.Accrightslen = int32(len(oob))
|
||||
}
|
||||
msg.Iov = &iov
|
||||
msg.Iovlen = 1
|
||||
if len(iov) > 0 {
|
||||
msg.Iov = &iov[0]
|
||||
msg.SetIovlen(len(iov))
|
||||
}
|
||||
if n, err = sendmsg(fd, &msg, flags); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(oob) > 0 && len(p) == 0 {
|
||||
if len(oob) > 0 && empty {
|
||||
n = 0
|
||||
}
|
||||
return n, nil
|
||||
@@ -618,6 +618,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
//sys Getpriority(which int, who int) (n int, err error)
|
||||
//sysnb Getrlimit(which int, lim *Rlimit) (err error)
|
||||
//sysnb Getrusage(who int, rusage *Rusage) (err error)
|
||||
//sysnb Getsid(pid int) (sid int, err error)
|
||||
//sysnb Gettimeofday(tv *Timeval) (err error)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sys Kill(pid int, signum syscall.Signal) (err error)
|
||||
|
||||
+72
-2
@@ -338,8 +338,13 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
|
||||
}
|
||||
|
||||
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
|
||||
var iov [1]Iovec
|
||||
if len(p) > 0 {
|
||||
iov[0].Base = &p[0]
|
||||
iov[0].SetLen(len(p))
|
||||
}
|
||||
var rsa RawSockaddrAny
|
||||
n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
|
||||
n, oobn, recvflags, err = recvmsgRaw(fd, iov[:], oob, flags, &rsa)
|
||||
// source address is only specified if the socket is unconnected
|
||||
if rsa.Addr.Family != AF_UNSPEC {
|
||||
from, err = anyToSockaddr(fd, &rsa)
|
||||
@@ -347,12 +352,42 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
|
||||
return
|
||||
}
|
||||
|
||||
// RecvmsgBuffers receives a message from a socket using the recvmsg
|
||||
// system call. The flags are passed to recvmsg. Any non-control data
|
||||
// read is scattered into the buffers slices. The results are:
|
||||
// - n is the number of non-control data read into bufs
|
||||
// - oobn is the number of control data read into oob; this may be interpreted using [ParseSocketControlMessage]
|
||||
// - recvflags is flags returned by recvmsg
|
||||
// - from is the address of the sender
|
||||
func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
|
||||
iov := make([]Iovec, len(buffers))
|
||||
for i := range buffers {
|
||||
if len(buffers[i]) > 0 {
|
||||
iov[i].Base = &buffers[i][0]
|
||||
iov[i].SetLen(len(buffers[i]))
|
||||
} else {
|
||||
iov[i].Base = (*byte)(unsafe.Pointer(&_zero))
|
||||
}
|
||||
}
|
||||
var rsa RawSockaddrAny
|
||||
n, oobn, recvflags, err = recvmsgRaw(fd, iov, oob, flags, &rsa)
|
||||
if err == nil && rsa.Addr.Family != AF_UNSPEC {
|
||||
from, err = anyToSockaddr(fd, &rsa)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
|
||||
_, err = SendmsgN(fd, p, oob, to, flags)
|
||||
return
|
||||
}
|
||||
|
||||
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
|
||||
var iov [1]Iovec
|
||||
if len(p) > 0 {
|
||||
iov[0].Base = &p[0]
|
||||
iov[0].SetLen(len(p))
|
||||
}
|
||||
var ptr unsafe.Pointer
|
||||
var salen _Socklen
|
||||
if to != nil {
|
||||
@@ -361,7 +396,32 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return sendmsgN(fd, p, oob, ptr, salen, flags)
|
||||
return sendmsgN(fd, iov[:], oob, ptr, salen, flags)
|
||||
}
|
||||
|
||||
// SendmsgBuffers sends a message on a socket to an address using the sendmsg
|
||||
// system call. The flags are passed to sendmsg. Any non-control data written
|
||||
// is gathered from buffers. The function returns the number of bytes written
|
||||
// to the socket.
|
||||
func SendmsgBuffers(fd int, buffers [][]byte, oob []byte, to Sockaddr, flags int) (n int, err error) {
|
||||
iov := make([]Iovec, len(buffers))
|
||||
for i := range buffers {
|
||||
if len(buffers[i]) > 0 {
|
||||
iov[i].Base = &buffers[i][0]
|
||||
iov[i].SetLen(len(buffers[i]))
|
||||
} else {
|
||||
iov[i].Base = (*byte)(unsafe.Pointer(&_zero))
|
||||
}
|
||||
}
|
||||
var ptr unsafe.Pointer
|
||||
var salen _Socklen
|
||||
if to != nil {
|
||||
ptr, salen, err = to.sockaddr()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return sendmsgN(fd, iov, oob, ptr, salen, flags)
|
||||
}
|
||||
|
||||
func Send(s int, buf []byte, flags int) (err error) {
|
||||
@@ -484,3 +544,13 @@ func Lutimes(path string, tv []Timeval) error {
|
||||
}
|
||||
return UtimesNanoAt(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
|
||||
// emptyIovec reports whether there are no bytes in the slice of Iovec.
|
||||
func emptyIovecs(iov []Iovec) bool {
|
||||
for i := range iov {
|
||||
if iov[i].Len > 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
+102
-7
@@ -151,6 +151,7 @@ const (
|
||||
BIOCSETF = 0x80084267
|
||||
BIOCSETFNR = 0x80084282
|
||||
BIOCSETIF = 0x8020426c
|
||||
BIOCSETVLANPCP = 0x80044285
|
||||
BIOCSETWF = 0x8008427b
|
||||
BIOCSETZBUF = 0x800c4281
|
||||
BIOCSHDRCMPLT = 0x80044275
|
||||
@@ -447,7 +448,7 @@ const (
|
||||
DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1
|
||||
DLT_INFINIBAND = 0xf7
|
||||
DLT_IPFILTER = 0x74
|
||||
DLT_IPMB = 0xc7
|
||||
DLT_IPMB_KONTRON = 0xc7
|
||||
DLT_IPMB_LINUX = 0xd1
|
||||
DLT_IPMI_HPM_2 = 0x104
|
||||
DLT_IPNET = 0xe2
|
||||
@@ -487,10 +488,11 @@ const (
|
||||
DLT_LINUX_LAPD = 0xb1
|
||||
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
|
||||
DLT_LINUX_SLL = 0x71
|
||||
DLT_LINUX_SLL2 = 0x114
|
||||
DLT_LOOP = 0x6c
|
||||
DLT_LORATAP = 0x10e
|
||||
DLT_LTALK = 0x72
|
||||
DLT_MATCHING_MAX = 0x113
|
||||
DLT_MATCHING_MAX = 0x114
|
||||
DLT_MATCHING_MIN = 0x68
|
||||
DLT_MFR = 0xb6
|
||||
DLT_MOST = 0xd3
|
||||
@@ -734,6 +736,7 @@ const (
|
||||
IPPROTO_CMTP = 0x26
|
||||
IPPROTO_CPHB = 0x49
|
||||
IPPROTO_CPNX = 0x48
|
||||
IPPROTO_DCCP = 0x21
|
||||
IPPROTO_DDP = 0x25
|
||||
IPPROTO_DGP = 0x56
|
||||
IPPROTO_DIVERT = 0x102
|
||||
@@ -814,7 +817,6 @@ const (
|
||||
IPPROTO_SCTP = 0x84
|
||||
IPPROTO_SDRP = 0x2a
|
||||
IPPROTO_SEND = 0x103
|
||||
IPPROTO_SEP = 0x21
|
||||
IPPROTO_SHIM6 = 0x8c
|
||||
IPPROTO_SKIP = 0x39
|
||||
IPPROTO_SPACER = 0x7fff
|
||||
@@ -911,6 +913,7 @@ const (
|
||||
IPV6_V6ONLY = 0x1b
|
||||
IPV6_VERSION = 0x60
|
||||
IPV6_VERSION_MASK = 0xf0
|
||||
IPV6_VLAN_PCP = 0x4b
|
||||
IP_ADD_MEMBERSHIP = 0xc
|
||||
IP_ADD_SOURCE_MEMBERSHIP = 0x46
|
||||
IP_BINDANY = 0x18
|
||||
@@ -989,8 +992,12 @@ const (
|
||||
IP_TOS = 0x3
|
||||
IP_TTL = 0x4
|
||||
IP_UNBLOCK_SOURCE = 0x49
|
||||
IP_VLAN_PCP = 0x4b
|
||||
ISIG = 0x80
|
||||
ISTRIP = 0x20
|
||||
ITIMER_PROF = 0x2
|
||||
ITIMER_REAL = 0x0
|
||||
ITIMER_VIRTUAL = 0x1
|
||||
IXANY = 0x800
|
||||
IXOFF = 0x400
|
||||
IXON = 0x200
|
||||
@@ -1000,7 +1007,6 @@ const (
|
||||
KERN_VERSION = 0x4
|
||||
LOCAL_CONNWAIT = 0x4
|
||||
LOCAL_CREDS = 0x2
|
||||
LOCAL_CREDS_PERSISTENT = 0x3
|
||||
LOCAL_PEERCRED = 0x1
|
||||
LOCAL_VENDOR = 0x80000000
|
||||
LOCK_EX = 0x2
|
||||
@@ -1179,6 +1185,8 @@ const (
|
||||
O_NONBLOCK = 0x4
|
||||
O_RDONLY = 0x0
|
||||
O_RDWR = 0x2
|
||||
O_RESOLVE_BENEATH = 0x800000
|
||||
O_SEARCH = 0x40000
|
||||
O_SHLOCK = 0x10
|
||||
O_SYNC = 0x80
|
||||
O_TRUNC = 0x400
|
||||
@@ -1189,6 +1197,10 @@ const (
|
||||
PARMRK = 0x8
|
||||
PARODD = 0x2000
|
||||
PENDIN = 0x20000000
|
||||
PIOD_READ_D = 0x1
|
||||
PIOD_READ_I = 0x3
|
||||
PIOD_WRITE_D = 0x2
|
||||
PIOD_WRITE_I = 0x4
|
||||
PRIO_PGRP = 0x1
|
||||
PRIO_PROCESS = 0x0
|
||||
PRIO_USER = 0x2
|
||||
@@ -1196,6 +1208,60 @@ const (
|
||||
PROT_NONE = 0x0
|
||||
PROT_READ = 0x1
|
||||
PROT_WRITE = 0x2
|
||||
PTRACE_DEFAULT = 0x1
|
||||
PTRACE_EXEC = 0x1
|
||||
PTRACE_FORK = 0x8
|
||||
PTRACE_LWP = 0x10
|
||||
PTRACE_SCE = 0x2
|
||||
PTRACE_SCX = 0x4
|
||||
PTRACE_SYSCALL = 0x6
|
||||
PTRACE_VFORK = 0x20
|
||||
PT_ATTACH = 0xa
|
||||
PT_CLEARSTEP = 0x10
|
||||
PT_CONTINUE = 0x7
|
||||
PT_DETACH = 0xb
|
||||
PT_FIRSTMACH = 0x40
|
||||
PT_FOLLOW_FORK = 0x17
|
||||
PT_GETDBREGS = 0x25
|
||||
PT_GETFPREGS = 0x23
|
||||
PT_GETFSBASE = 0x47
|
||||
PT_GETGSBASE = 0x49
|
||||
PT_GETLWPLIST = 0xf
|
||||
PT_GETNUMLWPS = 0xe
|
||||
PT_GETREGS = 0x21
|
||||
PT_GETXMMREGS = 0x40
|
||||
PT_GETXSTATE = 0x45
|
||||
PT_GETXSTATE_INFO = 0x44
|
||||
PT_GET_EVENT_MASK = 0x19
|
||||
PT_GET_SC_ARGS = 0x1b
|
||||
PT_GET_SC_RET = 0x1c
|
||||
PT_IO = 0xc
|
||||
PT_KILL = 0x8
|
||||
PT_LWPINFO = 0xd
|
||||
PT_LWP_EVENTS = 0x18
|
||||
PT_READ_D = 0x2
|
||||
PT_READ_I = 0x1
|
||||
PT_RESUME = 0x13
|
||||
PT_SETDBREGS = 0x26
|
||||
PT_SETFPREGS = 0x24
|
||||
PT_SETFSBASE = 0x48
|
||||
PT_SETGSBASE = 0x4a
|
||||
PT_SETREGS = 0x22
|
||||
PT_SETSTEP = 0x11
|
||||
PT_SETXMMREGS = 0x41
|
||||
PT_SETXSTATE = 0x46
|
||||
PT_SET_EVENT_MASK = 0x1a
|
||||
PT_STEP = 0x9
|
||||
PT_SUSPEND = 0x12
|
||||
PT_SYSCALL = 0x16
|
||||
PT_TO_SCE = 0x14
|
||||
PT_TO_SCX = 0x15
|
||||
PT_TRACE_ME = 0x0
|
||||
PT_VM_ENTRY = 0x29
|
||||
PT_VM_TIMESTAMP = 0x28
|
||||
PT_WRITE_D = 0x5
|
||||
PT_WRITE_I = 0x4
|
||||
P_ZONEID = 0xc
|
||||
RLIMIT_AS = 0xa
|
||||
RLIMIT_CORE = 0x4
|
||||
RLIMIT_CPU = 0x0
|
||||
@@ -1320,10 +1386,12 @@ const (
|
||||
SIOCGHWADDR = 0xc020693e
|
||||
SIOCGI2C = 0xc020693d
|
||||
SIOCGIFADDR = 0xc0206921
|
||||
SIOCGIFALIAS = 0xc044692d
|
||||
SIOCGIFBRDADDR = 0xc0206923
|
||||
SIOCGIFCAP = 0xc020691f
|
||||
SIOCGIFCONF = 0xc0086924
|
||||
SIOCGIFDESCR = 0xc020692a
|
||||
SIOCGIFDOWNREASON = 0xc058699a
|
||||
SIOCGIFDSTADDR = 0xc0206922
|
||||
SIOCGIFFIB = 0xc020695c
|
||||
SIOCGIFFLAGS = 0xc0206911
|
||||
@@ -1414,6 +1482,7 @@ const (
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RERROR = 0x20000
|
||||
SO_REUSEADDR = 0x4
|
||||
SO_REUSEPORT = 0x200
|
||||
SO_REUSEPORT_LB = 0x10000
|
||||
@@ -1472,22 +1541,40 @@ const (
|
||||
TCOFLUSH = 0x2
|
||||
TCOOFF = 0x1
|
||||
TCOON = 0x2
|
||||
TCPOPT_EOL = 0x0
|
||||
TCPOPT_FAST_OPEN = 0x22
|
||||
TCPOPT_MAXSEG = 0x2
|
||||
TCPOPT_NOP = 0x1
|
||||
TCPOPT_PAD = 0x0
|
||||
TCPOPT_SACK = 0x5
|
||||
TCPOPT_SACK_PERMITTED = 0x4
|
||||
TCPOPT_SIGNATURE = 0x13
|
||||
TCPOPT_TIMESTAMP = 0x8
|
||||
TCPOPT_WINDOW = 0x3
|
||||
TCP_BBR_ACK_COMP_ALG = 0x448
|
||||
TCP_BBR_ALGORITHM = 0x43b
|
||||
TCP_BBR_DRAIN_INC_EXTRA = 0x43c
|
||||
TCP_BBR_DRAIN_PG = 0x42e
|
||||
TCP_BBR_EXTRA_GAIN = 0x449
|
||||
TCP_BBR_EXTRA_STATE = 0x453
|
||||
TCP_BBR_FLOOR_MIN_TSO = 0x454
|
||||
TCP_BBR_HDWR_PACE = 0x451
|
||||
TCP_BBR_HOLD_TARGET = 0x436
|
||||
TCP_BBR_IWINTSO = 0x42b
|
||||
TCP_BBR_LOWGAIN_FD = 0x436
|
||||
TCP_BBR_LOWGAIN_HALF = 0x435
|
||||
TCP_BBR_LOWGAIN_THRESH = 0x434
|
||||
TCP_BBR_MAX_RTO = 0x439
|
||||
TCP_BBR_MIN_RTO = 0x438
|
||||
TCP_BBR_MIN_TOPACEOUT = 0x455
|
||||
TCP_BBR_ONE_RETRAN = 0x431
|
||||
TCP_BBR_PACE_CROSS = 0x442
|
||||
TCP_BBR_PACE_DEL_TAR = 0x43f
|
||||
TCP_BBR_PACE_OH = 0x435
|
||||
TCP_BBR_PACE_PER_SEC = 0x43e
|
||||
TCP_BBR_PACE_SEG_MAX = 0x440
|
||||
TCP_BBR_PACE_SEG_MIN = 0x441
|
||||
TCP_BBR_POLICER_DETECT = 0x457
|
||||
TCP_BBR_PROBE_RTT_GAIN = 0x44d
|
||||
TCP_BBR_PROBE_RTT_INT = 0x430
|
||||
TCP_BBR_PROBE_RTT_LEN = 0x44e
|
||||
@@ -1496,12 +1583,18 @@ const (
|
||||
TCP_BBR_REC_OVER_HPTS = 0x43a
|
||||
TCP_BBR_RETRAN_WTSO = 0x44b
|
||||
TCP_BBR_RWND_IS_APP = 0x42f
|
||||
TCP_BBR_SEND_IWND_IN_TSO = 0x44f
|
||||
TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d
|
||||
TCP_BBR_STARTUP_LOSS_EXIT = 0x432
|
||||
TCP_BBR_STARTUP_PG = 0x42d
|
||||
TCP_BBR_TMR_PACE_OH = 0x448
|
||||
TCP_BBR_TSLIMITS = 0x434
|
||||
TCP_BBR_TSTMP_RAISES = 0x456
|
||||
TCP_BBR_UNLIMITED = 0x43b
|
||||
TCP_BBR_USEDEL_RATE = 0x437
|
||||
TCP_BBR_USE_LOWGAIN = 0x433
|
||||
TCP_BBR_USE_RACK_CHEAT = 0x450
|
||||
TCP_BBR_UTTER_MAX_TSO = 0x452
|
||||
TCP_CA_NAME_MAX = 0x10
|
||||
TCP_CCALGOOPT = 0x41
|
||||
TCP_CONGESTION = 0x40
|
||||
@@ -1541,6 +1634,7 @@ const (
|
||||
TCP_PCAP_OUT = 0x800
|
||||
TCP_RACK_EARLY_RECOV = 0x423
|
||||
TCP_RACK_EARLY_SEG = 0x424
|
||||
TCP_RACK_GP_INCREASE = 0x446
|
||||
TCP_RACK_IDLE_REDUCE_HIGH = 0x444
|
||||
TCP_RACK_MIN_PACE = 0x445
|
||||
TCP_RACK_MIN_PACE_SEG = 0x446
|
||||
@@ -1554,7 +1648,6 @@ const (
|
||||
TCP_RACK_PRR_SENDALOT = 0x421
|
||||
TCP_RACK_REORD_FADE = 0x426
|
||||
TCP_RACK_REORD_THRESH = 0x425
|
||||
TCP_RACK_SESS_CWV = 0x42a
|
||||
TCP_RACK_TLP_INC_VAR = 0x429
|
||||
TCP_RACK_TLP_REDUCE = 0x41c
|
||||
TCP_RACK_TLP_THRESH = 0x427
|
||||
@@ -1694,12 +1787,13 @@ const (
|
||||
EIDRM = syscall.Errno(0x52)
|
||||
EILSEQ = syscall.Errno(0x56)
|
||||
EINPROGRESS = syscall.Errno(0x24)
|
||||
EINTEGRITY = syscall.Errno(0x61)
|
||||
EINTR = syscall.Errno(0x4)
|
||||
EINVAL = syscall.Errno(0x16)
|
||||
EIO = syscall.Errno(0x5)
|
||||
EISCONN = syscall.Errno(0x38)
|
||||
EISDIR = syscall.Errno(0x15)
|
||||
ELAST = syscall.Errno(0x60)
|
||||
ELAST = syscall.Errno(0x61)
|
||||
ELOOP = syscall.Errno(0x3e)
|
||||
EMFILE = syscall.Errno(0x18)
|
||||
EMLINK = syscall.Errno(0x1f)
|
||||
@@ -1842,7 +1936,7 @@ var errorList = [...]struct {
|
||||
{32, "EPIPE", "broken pipe"},
|
||||
{33, "EDOM", "numerical argument out of domain"},
|
||||
{34, "ERANGE", "result too large"},
|
||||
{35, "EAGAIN", "resource temporarily unavailable"},
|
||||
{35, "EWOULDBLOCK", "resource temporarily unavailable"},
|
||||
{36, "EINPROGRESS", "operation now in progress"},
|
||||
{37, "EALREADY", "operation already in progress"},
|
||||
{38, "ENOTSOCK", "socket operation on non-socket"},
|
||||
@@ -1904,6 +1998,7 @@ var errorList = [...]struct {
|
||||
{94, "ECAPMODE", "not permitted in capability mode"},
|
||||
{95, "ENOTRECOVERABLE", "state not recoverable"},
|
||||
{96, "EOWNERDEAD", "previous owner died"},
|
||||
{97, "EINTEGRITY", "integrity check failed"},
|
||||
}
|
||||
|
||||
// Signal table
|
||||
|
||||
+100
-7
@@ -151,6 +151,7 @@ const (
|
||||
BIOCSETF = 0x80104267
|
||||
BIOCSETFNR = 0x80104282
|
||||
BIOCSETIF = 0x8020426c
|
||||
BIOCSETVLANPCP = 0x80044285
|
||||
BIOCSETWF = 0x8010427b
|
||||
BIOCSETZBUF = 0x80184281
|
||||
BIOCSHDRCMPLT = 0x80044275
|
||||
@@ -447,7 +448,7 @@ const (
|
||||
DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1
|
||||
DLT_INFINIBAND = 0xf7
|
||||
DLT_IPFILTER = 0x74
|
||||
DLT_IPMB = 0xc7
|
||||
DLT_IPMB_KONTRON = 0xc7
|
||||
DLT_IPMB_LINUX = 0xd1
|
||||
DLT_IPMI_HPM_2 = 0x104
|
||||
DLT_IPNET = 0xe2
|
||||
@@ -487,10 +488,11 @@ const (
|
||||
DLT_LINUX_LAPD = 0xb1
|
||||
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
|
||||
DLT_LINUX_SLL = 0x71
|
||||
DLT_LINUX_SLL2 = 0x114
|
||||
DLT_LOOP = 0x6c
|
||||
DLT_LORATAP = 0x10e
|
||||
DLT_LTALK = 0x72
|
||||
DLT_MATCHING_MAX = 0x113
|
||||
DLT_MATCHING_MAX = 0x114
|
||||
DLT_MATCHING_MIN = 0x68
|
||||
DLT_MFR = 0xb6
|
||||
DLT_MOST = 0xd3
|
||||
@@ -734,6 +736,7 @@ const (
|
||||
IPPROTO_CMTP = 0x26
|
||||
IPPROTO_CPHB = 0x49
|
||||
IPPROTO_CPNX = 0x48
|
||||
IPPROTO_DCCP = 0x21
|
||||
IPPROTO_DDP = 0x25
|
||||
IPPROTO_DGP = 0x56
|
||||
IPPROTO_DIVERT = 0x102
|
||||
@@ -814,7 +817,6 @@ const (
|
||||
IPPROTO_SCTP = 0x84
|
||||
IPPROTO_SDRP = 0x2a
|
||||
IPPROTO_SEND = 0x103
|
||||
IPPROTO_SEP = 0x21
|
||||
IPPROTO_SHIM6 = 0x8c
|
||||
IPPROTO_SKIP = 0x39
|
||||
IPPROTO_SPACER = 0x7fff
|
||||
@@ -911,6 +913,7 @@ const (
|
||||
IPV6_V6ONLY = 0x1b
|
||||
IPV6_VERSION = 0x60
|
||||
IPV6_VERSION_MASK = 0xf0
|
||||
IPV6_VLAN_PCP = 0x4b
|
||||
IP_ADD_MEMBERSHIP = 0xc
|
||||
IP_ADD_SOURCE_MEMBERSHIP = 0x46
|
||||
IP_BINDANY = 0x18
|
||||
@@ -989,8 +992,12 @@ const (
|
||||
IP_TOS = 0x3
|
||||
IP_TTL = 0x4
|
||||
IP_UNBLOCK_SOURCE = 0x49
|
||||
IP_VLAN_PCP = 0x4b
|
||||
ISIG = 0x80
|
||||
ISTRIP = 0x20
|
||||
ITIMER_PROF = 0x2
|
||||
ITIMER_REAL = 0x0
|
||||
ITIMER_VIRTUAL = 0x1
|
||||
IXANY = 0x800
|
||||
IXOFF = 0x400
|
||||
IXON = 0x200
|
||||
@@ -1000,7 +1007,6 @@ const (
|
||||
KERN_VERSION = 0x4
|
||||
LOCAL_CONNWAIT = 0x4
|
||||
LOCAL_CREDS = 0x2
|
||||
LOCAL_CREDS_PERSISTENT = 0x3
|
||||
LOCAL_PEERCRED = 0x1
|
||||
LOCAL_VENDOR = 0x80000000
|
||||
LOCK_EX = 0x2
|
||||
@@ -1180,6 +1186,8 @@ const (
|
||||
O_NONBLOCK = 0x4
|
||||
O_RDONLY = 0x0
|
||||
O_RDWR = 0x2
|
||||
O_RESOLVE_BENEATH = 0x800000
|
||||
O_SEARCH = 0x40000
|
||||
O_SHLOCK = 0x10
|
||||
O_SYNC = 0x80
|
||||
O_TRUNC = 0x400
|
||||
@@ -1190,6 +1198,10 @@ const (
|
||||
PARMRK = 0x8
|
||||
PARODD = 0x2000
|
||||
PENDIN = 0x20000000
|
||||
PIOD_READ_D = 0x1
|
||||
PIOD_READ_I = 0x3
|
||||
PIOD_WRITE_D = 0x2
|
||||
PIOD_WRITE_I = 0x4
|
||||
PRIO_PGRP = 0x1
|
||||
PRIO_PROCESS = 0x0
|
||||
PRIO_USER = 0x2
|
||||
@@ -1197,6 +1209,58 @@ const (
|
||||
PROT_NONE = 0x0
|
||||
PROT_READ = 0x1
|
||||
PROT_WRITE = 0x2
|
||||
PTRACE_DEFAULT = 0x1
|
||||
PTRACE_EXEC = 0x1
|
||||
PTRACE_FORK = 0x8
|
||||
PTRACE_LWP = 0x10
|
||||
PTRACE_SCE = 0x2
|
||||
PTRACE_SCX = 0x4
|
||||
PTRACE_SYSCALL = 0x6
|
||||
PTRACE_VFORK = 0x20
|
||||
PT_ATTACH = 0xa
|
||||
PT_CLEARSTEP = 0x10
|
||||
PT_CONTINUE = 0x7
|
||||
PT_DETACH = 0xb
|
||||
PT_FIRSTMACH = 0x40
|
||||
PT_FOLLOW_FORK = 0x17
|
||||
PT_GETDBREGS = 0x25
|
||||
PT_GETFPREGS = 0x23
|
||||
PT_GETFSBASE = 0x47
|
||||
PT_GETGSBASE = 0x49
|
||||
PT_GETLWPLIST = 0xf
|
||||
PT_GETNUMLWPS = 0xe
|
||||
PT_GETREGS = 0x21
|
||||
PT_GETXSTATE = 0x45
|
||||
PT_GETXSTATE_INFO = 0x44
|
||||
PT_GET_EVENT_MASK = 0x19
|
||||
PT_GET_SC_ARGS = 0x1b
|
||||
PT_GET_SC_RET = 0x1c
|
||||
PT_IO = 0xc
|
||||
PT_KILL = 0x8
|
||||
PT_LWPINFO = 0xd
|
||||
PT_LWP_EVENTS = 0x18
|
||||
PT_READ_D = 0x2
|
||||
PT_READ_I = 0x1
|
||||
PT_RESUME = 0x13
|
||||
PT_SETDBREGS = 0x26
|
||||
PT_SETFPREGS = 0x24
|
||||
PT_SETFSBASE = 0x48
|
||||
PT_SETGSBASE = 0x4a
|
||||
PT_SETREGS = 0x22
|
||||
PT_SETSTEP = 0x11
|
||||
PT_SETXSTATE = 0x46
|
||||
PT_SET_EVENT_MASK = 0x1a
|
||||
PT_STEP = 0x9
|
||||
PT_SUSPEND = 0x12
|
||||
PT_SYSCALL = 0x16
|
||||
PT_TO_SCE = 0x14
|
||||
PT_TO_SCX = 0x15
|
||||
PT_TRACE_ME = 0x0
|
||||
PT_VM_ENTRY = 0x29
|
||||
PT_VM_TIMESTAMP = 0x28
|
||||
PT_WRITE_D = 0x5
|
||||
PT_WRITE_I = 0x4
|
||||
P_ZONEID = 0xc
|
||||
RLIMIT_AS = 0xa
|
||||
RLIMIT_CORE = 0x4
|
||||
RLIMIT_CPU = 0x0
|
||||
@@ -1321,10 +1385,12 @@ const (
|
||||
SIOCGHWADDR = 0xc020693e
|
||||
SIOCGI2C = 0xc020693d
|
||||
SIOCGIFADDR = 0xc0206921
|
||||
SIOCGIFALIAS = 0xc044692d
|
||||
SIOCGIFBRDADDR = 0xc0206923
|
||||
SIOCGIFCAP = 0xc020691f
|
||||
SIOCGIFCONF = 0xc0106924
|
||||
SIOCGIFDESCR = 0xc020692a
|
||||
SIOCGIFDOWNREASON = 0xc058699a
|
||||
SIOCGIFDSTADDR = 0xc0206922
|
||||
SIOCGIFFIB = 0xc020695c
|
||||
SIOCGIFFLAGS = 0xc0206911
|
||||
@@ -1415,6 +1481,7 @@ const (
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RERROR = 0x20000
|
||||
SO_REUSEADDR = 0x4
|
||||
SO_REUSEPORT = 0x200
|
||||
SO_REUSEPORT_LB = 0x10000
|
||||
@@ -1473,22 +1540,40 @@ const (
|
||||
TCOFLUSH = 0x2
|
||||
TCOOFF = 0x1
|
||||
TCOON = 0x2
|
||||
TCPOPT_EOL = 0x0
|
||||
TCPOPT_FAST_OPEN = 0x22
|
||||
TCPOPT_MAXSEG = 0x2
|
||||
TCPOPT_NOP = 0x1
|
||||
TCPOPT_PAD = 0x0
|
||||
TCPOPT_SACK = 0x5
|
||||
TCPOPT_SACK_PERMITTED = 0x4
|
||||
TCPOPT_SIGNATURE = 0x13
|
||||
TCPOPT_TIMESTAMP = 0x8
|
||||
TCPOPT_WINDOW = 0x3
|
||||
TCP_BBR_ACK_COMP_ALG = 0x448
|
||||
TCP_BBR_ALGORITHM = 0x43b
|
||||
TCP_BBR_DRAIN_INC_EXTRA = 0x43c
|
||||
TCP_BBR_DRAIN_PG = 0x42e
|
||||
TCP_BBR_EXTRA_GAIN = 0x449
|
||||
TCP_BBR_EXTRA_STATE = 0x453
|
||||
TCP_BBR_FLOOR_MIN_TSO = 0x454
|
||||
TCP_BBR_HDWR_PACE = 0x451
|
||||
TCP_BBR_HOLD_TARGET = 0x436
|
||||
TCP_BBR_IWINTSO = 0x42b
|
||||
TCP_BBR_LOWGAIN_FD = 0x436
|
||||
TCP_BBR_LOWGAIN_HALF = 0x435
|
||||
TCP_BBR_LOWGAIN_THRESH = 0x434
|
||||
TCP_BBR_MAX_RTO = 0x439
|
||||
TCP_BBR_MIN_RTO = 0x438
|
||||
TCP_BBR_MIN_TOPACEOUT = 0x455
|
||||
TCP_BBR_ONE_RETRAN = 0x431
|
||||
TCP_BBR_PACE_CROSS = 0x442
|
||||
TCP_BBR_PACE_DEL_TAR = 0x43f
|
||||
TCP_BBR_PACE_OH = 0x435
|
||||
TCP_BBR_PACE_PER_SEC = 0x43e
|
||||
TCP_BBR_PACE_SEG_MAX = 0x440
|
||||
TCP_BBR_PACE_SEG_MIN = 0x441
|
||||
TCP_BBR_POLICER_DETECT = 0x457
|
||||
TCP_BBR_PROBE_RTT_GAIN = 0x44d
|
||||
TCP_BBR_PROBE_RTT_INT = 0x430
|
||||
TCP_BBR_PROBE_RTT_LEN = 0x44e
|
||||
@@ -1497,12 +1582,18 @@ const (
|
||||
TCP_BBR_REC_OVER_HPTS = 0x43a
|
||||
TCP_BBR_RETRAN_WTSO = 0x44b
|
||||
TCP_BBR_RWND_IS_APP = 0x42f
|
||||
TCP_BBR_SEND_IWND_IN_TSO = 0x44f
|
||||
TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d
|
||||
TCP_BBR_STARTUP_LOSS_EXIT = 0x432
|
||||
TCP_BBR_STARTUP_PG = 0x42d
|
||||
TCP_BBR_TMR_PACE_OH = 0x448
|
||||
TCP_BBR_TSLIMITS = 0x434
|
||||
TCP_BBR_TSTMP_RAISES = 0x456
|
||||
TCP_BBR_UNLIMITED = 0x43b
|
||||
TCP_BBR_USEDEL_RATE = 0x437
|
||||
TCP_BBR_USE_LOWGAIN = 0x433
|
||||
TCP_BBR_USE_RACK_CHEAT = 0x450
|
||||
TCP_BBR_UTTER_MAX_TSO = 0x452
|
||||
TCP_CA_NAME_MAX = 0x10
|
||||
TCP_CCALGOOPT = 0x41
|
||||
TCP_CONGESTION = 0x40
|
||||
@@ -1542,6 +1633,7 @@ const (
|
||||
TCP_PCAP_OUT = 0x800
|
||||
TCP_RACK_EARLY_RECOV = 0x423
|
||||
TCP_RACK_EARLY_SEG = 0x424
|
||||
TCP_RACK_GP_INCREASE = 0x446
|
||||
TCP_RACK_IDLE_REDUCE_HIGH = 0x444
|
||||
TCP_RACK_MIN_PACE = 0x445
|
||||
TCP_RACK_MIN_PACE_SEG = 0x446
|
||||
@@ -1555,7 +1647,6 @@ const (
|
||||
TCP_RACK_PRR_SENDALOT = 0x421
|
||||
TCP_RACK_REORD_FADE = 0x426
|
||||
TCP_RACK_REORD_THRESH = 0x425
|
||||
TCP_RACK_SESS_CWV = 0x42a
|
||||
TCP_RACK_TLP_INC_VAR = 0x429
|
||||
TCP_RACK_TLP_REDUCE = 0x41c
|
||||
TCP_RACK_TLP_THRESH = 0x427
|
||||
@@ -1693,12 +1784,13 @@ const (
|
||||
EIDRM = syscall.Errno(0x52)
|
||||
EILSEQ = syscall.Errno(0x56)
|
||||
EINPROGRESS = syscall.Errno(0x24)
|
||||
EINTEGRITY = syscall.Errno(0x61)
|
||||
EINTR = syscall.Errno(0x4)
|
||||
EINVAL = syscall.Errno(0x16)
|
||||
EIO = syscall.Errno(0x5)
|
||||
EISCONN = syscall.Errno(0x38)
|
||||
EISDIR = syscall.Errno(0x15)
|
||||
ELAST = syscall.Errno(0x60)
|
||||
ELAST = syscall.Errno(0x61)
|
||||
ELOOP = syscall.Errno(0x3e)
|
||||
EMFILE = syscall.Errno(0x18)
|
||||
EMLINK = syscall.Errno(0x1f)
|
||||
@@ -1841,7 +1933,7 @@ var errorList = [...]struct {
|
||||
{32, "EPIPE", "broken pipe"},
|
||||
{33, "EDOM", "numerical argument out of domain"},
|
||||
{34, "ERANGE", "result too large"},
|
||||
{35, "EAGAIN", "resource temporarily unavailable"},
|
||||
{35, "EWOULDBLOCK", "resource temporarily unavailable"},
|
||||
{36, "EINPROGRESS", "operation now in progress"},
|
||||
{37, "EALREADY", "operation already in progress"},
|
||||
{38, "ENOTSOCK", "socket operation on non-socket"},
|
||||
@@ -1903,6 +1995,7 @@ var errorList = [...]struct {
|
||||
{94, "ECAPMODE", "not permitted in capability mode"},
|
||||
{95, "ENOTRECOVERABLE", "state not recoverable"},
|
||||
{96, "EOWNERDEAD", "previous owner died"},
|
||||
{97, "EINTEGRITY", "integrity check failed"},
|
||||
}
|
||||
|
||||
// Signal table
|
||||
|
||||
+204
-16
@@ -151,6 +151,7 @@ const (
|
||||
BIOCSETF = 0x80084267
|
||||
BIOCSETFNR = 0x80084282
|
||||
BIOCSETIF = 0x8020426c
|
||||
BIOCSETVLANPCP = 0x80044285
|
||||
BIOCSETWF = 0x8008427b
|
||||
BIOCSETZBUF = 0x800c4281
|
||||
BIOCSHDRCMPLT = 0x80044275
|
||||
@@ -362,7 +363,7 @@ const (
|
||||
CTL_KERN = 0x1
|
||||
CTL_MAXNAME = 0x18
|
||||
CTL_NET = 0x4
|
||||
DIOCGATTR = 0xc144648e
|
||||
DIOCGATTR = 0xc148648e
|
||||
DIOCGDELETE = 0x80106488
|
||||
DIOCGFLUSH = 0x20006487
|
||||
DIOCGFRONTSTUFF = 0x40086486
|
||||
@@ -377,7 +378,7 @@ const (
|
||||
DIOCGSTRIPESIZE = 0x4008648b
|
||||
DIOCSKERNELDUMP = 0x804c6490
|
||||
DIOCSKERNELDUMP_FREEBSD11 = 0x80046485
|
||||
DIOCZONECMD = 0xc06c648f
|
||||
DIOCZONECMD = 0xc078648f
|
||||
DLT_A429 = 0xb8
|
||||
DLT_A653_ICM = 0xb9
|
||||
DLT_AIRONET_HEADER = 0x78
|
||||
@@ -407,7 +408,9 @@ const (
|
||||
DLT_C_HDLC_WITH_DIR = 0xcd
|
||||
DLT_DBUS = 0xe7
|
||||
DLT_DECT = 0xdd
|
||||
DLT_DISPLAYPORT_AUX = 0x113
|
||||
DLT_DOCSIS = 0x8f
|
||||
DLT_DOCSIS31_XRA31 = 0x111
|
||||
DLT_DVB_CI = 0xeb
|
||||
DLT_ECONET = 0x73
|
||||
DLT_EN10MB = 0x1
|
||||
@@ -417,6 +420,7 @@ const (
|
||||
DLT_ERF = 0xc5
|
||||
DLT_ERF_ETH = 0xaf
|
||||
DLT_ERF_POS = 0xb0
|
||||
DLT_ETHERNET_MPACKET = 0x112
|
||||
DLT_FC_2 = 0xe0
|
||||
DLT_FC_2_WITH_FRAME_DELIMS = 0xe1
|
||||
DLT_FDDI = 0xa
|
||||
@@ -444,7 +448,7 @@ const (
|
||||
DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1
|
||||
DLT_INFINIBAND = 0xf7
|
||||
DLT_IPFILTER = 0x74
|
||||
DLT_IPMB = 0xc7
|
||||
DLT_IPMB_KONTRON = 0xc7
|
||||
DLT_IPMB_LINUX = 0xd1
|
||||
DLT_IPMI_HPM_2 = 0x104
|
||||
DLT_IPNET = 0xe2
|
||||
@@ -484,9 +488,11 @@ const (
|
||||
DLT_LINUX_LAPD = 0xb1
|
||||
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
|
||||
DLT_LINUX_SLL = 0x71
|
||||
DLT_LINUX_SLL2 = 0x114
|
||||
DLT_LOOP = 0x6c
|
||||
DLT_LORATAP = 0x10e
|
||||
DLT_LTALK = 0x72
|
||||
DLT_MATCHING_MAX = 0x109
|
||||
DLT_MATCHING_MAX = 0x114
|
||||
DLT_MATCHING_MIN = 0x68
|
||||
DLT_MFR = 0xb6
|
||||
DLT_MOST = 0xd3
|
||||
@@ -502,7 +508,9 @@ const (
|
||||
DLT_NFC_LLCP = 0xf5
|
||||
DLT_NFLOG = 0xef
|
||||
DLT_NG40 = 0xf4
|
||||
DLT_NORDIC_BLE = 0x110
|
||||
DLT_NULL = 0x0
|
||||
DLT_OPENFLOW = 0x10b
|
||||
DLT_PCI_EXP = 0x7d
|
||||
DLT_PFLOG = 0x75
|
||||
DLT_PFSYNC = 0x79
|
||||
@@ -526,15 +534,18 @@ const (
|
||||
DLT_RTAC_SERIAL = 0xfa
|
||||
DLT_SCCP = 0x8e
|
||||
DLT_SCTP = 0xf8
|
||||
DLT_SDLC = 0x10c
|
||||
DLT_SITA = 0xc4
|
||||
DLT_SLIP = 0x8
|
||||
DLT_SLIP_BSDOS = 0xd
|
||||
DLT_STANAG_5066_D_PDU = 0xed
|
||||
DLT_SUNATM = 0x7b
|
||||
DLT_SYMANTEC_FIREWALL = 0x63
|
||||
DLT_TI_LLN_SNIFFER = 0x10d
|
||||
DLT_TZSP = 0x80
|
||||
DLT_USB = 0xba
|
||||
DLT_USBPCAP = 0xf9
|
||||
DLT_USB_DARWIN = 0x10a
|
||||
DLT_USB_FREEBSD = 0xba
|
||||
DLT_USB_LINUX = 0xbd
|
||||
DLT_USB_LINUX_MMAPPED = 0xdc
|
||||
@@ -554,6 +565,7 @@ const (
|
||||
DLT_USER7 = 0x9a
|
||||
DLT_USER8 = 0x9b
|
||||
DLT_USER9 = 0x9c
|
||||
DLT_VSOCK = 0x10f
|
||||
DLT_WATTSTOPPER_DLM = 0x107
|
||||
DLT_WIHART = 0xdf
|
||||
DLT_WIRESHARK_UPPER_PDU = 0xfc
|
||||
@@ -578,6 +590,7 @@ const (
|
||||
ECHONL = 0x10
|
||||
ECHOPRT = 0x20
|
||||
EVFILT_AIO = -0x3
|
||||
EVFILT_EMPTY = -0xd
|
||||
EVFILT_FS = -0x9
|
||||
EVFILT_LIO = -0xa
|
||||
EVFILT_PROC = -0x5
|
||||
@@ -585,11 +598,12 @@ const (
|
||||
EVFILT_READ = -0x1
|
||||
EVFILT_SENDFILE = -0xc
|
||||
EVFILT_SIGNAL = -0x6
|
||||
EVFILT_SYSCOUNT = 0xc
|
||||
EVFILT_SYSCOUNT = 0xd
|
||||
EVFILT_TIMER = -0x7
|
||||
EVFILT_USER = -0xb
|
||||
EVFILT_VNODE = -0x4
|
||||
EVFILT_WRITE = -0x2
|
||||
EVNAMEMAP_NAME_SIZE = 0x40
|
||||
EV_ADD = 0x1
|
||||
EV_CLEAR = 0x20
|
||||
EV_DELETE = 0x2
|
||||
@@ -606,6 +620,7 @@ const (
|
||||
EV_RECEIPT = 0x40
|
||||
EV_SYSFLAGS = 0xf000
|
||||
EXTA = 0x4b00
|
||||
EXTATTR_MAXNAMELEN = 0xff
|
||||
EXTATTR_NAMESPACE_EMPTY = 0x0
|
||||
EXTATTR_NAMESPACE_SYSTEM = 0x2
|
||||
EXTATTR_NAMESPACE_USER = 0x1
|
||||
@@ -647,6 +662,7 @@ const (
|
||||
IEXTEN = 0x400
|
||||
IFAN_ARRIVAL = 0x0
|
||||
IFAN_DEPARTURE = 0x1
|
||||
IFCAP_WOL_MAGIC = 0x2000
|
||||
IFF_ALLMULTI = 0x200
|
||||
IFF_ALTPHYS = 0x4000
|
||||
IFF_BROADCAST = 0x2
|
||||
@@ -663,6 +679,7 @@ const (
|
||||
IFF_MONITOR = 0x40000
|
||||
IFF_MULTICAST = 0x8000
|
||||
IFF_NOARP = 0x80
|
||||
IFF_NOGROUP = 0x800000
|
||||
IFF_OACTIVE = 0x400
|
||||
IFF_POINTOPOINT = 0x10
|
||||
IFF_PPROMISC = 0x20000
|
||||
@@ -719,6 +736,7 @@ const (
|
||||
IPPROTO_CMTP = 0x26
|
||||
IPPROTO_CPHB = 0x49
|
||||
IPPROTO_CPNX = 0x48
|
||||
IPPROTO_DCCP = 0x21
|
||||
IPPROTO_DDP = 0x25
|
||||
IPPROTO_DGP = 0x56
|
||||
IPPROTO_DIVERT = 0x102
|
||||
@@ -799,7 +817,6 @@ const (
|
||||
IPPROTO_SCTP = 0x84
|
||||
IPPROTO_SDRP = 0x2a
|
||||
IPPROTO_SEND = 0x103
|
||||
IPPROTO_SEP = 0x21
|
||||
IPPROTO_SHIM6 = 0x8c
|
||||
IPPROTO_SKIP = 0x39
|
||||
IPPROTO_SPACER = 0x7fff
|
||||
@@ -837,6 +854,7 @@ const (
|
||||
IPV6_DSTOPTS = 0x32
|
||||
IPV6_FLOWID = 0x43
|
||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||
IPV6_FLOWLABEL_LEN = 0x14
|
||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||
IPV6_FLOWTYPE = 0x44
|
||||
IPV6_FRAGTTL = 0x78
|
||||
@@ -857,13 +875,13 @@ const (
|
||||
IPV6_MAX_GROUP_SRC_FILTER = 0x200
|
||||
IPV6_MAX_MEMBERSHIPS = 0xfff
|
||||
IPV6_MAX_SOCK_SRC_FILTER = 0x80
|
||||
IPV6_MIN_MEMBERSHIPS = 0x1f
|
||||
IPV6_MMTU = 0x500
|
||||
IPV6_MSFILTER = 0x4a
|
||||
IPV6_MULTICAST_HOPS = 0xa
|
||||
IPV6_MULTICAST_IF = 0x9
|
||||
IPV6_MULTICAST_LOOP = 0xb
|
||||
IPV6_NEXTHOP = 0x30
|
||||
IPV6_ORIGDSTADDR = 0x48
|
||||
IPV6_PATHMTU = 0x2c
|
||||
IPV6_PKTINFO = 0x2e
|
||||
IPV6_PORTRANGE = 0xe
|
||||
@@ -875,6 +893,7 @@ const (
|
||||
IPV6_RECVFLOWID = 0x46
|
||||
IPV6_RECVHOPLIMIT = 0x25
|
||||
IPV6_RECVHOPOPTS = 0x27
|
||||
IPV6_RECVORIGDSTADDR = 0x48
|
||||
IPV6_RECVPATHMTU = 0x2b
|
||||
IPV6_RECVPKTINFO = 0x24
|
||||
IPV6_RECVRSSBUCKETID = 0x47
|
||||
@@ -894,6 +913,7 @@ const (
|
||||
IPV6_V6ONLY = 0x1b
|
||||
IPV6_VERSION = 0x60
|
||||
IPV6_VERSION_MASK = 0xf0
|
||||
IPV6_VLAN_PCP = 0x4b
|
||||
IP_ADD_MEMBERSHIP = 0xc
|
||||
IP_ADD_SOURCE_MEMBERSHIP = 0x46
|
||||
IP_BINDANY = 0x18
|
||||
@@ -935,10 +955,8 @@ const (
|
||||
IP_MAX_MEMBERSHIPS = 0xfff
|
||||
IP_MAX_SOCK_MUTE_FILTER = 0x80
|
||||
IP_MAX_SOCK_SRC_FILTER = 0x80
|
||||
IP_MAX_SOURCE_FILTER = 0x400
|
||||
IP_MF = 0x2000
|
||||
IP_MINTTL = 0x42
|
||||
IP_MIN_MEMBERSHIPS = 0x1f
|
||||
IP_MSFILTER = 0x4a
|
||||
IP_MSS = 0x240
|
||||
IP_MULTICAST_IF = 0x9
|
||||
@@ -948,6 +966,7 @@ const (
|
||||
IP_OFFMASK = 0x1fff
|
||||
IP_ONESBCAST = 0x17
|
||||
IP_OPTIONS = 0x1
|
||||
IP_ORIGDSTADDR = 0x1b
|
||||
IP_PORTRANGE = 0x13
|
||||
IP_PORTRANGE_DEFAULT = 0x0
|
||||
IP_PORTRANGE_HIGH = 0x1
|
||||
@@ -956,6 +975,7 @@ const (
|
||||
IP_RECVFLOWID = 0x5d
|
||||
IP_RECVIF = 0x14
|
||||
IP_RECVOPTS = 0x5
|
||||
IP_RECVORIGDSTADDR = 0x1b
|
||||
IP_RECVRETOPTS = 0x6
|
||||
IP_RECVRSSBUCKETID = 0x5e
|
||||
IP_RECVTOS = 0x44
|
||||
@@ -972,8 +992,12 @@ const (
|
||||
IP_TOS = 0x3
|
||||
IP_TTL = 0x4
|
||||
IP_UNBLOCK_SOURCE = 0x49
|
||||
IP_VLAN_PCP = 0x4b
|
||||
ISIG = 0x80
|
||||
ISTRIP = 0x20
|
||||
ITIMER_PROF = 0x2
|
||||
ITIMER_REAL = 0x0
|
||||
ITIMER_VIRTUAL = 0x1
|
||||
IXANY = 0x800
|
||||
IXOFF = 0x400
|
||||
IXON = 0x200
|
||||
@@ -983,7 +1007,6 @@ const (
|
||||
KERN_VERSION = 0x4
|
||||
LOCAL_CONNWAIT = 0x4
|
||||
LOCAL_CREDS = 0x2
|
||||
LOCAL_CREDS_PERSISTENT = 0x3
|
||||
LOCAL_PEERCRED = 0x1
|
||||
LOCAL_VENDOR = 0x80000000
|
||||
LOCK_EX = 0x2
|
||||
@@ -1071,10 +1094,12 @@ const (
|
||||
MNT_SUSPEND = 0x4
|
||||
MNT_SYNCHRONOUS = 0x2
|
||||
MNT_UNION = 0x20
|
||||
MNT_UNTRUSTED = 0x800000000
|
||||
MNT_UPDATE = 0x10000
|
||||
MNT_UPDATEMASK = 0x2d8d0807e
|
||||
MNT_UPDATEMASK = 0xad8d0807e
|
||||
MNT_USER = 0x8000
|
||||
MNT_VISFLAGMASK = 0x3fef0ffff
|
||||
MNT_VERIFIED = 0x400000000
|
||||
MNT_VISFLAGMASK = 0xffef0ffff
|
||||
MNT_WAIT = 0x1
|
||||
MSG_CMSG_CLOEXEC = 0x40000
|
||||
MSG_COMPAT = 0x8000
|
||||
@@ -1103,6 +1128,7 @@ const (
|
||||
NFDBITS = 0x20
|
||||
NOFLSH = 0x80000000
|
||||
NOKERNINFO = 0x2000000
|
||||
NOTE_ABSTIME = 0x10
|
||||
NOTE_ATTRIB = 0x8
|
||||
NOTE_CHILD = 0x4
|
||||
NOTE_CLOSE = 0x100
|
||||
@@ -1159,6 +1185,8 @@ const (
|
||||
O_NONBLOCK = 0x4
|
||||
O_RDONLY = 0x0
|
||||
O_RDWR = 0x2
|
||||
O_RESOLVE_BENEATH = 0x800000
|
||||
O_SEARCH = 0x40000
|
||||
O_SHLOCK = 0x10
|
||||
O_SYNC = 0x80
|
||||
O_TRUNC = 0x400
|
||||
@@ -1169,6 +1197,10 @@ const (
|
||||
PARMRK = 0x8
|
||||
PARODD = 0x2000
|
||||
PENDIN = 0x20000000
|
||||
PIOD_READ_D = 0x1
|
||||
PIOD_READ_I = 0x3
|
||||
PIOD_WRITE_D = 0x2
|
||||
PIOD_WRITE_I = 0x4
|
||||
PRIO_PGRP = 0x1
|
||||
PRIO_PROCESS = 0x0
|
||||
PRIO_USER = 0x2
|
||||
@@ -1176,6 +1208,53 @@ const (
|
||||
PROT_NONE = 0x0
|
||||
PROT_READ = 0x1
|
||||
PROT_WRITE = 0x2
|
||||
PTRACE_DEFAULT = 0x1
|
||||
PTRACE_EXEC = 0x1
|
||||
PTRACE_FORK = 0x8
|
||||
PTRACE_LWP = 0x10
|
||||
PTRACE_SCE = 0x2
|
||||
PTRACE_SCX = 0x4
|
||||
PTRACE_SYSCALL = 0x6
|
||||
PTRACE_VFORK = 0x20
|
||||
PT_ATTACH = 0xa
|
||||
PT_CLEARSTEP = 0x10
|
||||
PT_CONTINUE = 0x7
|
||||
PT_DETACH = 0xb
|
||||
PT_FIRSTMACH = 0x40
|
||||
PT_FOLLOW_FORK = 0x17
|
||||
PT_GETDBREGS = 0x25
|
||||
PT_GETFPREGS = 0x23
|
||||
PT_GETLWPLIST = 0xf
|
||||
PT_GETNUMLWPS = 0xe
|
||||
PT_GETREGS = 0x21
|
||||
PT_GETVFPREGS = 0x40
|
||||
PT_GET_EVENT_MASK = 0x19
|
||||
PT_GET_SC_ARGS = 0x1b
|
||||
PT_GET_SC_RET = 0x1c
|
||||
PT_IO = 0xc
|
||||
PT_KILL = 0x8
|
||||
PT_LWPINFO = 0xd
|
||||
PT_LWP_EVENTS = 0x18
|
||||
PT_READ_D = 0x2
|
||||
PT_READ_I = 0x1
|
||||
PT_RESUME = 0x13
|
||||
PT_SETDBREGS = 0x26
|
||||
PT_SETFPREGS = 0x24
|
||||
PT_SETREGS = 0x22
|
||||
PT_SETSTEP = 0x11
|
||||
PT_SETVFPREGS = 0x41
|
||||
PT_SET_EVENT_MASK = 0x1a
|
||||
PT_STEP = 0x9
|
||||
PT_SUSPEND = 0x12
|
||||
PT_SYSCALL = 0x16
|
||||
PT_TO_SCE = 0x14
|
||||
PT_TO_SCX = 0x15
|
||||
PT_TRACE_ME = 0x0
|
||||
PT_VM_ENTRY = 0x29
|
||||
PT_VM_TIMESTAMP = 0x28
|
||||
PT_WRITE_D = 0x5
|
||||
PT_WRITE_I = 0x4
|
||||
P_ZONEID = 0xc
|
||||
RLIMIT_AS = 0xa
|
||||
RLIMIT_CORE = 0x4
|
||||
RLIMIT_CPU = 0x0
|
||||
@@ -1257,7 +1336,6 @@ const (
|
||||
RTV_WEIGHT = 0x100
|
||||
RT_ALL_FIBS = -0x1
|
||||
RT_BLACKHOLE = 0x40
|
||||
RT_CACHING_CONTEXT = 0x1
|
||||
RT_DEFAULT_FIB = 0x0
|
||||
RT_HAS_GW = 0x80
|
||||
RT_HAS_HEADER = 0x10
|
||||
@@ -1267,15 +1345,17 @@ const (
|
||||
RT_LLE_CACHE = 0x100
|
||||
RT_MAY_LOOP = 0x8
|
||||
RT_MAY_LOOP_BIT = 0x3
|
||||
RT_NORTREF = 0x2
|
||||
RT_REJECT = 0x20
|
||||
RUSAGE_CHILDREN = -0x1
|
||||
RUSAGE_SELF = 0x0
|
||||
RUSAGE_THREAD = 0x1
|
||||
SCM_BINTIME = 0x4
|
||||
SCM_CREDS = 0x3
|
||||
SCM_MONOTONIC = 0x6
|
||||
SCM_REALTIME = 0x5
|
||||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
SCM_TIME_INFO = 0x7
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x3
|
||||
SEEK_END = 0x2
|
||||
@@ -1299,10 +1379,12 @@ const (
|
||||
SIOCGHWADDR = 0xc020693e
|
||||
SIOCGI2C = 0xc020693d
|
||||
SIOCGIFADDR = 0xc0206921
|
||||
SIOCGIFALIAS = 0xc044692d
|
||||
SIOCGIFBRDADDR = 0xc0206923
|
||||
SIOCGIFCAP = 0xc020691f
|
||||
SIOCGIFCONF = 0xc0086924
|
||||
SIOCGIFDESCR = 0xc020692a
|
||||
SIOCGIFDOWNREASON = 0xc058699a
|
||||
SIOCGIFDSTADDR = 0xc0206922
|
||||
SIOCGIFFIB = 0xc020695c
|
||||
SIOCGIFFLAGS = 0xc0206911
|
||||
@@ -1318,8 +1400,11 @@ const (
|
||||
SIOCGIFPDSTADDR = 0xc0206948
|
||||
SIOCGIFPHYS = 0xc0206935
|
||||
SIOCGIFPSRCADDR = 0xc0206947
|
||||
SIOCGIFRSSHASH = 0xc0186997
|
||||
SIOCGIFRSSKEY = 0xc0946996
|
||||
SIOCGIFSTATUS = 0xc331693b
|
||||
SIOCGIFXMEDIA = 0xc028698b
|
||||
SIOCGLANPCP = 0xc0206998
|
||||
SIOCGLOWAT = 0x40047303
|
||||
SIOCGPGRP = 0x40047309
|
||||
SIOCGPRIVATE_0 = 0xc0206950
|
||||
@@ -1350,6 +1435,7 @@ const (
|
||||
SIOCSIFPHYS = 0x80206936
|
||||
SIOCSIFRVNET = 0xc020695b
|
||||
SIOCSIFVNET = 0xc020695a
|
||||
SIOCSLANPCP = 0x80206999
|
||||
SIOCSLOWAT = 0x80047302
|
||||
SIOCSPGRP = 0x80047308
|
||||
SIOCSTUNFIB = 0x8020695f
|
||||
@@ -1369,6 +1455,7 @@ const (
|
||||
SO_BINTIME = 0x2000
|
||||
SO_BROADCAST = 0x20
|
||||
SO_DEBUG = 0x1
|
||||
SO_DOMAIN = 0x1019
|
||||
SO_DONTROUTE = 0x10
|
||||
SO_ERROR = 0x1007
|
||||
SO_KEEPALIVE = 0x8
|
||||
@@ -1377,6 +1464,7 @@ const (
|
||||
SO_LISTENINCQLEN = 0x1013
|
||||
SO_LISTENQLEN = 0x1012
|
||||
SO_LISTENQLIMIT = 0x1011
|
||||
SO_MAX_PACING_RATE = 0x1018
|
||||
SO_NOSIGPIPE = 0x800
|
||||
SO_NO_DDP = 0x8000
|
||||
SO_NO_OFFLOAD = 0x4000
|
||||
@@ -1387,13 +1475,22 @@ const (
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RERROR = 0x20000
|
||||
SO_REUSEADDR = 0x4
|
||||
SO_REUSEPORT = 0x200
|
||||
SO_REUSEPORT_LB = 0x10000
|
||||
SO_SETFIB = 0x1014
|
||||
SO_SNDBUF = 0x1001
|
||||
SO_SNDLOWAT = 0x1003
|
||||
SO_SNDTIMEO = 0x1005
|
||||
SO_TIMESTAMP = 0x400
|
||||
SO_TS_BINTIME = 0x1
|
||||
SO_TS_CLOCK = 0x1017
|
||||
SO_TS_CLOCK_MAX = 0x3
|
||||
SO_TS_DEFAULT = 0x0
|
||||
SO_TS_MONOTONIC = 0x3
|
||||
SO_TS_REALTIME = 0x2
|
||||
SO_TS_REALTIME_MICRO = 0x0
|
||||
SO_TYPE = 0x1008
|
||||
SO_USELOOPBACK = 0x40
|
||||
SO_USER_COOKIE = 0x1015
|
||||
@@ -1437,10 +1534,69 @@ const (
|
||||
TCOFLUSH = 0x2
|
||||
TCOOFF = 0x1
|
||||
TCOON = 0x2
|
||||
TCPOPT_EOL = 0x0
|
||||
TCPOPT_FAST_OPEN = 0x22
|
||||
TCPOPT_MAXSEG = 0x2
|
||||
TCPOPT_NOP = 0x1
|
||||
TCPOPT_PAD = 0x0
|
||||
TCPOPT_SACK = 0x5
|
||||
TCPOPT_SACK_PERMITTED = 0x4
|
||||
TCPOPT_SIGNATURE = 0x13
|
||||
TCPOPT_TIMESTAMP = 0x8
|
||||
TCPOPT_WINDOW = 0x3
|
||||
TCP_BBR_ACK_COMP_ALG = 0x448
|
||||
TCP_BBR_ALGORITHM = 0x43b
|
||||
TCP_BBR_DRAIN_INC_EXTRA = 0x43c
|
||||
TCP_BBR_DRAIN_PG = 0x42e
|
||||
TCP_BBR_EXTRA_GAIN = 0x449
|
||||
TCP_BBR_EXTRA_STATE = 0x453
|
||||
TCP_BBR_FLOOR_MIN_TSO = 0x454
|
||||
TCP_BBR_HDWR_PACE = 0x451
|
||||
TCP_BBR_HOLD_TARGET = 0x436
|
||||
TCP_BBR_IWINTSO = 0x42b
|
||||
TCP_BBR_LOWGAIN_FD = 0x436
|
||||
TCP_BBR_LOWGAIN_HALF = 0x435
|
||||
TCP_BBR_LOWGAIN_THRESH = 0x434
|
||||
TCP_BBR_MAX_RTO = 0x439
|
||||
TCP_BBR_MIN_RTO = 0x438
|
||||
TCP_BBR_MIN_TOPACEOUT = 0x455
|
||||
TCP_BBR_ONE_RETRAN = 0x431
|
||||
TCP_BBR_PACE_CROSS = 0x442
|
||||
TCP_BBR_PACE_DEL_TAR = 0x43f
|
||||
TCP_BBR_PACE_OH = 0x435
|
||||
TCP_BBR_PACE_PER_SEC = 0x43e
|
||||
TCP_BBR_PACE_SEG_MAX = 0x440
|
||||
TCP_BBR_PACE_SEG_MIN = 0x441
|
||||
TCP_BBR_POLICER_DETECT = 0x457
|
||||
TCP_BBR_PROBE_RTT_GAIN = 0x44d
|
||||
TCP_BBR_PROBE_RTT_INT = 0x430
|
||||
TCP_BBR_PROBE_RTT_LEN = 0x44e
|
||||
TCP_BBR_RACK_RTT_USE = 0x44a
|
||||
TCP_BBR_RECFORCE = 0x42c
|
||||
TCP_BBR_REC_OVER_HPTS = 0x43a
|
||||
TCP_BBR_RETRAN_WTSO = 0x44b
|
||||
TCP_BBR_RWND_IS_APP = 0x42f
|
||||
TCP_BBR_SEND_IWND_IN_TSO = 0x44f
|
||||
TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d
|
||||
TCP_BBR_STARTUP_LOSS_EXIT = 0x432
|
||||
TCP_BBR_STARTUP_PG = 0x42d
|
||||
TCP_BBR_TMR_PACE_OH = 0x448
|
||||
TCP_BBR_TSLIMITS = 0x434
|
||||
TCP_BBR_TSTMP_RAISES = 0x456
|
||||
TCP_BBR_UNLIMITED = 0x43b
|
||||
TCP_BBR_USEDEL_RATE = 0x437
|
||||
TCP_BBR_USE_LOWGAIN = 0x433
|
||||
TCP_BBR_USE_RACK_CHEAT = 0x450
|
||||
TCP_BBR_UTTER_MAX_TSO = 0x452
|
||||
TCP_CA_NAME_MAX = 0x10
|
||||
TCP_CCALGOOPT = 0x41
|
||||
TCP_CONGESTION = 0x40
|
||||
TCP_DATA_AFTER_CLOSE = 0x44c
|
||||
TCP_DELACK = 0x48
|
||||
TCP_FASTOPEN = 0x401
|
||||
TCP_FASTOPEN_MAX_COOKIE_LEN = 0x10
|
||||
TCP_FASTOPEN_MIN_COOKIE_LEN = 0x4
|
||||
TCP_FASTOPEN_PSK_LEN = 0x10
|
||||
TCP_FUNCTION_BLK = 0x2000
|
||||
TCP_FUNCTION_NAME_LEN_MAX = 0x20
|
||||
TCP_INFO = 0x20
|
||||
@@ -1448,6 +1604,12 @@ const (
|
||||
TCP_KEEPIDLE = 0x100
|
||||
TCP_KEEPINIT = 0x80
|
||||
TCP_KEEPINTVL = 0x200
|
||||
TCP_LOG = 0x22
|
||||
TCP_LOGBUF = 0x23
|
||||
TCP_LOGDUMP = 0x25
|
||||
TCP_LOGDUMPID = 0x26
|
||||
TCP_LOGID = 0x24
|
||||
TCP_LOG_ID_LEN = 0x40
|
||||
TCP_MAXBURST = 0x4
|
||||
TCP_MAXHLEN = 0x3c
|
||||
TCP_MAXOLEN = 0x28
|
||||
@@ -1463,8 +1625,30 @@ const (
|
||||
TCP_NOPUSH = 0x4
|
||||
TCP_PCAP_IN = 0x1000
|
||||
TCP_PCAP_OUT = 0x800
|
||||
TCP_RACK_EARLY_RECOV = 0x423
|
||||
TCP_RACK_EARLY_SEG = 0x424
|
||||
TCP_RACK_GP_INCREASE = 0x446
|
||||
TCP_RACK_IDLE_REDUCE_HIGH = 0x444
|
||||
TCP_RACK_MIN_PACE = 0x445
|
||||
TCP_RACK_MIN_PACE_SEG = 0x446
|
||||
TCP_RACK_MIN_TO = 0x422
|
||||
TCP_RACK_PACE_ALWAYS = 0x41f
|
||||
TCP_RACK_PACE_MAX_SEG = 0x41e
|
||||
TCP_RACK_PACE_REDUCE = 0x41d
|
||||
TCP_RACK_PKT_DELAY = 0x428
|
||||
TCP_RACK_PROP = 0x41b
|
||||
TCP_RACK_PROP_RATE = 0x420
|
||||
TCP_RACK_PRR_SENDALOT = 0x421
|
||||
TCP_RACK_REORD_FADE = 0x426
|
||||
TCP_RACK_REORD_THRESH = 0x425
|
||||
TCP_RACK_TLP_INC_VAR = 0x429
|
||||
TCP_RACK_TLP_REDUCE = 0x41c
|
||||
TCP_RACK_TLP_THRESH = 0x427
|
||||
TCP_RACK_TLP_USE = 0x447
|
||||
TCP_VENDOR = 0x80000000
|
||||
TCSAFLUSH = 0x2
|
||||
TIMER_ABSTIME = 0x1
|
||||
TIMER_RELTIME = 0x0
|
||||
TIOCCBRK = 0x2000747a
|
||||
TIOCCDTR = 0x20007478
|
||||
TIOCCONS = 0x80047462
|
||||
@@ -1528,6 +1712,8 @@ const (
|
||||
TIOCTIMESTAMP = 0x40107459
|
||||
TIOCUCNTL = 0x80047466
|
||||
TOSTOP = 0x400000
|
||||
UTIME_NOW = -0x1
|
||||
UTIME_OMIT = -0x2
|
||||
VDISCARD = 0xf
|
||||
VDSUSP = 0xb
|
||||
VEOF = 0x0
|
||||
@@ -1592,12 +1778,13 @@ const (
|
||||
EIDRM = syscall.Errno(0x52)
|
||||
EILSEQ = syscall.Errno(0x56)
|
||||
EINPROGRESS = syscall.Errno(0x24)
|
||||
EINTEGRITY = syscall.Errno(0x61)
|
||||
EINTR = syscall.Errno(0x4)
|
||||
EINVAL = syscall.Errno(0x16)
|
||||
EIO = syscall.Errno(0x5)
|
||||
EISCONN = syscall.Errno(0x38)
|
||||
EISDIR = syscall.Errno(0x15)
|
||||
ELAST = syscall.Errno(0x60)
|
||||
ELAST = syscall.Errno(0x61)
|
||||
ELOOP = syscall.Errno(0x3e)
|
||||
EMFILE = syscall.Errno(0x18)
|
||||
EMLINK = syscall.Errno(0x1f)
|
||||
@@ -1740,7 +1927,7 @@ var errorList = [...]struct {
|
||||
{32, "EPIPE", "broken pipe"},
|
||||
{33, "EDOM", "numerical argument out of domain"},
|
||||
{34, "ERANGE", "result too large"},
|
||||
{35, "EAGAIN", "resource temporarily unavailable"},
|
||||
{35, "EWOULDBLOCK", "resource temporarily unavailable"},
|
||||
{36, "EINPROGRESS", "operation now in progress"},
|
||||
{37, "EALREADY", "operation already in progress"},
|
||||
{38, "ENOTSOCK", "socket operation on non-socket"},
|
||||
@@ -1802,6 +1989,7 @@ var errorList = [...]struct {
|
||||
{94, "ECAPMODE", "not permitted in capability mode"},
|
||||
{95, "ENOTRECOVERABLE", "state not recoverable"},
|
||||
{96, "EOWNERDEAD", "previous owner died"},
|
||||
{97, "EINTEGRITY", "integrity check failed"},
|
||||
}
|
||||
|
||||
// Signal table
|
||||
|
||||
+93
-7
@@ -151,6 +151,7 @@ const (
|
||||
BIOCSETF = 0x80104267
|
||||
BIOCSETFNR = 0x80104282
|
||||
BIOCSETIF = 0x8020426c
|
||||
BIOCSETVLANPCP = 0x80044285
|
||||
BIOCSETWF = 0x8010427b
|
||||
BIOCSETZBUF = 0x80184281
|
||||
BIOCSHDRCMPLT = 0x80044275
|
||||
@@ -447,7 +448,7 @@ const (
|
||||
DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1
|
||||
DLT_INFINIBAND = 0xf7
|
||||
DLT_IPFILTER = 0x74
|
||||
DLT_IPMB = 0xc7
|
||||
DLT_IPMB_KONTRON = 0xc7
|
||||
DLT_IPMB_LINUX = 0xd1
|
||||
DLT_IPMI_HPM_2 = 0x104
|
||||
DLT_IPNET = 0xe2
|
||||
@@ -487,10 +488,11 @@ const (
|
||||
DLT_LINUX_LAPD = 0xb1
|
||||
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
|
||||
DLT_LINUX_SLL = 0x71
|
||||
DLT_LINUX_SLL2 = 0x114
|
||||
DLT_LOOP = 0x6c
|
||||
DLT_LORATAP = 0x10e
|
||||
DLT_LTALK = 0x72
|
||||
DLT_MATCHING_MAX = 0x113
|
||||
DLT_MATCHING_MAX = 0x114
|
||||
DLT_MATCHING_MIN = 0x68
|
||||
DLT_MFR = 0xb6
|
||||
DLT_MOST = 0xd3
|
||||
@@ -734,6 +736,7 @@ const (
|
||||
IPPROTO_CMTP = 0x26
|
||||
IPPROTO_CPHB = 0x49
|
||||
IPPROTO_CPNX = 0x48
|
||||
IPPROTO_DCCP = 0x21
|
||||
IPPROTO_DDP = 0x25
|
||||
IPPROTO_DGP = 0x56
|
||||
IPPROTO_DIVERT = 0x102
|
||||
@@ -814,7 +817,6 @@ const (
|
||||
IPPROTO_SCTP = 0x84
|
||||
IPPROTO_SDRP = 0x2a
|
||||
IPPROTO_SEND = 0x103
|
||||
IPPROTO_SEP = 0x21
|
||||
IPPROTO_SHIM6 = 0x8c
|
||||
IPPROTO_SKIP = 0x39
|
||||
IPPROTO_SPACER = 0x7fff
|
||||
@@ -911,6 +913,7 @@ const (
|
||||
IPV6_V6ONLY = 0x1b
|
||||
IPV6_VERSION = 0x60
|
||||
IPV6_VERSION_MASK = 0xf0
|
||||
IPV6_VLAN_PCP = 0x4b
|
||||
IP_ADD_MEMBERSHIP = 0xc
|
||||
IP_ADD_SOURCE_MEMBERSHIP = 0x46
|
||||
IP_BINDANY = 0x18
|
||||
@@ -989,8 +992,12 @@ const (
|
||||
IP_TOS = 0x3
|
||||
IP_TTL = 0x4
|
||||
IP_UNBLOCK_SOURCE = 0x49
|
||||
IP_VLAN_PCP = 0x4b
|
||||
ISIG = 0x80
|
||||
ISTRIP = 0x20
|
||||
ITIMER_PROF = 0x2
|
||||
ITIMER_REAL = 0x0
|
||||
ITIMER_VIRTUAL = 0x1
|
||||
IXANY = 0x800
|
||||
IXOFF = 0x400
|
||||
IXON = 0x200
|
||||
@@ -1000,7 +1007,6 @@ const (
|
||||
KERN_VERSION = 0x4
|
||||
LOCAL_CONNWAIT = 0x4
|
||||
LOCAL_CREDS = 0x2
|
||||
LOCAL_CREDS_PERSISTENT = 0x3
|
||||
LOCAL_PEERCRED = 0x1
|
||||
LOCAL_VENDOR = 0x80000000
|
||||
LOCK_EX = 0x2
|
||||
@@ -1180,6 +1186,8 @@ const (
|
||||
O_NONBLOCK = 0x4
|
||||
O_RDONLY = 0x0
|
||||
O_RDWR = 0x2
|
||||
O_RESOLVE_BENEATH = 0x800000
|
||||
O_SEARCH = 0x40000
|
||||
O_SHLOCK = 0x10
|
||||
O_SYNC = 0x80
|
||||
O_TRUNC = 0x400
|
||||
@@ -1190,6 +1198,10 @@ const (
|
||||
PARMRK = 0x8
|
||||
PARODD = 0x2000
|
||||
PENDIN = 0x20000000
|
||||
PIOD_READ_D = 0x1
|
||||
PIOD_READ_I = 0x3
|
||||
PIOD_WRITE_D = 0x2
|
||||
PIOD_WRITE_I = 0x4
|
||||
PRIO_PGRP = 0x1
|
||||
PRIO_PROCESS = 0x0
|
||||
PRIO_USER = 0x2
|
||||
@@ -1197,6 +1209,51 @@ const (
|
||||
PROT_NONE = 0x0
|
||||
PROT_READ = 0x1
|
||||
PROT_WRITE = 0x2
|
||||
PTRACE_DEFAULT = 0x1
|
||||
PTRACE_EXEC = 0x1
|
||||
PTRACE_FORK = 0x8
|
||||
PTRACE_LWP = 0x10
|
||||
PTRACE_SCE = 0x2
|
||||
PTRACE_SCX = 0x4
|
||||
PTRACE_SYSCALL = 0x6
|
||||
PTRACE_VFORK = 0x20
|
||||
PT_ATTACH = 0xa
|
||||
PT_CLEARSTEP = 0x10
|
||||
PT_CONTINUE = 0x7
|
||||
PT_DETACH = 0xb
|
||||
PT_FIRSTMACH = 0x40
|
||||
PT_FOLLOW_FORK = 0x17
|
||||
PT_GETDBREGS = 0x25
|
||||
PT_GETFPREGS = 0x23
|
||||
PT_GETLWPLIST = 0xf
|
||||
PT_GETNUMLWPS = 0xe
|
||||
PT_GETREGS = 0x21
|
||||
PT_GET_EVENT_MASK = 0x19
|
||||
PT_GET_SC_ARGS = 0x1b
|
||||
PT_GET_SC_RET = 0x1c
|
||||
PT_IO = 0xc
|
||||
PT_KILL = 0x8
|
||||
PT_LWPINFO = 0xd
|
||||
PT_LWP_EVENTS = 0x18
|
||||
PT_READ_D = 0x2
|
||||
PT_READ_I = 0x1
|
||||
PT_RESUME = 0x13
|
||||
PT_SETDBREGS = 0x26
|
||||
PT_SETFPREGS = 0x24
|
||||
PT_SETREGS = 0x22
|
||||
PT_SETSTEP = 0x11
|
||||
PT_SET_EVENT_MASK = 0x1a
|
||||
PT_STEP = 0x9
|
||||
PT_SUSPEND = 0x12
|
||||
PT_SYSCALL = 0x16
|
||||
PT_TO_SCE = 0x14
|
||||
PT_TO_SCX = 0x15
|
||||
PT_TRACE_ME = 0x0
|
||||
PT_VM_ENTRY = 0x29
|
||||
PT_VM_TIMESTAMP = 0x28
|
||||
PT_WRITE_D = 0x5
|
||||
PT_WRITE_I = 0x4
|
||||
P_ZONEID = 0xc
|
||||
RLIMIT_AS = 0xa
|
||||
RLIMIT_CORE = 0x4
|
||||
RLIMIT_CPU = 0x0
|
||||
@@ -1321,10 +1378,12 @@ const (
|
||||
SIOCGHWADDR = 0xc020693e
|
||||
SIOCGI2C = 0xc020693d
|
||||
SIOCGIFADDR = 0xc0206921
|
||||
SIOCGIFALIAS = 0xc044692d
|
||||
SIOCGIFBRDADDR = 0xc0206923
|
||||
SIOCGIFCAP = 0xc020691f
|
||||
SIOCGIFCONF = 0xc0106924
|
||||
SIOCGIFDESCR = 0xc020692a
|
||||
SIOCGIFDOWNREASON = 0xc058699a
|
||||
SIOCGIFDSTADDR = 0xc0206922
|
||||
SIOCGIFFIB = 0xc020695c
|
||||
SIOCGIFFLAGS = 0xc0206911
|
||||
@@ -1415,6 +1474,7 @@ const (
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RERROR = 0x20000
|
||||
SO_REUSEADDR = 0x4
|
||||
SO_REUSEPORT = 0x200
|
||||
SO_REUSEPORT_LB = 0x10000
|
||||
@@ -1473,22 +1533,40 @@ const (
|
||||
TCOFLUSH = 0x2
|
||||
TCOOFF = 0x1
|
||||
TCOON = 0x2
|
||||
TCPOPT_EOL = 0x0
|
||||
TCPOPT_FAST_OPEN = 0x22
|
||||
TCPOPT_MAXSEG = 0x2
|
||||
TCPOPT_NOP = 0x1
|
||||
TCPOPT_PAD = 0x0
|
||||
TCPOPT_SACK = 0x5
|
||||
TCPOPT_SACK_PERMITTED = 0x4
|
||||
TCPOPT_SIGNATURE = 0x13
|
||||
TCPOPT_TIMESTAMP = 0x8
|
||||
TCPOPT_WINDOW = 0x3
|
||||
TCP_BBR_ACK_COMP_ALG = 0x448
|
||||
TCP_BBR_ALGORITHM = 0x43b
|
||||
TCP_BBR_DRAIN_INC_EXTRA = 0x43c
|
||||
TCP_BBR_DRAIN_PG = 0x42e
|
||||
TCP_BBR_EXTRA_GAIN = 0x449
|
||||
TCP_BBR_EXTRA_STATE = 0x453
|
||||
TCP_BBR_FLOOR_MIN_TSO = 0x454
|
||||
TCP_BBR_HDWR_PACE = 0x451
|
||||
TCP_BBR_HOLD_TARGET = 0x436
|
||||
TCP_BBR_IWINTSO = 0x42b
|
||||
TCP_BBR_LOWGAIN_FD = 0x436
|
||||
TCP_BBR_LOWGAIN_HALF = 0x435
|
||||
TCP_BBR_LOWGAIN_THRESH = 0x434
|
||||
TCP_BBR_MAX_RTO = 0x439
|
||||
TCP_BBR_MIN_RTO = 0x438
|
||||
TCP_BBR_MIN_TOPACEOUT = 0x455
|
||||
TCP_BBR_ONE_RETRAN = 0x431
|
||||
TCP_BBR_PACE_CROSS = 0x442
|
||||
TCP_BBR_PACE_DEL_TAR = 0x43f
|
||||
TCP_BBR_PACE_OH = 0x435
|
||||
TCP_BBR_PACE_PER_SEC = 0x43e
|
||||
TCP_BBR_PACE_SEG_MAX = 0x440
|
||||
TCP_BBR_PACE_SEG_MIN = 0x441
|
||||
TCP_BBR_POLICER_DETECT = 0x457
|
||||
TCP_BBR_PROBE_RTT_GAIN = 0x44d
|
||||
TCP_BBR_PROBE_RTT_INT = 0x430
|
||||
TCP_BBR_PROBE_RTT_LEN = 0x44e
|
||||
@@ -1497,12 +1575,18 @@ const (
|
||||
TCP_BBR_REC_OVER_HPTS = 0x43a
|
||||
TCP_BBR_RETRAN_WTSO = 0x44b
|
||||
TCP_BBR_RWND_IS_APP = 0x42f
|
||||
TCP_BBR_SEND_IWND_IN_TSO = 0x44f
|
||||
TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d
|
||||
TCP_BBR_STARTUP_LOSS_EXIT = 0x432
|
||||
TCP_BBR_STARTUP_PG = 0x42d
|
||||
TCP_BBR_TMR_PACE_OH = 0x448
|
||||
TCP_BBR_TSLIMITS = 0x434
|
||||
TCP_BBR_TSTMP_RAISES = 0x456
|
||||
TCP_BBR_UNLIMITED = 0x43b
|
||||
TCP_BBR_USEDEL_RATE = 0x437
|
||||
TCP_BBR_USE_LOWGAIN = 0x433
|
||||
TCP_BBR_USE_RACK_CHEAT = 0x450
|
||||
TCP_BBR_UTTER_MAX_TSO = 0x452
|
||||
TCP_CA_NAME_MAX = 0x10
|
||||
TCP_CCALGOOPT = 0x41
|
||||
TCP_CONGESTION = 0x40
|
||||
@@ -1542,6 +1626,7 @@ const (
|
||||
TCP_PCAP_OUT = 0x800
|
||||
TCP_RACK_EARLY_RECOV = 0x423
|
||||
TCP_RACK_EARLY_SEG = 0x424
|
||||
TCP_RACK_GP_INCREASE = 0x446
|
||||
TCP_RACK_IDLE_REDUCE_HIGH = 0x444
|
||||
TCP_RACK_MIN_PACE = 0x445
|
||||
TCP_RACK_MIN_PACE_SEG = 0x446
|
||||
@@ -1555,7 +1640,6 @@ const (
|
||||
TCP_RACK_PRR_SENDALOT = 0x421
|
||||
TCP_RACK_REORD_FADE = 0x426
|
||||
TCP_RACK_REORD_THRESH = 0x425
|
||||
TCP_RACK_SESS_CWV = 0x42a
|
||||
TCP_RACK_TLP_INC_VAR = 0x429
|
||||
TCP_RACK_TLP_REDUCE = 0x41c
|
||||
TCP_RACK_TLP_THRESH = 0x427
|
||||
@@ -1694,12 +1778,13 @@ const (
|
||||
EIDRM = syscall.Errno(0x52)
|
||||
EILSEQ = syscall.Errno(0x56)
|
||||
EINPROGRESS = syscall.Errno(0x24)
|
||||
EINTEGRITY = syscall.Errno(0x61)
|
||||
EINTR = syscall.Errno(0x4)
|
||||
EINVAL = syscall.Errno(0x16)
|
||||
EIO = syscall.Errno(0x5)
|
||||
EISCONN = syscall.Errno(0x38)
|
||||
EISDIR = syscall.Errno(0x15)
|
||||
ELAST = syscall.Errno(0x60)
|
||||
ELAST = syscall.Errno(0x61)
|
||||
ELOOP = syscall.Errno(0x3e)
|
||||
EMFILE = syscall.Errno(0x18)
|
||||
EMLINK = syscall.Errno(0x1f)
|
||||
@@ -1842,7 +1927,7 @@ var errorList = [...]struct {
|
||||
{32, "EPIPE", "broken pipe"},
|
||||
{33, "EDOM", "numerical argument out of domain"},
|
||||
{34, "ERANGE", "result too large"},
|
||||
{35, "EAGAIN", "resource temporarily unavailable"},
|
||||
{35, "EWOULDBLOCK", "resource temporarily unavailable"},
|
||||
{36, "EINPROGRESS", "operation now in progress"},
|
||||
{37, "EALREADY", "operation already in progress"},
|
||||
{38, "ENOTSOCK", "socket operation on non-socket"},
|
||||
@@ -1904,6 +1989,7 @@ var errorList = [...]struct {
|
||||
{94, "ECAPMODE", "not permitted in capability mode"},
|
||||
{95, "ENOTRECOVERABLE", "state not recoverable"},
|
||||
{96, "EOWNERDEAD", "previous owner died"},
|
||||
{97, "EINTEGRITY", "integrity check failed"},
|
||||
}
|
||||
|
||||
// Signal table
|
||||
|
||||
+2148
File diff suppressed because it is too large
Load Diff
+381
-8
@@ -140,6 +140,306 @@ const (
|
||||
ARPHRD_VOID = 0xffff
|
||||
ARPHRD_VSOCKMON = 0x33a
|
||||
ARPHRD_X25 = 0x10f
|
||||
AUDIT_ADD = 0x3eb
|
||||
AUDIT_ADD_RULE = 0x3f3
|
||||
AUDIT_ALWAYS = 0x2
|
||||
AUDIT_ANOM_ABEND = 0x6a5
|
||||
AUDIT_ANOM_CREAT = 0x6a7
|
||||
AUDIT_ANOM_LINK = 0x6a6
|
||||
AUDIT_ANOM_PROMISCUOUS = 0x6a4
|
||||
AUDIT_ARCH = 0xb
|
||||
AUDIT_ARCH_AARCH64 = 0xc00000b7
|
||||
AUDIT_ARCH_ALPHA = 0xc0009026
|
||||
AUDIT_ARCH_ARCOMPACT = 0x4000005d
|
||||
AUDIT_ARCH_ARCOMPACTBE = 0x5d
|
||||
AUDIT_ARCH_ARCV2 = 0x400000c3
|
||||
AUDIT_ARCH_ARCV2BE = 0xc3
|
||||
AUDIT_ARCH_ARM = 0x40000028
|
||||
AUDIT_ARCH_ARMEB = 0x28
|
||||
AUDIT_ARCH_C6X = 0x4000008c
|
||||
AUDIT_ARCH_C6XBE = 0x8c
|
||||
AUDIT_ARCH_CRIS = 0x4000004c
|
||||
AUDIT_ARCH_CSKY = 0x400000fc
|
||||
AUDIT_ARCH_FRV = 0x5441
|
||||
AUDIT_ARCH_H8300 = 0x2e
|
||||
AUDIT_ARCH_HEXAGON = 0xa4
|
||||
AUDIT_ARCH_I386 = 0x40000003
|
||||
AUDIT_ARCH_IA64 = 0xc0000032
|
||||
AUDIT_ARCH_LOONGARCH32 = 0x40000102
|
||||
AUDIT_ARCH_LOONGARCH64 = 0xc0000102
|
||||
AUDIT_ARCH_M32R = 0x58
|
||||
AUDIT_ARCH_M68K = 0x4
|
||||
AUDIT_ARCH_MICROBLAZE = 0xbd
|
||||
AUDIT_ARCH_MIPS = 0x8
|
||||
AUDIT_ARCH_MIPS64 = 0x80000008
|
||||
AUDIT_ARCH_MIPS64N32 = 0xa0000008
|
||||
AUDIT_ARCH_MIPSEL = 0x40000008
|
||||
AUDIT_ARCH_MIPSEL64 = 0xc0000008
|
||||
AUDIT_ARCH_MIPSEL64N32 = 0xe0000008
|
||||
AUDIT_ARCH_NDS32 = 0x400000a7
|
||||
AUDIT_ARCH_NDS32BE = 0xa7
|
||||
AUDIT_ARCH_NIOS2 = 0x40000071
|
||||
AUDIT_ARCH_OPENRISC = 0x5c
|
||||
AUDIT_ARCH_PARISC = 0xf
|
||||
AUDIT_ARCH_PARISC64 = 0x8000000f
|
||||
AUDIT_ARCH_PPC = 0x14
|
||||
AUDIT_ARCH_PPC64 = 0x80000015
|
||||
AUDIT_ARCH_PPC64LE = 0xc0000015
|
||||
AUDIT_ARCH_RISCV32 = 0x400000f3
|
||||
AUDIT_ARCH_RISCV64 = 0xc00000f3
|
||||
AUDIT_ARCH_S390 = 0x16
|
||||
AUDIT_ARCH_S390X = 0x80000016
|
||||
AUDIT_ARCH_SH = 0x2a
|
||||
AUDIT_ARCH_SH64 = 0x8000002a
|
||||
AUDIT_ARCH_SHEL = 0x4000002a
|
||||
AUDIT_ARCH_SHEL64 = 0xc000002a
|
||||
AUDIT_ARCH_SPARC = 0x2
|
||||
AUDIT_ARCH_SPARC64 = 0x8000002b
|
||||
AUDIT_ARCH_TILEGX = 0xc00000bf
|
||||
AUDIT_ARCH_TILEGX32 = 0x400000bf
|
||||
AUDIT_ARCH_TILEPRO = 0x400000bc
|
||||
AUDIT_ARCH_UNICORE = 0x4000006e
|
||||
AUDIT_ARCH_X86_64 = 0xc000003e
|
||||
AUDIT_ARCH_XTENSA = 0x5e
|
||||
AUDIT_ARG0 = 0xc8
|
||||
AUDIT_ARG1 = 0xc9
|
||||
AUDIT_ARG2 = 0xca
|
||||
AUDIT_ARG3 = 0xcb
|
||||
AUDIT_AVC = 0x578
|
||||
AUDIT_AVC_PATH = 0x57a
|
||||
AUDIT_BITMASK_SIZE = 0x40
|
||||
AUDIT_BIT_MASK = 0x8000000
|
||||
AUDIT_BIT_TEST = 0x48000000
|
||||
AUDIT_BPF = 0x536
|
||||
AUDIT_BPRM_FCAPS = 0x529
|
||||
AUDIT_CAPSET = 0x52a
|
||||
AUDIT_CLASS_CHATTR = 0x2
|
||||
AUDIT_CLASS_CHATTR_32 = 0x3
|
||||
AUDIT_CLASS_DIR_WRITE = 0x0
|
||||
AUDIT_CLASS_DIR_WRITE_32 = 0x1
|
||||
AUDIT_CLASS_READ = 0x4
|
||||
AUDIT_CLASS_READ_32 = 0x5
|
||||
AUDIT_CLASS_SIGNAL = 0x8
|
||||
AUDIT_CLASS_SIGNAL_32 = 0x9
|
||||
AUDIT_CLASS_WRITE = 0x6
|
||||
AUDIT_CLASS_WRITE_32 = 0x7
|
||||
AUDIT_COMPARE_AUID_TO_EUID = 0x10
|
||||
AUDIT_COMPARE_AUID_TO_FSUID = 0xe
|
||||
AUDIT_COMPARE_AUID_TO_OBJ_UID = 0x5
|
||||
AUDIT_COMPARE_AUID_TO_SUID = 0xf
|
||||
AUDIT_COMPARE_EGID_TO_FSGID = 0x17
|
||||
AUDIT_COMPARE_EGID_TO_OBJ_GID = 0x4
|
||||
AUDIT_COMPARE_EGID_TO_SGID = 0x18
|
||||
AUDIT_COMPARE_EUID_TO_FSUID = 0x12
|
||||
AUDIT_COMPARE_EUID_TO_OBJ_UID = 0x3
|
||||
AUDIT_COMPARE_EUID_TO_SUID = 0x11
|
||||
AUDIT_COMPARE_FSGID_TO_OBJ_GID = 0x9
|
||||
AUDIT_COMPARE_FSUID_TO_OBJ_UID = 0x8
|
||||
AUDIT_COMPARE_GID_TO_EGID = 0x14
|
||||
AUDIT_COMPARE_GID_TO_FSGID = 0x15
|
||||
AUDIT_COMPARE_GID_TO_OBJ_GID = 0x2
|
||||
AUDIT_COMPARE_GID_TO_SGID = 0x16
|
||||
AUDIT_COMPARE_SGID_TO_FSGID = 0x19
|
||||
AUDIT_COMPARE_SGID_TO_OBJ_GID = 0x7
|
||||
AUDIT_COMPARE_SUID_TO_FSUID = 0x13
|
||||
AUDIT_COMPARE_SUID_TO_OBJ_UID = 0x6
|
||||
AUDIT_COMPARE_UID_TO_AUID = 0xa
|
||||
AUDIT_COMPARE_UID_TO_EUID = 0xb
|
||||
AUDIT_COMPARE_UID_TO_FSUID = 0xc
|
||||
AUDIT_COMPARE_UID_TO_OBJ_UID = 0x1
|
||||
AUDIT_COMPARE_UID_TO_SUID = 0xd
|
||||
AUDIT_CONFIG_CHANGE = 0x519
|
||||
AUDIT_CWD = 0x51b
|
||||
AUDIT_DAEMON_ABORT = 0x4b2
|
||||
AUDIT_DAEMON_CONFIG = 0x4b3
|
||||
AUDIT_DAEMON_END = 0x4b1
|
||||
AUDIT_DAEMON_START = 0x4b0
|
||||
AUDIT_DEL = 0x3ec
|
||||
AUDIT_DEL_RULE = 0x3f4
|
||||
AUDIT_DEVMAJOR = 0x64
|
||||
AUDIT_DEVMINOR = 0x65
|
||||
AUDIT_DIR = 0x6b
|
||||
AUDIT_DM_CTRL = 0x53a
|
||||
AUDIT_DM_EVENT = 0x53b
|
||||
AUDIT_EGID = 0x6
|
||||
AUDIT_EOE = 0x528
|
||||
AUDIT_EQUAL = 0x40000000
|
||||
AUDIT_EUID = 0x2
|
||||
AUDIT_EVENT_LISTENER = 0x537
|
||||
AUDIT_EXE = 0x70
|
||||
AUDIT_EXECVE = 0x51d
|
||||
AUDIT_EXIT = 0x67
|
||||
AUDIT_FAIL_PANIC = 0x2
|
||||
AUDIT_FAIL_PRINTK = 0x1
|
||||
AUDIT_FAIL_SILENT = 0x0
|
||||
AUDIT_FANOTIFY = 0x533
|
||||
AUDIT_FD_PAIR = 0x525
|
||||
AUDIT_FEATURE_BITMAP_ALL = 0x7f
|
||||
AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT = 0x1
|
||||
AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME = 0x2
|
||||
AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND = 0x8
|
||||
AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH = 0x4
|
||||
AUDIT_FEATURE_BITMAP_FILTER_FS = 0x40
|
||||
AUDIT_FEATURE_BITMAP_LOST_RESET = 0x20
|
||||
AUDIT_FEATURE_BITMAP_SESSIONID_FILTER = 0x10
|
||||
AUDIT_FEATURE_CHANGE = 0x530
|
||||
AUDIT_FEATURE_LOGINUID_IMMUTABLE = 0x1
|
||||
AUDIT_FEATURE_ONLY_UNSET_LOGINUID = 0x0
|
||||
AUDIT_FEATURE_VERSION = 0x1
|
||||
AUDIT_FIELD_COMPARE = 0x6f
|
||||
AUDIT_FILETYPE = 0x6c
|
||||
AUDIT_FILTERKEY = 0xd2
|
||||
AUDIT_FILTER_ENTRY = 0x2
|
||||
AUDIT_FILTER_EXCLUDE = 0x5
|
||||
AUDIT_FILTER_EXIT = 0x4
|
||||
AUDIT_FILTER_FS = 0x6
|
||||
AUDIT_FILTER_PREPEND = 0x10
|
||||
AUDIT_FILTER_TASK = 0x1
|
||||
AUDIT_FILTER_TYPE = 0x5
|
||||
AUDIT_FILTER_URING_EXIT = 0x7
|
||||
AUDIT_FILTER_USER = 0x0
|
||||
AUDIT_FILTER_WATCH = 0x3
|
||||
AUDIT_FIRST_KERN_ANOM_MSG = 0x6a4
|
||||
AUDIT_FIRST_USER_MSG = 0x44c
|
||||
AUDIT_FIRST_USER_MSG2 = 0x834
|
||||
AUDIT_FSGID = 0x8
|
||||
AUDIT_FSTYPE = 0x1a
|
||||
AUDIT_FSUID = 0x4
|
||||
AUDIT_GET = 0x3e8
|
||||
AUDIT_GET_FEATURE = 0x3fb
|
||||
AUDIT_GID = 0x5
|
||||
AUDIT_GREATER_THAN = 0x20000000
|
||||
AUDIT_GREATER_THAN_OR_EQUAL = 0x60000000
|
||||
AUDIT_INODE = 0x66
|
||||
AUDIT_INTEGRITY_DATA = 0x708
|
||||
AUDIT_INTEGRITY_EVM_XATTR = 0x70e
|
||||
AUDIT_INTEGRITY_HASH = 0x70b
|
||||
AUDIT_INTEGRITY_METADATA = 0x709
|
||||
AUDIT_INTEGRITY_PCR = 0x70c
|
||||
AUDIT_INTEGRITY_POLICY_RULE = 0x70f
|
||||
AUDIT_INTEGRITY_RULE = 0x70d
|
||||
AUDIT_INTEGRITY_STATUS = 0x70a
|
||||
AUDIT_IPC = 0x517
|
||||
AUDIT_IPC_SET_PERM = 0x51f
|
||||
AUDIT_KERNEL = 0x7d0
|
||||
AUDIT_KERNEL_OTHER = 0x524
|
||||
AUDIT_KERN_MODULE = 0x532
|
||||
AUDIT_LAST_FEATURE = 0x1
|
||||
AUDIT_LAST_KERN_ANOM_MSG = 0x707
|
||||
AUDIT_LAST_USER_MSG = 0x4af
|
||||
AUDIT_LAST_USER_MSG2 = 0xbb7
|
||||
AUDIT_LESS_THAN = 0x10000000
|
||||
AUDIT_LESS_THAN_OR_EQUAL = 0x50000000
|
||||
AUDIT_LIST = 0x3ea
|
||||
AUDIT_LIST_RULES = 0x3f5
|
||||
AUDIT_LOGIN = 0x3ee
|
||||
AUDIT_LOGINUID = 0x9
|
||||
AUDIT_LOGINUID_SET = 0x18
|
||||
AUDIT_MAC_CALIPSO_ADD = 0x58a
|
||||
AUDIT_MAC_CALIPSO_DEL = 0x58b
|
||||
AUDIT_MAC_CIPSOV4_ADD = 0x57f
|
||||
AUDIT_MAC_CIPSOV4_DEL = 0x580
|
||||
AUDIT_MAC_CONFIG_CHANGE = 0x57d
|
||||
AUDIT_MAC_IPSEC_ADDSA = 0x583
|
||||
AUDIT_MAC_IPSEC_ADDSPD = 0x585
|
||||
AUDIT_MAC_IPSEC_DELSA = 0x584
|
||||
AUDIT_MAC_IPSEC_DELSPD = 0x586
|
||||
AUDIT_MAC_IPSEC_EVENT = 0x587
|
||||
AUDIT_MAC_MAP_ADD = 0x581
|
||||
AUDIT_MAC_MAP_DEL = 0x582
|
||||
AUDIT_MAC_POLICY_LOAD = 0x57b
|
||||
AUDIT_MAC_STATUS = 0x57c
|
||||
AUDIT_MAC_UNLBL_ALLOW = 0x57e
|
||||
AUDIT_MAC_UNLBL_STCADD = 0x588
|
||||
AUDIT_MAC_UNLBL_STCDEL = 0x589
|
||||
AUDIT_MAKE_EQUIV = 0x3f7
|
||||
AUDIT_MAX_FIELDS = 0x40
|
||||
AUDIT_MAX_FIELD_COMPARE = 0x19
|
||||
AUDIT_MAX_KEY_LEN = 0x100
|
||||
AUDIT_MESSAGE_TEXT_MAX = 0x2170
|
||||
AUDIT_MMAP = 0x52b
|
||||
AUDIT_MQ_GETSETATTR = 0x523
|
||||
AUDIT_MQ_NOTIFY = 0x522
|
||||
AUDIT_MQ_OPEN = 0x520
|
||||
AUDIT_MQ_SENDRECV = 0x521
|
||||
AUDIT_MSGTYPE = 0xc
|
||||
AUDIT_NEGATE = 0x80000000
|
||||
AUDIT_NETFILTER_CFG = 0x52d
|
||||
AUDIT_NETFILTER_PKT = 0x52c
|
||||
AUDIT_NEVER = 0x0
|
||||
AUDIT_NLGRP_MAX = 0x1
|
||||
AUDIT_NOT_EQUAL = 0x30000000
|
||||
AUDIT_NR_FILTERS = 0x8
|
||||
AUDIT_OBJ_GID = 0x6e
|
||||
AUDIT_OBJ_LEV_HIGH = 0x17
|
||||
AUDIT_OBJ_LEV_LOW = 0x16
|
||||
AUDIT_OBJ_PID = 0x526
|
||||
AUDIT_OBJ_ROLE = 0x14
|
||||
AUDIT_OBJ_TYPE = 0x15
|
||||
AUDIT_OBJ_UID = 0x6d
|
||||
AUDIT_OBJ_USER = 0x13
|
||||
AUDIT_OPENAT2 = 0x539
|
||||
AUDIT_OPERATORS = 0x78000000
|
||||
AUDIT_PATH = 0x516
|
||||
AUDIT_PERM = 0x6a
|
||||
AUDIT_PERM_ATTR = 0x8
|
||||
AUDIT_PERM_EXEC = 0x1
|
||||
AUDIT_PERM_READ = 0x4
|
||||
AUDIT_PERM_WRITE = 0x2
|
||||
AUDIT_PERS = 0xa
|
||||
AUDIT_PID = 0x0
|
||||
AUDIT_POSSIBLE = 0x1
|
||||
AUDIT_PPID = 0x12
|
||||
AUDIT_PROCTITLE = 0x52f
|
||||
AUDIT_REPLACE = 0x531
|
||||
AUDIT_SADDR_FAM = 0x71
|
||||
AUDIT_SECCOMP = 0x52e
|
||||
AUDIT_SELINUX_ERR = 0x579
|
||||
AUDIT_SESSIONID = 0x19
|
||||
AUDIT_SET = 0x3e9
|
||||
AUDIT_SET_FEATURE = 0x3fa
|
||||
AUDIT_SGID = 0x7
|
||||
AUDIT_SID_UNSET = 0xffffffff
|
||||
AUDIT_SIGNAL_INFO = 0x3f2
|
||||
AUDIT_SOCKADDR = 0x51a
|
||||
AUDIT_SOCKETCALL = 0x518
|
||||
AUDIT_STATUS_BACKLOG_LIMIT = 0x10
|
||||
AUDIT_STATUS_BACKLOG_WAIT_TIME = 0x20
|
||||
AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL = 0x80
|
||||
AUDIT_STATUS_ENABLED = 0x1
|
||||
AUDIT_STATUS_FAILURE = 0x2
|
||||
AUDIT_STATUS_LOST = 0x40
|
||||
AUDIT_STATUS_PID = 0x4
|
||||
AUDIT_STATUS_RATE_LIMIT = 0x8
|
||||
AUDIT_SUBJ_CLR = 0x11
|
||||
AUDIT_SUBJ_ROLE = 0xe
|
||||
AUDIT_SUBJ_SEN = 0x10
|
||||
AUDIT_SUBJ_TYPE = 0xf
|
||||
AUDIT_SUBJ_USER = 0xd
|
||||
AUDIT_SUCCESS = 0x68
|
||||
AUDIT_SUID = 0x3
|
||||
AUDIT_SYSCALL = 0x514
|
||||
AUDIT_SYSCALL_CLASSES = 0x10
|
||||
AUDIT_TIME_ADJNTPVAL = 0x535
|
||||
AUDIT_TIME_INJOFFSET = 0x534
|
||||
AUDIT_TRIM = 0x3f6
|
||||
AUDIT_TTY = 0x527
|
||||
AUDIT_TTY_GET = 0x3f8
|
||||
AUDIT_TTY_SET = 0x3f9
|
||||
AUDIT_UID = 0x1
|
||||
AUDIT_UID_UNSET = 0xffffffff
|
||||
AUDIT_UNUSED_BITS = 0x7fffc00
|
||||
AUDIT_URINGOP = 0x538
|
||||
AUDIT_USER = 0x3ed
|
||||
AUDIT_USER_AVC = 0x453
|
||||
AUDIT_USER_TTY = 0x464
|
||||
AUDIT_VERSION_BACKLOG_LIMIT = 0x1
|
||||
AUDIT_VERSION_BACKLOG_WAIT_TIME = 0x2
|
||||
AUDIT_VERSION_LATEST = 0x7f
|
||||
AUDIT_WATCH = 0x69
|
||||
AUDIT_WATCH_INS = 0x3ef
|
||||
AUDIT_WATCH_LIST = 0x3f1
|
||||
AUDIT_WATCH_REM = 0x3f0
|
||||
AUTOFS_SUPER_MAGIC = 0x187
|
||||
B0 = 0x0
|
||||
B110 = 0x3
|
||||
@@ -184,6 +484,7 @@ const (
|
||||
BPF_F_ALLOW_MULTI = 0x2
|
||||
BPF_F_ALLOW_OVERRIDE = 0x1
|
||||
BPF_F_ANY_ALIGNMENT = 0x2
|
||||
BPF_F_KPROBE_MULTI_RETURN = 0x1
|
||||
BPF_F_QUERY_EFFECTIVE = 0x1
|
||||
BPF_F_REPLACE = 0x4
|
||||
BPF_F_SLEEPABLE = 0x10
|
||||
@@ -191,6 +492,8 @@ const (
|
||||
BPF_F_TEST_RND_HI32 = 0x4
|
||||
BPF_F_TEST_RUN_ON_CPU = 0x1
|
||||
BPF_F_TEST_STATE_FREQ = 0x8
|
||||
BPF_F_TEST_XDP_LIVE_FRAMES = 0x2
|
||||
BPF_F_XDP_HAS_FRAGS = 0x20
|
||||
BPF_H = 0x8
|
||||
BPF_IMM = 0x0
|
||||
BPF_IND = 0x40
|
||||
@@ -517,9 +820,9 @@ const (
|
||||
DM_UUID_FLAG = 0x4000
|
||||
DM_UUID_LEN = 0x81
|
||||
DM_VERSION = 0xc138fd00
|
||||
DM_VERSION_EXTRA = "-ioctl (2021-03-22)"
|
||||
DM_VERSION_EXTRA = "-ioctl (2022-02-22)"
|
||||
DM_VERSION_MAJOR = 0x4
|
||||
DM_VERSION_MINOR = 0x2d
|
||||
DM_VERSION_MINOR = 0x2e
|
||||
DM_VERSION_PATCHLEVEL = 0x0
|
||||
DT_BLK = 0x6
|
||||
DT_CHR = 0x2
|
||||
@@ -535,6 +838,55 @@ const (
|
||||
EFD_SEMAPHORE = 0x1
|
||||
EFIVARFS_MAGIC = 0xde5e81e4
|
||||
EFS_SUPER_MAGIC = 0x414a53
|
||||
EM_386 = 0x3
|
||||
EM_486 = 0x6
|
||||
EM_68K = 0x4
|
||||
EM_860 = 0x7
|
||||
EM_88K = 0x5
|
||||
EM_AARCH64 = 0xb7
|
||||
EM_ALPHA = 0x9026
|
||||
EM_ALTERA_NIOS2 = 0x71
|
||||
EM_ARCOMPACT = 0x5d
|
||||
EM_ARCV2 = 0xc3
|
||||
EM_ARM = 0x28
|
||||
EM_BLACKFIN = 0x6a
|
||||
EM_BPF = 0xf7
|
||||
EM_CRIS = 0x4c
|
||||
EM_CSKY = 0xfc
|
||||
EM_CYGNUS_M32R = 0x9041
|
||||
EM_CYGNUS_MN10300 = 0xbeef
|
||||
EM_FRV = 0x5441
|
||||
EM_H8_300 = 0x2e
|
||||
EM_HEXAGON = 0xa4
|
||||
EM_IA_64 = 0x32
|
||||
EM_LOONGARCH = 0x102
|
||||
EM_M32 = 0x1
|
||||
EM_M32R = 0x58
|
||||
EM_MICROBLAZE = 0xbd
|
||||
EM_MIPS = 0x8
|
||||
EM_MIPS_RS3_LE = 0xa
|
||||
EM_MIPS_RS4_BE = 0xa
|
||||
EM_MN10300 = 0x59
|
||||
EM_NDS32 = 0xa7
|
||||
EM_NONE = 0x0
|
||||
EM_OPENRISC = 0x5c
|
||||
EM_PARISC = 0xf
|
||||
EM_PPC = 0x14
|
||||
EM_PPC64 = 0x15
|
||||
EM_RISCV = 0xf3
|
||||
EM_S390 = 0x16
|
||||
EM_S390_OLD = 0xa390
|
||||
EM_SH = 0x2a
|
||||
EM_SPARC = 0x2
|
||||
EM_SPARC32PLUS = 0x12
|
||||
EM_SPARCV9 = 0x2b
|
||||
EM_SPU = 0x17
|
||||
EM_TILEGX = 0xbf
|
||||
EM_TILEPRO = 0xbc
|
||||
EM_TI_C6000 = 0x8c
|
||||
EM_UNICORE = 0x6e
|
||||
EM_X86_64 = 0x3e
|
||||
EM_XTENSA = 0x5e
|
||||
ENCODING_DEFAULT = 0x0
|
||||
ENCODING_FM_MARK = 0x3
|
||||
ENCODING_FM_SPACE = 0x4
|
||||
@@ -712,6 +1064,7 @@ const (
|
||||
ETH_P_EDSA = 0xdada
|
||||
ETH_P_ERSPAN = 0x88be
|
||||
ETH_P_ERSPAN2 = 0x22eb
|
||||
ETH_P_ETHERCAT = 0x88a4
|
||||
ETH_P_FCOE = 0x8906
|
||||
ETH_P_FIP = 0x8914
|
||||
ETH_P_HDLC = 0x19
|
||||
@@ -749,6 +1102,7 @@ const (
|
||||
ETH_P_PPP_MP = 0x8
|
||||
ETH_P_PPP_SES = 0x8864
|
||||
ETH_P_PREAUTH = 0x88c7
|
||||
ETH_P_PROFINET = 0x8892
|
||||
ETH_P_PRP = 0x88fb
|
||||
ETH_P_PUP = 0x200
|
||||
ETH_P_PUPAT = 0x201
|
||||
@@ -837,6 +1191,7 @@ const (
|
||||
FAN_FS_ERROR = 0x8000
|
||||
FAN_MARK_ADD = 0x1
|
||||
FAN_MARK_DONT_FOLLOW = 0x4
|
||||
FAN_MARK_EVICTABLE = 0x200
|
||||
FAN_MARK_FILESYSTEM = 0x100
|
||||
FAN_MARK_FLUSH = 0x80
|
||||
FAN_MARK_IGNORED_MASK = 0x20
|
||||
@@ -1055,7 +1410,7 @@ const (
|
||||
IFA_F_STABLE_PRIVACY = 0x800
|
||||
IFA_F_TEMPORARY = 0x1
|
||||
IFA_F_TENTATIVE = 0x40
|
||||
IFA_MAX = 0xa
|
||||
IFA_MAX = 0xb
|
||||
IFF_ALLMULTI = 0x200
|
||||
IFF_ATTACH_QUEUE = 0x200
|
||||
IFF_AUTOMEDIA = 0x4000
|
||||
@@ -1403,6 +1758,7 @@ const (
|
||||
LANDLOCK_ACCESS_FS_MAKE_SYM = 0x1000
|
||||
LANDLOCK_ACCESS_FS_READ_DIR = 0x8
|
||||
LANDLOCK_ACCESS_FS_READ_FILE = 0x4
|
||||
LANDLOCK_ACCESS_FS_REFER = 0x2000
|
||||
LANDLOCK_ACCESS_FS_REMOVE_DIR = 0x10
|
||||
LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20
|
||||
LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2
|
||||
@@ -1758,6 +2114,7 @@ const (
|
||||
NLM_F_ACK_TLVS = 0x200
|
||||
NLM_F_APPEND = 0x800
|
||||
NLM_F_ATOMIC = 0x400
|
||||
NLM_F_BULK = 0x200
|
||||
NLM_F_CAPPED = 0x100
|
||||
NLM_F_CREATE = 0x400
|
||||
NLM_F_DUMP = 0x300
|
||||
@@ -2075,6 +2432,11 @@ const (
|
||||
PR_SET_UNALIGN = 0x6
|
||||
PR_SET_VMA = 0x53564d41
|
||||
PR_SET_VMA_ANON_NAME = 0x0
|
||||
PR_SME_GET_VL = 0x40
|
||||
PR_SME_SET_VL = 0x3f
|
||||
PR_SME_SET_VL_ONEXEC = 0x40000
|
||||
PR_SME_VL_INHERIT = 0x20000
|
||||
PR_SME_VL_LEN_MASK = 0xffff
|
||||
PR_SPEC_DISABLE = 0x4
|
||||
PR_SPEC_DISABLE_NOEXEC = 0x10
|
||||
PR_SPEC_ENABLE = 0x2
|
||||
@@ -2227,8 +2589,9 @@ const (
|
||||
RTC_FEATURE_ALARM = 0x0
|
||||
RTC_FEATURE_ALARM_RES_2S = 0x3
|
||||
RTC_FEATURE_ALARM_RES_MINUTE = 0x1
|
||||
RTC_FEATURE_ALARM_WAKEUP_ONLY = 0x7
|
||||
RTC_FEATURE_BACKUP_SWITCH_MODE = 0x6
|
||||
RTC_FEATURE_CNT = 0x7
|
||||
RTC_FEATURE_CNT = 0x8
|
||||
RTC_FEATURE_CORRECTION = 0x5
|
||||
RTC_FEATURE_NEED_WEEK_DAY = 0x2
|
||||
RTC_FEATURE_UPDATE_INTERRUPT = 0x4
|
||||
@@ -2302,6 +2665,7 @@ const (
|
||||
RTM_DELRULE = 0x21
|
||||
RTM_DELTCLASS = 0x29
|
||||
RTM_DELTFILTER = 0x2d
|
||||
RTM_DELTUNNEL = 0x79
|
||||
RTM_DELVLAN = 0x71
|
||||
RTM_F_CLONED = 0x200
|
||||
RTM_F_EQUALIZE = 0x400
|
||||
@@ -2334,8 +2698,9 @@ const (
|
||||
RTM_GETSTATS = 0x5e
|
||||
RTM_GETTCLASS = 0x2a
|
||||
RTM_GETTFILTER = 0x2e
|
||||
RTM_GETTUNNEL = 0x7a
|
||||
RTM_GETVLAN = 0x72
|
||||
RTM_MAX = 0x77
|
||||
RTM_MAX = 0x7b
|
||||
RTM_NEWACTION = 0x30
|
||||
RTM_NEWADDR = 0x14
|
||||
RTM_NEWADDRLABEL = 0x48
|
||||
@@ -2359,11 +2724,13 @@ const (
|
||||
RTM_NEWSTATS = 0x5c
|
||||
RTM_NEWTCLASS = 0x28
|
||||
RTM_NEWTFILTER = 0x2c
|
||||
RTM_NR_FAMILIES = 0x1a
|
||||
RTM_NR_MSGTYPES = 0x68
|
||||
RTM_NEWTUNNEL = 0x78
|
||||
RTM_NR_FAMILIES = 0x1b
|
||||
RTM_NR_MSGTYPES = 0x6c
|
||||
RTM_SETDCB = 0x4f
|
||||
RTM_SETLINK = 0x13
|
||||
RTM_SETNEIGHTBL = 0x43
|
||||
RTM_SETSTATS = 0x5f
|
||||
RTNH_ALIGNTO = 0x4
|
||||
RTNH_COMPARE_MASK = 0x59
|
||||
RTNH_F_DEAD = 0x1
|
||||
@@ -2544,6 +2911,9 @@ const (
|
||||
SOCK_RDM = 0x4
|
||||
SOCK_SEQPACKET = 0x5
|
||||
SOCK_SNDBUF_LOCK = 0x1
|
||||
SOCK_TXREHASH_DEFAULT = 0xff
|
||||
SOCK_TXREHASH_DISABLED = 0x0
|
||||
SOCK_TXREHASH_ENABLED = 0x1
|
||||
SOL_AAL = 0x109
|
||||
SOL_ALG = 0x117
|
||||
SOL_ATM = 0x108
|
||||
@@ -2559,6 +2929,8 @@ const (
|
||||
SOL_IUCV = 0x115
|
||||
SOL_KCM = 0x119
|
||||
SOL_LLC = 0x10c
|
||||
SOL_MCTP = 0x11d
|
||||
SOL_MPTCP = 0x11c
|
||||
SOL_NETBEUI = 0x10b
|
||||
SOL_NETLINK = 0x10e
|
||||
SOL_NFC = 0x118
|
||||
@@ -2568,6 +2940,7 @@ const (
|
||||
SOL_RAW = 0xff
|
||||
SOL_RDS = 0x114
|
||||
SOL_RXRPC = 0x110
|
||||
SOL_SMC = 0x11e
|
||||
SOL_TCP = 0x6
|
||||
SOL_TIPC = 0x10f
|
||||
SOL_TLS = 0x11a
|
||||
@@ -2674,7 +3047,7 @@ const (
|
||||
TASKSTATS_GENL_NAME = "TASKSTATS"
|
||||
TASKSTATS_GENL_VERSION = 0x1
|
||||
TASKSTATS_TYPE_MAX = 0x6
|
||||
TASKSTATS_VERSION = 0xb
|
||||
TASKSTATS_VERSION = 0xd
|
||||
TCIFLUSH = 0x0
|
||||
TCIOFF = 0x2
|
||||
TCIOFLUSH = 0x2
|
||||
|
||||
+2
@@ -326,6 +326,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
@@ -350,6 +351,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -327,6 +327,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
@@ -351,6 +352,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -333,6 +333,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
@@ -357,6 +358,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+3
@@ -323,6 +323,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
@@ -347,6 +348,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
@@ -511,6 +513,7 @@ const (
|
||||
WORDSIZE = 0x40
|
||||
XCASE = 0x4
|
||||
XTABS = 0x1800
|
||||
ZA_MAGIC = 0x54366345
|
||||
_HIDIOCGRAWNAME = 0x80804804
|
||||
_HIDIOCGRAWPHYS = 0x80404805
|
||||
_HIDIOCGRAWUNIQ = 0x80404808
|
||||
|
||||
+2
-2
@@ -109,8 +109,6 @@ const (
|
||||
IUCLC = 0x200
|
||||
IXOFF = 0x1000
|
||||
IXON = 0x400
|
||||
LASX_CTX_MAGIC = 0x41535801
|
||||
LSX_CTX_MAGIC = 0x53580001
|
||||
MAP_ANON = 0x20
|
||||
MAP_ANONYMOUS = 0x20
|
||||
MAP_DENYWRITE = 0x800
|
||||
@@ -319,6 +317,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
@@ -343,6 +342,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -326,6 +326,7 @@ const (
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x1006
|
||||
@@ -351,6 +352,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x1008
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -326,6 +326,7 @@ const (
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x1006
|
||||
@@ -351,6 +352,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x1008
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -326,6 +326,7 @@ const (
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x1006
|
||||
@@ -351,6 +352,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x1008
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -326,6 +326,7 @@ const (
|
||||
SO_RCVBUF = 0x1002
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x1004
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x1006
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x1006
|
||||
@@ -351,6 +352,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x1008
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -381,6 +381,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x10
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x12
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x12
|
||||
@@ -405,6 +406,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -385,6 +385,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x10
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x12
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x12
|
||||
@@ -409,6 +410,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -385,6 +385,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x10
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x12
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x12
|
||||
@@ -409,6 +410,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
+2
@@ -314,6 +314,7 @@ const (
|
||||
SO_RCVBUF = 0x8
|
||||
SO_RCVBUFFORCE = 0x21
|
||||
SO_RCVLOWAT = 0x12
|
||||
SO_RCVMARK = 0x4b
|
||||
SO_RCVTIMEO = 0x14
|
||||
SO_RCVTIMEO_NEW = 0x42
|
||||
SO_RCVTIMEO_OLD = 0x14
|
||||
@@ -338,6 +339,7 @@ const (
|
||||
SO_TIMESTAMPNS_NEW = 0x40
|
||||
SO_TIMESTAMPNS_OLD = 0x23
|
||||
SO_TIMESTAMP_NEW = 0x3f
|
||||
SO_TXREHASH = 0x4a
|
||||
SO_TXTIME = 0x3d
|
||||
SO_TYPE = 0x3
|
||||
SO_WIFI_STATUS = 0x29
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user