mirror of
https://github.com/containers/podman.git
synced 2025-06-13 19:52:11 +08:00
upgrade all dependencies
The dependabot does not update dependencies when they do not use a tag. This patch upgrades all untagged depenencies if possible. You can upgrade all dependencies with `go get -u ./... && make vendor` in theory however this failed since the k8s changes do not compile on go v1.16 so I only updated the other dependencies. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
go.modgo.summodules.txt
vendor
github.com
buger/goterm
.gitignorebox.gogo.modgo.sumplot.goterminal.goterminal_nosysioctl.goterminal_sysioctl.goterminal_windows.go
docker/go-plugins-helpers/volume
felixge/httpsnoop
.gitignore.travis.ymlLICENSE.txtMakefileREADME.mdcapture_metrics.godocs.gogo.modwrap_generated_gteq_1.8.gowrap_generated_lt_1.8.go
google/shlex
gorilla/handlers
.travis.ymlREADME.mdcanonical.gocompress.gocors.gogo.modgo.sumhandlers.gologging.goproxy_headers.gorecovery.go
opencontainers
runc/libcontainer
apparmor
cgroups
configs
cgroup_linux.gocgroup_unsupported.goconfig.goconfig_linux.goconfigs_fuzzer.gointelrdt.gomount.gonamespaces_syscall.gonamespaces_syscall_unsupported.gonamespaces_unsupported.gordma.go
devices
user
userns
utils
runtime-spec/specs-go
runtime-tools
seccomp/libseccomp-golang
vishvananda/netlink
.travis.ymlREADME.mdaddr_linux.gobpf_linux.goclass_linux.goconntrack_linux.godevlink_linux.gofilter.gofilter_linux.gohandle_linux.gohandle_unspecified.goipset_linux.golink.golink_linux.goneigh.goneigh_linux.gonetlink_unspecified.gonetns_linux.go
nl
conntrack_linux.godevlink_linux.golink_linux.golwt_linux.gonl_linux.gordma_link_linux.goseg6_linux.gosyscall.gotc_linux.go
proc_event.goqdisc_linux.gordma_link_linux.goroute.goroute_linux.gorule.gorule_linux.gosocket_linux.goxfrm_state_linux.gogolang.org/x/sys
unix
zerrors_linux.gozerrors_linux_386.gozerrors_linux_amd64.gozerrors_linux_arm.gozerrors_linux_arm64.gozerrors_linux_mips.gozerrors_linux_mips64.gozerrors_linux_mips64le.gozerrors_linux_mipsle.gozerrors_linux_ppc.gozerrors_linux_ppc64.gozerrors_linux_ppc64le.gozerrors_linux_riscv64.gozerrors_linux_s390x.gozerrors_linux_sparc64.gozsysnum_linux_386.gozsysnum_linux_amd64.gozsysnum_linux_arm.gozsysnum_linux_arm64.gozsysnum_linux_mips.gozsysnum_linux_mips64.gozsysnum_linux_mips64le.gozsysnum_linux_mipsle.gozsysnum_linux_ppc.gozsysnum_linux_ppc64.gozsysnum_linux_ppc64le.gozsysnum_linux_riscv64.gozsysnum_linux_s390x.gozsysnum_linux_sparc64.goztypes_linux.go
windows
24
go.mod
24
go.mod
@ -5,7 +5,7 @@ go 1.16
|
|||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.0.0
|
github.com/BurntSushi/toml v1.0.0
|
||||||
github.com/blang/semver v3.5.1+incompatible
|
github.com/blang/semver v3.5.1+incompatible
|
||||||
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
|
github.com/buger/goterm v1.0.1
|
||||||
github.com/checkpoint-restore/checkpointctl v0.0.0-20211204171957-54b4ebfdb681
|
github.com/checkpoint-restore/checkpointctl v0.0.0-20211204171957-54b4ebfdb681
|
||||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0
|
github.com/checkpoint-restore/go-criu/v5 v5.3.0
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20220111162300-46367ec063fd
|
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20220111162300-46367ec063fd
|
||||||
@ -22,19 +22,19 @@ require (
|
|||||||
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
|
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
|
||||||
github.com/cyphar/filepath-securejoin v0.2.3
|
github.com/cyphar/filepath-securejoin v0.2.3
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f
|
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
|
||||||
github.com/docker/distribution v2.7.1+incompatible
|
github.com/docker/distribution v2.7.1+incompatible
|
||||||
github.com/docker/docker v20.10.12+incompatible
|
github.com/docker/docker v20.10.12+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc
|
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/docker/go-units v0.4.0
|
||||||
github.com/dtylman/scp v0.0.0-20181017070807-f3000a34aef4
|
github.com/dtylman/scp v0.0.0-20181017070807-f3000a34aef4
|
||||||
github.com/fsnotify/fsnotify v1.5.1
|
github.com/fsnotify/fsnotify v1.5.1
|
||||||
github.com/ghodss/yaml v1.0.0
|
github.com/ghodss/yaml v1.0.0
|
||||||
github.com/godbus/dbus/v5 v5.0.6
|
github.com/godbus/dbus/v5 v5.0.6
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33
|
github.com/gorilla/handlers v1.5.1
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/gorilla/schema v1.2.0
|
github.com/gorilla/schema v1.2.0
|
||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
@ -46,10 +46,10 @@ require (
|
|||||||
github.com/onsi/ginkgo v1.16.5
|
github.com/onsi/ginkgo v1.16.5
|
||||||
github.com/onsi/gomega v1.17.0
|
github.com/onsi/gomega v1.17.0
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.0.3-0.20211215212317-ea0209f50ae1
|
github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198
|
||||||
github.com/opencontainers/runc v1.1.0
|
github.com/opencontainers/runc v1.0.3
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab
|
||||||
github.com/opencontainers/runtime-tools v0.9.1-0.20211020193359-09d837bf40a7
|
github.com/opencontainers/runtime-tools v0.9.1-0.20220110225228-7e2d60f1e41f
|
||||||
github.com/opencontainers/selinux v1.10.0
|
github.com/opencontainers/selinux v1.10.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
github.com/pmezard/go-difflib v1.0.0
|
||||||
@ -62,11 +62,11 @@ require (
|
|||||||
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
||||||
github.com/ulikunitz/xz v0.5.10
|
github.com/ulikunitz/xz v0.5.10
|
||||||
github.com/vbauerster/mpb/v6 v6.0.4
|
github.com/vbauerster/mpb/v6 v6.0.4
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
|
github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4
|
||||||
go.etcd.io/bbolt v1.3.6
|
go.etcd.io/bbolt v1.3.6
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
|
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
||||||
golang.org/x/text v0.3.7
|
golang.org/x/text v0.3.7
|
||||||
google.golang.org/protobuf v1.27.1
|
google.golang.org/protobuf v1.27.1
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
|
56
go.sum
56
go.sum
@ -160,6 +160,7 @@ github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edY
|
|||||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||||
github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI=
|
github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI=
|
||||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
|
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec=
|
github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec=
|
||||||
@ -167,8 +168,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR
|
|||||||
github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
|
github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
|
||||||
github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso=
|
github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso=
|
||||||
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||||
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37 h1:uxxtrnACqI9zK4ENDMf0WpXfUsHP5V8liuq5QdgDISU=
|
github.com/buger/goterm v1.0.1 h1:kSgw3jcjYUzC0Uh/eG8ULjccuz353solup27lUH8Zug=
|
||||||
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U=
|
github.com/buger/goterm v1.0.1/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=
|
||||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||||
@ -203,7 +204,6 @@ github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLI
|
|||||||
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
|
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
|
||||||
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
@ -240,7 +240,6 @@ github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on
|
|||||||
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
|
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
|
||||||
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
|
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
|
||||||
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
||||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
|
||||||
github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
@ -388,8 +387,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
|||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
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-20201209184759-e2a69bcd5bd1 h1:j6vGflaQ2T7yOWqVgPdiRF73j/U2Zmpbbzab8nyDCRQ=
|
github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1 h1:j6vGflaQ2T7yOWqVgPdiRF73j/U2Zmpbbzab8nyDCRQ=
|
||||||
github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1/go.mod h1:QS1XzqZLcDniNYrN7EZefq3wIyb/M2WmJbql4ZKoc1Q=
|
github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1/go.mod h1:QS1XzqZLcDniNYrN7EZefq3wIyb/M2WmJbql4ZKoc1Q=
|
||||||
github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f h1:N2HvbwONtcvzegFxOAgGt15JsajIk5QzY3j5X3VzFDI=
|
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001 h1:WAg57gnaAWWjMAELcwHjc2xy0PoXQ5G+vn3+XS6s1jI=
|
||||||
github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f/go.mod h1:IetBE52JfFxK46p2n2Rqm+p5Gx1gpu2hRHsrbnPOWZQ=
|
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001/go.mod h1:IetBE52JfFxK46p2n2Rqm+p5Gx1gpu2hRHsrbnPOWZQ=
|
||||||
github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWhkNRq8=
|
github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWhkNRq8=
|
||||||
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
|
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
@ -411,8 +410,8 @@ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6Uezg
|
|||||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||||
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
||||||
github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc h1:/A+mPcpajLsWiX9gSnzdVKM/IzZoYiNqXHe83z50k2c=
|
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651 h1:YcvzLmdrP/b8kLAGJ8GT7bdncgCAiWxJZIlt84D+RJg=
|
||||||
github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc/go.mod h1:LFyLie6XcDbyKGeVK6bHe+9aJTYCxWLBg5IrJZOaXKA=
|
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651/go.mod h1:LFyLie6XcDbyKGeVK6bHe+9aJTYCxWLBg5IrJZOaXKA=
|
||||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316 h1:moehPjPiGUaWdwgOl92xRyFHJyaqXDHcCyW9M6nmCK4=
|
github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316 h1:moehPjPiGUaWdwgOl92xRyFHJyaqXDHcCyW9M6nmCK4=
|
||||||
@ -452,6 +451,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
|
|||||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||||
|
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||||
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
@ -620,8 +621,8 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe
|
|||||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||||
github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw=
|
github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw=
|
||||||
github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@ -642,8 +643,9 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR
|
|||||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||||
github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw=
|
github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw=
|
||||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
|
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
|
||||||
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo=
|
|
||||||
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||||
|
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||||
|
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||||
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
@ -899,6 +901,7 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
|||||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
|
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
|
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
|
||||||
@ -976,29 +979,30 @@ github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
|
|||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.3-0.20211202193544-a5463b7f9c84/go.mod h1:Qnt1q4cjDNQI9bT832ziho5Iw2BhK8o1KwLOwW56VP4=
|
github.com/opencontainers/image-spec v1.0.3-0.20211202193544-a5463b7f9c84/go.mod h1:Qnt1q4cjDNQI9bT832ziho5Iw2BhK8o1KwLOwW56VP4=
|
||||||
github.com/opencontainers/image-spec v1.0.3-0.20211215212317-ea0209f50ae1 h1:R0VgKjcNQhH6AKteTyHcdoTgGRGEYZhXT05Gv1LJLh4=
|
github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 h1:+czc/J8SlhPKLOtVLMQc+xDCFBT73ZStMsRhSsUhsSg=
|
||||||
github.com/opencontainers/image-spec v1.0.3-0.20211215212317-ea0209f50ae1/go.mod h1:j4h1pJW6ZcJTgMZWP3+7RlG3zTaP02aDZ/Qw0sppK7Q=
|
github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198/go.mod h1:j4h1pJW6ZcJTgMZWP3+7RlG3zTaP02aDZ/Qw0sppK7Q=
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
|
github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
|
||||||
github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8=
|
|
||||||
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
|
||||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20201121164853-7413a7f753e1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
|
github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab h1:YQZXa3elcHgKXAa2GjVFC9M3JeP7ZPyFD1YByDx/dgQ=
|
||||||
|
github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||||
github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||||
github.com/opencontainers/runtime-tools v0.9.1-0.20211020193359-09d837bf40a7 h1:6JHkPc2wUOsj2XBpYzyvmCL5Y/fA3TFaomYv/Iggt1g=
|
github.com/opencontainers/runtime-tools v0.9.1-0.20220110225228-7e2d60f1e41f h1:MMcsVl0FAVEahmXTy+uXoDTw3yJq7nGrK8ITs/kkreo=
|
||||||
github.com/opencontainers/runtime-tools v0.9.1-0.20211020193359-09d837bf40a7/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-tools v0.9.1-0.20220110225228-7e2d60f1e41f/go.mod h1:/tgP02fPXGHkU3/qKK1Y0Db4yqNyGm03vLq/mzHzcS4=
|
||||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
@ -1110,9 +1114,8 @@ github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZ
|
|||||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||||
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf h1:b0+ZBD3rohnkQ4q5duD1+RyTXTg9yk+qTOPMSQtapO0=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 h1:58EBmR2dMNL2n/FnbQewK3D14nXr0V9CObDSvMJLq+Y=
|
|
||||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
|
||||||
github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc=
|
github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs=
|
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs=
|
||||||
@ -1217,6 +1220,7 @@ github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0o
|
|||||||
github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
|
github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
|
||||||
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
|
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
|
||||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
@ -1237,8 +1241,9 @@ github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG
|
|||||||
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA=
|
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||||
|
github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4 h1:fB26rIBlWTVJyEB6ONHdoEvUbvwoudH0/cMEXHiD1RU=
|
||||||
|
github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||||
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
|
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
|
||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
@ -1330,8 +1335,9 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
|
|||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI=
|
||||||
|
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -1558,6 +1564,7 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -1575,7 +1582,6 @@ golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -1584,11 +1590,11 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d h1:1oIt9o40TWWI9FUaveVpUvBe13FNqBNVXy3ue2fcfkw=
|
|
||||||
golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
||||||
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||||
|
1
vendor/github.com/buger/goterm/.gitignore
generated
vendored
Normal file
1
vendor/github.com/buger/goterm/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.swp
|
66
vendor/github.com/buger/goterm/box.go
generated
vendored
66
vendor/github.com/buger/goterm/box.go
generated
vendored
@ -2,7 +2,9 @@ package goterm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
_ "unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DEFAULT_BORDER = "- │ ┌ ┐ └ ┘"
|
const DEFAULT_BORDER = "- │ ┌ ┐ └ ┘"
|
||||||
@ -61,7 +63,9 @@ func (b *Box) Write(p []byte) (int, error) {
|
|||||||
return b.Buf.Write(p)
|
return b.Buf.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render Box
|
var ANSI_RE = regexp.MustCompile(`\\0\d+\[\d+(?:;\d+)?m`)
|
||||||
|
|
||||||
|
// String renders Box
|
||||||
func (b *Box) String() (out string) {
|
func (b *Box) String() (out string) {
|
||||||
borders := strings.Split(b.Border, " ")
|
borders := strings.Split(b.Border, " ")
|
||||||
lines := strings.Split(b.Buf.String(), "\n")
|
lines := strings.Split(b.Buf.String(), "\n")
|
||||||
@ -74,7 +78,6 @@ func (b *Box) String() (out string) {
|
|||||||
|
|
||||||
// Content width without borders and padding
|
// Content width without borders and padding
|
||||||
contentWidth := b.Width - (b.PaddingX+1)*2
|
contentWidth := b.Width - (b.PaddingX+1)*2
|
||||||
|
|
||||||
for y := 0; y < b.Height; y++ {
|
for y := 0; y < b.Height; y++ {
|
||||||
var line string
|
var line string
|
||||||
|
|
||||||
@ -99,12 +102,63 @@ func (b *Box) String() (out string) {
|
|||||||
line = ""
|
line = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(line) > contentWidth-1 {
|
r := []rune(line)
|
||||||
|
|
||||||
|
lastAnsii := ""
|
||||||
|
withoutAnsii := []rune{}
|
||||||
|
withOffset := []rune{}
|
||||||
|
i := 0
|
||||||
|
|
||||||
|
for {
|
||||||
|
if i >= len(r) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if r[i] == 27 {
|
||||||
|
lastAnsii = ""
|
||||||
|
withOffset = append(withOffset, r[i])
|
||||||
|
lastAnsii += string(r[i])
|
||||||
|
i++
|
||||||
|
for {
|
||||||
|
|
||||||
|
i++
|
||||||
|
if i > len(r) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
withOffset = append(withOffset, r[i])
|
||||||
|
lastAnsii += string(r[i])
|
||||||
|
|
||||||
|
if r[i] == 'm' {
|
||||||
|
i++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= len(r) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
withoutAnsii = append(withoutAnsii, r[i])
|
||||||
|
|
||||||
|
if len(withoutAnsii) <= contentWidth {
|
||||||
|
withOffset = append(withOffset, r[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(withoutAnsii) > contentWidth {
|
||||||
// If line is too large limit it
|
// If line is too large limit it
|
||||||
line = line[0:contentWidth]
|
line = string(withOffset)
|
||||||
} else {
|
} else {
|
||||||
// If line is too small enlarge it by adding spaces
|
// If line is too small enlarge it by adding spaces
|
||||||
line = line + strings.Repeat(" ", contentWidth-len(line))
|
line += strings.Repeat(" ", contentWidth-len(withoutAnsii))
|
||||||
|
}
|
||||||
|
|
||||||
|
if lastAnsii != "" {
|
||||||
|
line += RESET
|
||||||
}
|
}
|
||||||
|
|
||||||
line = prefix + line + suffix
|
line = prefix + line + suffix
|
||||||
@ -112,7 +166,7 @@ func (b *Box) String() (out string) {
|
|||||||
|
|
||||||
// Don't add newline for last element
|
// Don't add newline for last element
|
||||||
if y != b.Height-1 {
|
if y != b.Height-1 {
|
||||||
line = line + "\n"
|
line += "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
out += line
|
out += line
|
||||||
|
5
vendor/github.com/buger/goterm/go.mod
generated
vendored
Normal file
5
vendor/github.com/buger/goterm/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module github.com/buger/goterm
|
||||||
|
|
||||||
|
go 1.15
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54
|
2
vendor/github.com/buger/goterm/go.sum
generated
vendored
Normal file
2
vendor/github.com/buger/goterm/go.sum
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0=
|
||||||
|
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
3
vendor/github.com/buger/goterm/plot.go
generated
vendored
3
vendor/github.com/buger/goterm/plot.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -119,7 +120,7 @@ func (c *LineChart) DrawAxes(maxX, minX, maxY, minY float64, index int) {
|
|||||||
c.writeText(ff(minX), c.paddingX, 0)
|
c.writeText(ff(minX), c.paddingX, 0)
|
||||||
|
|
||||||
x_col := c.data.columns[0]
|
x_col := c.data.columns[0]
|
||||||
c.writeText(c.data.columns[0], c.Width/2-len(x_col)/2, 1)
|
c.writeText(c.data.columns[0], c.Width/2-utf8.RuneCountInString(x_col)/2, 1)
|
||||||
|
|
||||||
if c.Flags&DRAW_INDEPENDENT != 0 || len(c.data.columns) < 3 {
|
if c.Flags&DRAW_INDEPENDENT != 0 || len(c.data.columns) < 3 {
|
||||||
col := c.data.columns[index]
|
col := c.data.columns[index]
|
||||||
|
10
vendor/github.com/buger/goterm/terminal.go
generated
vendored
10
vendor/github.com/buger/goterm/terminal.go
generated
vendored
@ -71,7 +71,7 @@ type winsize struct {
|
|||||||
// Its not recommended write to buffer dirrectly, use package Print,Printf,Println fucntions instead.
|
// Its not recommended write to buffer dirrectly, use package Print,Printf,Println fucntions instead.
|
||||||
var Screen *bytes.Buffer = new(bytes.Buffer)
|
var Screen *bytes.Buffer = new(bytes.Buffer)
|
||||||
|
|
||||||
// Get relative or absolute coordinates
|
// GetXY gets relative or absolute coordinates
|
||||||
// To get relative, set PCT flag to number:
|
// To get relative, set PCT flag to number:
|
||||||
//
|
//
|
||||||
// // Get 10% of total width to `x` and 20 to y
|
// // Get 10% of total width to `x` and 20 to y
|
||||||
@ -145,7 +145,7 @@ func MoveTo(str string, x int, y int) (out string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return carrier to start of line
|
// ResetLine returns carrier to start of line
|
||||||
func ResetLine(str string) (out string) {
|
func ResetLine(str string) (out string) {
|
||||||
return applyTransform(str, func(idx int, line string) string {
|
return applyTransform(str, func(idx int, line string) string {
|
||||||
return fmt.Sprintf("%s%s", RESET_LINE, line)
|
return fmt.Sprintf("%s%s", RESET_LINE, line)
|
||||||
@ -188,7 +188,7 @@ func Background(str string, color int) string {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get console width
|
// Width gets console width
|
||||||
func Width() int {
|
func Width() int {
|
||||||
ws, err := getWinsize()
|
ws, err := getWinsize()
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ func Width() int {
|
|||||||
return int(ws.Col)
|
return int(ws.Col)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get console height
|
// Height gets console height
|
||||||
func Height() int {
|
func Height() int {
|
||||||
ws, err := getWinsize()
|
ws, err := getWinsize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -208,7 +208,7 @@ func Height() int {
|
|||||||
return int(ws.Row)
|
return int(ws.Row)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current height. Line count in Screen buffer.
|
// CurrentHeight gets current height. Line count in Screen buffer.
|
||||||
func CurrentHeight() int {
|
func CurrentHeight() int {
|
||||||
return strings.Count(Screen.String(), "\n")
|
return strings.Count(Screen.String(), "\n")
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/buger/goterm/terminal_nosysioctl.go
generated
vendored
2
vendor/github.com/buger/goterm/terminal_nosysioctl.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// +build windows plan9 solaris
|
// +build plan9 solaris
|
||||||
|
|
||||||
package goterm
|
package goterm
|
||||||
|
|
||||||
|
1
vendor/github.com/buger/goterm/terminal_sysioctl.go
generated
vendored
1
vendor/github.com/buger/goterm/terminal_sysioctl.go
generated
vendored
@ -4,6 +4,7 @@ package goterm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
23
vendor/github.com/buger/goterm/terminal_windows.go
generated
vendored
Normal file
23
vendor/github.com/buger/goterm/terminal_windows.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package goterm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getWinsize() (*winsize, error) {
|
||||||
|
ws := new(winsize)
|
||||||
|
fd := os.Stdout.Fd()
|
||||||
|
var info windows.ConsoleScreenBufferInfo
|
||||||
|
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.Col = uint16(info.Window.Right - info.Window.Left + 1)
|
||||||
|
ws.Row = uint16(info.Window.Bottom - info.Window.Top + 1)
|
||||||
|
|
||||||
|
return ws, nil
|
||||||
|
}
|
9
vendor/github.com/docker/go-plugins-helpers/volume/api.go
generated
vendored
9
vendor/github.com/docker/go-plugins-helpers/volume/api.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
package volume
|
package volume
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/docker/go-plugins-helpers/sdk"
|
"github.com/docker/go-plugins-helpers/sdk"
|
||||||
@ -130,7 +129,6 @@ func NewHandler(driver Driver) *Handler {
|
|||||||
|
|
||||||
func (h *Handler) initMux() {
|
func (h *Handler) initMux() {
|
||||||
h.HandleFunc(createPath, func(w http.ResponseWriter, r *http.Request) {
|
h.HandleFunc(createPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Entering go-plugins-helpers createPath")
|
|
||||||
req := &CreateRequest{}
|
req := &CreateRequest{}
|
||||||
err := sdk.DecodeRequest(w, r, req)
|
err := sdk.DecodeRequest(w, r, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -144,7 +142,6 @@ func (h *Handler) initMux() {
|
|||||||
sdk.EncodeResponse(w, struct{}{}, false)
|
sdk.EncodeResponse(w, struct{}{}, false)
|
||||||
})
|
})
|
||||||
h.HandleFunc(removePath, func(w http.ResponseWriter, r *http.Request) {
|
h.HandleFunc(removePath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Entering go-plugins-helpers removePath")
|
|
||||||
req := &RemoveRequest{}
|
req := &RemoveRequest{}
|
||||||
err := sdk.DecodeRequest(w, r, req)
|
err := sdk.DecodeRequest(w, r, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -158,7 +155,6 @@ func (h *Handler) initMux() {
|
|||||||
sdk.EncodeResponse(w, struct{}{}, false)
|
sdk.EncodeResponse(w, struct{}{}, false)
|
||||||
})
|
})
|
||||||
h.HandleFunc(mountPath, func(w http.ResponseWriter, r *http.Request) {
|
h.HandleFunc(mountPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Entering go-plugins-helpers mountPath")
|
|
||||||
req := &MountRequest{}
|
req := &MountRequest{}
|
||||||
err := sdk.DecodeRequest(w, r, req)
|
err := sdk.DecodeRequest(w, r, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -172,7 +168,6 @@ func (h *Handler) initMux() {
|
|||||||
sdk.EncodeResponse(w, res, false)
|
sdk.EncodeResponse(w, res, false)
|
||||||
})
|
})
|
||||||
h.HandleFunc(hostVirtualPath, func(w http.ResponseWriter, r *http.Request) {
|
h.HandleFunc(hostVirtualPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Entering go-plugins-helpers hostVirtualPath")
|
|
||||||
req := &PathRequest{}
|
req := &PathRequest{}
|
||||||
err := sdk.DecodeRequest(w, r, req)
|
err := sdk.DecodeRequest(w, r, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -186,7 +181,6 @@ func (h *Handler) initMux() {
|
|||||||
sdk.EncodeResponse(w, res, false)
|
sdk.EncodeResponse(w, res, false)
|
||||||
})
|
})
|
||||||
h.HandleFunc(getPath, func(w http.ResponseWriter, r *http.Request) {
|
h.HandleFunc(getPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Entering go-plugins-helpers getPath")
|
|
||||||
req := &GetRequest{}
|
req := &GetRequest{}
|
||||||
err := sdk.DecodeRequest(w, r, req)
|
err := sdk.DecodeRequest(w, r, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -200,7 +194,6 @@ func (h *Handler) initMux() {
|
|||||||
sdk.EncodeResponse(w, res, false)
|
sdk.EncodeResponse(w, res, false)
|
||||||
})
|
})
|
||||||
h.HandleFunc(unmountPath, func(w http.ResponseWriter, r *http.Request) {
|
h.HandleFunc(unmountPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Entering go-plugins-helpers unmountPath")
|
|
||||||
req := &UnmountRequest{}
|
req := &UnmountRequest{}
|
||||||
err := sdk.DecodeRequest(w, r, req)
|
err := sdk.DecodeRequest(w, r, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -214,7 +207,6 @@ func (h *Handler) initMux() {
|
|||||||
sdk.EncodeResponse(w, struct{}{}, false)
|
sdk.EncodeResponse(w, struct{}{}, false)
|
||||||
})
|
})
|
||||||
h.HandleFunc(listPath, func(w http.ResponseWriter, r *http.Request) {
|
h.HandleFunc(listPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Entering go-plugins-helpers listPath")
|
|
||||||
res, err := h.driver.List()
|
res, err := h.driver.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
|
sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
|
||||||
@ -224,7 +216,6 @@ func (h *Handler) initMux() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
h.HandleFunc(capabilitiesPath, func(w http.ResponseWriter, r *http.Request) {
|
h.HandleFunc(capabilitiesPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Entering go-plugins-helpers capabilitiesPath")
|
|
||||||
sdk.EncodeResponse(w, h.driver.Capabilities(), false)
|
sdk.EncodeResponse(w, h.driver.Capabilities(), false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
0
vendor/github.com/felixge/httpsnoop/.gitignore
generated
vendored
Normal file
0
vendor/github.com/felixge/httpsnoop/.gitignore
generated
vendored
Normal file
6
vendor/github.com/felixge/httpsnoop/.travis.yml
generated
vendored
Normal file
6
vendor/github.com/felixge/httpsnoop/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.6
|
||||||
|
- 1.7
|
||||||
|
- 1.8
|
19
vendor/github.com/felixge/httpsnoop/LICENSE.txt
generated
vendored
Normal file
19
vendor/github.com/felixge/httpsnoop/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2016 Felix Geisendörfer (felix@debuggable.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
10
vendor/github.com/felixge/httpsnoop/Makefile
generated
vendored
Normal file
10
vendor/github.com/felixge/httpsnoop/Makefile
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.PHONY: ci generate clean
|
||||||
|
|
||||||
|
ci: clean generate
|
||||||
|
go test -v ./...
|
||||||
|
|
||||||
|
generate:
|
||||||
|
go generate .
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *_generated*.go
|
94
vendor/github.com/felixge/httpsnoop/README.md
generated
vendored
Normal file
94
vendor/github.com/felixge/httpsnoop/README.md
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# httpsnoop
|
||||||
|
|
||||||
|
Package httpsnoop provides an easy way to capture http related metrics (i.e.
|
||||||
|
response time, bytes written, and http status code) from your application's
|
||||||
|
http.Handlers.
|
||||||
|
|
||||||
|
Doing this requires non-trivial wrapping of the http.ResponseWriter interface,
|
||||||
|
which is also exposed for users interested in a more low-level API.
|
||||||
|
|
||||||
|
[](https://godoc.org/github.com/felixge/httpsnoop)
|
||||||
|
[](https://travis-ci.org/felixge/httpsnoop)
|
||||||
|
|
||||||
|
## Usage Example
|
||||||
|
|
||||||
|
```go
|
||||||
|
// myH is your app's http handler, perhaps a http.ServeMux or similar.
|
||||||
|
var myH http.Handler
|
||||||
|
// wrappedH wraps myH in order to log every request.
|
||||||
|
wrappedH := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
m := httpsnoop.CaptureMetrics(myH, w, r)
|
||||||
|
log.Printf(
|
||||||
|
"%s %s (code=%d dt=%s written=%d)",
|
||||||
|
r.Method,
|
||||||
|
r.URL,
|
||||||
|
m.Code,
|
||||||
|
m.Duration,
|
||||||
|
m.Written,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
http.ListenAndServe(":8080", wrappedH)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why this package exists
|
||||||
|
|
||||||
|
Instrumenting an application's http.Handler is surprisingly difficult.
|
||||||
|
|
||||||
|
However if you google for e.g. "capture ResponseWriter status code" you'll find
|
||||||
|
lots of advise and code examples that suggest it to be a fairly trivial
|
||||||
|
undertaking. Unfortunately everything I've seen so far has a high chance of
|
||||||
|
breaking your application.
|
||||||
|
|
||||||
|
The main problem is that a `http.ResponseWriter` often implements additional
|
||||||
|
interfaces such as `http.Flusher`, `http.CloseNotifier`, `http.Hijacker`, `http.Pusher`, and
|
||||||
|
`io.ReaderFrom`. So the naive approach of just wrapping `http.ResponseWriter`
|
||||||
|
in your own struct that also implements the `http.ResponseWriter` interface
|
||||||
|
will hide the additional interfaces mentioned above. This has a high change of
|
||||||
|
introducing subtle bugs into any non-trivial application.
|
||||||
|
|
||||||
|
Another approach I've seen people take is to return a struct that implements
|
||||||
|
all of the interfaces above. However, that's also problematic, because it's
|
||||||
|
difficult to fake some of these interfaces behaviors when the underlying
|
||||||
|
`http.ResponseWriter` doesn't have an implementation. It's also dangerous,
|
||||||
|
because an application may choose to operate differently, merely because it
|
||||||
|
detects the presence of these additional interfaces.
|
||||||
|
|
||||||
|
This package solves this problem by checking which additional interfaces a
|
||||||
|
`http.ResponseWriter` implements, returning a wrapped version implementing the
|
||||||
|
exact same set of interfaces.
|
||||||
|
|
||||||
|
Additionally this package properly handles edge cases such as `WriteHeader` not
|
||||||
|
being called, or called more than once, as well as concurrent calls to
|
||||||
|
`http.ResponseWriter` methods, and even calls happening after the wrapped
|
||||||
|
`ServeHTTP` has already returned.
|
||||||
|
|
||||||
|
Unfortunately this package is not perfect either. It's possible that it is
|
||||||
|
still missing some interfaces provided by the go core (let me know if you find
|
||||||
|
one), and it won't work for applications adding their own interfaces into the
|
||||||
|
mix.
|
||||||
|
|
||||||
|
However, hopefully the explanation above has sufficiently scared you of rolling
|
||||||
|
your own solution to this problem. httpsnoop may still break your application,
|
||||||
|
but at least it tries to avoid it as much as possible.
|
||||||
|
|
||||||
|
Anyway, the real problem here is that smuggling additional interfaces inside
|
||||||
|
`http.ResponseWriter` is a problematic design choice, but it probably goes as
|
||||||
|
deep as the Go language specification itself. But that's okay, I still prefer
|
||||||
|
Go over the alternatives ;).
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
```
|
||||||
|
BenchmarkBaseline-8 20000 94912 ns/op
|
||||||
|
BenchmarkCaptureMetrics-8 20000 95461 ns/op
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, using `CaptureMetrics` on a vanilla http.Handler introduces an
|
||||||
|
overhead of ~500 ns per http request on my machine. However, the margin of
|
||||||
|
error appears to be larger than that, therefor it should be reasonable to
|
||||||
|
assume that the overhead introduced by `CaptureMetrics` is absolutely
|
||||||
|
negligible.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
84
vendor/github.com/felixge/httpsnoop/capture_metrics.go
generated
vendored
Normal file
84
vendor/github.com/felixge/httpsnoop/capture_metrics.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package httpsnoop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Metrics holds metrics captured from CaptureMetrics.
|
||||||
|
type Metrics struct {
|
||||||
|
// Code is the first http response code passed to the WriteHeader func of
|
||||||
|
// the ResponseWriter. If no such call is made, a default code of 200 is
|
||||||
|
// assumed instead.
|
||||||
|
Code int
|
||||||
|
// Duration is the time it took to execute the handler.
|
||||||
|
Duration time.Duration
|
||||||
|
// Written is the number of bytes successfully written by the Write or
|
||||||
|
// ReadFrom function of the ResponseWriter. ResponseWriters may also write
|
||||||
|
// data to their underlaying connection directly (e.g. headers), but those
|
||||||
|
// are not tracked. Therefor the number of Written bytes will usually match
|
||||||
|
// the size of the response body.
|
||||||
|
Written int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// CaptureMetrics wraps the given hnd, executes it with the given w and r, and
|
||||||
|
// returns the metrics it captured from it.
|
||||||
|
func CaptureMetrics(hnd http.Handler, w http.ResponseWriter, r *http.Request) Metrics {
|
||||||
|
return CaptureMetricsFn(w, func(ww http.ResponseWriter) {
|
||||||
|
hnd.ServeHTTP(ww, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CaptureMetricsFn wraps w and calls fn with the wrapped w and returns the
|
||||||
|
// resulting metrics. This is very similar to CaptureMetrics (which is just
|
||||||
|
// sugar on top of this func), but is a more usable interface if your
|
||||||
|
// application doesn't use the Go http.Handler interface.
|
||||||
|
func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metrics {
|
||||||
|
var (
|
||||||
|
start = time.Now()
|
||||||
|
m = Metrics{Code: http.StatusOK}
|
||||||
|
headerWritten bool
|
||||||
|
lock sync.Mutex
|
||||||
|
hooks = Hooks{
|
||||||
|
WriteHeader: func(next WriteHeaderFunc) WriteHeaderFunc {
|
||||||
|
return func(code int) {
|
||||||
|
next(code)
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
if !headerWritten {
|
||||||
|
m.Code = code
|
||||||
|
headerWritten = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Write: func(next WriteFunc) WriteFunc {
|
||||||
|
return func(p []byte) (int, error) {
|
||||||
|
n, err := next(p)
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
m.Written += int64(n)
|
||||||
|
headerWritten = true
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ReadFrom: func(next ReadFromFunc) ReadFromFunc {
|
||||||
|
return func(src io.Reader) (int64, error) {
|
||||||
|
n, err := next(src)
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
headerWritten = true
|
||||||
|
m.Written += n
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
fn(Wrap(w, hooks))
|
||||||
|
m.Duration = time.Since(start)
|
||||||
|
return m
|
||||||
|
}
|
10
vendor/github.com/felixge/httpsnoop/docs.go
generated
vendored
Normal file
10
vendor/github.com/felixge/httpsnoop/docs.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Package httpsnoop provides an easy way to capture http related metrics (i.e.
|
||||||
|
// response time, bytes written, and http status code) from your application's
|
||||||
|
// http.Handlers.
|
||||||
|
//
|
||||||
|
// Doing this requires non-trivial wrapping of the http.ResponseWriter
|
||||||
|
// interface, which is also exposed for users interested in a more low-level
|
||||||
|
// API.
|
||||||
|
package httpsnoop
|
||||||
|
|
||||||
|
//go:generate go run codegen/main.go
|
3
vendor/github.com/felixge/httpsnoop/go.mod
generated
vendored
Normal file
3
vendor/github.com/felixge/httpsnoop/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/felixge/httpsnoop
|
||||||
|
|
||||||
|
go 1.13
|
385
vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go
generated
vendored
Normal file
385
vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go
generated
vendored
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
// +build go1.8
|
||||||
|
// Code generated by "httpsnoop/codegen"; DO NOT EDIT
|
||||||
|
|
||||||
|
package httpsnoop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HeaderFunc is part of the http.ResponseWriter interface.
|
||||||
|
type HeaderFunc func() http.Header
|
||||||
|
|
||||||
|
// WriteHeaderFunc is part of the http.ResponseWriter interface.
|
||||||
|
type WriteHeaderFunc func(code int)
|
||||||
|
|
||||||
|
// WriteFunc is part of the http.ResponseWriter interface.
|
||||||
|
type WriteFunc func(b []byte) (int, error)
|
||||||
|
|
||||||
|
// FlushFunc is part of the http.Flusher interface.
|
||||||
|
type FlushFunc func()
|
||||||
|
|
||||||
|
// CloseNotifyFunc is part of the http.CloseNotifier interface.
|
||||||
|
type CloseNotifyFunc func() <-chan bool
|
||||||
|
|
||||||
|
// HijackFunc is part of the http.Hijacker interface.
|
||||||
|
type HijackFunc func() (net.Conn, *bufio.ReadWriter, error)
|
||||||
|
|
||||||
|
// ReadFromFunc is part of the io.ReaderFrom interface.
|
||||||
|
type ReadFromFunc func(src io.Reader) (int64, error)
|
||||||
|
|
||||||
|
// PushFunc is part of the http.Pusher interface.
|
||||||
|
type PushFunc func(target string, opts *http.PushOptions) error
|
||||||
|
|
||||||
|
// Hooks defines a set of method interceptors for methods included in
|
||||||
|
// http.ResponseWriter as well as some others. You can think of them as
|
||||||
|
// middleware for the function calls they target. See Wrap for more details.
|
||||||
|
type Hooks struct {
|
||||||
|
Header func(HeaderFunc) HeaderFunc
|
||||||
|
WriteHeader func(WriteHeaderFunc) WriteHeaderFunc
|
||||||
|
Write func(WriteFunc) WriteFunc
|
||||||
|
Flush func(FlushFunc) FlushFunc
|
||||||
|
CloseNotify func(CloseNotifyFunc) CloseNotifyFunc
|
||||||
|
Hijack func(HijackFunc) HijackFunc
|
||||||
|
ReadFrom func(ReadFromFunc) ReadFromFunc
|
||||||
|
Push func(PushFunc) PushFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap returns a wrapped version of w that provides the exact same interface
|
||||||
|
// as w. Specifically if w implements any combination of:
|
||||||
|
//
|
||||||
|
// - http.Flusher
|
||||||
|
// - http.CloseNotifier
|
||||||
|
// - http.Hijacker
|
||||||
|
// - io.ReaderFrom
|
||||||
|
// - http.Pusher
|
||||||
|
//
|
||||||
|
// The wrapped version will implement the exact same combination. If no hooks
|
||||||
|
// are set, the wrapped version also behaves exactly as w. Hooks targeting
|
||||||
|
// methods not supported by w are ignored. Any other hooks will intercept the
|
||||||
|
// method they target and may modify the call's arguments and/or return values.
|
||||||
|
// The CaptureMetrics implementation serves as a working example for how the
|
||||||
|
// hooks can be used.
|
||||||
|
func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter {
|
||||||
|
rw := &rw{w: w, h: hooks}
|
||||||
|
_, i0 := w.(http.Flusher)
|
||||||
|
_, i1 := w.(http.CloseNotifier)
|
||||||
|
_, i2 := w.(http.Hijacker)
|
||||||
|
_, i3 := w.(io.ReaderFrom)
|
||||||
|
_, i4 := w.(http.Pusher)
|
||||||
|
switch {
|
||||||
|
// combination 1/32
|
||||||
|
case !i0 && !i1 && !i2 && !i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
}{rw}
|
||||||
|
// combination 2/32
|
||||||
|
case !i0 && !i1 && !i2 && !i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 3/32
|
||||||
|
case !i0 && !i1 && !i2 && i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 4/32
|
||||||
|
case !i0 && !i1 && !i2 && i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
io.ReaderFrom
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 5/32
|
||||||
|
case !i0 && !i1 && i2 && !i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Hijacker
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 6/32
|
||||||
|
case !i0 && !i1 && i2 && !i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Hijacker
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 7/32
|
||||||
|
case !i0 && !i1 && i2 && i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 8/32
|
||||||
|
case !i0 && !i1 && i2 && i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 9/32
|
||||||
|
case !i0 && i1 && !i2 && !i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 10/32
|
||||||
|
case !i0 && i1 && !i2 && !i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 11/32
|
||||||
|
case !i0 && i1 && !i2 && i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 12/32
|
||||||
|
case !i0 && i1 && !i2 && i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
io.ReaderFrom
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 13/32
|
||||||
|
case !i0 && i1 && i2 && !i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 14/32
|
||||||
|
case !i0 && i1 && i2 && !i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 15/32
|
||||||
|
case !i0 && i1 && i2 && i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 16/32
|
||||||
|
case !i0 && i1 && i2 && i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw, rw}
|
||||||
|
// combination 17/32
|
||||||
|
case i0 && !i1 && !i2 && !i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 18/32
|
||||||
|
case i0 && !i1 && !i2 && !i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 19/32
|
||||||
|
case i0 && !i1 && !i2 && i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 20/32
|
||||||
|
case i0 && !i1 && !i2 && i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
io.ReaderFrom
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 21/32
|
||||||
|
case i0 && !i1 && i2 && !i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.Hijacker
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 22/32
|
||||||
|
case i0 && !i1 && i2 && !i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.Hijacker
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 23/32
|
||||||
|
case i0 && !i1 && i2 && i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 24/32
|
||||||
|
case i0 && !i1 && i2 && i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw, rw}
|
||||||
|
// combination 25/32
|
||||||
|
case i0 && i1 && !i2 && !i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 26/32
|
||||||
|
case i0 && i1 && !i2 && !i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 27/32
|
||||||
|
case i0 && i1 && !i2 && i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 28/32
|
||||||
|
case i0 && i1 && !i2 && i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
io.ReaderFrom
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw, rw}
|
||||||
|
// combination 29/32
|
||||||
|
case i0 && i1 && i2 && !i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 30/32
|
||||||
|
case i0 && i1 && i2 && !i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw, rw}
|
||||||
|
// combination 31/32
|
||||||
|
case i0 && i1 && i2 && i3 && !i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw, rw, rw}
|
||||||
|
// combination 32/32
|
||||||
|
case i0 && i1 && i2 && i3 && i4:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
http.Pusher
|
||||||
|
}{rw, rw, rw, rw, rw, rw}
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
type rw struct {
|
||||||
|
w http.ResponseWriter
|
||||||
|
h Hooks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Header() http.Header {
|
||||||
|
f := w.w.(http.ResponseWriter).Header
|
||||||
|
if w.h.Header != nil {
|
||||||
|
f = w.h.Header(f)
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) WriteHeader(code int) {
|
||||||
|
f := w.w.(http.ResponseWriter).WriteHeader
|
||||||
|
if w.h.WriteHeader != nil {
|
||||||
|
f = w.h.WriteHeader(f)
|
||||||
|
}
|
||||||
|
f(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Write(b []byte) (int, error) {
|
||||||
|
f := w.w.(http.ResponseWriter).Write
|
||||||
|
if w.h.Write != nil {
|
||||||
|
f = w.h.Write(f)
|
||||||
|
}
|
||||||
|
return f(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Flush() {
|
||||||
|
f := w.w.(http.Flusher).Flush
|
||||||
|
if w.h.Flush != nil {
|
||||||
|
f = w.h.Flush(f)
|
||||||
|
}
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) CloseNotify() <-chan bool {
|
||||||
|
f := w.w.(http.CloseNotifier).CloseNotify
|
||||||
|
if w.h.CloseNotify != nil {
|
||||||
|
f = w.h.CloseNotify(f)
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
f := w.w.(http.Hijacker).Hijack
|
||||||
|
if w.h.Hijack != nil {
|
||||||
|
f = w.h.Hijack(f)
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) ReadFrom(src io.Reader) (int64, error) {
|
||||||
|
f := w.w.(io.ReaderFrom).ReadFrom
|
||||||
|
if w.h.ReadFrom != nil {
|
||||||
|
f = w.h.ReadFrom(f)
|
||||||
|
}
|
||||||
|
return f(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Push(target string, opts *http.PushOptions) error {
|
||||||
|
f := w.w.(http.Pusher).Push
|
||||||
|
if w.h.Push != nil {
|
||||||
|
f = w.h.Push(f)
|
||||||
|
}
|
||||||
|
return f(target, opts)
|
||||||
|
}
|
243
vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go
generated
vendored
Normal file
243
vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go
generated
vendored
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
// +build !go1.8
|
||||||
|
// Code generated by "httpsnoop/codegen"; DO NOT EDIT
|
||||||
|
|
||||||
|
package httpsnoop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HeaderFunc is part of the http.ResponseWriter interface.
|
||||||
|
type HeaderFunc func() http.Header
|
||||||
|
|
||||||
|
// WriteHeaderFunc is part of the http.ResponseWriter interface.
|
||||||
|
type WriteHeaderFunc func(code int)
|
||||||
|
|
||||||
|
// WriteFunc is part of the http.ResponseWriter interface.
|
||||||
|
type WriteFunc func(b []byte) (int, error)
|
||||||
|
|
||||||
|
// FlushFunc is part of the http.Flusher interface.
|
||||||
|
type FlushFunc func()
|
||||||
|
|
||||||
|
// CloseNotifyFunc is part of the http.CloseNotifier interface.
|
||||||
|
type CloseNotifyFunc func() <-chan bool
|
||||||
|
|
||||||
|
// HijackFunc is part of the http.Hijacker interface.
|
||||||
|
type HijackFunc func() (net.Conn, *bufio.ReadWriter, error)
|
||||||
|
|
||||||
|
// ReadFromFunc is part of the io.ReaderFrom interface.
|
||||||
|
type ReadFromFunc func(src io.Reader) (int64, error)
|
||||||
|
|
||||||
|
// Hooks defines a set of method interceptors for methods included in
|
||||||
|
// http.ResponseWriter as well as some others. You can think of them as
|
||||||
|
// middleware for the function calls they target. See Wrap for more details.
|
||||||
|
type Hooks struct {
|
||||||
|
Header func(HeaderFunc) HeaderFunc
|
||||||
|
WriteHeader func(WriteHeaderFunc) WriteHeaderFunc
|
||||||
|
Write func(WriteFunc) WriteFunc
|
||||||
|
Flush func(FlushFunc) FlushFunc
|
||||||
|
CloseNotify func(CloseNotifyFunc) CloseNotifyFunc
|
||||||
|
Hijack func(HijackFunc) HijackFunc
|
||||||
|
ReadFrom func(ReadFromFunc) ReadFromFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap returns a wrapped version of w that provides the exact same interface
|
||||||
|
// as w. Specifically if w implements any combination of:
|
||||||
|
//
|
||||||
|
// - http.Flusher
|
||||||
|
// - http.CloseNotifier
|
||||||
|
// - http.Hijacker
|
||||||
|
// - io.ReaderFrom
|
||||||
|
//
|
||||||
|
// The wrapped version will implement the exact same combination. If no hooks
|
||||||
|
// are set, the wrapped version also behaves exactly as w. Hooks targeting
|
||||||
|
// methods not supported by w are ignored. Any other hooks will intercept the
|
||||||
|
// method they target and may modify the call's arguments and/or return values.
|
||||||
|
// The CaptureMetrics implementation serves as a working example for how the
|
||||||
|
// hooks can be used.
|
||||||
|
func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter {
|
||||||
|
rw := &rw{w: w, h: hooks}
|
||||||
|
_, i0 := w.(http.Flusher)
|
||||||
|
_, i1 := w.(http.CloseNotifier)
|
||||||
|
_, i2 := w.(http.Hijacker)
|
||||||
|
_, i3 := w.(io.ReaderFrom)
|
||||||
|
switch {
|
||||||
|
// combination 1/16
|
||||||
|
case !i0 && !i1 && !i2 && !i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
}{rw}
|
||||||
|
// combination 2/16
|
||||||
|
case !i0 && !i1 && !i2 && i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 3/16
|
||||||
|
case !i0 && !i1 && i2 && !i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Hijacker
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 4/16
|
||||||
|
case !i0 && !i1 && i2 && i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 5/16
|
||||||
|
case !i0 && i1 && !i2 && !i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 6/16
|
||||||
|
case !i0 && i1 && !i2 && i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 7/16
|
||||||
|
case !i0 && i1 && i2 && !i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 8/16
|
||||||
|
case !i0 && i1 && i2 && i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 9/16
|
||||||
|
case i0 && !i1 && !i2 && !i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
}{rw, rw}
|
||||||
|
// combination 10/16
|
||||||
|
case i0 && !i1 && !i2 && i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 11/16
|
||||||
|
case i0 && !i1 && i2 && !i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.Hijacker
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 12/16
|
||||||
|
case i0 && !i1 && i2 && i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 13/16
|
||||||
|
case i0 && i1 && !i2 && !i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
}{rw, rw, rw}
|
||||||
|
// combination 14/16
|
||||||
|
case i0 && i1 && !i2 && i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 15/16
|
||||||
|
case i0 && i1 && i2 && !i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
}{rw, rw, rw, rw}
|
||||||
|
// combination 16/16
|
||||||
|
case i0 && i1 && i2 && i3:
|
||||||
|
return struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
http.Flusher
|
||||||
|
http.CloseNotifier
|
||||||
|
http.Hijacker
|
||||||
|
io.ReaderFrom
|
||||||
|
}{rw, rw, rw, rw, rw}
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
type rw struct {
|
||||||
|
w http.ResponseWriter
|
||||||
|
h Hooks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Header() http.Header {
|
||||||
|
f := w.w.(http.ResponseWriter).Header
|
||||||
|
if w.h.Header != nil {
|
||||||
|
f = w.h.Header(f)
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) WriteHeader(code int) {
|
||||||
|
f := w.w.(http.ResponseWriter).WriteHeader
|
||||||
|
if w.h.WriteHeader != nil {
|
||||||
|
f = w.h.WriteHeader(f)
|
||||||
|
}
|
||||||
|
f(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Write(b []byte) (int, error) {
|
||||||
|
f := w.w.(http.ResponseWriter).Write
|
||||||
|
if w.h.Write != nil {
|
||||||
|
f = w.h.Write(f)
|
||||||
|
}
|
||||||
|
return f(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Flush() {
|
||||||
|
f := w.w.(http.Flusher).Flush
|
||||||
|
if w.h.Flush != nil {
|
||||||
|
f = w.h.Flush(f)
|
||||||
|
}
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) CloseNotify() <-chan bool {
|
||||||
|
f := w.w.(http.CloseNotifier).CloseNotify
|
||||||
|
if w.h.CloseNotify != nil {
|
||||||
|
f = w.h.CloseNotify(f)
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
f := w.w.(http.Hijacker).Hijack
|
||||||
|
if w.h.Hijack != nil {
|
||||||
|
f = w.h.Hijack(f)
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *rw) ReadFrom(src io.Reader) (int64, error) {
|
||||||
|
f := w.w.(io.ReaderFrom).ReadFrom
|
||||||
|
if w.h.ReadFrom != nil {
|
||||||
|
f = w.h.ReadFrom(f)
|
||||||
|
}
|
||||||
|
return f(src)
|
||||||
|
}
|
3
vendor/github.com/google/shlex/go.mod
generated
vendored
Normal file
3
vendor/github.com/google/shlex/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/google/shlex
|
||||||
|
|
||||||
|
go 1.13
|
8
vendor/github.com/gorilla/handlers/.travis.yml
generated
vendored
8
vendor/github.com/gorilla/handlers/.travis.yml
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.1
|
|
||||||
- 1.2
|
|
||||||
- 1.3
|
|
||||||
- 1.4
|
|
||||||
- tip
|
|
22
vendor/github.com/gorilla/handlers/README.md
generated
vendored
22
vendor/github.com/gorilla/handlers/README.md
generated
vendored
@ -1,28 +1,32 @@
|
|||||||
gorilla/handlers
|
gorilla/handlers
|
||||||
================
|
================
|
||||||
[](https://godoc.org/github.com/gorilla/handlers) [](https://travis-ci.org/gorilla/handlers)
|
[](https://godoc.org/github.com/gorilla/handlers)
|
||||||
|
[](https://circleci.com/gh/gorilla/handlers)
|
||||||
|
[](https://sourcegraph.com/github.com/gorilla/handlers?badge)
|
||||||
|
|
||||||
|
|
||||||
Package handlers is a collection of handlers (aka "HTTP middleware") for use
|
Package handlers is a collection of handlers (aka "HTTP middleware") for use
|
||||||
with Go's `net/http` package (or any framework supporting `http.Handler`), including:
|
with Go's `net/http` package (or any framework supporting `http.Handler`), including:
|
||||||
|
|
||||||
* `LoggingHandler` for logging HTTP requests in the Apache [Common Log
|
* [**LoggingHandler**](https://godoc.org/github.com/gorilla/handlers#LoggingHandler) for logging HTTP requests in the Apache [Common Log
|
||||||
Format](http://httpd.apache.org/docs/2.2/logs.html#common).
|
Format](http://httpd.apache.org/docs/2.2/logs.html#common).
|
||||||
* `CombinedLoggingHandler` for logging HTTP requests in the Apache [Combined Log
|
* [**CombinedLoggingHandler**](https://godoc.org/github.com/gorilla/handlers#CombinedLoggingHandler) for logging HTTP requests in the Apache [Combined Log
|
||||||
Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by
|
Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by
|
||||||
both Apache and nginx.
|
both Apache and nginx.
|
||||||
* `CompressHandler` for gzipping responses.
|
* [**CompressHandler**](https://godoc.org/github.com/gorilla/handlers#CompressHandler) for gzipping responses.
|
||||||
* `ContentTypeHandler` for validating requests against a list of accepted
|
* [**ContentTypeHandler**](https://godoc.org/github.com/gorilla/handlers#ContentTypeHandler) for validating requests against a list of accepted
|
||||||
content types.
|
content types.
|
||||||
* `MethodHandler` for matching HTTP methods against handlers in a
|
* [**MethodHandler**](https://godoc.org/github.com/gorilla/handlers#MethodHandler) for matching HTTP methods against handlers in a
|
||||||
`map[string]http.Handler`
|
`map[string]http.Handler`
|
||||||
* `ProxyHeaders` for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
|
* [**ProxyHeaders**](https://godoc.org/github.com/gorilla/handlers#ProxyHeaders) for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
|
||||||
`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded`
|
`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded`
|
||||||
headers when running a Go server behind a HTTP reverse proxy.
|
headers when running a Go server behind a HTTP reverse proxy.
|
||||||
* `CanonicalHost` for re-directing to the preferred host when handling multiple
|
* [**CanonicalHost**](https://godoc.org/github.com/gorilla/handlers#CanonicalHost) for re-directing to the preferred host when handling multiple
|
||||||
domains (i.e. multiple CNAME aliases).
|
domains (i.e. multiple CNAME aliases).
|
||||||
|
* [**RecoveryHandler**](https://godoc.org/github.com/gorilla/handlers#RecoveryHandler) for recovering from unexpected panics.
|
||||||
|
|
||||||
Other handlers are documented [on the Gorilla
|
Other handlers are documented [on the Gorilla
|
||||||
website](http://www.gorillatoolkit.org/pkg/handlers).
|
website](https://www.gorillatoolkit.org/pkg/handlers).
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
5
vendor/github.com/gorilla/handlers/canonical.go
generated
vendored
5
vendor/github.com/gorilla/handlers/canonical.go
generated
vendored
@ -18,7 +18,6 @@ type canonical struct {
|
|||||||
//
|
//
|
||||||
// Note: If the provided domain is considered invalid by url.Parse or otherwise
|
// Note: If the provided domain is considered invalid by url.Parse or otherwise
|
||||||
// returns an empty scheme or host, clients are not re-directed.
|
// returns an empty scheme or host, clients are not re-directed.
|
||||||
// not re-directed.
|
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
@ -54,7 +53,11 @@ func (c canonical) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if !strings.EqualFold(cleanHost(r.Host), dest.Host) {
|
if !strings.EqualFold(cleanHost(r.Host), dest.Host) {
|
||||||
// Re-build the destination URL
|
// Re-build the destination URL
|
||||||
dest := dest.Scheme + "://" + dest.Host + r.URL.Path
|
dest := dest.Scheme + "://" + dest.Host + r.URL.Path
|
||||||
|
if r.URL.RawQuery != "" {
|
||||||
|
dest += "?" + r.URL.RawQuery
|
||||||
|
}
|
||||||
http.Redirect(w, r, dest, c.code)
|
http.Redirect(w, r, dest, c.code)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.h.ServeHTTP(w, r)
|
c.h.ServeHTTP(w, r)
|
||||||
|
157
vendor/github.com/gorilla/handlers/compress.go
generated
vendored
157
vendor/github.com/gorilla/handlers/compress.go
generated
vendored
@ -10,75 +10,134 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/felixge/httpsnoop"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const acceptEncoding string = "Accept-Encoding"
|
||||||
|
|
||||||
type compressResponseWriter struct {
|
type compressResponseWriter struct {
|
||||||
io.Writer
|
compressor io.Writer
|
||||||
http.ResponseWriter
|
w http.ResponseWriter
|
||||||
http.Hijacker
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *compressResponseWriter) Header() http.Header {
|
func (cw *compressResponseWriter) WriteHeader(c int) {
|
||||||
return w.ResponseWriter.Header()
|
cw.w.Header().Del("Content-Length")
|
||||||
|
cw.w.WriteHeader(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *compressResponseWriter) Write(b []byte) (int, error) {
|
func (cw *compressResponseWriter) Write(b []byte) (int, error) {
|
||||||
h := w.ResponseWriter.Header()
|
h := cw.w.Header()
|
||||||
if h.Get("Content-Type") == "" {
|
if h.Get("Content-Type") == "" {
|
||||||
h.Set("Content-Type", http.DetectContentType(b))
|
h.Set("Content-Type", http.DetectContentType(b))
|
||||||
}
|
}
|
||||||
|
h.Del("Content-Length")
|
||||||
|
|
||||||
return w.Writer.Write(b)
|
return cw.compressor.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *compressResponseWriter) ReadFrom(r io.Reader) (int64, error) {
|
||||||
|
return io.Copy(cw.compressor, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
type flusher interface {
|
||||||
|
Flush() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *compressResponseWriter) Flush() {
|
||||||
|
// Flush compressed data if compressor supports it.
|
||||||
|
if f, ok := w.compressor.(flusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
|
// Flush HTTP response.
|
||||||
|
if f, ok := w.w.(http.Flusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompressHandler gzip compresses HTTP responses for clients that support it
|
// CompressHandler gzip compresses HTTP responses for clients that support it
|
||||||
// via the 'Accept-Encoding' header.
|
// via the 'Accept-Encoding' header.
|
||||||
|
//
|
||||||
|
// Compressing TLS traffic may leak the page contents to an attacker if the
|
||||||
|
// page contains user input: http://security.stackexchange.com/a/102015/12208
|
||||||
func CompressHandler(h http.Handler) http.Handler {
|
func CompressHandler(h http.Handler) http.Handler {
|
||||||
|
return CompressHandlerLevel(h, gzip.DefaultCompression)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompressHandlerLevel gzip compresses HTTP responses with specified compression level
|
||||||
|
// for clients that support it via the 'Accept-Encoding' header.
|
||||||
|
//
|
||||||
|
// The compression level should be gzip.DefaultCompression, gzip.NoCompression,
|
||||||
|
// or any integer value between gzip.BestSpeed and gzip.BestCompression inclusive.
|
||||||
|
// gzip.DefaultCompression is used in case of invalid compression level.
|
||||||
|
func CompressHandlerLevel(h http.Handler, level int) http.Handler {
|
||||||
|
if level < gzip.DefaultCompression || level > gzip.BestCompression {
|
||||||
|
level = gzip.DefaultCompression
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
gzipEncoding = "gzip"
|
||||||
|
flateEncoding = "deflate"
|
||||||
|
)
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
L:
|
// detect what encoding to use
|
||||||
for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") {
|
var encoding string
|
||||||
switch strings.TrimSpace(enc) {
|
for _, curEnc := range strings.Split(r.Header.Get(acceptEncoding), ",") {
|
||||||
case "gzip":
|
curEnc = strings.TrimSpace(curEnc)
|
||||||
w.Header().Set("Content-Encoding", "gzip")
|
if curEnc == gzipEncoding || curEnc == flateEncoding {
|
||||||
w.Header().Add("Vary", "Accept-Encoding")
|
encoding = curEnc
|
||||||
|
break
|
||||||
gw := gzip.NewWriter(w)
|
|
||||||
defer gw.Close()
|
|
||||||
|
|
||||||
h, hok := w.(http.Hijacker)
|
|
||||||
if !hok { /* w is not Hijacker... oh well... */
|
|
||||||
h = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
w = &compressResponseWriter{
|
|
||||||
Writer: gw,
|
|
||||||
ResponseWriter: w,
|
|
||||||
Hijacker: h,
|
|
||||||
}
|
|
||||||
|
|
||||||
break L
|
|
||||||
case "deflate":
|
|
||||||
w.Header().Set("Content-Encoding", "deflate")
|
|
||||||
w.Header().Add("Vary", "Accept-Encoding")
|
|
||||||
|
|
||||||
fw, _ := flate.NewWriter(w, flate.DefaultCompression)
|
|
||||||
defer fw.Close()
|
|
||||||
|
|
||||||
h, hok := w.(http.Hijacker)
|
|
||||||
if !hok { /* w is not Hijacker... oh well... */
|
|
||||||
h = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
w = &compressResponseWriter{
|
|
||||||
Writer: fw,
|
|
||||||
ResponseWriter: w,
|
|
||||||
Hijacker: h,
|
|
||||||
}
|
|
||||||
|
|
||||||
break L
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// always add Accept-Encoding to Vary to prevent intermediate caches corruption
|
||||||
|
w.Header().Add("Vary", acceptEncoding)
|
||||||
|
|
||||||
|
// if we weren't able to identify an encoding we're familiar with, pass on the
|
||||||
|
// request to the handler and return
|
||||||
|
if encoding == "" {
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Header.Get("Upgrade") != "" {
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrap the ResponseWriter with the writer for the chosen encoding
|
||||||
|
var encWriter io.WriteCloser
|
||||||
|
if encoding == gzipEncoding {
|
||||||
|
encWriter, _ = gzip.NewWriterLevel(w, level)
|
||||||
|
} else if encoding == flateEncoding {
|
||||||
|
encWriter, _ = flate.NewWriter(w, level)
|
||||||
|
}
|
||||||
|
defer encWriter.Close()
|
||||||
|
|
||||||
|
w.Header().Set("Content-Encoding", encoding)
|
||||||
|
r.Header.Del(acceptEncoding)
|
||||||
|
|
||||||
|
cw := &compressResponseWriter{
|
||||||
|
w: w,
|
||||||
|
compressor: encWriter,
|
||||||
|
}
|
||||||
|
|
||||||
|
w = httpsnoop.Wrap(w, httpsnoop.Hooks{
|
||||||
|
Write: func(httpsnoop.WriteFunc) httpsnoop.WriteFunc {
|
||||||
|
return cw.Write
|
||||||
|
},
|
||||||
|
WriteHeader: func(httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
|
||||||
|
return cw.WriteHeader
|
||||||
|
},
|
||||||
|
Flush: func(httpsnoop.FlushFunc) httpsnoop.FlushFunc {
|
||||||
|
return cw.Flush
|
||||||
|
},
|
||||||
|
ReadFrom: func(rff httpsnoop.ReadFromFunc) httpsnoop.ReadFromFunc {
|
||||||
|
return cw.ReadFrom
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
h.ServeHTTP(w, r)
|
h.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
355
vendor/github.com/gorilla/handlers/cors.go
generated
vendored
Normal file
355
vendor/github.com/gorilla/handlers/cors.go
generated
vendored
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CORSOption represents a functional option for configuring the CORS middleware.
|
||||||
|
type CORSOption func(*cors) error
|
||||||
|
|
||||||
|
type cors struct {
|
||||||
|
h http.Handler
|
||||||
|
allowedHeaders []string
|
||||||
|
allowedMethods []string
|
||||||
|
allowedOrigins []string
|
||||||
|
allowedOriginValidator OriginValidator
|
||||||
|
exposedHeaders []string
|
||||||
|
maxAge int
|
||||||
|
ignoreOptions bool
|
||||||
|
allowCredentials bool
|
||||||
|
optionStatusCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
// OriginValidator takes an origin string and returns whether or not that origin is allowed.
|
||||||
|
type OriginValidator func(string) bool
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultCorsOptionStatusCode = 200
|
||||||
|
defaultCorsMethods = []string{"GET", "HEAD", "POST"}
|
||||||
|
defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"}
|
||||||
|
// (WebKit/Safari v9 sends the Origin header by default in AJAX requests)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
corsOptionMethod string = "OPTIONS"
|
||||||
|
corsAllowOriginHeader string = "Access-Control-Allow-Origin"
|
||||||
|
corsExposeHeadersHeader string = "Access-Control-Expose-Headers"
|
||||||
|
corsMaxAgeHeader string = "Access-Control-Max-Age"
|
||||||
|
corsAllowMethodsHeader string = "Access-Control-Allow-Methods"
|
||||||
|
corsAllowHeadersHeader string = "Access-Control-Allow-Headers"
|
||||||
|
corsAllowCredentialsHeader string = "Access-Control-Allow-Credentials"
|
||||||
|
corsRequestMethodHeader string = "Access-Control-Request-Method"
|
||||||
|
corsRequestHeadersHeader string = "Access-Control-Request-Headers"
|
||||||
|
corsOriginHeader string = "Origin"
|
||||||
|
corsVaryHeader string = "Vary"
|
||||||
|
corsOriginMatchAll string = "*"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
origin := r.Header.Get(corsOriginHeader)
|
||||||
|
if !ch.isOriginAllowed(origin) {
|
||||||
|
if r.Method != corsOptionMethod || ch.ignoreOptions {
|
||||||
|
ch.h.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Method == corsOptionMethod {
|
||||||
|
if ch.ignoreOptions {
|
||||||
|
ch.h.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.Header[corsRequestMethodHeader]; !ok {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
method := r.Header.Get(corsRequestMethodHeader)
|
||||||
|
if !ch.isMatch(method, ch.allowedMethods) {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
requestHeaders := strings.Split(r.Header.Get(corsRequestHeadersHeader), ",")
|
||||||
|
allowedHeaders := []string{}
|
||||||
|
for _, v := range requestHeaders {
|
||||||
|
canonicalHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
|
||||||
|
if canonicalHeader == "" || ch.isMatch(canonicalHeader, defaultCorsHeaders) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ch.isMatch(canonicalHeader, ch.allowedHeaders) {
|
||||||
|
w.WriteHeader(http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
allowedHeaders = append(allowedHeaders, canonicalHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(allowedHeaders) > 0 {
|
||||||
|
w.Header().Set(corsAllowHeadersHeader, strings.Join(allowedHeaders, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch.maxAge > 0 {
|
||||||
|
w.Header().Set(corsMaxAgeHeader, strconv.Itoa(ch.maxAge))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ch.isMatch(method, defaultCorsMethods) {
|
||||||
|
w.Header().Set(corsAllowMethodsHeader, method)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(ch.exposedHeaders) > 0 {
|
||||||
|
w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch.allowCredentials {
|
||||||
|
w.Header().Set(corsAllowCredentialsHeader, "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ch.allowedOrigins) > 1 {
|
||||||
|
w.Header().Set(corsVaryHeader, corsOriginHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
returnOrigin := origin
|
||||||
|
if ch.allowedOriginValidator == nil && len(ch.allowedOrigins) == 0 {
|
||||||
|
returnOrigin = "*"
|
||||||
|
} else {
|
||||||
|
for _, o := range ch.allowedOrigins {
|
||||||
|
// A configuration of * is different than explicitly setting an allowed
|
||||||
|
// origin. Returning arbitrary origin headers in an access control allow
|
||||||
|
// origin header is unsafe and is not required by any use case.
|
||||||
|
if o == corsOriginMatchAll {
|
||||||
|
returnOrigin = "*"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.Header().Set(corsAllowOriginHeader, returnOrigin)
|
||||||
|
|
||||||
|
if r.Method == corsOptionMethod {
|
||||||
|
w.WriteHeader(ch.optionStatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch.h.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CORS provides Cross-Origin Resource Sharing middleware.
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "net/http"
|
||||||
|
//
|
||||||
|
// "github.com/gorilla/handlers"
|
||||||
|
// "github.com/gorilla/mux"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// func main() {
|
||||||
|
// r := mux.NewRouter()
|
||||||
|
// r.HandleFunc("/users", UserEndpoint)
|
||||||
|
// r.HandleFunc("/projects", ProjectEndpoint)
|
||||||
|
//
|
||||||
|
// // Apply the CORS middleware to our top-level router, with the defaults.
|
||||||
|
// http.ListenAndServe(":8000", handlers.CORS()(r))
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func CORS(opts ...CORSOption) func(http.Handler) http.Handler {
|
||||||
|
return func(h http.Handler) http.Handler {
|
||||||
|
ch := parseCORSOptions(opts...)
|
||||||
|
ch.h = h
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCORSOptions(opts ...CORSOption) *cors {
|
||||||
|
ch := &cors{
|
||||||
|
allowedMethods: defaultCorsMethods,
|
||||||
|
allowedHeaders: defaultCorsHeaders,
|
||||||
|
allowedOrigins: []string{},
|
||||||
|
optionStatusCode: defaultCorsOptionStatusCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, option := range opts {
|
||||||
|
option(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functional options for configuring CORS.
|
||||||
|
//
|
||||||
|
|
||||||
|
// AllowedHeaders adds the provided headers to the list of allowed headers in a
|
||||||
|
// CORS request.
|
||||||
|
// This is an append operation so the headers Accept, Accept-Language,
|
||||||
|
// and Content-Language are always allowed.
|
||||||
|
// Content-Type must be explicitly declared if accepting Content-Types other than
|
||||||
|
// application/x-www-form-urlencoded, multipart/form-data, or text/plain.
|
||||||
|
func AllowedHeaders(headers []string) CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
for _, v := range headers {
|
||||||
|
normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
|
||||||
|
if normalizedHeader == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ch.isMatch(normalizedHeader, ch.allowedHeaders) {
|
||||||
|
ch.allowedHeaders = append(ch.allowedHeaders, normalizedHeader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowedMethods can be used to explicitly allow methods in the
|
||||||
|
// Access-Control-Allow-Methods header.
|
||||||
|
// This is a replacement operation so you must also
|
||||||
|
// pass GET, HEAD, and POST if you wish to support those methods.
|
||||||
|
func AllowedMethods(methods []string) CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
ch.allowedMethods = []string{}
|
||||||
|
for _, v := range methods {
|
||||||
|
normalizedMethod := strings.ToUpper(strings.TrimSpace(v))
|
||||||
|
if normalizedMethod == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ch.isMatch(normalizedMethod, ch.allowedMethods) {
|
||||||
|
ch.allowedMethods = append(ch.allowedMethods, normalizedMethod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowedOrigins sets the allowed origins for CORS requests, as used in the
|
||||||
|
// 'Allow-Access-Control-Origin' HTTP header.
|
||||||
|
// Note: Passing in a []string{"*"} will allow any domain.
|
||||||
|
func AllowedOrigins(origins []string) CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
for _, v := range origins {
|
||||||
|
if v == corsOriginMatchAll {
|
||||||
|
ch.allowedOrigins = []string{corsOriginMatchAll}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ch.allowedOrigins = origins
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowedOriginValidator sets a function for evaluating allowed origins in CORS requests, represented by the
|
||||||
|
// 'Allow-Access-Control-Origin' HTTP header.
|
||||||
|
func AllowedOriginValidator(fn OriginValidator) CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
ch.allowedOriginValidator = fn
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionStatusCode sets a custom status code on the OPTIONS requests.
|
||||||
|
// Default behaviour sets it to 200 to reflect best practices. This is option is not mandatory
|
||||||
|
// and can be used if you need a custom status code (i.e 204).
|
||||||
|
//
|
||||||
|
// More informations on the spec:
|
||||||
|
// https://fetch.spec.whatwg.org/#cors-preflight-fetch
|
||||||
|
func OptionStatusCode(code int) CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
ch.optionStatusCode = code
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExposedHeaders can be used to specify headers that are available
|
||||||
|
// and will not be stripped out by the user-agent.
|
||||||
|
func ExposedHeaders(headers []string) CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
ch.exposedHeaders = []string{}
|
||||||
|
for _, v := range headers {
|
||||||
|
normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
|
||||||
|
if normalizedHeader == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ch.isMatch(normalizedHeader, ch.exposedHeaders) {
|
||||||
|
ch.exposedHeaders = append(ch.exposedHeaders, normalizedHeader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxAge determines the maximum age (in seconds) between preflight requests. A
|
||||||
|
// maximum of 10 minutes is allowed. An age above this value will default to 10
|
||||||
|
// minutes.
|
||||||
|
func MaxAge(age int) CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
// Maximum of 10 minutes.
|
||||||
|
if age > 600 {
|
||||||
|
age = 600
|
||||||
|
}
|
||||||
|
|
||||||
|
ch.maxAge = age
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IgnoreOptions causes the CORS middleware to ignore OPTIONS requests, instead
|
||||||
|
// passing them through to the next handler. This is useful when your application
|
||||||
|
// or framework has a pre-existing mechanism for responding to OPTIONS requests.
|
||||||
|
func IgnoreOptions() CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
ch.ignoreOptions = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowCredentials can be used to specify that the user agent may pass
|
||||||
|
// authentication details along with the request.
|
||||||
|
func AllowCredentials() CORSOption {
|
||||||
|
return func(ch *cors) error {
|
||||||
|
ch.allowCredentials = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *cors) isOriginAllowed(origin string) bool {
|
||||||
|
if origin == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch.allowedOriginValidator != nil {
|
||||||
|
return ch.allowedOriginValidator(origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ch.allowedOrigins) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, allowedOrigin := range ch.allowedOrigins {
|
||||||
|
if allowedOrigin == origin || allowedOrigin == corsOriginMatchAll {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *cors) isMatch(needle string, haystack []string) bool {
|
||||||
|
for _, v := range haystack {
|
||||||
|
if v == needle {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
5
vendor/github.com/gorilla/handlers/go.mod
generated
vendored
Normal file
5
vendor/github.com/gorilla/handlers/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module github.com/gorilla/handlers
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require github.com/felixge/httpsnoop v1.0.1
|
2
vendor/github.com/gorilla/handlers/go.sum
generated
vendored
Normal file
2
vendor/github.com/gorilla/handlers/go.sum
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||||
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
287
vendor/github.com/gorilla/handlers/handlers.go
generated
vendored
287
vendor/github.com/gorilla/handlers/handlers.go
generated
vendored
@ -7,27 +7,22 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MethodHandler is an http.Handler that dispatches to a handler whose key in the MethodHandler's
|
// MethodHandler is an http.Handler that dispatches to a handler whose key in the
|
||||||
// map matches the name of the HTTP request's method, eg: GET
|
// MethodHandler's map matches the name of the HTTP request's method, eg: GET
|
||||||
//
|
//
|
||||||
// If the request's method is OPTIONS and OPTIONS is not a key in the map then the handler
|
// If the request's method is OPTIONS and OPTIONS is not a key in the map then
|
||||||
// responds with a status of 200 and sets the Allow header to a comma-separated list of
|
// the handler responds with a status of 200 and sets the Allow header to a
|
||||||
// available methods.
|
// comma-separated list of available methods.
|
||||||
//
|
//
|
||||||
// If the request's method doesn't match any of its keys the handler responds with
|
// If the request's method doesn't match any of its keys the handler responds
|
||||||
// a status of 405, Method not allowed and sets the Allow header to a comma-separated list
|
// with a status of HTTP 405 "Method Not Allowed" and sets the Allow header to a
|
||||||
// of available methods.
|
// comma-separated list of available methods.
|
||||||
type MethodHandler map[string]http.Handler
|
type MethodHandler map[string]http.Handler
|
||||||
|
|
||||||
func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
@ -48,74 +43,15 @@ func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
|
// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP
|
||||||
type loggingHandler struct {
|
// status code and body size
|
||||||
writer io.Writer
|
|
||||||
handler http.Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
|
|
||||||
type combinedLoggingHandler struct {
|
|
||||||
writer io.Writer
|
|
||||||
handler http.Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|
||||||
t := time.Now()
|
|
||||||
logger := makeLogger(w)
|
|
||||||
url := *req.URL
|
|
||||||
h.handler.ServeHTTP(logger, req)
|
|
||||||
writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|
||||||
t := time.Now()
|
|
||||||
logger := makeLogger(w)
|
|
||||||
url := *req.URL
|
|
||||||
h.handler.ServeHTTP(logger, req)
|
|
||||||
writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeLogger(w http.ResponseWriter) loggingResponseWriter {
|
|
||||||
var logger loggingResponseWriter = &responseLogger{w: w}
|
|
||||||
if _, ok := w.(http.Hijacker); ok {
|
|
||||||
logger = &hijackLogger{responseLogger{w: w}}
|
|
||||||
}
|
|
||||||
h, ok1 := logger.(http.Hijacker)
|
|
||||||
c, ok2 := w.(http.CloseNotifier)
|
|
||||||
if ok1 && ok2 {
|
|
||||||
return hijackCloseNotifier{logger, h, c}
|
|
||||||
}
|
|
||||||
if ok2 {
|
|
||||||
return &closeNotifyWriter{logger, c}
|
|
||||||
}
|
|
||||||
return logger
|
|
||||||
}
|
|
||||||
|
|
||||||
type loggingResponseWriter interface {
|
|
||||||
http.ResponseWriter
|
|
||||||
http.Flusher
|
|
||||||
Status() int
|
|
||||||
Size() int
|
|
||||||
}
|
|
||||||
|
|
||||||
// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
|
|
||||||
// code and body size
|
|
||||||
type responseLogger struct {
|
type responseLogger struct {
|
||||||
w http.ResponseWriter
|
w http.ResponseWriter
|
||||||
status int
|
status int
|
||||||
size int
|
size int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *responseLogger) Header() http.Header {
|
|
||||||
return l.w.Header()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *responseLogger) Write(b []byte) (int, error) {
|
func (l *responseLogger) Write(b []byte) (int, error) {
|
||||||
if l.status == 0 {
|
|
||||||
// The status will be StatusOK if WriteHeader has not been called yet
|
|
||||||
l.status = http.StatusOK
|
|
||||||
}
|
|
||||||
size, err := l.w.Write(b)
|
size, err := l.w.Write(b)
|
||||||
l.size += size
|
l.size += size
|
||||||
return size, err
|
return size, err
|
||||||
@ -134,187 +70,18 @@ func (l *responseLogger) Size() int {
|
|||||||
return l.size
|
return l.size
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *responseLogger) Flush() {
|
func (l *responseLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
f, ok := l.w.(http.Flusher)
|
conn, rw, err := l.w.(http.Hijacker).Hijack()
|
||||||
if ok {
|
if err == nil && l.status == 0 {
|
||||||
f.Flush()
|
// The status will be StatusSwitchingProtocols if there was no error and
|
||||||
}
|
// WriteHeader has not been called yet
|
||||||
}
|
l.status = http.StatusSwitchingProtocols
|
||||||
|
|
||||||
type hijackLogger struct {
|
|
||||||
responseLogger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|
||||||
h := l.responseLogger.w.(http.Hijacker)
|
|
||||||
conn, rw, err := h.Hijack()
|
|
||||||
if err == nil && l.responseLogger.status == 0 {
|
|
||||||
// The status will be StatusSwitchingProtocols if there was no error and WriteHeader has not been called yet
|
|
||||||
l.responseLogger.status = http.StatusSwitchingProtocols
|
|
||||||
}
|
}
|
||||||
return conn, rw, err
|
return conn, rw, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type closeNotifyWriter struct {
|
// isContentType validates the Content-Type header matches the supplied
|
||||||
loggingResponseWriter
|
// contentType. That is, its type and subtype match.
|
||||||
http.CloseNotifier
|
|
||||||
}
|
|
||||||
|
|
||||||
type hijackCloseNotifier struct {
|
|
||||||
loggingResponseWriter
|
|
||||||
http.Hijacker
|
|
||||||
http.CloseNotifier
|
|
||||||
}
|
|
||||||
|
|
||||||
const lowerhex = "0123456789abcdef"
|
|
||||||
|
|
||||||
func appendQuoted(buf []byte, s string) []byte {
|
|
||||||
var runeTmp [utf8.UTFMax]byte
|
|
||||||
for width := 0; len(s) > 0; s = s[width:] {
|
|
||||||
r := rune(s[0])
|
|
||||||
width = 1
|
|
||||||
if r >= utf8.RuneSelf {
|
|
||||||
r, width = utf8.DecodeRuneInString(s)
|
|
||||||
}
|
|
||||||
if width == 1 && r == utf8.RuneError {
|
|
||||||
buf = append(buf, `\x`...)
|
|
||||||
buf = append(buf, lowerhex[s[0]>>4])
|
|
||||||
buf = append(buf, lowerhex[s[0]&0xF])
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if r == rune('"') || r == '\\' { // always backslashed
|
|
||||||
buf = append(buf, '\\')
|
|
||||||
buf = append(buf, byte(r))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strconv.IsPrint(r) {
|
|
||||||
n := utf8.EncodeRune(runeTmp[:], r)
|
|
||||||
buf = append(buf, runeTmp[:n]...)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case '\a':
|
|
||||||
buf = append(buf, `\a`...)
|
|
||||||
case '\b':
|
|
||||||
buf = append(buf, `\b`...)
|
|
||||||
case '\f':
|
|
||||||
buf = append(buf, `\f`...)
|
|
||||||
case '\n':
|
|
||||||
buf = append(buf, `\n`...)
|
|
||||||
case '\r':
|
|
||||||
buf = append(buf, `\r`...)
|
|
||||||
case '\t':
|
|
||||||
buf = append(buf, `\t`...)
|
|
||||||
case '\v':
|
|
||||||
buf = append(buf, `\v`...)
|
|
||||||
default:
|
|
||||||
switch {
|
|
||||||
case r < ' ':
|
|
||||||
buf = append(buf, `\x`...)
|
|
||||||
buf = append(buf, lowerhex[s[0]>>4])
|
|
||||||
buf = append(buf, lowerhex[s[0]&0xF])
|
|
||||||
case r > utf8.MaxRune:
|
|
||||||
r = 0xFFFD
|
|
||||||
fallthrough
|
|
||||||
case r < 0x10000:
|
|
||||||
buf = append(buf, `\u`...)
|
|
||||||
for s := 12; s >= 0; s -= 4 {
|
|
||||||
buf = append(buf, lowerhex[r>>uint(s)&0xF])
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
buf = append(buf, `\U`...)
|
|
||||||
for s := 28; s >= 0; s -= 4 {
|
|
||||||
buf = append(buf, lowerhex[r>>uint(s)&0xF])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
|
|
||||||
// ts is the timestamp with which the entry should be logged.
|
|
||||||
// status and size are used to provide the response HTTP status and size.
|
|
||||||
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
|
|
||||||
username := "-"
|
|
||||||
if url.User != nil {
|
|
||||||
if name := url.User.Username(); name != "" {
|
|
||||||
username = name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
host, _, err := net.SplitHostPort(req.RemoteAddr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
host = req.RemoteAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
uri := url.RequestURI()
|
|
||||||
|
|
||||||
buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
|
|
||||||
buf = append(buf, host...)
|
|
||||||
buf = append(buf, " - "...)
|
|
||||||
buf = append(buf, username...)
|
|
||||||
buf = append(buf, " ["...)
|
|
||||||
buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
|
|
||||||
buf = append(buf, `] "`...)
|
|
||||||
buf = append(buf, req.Method...)
|
|
||||||
buf = append(buf, " "...)
|
|
||||||
buf = appendQuoted(buf, uri)
|
|
||||||
buf = append(buf, " "...)
|
|
||||||
buf = append(buf, req.Proto...)
|
|
||||||
buf = append(buf, `" `...)
|
|
||||||
buf = append(buf, strconv.Itoa(status)...)
|
|
||||||
buf = append(buf, " "...)
|
|
||||||
buf = append(buf, strconv.Itoa(size)...)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeLog writes a log entry for req to w in Apache Common Log Format.
|
|
||||||
// ts is the timestamp with which the entry should be logged.
|
|
||||||
// status and size are used to provide the response HTTP status and size.
|
|
||||||
func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
|
|
||||||
buf := buildCommonLogLine(req, url, ts, status, size)
|
|
||||||
buf = append(buf, '\n')
|
|
||||||
w.Write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
|
|
||||||
// ts is the timestamp with which the entry should be logged.
|
|
||||||
// status and size are used to provide the response HTTP status and size.
|
|
||||||
func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
|
|
||||||
buf := buildCommonLogLine(req, url, ts, status, size)
|
|
||||||
buf = append(buf, ` "`...)
|
|
||||||
buf = appendQuoted(buf, req.Referer())
|
|
||||||
buf = append(buf, `" "`...)
|
|
||||||
buf = appendQuoted(buf, req.UserAgent())
|
|
||||||
buf = append(buf, '"', '\n')
|
|
||||||
w.Write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
|
|
||||||
// Apache Combined Log Format.
|
|
||||||
//
|
|
||||||
// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
|
|
||||||
//
|
|
||||||
// LoggingHandler always sets the ident field of the log to -
|
|
||||||
func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
|
|
||||||
return combinedLoggingHandler{out, h}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoggingHandler return a http.Handler that wraps h and logs requests to out in
|
|
||||||
// Apache Common Log Format (CLF).
|
|
||||||
//
|
|
||||||
// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
|
|
||||||
//
|
|
||||||
// LoggingHandler always sets the ident field of the log to -
|
|
||||||
func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
|
|
||||||
return loggingHandler{out, h}
|
|
||||||
}
|
|
||||||
|
|
||||||
// isContentType validates the Content-Type header
|
|
||||||
// is contentType. That is, its type and subtype match.
|
|
||||||
func isContentType(h http.Header, contentType string) bool {
|
func isContentType(h http.Header, contentType string) bool {
|
||||||
ct := h.Get("Content-Type")
|
ct := h.Get("Content-Type")
|
||||||
if i := strings.IndexRune(ct, ';'); i != -1 {
|
if i := strings.IndexRune(ct, ';'); i != -1 {
|
||||||
@ -323,9 +90,9 @@ func isContentType(h http.Header, contentType string) bool {
|
|||||||
return ct == contentType
|
return ct == contentType
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContentTypeHandler wraps and returns a http.Handler, validating the request content type
|
// ContentTypeHandler wraps and returns a http.Handler, validating the request
|
||||||
// is acompatible with the contentTypes list.
|
// content type is compatible with the contentTypes list. It writes a HTTP 415
|
||||||
// It writes a HTTP 415 error if that fails.
|
// error if that fails.
|
||||||
//
|
//
|
||||||
// Only PUT, POST, and PATCH requests are considered.
|
// Only PUT, POST, and PATCH requests are considered.
|
||||||
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
|
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
|
||||||
@ -354,12 +121,14 @@ const (
|
|||||||
HTTPMethodOverrideFormKey = "_method"
|
HTTPMethodOverrideFormKey = "_method"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for the X-HTTP-Method-Override header
|
// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for
|
||||||
// or the _method form key, and overrides (if valid) request.Method with its value.
|
// the X-HTTP-Method-Override header or the _method form key, and overrides (if
|
||||||
|
// valid) request.Method with its value.
|
||||||
//
|
//
|
||||||
// This is especially useful for http clients that don't support many http verbs.
|
// This is especially useful for HTTP clients that don't support many http verbs.
|
||||||
// It isn't secure to override e.g a GET to a POST, so only POST requests are considered.
|
// It isn't secure to override e.g a GET to a POST, so only POST requests are
|
||||||
// Likewise, the override method can only be a "write" method: PUT, PATCH or DELETE.
|
// considered. Likewise, the override method can only be a "write" method: PUT,
|
||||||
|
// PATCH or DELETE.
|
||||||
//
|
//
|
||||||
// Form method takes precedence over header method.
|
// Form method takes precedence over header method.
|
||||||
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
|
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
|
||||||
|
244
vendor/github.com/gorilla/handlers/logging.go
generated
vendored
Normal file
244
vendor/github.com/gorilla/handlers/logging.go
generated
vendored
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
// Copyright 2013 The Gorilla 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 handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/felixge/httpsnoop"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
|
||||||
|
// LogFormatterParams is the structure any formatter will be handed when time to log comes
|
||||||
|
type LogFormatterParams struct {
|
||||||
|
Request *http.Request
|
||||||
|
URL url.URL
|
||||||
|
TimeStamp time.Time
|
||||||
|
StatusCode int
|
||||||
|
Size int
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogFormatter gives the signature of the formatter function passed to CustomLoggingHandler
|
||||||
|
type LogFormatter func(writer io.Writer, params LogFormatterParams)
|
||||||
|
|
||||||
|
// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its
|
||||||
|
// friends
|
||||||
|
|
||||||
|
type loggingHandler struct {
|
||||||
|
writer io.Writer
|
||||||
|
handler http.Handler
|
||||||
|
formatter LogFormatter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
t := time.Now()
|
||||||
|
logger, w := makeLogger(w)
|
||||||
|
url := *req.URL
|
||||||
|
|
||||||
|
h.handler.ServeHTTP(w, req)
|
||||||
|
if req.MultipartForm != nil {
|
||||||
|
req.MultipartForm.RemoveAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
params := LogFormatterParams{
|
||||||
|
Request: req,
|
||||||
|
URL: url,
|
||||||
|
TimeStamp: t,
|
||||||
|
StatusCode: logger.Status(),
|
||||||
|
Size: logger.Size(),
|
||||||
|
}
|
||||||
|
|
||||||
|
h.formatter(h.writer, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeLogger(w http.ResponseWriter) (*responseLogger, http.ResponseWriter) {
|
||||||
|
logger := &responseLogger{w: w, status: http.StatusOK}
|
||||||
|
return logger, httpsnoop.Wrap(w, httpsnoop.Hooks{
|
||||||
|
Write: func(httpsnoop.WriteFunc) httpsnoop.WriteFunc {
|
||||||
|
return logger.Write
|
||||||
|
},
|
||||||
|
WriteHeader: func(httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
|
||||||
|
return logger.WriteHeader
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const lowerhex = "0123456789abcdef"
|
||||||
|
|
||||||
|
func appendQuoted(buf []byte, s string) []byte {
|
||||||
|
var runeTmp [utf8.UTFMax]byte
|
||||||
|
for width := 0; len(s) > 0; s = s[width:] {
|
||||||
|
r := rune(s[0])
|
||||||
|
width = 1
|
||||||
|
if r >= utf8.RuneSelf {
|
||||||
|
r, width = utf8.DecodeRuneInString(s)
|
||||||
|
}
|
||||||
|
if width == 1 && r == utf8.RuneError {
|
||||||
|
buf = append(buf, `\x`...)
|
||||||
|
buf = append(buf, lowerhex[s[0]>>4])
|
||||||
|
buf = append(buf, lowerhex[s[0]&0xF])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if r == rune('"') || r == '\\' { // always backslashed
|
||||||
|
buf = append(buf, '\\')
|
||||||
|
buf = append(buf, byte(r))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strconv.IsPrint(r) {
|
||||||
|
n := utf8.EncodeRune(runeTmp[:], r)
|
||||||
|
buf = append(buf, runeTmp[:n]...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch r {
|
||||||
|
case '\a':
|
||||||
|
buf = append(buf, `\a`...)
|
||||||
|
case '\b':
|
||||||
|
buf = append(buf, `\b`...)
|
||||||
|
case '\f':
|
||||||
|
buf = append(buf, `\f`...)
|
||||||
|
case '\n':
|
||||||
|
buf = append(buf, `\n`...)
|
||||||
|
case '\r':
|
||||||
|
buf = append(buf, `\r`...)
|
||||||
|
case '\t':
|
||||||
|
buf = append(buf, `\t`...)
|
||||||
|
case '\v':
|
||||||
|
buf = append(buf, `\v`...)
|
||||||
|
default:
|
||||||
|
switch {
|
||||||
|
case r < ' ':
|
||||||
|
buf = append(buf, `\x`...)
|
||||||
|
buf = append(buf, lowerhex[s[0]>>4])
|
||||||
|
buf = append(buf, lowerhex[s[0]&0xF])
|
||||||
|
case r > utf8.MaxRune:
|
||||||
|
r = 0xFFFD
|
||||||
|
fallthrough
|
||||||
|
case r < 0x10000:
|
||||||
|
buf = append(buf, `\u`...)
|
||||||
|
for s := 12; s >= 0; s -= 4 {
|
||||||
|
buf = append(buf, lowerhex[r>>uint(s)&0xF])
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
buf = append(buf, `\U`...)
|
||||||
|
for s := 28; s >= 0; s -= 4 {
|
||||||
|
buf = append(buf, lowerhex[r>>uint(s)&0xF])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
|
||||||
|
// ts is the timestamp with which the entry should be logged.
|
||||||
|
// status and size are used to provide the response HTTP status and size.
|
||||||
|
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
|
||||||
|
username := "-"
|
||||||
|
if url.User != nil {
|
||||||
|
if name := url.User.Username(); name != "" {
|
||||||
|
username = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
host, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||||
|
if err != nil {
|
||||||
|
host = req.RemoteAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
uri := req.RequestURI
|
||||||
|
|
||||||
|
// Requests using the CONNECT method over HTTP/2.0 must use
|
||||||
|
// the authority field (aka r.Host) to identify the target.
|
||||||
|
// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
|
||||||
|
if req.ProtoMajor == 2 && req.Method == "CONNECT" {
|
||||||
|
uri = req.Host
|
||||||
|
}
|
||||||
|
if uri == "" {
|
||||||
|
uri = url.RequestURI()
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
|
||||||
|
buf = append(buf, host...)
|
||||||
|
buf = append(buf, " - "...)
|
||||||
|
buf = append(buf, username...)
|
||||||
|
buf = append(buf, " ["...)
|
||||||
|
buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
|
||||||
|
buf = append(buf, `] "`...)
|
||||||
|
buf = append(buf, req.Method...)
|
||||||
|
buf = append(buf, " "...)
|
||||||
|
buf = appendQuoted(buf, uri)
|
||||||
|
buf = append(buf, " "...)
|
||||||
|
buf = append(buf, req.Proto...)
|
||||||
|
buf = append(buf, `" `...)
|
||||||
|
buf = append(buf, strconv.Itoa(status)...)
|
||||||
|
buf = append(buf, " "...)
|
||||||
|
buf = append(buf, strconv.Itoa(size)...)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeLog writes a log entry for req to w in Apache Common Log Format.
|
||||||
|
// ts is the timestamp with which the entry should be logged.
|
||||||
|
// status and size are used to provide the response HTTP status and size.
|
||||||
|
func writeLog(writer io.Writer, params LogFormatterParams) {
|
||||||
|
buf := buildCommonLogLine(params.Request, params.URL, params.TimeStamp, params.StatusCode, params.Size)
|
||||||
|
buf = append(buf, '\n')
|
||||||
|
writer.Write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
|
||||||
|
// ts is the timestamp with which the entry should be logged.
|
||||||
|
// status and size are used to provide the response HTTP status and size.
|
||||||
|
func writeCombinedLog(writer io.Writer, params LogFormatterParams) {
|
||||||
|
buf := buildCommonLogLine(params.Request, params.URL, params.TimeStamp, params.StatusCode, params.Size)
|
||||||
|
buf = append(buf, ` "`...)
|
||||||
|
buf = appendQuoted(buf, params.Request.Referer())
|
||||||
|
buf = append(buf, `" "`...)
|
||||||
|
buf = appendQuoted(buf, params.Request.UserAgent())
|
||||||
|
buf = append(buf, '"', '\n')
|
||||||
|
writer.Write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
|
||||||
|
// Apache Combined Log Format.
|
||||||
|
//
|
||||||
|
// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
|
||||||
|
//
|
||||||
|
// LoggingHandler always sets the ident field of the log to -
|
||||||
|
func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
|
||||||
|
return loggingHandler{out, h, writeCombinedLog}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoggingHandler return a http.Handler that wraps h and logs requests to out in
|
||||||
|
// Apache Common Log Format (CLF).
|
||||||
|
//
|
||||||
|
// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
|
||||||
|
//
|
||||||
|
// LoggingHandler always sets the ident field of the log to -
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// r := mux.NewRouter()
|
||||||
|
// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// w.Write([]byte("This is a catch-all route"))
|
||||||
|
// })
|
||||||
|
// loggedRouter := handlers.LoggingHandler(os.Stdout, r)
|
||||||
|
// http.ListenAndServe(":1123", loggedRouter)
|
||||||
|
//
|
||||||
|
func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
|
||||||
|
return loggingHandler{out, h, writeLog}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomLoggingHandler provides a way to supply a custom log formatter
|
||||||
|
// while taking advantage of the mechanisms in this package
|
||||||
|
func CustomLoggingHandler(out io.Writer, h http.Handler, f LogFormatter) http.Handler {
|
||||||
|
return loggingHandler{out, h, f}
|
||||||
|
}
|
23
vendor/github.com/gorilla/handlers/proxy_headers.go
generated
vendored
23
vendor/github.com/gorilla/handlers/proxy_headers.go
generated
vendored
@ -8,9 +8,11 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// De-facto standard header keys.
|
// De-facto standard header keys.
|
||||||
xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
|
xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
|
||||||
xRealIP = http.CanonicalHeaderKey("X-Real-IP")
|
xForwardedHost = http.CanonicalHeaderKey("X-Forwarded-Host")
|
||||||
xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Scheme")
|
xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Proto")
|
||||||
|
xForwardedScheme = http.CanonicalHeaderKey("X-Forwarded-Scheme")
|
||||||
|
xRealIP = http.CanonicalHeaderKey("X-Real-IP")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -28,9 +30,9 @@ var (
|
|||||||
|
|
||||||
// ProxyHeaders inspects common reverse proxy headers and sets the corresponding
|
// ProxyHeaders inspects common reverse proxy headers and sets the corresponding
|
||||||
// fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP
|
// fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP
|
||||||
// for the remote (client) IP address, X-Forwarded-Proto for the scheme
|
// for the remote (client) IP address, X-Forwarded-Proto or X-Forwarded-Scheme
|
||||||
// (http|https) and the RFC7239 Forwarded header, which may include both client
|
// for the scheme (http|https), X-Forwarded-Host for the host and the RFC7239
|
||||||
// IPs and schemes.
|
// Forwarded header, which may include both client IPs and schemes.
|
||||||
//
|
//
|
||||||
// NOTE: This middleware should only be used when behind a reverse
|
// NOTE: This middleware should only be used when behind a reverse
|
||||||
// proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are
|
// proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are
|
||||||
@ -49,7 +51,10 @@ func ProxyHeaders(h http.Handler) http.Handler {
|
|||||||
if scheme := getScheme(r); scheme != "" {
|
if scheme := getScheme(r); scheme != "" {
|
||||||
r.URL.Scheme = scheme
|
r.URL.Scheme = scheme
|
||||||
}
|
}
|
||||||
|
// Set the host with the value passed by the proxy
|
||||||
|
if r.Header.Get(xForwardedHost) != "" {
|
||||||
|
r.Host = r.Header.Get(xForwardedHost)
|
||||||
|
}
|
||||||
// Call the next handler in the chain.
|
// Call the next handler in the chain.
|
||||||
h.ServeHTTP(w, r)
|
h.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@ -99,7 +104,9 @@ func getScheme(r *http.Request) string {
|
|||||||
// Retrieve the scheme from X-Forwarded-Proto.
|
// Retrieve the scheme from X-Forwarded-Proto.
|
||||||
if proto := r.Header.Get(xForwardedProto); proto != "" {
|
if proto := r.Header.Get(xForwardedProto); proto != "" {
|
||||||
scheme = strings.ToLower(proto)
|
scheme = strings.ToLower(proto)
|
||||||
} else if proto := r.Header.Get(forwarded); proto != "" {
|
} else if proto = r.Header.Get(xForwardedScheme); proto != "" {
|
||||||
|
scheme = strings.ToLower(proto)
|
||||||
|
} else if proto = r.Header.Get(forwarded); proto != "" {
|
||||||
// match should contain at least two elements if the protocol was
|
// match should contain at least two elements if the protocol was
|
||||||
// specified in the Forwarded header. The first element will always be
|
// specified in the Forwarded header. The first element will always be
|
||||||
// the 'proto=' capture, which we ignore. In the case of multiple proto
|
// the 'proto=' capture, which we ignore. In the case of multiple proto
|
||||||
|
96
vendor/github.com/gorilla/handlers/recovery.go
generated
vendored
Normal file
96
vendor/github.com/gorilla/handlers/recovery.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"runtime/debug"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RecoveryHandlerLogger is an interface used by the recovering handler to print logs.
|
||||||
|
type RecoveryHandlerLogger interface {
|
||||||
|
Println(...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type recoveryHandler struct {
|
||||||
|
handler http.Handler
|
||||||
|
logger RecoveryHandlerLogger
|
||||||
|
printStack bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecoveryOption provides a functional approach to define
|
||||||
|
// configuration for a handler; such as setting the logging
|
||||||
|
// whether or not to print stack traces on panic.
|
||||||
|
type RecoveryOption func(http.Handler)
|
||||||
|
|
||||||
|
func parseRecoveryOptions(h http.Handler, opts ...RecoveryOption) http.Handler {
|
||||||
|
for _, option := range opts {
|
||||||
|
option(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecoveryHandler is HTTP middleware that recovers from a panic,
|
||||||
|
// logs the panic, writes http.StatusInternalServerError, and
|
||||||
|
// continues to the next handler.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// r := mux.NewRouter()
|
||||||
|
// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// panic("Unexpected error!")
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// http.ListenAndServe(":1123", handlers.RecoveryHandler()(r))
|
||||||
|
func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler {
|
||||||
|
return func(h http.Handler) http.Handler {
|
||||||
|
r := &recoveryHandler{handler: h}
|
||||||
|
return parseRecoveryOptions(r, opts...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecoveryLogger is a functional option to override
|
||||||
|
// the default logger
|
||||||
|
func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption {
|
||||||
|
return func(h http.Handler) {
|
||||||
|
r := h.(*recoveryHandler)
|
||||||
|
r.logger = logger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintRecoveryStack is a functional option to enable
|
||||||
|
// or disable printing stack traces on panic.
|
||||||
|
func PrintRecoveryStack(print bool) RecoveryOption {
|
||||||
|
return func(h http.Handler) {
|
||||||
|
r := h.(*recoveryHandler)
|
||||||
|
r.printStack = print
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h recoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
h.log(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
h.handler.ServeHTTP(w, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h recoveryHandler) log(v ...interface{}) {
|
||||||
|
if h.logger != nil {
|
||||||
|
h.logger.Println(v...)
|
||||||
|
} else {
|
||||||
|
log.Println(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if h.printStack {
|
||||||
|
stack := string(debug.Stack())
|
||||||
|
if h.logger != nil {
|
||||||
|
h.logger.Println(stack)
|
||||||
|
} else {
|
||||||
|
log.Println(stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
generated
vendored
5
vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
generated
vendored
@ -3,6 +3,7 @@ package apparmor
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ var (
|
|||||||
func isEnabled() bool {
|
func isEnabled() bool {
|
||||||
checkAppArmor.Do(func() {
|
checkAppArmor.Do(func() {
|
||||||
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil {
|
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil {
|
||||||
buf, err := os.ReadFile("/sys/module/apparmor/parameters/enabled")
|
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
|
||||||
appArmorEnabled = err == nil && len(buf) > 1 && buf[0] == 'Y'
|
appArmorEnabled = err == nil && len(buf) > 1 && buf[0] == 'Y'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -51,7 +52,7 @@ func setProcAttr(attr, value string) error {
|
|||||||
// changeOnExec reimplements aa_change_onexec from libapparmor in Go
|
// changeOnExec reimplements aa_change_onexec from libapparmor in Go
|
||||||
func changeOnExec(name string) error {
|
func changeOnExec(name string) error {
|
||||||
if err := setProcAttr("exec", "exec "+name); err != nil {
|
if err := setProcAttr("exec", "exec "+name); err != nil {
|
||||||
return fmt.Errorf("apparmor failed to apply profile: %w", err)
|
return fmt.Errorf("apparmor failed to apply profile: %s", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build !linux
|
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package apparmor
|
package apparmor
|
||||||
|
2
vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
generated
vendored
2
vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package cgroups
|
package cgroups
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
3
vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go
generated
vendored
Normal file
3
vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package cgroups
|
60
vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
generated
vendored
60
vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
generated
vendored
@ -2,27 +2,20 @@ package cgroups
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OpenFile opens a cgroup file in a given dir with given flags.
|
// OpenFile opens a cgroup file in a given dir with given flags.
|
||||||
// It is supposed to be used for cgroup files only, and returns
|
// It is supposed to be used for cgroup files only.
|
||||||
// an error if the file is not a cgroup file.
|
|
||||||
//
|
|
||||||
// Arguments dir and file are joined together to form an absolute path
|
|
||||||
// to a file being opened.
|
|
||||||
func OpenFile(dir, file string, flags int) (*os.File, error) {
|
func OpenFile(dir, file string, flags int) (*os.File, error) {
|
||||||
if dir == "" {
|
if dir == "" {
|
||||||
return nil, fmt.Errorf("no directory specified for %s", file)
|
return nil, errors.Errorf("no directory specified for %s", file)
|
||||||
}
|
}
|
||||||
return openFile(dir, file, flags)
|
return openFile(dir, file, flags)
|
||||||
}
|
}
|
||||||
@ -50,8 +43,7 @@ func WriteFile(dir, file, data string) error {
|
|||||||
}
|
}
|
||||||
defer fd.Close()
|
defer fd.Close()
|
||||||
if err := retryingWriteFile(fd, data); err != nil {
|
if err := retryingWriteFile(fd, data); err != nil {
|
||||||
// Having data in the error message helps in debugging.
|
return errors.Wrapf(err, "failed to write %q", data)
|
||||||
return fmt.Errorf("failed to write %q: %w", data, err)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -89,7 +81,7 @@ func prepareOpenat2() error {
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
|
prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
|
||||||
if err != unix.ENOSYS { //nolint:errorlint // unix errors are bare
|
if err != unix.ENOSYS {
|
||||||
logrus.Warnf("falling back to securejoin: %s", prepErr)
|
logrus.Warnf("falling back to securejoin: %s", prepErr)
|
||||||
} else {
|
} else {
|
||||||
logrus.Debug("openat2 not available, falling back to securejoin")
|
logrus.Debug("openat2 not available, falling back to securejoin")
|
||||||
@ -115,6 +107,8 @@ func prepareOpenat2() error {
|
|||||||
return prepErr
|
return prepErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenFile opens a cgroup file in a given dir with given flags.
|
||||||
|
// It is supposed to be used for cgroup files only.
|
||||||
func openFile(dir, file string, flags int) (*os.File, error) {
|
func openFile(dir, file string, flags int) (*os.File, error) {
|
||||||
mode := os.FileMode(0)
|
mode := os.FileMode(0)
|
||||||
if TestMode && flags&os.O_WRONLY != 0 {
|
if TestMode && flags&os.O_WRONLY != 0 {
|
||||||
@ -122,52 +116,34 @@ func openFile(dir, file string, flags int) (*os.File, error) {
|
|||||||
flags |= os.O_TRUNC | os.O_CREATE
|
flags |= os.O_TRUNC | os.O_CREATE
|
||||||
mode = 0o600
|
mode = 0o600
|
||||||
}
|
}
|
||||||
path := path.Join(dir, file)
|
|
||||||
if prepareOpenat2() != nil {
|
if prepareOpenat2() != nil {
|
||||||
return openFallback(path, flags, mode)
|
return openFallback(dir, file, flags, mode)
|
||||||
}
|
}
|
||||||
relPath := strings.TrimPrefix(path, cgroupfsPrefix)
|
reldir := strings.TrimPrefix(dir, cgroupfsPrefix)
|
||||||
if len(relPath) == len(path) { // non-standard path, old system?
|
if len(reldir) == len(dir) { // non-standard path, old system?
|
||||||
return openFallback(path, flags, mode)
|
return openFallback(dir, file, flags, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := unix.Openat2(cgroupFd, relPath,
|
relname := reldir + "/" + file
|
||||||
|
fd, err := unix.Openat2(cgroupFd, relname,
|
||||||
&unix.OpenHow{
|
&unix.OpenHow{
|
||||||
Resolve: resolveFlags,
|
Resolve: resolveFlags,
|
||||||
Flags: uint64(flags) | unix.O_CLOEXEC,
|
Flags: uint64(flags) | unix.O_CLOEXEC,
|
||||||
Mode: uint64(mode),
|
Mode: uint64(mode),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = &os.PathError{Op: "openat2", Path: path, Err: err}
|
return nil, &os.PathError{Op: "openat2", Path: dir + "/" + file, Err: err}
|
||||||
// Check if cgroupFd is still opened to cgroupfsDir
|
|
||||||
// (happens when this package is incorrectly used
|
|
||||||
// across the chroot/pivot_root/mntns boundary, or
|
|
||||||
// when /sys/fs/cgroup is remounted).
|
|
||||||
//
|
|
||||||
// TODO: if such usage will ever be common, amend this
|
|
||||||
// to reopen cgroupFd and retry openat2.
|
|
||||||
fdStr := strconv.Itoa(cgroupFd)
|
|
||||||
fdDest, _ := os.Readlink("/proc/self/fd/" + fdStr)
|
|
||||||
if fdDest != cgroupfsDir {
|
|
||||||
// Wrap the error so it is clear that cgroupFd
|
|
||||||
// is opened to an unexpected/wrong directory.
|
|
||||||
err = fmt.Errorf("cgroupFd %s unexpectedly opened to %s != %s: %w",
|
|
||||||
fdStr, fdDest, cgroupfsDir, err)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return os.NewFile(uintptr(fd), path), nil
|
return os.NewFile(uintptr(fd), cgroupfsPrefix+relname), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var errNotCgroupfs = errors.New("not a cgroup file")
|
var errNotCgroupfs = errors.New("not a cgroup file")
|
||||||
|
|
||||||
// Can be changed by unit tests.
|
// openFallback is used when openat2(2) is not available. It checks the opened
|
||||||
var openFallback = openAndCheck
|
|
||||||
|
|
||||||
// openAndCheck is used when openat2(2) is not available. It checks the opened
|
|
||||||
// file is on cgroupfs, returning an error otherwise.
|
// file is on cgroupfs, returning an error otherwise.
|
||||||
func openAndCheck(path string, flags int, mode os.FileMode) (*os.File, error) {
|
func openFallback(dir, file string, flags int, mode os.FileMode) (*os.File, error) {
|
||||||
|
path := dir + "/" + file
|
||||||
fd, err := os.OpenFile(path, flags, mode)
|
fd, err := os.OpenFile(path, flags, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
27
vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go
generated
vendored
27
vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
package cgroups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/fs"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetAllPids returns all pids from the cgroup identified by path, and all its
|
|
||||||
// sub-cgroups.
|
|
||||||
func GetAllPids(path string) ([]int, error) {
|
|
||||||
var pids []int
|
|
||||||
err := filepath.WalkDir(path, func(p string, d fs.DirEntry, iErr error) error {
|
|
||||||
if iErr != nil {
|
|
||||||
return iErr
|
|
||||||
}
|
|
||||||
if !d.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
cPids, err := readProcsFile(p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pids = append(pids, cPids...)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return pids, err
|
|
||||||
}
|
|
16
vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
generated
vendored
16
vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package cgroups
|
package cgroups
|
||||||
|
|
||||||
type ThrottlingData struct {
|
type ThrottlingData struct {
|
||||||
@ -124,7 +126,7 @@ type BlkioStatEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BlkioStats struct {
|
type BlkioStats struct {
|
||||||
// number of bytes transferred to and from the block device
|
// number of bytes tranferred to and from the block device
|
||||||
IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
|
IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
|
||||||
IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
|
IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
|
||||||
IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
|
IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
|
||||||
@ -144,17 +146,6 @@ type HugetlbStats struct {
|
|||||||
Failcnt uint64 `json:"failcnt"`
|
Failcnt uint64 `json:"failcnt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RdmaEntry struct {
|
|
||||||
Device string `json:"device,omitempty"`
|
|
||||||
HcaHandles uint32 `json:"hca_handles,omitempty"`
|
|
||||||
HcaObjects uint32 `json:"hca_objects,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RdmaStats struct {
|
|
||||||
RdmaLimit []RdmaEntry `json:"rdma_limit,omitempty"`
|
|
||||||
RdmaCurrent []RdmaEntry `json:"rdma_current,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
CpuStats CpuStats `json:"cpu_stats,omitempty"`
|
CpuStats CpuStats `json:"cpu_stats,omitempty"`
|
||||||
CPUSetStats CPUSetStats `json:"cpuset_stats,omitempty"`
|
CPUSetStats CPUSetStats `json:"cpuset_stats,omitempty"`
|
||||||
@ -163,7 +154,6 @@ type Stats struct {
|
|||||||
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
|
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
|
||||||
// the map is in the format "size of hugepage: stats of the hugepage"
|
// the map is in the format "size of hugepage: stats of the hugepage"
|
||||||
HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitempty"`
|
HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitempty"`
|
||||||
RdmaStats RdmaStats `json:"rdma_stats,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStats() *Stats {
|
func NewStats() *Stats {
|
||||||
|
115
vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
generated
vendored
115
vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package cgroups
|
package cgroups
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -5,6 +7,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -20,14 +23,11 @@ import (
|
|||||||
const (
|
const (
|
||||||
CgroupProcesses = "cgroup.procs"
|
CgroupProcesses = "cgroup.procs"
|
||||||
unifiedMountpoint = "/sys/fs/cgroup"
|
unifiedMountpoint = "/sys/fs/cgroup"
|
||||||
hybridMountpoint = "/sys/fs/cgroup/unified"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
isUnifiedOnce sync.Once
|
isUnifiedOnce sync.Once
|
||||||
isUnified bool
|
isUnified bool
|
||||||
isHybridOnce sync.Once
|
|
||||||
isHybrid bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
|
// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
|
||||||
@ -49,24 +49,6 @@ func IsCgroup2UnifiedMode() bool {
|
|||||||
return isUnified
|
return isUnified
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsCgroup2HybridMode returns whether we are running in cgroup v2 hybrid mode.
|
|
||||||
func IsCgroup2HybridMode() bool {
|
|
||||||
isHybridOnce.Do(func() {
|
|
||||||
var st unix.Statfs_t
|
|
||||||
err := unix.Statfs(hybridMountpoint, &st)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
// ignore the "not found" error
|
|
||||||
isHybrid = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("cannot statfs cgroup root: %s", err))
|
|
||||||
}
|
|
||||||
isHybrid = st.Type == unix.CGROUP2_SUPER_MAGIC
|
|
||||||
})
|
|
||||||
return isHybrid
|
|
||||||
}
|
|
||||||
|
|
||||||
type Mount struct {
|
type Mount struct {
|
||||||
Mountpoint string
|
Mountpoint string
|
||||||
Root string
|
Root string
|
||||||
@ -136,8 +118,8 @@ func GetAllSubsystems() ([]string, error) {
|
|||||||
return subsystems, nil
|
return subsystems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readProcsFile(dir string) ([]int, error) {
|
func readProcsFile(file string) ([]int, error) {
|
||||||
f, err := OpenFile(dir, CgroupProcesses, os.O_RDONLY)
|
f, err := os.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -228,7 +210,7 @@ func EnterPid(cgroupPaths map[string]string, pid int) error {
|
|||||||
|
|
||||||
func rmdir(path string) error {
|
func rmdir(path string) error {
|
||||||
err := unix.Rmdir(path)
|
err := unix.Rmdir(path)
|
||||||
if err == nil || err == unix.ENOENT { //nolint:errorlint // unix errors are bare
|
if err == nil || err == unix.ENOENT {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &os.PathError{Op: "rmdir", Path: path, Err: err}
|
return &os.PathError{Op: "rmdir", Path: path, Err: err}
|
||||||
@ -242,7 +224,7 @@ func RemovePath(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
infos, err := os.ReadDir(path)
|
infos, err := ioutil.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
err = nil
|
err = nil
|
||||||
@ -302,61 +284,40 @@ func RemovePaths(paths map[string]string) (err error) {
|
|||||||
return fmt.Errorf("Failed to remove paths: %v", paths)
|
return fmt.Errorf("Failed to remove paths: %v", paths)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
func GetHugePageSize() ([]string, error) {
|
||||||
hugePageSizes []string
|
dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
|
||||||
initHPSOnce sync.Once
|
if err != nil {
|
||||||
)
|
return nil, err
|
||||||
|
}
|
||||||
|
files, err := dir.Readdirnames(0)
|
||||||
|
dir.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
func HugePageSizes() []string {
|
return getHugePageSizeFromFilenames(files)
|
||||||
initHPSOnce.Do(func() {
|
|
||||||
dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
files, err := dir.Readdirnames(0)
|
|
||||||
dir.Close()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hugePageSizes, err = getHugePageSizeFromFilenames(files)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Warn("HugePageSizes: ", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return hugePageSizes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
|
func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
|
||||||
pageSizes := make([]string, 0, len(fileNames))
|
pageSizes := make([]string, 0, len(fileNames))
|
||||||
var warn error
|
|
||||||
|
|
||||||
for _, file := range fileNames {
|
for _, file := range fileNames {
|
||||||
// example: hugepages-1048576kB
|
// example: hugepages-1048576kB
|
||||||
val := strings.TrimPrefix(file, "hugepages-")
|
val := strings.TrimPrefix(file, "hugepages-")
|
||||||
if len(val) == len(file) {
|
if len(val) == len(file) {
|
||||||
// Unexpected file name: no prefix found, ignore it.
|
// unexpected file name: no prefix found
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// The suffix is always "kB" (as of Linux 5.13). If we find
|
// The suffix is always "kB" (as of Linux 5.9)
|
||||||
// something else, produce an error but keep going.
|
|
||||||
eLen := len(val) - 2
|
eLen := len(val) - 2
|
||||||
val = strings.TrimSuffix(val, "kB")
|
val = strings.TrimSuffix(val, "kB")
|
||||||
if len(val) != eLen {
|
if len(val) != eLen {
|
||||||
// Highly unlikely.
|
logrus.Warnf("GetHugePageSize: %s: invalid filename suffix (expected \"kB\")", file)
|
||||||
if warn == nil {
|
|
||||||
warn = errors.New(file + `: invalid suffix (expected "kB")`)
|
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
size, err := strconv.Atoi(val)
|
size, err := strconv.Atoi(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Highly unlikely.
|
return nil, err
|
||||||
if warn == nil {
|
|
||||||
warn = fmt.Errorf("%s: %w", file, err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
// Model after https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/hugetlb_cgroup.c?id=eff48ddeab782e35e58ccc8853f7386bbae9dec4#n574
|
// Model after https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/hugetlb_cgroup.c?id=eff48ddeab782e35e58ccc8853f7386bbae9dec4#n574
|
||||||
// but in our case the size is in KB already.
|
// but in our case the size is in KB already.
|
||||||
@ -370,12 +331,34 @@ func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
|
|||||||
pageSizes = append(pageSizes, val)
|
pageSizes = append(pageSizes, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageSizes, warn
|
return pageSizes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPids returns all pids, that were added to cgroup at path.
|
// GetPids returns all pids, that were added to cgroup at path.
|
||||||
func GetPids(dir string) ([]int, error) {
|
func GetPids(dir string) ([]int, error) {
|
||||||
return readProcsFile(dir)
|
return readProcsFile(filepath.Join(dir, CgroupProcesses))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllPids returns all pids, that were added to cgroup at path and to all its
|
||||||
|
// subcgroups.
|
||||||
|
func GetAllPids(path string) ([]int, error) {
|
||||||
|
var pids []int
|
||||||
|
// collect pids from all sub-cgroups
|
||||||
|
err := filepath.Walk(path, func(p string, info os.FileInfo, iErr error) error {
|
||||||
|
if iErr != nil {
|
||||||
|
return iErr
|
||||||
|
}
|
||||||
|
if info.IsDir() || info.Name() != CgroupProcesses {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cPids, err := readProcsFile(p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pids = append(pids, cPids...)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return pids, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteCgroupProc writes the specified pid into the cgroup's cgroup.procs file
|
// WriteCgroupProc writes the specified pid into the cgroup's cgroup.procs file
|
||||||
@ -393,7 +376,7 @@ func WriteCgroupProc(dir string, pid int) error {
|
|||||||
|
|
||||||
file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY)
|
file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to write %v: %w", pid, err)
|
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
@ -410,7 +393,7 @@ func WriteCgroupProc(dir string, pid int) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("failed to write %v: %w", pid, err)
|
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -463,5 +446,5 @@ func ConvertBlkIOToIOWeightValue(blkIoWeight uint16) uint64 {
|
|||||||
if blkIoWeight == 0 {
|
if blkIoWeight == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1 + (uint64(blkIoWeight)-10)*9999/990
|
return uint64(1 + (uint64(blkIoWeight)-10)*9999/990)
|
||||||
}
|
}
|
||||||
|
19
vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
generated
vendored
19
vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
generated
vendored
@ -46,8 +46,11 @@ func NewNotFoundError(sub string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func IsNotFound(err error) bool {
|
func IsNotFound(err error) bool {
|
||||||
var nfErr *NotFoundError
|
if err == nil {
|
||||||
return errors.As(err, &nfErr)
|
return false
|
||||||
|
}
|
||||||
|
_, ok := err.(*NotFoundError)
|
||||||
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryDefaultPath(cgroupPath, subsystem string) string {
|
func tryDefaultPath(cgroupPath, subsystem string) string {
|
||||||
@ -113,11 +116,6 @@ func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
|
|||||||
return "", errUnified
|
return "", errUnified
|
||||||
}
|
}
|
||||||
|
|
||||||
// If subsystem is empty, we look for the cgroupv2 hybrid path.
|
|
||||||
if len(subsystem) == 0 {
|
|
||||||
return hybridMountpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid parsing mountinfo by trying the default path first, if possible.
|
// Avoid parsing mountinfo by trying the default path first, if possible.
|
||||||
if path := tryDefaultPath(cgroupPath, subsystem); path != "" {
|
if path := tryDefaultPath(cgroupPath, subsystem); path != "" {
|
||||||
return path, nil
|
return path, nil
|
||||||
@ -156,7 +154,7 @@ func findCgroupMountpointAndRootFromMI(mounts []*mountinfo.Info, cgroupPath, sub
|
|||||||
|
|
||||||
func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
|
func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
|
||||||
if len(m.Subsystems) == 0 {
|
if len(m.Subsystems) == 0 {
|
||||||
return "", errors.New("no subsystem for mount")
|
return "", fmt.Errorf("no subsystem for mount")
|
||||||
}
|
}
|
||||||
|
|
||||||
return getControllerPath(m.Subsystems[0], cgroups)
|
return getControllerPath(m.Subsystems[0], cgroups)
|
||||||
@ -228,11 +226,6 @@ func GetOwnCgroupPath(subsystem string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If subsystem is empty, we look for the cgroupv2 hybrid path.
|
|
||||||
if len(subsystem) == 0 {
|
|
||||||
return hybridMountpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return getCgroupPathHelper(subsystem, cgroup)
|
return getCgroupPathHelper(subsystem, cgroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
generated
vendored
20
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
generated
vendored
@ -28,26 +28,17 @@ type Cgroup struct {
|
|||||||
// ScopePrefix describes prefix for the scope name
|
// ScopePrefix describes prefix for the scope name
|
||||||
ScopePrefix string `json:"scope_prefix"`
|
ScopePrefix string `json:"scope_prefix"`
|
||||||
|
|
||||||
|
// Paths represent the absolute cgroups paths to join.
|
||||||
|
// This takes precedence over Path.
|
||||||
|
Paths map[string]string
|
||||||
|
|
||||||
// Resources contains various cgroups settings to apply
|
// Resources contains various cgroups settings to apply
|
||||||
*Resources
|
*Resources
|
||||||
|
|
||||||
// Systemd tells if systemd should be used to manage cgroups.
|
|
||||||
Systemd bool
|
|
||||||
|
|
||||||
// SystemdProps are any additional properties for systemd,
|
// SystemdProps are any additional properties for systemd,
|
||||||
// derived from org.systemd.property.xxx annotations.
|
// derived from org.systemd.property.xxx annotations.
|
||||||
// Ignored unless systemd is used for managing cgroups.
|
// Ignored unless systemd is used for managing cgroups.
|
||||||
SystemdProps []systemdDbus.Property `json:"-"`
|
SystemdProps []systemdDbus.Property `json:"-"`
|
||||||
|
|
||||||
// Rootless tells if rootless cgroups should be used.
|
|
||||||
Rootless bool
|
|
||||||
|
|
||||||
// The host UID that should own the cgroup, or nil to accept
|
|
||||||
// the default ownership. This should only be set when the
|
|
||||||
// cgroupfs is to be mounted read/write.
|
|
||||||
// Not all cgroup manager implementations support changing
|
|
||||||
// the ownership.
|
|
||||||
OwnerUID *int `json:"owner_uid,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Resources struct {
|
type Resources struct {
|
||||||
@ -126,9 +117,6 @@ type Resources struct {
|
|||||||
// Set class identifier for container's network packets
|
// Set class identifier for container's network packets
|
||||||
NetClsClassid uint32 `json:"net_cls_classid_u"`
|
NetClsClassid uint32 `json:"net_cls_classid_u"`
|
||||||
|
|
||||||
// Rdma resource restriction configuration
|
|
||||||
Rdma map[string]LinuxRdma `json:"rdma"`
|
|
||||||
|
|
||||||
// Used on cgroups v2:
|
// Used on cgroups v2:
|
||||||
|
|
||||||
// CpuWeight sets a proportional bandwidth limit.
|
// CpuWeight sets a proportional bandwidth limit.
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build !linux
|
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package configs
|
package configs
|
||||||
|
34
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
34
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
@ -7,10 +7,10 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
"github.com/opencontainers/runc/libcontainer/devices"
|
"github.com/opencontainers/runc/libcontainer/devices"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Rlimit struct {
|
type Rlimit struct {
|
||||||
@ -31,12 +31,10 @@ type IDMap struct {
|
|||||||
// for syscalls. Additional architectures can be added by specifying them in
|
// for syscalls. Additional architectures can be added by specifying them in
|
||||||
// Architectures.
|
// Architectures.
|
||||||
type Seccomp struct {
|
type Seccomp struct {
|
||||||
DefaultAction Action `json:"default_action"`
|
DefaultAction Action `json:"default_action"`
|
||||||
Architectures []string `json:"architectures"`
|
Architectures []string `json:"architectures"`
|
||||||
Syscalls []*Syscall `json:"syscalls"`
|
Syscalls []*Syscall `json:"syscalls"`
|
||||||
DefaultErrnoRet *uint `json:"default_errno_ret"`
|
DefaultErrnoRet *uint `json:"default_errno_ret"`
|
||||||
ListenerPath string `json:"listener_path,omitempty"`
|
|
||||||
ListenerMetadata string `json:"listener_metadata,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action is taken upon rule match in Seccomp
|
// Action is taken upon rule match in Seccomp
|
||||||
@ -49,9 +47,6 @@ const (
|
|||||||
Allow
|
Allow
|
||||||
Trace
|
Trace
|
||||||
Log
|
Log
|
||||||
Notify
|
|
||||||
KillThread
|
|
||||||
KillProcess
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Operator is a comparison operator to be used when matching syscall arguments in Seccomp
|
// Operator is a comparison operator to be used when matching syscall arguments in Seccomp
|
||||||
@ -251,19 +246,6 @@ const (
|
|||||||
Poststop HookName = "poststop"
|
Poststop HookName = "poststop"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KnownHookNames returns the known hook names.
|
|
||||||
// Used by `runc features`.
|
|
||||||
func KnownHookNames() []string {
|
|
||||||
return []string{
|
|
||||||
string(Prestart), // deprecated
|
|
||||||
string(CreateRuntime),
|
|
||||||
string(CreateContainer),
|
|
||||||
string(StartContainer),
|
|
||||||
string(Poststart),
|
|
||||||
string(Poststop),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Capabilities struct {
|
type Capabilities struct {
|
||||||
// Bounding is the set of capabilities checked by the kernel.
|
// Bounding is the set of capabilities checked by the kernel.
|
||||||
Bounding []string
|
Bounding []string
|
||||||
@ -280,7 +262,7 @@ type Capabilities struct {
|
|||||||
func (hooks HookList) RunHooks(state *specs.State) error {
|
func (hooks HookList) RunHooks(state *specs.State) error {
|
||||||
for i, h := range hooks {
|
for i, h := range hooks {
|
||||||
if err := h.Run(state); err != nil {
|
if err := h.Run(state); err != nil {
|
||||||
return fmt.Errorf("error running hook #%d: %w", i, err)
|
return errors.Wrapf(err, "Running hook #%d:", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +375,7 @@ func (c Command) Run(s *specs.State) error {
|
|||||||
go func() {
|
go func() {
|
||||||
err := cmd.Wait()
|
err := cmd.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("error running hook: %w, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
|
err = fmt.Errorf("error running hook: %v, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
|
||||||
}
|
}
|
||||||
errC <- err
|
errC <- err
|
||||||
}()
|
}()
|
||||||
|
17
vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
generated
vendored
17
vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
generated
vendored
@ -1,24 +1,17 @@
|
|||||||
package configs
|
package configs
|
||||||
|
|
||||||
import "errors"
|
import "fmt"
|
||||||
|
|
||||||
var (
|
|
||||||
errNoUIDMap = errors.New("User namespaces enabled, but no uid mappings found.")
|
|
||||||
errNoUserMap = errors.New("User namespaces enabled, but no user mapping found.")
|
|
||||||
errNoGIDMap = errors.New("User namespaces enabled, but no gid mappings found.")
|
|
||||||
errNoGroupMap = errors.New("User namespaces enabled, but no group mapping found.")
|
|
||||||
)
|
|
||||||
|
|
||||||
// HostUID gets the translated uid for the process on host which could be
|
// HostUID gets the translated uid for the process on host which could be
|
||||||
// different when user namespaces are enabled.
|
// different when user namespaces are enabled.
|
||||||
func (c Config) HostUID(containerId int) (int, error) {
|
func (c Config) HostUID(containerId int) (int, error) {
|
||||||
if c.Namespaces.Contains(NEWUSER) {
|
if c.Namespaces.Contains(NEWUSER) {
|
||||||
if c.UidMappings == nil {
|
if c.UidMappings == nil {
|
||||||
return -1, errNoUIDMap
|
return -1, fmt.Errorf("User namespaces enabled, but no uid mappings found.")
|
||||||
}
|
}
|
||||||
id, found := c.hostIDFromMapping(containerId, c.UidMappings)
|
id, found := c.hostIDFromMapping(containerId, c.UidMappings)
|
||||||
if !found {
|
if !found {
|
||||||
return -1, errNoUserMap
|
return -1, fmt.Errorf("User namespaces enabled, but no user mapping found.")
|
||||||
}
|
}
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
@ -37,11 +30,11 @@ func (c Config) HostRootUID() (int, error) {
|
|||||||
func (c Config) HostGID(containerId int) (int, error) {
|
func (c Config) HostGID(containerId int) (int, error) {
|
||||||
if c.Namespaces.Contains(NEWUSER) {
|
if c.Namespaces.Contains(NEWUSER) {
|
||||||
if c.GidMappings == nil {
|
if c.GidMappings == nil {
|
||||||
return -1, errNoGIDMap
|
return -1, fmt.Errorf("User namespaces enabled, but no gid mappings found.")
|
||||||
}
|
}
|
||||||
id, found := c.hostIDFromMapping(containerId, c.GidMappings)
|
id, found := c.hostIDFromMapping(containerId, c.GidMappings)
|
||||||
if !found {
|
if !found {
|
||||||
return -1, errNoGroupMap
|
return -1, fmt.Errorf("User namespaces enabled, but no group mapping found.")
|
||||||
}
|
}
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build gofuzz
|
|
||||||
// +build gofuzz
|
// +build gofuzz
|
||||||
|
|
||||||
package configs
|
package configs
|
||||||
|
3
vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
generated
vendored
3
vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
generated
vendored
@ -1,9 +1,6 @@
|
|||||||
package configs
|
package configs
|
||||||
|
|
||||||
type IntelRdt struct {
|
type IntelRdt struct {
|
||||||
// The identity for RDT Class of Service
|
|
||||||
ClosID string `json:"closID,omitempty"`
|
|
||||||
|
|
||||||
// The schema for L3 cache id and capacity bitmask (CBM)
|
// The schema for L3 cache id and capacity bitmask (CBM)
|
||||||
// Format: "L3:<cache_id0>=<cbm0>;<cache_id1>=<cbm1>;..."
|
// Format: "L3:<cache_id0>=<cbm0>;<cache_id1>=<cbm1>;..."
|
||||||
L3CacheSchema string `json:"l3_cache_schema,omitempty"`
|
L3CacheSchema string `json:"l3_cache_schema,omitempty"`
|
||||||
|
9
vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
generated
vendored
9
vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
generated
vendored
@ -1,7 +1,5 @@
|
|||||||
package configs
|
package configs
|
||||||
|
|
||||||
import "golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// EXT_COPYUP is a directive to copy up the contents of a directory when
|
// EXT_COPYUP is a directive to copy up the contents of a directory when
|
||||||
// a tmpfs is mounted over it.
|
// a tmpfs is mounted over it.
|
||||||
@ -30,9 +28,6 @@ type Mount struct {
|
|||||||
// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
|
// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
|
||||||
Relabel string `json:"relabel"`
|
Relabel string `json:"relabel"`
|
||||||
|
|
||||||
// RecAttr represents mount properties to be applied recursively (AT_RECURSIVE), see mount_setattr(2).
|
|
||||||
RecAttr *unix.MountAttr `json:"rec_attr"`
|
|
||||||
|
|
||||||
// Extensions are additional flags that are specific to runc.
|
// Extensions are additional flags that are specific to runc.
|
||||||
Extensions int `json:"extensions"`
|
Extensions int `json:"extensions"`
|
||||||
|
|
||||||
@ -42,7 +37,3 @@ type Mount struct {
|
|||||||
// Optional Command to be run after Source is mounted.
|
// Optional Command to be run after Source is mounted.
|
||||||
PostmountCmds []Command `json:"postmount_cmds"`
|
PostmountCmds []Command `json:"postmount_cmds"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mount) IsBind() bool {
|
|
||||||
return m.Flags&unix.MS_BIND != 0
|
|
||||||
}
|
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build linux
|
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package configs
|
package configs
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build !linux && !windows
|
|
||||||
// +build !linux,!windows
|
// +build !linux,!windows
|
||||||
|
|
||||||
package configs
|
package configs
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build !linux
|
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package configs
|
package configs
|
||||||
|
9
vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go
generated
vendored
9
vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
package configs
|
|
||||||
|
|
||||||
// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11)
|
|
||||||
type LinuxRdma struct {
|
|
||||||
// Maximum number of HCA handles that can be opened. Default is "no limit".
|
|
||||||
HcaHandles *uint32 `json:"hca_handles,omitempty"`
|
|
||||||
// Maximum number of HCA objects that can be created. Default is "no limit".
|
|
||||||
HcaObjects *uint32 `json:"hca_objects,omitempty"`
|
|
||||||
}
|
|
12
vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
generated
vendored
12
vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
generated
vendored
@ -1,10 +1,10 @@
|
|||||||
//go:build !windows
|
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package devices
|
package devices
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
@ -16,8 +16,8 @@ var ErrNotADevice = errors.New("not a device node")
|
|||||||
|
|
||||||
// Testing dependencies
|
// Testing dependencies
|
||||||
var (
|
var (
|
||||||
unixLstat = unix.Lstat
|
unixLstat = unix.Lstat
|
||||||
osReadDir = os.ReadDir
|
ioutilReadDir = ioutil.ReadDir
|
||||||
)
|
)
|
||||||
|
|
||||||
func mkDev(d *Rule) (uint64, error) {
|
func mkDev(d *Rule) (uint64, error) {
|
||||||
@ -40,7 +40,7 @@ func DeviceFromPath(path, permissions string) (*Device, error) {
|
|||||||
var (
|
var (
|
||||||
devType Type
|
devType Type
|
||||||
mode = stat.Mode
|
mode = stat.Mode
|
||||||
devNumber = uint64(stat.Rdev) //nolint:unconvert // Rdev is uint32 on e.g. MIPS.
|
devNumber = uint64(stat.Rdev)
|
||||||
major = unix.Major(devNumber)
|
major = unix.Major(devNumber)
|
||||||
minor = unix.Minor(devNumber)
|
minor = unix.Minor(devNumber)
|
||||||
)
|
)
|
||||||
@ -76,7 +76,7 @@ func HostDevices() ([]*Device, error) {
|
|||||||
// GetDevices recursively traverses a directory specified by path
|
// GetDevices recursively traverses a directory specified by path
|
||||||
// and returns all devices found there.
|
// and returns all devices found there.
|
||||||
func GetDevices(path string) ([]*Device, error) {
|
func GetDevices(path string) ([]*Device, error) {
|
||||||
files, err := osReadDir(path)
|
files, err := ioutilReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ func GetDevices(path string) ([]*Device, error) {
|
|||||||
}
|
}
|
||||||
device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
|
device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrNotADevice) {
|
if err == ErrNotADevice {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
|
||||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
package user
|
package user
|
||||||
|
21
vendor/github.com/opencontainers/runc/libcontainer/user/user.go
generated
vendored
21
vendor/github.com/opencontainers/runc/libcontainer/user/user.go
generated
vendored
@ -120,7 +120,7 @@ func ParsePasswdFileFilter(path string, filter func(User) bool) ([]User, error)
|
|||||||
|
|
||||||
func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
|
func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, errors.New("nil source for passwd-formatted data")
|
return nil, fmt.Errorf("nil source for passwd-formatted data")
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -178,7 +178,7 @@ func ParseGroupFileFilter(path string, filter func(Group) bool) ([]Group, error)
|
|||||||
|
|
||||||
func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
|
func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, errors.New("nil source for group-formatted data")
|
return nil, fmt.Errorf("nil source for group-formatted data")
|
||||||
}
|
}
|
||||||
rd := bufio.NewReader(r)
|
rd := bufio.NewReader(r)
|
||||||
out := []Group{}
|
out := []Group{}
|
||||||
@ -339,7 +339,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
|||||||
if userArg == "" {
|
if userArg == "" {
|
||||||
userArg = strconv.Itoa(user.Uid)
|
userArg = strconv.Itoa(user.Uid)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("unable to find user %s: %w", userArg, err)
|
return nil, fmt.Errorf("unable to find user %s: %v", userArg, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var matchedUserName string
|
var matchedUserName string
|
||||||
@ -355,7 +355,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
|||||||
|
|
||||||
if uidErr != nil {
|
if uidErr != nil {
|
||||||
// Not numeric.
|
// Not numeric.
|
||||||
return nil, fmt.Errorf("unable to find user %s: %w", userArg, ErrNoPasswdEntries)
|
return nil, fmt.Errorf("unable to find user %s: %v", userArg, ErrNoPasswdEntries)
|
||||||
}
|
}
|
||||||
user.Uid = uidArg
|
user.Uid = uidArg
|
||||||
|
|
||||||
@ -390,7 +390,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
|||||||
return g.Name == groupArg
|
return g.Name == groupArg
|
||||||
})
|
})
|
||||||
if err != nil && group != nil {
|
if err != nil && group != nil {
|
||||||
return nil, fmt.Errorf("unable to find groups for spec %v: %w", matchedUserName, err)
|
return nil, fmt.Errorf("unable to find groups for spec %v: %v", matchedUserName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only start modifying user.Gid if it is in explicit form.
|
// Only start modifying user.Gid if it is in explicit form.
|
||||||
@ -404,7 +404,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
|||||||
|
|
||||||
if gidErr != nil {
|
if gidErr != nil {
|
||||||
// Not numeric.
|
// Not numeric.
|
||||||
return nil, fmt.Errorf("unable to find group %s: %w", groupArg, ErrNoGroupEntries)
|
return nil, fmt.Errorf("unable to find group %s: %v", groupArg, ErrNoGroupEntries)
|
||||||
}
|
}
|
||||||
user.Gid = gidArg
|
user.Gid = gidArg
|
||||||
|
|
||||||
@ -445,7 +445,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
|
|||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Unable to find additional groups %v: %w", additionalGroups, err)
|
return nil, fmt.Errorf("Unable to find additional groups %v: %v", additionalGroups, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,8 +468,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
|
|||||||
if !found {
|
if !found {
|
||||||
gid, err := strconv.ParseInt(ag, 10, 64)
|
gid, err := strconv.ParseInt(ag, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Not a numeric ID either.
|
return nil, fmt.Errorf("Unable to find group %s", ag)
|
||||||
return nil, fmt.Errorf("Unable to find group %s: %w", ag, ErrNoGroupEntries)
|
|
||||||
}
|
}
|
||||||
// Ensure gid is inside gid range.
|
// Ensure gid is inside gid range.
|
||||||
if gid < minID || gid > maxID {
|
if gid < minID || gid > maxID {
|
||||||
@ -522,7 +521,7 @@ func ParseSubIDFileFilter(path string, filter func(SubID) bool) ([]SubID, error)
|
|||||||
|
|
||||||
func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
|
func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, errors.New("nil source for subid-formatted data")
|
return nil, fmt.Errorf("nil source for subid-formatted data")
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -575,7 +574,7 @@ func ParseIDMapFileFilter(path string, filter func(IDMap) bool) ([]IDMap, error)
|
|||||||
|
|
||||||
func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
|
func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, errors.New("nil source for idmap-formatted data")
|
return nil, fmt.Errorf("nil source for idmap-formatted data")
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build gofuzz
|
|
||||||
// +build gofuzz
|
// +build gofuzz
|
||||||
|
|
||||||
package user
|
package user
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build gofuzz
|
|
||||||
// +build gofuzz
|
// +build gofuzz
|
||||||
|
|
||||||
package userns
|
package userns
|
||||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build !linux
|
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package userns
|
package userns
|
||||||
|
11
vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
generated
vendored
11
vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
generated
vendored
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -86,11 +88,6 @@ func SendFd(socket *os.File, name string, fd uintptr) error {
|
|||||||
if len(name) >= MaxNameLen {
|
if len(name) >= MaxNameLen {
|
||||||
return fmt.Errorf("sendfd: filename too long: %s", name)
|
return fmt.Errorf("sendfd: filename too long: %s", name)
|
||||||
}
|
}
|
||||||
return SendFds(socket, []byte(name), int(fd))
|
oob := unix.UnixRights(int(fd))
|
||||||
}
|
return unix.Sendmsg(int(socket.Fd()), []byte(name), oob, nil, 0)
|
||||||
|
|
||||||
// SendFds sends a list of files descriptor and msg over the given AF_UNIX socket.
|
|
||||||
func SendFds(socket *os.File, msg []byte, fds ...int) error {
|
|
||||||
oob := unix.UnixRights(fds...)
|
|
||||||
return unix.Sendmsg(int(socket.Fd()), msg, oob, nil, 0)
|
|
||||||
}
|
}
|
||||||
|
14
vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
generated
vendored
14
vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
securejoin "github.com/cyphar/filepath-securejoin"
|
"github.com/cyphar/filepath-securejoin"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +33,16 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveRootfs ensures that the current working directory is
|
||||||
|
// not a symlink and returns the absolute path to the rootfs
|
||||||
|
func ResolveRootfs(uncleanRootfs string) (string, error) {
|
||||||
|
rootfs, err := filepath.Abs(uncleanRootfs)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.EvalSymlinks(rootfs)
|
||||||
|
}
|
||||||
|
|
||||||
// ExitStatus returns the correct exit status for a process based on if it
|
// ExitStatus returns the correct exit status for a process based on if it
|
||||||
// was signaled or exited cleanly
|
// was signaled or exited cleanly
|
||||||
func ExitStatus(status unix.WaitStatus) int {
|
func ExitStatus(status unix.WaitStatus) int {
|
||||||
@ -110,7 +120,7 @@ func WithProcfd(root, unsafePath string, fn func(procfd string) error) error {
|
|||||||
unsafePath = stripRoot(root, unsafePath)
|
unsafePath = stripRoot(root, unsafePath)
|
||||||
path, err := securejoin.SecureJoin(root, unsafePath)
|
path, err := securejoin.SecureJoin(root, unsafePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("resolving path inside rootfs failed: %w", err)
|
return fmt.Errorf("resolving path inside rootfs failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the target path.
|
// Open the target path.
|
||||||
|
5
vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
generated
vendored
5
vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
//go:build !windows
|
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package utils
|
package utils
|
||||||
@ -15,7 +14,7 @@ import (
|
|||||||
func EnsureProcHandle(fh *os.File) error {
|
func EnsureProcHandle(fh *os.File) error {
|
||||||
var buf unix.Statfs_t
|
var buf unix.Statfs_t
|
||||||
if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil {
|
if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil {
|
||||||
return fmt.Errorf("ensure %s is on procfs: %w", fh.Name(), err)
|
return fmt.Errorf("ensure %s is on procfs: %v", fh.Name(), err)
|
||||||
}
|
}
|
||||||
if buf.Type != unix.PROC_SUPER_MAGIC {
|
if buf.Type != unix.PROC_SUPER_MAGIC {
|
||||||
return fmt.Errorf("%s is not on procfs", fh.Name())
|
return fmt.Errorf("%s is not on procfs", fh.Name())
|
||||||
@ -53,7 +52,7 @@ func CloseExecFrom(minFd int) error {
|
|||||||
// Intentionally ignore errors from unix.CloseOnExec -- the cases where
|
// Intentionally ignore errors from unix.CloseOnExec -- the cases where
|
||||||
// this might fail are basically file descriptors that have already
|
// this might fail are basically file descriptors that have already
|
||||||
// been closed (including and especially the one that was created when
|
// been closed (including and especially the one that was created when
|
||||||
// os.ReadDir did the "opendir" syscall).
|
// ioutil.ReadDir did the "opendir" syscall).
|
||||||
unix.CloseOnExec(fd)
|
unix.CloseOnExec(fd)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
53
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
generated
vendored
53
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
generated
vendored
@ -15,7 +15,7 @@ type Spec struct {
|
|||||||
// Mounts configures additional mounts (on top of Root).
|
// Mounts configures additional mounts (on top of Root).
|
||||||
Mounts []Mount `json:"mounts,omitempty"`
|
Mounts []Mount `json:"mounts,omitempty"`
|
||||||
// Hooks configures callbacks for container lifecycle events.
|
// Hooks configures callbacks for container lifecycle events.
|
||||||
Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris"`
|
Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris,zos"`
|
||||||
// Annotations contains arbitrary metadata for the container.
|
// Annotations contains arbitrary metadata for the container.
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
|
||||||
@ -27,6 +27,8 @@ type Spec struct {
|
|||||||
Windows *Windows `json:"windows,omitempty" platform:"windows"`
|
Windows *Windows `json:"windows,omitempty" platform:"windows"`
|
||||||
// VM specifies configuration for virtual-machine-based containers.
|
// VM specifies configuration for virtual-machine-based containers.
|
||||||
VM *VM `json:"vm,omitempty" platform:"vm"`
|
VM *VM `json:"vm,omitempty" platform:"vm"`
|
||||||
|
// ZOS is platform-specific configuration for z/OS based containers.
|
||||||
|
ZOS *ZOS `json:"zos,omitempty" platform:"zos"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process contains information to start a specific application inside the container.
|
// Process contains information to start a specific application inside the container.
|
||||||
@ -49,7 +51,7 @@ type Process struct {
|
|||||||
// Capabilities are Linux capabilities that are kept for the process.
|
// Capabilities are Linux capabilities that are kept for the process.
|
||||||
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
|
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
|
||||||
// Rlimits specifies rlimit options to apply to the process.
|
// Rlimits specifies rlimit options to apply to the process.
|
||||||
Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris"`
|
Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris,zos"`
|
||||||
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container.
|
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container.
|
||||||
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"`
|
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"`
|
||||||
// ApparmorProfile specifies the apparmor profile for the container.
|
// ApparmorProfile specifies the apparmor profile for the container.
|
||||||
@ -86,11 +88,11 @@ type Box struct {
|
|||||||
// User specifies specific user (and group) information for the container process.
|
// User specifies specific user (and group) information for the container process.
|
||||||
type User struct {
|
type User struct {
|
||||||
// UID is the user id.
|
// UID is the user id.
|
||||||
UID uint32 `json:"uid" platform:"linux,solaris"`
|
UID uint32 `json:"uid" platform:"linux,solaris,zos"`
|
||||||
// GID is the group id.
|
// GID is the group id.
|
||||||
GID uint32 `json:"gid" platform:"linux,solaris"`
|
GID uint32 `json:"gid" platform:"linux,solaris,zos"`
|
||||||
// Umask is the umask for the init process.
|
// Umask is the umask for the init process.
|
||||||
Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris"`
|
Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris,zos"`
|
||||||
// AdditionalGids are additional group ids set for the container's process.
|
// AdditionalGids are additional group ids set for the container's process.
|
||||||
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
||||||
// Username is the user name.
|
// Username is the user name.
|
||||||
@ -110,7 +112,7 @@ type Mount struct {
|
|||||||
// Destination is the absolute path where the mount will be placed in the container.
|
// Destination is the absolute path where the mount will be placed in the container.
|
||||||
Destination string `json:"destination"`
|
Destination string `json:"destination"`
|
||||||
// Type specifies the mount kind.
|
// Type specifies the mount kind.
|
||||||
Type string `json:"type,omitempty" platform:"linux,solaris"`
|
Type string `json:"type,omitempty" platform:"linux,solaris,zos"`
|
||||||
// Source specifies the source path of the mount.
|
// Source specifies the source path of the mount.
|
||||||
Source string `json:"source,omitempty"`
|
Source string `json:"source,omitempty"`
|
||||||
// Options are fstab style mount options.
|
// Options are fstab style mount options.
|
||||||
@ -178,7 +180,7 @@ type Linux struct {
|
|||||||
// MountLabel specifies the selinux context for the mounts in the container.
|
// MountLabel specifies the selinux context for the mounts in the container.
|
||||||
MountLabel string `json:"mountLabel,omitempty"`
|
MountLabel string `json:"mountLabel,omitempty"`
|
||||||
// IntelRdt contains Intel Resource Director Technology (RDT) information for
|
// IntelRdt contains Intel Resource Director Technology (RDT) information for
|
||||||
// handling resource constraints (e.g., L3 cache, memory bandwidth) for the container
|
// handling resource constraints and monitoring metrics (e.g., L3 cache, memory bandwidth) for the container
|
||||||
IntelRdt *LinuxIntelRdt `json:"intelRdt,omitempty"`
|
IntelRdt *LinuxIntelRdt `json:"intelRdt,omitempty"`
|
||||||
// Personality contains configuration for the Linux personality syscall
|
// Personality contains configuration for the Linux personality syscall
|
||||||
Personality *LinuxPersonality `json:"personality,omitempty"`
|
Personality *LinuxPersonality `json:"personality,omitempty"`
|
||||||
@ -683,8 +685,9 @@ type LinuxSyscall struct {
|
|||||||
Args []LinuxSeccompArg `json:"args,omitempty"`
|
Args []LinuxSeccompArg `json:"args,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxIntelRdt has container runtime resource constraints for Intel RDT
|
// LinuxIntelRdt has container runtime resource constraints for Intel RDT CAT and MBA
|
||||||
// CAT and MBA features which introduced in Linux 4.10 and 4.12 kernel
|
// features and flags enabling Intel RDT CMT and MBM features.
|
||||||
|
// Intel RDT features are available in Linux 4.14 and newer kernel versions.
|
||||||
type LinuxIntelRdt struct {
|
type LinuxIntelRdt struct {
|
||||||
// The identity for RDT Class of Service
|
// The identity for RDT Class of Service
|
||||||
ClosID string `json:"closID,omitempty"`
|
ClosID string `json:"closID,omitempty"`
|
||||||
@ -697,4 +700,36 @@ type LinuxIntelRdt struct {
|
|||||||
// The unit of memory bandwidth is specified in "percentages" by
|
// The unit of memory bandwidth is specified in "percentages" by
|
||||||
// default, and in "MBps" if MBA Software Controller is enabled.
|
// default, and in "MBps" if MBA Software Controller is enabled.
|
||||||
MemBwSchema string `json:"memBwSchema,omitempty"`
|
MemBwSchema string `json:"memBwSchema,omitempty"`
|
||||||
|
|
||||||
|
// EnableCMT is the flag to indicate if the Intel RDT CMT is enabled. CMT (Cache Monitoring Technology) supports monitoring of
|
||||||
|
// the last-level cache (LLC) occupancy for the container.
|
||||||
|
EnableCMT bool `json:"enableCMT,omitempty"`
|
||||||
|
|
||||||
|
// EnableMBM is the flag to indicate if the Intel RDT MBM is enabled. MBM (Memory Bandwidth Monitoring) supports monitoring of
|
||||||
|
// total and local memory bandwidth for the container.
|
||||||
|
EnableMBM bool `json:"enableMBM,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOS contains platform-specific configuration for z/OS based containers.
|
||||||
|
type ZOS struct {
|
||||||
|
// Devices are a list of device nodes that are created for the container
|
||||||
|
Devices []ZOSDevice `json:"devices,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOSDevice represents the mknod information for a z/OS special device file
|
||||||
|
type ZOSDevice struct {
|
||||||
|
// Path to the device.
|
||||||
|
Path string `json:"path"`
|
||||||
|
// Device type, block, char, etc.
|
||||||
|
Type string `json:"type"`
|
||||||
|
// Major is the device's major number.
|
||||||
|
Major int64 `json:"major"`
|
||||||
|
// Minor is the device's minor number.
|
||||||
|
Minor int64 `json:"minor"`
|
||||||
|
// FileMode permission bits for the device.
|
||||||
|
FileMode *os.FileMode `json:"fileMode,omitempty"`
|
||||||
|
// UID of the device.
|
||||||
|
UID *uint32 `json:"uid,omitempty"`
|
||||||
|
// Gid of the device.
|
||||||
|
GID *uint32 `json:"gid,omitempty"`
|
||||||
}
|
}
|
||||||
|
28
vendor/github.com/opencontainers/runtime-tools/generate/config.go
generated
vendored
28
vendor/github.com/opencontainers/runtime-tools/generate/config.go
generated
vendored
@ -123,6 +123,13 @@ func (g *Generator) initConfigLinuxResourcesPids() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Generator) initConfigLinuxResourcesUnified() {
|
||||||
|
g.initConfigLinuxResources()
|
||||||
|
if g.Config.Linux.Resources.Unified == nil {
|
||||||
|
g.Config.Linux.Resources.Unified = map[string]string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Generator) initConfigSolaris() {
|
func (g *Generator) initConfigSolaris() {
|
||||||
g.initConfig()
|
g.initConfig()
|
||||||
if g.Config.Solaris == nil {
|
if g.Config.Solaris == nil {
|
||||||
@ -185,24 +192,3 @@ func (g *Generator) initConfigVM() {
|
|||||||
g.Config.VM = &rspec.VM{}
|
g.Config.VM = &rspec.VM{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Generator) initConfigVMHypervisor() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Hypervisor == nil {
|
|
||||||
g.Config.VM.Hypervisor = rspec.VMHypervisor{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) initConfigVMKernel() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Kernel == nil {
|
|
||||||
g.Config.VM.Kernel = rspec.VMKernel{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) initConfigVMImage() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Image == nil {
|
|
||||||
g.Config.VM.Image = rspec.VMImage{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
55
vendor/github.com/opencontainers/runtime-tools/generate/generate.go
generated
vendored
55
vendor/github.com/opencontainers/runtime-tools/generate/generate.go
generated
vendored
@ -604,6 +604,12 @@ func (g *Generator) SetLinuxCgroupsPath(path string) {
|
|||||||
g.Config.Linux.CgroupsPath = path
|
g.Config.Linux.CgroupsPath = path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLinuxIntelRdtClosID sets g.Config.Linux.IntelRdt.ClosID
|
||||||
|
func (g *Generator) SetLinuxIntelRdtClosID(clos string) {
|
||||||
|
g.initConfigLinuxIntelRdt()
|
||||||
|
g.Config.Linux.IntelRdt.ClosID = clos
|
||||||
|
}
|
||||||
|
|
||||||
// SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
|
// SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
|
||||||
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
|
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
|
||||||
g.initConfigLinuxIntelRdt()
|
g.initConfigLinuxIntelRdt()
|
||||||
@ -851,6 +857,28 @@ func (g *Generator) DropLinuxResourcesHugepageLimit(pageSize string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddLinuxResourcesUnified sets the g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) SetLinuxResourcesUnified(unified map[string]string) {
|
||||||
|
g.initConfigLinuxResourcesUnified()
|
||||||
|
for k, v := range unified {
|
||||||
|
g.Config.Linux.Resources.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxResourcesUnified adds or updates the key-value pair from g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) AddLinuxResourcesUnified(key, val string) {
|
||||||
|
g.initConfigLinuxResourcesUnified()
|
||||||
|
g.Config.Linux.Resources.Unified[key] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// DropLinuxResourcesUnified drops a key-value pair from g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) DropLinuxResourcesUnified(key string) {
|
||||||
|
if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.Unified == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(g.Config.Linux.Resources.Unified, key)
|
||||||
|
}
|
||||||
|
|
||||||
// SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
|
// SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
|
||||||
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
|
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
|
||||||
g.initConfigLinuxResourcesMemory()
|
g.initConfigLinuxResourcesMemory()
|
||||||
@ -1025,10 +1053,9 @@ func (g *Generator) ClearPreStartHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
|
// AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
|
||||||
func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) error {
|
func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
|
g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
|
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
|
||||||
@ -1040,10 +1067,9 @@ func (g *Generator) ClearPostStopHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
|
// AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
|
||||||
func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) error {
|
func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
|
g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
|
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
|
||||||
@ -1055,10 +1081,9 @@ func (g *Generator) ClearPostStartHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
|
// AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
|
||||||
func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) error {
|
func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
|
g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddMount adds a mount into g.Config.Mounts.
|
// AddMount adds a mount into g.Config.Mounts.
|
||||||
@ -1560,12 +1585,8 @@ func (g *Generator) RemoveLinuxResourcesDevice(allow bool, devType string, major
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// strPtr returns the pointer pointing to the string s.
|
|
||||||
func strPtr(s string) *string { return &s }
|
|
||||||
|
|
||||||
// SetSyscallAction adds rules for syscalls with the specified action
|
// SetSyscallAction adds rules for syscalls with the specified action
|
||||||
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
|
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
|
||||||
g.initConfigLinuxSeccomp()
|
g.initConfigLinuxSeccomp()
|
||||||
@ -1691,14 +1712,14 @@ func (g *Generator) SetVMHypervisorPath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
|
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMHypervisor()
|
g.initConfigVM()
|
||||||
g.Config.VM.Hypervisor.Path = path
|
g.Config.VM.Hypervisor.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
|
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
|
||||||
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
|
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
|
||||||
g.initConfigVMHypervisor()
|
g.initConfigVM()
|
||||||
g.Config.VM.Hypervisor.Parameters = parameters
|
g.Config.VM.Hypervisor.Parameters = parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1707,14 +1728,14 @@ func (g *Generator) SetVMKernelPath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("kernelPath %v is not an absolute path", path)
|
return fmt.Errorf("kernelPath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.Path = path
|
g.Config.VM.Kernel.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
|
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
|
||||||
func (g *Generator) SetVMKernelParameters(parameters []string) {
|
func (g *Generator) SetVMKernelParameters(parameters []string) {
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.Parameters = parameters
|
g.Config.VM.Kernel.Parameters = parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1723,7 +1744,7 @@ func (g *Generator) SetVMKernelInitRD(initrd string) error {
|
|||||||
if !strings.HasPrefix(initrd, "/") {
|
if !strings.HasPrefix(initrd, "/") {
|
||||||
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
|
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
|
||||||
}
|
}
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.InitRD = initrd
|
g.Config.VM.Kernel.InitRD = initrd
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1733,7 +1754,7 @@ func (g *Generator) SetVMImagePath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("imagePath %v is not an absolute path", path)
|
return fmt.Errorf("imagePath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMImage()
|
g.initConfigVM()
|
||||||
g.Config.VM.Image.Path = path
|
g.Config.VM.Image.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1749,7 +1770,7 @@ func (g *Generator) SetVMImageFormat(format string) error {
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
|
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
|
||||||
}
|
}
|
||||||
g.initConfigVMImage()
|
g.initConfigVM()
|
||||||
g.Config.VM.Image.Format = format
|
g.Config.VM.Image.Format = format
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
5
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
generated
vendored
5
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
generated
vendored
@ -4,9 +4,4 @@ const (
|
|||||||
seccompOverwrite = "overwrite"
|
seccompOverwrite = "overwrite"
|
||||||
seccompAppend = "append"
|
seccompAppend = "append"
|
||||||
nothing = "nothing"
|
nothing = "nothing"
|
||||||
kill = "kill"
|
|
||||||
trap = "trap"
|
|
||||||
trace = "trace"
|
|
||||||
allow = "allow"
|
|
||||||
errno = "errno"
|
|
||||||
)
|
)
|
||||||
|
1
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
generated
vendored
1
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package seccomp
|
package seccomp
|
||||||
|
1
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go
generated
vendored
1
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package seccomp
|
package seccomp
|
||||||
|
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
generated
vendored
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
generated
vendored
@ -92,22 +92,6 @@ func identical(config1, config2 *rspec.LinuxSyscall) bool {
|
|||||||
return reflect.DeepEqual(config1, config2)
|
return reflect.DeepEqual(config1, config2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool {
|
|
||||||
samename := sameName(config1, config2)
|
|
||||||
sameAction := sameAction(config1, config2)
|
|
||||||
sameArgs := sameArgs(config1, config2)
|
|
||||||
|
|
||||||
return samename && !sameAction && sameArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool {
|
|
||||||
samename := sameName(config1, config2)
|
|
||||||
sameAction := sameAction(config1, config2)
|
|
||||||
sameArgs := sameArgs(config1, config2)
|
|
||||||
|
|
||||||
return samename && sameAction && !sameArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
|
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
|
||||||
return reflect.DeepEqual(config1.Names, config2.Names)
|
return reflect.DeepEqual(config1.Names, config2.Names)
|
||||||
}
|
}
|
||||||
|
5
vendor/github.com/opencontainers/runtime-tools/validate/validate.go
generated
vendored
5
vendor/github.com/opencontainers/runtime-tools/validate/validate.go
generated
vendored
@ -131,9 +131,8 @@ func JSONSchemaURL(version string) (url string, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", specerror.NewError(specerror.SpecVersionInSemVer, err, rspec.Version)
|
return "", specerror.NewError(specerror.SpecVersionInSemVer, err, rspec.Version)
|
||||||
}
|
}
|
||||||
configRenamedToConfigSchemaVersion, err := semver.Parse("1.0.0-rc2") // config.json became config-schema.json in 1.0.0-rc2
|
if ver.LT(semver.Version{Major: 1, Minor: 0, Patch: 2}) {
|
||||||
if ver.Compare(configRenamedToConfigSchemaVersion) == -1 {
|
return "", errors.New("unsupported configuration version (older than 1.0.2)")
|
||||||
return "", fmt.Errorf("unsupported configuration version (older than %s)", configRenamedToConfigSchemaVersion)
|
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(configSchemaTemplate, version), nil
|
return fmt.Sprintf(configSchemaTemplate, version), nil
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
generated
vendored
1
vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package validate
|
package validate
|
||||||
|
1
vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go
generated
vendored
1
vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package validate
|
package validate
|
||||||
|
28
vendor/github.com/seccomp/libseccomp-golang/.travis.yml
generated
vendored
28
vendor/github.com/seccomp/libseccomp-golang/.travis.yml
generated
vendored
@ -19,39 +19,19 @@ os:
|
|||||||
|
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- name: "last libseccomp 2.5.0"
|
|
||||||
env:
|
|
||||||
- SECCOMP_VER=2.5.0
|
|
||||||
- SECCOMP_SHA256SUM=1ffa7038d2720ad191919816db3479295a4bcca1ec14e02f672539f4983014f3
|
|
||||||
- name: "compat libseccomp 2.4.4"
|
|
||||||
env:
|
|
||||||
- SECCOMP_VER=2.4.4
|
|
||||||
- SECCOMP_SHA256SUM=4e79738d1ef3c9b7ca9769f1f8b8d84fc17143c2c1c432e53b9c64787e0ff3eb
|
|
||||||
- name: "compat libseccomp 2.2.1"
|
|
||||||
env:
|
|
||||||
- SECCOMP_VER=2.2.1
|
|
||||||
- SECCOMP_SHA256SUM=0ba1789f54786c644af54cdffc9fd0dd0a8bb2b2ee153933f658855d2851a740
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
- build-essential
|
- build-essential
|
||||||
- astyle
|
# TODO: use the main libseccomp git repo instead of a distro package
|
||||||
- golint
|
- libseccomp2
|
||||||
- gperf
|
- libseccomp-dev
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- go get -u golang.org/x/lint/golint
|
- go get -u golang.org/x/lint/golint
|
||||||
|
|
||||||
# run all of the tests independently, fail if any of the tests error
|
# run all of the tests independently, fail if any of the tests error
|
||||||
script:
|
script:
|
||||||
- wget https://github.com/seccomp/libseccomp/releases/download/v$SECCOMP_VER/libseccomp-$SECCOMP_VER.tar.gz
|
|
||||||
- echo $SECCOMP_SHA256SUM libseccomp-$SECCOMP_VER.tar.gz | sha256sum -c
|
|
||||||
- tar xf libseccomp-$SECCOMP_VER.tar.gz
|
|
||||||
- pushd libseccomp-$SECCOMP_VER && ./configure --prefix=/opt/libseccomp-$SECCOMP_VER && make && sudo make install && popd
|
|
||||||
- make check-syntax
|
- make check-syntax
|
||||||
- make lint
|
- make lint
|
||||||
- PKG_CONFIG_PATH=/opt/libseccomp-$SECCOMP_VER/lib/pkgconfig LD_LIBRARY_PATH=/opt/libseccomp-$SECCOMP_VER/lib make vet
|
- make check
|
||||||
- PKG_CONFIG_PATH=/opt/libseccomp-$SECCOMP_VER/lib/pkgconfig LD_LIBRARY_PATH=/opt/libseccomp-$SECCOMP_VER/lib make test
|
|
||||||
|
8
vendor/github.com/seccomp/libseccomp-golang/Makefile
generated
vendored
8
vendor/github.com/seccomp/libseccomp-golang/Makefile
generated
vendored
@ -18,14 +18,8 @@ fix-syntax:
|
|||||||
vet:
|
vet:
|
||||||
go vet -v
|
go vet -v
|
||||||
|
|
||||||
# Previous bugs have made the tests freeze until the timeout. Golang default
|
|
||||||
# timeout for tests is 10 minutes, which is too long, considering current tests
|
|
||||||
# can be executed in less than 1 second. Reduce the timeout, so problems can
|
|
||||||
# be noticed earlier in the CI.
|
|
||||||
TEST_TIMEOUT=10s
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test -v -timeout $(TEST_TIMEOUT)
|
go test -v
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@$(if $(shell which golint),true,$(error "install golint and include it in your PATH"))
|
@$(if $(shell which golint),true,$(error "install golint and include it in your PATH"))
|
||||||
|
2
vendor/github.com/seccomp/libseccomp-golang/README.md
generated
vendored
2
vendor/github.com/seccomp/libseccomp-golang/README.md
generated
vendored
@ -2,7 +2,7 @@
|
|||||||
===============================================================================
|
===============================================================================
|
||||||
https://github.com/seccomp/libseccomp-golang
|
https://github.com/seccomp/libseccomp-golang
|
||||||
|
|
||||||
[](https://travis-ci.org/seccomp/libseccomp-golang)
|
[](https://travis-ci.org/seccomp/libseccomp-golang)
|
||||||
|
|
||||||
The libseccomp library provides an easy to use, platform independent, interface
|
The libseccomp library provides an easy to use, platform independent, interface
|
||||||
to the Linux Kernel's syscall filtering mechanism. The libseccomp API is
|
to the Linux Kernel's syscall filtering mechanism. The libseccomp API is
|
||||||
|
225
vendor/github.com/seccomp/libseccomp-golang/seccomp.go
generated
vendored
225
vendor/github.com/seccomp/libseccomp-golang/seccomp.go
generated
vendored
@ -20,13 +20,6 @@ import (
|
|||||||
|
|
||||||
// C wrapping code
|
// C wrapping code
|
||||||
|
|
||||||
// To compile libseccomp-golang against a specific version of libseccomp:
|
|
||||||
// cd ../libseccomp && mkdir -p prefix
|
|
||||||
// ./configure --prefix=$PWD/prefix && make && make install
|
|
||||||
// cd ../libseccomp-golang
|
|
||||||
// PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make
|
|
||||||
// LD_PRELOAD=$PWD/../libseccomp/prefix/lib/libseccomp.so.2.5.0 PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make test
|
|
||||||
|
|
||||||
// #cgo pkg-config: libseccomp
|
// #cgo pkg-config: libseccomp
|
||||||
// #include <stdlib.h>
|
// #include <stdlib.h>
|
||||||
// #include <seccomp.h>
|
// #include <seccomp.h>
|
||||||
@ -41,25 +34,19 @@ type VersionError struct {
|
|||||||
minimum string
|
minimum string
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
// This forces the cgo libseccomp to initialize its internal API support state,
|
|
||||||
// which is necessary on older versions of libseccomp in order to work
|
|
||||||
// correctly.
|
|
||||||
GetAPI()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e VersionError) Error() string {
|
func (e VersionError) Error() string {
|
||||||
messageStr := ""
|
format := "Libseccomp version too low: "
|
||||||
if e.message != "" {
|
if e.message != "" {
|
||||||
messageStr = e.message + ": "
|
format += e.message + ": "
|
||||||
}
|
}
|
||||||
minimumStr := ""
|
format += "minimum supported is "
|
||||||
if e.minimum != "" {
|
if e.minimum != "" {
|
||||||
minimumStr = e.minimum
|
format += e.minimum + ": "
|
||||||
} else {
|
} else {
|
||||||
minimumStr = "2.2.0"
|
format += "2.2.0: "
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("Libseccomp version too low: %sminimum supported is %s: detected %d.%d.%d", messageStr, minimumStr, verMajor, verMinor, verMicro)
|
format += "detected %d.%d.%d"
|
||||||
|
return fmt.Sprintf(format, verMajor, verMinor, verMicro)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScmpArch represents a CPU architecture. Seccomp can restrict syscalls on a
|
// ScmpArch represents a CPU architecture. Seccomp can restrict syscalls on a
|
||||||
@ -82,61 +69,9 @@ type ScmpCondition struct {
|
|||||||
Operand2 uint64 `json:"operand_two,omitempty"`
|
Operand2 uint64 `json:"operand_two,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seccomp userspace notification structures associated with filters that use the ActNotify action.
|
// ScmpSyscall represents a Linux System Call
|
||||||
|
|
||||||
// ScmpSyscall identifies a Linux System Call by its number.
|
|
||||||
type ScmpSyscall int32
|
type ScmpSyscall int32
|
||||||
|
|
||||||
// ScmpFd represents a file-descriptor used for seccomp userspace notifications.
|
|
||||||
type ScmpFd int32
|
|
||||||
|
|
||||||
// ScmpNotifData describes the system call context that triggered a notification.
|
|
||||||
//
|
|
||||||
// Syscall: the syscall number
|
|
||||||
// Arch: the filter architecture
|
|
||||||
// InstrPointer: address of the instruction that triggered a notification
|
|
||||||
// Args: arguments (up to 6) for the syscall
|
|
||||||
//
|
|
||||||
type ScmpNotifData struct {
|
|
||||||
Syscall ScmpSyscall `json:"syscall,omitempty"`
|
|
||||||
Arch ScmpArch `json:"arch,omitempty"`
|
|
||||||
InstrPointer uint64 `json:"instr_pointer,omitempty"`
|
|
||||||
Args []uint64 `json:"args,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScmpNotifReq represents a seccomp userspace notification. See NotifReceive() for
|
|
||||||
// info on how to pull such a notification.
|
|
||||||
//
|
|
||||||
// ID: notification ID
|
|
||||||
// Pid: process that triggered the notification event
|
|
||||||
// Flags: filter flags (see seccomp(2))
|
|
||||||
// Data: system call context that triggered the notification
|
|
||||||
//
|
|
||||||
type ScmpNotifReq struct {
|
|
||||||
ID uint64 `json:"id,omitempty"`
|
|
||||||
Pid uint32 `json:"pid,omitempty"`
|
|
||||||
Flags uint32 `json:"flags,omitempty"`
|
|
||||||
Data ScmpNotifData `json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScmpNotifResp represents a seccomp userspace notification response. See NotifRespond()
|
|
||||||
// for info on how to push such a response.
|
|
||||||
//
|
|
||||||
// ID: notification ID (must match the corresponding ScmpNotifReq ID)
|
|
||||||
// Error: must be 0 if no error occurred, or an error constant from package
|
|
||||||
// syscall (e.g., syscall.EPERM, etc). In the latter case, it's used
|
|
||||||
// as an error return from the syscall that created the notification.
|
|
||||||
// Val: return value for the syscall that created the notification. Only
|
|
||||||
// relevant if Error is 0.
|
|
||||||
// Flags: userspace notification response flag (e.g., NotifRespFlagContinue)
|
|
||||||
//
|
|
||||||
type ScmpNotifResp struct {
|
|
||||||
ID uint64 `json:"id,omitempty"`
|
|
||||||
Error int32 `json:"error,omitempty"`
|
|
||||||
Val uint64 `json:"val,omitempty"`
|
|
||||||
Flags uint32 `json:"flags,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exported Constants
|
// Exported Constants
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -182,10 +117,6 @@ const (
|
|||||||
ArchS390 ScmpArch = iota
|
ArchS390 ScmpArch = iota
|
||||||
// ArchS390X represents 64-bit System z/390 syscalls
|
// ArchS390X represents 64-bit System z/390 syscalls
|
||||||
ArchS390X ScmpArch = iota
|
ArchS390X ScmpArch = iota
|
||||||
// ArchPARISC represents 32-bit PA-RISC
|
|
||||||
ArchPARISC ScmpArch = iota
|
|
||||||
// ArchPARISC64 represents 64-bit PA-RISC
|
|
||||||
ArchPARISC64 ScmpArch = iota
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -199,9 +130,6 @@ const (
|
|||||||
ActKill ScmpAction = iota
|
ActKill ScmpAction = iota
|
||||||
// ActTrap throws SIGSYS
|
// ActTrap throws SIGSYS
|
||||||
ActTrap ScmpAction = iota
|
ActTrap ScmpAction = iota
|
||||||
// ActNotify triggers a userspace notification. This action is only usable when
|
|
||||||
// libseccomp API level 6 or higher is supported.
|
|
||||||
ActNotify ScmpAction = iota
|
|
||||||
// ActErrno causes the syscall to return a negative error code. This
|
// ActErrno causes the syscall to return a negative error code. This
|
||||||
// code can be set with the SetReturnCode method
|
// code can be set with the SetReturnCode method
|
||||||
ActErrno ScmpAction = iota
|
ActErrno ScmpAction = iota
|
||||||
@ -253,21 +181,6 @@ const (
|
|||||||
CompareMaskedEqual ScmpCompareOp = iota
|
CompareMaskedEqual ScmpCompareOp = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrSyscallDoesNotExist represents an error condition where
|
|
||||||
// libseccomp is unable to resolve the syscall
|
|
||||||
ErrSyscallDoesNotExist = fmt.Errorf("could not resolve syscall name")
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Userspace notification response flags
|
|
||||||
|
|
||||||
// NotifRespFlagContinue tells the kernel to continue executing the system
|
|
||||||
// call that triggered the notification. Must only be used when the notication
|
|
||||||
// response's error is 0.
|
|
||||||
NotifRespFlagContinue uint32 = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
// Helpers for types
|
// Helpers for types
|
||||||
|
|
||||||
// GetArchFromString returns an ScmpArch constant from a string representing an
|
// GetArchFromString returns an ScmpArch constant from a string representing an
|
||||||
@ -310,10 +223,6 @@ func GetArchFromString(arch string) (ScmpArch, error) {
|
|||||||
return ArchS390, nil
|
return ArchS390, nil
|
||||||
case "s390x":
|
case "s390x":
|
||||||
return ArchS390X, nil
|
return ArchS390X, nil
|
||||||
case "parisc":
|
|
||||||
return ArchPARISC, nil
|
|
||||||
case "parisc64":
|
|
||||||
return ArchPARISC64, nil
|
|
||||||
default:
|
default:
|
||||||
return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %q", arch)
|
return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %q", arch)
|
||||||
}
|
}
|
||||||
@ -354,10 +263,6 @@ func (a ScmpArch) String() string {
|
|||||||
return "s390"
|
return "s390"
|
||||||
case ArchS390X:
|
case ArchS390X:
|
||||||
return "s390x"
|
return "s390x"
|
||||||
case ArchPARISC:
|
|
||||||
return "parisc"
|
|
||||||
case ArchPARISC64:
|
|
||||||
return "parisc64"
|
|
||||||
case ArchNative:
|
case ArchNative:
|
||||||
return "native"
|
return "native"
|
||||||
case ArchInvalid:
|
case ArchInvalid:
|
||||||
@ -405,8 +310,6 @@ func (a ScmpAction) String() string {
|
|||||||
case ActTrace:
|
case ActTrace:
|
||||||
return fmt.Sprintf("Action: Notify tracing processes with code %d",
|
return fmt.Sprintf("Action: Notify tracing processes with code %d",
|
||||||
(a >> 16))
|
(a >> 16))
|
||||||
case ActNotify:
|
|
||||||
return "Action: Notify userspace"
|
|
||||||
case ActLog:
|
case ActLog:
|
||||||
return "Action: Log system call"
|
return "Action: Log system call"
|
||||||
case ActAllow:
|
case ActAllow:
|
||||||
@ -446,7 +349,7 @@ func GetLibraryVersion() (major, minor, micro uint) {
|
|||||||
// Returns a positive int containing the API level, or 0 with an error if the
|
// Returns a positive int containing the API level, or 0 with an error if the
|
||||||
// API level could not be detected due to the library being older than v2.4.0.
|
// API level could not be detected due to the library being older than v2.4.0.
|
||||||
// See the seccomp_api_get(3) man page for details on available API levels:
|
// See the seccomp_api_get(3) man page for details on available API levels:
|
||||||
// https://github.com/seccomp/libseccomp/blob/main/doc/man/man3/seccomp_api_get.3
|
// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
|
||||||
func GetAPI() (uint, error) {
|
func GetAPI() (uint, error) {
|
||||||
return getAPI()
|
return getAPI()
|
||||||
}
|
}
|
||||||
@ -456,7 +359,7 @@ func GetAPI() (uint, error) {
|
|||||||
// Returns an error if the API level could not be set. An error is always
|
// Returns an error if the API level could not be set. An error is always
|
||||||
// returned if the library is older than v2.4.0
|
// returned if the library is older than v2.4.0
|
||||||
// See the seccomp_api_get(3) man page for details on available API levels:
|
// See the seccomp_api_get(3) man page for details on available API levels:
|
||||||
// https://github.com/seccomp/libseccomp/blob/main/doc/man/man3/seccomp_api_get.3
|
// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
|
||||||
func SetAPI(api uint) error {
|
func SetAPI(api uint) error {
|
||||||
return setAPI(api)
|
return setAPI(api)
|
||||||
}
|
}
|
||||||
@ -483,7 +386,7 @@ func (s ScmpSyscall) GetNameByArch(arch ScmpArch) (string, error) {
|
|||||||
|
|
||||||
cString := C.seccomp_syscall_resolve_num_arch(arch.toNative(), C.int(s))
|
cString := C.seccomp_syscall_resolve_num_arch(arch.toNative(), C.int(s))
|
||||||
if cString == nil {
|
if cString == nil {
|
||||||
return "", ErrSyscallDoesNotExist
|
return "", fmt.Errorf("could not resolve syscall name for %#x", int32(s))
|
||||||
}
|
}
|
||||||
defer C.free(unsafe.Pointer(cString))
|
defer C.free(unsafe.Pointer(cString))
|
||||||
|
|
||||||
@ -506,7 +409,7 @@ func GetSyscallFromName(name string) (ScmpSyscall, error) {
|
|||||||
|
|
||||||
result := C.seccomp_syscall_resolve_name(cString)
|
result := C.seccomp_syscall_resolve_name(cString)
|
||||||
if result == scmpError {
|
if result == scmpError {
|
||||||
return 0, ErrSyscallDoesNotExist
|
return 0, fmt.Errorf("could not resolve name to syscall: %q", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ScmpSyscall(result), nil
|
return ScmpSyscall(result), nil
|
||||||
@ -530,7 +433,7 @@ func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) {
|
|||||||
|
|
||||||
result := C.seccomp_syscall_resolve_name_arch(arch.toNative(), cString)
|
result := C.seccomp_syscall_resolve_name_arch(arch.toNative(), cString)
|
||||||
if result == scmpError {
|
if result == scmpError {
|
||||||
return 0, ErrSyscallDoesNotExist
|
return 0, fmt.Errorf("could not resolve name to syscall: %q on %v", name, arch)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ScmpSyscall(result), nil
|
return ScmpSyscall(result), nil
|
||||||
@ -603,10 +506,11 @@ type ScmpFilter struct {
|
|||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFilter creates and returns a new filter context. Accepts a default action to be
|
// NewFilter creates and returns a new filter context.
|
||||||
// taken for syscalls which match no rules in the filter.
|
// Accepts a default action to be taken for syscalls which match no rules in
|
||||||
// Returns a reference to a valid filter context, or nil and an error
|
// the filter.
|
||||||
// if the filter context could not be created or an invalid default action was given.
|
// Returns a reference to a valid filter context, or nil and an error if the
|
||||||
|
// filter context could not be created or an invalid default action was given.
|
||||||
func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
|
func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
|
||||||
if err := ensureSupportedVersion(); err != nil {
|
if err := ensureSupportedVersion(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -626,8 +530,8 @@ func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
|
|||||||
filter.valid = true
|
filter.valid = true
|
||||||
runtime.SetFinalizer(filter, filterFinalizer)
|
runtime.SetFinalizer(filter, filterFinalizer)
|
||||||
|
|
||||||
// Enable TSync so all goroutines will receive the same rules.
|
// Enable TSync so all goroutines will receive the same rules
|
||||||
// If the kernel does not support TSYNC, allow us to continue without error.
|
// If the kernel does not support TSYNC, allow us to continue without error
|
||||||
if err := filter.setFilterAttr(filterAttrTsync, 0x1); err != nil && err != syscall.ENOTSUP {
|
if err := filter.setFilterAttr(filterAttrTsync, 0x1); err != nil && err != syscall.ENOTSUP {
|
||||||
filter.Release()
|
filter.Release()
|
||||||
return nil, fmt.Errorf("could not create filter - error setting tsync bit: %v", err)
|
return nil, fmt.Errorf("could not create filter - error setting tsync bit: %v", err)
|
||||||
@ -874,9 +778,8 @@ func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) {
|
|||||||
func (f *ScmpFilter) GetLogBit() (bool, error) {
|
func (f *ScmpFilter) GetLogBit() (bool, error) {
|
||||||
log, err := f.getFilterAttr(filterAttrLog)
|
log, err := f.getFilterAttr(filterAttrLog)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Ignore error, if not supported returns apiLevel == 0
|
api, apiErr := getAPI()
|
||||||
apiLevel, _ := GetAPI()
|
if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
|
||||||
if apiLevel < 3 {
|
|
||||||
return false, fmt.Errorf("getting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
|
return false, fmt.Errorf("getting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -890,30 +793,6 @@ func (f *ScmpFilter) GetLogBit() (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSSB returns the current state the SSB bit will be set to on the filter
|
|
||||||
// being loaded, or an error if an issue was encountered retrieving the value.
|
|
||||||
// The SSB bit tells the kernel that a seccomp user is not interested in enabling
|
|
||||||
// Speculative Store Bypass mitigation.
|
|
||||||
// The SSB bit is only usable when libseccomp API level 4 or higher is
|
|
||||||
// supported.
|
|
||||||
func (f *ScmpFilter) GetSSB() (bool, error) {
|
|
||||||
ssb, err := f.getFilterAttr(filterAttrSSB)
|
|
||||||
if err != nil {
|
|
||||||
api, apiErr := getAPI()
|
|
||||||
if (apiErr != nil && api == 0) || (apiErr == nil && api < 4) {
|
|
||||||
return false, fmt.Errorf("getting the SSB flag is only supported in libseccomp 2.5.0 and newer with API level 4 or higher")
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ssb == 0 {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetBadArchAction sets the default action taken on a syscall for an
|
// SetBadArchAction sets the default action taken on a syscall for an
|
||||||
// architecture not in the filter, or an error if an issue was encountered
|
// architecture not in the filter, or an error if an issue was encountered
|
||||||
// setting the value.
|
// setting the value.
|
||||||
@ -952,33 +831,10 @@ func (f *ScmpFilter) SetLogBit(state bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := f.setFilterAttr(filterAttrLog, toSet)
|
err := f.setFilterAttr(filterAttrLog, toSet)
|
||||||
if err != nil {
|
|
||||||
// Ignore error, if not supported returns apiLevel == 0
|
|
||||||
apiLevel, _ := GetAPI()
|
|
||||||
if apiLevel < 3 {
|
|
||||||
return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetSSB sets the state of the SSB bit, which will be applied on filter
|
|
||||||
// load, or an error if an issue was encountered setting the value.
|
|
||||||
// The SSB bit is only usable when libseccomp API level 4 or higher is
|
|
||||||
// supported.
|
|
||||||
func (f *ScmpFilter) SetSSB(state bool) error {
|
|
||||||
var toSet C.uint32_t = 0x0
|
|
||||||
|
|
||||||
if state {
|
|
||||||
toSet = 0x1
|
|
||||||
}
|
|
||||||
|
|
||||||
err := f.setFilterAttr(filterAttrSSB, toSet)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api, apiErr := getAPI()
|
api, apiErr := getAPI()
|
||||||
if (apiErr != nil && api == 0) || (apiErr == nil && api < 4) {
|
if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
|
||||||
return fmt.Errorf("setting the SSB flag is only supported in libseccomp 2.5.0 and newer with API level 4 or higher")
|
return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1091,36 +947,3 @@ func (f *ScmpFilter) ExportBPF(file *os.File) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Userspace Notification API
|
|
||||||
|
|
||||||
// GetNotifFd returns the userspace notification file descriptor associated with the given
|
|
||||||
// filter context. Such a file descriptor is only valid after the filter has been loaded
|
|
||||||
// and only when the filter uses the ActNotify action. The file descriptor can be used to
|
|
||||||
// retrieve and respond to notifications associated with the filter (see NotifReceive(),
|
|
||||||
// NotifRespond(), and NotifIDValid()).
|
|
||||||
func (f *ScmpFilter) GetNotifFd() (ScmpFd, error) {
|
|
||||||
return f.getNotifFd()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifReceive retrieves a seccomp userspace notification from a filter whose ActNotify
|
|
||||||
// action has triggered. The caller is expected to process the notification and return a
|
|
||||||
// response via NotifRespond(). Each invocation of this function returns one
|
|
||||||
// notification. As multiple notifications may be pending at any time, this function is
|
|
||||||
// normally called within a polling loop.
|
|
||||||
func NotifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
|
|
||||||
return notifReceive(fd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifRespond responds to a notification retrieved via NotifReceive(). The response Id
|
|
||||||
// must match that of the corresponding notification retrieved via NotifReceive().
|
|
||||||
func NotifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
|
|
||||||
return notifRespond(fd, scmpResp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifIDValid checks if a notification is still valid. An return value of nil means the
|
|
||||||
// notification is still valid. Otherwise the notification is not valid. This can be used
|
|
||||||
// to mitigate time-of-check-time-of-use (TOCTOU) attacks as described in seccomp_notify_id_valid(2).
|
|
||||||
func NotifIDValid(fd ScmpFd, id uint64) error {
|
|
||||||
return notifIDValid(fd, id)
|
|
||||||
}
|
|
||||||
|
260
vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
generated
vendored
260
vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
generated
vendored
@ -14,13 +14,6 @@ import (
|
|||||||
// Get the seccomp header in scope
|
// Get the seccomp header in scope
|
||||||
// Need stdlib.h for free() on cstrings
|
// Need stdlib.h for free() on cstrings
|
||||||
|
|
||||||
// To compile libseccomp-golang against a specific version of libseccomp:
|
|
||||||
// cd ../libseccomp && mkdir -p prefix
|
|
||||||
// ./configure --prefix=$PWD/prefix && make && make install
|
|
||||||
// cd ../libseccomp-golang
|
|
||||||
// PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make
|
|
||||||
// LD_PRELOAD=$PWD/../libseccomp/prefix/lib/libseccomp.so.2.5.0 PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make test
|
|
||||||
|
|
||||||
// #cgo pkg-config: libseccomp
|
// #cgo pkg-config: libseccomp
|
||||||
/*
|
/*
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -57,14 +50,6 @@ const uint32_t C_ARCH_BAD = ARCH_BAD;
|
|||||||
#define SCMP_ARCH_S390X ARCH_BAD
|
#define SCMP_ARCH_S390X ARCH_BAD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SCMP_ARCH_PARISC
|
|
||||||
#define SCMP_ARCH_PARISC ARCH_BAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SCMP_ARCH_PARISC64
|
|
||||||
#define SCMP_ARCH_PARISC64 ARCH_BAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint32_t C_ARCH_NATIVE = SCMP_ARCH_NATIVE;
|
const uint32_t C_ARCH_NATIVE = SCMP_ARCH_NATIVE;
|
||||||
const uint32_t C_ARCH_X86 = SCMP_ARCH_X86;
|
const uint32_t C_ARCH_X86 = SCMP_ARCH_X86;
|
||||||
const uint32_t C_ARCH_X86_64 = SCMP_ARCH_X86_64;
|
const uint32_t C_ARCH_X86_64 = SCMP_ARCH_X86_64;
|
||||||
@ -82,8 +67,6 @@ const uint32_t C_ARCH_PPC64 = SCMP_ARCH_PPC64;
|
|||||||
const uint32_t C_ARCH_PPC64LE = SCMP_ARCH_PPC64LE;
|
const uint32_t C_ARCH_PPC64LE = SCMP_ARCH_PPC64LE;
|
||||||
const uint32_t C_ARCH_S390 = SCMP_ARCH_S390;
|
const uint32_t C_ARCH_S390 = SCMP_ARCH_S390;
|
||||||
const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X;
|
const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X;
|
||||||
const uint32_t C_ARCH_PARISC = SCMP_ARCH_PARISC;
|
|
||||||
const uint32_t C_ARCH_PARISC64 = SCMP_ARCH_PARISC64;
|
|
||||||
|
|
||||||
#ifndef SCMP_ACT_LOG
|
#ifndef SCMP_ACT_LOG
|
||||||
#define SCMP_ACT_LOG 0x7ffc0000U
|
#define SCMP_ACT_LOG 0x7ffc0000U
|
||||||
@ -97,10 +80,6 @@ const uint32_t C_ARCH_PARISC64 = SCMP_ARCH_PARISC64;
|
|||||||
#define SCMP_ACT_KILL_THREAD 0x00000000U
|
#define SCMP_ACT_KILL_THREAD 0x00000000U
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SCMP_ACT_NOTIFY
|
|
||||||
#define SCMP_ACT_NOTIFY 0x7fc00000U
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint32_t C_ACT_KILL = SCMP_ACT_KILL;
|
const uint32_t C_ACT_KILL = SCMP_ACT_KILL;
|
||||||
const uint32_t C_ACT_KILL_PROCESS = SCMP_ACT_KILL_PROCESS;
|
const uint32_t C_ACT_KILL_PROCESS = SCMP_ACT_KILL_PROCESS;
|
||||||
const uint32_t C_ACT_KILL_THREAD = SCMP_ACT_KILL_THREAD;
|
const uint32_t C_ACT_KILL_THREAD = SCMP_ACT_KILL_THREAD;
|
||||||
@ -109,7 +88,6 @@ const uint32_t C_ACT_ERRNO = SCMP_ACT_ERRNO(0);
|
|||||||
const uint32_t C_ACT_TRACE = SCMP_ACT_TRACE(0);
|
const uint32_t C_ACT_TRACE = SCMP_ACT_TRACE(0);
|
||||||
const uint32_t C_ACT_LOG = SCMP_ACT_LOG;
|
const uint32_t C_ACT_LOG = SCMP_ACT_LOG;
|
||||||
const uint32_t C_ACT_ALLOW = SCMP_ACT_ALLOW;
|
const uint32_t C_ACT_ALLOW = SCMP_ACT_ALLOW;
|
||||||
const uint32_t C_ACT_NOTIFY = SCMP_ACT_NOTIFY;
|
|
||||||
|
|
||||||
// The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was
|
// The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was
|
||||||
// added in v2.4.0
|
// added in v2.4.0
|
||||||
@ -117,16 +95,12 @@ const uint32_t C_ACT_NOTIFY = SCMP_ACT_NOTIFY;
|
|||||||
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
|
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
|
||||||
#define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN
|
#define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN
|
||||||
#endif
|
#endif
|
||||||
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
|
|
||||||
#define SCMP_FLTATR_CTL_SSB _SCMP_FLTATR_MIN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint32_t C_ATTRIBUTE_DEFAULT = (uint32_t)SCMP_FLTATR_ACT_DEFAULT;
|
const uint32_t C_ATTRIBUTE_DEFAULT = (uint32_t)SCMP_FLTATR_ACT_DEFAULT;
|
||||||
const uint32_t C_ATTRIBUTE_BADARCH = (uint32_t)SCMP_FLTATR_ACT_BADARCH;
|
const uint32_t C_ATTRIBUTE_BADARCH = (uint32_t)SCMP_FLTATR_ACT_BADARCH;
|
||||||
const uint32_t C_ATTRIBUTE_NNP = (uint32_t)SCMP_FLTATR_CTL_NNP;
|
const uint32_t C_ATTRIBUTE_NNP = (uint32_t)SCMP_FLTATR_CTL_NNP;
|
||||||
const uint32_t C_ATTRIBUTE_TSYNC = (uint32_t)SCMP_FLTATR_CTL_TSYNC;
|
const uint32_t C_ATTRIBUTE_TSYNC = (uint32_t)SCMP_FLTATR_CTL_TSYNC;
|
||||||
const uint32_t C_ATTRIBUTE_LOG = (uint32_t)SCMP_FLTATR_CTL_LOG;
|
const uint32_t C_ATTRIBUTE_LOG = (uint32_t)SCMP_FLTATR_CTL_LOG;
|
||||||
const uint32_t C_ATTRIBUTE_SSB = (uint32_t)SCMP_FLTATR_CTL_SSB;
|
|
||||||
|
|
||||||
const int C_CMP_NE = (int)SCMP_CMP_NE;
|
const int C_CMP_NE = (int)SCMP_CMP_NE;
|
||||||
const int C_CMP_LT = (int)SCMP_CMP_LT;
|
const int C_CMP_LT = (int)SCMP_CMP_LT;
|
||||||
@ -215,51 +189,6 @@ void add_struct_arg_cmp(
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The seccomp notify API functions were added in v2.5.0
|
|
||||||
#if (SCMP_VER_MAJOR < 2) || \
|
|
||||||
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5)
|
|
||||||
|
|
||||||
struct seccomp_data {
|
|
||||||
int nr;
|
|
||||||
__u32 arch;
|
|
||||||
__u64 instruction_pointer;
|
|
||||||
__u64 args[6];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct seccomp_notif {
|
|
||||||
__u64 id;
|
|
||||||
__u32 pid;
|
|
||||||
__u32 flags;
|
|
||||||
struct seccomp_data data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct seccomp_notif_resp {
|
|
||||||
__u64 id;
|
|
||||||
__s64 val;
|
|
||||||
__s32 error;
|
|
||||||
__u32 flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
int seccomp_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp) {
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
int seccomp_notify_fd(const scmp_filter_ctx ctx) {
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
void seccomp_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp) {
|
|
||||||
}
|
|
||||||
int seccomp_notify_id_valid(int fd, uint64_t id) {
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
int seccomp_notify_receive(int fd, struct seccomp_notif *req) {
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp) {
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
@ -274,7 +203,6 @@ const (
|
|||||||
filterAttrNNP scmpFilterAttr = iota
|
filterAttrNNP scmpFilterAttr = iota
|
||||||
filterAttrTsync scmpFilterAttr = iota
|
filterAttrTsync scmpFilterAttr = iota
|
||||||
filterAttrLog scmpFilterAttr = iota
|
filterAttrLog scmpFilterAttr = iota
|
||||||
filterAttrSSB scmpFilterAttr = iota
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -282,7 +210,7 @@ const (
|
|||||||
scmpError C.int = -1
|
scmpError C.int = -1
|
||||||
// Comparison boundaries to check for architecture validity
|
// Comparison boundaries to check for architecture validity
|
||||||
archStart ScmpArch = ArchNative
|
archStart ScmpArch = ArchNative
|
||||||
archEnd ScmpArch = ArchPARISC64
|
archEnd ScmpArch = ArchS390X
|
||||||
// Comparison boundaries to check for action validity
|
// Comparison boundaries to check for action validity
|
||||||
actionStart ScmpAction = ActKill
|
actionStart ScmpAction = ActKill
|
||||||
actionEnd ScmpAction = ActKillProcess
|
actionEnd ScmpAction = ActKillProcess
|
||||||
@ -532,10 +460,6 @@ func archFromNative(a C.uint32_t) (ScmpArch, error) {
|
|||||||
return ArchS390, nil
|
return ArchS390, nil
|
||||||
case C.C_ARCH_S390X:
|
case C.C_ARCH_S390X:
|
||||||
return ArchS390X, nil
|
return ArchS390X, nil
|
||||||
case C.C_ARCH_PARISC:
|
|
||||||
return ArchPARISC, nil
|
|
||||||
case C.C_ARCH_PARISC64:
|
|
||||||
return ArchPARISC64, nil
|
|
||||||
default:
|
default:
|
||||||
return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a))
|
return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a))
|
||||||
}
|
}
|
||||||
@ -576,10 +500,6 @@ func (a ScmpArch) toNative() C.uint32_t {
|
|||||||
return C.C_ARCH_S390
|
return C.C_ARCH_S390
|
||||||
case ArchS390X:
|
case ArchS390X:
|
||||||
return C.C_ARCH_S390X
|
return C.C_ARCH_S390X
|
||||||
case ArchPARISC:
|
|
||||||
return C.C_ARCH_PARISC
|
|
||||||
case ArchPARISC64:
|
|
||||||
return C.C_ARCH_PARISC64
|
|
||||||
case ArchNative:
|
case ArchNative:
|
||||||
return C.C_ARCH_NATIVE
|
return C.C_ARCH_NATIVE
|
||||||
default:
|
default:
|
||||||
@ -628,8 +548,6 @@ func actionFromNative(a C.uint32_t) (ScmpAction, error) {
|
|||||||
return ActLog, nil
|
return ActLog, nil
|
||||||
case C.C_ACT_ALLOW:
|
case C.C_ACT_ALLOW:
|
||||||
return ActAllow, nil
|
return ActAllow, nil
|
||||||
case C.C_ACT_NOTIFY:
|
|
||||||
return ActNotify, nil
|
|
||||||
default:
|
default:
|
||||||
return 0x0, fmt.Errorf("unrecognized action %#x", uint32(a))
|
return 0x0, fmt.Errorf("unrecognized action %#x", uint32(a))
|
||||||
}
|
}
|
||||||
@ -654,8 +572,6 @@ func (a ScmpAction) toNative() C.uint32_t {
|
|||||||
return C.C_ACT_LOG
|
return C.C_ACT_LOG
|
||||||
case ActAllow:
|
case ActAllow:
|
||||||
return C.C_ACT_ALLOW
|
return C.C_ACT_ALLOW
|
||||||
case ActNotify:
|
|
||||||
return C.C_ACT_NOTIFY
|
|
||||||
default:
|
default:
|
||||||
return 0x0
|
return 0x0
|
||||||
}
|
}
|
||||||
@ -674,181 +590,7 @@ func (a scmpFilterAttr) toNative() uint32 {
|
|||||||
return uint32(C.C_ATTRIBUTE_TSYNC)
|
return uint32(C.C_ATTRIBUTE_TSYNC)
|
||||||
case filterAttrLog:
|
case filterAttrLog:
|
||||||
return uint32(C.C_ATTRIBUTE_LOG)
|
return uint32(C.C_ATTRIBUTE_LOG)
|
||||||
case filterAttrSSB:
|
|
||||||
return uint32(C.C_ATTRIBUTE_SSB)
|
|
||||||
default:
|
default:
|
||||||
return 0x0
|
return 0x0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a ScmpSyscall) toNative() C.uint32_t {
|
|
||||||
return C.uint32_t(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func syscallFromNative(a C.int) ScmpSyscall {
|
|
||||||
return ScmpSyscall(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func notifReqFromNative(req *C.struct_seccomp_notif) (*ScmpNotifReq, error) {
|
|
||||||
scmpArgs := make([]uint64, 6)
|
|
||||||
for i := 0; i < len(scmpArgs); i++ {
|
|
||||||
scmpArgs[i] = uint64(req.data.args[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
arch, err := archFromNative(req.data.arch)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
scmpData := ScmpNotifData{
|
|
||||||
Syscall: syscallFromNative(req.data.nr),
|
|
||||||
Arch: arch,
|
|
||||||
InstrPointer: uint64(req.data.instruction_pointer),
|
|
||||||
Args: scmpArgs,
|
|
||||||
}
|
|
||||||
|
|
||||||
scmpReq := &ScmpNotifReq{
|
|
||||||
ID: uint64(req.id),
|
|
||||||
Pid: uint32(req.pid),
|
|
||||||
Flags: uint32(req.flags),
|
|
||||||
Data: scmpData,
|
|
||||||
}
|
|
||||||
|
|
||||||
return scmpReq, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (scmpResp *ScmpNotifResp) toNative(resp *C.struct_seccomp_notif_resp) {
|
|
||||||
resp.id = C.__u64(scmpResp.ID)
|
|
||||||
resp.val = C.__s64(scmpResp.Val)
|
|
||||||
resp.error = (C.__s32(scmpResp.Error) * -1) // kernel requires a negated value
|
|
||||||
resp.flags = C.__u32(scmpResp.Flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Userspace Notification API
|
|
||||||
// Calls to C.seccomp_notify* hidden from seccomp.go
|
|
||||||
|
|
||||||
func (f *ScmpFilter) getNotifFd() (ScmpFd, error) {
|
|
||||||
f.lock.Lock()
|
|
||||||
defer f.lock.Unlock()
|
|
||||||
|
|
||||||
if !f.valid {
|
|
||||||
return -1, errBadFilter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore error, if not supported returns apiLevel == 0
|
|
||||||
apiLevel, _ := GetAPI()
|
|
||||||
if apiLevel < 6 {
|
|
||||||
return -1, fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
fd := C.seccomp_notify_fd(f.filterCtx)
|
|
||||||
|
|
||||||
return ScmpFd(fd), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func notifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
|
|
||||||
var req *C.struct_seccomp_notif
|
|
||||||
var resp *C.struct_seccomp_notif_resp
|
|
||||||
|
|
||||||
// Ignore error, if not supported returns apiLevel == 0
|
|
||||||
apiLevel, _ := GetAPI()
|
|
||||||
if apiLevel < 6 {
|
|
||||||
return nil, fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// we only use the request here; the response is unused
|
|
||||||
if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
|
|
||||||
return nil, errRc(retCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
C.seccomp_notify_free(req, resp)
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
|
||||||
retCode, errno := C.seccomp_notify_receive(C.int(fd), req)
|
|
||||||
if retCode == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if errno == syscall.EINTR {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if errno == syscall.ENOENT {
|
|
||||||
return nil, errno
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errRc(retCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return notifReqFromNative(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func notifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
|
|
||||||
var req *C.struct_seccomp_notif
|
|
||||||
var resp *C.struct_seccomp_notif_resp
|
|
||||||
|
|
||||||
// Ignore error, if not supported returns apiLevel == 0
|
|
||||||
apiLevel, _ := GetAPI()
|
|
||||||
if apiLevel < 6 {
|
|
||||||
return fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// we only use the reponse here; the request is discarded
|
|
||||||
if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
|
|
||||||
return errRc(retCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
C.seccomp_notify_free(req, resp)
|
|
||||||
}()
|
|
||||||
|
|
||||||
scmpResp.toNative(resp)
|
|
||||||
|
|
||||||
for {
|
|
||||||
retCode, errno := C.seccomp_notify_respond(C.int(fd), resp)
|
|
||||||
if retCode == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if errno == syscall.EINTR {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if errno == syscall.ENOENT {
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
|
|
||||||
return errRc(retCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func notifIDValid(fd ScmpFd, id uint64) error {
|
|
||||||
// Ignore error, if not supported returns apiLevel == 0
|
|
||||||
apiLevel, _ := GetAPI()
|
|
||||||
if apiLevel < 6 {
|
|
||||||
return fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
retCode, errno := C.seccomp_notify_id_valid(C.int(fd), C.uint64_t(id))
|
|
||||||
if retCode == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if errno == syscall.EINTR {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if errno == syscall.ENOENT {
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
|
|
||||||
return errRc(retCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
20
vendor/github.com/vishvananda/netlink/.travis.yml
generated
vendored
20
vendor/github.com/vishvananda/netlink/.travis.yml
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
language: go
|
|
||||||
go:
|
|
||||||
- "1.12.x"
|
|
||||||
- "1.13.x"
|
|
||||||
- "1.14.x"
|
|
||||||
before_script:
|
|
||||||
# make sure we keep path in tact when we sudo
|
|
||||||
- sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
|
|
||||||
# modprobe ip_gre or else the first gre device can't be deleted
|
|
||||||
- sudo modprobe ip_gre
|
|
||||||
# modprobe nf_conntrack for the conntrack testing
|
|
||||||
- sudo modprobe nf_conntrack
|
|
||||||
- sudo modprobe nf_conntrack_netlink
|
|
||||||
- sudo modprobe nf_conntrack_ipv4
|
|
||||||
- sudo modprobe nf_conntrack_ipv6
|
|
||||||
- sudo modprobe sch_hfsc
|
|
||||||
- sudo modprobe sch_sfq
|
|
||||||
install:
|
|
||||||
- go get -v -t ./...
|
|
||||||
go_import_path: github.com/vishvananda/netlink
|
|
2
vendor/github.com/vishvananda/netlink/README.md
generated
vendored
2
vendor/github.com/vishvananda/netlink/README.md
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
# netlink - netlink library for go #
|
# netlink - netlink library for go #
|
||||||
|
|
||||||
[](https://travis-ci.org/vishvananda/netlink) [](https://godoc.org/github.com/vishvananda/netlink)
|
 [](https://godoc.org/github.com/vishvananda/netlink)
|
||||||
|
|
||||||
The netlink package provides a simple netlink library for go. Netlink
|
The netlink package provides a simple netlink library for go. Netlink
|
||||||
is the interface a user-space program in linux uses to communicate with
|
is the interface a user-space program in linux uses to communicate with
|
||||||
|
6
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
6
vendor/github.com/vishvananda/netlink/addr_linux.go
generated
vendored
@ -268,7 +268,7 @@ func parseAddr(m []byte) (addr Addr, family int, err error) {
|
|||||||
// But obviously, as there are IPv6 PtP addresses, too,
|
// But obviously, as there are IPv6 PtP addresses, too,
|
||||||
// IFA_LOCAL should also be handled for IPv6.
|
// IFA_LOCAL should also be handled for IPv6.
|
||||||
if local != nil {
|
if local != nil {
|
||||||
if family == FAMILY_V4 && local.IP.Equal(dst.IP) {
|
if family == FAMILY_V4 && dst != nil && local.IP.Equal(dst.IP) {
|
||||||
addr.IPNet = dst
|
addr.IPNet = dst
|
||||||
} else {
|
} else {
|
||||||
addr.IPNet = local
|
addr.IPNet = local
|
||||||
@ -357,7 +357,8 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
|
|||||||
msgs, from, err := s.Receive()
|
msgs, from, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(err)
|
cberr(fmt.Errorf("Receive failed: %v",
|
||||||
|
err))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -372,7 +373,6 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if m.Header.Type == unix.NLMSG_ERROR {
|
if m.Header.Type == unix.NLMSG_ERROR {
|
||||||
native := nl.NativeEndian()
|
|
||||||
error := int32(native.Uint32(m.Data[0:4]))
|
error := int32(native.Uint32(m.Data[0:4]))
|
||||||
if error == 0 {
|
if error == 0 {
|
||||||
continue
|
continue
|
||||||
|
24
vendor/github.com/vishvananda/netlink/bpf_linux.go
generated
vendored
24
vendor/github.com/vishvananda/netlink/bpf_linux.go
generated
vendored
@ -16,6 +16,30 @@ const (
|
|||||||
BPF_PROG_TYPE_SCHED_ACT
|
BPF_PROG_TYPE_SCHED_ACT
|
||||||
BPF_PROG_TYPE_TRACEPOINT
|
BPF_PROG_TYPE_TRACEPOINT
|
||||||
BPF_PROG_TYPE_XDP
|
BPF_PROG_TYPE_XDP
|
||||||
|
BPF_PROG_TYPE_PERF_EVENT
|
||||||
|
BPF_PROG_TYPE_CGROUP_SKB
|
||||||
|
BPF_PROG_TYPE_CGROUP_SOCK
|
||||||
|
BPF_PROG_TYPE_LWT_IN
|
||||||
|
BPF_PROG_TYPE_LWT_OUT
|
||||||
|
BPF_PROG_TYPE_LWT_XMIT
|
||||||
|
BPF_PROG_TYPE_SOCK_OPS
|
||||||
|
BPF_PROG_TYPE_SK_SKB
|
||||||
|
BPF_PROG_TYPE_CGROUP_DEVICE
|
||||||
|
BPF_PROG_TYPE_SK_MSG
|
||||||
|
BPF_PROG_TYPE_RAW_TRACEPOINT
|
||||||
|
BPF_PROG_TYPE_CGROUP_SOCK_ADDR
|
||||||
|
BPF_PROG_TYPE_LWT_SEG6LOCAL
|
||||||
|
BPF_PROG_TYPE_LIRC_MODE2
|
||||||
|
BPF_PROG_TYPE_SK_REUSEPORT
|
||||||
|
BPF_PROG_TYPE_FLOW_DISSECTOR
|
||||||
|
BPF_PROG_TYPE_CGROUP_SYSCTL
|
||||||
|
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE
|
||||||
|
BPF_PROG_TYPE_CGROUP_SOCKOPT
|
||||||
|
BPF_PROG_TYPE_TRACING
|
||||||
|
BPF_PROG_TYPE_STRUCT_OPS
|
||||||
|
BPF_PROG_TYPE_EXT
|
||||||
|
BPF_PROG_TYPE_LSM
|
||||||
|
BPF_PROG_TYPE_SK_LOOKUP
|
||||||
)
|
)
|
||||||
|
|
||||||
type BPFAttr struct {
|
type BPFAttr struct {
|
||||||
|
8
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
8
vendor/github.com/vishvananda/netlink/class_linux.go
generated
vendored
@ -191,9 +191,9 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
|
|||||||
opt.Fsc.Set(fm1/8, fd, fm2/8)
|
opt.Fsc.Set(fm1/8, fd, fm2/8)
|
||||||
um1, ud, um2 := hfsc.Usc.Attrs()
|
um1, ud, um2 := hfsc.Usc.Attrs()
|
||||||
opt.Usc.Set(um1/8, ud, um2/8)
|
opt.Usc.Set(um1/8, ud, um2/8)
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
|
options.AddRtAttr(nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
|
options.AddRtAttr(nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
|
||||||
nl.NewRtAttrChild(options, nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
|
options.AddRtAttr(nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
|
||||||
}
|
}
|
||||||
req.AddData(options)
|
req.AddData(options)
|
||||||
return nil
|
return nil
|
||||||
@ -341,7 +341,6 @@ func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, err
|
|||||||
func parseTcStats(data []byte) (*ClassStatistics, error) {
|
func parseTcStats(data []byte) (*ClassStatistics, error) {
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
buf.Write(data)
|
buf.Write(data)
|
||||||
native := nl.NativeEndian()
|
|
||||||
tcStats := &tcStats{}
|
tcStats := &tcStats{}
|
||||||
if err := binary.Read(buf, native, tcStats); err != nil {
|
if err := binary.Read(buf, native, tcStats); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -363,7 +362,6 @@ func parseTcStats(data []byte) (*ClassStatistics, error) {
|
|||||||
func parseGnetStats(data []byte, gnetStats interface{}) error {
|
func parseGnetStats(data []byte, gnetStats interface{}) error {
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
buf.Write(data)
|
buf.Write(data)
|
||||||
native := nl.NativeEndian()
|
|
||||||
return binary.Read(buf, native, gnetStats)
|
return binary.Read(buf, native, gnetStats)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
143
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
143
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
@ -145,16 +146,23 @@ type ConntrackFlow struct {
|
|||||||
Forward ipTuple
|
Forward ipTuple
|
||||||
Reverse ipTuple
|
Reverse ipTuple
|
||||||
Mark uint32
|
Mark uint32
|
||||||
|
TimeStart uint64
|
||||||
|
TimeStop uint64
|
||||||
|
TimeOut uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConntrackFlow) String() string {
|
func (s *ConntrackFlow) String() string {
|
||||||
// conntrack cmd output:
|
// conntrack cmd output:
|
||||||
// udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0
|
// udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0
|
||||||
return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=%d",
|
// start=2019-07-26 01:26:21.557800506 +0000 UTC stop=1970-01-01 00:00:00 +0000 UTC timeout=30(sec)
|
||||||
|
start := time.Unix(0, int64(s.TimeStart))
|
||||||
|
stop := time.Unix(0, int64(s.TimeStop))
|
||||||
|
timeout := int32(s.TimeOut)
|
||||||
|
return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=0x%x start=%v stop=%v timeout=%d(sec)",
|
||||||
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
|
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
|
||||||
s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes,
|
s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes,
|
||||||
s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes,
|
s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes,
|
||||||
s.Mark)
|
s.Mark, start, stop, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method parse the ip tuple structure
|
// This method parse the ip tuple structure
|
||||||
@ -174,25 +182,43 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
|
|||||||
tpl.DstIP = v
|
tpl.DstIP = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Skip the next 4 bytes nl.NLA_F_NESTED|nl.CTA_TUPLE_PROTO
|
// Get total length of nested protocol-specific info.
|
||||||
reader.Seek(4, seekCurrent)
|
_, _, protoInfoTotalLen := parseNfAttrTL(reader)
|
||||||
_, t, _, v := parseNfAttrTLV(reader)
|
_, t, l, v := parseNfAttrTLV(reader)
|
||||||
|
// Track the number of bytes read.
|
||||||
|
protoInfoBytesRead := uint16(nl.SizeofNfattr) + l
|
||||||
if t == nl.CTA_PROTO_NUM {
|
if t == nl.CTA_PROTO_NUM {
|
||||||
tpl.Protocol = uint8(v[0])
|
tpl.Protocol = uint8(v[0])
|
||||||
}
|
}
|
||||||
// Skip some padding 3 bytes
|
// We only parse TCP & UDP headers. Skip the others.
|
||||||
|
if tpl.Protocol != 6 && tpl.Protocol != 17 {
|
||||||
|
// skip the rest
|
||||||
|
bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
|
||||||
|
reader.Seek(int64(bytesRemaining), seekCurrent)
|
||||||
|
return tpl.Protocol
|
||||||
|
}
|
||||||
|
// Skip 3 bytes of padding
|
||||||
reader.Seek(3, seekCurrent)
|
reader.Seek(3, seekCurrent)
|
||||||
|
protoInfoBytesRead += 3
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
_, t, _ := parseNfAttrTL(reader)
|
_, t, _ := parseNfAttrTL(reader)
|
||||||
|
protoInfoBytesRead += uint16(nl.SizeofNfattr)
|
||||||
switch t {
|
switch t {
|
||||||
case nl.CTA_PROTO_SRC_PORT:
|
case nl.CTA_PROTO_SRC_PORT:
|
||||||
parseBERaw16(reader, &tpl.SrcPort)
|
parseBERaw16(reader, &tpl.SrcPort)
|
||||||
|
protoInfoBytesRead += 2
|
||||||
case nl.CTA_PROTO_DST_PORT:
|
case nl.CTA_PROTO_DST_PORT:
|
||||||
parseBERaw16(reader, &tpl.DstPort)
|
parseBERaw16(reader, &tpl.DstPort)
|
||||||
|
protoInfoBytesRead += 2
|
||||||
}
|
}
|
||||||
// Skip some padding 2 byte
|
// Skip 2 bytes of padding
|
||||||
reader.Seek(2, seekCurrent)
|
reader.Seek(2, seekCurrent)
|
||||||
|
protoInfoBytesRead += 2
|
||||||
}
|
}
|
||||||
|
// Skip any remaining/unknown parts of the message
|
||||||
|
bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
|
||||||
|
reader.Seek(int64(bytesRemaining), seekCurrent)
|
||||||
|
|
||||||
return tpl.Protocol
|
return tpl.Protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,10 +237,14 @@ func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) {
|
|||||||
binary.Read(r, nl.NativeEndian(), &attrType)
|
binary.Read(r, nl.NativeEndian(), &attrType)
|
||||||
isNested = (attrType & nl.NLA_F_NESTED) == nl.NLA_F_NESTED
|
isNested = (attrType & nl.NLA_F_NESTED) == nl.NLA_F_NESTED
|
||||||
attrType = attrType & (nl.NLA_F_NESTED - 1)
|
attrType = attrType & (nl.NLA_F_NESTED - 1)
|
||||||
|
|
||||||
return isNested, attrType, len
|
return isNested, attrType, len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func skipNfAttrValue(r *bytes.Reader, len uint16) {
|
||||||
|
len = (len + nl.NLA_ALIGNTO - 1) & ^(nl.NLA_ALIGNTO - 1)
|
||||||
|
r.Seek(int64(len), seekCurrent)
|
||||||
|
}
|
||||||
|
|
||||||
func parseBERaw16(r *bytes.Reader, v *uint16) {
|
func parseBERaw16(r *bytes.Reader, v *uint16) {
|
||||||
binary.Read(r, binary.BigEndian, v)
|
binary.Read(r, binary.BigEndian, v)
|
||||||
}
|
}
|
||||||
@ -241,6 +271,36 @@ func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when the flow is alive, only the timestamp_start is returned in structure
|
||||||
|
func parseTimeStamp(r *bytes.Reader, readSize uint16) (tstart, tstop uint64) {
|
||||||
|
var numTimeStamps int
|
||||||
|
oneItem := nl.SizeofNfattr + 8 // 4 bytes attr header + 8 bytes timestamp
|
||||||
|
if readSize == uint16(oneItem) {
|
||||||
|
numTimeStamps = 1
|
||||||
|
} else if readSize == 2*uint16(oneItem) {
|
||||||
|
numTimeStamps = 2
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := 0; i < numTimeStamps; i++ {
|
||||||
|
switch _, t, _ := parseNfAttrTL(r); t {
|
||||||
|
case nl.CTA_TIMESTAMP_START:
|
||||||
|
parseBERaw64(r, &tstart)
|
||||||
|
case nl.CTA_TIMESTAMP_STOP:
|
||||||
|
parseBERaw64(r, &tstop)
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTimeOut(r *bytes.Reader) (ttimeout uint32) {
|
||||||
|
parseBERaw32(r, &ttimeout)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func parseConnectionMark(r *bytes.Reader) (mark uint32) {
|
func parseConnectionMark(r *bytes.Reader) (mark uint32) {
|
||||||
parseBERaw32(r, &mark)
|
parseBERaw32(r, &mark)
|
||||||
return
|
return
|
||||||
@ -266,25 +326,37 @@ func parseRawData(data []byte) *ConntrackFlow {
|
|||||||
if nested, t, l := parseNfAttrTL(reader); nested {
|
if nested, t, l := parseNfAttrTL(reader); nested {
|
||||||
switch t {
|
switch t {
|
||||||
case nl.CTA_TUPLE_ORIG:
|
case nl.CTA_TUPLE_ORIG:
|
||||||
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
if nested, t, l = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
||||||
parseIpTuple(reader, &s.Forward)
|
parseIpTuple(reader, &s.Forward)
|
||||||
}
|
}
|
||||||
case nl.CTA_TUPLE_REPLY:
|
case nl.CTA_TUPLE_REPLY:
|
||||||
if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
if nested, t, l = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
|
||||||
parseIpTuple(reader, &s.Reverse)
|
parseIpTuple(reader, &s.Reverse)
|
||||||
} else {
|
} else {
|
||||||
// Header not recognized skip it
|
// Header not recognized skip it
|
||||||
reader.Seek(int64(l), seekCurrent)
|
skipNfAttrValue(reader, l)
|
||||||
}
|
}
|
||||||
case nl.CTA_COUNTERS_ORIG:
|
case nl.CTA_COUNTERS_ORIG:
|
||||||
s.Forward.Bytes, s.Forward.Packets = parseByteAndPacketCounters(reader)
|
s.Forward.Bytes, s.Forward.Packets = parseByteAndPacketCounters(reader)
|
||||||
case nl.CTA_COUNTERS_REPLY:
|
case nl.CTA_COUNTERS_REPLY:
|
||||||
s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader)
|
s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader)
|
||||||
|
case nl.CTA_TIMESTAMP:
|
||||||
|
s.TimeStart, s.TimeStop = parseTimeStamp(reader, l)
|
||||||
|
case nl.CTA_PROTOINFO:
|
||||||
|
skipNfAttrValue(reader, l)
|
||||||
|
default:
|
||||||
|
skipNfAttrValue(reader, l)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch t {
|
switch t {
|
||||||
case nl.CTA_MARK:
|
case nl.CTA_MARK:
|
||||||
s.Mark = parseConnectionMark(reader)
|
s.Mark = parseConnectionMark(reader)
|
||||||
|
case nl.CTA_TIMEOUT:
|
||||||
|
s.TimeOut = parseTimeOut(reader)
|
||||||
|
case nl.CTA_STATUS, nl.CTA_USE, nl.CTA_ID:
|
||||||
|
skipNfAttrValue(reader, l)
|
||||||
|
default:
|
||||||
|
skipNfAttrValue(reader, l)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -346,23 +418,34 @@ type CustomConntrackFilter interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ConntrackFilter struct {
|
type ConntrackFilter struct {
|
||||||
ipFilter map[ConntrackFilterType]net.IP
|
ipNetFilter map[ConntrackFilterType]*net.IPNet
|
||||||
portFilter map[ConntrackFilterType]uint16
|
portFilter map[ConntrackFilterType]uint16
|
||||||
protoFilter uint8
|
protoFilter uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddIP adds an IP to the conntrack filter
|
// AddIPNet adds a IP subnet to the conntrack filter
|
||||||
func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error {
|
func (f *ConntrackFilter) AddIPNet(tp ConntrackFilterType, ipNet *net.IPNet) error {
|
||||||
if f.ipFilter == nil {
|
if ipNet == nil {
|
||||||
f.ipFilter = make(map[ConntrackFilterType]net.IP)
|
return fmt.Errorf("Filter attribute empty")
|
||||||
}
|
}
|
||||||
if _, ok := f.ipFilter[tp]; ok {
|
if f.ipNetFilter == nil {
|
||||||
|
f.ipNetFilter = make(map[ConntrackFilterType]*net.IPNet)
|
||||||
|
}
|
||||||
|
if _, ok := f.ipNetFilter[tp]; ok {
|
||||||
return errors.New("Filter attribute already present")
|
return errors.New("Filter attribute already present")
|
||||||
}
|
}
|
||||||
f.ipFilter[tp] = ip
|
f.ipNetFilter[tp] = ipNet
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddIP adds an IP to the conntrack filter
|
||||||
|
func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error {
|
||||||
|
if ip == nil {
|
||||||
|
return fmt.Errorf("Filter attribute empty")
|
||||||
|
}
|
||||||
|
return f.AddIPNet(tp, NewIPNet(ip))
|
||||||
|
}
|
||||||
|
|
||||||
// AddPort adds a Port to the conntrack filter if the Layer 4 protocol allows it
|
// AddPort adds a Port to the conntrack filter if the Layer 4 protocol allows it
|
||||||
func (f *ConntrackFilter) AddPort(tp ConntrackFilterType, port uint16) error {
|
func (f *ConntrackFilter) AddPort(tp ConntrackFilterType, port uint16) error {
|
||||||
switch f.protoFilter {
|
switch f.protoFilter {
|
||||||
@ -394,7 +477,7 @@ func (f *ConntrackFilter) AddProtocol(proto uint8) error {
|
|||||||
// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter
|
// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter
|
||||||
// false otherwise
|
// false otherwise
|
||||||
func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||||
if len(f.ipFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
|
if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
|
||||||
// empty filter always not match
|
// empty filter always not match
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -408,30 +491,30 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
|||||||
match := true
|
match := true
|
||||||
|
|
||||||
// IP conntrack filter
|
// IP conntrack filter
|
||||||
if len(f.ipFilter) > 0 {
|
if len(f.ipNetFilter) > 0 {
|
||||||
// -orig-src ip Source address from original direction
|
// -orig-src ip Source address from original direction
|
||||||
if elem, found := f.ipFilter[ConntrackOrigSrcIP]; found {
|
if elem, found := f.ipNetFilter[ConntrackOrigSrcIP]; found {
|
||||||
match = match && elem.Equal(flow.Forward.SrcIP)
|
match = match && elem.Contains(flow.Forward.SrcIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -orig-dst ip Destination address from original direction
|
// -orig-dst ip Destination address from original direction
|
||||||
if elem, found := f.ipFilter[ConntrackOrigDstIP]; match && found {
|
if elem, found := f.ipNetFilter[ConntrackOrigDstIP]; match && found {
|
||||||
match = match && elem.Equal(flow.Forward.DstIP)
|
match = match && elem.Contains(flow.Forward.DstIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -src-nat ip Source NAT ip
|
// -src-nat ip Source NAT ip
|
||||||
if elem, found := f.ipFilter[ConntrackReplySrcIP]; match && found {
|
if elem, found := f.ipNetFilter[ConntrackReplySrcIP]; match && found {
|
||||||
match = match && elem.Equal(flow.Reverse.SrcIP)
|
match = match && elem.Contains(flow.Reverse.SrcIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -dst-nat ip Destination NAT ip
|
// -dst-nat ip Destination NAT ip
|
||||||
if elem, found := f.ipFilter[ConntrackReplyDstIP]; match && found {
|
if elem, found := f.ipNetFilter[ConntrackReplyDstIP]; match && found {
|
||||||
match = match && elem.Equal(flow.Reverse.DstIP)
|
match = match && elem.Contains(flow.Reverse.DstIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match source or destination reply IP
|
// Match source or destination reply IP
|
||||||
if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found {
|
if elem, found := f.ipNetFilter[ConntrackReplyAnyIP]; match && found {
|
||||||
match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP))
|
match = match && (elem.Contains(flow.Reverse.SrcIP) || elem.Contains(flow.Reverse.DstIP))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
353
vendor/github.com/vishvananda/netlink/devlink_linux.go
generated
vendored
353
vendor/github.com/vishvananda/netlink/devlink_linux.go
generated
vendored
@ -1,9 +1,11 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
@ -27,6 +29,20 @@ type DevlinkDevice struct {
|
|||||||
Attrs DevlinkDevAttrs
|
Attrs DevlinkDevAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DevlinkPortFn represents port function and its attributes
|
||||||
|
type DevlinkPortFn struct {
|
||||||
|
HwAddr net.HardwareAddr
|
||||||
|
State uint8
|
||||||
|
OpState uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevlinkPortFnSetAttrs represents attributes to set
|
||||||
|
type DevlinkPortFnSetAttrs struct {
|
||||||
|
FnAttrs DevlinkPortFn
|
||||||
|
HwAddrValid bool
|
||||||
|
StateValid bool
|
||||||
|
}
|
||||||
|
|
||||||
// DevlinkPort represents port and its attributes
|
// DevlinkPort represents port and its attributes
|
||||||
type DevlinkPort struct {
|
type DevlinkPort struct {
|
||||||
BusName string
|
BusName string
|
||||||
@ -37,6 +53,35 @@ type DevlinkPort struct {
|
|||||||
NetdevIfIndex uint32
|
NetdevIfIndex uint32
|
||||||
RdmaDeviceName string
|
RdmaDeviceName string
|
||||||
PortFlavour uint16
|
PortFlavour uint16
|
||||||
|
Fn *DevlinkPortFn
|
||||||
|
}
|
||||||
|
|
||||||
|
type DevLinkPortAddAttrs struct {
|
||||||
|
Controller uint32
|
||||||
|
SfNumber uint32
|
||||||
|
PortIndex uint32
|
||||||
|
PfNumber uint16
|
||||||
|
SfNumberValid bool
|
||||||
|
PortIndexValid bool
|
||||||
|
ControllerValid bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevlinkDeviceInfo represents devlink info
|
||||||
|
type DevlinkDeviceInfo struct {
|
||||||
|
Driver string
|
||||||
|
SerialNumber string
|
||||||
|
BoardID string
|
||||||
|
FwApp string
|
||||||
|
FwAppBoundleID string
|
||||||
|
FwAppName string
|
||||||
|
FwBoundleID string
|
||||||
|
FwMgmt string
|
||||||
|
FwMgmtAPI string
|
||||||
|
FwMgmtBuild string
|
||||||
|
FwNetlist string
|
||||||
|
FwNetlistBuild string
|
||||||
|
FwPsidAPI string
|
||||||
|
FwUndi string
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
|
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
|
||||||
@ -107,9 +152,9 @@ func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error
|
|||||||
for _, a := range attrs {
|
for _, a := range attrs {
|
||||||
switch a.Attr.Type {
|
switch a.Attr.Type {
|
||||||
case nl.DEVLINK_ATTR_BUS_NAME:
|
case nl.DEVLINK_ATTR_BUS_NAME:
|
||||||
d.BusName = string(a.Value)
|
d.BusName = string(a.Value[:len(a.Value)-1])
|
||||||
case nl.DEVLINK_ATTR_DEV_NAME:
|
case nl.DEVLINK_ATTR_DEV_NAME:
|
||||||
d.DeviceName = string(a.Value)
|
d.DeviceName = string(a.Value[:len(a.Value)-1])
|
||||||
case nl.DEVLINK_ATTR_ESWITCH_MODE:
|
case nl.DEVLINK_ATTR_ESWITCH_MODE:
|
||||||
d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value))
|
d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value))
|
||||||
case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE:
|
case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE:
|
||||||
@ -138,12 +183,12 @@ func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) {
|
|||||||
req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK)
|
req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
b := make([]byte, len(dev.BusName))
|
b := make([]byte, len(dev.BusName)+1)
|
||||||
copy(b, dev.BusName)
|
copy(b, dev.BusName)
|
||||||
data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
|
data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
|
||||||
req.AddData(data)
|
req.AddData(data)
|
||||||
|
|
||||||
b = make([]byte, len(dev.DeviceName))
|
b = make([]byte, len(dev.DeviceName)+1)
|
||||||
copy(b, dev.DeviceName)
|
copy(b, dev.DeviceName)
|
||||||
data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
|
data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
|
||||||
req.AddData(data)
|
req.AddData(data)
|
||||||
@ -287,21 +332,33 @@ func (port *DevlinkPort) parseAttributes(attrs []syscall.NetlinkRouteAttr) error
|
|||||||
for _, a := range attrs {
|
for _, a := range attrs {
|
||||||
switch a.Attr.Type {
|
switch a.Attr.Type {
|
||||||
case nl.DEVLINK_ATTR_BUS_NAME:
|
case nl.DEVLINK_ATTR_BUS_NAME:
|
||||||
port.BusName = string(a.Value)
|
port.BusName = string(a.Value[:len(a.Value)-1])
|
||||||
case nl.DEVLINK_ATTR_DEV_NAME:
|
case nl.DEVLINK_ATTR_DEV_NAME:
|
||||||
port.DeviceName = string(a.Value)
|
port.DeviceName = string(a.Value[:len(a.Value)-1])
|
||||||
case nl.DEVLINK_ATTR_PORT_INDEX:
|
case nl.DEVLINK_ATTR_PORT_INDEX:
|
||||||
port.PortIndex = native.Uint32(a.Value)
|
port.PortIndex = native.Uint32(a.Value)
|
||||||
case nl.DEVLINK_ATTR_PORT_TYPE:
|
case nl.DEVLINK_ATTR_PORT_TYPE:
|
||||||
port.PortType = native.Uint16(a.Value)
|
port.PortType = native.Uint16(a.Value)
|
||||||
case nl.DEVLINK_ATTR_PORT_NETDEV_NAME:
|
case nl.DEVLINK_ATTR_PORT_NETDEV_NAME:
|
||||||
port.NetdeviceName = string(a.Value)
|
port.NetdeviceName = string(a.Value[:len(a.Value)-1])
|
||||||
case nl.DEVLINK_ATTR_PORT_NETDEV_IFINDEX:
|
case nl.DEVLINK_ATTR_PORT_NETDEV_IFINDEX:
|
||||||
port.NetdevIfIndex = native.Uint32(a.Value)
|
port.NetdevIfIndex = native.Uint32(a.Value)
|
||||||
case nl.DEVLINK_ATTR_PORT_IBDEV_NAME:
|
case nl.DEVLINK_ATTR_PORT_IBDEV_NAME:
|
||||||
port.RdmaDeviceName = string(a.Value)
|
port.RdmaDeviceName = string(a.Value[:len(a.Value)-1])
|
||||||
case nl.DEVLINK_ATTR_PORT_FLAVOUR:
|
case nl.DEVLINK_ATTR_PORT_FLAVOUR:
|
||||||
port.PortFlavour = native.Uint16(a.Value)
|
port.PortFlavour = native.Uint16(a.Value)
|
||||||
|
case nl.DEVLINK_ATTR_PORT_FUNCTION:
|
||||||
|
port.Fn = &DevlinkPortFn{}
|
||||||
|
for nested := range nl.ParseAttributes(a.Value) {
|
||||||
|
switch nested.Type {
|
||||||
|
case nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR:
|
||||||
|
port.Fn.HwAddr = nested.Value[:]
|
||||||
|
case nl.DEVLINK_PORT_FN_ATTR_STATE:
|
||||||
|
port.Fn.State = uint8(nested.Value[0])
|
||||||
|
case nl.DEVLINK_PORT_FN_ATTR_OPSTATE:
|
||||||
|
port.Fn.OpState = uint8(nested.Value[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -391,3 +448,281 @@ func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint
|
|||||||
func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
|
func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
|
||||||
return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex)
|
return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DevLinkPortAdd adds a devlink port and returns a port on success
|
||||||
|
// otherwise returns nil port and an error code.
|
||||||
|
func (h *Handle) DevLinkPortAdd(Bus string, Device string, Flavour uint16, Attrs DevLinkPortAddAttrs) (*DevlinkPort, error) {
|
||||||
|
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_NEW, Bus, Device)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FLAVOUR, nl.Uint16Attr(Flavour)))
|
||||||
|
|
||||||
|
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_PCI_PF_NUMBER, nl.Uint16Attr(Attrs.PfNumber)))
|
||||||
|
if Flavour == nl.DEVLINK_PORT_FLAVOUR_PCI_SF && Attrs.SfNumberValid {
|
||||||
|
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_PCI_SF_NUMBER, nl.Uint32Attr(Attrs.SfNumber)))
|
||||||
|
}
|
||||||
|
if Attrs.PortIndexValid {
|
||||||
|
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(Attrs.PortIndex)))
|
||||||
|
}
|
||||||
|
if Attrs.ControllerValid {
|
||||||
|
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, nl.Uint32Attr(Attrs.Controller)))
|
||||||
|
}
|
||||||
|
respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
port, err := parseDevlinkPortMsg(respmsg)
|
||||||
|
return port, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevLinkPortAdd adds a devlink port and returns a port on success
|
||||||
|
// otherwise returns nil port and an error code.
|
||||||
|
func DevLinkPortAdd(Bus string, Device string, Flavour uint16, Attrs DevLinkPortAddAttrs) (*DevlinkPort, error) {
|
||||||
|
return pkgHandle.DevLinkPortAdd(Bus, Device, Flavour, Attrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevLinkPortDel deletes a devlink port and returns success or error code.
|
||||||
|
func (h *Handle) DevLinkPortDel(Bus string, Device string, PortIndex uint32) error {
|
||||||
|
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_DEL, Bus, Device)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
|
||||||
|
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevLinkPortDel deletes a devlink port and returns success or error code.
|
||||||
|
func DevLinkPortDel(Bus string, Device string, PortIndex uint32) error {
|
||||||
|
return pkgHandle.DevLinkPortDel(Bus, Device, PortIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask.
|
||||||
|
// It returns 0 on success or error code.
|
||||||
|
func (h *Handle) DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error {
|
||||||
|
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_SET, Bus, Device)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
|
||||||
|
|
||||||
|
fnAttr := nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FUNCTION|unix.NLA_F_NESTED, nil)
|
||||||
|
|
||||||
|
if FnAttrs.HwAddrValid {
|
||||||
|
fnAttr.AddRtAttr(nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, []byte(FnAttrs.FnAttrs.HwAddr))
|
||||||
|
}
|
||||||
|
|
||||||
|
if FnAttrs.StateValid {
|
||||||
|
fnAttr.AddRtAttr(nl.DEVLINK_PORT_FN_ATTR_STATE, nl.Uint8Attr(FnAttrs.FnAttrs.State))
|
||||||
|
}
|
||||||
|
req.AddData(fnAttr)
|
||||||
|
|
||||||
|
_, err = req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask.
|
||||||
|
// It returns 0 on success or error code.
|
||||||
|
func DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error {
|
||||||
|
return pkgHandle.DevlinkPortFnSet(Bus, Device, PortIndex, FnAttrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// devlinkInfoGetter is function that is responsible for getting devlink info message
|
||||||
|
// this is introduced for test purpose
|
||||||
|
type devlinkInfoGetter func(bus, device string) ([]byte, error)
|
||||||
|
|
||||||
|
// DevlinkGetDeviceInfoByName returns devlink info for selected device,
|
||||||
|
// otherwise returns an error code.
|
||||||
|
// Equivalent to: `devlink dev info $dev`
|
||||||
|
func (h *Handle) DevlinkGetDeviceInfoByName(Bus string, Device string, getInfoMsg devlinkInfoGetter) (*DevlinkDeviceInfo, error) {
|
||||||
|
info, err := h.DevlinkGetDeviceInfoByNameAsMap(Bus, Device, getInfoMsg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseInfoData(info), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevlinkGetDeviceInfoByName returns devlink info for selected device,
|
||||||
|
// otherwise returns an error code.
|
||||||
|
// Equivalent to: `devlink dev info $dev`
|
||||||
|
func DevlinkGetDeviceInfoByName(Bus string, Device string) (*DevlinkDeviceInfo, error) {
|
||||||
|
return pkgHandle.DevlinkGetDeviceInfoByName(Bus, Device, pkgHandle.getDevlinkInfoMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevlinkGetDeviceInfoByNameAsMap returns devlink info for selected device as a map,
|
||||||
|
// otherwise returns an error code.
|
||||||
|
// Equivalent to: `devlink dev info $dev`
|
||||||
|
func (h *Handle) DevlinkGetDeviceInfoByNameAsMap(Bus string, Device string, getInfoMsg devlinkInfoGetter) (map[string]string, error) {
|
||||||
|
response, err := getInfoMsg(Bus, Device)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := parseInfoMsg(response)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevlinkGetDeviceInfoByNameAsMap returns devlink info for selected device as a map,
|
||||||
|
// otherwise returns an error code.
|
||||||
|
// Equivalent to: `devlink dev info $dev`
|
||||||
|
func DevlinkGetDeviceInfoByNameAsMap(Bus string, Device string) (map[string]string, error) {
|
||||||
|
return pkgHandle.DevlinkGetDeviceInfoByNameAsMap(Bus, Device, pkgHandle.getDevlinkInfoMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDevlinkInfo returns devlink info for target device,
|
||||||
|
// otherwise returns an error code.
|
||||||
|
func (d *DevlinkDevice) GetDevlinkInfo() (*DevlinkDeviceInfo, error) {
|
||||||
|
return pkgHandle.DevlinkGetDeviceInfoByName(d.BusName, d.DeviceName, pkgHandle.getDevlinkInfoMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDevlinkInfoAsMap returns devlink info for target device as a map,
|
||||||
|
// otherwise returns an error code.
|
||||||
|
func (d *DevlinkDevice) GetDevlinkInfoAsMap() (map[string]string, error) {
|
||||||
|
return pkgHandle.DevlinkGetDeviceInfoByNameAsMap(d.BusName, d.DeviceName, pkgHandle.getDevlinkInfoMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) getDevlinkInfoMsg(bus, device string) ([]byte, error) {
|
||||||
|
_, req, err := h.createCmdReq(nl.DEVLINK_CMD_INFO_GET, bus, device)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := req.Execute(unix.NETLINK_GENERIC, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(response) < 1 {
|
||||||
|
return nil, fmt.Errorf("getDevlinkInfoMsg: message too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInfoMsg(msg []byte) (map[string]string, error) {
|
||||||
|
if len(msg) < nl.SizeofGenlmsg {
|
||||||
|
return nil, fmt.Errorf("parseInfoMsg: message too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
info := make(map[string]string)
|
||||||
|
err := collectInfoData(msg[nl.SizeofGenlmsg:], info)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectInfoData(msg []byte, data map[string]string) error {
|
||||||
|
attrs, err := nl.ParseRouteAttr(msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, attr := range attrs {
|
||||||
|
switch attr.Attr.Type {
|
||||||
|
case nl.DEVLINK_ATTR_INFO_DRIVER_NAME:
|
||||||
|
data["driver"] = parseInfoValue(attr.Value)
|
||||||
|
case nl.DEVLINK_ATTR_INFO_SERIAL_NUMBER:
|
||||||
|
data["serialNumber"] = parseInfoValue(attr.Value)
|
||||||
|
case nl.DEVLINK_ATTR_INFO_VERSION_RUNNING, nl.DEVLINK_ATTR_INFO_VERSION_FIXED,
|
||||||
|
nl.DEVLINK_ATTR_INFO_VERSION_STORED:
|
||||||
|
key, value, err := getNestedInfoData(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(data) == 0 {
|
||||||
|
return fmt.Errorf("collectInfoData: could not read attributes")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNestedInfoData(msg []byte) (string, string, error) {
|
||||||
|
nestedAttrs, err := nl.ParseRouteAttr(msg)
|
||||||
|
|
||||||
|
var key, value string
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(nestedAttrs) != 2 {
|
||||||
|
return "", "", fmt.Errorf("getNestedInfoData: too few attributes in nested structure")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, nestedAttr := range nestedAttrs {
|
||||||
|
switch nestedAttr.Attr.Type {
|
||||||
|
case nl.DEVLINK_ATTR_INFO_VERSION_NAME:
|
||||||
|
key = parseInfoValue(nestedAttr.Value)
|
||||||
|
case nl.DEVLINK_ATTR_INFO_VERSION_VALUE:
|
||||||
|
value = parseInfoValue(nestedAttr.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == "" {
|
||||||
|
return "", "", fmt.Errorf("getNestedInfoData: key not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == "" {
|
||||||
|
return "", "", fmt.Errorf("getNestedInfoData: value not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInfoData(data map[string]string) *DevlinkDeviceInfo {
|
||||||
|
info := new(DevlinkDeviceInfo)
|
||||||
|
for key, value := range data {
|
||||||
|
switch key {
|
||||||
|
case "driver":
|
||||||
|
info.Driver = value
|
||||||
|
case "serialNumber":
|
||||||
|
info.SerialNumber = value
|
||||||
|
case "board.id":
|
||||||
|
info.BoardID = value
|
||||||
|
case "fw.app":
|
||||||
|
info.FwApp = value
|
||||||
|
case "fw.app.bundle_id":
|
||||||
|
info.FwAppBoundleID = value
|
||||||
|
case "fw.app.name":
|
||||||
|
info.FwAppName = value
|
||||||
|
case "fw.bundle_id":
|
||||||
|
info.FwBoundleID = value
|
||||||
|
case "fw.mgmt":
|
||||||
|
info.FwMgmt = value
|
||||||
|
case "fw.mgmt.api":
|
||||||
|
info.FwMgmtAPI = value
|
||||||
|
case "fw.mgmt.build":
|
||||||
|
info.FwMgmtBuild = value
|
||||||
|
case "fw.netlist":
|
||||||
|
info.FwNetlist = value
|
||||||
|
case "fw.netlist.build":
|
||||||
|
info.FwNetlistBuild = value
|
||||||
|
case "fw.psid.api":
|
||||||
|
info.FwPsidAPI = value
|
||||||
|
case "fw.undi":
|
||||||
|
info.FwUndi = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInfoValue(value []byte) string {
|
||||||
|
v := strings.ReplaceAll(string(value), "\x00", "")
|
||||||
|
return strings.TrimSpace(v)
|
||||||
|
}
|
||||||
|
62
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
62
vendor/github.com/vishvananda/netlink/filter.go
generated
vendored
@ -260,6 +260,40 @@ func NewSkbEditAction() *SkbEditAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PoliceAction struct {
|
||||||
|
ActionAttrs
|
||||||
|
Rate uint32 // in byte per second
|
||||||
|
Burst uint32 // in byte
|
||||||
|
RCellLog int
|
||||||
|
Mtu uint32
|
||||||
|
Mpu uint16 // in byte
|
||||||
|
PeakRate uint32 // in byte per second
|
||||||
|
PCellLog int
|
||||||
|
AvRate uint32 // in byte per second
|
||||||
|
Overhead uint16
|
||||||
|
LinkLayer int
|
||||||
|
ExceedAction TcPolAct
|
||||||
|
NotExceedAction TcPolAct
|
||||||
|
}
|
||||||
|
|
||||||
|
func (action *PoliceAction) Type() string {
|
||||||
|
return "police"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (action *PoliceAction) Attrs() *ActionAttrs {
|
||||||
|
return &action.ActionAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPoliceAction() *PoliceAction {
|
||||||
|
return &PoliceAction{
|
||||||
|
RCellLog: -1,
|
||||||
|
PCellLog: -1,
|
||||||
|
LinkLayer: 1, // ETHERNET
|
||||||
|
ExceedAction: TC_POLICE_RECLASSIFY,
|
||||||
|
NotExceedAction: TC_POLICE_OK,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MatchAll filters match all packets
|
// MatchAll filters match all packets
|
||||||
type MatchAll struct {
|
type MatchAll struct {
|
||||||
FilterAttrs
|
FilterAttrs
|
||||||
@ -275,20 +309,20 @@ func (filter *MatchAll) Type() string {
|
|||||||
return "matchall"
|
return "matchall"
|
||||||
}
|
}
|
||||||
|
|
||||||
type FilterFwAttrs struct {
|
type FwFilter struct {
|
||||||
ClassId uint32
|
FilterAttrs
|
||||||
InDev string
|
ClassId uint32
|
||||||
Mask uint32
|
InDev string
|
||||||
Index uint32
|
Mask uint32
|
||||||
Buffer uint32
|
Police *PoliceAction
|
||||||
Mtu uint32
|
}
|
||||||
Mpu uint16
|
|
||||||
Rate uint32
|
func (filter *FwFilter) Attrs() *FilterAttrs {
|
||||||
AvRate uint32
|
return &filter.FilterAttrs
|
||||||
PeakRate uint32
|
}
|
||||||
Action TcPolAct
|
|
||||||
Overhead uint16
|
func (filter *FwFilter) Type() string {
|
||||||
LinkLayer int
|
return "fw"
|
||||||
}
|
}
|
||||||
|
|
||||||
type BpfFilter struct {
|
type BpfFilter struct {
|
||||||
|
314
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
314
vendor/github.com/vishvananda/netlink/filter_linux.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
@ -50,74 +51,129 @@ func (filter *U32) Type() string {
|
|||||||
return "u32"
|
return "u32"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fw filter filters on firewall marks
|
type Flower struct {
|
||||||
// NOTE: this is in filter_linux because it refers to nl.TcPolice which
|
|
||||||
// is defined in nl/tc_linux.go
|
|
||||||
type Fw struct {
|
|
||||||
FilterAttrs
|
FilterAttrs
|
||||||
ClassId uint32
|
DestIP net.IP
|
||||||
// TODO remove nl type from interface
|
DestIPMask net.IPMask
|
||||||
Police nl.TcPolice
|
SrcIP net.IP
|
||||||
InDev string
|
SrcIPMask net.IPMask
|
||||||
// TODO Action
|
EthType uint16
|
||||||
Mask uint32
|
EncDestIP net.IP
|
||||||
AvRate uint32
|
EncDestIPMask net.IPMask
|
||||||
Rtab [256]uint32
|
EncSrcIP net.IP
|
||||||
Ptab [256]uint32
|
EncSrcIPMask net.IPMask
|
||||||
|
EncDestPort uint16
|
||||||
|
EncKeyId uint32
|
||||||
|
|
||||||
|
Actions []Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
|
func (filter *Flower) Attrs() *FilterAttrs {
|
||||||
var rtab [256]uint32
|
|
||||||
var ptab [256]uint32
|
|
||||||
rcellLog := -1
|
|
||||||
pcellLog := -1
|
|
||||||
avrate := fattrs.AvRate / 8
|
|
||||||
police := nl.TcPolice{}
|
|
||||||
police.Rate.Rate = fattrs.Rate / 8
|
|
||||||
police.PeakRate.Rate = fattrs.PeakRate / 8
|
|
||||||
buffer := fattrs.Buffer
|
|
||||||
linklayer := nl.LINKLAYER_ETHERNET
|
|
||||||
|
|
||||||
if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC {
|
|
||||||
linklayer = fattrs.LinkLayer
|
|
||||||
}
|
|
||||||
|
|
||||||
police.Action = int32(fattrs.Action)
|
|
||||||
if police.Rate.Rate != 0 {
|
|
||||||
police.Rate.Mpu = fattrs.Mpu
|
|
||||||
police.Rate.Overhead = fattrs.Overhead
|
|
||||||
if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 {
|
|
||||||
return nil, errors.New("TBF: failed to calculate rate table")
|
|
||||||
}
|
|
||||||
police.Burst = Xmittime(uint64(police.Rate.Rate), uint32(buffer))
|
|
||||||
}
|
|
||||||
police.Mtu = fattrs.Mtu
|
|
||||||
if police.PeakRate.Rate != 0 {
|
|
||||||
police.PeakRate.Mpu = fattrs.Mpu
|
|
||||||
police.PeakRate.Overhead = fattrs.Overhead
|
|
||||||
if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 {
|
|
||||||
return nil, errors.New("POLICE: failed to calculate peak rate table")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Fw{
|
|
||||||
FilterAttrs: attrs,
|
|
||||||
ClassId: fattrs.ClassId,
|
|
||||||
InDev: fattrs.InDev,
|
|
||||||
Mask: fattrs.Mask,
|
|
||||||
Police: police,
|
|
||||||
AvRate: avrate,
|
|
||||||
Rtab: rtab,
|
|
||||||
Ptab: ptab,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (filter *Fw) Attrs() *FilterAttrs {
|
|
||||||
return &filter.FilterAttrs
|
return &filter.FilterAttrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (filter *Fw) Type() string {
|
func (filter *Flower) Type() string {
|
||||||
return "fw"
|
return "flower"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (filter *Flower) encodeIP(parent *nl.RtAttr, ip net.IP, mask net.IPMask, v4Type, v6Type int, v4MaskType, v6MaskType int) {
|
||||||
|
ipType := v4Type
|
||||||
|
maskType := v4MaskType
|
||||||
|
|
||||||
|
encodeMask := mask
|
||||||
|
if mask == nil {
|
||||||
|
encodeMask = net.CIDRMask(32, 32)
|
||||||
|
}
|
||||||
|
v4IP := ip.To4()
|
||||||
|
if v4IP == nil {
|
||||||
|
ipType = v6Type
|
||||||
|
maskType = v6MaskType
|
||||||
|
if mask == nil {
|
||||||
|
encodeMask = net.CIDRMask(128, 128)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ip = v4IP
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.AddRtAttr(ipType, ip)
|
||||||
|
parent.AddRtAttr(maskType, encodeMask)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (filter *Flower) encode(parent *nl.RtAttr) error {
|
||||||
|
if filter.EthType != 0 {
|
||||||
|
parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_TYPE, htons(filter.EthType))
|
||||||
|
}
|
||||||
|
if filter.SrcIP != nil {
|
||||||
|
filter.encodeIP(parent, filter.SrcIP, filter.SrcIPMask,
|
||||||
|
nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC,
|
||||||
|
nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK)
|
||||||
|
}
|
||||||
|
if filter.DestIP != nil {
|
||||||
|
filter.encodeIP(parent, filter.DestIP, filter.DestIPMask,
|
||||||
|
nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST,
|
||||||
|
nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK)
|
||||||
|
}
|
||||||
|
if filter.EncSrcIP != nil {
|
||||||
|
filter.encodeIP(parent, filter.EncSrcIP, filter.EncSrcIPMask,
|
||||||
|
nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC,
|
||||||
|
nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK)
|
||||||
|
}
|
||||||
|
if filter.EncDestIP != nil {
|
||||||
|
filter.encodeIP(parent, filter.EncDestIP, filter.EncSrcIPMask,
|
||||||
|
nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST,
|
||||||
|
nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK)
|
||||||
|
}
|
||||||
|
if filter.EncDestPort != 0 {
|
||||||
|
parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT, htons(filter.EncDestPort))
|
||||||
|
}
|
||||||
|
if filter.EncKeyId != 0 {
|
||||||
|
parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
|
||||||
|
}
|
||||||
|
|
||||||
|
actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil)
|
||||||
|
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
|
||||||
|
for _, datum := range data {
|
||||||
|
switch datum.Attr.Type {
|
||||||
|
case nl.TCA_FLOWER_KEY_ETH_TYPE:
|
||||||
|
filter.EthType = ntohs(datum.Value)
|
||||||
|
case nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC:
|
||||||
|
filter.SrcIP = datum.Value
|
||||||
|
case nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK:
|
||||||
|
filter.SrcIPMask = datum.Value
|
||||||
|
case nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST:
|
||||||
|
filter.DestIP = datum.Value
|
||||||
|
case nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK:
|
||||||
|
filter.DestIPMask = datum.Value
|
||||||
|
case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC:
|
||||||
|
filter.EncSrcIP = datum.Value
|
||||||
|
case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK:
|
||||||
|
filter.EncSrcIPMask = datum.Value
|
||||||
|
case nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST:
|
||||||
|
filter.EncDestIP = datum.Value
|
||||||
|
case nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK:
|
||||||
|
filter.EncDestIPMask = datum.Value
|
||||||
|
case nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT:
|
||||||
|
filter.EncDestPort = ntohs(datum.Value)
|
||||||
|
case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
|
||||||
|
filter.EncKeyId = ntohl(datum.Value)
|
||||||
|
case nl.TCA_FLOWER_ACT:
|
||||||
|
tables, err := nl.ParseRouteAttr(datum.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
filter.Actions, err = parseActions(tables)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterDel will delete a filter from the system.
|
// FilterDel will delete a filter from the system.
|
||||||
@ -169,7 +225,6 @@ func (h *Handle) FilterReplace(filter Filter) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) filterModify(filter Filter, flags int) error {
|
func (h *Handle) filterModify(filter Filter, flags int) error {
|
||||||
native = nl.NativeEndian()
|
|
||||||
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
|
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
|
||||||
base := filter.Attrs()
|
base := filter.Attrs()
|
||||||
msg := &nl.TcMsg{
|
msg := &nl.TcMsg{
|
||||||
@ -237,7 +292,7 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|||||||
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case *Fw:
|
case *FwFilter:
|
||||||
if filter.Mask != 0 {
|
if filter.Mask != 0 {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, filter.Mask)
|
native.PutUint32(b, filter.Mask)
|
||||||
@ -246,17 +301,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|||||||
if filter.InDev != "" {
|
if filter.InDev != "" {
|
||||||
options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
|
options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
|
||||||
}
|
}
|
||||||
if (filter.Police != nl.TcPolice{}) {
|
if filter.Police != nil {
|
||||||
|
|
||||||
police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
|
police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
|
||||||
police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize())
|
if err := encodePolice(police, filter.Police); err != nil {
|
||||||
if (filter.Police.Rate != nl.TcRateSpec{}) {
|
return err
|
||||||
payload := SerializeRtab(filter.Rtab)
|
|
||||||
police.AddRtAttr(nl.TCA_POLICE_RATE, payload)
|
|
||||||
}
|
|
||||||
if (filter.Police.PeakRate != nl.TcRateSpec{}) {
|
|
||||||
payload := SerializeRtab(filter.Ptab)
|
|
||||||
police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if filter.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
@ -287,6 +335,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|||||||
if filter.ClassId != 0 {
|
if filter.ClassId != 0 {
|
||||||
options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
|
options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
|
||||||
}
|
}
|
||||||
|
case *Flower:
|
||||||
|
if err := filter.encode(options); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req.AddData(options)
|
req.AddData(options)
|
||||||
@ -350,11 +402,13 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|||||||
case "u32":
|
case "u32":
|
||||||
filter = &U32{}
|
filter = &U32{}
|
||||||
case "fw":
|
case "fw":
|
||||||
filter = &Fw{}
|
filter = &FwFilter{}
|
||||||
case "bpf":
|
case "bpf":
|
||||||
filter = &BpfFilter{}
|
filter = &BpfFilter{}
|
||||||
case "matchall":
|
case "matchall":
|
||||||
filter = &MatchAll{}
|
filter = &MatchAll{}
|
||||||
|
case "flower":
|
||||||
|
filter = &Flower{}
|
||||||
default:
|
default:
|
||||||
filter = &GenericFilter{FilterType: filterType}
|
filter = &GenericFilter{FilterType: filterType}
|
||||||
}
|
}
|
||||||
@ -384,6 +438,11 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
case "flower":
|
||||||
|
detailed, err = parseFlowerData(filter, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
detailed = true
|
detailed = true
|
||||||
}
|
}
|
||||||
@ -415,6 +474,53 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
|
|||||||
attrs.Bindcnt = int(tcgen.Bindcnt)
|
attrs.Bindcnt = int(tcgen.Bindcnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodePolice(attr *nl.RtAttr, action *PoliceAction) error {
|
||||||
|
var rtab [256]uint32
|
||||||
|
var ptab [256]uint32
|
||||||
|
police := nl.TcPolice{}
|
||||||
|
police.Index = uint32(action.Attrs().Index)
|
||||||
|
police.Bindcnt = int32(action.Attrs().Bindcnt)
|
||||||
|
police.Capab = uint32(action.Attrs().Capab)
|
||||||
|
police.Refcnt = int32(action.Attrs().Refcnt)
|
||||||
|
police.Rate.Rate = action.Rate
|
||||||
|
police.PeakRate.Rate = action.PeakRate
|
||||||
|
police.Action = int32(action.ExceedAction)
|
||||||
|
|
||||||
|
if police.Rate.Rate != 0 {
|
||||||
|
police.Rate.Mpu = action.Mpu
|
||||||
|
police.Rate.Overhead = action.Overhead
|
||||||
|
if CalcRtable(&police.Rate, rtab[:], action.RCellLog, action.Mtu, action.LinkLayer) < 0 {
|
||||||
|
return errors.New("TBF: failed to calculate rate table")
|
||||||
|
}
|
||||||
|
police.Burst = Xmittime(uint64(police.Rate.Rate), action.Burst)
|
||||||
|
}
|
||||||
|
|
||||||
|
police.Mtu = action.Mtu
|
||||||
|
if police.PeakRate.Rate != 0 {
|
||||||
|
police.PeakRate.Mpu = action.Mpu
|
||||||
|
police.PeakRate.Overhead = action.Overhead
|
||||||
|
if CalcRtable(&police.PeakRate, ptab[:], action.PCellLog, action.Mtu, action.LinkLayer) < 0 {
|
||||||
|
return errors.New("POLICE: failed to calculate peak rate table")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.AddRtAttr(nl.TCA_POLICE_TBF, police.Serialize())
|
||||||
|
if police.Rate.Rate != 0 {
|
||||||
|
attr.AddRtAttr(nl.TCA_POLICE_RATE, SerializeRtab(rtab))
|
||||||
|
}
|
||||||
|
if police.PeakRate.Rate != 0 {
|
||||||
|
attr.AddRtAttr(nl.TCA_POLICE_PEAKRATE, SerializeRtab(ptab))
|
||||||
|
}
|
||||||
|
if action.AvRate != 0 {
|
||||||
|
attr.AddRtAttr(nl.TCA_POLICE_AVRATE, nl.Uint32Attr(action.AvRate))
|
||||||
|
}
|
||||||
|
if action.NotExceedAction != 0 {
|
||||||
|
attr.AddRtAttr(nl.TCA_POLICE_RESULT, nl.Uint32Attr(uint32(action.NotExceedAction)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
||||||
tabIndex := int(nl.TCA_ACT_TAB)
|
tabIndex := int(nl.TCA_ACT_TAB)
|
||||||
|
|
||||||
@ -422,6 +528,14 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|||||||
switch action := action.(type) {
|
switch action := action.(type) {
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown action type %s", action.Type())
|
return fmt.Errorf("unknown action type %s", action.Type())
|
||||||
|
case *PoliceAction:
|
||||||
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
|
tabIndex++
|
||||||
|
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("police"))
|
||||||
|
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
||||||
|
if err := encodePolice(aopts, action); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case *MirredAction:
|
case *MirredAction:
|
||||||
table := attr.AddRtAttr(tabIndex, nil)
|
table := attr.AddRtAttr(tabIndex, nil)
|
||||||
tabIndex++
|
tabIndex++
|
||||||
@ -516,6 +630,29 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parsePolice(data syscall.NetlinkRouteAttr, police *PoliceAction) {
|
||||||
|
switch data.Attr.Type {
|
||||||
|
case nl.TCA_POLICE_RESULT:
|
||||||
|
police.NotExceedAction = TcPolAct(native.Uint32(data.Value[0:4]))
|
||||||
|
case nl.TCA_POLICE_AVRATE:
|
||||||
|
police.AvRate = native.Uint32(data.Value[0:4])
|
||||||
|
case nl.TCA_POLICE_TBF:
|
||||||
|
p := *nl.DeserializeTcPolice(data.Value)
|
||||||
|
police.ActionAttrs = ActionAttrs{}
|
||||||
|
police.Attrs().Index = int(p.Index)
|
||||||
|
police.Attrs().Bindcnt = int(p.Bindcnt)
|
||||||
|
police.Attrs().Capab = int(p.Capab)
|
||||||
|
police.Attrs().Refcnt = int(p.Refcnt)
|
||||||
|
police.ExceedAction = TcPolAct(p.Action)
|
||||||
|
police.Rate = p.Rate.Rate
|
||||||
|
police.PeakRate = p.PeakRate.Rate
|
||||||
|
police.Burst = Xmitsize(uint64(p.Rate.Rate), p.Burst)
|
||||||
|
police.Mtu = p.Mtu
|
||||||
|
police.LinkLayer = int(p.Rate.Linklayer) & nl.TC_LINKLAYER_MASK
|
||||||
|
police.Overhead = p.Rate.Overhead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
||||||
var actions []Action
|
var actions []Action
|
||||||
for _, table := range tables {
|
for _, table := range tables {
|
||||||
@ -544,6 +681,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|||||||
action = &TunnelKeyAction{}
|
action = &TunnelKeyAction{}
|
||||||
case "skbedit":
|
case "skbedit":
|
||||||
action = &SkbEditAction{}
|
action = &SkbEditAction{}
|
||||||
|
case "police":
|
||||||
|
action = &PoliceAction{}
|
||||||
default:
|
default:
|
||||||
break nextattr
|
break nextattr
|
||||||
}
|
}
|
||||||
@ -622,6 +761,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|||||||
gen := *nl.DeserializeTcGen(adatum.Value)
|
gen := *nl.DeserializeTcGen(adatum.Value)
|
||||||
toAttrs(&gen, action.Attrs())
|
toAttrs(&gen, action.Attrs())
|
||||||
}
|
}
|
||||||
|
case "police":
|
||||||
|
parsePolice(adatum, action.(*PoliceAction))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,7 +773,6 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
||||||
native = nl.NativeEndian()
|
|
||||||
u32 := filter.(*U32)
|
u32 := filter.(*U32)
|
||||||
detailed := false
|
detailed := false
|
||||||
for _, datum := range data {
|
for _, datum := range data {
|
||||||
@ -678,8 +818,7 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
||||||
native = nl.NativeEndian()
|
fw := filter.(*FwFilter)
|
||||||
fw := filter.(*Fw)
|
|
||||||
detailed := true
|
detailed := true
|
||||||
for _, datum := range data {
|
for _, datum := range data {
|
||||||
switch datum.Attr.Type {
|
switch datum.Attr.Type {
|
||||||
@ -690,24 +829,18 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
|||||||
case nl.TCA_FW_INDEV:
|
case nl.TCA_FW_INDEV:
|
||||||
fw.InDev = string(datum.Value[:len(datum.Value)-1])
|
fw.InDev = string(datum.Value[:len(datum.Value)-1])
|
||||||
case nl.TCA_FW_POLICE:
|
case nl.TCA_FW_POLICE:
|
||||||
|
var police PoliceAction
|
||||||
adata, _ := nl.ParseRouteAttr(datum.Value)
|
adata, _ := nl.ParseRouteAttr(datum.Value)
|
||||||
for _, aattr := range adata {
|
for _, aattr := range adata {
|
||||||
switch aattr.Attr.Type {
|
parsePolice(aattr, &police)
|
||||||
case nl.TCA_POLICE_TBF:
|
|
||||||
fw.Police = *nl.DeserializeTcPolice(aattr.Value)
|
|
||||||
case nl.TCA_POLICE_RATE:
|
|
||||||
fw.Rtab = DeserializeRtab(aattr.Value)
|
|
||||||
case nl.TCA_POLICE_PEAKRATE:
|
|
||||||
fw.Ptab = DeserializeRtab(aattr.Value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
fw.Police = &police
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return detailed, nil
|
return detailed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
||||||
native = nl.NativeEndian()
|
|
||||||
bpf := filter.(*BpfFilter)
|
bpf := filter.(*BpfFilter)
|
||||||
detailed := true
|
detailed := true
|
||||||
for _, datum := range data {
|
for _, datum := range data {
|
||||||
@ -733,7 +866,6 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
||||||
native = nl.NativeEndian()
|
|
||||||
matchall := filter.(*MatchAll)
|
matchall := filter.(*MatchAll)
|
||||||
detailed := true
|
detailed := true
|
||||||
for _, datum := range data {
|
for _, datum := range data {
|
||||||
@ -754,6 +886,10 @@ func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, er
|
|||||||
return detailed, nil
|
return detailed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseFlowerData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
||||||
|
return true, filter.(*Flower).decode(data)
|
||||||
|
}
|
||||||
|
|
||||||
func AlignToAtm(size uint) uint {
|
func AlignToAtm(size uint) uint {
|
||||||
var linksize, cells int
|
var linksize, cells int
|
||||||
cells = int(size / nl.ATM_CELL_PAYLOAD)
|
cells = int(size / nl.ATM_CELL_PAYLOAD)
|
||||||
@ -801,14 +937,12 @@ func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, lin
|
|||||||
|
|
||||||
func DeserializeRtab(b []byte) [256]uint32 {
|
func DeserializeRtab(b []byte) [256]uint32 {
|
||||||
var rtab [256]uint32
|
var rtab [256]uint32
|
||||||
native := nl.NativeEndian()
|
|
||||||
r := bytes.NewReader(b)
|
r := bytes.NewReader(b)
|
||||||
_ = binary.Read(r, native, &rtab)
|
_ = binary.Read(r, native, &rtab)
|
||||||
return rtab
|
return rtab
|
||||||
}
|
}
|
||||||
|
|
||||||
func SerializeRtab(rtab [256]uint32) []byte {
|
func SerializeRtab(rtab [256]uint32) []byte {
|
||||||
native := nl.NativeEndian()
|
|
||||||
var w bytes.Buffer
|
var w bytes.Buffer
|
||||||
_ = binary.Write(&w, native, rtab)
|
_ = binary.Write(&w, native, rtab)
|
||||||
return w.Bytes()
|
return w.Bytes()
|
||||||
|
14
vendor/github.com/vishvananda/netlink/handle_linux.go
generated
vendored
14
vendor/github.com/vishvananda/netlink/handle_linux.go
generated
vendored
@ -15,7 +15,7 @@ var pkgHandle = &Handle{}
|
|||||||
// Handle is an handle for the netlink requests on a
|
// Handle is an handle for the netlink requests on a
|
||||||
// specific network namespace. All the requests on the
|
// specific network namespace. All the requests on the
|
||||||
// same netlink family share the same netlink socket,
|
// same netlink family share the same netlink socket,
|
||||||
// which gets released when the handle is deleted.
|
// which gets released when the handle is Close'd.
|
||||||
type Handle struct {
|
type Handle struct {
|
||||||
sockets map[int]*nl.SocketHandle
|
sockets map[int]*nl.SocketHandle
|
||||||
lookupByDump bool
|
lookupByDump bool
|
||||||
@ -136,14 +136,22 @@ func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error)
|
|||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete releases the resources allocated to this handle
|
// Close releases the resources allocated to this handle
|
||||||
func (h *Handle) Delete() {
|
func (h *Handle) Close() {
|
||||||
for _, sh := range h.sockets {
|
for _, sh := range h.sockets {
|
||||||
sh.Close()
|
sh.Close()
|
||||||
}
|
}
|
||||||
h.sockets = nil
|
h.sockets = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete releases the resources allocated to this handle
|
||||||
|
//
|
||||||
|
// Deprecated: use Close instead which is in line with typical resource release
|
||||||
|
// patterns for files and other resources.
|
||||||
|
func (h *Handle) Delete() {
|
||||||
|
h.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
|
func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
|
||||||
// Do this so that package API still use nl package variable nextSeqNr
|
// Do this so that package API still use nl package variable nextSeqNr
|
||||||
if h.sockets == nil {
|
if h.sockets == nil {
|
||||||
|
2
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
2
vendor/github.com/vishvananda/netlink/handle_unspecified.go
generated
vendored
@ -23,6 +23,8 @@ func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
|
|||||||
return nil, ErrNotImplemented
|
return nil, ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handle) Close() {}
|
||||||
|
|
||||||
func (h *Handle) Delete() {}
|
func (h *Handle) Delete() {}
|
||||||
|
|
||||||
func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
|
func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
|
||||||
|
167
vendor/github.com/vishvananda/netlink/ipset_linux.go
generated
vendored
167
vendor/github.com/vishvananda/netlink/ipset_linux.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -11,12 +12,19 @@ import (
|
|||||||
|
|
||||||
// IPSetEntry is used for adding, updating, retreiving and deleting entries
|
// IPSetEntry is used for adding, updating, retreiving and deleting entries
|
||||||
type IPSetEntry struct {
|
type IPSetEntry struct {
|
||||||
Comment string
|
Comment string
|
||||||
MAC net.HardwareAddr
|
MAC net.HardwareAddr
|
||||||
IP net.IP
|
IP net.IP
|
||||||
Timeout *uint32
|
CIDR uint8
|
||||||
Packets *uint64
|
Timeout *uint32
|
||||||
Bytes *uint64
|
Packets *uint64
|
||||||
|
Bytes *uint64
|
||||||
|
Protocol *uint8
|
||||||
|
Port *uint16
|
||||||
|
IP2 net.IP
|
||||||
|
CIDR2 uint8
|
||||||
|
IFace string
|
||||||
|
Mark *uint32
|
||||||
|
|
||||||
Replace bool // replace existing entry
|
Replace bool // replace existing entry
|
||||||
}
|
}
|
||||||
@ -32,6 +40,12 @@ type IPSetResult struct {
|
|||||||
SetName string
|
SetName string
|
||||||
TypeName string
|
TypeName string
|
||||||
Comment string
|
Comment string
|
||||||
|
MarkMask uint32
|
||||||
|
|
||||||
|
IPFrom net.IP
|
||||||
|
IPTo net.IP
|
||||||
|
PortFrom uint16
|
||||||
|
PortTo uint16
|
||||||
|
|
||||||
HashSize uint32
|
HashSize uint32
|
||||||
NumEntries uint32
|
NumEntries uint32
|
||||||
@ -52,6 +66,12 @@ type IpsetCreateOptions struct {
|
|||||||
Counters bool
|
Counters bool
|
||||||
Comments bool
|
Comments bool
|
||||||
Skbinfo bool
|
Skbinfo bool
|
||||||
|
|
||||||
|
Revision uint8
|
||||||
|
IPFrom net.IP
|
||||||
|
IPTo net.IP
|
||||||
|
PortFrom uint16
|
||||||
|
PortTo uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// IpsetProtocol returns the ipset protocol version from the kernel
|
// IpsetProtocol returns the ipset protocol version from the kernel
|
||||||
@ -86,12 +106,12 @@ func IpsetListAll() ([]IPSetResult, error) {
|
|||||||
|
|
||||||
// IpsetAdd adds an entry to an existing ipset.
|
// IpsetAdd adds an entry to an existing ipset.
|
||||||
func IpsetAdd(setname string, entry *IPSetEntry) error {
|
func IpsetAdd(setname string, entry *IPSetEntry) error {
|
||||||
return pkgHandle.ipsetAddDel(nl.IPSET_CMD_ADD, setname, entry)
|
return pkgHandle.IpsetAdd(setname, entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IpsetDel deletes an entry from an existing ipset.
|
// IpsetDel deletes an entry from an existing ipset.
|
||||||
func IpsetDel(setname string, entry *IPSetEntry) error {
|
func IpsetDel(setname string, entry *IPSetEntry) error {
|
||||||
return pkgHandle.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
|
return pkgHandle.IpsetDel(setname, entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) IpsetProtocol() (protocol uint8, minVersion uint8, err error) {
|
func (h *Handle) IpsetProtocol() (protocol uint8, minVersion uint8, err error) {
|
||||||
@ -114,11 +134,30 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption
|
|||||||
|
|
||||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(typename)))
|
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(typename)))
|
||||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(0)))
|
|
||||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(2))) // 2 == inet
|
revision := options.Revision
|
||||||
|
if revision == 0 {
|
||||||
|
revision = getIpsetDefaultWithTypeName(typename)
|
||||||
|
}
|
||||||
|
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(revision)))
|
||||||
|
|
||||||
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
|
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
|
||||||
|
|
||||||
|
var family uint8
|
||||||
|
switch typename {
|
||||||
|
case "hash:mac":
|
||||||
|
case "bitmap:port":
|
||||||
|
buf := make([]byte, 4)
|
||||||
|
binary.BigEndian.PutUint16(buf, options.PortFrom)
|
||||||
|
binary.BigEndian.PutUint16(buf[2:], options.PortTo)
|
||||||
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_FROM|int(nl.NLA_F_NET_BYTEORDER), buf[:2]))
|
||||||
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_TO|int(nl.NLA_F_NET_BYTEORDER), buf[2:]))
|
||||||
|
default:
|
||||||
|
family = unix.AF_INET
|
||||||
|
}
|
||||||
|
|
||||||
|
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(family)))
|
||||||
|
|
||||||
if timeout := options.Timeout; timeout != nil {
|
if timeout := options.Timeout; timeout != nil {
|
||||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *timeout})
|
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *timeout})
|
||||||
}
|
}
|
||||||
@ -187,6 +226,16 @@ func (h *Handle) IpsetListAll() ([]IPSetResult, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IpsetAdd adds an entry to an existing ipset.
|
||||||
|
func (h *Handle) IpsetAdd(setname string, entry *IPSetEntry) error {
|
||||||
|
return h.ipsetAddDel(nl.IPSET_CMD_ADD, setname, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IpsetDel deletes an entry from an existing ipset.
|
||||||
|
func (h *Handle) IpsetDel(setname string, entry *IPSetEntry) error {
|
||||||
|
return h.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
|
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
|
||||||
req := h.newIpsetRequest(nlCmd)
|
req := h.newIpsetRequest(nlCmd)
|
||||||
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
|
||||||
@ -204,15 +253,49 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
|
|||||||
if entry.Timeout != nil {
|
if entry.Timeout != nil {
|
||||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *entry.Timeout})
|
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *entry.Timeout})
|
||||||
}
|
}
|
||||||
if entry.MAC != nil {
|
|
||||||
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_ETHER|int(nl.NLA_F_NET_BYTEORDER), entry.MAC)
|
|
||||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER|int(nl.NLA_F_NESTED), nestedData.Serialize()))
|
|
||||||
}
|
|
||||||
if entry.IP != nil {
|
if entry.IP != nil {
|
||||||
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP)
|
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP)
|
||||||
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NESTED), nestedData.Serialize()))
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NESTED), nestedData.Serialize()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if entry.MAC != nil {
|
||||||
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER, entry.MAC))
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.CIDR != 0 {
|
||||||
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_CIDR, nl.Uint8Attr(entry.CIDR)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.IP2 != nil {
|
||||||
|
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP2)
|
||||||
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP2|int(nl.NLA_F_NESTED), nestedData.Serialize()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.CIDR2 != 0 {
|
||||||
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_CIDR2, nl.Uint8Attr(entry.CIDR2)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.Port != nil {
|
||||||
|
if entry.Protocol == nil {
|
||||||
|
// use tcp protocol as default
|
||||||
|
val := uint8(unix.IPPROTO_TCP)
|
||||||
|
entry.Protocol = &val
|
||||||
|
}
|
||||||
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PROTO, nl.Uint8Attr(*entry.Protocol)))
|
||||||
|
buf := make([]byte, 2)
|
||||||
|
binary.BigEndian.PutUint16(buf, *entry.Port)
|
||||||
|
data.AddChild(nl.NewRtAttr(int(nl.IPSET_ATTR_PORT|nl.NLA_F_NET_BYTEORDER), buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.IFace != "" {
|
||||||
|
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IFACE, nl.ZeroTerminated(entry.IFace)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.Mark != nil {
|
||||||
|
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER, Value: *entry.Mark})
|
||||||
|
}
|
||||||
|
|
||||||
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_LINENO | nl.NLA_F_NET_BYTEORDER, Value: 0})
|
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_LINENO | nl.NLA_F_NET_BYTEORDER, Value: 0})
|
||||||
req.AddData(data)
|
req.AddData(data)
|
||||||
|
|
||||||
@ -235,6 +318,17 @@ func (h *Handle) newIpsetRequest(cmd int) *nl.NetlinkRequest {
|
|||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getIpsetDefaultWithTypeName(typename string) uint8 {
|
||||||
|
switch typename {
|
||||||
|
case "hash:ip,port",
|
||||||
|
"hash:ip,port,ip",
|
||||||
|
"hash:ip,port,net",
|
||||||
|
"hash:net,port":
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func ipsetExecute(req *nl.NetlinkRequest) (msgs [][]byte, err error) {
|
func ipsetExecute(req *nl.NetlinkRequest) (msgs [][]byte, err error) {
|
||||||
msgs, err = req.Execute(unix.NETLINK_NETFILTER, 0)
|
msgs, err = req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||||
|
|
||||||
@ -278,6 +372,8 @@ func (result *IPSetResult) unserialize(msg []byte) {
|
|||||||
result.parseAttrADT(attr.Value)
|
result.parseAttrADT(attr.Value)
|
||||||
case nl.IPSET_ATTR_PROTOCOL_MIN:
|
case nl.IPSET_ATTR_PROTOCOL_MIN:
|
||||||
result.ProtocolMinVersion = attr.Value[0]
|
result.ProtocolMinVersion = attr.Value[0]
|
||||||
|
case nl.IPSET_ATTR_MARKMASK:
|
||||||
|
result.MarkMask = attr.Uint32()
|
||||||
default:
|
default:
|
||||||
log.Printf("unknown ipset attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
|
log.Printf("unknown ipset attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
|
||||||
}
|
}
|
||||||
@ -307,12 +403,31 @@ func (result *IPSetResult) parseAttrData(data []byte) {
|
|||||||
switch nested.Type {
|
switch nested.Type {
|
||||||
case nl.IPSET_ATTR_IP | nl.NLA_F_NET_BYTEORDER:
|
case nl.IPSET_ATTR_IP | nl.NLA_F_NET_BYTEORDER:
|
||||||
result.Entries = append(result.Entries, IPSetEntry{IP: nested.Value})
|
result.Entries = append(result.Entries, IPSetEntry{IP: nested.Value})
|
||||||
|
case nl.IPSET_ATTR_IP:
|
||||||
|
result.IPFrom = nested.Value
|
||||||
|
default:
|
||||||
|
log.Printf("unknown nested ipset data attribute from kernel: %+v %v", nested, nested.Type&nl.NLA_TYPE_MASK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case nl.IPSET_ATTR_IP_TO | nl.NLA_F_NESTED:
|
||||||
|
for nested := range nl.ParseAttributes(attr.Value) {
|
||||||
|
switch nested.Type {
|
||||||
|
case nl.IPSET_ATTR_IP:
|
||||||
|
result.IPTo = nested.Value
|
||||||
|
default:
|
||||||
|
log.Printf("unknown nested ipset data attribute from kernel: %+v %v", nested, nested.Type&nl.NLA_TYPE_MASK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case nl.IPSET_ATTR_PORT_FROM | nl.NLA_F_NET_BYTEORDER:
|
||||||
|
result.PortFrom = networkOrder.Uint16(attr.Value)
|
||||||
|
case nl.IPSET_ATTR_PORT_TO | nl.NLA_F_NET_BYTEORDER:
|
||||||
|
result.PortTo = networkOrder.Uint16(attr.Value)
|
||||||
case nl.IPSET_ATTR_CADT_LINENO | nl.NLA_F_NET_BYTEORDER:
|
case nl.IPSET_ATTR_CADT_LINENO | nl.NLA_F_NET_BYTEORDER:
|
||||||
result.LineNo = attr.Uint32()
|
result.LineNo = attr.Uint32()
|
||||||
case nl.IPSET_ATTR_COMMENT:
|
case nl.IPSET_ATTR_COMMENT:
|
||||||
result.Comment = nl.BytesToString(attr.Value)
|
result.Comment = nl.BytesToString(attr.Value)
|
||||||
|
case nl.IPSET_ATTR_MARKMASK:
|
||||||
|
result.MarkMask = attr.Uint32()
|
||||||
default:
|
default:
|
||||||
log.Printf("unknown ipset data attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
|
log.Printf("unknown ipset data attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
|
||||||
}
|
}
|
||||||
@ -357,6 +472,30 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
|
|||||||
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
|
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case nl.IPSET_ATTR_IP2 | nl.NLA_F_NESTED:
|
||||||
|
for attr := range nl.ParseAttributes(attr.Value) {
|
||||||
|
switch attr.Type {
|
||||||
|
case nl.IPSET_ATTR_IP:
|
||||||
|
entry.IP2 = net.IP(attr.Value)
|
||||||
|
default:
|
||||||
|
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case nl.IPSET_ATTR_CIDR:
|
||||||
|
entry.CIDR = attr.Value[0]
|
||||||
|
case nl.IPSET_ATTR_CIDR2:
|
||||||
|
entry.CIDR2 = attr.Value[0]
|
||||||
|
case nl.IPSET_ATTR_PORT | nl.NLA_F_NET_BYTEORDER:
|
||||||
|
val := networkOrder.Uint16(attr.Value)
|
||||||
|
entry.Port = &val
|
||||||
|
case nl.IPSET_ATTR_PROTO:
|
||||||
|
val := attr.Value[0]
|
||||||
|
entry.Protocol = &val
|
||||||
|
case nl.IPSET_ATTR_IFACE:
|
||||||
|
entry.IFace = nl.BytesToString(attr.Value)
|
||||||
|
case nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER:
|
||||||
|
val := attr.Uint32()
|
||||||
|
entry.Mark = &val
|
||||||
default:
|
default:
|
||||||
log.Printf("unknown ADT attribute from kernel: %+v", attr)
|
log.Printf("unknown ADT attribute from kernel: %+v", attr)
|
||||||
}
|
}
|
||||||
|
73
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
73
vendor/github.com/vishvananda/netlink/link.go
generated
vendored
@ -35,10 +35,13 @@ type LinkAttrs struct {
|
|||||||
Alias string
|
Alias string
|
||||||
Statistics *LinkStatistics
|
Statistics *LinkStatistics
|
||||||
Promisc int
|
Promisc int
|
||||||
|
Allmulti int
|
||||||
|
Multi int
|
||||||
Xdp *LinkXdp
|
Xdp *LinkXdp
|
||||||
EncapType string
|
EncapType string
|
||||||
Protinfo *Protinfo
|
Protinfo *Protinfo
|
||||||
OperState LinkOperState
|
OperState LinkOperState
|
||||||
|
PhysSwitchID int
|
||||||
NetNsID int
|
NetNsID int
|
||||||
NumTxQueues int
|
NumTxQueues int
|
||||||
NumRxQueues int
|
NumRxQueues int
|
||||||
@ -456,6 +459,19 @@ func (ipvlan *IPVlan) Type() string {
|
|||||||
return "ipvlan"
|
return "ipvlan"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPVtap - IPVtap is a virtual interfaces based on ipvlan
|
||||||
|
type IPVtap struct {
|
||||||
|
IPVlan
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ipvtap *IPVtap) Attrs() *LinkAttrs {
|
||||||
|
return &ipvtap.LinkAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ipvtap IPVtap) Type() string {
|
||||||
|
return "ipvtap"
|
||||||
|
}
|
||||||
|
|
||||||
// VlanProtocol type
|
// VlanProtocol type
|
||||||
type VlanProtocol int
|
type VlanProtocol int
|
||||||
|
|
||||||
@ -946,6 +962,14 @@ func (b *BondSlave) SlaveType() string {
|
|||||||
return "bond"
|
return "bond"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VrfSlave struct {
|
||||||
|
Table uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VrfSlave) SlaveType() string {
|
||||||
|
return "vrf"
|
||||||
|
}
|
||||||
|
|
||||||
// Geneve devices must specify RemoteIP and ID (VNI) on create
|
// Geneve devices must specify RemoteIP and ID (VNI) on create
|
||||||
// https://github.com/torvalds/linux/blob/47ec5303d73ea344e84f46660fff693c57641386/drivers/net/geneve.c#L1209-L1223
|
// https://github.com/torvalds/linux/blob/47ec5303d73ea344e84f46660fff693c57641386/drivers/net/geneve.c#L1209-L1223
|
||||||
type Geneve struct {
|
type Geneve struct {
|
||||||
@ -1049,6 +1073,37 @@ func (ip6tnl *Ip6tnl) Type() string {
|
|||||||
return "ip6tnl"
|
return "ip6tnl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from https://elixir.bootlin.com/linux/v5.15.4/source/include/uapi/linux/if_tunnel.h#L84
|
||||||
|
type TunnelEncapType uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
None TunnelEncapType = iota
|
||||||
|
FOU
|
||||||
|
GUE
|
||||||
|
)
|
||||||
|
|
||||||
|
// from https://elixir.bootlin.com/linux/v5.15.4/source/include/uapi/linux/if_tunnel.h#L91
|
||||||
|
type TunnelEncapFlag uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
CSum TunnelEncapFlag = 1 << 0
|
||||||
|
CSum6 = 1 << 1
|
||||||
|
RemCSum = 1 << 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// from https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/ip6_tunnel.h#L12
|
||||||
|
type IP6TunnelFlag uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
IP6_TNL_F_IGN_ENCAP_LIMIT IP6TunnelFlag = 1 // don't add encapsulation limit if one isn't present in inner packet
|
||||||
|
IP6_TNL_F_USE_ORIG_TCLASS = 2 // copy the traffic class field from the inner packet
|
||||||
|
IP6_TNL_F_USE_ORIG_FLOWLABEL = 4 // copy the flowlabel from the inner packet
|
||||||
|
IP6_TNL_F_MIP6_DEV = 8 // being used for Mobile IPv6
|
||||||
|
IP6_TNL_F_RCV_DSCP_COPY = 10 // copy DSCP from the outer packet
|
||||||
|
IP6_TNL_F_USE_ORIG_FWMARK = 20 // copy fwmark from inner packet
|
||||||
|
IP6_TNL_F_ALLOW_LOCAL_REMOTE = 40 // allow remote endpoint on the local node
|
||||||
|
)
|
||||||
|
|
||||||
type Sittun struct {
|
type Sittun struct {
|
||||||
LinkAttrs
|
LinkAttrs
|
||||||
Link uint32
|
Link uint32
|
||||||
@ -1260,11 +1315,27 @@ func (ipoib *IPoIB) Type() string {
|
|||||||
return "ipoib"
|
return "ipoib"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BareUDP struct {
|
||||||
|
LinkAttrs
|
||||||
|
Port uint16
|
||||||
|
EtherType uint16
|
||||||
|
SrcPortMin uint16
|
||||||
|
MultiProto bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bareudp *BareUDP) Attrs() *LinkAttrs {
|
||||||
|
return &bareudp.LinkAttrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bareudp *BareUDP) Type() string {
|
||||||
|
return "bareudp"
|
||||||
|
}
|
||||||
|
|
||||||
// iproute2 supported devices;
|
// iproute2 supported devices;
|
||||||
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
|
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
|
||||||
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
|
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
|
||||||
// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon |
|
// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon |
|
||||||
// bond_slave | ipvlan | xfrm
|
// bond_slave | ipvlan | xfrm | bareudp
|
||||||
|
|
||||||
// LinkNotFoundError wraps the various not found errors when
|
// LinkNotFoundError wraps the various not found errors when
|
||||||
// getting/reading links. This is intended for better error
|
// getting/reading links. This is intended for better error
|
||||||
|
182
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
182
vendor/github.com/vishvananda/netlink/link_linux.go
generated
vendored
@ -55,8 +55,6 @@ const (
|
|||||||
VF_LINK_STATE_DISABLE uint32 = 2
|
VF_LINK_STATE_DISABLE uint32 = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
var lookupByDump = false
|
|
||||||
|
|
||||||
var macvlanModes = [...]uint32{
|
var macvlanModes = [...]uint32{
|
||||||
0,
|
0,
|
||||||
nl.MACVLAN_MODE_PRIVATE,
|
nl.MACVLAN_MODE_PRIVATE,
|
||||||
@ -153,7 +151,6 @@ func (h *Handle) LinkSetAllmulticastOn(link Link) error {
|
|||||||
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||||
msg.Change = unix.IFF_ALLMULTI
|
msg.Change = unix.IFF_ALLMULTI
|
||||||
msg.Flags = unix.IFF_ALLMULTI
|
msg.Flags = unix.IFF_ALLMULTI
|
||||||
|
|
||||||
msg.Index = int32(base.Index)
|
msg.Index = int32(base.Index)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
@ -183,6 +180,51 @@ func (h *Handle) LinkSetAllmulticastOff(link Link) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LinkSetMulticastOn enables the reception of multicast packets for the link device.
|
||||||
|
// Equivalent to: `ip link set $link multicast on`
|
||||||
|
func LinkSetMulticastOn(link Link) error {
|
||||||
|
return pkgHandle.LinkSetMulticastOn(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkSetMulticastOn enables the reception of multicast packets for the link device.
|
||||||
|
// Equivalent to: `ip link set $link multicast on`
|
||||||
|
func (h *Handle) LinkSetMulticastOn(link Link) error {
|
||||||
|
base := link.Attrs()
|
||||||
|
h.ensureIndex(base)
|
||||||
|
req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
|
||||||
|
|
||||||
|
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||||
|
msg.Change = unix.IFF_MULTICAST
|
||||||
|
msg.Flags = unix.IFF_MULTICAST
|
||||||
|
msg.Index = int32(base.Index)
|
||||||
|
req.AddData(msg)
|
||||||
|
|
||||||
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
|
||||||
|
// Equivalent to: `ip link set $link multicast off`
|
||||||
|
func LinkSetMulticastOff(link Link) error {
|
||||||
|
return pkgHandle.LinkSetMulticastOff(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
|
||||||
|
// Equivalent to: `ip link set $link multicast off`
|
||||||
|
func (h *Handle) LinkSetMulticastOff(link Link) error {
|
||||||
|
base := link.Attrs()
|
||||||
|
h.ensureIndex(base)
|
||||||
|
req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
|
||||||
|
|
||||||
|
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
|
||||||
|
msg.Change = unix.IFF_MULTICAST
|
||||||
|
msg.Index = int32(base.Index)
|
||||||
|
req.AddData(msg)
|
||||||
|
|
||||||
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
|
func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
|
||||||
return pkgHandle.MacvlanMACAddrAdd(link, addr)
|
return pkgHandle.MacvlanMACAddrAdd(link, addr)
|
||||||
}
|
}
|
||||||
@ -547,13 +589,13 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
|
|||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
|
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
|
||||||
info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
|
info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
|
||||||
vfmsg := nl.VfVlan{
|
vfmsg := nl.VfVlan{
|
||||||
Vf: uint32(vf),
|
Vf: uint32(vf),
|
||||||
Vlan: uint32(vlan),
|
Vlan: uint32(vlan),
|
||||||
Qos: uint32(qos),
|
Qos: uint32(qos),
|
||||||
}
|
}
|
||||||
nl.NewRtAttrChild(info, nl.IFLA_VF_VLAN, vfmsg.Serialize())
|
info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize())
|
||||||
req.AddData(data)
|
req.AddData(data)
|
||||||
|
|
||||||
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
||||||
@ -1104,6 +1146,10 @@ func (h *Handle) LinkAdd(link Link) error {
|
|||||||
return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LinkModify(link Link) error {
|
||||||
|
return pkgHandle.LinkModify(link)
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) LinkModify(link Link) error {
|
func (h *Handle) LinkModify(link Link) error {
|
||||||
return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
|
return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
|
||||||
}
|
}
|
||||||
@ -1218,9 +1264,26 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
control := func(file *os.File, f func(fd uintptr)) error {
|
||||||
|
name := file.Name()
|
||||||
|
conn, err := file.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SyscallConn() failed on %s: %v", name, err)
|
||||||
|
}
|
||||||
|
if err := conn.Control(f); err != nil {
|
||||||
|
return fmt.Errorf("Failed to get file descriptor for %s: %v", name, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// only persist interface if NonPersist is NOT set
|
// only persist interface if NonPersist is NOT set
|
||||||
if !tuntap.NonPersist {
|
if !tuntap.NonPersist {
|
||||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 1)
|
var errno syscall.Errno
|
||||||
|
if err := control(fds[0], func(fd uintptr) {
|
||||||
|
_, _, errno = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 1)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
cleanupFds(fds)
|
cleanupFds(fds)
|
||||||
return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
|
return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
|
||||||
@ -1237,7 +1300,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
|||||||
// un-persist (e.g. allow the interface to be removed) the tuntap
|
// un-persist (e.g. allow the interface to be removed) the tuntap
|
||||||
// should not hurt if not set prior, condition might be not needed
|
// should not hurt if not set prior, condition might be not needed
|
||||||
if !tuntap.NonPersist {
|
if !tuntap.NonPersist {
|
||||||
_, _, _ = unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 0)
|
// ignore error
|
||||||
|
_ = control(fds[0], func(fd uintptr) {
|
||||||
|
_, _, _ = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 0)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
cleanupFds(fds)
|
cleanupFds(fds)
|
||||||
return err
|
return err
|
||||||
@ -1409,6 +1475,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
|||||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||||
data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
|
data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
|
||||||
data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
|
data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
|
||||||
|
case *IPVtap:
|
||||||
|
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||||
|
data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
|
||||||
|
data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
|
||||||
case *Macvlan:
|
case *Macvlan:
|
||||||
if link.Mode != MACVLAN_MODE_DEFAULT {
|
if link.Mode != MACVLAN_MODE_DEFAULT {
|
||||||
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||||
@ -1443,6 +1513,8 @@ func (h *Handle) linkModify(link Link, flags int) error {
|
|||||||
addXfrmiAttrs(link, linkInfo)
|
addXfrmiAttrs(link, linkInfo)
|
||||||
case *IPoIB:
|
case *IPoIB:
|
||||||
addIPoIBAttrs(link, linkInfo)
|
addIPoIBAttrs(link, linkInfo)
|
||||||
|
case *BareUDP:
|
||||||
|
addBareUDPAttrs(link, linkInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.AddData(linkInfo)
|
req.AddData(linkInfo)
|
||||||
@ -1624,7 +1696,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// linkDeserialize deserializes a raw message received from netlink into
|
// LinkDeserialize deserializes a raw message received from netlink into
|
||||||
// a link object.
|
// a link object.
|
||||||
func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
||||||
msg := nl.DeserializeIfInfomsg(m)
|
msg := nl.DeserializeIfInfomsg(m)
|
||||||
@ -1639,9 +1711,17 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
|||||||
base.RawFlags = msg.Flags
|
base.RawFlags = msg.Flags
|
||||||
base.Flags = linkFlags(msg.Flags)
|
base.Flags = linkFlags(msg.Flags)
|
||||||
base.EncapType = msg.EncapType()
|
base.EncapType = msg.EncapType()
|
||||||
|
base.NetNsID = -1
|
||||||
if msg.Flags&unix.IFF_PROMISC != 0 {
|
if msg.Flags&unix.IFF_PROMISC != 0 {
|
||||||
base.Promisc = 1
|
base.Promisc = 1
|
||||||
}
|
}
|
||||||
|
if msg.Flags&unix.IFF_ALLMULTI != 0 {
|
||||||
|
base.Allmulti = 1
|
||||||
|
}
|
||||||
|
if msg.Flags&unix.IFF_MULTICAST != 0 {
|
||||||
|
base.Multi = 1
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
link Link
|
link Link
|
||||||
stats32 *LinkStatistics32
|
stats32 *LinkStatistics32
|
||||||
@ -1680,6 +1760,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
|||||||
link = &Bond{}
|
link = &Bond{}
|
||||||
case "ipvlan":
|
case "ipvlan":
|
||||||
link = &IPVlan{}
|
link = &IPVlan{}
|
||||||
|
case "ipvtap":
|
||||||
|
link = &IPVtap{}
|
||||||
case "macvlan":
|
case "macvlan":
|
||||||
link = &Macvlan{}
|
link = &Macvlan{}
|
||||||
case "macvtap":
|
case "macvtap":
|
||||||
@ -1714,6 +1796,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
|||||||
link = &IPoIB{}
|
link = &IPoIB{}
|
||||||
case "can":
|
case "can":
|
||||||
link = &Can{}
|
link = &Can{}
|
||||||
|
case "bareudp":
|
||||||
|
link = &BareUDP{}
|
||||||
default:
|
default:
|
||||||
link = &GenericLink{LinkType: linkType}
|
link = &GenericLink{LinkType: linkType}
|
||||||
}
|
}
|
||||||
@ -1731,6 +1815,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
|||||||
parseBondData(link, data)
|
parseBondData(link, data)
|
||||||
case "ipvlan":
|
case "ipvlan":
|
||||||
parseIPVlanData(link, data)
|
parseIPVlanData(link, data)
|
||||||
|
case "ipvtap":
|
||||||
|
parseIPVtapData(link, data)
|
||||||
case "macvlan":
|
case "macvlan":
|
||||||
parseMacvlanData(link, data)
|
parseMacvlanData(link, data)
|
||||||
case "macvtap":
|
case "macvtap":
|
||||||
@ -1767,13 +1853,19 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
|||||||
parseIPoIBData(link, data)
|
parseIPoIBData(link, data)
|
||||||
case "can":
|
case "can":
|
||||||
parseCanData(link, data)
|
parseCanData(link, data)
|
||||||
|
case "bareudp":
|
||||||
|
parseBareUDPData(link, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
case nl.IFLA_INFO_SLAVE_KIND:
|
case nl.IFLA_INFO_SLAVE_KIND:
|
||||||
slaveType = string(info.Value[:len(info.Value)-1])
|
slaveType = string(info.Value[:len(info.Value)-1])
|
||||||
switch slaveType {
|
switch slaveType {
|
||||||
case "bond":
|
case "bond":
|
||||||
linkSlave = &BondSlave{}
|
linkSlave = &BondSlave{}
|
||||||
|
case "vrf":
|
||||||
|
linkSlave = &VrfSlave{}
|
||||||
}
|
}
|
||||||
|
|
||||||
case nl.IFLA_INFO_SLAVE_DATA:
|
case nl.IFLA_INFO_SLAVE_DATA:
|
||||||
switch slaveType {
|
switch slaveType {
|
||||||
case "bond":
|
case "bond":
|
||||||
@ -1782,6 +1874,12 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
parseBondSlaveData(linkSlave, data)
|
parseBondSlaveData(linkSlave, data)
|
||||||
|
case "vrf":
|
||||||
|
data, err := nl.ParseRouteAttr(info.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
parseVrfSlaveData(linkSlave, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1835,6 +1933,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
|
|||||||
}
|
}
|
||||||
case unix.IFLA_OPERSTATE:
|
case unix.IFLA_OPERSTATE:
|
||||||
base.OperState = LinkOperState(uint8(attr.Value[0]))
|
base.OperState = LinkOperState(uint8(attr.Value[0]))
|
||||||
|
case unix.IFLA_PHYS_SWITCH_ID:
|
||||||
|
base.PhysSwitchID = int(native.Uint32(attr.Value[0:4]))
|
||||||
case unix.IFLA_LINK_NETNSID:
|
case unix.IFLA_LINK_NETNSID:
|
||||||
base.NetNsID = int(native.Uint32(attr.Value[0:4]))
|
base.NetNsID = int(native.Uint32(attr.Value[0:4]))
|
||||||
case unix.IFLA_GSO_MAX_SIZE:
|
case unix.IFLA_GSO_MAX_SIZE:
|
||||||
@ -2023,7 +2123,8 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
|
|||||||
msgs, from, err := s.Receive()
|
msgs, from, err := s.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(err)
|
cberr(fmt.Errorf("Receive failed: %v",
|
||||||
|
err))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -2038,15 +2139,15 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if m.Header.Type == unix.NLMSG_ERROR {
|
if m.Header.Type == unix.NLMSG_ERROR {
|
||||||
native := nl.NativeEndian()
|
|
||||||
error := int32(native.Uint32(m.Data[0:4]))
|
error := int32(native.Uint32(m.Data[0:4]))
|
||||||
if error == 0 {
|
if error == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(syscall.Errno(-error))
|
cberr(fmt.Errorf("error message: %v",
|
||||||
|
syscall.Errno(-error)))
|
||||||
}
|
}
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
ifmsg := nl.DeserializeIfInfomsg(m.Data)
|
ifmsg := nl.DeserializeIfInfomsg(m.Data)
|
||||||
header := unix.NlMsghdr(m.Header)
|
header := unix.NlMsghdr(m.Header)
|
||||||
@ -2055,7 +2156,7 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
|
|||||||
if cberr != nil {
|
if cberr != nil {
|
||||||
cberr(err)
|
cberr(err)
|
||||||
}
|
}
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link}
|
ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link}
|
||||||
}
|
}
|
||||||
@ -2404,6 +2505,16 @@ func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseVrfSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
|
||||||
|
vrfSlave := slave.(*VrfSlave)
|
||||||
|
for i := range data {
|
||||||
|
switch data[i].Attr.Type {
|
||||||
|
case nl.IFLA_BOND_SLAVE_STATE:
|
||||||
|
vrfSlave.Table = native.Uint32(data[i].Value[0:4])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
ipv := link.(*IPVlan)
|
ipv := link.(*IPVlan)
|
||||||
for _, datum := range data {
|
for _, datum := range data {
|
||||||
@ -2416,6 +2527,18 @@ func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
|
ipv := link.(*IPVtap)
|
||||||
|
for _, datum := range data {
|
||||||
|
switch datum.Attr.Type {
|
||||||
|
case nl.IFLA_IPVLAN_MODE:
|
||||||
|
ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
|
||||||
|
case nl.IFLA_IPVLAN_FLAG:
|
||||||
|
ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
|
func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
macv := link.(*Macvtap)
|
macv := link.(*Macvtap)
|
||||||
parseMacvlanData(&macv.Macvlan, data)
|
parseMacvlanData(&macv.Macvlan, data)
|
||||||
@ -2756,6 +2879,10 @@ func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
|
|||||||
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
|
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
iptun := link.(*Iptun)
|
iptun := link.(*Iptun)
|
||||||
for _, datum := range data {
|
for _, datum := range data {
|
||||||
|
// NOTE: same with vxlan, ip tunnel may also has null datum.Value
|
||||||
|
if len(datum.Value) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
switch datum.Attr.Type {
|
switch datum.Attr.Type {
|
||||||
case nl.IFLA_IPTUN_LOCAL:
|
case nl.IFLA_IPTUN_LOCAL:
|
||||||
iptun.Local = net.IP(datum.Value[0:4])
|
iptun.Local = net.IP(datum.Value[0:4])
|
||||||
@ -3303,3 +3430,32 @@ func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
|
|||||||
data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode)))
|
data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode)))
|
||||||
data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast)))
|
data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addBareUDPAttrs(bareudp *BareUDP, linkInfo *nl.RtAttr) {
|
||||||
|
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
|
||||||
|
|
||||||
|
data.AddRtAttr(nl.IFLA_BAREUDP_PORT, nl.Uint16Attr(nl.Swap16(bareudp.Port)))
|
||||||
|
data.AddRtAttr(nl.IFLA_BAREUDP_ETHERTYPE, nl.Uint16Attr(nl.Swap16(bareudp.EtherType)))
|
||||||
|
if bareudp.SrcPortMin != 0 {
|
||||||
|
data.AddRtAttr(nl.IFLA_BAREUDP_SRCPORT_MIN, nl.Uint16Attr(bareudp.SrcPortMin))
|
||||||
|
}
|
||||||
|
if bareudp.MultiProto {
|
||||||
|
data.AddRtAttr(nl.IFLA_BAREUDP_MULTIPROTO_MODE, []byte{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBareUDPData(link Link, data []syscall.NetlinkRouteAttr) {
|
||||||
|
bareudp := link.(*BareUDP)
|
||||||
|
for _, attr := range data {
|
||||||
|
switch attr.Attr.Type {
|
||||||
|
case nl.IFLA_BAREUDP_PORT:
|
||||||
|
bareudp.Port = binary.BigEndian.Uint16(attr.Value)
|
||||||
|
case nl.IFLA_BAREUDP_ETHERTYPE:
|
||||||
|
bareudp.EtherType = binary.BigEndian.Uint16(attr.Value)
|
||||||
|
case nl.IFLA_BAREUDP_SRCPORT_MIN:
|
||||||
|
bareudp.SrcPortMin = native.Uint16(attr.Value)
|
||||||
|
case nl.IFLA_BAREUDP_MULTIPROTO_MODE:
|
||||||
|
bareudp.MultiProto = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1
vendor/github.com/vishvananda/netlink/neigh.go
generated
vendored
1
vendor/github.com/vishvananda/netlink/neigh.go
generated
vendored
@ -12,6 +12,7 @@ type Neigh struct {
|
|||||||
State int
|
State int
|
||||||
Type int
|
Type int
|
||||||
Flags int
|
Flags int
|
||||||
|
FlagsExt int
|
||||||
IP net.IP
|
IP net.IP
|
||||||
HardwareAddr net.HardwareAddr
|
HardwareAddr net.HardwareAddr
|
||||||
LLIPAddr net.IP //Used in the case of NHRP
|
LLIPAddr net.IP //Used in the case of NHRP
|
||||||
|
34
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
34
vendor/github.com/vishvananda/netlink/neigh_linux.go
generated
vendored
@ -24,7 +24,11 @@ const (
|
|||||||
NDA_MASTER
|
NDA_MASTER
|
||||||
NDA_LINK_NETNSID
|
NDA_LINK_NETNSID
|
||||||
NDA_SRC_VNI
|
NDA_SRC_VNI
|
||||||
NDA_MAX = NDA_SRC_VNI
|
NDA_PROTOCOL
|
||||||
|
NDA_NH_ID
|
||||||
|
NDA_FDB_EXT_ATTRS
|
||||||
|
NDA_FLAGS_EXT
|
||||||
|
NDA_MAX = NDA_FLAGS_EXT
|
||||||
)
|
)
|
||||||
|
|
||||||
// Neighbor Cache Entry States.
|
// Neighbor Cache Entry States.
|
||||||
@ -42,11 +46,19 @@ const (
|
|||||||
|
|
||||||
// Neighbor Flags
|
// Neighbor Flags
|
||||||
const (
|
const (
|
||||||
NTF_USE = 0x01
|
NTF_USE = 0x01
|
||||||
NTF_SELF = 0x02
|
NTF_SELF = 0x02
|
||||||
NTF_MASTER = 0x04
|
NTF_MASTER = 0x04
|
||||||
NTF_PROXY = 0x08
|
NTF_PROXY = 0x08
|
||||||
NTF_ROUTER = 0x80
|
NTF_EXT_LEARNED = 0x10
|
||||||
|
NTF_OFFLOADED = 0x20
|
||||||
|
NTF_STICKY = 0x40
|
||||||
|
NTF_ROUTER = 0x80
|
||||||
|
)
|
||||||
|
|
||||||
|
// Extended Neighbor Flags
|
||||||
|
const (
|
||||||
|
NTF_EXT_MANAGED = 0x00000001
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ndmsg is for adding, removing or receiving information about a neighbor table entry
|
// Ndmsg is for adding, removing or receiving information about a neighbor table entry
|
||||||
@ -162,11 +174,16 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
|
|||||||
if neigh.LLIPAddr != nil {
|
if neigh.LLIPAddr != nil {
|
||||||
llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4())
|
llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4())
|
||||||
req.AddData(llIPData)
|
req.AddData(llIPData)
|
||||||
} else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
|
} else if neigh.HardwareAddr != nil {
|
||||||
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
|
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
|
||||||
req.AddData(hwData)
|
req.AddData(hwData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if neigh.FlagsExt != 0 {
|
||||||
|
flagsExtData := nl.NewRtAttr(NDA_FLAGS_EXT, nl.Uint32Attr(uint32(neigh.FlagsExt)))
|
||||||
|
req.AddData(flagsExtData)
|
||||||
|
}
|
||||||
|
|
||||||
if neigh.Vlan != 0 {
|
if neigh.Vlan != 0 {
|
||||||
vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan)))
|
vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan)))
|
||||||
req.AddData(vlanData)
|
req.AddData(vlanData)
|
||||||
@ -305,6 +322,8 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
|
|||||||
} else {
|
} else {
|
||||||
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
|
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
|
||||||
}
|
}
|
||||||
|
case NDA_FLAGS_EXT:
|
||||||
|
neigh.FlagsExt = int(native.Uint32(attr.Value[0:4]))
|
||||||
case NDA_VLAN:
|
case NDA_VLAN:
|
||||||
neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
|
neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
|
||||||
case NDA_VNI:
|
case NDA_VNI:
|
||||||
@ -408,7 +427,6 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if m.Header.Type == unix.NLMSG_ERROR {
|
if m.Header.Type == unix.NLMSG_ERROR {
|
||||||
native := nl.NativeEndian()
|
|
||||||
error := int32(native.Uint32(m.Data[0:4]))
|
error := int32(native.Uint32(m.Data[0:4]))
|
||||||
if error == 0 {
|
if error == 0 {
|
||||||
continue
|
continue
|
||||||
|
16
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
16
vendor/github.com/vishvananda/netlink/netlink_unspecified.go
generated
vendored
@ -180,14 +180,30 @@ func RouteAdd(route *Route) error {
|
|||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RouteAppend(route *Route) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func RouteDel(route *Route) error {
|
func RouteDel(route *Route) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RouteGet(destination net.IP) ([]Route, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func RouteList(link Link, family int) ([]Route, error) {
|
func RouteList(link Link, family int) ([]Route, error) {
|
||||||
return nil, ErrNotImplemented
|
return nil, ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func RouteReplace(route *Route) error {
|
||||||
|
return ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func XfrmPolicyAdd(policy *XfrmPolicy) error {
|
func XfrmPolicyAdd(policy *XfrmPolicy) error {
|
||||||
return ErrNotImplemented
|
return ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
6
vendor/github.com/vishvananda/netlink/netns_linux.go
generated
vendored
6
vendor/github.com/vishvananda/netlink/netns_linux.go
generated
vendored
@ -87,7 +87,7 @@ func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) {
|
|||||||
rtgen := nl.NewRtGenMsg()
|
rtgen := nl.NewRtGenMsg()
|
||||||
req.AddData(rtgen)
|
req.AddData(rtgen)
|
||||||
|
|
||||||
b := make([]byte, 4, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, val)
|
native.PutUint32(b, val)
|
||||||
attr := nl.NewRtAttr(attrType, b)
|
attr := nl.NewRtAttr(attrType, b)
|
||||||
req.AddData(attr)
|
req.AddData(attr)
|
||||||
@ -126,12 +126,12 @@ func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error {
|
|||||||
rtgen := nl.NewRtGenMsg()
|
rtgen := nl.NewRtGenMsg()
|
||||||
req.AddData(rtgen)
|
req.AddData(rtgen)
|
||||||
|
|
||||||
b := make([]byte, 4, 4)
|
b := make([]byte, 4)
|
||||||
native.PutUint32(b, val)
|
native.PutUint32(b, val)
|
||||||
attr := nl.NewRtAttr(attrType, b)
|
attr := nl.NewRtAttr(attrType, b)
|
||||||
req.AddData(attr)
|
req.AddData(attr)
|
||||||
|
|
||||||
b1 := make([]byte, 4, 4)
|
b1 := make([]byte, 4)
|
||||||
native.PutUint32(b1, newnsid)
|
native.PutUint32(b1, newnsid)
|
||||||
attr1 := nl.NewRtAttr(NETNSA_NSID, b1)
|
attr1 := nl.NewRtAttr(NETNSA_NSID, b1)
|
||||||
req.AddData(attr1)
|
req.AddData(attr1)
|
||||||
|
1
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
1
vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
generated
vendored
@ -44,6 +44,7 @@ const (
|
|||||||
NLA_F_NESTED uint16 = (1 << 15) // #define NLA_F_NESTED (1 << 15)
|
NLA_F_NESTED uint16 = (1 << 15) // #define NLA_F_NESTED (1 << 15)
|
||||||
NLA_F_NET_BYTEORDER uint16 = (1 << 14) // #define NLA_F_NESTED (1 << 14)
|
NLA_F_NET_BYTEORDER uint16 = (1 << 14) // #define NLA_F_NESTED (1 << 14)
|
||||||
NLA_TYPE_MASK = ^(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
|
NLA_TYPE_MASK = ^(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
|
||||||
|
NLA_ALIGNTO uint16 = 4 // #define NLA_ALIGNTO 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// enum ctattr_type {
|
// enum ctattr_type {
|
||||||
|
55
vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
generated
vendored
55
vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
generated
vendored
@ -11,22 +11,37 @@ const (
|
|||||||
const (
|
const (
|
||||||
DEVLINK_CMD_GET = 1
|
DEVLINK_CMD_GET = 1
|
||||||
DEVLINK_CMD_PORT_GET = 5
|
DEVLINK_CMD_PORT_GET = 5
|
||||||
|
DEVLINK_CMD_PORT_SET = 6
|
||||||
|
DEVLINK_CMD_PORT_NEW = 7
|
||||||
|
DEVLINK_CMD_PORT_DEL = 8
|
||||||
DEVLINK_CMD_ESWITCH_GET = 29
|
DEVLINK_CMD_ESWITCH_GET = 29
|
||||||
DEVLINK_CMD_ESWITCH_SET = 30
|
DEVLINK_CMD_ESWITCH_SET = 30
|
||||||
|
DEVLINK_CMD_INFO_GET = 51
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DEVLINK_ATTR_BUS_NAME = 1
|
DEVLINK_ATTR_BUS_NAME = 1
|
||||||
DEVLINK_ATTR_DEV_NAME = 2
|
DEVLINK_ATTR_DEV_NAME = 2
|
||||||
DEVLINK_ATTR_PORT_INDEX = 3
|
DEVLINK_ATTR_PORT_INDEX = 3
|
||||||
DEVLINK_ATTR_PORT_TYPE = 4
|
DEVLINK_ATTR_PORT_TYPE = 4
|
||||||
DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
|
DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
|
||||||
DEVLINK_ATTR_PORT_NETDEV_NAME = 7
|
DEVLINK_ATTR_PORT_NETDEV_NAME = 7
|
||||||
DEVLINK_ATTR_PORT_IBDEV_NAME = 8
|
DEVLINK_ATTR_PORT_IBDEV_NAME = 8
|
||||||
DEVLINK_ATTR_ESWITCH_MODE = 25
|
DEVLINK_ATTR_ESWITCH_MODE = 25
|
||||||
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
|
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
|
||||||
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
|
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
|
||||||
DEVLINK_ATTR_PORT_FLAVOUR = 77
|
DEVLINK_ATTR_PORT_FLAVOUR = 77
|
||||||
|
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
|
||||||
|
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
|
||||||
|
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
|
||||||
|
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
|
||||||
|
DEVLINK_ATTR_INFO_VERSION_STORED = 102
|
||||||
|
DEVLINK_ATTR_INFO_VERSION_NAME = 103
|
||||||
|
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
|
||||||
|
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
|
||||||
|
DEVLINK_ATTR_PORT_FUNCTION = 145
|
||||||
|
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
|
||||||
|
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -53,6 +68,8 @@ const (
|
|||||||
DEVLINK_PORT_FLAVOUR_PCI_PF = 3
|
DEVLINK_PORT_FLAVOUR_PCI_PF = 3
|
||||||
DEVLINK_PORT_FLAVOUR_PCI_VF = 4
|
DEVLINK_PORT_FLAVOUR_PCI_VF = 4
|
||||||
DEVLINK_PORT_FLAVOUR_VIRTUAL = 5
|
DEVLINK_PORT_FLAVOUR_VIRTUAL = 5
|
||||||
|
DEVLINK_PORT_FLAVOUR_UNUSED = 6
|
||||||
|
DEVLINK_PORT_FLAVOUR_PCI_SF = 7
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -61,3 +78,19 @@ const (
|
|||||||
DEVLINK_PORT_TYPE_ETH = 2
|
DEVLINK_PORT_TYPE_ETH = 2
|
||||||
DEVLINK_PORT_TYPE_IB = 3
|
DEVLINK_PORT_TYPE_IB = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR = 1
|
||||||
|
DEVLINK_PORT_FN_ATTR_STATE = 2
|
||||||
|
DEVLINK_PORT_FN_ATTR_OPSTATE = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEVLINK_PORT_FN_STATE_INACTIVE = 0
|
||||||
|
DEVLINK_PORT_FN_STATE_ACTIVE = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEVLINK_PORT_FN_OPSTATE_DETACHED = 0
|
||||||
|
DEVLINK_PORT_FN_OPSTATE_ATTACHED = 1
|
||||||
|
)
|
||||||
|
9
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
9
vendor/github.com/vishvananda/netlink/nl/link_linux.go
generated
vendored
@ -709,3 +709,12 @@ const (
|
|||||||
IFLA_CAN_BITRATE_MAX
|
IFLA_CAN_BITRATE_MAX
|
||||||
IFLA_CAN_MAX = IFLA_CAN_BITRATE_MAX
|
IFLA_CAN_MAX = IFLA_CAN_BITRATE_MAX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IFLA_BAREUDP_UNSPEC = iota
|
||||||
|
IFLA_BAREUDP_PORT
|
||||||
|
IFLA_BAREUDP_ETHERTYPE
|
||||||
|
IFLA_BAREUDP_SRCPORT_MIN
|
||||||
|
IFLA_BAREUDP_MULTIPROTO_MODE
|
||||||
|
IFLA_BAREUDP_MAX = IFLA_BAREUDP_MULTIPROTO_MODE
|
||||||
|
)
|
||||||
|
29
vendor/github.com/vishvananda/netlink/nl/lwt_linux.go
generated
vendored
Normal file
29
vendor/github.com/vishvananda/netlink/nl/lwt_linux.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package nl
|
||||||
|
|
||||||
|
const (
|
||||||
|
LWT_BPF_PROG_UNSPEC = iota
|
||||||
|
LWT_BPF_PROG_FD
|
||||||
|
LWT_BPF_PROG_NAME
|
||||||
|
__LWT_BPF_PROG_MAX
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LWT_BPF_PROG_MAX = __LWT_BPF_PROG_MAX - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LWT_BPF_UNSPEC = iota
|
||||||
|
LWT_BPF_IN
|
||||||
|
LWT_BPF_OUT
|
||||||
|
LWT_BPF_XMIT
|
||||||
|
LWT_BPF_XMIT_HEADROOM
|
||||||
|
__LWT_BPF_MAX
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LWT_BPF_MAX = __LWT_BPF_MAX - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LWT_BPF_MAX_HEADROOM = 256
|
||||||
|
)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user