Compare commits
83 Commits
Author | SHA1 | Date | |
---|---|---|---|
9b8de6a613 | |||
dacb671328 | |||
799d3cbf4c | |||
bd589992fb | |||
839d918e35 | |||
c50490eb76 | |||
01a8de9997 | |||
8a88f90f94 | |||
2b6cd5467f | |||
3aadb402e4 | |||
021462563b | |||
d713ec692c | |||
813f541d30 | |||
6eb8e31d21 | |||
051452cdcf | |||
877602d627 | |||
c90b165c6e | |||
28773dc925 | |||
2bd04cb92f | |||
d4775ecff5 | |||
e1f8f9bee5 | |||
68a80bcf9b | |||
1fb9793607 | |||
5cb3a5e897 | |||
b76fdd7c03 | |||
67175607ad | |||
b9560fd5c1 | |||
79192cb1f1 | |||
ad10b6fa91 | |||
219eb9e046 | |||
f7a2fc97e4 | |||
6957f6ca4e | |||
02bfece2e9 | |||
5af9ff493e | |||
44d92c19de | |||
5e0fbd8374 | |||
a78853f29f | |||
2d2583ee33 | |||
f4332fec59 | |||
ed16760739 | |||
30776ff858 | |||
2a48d68937 | |||
117e30ff21 | |||
486ef96e6f | |||
8a0e3fe10e | |||
ca419073e4 | |||
47a9fd80c8 | |||
112288ecb2 | |||
32fc3ee9d3 | |||
c7e2cf7602 | |||
53854dd948 | |||
5c512194eb | |||
a9b4e04bc4 | |||
f5c3d1b1ba | |||
8bf6a7b362 | |||
66e0aaf9c1 | |||
45fd949465 | |||
2ff84a481e | |||
37207f05b4 | |||
832f2699c2 | |||
d1360b82ab | |||
1f33fb729a | |||
754e153b03 | |||
0edf8a4208 | |||
db7e6cfabf | |||
963aaf86e6 | |||
cd9d6b28da | |||
0452c1dd10 | |||
d671d29ad5 | |||
cc6154603e | |||
62b36d2fbc | |||
e5fdd449dd | |||
8db5e4d41b | |||
ec8f6c99d0 | |||
7dea2a4c1b | |||
5a02c5bc61 | |||
bf8f171041 | |||
3603738c6a | |||
d8b1289098 | |||
6551165853 | |||
10a01b09ae | |||
497560f35f | |||
58dd90b996 |
@ -3,9 +3,8 @@ sudo: required
|
|||||||
dist: xenial
|
dist: xenial
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.11.x
|
|
||||||
- 1.12.x
|
|
||||||
- 1.13.x
|
- 1.13.x
|
||||||
|
- 1.14.x
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
@ -18,16 +17,17 @@ env:
|
|||||||
- TARGET=arm64
|
- TARGET=arm64
|
||||||
- TARGET=ppc64le
|
- TARGET=ppc64le
|
||||||
- TARGET=s390x
|
- TARGET=s390x
|
||||||
|
- TARGET=mips64le
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
include:
|
include:
|
||||||
- os: windows
|
- os: windows
|
||||||
env: TARGET=amd64
|
env: TARGET=amd64
|
||||||
go: 1.11.x
|
go: 1.13.x
|
||||||
- os: windows
|
- os: windows
|
||||||
env: TARGET=amd64
|
env: TARGET=amd64
|
||||||
go: 1.12.x
|
go: 1.14.x
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- go get github.com/onsi/ginkgo/ginkgo
|
- go get github.com/onsi/ginkgo/ginkgo
|
||||||
@ -35,6 +35,7 @@ install:
|
|||||||
- go get golang.org/x/tools/cmd/cover
|
- go get golang.org/x/tools/cmd/cover
|
||||||
- go get github.com/modocache/gover
|
- go get github.com/modocache/gover
|
||||||
- go get github.com/mattn/goveralls
|
- go get github.com/mattn/goveralls
|
||||||
|
- go mod vendor
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- |
|
- |
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
# Owners
|
# Owners
|
||||||
This is the official list of the CNI network plugins owners:
|
This is the official list of the CNI network plugins owners:
|
||||||
|
- Bruce Ma <brucema19901024@gmail.com> (@mars1024)
|
||||||
- Bryan Boreham <bryan@weave.works> (@bboreham)
|
- Bryan Boreham <bryan@weave.works> (@bboreham)
|
||||||
- Casey Callendrello <casey.callendrello@coreos.com> (@squeed)
|
- Casey Callendrello <cdc@redhat.com> (@squeed)
|
||||||
- Dan Williams <dcbw@redhat.com> (@dcbw)
|
- Dan Williams <dcbw@redhat.com> (@dcbw)
|
||||||
- Gabe Rosenhouse <grosenhouse@pivotal.io> (@rosenhouse)
|
- Gabe Rosenhouse <grosenhouse@pivotal.io> (@rosenhouse)
|
||||||
- Matt Dupre <matt@tigera.io> (@matthewdupre)
|
- Matt Dupre <matt@tigera.io> (@matthewdupre)
|
||||||
- Stefan Junker <stefan.junker@coreos.com> (@steveeJ)
|
- Michael Cambria <mcambria@redhat.com> (@mccv1r0)
|
||||||
|
- Piotr Skarmuk <piotr.skarmuk@gmail.com> (@jellonek)
|
||||||
|
@ -32,3 +32,11 @@ Read [CONTRIBUTING](CONTRIBUTING.md) for build and test instructions.
|
|||||||
|
|
||||||
### Sample
|
### Sample
|
||||||
The sample plugin provides an example for building your own plugin.
|
The sample plugin provides an example for building your own plugin.
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
For any questions about CNI, please reach out via:
|
||||||
|
- Email: [cni-dev](https://groups.google.com/forum/#!forum/cni-dev)
|
||||||
|
- Slack: #cni on the [CNCF slack](https://slack.cncf.io/).
|
||||||
|
|
||||||
|
If you have a _security_ issue to report, please do so privately to the email addresses listed in the [OWNERS](OWNERS.md) file.
|
||||||
|
18
Vagrantfile
vendored
18
Vagrantfile
vendored
@ -1,18 +0,0 @@
|
|||||||
# -*- mode: ruby -*-
|
|
||||||
# vi: set ft=ruby :
|
|
||||||
|
|
||||||
Vagrant.configure(2) do |config|
|
|
||||||
config.vm.box = "bento/ubuntu-16.04"
|
|
||||||
|
|
||||||
config.vm.synced_folder "..", "/go/src/github.com/containernetworking"
|
|
||||||
|
|
||||||
config.vm.provision "shell", inline: <<-SHELL
|
|
||||||
set -e -x -u
|
|
||||||
apt-get update -y || (sleep 40 && apt-get update -y)
|
|
||||||
apt-get install -y git gcc-multilib gcc-mingw-w64
|
|
||||||
wget -qO- https://storage.googleapis.com/golang/go1.12.7.linux-amd64.tar.gz | tar -C /usr/local -xz
|
|
||||||
echo 'export GOPATH=/go' >> /root/.bashrc
|
|
||||||
echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin' >> /root/.bashrc
|
|
||||||
cd /go/src/github.com/containernetworking/plugins
|
|
||||||
SHELL
|
|
||||||
end
|
|
13
go.mod
13
go.mod
@ -1,14 +1,14 @@
|
|||||||
module github.com/containernetworking/plugins
|
module github.com/containernetworking/plugins
|
||||||
|
|
||||||
go 1.12
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.4.11 // indirect
|
github.com/Microsoft/go-winio v0.4.11 // indirect
|
||||||
github.com/Microsoft/hcsshim v0.8.6
|
github.com/Microsoft/hcsshim v0.8.6
|
||||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae
|
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae
|
||||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44
|
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44
|
||||||
github.com/containernetworking/cni v0.7.1
|
github.com/containernetworking/cni v0.8.0
|
||||||
github.com/coreos/go-iptables v0.4.2
|
github.com/coreos/go-iptables v0.4.5
|
||||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7
|
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7
|
||||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c
|
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c
|
||||||
github.com/d2g/dhcp4client v1.0.0
|
github.com/d2g/dhcp4client v1.0.0
|
||||||
@ -17,10 +17,6 @@ require (
|
|||||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c
|
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c
|
||||||
github.com/golang/protobuf v1.3.1 // indirect
|
github.com/golang/protobuf v1.3.1 // indirect
|
||||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56
|
||||||
github.com/juju/errors v0.0.0-20180806074554-22422dad46e1
|
|
||||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
|
|
||||||
github.com/juju/testing v0.0.0-20190613124551-e81189438503 // indirect
|
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
|
||||||
github.com/mattn/go-shellwords v1.0.3
|
github.com/mattn/go-shellwords v1.0.3
|
||||||
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b
|
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b
|
||||||
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a
|
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a
|
||||||
@ -33,8 +29,5 @@ require (
|
|||||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 // indirect
|
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 // indirect
|
||||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f
|
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
|
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
|
||||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
|
||||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
|
||||||
)
|
)
|
||||||
|
26
go.sum
26
go.sum
@ -6,10 +6,10 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae h1:AMzIhMUq
|
|||||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44 h1:y853v6rXx+zefEcjET3JuKAqvhj+FKflQijjeaSv2iA=
|
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44 h1:y853v6rXx+zefEcjET3JuKAqvhj+FKflQijjeaSv2iA=
|
||||||
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/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE=
|
github.com/containernetworking/cni v0.8.0 h1:BT9lpgGoH4jw3lFC7Odz2prU5ruiYKcgAjMCbgybcKI=
|
||||||
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||||
github.com/coreos/go-iptables v0.4.2 h1:KH0EwId05JwWIfb96gWvkiT2cbuOu8ygqUaB+yPAwIg=
|
github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
|
||||||
github.com/coreos/go-iptables v0.4.2/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
|
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
|
||||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c h1:Xo2rK1pzOm0jO6abTPIQwbAmqBIOj132otexc1mmzFc=
|
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c h1:Xo2rK1pzOm0jO6abTPIQwbAmqBIOj132otexc1mmzFc=
|
||||||
@ -28,17 +28,6 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg
|
|||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56 h1:742eGXur0715JMq73aD95/FU0XpVKXqNuTnEfXsLOYQ=
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56 h1:742eGXur0715JMq73aD95/FU0XpVKXqNuTnEfXsLOYQ=
|
||||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||||
github.com/juju/errors v0.0.0-20180806074554-22422dad46e1 h1:wnhMXidtb70kDZCeLt/EfsVtkXS5c8zLnE9y/6DIRAU=
|
|
||||||
github.com/juju/errors v0.0.0-20180806074554-22422dad46e1/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
|
||||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI=
|
|
||||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
|
||||||
github.com/juju/testing v0.0.0-20190613124551-e81189438503 h1:ZUgTbk8oHgP0jpMieifGC9Lv47mHn8Pb3mFX3/Ew4iY=
|
|
||||||
github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/mattn/go-shellwords v1.0.3 h1:K/VxK7SZ+cvuPgFSLKi5QPI9Vr/ipOf4C1gN+ntueUk=
|
github.com/mattn/go-shellwords v1.0.3 h1:K/VxK7SZ+cvuPgFSLKi5QPI9Vr/ipOf4C1gN+ntueUk=
|
||||||
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||||
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b h1:Ey6yH0acn50T/v6CB75bGP4EMJqnv9WvnjN7oZaj+xE=
|
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b h1:Ey6yH0acn50T/v6CB75bGP4EMJqnv9WvnjN7oZaj+xE=
|
||||||
@ -66,12 +55,5 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v
|
|||||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
|
||||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
|
|
||||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
|
37
pkg/errors/errors.go
Normal file
37
pkg/errors/errors.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2020 CNI authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Annotate is used to add extra context to an existing error. The return will be
|
||||||
|
// a new error which carries error message from both context message and existing error.
|
||||||
|
func Annotate(err error, message string) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("%s: %v", message, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotatef is used to add extra context with args to an existing error. The return will be
|
||||||
|
// a new error which carries error message from both context message and existing error.
|
||||||
|
func Annotatef(err error, message string, args ...interface{}) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("%s: %v", fmt.Sprintf(message, args...), err)
|
||||||
|
}
|
96
pkg/errors/errors_test.go
Normal file
96
pkg/errors/errors_test.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2020 CNI authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAnnotate(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
existingErr error
|
||||||
|
contextMessage string
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"nil error",
|
||||||
|
nil,
|
||||||
|
"context",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"normal case",
|
||||||
|
errors.New("existing error"),
|
||||||
|
"context",
|
||||||
|
errors.New("context: existing error"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
if !reflect.DeepEqual(Annotatef(test.existingErr, test.contextMessage), test.expectedErr) {
|
||||||
|
t.Errorf("test case %s fails", test.name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAnnotatef(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
existingErr error
|
||||||
|
contextMessage string
|
||||||
|
contextArgs []interface{}
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"nil error",
|
||||||
|
nil,
|
||||||
|
"context",
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"normal case",
|
||||||
|
errors.New("existing error"),
|
||||||
|
"context",
|
||||||
|
nil,
|
||||||
|
errors.New("context: existing error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"normal case with args",
|
||||||
|
errors.New("existing error"),
|
||||||
|
"context %s %d",
|
||||||
|
[]interface{}{
|
||||||
|
"arg",
|
||||||
|
100,
|
||||||
|
},
|
||||||
|
errors.New("context arg 100: existing error"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
if !reflect.DeepEqual(Annotatef(test.existingErr, test.contextMessage, test.contextArgs...), test.expectedErr) {
|
||||||
|
t.Errorf("test case %s fails", test.name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -21,9 +21,10 @@ import (
|
|||||||
|
|
||||||
"github.com/Microsoft/hcsshim"
|
"github.com/Microsoft/hcsshim"
|
||||||
"github.com/Microsoft/hcsshim/hcn"
|
"github.com/Microsoft/hcsshim/hcn"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
"github.com/containernetworking/cni/pkg/types/current"
|
||||||
"github.com/juju/errors"
|
"github.com/containernetworking/plugins/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -64,14 +65,14 @@ func GenerateHnsEndpoint(epInfo *EndpointInfo, n *NetConf) (*hcsshim.HNSEndpoint
|
|||||||
// run the IPAM plugin and get back the config to apply
|
// run the IPAM plugin and get back the config to apply
|
||||||
hnsEndpoint, err := hcsshim.GetHNSEndpointByName(epInfo.EndpointName)
|
hnsEndpoint, err := hcsshim.GetHNSEndpointByName(epInfo.EndpointName)
|
||||||
if err != nil && !hcsshim.IsNotExist(err) {
|
if err != nil && !hcsshim.IsNotExist(err) {
|
||||||
return nil, errors.Annotatef(err, "Attempt to get endpoint \"%v\" failed", epInfo.EndpointName)
|
return nil, errors.Annotatef(err, "failed to get endpoint %q", epInfo.EndpointName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hnsEndpoint != nil {
|
if hnsEndpoint != nil {
|
||||||
if hnsEndpoint.VirtualNetwork != epInfo.NetworkId {
|
if hnsEndpoint.VirtualNetwork != epInfo.NetworkId {
|
||||||
_, err = hnsEndpoint.Delete()
|
_, err = hnsEndpoint.Delete()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "Failed to delete endpoint %v", epInfo.EndpointName)
|
return nil, errors.Annotatef(err, "failed to delete endpoint %s", epInfo.EndpointName)
|
||||||
}
|
}
|
||||||
hnsEndpoint = nil
|
hnsEndpoint = nil
|
||||||
}
|
}
|
||||||
@ -98,7 +99,7 @@ func GenerateHcnEndpoint(epInfo *EndpointInfo, n *NetConf) (*hcn.HostComputeEndp
|
|||||||
// run the IPAM plugin and get back the config to apply
|
// run the IPAM plugin and get back the config to apply
|
||||||
hcnEndpoint, err := hcn.GetEndpointByName(epInfo.EndpointName)
|
hcnEndpoint, err := hcn.GetEndpointByName(epInfo.EndpointName)
|
||||||
if err != nil && !hcn.IsNotFoundError(err) {
|
if err != nil && !hcn.IsNotFoundError(err) {
|
||||||
return nil, errors.Annotatef(err, "Attempt to get endpoint \"%v\" failed", epInfo.EndpointName)
|
return nil, errors.Annotatef(err, "failed to get endpoint %q", epInfo.EndpointName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hcnEndpoint != nil {
|
if hcnEndpoint != nil {
|
||||||
@ -108,12 +109,10 @@ func GenerateHcnEndpoint(epInfo *EndpointInfo, n *NetConf) (*hcn.HostComputeEndp
|
|||||||
if !strings.EqualFold(hcnEndpoint.HostComputeNetwork, epInfo.NetworkId) {
|
if !strings.EqualFold(hcnEndpoint.HostComputeNetwork, epInfo.NetworkId) {
|
||||||
err = hcnEndpoint.Delete()
|
err = hcnEndpoint.Delete()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "Failed to delete endpoint %v", epInfo.EndpointName)
|
return nil, errors.Annotatef(err, "failed to delete endpoint %s", epInfo.EndpointName)
|
||||||
hcnEndpoint = nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("Endpoint \"%v\" already exits", epInfo.EndpointName)
|
return nil, fmt.Errorf("endpoint %q already exits", epInfo.EndpointName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +269,7 @@ func AddHcnEndpoint(epName string, expectedNetworkId string, namespace string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "failed to Remove Endpoint after AddNamespaceEndpoint failure")
|
return nil, errors.Annotatef(err, "failed to Remove Endpoint after AddNamespaceEndpoint failure")
|
||||||
}
|
}
|
||||||
return nil, errors.Annotatef(err, "Failed to Add endpoint to namespace")
|
return nil, errors.Annotate(err, "failed to Add endpoint to namespace")
|
||||||
}
|
}
|
||||||
return hcnEndpoint, nil
|
return hcnEndpoint, nil
|
||||||
|
|
||||||
|
@ -20,10 +20,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim/hcn"
|
"github.com/Microsoft/hcsshim/hcn"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NetConf is the CNI spec
|
// NetConf is the CNI spec
|
||||||
@ -46,8 +47,16 @@ type RuntimeDNS struct {
|
|||||||
Search []string `json:"searches,omitempty"`
|
Search []string `json:"searches,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PortMapEntry struct {
|
||||||
|
HostPort int `json:"hostPort"`
|
||||||
|
ContainerPort int `json:"containerPort"`
|
||||||
|
Protocol string `json:"protocol"`
|
||||||
|
HostIP string `json:"hostIP,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type RuntimeConfig struct {
|
type RuntimeConfig struct {
|
||||||
DNS RuntimeDNS `json:"dns"`
|
DNS RuntimeDNS `json:"dns"`
|
||||||
|
PortMaps []PortMapEntry `json:"portMappings,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type policy struct {
|
type policy struct {
|
||||||
@ -207,3 +216,21 @@ func (n *NetConf) ApplyDefaultPAPolicy(paAddress string) {
|
|||||||
Value: []byte(`{"Type": "PA", "PA": "` + paAddress + `"}`),
|
Value: []byte(`{"Type": "PA", "PA": "` + paAddress + `"}`),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyPortMappingPolicy is used to configure HostPort<>ContainerPort mapping in HNS
|
||||||
|
func (n *NetConf) ApplyPortMappingPolicy(portMappings []PortMapEntry) {
|
||||||
|
if portMappings == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.Policies == nil {
|
||||||
|
n.Policies = make([]policy, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, portMapping := range portMappings {
|
||||||
|
n.Policies = append(n.Policies, policy{
|
||||||
|
Name: "EndpointPolicy",
|
||||||
|
Value: []byte(fmt.Sprintf(`{"Type": "NAT", "InternalPort": %d, "ExternalPort": %d, "Protocol": "%s"}`, portMapping.ContainerPort, portMapping.HostPort, portMapping.Protocol)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -128,6 +128,53 @@ var _ = Describe("HNS NetConf", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Describe("ApplyPortMappingPolicy", func() {
|
||||||
|
Context("when portMappings not activated", func() {
|
||||||
|
It("does nothing", func() {
|
||||||
|
n := NetConf{}
|
||||||
|
n.ApplyPortMappingPolicy(nil)
|
||||||
|
Expect(n.Policies).Should(BeNil())
|
||||||
|
|
||||||
|
n.ApplyPortMappingPolicy([]PortMapEntry{})
|
||||||
|
Expect(n.Policies).Should(HaveLen(0))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("when portMappings is activated", func() {
|
||||||
|
It("creates NAT policies", func() {
|
||||||
|
n := NetConf{}
|
||||||
|
n.ApplyPortMappingPolicy([]PortMapEntry{
|
||||||
|
{
|
||||||
|
ContainerPort: 80,
|
||||||
|
HostPort: 8080,
|
||||||
|
Protocol: "TCP",
|
||||||
|
HostIP: "ignored",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
Expect(n.Policies).Should(HaveLen(1))
|
||||||
|
|
||||||
|
policy := n.Policies[0]
|
||||||
|
Expect(policy.Name).Should(Equal("EndpointPolicy"))
|
||||||
|
|
||||||
|
value := make(map[string]interface{})
|
||||||
|
json.Unmarshal(policy.Value, &value)
|
||||||
|
|
||||||
|
Expect(value).Should(HaveKey("Type"))
|
||||||
|
Expect(value["Type"]).Should(Equal("NAT"))
|
||||||
|
|
||||||
|
Expect(value).Should(HaveKey("InternalPort"))
|
||||||
|
Expect(value["InternalPort"]).Should(Equal(float64(80)))
|
||||||
|
|
||||||
|
Expect(value).Should(HaveKey("ExternalPort"))
|
||||||
|
Expect(value["ExternalPort"]).Should(Equal(float64(8080)))
|
||||||
|
|
||||||
|
Expect(value).Should(HaveKey("Protocol"))
|
||||||
|
Expect(value["Protocol"]).Should(Equal("TCP"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Describe("MarshalPolicies", func() {
|
Describe("MarshalPolicies", func() {
|
||||||
Context("when not set by user", func() {
|
Context("when not set by user", func() {
|
||||||
It("sets it by adding a policy", func() {
|
It("sets it by adding a policy", func() {
|
||||||
|
@ -21,10 +21,12 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
|
||||||
"github.com/containernetworking/plugins/pkg/utils/hwaddr"
|
|
||||||
"github.com/safchain/ethtool"
|
"github.com/safchain/ethtool"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
"github.com/containernetworking/plugins/pkg/utils/hwaddr"
|
||||||
|
"github.com/containernetworking/plugins/pkg/utils/sysctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -158,6 +160,9 @@ func SetupVethWithName(contVethName, hostVethName string, mtu int, hostNS ns.Net
|
|||||||
if err = netlink.LinkSetUp(hostVeth); err != nil {
|
if err = netlink.LinkSetUp(hostVeth); err != nil {
|
||||||
return fmt.Errorf("failed to set %q up: %v", hostVethName, err)
|
return fmt.Errorf("failed to set %q up: %v", hostVethName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we want to own the routes for this interface
|
||||||
|
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", hostVethName), "0")
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -178,7 +183,7 @@ func SetupVeth(contVethName string, mtu int, hostNS ns.NetNS) (net.Interface, ne
|
|||||||
func DelLinkByName(ifName string) error {
|
func DelLinkByName(ifName string) error {
|
||||||
iface, err := netlink.LinkByName(ifName)
|
iface, err := netlink.LinkByName(ifName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "Link not found" {
|
if _, ok := err.(netlink.LinkNotFoundError); ok {
|
||||||
return ErrLinkNotFound
|
return ErrLinkNotFound
|
||||||
}
|
}
|
||||||
return fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
return fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
||||||
@ -195,7 +200,7 @@ func DelLinkByName(ifName string) error {
|
|||||||
func DelLinkByNameAddr(ifName string) ([]*net.IPNet, error) {
|
func DelLinkByNameAddr(ifName string) ([]*net.IPNet, error) {
|
||||||
iface, err := netlink.LinkByName(ifName)
|
iface, err := netlink.LinkByName(ifName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != nil && err.Error() == "Link not found" {
|
if _, ok := err.(netlink.LinkNotFoundError); ok {
|
||||||
return nil, ErrLinkNotFound
|
return nil, ErrLinkNotFound
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
return nil, fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
||||||
|
@ -26,6 +26,11 @@ import (
|
|||||||
|
|
||||||
// Returns an object representing the current OS thread's network namespace
|
// Returns an object representing the current OS thread's network namespace
|
||||||
func GetCurrentNS() (NetNS, error) {
|
func GetCurrentNS() (NetNS, error) {
|
||||||
|
// Lock the thread in case other goroutine executes in it and changes its
|
||||||
|
// network namespace after getCurrentThreadNetNSPath(), otherwise it might
|
||||||
|
// return an unexpected network namespace.
|
||||||
|
runtime.LockOSThread()
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
return GetNS(getCurrentThreadNetNSPath())
|
return GetNS(getCurrentThreadNetNSPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +183,16 @@ func (ns *netNS) Do(toRun func(NetNS) error) error {
|
|||||||
if err = ns.Set(); err != nil {
|
if err = ns.Set(); err != nil {
|
||||||
return fmt.Errorf("error switching to ns %v: %v", ns.file.Name(), err)
|
return fmt.Errorf("error switching to ns %v: %v", ns.file.Name(), err)
|
||||||
}
|
}
|
||||||
defer threadNS.Set() // switch back
|
defer func() {
|
||||||
|
err := threadNS.Set() // switch back
|
||||||
|
if err == nil {
|
||||||
|
// Unlock the current thread only when we successfully switched back
|
||||||
|
// to the original namespace; otherwise leave the thread locked which
|
||||||
|
// will force the runtime to scrap the current thread, that is maybe
|
||||||
|
// not as optimal but at least always safe to do.
|
||||||
|
runtime.UnlockOSThread()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
return toRun(hostNS)
|
return toRun(hostNS)
|
||||||
}
|
}
|
||||||
@ -193,6 +207,10 @@ func (ns *netNS) Do(toRun func(NetNS) error) error {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
|
// Start the callback in a new green thread so that if we later fail
|
||||||
|
// to switch the namespace back to the original one, we can safely
|
||||||
|
// leave the thread locked to die without a risk of the current thread
|
||||||
|
// left lingering with incorrect namespace.
|
||||||
var innerError error
|
var innerError error
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
"github.com/containernetworking/plugins/pkg/testutils"
|
"github.com/containernetworking/plugins/pkg/testutils"
|
||||||
@ -118,6 +119,33 @@ var _ = Describe("Linux namespace operations", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("when called concurrently", func() {
|
||||||
|
It("provides the original namespace as the argument to the callback", func() {
|
||||||
|
concurrency := 200
|
||||||
|
origNS, err := ns.GetCurrentNS()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
origNSInode, err := getInodeNS(origNS)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(concurrency)
|
||||||
|
for i := 0; i < concurrency; i++ {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
targetNetNS.Do(func(hostNS ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
hostNSInode, err := getInodeNS(hostNS)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(hostNSInode).To(Equal(origNSInode))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Context("when the callback returns an error", func() {
|
Context("when the callback returns an error", func() {
|
||||||
It("restores the calling thread to the original namespace before returning", func() {
|
It("restores the calling thread to the original namespace before returning", func() {
|
||||||
err := originalNetNS.Do(func(ns.NetNS) error {
|
err := originalNetNS.Do(func(ns.NetNS) error {
|
||||||
|
121
pkg/utils/iptables.go
Normal file
121
pkg/utils/iptables.go
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
// Copyright 2017 CNI authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/coreos/go-iptables/iptables"
|
||||||
|
)
|
||||||
|
|
||||||
|
const statusChainExists = 1
|
||||||
|
|
||||||
|
// EnsureChain idempotently creates the iptables chain. It does not
|
||||||
|
// return an error if the chain already exists.
|
||||||
|
func EnsureChain(ipt *iptables.IPTables, table, chain string) error {
|
||||||
|
if ipt == nil {
|
||||||
|
return errors.New("failed to ensure iptable chain: IPTables was nil")
|
||||||
|
}
|
||||||
|
exists, err := ChainExists(ipt, table, chain)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to list iptables chains: %v", err)
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
err = ipt.NewChain(table, chain)
|
||||||
|
if err != nil {
|
||||||
|
eerr, eok := err.(*iptables.Error)
|
||||||
|
if eok && eerr.ExitStatus() != statusChainExists {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainExists checks whether an iptables chain exists.
|
||||||
|
func ChainExists(ipt *iptables.IPTables, table, chain string) (bool, error) {
|
||||||
|
if ipt == nil {
|
||||||
|
return false, errors.New("failed to check iptable chain: IPTables was nil")
|
||||||
|
}
|
||||||
|
chains, err := ipt.ListChains(table)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ch := range chains {
|
||||||
|
if ch == chain {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRule idempotently delete the iptables rule in the specified table/chain.
|
||||||
|
// It does not return an error if the referring chain doesn't exist
|
||||||
|
func DeleteRule(ipt *iptables.IPTables, table, chain string, rulespec ...string) error {
|
||||||
|
if ipt == nil {
|
||||||
|
return errors.New("failed to ensure iptable chain: IPTables was nil")
|
||||||
|
}
|
||||||
|
if err := ipt.Delete(table, chain, rulespec...); err != nil {
|
||||||
|
eerr, eok := err.(*iptables.Error)
|
||||||
|
switch {
|
||||||
|
case eok && eerr.IsNotExist():
|
||||||
|
// swallow here, the chain was already deleted
|
||||||
|
return nil
|
||||||
|
case eok && eerr.ExitStatus() == 2:
|
||||||
|
// swallow here, invalid command line parameter because the referring rule is missing
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Failed to delete referring rule %s %s: %v", table, chain, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteChain idempotently deletes the specified table/chain.
|
||||||
|
// It does not return an errors if the chain does not exist
|
||||||
|
func DeleteChain(ipt *iptables.IPTables, table, chain string) error {
|
||||||
|
if ipt == nil {
|
||||||
|
return errors.New("failed to ensure iptable chain: IPTables was nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ipt.DeleteChain(table, chain)
|
||||||
|
eerr, eok := err.(*iptables.Error)
|
||||||
|
switch {
|
||||||
|
case eok && eerr.IsNotExist():
|
||||||
|
// swallow here, the chain was already deleted
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearChain idempotently clear the iptables rules in the specified table/chain.
|
||||||
|
// If the chain does not exist, a new one will be created
|
||||||
|
func ClearChain(ipt *iptables.IPTables, table, chain string) error {
|
||||||
|
if ipt == nil {
|
||||||
|
return errors.New("failed to ensure iptable chain: IPTables was nil")
|
||||||
|
}
|
||||||
|
err := ipt.ClearChain(table, chain)
|
||||||
|
eerr, eok := err.(*iptables.Error)
|
||||||
|
switch {
|
||||||
|
case eok && eerr.IsNotExist():
|
||||||
|
// swallow here, the chain was already deleted
|
||||||
|
return EnsureChain(ipt, table, chain)
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
97
pkg/utils/iptables_test.go
Normal file
97
pkg/utils/iptables_test.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2017-2018 CNI authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
"github.com/containernetworking/plugins/pkg/testutils"
|
||||||
|
"github.com/coreos/go-iptables/iptables"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
const TABLE = "filter" // We'll monkey around here
|
||||||
|
|
||||||
|
var _ = Describe("chain tests", func() {
|
||||||
|
var testChain string
|
||||||
|
var ipt *iptables.IPTables
|
||||||
|
var cleanup func()
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
|
||||||
|
// Save a reference to the original namespace,
|
||||||
|
// Add a new NS
|
||||||
|
currNs, err := ns.GetCurrentNS()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
testNs, err := testutils.NewNS()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
testChain = fmt.Sprintf("cni-test-%d", rand.Intn(10000000))
|
||||||
|
|
||||||
|
ipt, err = iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
runtime.LockOSThread()
|
||||||
|
err = testNs.Set()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
cleanup = func() {
|
||||||
|
if ipt == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ipt.ClearChain(TABLE, testChain)
|
||||||
|
ipt.DeleteChain(TABLE, testChain)
|
||||||
|
currNs.Set()
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
cleanup()
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("EnsureChain", func() {
|
||||||
|
It("creates chains idempotently", func() {
|
||||||
|
err := EnsureChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Create it again!
|
||||||
|
err = EnsureChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("DeleteChain", func() {
|
||||||
|
It("delete chains idempotently", func() {
|
||||||
|
// Create chain
|
||||||
|
err := EnsureChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Delete chain
|
||||||
|
err = DeleteChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Delete it again!
|
||||||
|
err = DeleteChain(ipt, TABLE, testChain)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
@ -35,7 +35,7 @@ func Sysctl(name string, params ...string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getSysctl(name string) (string, error) {
|
func getSysctl(name string) (string, error) {
|
||||||
fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1))
|
fullName := filepath.Join("/proc/sys", toNormalName(name))
|
||||||
fullName = filepath.Clean(fullName)
|
fullName = filepath.Clean(fullName)
|
||||||
data, err := ioutil.ReadFile(fullName)
|
data, err := ioutil.ReadFile(fullName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -46,7 +46,7 @@ func getSysctl(name string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setSysctl(name, value string) (string, error) {
|
func setSysctl(name, value string) (string, error) {
|
||||||
fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1))
|
fullName := filepath.Join("/proc/sys", toNormalName(name))
|
||||||
fullName = filepath.Clean(fullName)
|
fullName = filepath.Clean(fullName)
|
||||||
if err := ioutil.WriteFile(fullName, []byte(value), 0644); err != nil {
|
if err := ioutil.WriteFile(fullName, []byte(value), 0644); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -54,3 +54,27 @@ func setSysctl(name, value string) (string, error) {
|
|||||||
|
|
||||||
return getSysctl(name)
|
return getSysctl(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize names by using slash as separator
|
||||||
|
// Sysctl names can use dots or slashes as separator:
|
||||||
|
// - if dots are used, dots and slashes are interchanged.
|
||||||
|
// - if slashes are used, slashes and dots are left intact.
|
||||||
|
// Separator in use is determined by first occurrence.
|
||||||
|
func toNormalName(name string) string {
|
||||||
|
interchange := false
|
||||||
|
for _, c := range name {
|
||||||
|
if c == '.' {
|
||||||
|
interchange = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if c == '/' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if interchange {
|
||||||
|
r := strings.NewReplacer(".", "/", "/", ".")
|
||||||
|
return r.Replace(name)
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
114
pkg/utils/sysctl/sysctl_linux_test.go
Normal file
114
pkg/utils/sysctl/sysctl_linux_test.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// Copyright 2017-2020 CNI authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package sysctl_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
"github.com/containernetworking/plugins/pkg/testutils"
|
||||||
|
"github.com/containernetworking/plugins/pkg/utils/sysctl"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysctlDotKeyTemplate = "net.ipv4.conf.%s.proxy_arp"
|
||||||
|
sysctlSlashKeyTemplate = "net/ipv4/conf/%s/proxy_arp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Sysctl tests", func() {
|
||||||
|
var testIfaceName string
|
||||||
|
var cleanup func()
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
|
||||||
|
// Save a reference to the original namespace,
|
||||||
|
// Add a new NS
|
||||||
|
currNs, err := ns.GetCurrentNS()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
testNs, err := testutils.NewNS()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
testIfaceName = fmt.Sprintf("cnitest.%d", rand.Intn(100000))
|
||||||
|
testIface := &netlink.Dummy{
|
||||||
|
LinkAttrs: netlink.LinkAttrs{
|
||||||
|
Name: testIfaceName,
|
||||||
|
Namespace: netlink.NsFd(int(testNs.Fd())),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = netlink.LinkAdd(testIface)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
runtime.LockOSThread()
|
||||||
|
err = testNs.Set()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
cleanup = func() {
|
||||||
|
netlink.LinkDel(testIface)
|
||||||
|
currNs.Set()
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
cleanup()
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Sysctl", func() {
|
||||||
|
It("reads keys with dot separators", func() {
|
||||||
|
sysctlIfaceName := strings.Replace(testIfaceName, ".", "/", -1)
|
||||||
|
sysctlKey := fmt.Sprintf(sysctlDotKeyTemplate, sysctlIfaceName)
|
||||||
|
|
||||||
|
_, err := sysctl.Sysctl(sysctlKey)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Sysctl", func() {
|
||||||
|
It("reads keys with slash separators", func() {
|
||||||
|
sysctlKey := fmt.Sprintf(sysctlSlashKeyTemplate, testIfaceName)
|
||||||
|
|
||||||
|
_, err := sysctl.Sysctl(sysctlKey)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Sysctl", func() {
|
||||||
|
It("writes keys with dot separators", func() {
|
||||||
|
sysctlIfaceName := strings.Replace(testIfaceName, ".", "/", -1)
|
||||||
|
sysctlKey := fmt.Sprintf(sysctlDotKeyTemplate, sysctlIfaceName)
|
||||||
|
|
||||||
|
_, err := sysctl.Sysctl(sysctlKey, "1")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("Sysctl", func() {
|
||||||
|
It("writes keys with slash separators", func() {
|
||||||
|
sysctlKey := fmt.Sprintf(sysctlSlashKeyTemplate, testIfaceName)
|
||||||
|
|
||||||
|
_, err := sysctl.Sysctl(sysctlKey, "1")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
27
pkg/utils/sysctl/sysctl_suite_test.go
Normal file
27
pkg/utils/sysctl/sysctl_suite_test.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2017-2020 CNI authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package sysctl_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSysctl(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "Sysctl Suite")
|
||||||
|
}
|
@ -34,7 +34,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const listenFdsStart = 3
|
const listenFdsStart = 3
|
||||||
const resendCount = 3
|
|
||||||
|
|
||||||
var errNoMoreTries = errors.New("no more tries")
|
var errNoMoreTries = errors.New("no more tries")
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ import (
|
|||||||
// RFC 2131 suggests using exponential backoff, starting with 4sec
|
// RFC 2131 suggests using exponential backoff, starting with 4sec
|
||||||
// and randomized to +/- 1sec
|
// and randomized to +/- 1sec
|
||||||
const resendDelay0 = 4 * time.Second
|
const resendDelay0 = 4 * time.Second
|
||||||
const resendDelayMax = 32 * time.Second
|
const resendDelayMax = 62 * time.Second
|
||||||
|
|
||||||
const (
|
const (
|
||||||
leaseStateBound = iota
|
leaseStateBound = iota
|
||||||
@ -335,8 +335,9 @@ func jitter(span time.Duration) time.Duration {
|
|||||||
|
|
||||||
func backoffRetry(f func() (*dhcp4.Packet, error)) (*dhcp4.Packet, error) {
|
func backoffRetry(f func() (*dhcp4.Packet, error)) (*dhcp4.Packet, error) {
|
||||||
var baseDelay time.Duration = resendDelay0
|
var baseDelay time.Duration = resendDelay0
|
||||||
|
var sleepTime time.Duration
|
||||||
|
|
||||||
for i := 0; i < resendCount; i++ {
|
for {
|
||||||
pkt, err := f()
|
pkt, err := f()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return pkt, nil
|
return pkt, nil
|
||||||
@ -344,10 +345,16 @@ func backoffRetry(f func() (*dhcp4.Packet, error)) (*dhcp4.Packet, error) {
|
|||||||
|
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
|
|
||||||
time.Sleep(baseDelay + jitter(time.Second))
|
sleepTime = baseDelay + jitter(time.Second)
|
||||||
|
|
||||||
|
log.Printf("retrying in %f seconds", sleepTime.Seconds())
|
||||||
|
|
||||||
|
time.Sleep(sleepTime)
|
||||||
|
|
||||||
if baseDelay < resendDelayMax {
|
if baseDelay < resendDelayMax {
|
||||||
baseDelay *= 2
|
baseDelay *= 2
|
||||||
|
} else {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,17 +14,18 @@ If the bridge is missing, the plugin will create one on first use and, if gatewa
|
|||||||
## Example configuration
|
## Example configuration
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
"name": "mynet",
|
"cniVersion": "0.3.1",
|
||||||
"type": "bridge",
|
"name": "mynet",
|
||||||
"bridge": "mynet0",
|
"type": "bridge",
|
||||||
"isDefaultGateway": true,
|
"bridge": "mynet0",
|
||||||
"forceAddress": false,
|
"isDefaultGateway": true,
|
||||||
"ipMasq": true,
|
"forceAddress": false,
|
||||||
"hairpinMode": true,
|
"ipMasq": true,
|
||||||
"ipam": {
|
"hairpinMode": true,
|
||||||
"type": "host-local",
|
"ipam": {
|
||||||
"subnet": "10.10.0.0/16"
|
"type": "host-local",
|
||||||
}
|
"subnet": "10.10.0.0/16"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -32,10 +33,10 @@ If the bridge is missing, the plugin will create one on first use and, if gatewa
|
|||||||
```
|
```
|
||||||
{
|
{
|
||||||
"cniVersion": "0.3.1",
|
"cniVersion": "0.3.1",
|
||||||
"name": "mynet",
|
"name": "mynet",
|
||||||
"type": "bridge",
|
"type": "bridge",
|
||||||
"bridge": "mynet0",
|
"bridge": "mynet0",
|
||||||
"ipam": {}
|
"ipam": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/j-keck/arping"
|
"github.com/j-keck/arping"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
@ -35,6 +36,7 @@ import (
|
|||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
"github.com/containernetworking/plugins/pkg/utils"
|
"github.com/containernetworking/plugins/pkg/utils"
|
||||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
||||||
|
"github.com/containernetworking/plugins/pkg/utils/sysctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
// For testcases to force an error after IPAM has been performed
|
// For testcases to force an error after IPAM has been performed
|
||||||
@ -224,7 +226,9 @@ func ensureBridge(brName string, mtu int, promiscMode, vlanFiltering bool) (*net
|
|||||||
// default packet limit
|
// default packet limit
|
||||||
TxQLen: -1,
|
TxQLen: -1,
|
||||||
},
|
},
|
||||||
VlanFiltering: &vlanFiltering,
|
}
|
||||||
|
if vlanFiltering {
|
||||||
|
br.VlanFiltering = &vlanFiltering
|
||||||
}
|
}
|
||||||
|
|
||||||
err := netlink.LinkAdd(br)
|
err := netlink.LinkAdd(br)
|
||||||
@ -245,6 +249,9 @@ func ensureBridge(brName string, mtu int, promiscMode, vlanFiltering bool) (*net
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we want to own the routes for this interface
|
||||||
|
_, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", brName), "0")
|
||||||
|
|
||||||
if err := netlink.LinkSetUp(br); err != nil {
|
if err := netlink.LinkSetUp(br); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -442,11 +449,6 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
|
|
||||||
// Configure the container hardware address and IP address(es)
|
// Configure the container hardware address and IP address(es)
|
||||||
if err := netns.Do(func(_ ns.NetNS) error {
|
if err := netns.Do(func(_ ns.NetNS) error {
|
||||||
contVeth, err := net.InterfaceByName(args.IfName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable IPv6 DAD just in case hairpin mode is enabled on the
|
// Disable IPv6 DAD just in case hairpin mode is enabled on the
|
||||||
// bridge. Hairpin mode causes echos of neighbor solicitation
|
// bridge. Hairpin mode causes echos of neighbor solicitation
|
||||||
// packets, which causes DAD failures.
|
// packets, which causes DAD failures.
|
||||||
@ -463,8 +465,36 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
if err := ipam.ConfigureIface(args.IfName, result); err != nil {
|
if err := ipam.ConfigureIface(args.IfName, result); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check bridge port state
|
||||||
|
retries := []int{0, 50, 500, 1000, 1000}
|
||||||
|
for idx, sleep := range retries {
|
||||||
|
time.Sleep(time.Duration(sleep) * time.Millisecond)
|
||||||
|
|
||||||
|
hostVeth, err := netlink.LinkByName(hostInterface.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if hostVeth.Attrs().OperState == netlink.OperUp {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx == len(retries)-1 {
|
||||||
|
return fmt.Errorf("bridge port in error state: %s", hostVeth.Attrs().OperState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a gratuitous arp
|
||||||
|
if err := netns.Do(func(_ ns.NetNS) error {
|
||||||
|
contVeth, err := net.InterfaceByName(args.IfName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Send a gratuitous arp
|
|
||||||
for _, ipc := range result.IPs {
|
for _, ipc := range result.IPs {
|
||||||
if ipc.Version == "4" {
|
if ipc.Version == "4" {
|
||||||
_ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth)
|
_ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth)
|
||||||
|
@ -17,6 +17,9 @@ The device can be specified with any one of four properties:
|
|||||||
|
|
||||||
For this plugin, `CNI_IFNAME` will be ignored. Upon DEL, the device will be moved back.
|
For this plugin, `CNI_IFNAME` will be ignored. Upon DEL, the device will be moved back.
|
||||||
|
|
||||||
|
The plugin also supports the following [capability argument](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md):
|
||||||
|
* `deviceID`: A PCI address of the network device, e.g `0000:00:1f.6`
|
||||||
|
|
||||||
## Example configuration
|
## Example configuration
|
||||||
|
|
||||||
A sample configuration with `device` property looks like:
|
A sample configuration with `device` property looks like:
|
||||||
@ -38,3 +41,26 @@ A sample configuration with `pciBusID` property looks like:
|
|||||||
"pciBusID": "0000:3d:00.1"
|
"pciBusID": "0000:3d:00.1"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
A sample configuration utilizing `deviceID` runtime configuration looks like:
|
||||||
|
|
||||||
|
1. From operator perspective:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"type": "host-device",
|
||||||
|
"capabilities": {
|
||||||
|
"deviceID": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
2. From plugin perspective:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"type": "host-device",
|
||||||
|
"runtimeConfig": {
|
||||||
|
"deviceID": "0000:3d:00.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -46,10 +46,13 @@ const (
|
|||||||
//NetConf for host-device config, look the README to learn how to use those parameters
|
//NetConf for host-device config, look the README to learn how to use those parameters
|
||||||
type NetConf struct {
|
type NetConf struct {
|
||||||
types.NetConf
|
types.NetConf
|
||||||
Device string `json:"device"` // Device-Name, something like eth0 or can0 etc.
|
Device string `json:"device"` // Device-Name, something like eth0 or can0 etc.
|
||||||
HWAddr string `json:"hwaddr"` // MAC Address of target network interface
|
HWAddr string `json:"hwaddr"` // MAC Address of target network interface
|
||||||
KernelPath string `json:"kernelpath"` // Kernelpath of the device
|
KernelPath string `json:"kernelpath"` // Kernelpath of the device
|
||||||
PCIAddr string `json:"pciBusID"` // PCI Address of target network device
|
PCIAddr string `json:"pciBusID"` // PCI Address of target network device
|
||||||
|
RuntimeConfig struct {
|
||||||
|
DeviceID string `json:"deviceID,omitempty"`
|
||||||
|
} `json:"runtimeConfig,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -64,9 +67,16 @@ func loadConf(bytes []byte) (*NetConf, error) {
|
|||||||
if err := json.Unmarshal(bytes, n); err != nil {
|
if err := json.Unmarshal(bytes, n); err != nil {
|
||||||
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n.RuntimeConfig.DeviceID != "" {
|
||||||
|
// Override PCI device with the standardized DeviceID provided in Runtime Config.
|
||||||
|
n.PCIAddr = n.RuntimeConfig.DeviceID
|
||||||
|
}
|
||||||
|
|
||||||
if n.Device == "" && n.HWAddr == "" && n.KernelPath == "" && n.PCIAddr == "" {
|
if n.Device == "" && n.HWAddr == "" && n.KernelPath == "" && n.PCIAddr == "" {
|
||||||
return nil, fmt.Errorf(`specify either "device", "hwaddr", "kernelpath" or "pciBusID"`)
|
return nil, fmt.Errorf(`specify either "device", "hwaddr", "kernelpath" or "pciBusID"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,6 +193,10 @@ func moveLinkIn(hostDev netlink.Link, containerNs ns.NetNS, ifName string) (netl
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to find %q: %v", hostDev.Attrs().Name, err)
|
return fmt.Errorf("failed to find %q: %v", hostDev.Attrs().Name, err)
|
||||||
}
|
}
|
||||||
|
// Devices can be renamed only when down
|
||||||
|
if err = netlink.LinkSetDown(contDev); err != nil {
|
||||||
|
return fmt.Errorf("failed to set %q down: %v", hostDev.Attrs().Name, err)
|
||||||
|
}
|
||||||
// Save host device name into the container device's alias property
|
// Save host device name into the container device's alias property
|
||||||
if err := netlink.LinkSetAlias(contDev, hostDev.Attrs().Name); err != nil {
|
if err := netlink.LinkSetAlias(contDev, hostDev.Attrs().Name); err != nil {
|
||||||
return fmt.Errorf("failed to set alias to %q: %v", hostDev.Attrs().Name, err)
|
return fmt.Errorf("failed to set alias to %q: %v", hostDev.Attrs().Name, err)
|
||||||
@ -296,7 +310,12 @@ func getLink(devname, hwaddr, kernelpath, pciaddr string) (netlink.Link, error)
|
|||||||
} else if len(pciaddr) > 0 {
|
} else if len(pciaddr) > 0 {
|
||||||
netDir := filepath.Join(sysBusPCI, pciaddr, "net")
|
netDir := filepath.Join(sysBusPCI, pciaddr, "net")
|
||||||
if _, err := os.Lstat(netDir); err != nil {
|
if _, err := os.Lstat(netDir); err != nil {
|
||||||
return nil, fmt.Errorf("no net directory under pci device %s: %q", pciaddr, err)
|
virtioNetDir := filepath.Join(sysBusPCI, pciaddr, "virtio*", "net")
|
||||||
|
matches, err := filepath.Glob(virtioNetDir)
|
||||||
|
if matches == nil || err != nil {
|
||||||
|
return nil, fmt.Errorf("no net directory under pci device %s", pciaddr)
|
||||||
|
}
|
||||||
|
netDir = matches[0]
|
||||||
}
|
}
|
||||||
fInfo, err := ioutil.ReadDir(netDir)
|
fInfo, err := ioutil.ReadDir(netDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -68,6 +68,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err // not tested
|
return err // not tested
|
||||||
}
|
}
|
||||||
|
|
||||||
v4Addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
|
v4Addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err // not tested
|
return err // not tested
|
||||||
@ -89,7 +90,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
if len(v6Addrs) != 0 {
|
if len(v6Addrs) != 0 {
|
||||||
v6Addr = v6Addrs[0].IPNet
|
v6Addr = v6Addrs[0].IPNet
|
||||||
// sanity check that this is a loopback address
|
// sanity check that this is a loopback address
|
||||||
for _, addr := range v4Addrs {
|
for _, addr := range v6Addrs {
|
||||||
if !addr.IP.IsLoopback() {
|
if !addr.IP.IsLoopback() {
|
||||||
return fmt.Errorf("loopback interface found with non-loopback address %q", addr.IP)
|
return fmt.Errorf("loopback interface found with non-loopback address %q", addr.IP)
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ var _ = Describe("Loopback", func() {
|
|||||||
environ = []string{
|
environ = []string{
|
||||||
fmt.Sprintf("CNI_CONTAINERID=%s", "dummy"),
|
fmt.Sprintf("CNI_CONTAINERID=%s", "dummy"),
|
||||||
fmt.Sprintf("CNI_NETNS=%s", networkNS.Path()),
|
fmt.Sprintf("CNI_NETNS=%s", networkNS.Path()),
|
||||||
fmt.Sprintf("CNI_IFNAME=%s", "this is ignored"),
|
fmt.Sprintf("CNI_IFNAME=%s", "lo"),
|
||||||
fmt.Sprintf("CNI_ARGS=%s", "none"),
|
fmt.Sprintf("CNI_ARGS=%s", "none"),
|
||||||
fmt.Sprintf("CNI_PATH=%s", "/some/test/path"),
|
fmt.Sprintf("CNI_PATH=%s", "/some/test/path"),
|
||||||
}
|
}
|
||||||
|
@ -30,5 +30,5 @@ Since each macvlan interface has its own MAC address, it makes it easy to use wi
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
* If are testing on a laptop, please remember that most wireless cards do not support being enslaved by macvlan.
|
* If you are testing on a laptop, please remember that most wireless cards do not support being enslaved by macvlan.
|
||||||
* A single master interface can not be enslaved by both `macvlan` and `ipvlan`.
|
* A single master interface can not be enslaved by both `macvlan` and `ipvlan`.
|
||||||
|
@ -45,6 +45,17 @@ type NetConf struct {
|
|||||||
Master string `json:"master"`
|
Master string `json:"master"`
|
||||||
Mode string `json:"mode"`
|
Mode string `json:"mode"`
|
||||||
MTU int `json:"mtu"`
|
MTU int `json:"mtu"`
|
||||||
|
Mac string `json:"mac,omitempty"`
|
||||||
|
|
||||||
|
RuntimeConfig struct {
|
||||||
|
Mac string `json:"mac,omitempty"`
|
||||||
|
} `json:"runtimeConfig,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MacEnvArgs represents CNI_ARG
|
||||||
|
type MacEnvArgs struct {
|
||||||
|
types.CommonArgs
|
||||||
|
MAC types.UnmarshallableString `json:"mac,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -73,7 +84,7 @@ func getDefaultRouteInterfaceName() (string, error) {
|
|||||||
return "", fmt.Errorf("no default route interface found")
|
return "", fmt.Errorf("no default route interface found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConf(bytes []byte) (*NetConf, string, error) {
|
func loadConf(bytes []byte, envArgs string) (*NetConf, string, error) {
|
||||||
n := &NetConf{}
|
n := &NetConf{}
|
||||||
if err := json.Unmarshal(bytes, n); err != nil {
|
if err := json.Unmarshal(bytes, n); err != nil {
|
||||||
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
|
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
|
||||||
@ -95,6 +106,22 @@ func loadConf(bytes []byte) (*NetConf, string, error) {
|
|||||||
return nil, "", fmt.Errorf("invalid MTU %d, must be [0, master MTU(%d)]", n.MTU, masterMTU)
|
return nil, "", fmt.Errorf("invalid MTU %d, must be [0, master MTU(%d)]", n.MTU, masterMTU)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if envArgs != "" {
|
||||||
|
e := MacEnvArgs{}
|
||||||
|
err := types.LoadArgs(envArgs, &e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.MAC != "" {
|
||||||
|
n.Mac = string(e.MAC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.RuntimeConfig.Mac != "" {
|
||||||
|
n.Mac = n.RuntimeConfig.Mac
|
||||||
|
}
|
||||||
|
|
||||||
return n, n.CNIVersion, nil
|
return n, n.CNIVersion, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,14 +183,24 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
linkAttrs := netlink.LinkAttrs{
|
||||||
|
MTU: conf.MTU,
|
||||||
|
Name: tmpName,
|
||||||
|
ParentIndex: m.Attrs().Index,
|
||||||
|
Namespace: netlink.NsFd(int(netns.Fd())),
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Mac != "" {
|
||||||
|
addr, err := net.ParseMAC(conf.Mac)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid args %v for MAC addr: %v", conf.Mac, err)
|
||||||
|
}
|
||||||
|
linkAttrs.HardwareAddr = addr
|
||||||
|
}
|
||||||
|
|
||||||
mv := &netlink.Macvlan{
|
mv := &netlink.Macvlan{
|
||||||
LinkAttrs: netlink.LinkAttrs{
|
LinkAttrs: linkAttrs,
|
||||||
MTU: conf.MTU,
|
Mode: mode,
|
||||||
Name: tmpName,
|
|
||||||
ParentIndex: m.Attrs().Index,
|
|
||||||
Namespace: netlink.NsFd(int(netns.Fd())),
|
|
||||||
},
|
|
||||||
Mode: mode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := netlink.LinkAdd(mv); err != nil {
|
if err := netlink.LinkAdd(mv); err != nil {
|
||||||
@ -204,7 +241,7 @@ func createMacvlan(conf *NetConf, ifName string, netns ns.NetNS) (*current.Inter
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
func cmdAdd(args *skel.CmdArgs) error {
|
||||||
n, cniVersion, err := loadConf(args.StdinData)
|
n, cniVersion, err := loadConf(args.StdinData, args.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -311,7 +348,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cmdDel(args *skel.CmdArgs) error {
|
func cmdDel(args *skel.CmdArgs) error {
|
||||||
n, _, err := loadConf(args.StdinData)
|
n, _, err := loadConf(args.StdinData, args.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -349,7 +386,7 @@ func main() {
|
|||||||
|
|
||||||
func cmdCheck(args *skel.CmdArgs) error {
|
func cmdCheck(args *skel.CmdArgs) error {
|
||||||
|
|
||||||
n, _, err := loadConf(args.StdinData)
|
n, _, err := loadConf(args.StdinData, args.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -594,4 +594,176 @@ var _ = Describe("macvlan Operations", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures l2 macvlan link with mac address (from CNI_ARGS) with CNI v4 ADD/DEL", func() {
|
||||||
|
const IFNAME = "macvl0"
|
||||||
|
|
||||||
|
conf := fmt.Sprintf(`{
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"name": "mynet",
|
||||||
|
"type": "macvlan",
|
||||||
|
"master": "%s",
|
||||||
|
"ipam": {}
|
||||||
|
}`, MASTER_NAME)
|
||||||
|
|
||||||
|
targetNs, err := testutils.NewNS()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
defer targetNs.Close()
|
||||||
|
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "dummy",
|
||||||
|
Netns: targetNs.Path(),
|
||||||
|
IfName: IFNAME,
|
||||||
|
StdinData: []byte(conf),
|
||||||
|
Args: "IgnoreUnknown=true;MAC=c2:11:22:33:44:55",
|
||||||
|
}
|
||||||
|
|
||||||
|
var result *current.Result
|
||||||
|
err = originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||||
|
return cmdAdd(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err = current.GetResult(r)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(len(result.Interfaces)).To(Equal(1))
|
||||||
|
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||||
|
Expect(len(result.IPs)).To(Equal(0))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Make sure macvlan link exists in the target namespace
|
||||||
|
err = targetNs.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(IFNAME)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||||
|
|
||||||
|
hwaddr, err := net.ParseMAC("c2:11:22:33:44:55")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||||
|
|
||||||
|
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(addrs)).To(Equal(0))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
err = originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
err := testutils.CmdDelWithArgs(args, func() error {
|
||||||
|
return cmdDel(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Make sure macvlan link has been deleted
|
||||||
|
err = targetNs.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(IFNAME)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(link).To(BeNil())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures l2 macvlan link with mac address (from RuntimeConfig) with ADD/DEL", func() {
|
||||||
|
const IFNAME = "macvl0"
|
||||||
|
|
||||||
|
conf := fmt.Sprintf(`{
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"capabilities": {"mac": true},
|
||||||
|
"RuntimeConfig": {
|
||||||
|
"mac": "c2:11:22:33:44:55"
|
||||||
|
},
|
||||||
|
"name": "mynet",
|
||||||
|
"type": "macvlan",
|
||||||
|
"master": "%s",
|
||||||
|
"ipam": {}
|
||||||
|
}`, MASTER_NAME)
|
||||||
|
|
||||||
|
targetNs, err := testutils.NewNS()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
defer targetNs.Close()
|
||||||
|
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "dummy",
|
||||||
|
Netns: targetNs.Path(),
|
||||||
|
IfName: IFNAME,
|
||||||
|
StdinData: []byte(conf),
|
||||||
|
}
|
||||||
|
|
||||||
|
var result *current.Result
|
||||||
|
err = originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||||
|
return cmdAdd(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err = current.GetResult(r)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(len(result.Interfaces)).To(Equal(1))
|
||||||
|
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||||
|
Expect(len(result.IPs)).To(Equal(0))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Make sure macvlan link exists in the target namespace
|
||||||
|
err = targetNs.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(IFNAME)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||||
|
|
||||||
|
hwaddr, err := net.ParseMAC("c2:11:22:33:44:55")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||||
|
|
||||||
|
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(addrs)).To(Equal(0))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
err = originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
err := testutils.CmdDelWithArgs(args, func() error {
|
||||||
|
return cmdDel(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Make sure macvlan link has been deleted
|
||||||
|
err = targetNs.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(IFNAME)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(link).To(BeNil())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -228,7 +228,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
defer netns.Close()
|
defer netns.Close()
|
||||||
|
|
||||||
hostInterface, containerInterface, err := setupContainerVeth(netns, args.IfName, conf.MTU, result)
|
hostInterface, _, err := setupContainerVeth(netns, args.IfName, conf.MTU, result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -254,8 +254,6 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
result.DNS = conf.DNS
|
result.DNS = conf.DNS
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Interfaces = []*current.Interface{hostInterface, containerInterface}
|
|
||||||
|
|
||||||
return types.PrintResult(result, conf.CNIVersion)
|
return types.PrintResult(result, conf.CNIVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
|
|
||||||
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
||||||
err = ip.DelLinkByName(args.IfName)
|
err = ip.DelLinkByName(args.IfName)
|
||||||
if err != nil && err != ip.ErrLinkNotFound {
|
if err != nil && err == ip.ErrLinkNotFound {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -292,6 +292,19 @@ var _ = Describe("vlan Operations", func() {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// DEL can be called multiple times, make sure no error is returned
|
||||||
|
// if the device is already removed.
|
||||||
|
err = originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
err = testutils.CmdDelWithArgs(args, func() error {
|
||||||
|
return cmdDel(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("configures and deconfigures an CNI V4 vlan link with ADD/CHECK/DEL", func() {
|
It("configures and deconfigures an CNI V4 vlan link with ADD/CHECK/DEL", func() {
|
||||||
|
@ -35,7 +35,8 @@ With win-bridge plugin, all containers (on the same host) are plugged into an L2
|
|||||||
],
|
],
|
||||||
"loopbackDSR": true,
|
"loopbackDSR": true,
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"dns": true
|
"dns": true,
|
||||||
|
"portMappings": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -55,3 +56,4 @@ With win-bridge plugin, all containers (on the same host) are plugged into an L2
|
|||||||
* `loopbackDSR` (bool, optional): If true, will add a policy to allow the interface to support loopback direct server return.
|
* `loopbackDSR` (bool, optional): If true, will add a policy to allow the interface to support loopback direct server return.
|
||||||
* `capabilities` (dictionary, optional): Runtime capabilities to enable.
|
* `capabilities` (dictionary, optional): Runtime capabilities to enable.
|
||||||
* `dns` (boolean, optional): If true, will take the dns config supplied by the runtime and override other settings.
|
* `dns` (boolean, optional): If true, will take the dns config supplied by the runtime and override other settings.
|
||||||
|
* `portMappings` (boolean, optional): If true, will handle HostPort<>ContainerPort mapping using NAT HNS Policies
|
@ -22,13 +22,13 @@ import (
|
|||||||
|
|
||||||
"github.com/Microsoft/hcsshim"
|
"github.com/Microsoft/hcsshim"
|
||||||
"github.com/Microsoft/hcsshim/hcn"
|
"github.com/Microsoft/hcsshim/hcn"
|
||||||
"github.com/juju/errors"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
"github.com/containernetworking/cni/pkg/skel"
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
"github.com/containernetworking/cni/pkg/types/current"
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/errors"
|
||||||
"github.com/containernetworking/plugins/pkg/hns"
|
"github.com/containernetworking/plugins/pkg/hns"
|
||||||
"github.com/containernetworking/plugins/pkg/ipam"
|
"github.com/containernetworking/plugins/pkg/ipam"
|
||||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
||||||
@ -72,7 +72,7 @@ func ProcessEndpointArgs(args *skel.CmdArgs, n *NetConf) (*hns.EndpointInfo, err
|
|||||||
return nil, errors.Annotatef(err, "error while NewResultFromResult")
|
return nil, errors.Annotatef(err, "error while NewResultFromResult")
|
||||||
} else {
|
} else {
|
||||||
if len(result.IPs) == 0 {
|
if len(result.IPs) == 0 {
|
||||||
return nil, errors.New("IPAM plugin return is missing IP config")
|
return nil, fmt.Errorf("IPAM plugin return is missing IP config")
|
||||||
}
|
}
|
||||||
epInfo.IpAddress = result.IPs[0].Address.IP
|
epInfo.IpAddress = result.IPs[0].Address.IP
|
||||||
epInfo.Gateway = result.IPs[0].Address.IP.Mask(result.IPs[0].Address.Mask)
|
epInfo.Gateway = result.IPs[0].Address.IP.Mask(result.IPs[0].Address.Mask)
|
||||||
@ -86,6 +86,9 @@ func ProcessEndpointArgs(args *skel.CmdArgs, n *NetConf) (*hns.EndpointInfo, err
|
|||||||
n.ApplyOutboundNatPolicy(n.IPMasqNetwork)
|
n.ApplyOutboundNatPolicy(n.IPMasqNetwork)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add HostPort mapping if any present
|
||||||
|
n.ApplyPortMappingPolicy(n.RuntimeConfig.PortMaps)
|
||||||
|
|
||||||
epInfo.DNS = n.GetDNS()
|
epInfo.DNS = n.GetDNS()
|
||||||
|
|
||||||
return epInfo, nil
|
return epInfo, nil
|
||||||
@ -107,7 +110,6 @@ func cmdHnsAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
epName := hns.ConstructEndpointName(args.ContainerID, args.Netns, n.Name)
|
epName := hns.ConstructEndpointName(args.ContainerID, args.Netns, n.Name)
|
||||||
|
|
||||||
hnsEndpoint, err := hns.ProvisionEndpoint(epName, hnsNetwork.Id, args.ContainerID, args.Netns, func() (*hcsshim.HNSEndpoint, error) {
|
hnsEndpoint, err := hns.ProvisionEndpoint(epName, hnsNetwork.Id, args.ContainerID, args.Netns, func() (*hcsshim.HNSEndpoint, error) {
|
||||||
epInfo, err := ProcessEndpointArgs(args, n)
|
epInfo, err := ProcessEndpointArgs(args, n)
|
||||||
epInfo.NetworkId = hnsNetwork.Id
|
epInfo.NetworkId = hnsNetwork.Id
|
||||||
@ -130,7 +132,6 @@ func cmdHnsAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdHcnAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) {
|
func cmdHcnAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) {
|
||||||
@ -194,7 +195,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if result == nil {
|
if result == nil {
|
||||||
return errors.New("result for ADD not populated correctly")
|
return fmt.Errorf("result for ADD not populated correctly")
|
||||||
}
|
}
|
||||||
return types.PrintResult(result, cniVersion)
|
return types.PrintResult(result, cniVersion)
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim"
|
"github.com/Microsoft/hcsshim"
|
||||||
"github.com/juju/errors"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
"github.com/containernetworking/cni/pkg/skel"
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
"github.com/containernetworking/cni/pkg/types/current"
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/errors"
|
||||||
"github.com/containernetworking/plugins/pkg/hns"
|
"github.com/containernetworking/plugins/pkg/hns"
|
||||||
"github.com/containernetworking/plugins/pkg/ipam"
|
"github.com/containernetworking/plugins/pkg/ipam"
|
||||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
||||||
@ -100,12 +100,12 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(result.IPs) == 0 {
|
if len(result.IPs) == 0 {
|
||||||
return nil, errors.New("IPAM plugin return is missing IP config")
|
return nil, fmt.Errorf("IPAM plugin return is missing IP config")
|
||||||
}
|
}
|
||||||
|
|
||||||
ipAddr := result.IPs[0].Address.IP.To4()
|
ipAddr := result.IPs[0].Address.IP.To4()
|
||||||
if ipAddr == nil {
|
if ipAddr == nil {
|
||||||
return nil, errors.New("win-overlay doesn't support IPv6 now")
|
return nil, fmt.Errorf("win-overlay doesn't support IPv6 now")
|
||||||
}
|
}
|
||||||
|
|
||||||
// conjure a MAC based on the IP for Overlay
|
// conjure a MAC based on the IP for Overlay
|
||||||
|
@ -28,7 +28,7 @@ The following network configuration file
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "firewall",
|
"type": "firewall"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ look like:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "firewall",
|
"type": "firewall",
|
||||||
"backend": "firewalld"
|
"backend": "firewalld"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ look like:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "firewall",
|
"type": "firewall",
|
||||||
"backend": "iptables"
|
"backend": "iptables"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -129,7 +129,21 @@ when containers are created and from where rules will be removed when containers
|
|||||||
CNI-FORWARD will have a pair of rules added, one for each direction, using the IPAM assigned IP address
|
CNI-FORWARD will have a pair of rules added, one for each direction, using the IPAM assigned IP address
|
||||||
of the container as shown:
|
of the container as shown:
|
||||||
|
|
||||||
`CNI_FORWARD` chain:
|
`CNI-FORWARD` chain:
|
||||||
- `-s 10.88.0.2 -m conntrack --ctstate RELATED,ESTABLISHED -j CNI-FORWARD`
|
- `-s 10.88.0.2 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT`
|
||||||
- `-d 10.88.0.2 -j CNI-FORWARD`
|
- `-d 10.88.0.2 -j ACCEPT`
|
||||||
|
|
||||||
|
The `CNI-FORWARD` chain first sends all traffic to `CNI-ADMIN` chain, which is intended as an user-controlled chain for custom rules that run prior to rules managed by the `firewall` plugin. The `firewall` plugin does not add, delete or modify rules in the `CNI-ADMIN` chain.
|
||||||
|
|
||||||
|
`CNI-FORWARD` chain:
|
||||||
|
- `-j CNI-ADMIN`
|
||||||
|
|
||||||
|
The chain name `CNI-ADMIN` can be overridden by specifying `iptablesAdminChainName` in the plugin configuration
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"type": "firewall",
|
||||||
|
"backend": "iptables",
|
||||||
|
"iptablesAdminChainName": "SOME-OTHER-CHAIN-NAME",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -270,6 +270,13 @@ var _ = Describe("firewall plugin iptables backend", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
validateFullRuleset(fullConf)
|
validateFullRuleset(fullConf)
|
||||||
|
|
||||||
|
// ensure creation is idempotent
|
||||||
|
_, _, err = testutils.CmdAdd(targetNS.Path(), args.ContainerID, IFNAME, fullConf, func() error {
|
||||||
|
return cmdAdd(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
"github.com/containernetworking/cni/pkg/types/current"
|
||||||
|
"github.com/containernetworking/plugins/pkg/utils"
|
||||||
"github.com/coreos/go-iptables/iptables"
|
"github.com/coreos/go-iptables/iptables"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,20 +33,6 @@ func getPrivChainRules(ip string) [][]string {
|
|||||||
return rules
|
return rules
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureChain(ipt *iptables.IPTables, table, chain string) error {
|
|
||||||
chains, err := ipt.ListChains(table)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to list iptables chains: %v", err)
|
|
||||||
}
|
|
||||||
for _, ch := range chains {
|
|
||||||
if ch == chain {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ipt.NewChain(table, chain)
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateFilterRule(privChainName string) []string {
|
func generateFilterRule(privChainName string) []string {
|
||||||
return []string{"-m", "comment", "--comment", "CNI firewall plugin rules", "-j", privChainName}
|
return []string{"-m", "comment", "--comment", "CNI firewall plugin rules", "-j", privChainName}
|
||||||
}
|
}
|
||||||
@ -70,13 +57,13 @@ func ensureFirstChainRule(ipt *iptables.IPTables, chain string, rule []string) e
|
|||||||
|
|
||||||
func (ib *iptablesBackend) setupChains(ipt *iptables.IPTables) error {
|
func (ib *iptablesBackend) setupChains(ipt *iptables.IPTables) error {
|
||||||
privRule := generateFilterRule(ib.privChainName)
|
privRule := generateFilterRule(ib.privChainName)
|
||||||
adminRule := generateFilterRule(ib.adminChainName)
|
adminRule := generateAdminRule(ib.adminChainName)
|
||||||
|
|
||||||
// Ensure our private chains exist
|
// Ensure our private chains exist
|
||||||
if err := ensureChain(ipt, "filter", ib.privChainName); err != nil {
|
if err := utils.EnsureChain(ipt, "filter", ib.privChainName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ensureChain(ipt, "filter", ib.adminChainName); err != nil {
|
if err := utils.EnsureChain(ipt, "filter", ib.adminChainName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,10 +147,10 @@ func (ib *iptablesBackend) checkRules(conf *FirewallNetConf, result *current.Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure our private chains exist
|
// Ensure our private chains exist
|
||||||
if err := ensureChain(ipt, "filter", ib.privChainName); err != nil {
|
if err := utils.EnsureChain(ipt, "filter", ib.privChainName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ensureChain(ipt, "filter", ib.adminChainName); err != nil {
|
if err := utils.EnsureChain(ipt, "filter", ib.adminChainName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +165,7 @@ func (ib *iptablesBackend) checkRules(conf *FirewallNetConf, result *current.Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure our admin override chain rule exists in our private chain
|
// Ensure our admin override chain rule exists in our private chain
|
||||||
adminRule := generateFilterRule(ib.adminChainName)
|
adminRule := generateAdminRule(ib.adminChainName)
|
||||||
adminExists, err := ipt.Exists("filter", ib.privChainName, adminRule...)
|
adminExists, err := ipt.Exists("filter", ib.privChainName, adminRule...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -89,7 +89,7 @@ Additionally, for the bridge plugin, `isGateway` will be set to `true`, if not p
|
|||||||
|
|
||||||
## Windows Support (Experimental)
|
## Windows Support (Experimental)
|
||||||
This plugin supports delegating to the windows CNI plugins (overlay.exe, l2bridge.exe) to work in conjunction with [Flannel on Windows](https://github.com/coreos/flannel/issues/833).
|
This plugin supports delegating to the windows CNI plugins (overlay.exe, l2bridge.exe) to work in conjunction with [Flannel on Windows](https://github.com/coreos/flannel/issues/833).
|
||||||
Flannel sets up an [HNS Network](https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/container-networking) in L2Bridge mode for host-gw and in Overlay mode for vxlan.
|
Flannel sets up an [HNS Network](https://docs.microsoft.com/en-us/virtualization/windowscontainers/container-networking/architecture) in L2Bridge mode for host-gw and in Overlay mode for vxlan.
|
||||||
|
|
||||||
The following fields must be set in the delegated plugin configuration:
|
The following fields must be set in the delegated plugin configuration:
|
||||||
* `name` (string, required): the name of the network (must match the name in Flannel config / name of the HNS network)
|
* `name` (string, required): the name of the network (must match the name in Flannel config / name of the HNS network)
|
||||||
|
@ -146,12 +146,19 @@ func saveScratchNetConf(containerID, dataDir string, netconf []byte) error {
|
|||||||
return ioutil.WriteFile(path, netconf, 0600)
|
return ioutil.WriteFile(path, netconf, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
func consumeScratchNetConf(containerID, dataDir string) ([]byte, error) {
|
func consumeScratchNetConf(containerID, dataDir string) (func(error), []byte, error) {
|
||||||
path := filepath.Join(dataDir, containerID)
|
path := filepath.Join(dataDir, containerID)
|
||||||
// Ignore errors when removing - Per spec safe to continue during DEL
|
|
||||||
defer os.Remove(path)
|
|
||||||
|
|
||||||
return ioutil.ReadFile(path)
|
// cleanup will do clean job when no error happens in consuming/using process
|
||||||
|
cleanup := func(err error) {
|
||||||
|
if err == nil {
|
||||||
|
// Ignore errors when removing - Per spec safe to continue during DEL
|
||||||
|
_ = os.Remove(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
netConfBytes, err := ioutil.ReadFile(path)
|
||||||
|
|
||||||
|
return cleanup, netConfBytes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func delegateAdd(cid, dataDir string, netconf map[string]interface{}) error {
|
func delegateAdd(cid, dataDir string, netconf map[string]interface{}) error {
|
||||||
|
@ -68,8 +68,8 @@ func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error {
|
|||||||
return delegateAdd(args.ContainerID, n.DataDir, n.Delegate)
|
return delegateAdd(args.ContainerID, n.DataDir, n.Delegate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func doCmdDel(args *skel.CmdArgs, n *NetConf) error {
|
func doCmdDel(args *skel.CmdArgs, n *NetConf) (err error) {
|
||||||
netconfBytes, err := consumeScratchNetConf(args.ContainerID, n.DataDir)
|
cleanup, netConfBytes, err := consumeScratchNetConf(args.ContainerID, n.DataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
// Per spec should ignore error if resources are missing / already removed
|
// Per spec should ignore error if resources are missing / already removed
|
||||||
@ -78,10 +78,15 @@ func doCmdDel(args *skel.CmdArgs, n *NetConf) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cleanup will work when no error happens
|
||||||
|
defer func() {
|
||||||
|
cleanup(err)
|
||||||
|
}()
|
||||||
|
|
||||||
nc := &types.NetConf{}
|
nc := &types.NetConf{}
|
||||||
if err = json.Unmarshal(netconfBytes, nc); err != nil {
|
if err = json.Unmarshal(netConfBytes, nc); err != nil {
|
||||||
return fmt.Errorf("failed to parse netconf: %v", err)
|
return fmt.Errorf("failed to parse netconf: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return invoke.DelegateDel(context.TODO(), nc.Type, netconfBytes, nil)
|
return invoke.DelegateDel(context.TODO(), nc.Type, netConfBytes, nil)
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,8 @@ func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error {
|
|||||||
return delegateAdd(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir, n.Delegate)
|
return delegateAdd(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir, n.Delegate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func doCmdDel(args *skel.CmdArgs, n *NetConf) error {
|
func doCmdDel(args *skel.CmdArgs, n *NetConf) (err error) {
|
||||||
netconfBytes, err := consumeScratchNetConf(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir)
|
cleanup, netConfBytes, err := consumeScratchNetConf(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
// Per spec should ignore error if resources are missing / already removed
|
// Per spec should ignore error if resources are missing / already removed
|
||||||
@ -65,10 +65,15 @@ func doCmdDel(args *skel.CmdArgs, n *NetConf) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cleanup will work when no error happens
|
||||||
|
defer func() {
|
||||||
|
cleanup(err)
|
||||||
|
}()
|
||||||
|
|
||||||
nc := &types.NetConf{}
|
nc := &types.NetConf{}
|
||||||
if err = json.Unmarshal(netconfBytes, nc); err != nil {
|
if err = json.Unmarshal(netConfBytes, nc); err != nil {
|
||||||
return fmt.Errorf("failed to parse netconf: %v", err)
|
return fmt.Errorf("failed to parse netconf: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return invoke.DelegateDel(context.TODO(), nc.Type, netconfBytes, nil)
|
return invoke.DelegateDel(context.TODO(), nc.Type, netConfBytes, nil)
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ will masquerade traffic as needed.
|
|||||||
The DNAT rule rewrites the destination port and address of new connections.
|
The DNAT rule rewrites the destination port and address of new connections.
|
||||||
There is a top-level chain, `CNI-HOSTPORT-DNAT` which is always created and
|
There is a top-level chain, `CNI-HOSTPORT-DNAT` which is always created and
|
||||||
never deleted. Each plugin execution creates an additional chain for ease
|
never deleted. Each plugin execution creates an additional chain for ease
|
||||||
of cleanup. So, if a single container exists on IP 172.16.30.2 with ports
|
of cleanup. So, if a single container exists on IP 172.16.30.2/24 with ports
|
||||||
8080 and 8043 on the host forwarded to ports 80 and 443 in the container, the
|
8080 and 8043 on the host forwarded to ports 80 and 443 in the container, the
|
||||||
rules look like this:
|
rules look like this:
|
||||||
|
|
||||||
@ -86,10 +86,10 @@ rules look like this:
|
|||||||
- `-j MARK --set-xmark 0x2000/0x2000`
|
- `-j MARK --set-xmark 0x2000/0x2000`
|
||||||
|
|
||||||
`CNI-DN-xxxxxx` chain:
|
`CNI-DN-xxxxxx` chain:
|
||||||
- `-p tcp -s 172.16.30.2 --dport 8080 -j CNI-HOSTPORT-SETMARK` (masquerade hairpin traffic)
|
- `-p tcp -s 172.16.30.0/24 --dport 8080 -j CNI-HOSTPORT-SETMARK` (masquerade hairpin traffic)
|
||||||
- `-p tcp -s 127.0.0.1 --dport 8080 -j CNI-HOSTPORT-SETMARK` (masquerade localhost traffic)
|
- `-p tcp -s 127.0.0.1 --dport 8080 -j CNI-HOSTPORT-SETMARK` (masquerade localhost traffic)
|
||||||
- `-p tcp --dport 8080 -j DNAT --to-destination 172.16.30.2:80` (rewrite destination)
|
- `-p tcp --dport 8080 -j DNAT --to-destination 172.16.30.2:80` (rewrite destination)
|
||||||
- `-p tcp -s 172.16.30.2 --dport 8043 -j CNI-HOSTPORT-SETMARK`
|
- `-p tcp -s 172.16.30.0/24 --dport 8043 -j CNI-HOSTPORT-SETMARK`
|
||||||
- `-p tcp -s 127.0.0.1 --dport 8043 -j CNI-HOSTPORT-SETMARK`
|
- `-p tcp -s 127.0.0.1 --dport 8043 -j CNI-HOSTPORT-SETMARK`
|
||||||
- `-p tcp --dport 8043 -j DNAT --to-destination 172.16.30.2:443`
|
- `-p tcp --dport 8043 -j DNAT --to-destination 172.16.30.2:443`
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containernetworking/plugins/pkg/utils"
|
||||||
"github.com/coreos/go-iptables/iptables"
|
"github.com/coreos/go-iptables/iptables"
|
||||||
"github.com/mattn/go-shellwords"
|
"github.com/mattn/go-shellwords"
|
||||||
)
|
)
|
||||||
@ -35,16 +36,11 @@ type chain struct {
|
|||||||
|
|
||||||
// setup idempotently creates the chain. It will not error if the chain exists.
|
// setup idempotently creates the chain. It will not error if the chain exists.
|
||||||
func (c *chain) setup(ipt *iptables.IPTables) error {
|
func (c *chain) setup(ipt *iptables.IPTables) error {
|
||||||
// create the chain
|
|
||||||
exists, err := chainExists(ipt, c.table, c.name)
|
err := utils.EnsureChain(ipt, c.table, c.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !exists {
|
|
||||||
if err := ipt.NewChain(c.table, c.name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the rules to the chain
|
// Add the rules to the chain
|
||||||
for _, rule := range c.rules {
|
for _, rule := range c.rules {
|
||||||
@ -74,7 +70,7 @@ func (c *chain) teardown(ipt *iptables.IPTables) error {
|
|||||||
// flush the chain
|
// flush the chain
|
||||||
// This will succeed *and create the chain* if it does not exist.
|
// This will succeed *and create the chain* if it does not exist.
|
||||||
// If the chain doesn't exist, the next checks will fail.
|
// If the chain doesn't exist, the next checks will fail.
|
||||||
if err := ipt.ClearChain(c.table, c.name); err != nil {
|
if err := utils.ClearChain(ipt, c.table, c.name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,17 +90,15 @@ func (c *chain) teardown(ipt *iptables.IPTables) error {
|
|||||||
}
|
}
|
||||||
chainParts = chainParts[2:] // List results always include an -A CHAINNAME
|
chainParts = chainParts[2:] // List results always include an -A CHAINNAME
|
||||||
|
|
||||||
if err := ipt.Delete(c.table, entryChain, chainParts...); err != nil {
|
if err := utils.DeleteRule(ipt, c.table, entryChain, chainParts...); err != nil {
|
||||||
return fmt.Errorf("Failed to delete referring rule %s %s: %v", c.table, entryChainRule, err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.DeleteChain(c.table, c.name); err != nil {
|
return utils.DeleteChain(ipt, c.table, c.name)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertUnique will add a rule to a chain if it does not already exist.
|
// insertUnique will add a rule to a chain if it does not already exist.
|
||||||
@ -125,24 +119,10 @@ func insertUnique(ipt *iptables.IPTables, table, chain string, prepend bool, rul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func chainExists(ipt *iptables.IPTables, tableName, chainName string) (bool, error) {
|
|
||||||
chains, err := ipt.ListChains(tableName)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ch := range chains {
|
|
||||||
if ch == chainName {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the chain.
|
// check the chain.
|
||||||
func (c *chain) check(ipt *iptables.IPTables) error {
|
func (c *chain) check(ipt *iptables.IPTables) error {
|
||||||
|
|
||||||
exists, err := chainExists(ipt, c.table, c.name)
|
exists, err := utils.ChainExists(ipt, c.table, c.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
"github.com/containernetworking/plugins/pkg/testutils"
|
"github.com/containernetworking/plugins/pkg/testutils"
|
||||||
@ -32,6 +33,7 @@ const TABLE = "filter" // We'll monkey around here
|
|||||||
var _ = Describe("chain tests", func() {
|
var _ = Describe("chain tests", func() {
|
||||||
var testChain chain
|
var testChain chain
|
||||||
var ipt *iptables.IPTables
|
var ipt *iptables.IPTables
|
||||||
|
var testNs ns.NetNS
|
||||||
var cleanup func()
|
var cleanup func()
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
@ -41,7 +43,7 @@ var _ = Describe("chain tests", func() {
|
|||||||
currNs, err := ns.GetCurrentNS()
|
currNs, err := ns.GetCurrentNS()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
testNs, err := testutils.NewNS()
|
testNs, err = testutils.NewNS()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
tlChainName := fmt.Sprintf("cni-test-%d", rand.Intn(10000000))
|
tlChainName := fmt.Sprintf("cni-test-%d", rand.Intn(10000000))
|
||||||
@ -195,4 +197,38 @@ var _ = Describe("chain tests", func() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("deletes chains idempotently in parallel", func() {
|
||||||
|
defer cleanup()
|
||||||
|
// number of parallel executions
|
||||||
|
N := 10
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
err := testChain.setup(ipt)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
errCh := make(chan error, N)
|
||||||
|
for i := 0; i < N; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
// teardown chain
|
||||||
|
errCh <- testNs.Do(func(ns.NetNS) error {
|
||||||
|
return testChain.teardown(ipt)
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
close(errCh)
|
||||||
|
for err := range errCh {
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
chains, err := ipt.ListChains(TABLE)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
for _, chain := range chains {
|
||||||
|
if chain == testChain.name {
|
||||||
|
Fail("Chain was not deleted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -60,9 +60,9 @@ type PortMapConf struct {
|
|||||||
|
|
||||||
// These are fields parsed out of the config or the environment;
|
// These are fields parsed out of the config or the environment;
|
||||||
// included here for convenience
|
// included here for convenience
|
||||||
ContainerID string `json:"-"`
|
ContainerID string `json:"-"`
|
||||||
ContIPv4 net.IP `json:"-"`
|
ContIPv4 net.IPNet `json:"-"`
|
||||||
ContIPv6 net.IP `json:"-"`
|
ContIPv6 net.IPNet `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// The default mark bit to signal that masquerading is required
|
// The default mark bit to signal that masquerading is required
|
||||||
@ -85,13 +85,13 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
|
|
||||||
netConf.ContainerID = args.ContainerID
|
netConf.ContainerID = args.ContainerID
|
||||||
|
|
||||||
if netConf.ContIPv4 != nil {
|
if netConf.ContIPv4.IP != nil {
|
||||||
if err := forwardPorts(netConf, netConf.ContIPv4); err != nil {
|
if err := forwardPorts(netConf, netConf.ContIPv4); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if netConf.ContIPv6 != nil {
|
if netConf.ContIPv6.IP != nil {
|
||||||
if err := forwardPorts(netConf, netConf.ContIPv6); err != nil {
|
if err := forwardPorts(netConf, netConf.ContIPv6); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -107,6 +107,10 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
return fmt.Errorf("failed to parse config: %v", err)
|
return fmt.Errorf("failed to parse config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(netConf.RuntimeConfig.PortMaps) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
netConf.ContainerID = args.ContainerID
|
netConf.ContainerID = args.ContainerID
|
||||||
|
|
||||||
// We don't need to parse out whether or not we're using v6 or snat,
|
// We don't need to parse out whether or not we're using v6 or snat,
|
||||||
@ -138,13 +142,13 @@ func cmdCheck(args *skel.CmdArgs) error {
|
|||||||
|
|
||||||
conf.ContainerID = args.ContainerID
|
conf.ContainerID = args.ContainerID
|
||||||
|
|
||||||
if conf.ContIPv4 != nil {
|
if conf.ContIPv4.IP != nil {
|
||||||
if err := checkPorts(conf, conf.ContIPv4); err != nil {
|
if err := checkPorts(conf, conf.ContIPv4); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.ContIPv6 != nil {
|
if conf.ContIPv6.IP != nil {
|
||||||
if err := checkPorts(conf, conf.ContIPv6); err != nil {
|
if err := checkPorts(conf, conf.ContIPv6); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -205,9 +209,9 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, er
|
|||||||
|
|
||||||
if conf.PrevResult != nil {
|
if conf.PrevResult != nil {
|
||||||
for _, ip := range result.IPs {
|
for _, ip := range result.IPs {
|
||||||
if ip.Version == "6" && conf.ContIPv6 != nil {
|
if ip.Version == "6" && conf.ContIPv6.IP != nil {
|
||||||
continue
|
continue
|
||||||
} else if ip.Version == "4" && conf.ContIPv4 != nil {
|
} else if ip.Version == "4" && conf.ContIPv4.IP != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,9 +227,9 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, er
|
|||||||
}
|
}
|
||||||
switch ip.Version {
|
switch ip.Version {
|
||||||
case "6":
|
case "6":
|
||||||
conf.ContIPv6 = ip.Address.IP
|
conf.ContIPv6 = ip.Address
|
||||||
case "4":
|
case "4":
|
||||||
conf.ContIPv4 = ip.Address.IP
|
conf.ContIPv4 = ip.Address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,9 @@ const MarkMasqChainName = "CNI-HOSTPORT-MASQ"
|
|||||||
const OldTopLevelSNATChainName = "CNI-HOSTPORT-SNAT"
|
const OldTopLevelSNATChainName = "CNI-HOSTPORT-SNAT"
|
||||||
|
|
||||||
// forwardPorts establishes port forwarding to a given container IP.
|
// forwardPorts establishes port forwarding to a given container IP.
|
||||||
// containerIP can be either v4 or v6.
|
// containerNet.IP can be either v4 or v6.
|
||||||
func forwardPorts(config *PortMapConf, containerIP net.IP) error {
|
func forwardPorts(config *PortMapConf, containerNet net.IPNet) error {
|
||||||
isV6 := (containerIP.To4() == nil)
|
isV6 := (containerNet.IP.To4() == nil)
|
||||||
|
|
||||||
var ipt *iptables.IPTables
|
var ipt *iptables.IPTables
|
||||||
var err error
|
var err error
|
||||||
@ -86,7 +86,7 @@ func forwardPorts(config *PortMapConf, containerIP net.IP) error {
|
|||||||
if !isV6 {
|
if !isV6 {
|
||||||
// Set the route_localnet bit on the host interface, so that
|
// Set the route_localnet bit on the host interface, so that
|
||||||
// 127/8 can cross a routing boundary.
|
// 127/8 can cross a routing boundary.
|
||||||
hostIfName := getRoutableHostIF(containerIP)
|
hostIfName := getRoutableHostIF(containerNet.IP)
|
||||||
if hostIfName != "" {
|
if hostIfName != "" {
|
||||||
if err := enableLocalnetRouting(hostIfName); err != nil {
|
if err := enableLocalnetRouting(hostIfName); err != nil {
|
||||||
return fmt.Errorf("unable to enable route_localnet: %v", err)
|
return fmt.Errorf("unable to enable route_localnet: %v", err)
|
||||||
@ -104,7 +104,7 @@ func forwardPorts(config *PortMapConf, containerIP net.IP) error {
|
|||||||
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
||||||
// First, idempotently tear down this chain in case there was some
|
// First, idempotently tear down this chain in case there was some
|
||||||
// sort of collision or bad state.
|
// sort of collision or bad state.
|
||||||
fillDnatRules(&dnatChain, config, containerIP)
|
fillDnatRules(&dnatChain, config, containerNet)
|
||||||
if err := dnatChain.setup(ipt); err != nil {
|
if err := dnatChain.setup(ipt); err != nil {
|
||||||
return fmt.Errorf("unable to setup DNAT: %v", err)
|
return fmt.Errorf("unable to setup DNAT: %v", err)
|
||||||
}
|
}
|
||||||
@ -112,10 +112,10 @@ func forwardPorts(config *PortMapConf, containerIP net.IP) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPorts(config *PortMapConf, containerIP net.IP) error {
|
func checkPorts(config *PortMapConf, containerNet net.IPNet) error {
|
||||||
|
|
||||||
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
||||||
fillDnatRules(&dnatChain, config, containerIP)
|
fillDnatRules(&dnatChain, config, containerNet)
|
||||||
|
|
||||||
ip4t := maybeGetIptables(false)
|
ip4t := maybeGetIptables(false)
|
||||||
ip6t := maybeGetIptables(true)
|
ip6t := maybeGetIptables(true)
|
||||||
@ -124,7 +124,7 @@ func checkPorts(config *PortMapConf, containerIP net.IP) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ip4t != nil {
|
if ip4t != nil {
|
||||||
exists, err := chainExists(ip4t, dnatChain.table, dnatChain.name)
|
exists, err := utils.ChainExists(ip4t, dnatChain.table, dnatChain.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ func checkPorts(config *PortMapConf, containerIP net.IP) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ip6t != nil {
|
if ip6t != nil {
|
||||||
exists, err := chainExists(ip6t, dnatChain.table, dnatChain.name)
|
exists, err := utils.ChainExists(ip6t, dnatChain.table, dnatChain.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -180,8 +180,8 @@ func genDnatChain(netName, containerID string) chain {
|
|||||||
|
|
||||||
// dnatRules generates the destination NAT rules, one per port, to direct
|
// dnatRules generates the destination NAT rules, one per port, to direct
|
||||||
// traffic from hostip:hostport to podip:podport
|
// traffic from hostip:hostport to podip:podport
|
||||||
func fillDnatRules(c *chain, config *PortMapConf, containerIP net.IP) {
|
func fillDnatRules(c *chain, config *PortMapConf, containerNet net.IPNet) {
|
||||||
isV6 := (containerIP.To4() == nil)
|
isV6 := (containerNet.IP.To4() == nil)
|
||||||
comment := trimComment(fmt.Sprintf(`dnat name: "%s" id: "%s"`, config.Name, config.ContainerID))
|
comment := trimComment(fmt.Sprintf(`dnat name: "%s" id: "%s"`, config.Name, config.ContainerID))
|
||||||
entries := config.RuntimeConfig.PortMaps
|
entries := config.RuntimeConfig.PortMaps
|
||||||
setMarkChainName := SetMarkChainName
|
setMarkChainName := SetMarkChainName
|
||||||
@ -225,6 +225,8 @@ func fillDnatRules(c *chain, config *PortMapConf, containerIP net.IP) {
|
|||||||
c.rules = make([][]string, 0, 3*len(entries))
|
c.rules = make([][]string, 0, 3*len(entries))
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
// If a HostIP is given, only process the entry if host and container address families match
|
// If a HostIP is given, only process the entry if host and container address families match
|
||||||
|
// and append it to the iptables rules
|
||||||
|
addRuleBaseDst := false
|
||||||
if entry.HostIP != "" {
|
if entry.HostIP != "" {
|
||||||
hostIP := net.ParseIP(entry.HostIP)
|
hostIP := net.ParseIP(entry.HostIP)
|
||||||
isHostV6 := (hostIP.To4() == nil)
|
isHostV6 := (hostIP.To4() == nil)
|
||||||
@ -232,12 +234,17 @@ func fillDnatRules(c *chain, config *PortMapConf, containerIP net.IP) {
|
|||||||
if isV6 != isHostV6 {
|
if isV6 != isHostV6 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unspecified addresses can not be used as destination
|
||||||
|
if !hostIP.IsUnspecified() {
|
||||||
|
addRuleBaseDst = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleBase := []string{
|
ruleBase := []string{
|
||||||
"-p", entry.Protocol,
|
"-p", entry.Protocol,
|
||||||
"--dport", strconv.Itoa(entry.HostPort)}
|
"--dport", strconv.Itoa(entry.HostPort)}
|
||||||
if entry.HostIP != "" {
|
if addRuleBaseDst {
|
||||||
ruleBase = append(ruleBase,
|
ruleBase = append(ruleBase,
|
||||||
"-d", entry.HostIP)
|
"-d", entry.HostIP)
|
||||||
}
|
}
|
||||||
@ -249,7 +256,7 @@ func fillDnatRules(c *chain, config *PortMapConf, containerIP net.IP) {
|
|||||||
copy(hpRule, ruleBase)
|
copy(hpRule, ruleBase)
|
||||||
|
|
||||||
hpRule = append(hpRule,
|
hpRule = append(hpRule,
|
||||||
"-s", containerIP.String(),
|
"-s", containerNet.String(),
|
||||||
"-j", setMarkChainName,
|
"-j", setMarkChainName,
|
||||||
)
|
)
|
||||||
c.rules = append(c.rules, hpRule)
|
c.rules = append(c.rules, hpRule)
|
||||||
@ -272,7 +279,7 @@ func fillDnatRules(c *chain, config *PortMapConf, containerIP net.IP) {
|
|||||||
copy(dnatRule, ruleBase)
|
copy(dnatRule, ruleBase)
|
||||||
dnatRule = append(dnatRule,
|
dnatRule = append(dnatRule,
|
||||||
"-j", "DNAT",
|
"-j", "DNAT",
|
||||||
"--to-destination", fmtIpPort(containerIP, entry.ContainerPort),
|
"--to-destination", fmtIpPort(containerNet.IP, entry.ContainerPort),
|
||||||
)
|
)
|
||||||
c.rules = append(c.rules, dnatRule)
|
c.rules = append(c.rules, dnatRule)
|
||||||
}
|
}
|
||||||
|
@ -96,119 +96,133 @@ var _ = Describe("portmap integration tests", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// This needs to be done using Ginkgo's asynchronous testing mode.
|
Describe("Creating an interface in a namespace with the ptp plugin", func() {
|
||||||
It("forwards a TCP port on ipv4", func(done Done) {
|
// This needs to be done using Ginkgo's asynchronous testing mode.
|
||||||
var err error
|
It("forwards a TCP port on ipv4", func(done Done) {
|
||||||
hostPort := rand.Intn(10000) + 1025
|
var err error
|
||||||
runtimeConfig := libcni.RuntimeConf{
|
hostPort := rand.Intn(10000) + 1025
|
||||||
ContainerID: fmt.Sprintf("unit-test-%d", hostPort),
|
runtimeConfig := libcni.RuntimeConf{
|
||||||
NetNS: targetNS.Path(),
|
ContainerID: fmt.Sprintf("unit-test-%d", hostPort),
|
||||||
IfName: "eth0",
|
NetNS: targetNS.Path(),
|
||||||
CapabilityArgs: map[string]interface{}{
|
IfName: "eth0",
|
||||||
"portMappings": []map[string]interface{}{
|
CapabilityArgs: map[string]interface{}{
|
||||||
{
|
"portMappings": []map[string]interface{}{
|
||||||
"hostPort": hostPort,
|
{
|
||||||
"containerPort": containerPort,
|
"hostPort": hostPort,
|
||||||
"protocol": "tcp",
|
"containerPort": containerPort,
|
||||||
|
"protocol": "tcp",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make delete idempotent, so we can clean up on failure
|
|
||||||
netDeleted := false
|
|
||||||
deleteNetwork := func() error {
|
|
||||||
if netDeleted {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
netDeleted = true
|
|
||||||
return cniConf.DelNetworkList(context.TODO(), configList, &runtimeConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// we'll also manually check the iptables chains
|
// Make delete idempotent, so we can clean up on failure
|
||||||
ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
netDeleted := false
|
||||||
Expect(err).NotTo(HaveOccurred())
|
deleteNetwork := func() error {
|
||||||
dnatChainName := genDnatChain("cni-portmap-unit-test", runtimeConfig.ContainerID).name
|
if netDeleted {
|
||||||
|
return nil
|
||||||
// Create the network
|
}
|
||||||
resI, err := cniConf.AddNetworkList(context.TODO(), configList, &runtimeConfig)
|
netDeleted = true
|
||||||
Expect(err).NotTo(HaveOccurred())
|
return cniConf.DelNetworkList(context.TODO(), configList, &runtimeConfig)
|
||||||
defer deleteNetwork()
|
|
||||||
|
|
||||||
// Undo Docker's forwarding policy
|
|
||||||
cmd := exec.Command("iptables", "-t", "filter",
|
|
||||||
"-P", "FORWARD", "ACCEPT")
|
|
||||||
cmd.Stderr = GinkgoWriter
|
|
||||||
err = cmd.Run()
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
// Check the chain exists
|
|
||||||
_, err = ipt.List("nat", dnatChainName)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
result, err := current.GetResult(resI)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
var contIP net.IP
|
|
||||||
|
|
||||||
for _, ip := range result.IPs {
|
|
||||||
intfIndex := *ip.Interface
|
|
||||||
if result.Interfaces[intfIndex].Sandbox == "" {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
contIP = ip.Address.IP
|
|
||||||
}
|
|
||||||
if contIP == nil {
|
|
||||||
Fail("could not determine container IP")
|
|
||||||
}
|
|
||||||
|
|
||||||
hostIP := getLocalIP()
|
// we'll also manually check the iptables chains
|
||||||
fmt.Fprintf(GinkgoWriter, "hostIP: %s:%d, contIP: %s:%d\n",
|
ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
||||||
hostIP, hostPort, contIP, containerPort)
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
dnatChainName := genDnatChain("cni-portmap-unit-test", runtimeConfig.ContainerID).name
|
||||||
|
|
||||||
// dump iptables-save output for debugging
|
// Create the network
|
||||||
cmd = exec.Command("iptables-save")
|
resI, err := cniConf.AddNetworkList(context.TODO(), configList, &runtimeConfig)
|
||||||
cmd.Stderr = GinkgoWriter
|
Expect(err).NotTo(HaveOccurred())
|
||||||
cmd.Stdout = GinkgoWriter
|
defer deleteNetwork()
|
||||||
Expect(cmd.Run()).To(Succeed())
|
|
||||||
|
|
||||||
// Sanity check: verify that the container is reachable directly
|
// Undo Docker's forwarding policy
|
||||||
contOK := testEchoServer(contIP.String(), containerPort, "")
|
cmd := exec.Command("iptables", "-t", "filter",
|
||||||
|
"-P", "FORWARD", "ACCEPT")
|
||||||
|
cmd.Stderr = GinkgoWriter
|
||||||
|
err = cmd.Run()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
// Verify that a connection to the forwarded port works
|
// Check the chain exists
|
||||||
dnatOK := testEchoServer(hostIP, hostPort, "")
|
_, err = ipt.List("nat", dnatChainName)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
// Verify that a connection to localhost works
|
result, err := current.GetResult(resI)
|
||||||
snatOK := testEchoServer("127.0.0.1", hostPort, "")
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
var contIP net.IP
|
||||||
|
|
||||||
// verify that hairpin works
|
for _, ip := range result.IPs {
|
||||||
hairpinOK := testEchoServer(hostIP, hostPort, targetNS.Path())
|
intfIndex := *ip.Interface
|
||||||
|
if result.Interfaces[intfIndex].Sandbox == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
contIP = ip.Address.IP
|
||||||
|
}
|
||||||
|
if contIP == nil {
|
||||||
|
Fail("could not determine container IP")
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup
|
hostIP := getLocalIP()
|
||||||
session.Terminate()
|
fmt.Fprintf(GinkgoWriter, "hostIP: %s:%d, contIP: %s:%d\n",
|
||||||
err = deleteNetwork()
|
hostIP, hostPort, contIP, containerPort)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
// Verify iptables rules are gone
|
// dump iptables-save output for debugging
|
||||||
_, err = ipt.List("nat", dnatChainName)
|
cmd = exec.Command("iptables-save")
|
||||||
Expect(err).To(MatchError(ContainSubstring("iptables: No chain/target/match by that name.")))
|
cmd.Stderr = GinkgoWriter
|
||||||
|
cmd.Stdout = GinkgoWriter
|
||||||
|
Expect(cmd.Run()).To(Succeed())
|
||||||
|
|
||||||
// Check that everything succeeded *after* we clean up the network
|
// dump ip routes output for debugging
|
||||||
if !contOK {
|
cmd = exec.Command("ip", "route")
|
||||||
Fail("connection direct to " + contIP.String() + " failed")
|
cmd.Stderr = GinkgoWriter
|
||||||
}
|
cmd.Stdout = GinkgoWriter
|
||||||
if !dnatOK {
|
Expect(cmd.Run()).To(Succeed())
|
||||||
Fail("Connection to " + hostIP + " was not forwarded")
|
|
||||||
}
|
|
||||||
if !snatOK {
|
|
||||||
Fail("connection to 127.0.0.1 was not forwarded")
|
|
||||||
}
|
|
||||||
if !hairpinOK {
|
|
||||||
Fail("Hairpin connection failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
close(done)
|
// dump ip addresses output for debugging
|
||||||
|
cmd = exec.Command("ip", "addr")
|
||||||
|
cmd.Stderr = GinkgoWriter
|
||||||
|
cmd.Stdout = GinkgoWriter
|
||||||
|
Expect(cmd.Run()).To(Succeed())
|
||||||
|
|
||||||
}, TIMEOUT*9)
|
// Sanity check: verify that the container is reachable directly
|
||||||
|
contOK := testEchoServer(contIP.String(), containerPort, "")
|
||||||
|
|
||||||
|
// Verify that a connection to the forwarded port works
|
||||||
|
dnatOK := testEchoServer(hostIP, hostPort, "")
|
||||||
|
|
||||||
|
// Verify that a connection to localhost works
|
||||||
|
snatOK := testEchoServer("127.0.0.1", hostPort, "")
|
||||||
|
|
||||||
|
// verify that hairpin works
|
||||||
|
hairpinOK := testEchoServer(hostIP, hostPort, targetNS.Path())
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
session.Terminate()
|
||||||
|
err = deleteNetwork()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Verify iptables rules are gone
|
||||||
|
_, err = ipt.List("nat", dnatChainName)
|
||||||
|
Expect(err).To(MatchError(ContainSubstring("iptables: No chain/target/match by that name.")))
|
||||||
|
|
||||||
|
// Check that everything succeeded *after* we clean up the network
|
||||||
|
if !contOK {
|
||||||
|
Fail("connection direct to " + contIP.String() + " failed")
|
||||||
|
}
|
||||||
|
if !dnatOK {
|
||||||
|
Fail("Connection to " + hostIP + " was not forwarded")
|
||||||
|
}
|
||||||
|
if !snatOK {
|
||||||
|
Fail("connection to 127.0.0.1 was not forwarded")
|
||||||
|
}
|
||||||
|
if !hairpinOK {
|
||||||
|
Fail("Hairpin connection failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
close(done)
|
||||||
|
|
||||||
|
}, TIMEOUT*9)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// testEchoServer returns true if we found an echo server on the port
|
// testEchoServer returns true if we found an echo server on the port
|
||||||
|
@ -16,7 +16,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@ -77,8 +78,10 @@ var _ = Describe("portmapping configuration", func() {
|
|||||||
Expect(c.SNAT).To(Equal(&fvar))
|
Expect(c.SNAT).To(Equal(&fvar))
|
||||||
Expect(c.Name).To(Equal("test"))
|
Expect(c.Name).To(Equal("test"))
|
||||||
|
|
||||||
Expect(c.ContIPv4).To(Equal(net.ParseIP("10.0.0.2")))
|
n, err := types.ParseCIDR("10.0.0.2/24")
|
||||||
Expect(c.ContIPv6).To(Equal(net.ParseIP("2001:db8:1::2")))
|
Expect(c.ContIPv4).To(Equal(*n))
|
||||||
|
n, err = types.ParseCIDR("2001:db8:1::2/64")
|
||||||
|
Expect(c.ContIPv6).To(Equal(*n))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Correctly parses a DEL config", func() {
|
It("Correctly parses a DEL config", func() {
|
||||||
@ -167,7 +170,11 @@ var _ = Describe("portmapping configuration", func() {
|
|||||||
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"},
|
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"},
|
||||||
{ "hostPort": 8081, "containerPort": 80, "protocol": "tcp"},
|
{ "hostPort": 8081, "containerPort": 80, "protocol": "tcp"},
|
||||||
{ "hostPort": 8080, "containerPort": 81, "protocol": "udp"},
|
{ "hostPort": 8080, "containerPort": 81, "protocol": "udp"},
|
||||||
{ "hostPort": 8082, "containerPort": 82, "protocol": "udp"}
|
{ "hostPort": 8082, "containerPort": 82, "protocol": "udp"},
|
||||||
|
{ "hostPort": 8083, "containerPort": 83, "protocol": "tcp", "hostIP": "192.168.0.2"},
|
||||||
|
{ "hostPort": 8084, "containerPort": 84, "protocol": "tcp", "hostIP": "0.0.0.0"},
|
||||||
|
{ "hostPort": 8085, "containerPort": 85, "protocol": "tcp", "hostIP": "2001:db8:a::1"},
|
||||||
|
{ "hostPort": 8086, "containerPort": 86, "protocol": "tcp", "hostIP": "::"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"snat": true,
|
"snat": true,
|
||||||
@ -186,14 +193,15 @@ var _ = Describe("portmapping configuration", func() {
|
|||||||
entryChains: []string{"CNI-HOSTPORT-DNAT"},
|
entryChains: []string{"CNI-HOSTPORT-DNAT"},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
fillDnatRules(&ch, conf, net.ParseIP("10.0.0.2"))
|
n, err := types.ParseCIDR("10.0.0.2/24")
|
||||||
|
fillDnatRules(&ch, conf, *n)
|
||||||
|
|
||||||
Expect(ch.entryRules).To(Equal([][]string{
|
Expect(ch.entryRules).To(Equal([][]string{
|
||||||
{"-m", "comment", "--comment",
|
{"-m", "comment", "--comment",
|
||||||
fmt.Sprintf("dnat name: \"test\" id: \"%s\"", containerID),
|
fmt.Sprintf("dnat name: \"test\" id: \"%s\"", containerID),
|
||||||
"-m", "multiport",
|
"-m", "multiport",
|
||||||
"-p", "tcp",
|
"-p", "tcp",
|
||||||
"--destination-ports", "8080,8081",
|
"--destination-ports", "8080,8081,8083,8084,8085,8086",
|
||||||
"a", "b"},
|
"a", "b"},
|
||||||
{"-m", "comment", "--comment",
|
{"-m", "comment", "--comment",
|
||||||
fmt.Sprintf("dnat name: \"test\" id: \"%s\"", containerID),
|
fmt.Sprintf("dnat name: \"test\" id: \"%s\"", containerID),
|
||||||
@ -204,34 +212,53 @@ var _ = Describe("portmapping configuration", func() {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
Expect(ch.rules).To(Equal([][]string{
|
Expect(ch.rules).To(Equal([][]string{
|
||||||
{"-p", "tcp", "--dport", "8080", "-s", "10.0.0.2", "-j", "CNI-HOSTPORT-SETMARK"},
|
// tcp rules and not hostIP
|
||||||
|
{"-p", "tcp", "--dport", "8080", "-s", "10.0.0.2/24", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "tcp", "--dport", "8080", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
{"-p", "tcp", "--dport", "8080", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "tcp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
{"-p", "tcp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
||||||
{"-p", "tcp", "--dport", "8081", "-s", "10.0.0.2", "-j", "CNI-HOSTPORT-SETMARK"},
|
{"-p", "tcp", "--dport", "8081", "-s", "10.0.0.2/24", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "tcp", "--dport", "8081", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
{"-p", "tcp", "--dport", "8081", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "tcp", "--dport", "8081", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
{"-p", "tcp", "--dport", "8081", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
||||||
{"-p", "udp", "--dport", "8080", "-s", "10.0.0.2", "-j", "CNI-HOSTPORT-SETMARK"},
|
// udp rules and not hostIP
|
||||||
|
{"-p", "udp", "--dport", "8080", "-s", "10.0.0.2/24", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "udp", "--dport", "8080", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
{"-p", "udp", "--dport", "8080", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "udp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:81"},
|
{"-p", "udp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:81"},
|
||||||
{"-p", "udp", "--dport", "8082", "-s", "10.0.0.2", "-j", "CNI-HOSTPORT-SETMARK"},
|
{"-p", "udp", "--dport", "8082", "-s", "10.0.0.2/24", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "udp", "--dport", "8082", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
{"-p", "udp", "--dport", "8082", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "udp", "--dport", "8082", "-j", "DNAT", "--to-destination", "10.0.0.2:82"},
|
{"-p", "udp", "--dport", "8082", "-j", "DNAT", "--to-destination", "10.0.0.2:82"},
|
||||||
|
// tcp rules and hostIP
|
||||||
|
{"-p", "tcp", "--dport", "8083", "-d", "192.168.0.2", "-s", "10.0.0.2/24", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
|
{"-p", "tcp", "--dport", "8083", "-d", "192.168.0.2", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
|
{"-p", "tcp", "--dport", "8083", "-d", "192.168.0.2", "-j", "DNAT", "--to-destination", "10.0.0.2:83"},
|
||||||
|
// tcp rules and hostIP = "0.0.0.0"
|
||||||
|
{"-p", "tcp", "--dport", "8084", "-s", "10.0.0.2/24", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
|
{"-p", "tcp", "--dport", "8084", "-s", "127.0.0.1", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
|
{"-p", "tcp", "--dport", "8084", "-j", "DNAT", "--to-destination", "10.0.0.2:84"},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
ch.rules = nil
|
ch.rules = nil
|
||||||
ch.entryRules = nil
|
ch.entryRules = nil
|
||||||
|
|
||||||
fillDnatRules(&ch, conf, net.ParseIP("2001:db8::2"))
|
n, err = types.ParseCIDR("2001:db8::2/64")
|
||||||
|
fillDnatRules(&ch, conf, *n)
|
||||||
|
|
||||||
Expect(ch.rules).To(Equal([][]string{
|
Expect(ch.rules).To(Equal([][]string{
|
||||||
{"-p", "tcp", "--dport", "8080", "-s", "2001:db8::2", "-j", "CNI-HOSTPORT-SETMARK"},
|
// tcp rules and not hostIP
|
||||||
|
{"-p", "tcp", "--dport", "8080", "-s", "2001:db8::2/64", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "tcp", "--dport", "8080", "-j", "DNAT", "--to-destination", "[2001:db8::2]:80"},
|
{"-p", "tcp", "--dport", "8080", "-j", "DNAT", "--to-destination", "[2001:db8::2]:80"},
|
||||||
{"-p", "tcp", "--dport", "8081", "-s", "2001:db8::2", "-j", "CNI-HOSTPORT-SETMARK"},
|
{"-p", "tcp", "--dport", "8081", "-s", "2001:db8::2/64", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "tcp", "--dport", "8081", "-j", "DNAT", "--to-destination", "[2001:db8::2]:80"},
|
{"-p", "tcp", "--dport", "8081", "-j", "DNAT", "--to-destination", "[2001:db8::2]:80"},
|
||||||
{"-p", "udp", "--dport", "8080", "-s", "2001:db8::2", "-j", "CNI-HOSTPORT-SETMARK"},
|
// udp rules and not hostIP
|
||||||
|
{"-p", "udp", "--dport", "8080", "-s", "2001:db8::2/64", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "udp", "--dport", "8080", "-j", "DNAT", "--to-destination", "[2001:db8::2]:81"},
|
{"-p", "udp", "--dport", "8080", "-j", "DNAT", "--to-destination", "[2001:db8::2]:81"},
|
||||||
{"-p", "udp", "--dport", "8082", "-s", "2001:db8::2", "-j", "CNI-HOSTPORT-SETMARK"},
|
{"-p", "udp", "--dport", "8082", "-s", "2001:db8::2/64", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
{"-p", "udp", "--dport", "8082", "-j", "DNAT", "--to-destination", "[2001:db8::2]:82"},
|
{"-p", "udp", "--dport", "8082", "-j", "DNAT", "--to-destination", "[2001:db8::2]:82"},
|
||||||
|
// tcp rules and hostIP
|
||||||
|
{"-p", "tcp", "--dport", "8085", "-d", "2001:db8:a::1", "-s", "2001:db8::2/64", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
|
{"-p", "tcp", "--dport", "8085", "-d", "2001:db8:a::1", "-j", "DNAT", "--to-destination", "[2001:db8::2]:85"},
|
||||||
|
// tcp rules and hostIP = "::"
|
||||||
|
{"-p", "tcp", "--dport", "8086", "-s", "2001:db8::2/64", "-j", "CNI-HOSTPORT-SETMARK"},
|
||||||
|
{"-p", "tcp", "--dport", "8086", "-j", "DNAT", "--to-destination", "[2001:db8::2]:86"},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Disable snat, generate rules
|
// Disable snat, generate rules
|
||||||
@ -240,12 +267,15 @@ var _ = Describe("portmapping configuration", func() {
|
|||||||
fvar := false
|
fvar := false
|
||||||
conf.SNAT = &fvar
|
conf.SNAT = &fvar
|
||||||
|
|
||||||
fillDnatRules(&ch, conf, net.ParseIP("10.0.0.2"))
|
n, err = types.ParseCIDR("10.0.0.2/24")
|
||||||
|
fillDnatRules(&ch, conf, *n)
|
||||||
Expect(ch.rules).To(Equal([][]string{
|
Expect(ch.rules).To(Equal([][]string{
|
||||||
{"-p", "tcp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
{"-p", "tcp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
||||||
{"-p", "tcp", "--dport", "8081", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
{"-p", "tcp", "--dport", "8081", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
||||||
{"-p", "udp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:81"},
|
{"-p", "udp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:81"},
|
||||||
{"-p", "udp", "--dport", "8082", "-j", "DNAT", "--to-destination", "10.0.0.2:82"},
|
{"-p", "udp", "--dport", "8082", "-j", "DNAT", "--to-destination", "10.0.0.2:82"},
|
||||||
|
{"-p", "tcp", "--dport", "8083", "-d", "192.168.0.2", "-j", "DNAT", "--to-destination", "10.0.0.2:83"},
|
||||||
|
{"-p", "tcp", "--dport", "8084", "-j", "DNAT", "--to-destination", "10.0.0.2:84"},
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -276,9 +306,10 @@ var _ = Describe("portmapping configuration", func() {
|
|||||||
conf.ContainerID = containerID
|
conf.ContainerID = containerID
|
||||||
|
|
||||||
ch = genDnatChain(conf.Name, containerID)
|
ch = genDnatChain(conf.Name, containerID)
|
||||||
fillDnatRules(&ch, conf, net.ParseIP("10.0.0.2"))
|
n, err := types.ParseCIDR("10.0.0.2/24")
|
||||||
|
fillDnatRules(&ch, conf, *n)
|
||||||
Expect(ch.rules).To(Equal([][]string{
|
Expect(ch.rules).To(Equal([][]string{
|
||||||
{"-p", "tcp", "--dport", "8080", "-s", "10.0.0.2", "-j", "PLZ-SET-MARK"},
|
{"-p", "tcp", "--dport", "8080", "-s", "10.0.0.2/24", "-j", "PLZ-SET-MARK"},
|
||||||
{"-p", "tcp", "--dport", "8080", "-s", "127.0.0.1", "-j", "PLZ-SET-MARK"},
|
{"-p", "tcp", "--dport", "8080", "-s", "127.0.0.1", "-j", "PLZ-SET-MARK"},
|
||||||
{"-p", "tcp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
{"-p", "tcp", "--dport", "8080", "-j", "DNAT", "--to-destination", "10.0.0.2:80"},
|
||||||
}))
|
}))
|
||||||
|
@ -237,7 +237,7 @@ func doRoutes(ipCfgs []*current.IPConfig, origRoutes []*types.Route, iface strin
|
|||||||
if ipCfg.Version == "4" {
|
if ipCfg.Version == "4" {
|
||||||
src.Mask = net.CIDRMask(32, 32)
|
src.Mask = net.CIDRMask(32, 32)
|
||||||
} else {
|
} else {
|
||||||
src.Mask = net.CIDRMask(64, 64)
|
src.Mask = net.CIDRMask(128, 128)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Source to use %s", src.String())
|
log.Printf("Source to use %s", src.String())
|
||||||
@ -258,7 +258,7 @@ func doRoutes(ipCfgs []*current.IPConfig, origRoutes []*types.Route, iface strin
|
|||||||
dest.Mask = net.CIDRMask(0, 32)
|
dest.Mask = net.CIDRMask(0, 32)
|
||||||
} else {
|
} else {
|
||||||
dest.IP = net.IPv6zero
|
dest.IP = net.IPv6zero
|
||||||
dest.Mask = net.CIDRMask(0, 64)
|
dest.Mask = net.CIDRMask(0, 128)
|
||||||
}
|
}
|
||||||
|
|
||||||
route := netlink.Route{
|
route := netlink.Route{
|
||||||
@ -296,6 +296,10 @@ func doRoutes(ipCfgs []*current.IPConfig, origRoutes []*types.Route, iface strin
|
|||||||
|
|
||||||
route.Table = table
|
route.Table = table
|
||||||
|
|
||||||
|
// Reset the route flags since if it is dynamically created,
|
||||||
|
// adding it to the new table will fail with "invalid argument"
|
||||||
|
route.Flags = 0
|
||||||
|
|
||||||
// We use route replace in case the route already exists, which
|
// We use route replace in case the route already exists, which
|
||||||
// is possible for the default gateway we added above.
|
// is possible for the default gateway we added above.
|
||||||
err = netlink.RouteReplace(&route)
|
err = netlink.RouteReplace(&route)
|
||||||
|
@ -16,12 +16,12 @@ rm -Rf ${SRC_DIR}/${RELEASE_DIR}
|
|||||||
mkdir -p ${SRC_DIR}/${RELEASE_DIR}
|
mkdir -p ${SRC_DIR}/${RELEASE_DIR}
|
||||||
mkdir -p ${OUTPUT_DIR}
|
mkdir -p ${OUTPUT_DIR}
|
||||||
|
|
||||||
$DOCKER run -ti -v ${SRC_DIR}:/go/src/github.com/containernetworking/plugins --rm golang:1.12-alpine \
|
$DOCKER run -ti -v ${SRC_DIR}:/go/src/github.com/containernetworking/plugins --rm golang:1.14-alpine \
|
||||||
/bin/sh -xe -c "\
|
/bin/sh -xe -c "\
|
||||||
apk --no-cache add bash tar;
|
apk --no-cache add bash tar;
|
||||||
cd /go/src/github.com/containernetworking/plugins; umask 0022;
|
cd /go/src/github.com/containernetworking/plugins; umask 0022;
|
||||||
|
|
||||||
for arch in amd64 arm arm64 ppc64le s390x; do \
|
for arch in amd64 arm arm64 ppc64le s390x mips64le; do \
|
||||||
rm -f ${OUTPUT_DIR}/*; \
|
rm -f ${OUTPUT_DIR}/*; \
|
||||||
CGO_ENABLED=0 GOARCH=\$arch ./build_linux.sh ${BUILDFLAGS}; \
|
CGO_ENABLED=0 GOARCH=\$arch ./build_linux.sh ${BUILDFLAGS}; \
|
||||||
for format in tgz; do \
|
for format in tgz; do \
|
||||||
|
943
vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go
generated
vendored
943
vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go
generated
vendored
@ -1,943 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
mksyscall_windows generates windows system call bodies
|
|
||||||
|
|
||||||
It parses all files specified on command line containing function
|
|
||||||
prototypes (like syscall_windows.go) and prints system call bodies
|
|
||||||
to standard output.
|
|
||||||
|
|
||||||
The prototypes are marked by lines beginning with "//sys" and read
|
|
||||||
like func declarations if //sys is replaced by func, but:
|
|
||||||
|
|
||||||
* The parameter lists must give a name for each argument. This
|
|
||||||
includes return parameters.
|
|
||||||
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
|
|
||||||
* If the return parameter is an error number, it must be named err.
|
|
||||||
|
|
||||||
* If go func name needs to be different from it's winapi dll name,
|
|
||||||
the winapi name could be specified at the end, after "=" sign, like
|
|
||||||
//sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA
|
|
||||||
|
|
||||||
* Each function that returns err needs to supply a condition, that
|
|
||||||
return value of winapi will be tested against to detect failure.
|
|
||||||
This would set err to windows "last-error", otherwise it will be nil.
|
|
||||||
The value can be provided at end of //sys declaration, like
|
|
||||||
//sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA
|
|
||||||
and is [failretval==0] by default.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
mksyscall_windows [flags] [path ...]
|
|
||||||
|
|
||||||
The flags are:
|
|
||||||
-output
|
|
||||||
Specify output file name (outputs to console if blank).
|
|
||||||
-trace
|
|
||||||
Generate print statement after every syscall.
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
|
||||||
printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall")
|
|
||||||
systemDLL = flag.Bool("systemdll", true, "whether all DLLs should be loaded from the Windows system directory")
|
|
||||||
winio = flag.Bool("winio", false, "import go-winio")
|
|
||||||
)
|
|
||||||
|
|
||||||
func trim(s string) string {
|
|
||||||
return strings.Trim(s, " \t")
|
|
||||||
}
|
|
||||||
|
|
||||||
var packageName string
|
|
||||||
|
|
||||||
func packagename() string {
|
|
||||||
return packageName
|
|
||||||
}
|
|
||||||
|
|
||||||
func syscalldot() string {
|
|
||||||
if packageName == "syscall" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return "syscall."
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
fn *Fn
|
|
||||||
tmpVarIdx int
|
|
||||||
}
|
|
||||||
|
|
||||||
// tmpVar returns temp variable name that will be used to represent p during syscall.
|
|
||||||
func (p *Param) tmpVar() string {
|
|
||||||
if p.tmpVarIdx < 0 {
|
|
||||||
p.tmpVarIdx = p.fn.curTmpVarIdx
|
|
||||||
p.fn.curTmpVarIdx++
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("_p%d", p.tmpVarIdx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolTmpVarCode returns source code for bool temp variable.
|
|
||||||
func (p *Param) BoolTmpVarCode() string {
|
|
||||||
const code = `var %s uint32
|
|
||||||
if %s {
|
|
||||||
%s = 1
|
|
||||||
} else {
|
|
||||||
%s = 0
|
|
||||||
}`
|
|
||||||
tmp := p.tmpVar()
|
|
||||||
return fmt.Sprintf(code, tmp, p.Name, tmp, tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SliceTmpVarCode returns source code for slice temp variable.
|
|
||||||
func (p *Param) SliceTmpVarCode() string {
|
|
||||||
const code = `var %s *%s
|
|
||||||
if len(%s) > 0 {
|
|
||||||
%s = &%s[0]
|
|
||||||
}`
|
|
||||||
tmp := p.tmpVar()
|
|
||||||
return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringTmpVarCode returns source code for string temp variable.
|
|
||||||
func (p *Param) StringTmpVarCode() string {
|
|
||||||
errvar := p.fn.Rets.ErrorVarName()
|
|
||||||
if errvar == "" {
|
|
||||||
errvar = "_"
|
|
||||||
}
|
|
||||||
tmp := p.tmpVar()
|
|
||||||
const code = `var %s %s
|
|
||||||
%s, %s = %s(%s)`
|
|
||||||
s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name)
|
|
||||||
if errvar == "-" {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
const morecode = `
|
|
||||||
if %s != nil {
|
|
||||||
return
|
|
||||||
}`
|
|
||||||
return s + fmt.Sprintf(morecode, errvar)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TmpVarCode returns source code for temp variable.
|
|
||||||
func (p *Param) TmpVarCode() string {
|
|
||||||
switch {
|
|
||||||
case p.Type == "bool":
|
|
||||||
return p.BoolTmpVarCode()
|
|
||||||
case strings.HasPrefix(p.Type, "[]"):
|
|
||||||
return p.SliceTmpVarCode()
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TmpVarHelperCode returns source code for helper's temp variable.
|
|
||||||
func (p *Param) TmpVarHelperCode() string {
|
|
||||||
if p.Type != "string" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return p.StringTmpVarCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyscallArgList returns source code fragments representing p parameter
|
|
||||||
// in syscall. Slices are translated into 2 syscall parameters: pointer to
|
|
||||||
// the first element and length.
|
|
||||||
func (p *Param) SyscallArgList() []string {
|
|
||||||
t := p.HelperType()
|
|
||||||
var s string
|
|
||||||
switch {
|
|
||||||
case t[0] == '*':
|
|
||||||
s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name)
|
|
||||||
case t == "bool":
|
|
||||||
s = p.tmpVar()
|
|
||||||
case strings.HasPrefix(t, "[]"):
|
|
||||||
return []string{
|
|
||||||
fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()),
|
|
||||||
fmt.Sprintf("uintptr(len(%s))", p.Name),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
s = p.Name
|
|
||||||
}
|
|
||||||
return []string{fmt.Sprintf("uintptr(%s)", s)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsError determines if p parameter is used to return error.
|
|
||||||
func (p *Param) IsError() bool {
|
|
||||||
return p.Name == "err" && p.Type == "error"
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelperType returns type of parameter p used in helper function.
|
|
||||||
func (p *Param) HelperType() string {
|
|
||||||
if p.Type == "string" {
|
|
||||||
return p.fn.StrconvType()
|
|
||||||
}
|
|
||||||
return p.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
// join concatenates parameters ps into a string with sep separator.
|
|
||||||
// Each parameter is converted into string by applying fn to it
|
|
||||||
// before conversion.
|
|
||||||
func join(ps []*Param, fn func(*Param) string, sep string) string {
|
|
||||||
if len(ps) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
a := make([]string, 0)
|
|
||||||
for _, p := range ps {
|
|
||||||
a = append(a, fn(p))
|
|
||||||
}
|
|
||||||
return strings.Join(a, sep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rets describes function return parameters.
|
|
||||||
type Rets struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
ReturnsError bool
|
|
||||||
FailCond string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorVarName returns error variable name for r.
|
|
||||||
func (r *Rets) ErrorVarName() string {
|
|
||||||
if r.ReturnsError {
|
|
||||||
return "err"
|
|
||||||
}
|
|
||||||
if r.Type == "error" {
|
|
||||||
return r.Name
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToParams converts r into slice of *Param.
|
|
||||||
func (r *Rets) ToParams() []*Param {
|
|
||||||
ps := make([]*Param, 0)
|
|
||||||
if len(r.Name) > 0 {
|
|
||||||
ps = append(ps, &Param{Name: r.Name, Type: r.Type})
|
|
||||||
}
|
|
||||||
if r.ReturnsError {
|
|
||||||
ps = append(ps, &Param{Name: "err", Type: "error"})
|
|
||||||
}
|
|
||||||
return ps
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns source code of syscall return parameters.
|
|
||||||
func (r *Rets) List() string {
|
|
||||||
s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
|
||||||
if len(s) > 0 {
|
|
||||||
s = "(" + s + ")"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrintList returns source code of trace printing part correspondent
|
|
||||||
// to syscall return values.
|
|
||||||
func (r *Rets) PrintList() string {
|
|
||||||
return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetReturnValuesCode returns source code that accepts syscall return values.
|
|
||||||
func (r *Rets) SetReturnValuesCode() string {
|
|
||||||
if r.Name == "" && !r.ReturnsError {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
retvar := "r0"
|
|
||||||
if r.Name == "" {
|
|
||||||
retvar = "r1"
|
|
||||||
}
|
|
||||||
errvar := "_"
|
|
||||||
if r.ReturnsError {
|
|
||||||
errvar = "e1"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s, _, %s := ", retvar, errvar)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Rets) useLongHandleErrorCode(retvar string) string {
|
|
||||||
const code = `if %s {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
} else {
|
|
||||||
err = %sEINVAL
|
|
||||||
}
|
|
||||||
}`
|
|
||||||
cond := retvar + " == 0"
|
|
||||||
if r.FailCond != "" {
|
|
||||||
cond = strings.Replace(r.FailCond, "failretval", retvar, 1)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(code, cond, syscalldot())
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetErrorCode returns source code that sets return parameters.
|
|
||||||
func (r *Rets) SetErrorCode() string {
|
|
||||||
const code = `if r0 != 0 {
|
|
||||||
%s = %sErrno(r0)
|
|
||||||
}`
|
|
||||||
const hrCode = `if int32(r0) < 0 {
|
|
||||||
if r0&0x1fff0000 == 0x00070000 {
|
|
||||||
r0 &= 0xffff
|
|
||||||
}
|
|
||||||
%s = %sErrno(r0)
|
|
||||||
}`
|
|
||||||
if r.Name == "" && !r.ReturnsError {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if r.Name == "" {
|
|
||||||
return r.useLongHandleErrorCode("r1")
|
|
||||||
}
|
|
||||||
if r.Type == "error" {
|
|
||||||
if r.Name == "hr" {
|
|
||||||
return fmt.Sprintf(hrCode, r.Name, syscalldot())
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf(code, r.Name, syscalldot())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s := ""
|
|
||||||
switch {
|
|
||||||
case r.Type[0] == '*':
|
|
||||||
s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type)
|
|
||||||
case r.Type == "bool":
|
|
||||||
s = fmt.Sprintf("%s = r0 != 0", r.Name)
|
|
||||||
default:
|
|
||||||
s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type)
|
|
||||||
}
|
|
||||||
if !r.ReturnsError {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return s + "\n\t" + r.useLongHandleErrorCode(r.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fn describes syscall function.
|
|
||||||
type Fn struct {
|
|
||||||
Name string
|
|
||||||
Params []*Param
|
|
||||||
Rets *Rets
|
|
||||||
PrintTrace bool
|
|
||||||
confirmproc bool
|
|
||||||
dllname string
|
|
||||||
dllfuncname string
|
|
||||||
src string
|
|
||||||
// TODO: get rid of this field and just use parameter index instead
|
|
||||||
curTmpVarIdx int // insure tmp variables have uniq names
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractParams parses s to extract function parameters.
|
|
||||||
func extractParams(s string, f *Fn) ([]*Param, error) {
|
|
||||||
s = trim(s)
|
|
||||||
if s == "" {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
a := strings.Split(s, ",")
|
|
||||||
ps := make([]*Param, len(a))
|
|
||||||
for i := range ps {
|
|
||||||
s2 := trim(a[i])
|
|
||||||
b := strings.Split(s2, " ")
|
|
||||||
if len(b) != 2 {
|
|
||||||
b = strings.Split(s2, "\t")
|
|
||||||
if len(b) != 2 {
|
|
||||||
return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ps[i] = &Param{
|
|
||||||
Name: trim(b[0]),
|
|
||||||
Type: trim(b[1]),
|
|
||||||
fn: f,
|
|
||||||
tmpVarIdx: -1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ps, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractSection extracts text out of string s starting after start
|
|
||||||
// and ending just before end. found return value will indicate success,
|
|
||||||
// and prefix, body and suffix will contain correspondent parts of string s.
|
|
||||||
func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) {
|
|
||||||
s = trim(s)
|
|
||||||
if strings.HasPrefix(s, string(start)) {
|
|
||||||
// no prefix
|
|
||||||
body = s[1:]
|
|
||||||
} else {
|
|
||||||
a := strings.SplitN(s, string(start), 2)
|
|
||||||
if len(a) != 2 {
|
|
||||||
return "", "", s, false
|
|
||||||
}
|
|
||||||
prefix = a[0]
|
|
||||||
body = a[1]
|
|
||||||
}
|
|
||||||
a := strings.SplitN(body, string(end), 2)
|
|
||||||
if len(a) != 2 {
|
|
||||||
return "", "", "", false
|
|
||||||
}
|
|
||||||
return prefix, a[0], a[1], true
|
|
||||||
}
|
|
||||||
|
|
||||||
// newFn parses string s and return created function Fn.
|
|
||||||
func newFn(s string) (*Fn, error) {
|
|
||||||
s = trim(s)
|
|
||||||
f := &Fn{
|
|
||||||
Rets: &Rets{},
|
|
||||||
src: s,
|
|
||||||
PrintTrace: *printTraceFlag,
|
|
||||||
}
|
|
||||||
// function name and args
|
|
||||||
prefix, body, s, found := extractSection(s, '(', ')')
|
|
||||||
if !found || prefix == "" {
|
|
||||||
return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
f.Name = prefix
|
|
||||||
var err error
|
|
||||||
f.Params, err = extractParams(body, f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// return values
|
|
||||||
_, body, s, found = extractSection(s, '(', ')')
|
|
||||||
if found {
|
|
||||||
r, err := extractParams(body, f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch len(r) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
if r[0].IsError() {
|
|
||||||
f.Rets.ReturnsError = true
|
|
||||||
} else {
|
|
||||||
f.Rets.Name = r[0].Name
|
|
||||||
f.Rets.Type = r[0].Type
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
if !r[1].IsError() {
|
|
||||||
return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
f.Rets.ReturnsError = true
|
|
||||||
f.Rets.Name = r[0].Name
|
|
||||||
f.Rets.Type = r[0].Type
|
|
||||||
default:
|
|
||||||
return nil, errors.New("Too many return values in \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fail condition
|
|
||||||
_, body, s, found = extractSection(s, '[', ']')
|
|
||||||
if found {
|
|
||||||
f.Rets.FailCond = body
|
|
||||||
}
|
|
||||||
// dll and dll function names
|
|
||||||
s = trim(s)
|
|
||||||
if s == "" {
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(s, "=") {
|
|
||||||
return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
s = trim(s[1:])
|
|
||||||
a := strings.Split(s, ".")
|
|
||||||
switch len(a) {
|
|
||||||
case 1:
|
|
||||||
f.dllfuncname = a[0]
|
|
||||||
case 2:
|
|
||||||
f.dllname = a[0]
|
|
||||||
f.dllfuncname = a[1]
|
|
||||||
default:
|
|
||||||
return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
|
|
||||||
}
|
|
||||||
if f.dllfuncname[len(f.dllfuncname)-1] == '?' {
|
|
||||||
f.confirmproc = true
|
|
||||||
f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1]
|
|
||||||
}
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DLLName returns DLL name for function f.
|
|
||||||
func (f *Fn) DLLName() string {
|
|
||||||
if f.dllname == "" {
|
|
||||||
return "kernel32"
|
|
||||||
}
|
|
||||||
return f.dllname
|
|
||||||
}
|
|
||||||
|
|
||||||
// DLLName returns DLL function name for function f.
|
|
||||||
func (f *Fn) DLLFuncName() string {
|
|
||||||
if f.dllfuncname == "" {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
return f.dllfuncname
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Fn) ConfirmProc() bool {
|
|
||||||
return f.confirmproc
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamList returns source code for function f parameters.
|
|
||||||
func (f *Fn) ParamList() string {
|
|
||||||
return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelperParamList returns source code for helper function f parameters.
|
|
||||||
func (f *Fn) HelperParamList() string {
|
|
||||||
return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamPrintList returns source code of trace printing part correspondent
|
|
||||||
// to syscall input parameters.
|
|
||||||
func (f *Fn) ParamPrintList() string {
|
|
||||||
return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamCount return number of syscall parameters for function f.
|
|
||||||
func (f *Fn) ParamCount() int {
|
|
||||||
n := 0
|
|
||||||
for _, p := range f.Params {
|
|
||||||
n += len(p.SyscallArgList())
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/...
|
|
||||||
// to use. It returns parameter count for correspondent SyscallX function.
|
|
||||||
func (f *Fn) SyscallParamCount() int {
|
|
||||||
n := f.ParamCount()
|
|
||||||
switch {
|
|
||||||
case n <= 3:
|
|
||||||
return 3
|
|
||||||
case n <= 6:
|
|
||||||
return 6
|
|
||||||
case n <= 9:
|
|
||||||
return 9
|
|
||||||
case n <= 12:
|
|
||||||
return 12
|
|
||||||
case n <= 15:
|
|
||||||
return 15
|
|
||||||
default:
|
|
||||||
panic("too many arguments to system call")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Syscall determines which SyscallX function to use for function f.
|
|
||||||
func (f *Fn) Syscall() string {
|
|
||||||
c := f.SyscallParamCount()
|
|
||||||
if c == 3 {
|
|
||||||
return syscalldot() + "Syscall"
|
|
||||||
}
|
|
||||||
return syscalldot() + "Syscall" + strconv.Itoa(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyscallParamList returns source code for SyscallX parameters for function f.
|
|
||||||
func (f *Fn) SyscallParamList() string {
|
|
||||||
a := make([]string, 0)
|
|
||||||
for _, p := range f.Params {
|
|
||||||
a = append(a, p.SyscallArgList()...)
|
|
||||||
}
|
|
||||||
for len(a) < f.SyscallParamCount() {
|
|
||||||
a = append(a, "0")
|
|
||||||
}
|
|
||||||
return strings.Join(a, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelperCallParamList returns source code of call into function f helper.
|
|
||||||
func (f *Fn) HelperCallParamList() string {
|
|
||||||
a := make([]string, 0, len(f.Params))
|
|
||||||
for _, p := range f.Params {
|
|
||||||
s := p.Name
|
|
||||||
if p.Type == "string" {
|
|
||||||
s = p.tmpVar()
|
|
||||||
}
|
|
||||||
a = append(a, s)
|
|
||||||
}
|
|
||||||
return strings.Join(a, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUTF16 is true, if f is W (utf16) function. It is false
|
|
||||||
// for all A (ascii) functions.
|
|
||||||
func (_ *Fn) IsUTF16() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrconvFunc returns name of Go string to OS string function for f.
|
|
||||||
func (f *Fn) StrconvFunc() string {
|
|
||||||
if f.IsUTF16() {
|
|
||||||
return syscalldot() + "UTF16PtrFromString"
|
|
||||||
}
|
|
||||||
return syscalldot() + "BytePtrFromString"
|
|
||||||
}
|
|
||||||
|
|
||||||
// StrconvType returns Go type name used for OS string for f.
|
|
||||||
func (f *Fn) StrconvType() string {
|
|
||||||
if f.IsUTF16() {
|
|
||||||
return "*uint16"
|
|
||||||
}
|
|
||||||
return "*byte"
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasStringParam is true, if f has at least one string parameter.
|
|
||||||
// Otherwise it is false.
|
|
||||||
func (f *Fn) HasStringParam() bool {
|
|
||||||
for _, p := range f.Params {
|
|
||||||
if p.Type == "string" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var uniqDllFuncName = make(map[string]bool)
|
|
||||||
|
|
||||||
// IsNotDuplicate is true if f is not a duplicated function
|
|
||||||
func (f *Fn) IsNotDuplicate() bool {
|
|
||||||
funcName := f.DLLFuncName()
|
|
||||||
if uniqDllFuncName[funcName] == false {
|
|
||||||
uniqDllFuncName[funcName] = true
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelperName returns name of function f helper.
|
|
||||||
func (f *Fn) HelperName() string {
|
|
||||||
if !f.HasStringParam() {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
return "_" + f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Source files and functions.
|
|
||||||
type Source struct {
|
|
||||||
Funcs []*Fn
|
|
||||||
Files []string
|
|
||||||
StdLibImports []string
|
|
||||||
ExternalImports []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (src *Source) Import(pkg string) {
|
|
||||||
src.StdLibImports = append(src.StdLibImports, pkg)
|
|
||||||
sort.Strings(src.StdLibImports)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (src *Source) ExternalImport(pkg string) {
|
|
||||||
src.ExternalImports = append(src.ExternalImports, pkg)
|
|
||||||
sort.Strings(src.ExternalImports)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseFiles parses files listed in fs and extracts all syscall
|
|
||||||
// functions listed in sys comments. It returns source files
|
|
||||||
// and functions collection *Source if successful.
|
|
||||||
func ParseFiles(fs []string) (*Source, error) {
|
|
||||||
src := &Source{
|
|
||||||
Funcs: make([]*Fn, 0),
|
|
||||||
Files: make([]string, 0),
|
|
||||||
StdLibImports: []string{
|
|
||||||
"unsafe",
|
|
||||||
},
|
|
||||||
ExternalImports: make([]string, 0),
|
|
||||||
}
|
|
||||||
for _, file := range fs {
|
|
||||||
if err := src.ParseFile(file); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return src, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DLLs return dll names for a source set src.
|
|
||||||
func (src *Source) DLLs() []string {
|
|
||||||
uniq := make(map[string]bool)
|
|
||||||
r := make([]string, 0)
|
|
||||||
for _, f := range src.Funcs {
|
|
||||||
name := f.DLLName()
|
|
||||||
if _, found := uniq[name]; !found {
|
|
||||||
uniq[name] = true
|
|
||||||
r = append(r, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseFile adds additional file path to a source set src.
|
|
||||||
func (src *Source) ParseFile(path string) error {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := trim(s.Text())
|
|
||||||
if len(t) < 7 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(t, "//sys") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t = t[5:]
|
|
||||||
if !(t[0] == ' ' || t[0] == '\t') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f, err := newFn(t[1:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
src.Funcs = append(src.Funcs, f)
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
src.Files = append(src.Files, path)
|
|
||||||
|
|
||||||
// get package name
|
|
||||||
fset := token.NewFileSet()
|
|
||||||
_, err = file.Seek(0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
packageName = pkg.Name.Name
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsStdRepo returns true if src is part of standard library.
|
|
||||||
func (src *Source) IsStdRepo() (bool, error) {
|
|
||||||
if len(src.Files) == 0 {
|
|
||||||
return false, errors.New("no input files provided")
|
|
||||||
}
|
|
||||||
abspath, err := filepath.Abs(src.Files[0])
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
goroot := runtime.GOROOT()
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
abspath = strings.ToLower(abspath)
|
|
||||||
goroot = strings.ToLower(goroot)
|
|
||||||
}
|
|
||||||
sep := string(os.PathSeparator)
|
|
||||||
if !strings.HasSuffix(goroot, sep) {
|
|
||||||
goroot += sep
|
|
||||||
}
|
|
||||||
return strings.HasPrefix(abspath, goroot), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate output source file from a source set src.
|
|
||||||
func (src *Source) Generate(w io.Writer) error {
|
|
||||||
const (
|
|
||||||
pkgStd = iota // any package in std library
|
|
||||||
pkgXSysWindows // x/sys/windows package
|
|
||||||
pkgOther
|
|
||||||
)
|
|
||||||
isStdRepo, err := src.IsStdRepo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var pkgtype int
|
|
||||||
switch {
|
|
||||||
case isStdRepo:
|
|
||||||
pkgtype = pkgStd
|
|
||||||
case packageName == "windows":
|
|
||||||
// TODO: this needs better logic than just using package name
|
|
||||||
pkgtype = pkgXSysWindows
|
|
||||||
default:
|
|
||||||
pkgtype = pkgOther
|
|
||||||
}
|
|
||||||
if *systemDLL {
|
|
||||||
switch pkgtype {
|
|
||||||
case pkgStd:
|
|
||||||
src.Import("internal/syscall/windows/sysdll")
|
|
||||||
case pkgXSysWindows:
|
|
||||||
default:
|
|
||||||
src.ExternalImport("golang.org/x/sys/windows")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if *winio {
|
|
||||||
src.ExternalImport("github.com/Microsoft/go-winio")
|
|
||||||
}
|
|
||||||
if packageName != "syscall" {
|
|
||||||
src.Import("syscall")
|
|
||||||
}
|
|
||||||
funcMap := template.FuncMap{
|
|
||||||
"packagename": packagename,
|
|
||||||
"syscalldot": syscalldot,
|
|
||||||
"newlazydll": func(dll string) string {
|
|
||||||
arg := "\"" + dll + ".dll\""
|
|
||||||
if !*systemDLL {
|
|
||||||
return syscalldot() + "NewLazyDLL(" + arg + ")"
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(dll, "api_") || strings.HasPrefix(dll, "ext_") {
|
|
||||||
arg = strings.Replace(arg, "_", "-", -1)
|
|
||||||
}
|
|
||||||
switch pkgtype {
|
|
||||||
case pkgStd:
|
|
||||||
return syscalldot() + "NewLazyDLL(sysdll.Add(" + arg + "))"
|
|
||||||
case pkgXSysWindows:
|
|
||||||
return "NewLazySystemDLL(" + arg + ")"
|
|
||||||
default:
|
|
||||||
return "windows.NewLazySystemDLL(" + arg + ")"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
|
|
||||||
err = t.Execute(w, src)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("Failed to execute template: " + err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n")
|
|
||||||
flag.PrintDefaults()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
src, err := ParseFiles(flag.Args())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := src.Generate(&buf); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := format.Source(buf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if *filename == "" {
|
|
||||||
_, err = os.Stdout.Write(data)
|
|
||||||
} else {
|
|
||||||
err = ioutil.WriteFile(*filename, data, 0644)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: use println instead to print in the following template
|
|
||||||
const srcTemplate = `
|
|
||||||
|
|
||||||
{{define "main"}}// Code generated mksyscall_windows.exe DO NOT EDIT
|
|
||||||
|
|
||||||
package {{packagename}}
|
|
||||||
|
|
||||||
import (
|
|
||||||
{{range .StdLibImports}}"{{.}}"
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{range .ExternalImports}}"{{.}}"
|
|
||||||
{{end}}
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ unsafe.Pointer
|
|
||||||
|
|
||||||
// Do the interface allocations only once for common
|
|
||||||
// Errno values.
|
|
||||||
const (
|
|
||||||
errnoERROR_IO_PENDING = 997
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errERROR_IO_PENDING error = {{syscalldot}}Errno(errnoERROR_IO_PENDING)
|
|
||||||
)
|
|
||||||
|
|
||||||
// errnoErr returns common boxed Errno values, to prevent
|
|
||||||
// allocations at runtime.
|
|
||||||
func errnoErr(e {{syscalldot}}Errno) error {
|
|
||||||
switch e {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case errnoERROR_IO_PENDING:
|
|
||||||
return errERROR_IO_PENDING
|
|
||||||
}
|
|
||||||
// TODO: add more here, after collecting data on the common
|
|
||||||
// error values see on Windows. (perhaps when running
|
|
||||||
// all.bat?)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
{{template "dlls" .}}
|
|
||||||
{{template "funcnames" .}})
|
|
||||||
{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{/* help functions */}}
|
|
||||||
|
|
||||||
{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{newlazydll .}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "funcnames"}}{{range .Funcs}}{{if .IsNotDuplicate}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}"){{end}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "helperbody"}}
|
|
||||||
func {{.Name}}({{.ParamList}}) {{template "results" .}}{
|
|
||||||
{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}})
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{define "funcbody"}}
|
|
||||||
func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
|
|
||||||
{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}}
|
|
||||||
{{template "seterror" .}}{{template "printtrace" .}} return
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}}
|
|
||||||
{{end}}{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}}
|
|
||||||
{{end}}{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
|
|
||||||
|
|
||||||
{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
|
|
||||||
{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n")
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
`
|
|
238
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
238
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/invoke"
|
"github.com/containernetworking/cni/pkg/invoke"
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
|
"github.com/containernetworking/cni/pkg/utils"
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,6 +33,10 @@ var (
|
|||||||
CacheDir = "/var/lib/cni"
|
CacheDir = "/var/lib/cni"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CNICacheV1 = "cniCacheV1"
|
||||||
|
)
|
||||||
|
|
||||||
// A RuntimeConf holds the arguments to one invocation of a CNI plugin
|
// A RuntimeConf holds the arguments to one invocation of a CNI plugin
|
||||||
// excepting the network configuration, with the nested exception that
|
// excepting the network configuration, with the nested exception that
|
||||||
// the `runtimeConfig` from the network configuration is included
|
// the `runtimeConfig` from the network configuration is included
|
||||||
@ -48,7 +53,7 @@ type RuntimeConf struct {
|
|||||||
// to the plugin
|
// to the plugin
|
||||||
CapabilityArgs map[string]interface{}
|
CapabilityArgs map[string]interface{}
|
||||||
|
|
||||||
// A cache directory in which to library data. Defaults to CacheDir
|
// DEPRECATED. Will be removed in a future release.
|
||||||
CacheDir string
|
CacheDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,19 +75,22 @@ type CNI interface {
|
|||||||
CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
|
CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
|
||||||
DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
|
DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
|
||||||
GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
|
GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
|
||||||
|
GetNetworkListCachedConfig(net *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error)
|
||||||
|
|
||||||
AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
||||||
CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
|
CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
|
||||||
DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
|
DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
|
||||||
GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
||||||
|
GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error)
|
||||||
|
|
||||||
ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
|
ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
|
||||||
ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
|
ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CNIConfig struct {
|
type CNIConfig struct {
|
||||||
Path []string
|
Path []string
|
||||||
exec invoke.Exec
|
exec invoke.Exec
|
||||||
|
cacheDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CNIConfig implements the CNI interface
|
// CNIConfig implements the CNI interface
|
||||||
@ -92,9 +100,18 @@ var _ CNI = &CNIConfig{}
|
|||||||
// in the given paths and use the given exec interface to run those plugins,
|
// in the given paths and use the given exec interface to run those plugins,
|
||||||
// or if the exec interface is not given, will use a default exec handler.
|
// or if the exec interface is not given, will use a default exec handler.
|
||||||
func NewCNIConfig(path []string, exec invoke.Exec) *CNIConfig {
|
func NewCNIConfig(path []string, exec invoke.Exec) *CNIConfig {
|
||||||
|
return NewCNIConfigWithCacheDir(path, "", exec)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCNIConfigWithCacheDir returns a new CNIConfig object that will search for plugins
|
||||||
|
// in the given paths use the given exec interface to run those plugins,
|
||||||
|
// or if the exec interface is not given, will use a default exec handler.
|
||||||
|
// The given cache directory will be used for temporary data storage when needed.
|
||||||
|
func NewCNIConfigWithCacheDir(path []string, cacheDir string, exec invoke.Exec) *CNIConfig {
|
||||||
return &CNIConfig{
|
return &CNIConfig{
|
||||||
Path: path,
|
Path: path,
|
||||||
exec: exec,
|
cacheDir: cacheDir,
|
||||||
|
exec: exec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,33 +182,122 @@ func (c *CNIConfig) ensureExec() invoke.Exec {
|
|||||||
return c.exec
|
return c.exec
|
||||||
}
|
}
|
||||||
|
|
||||||
func getResultCacheFilePath(netName string, rt *RuntimeConf) string {
|
type cachedInfo struct {
|
||||||
cacheDir := rt.CacheDir
|
Kind string `json:"kind"`
|
||||||
if cacheDir == "" {
|
ContainerID string `json:"containerId"`
|
||||||
cacheDir = CacheDir
|
Config []byte `json:"config"`
|
||||||
}
|
IfName string `json:"ifName"`
|
||||||
return filepath.Join(cacheDir, "results", fmt.Sprintf("%s-%s-%s", netName, rt.ContainerID, rt.IfName))
|
NetworkName string `json:"networkName"`
|
||||||
|
CniArgs [][2]string `json:"cniArgs,omitempty"`
|
||||||
|
CapabilityArgs map[string]interface{} `json:"capabilityArgs,omitempty"`
|
||||||
|
RawResult map[string]interface{} `json:"result,omitempty"`
|
||||||
|
Result types.Result `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func setCachedResult(result types.Result, netName string, rt *RuntimeConf) error {
|
// getCacheDir returns the cache directory in this order:
|
||||||
|
// 1) global cacheDir from CNIConfig object
|
||||||
|
// 2) deprecated cacheDir from RuntimeConf object
|
||||||
|
// 3) fall back to default cache directory
|
||||||
|
func (c *CNIConfig) getCacheDir(rt *RuntimeConf) string {
|
||||||
|
if c.cacheDir != "" {
|
||||||
|
return c.cacheDir
|
||||||
|
}
|
||||||
|
if rt.CacheDir != "" {
|
||||||
|
return rt.CacheDir
|
||||||
|
}
|
||||||
|
return CacheDir
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CNIConfig) getCacheFilePath(netName string, rt *RuntimeConf) (string, error) {
|
||||||
|
if netName == "" || rt.ContainerID == "" || rt.IfName == "" {
|
||||||
|
return "", fmt.Errorf("cache file path requires network name (%q), container ID (%q), and interface name (%q)", netName, rt.ContainerID, rt.IfName)
|
||||||
|
}
|
||||||
|
return filepath.Join(c.getCacheDir(rt), "results", fmt.Sprintf("%s-%s-%s", netName, rt.ContainerID, rt.IfName)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CNIConfig) cacheAdd(result types.Result, config []byte, netName string, rt *RuntimeConf) error {
|
||||||
|
cached := cachedInfo{
|
||||||
|
Kind: CNICacheV1,
|
||||||
|
ContainerID: rt.ContainerID,
|
||||||
|
Config: config,
|
||||||
|
IfName: rt.IfName,
|
||||||
|
NetworkName: netName,
|
||||||
|
CniArgs: rt.Args,
|
||||||
|
CapabilityArgs: rt.CapabilityArgs,
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to get type.Result into cachedInfo as JSON map
|
||||||
|
// Marshal to []byte, then Unmarshal into cached.RawResult
|
||||||
data, err := json.Marshal(result)
|
data, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fname := getResultCacheFilePath(netName, rt)
|
|
||||||
|
err = json.Unmarshal(data, &cached.RawResult)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
newBytes, err := json.Marshal(&cached)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fname, err := c.getCacheFilePath(netName, rt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil {
|
if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return ioutil.WriteFile(fname, data, 0600)
|
|
||||||
|
return ioutil.WriteFile(fname, newBytes, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
func delCachedResult(netName string, rt *RuntimeConf) error {
|
func (c *CNIConfig) cacheDel(netName string, rt *RuntimeConf) error {
|
||||||
fname := getResultCacheFilePath(netName, rt)
|
fname, err := c.getCacheFilePath(netName, rt)
|
||||||
|
if err != nil {
|
||||||
|
// Ignore error
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return os.Remove(fname)
|
return os.Remove(fname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) {
|
func (c *CNIConfig) getCachedConfig(netName string, rt *RuntimeConf) ([]byte, *RuntimeConf, error) {
|
||||||
fname := getResultCacheFilePath(netName, rt)
|
var bytes []byte
|
||||||
|
|
||||||
|
fname, err := c.getCacheFilePath(netName, rt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bytes, err = ioutil.ReadFile(fname)
|
||||||
|
if err != nil {
|
||||||
|
// Ignore read errors; the cached result may not exist on-disk
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
unmarshaled := cachedInfo{}
|
||||||
|
if err := json.Unmarshal(bytes, &unmarshaled); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to unmarshal cached network %q config: %v", netName, err)
|
||||||
|
}
|
||||||
|
if unmarshaled.Kind != CNICacheV1 {
|
||||||
|
return nil, nil, fmt.Errorf("read cached network %q config has wrong kind: %v", netName, unmarshaled.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
newRt := *rt
|
||||||
|
if unmarshaled.CniArgs != nil {
|
||||||
|
newRt.Args = unmarshaled.CniArgs
|
||||||
|
}
|
||||||
|
newRt.CapabilityArgs = unmarshaled.CapabilityArgs
|
||||||
|
|
||||||
|
return unmarshaled.Config, &newRt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CNIConfig) getLegacyCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) {
|
||||||
|
fname, err := c.getCacheFilePath(netName, rt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
data, err := ioutil.ReadFile(fname)
|
data, err := ioutil.ReadFile(fname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Ignore read errors; the cached result may not exist on-disk
|
// Ignore read errors; the cached result may not exist on-disk
|
||||||
@ -222,16 +328,73 @@ func getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result,
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) {
|
||||||
|
fname, err := c.getCacheFilePath(netName, rt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fdata, err := ioutil.ReadFile(fname)
|
||||||
|
if err != nil {
|
||||||
|
// Ignore read errors; the cached result may not exist on-disk
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedInfo := cachedInfo{}
|
||||||
|
if err := json.Unmarshal(fdata, &cachedInfo); err != nil || cachedInfo.Kind != CNICacheV1 {
|
||||||
|
return c.getLegacyCachedResult(netName, cniVersion, rt)
|
||||||
|
}
|
||||||
|
|
||||||
|
newBytes, err := json.Marshal(&cachedInfo.RawResult)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to marshal cached network %q config: %v", netName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the version of the cached result
|
||||||
|
decoder := version.ConfigDecoder{}
|
||||||
|
resultCniVersion, err := decoder.Decode(newBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we can understand the result
|
||||||
|
result, err := version.NewResult(resultCniVersion, newBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to the config version to ensure plugins get prevResult
|
||||||
|
// in the same version as the config. The cached result version
|
||||||
|
// should match the config version unless the config was changed
|
||||||
|
// while the container was running.
|
||||||
|
result, err = result.GetAsVersion(cniVersion)
|
||||||
|
if err != nil && resultCniVersion != cniVersion {
|
||||||
|
return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err)
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetNetworkListCachedResult returns the cached Result of the previous
|
// GetNetworkListCachedResult returns the cached Result of the previous
|
||||||
// previous AddNetworkList() operation for a network list, or an error.
|
// AddNetworkList() operation for a network list, or an error.
|
||||||
func (c *CNIConfig) GetNetworkListCachedResult(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
func (c *CNIConfig) GetNetworkListCachedResult(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
||||||
return getCachedResult(list.Name, list.CNIVersion, rt)
|
return c.getCachedResult(list.Name, list.CNIVersion, rt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNetworkCachedResult returns the cached Result of the previous
|
// GetNetworkCachedResult returns the cached Result of the previous
|
||||||
// previous AddNetwork() operation for a network, or an error.
|
// AddNetwork() operation for a network, or an error.
|
||||||
func (c *CNIConfig) GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
|
func (c *CNIConfig) GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
|
||||||
return getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
return c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkListCachedConfig copies the input RuntimeConf to output
|
||||||
|
// RuntimeConf with fields updated with info from the cached Config.
|
||||||
|
func (c *CNIConfig) GetNetworkListCachedConfig(list *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error) {
|
||||||
|
return c.getCachedConfig(list.Name, rt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkCachedConfig copies the input RuntimeConf to output
|
||||||
|
// RuntimeConf with fields updated with info from the cached Config.
|
||||||
|
func (c *CNIConfig) GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error) {
|
||||||
|
return c.getCachedConfig(net.Network.Name, rt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) {
|
func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) {
|
||||||
@ -240,6 +403,15 @@ func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := utils.ValidateContainerID(rt.ContainerID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := utils.ValidateNetworkName(name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := utils.ValidateInterfaceName(rt.IfName); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
|
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -260,7 +432,7 @@ func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = setCachedResult(result, list.Name, rt); err != nil {
|
if err = c.cacheAdd(result, list.Bytes, list.Name, rt); err != nil {
|
||||||
return nil, fmt.Errorf("failed to set network %q cached result: %v", list.Name, err)
|
return nil, fmt.Errorf("failed to set network %q cached result: %v", list.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +467,7 @@ func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigLis
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedResult, err := getCachedResult(list.Name, list.CNIVersion, rt)
|
cachedResult, err := c.getCachedResult(list.Name, list.CNIVersion, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
|
return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
|
||||||
}
|
}
|
||||||
@ -332,7 +504,7 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList,
|
|||||||
if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
|
if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if gtet {
|
} else if gtet {
|
||||||
cachedResult, err = getCachedResult(list.Name, list.CNIVersion, rt)
|
cachedResult, err = c.getCachedResult(list.Name, list.CNIVersion, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
|
return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
|
||||||
}
|
}
|
||||||
@ -344,7 +516,7 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = delCachedResult(list.Name, rt)
|
_ = c.cacheDel(list.Name, rt)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -356,7 +528,7 @@ func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *Runt
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = setCachedResult(result, net.Network.Name, rt); err != nil {
|
if err = c.cacheAdd(result, net.Bytes, net.Network.Name, rt); err != nil {
|
||||||
return nil, fmt.Errorf("failed to set network %q cached result: %v", net.Network.Name, err)
|
return nil, fmt.Errorf("failed to set network %q cached result: %v", net.Network.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,7 +544,7 @@ func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *Ru
|
|||||||
return fmt.Errorf("configuration version %q does not support the CHECK command", net.Network.CNIVersion)
|
return fmt.Errorf("configuration version %q does not support the CHECK command", net.Network.CNIVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedResult, err := getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
cachedResult, err := c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
|
return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
|
||||||
}
|
}
|
||||||
@ -387,7 +559,7 @@ func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *Runt
|
|||||||
if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil {
|
if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if gtet {
|
} else if gtet {
|
||||||
cachedResult, err = getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
cachedResult, err = c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
|
return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
|
||||||
}
|
}
|
||||||
@ -396,7 +568,7 @@ func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *Runt
|
|||||||
if err := c.delNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt); err != nil {
|
if err := c.delNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_ = delCachedResult(net.Network.Name, rt)
|
_ = c.cacheDel(net.Network.Name, rt)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,10 +627,14 @@ func (c *CNIConfig) ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]
|
|||||||
|
|
||||||
// validatePlugin checks that an individual plugin's configuration is sane
|
// validatePlugin checks that an individual plugin's configuration is sane
|
||||||
func (c *CNIConfig) validatePlugin(ctx context.Context, pluginName, expectedVersion string) error {
|
func (c *CNIConfig) validatePlugin(ctx context.Context, pluginName, expectedVersion string) error {
|
||||||
pluginPath, err := invoke.FindInPath(pluginName, c.Path)
|
c.ensureExec()
|
||||||
|
pluginPath, err := c.exec.FindInPath(pluginName, c.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if expectedVersion == "" {
|
||||||
|
expectedVersion = "0.1.0"
|
||||||
|
}
|
||||||
|
|
||||||
vi, err := invoke.GetVersionInfo(ctx, pluginPath, c.exec)
|
vi, err := invoke.GetVersionInfo(ctx, pluginPath, c.exec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
4
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
4
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
@ -114,11 +114,11 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
|
|||||||
for i, conf := range plugins {
|
for i, conf := range plugins {
|
||||||
newBytes, err := json.Marshal(conf)
|
newBytes, err := json.Marshal(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to marshal plugin config %d: %v", i, err)
|
return nil, fmt.Errorf("failed to marshal plugin config %d: %v", i, err)
|
||||||
}
|
}
|
||||||
netConf, err := ConfFromBytes(newBytes)
|
netConf, err := ConfFromBytes(newBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to parse plugin config %d: %v", i, err)
|
return nil, fmt.Errorf("failed to parse plugin config %d: %v", i, err)
|
||||||
}
|
}
|
||||||
list.Plugins = append(list.Plugins, netConf)
|
list.Plugins = append(list.Plugins, netConf)
|
||||||
}
|
}
|
||||||
|
6
vendor/github.com/containernetworking/cni/pkg/invoke/args.go
generated
vendored
6
vendor/github.com/containernetworking/cni/pkg/invoke/args.go
generated
vendored
@ -32,7 +32,7 @@ type inherited struct{}
|
|||||||
|
|
||||||
var inheritArgsFromEnv inherited
|
var inheritArgsFromEnv inherited
|
||||||
|
|
||||||
func (_ *inherited) AsEnv() []string {
|
func (*inherited) AsEnv() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +60,8 @@ func (args *Args) AsEnv() []string {
|
|||||||
pluginArgsStr = stringify(args.PluginArgs)
|
pluginArgsStr = stringify(args.PluginArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duplicated values which come first will be overrided, so we must put the
|
// Duplicated values which come first will be overridden, so we must put the
|
||||||
// custom values in the end to avoid being overrided by the process environments.
|
// custom values in the end to avoid being overridden by the process environments.
|
||||||
env = append(env,
|
env = append(env,
|
||||||
"CNI_COMMAND="+args.Command,
|
"CNI_COMMAND="+args.Command,
|
||||||
"CNI_CONTAINERID="+args.ContainerID,
|
"CNI_CONTAINERID="+args.ContainerID,
|
||||||
|
52
vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
generated
vendored
52
vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
generated
vendored
@ -21,6 +21,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
)
|
)
|
||||||
@ -31,30 +33,54 @@ type RawExec struct {
|
|||||||
|
|
||||||
func (e *RawExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
|
func (e *RawExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
|
||||||
stdout := &bytes.Buffer{}
|
stdout := &bytes.Buffer{}
|
||||||
|
stderr := &bytes.Buffer{}
|
||||||
c := exec.CommandContext(ctx, pluginPath)
|
c := exec.CommandContext(ctx, pluginPath)
|
||||||
c.Env = environ
|
c.Env = environ
|
||||||
c.Stdin = bytes.NewBuffer(stdinData)
|
c.Stdin = bytes.NewBuffer(stdinData)
|
||||||
c.Stdout = stdout
|
c.Stdout = stdout
|
||||||
c.Stderr = e.Stderr
|
c.Stderr = stderr
|
||||||
if err := c.Run(); err != nil {
|
|
||||||
return nil, pluginErr(err, stdout.Bytes())
|
// Retry the command on "text file busy" errors
|
||||||
|
for i := 0; i <= 5; i++ {
|
||||||
|
err := c.Run()
|
||||||
|
|
||||||
|
// Command succeeded
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the plugin is currently about to be written, then we wait a
|
||||||
|
// second and try it again
|
||||||
|
if strings.Contains(err.Error(), "text file busy") {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other errors except than the busy text file
|
||||||
|
return nil, e.pluginErr(err, stdout.Bytes(), stderr.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy stderr to caller's buffer in case plugin printed to both
|
||||||
|
// stdout and stderr for some reason. Ignore failures as stderr is
|
||||||
|
// only informational.
|
||||||
|
if e.Stderr != nil && stderr.Len() > 0 {
|
||||||
|
_, _ = stderr.WriteTo(e.Stderr)
|
||||||
|
}
|
||||||
return stdout.Bytes(), nil
|
return stdout.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func pluginErr(err error, output []byte) error {
|
func (e *RawExec) pluginErr(err error, stdout, stderr []byte) error {
|
||||||
if _, ok := err.(*exec.ExitError); ok {
|
emsg := types.Error{}
|
||||||
emsg := types.Error{}
|
if len(stdout) == 0 {
|
||||||
if len(output) == 0 {
|
if len(stderr) == 0 {
|
||||||
emsg.Msg = "netplugin failed with no error message"
|
emsg.Msg = fmt.Sprintf("netplugin failed with no error message: %v", err)
|
||||||
} else if perr := json.Unmarshal(output, &emsg); perr != nil {
|
} else {
|
||||||
emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr)
|
emsg.Msg = fmt.Sprintf("netplugin failed: %q", string(stderr))
|
||||||
}
|
}
|
||||||
return &emsg
|
} else if perr := json.Unmarshal(stdout, &emsg); perr != nil {
|
||||||
|
emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(stdout), perr)
|
||||||
}
|
}
|
||||||
|
return &emsg
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *RawExec) FindInPath(plugin string, paths []string) (string, error) {
|
func (e *RawExec) FindInPath(plugin string, paths []string) (string, error) {
|
||||||
|
99
vendor/github.com/containernetworking/cni/pkg/skel/skel.go
generated
vendored
99
vendor/github.com/containernetworking/cni/pkg/skel/skel.go
generated
vendored
@ -27,6 +27,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
|
"github.com/containernetworking/cni/pkg/utils"
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,16 +54,7 @@ type dispatcher struct {
|
|||||||
|
|
||||||
type reqForCmdEntry map[string]bool
|
type reqForCmdEntry map[string]bool
|
||||||
|
|
||||||
// internal only error to indicate lack of required environment variables
|
func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, *types.Error) {
|
||||||
type missingEnvError struct {
|
|
||||||
msg string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e missingEnvError) Error() string {
|
|
||||||
return e.msg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|
||||||
var cmd, contID, netns, ifName, args, path string
|
var cmd, contID, netns, ifName, args, path string
|
||||||
|
|
||||||
vars := []struct {
|
vars := []struct {
|
||||||
@ -138,7 +130,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
|
|
||||||
if len(argsMissing) > 0 {
|
if len(argsMissing) > 0 {
|
||||||
joined := strings.Join(argsMissing, ",")
|
joined := strings.Join(argsMissing, ",")
|
||||||
return "", nil, missingEnvError{fmt.Sprintf("required env variables [%s] missing", joined)}
|
return "", nil, types.NewError(types.ErrInvalidEnvironmentVariables, fmt.Sprintf("required env variables [%s] missing", joined), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd == "VERSION" {
|
if cmd == "VERSION" {
|
||||||
@ -147,7 +139,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
|
|
||||||
stdinData, err := ioutil.ReadAll(t.Stdin)
|
stdinData, err := ioutil.ReadAll(t.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, fmt.Errorf("error reading from stdin: %v", err)
|
return "", nil, types.NewError(types.ErrIOFailure, fmt.Sprintf("error reading from stdin: %v", err), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdArgs := &CmdArgs{
|
cmdArgs := &CmdArgs{
|
||||||
@ -161,39 +153,39 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
return cmd, cmdArgs, nil
|
return cmd, cmdArgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTypedError(f string, args ...interface{}) *types.Error {
|
func (t *dispatcher) checkVersionAndCall(cmdArgs *CmdArgs, pluginVersionInfo version.PluginInfo, toCall func(*CmdArgs) error) *types.Error {
|
||||||
return &types.Error{
|
|
||||||
Code: 100,
|
|
||||||
Msg: fmt.Sprintf(f, args...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *dispatcher) checkVersionAndCall(cmdArgs *CmdArgs, pluginVersionInfo version.PluginInfo, toCall func(*CmdArgs) error) error {
|
|
||||||
configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData)
|
configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return types.NewError(types.ErrDecodingFailure, err.Error(), "")
|
||||||
}
|
}
|
||||||
verErr := t.VersionReconciler.Check(configVersion, pluginVersionInfo)
|
verErr := t.VersionReconciler.Check(configVersion, pluginVersionInfo)
|
||||||
if verErr != nil {
|
if verErr != nil {
|
||||||
return &types.Error{
|
return types.NewError(types.ErrIncompatibleCNIVersion, "incompatible CNI versions", verErr.Details())
|
||||||
Code: types.ErrIncompatibleCNIVersion,
|
|
||||||
Msg: "incompatible CNI versions",
|
|
||||||
Details: verErr.Details(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return toCall(cmdArgs)
|
if err = toCall(cmdArgs); err != nil {
|
||||||
|
if e, ok := err.(*types.Error); ok {
|
||||||
|
// don't wrap Error in Error
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return types.NewError(types.ErrInternal, err.Error(), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateConfig(jsonBytes []byte) error {
|
func validateConfig(jsonBytes []byte) *types.Error {
|
||||||
var conf struct {
|
var conf struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonBytes, &conf); err != nil {
|
if err := json.Unmarshal(jsonBytes, &conf); err != nil {
|
||||||
return fmt.Errorf("error reading network config: %s", err)
|
return types.NewError(types.ErrDecodingFailure, fmt.Sprintf("error unmarshall network config: %v", err), "")
|
||||||
}
|
}
|
||||||
if conf.Name == "" {
|
if conf.Name == "" {
|
||||||
return fmt.Errorf("missing network name")
|
return types.NewError(types.ErrInvalidNetworkConfig, "missing network name", "")
|
||||||
|
}
|
||||||
|
if err := utils.ValidateNetworkName(conf.Name); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -202,17 +194,22 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error,
|
|||||||
cmd, cmdArgs, err := t.getCmdArgsFromEnv()
|
cmd, cmdArgs, err := t.getCmdArgsFromEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Print the about string to stderr when no command is set
|
// Print the about string to stderr when no command is set
|
||||||
if _, ok := err.(missingEnvError); ok && t.Getenv("CNI_COMMAND") == "" && about != "" {
|
if err.Code == types.ErrInvalidEnvironmentVariables && t.Getenv("CNI_COMMAND") == "" && about != "" {
|
||||||
fmt.Fprintln(t.Stderr, about)
|
_, _ = fmt.Fprintln(t.Stderr, about)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return createTypedError(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd != "VERSION" {
|
if cmd != "VERSION" {
|
||||||
err = validateConfig(cmdArgs.StdinData)
|
if err = validateConfig(cmdArgs.StdinData); err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return createTypedError(err.Error())
|
}
|
||||||
|
if err = utils.ValidateContainerID(cmdArgs.ContainerID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = utils.ValidateInterfaceName(cmdArgs.IfName); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,45 +219,37 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error,
|
|||||||
case "CHECK":
|
case "CHECK":
|
||||||
configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData)
|
configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return createTypedError(err.Error())
|
return types.NewError(types.ErrDecodingFailure, err.Error(), "")
|
||||||
}
|
}
|
||||||
if gtet, err := version.GreaterThanOrEqualTo(configVersion, "0.4.0"); err != nil {
|
if gtet, err := version.GreaterThanOrEqualTo(configVersion, "0.4.0"); err != nil {
|
||||||
return createTypedError(err.Error())
|
return types.NewError(types.ErrDecodingFailure, err.Error(), "")
|
||||||
} else if !gtet {
|
} else if !gtet {
|
||||||
return &types.Error{
|
return types.NewError(types.ErrIncompatibleCNIVersion, "config version does not allow CHECK", "")
|
||||||
Code: types.ErrIncompatibleCNIVersion,
|
|
||||||
Msg: "config version does not allow CHECK",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for _, pluginVersion := range versionInfo.SupportedVersions() {
|
for _, pluginVersion := range versionInfo.SupportedVersions() {
|
||||||
gtet, err := version.GreaterThanOrEqualTo(pluginVersion, configVersion)
|
gtet, err := version.GreaterThanOrEqualTo(pluginVersion, configVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return createTypedError(err.Error())
|
return types.NewError(types.ErrDecodingFailure, err.Error(), "")
|
||||||
} else if gtet {
|
} else if gtet {
|
||||||
if err := t.checkVersionAndCall(cmdArgs, versionInfo, cmdCheck); err != nil {
|
if err := t.checkVersionAndCall(cmdArgs, versionInfo, cmdCheck); err != nil {
|
||||||
return createTypedError(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &types.Error{
|
return types.NewError(types.ErrIncompatibleCNIVersion, "plugin version does not allow CHECK", "")
|
||||||
Code: types.ErrIncompatibleCNIVersion,
|
|
||||||
Msg: "plugin version does not allow CHECK",
|
|
||||||
}
|
|
||||||
case "DEL":
|
case "DEL":
|
||||||
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdDel)
|
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdDel)
|
||||||
case "VERSION":
|
case "VERSION":
|
||||||
err = versionInfo.Encode(t.Stdout)
|
if err := versionInfo.Encode(t.Stdout); err != nil {
|
||||||
|
return types.NewError(types.ErrIOFailure, err.Error(), "")
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return createTypedError("unknown CNI_COMMAND: %v", cmd)
|
return types.NewError(types.ErrInvalidEnvironmentVariables, fmt.Sprintf("unknown CNI_COMMAND: %v", cmd), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if e, ok := err.(*types.Error); ok {
|
return err
|
||||||
// don't wrap Error in Error
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
return createTypedError(err.Error())
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
14
vendor/github.com/containernetworking/cni/pkg/types/020/types.go
generated
vendored
14
vendor/github.com/containernetworking/cni/pkg/types/020/types.go
generated
vendored
@ -86,20 +86,6 @@ func (r *Result) PrintTo(writer io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a formatted string in the form of "[IP4: $1,][ IP6: $2,] DNS: $3" where
|
|
||||||
// $1 represents the receiver's IPv4, $2 represents the receiver's IPv6 and $3 the
|
|
||||||
// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
|
|
||||||
func (r *Result) String() string {
|
|
||||||
var str string
|
|
||||||
if r.IP4 != nil {
|
|
||||||
str = fmt.Sprintf("IP4:%+v, ", *r.IP4)
|
|
||||||
}
|
|
||||||
if r.IP6 != nil {
|
|
||||||
str += fmt.Sprintf("IP6:%+v, ", *r.IP6)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%sDNS:%+v", str, r.DNS)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPConfig contains values necessary to configure an interface
|
// IPConfig contains values necessary to configure an interface
|
||||||
type IPConfig struct {
|
type IPConfig struct {
|
||||||
IP net.IPNet
|
IP net.IPNet
|
||||||
|
2
vendor/github.com/containernetworking/cni/pkg/types/args.go
generated
vendored
2
vendor/github.com/containernetworking/cni/pkg/types/args.go
generated
vendored
@ -36,7 +36,7 @@ func (b *UnmarshallableBool) UnmarshalText(data []byte) error {
|
|||||||
case "0", "false":
|
case "0", "false":
|
||||||
*b = false
|
*b = false
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Boolean unmarshal error: invalid input %s", s)
|
return fmt.Errorf("boolean unmarshal error: invalid input %s", s)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
17
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
17
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
@ -207,23 +207,6 @@ func (r *Result) PrintTo(writer io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a formatted string in the form of "[Interfaces: $1,][ IP: $2,] DNS: $3" where
|
|
||||||
// $1 represents the receiver's Interfaces, $2 represents the receiver's IP addresses and $3 the
|
|
||||||
// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
|
|
||||||
func (r *Result) String() string {
|
|
||||||
var str string
|
|
||||||
if len(r.Interfaces) > 0 {
|
|
||||||
str += fmt.Sprintf("Interfaces:%+v, ", r.Interfaces)
|
|
||||||
}
|
|
||||||
if len(r.IPs) > 0 {
|
|
||||||
str += fmt.Sprintf("IP:%+v, ", r.IPs)
|
|
||||||
}
|
|
||||||
if len(r.Routes) > 0 {
|
|
||||||
str += fmt.Sprintf("Routes:%+v, ", r.Routes)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%sDNS:%+v", str, r.DNS)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert this old version result to the current CNI version result
|
// Convert this old version result to the current CNI version result
|
||||||
func (r *Result) Convert() (*Result, error) {
|
func (r *Result) Convert() (*Result, error) {
|
||||||
return r, nil
|
return r, nil
|
||||||
|
28
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
28
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
@ -16,7 +16,6 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@ -101,9 +100,6 @@ type Result interface {
|
|||||||
|
|
||||||
// Prints the result in JSON format to provided writer
|
// Prints the result in JSON format to provided writer
|
||||||
PrintTo(writer io.Writer) error
|
PrintTo(writer io.Writer) error
|
||||||
|
|
||||||
// Returns a JSON string representation of the result
|
|
||||||
String() string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrintResult(result Result, version string) error {
|
func PrintResult(result Result, version string) error {
|
||||||
@ -134,9 +130,16 @@ func (r *Route) String() string {
|
|||||||
// Well known error codes
|
// Well known error codes
|
||||||
// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
|
// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
|
||||||
const (
|
const (
|
||||||
ErrUnknown uint = iota // 0
|
ErrUnknown uint = iota // 0
|
||||||
ErrIncompatibleCNIVersion // 1
|
ErrIncompatibleCNIVersion // 1
|
||||||
ErrUnsupportedField // 2
|
ErrUnsupportedField // 2
|
||||||
|
ErrUnknownContainer // 3
|
||||||
|
ErrInvalidEnvironmentVariables // 4
|
||||||
|
ErrIOFailure // 5
|
||||||
|
ErrDecodingFailure // 6
|
||||||
|
ErrInvalidNetworkConfig // 7
|
||||||
|
ErrTryAgainLater uint = 11
|
||||||
|
ErrInternal uint = 999
|
||||||
)
|
)
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
@ -145,6 +148,14 @@ type Error struct {
|
|||||||
Details string `json:"details,omitempty"`
|
Details string `json:"details,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewError(code uint, msg, details string) *Error {
|
||||||
|
return &Error{
|
||||||
|
Code: code,
|
||||||
|
Msg: msg,
|
||||||
|
Details: details,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Error) Error() string {
|
func (e *Error) Error() string {
|
||||||
details := ""
|
details := ""
|
||||||
if e.Details != "" {
|
if e.Details != "" {
|
||||||
@ -194,6 +205,3 @@ func prettyPrint(obj interface{}) error {
|
|||||||
_, err = os.Stdout.Write(data)
|
_, err = os.Stdout.Write(data)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotImplementedError is used to indicate that a method is not implemented for the given platform
|
|
||||||
var NotImplementedError = errors.New("Not Implemented")
|
|
||||||
|
84
vendor/github.com/containernetworking/cni/pkg/utils/utils.go
generated
vendored
Normal file
84
vendor/github.com/containernetworking/cni/pkg/utils/utils.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright 2019 CNI authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// cniValidNameChars is the regexp used to validate valid characters in
|
||||||
|
// containerID and networkName
|
||||||
|
cniValidNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.\-]`
|
||||||
|
|
||||||
|
// maxInterfaceNameLength is the length max of a valid interface name
|
||||||
|
maxInterfaceNameLength = 15
|
||||||
|
)
|
||||||
|
|
||||||
|
var cniReg = regexp.MustCompile(`^` + cniValidNameChars + `*$`)
|
||||||
|
|
||||||
|
// ValidateContainerID will validate that the supplied containerID is not empty does not contain invalid characters
|
||||||
|
func ValidateContainerID(containerID string) *types.Error {
|
||||||
|
|
||||||
|
if containerID == "" {
|
||||||
|
return types.NewError(types.ErrUnknownContainer, "missing containerID", "")
|
||||||
|
}
|
||||||
|
if !cniReg.MatchString(containerID) {
|
||||||
|
return types.NewError(types.ErrInvalidEnvironmentVariables, "invalid characters in containerID", containerID)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateNetworkName will validate that the supplied networkName does not contain invalid characters
|
||||||
|
func ValidateNetworkName(networkName string) *types.Error {
|
||||||
|
|
||||||
|
if networkName == "" {
|
||||||
|
return types.NewError(types.ErrInvalidNetworkConfig, "missing network name:", "")
|
||||||
|
}
|
||||||
|
if !cniReg.MatchString(networkName) {
|
||||||
|
return types.NewError(types.ErrInvalidNetworkConfig, "invalid characters found in network name", networkName)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateInterfaceName will validate the interface name based on the three rules below
|
||||||
|
// 1. The name must not be empty
|
||||||
|
// 2. The name must be less than 16 characters
|
||||||
|
// 3. The name must not be "." or ".."
|
||||||
|
// 3. The name must not contain / or : or any whitespace characters
|
||||||
|
// ref to https://github.com/torvalds/linux/blob/master/net/core/dev.c#L1024
|
||||||
|
func ValidateInterfaceName(ifName string) *types.Error {
|
||||||
|
if len(ifName) == 0 {
|
||||||
|
return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is empty", "")
|
||||||
|
}
|
||||||
|
if len(ifName) > maxInterfaceNameLength {
|
||||||
|
return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is too long", fmt.Sprintf("interface name should be less than %d characters", maxInterfaceNameLength+1))
|
||||||
|
}
|
||||||
|
if ifName == "." || ifName == ".." {
|
||||||
|
return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is . or ..", "")
|
||||||
|
}
|
||||||
|
for _, r := range bytes.Runes([]byte(ifName)) {
|
||||||
|
if r == '/' || r == ':' || unicode.IsSpace(r) {
|
||||||
|
return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name contains / or : or whitespace characters", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
29
vendor/github.com/coreos/go-iptables/iptables/iptables.go
generated
vendored
29
vendor/github.com/coreos/go-iptables/iptables/iptables.go
generated
vendored
@ -48,9 +48,13 @@ func (e *Error) Error() string {
|
|||||||
|
|
||||||
// IsNotExist returns true if the error is due to the chain or rule not existing
|
// IsNotExist returns true if the error is due to the chain or rule not existing
|
||||||
func (e *Error) IsNotExist() bool {
|
func (e *Error) IsNotExist() bool {
|
||||||
return e.ExitStatus() == 1 &&
|
if e.ExitStatus() != 1 {
|
||||||
(e.msg == fmt.Sprintf("%s: Bad rule (does a matching rule exist in that chain?).\n", getIptablesCommand(e.proto)) ||
|
return false
|
||||||
e.msg == fmt.Sprintf("%s: No chain/target/match by that name.\n", getIptablesCommand(e.proto)))
|
}
|
||||||
|
cmdIptables := getIptablesCommand(e.proto)
|
||||||
|
msgNoRuleExist := fmt.Sprintf("%s: Bad rule (does a matching rule exist in that chain?).\n", cmdIptables)
|
||||||
|
msgNoChainExist := fmt.Sprintf("%s: No chain/target/match by that name.\n", cmdIptables)
|
||||||
|
return strings.Contains(e.msg, msgNoRuleExist) || strings.Contains(e.msg, msgNoChainExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protocol to differentiate between IPv4 and IPv6
|
// Protocol to differentiate between IPv4 and IPv6
|
||||||
@ -101,7 +105,13 @@ func NewWithProtocol(proto Protocol) (*IPTables, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
vstring, err := getIptablesVersionString(path)
|
vstring, err := getIptablesVersionString(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not get iptables version: %v", err)
|
||||||
|
}
|
||||||
v1, v2, v3, mode, err := extractIptablesVersion(vstring)
|
v1, v2, v3, mode, err := extractIptablesVersion(vstring)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to extract iptables version from [%s]: %v", vstring, err)
|
||||||
|
}
|
||||||
|
|
||||||
checkPresent, waitPresent, randomFullyPresent := getIptablesCommandSupport(v1, v2, v3)
|
checkPresent, waitPresent, randomFullyPresent := getIptablesCommandSupport(v1, v2, v3)
|
||||||
|
|
||||||
@ -348,18 +358,6 @@ func (ipt *IPTables) executeList(args []string) ([]string, error) {
|
|||||||
rules = rules[:len(rules)-1]
|
rules = rules[:len(rules)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// nftables mode doesn't return an error code when listing a non-existent
|
|
||||||
// chain. Patch that up.
|
|
||||||
if len(rules) == 0 && ipt.mode == "nf_tables" {
|
|
||||||
v := 1
|
|
||||||
return nil, &Error{
|
|
||||||
cmd: exec.Cmd{Args: args},
|
|
||||||
msg: fmt.Sprintf("%s: No chain/target/match by that name.\n", getIptablesCommand(ipt.proto)),
|
|
||||||
proto: ipt.proto,
|
|
||||||
exitStatus: &v,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, rule := range rules {
|
for i, rule := range rules {
|
||||||
rules[i] = filterRuleOutput(rule)
|
rules[i] = filterRuleOutput(rule)
|
||||||
}
|
}
|
||||||
@ -437,6 +435,7 @@ func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error {
|
|||||||
}
|
}
|
||||||
ul, err := fmu.tryLock()
|
ul, err := fmu.tryLock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
syscall.Close(fmu.fd)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer ul.Unlock()
|
defer ul.Unlock()
|
||||||
|
23
vendor/github.com/juju/errors/.gitignore
generated
vendored
23
vendor/github.com/juju/errors/.gitignore
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
191
vendor/github.com/juju/errors/LICENSE
generated
vendored
191
vendor/github.com/juju/errors/LICENSE
generated
vendored
@ -1,191 +0,0 @@
|
|||||||
All files in this repository are licensed as follows. If you contribute
|
|
||||||
to this repository, it is assumed that you license your contribution
|
|
||||||
under the same license unless you state otherwise.
|
|
||||||
|
|
||||||
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
|
||||||
|
|
||||||
This software is licensed under the LGPLv3, included below.
|
|
||||||
|
|
||||||
As a special exception to the GNU Lesser General Public License version 3
|
|
||||||
("LGPL3"), the copyright holders of this Library give you permission to
|
|
||||||
convey to a third party a Combined Work that links statically or dynamically
|
|
||||||
to this Library without providing any Minimal Corresponding Source or
|
|
||||||
Minimal Application Code as set out in 4d or providing the installation
|
|
||||||
information set out in section 4e, provided that you comply with the other
|
|
||||||
provisions of LGPL3 and provided that you meet, for the Application the
|
|
||||||
terms and conditions of the license(s) which apply to the Application.
|
|
||||||
|
|
||||||
Except as stated in this special exception, the provisions of LGPL3 will
|
|
||||||
continue to comply in full to this Library. If you modify this Library, you
|
|
||||||
may apply this exception to your version of this Library, but you are not
|
|
||||||
obliged to do so. If you do not wish to do so, delete this exception
|
|
||||||
statement from your version. This exception does not (and cannot) modify any
|
|
||||||
license terms which apply to the Application, with which you must still
|
|
||||||
comply.
|
|
||||||
|
|
||||||
|
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.
|
|
24
vendor/github.com/juju/errors/Makefile
generated
vendored
24
vendor/github.com/juju/errors/Makefile
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
PROJECT := github.com/juju/errors
|
|
||||||
|
|
||||||
.PHONY: check-licence check-go check docs
|
|
||||||
|
|
||||||
check: check-licence check-go
|
|
||||||
go test $(PROJECT)/...
|
|
||||||
|
|
||||||
check-licence:
|
|
||||||
@(fgrep -rl "Licensed under the LGPLv3" --exclude *.s .;\
|
|
||||||
fgrep -rl "MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT" --exclude *.s .;\
|
|
||||||
find . -name "*.go") | sed -e 's,\./,,' | sort | uniq -u | \
|
|
||||||
xargs -I {} echo FAIL: licence missed: {}
|
|
||||||
|
|
||||||
check-go:
|
|
||||||
$(eval GOFMT := $(strip $(shell gofmt -l .| sed -e "s/^/ /g")))
|
|
||||||
@(if [ x$(GOFMT) != x"" ]; then \
|
|
||||||
echo go fmt is sad: $(GOFMT); \
|
|
||||||
exit 1; \
|
|
||||||
fi )
|
|
||||||
@(go tool vet -all -composites=false -copylocks=false .)
|
|
||||||
|
|
||||||
docs:
|
|
||||||
godoc2md github.com/juju/errors > README.md
|
|
||||||
sed -i 's|\[godoc-link-here\]|[](https://godoc.org/github.com/juju/errors)|' README.md
|
|
707
vendor/github.com/juju/errors/README.md
generated
vendored
707
vendor/github.com/juju/errors/README.md
generated
vendored
@ -1,707 +0,0 @@
|
|||||||
|
|
||||||
# errors
|
|
||||||
import "github.com/juju/errors"
|
|
||||||
|
|
||||||
[](https://godoc.org/github.com/juju/errors)
|
|
||||||
|
|
||||||
The juju/errors provides an easy way to annotate errors without losing the
|
|
||||||
orginal error context.
|
|
||||||
|
|
||||||
The exported `New` and `Errorf` functions are designed to replace the
|
|
||||||
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
|
|
||||||
error is there, but the package also records the location at which the error
|
|
||||||
was created.
|
|
||||||
|
|
||||||
A primary use case for this library is to add extra context any time an
|
|
||||||
error is returned from a function.
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
This instead becomes:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Trace(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
which just records the file and line number of the Trace call, or
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Annotate(err, "more context")
|
|
||||||
}
|
|
||||||
|
|
||||||
which also adds an annotation to the error.
|
|
||||||
|
|
||||||
When you want to check to see if an error is of a particular type, a helper
|
|
||||||
function is normally exported by the package that returned the error, like the
|
|
||||||
`os` package does. The underlying cause of the error is available using the
|
|
||||||
`Cause` function.
|
|
||||||
|
|
||||||
|
|
||||||
os.IsNotExist(errors.Cause(err))
|
|
||||||
|
|
||||||
The result of the `Error()` call on an annotated error is the annotations joined
|
|
||||||
with colons, then the result of the `Error()` method for the underlying error
|
|
||||||
that was the cause.
|
|
||||||
|
|
||||||
|
|
||||||
err := errors.Errorf("original")
|
|
||||||
err = errors.Annotatef(err, "context")
|
|
||||||
err = errors.Annotatef(err, "more context")
|
|
||||||
err.Error() -> "more context: context: original"
|
|
||||||
|
|
||||||
Obviously recording the file, line and functions is not very useful if you
|
|
||||||
cannot get them back out again.
|
|
||||||
|
|
||||||
|
|
||||||
errors.ErrorStack(err)
|
|
||||||
|
|
||||||
will return something like:
|
|
||||||
|
|
||||||
|
|
||||||
first error
|
|
||||||
github.com/juju/errors/annotation_test.go:193:
|
|
||||||
github.com/juju/errors/annotation_test.go:194: annotation
|
|
||||||
github.com/juju/errors/annotation_test.go:195:
|
|
||||||
github.com/juju/errors/annotation_test.go:196: more context
|
|
||||||
github.com/juju/errors/annotation_test.go:197:
|
|
||||||
|
|
||||||
The first error was generated by an external system, so there was no location
|
|
||||||
associated. The second, fourth, and last lines were generated with Trace calls,
|
|
||||||
and the other two through Annotate.
|
|
||||||
|
|
||||||
Sometimes when responding to an error you want to return a more specific error
|
|
||||||
for the situation.
|
|
||||||
|
|
||||||
|
|
||||||
if err := FindField(field); err != nil {
|
|
||||||
return errors.Wrap(err, errors.NotFoundf(field))
|
|
||||||
}
|
|
||||||
|
|
||||||
This returns an error where the complete error stack is still available, and
|
|
||||||
`errors.Cause()` will return the `NotFound` error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## func AlreadyExistsf
|
|
||||||
``` go
|
|
||||||
func AlreadyExistsf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
AlreadyExistsf returns an error which satisfies IsAlreadyExists().
|
|
||||||
|
|
||||||
|
|
||||||
## func Annotate
|
|
||||||
``` go
|
|
||||||
func Annotate(other error, message string) error
|
|
||||||
```
|
|
||||||
Annotate is used to add extra context to an existing error. The location of
|
|
||||||
the Annotate call is recorded with the annotations. The file, line and
|
|
||||||
function are also recorded.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Annotate(err, "failed to frombulate")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## func Annotatef
|
|
||||||
``` go
|
|
||||||
func Annotatef(other error, format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Annotatef is used to add extra context to an existing error. The location of
|
|
||||||
the Annotate call is recorded with the annotations. The file, line and
|
|
||||||
function are also recorded.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Annotatef(err, "failed to frombulate the %s", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## func BadRequestf
|
|
||||||
``` go
|
|
||||||
func BadRequestf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
BadRequestf returns an error which satisfies IsBadRequest().
|
|
||||||
|
|
||||||
|
|
||||||
## func Cause
|
|
||||||
``` go
|
|
||||||
func Cause(err error) error
|
|
||||||
```
|
|
||||||
Cause returns the cause of the given error. This will be either the
|
|
||||||
original error, or the result of a Wrap or Mask call.
|
|
||||||
|
|
||||||
Cause is the usual way to diagnose errors that may have been wrapped by
|
|
||||||
the other errors functions.
|
|
||||||
|
|
||||||
|
|
||||||
## func DeferredAnnotatef
|
|
||||||
``` go
|
|
||||||
func DeferredAnnotatef(err *error, format string, args ...interface{})
|
|
||||||
```
|
|
||||||
DeferredAnnotatef annotates the given error (when it is not nil) with the given
|
|
||||||
format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
|
|
||||||
does nothing. This method is used in a defer statement in order to annotate any
|
|
||||||
resulting error with the same message.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
|
|
||||||
|
|
||||||
|
|
||||||
## func Details
|
|
||||||
``` go
|
|
||||||
func Details(err error) string
|
|
||||||
```
|
|
||||||
Details returns information about the stack of errors wrapped by err, in
|
|
||||||
the format:
|
|
||||||
|
|
||||||
|
|
||||||
[{filename:99: error one} {otherfile:55: cause of error one}]
|
|
||||||
|
|
||||||
This is a terse alternative to ErrorStack as it returns a single line.
|
|
||||||
|
|
||||||
|
|
||||||
## func ErrorStack
|
|
||||||
``` go
|
|
||||||
func ErrorStack(err error) string
|
|
||||||
```
|
|
||||||
ErrorStack returns a string representation of the annotated error. If the
|
|
||||||
error passed as the parameter is not an annotated error, the result is
|
|
||||||
simply the result of the Error() method on that error.
|
|
||||||
|
|
||||||
If the error is an annotated error, a multi-line string is returned where
|
|
||||||
each line represents one entry in the annotation stack. The full filename
|
|
||||||
from the call stack is used in the output.
|
|
||||||
|
|
||||||
|
|
||||||
first error
|
|
||||||
github.com/juju/errors/annotation_test.go:193:
|
|
||||||
github.com/juju/errors/annotation_test.go:194: annotation
|
|
||||||
github.com/juju/errors/annotation_test.go:195:
|
|
||||||
github.com/juju/errors/annotation_test.go:196: more context
|
|
||||||
github.com/juju/errors/annotation_test.go:197:
|
|
||||||
|
|
||||||
|
|
||||||
## func Errorf
|
|
||||||
``` go
|
|
||||||
func Errorf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Errorf creates a new annotated error and records the location that the
|
|
||||||
error is created. This should be a drop in replacement for fmt.Errorf.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
return errors.Errorf("validation failed: %s", message)
|
|
||||||
|
|
||||||
|
|
||||||
## func Forbiddenf
|
|
||||||
``` go
|
|
||||||
func Forbiddenf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Forbiddenf returns an error which satistifes IsForbidden()
|
|
||||||
|
|
||||||
|
|
||||||
## func IsAlreadyExists
|
|
||||||
``` go
|
|
||||||
func IsAlreadyExists(err error) bool
|
|
||||||
```
|
|
||||||
IsAlreadyExists reports whether the error was created with
|
|
||||||
AlreadyExistsf() or NewAlreadyExists().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsBadRequest
|
|
||||||
``` go
|
|
||||||
func IsBadRequest(err error) bool
|
|
||||||
```
|
|
||||||
IsBadRequest reports whether err was created with BadRequestf() or
|
|
||||||
NewBadRequest().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsForbidden
|
|
||||||
``` go
|
|
||||||
func IsForbidden(err error) bool
|
|
||||||
```
|
|
||||||
IsForbidden reports whether err was created with Forbiddenf() or
|
|
||||||
NewForbidden().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsMethodNotAllowed
|
|
||||||
``` go
|
|
||||||
func IsMethodNotAllowed(err error) bool
|
|
||||||
```
|
|
||||||
IsMethodNotAllowed reports whether err was created with MethodNotAllowedf() or
|
|
||||||
NewMethodNotAllowed().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotAssigned
|
|
||||||
``` go
|
|
||||||
func IsNotAssigned(err error) bool
|
|
||||||
```
|
|
||||||
IsNotAssigned reports whether err was created with NotAssignedf() or
|
|
||||||
NewNotAssigned().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotFound
|
|
||||||
``` go
|
|
||||||
func IsNotFound(err error) bool
|
|
||||||
```
|
|
||||||
IsNotFound reports whether err was created with NotFoundf() or
|
|
||||||
NewNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotImplemented
|
|
||||||
``` go
|
|
||||||
func IsNotImplemented(err error) bool
|
|
||||||
```
|
|
||||||
IsNotImplemented reports whether err was created with
|
|
||||||
NotImplementedf() or NewNotImplemented().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotProvisioned
|
|
||||||
``` go
|
|
||||||
func IsNotProvisioned(err error) bool
|
|
||||||
```
|
|
||||||
IsNotProvisioned reports whether err was created with NotProvisionedf() or
|
|
||||||
NewNotProvisioned().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotSupported
|
|
||||||
``` go
|
|
||||||
func IsNotSupported(err error) bool
|
|
||||||
```
|
|
||||||
IsNotSupported reports whether the error was created with
|
|
||||||
NotSupportedf() or NewNotSupported().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsNotValid
|
|
||||||
``` go
|
|
||||||
func IsNotValid(err error) bool
|
|
||||||
```
|
|
||||||
IsNotValid reports whether the error was created with NotValidf() or
|
|
||||||
NewNotValid().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsUnauthorized
|
|
||||||
``` go
|
|
||||||
func IsUnauthorized(err error) bool
|
|
||||||
```
|
|
||||||
IsUnauthorized reports whether err was created with Unauthorizedf() or
|
|
||||||
NewUnauthorized().
|
|
||||||
|
|
||||||
|
|
||||||
## func IsUserNotFound
|
|
||||||
``` go
|
|
||||||
func IsUserNotFound(err error) bool
|
|
||||||
```
|
|
||||||
IsUserNotFound reports whether err was created with UserNotFoundf() or
|
|
||||||
NewUserNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func Mask
|
|
||||||
``` go
|
|
||||||
func Mask(other error) error
|
|
||||||
```
|
|
||||||
Mask hides the underlying error type, and records the location of the masking.
|
|
||||||
|
|
||||||
|
|
||||||
## func Maskf
|
|
||||||
``` go
|
|
||||||
func Maskf(other error, format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Mask masks the given error with the given format string and arguments (like
|
|
||||||
fmt.Sprintf), returning a new error that maintains the error stack, but
|
|
||||||
hides the underlying error type. The error string still contains the full
|
|
||||||
annotations. If you want to hide the annotations, call Wrap.
|
|
||||||
|
|
||||||
|
|
||||||
## func MethodNotAllowedf
|
|
||||||
``` go
|
|
||||||
func MethodNotAllowedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
MethodNotAllowedf returns an error which satisfies IsMethodNotAllowed().
|
|
||||||
|
|
||||||
|
|
||||||
## func New
|
|
||||||
``` go
|
|
||||||
func New(message string) error
|
|
||||||
```
|
|
||||||
New is a drop in replacement for the standard library errors module that records
|
|
||||||
the location that the error is created.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
return errors.New("validation failed")
|
|
||||||
|
|
||||||
|
|
||||||
## func NewAlreadyExists
|
|
||||||
``` go
|
|
||||||
func NewAlreadyExists(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewAlreadyExists returns an error which wraps err and satisfies
|
|
||||||
IsAlreadyExists().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewBadRequest
|
|
||||||
``` go
|
|
||||||
func NewBadRequest(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewBadRequest returns an error which wraps err that satisfies
|
|
||||||
IsBadRequest().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewForbidden
|
|
||||||
``` go
|
|
||||||
func NewForbidden(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewForbidden returns an error which wraps err that satisfies
|
|
||||||
IsForbidden().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewMethodNotAllowed
|
|
||||||
``` go
|
|
||||||
func NewMethodNotAllowed(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewMethodNotAllowed returns an error which wraps err that satisfies
|
|
||||||
IsMethodNotAllowed().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotAssigned
|
|
||||||
``` go
|
|
||||||
func NewNotAssigned(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotAssigned returns an error which wraps err that satisfies
|
|
||||||
IsNotAssigned().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotFound
|
|
||||||
``` go
|
|
||||||
func NewNotFound(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotFound returns an error which wraps err that satisfies
|
|
||||||
IsNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotImplemented
|
|
||||||
``` go
|
|
||||||
func NewNotImplemented(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotImplemented returns an error which wraps err and satisfies
|
|
||||||
IsNotImplemented().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotProvisioned
|
|
||||||
``` go
|
|
||||||
func NewNotProvisioned(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotProvisioned returns an error which wraps err that satisfies
|
|
||||||
IsNotProvisioned().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotSupported
|
|
||||||
``` go
|
|
||||||
func NewNotSupported(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotSupported returns an error which wraps err and satisfies
|
|
||||||
IsNotSupported().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewNotValid
|
|
||||||
``` go
|
|
||||||
func NewNotValid(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewNotValid returns an error which wraps err and satisfies IsNotValid().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewUnauthorized
|
|
||||||
``` go
|
|
||||||
func NewUnauthorized(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewUnauthorized returns an error which wraps err and satisfies
|
|
||||||
IsUnauthorized().
|
|
||||||
|
|
||||||
|
|
||||||
## func NewUserNotFound
|
|
||||||
``` go
|
|
||||||
func NewUserNotFound(err error, msg string) error
|
|
||||||
```
|
|
||||||
NewUserNotFound returns an error which wraps err and satisfies
|
|
||||||
IsUserNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotAssignedf
|
|
||||||
``` go
|
|
||||||
func NotAssignedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotAssignedf returns an error which satisfies IsNotAssigned().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotFoundf
|
|
||||||
``` go
|
|
||||||
func NotFoundf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotFoundf returns an error which satisfies IsNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotImplementedf
|
|
||||||
``` go
|
|
||||||
func NotImplementedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotImplementedf returns an error which satisfies IsNotImplemented().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotProvisionedf
|
|
||||||
``` go
|
|
||||||
func NotProvisionedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotProvisionedf returns an error which satisfies IsNotProvisioned().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotSupportedf
|
|
||||||
``` go
|
|
||||||
func NotSupportedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotSupportedf returns an error which satisfies IsNotSupported().
|
|
||||||
|
|
||||||
|
|
||||||
## func NotValidf
|
|
||||||
``` go
|
|
||||||
func NotValidf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
NotValidf returns an error which satisfies IsNotValid().
|
|
||||||
|
|
||||||
|
|
||||||
## func Trace
|
|
||||||
``` go
|
|
||||||
func Trace(other error) error
|
|
||||||
```
|
|
||||||
Trace adds the location of the Trace call to the stack. The Cause of the
|
|
||||||
resulting error is the same as the error parameter. If the other error is
|
|
||||||
nil, the result will be nil.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Trace(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## func Unauthorizedf
|
|
||||||
``` go
|
|
||||||
func Unauthorizedf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Unauthorizedf returns an error which satisfies IsUnauthorized().
|
|
||||||
|
|
||||||
|
|
||||||
## func UserNotFoundf
|
|
||||||
``` go
|
|
||||||
func UserNotFoundf(format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
UserNotFoundf returns an error which satisfies IsUserNotFound().
|
|
||||||
|
|
||||||
|
|
||||||
## func Wrap
|
|
||||||
``` go
|
|
||||||
func Wrap(other, newDescriptive error) error
|
|
||||||
```
|
|
||||||
Wrap changes the Cause of the error. The location of the Wrap call is also
|
|
||||||
stored in the error stack.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
newErr := &packageError{"more context", private_value}
|
|
||||||
return errors.Wrap(err, newErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## func Wrapf
|
|
||||||
``` go
|
|
||||||
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error
|
|
||||||
```
|
|
||||||
Wrapf changes the Cause of the error, and adds an annotation. The location
|
|
||||||
of the Wrap call is also stored in the error stack.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## type Err
|
|
||||||
``` go
|
|
||||||
type Err struct {
|
|
||||||
// contains filtered or unexported fields
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Err holds a description of an error along with information about
|
|
||||||
where the error was created.
|
|
||||||
|
|
||||||
It may be embedded in custom error types to add extra information that
|
|
||||||
this errors package can understand.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func NewErr
|
|
||||||
``` go
|
|
||||||
func NewErr(format string, args ...interface{}) Err
|
|
||||||
```
|
|
||||||
NewErr is used to return an Err for the purpose of embedding in other
|
|
||||||
structures. The location is not specified, and needs to be set with a call
|
|
||||||
to SetLocation.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
type FooError struct {
|
|
||||||
errors.Err
|
|
||||||
code int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFooError(code int) error {
|
|
||||||
err := &FooError{errors.NewErr("foo"), code}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
### func NewErrWithCause
|
|
||||||
``` go
|
|
||||||
func NewErrWithCause(other error, format string, args ...interface{}) Err
|
|
||||||
```
|
|
||||||
NewErrWithCause is used to return an Err with case by other error for the purpose of embedding in other
|
|
||||||
structures. The location is not specified, and needs to be set with a call
|
|
||||||
to SetLocation.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
|
|
||||||
type FooError struct {
|
|
||||||
errors.Err
|
|
||||||
code int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *FooError) Annotate(format string, args ...interface{}) error {
|
|
||||||
err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Cause
|
|
||||||
``` go
|
|
||||||
func (e *Err) Cause() error
|
|
||||||
```
|
|
||||||
The Cause of an error is the most recent error in the error stack that
|
|
||||||
meets one of these criteria: the original error that was raised; the new
|
|
||||||
error that was passed into the Wrap function; the most recently masked
|
|
||||||
error; or nil if the error itself is considered the Cause. Normally this
|
|
||||||
method is not invoked directly, but instead through the Cause stand alone
|
|
||||||
function.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Error
|
|
||||||
``` go
|
|
||||||
func (e *Err) Error() string
|
|
||||||
```
|
|
||||||
Error implements error.Error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Format
|
|
||||||
``` go
|
|
||||||
func (e *Err) Format(s fmt.State, verb rune)
|
|
||||||
```
|
|
||||||
Format implements fmt.Formatter
|
|
||||||
When printing errors with %+v it also prints the stack trace.
|
|
||||||
%#v unsurprisingly will print the real underlying type.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Location
|
|
||||||
``` go
|
|
||||||
func (e *Err) Location() (filename string, line int)
|
|
||||||
```
|
|
||||||
Location is the file and line of where the error was most recently
|
|
||||||
created or annotated.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Message
|
|
||||||
``` go
|
|
||||||
func (e *Err) Message() string
|
|
||||||
```
|
|
||||||
Message returns the message stored with the most recent location. This is
|
|
||||||
the empty string if the most recent call was Trace, or the message stored
|
|
||||||
with Annotate or Mask.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) SetLocation
|
|
||||||
``` go
|
|
||||||
func (e *Err) SetLocation(callDepth int)
|
|
||||||
```
|
|
||||||
SetLocation records the source location of the error at callDepth stack
|
|
||||||
frames above the call.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) StackTrace
|
|
||||||
``` go
|
|
||||||
func (e *Err) StackTrace() []string
|
|
||||||
```
|
|
||||||
StackTrace returns one string for each location recorded in the stack of
|
|
||||||
errors. The first value is the originating error, with a line for each
|
|
||||||
other annotation or tracing of the error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### func (\*Err) Underlying
|
|
||||||
``` go
|
|
||||||
func (e *Err) Underlying() error
|
|
||||||
```
|
|
||||||
Underlying returns the previous error in the error stack, if any. A client
|
|
||||||
should not ever really call this method. It is used to build the error
|
|
||||||
stack and should not be introspected by client calls. Or more
|
|
||||||
specifically, clients should not depend on anything but the `Cause` of an
|
|
||||||
error.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- - -
|
|
||||||
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
|
5
vendor/github.com/juju/errors/dependencies.tsv
generated
vendored
5
vendor/github.com/juju/errors/dependencies.tsv
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
github.com/juju/loggo git 8232ab8918d91c72af1a9fb94d3edbe31d88b790 2017-06-05T01:46:07Z
|
|
||||||
github.com/juju/testing git 72703b1e95eb8ce4737fd8a3d8496c6b0be280a6 2018-05-17T13:41:05Z
|
|
||||||
gopkg.in/check.v1 git 4f90aeace3a26ad7021961c297b22c42160c7b25 2016-01-05T16:49:36Z
|
|
||||||
gopkg.in/mgo.v2 git f2b6f6c918c452ad107eec89615f074e3bd80e33 2016-08-18T01:52:18Z
|
|
||||||
gopkg.in/yaml.v2 git 1be3d31502d6eabc0dd7ce5b0daab022e14a5538 2017-07-12T05:45:46Z
|
|
|
81
vendor/github.com/juju/errors/doc.go
generated
vendored
81
vendor/github.com/juju/errors/doc.go
generated
vendored
@ -1,81 +0,0 @@
|
|||||||
// Copyright 2013, 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
/*
|
|
||||||
[godoc-link-here]
|
|
||||||
|
|
||||||
The juju/errors provides an easy way to annotate errors without losing the
|
|
||||||
orginal error context.
|
|
||||||
|
|
||||||
The exported `New` and `Errorf` functions are designed to replace the
|
|
||||||
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
|
|
||||||
error is there, but the package also records the location at which the error
|
|
||||||
was created.
|
|
||||||
|
|
||||||
A primary use case for this library is to add extra context any time an
|
|
||||||
error is returned from a function.
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
This instead becomes:
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Trace(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
which just records the file and line number of the Trace call, or
|
|
||||||
|
|
||||||
if err := SomeFunc(); err != nil {
|
|
||||||
return errors.Annotate(err, "more context")
|
|
||||||
}
|
|
||||||
|
|
||||||
which also adds an annotation to the error.
|
|
||||||
|
|
||||||
When you want to check to see if an error is of a particular type, a helper
|
|
||||||
function is normally exported by the package that returned the error, like the
|
|
||||||
`os` package does. The underlying cause of the error is available using the
|
|
||||||
`Cause` function.
|
|
||||||
|
|
||||||
os.IsNotExist(errors.Cause(err))
|
|
||||||
|
|
||||||
The result of the `Error()` call on an annotated error is the annotations joined
|
|
||||||
with colons, then the result of the `Error()` method for the underlying error
|
|
||||||
that was the cause.
|
|
||||||
|
|
||||||
err := errors.Errorf("original")
|
|
||||||
err = errors.Annotatef(err, "context")
|
|
||||||
err = errors.Annotatef(err, "more context")
|
|
||||||
err.Error() -> "more context: context: original"
|
|
||||||
|
|
||||||
Obviously recording the file, line and functions is not very useful if you
|
|
||||||
cannot get them back out again.
|
|
||||||
|
|
||||||
errors.ErrorStack(err)
|
|
||||||
|
|
||||||
will return something like:
|
|
||||||
|
|
||||||
first error
|
|
||||||
github.com/juju/errors/annotation_test.go:193:
|
|
||||||
github.com/juju/errors/annotation_test.go:194: annotation
|
|
||||||
github.com/juju/errors/annotation_test.go:195:
|
|
||||||
github.com/juju/errors/annotation_test.go:196: more context
|
|
||||||
github.com/juju/errors/annotation_test.go:197:
|
|
||||||
|
|
||||||
The first error was generated by an external system, so there was no location
|
|
||||||
associated. The second, fourth, and last lines were generated with Trace calls,
|
|
||||||
and the other two through Annotate.
|
|
||||||
|
|
||||||
Sometimes when responding to an error you want to return a more specific error
|
|
||||||
for the situation.
|
|
||||||
|
|
||||||
if err := FindField(field); err != nil {
|
|
||||||
return errors.Wrap(err, errors.NotFoundf(field))
|
|
||||||
}
|
|
||||||
|
|
||||||
This returns an error where the complete error stack is still available, and
|
|
||||||
`errors.Cause()` will return the `NotFound` error.
|
|
||||||
|
|
||||||
*/
|
|
||||||
package errors
|
|
172
vendor/github.com/juju/errors/error.go
generated
vendored
172
vendor/github.com/juju/errors/error.go
generated
vendored
@ -1,172 +0,0 @@
|
|||||||
// Copyright 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Err holds a description of an error along with information about
|
|
||||||
// where the error was created.
|
|
||||||
//
|
|
||||||
// It may be embedded in custom error types to add extra information that
|
|
||||||
// this errors package can understand.
|
|
||||||
type Err struct {
|
|
||||||
// message holds an annotation of the error.
|
|
||||||
message string
|
|
||||||
|
|
||||||
// cause holds the cause of the error as returned
|
|
||||||
// by the Cause method.
|
|
||||||
cause error
|
|
||||||
|
|
||||||
// previous holds the previous error in the error stack, if any.
|
|
||||||
previous error
|
|
||||||
|
|
||||||
// file and line hold the source code location where the error was
|
|
||||||
// created.
|
|
||||||
file string
|
|
||||||
line int
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErr is used to return an Err for the purpose of embedding in other
|
|
||||||
// structures. The location is not specified, and needs to be set with a call
|
|
||||||
// to SetLocation.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// type FooError struct {
|
|
||||||
// errors.Err
|
|
||||||
// code int
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func NewFooError(code int) error {
|
|
||||||
// err := &FooError{errors.NewErr("foo"), code}
|
|
||||||
// err.SetLocation(1)
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
func NewErr(format string, args ...interface{}) Err {
|
|
||||||
return Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrWithCause is used to return an Err with case by other error for the purpose of embedding in other
|
|
||||||
// structures. The location is not specified, and needs to be set with a call
|
|
||||||
// to SetLocation.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// type FooError struct {
|
|
||||||
// errors.Err
|
|
||||||
// code int
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (e *FooError) Annotate(format string, args ...interface{}) error {
|
|
||||||
// err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
|
|
||||||
// err.SetLocation(1)
|
|
||||||
// return err
|
|
||||||
// })
|
|
||||||
func NewErrWithCause(other error, format string, args ...interface{}) Err {
|
|
||||||
return Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
cause: Cause(other),
|
|
||||||
previous: other,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Location is the file and line of where the error was most recently
|
|
||||||
// created or annotated.
|
|
||||||
func (e *Err) Location() (filename string, line int) {
|
|
||||||
return e.file, e.line
|
|
||||||
}
|
|
||||||
|
|
||||||
// Underlying returns the previous error in the error stack, if any. A client
|
|
||||||
// should not ever really call this method. It is used to build the error
|
|
||||||
// stack and should not be introspected by client calls. Or more
|
|
||||||
// specifically, clients should not depend on anything but the `Cause` of an
|
|
||||||
// error.
|
|
||||||
func (e *Err) Underlying() error {
|
|
||||||
return e.previous
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Cause of an error is the most recent error in the error stack that
|
|
||||||
// meets one of these criteria: the original error that was raised; the new
|
|
||||||
// error that was passed into the Wrap function; the most recently masked
|
|
||||||
// error; or nil if the error itself is considered the Cause. Normally this
|
|
||||||
// method is not invoked directly, but instead through the Cause stand alone
|
|
||||||
// function.
|
|
||||||
func (e *Err) Cause() error {
|
|
||||||
return e.cause
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message returns the message stored with the most recent location. This is
|
|
||||||
// the empty string if the most recent call was Trace, or the message stored
|
|
||||||
// with Annotate or Mask.
|
|
||||||
func (e *Err) Message() string {
|
|
||||||
return e.message
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements error.Error.
|
|
||||||
func (e *Err) Error() string {
|
|
||||||
// We want to walk up the stack of errors showing the annotations
|
|
||||||
// as long as the cause is the same.
|
|
||||||
err := e.previous
|
|
||||||
if !sameError(Cause(err), e.cause) && e.cause != nil {
|
|
||||||
err = e.cause
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case err == nil:
|
|
||||||
return e.message
|
|
||||||
case e.message == "":
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s: %v", e.message, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format implements fmt.Formatter
|
|
||||||
// When printing errors with %+v it also prints the stack trace.
|
|
||||||
// %#v unsurprisingly will print the real underlying type.
|
|
||||||
func (e *Err) Format(s fmt.State, verb rune) {
|
|
||||||
switch verb {
|
|
||||||
case 'v':
|
|
||||||
switch {
|
|
||||||
case s.Flag('+'):
|
|
||||||
fmt.Fprintf(s, "%s", ErrorStack(e))
|
|
||||||
return
|
|
||||||
case s.Flag('#'):
|
|
||||||
// avoid infinite recursion by wrapping e into a type
|
|
||||||
// that doesn't implement Formatter.
|
|
||||||
fmt.Fprintf(s, "%#v", (*unformatter)(e))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
case 's':
|
|
||||||
fmt.Fprintf(s, "%s", e.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper for Format
|
|
||||||
type unformatter Err
|
|
||||||
|
|
||||||
func (unformatter) Format() { /* break the fmt.Formatter interface */ }
|
|
||||||
|
|
||||||
// SetLocation records the source location of the error at callDepth stack
|
|
||||||
// frames above the call.
|
|
||||||
func (e *Err) SetLocation(callDepth int) {
|
|
||||||
_, file, line, _ := runtime.Caller(callDepth + 1)
|
|
||||||
e.file = trimGoPath(file)
|
|
||||||
e.line = line
|
|
||||||
}
|
|
||||||
|
|
||||||
// StackTrace returns one string for each location recorded in the stack of
|
|
||||||
// errors. The first value is the originating error, with a line for each
|
|
||||||
// other annotation or tracing of the error.
|
|
||||||
func (e *Err) StackTrace() []string {
|
|
||||||
return errorStack(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ideally we'd have a way to check identity, but deep equals will do.
|
|
||||||
func sameError(e1, e2 error) bool {
|
|
||||||
return reflect.DeepEqual(e1, e2)
|
|
||||||
}
|
|
333
vendor/github.com/juju/errors/errortypes.go
generated
vendored
333
vendor/github.com/juju/errors/errortypes.go
generated
vendored
@ -1,333 +0,0 @@
|
|||||||
// Copyright 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// wrap is a helper to construct an *wrapper.
|
|
||||||
func wrap(err error, format, suffix string, args ...interface{}) Err {
|
|
||||||
newErr := Err{
|
|
||||||
message: fmt.Sprintf(format+suffix, args...),
|
|
||||||
previous: err,
|
|
||||||
}
|
|
||||||
newErr.SetLocation(2)
|
|
||||||
return newErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// timeout represents an error on timeout.
|
|
||||||
type timeout struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timeoutf returns an error which satisfies IsTimeout().
|
|
||||||
func Timeoutf(format string, args ...interface{}) error {
|
|
||||||
return &timeout{wrap(nil, format, " timeout", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTimeout returns an error which wraps err that satisfies
|
|
||||||
// IsTimeout().
|
|
||||||
func NewTimeout(err error, msg string) error {
|
|
||||||
return &timeout{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsTimeout reports whether err was created with Timeoutf() or
|
|
||||||
// NewTimeout().
|
|
||||||
func IsTimeout(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*timeout)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// notFound represents an error when something has not been found.
|
|
||||||
type notFound struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotFoundf returns an error which satisfies IsNotFound().
|
|
||||||
func NotFoundf(format string, args ...interface{}) error {
|
|
||||||
return ¬Found{wrap(nil, format, " not found", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotFound returns an error which wraps err that satisfies
|
|
||||||
// IsNotFound().
|
|
||||||
func NewNotFound(err error, msg string) error {
|
|
||||||
return ¬Found{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotFound reports whether err was created with NotFoundf() or
|
|
||||||
// NewNotFound().
|
|
||||||
func IsNotFound(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*notFound)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// userNotFound represents an error when an inexistent user is looked up.
|
|
||||||
type userNotFound struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserNotFoundf returns an error which satisfies IsUserNotFound().
|
|
||||||
func UserNotFoundf(format string, args ...interface{}) error {
|
|
||||||
return &userNotFound{wrap(nil, format, " user not found", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUserNotFound returns an error which wraps err and satisfies
|
|
||||||
// IsUserNotFound().
|
|
||||||
func NewUserNotFound(err error, msg string) error {
|
|
||||||
return &userNotFound{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUserNotFound reports whether err was created with UserNotFoundf() or
|
|
||||||
// NewUserNotFound().
|
|
||||||
func IsUserNotFound(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*userNotFound)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// unauthorized represents an error when an operation is unauthorized.
|
|
||||||
type unauthorized struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unauthorizedf returns an error which satisfies IsUnauthorized().
|
|
||||||
func Unauthorizedf(format string, args ...interface{}) error {
|
|
||||||
return &unauthorized{wrap(nil, format, "", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUnauthorized returns an error which wraps err and satisfies
|
|
||||||
// IsUnauthorized().
|
|
||||||
func NewUnauthorized(err error, msg string) error {
|
|
||||||
return &unauthorized{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUnauthorized reports whether err was created with Unauthorizedf() or
|
|
||||||
// NewUnauthorized().
|
|
||||||
func IsUnauthorized(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*unauthorized)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// notImplemented represents an error when something is not
|
|
||||||
// implemented.
|
|
||||||
type notImplemented struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotImplementedf returns an error which satisfies IsNotImplemented().
|
|
||||||
func NotImplementedf(format string, args ...interface{}) error {
|
|
||||||
return ¬Implemented{wrap(nil, format, " not implemented", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotImplemented returns an error which wraps err and satisfies
|
|
||||||
// IsNotImplemented().
|
|
||||||
func NewNotImplemented(err error, msg string) error {
|
|
||||||
return ¬Implemented{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotImplemented reports whether err was created with
|
|
||||||
// NotImplementedf() or NewNotImplemented().
|
|
||||||
func IsNotImplemented(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*notImplemented)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// alreadyExists represents and error when something already exists.
|
|
||||||
type alreadyExists struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// AlreadyExistsf returns an error which satisfies IsAlreadyExists().
|
|
||||||
func AlreadyExistsf(format string, args ...interface{}) error {
|
|
||||||
return &alreadyExists{wrap(nil, format, " already exists", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAlreadyExists returns an error which wraps err and satisfies
|
|
||||||
// IsAlreadyExists().
|
|
||||||
func NewAlreadyExists(err error, msg string) error {
|
|
||||||
return &alreadyExists{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAlreadyExists reports whether the error was created with
|
|
||||||
// AlreadyExistsf() or NewAlreadyExists().
|
|
||||||
func IsAlreadyExists(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*alreadyExists)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// notSupported represents an error when something is not supported.
|
|
||||||
type notSupported struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotSupportedf returns an error which satisfies IsNotSupported().
|
|
||||||
func NotSupportedf(format string, args ...interface{}) error {
|
|
||||||
return ¬Supported{wrap(nil, format, " not supported", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotSupported returns an error which wraps err and satisfies
|
|
||||||
// IsNotSupported().
|
|
||||||
func NewNotSupported(err error, msg string) error {
|
|
||||||
return ¬Supported{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotSupported reports whether the error was created with
|
|
||||||
// NotSupportedf() or NewNotSupported().
|
|
||||||
func IsNotSupported(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*notSupported)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// notValid represents an error when something is not valid.
|
|
||||||
type notValid struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotValidf returns an error which satisfies IsNotValid().
|
|
||||||
func NotValidf(format string, args ...interface{}) error {
|
|
||||||
return ¬Valid{wrap(nil, format, " not valid", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotValid returns an error which wraps err and satisfies IsNotValid().
|
|
||||||
func NewNotValid(err error, msg string) error {
|
|
||||||
return ¬Valid{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotValid reports whether the error was created with NotValidf() or
|
|
||||||
// NewNotValid().
|
|
||||||
func IsNotValid(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*notValid)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// notProvisioned represents an error when something is not yet provisioned.
|
|
||||||
type notProvisioned struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotProvisionedf returns an error which satisfies IsNotProvisioned().
|
|
||||||
func NotProvisionedf(format string, args ...interface{}) error {
|
|
||||||
return ¬Provisioned{wrap(nil, format, " not provisioned", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotProvisioned returns an error which wraps err that satisfies
|
|
||||||
// IsNotProvisioned().
|
|
||||||
func NewNotProvisioned(err error, msg string) error {
|
|
||||||
return ¬Provisioned{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotProvisioned reports whether err was created with NotProvisionedf() or
|
|
||||||
// NewNotProvisioned().
|
|
||||||
func IsNotProvisioned(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*notProvisioned)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// notAssigned represents an error when something is not yet assigned to
|
|
||||||
// something else.
|
|
||||||
type notAssigned struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotAssignedf returns an error which satisfies IsNotAssigned().
|
|
||||||
func NotAssignedf(format string, args ...interface{}) error {
|
|
||||||
return ¬Assigned{wrap(nil, format, " not assigned", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotAssigned returns an error which wraps err that satisfies
|
|
||||||
// IsNotAssigned().
|
|
||||||
func NewNotAssigned(err error, msg string) error {
|
|
||||||
return ¬Assigned{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotAssigned reports whether err was created with NotAssignedf() or
|
|
||||||
// NewNotAssigned().
|
|
||||||
func IsNotAssigned(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*notAssigned)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// badRequest represents an error when a request has bad parameters.
|
|
||||||
type badRequest struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// BadRequestf returns an error which satisfies IsBadRequest().
|
|
||||||
func BadRequestf(format string, args ...interface{}) error {
|
|
||||||
return &badRequest{wrap(nil, format, "", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBadRequest returns an error which wraps err that satisfies
|
|
||||||
// IsBadRequest().
|
|
||||||
func NewBadRequest(err error, msg string) error {
|
|
||||||
return &badRequest{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsBadRequest reports whether err was created with BadRequestf() or
|
|
||||||
// NewBadRequest().
|
|
||||||
func IsBadRequest(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*badRequest)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// methodNotAllowed represents an error when an HTTP request
|
|
||||||
// is made with an inappropriate method.
|
|
||||||
type methodNotAllowed struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MethodNotAllowedf returns an error which satisfies IsMethodNotAllowed().
|
|
||||||
func MethodNotAllowedf(format string, args ...interface{}) error {
|
|
||||||
return &methodNotAllowed{wrap(nil, format, "", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMethodNotAllowed returns an error which wraps err that satisfies
|
|
||||||
// IsMethodNotAllowed().
|
|
||||||
func NewMethodNotAllowed(err error, msg string) error {
|
|
||||||
return &methodNotAllowed{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMethodNotAllowed reports whether err was created with MethodNotAllowedf() or
|
|
||||||
// NewMethodNotAllowed().
|
|
||||||
func IsMethodNotAllowed(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*methodNotAllowed)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// forbidden represents an error when a request cannot be completed because of
|
|
||||||
// missing privileges
|
|
||||||
type forbidden struct {
|
|
||||||
Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forbiddenf returns an error which satistifes IsForbidden()
|
|
||||||
func Forbiddenf(format string, args ...interface{}) error {
|
|
||||||
return &forbidden{wrap(nil, format, "", args...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewForbidden returns an error which wraps err that satisfies
|
|
||||||
// IsForbidden().
|
|
||||||
func NewForbidden(err error, msg string) error {
|
|
||||||
return &forbidden{wrap(err, msg, "")}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsForbidden reports whether err was created with Forbiddenf() or
|
|
||||||
// NewForbidden().
|
|
||||||
func IsForbidden(err error) bool {
|
|
||||||
err = Cause(err)
|
|
||||||
_, ok := err.(*forbidden)
|
|
||||||
return ok
|
|
||||||
}
|
|
330
vendor/github.com/juju/errors/functions.go
generated
vendored
330
vendor/github.com/juju/errors/functions.go
generated
vendored
@ -1,330 +0,0 @@
|
|||||||
// Copyright 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// New is a drop in replacement for the standard library errors module that records
|
|
||||||
// the location that the error is created.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// return errors.New("validation failed")
|
|
||||||
//
|
|
||||||
func New(message string) error {
|
|
||||||
err := &Err{message: message}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf creates a new annotated error and records the location that the
|
|
||||||
// error is created. This should be a drop in replacement for fmt.Errorf.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// return errors.Errorf("validation failed: %s", message)
|
|
||||||
//
|
|
||||||
func Errorf(format string, args ...interface{}) error {
|
|
||||||
err := &Err{message: fmt.Sprintf(format, args...)}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trace adds the location of the Trace call to the stack. The Cause of the
|
|
||||||
// resulting error is the same as the error parameter. If the other error is
|
|
||||||
// nil, the result will be nil.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// return errors.Trace(err)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Trace(other error) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{previous: other, cause: Cause(other)}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Annotate is used to add extra context to an existing error. The location of
|
|
||||||
// the Annotate call is recorded with the annotations. The file, line and
|
|
||||||
// function are also recorded.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// return errors.Annotate(err, "failed to frombulate")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Annotate(other error, message string) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{
|
|
||||||
previous: other,
|
|
||||||
cause: Cause(other),
|
|
||||||
message: message,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Annotatef is used to add extra context to an existing error. The location of
|
|
||||||
// the Annotate call is recorded with the annotations. The file, line and
|
|
||||||
// function are also recorded.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// return errors.Annotatef(err, "failed to frombulate the %s", arg)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Annotatef(other error, format string, args ...interface{}) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{
|
|
||||||
previous: other,
|
|
||||||
cause: Cause(other),
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeferredAnnotatef annotates the given error (when it is not nil) with the given
|
|
||||||
// format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
|
|
||||||
// does nothing. This method is used in a defer statement in order to annotate any
|
|
||||||
// resulting error with the same message.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
//
|
|
||||||
// defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
|
|
||||||
//
|
|
||||||
func DeferredAnnotatef(err *error, format string, args ...interface{}) {
|
|
||||||
if *err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
newErr := &Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
cause: Cause(*err),
|
|
||||||
previous: *err,
|
|
||||||
}
|
|
||||||
newErr.SetLocation(1)
|
|
||||||
*err = newErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap changes the Cause of the error. The location of the Wrap call is also
|
|
||||||
// stored in the error stack.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// newErr := &packageError{"more context", private_value}
|
|
||||||
// return errors.Wrap(err, newErr)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Wrap(other, newDescriptive error) error {
|
|
||||||
err := &Err{
|
|
||||||
previous: other,
|
|
||||||
cause: newDescriptive,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrapf changes the Cause of the error, and adds an annotation. The location
|
|
||||||
// of the Wrap call is also stored in the error stack.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// if err := SomeFunc(); err != nil {
|
|
||||||
// return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error {
|
|
||||||
err := &Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
previous: other,
|
|
||||||
cause: newDescriptive,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mask masks the given error with the given format string and arguments (like
|
|
||||||
// fmt.Sprintf), returning a new error that maintains the error stack, but
|
|
||||||
// hides the underlying error type. The error string still contains the full
|
|
||||||
// annotations. If you want to hide the annotations, call Wrap.
|
|
||||||
func Maskf(other error, format string, args ...interface{}) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{
|
|
||||||
message: fmt.Sprintf(format, args...),
|
|
||||||
previous: other,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mask hides the underlying error type, and records the location of the masking.
|
|
||||||
func Mask(other error) error {
|
|
||||||
if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := &Err{
|
|
||||||
previous: other,
|
|
||||||
}
|
|
||||||
err.SetLocation(1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cause returns the cause of the given error. This will be either the
|
|
||||||
// original error, or the result of a Wrap or Mask call.
|
|
||||||
//
|
|
||||||
// Cause is the usual way to diagnose errors that may have been wrapped by
|
|
||||||
// the other errors functions.
|
|
||||||
func Cause(err error) error {
|
|
||||||
var diag error
|
|
||||||
if err, ok := err.(causer); ok {
|
|
||||||
diag = err.Cause()
|
|
||||||
}
|
|
||||||
if diag != nil {
|
|
||||||
return diag
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type causer interface {
|
|
||||||
Cause() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type wrapper interface {
|
|
||||||
// Message returns the top level error message,
|
|
||||||
// not including the message from the Previous
|
|
||||||
// error.
|
|
||||||
Message() string
|
|
||||||
|
|
||||||
// Underlying returns the Previous error, or nil
|
|
||||||
// if there is none.
|
|
||||||
Underlying() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type locationer interface {
|
|
||||||
Location() (string, int)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ wrapper = (*Err)(nil)
|
|
||||||
_ locationer = (*Err)(nil)
|
|
||||||
_ causer = (*Err)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Details returns information about the stack of errors wrapped by err, in
|
|
||||||
// the format:
|
|
||||||
//
|
|
||||||
// [{filename:99: error one} {otherfile:55: cause of error one}]
|
|
||||||
//
|
|
||||||
// This is a terse alternative to ErrorStack as it returns a single line.
|
|
||||||
func Details(err error) string {
|
|
||||||
if err == nil {
|
|
||||||
return "[]"
|
|
||||||
}
|
|
||||||
var s []byte
|
|
||||||
s = append(s, '[')
|
|
||||||
for {
|
|
||||||
s = append(s, '{')
|
|
||||||
if err, ok := err.(locationer); ok {
|
|
||||||
file, line := err.Location()
|
|
||||||
if file != "" {
|
|
||||||
s = append(s, fmt.Sprintf("%s:%d", file, line)...)
|
|
||||||
s = append(s, ": "...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cerr, ok := err.(wrapper); ok {
|
|
||||||
s = append(s, cerr.Message()...)
|
|
||||||
err = cerr.Underlying()
|
|
||||||
} else {
|
|
||||||
s = append(s, err.Error()...)
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
s = append(s, '}')
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
s = append(s, ' ')
|
|
||||||
}
|
|
||||||
s = append(s, ']')
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorStack returns a string representation of the annotated error. If the
|
|
||||||
// error passed as the parameter is not an annotated error, the result is
|
|
||||||
// simply the result of the Error() method on that error.
|
|
||||||
//
|
|
||||||
// If the error is an annotated error, a multi-line string is returned where
|
|
||||||
// each line represents one entry in the annotation stack. The full filename
|
|
||||||
// from the call stack is used in the output.
|
|
||||||
//
|
|
||||||
// first error
|
|
||||||
// github.com/juju/errors/annotation_test.go:193:
|
|
||||||
// github.com/juju/errors/annotation_test.go:194: annotation
|
|
||||||
// github.com/juju/errors/annotation_test.go:195:
|
|
||||||
// github.com/juju/errors/annotation_test.go:196: more context
|
|
||||||
// github.com/juju/errors/annotation_test.go:197:
|
|
||||||
func ErrorStack(err error) string {
|
|
||||||
return strings.Join(errorStack(err), "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func errorStack(err error) []string {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want the first error first
|
|
||||||
var lines []string
|
|
||||||
for {
|
|
||||||
var buff []byte
|
|
||||||
if err, ok := err.(locationer); ok {
|
|
||||||
file, line := err.Location()
|
|
||||||
// Strip off the leading GOPATH/src path elements.
|
|
||||||
file = trimGoPath(file)
|
|
||||||
if file != "" {
|
|
||||||
buff = append(buff, fmt.Sprintf("%s:%d", file, line)...)
|
|
||||||
buff = append(buff, ": "...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cerr, ok := err.(wrapper); ok {
|
|
||||||
message := cerr.Message()
|
|
||||||
buff = append(buff, message...)
|
|
||||||
// If there is a cause for this error, and it is different to the cause
|
|
||||||
// of the underlying error, then output the error string in the stack trace.
|
|
||||||
var cause error
|
|
||||||
if err1, ok := err.(causer); ok {
|
|
||||||
cause = err1.Cause()
|
|
||||||
}
|
|
||||||
err = cerr.Underlying()
|
|
||||||
if cause != nil && !sameError(Cause(err), cause) {
|
|
||||||
if message != "" {
|
|
||||||
buff = append(buff, ": "...)
|
|
||||||
}
|
|
||||||
buff = append(buff, cause.Error()...)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buff = append(buff, err.Error()...)
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
lines = append(lines, string(buff))
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// reverse the lines to get the original error, which was at the end of
|
|
||||||
// the list, back to the start.
|
|
||||||
var result []string
|
|
||||||
for i := len(lines); i > 0; i-- {
|
|
||||||
result = append(result, lines[i-1])
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
19
vendor/github.com/juju/errors/path.go
generated
vendored
19
vendor/github.com/juju/errors/path.go
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
// Copyright 2013, 2014 Canonical Ltd.
|
|
||||||
// Licensed under the LGPLv3, see LICENCE file for details.
|
|
||||||
|
|
||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var goPath = build.Default.GOPATH
|
|
||||||
var srcDir = filepath.Join(goPath, "src")
|
|
||||||
|
|
||||||
func trimGoPath(filename string) string {
|
|
||||||
return strings.TrimPrefix(filename, fmt.Sprintf("%s%s", srcDir, string(os.PathSeparator)))
|
|
||||||
}
|
|
383
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
383
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
@ -1,383 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
//go:generate go run gen.go
|
|
||||||
|
|
||||||
// This program generates internet protocol constants and tables by
|
|
||||||
// reading IANA protocol registries.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var registries = []struct {
|
|
||||||
url string
|
|
||||||
parse func(io.Writer, io.Reader) error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
|
|
||||||
parseDSCPRegistry,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
|
||||||
parseProtocolNumbers,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
|
|
||||||
parseAddrFamilyNumbers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var bb bytes.Buffer
|
|
||||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
|
||||||
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
|
||||||
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
|
|
||||||
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
|
|
||||||
for _, r := range registries {
|
|
||||||
resp, err := http.Get(r.url)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := r.parse(&bb, resp.Body); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&bb, "\n")
|
|
||||||
}
|
|
||||||
b, err := format.Source(bb.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var dr dscpRegistry
|
|
||||||
if err := dec.Decode(&dr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, dr := range dr.escapeDSCP() {
|
|
||||||
fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", dr.OrigName)
|
|
||||||
}
|
|
||||||
for _, er := range dr.escapeECN() {
|
|
||||||
fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", er.OrigDescr)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type dscpRegistry struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
Note string `xml:"note"`
|
|
||||||
Registries []struct {
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Registries []struct {
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Records []struct {
|
|
||||||
Name string `xml:"name"`
|
|
||||||
Space string `xml:"space"`
|
|
||||||
} `xml:"record"`
|
|
||||||
} `xml:"registry"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Descr string `xml:"description"`
|
|
||||||
} `xml:"record"`
|
|
||||||
} `xml:"registry"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonDSCPRecord struct {
|
|
||||||
OrigName string
|
|
||||||
Name string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord {
|
|
||||||
var drs []canonDSCPRecord
|
|
||||||
for _, preg := range drr.Registries {
|
|
||||||
if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, reg := range preg.Registries {
|
|
||||||
if !strings.Contains(reg.Title, "Pool 1 Codepoints") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
drs = make([]canonDSCPRecord, len(reg.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"+", "",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, dr := range reg.Records {
|
|
||||||
s := strings.TrimSpace(dr.Name)
|
|
||||||
drs[i].OrigName = s
|
|
||||||
drs[i].Name = sr.Replace(s)
|
|
||||||
n, err := strconv.ParseUint(dr.Space, 2, 8)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
drs[i].Value = int(n) << 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return drs
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonECNRecord struct {
|
|
||||||
OrigDescr string
|
|
||||||
Descr string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (drr *dscpRegistry) escapeECN() []canonECNRecord {
|
|
||||||
var ers []canonECNRecord
|
|
||||||
for _, reg := range drr.Registries {
|
|
||||||
if !strings.Contains(reg.Title, "ECN Field") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ers = make([]canonECNRecord, len(reg.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"Capable", "",
|
|
||||||
"Not-ECT", "",
|
|
||||||
"ECT(1)", "",
|
|
||||||
"ECT(0)", "",
|
|
||||||
"CE", "",
|
|
||||||
"(", "",
|
|
||||||
")", "",
|
|
||||||
"+", "",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, er := range reg.Records {
|
|
||||||
s := strings.TrimSpace(er.Descr)
|
|
||||||
ers[i].OrigDescr = s
|
|
||||||
ss := strings.Split(s, " ")
|
|
||||||
if len(ss) > 1 {
|
|
||||||
ers[i].Descr = strings.Join(ss[1:], " ")
|
|
||||||
} else {
|
|
||||||
ers[i].Descr = ss[0]
|
|
||||||
}
|
|
||||||
ers[i].Descr = sr.Replace(er.Descr)
|
|
||||||
n, err := strconv.ParseUint(er.Value, 2, 8)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ers[i].Value = int(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ers
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var pn protocolNumbers
|
|
||||||
if err := dec.Decode(&pn); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
prs := pn.escape()
|
|
||||||
prs = append([]canonProtocolRecord{{
|
|
||||||
Name: "IP",
|
|
||||||
Descr: "IPv4 encapsulation, pseudo protocol number",
|
|
||||||
Value: 0,
|
|
||||||
}}, prs...)
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, pr := range prs {
|
|
||||||
if pr.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
|
|
||||||
s := pr.Descr
|
|
||||||
if s == "" {
|
|
||||||
s = pr.OrigName
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "// %s\n", s)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type protocolNumbers struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
RegTitle string `xml:"registry>title"`
|
|
||||||
Note string `xml:"registry>note"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Name string `xml:"name"`
|
|
||||||
Descr string `xml:"description"`
|
|
||||||
} `xml:"registry>record"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonProtocolRecord struct {
|
|
||||||
OrigName string
|
|
||||||
Name string
|
|
||||||
Descr string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pn *protocolNumbers) escape() []canonProtocolRecord {
|
|
||||||
prs := make([]canonProtocolRecord, len(pn.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"-in-", "in",
|
|
||||||
"-within-", "within",
|
|
||||||
"-over-", "over",
|
|
||||||
"+", "P",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, pr := range pn.Records {
|
|
||||||
if strings.Contains(pr.Name, "Deprecated") ||
|
|
||||||
strings.Contains(pr.Name, "deprecated") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
prs[i].OrigName = pr.Name
|
|
||||||
s := strings.TrimSpace(pr.Name)
|
|
||||||
switch pr.Name {
|
|
||||||
case "ISIS over IPv4":
|
|
||||||
prs[i].Name = "ISIS"
|
|
||||||
case "manet":
|
|
||||||
prs[i].Name = "MANET"
|
|
||||||
default:
|
|
||||||
prs[i].Name = sr.Replace(s)
|
|
||||||
}
|
|
||||||
ss := strings.Split(pr.Descr, "\n")
|
|
||||||
for i := range ss {
|
|
||||||
ss[i] = strings.TrimSpace(ss[i])
|
|
||||||
}
|
|
||||||
if len(ss) > 1 {
|
|
||||||
prs[i].Descr = strings.Join(ss, " ")
|
|
||||||
} else {
|
|
||||||
prs[i].Descr = ss[0]
|
|
||||||
}
|
|
||||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
|
||||||
}
|
|
||||||
return prs
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var afn addrFamilylNumbers
|
|
||||||
if err := dec.Decode(&afn); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
afrs := afn.escape()
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, afr := range afrs {
|
|
||||||
if afr.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", afr.Descr)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type addrFamilylNumbers struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
RegTitle string `xml:"registry>title"`
|
|
||||||
Note string `xml:"registry>note"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Descr string `xml:"description"`
|
|
||||||
} `xml:"registry>record"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonAddrFamilyRecord struct {
|
|
||||||
Name string
|
|
||||||
Descr string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
|
|
||||||
afrs := make([]canonAddrFamilyRecord, len(afn.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"IP version 4", "IPv4",
|
|
||||||
"IP version 6", "IPv6",
|
|
||||||
"Identifier", "ID",
|
|
||||||
"-", "",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, afr := range afn.Records {
|
|
||||||
if strings.Contains(afr.Descr, "Unassigned") ||
|
|
||||||
strings.Contains(afr.Descr, "Reserved") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
afrs[i].Descr = afr.Descr
|
|
||||||
s := strings.TrimSpace(afr.Descr)
|
|
||||||
switch s {
|
|
||||||
case "IP (IP version 4)":
|
|
||||||
afrs[i].Name = "IPv4"
|
|
||||||
case "IP6 (IP version 6)":
|
|
||||||
afrs[i].Name = "IPv6"
|
|
||||||
case "AFI for L2VPN information":
|
|
||||||
afrs[i].Name = "L2VPN"
|
|
||||||
case "E.164 with NSAP format subaddress":
|
|
||||||
afrs[i].Name = "E164withSubaddress"
|
|
||||||
case "MT IP: Multi-Topology IP version 4":
|
|
||||||
afrs[i].Name = "MTIPv4"
|
|
||||||
case "MAC/24":
|
|
||||||
afrs[i].Name = "MACFinal24bits"
|
|
||||||
case "MAC/40":
|
|
||||||
afrs[i].Name = "MACFinal40bits"
|
|
||||||
case "IPv6/64":
|
|
||||||
afrs[i].Name = "IPv6Initial64bits"
|
|
||||||
default:
|
|
||||||
n := strings.Index(s, "(")
|
|
||||||
if n > 0 {
|
|
||||||
s = s[:n]
|
|
||||||
}
|
|
||||||
n = strings.Index(s, ":")
|
|
||||||
if n > 0 {
|
|
||||||
s = s[:n]
|
|
||||||
}
|
|
||||||
afrs[i].Name = sr.Replace(s)
|
|
||||||
}
|
|
||||||
afrs[i].Value, _ = strconv.Atoi(afr.Value)
|
|
||||||
}
|
|
||||||
return afrs
|
|
||||||
}
|
|
44
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
44
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysAF_UNSPEC = C.AF_UNSPEC
|
|
||||||
sysAF_INET = C.AF_INET
|
|
||||||
sysAF_INET6 = C.AF_INET6
|
|
||||||
|
|
||||||
sysSOCK_RAW = C.SOCK_RAW
|
|
||||||
)
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
44
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
44
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysAF_UNSPEC = C.AF_UNSPEC
|
|
||||||
sysAF_INET = C.AF_INET
|
|
||||||
sysAF_INET6 = C.AF_INET6
|
|
||||||
|
|
||||||
sysSOCK_RAW = C.SOCK_RAW
|
|
||||||
)
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
44
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
44
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysAF_UNSPEC = C.AF_UNSPEC
|
|
||||||
sysAF_INET = C.AF_INET
|
|
||||||
sysAF_INET6 = C.AF_INET6
|
|
||||||
|
|
||||||
sysSOCK_RAW = C.SOCK_RAW
|
|
||||||
)
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
49
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
49
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
@ -1,49 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <linux/in.h>
|
|
||||||
#include <linux/in6.h>
|
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <sys/socket.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysAF_UNSPEC = C.AF_UNSPEC
|
|
||||||
sysAF_INET = C.AF_INET
|
|
||||||
sysAF_INET6 = C.AF_INET6
|
|
||||||
|
|
||||||
sysSOCK_RAW = C.SOCK_RAW
|
|
||||||
)
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type mmsghdr C.struct_mmsghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
47
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
47
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
@ -1,47 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysAF_UNSPEC = C.AF_UNSPEC
|
|
||||||
sysAF_INET = C.AF_INET
|
|
||||||
sysAF_INET6 = C.AF_INET6
|
|
||||||
|
|
||||||
sysSOCK_RAW = C.SOCK_RAW
|
|
||||||
)
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type mmsghdr C.struct_mmsghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
44
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
44
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysAF_UNSPEC = C.AF_UNSPEC
|
|
||||||
sysAF_INET = C.AF_INET
|
|
||||||
sysAF_INET6 = C.AF_INET6
|
|
||||||
|
|
||||||
sysSOCK_RAW = C.SOCK_RAW
|
|
||||||
)
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
44
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
44
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysAF_UNSPEC = C.AF_UNSPEC
|
|
||||||
sysAF_INET = C.AF_INET
|
|
||||||
sysAF_INET6 = C.AF_INET6
|
|
||||||
|
|
||||||
sysSOCK_RAW = C.SOCK_RAW
|
|
||||||
)
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
77
vendor/golang.org/x/net/ipv4/defs_darwin.go
generated
vendored
77
vendor/golang.org/x/net/ipv4/defs_darwin.go
generated
vendored
@ -1,77 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_STRIPHDR = C.IP_STRIPHDR
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
sysIP_BOUND_IF = C.IP_BOUND_IF
|
|
||||||
sysIP_PKTINFO = C.IP_PKTINFO
|
|
||||||
sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
|
||||||
sysIP_MULTICAST_IFINDEX = C.IP_MULTICAST_IFINDEX
|
|
||||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
|
||||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
|
||||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type inetPktinfo C.struct_in_pktinfo
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type ipMreqn C.struct_ip_mreqn
|
|
||||||
|
|
||||||
type ipMreqSource C.struct_ip_mreq_source
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
38
vendor/golang.org/x/net/ipv4/defs_dragonfly.go
generated
vendored
38
vendor/golang.org/x/net/ipv4/defs_dragonfly.go
generated
vendored
@ -1,38 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
)
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
75
vendor/golang.org/x/net/ipv4/defs_freebsd.go
generated
vendored
75
vendor/golang.org/x/net/ipv4/defs_freebsd.go
generated
vendored
@ -1,75 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_SENDSRCADDR = C.IP_SENDSRCADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_ONESBCAST = C.IP_ONESBCAST
|
|
||||||
sysIP_BINDANY = C.IP_BINDANY
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
sysIP_MINTTL = C.IP_MINTTL
|
|
||||||
sysIP_DONTFRAG = C.IP_DONTFRAG
|
|
||||||
sysIP_RECVTOS = C.IP_RECVTOS
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
|
||||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
|
||||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
|
||||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type ipMreqn C.struct_ip_mreqn
|
|
||||||
|
|
||||||
type ipMreqSource C.struct_ip_mreq_source
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
122
vendor/golang.org/x/net/ipv4/defs_linux.go
generated
vendored
122
vendor/golang.org/x/net/ipv4/defs_linux.go
generated
vendored
@ -1,122 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <linux/errqueue.h>
|
|
||||||
#include <linux/icmp.h>
|
|
||||||
#include <linux/in.h>
|
|
||||||
#include <linux/filter.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_ROUTER_ALERT = C.IP_ROUTER_ALERT
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_PKTINFO = C.IP_PKTINFO
|
|
||||||
sysIP_PKTOPTIONS = C.IP_PKTOPTIONS
|
|
||||||
sysIP_MTU_DISCOVER = C.IP_MTU_DISCOVER
|
|
||||||
sysIP_RECVERR = C.IP_RECVERR
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
sysIP_RECVTOS = C.IP_RECVTOS
|
|
||||||
sysIP_MTU = C.IP_MTU
|
|
||||||
sysIP_FREEBIND = C.IP_FREEBIND
|
|
||||||
sysIP_TRANSPARENT = C.IP_TRANSPARENT
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_ORIGDSTADDR = C.IP_ORIGDSTADDR
|
|
||||||
sysIP_RECVORIGDSTADDR = C.IP_RECVORIGDSTADDR
|
|
||||||
sysIP_MINTTL = C.IP_MINTTL
|
|
||||||
sysIP_NODEFRAG = C.IP_NODEFRAG
|
|
||||||
sysIP_UNICAST_IF = C.IP_UNICAST_IF
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
|
||||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
|
||||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_MSFILTER = C.IP_MSFILTER
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_MSFILTER = C.MCAST_MSFILTER
|
|
||||||
sysIP_MULTICAST_ALL = C.IP_MULTICAST_ALL
|
|
||||||
|
|
||||||
//sysIP_PMTUDISC_DONT = C.IP_PMTUDISC_DONT
|
|
||||||
//sysIP_PMTUDISC_WANT = C.IP_PMTUDISC_WANT
|
|
||||||
//sysIP_PMTUDISC_DO = C.IP_PMTUDISC_DO
|
|
||||||
//sysIP_PMTUDISC_PROBE = C.IP_PMTUDISC_PROBE
|
|
||||||
//sysIP_PMTUDISC_INTERFACE = C.IP_PMTUDISC_INTERFACE
|
|
||||||
//sysIP_PMTUDISC_OMIT = C.IP_PMTUDISC_OMIT
|
|
||||||
|
|
||||||
sysICMP_FILTER = C.ICMP_FILTER
|
|
||||||
|
|
||||||
sysSO_EE_ORIGIN_NONE = C.SO_EE_ORIGIN_NONE
|
|
||||||
sysSO_EE_ORIGIN_LOCAL = C.SO_EE_ORIGIN_LOCAL
|
|
||||||
sysSO_EE_ORIGIN_ICMP = C.SO_EE_ORIGIN_ICMP
|
|
||||||
sysSO_EE_ORIGIN_ICMP6 = C.SO_EE_ORIGIN_ICMP6
|
|
||||||
sysSO_EE_ORIGIN_TXSTATUS = C.SO_EE_ORIGIN_TXSTATUS
|
|
||||||
sysSO_EE_ORIGIN_TIMESTAMPING = C.SO_EE_ORIGIN_TIMESTAMPING
|
|
||||||
|
|
||||||
sysSOL_SOCKET = C.SOL_SOCKET
|
|
||||||
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
|
|
||||||
|
|
||||||
sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
|
||||||
sizeofSockExtendedErr = C.sizeof_struct_sock_extended_err
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
|
||||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPFilter = C.sizeof_struct_icmp_filter
|
|
||||||
|
|
||||||
sizeofSockFprog = C.sizeof_struct_sock_fprog
|
|
||||||
)
|
|
||||||
|
|
||||||
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type inetPktinfo C.struct_in_pktinfo
|
|
||||||
|
|
||||||
type sockExtendedErr C.struct_sock_extended_err
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type ipMreqn C.struct_ip_mreqn
|
|
||||||
|
|
||||||
type ipMreqSource C.struct_ip_mreq_source
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
||||||
|
|
||||||
type icmpFilter C.struct_icmp_filter
|
|
||||||
|
|
||||||
type sockFProg C.struct_sock_fprog
|
|
||||||
|
|
||||||
type sockFilter C.struct_sock_filter
|
|
37
vendor/golang.org/x/net/ipv4/defs_netbsd.go
generated
vendored
37
vendor/golang.org/x/net/ipv4/defs_netbsd.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
)
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
37
vendor/golang.org/x/net/ipv4/defs_openbsd.go
generated
vendored
37
vendor/golang.org/x/net/ipv4/defs_openbsd.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
)
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
84
vendor/golang.org/x/net/ipv4/defs_solaris.go
generated
vendored
84
vendor/golang.org/x/net/ipv4/defs_solaris.go
generated
vendored
@ -1,84 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_RECVSLLA = C.IP_RECVSLLA
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
|
||||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
|
||||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_NEXTHOP = C.IP_NEXTHOP
|
|
||||||
|
|
||||||
sysIP_PKTINFO = C.IP_PKTINFO
|
|
||||||
sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
|
|
||||||
sysIP_DONTFRAG = C.IP_DONTFRAG
|
|
||||||
|
|
||||||
sysIP_BOUND_IF = C.IP_BOUND_IF
|
|
||||||
sysIP_UNSPEC_SRC = C.IP_UNSPEC_SRC
|
|
||||||
sysIP_BROADCAST_TTL = C.IP_BROADCAST_TTL
|
|
||||||
sysIP_DHCPINIT_IF = C.IP_DHCPINIT_IF
|
|
||||||
|
|
||||||
sysIP_REUSEADDR = C.IP_REUSEADDR
|
|
||||||
sysIP_DONTROUTE = C.IP_DONTROUTE
|
|
||||||
sysIP_BROADCAST = C.IP_BROADCAST
|
|
||||||
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type inetPktinfo C.struct_in_pktinfo
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type ipMreqSource C.struct_ip_mreq_source
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
199
vendor/golang.org/x/net/ipv4/gen.go
generated
vendored
199
vendor/golang.org/x/net/ipv4/gen.go
generated
vendored
@ -1,199 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
//go:generate go run gen.go
|
|
||||||
|
|
||||||
// This program generates system adaptation constants and types,
|
|
||||||
// internet protocol constants and tables by reading template files
|
|
||||||
// and IANA protocol registries.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := genzsys(); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := geniana(); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func genzsys() error {
|
|
||||||
defs := "defs_" + runtime.GOOS + ".go"
|
|
||||||
f, err := os.Open(defs)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.Close()
|
|
||||||
cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
|
|
||||||
b, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b, err = format.Source(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
zsys := "zsys_" + runtime.GOOS + ".go"
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "freebsd", "linux":
|
|
||||||
zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var registries = []struct {
|
|
||||||
url string
|
|
||||||
parse func(io.Writer, io.Reader) error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
|
|
||||||
parseICMPv4Parameters,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func geniana() error {
|
|
||||||
var bb bytes.Buffer
|
|
||||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
|
||||||
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
|
||||||
fmt.Fprintf(&bb, "package ipv4\n\n")
|
|
||||||
for _, r := range registries {
|
|
||||||
resp, err := http.Get(r.url)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
|
||||||
}
|
|
||||||
if err := r.parse(&bb, resp.Body); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&bb, "\n")
|
|
||||||
}
|
|
||||||
b, err := format.Source(bb.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var icp icmpv4Parameters
|
|
||||||
if err := dec.Decode(&icp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
prs := icp.escape()
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, pr := range prs {
|
|
||||||
if pr.Descr == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n\n")
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
|
||||||
fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
|
|
||||||
for _, pr := range prs {
|
|
||||||
if pr.Descr == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "}\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type icmpv4Parameters struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
Registries []struct {
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Descr string `xml:"description"`
|
|
||||||
} `xml:"record"`
|
|
||||||
} `xml:"registry"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonICMPv4ParamRecord struct {
|
|
||||||
OrigDescr string
|
|
||||||
Descr string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
|
|
||||||
id := -1
|
|
||||||
for i, r := range icp.Registries {
|
|
||||||
if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
|
|
||||||
id = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if id < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"Messages", "",
|
|
||||||
"Message", "",
|
|
||||||
"ICMP", "",
|
|
||||||
"+", "P",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, pr := range icp.Registries[id].Records {
|
|
||||||
if strings.Contains(pr.Descr, "Reserved") ||
|
|
||||||
strings.Contains(pr.Descr, "Unassigned") ||
|
|
||||||
strings.Contains(pr.Descr, "Deprecated") ||
|
|
||||||
strings.Contains(pr.Descr, "Experiment") ||
|
|
||||||
strings.Contains(pr.Descr, "experiment") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ss := strings.Split(pr.Descr, "\n")
|
|
||||||
if len(ss) > 1 {
|
|
||||||
prs[i].Descr = strings.Join(ss, " ")
|
|
||||||
} else {
|
|
||||||
prs[i].Descr = ss[0]
|
|
||||||
}
|
|
||||||
s := strings.TrimSpace(prs[i].Descr)
|
|
||||||
prs[i].OrigDescr = s
|
|
||||||
prs[i].Descr = sr.Replace(s)
|
|
||||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
|
||||||
}
|
|
||||||
return prs
|
|
||||||
}
|
|
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
@ -1,61 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
|
|
||||||
//This program must be run after mksyscall.go.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
in1, err := ioutil.ReadFile("syscall_darwin.go")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("can't open syscall_darwin.go: %s", err)
|
|
||||||
}
|
|
||||||
arch := os.Args[1]
|
|
||||||
in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
|
|
||||||
}
|
|
||||||
in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
|
|
||||||
}
|
|
||||||
in := string(in1) + string(in2) + string(in3)
|
|
||||||
|
|
||||||
trampolines := map[string]bool{}
|
|
||||||
|
|
||||||
var out bytes.Buffer
|
|
||||||
|
|
||||||
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
|
|
||||||
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
|
|
||||||
fmt.Fprintf(&out, "\n")
|
|
||||||
fmt.Fprintf(&out, "// +build go1.12\n")
|
|
||||||
fmt.Fprintf(&out, "\n")
|
|
||||||
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
|
|
||||||
for _, line := range strings.Split(in, "\n") {
|
|
||||||
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fn := line[5 : len(line)-13]
|
|
||||||
if !trampolines[fn] {
|
|
||||||
trampolines[fn] = true
|
|
||||||
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
|
|
||||||
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
|
|
||||||
}
|
|
||||||
}
|
|
122
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
122
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
@ -1,122 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// mkpost processes the output of cgo -godefs to
|
|
||||||
// modify the generated types. It is used to clean up
|
|
||||||
// the sys API in an architecture specific manner.
|
|
||||||
//
|
|
||||||
// mkpost is run after cgo -godefs; see README.md.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goos := os.Getenv("GOOS")
|
|
||||||
goarch := os.Getenv("GOARCH_TARGET")
|
|
||||||
if goarch == "" {
|
|
||||||
goarch = os.Getenv("GOARCH")
|
|
||||||
}
|
|
||||||
// Check that we are using the Docker-based build system if we should be.
|
|
||||||
if goos == "linux" {
|
|
||||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
|
||||||
os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n")
|
|
||||||
os.Stderr.WriteString("See README.md\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(os.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if goos == "aix" {
|
|
||||||
// Replace type of Atim, Mtim and Ctim by Timespec in Stat_t
|
|
||||||
// to avoid having both StTimespec and Timespec.
|
|
||||||
sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`)
|
|
||||||
b = sttimespec.ReplaceAll(b, []byte("Timespec"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intentionally export __val fields in Fsid and Sigset_t
|
|
||||||
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__val(\s+\S+\s+)}`)
|
|
||||||
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$3}"))
|
|
||||||
|
|
||||||
// Intentionally export __fds_bits field in FdSet
|
|
||||||
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`)
|
|
||||||
b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}"))
|
|
||||||
|
|
||||||
// If we have empty Ptrace structs, we should delete them. Only s390x emits
|
|
||||||
// nonempty Ptrace structs.
|
|
||||||
ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`)
|
|
||||||
b = ptraceRexexp.ReplaceAll(b, nil)
|
|
||||||
|
|
||||||
// Replace the control_regs union with a blank identifier for now.
|
|
||||||
controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`)
|
|
||||||
b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64"))
|
|
||||||
|
|
||||||
// Remove fields that are added by glibc
|
|
||||||
// Note that this is unstable as the identifers are private.
|
|
||||||
removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`)
|
|
||||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
|
|
||||||
// Convert [65]int8 to [65]byte in Utsname members to simplify
|
|
||||||
// conversion to string; see golang.org/issue/20753
|
|
||||||
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
|
|
||||||
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
|
|
||||||
|
|
||||||
// Convert [1024]int8 to [1024]byte in Ptmget members
|
|
||||||
convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`)
|
|
||||||
b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte"))
|
|
||||||
|
|
||||||
// Remove spare fields (e.g. in Statx_t)
|
|
||||||
spareFieldsRegex := regexp.MustCompile(`X__spare\S*`)
|
|
||||||
b = spareFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
|
|
||||||
// Remove cgo padding fields
|
|
||||||
removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`)
|
|
||||||
b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
|
|
||||||
// Remove padding, hidden, or unused fields
|
|
||||||
removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`)
|
|
||||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
|
|
||||||
// Remove the first line of warning from cgo
|
|
||||||
b = b[bytes.IndexByte(b, '\n')+1:]
|
|
||||||
// Modify the command in the header to include:
|
|
||||||
// mkpost, our own warning, and a build tag.
|
|
||||||
replacement := fmt.Sprintf(`$1 | go run mkpost.go
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s,%s`, goarch, goos)
|
|
||||||
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
|
|
||||||
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
|
|
||||||
|
|
||||||
// Rename Stat_t time fields
|
|
||||||
if goos == "freebsd" && goarch == "386" {
|
|
||||||
// Hide Stat_t.[AMCB]tim_ext fields
|
|
||||||
renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`)
|
|
||||||
b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
}
|
|
||||||
renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`)
|
|
||||||
b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}"))
|
|
||||||
|
|
||||||
// gofmt
|
|
||||||
b, err = format.Source(b)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Stdout.Write(b)
|
|
||||||
}
|
|
407
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
407
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
@ -1,407 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
This program reads a file containing function prototypes
|
|
||||||
(like syscall_darwin.go) and generates system call bodies.
|
|
||||||
The prototypes are marked by lines beginning with "//sys"
|
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument.
|
|
||||||
This includes return parameters.
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
* If the return parameter is an error number, it must be named errno.
|
|
||||||
|
|
||||||
A line beginning with //sysnb is like //sys, except that the
|
|
||||||
goroutine will not be suspended during the execution of the system
|
|
||||||
call. This must only be used for system calls which can never
|
|
||||||
block, as otherwise the system call could cause all goroutines to
|
|
||||||
hang.
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
|
||||||
plan9 = flag.Bool("plan9", false, "plan9")
|
|
||||||
openbsd = flag.Bool("openbsd", false, "openbsd")
|
|
||||||
netbsd = flag.Bool("netbsd", false, "netbsd")
|
|
||||||
dragonfly = flag.Bool("dragonfly", false, "dragonfly")
|
|
||||||
arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair
|
|
||||||
tags = flag.String("tags", "", "build tags")
|
|
||||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksyscall.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return *tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string {
|
|
||||||
list = strings.TrimSpace(list)
|
|
||||||
if list == "" {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param {
|
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
|
||||||
if ps == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return Param{ps[1], ps[2]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goos := os.Getenv("GOOS")
|
|
||||||
if goos == "" {
|
|
||||||
fmt.Fprintln(os.Stderr, "GOOS not defined in environment")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
goarch := os.Getenv("GOARCH_TARGET")
|
|
||||||
if goarch == "" {
|
|
||||||
goarch = os.Getenv("GOARCH")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that we are using the Docker-based build system if we should
|
|
||||||
if goos == "linux" {
|
|
||||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
|
||||||
fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n")
|
|
||||||
fmt.Fprintf(os.Stderr, "See README.md\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness := ""
|
|
||||||
if *b32 {
|
|
||||||
endianness = "big-endian"
|
|
||||||
} else if *l32 {
|
|
||||||
endianness = "little-endian"
|
|
||||||
}
|
|
||||||
|
|
||||||
libc := false
|
|
||||||
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") {
|
|
||||||
libc = true
|
|
||||||
}
|
|
||||||
trampolines := map[string]bool{}
|
|
||||||
|
|
||||||
text := ""
|
|
||||||
for _, path := range flag.Args() {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := s.Text()
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, errno error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t)
|
|
||||||
if f == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
funct, inps, outps, sysname := f[2], f[3], f[4], f[5]
|
|
||||||
|
|
||||||
// ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers.
|
|
||||||
if goos == "darwin" && !libc && funct == "ClockGettime" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps)
|
|
||||||
out := parseParamList(outps)
|
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
outDecl := ""
|
|
||||||
if len(out) > 0 {
|
|
||||||
outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", "))
|
|
||||||
}
|
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl)
|
|
||||||
|
|
||||||
// Check if err return available
|
|
||||||
errvar := ""
|
|
||||||
for _, param := range out {
|
|
||||||
p := parseParam(param)
|
|
||||||
if p.Type == "error" {
|
|
||||||
errvar = p.Name
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string
|
|
||||||
n := 0
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
|
||||||
} else if p.Type == "string" && errvar != "" {
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
|
||||||
text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name)
|
|
||||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
|
||||||
text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
n++
|
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass dummy pointer in that case.
|
|
||||||
// Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
|
|
||||||
text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n)
|
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name)
|
|
||||||
text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "int64" && (*openbsd || *netbsd) {
|
|
||||||
args = append(args, "0")
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else if endianness == "little-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "int64" && *dragonfly {
|
|
||||||
if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else if endianness == "little-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
}
|
|
||||||
} else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" {
|
|
||||||
if len(args)%2 == 1 && *arm {
|
|
||||||
// arm abi specifies 64-bit argument uses
|
|
||||||
// (even, odd) pair
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which form to use; pad args with zeros.
|
|
||||||
asm := "Syscall"
|
|
||||||
if nonblock != nil {
|
|
||||||
if errvar == "" && goos == "linux" {
|
|
||||||
asm = "RawSyscallNoError"
|
|
||||||
} else {
|
|
||||||
asm = "RawSyscall"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if errvar == "" && goos == "linux" {
|
|
||||||
asm = "SyscallNoError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(args) <= 3 {
|
|
||||||
for len(args) < 3 {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
} else if len(args) <= 6 {
|
|
||||||
asm += "6"
|
|
||||||
for len(args) < 6 {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
} else if len(args) <= 9 {
|
|
||||||
asm += "9"
|
|
||||||
for len(args) < 9 {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct)
|
|
||||||
}
|
|
||||||
|
|
||||||
// System call number.
|
|
||||||
if sysname == "" {
|
|
||||||
sysname = "SYS_" + funct
|
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
|
||||||
sysname = strings.ToUpper(sysname)
|
|
||||||
}
|
|
||||||
|
|
||||||
var libcFn string
|
|
||||||
if libc {
|
|
||||||
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
|
|
||||||
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
|
|
||||||
sysname = strings.ToLower(sysname) // lowercase
|
|
||||||
if sysname == "getdirentries64" {
|
|
||||||
// Special case - libSystem name and
|
|
||||||
// raw syscall name don't match.
|
|
||||||
sysname = "__getdirentries64"
|
|
||||||
}
|
|
||||||
libcFn = sysname
|
|
||||||
sysname = "funcPC(libc_" + sysname + "_trampoline)"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ")
|
|
||||||
call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist)
|
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := ""
|
|
||||||
ret := []string{"_", "_", "_"}
|
|
||||||
doErrno := false
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
p := parseParam(out[i])
|
|
||||||
reg := ""
|
|
||||||
if p.Name == "err" && !*plan9 {
|
|
||||||
reg = "e1"
|
|
||||||
ret[2] = reg
|
|
||||||
doErrno = true
|
|
||||||
} else if p.Name == "err" && *plan9 {
|
|
||||||
ret[0] = "r0"
|
|
||||||
ret[2] = "e1"
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
reg = fmt.Sprintf("r%d", i)
|
|
||||||
ret[i] = reg
|
|
||||||
}
|
|
||||||
if p.Type == "bool" {
|
|
||||||
reg = fmt.Sprintf("%s != 0", reg)
|
|
||||||
}
|
|
||||||
if p.Type == "int64" && endianness != "" {
|
|
||||||
// 64-bit number in r1:r0 or r0:r1.
|
|
||||||
if i+2 > len(out) {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct)
|
|
||||||
}
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
|
||||||
} else {
|
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
|
||||||
}
|
|
||||||
ret[i] = fmt.Sprintf("r%d", i)
|
|
||||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
|
||||||
}
|
|
||||||
if reg != "e1" || *plan9 {
|
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
|
||||||
text += fmt.Sprintf("\t%s\n", call)
|
|
||||||
} else {
|
|
||||||
if errvar == "" && goos == "linux" {
|
|
||||||
// raw syscall without error on Linux, see golang.org/issue/22924
|
|
||||||
text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call)
|
|
||||||
} else {
|
|
||||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text += body
|
|
||||||
|
|
||||||
if *plan9 && ret[2] == "e1" {
|
|
||||||
text += "\tif int32(r0) == -1 {\n"
|
|
||||||
text += "\t\terr = e1\n"
|
|
||||||
text += "\t}\n"
|
|
||||||
} else if doErrno {
|
|
||||||
text += "\tif e1 != 0 {\n"
|
|
||||||
text += "\t\terr = errnoErr(e1)\n"
|
|
||||||
text += "\t}\n"
|
|
||||||
}
|
|
||||||
text += "\treturn\n"
|
|
||||||
text += "}\n\n"
|
|
||||||
|
|
||||||
if libc && !trampolines[libcFn] {
|
|
||||||
// some system calls share a trampoline, like read and readlen.
|
|
||||||
trampolines[libcFn] = true
|
|
||||||
// Declare assembly trampoline.
|
|
||||||
text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn)
|
|
||||||
// Assembly trampoline calls the libc_* function, which this magic
|
|
||||||
// redirects to use the function from libSystem.
|
|
||||||
text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn)
|
|
||||||
text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn)
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ syscall.Errno
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
415
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
415
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
@ -1,415 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
This program reads a file containing function prototypes
|
|
||||||
(like syscall_aix.go) and generates system call bodies.
|
|
||||||
The prototypes are marked by lines beginning with "//sys"
|
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument.
|
|
||||||
This includes return parameters.
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
* If the return parameter is an error number, it must be named err.
|
|
||||||
* If go func name needs to be different than its libc name,
|
|
||||||
* or the function is not in libc, name could be specified
|
|
||||||
* at the end, after "=" sign, like
|
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
|
||||||
aix = flag.Bool("aix", false, "aix")
|
|
||||||
tags = flag.String("tags", "", "build tags")
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return *tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string {
|
|
||||||
list = strings.TrimSpace(list)
|
|
||||||
if list == "" {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param {
|
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
|
||||||
if ps == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return Param{ps[1], ps[2]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness := ""
|
|
||||||
if *b32 {
|
|
||||||
endianness = "big-endian"
|
|
||||||
} else if *l32 {
|
|
||||||
endianness = "little-endian"
|
|
||||||
}
|
|
||||||
|
|
||||||
pack := ""
|
|
||||||
text := ""
|
|
||||||
cExtern := "/*\n#include <stdint.h>\n#include <stddef.h>\n"
|
|
||||||
for _, path := range flag.Args() {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := s.Text()
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
|
||||||
pack = p[1]
|
|
||||||
}
|
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
|
||||||
if f == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps)
|
|
||||||
out := parseParamList(outps)
|
|
||||||
|
|
||||||
inps = strings.Join(in, ", ")
|
|
||||||
outps = strings.Join(out, ", ")
|
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
|
|
||||||
// Check if value return, err return available
|
|
||||||
errvar := ""
|
|
||||||
retvar := ""
|
|
||||||
rettype := ""
|
|
||||||
for _, param := range out {
|
|
||||||
p := parseParam(param)
|
|
||||||
if p.Type == "error" {
|
|
||||||
errvar = p.Name
|
|
||||||
} else {
|
|
||||||
retvar = p.Name
|
|
||||||
rettype = p.Type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// System call name.
|
|
||||||
if sysname == "" {
|
|
||||||
sysname = funct
|
|
||||||
}
|
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
cRettype := ""
|
|
||||||
if rettype == "unsafe.Pointer" {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if rettype == "uintptr" {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if rettype == "int" {
|
|
||||||
cRettype = "int"
|
|
||||||
} else if rettype == "int32" {
|
|
||||||
cRettype = "int"
|
|
||||||
} else if rettype == "int64" {
|
|
||||||
cRettype = "long long"
|
|
||||||
} else if rettype == "uint32" {
|
|
||||||
cRettype = "unsigned int"
|
|
||||||
} else if rettype == "uint64" {
|
|
||||||
cRettype = "unsigned long long"
|
|
||||||
} else {
|
|
||||||
cRettype = "int"
|
|
||||||
}
|
|
||||||
if sysname == "exit" {
|
|
||||||
cRettype = "void"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change p.Types to c
|
|
||||||
var cIn []string
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t", "size_t")
|
|
||||||
} else if p.Type == "unsafe.Pointer" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "uintptr" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "int" {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
} else if p.Type == "int32" {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
} else if p.Type == "int64" {
|
|
||||||
cIn = append(cIn, "long long")
|
|
||||||
} else if p.Type == "uint32" {
|
|
||||||
cIn = append(cIn, "unsigned int")
|
|
||||||
} else if p.Type == "uint64" {
|
|
||||||
cIn = append(cIn, "unsigned long long")
|
|
||||||
} else {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
|
|
||||||
if sysname == "select" {
|
|
||||||
// select is a keyword of Go. Its name is
|
|
||||||
// changed to c_select.
|
|
||||||
cExtern += "#define c_select select\n"
|
|
||||||
}
|
|
||||||
// Imports of system calls from libc
|
|
||||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
|
||||||
cIn := strings.Join(cIn, ", ")
|
|
||||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// So file name.
|
|
||||||
if *aix {
|
|
||||||
if modname == "" {
|
|
||||||
modname = "libc.a/shr_64.o"
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strconvfunc := "C.CString"
|
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
if outps != "" {
|
|
||||||
outps = fmt.Sprintf(" (%s)", outps)
|
|
||||||
}
|
|
||||||
if text != "" {
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string
|
|
||||||
n := 0
|
|
||||||
argN := 0
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))")
|
|
||||||
} else if p.Type == "string" && errvar != "" {
|
|
||||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
|
||||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n))
|
|
||||||
n++
|
|
||||||
text += fmt.Sprintf("\tvar _p%d int\n", n)
|
|
||||||
text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("C.size_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "int64" && endianness != "" {
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
}
|
|
||||||
n++
|
|
||||||
} else if p.Type == "bool" {
|
|
||||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
|
||||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
|
||||||
args = append(args, fmt.Sprintf("_p%d", n))
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
|
||||||
} else if p.Type == "unsafe.Pointer" {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
|
||||||
} else if p.Type == "int" {
|
|
||||||
if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) {
|
|
||||||
args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name))
|
|
||||||
} else if argN == 0 && funct == "fcntl" {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "int32" {
|
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
} else if p.Type == "int64" {
|
|
||||||
args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name))
|
|
||||||
} else if p.Type == "uint32" {
|
|
||||||
args = append(args, fmt.Sprintf("C.uint(%s)", p.Name))
|
|
||||||
} else if p.Type == "uint64" {
|
|
||||||
args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
|
||||||
} else if p.Type == "uintptr" {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
}
|
|
||||||
argN++
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ")
|
|
||||||
call := ""
|
|
||||||
if sysname == "exit" {
|
|
||||||
if errvar != "" {
|
|
||||||
call += "er :="
|
|
||||||
} else {
|
|
||||||
call += ""
|
|
||||||
}
|
|
||||||
} else if errvar != "" {
|
|
||||||
call += "r0,er :="
|
|
||||||
} else if retvar != "" {
|
|
||||||
call += "r0,_ :="
|
|
||||||
} else {
|
|
||||||
call += ""
|
|
||||||
}
|
|
||||||
if sysname == "select" {
|
|
||||||
// select is a keyword of Go. Its name is
|
|
||||||
// changed to c_select.
|
|
||||||
call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist)
|
|
||||||
} else {
|
|
||||||
call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := ""
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
p := parseParam(out[i])
|
|
||||||
reg := ""
|
|
||||||
if p.Name == "err" {
|
|
||||||
reg = "e1"
|
|
||||||
} else {
|
|
||||||
reg = "r0"
|
|
||||||
}
|
|
||||||
if reg != "e1" {
|
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify return
|
|
||||||
if sysname != "exit" && errvar != "" {
|
|
||||||
if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil {
|
|
||||||
body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n"
|
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
|
||||||
body += "\t}\n"
|
|
||||||
} else {
|
|
||||||
body += "\tif (r0 ==-1 && er != nil) {\n"
|
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
|
||||||
body += "\t}\n"
|
|
||||||
}
|
|
||||||
} else if errvar != "" {
|
|
||||||
body += "\tif (er != nil) {\n"
|
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
|
||||||
body += "\t}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
text += fmt.Sprintf("\t%s\n", call)
|
|
||||||
text += body
|
|
||||||
|
|
||||||
text += "\treturn\n"
|
|
||||||
text += "}\n"
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
imp := ""
|
|
||||||
if pack != "unix" {
|
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
|
||||||
|
|
||||||
}
|
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
|
|
||||||
%s
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
614
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
614
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
@ -1,614 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
This program reads a file containing function prototypes
|
|
||||||
(like syscall_aix.go) and generates system call bodies.
|
|
||||||
The prototypes are marked by lines beginning with "//sys"
|
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument.
|
|
||||||
This includes return parameters.
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
* If the return parameter is an error number, it must be named err.
|
|
||||||
* If go func name needs to be different than its libc name,
|
|
||||||
* or the function is not in libc, name could be specified
|
|
||||||
* at the end, after "=" sign, like
|
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
|
|
||||||
|
|
||||||
This program will generate three files and handle both gc and gccgo implementation:
|
|
||||||
- zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
|
|
||||||
- zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
|
|
||||||
- zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
|
|
||||||
|
|
||||||
The generated code looks like this
|
|
||||||
|
|
||||||
zsyscall_aix_ppc64.go
|
|
||||||
func asyscall(...) (n int, err error) {
|
|
||||||
// Pointer Creation
|
|
||||||
r1, e1 := callasyscall(...)
|
|
||||||
// Type Conversion
|
|
||||||
// Error Handler
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
zsyscall_aix_ppc64_gc.go
|
|
||||||
//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
|
|
||||||
//go:linkname libc_asyscall libc_asyscall
|
|
||||||
var asyscall syscallFunc
|
|
||||||
|
|
||||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
|
||||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
zsyscall_aix_ppc64_ggcgo.go
|
|
||||||
|
|
||||||
// int asyscall(...)
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
|
||||||
r1 = uintptr(C.asyscall(...))
|
|
||||||
e1 = syscall.GetErrno()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
|
||||||
aix = flag.Bool("aix", false, "aix")
|
|
||||||
tags = flag.String("tags", "", "build tags")
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return *tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string {
|
|
||||||
list = strings.TrimSpace(list)
|
|
||||||
if list == "" {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param {
|
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
|
||||||
if ps == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return Param{ps[1], ps[2]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness := ""
|
|
||||||
if *b32 {
|
|
||||||
endianness = "big-endian"
|
|
||||||
} else if *l32 {
|
|
||||||
endianness = "little-endian"
|
|
||||||
}
|
|
||||||
|
|
||||||
pack := ""
|
|
||||||
// GCCGO
|
|
||||||
textgccgo := ""
|
|
||||||
cExtern := "/*\n#include <stdint.h>\n"
|
|
||||||
// GC
|
|
||||||
textgc := ""
|
|
||||||
dynimports := ""
|
|
||||||
linknames := ""
|
|
||||||
var vars []string
|
|
||||||
// COMMON
|
|
||||||
textcommon := ""
|
|
||||||
for _, path := range flag.Args() {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := s.Text()
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
|
||||||
pack = p[1]
|
|
||||||
}
|
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
|
||||||
if f == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps)
|
|
||||||
out := parseParamList(outps)
|
|
||||||
|
|
||||||
inps = strings.Join(in, ", ")
|
|
||||||
outps = strings.Join(out, ", ")
|
|
||||||
|
|
||||||
if sysname == "" {
|
|
||||||
sysname = funct
|
|
||||||
}
|
|
||||||
|
|
||||||
onlyCommon := false
|
|
||||||
if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" {
|
|
||||||
// This function call another syscall which is already implemented.
|
|
||||||
// Therefore, the gc and gccgo part must not be generated.
|
|
||||||
onlyCommon = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
|
|
||||||
textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
if !onlyCommon {
|
|
||||||
textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if value return, err return available
|
|
||||||
errvar := ""
|
|
||||||
rettype := ""
|
|
||||||
for _, param := range out {
|
|
||||||
p := parseParam(param)
|
|
||||||
if p.Type == "error" {
|
|
||||||
errvar = p.Name
|
|
||||||
} else {
|
|
||||||
rettype = p.Type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
// GCCGO Prototype return type
|
|
||||||
cRettype := ""
|
|
||||||
if rettype == "unsafe.Pointer" {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if rettype == "uintptr" {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if rettype == "int" {
|
|
||||||
cRettype = "int"
|
|
||||||
} else if rettype == "int32" {
|
|
||||||
cRettype = "int"
|
|
||||||
} else if rettype == "int64" {
|
|
||||||
cRettype = "long long"
|
|
||||||
} else if rettype == "uint32" {
|
|
||||||
cRettype = "unsigned int"
|
|
||||||
} else if rettype == "uint64" {
|
|
||||||
cRettype = "unsigned long long"
|
|
||||||
} else {
|
|
||||||
cRettype = "int"
|
|
||||||
}
|
|
||||||
if sysname == "exit" {
|
|
||||||
cRettype = "void"
|
|
||||||
}
|
|
||||||
|
|
||||||
// GCCGO Prototype arguments type
|
|
||||||
var cIn []string
|
|
||||||
for i, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t", "size_t")
|
|
||||||
} else if p.Type == "unsafe.Pointer" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "uintptr" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "int" {
|
|
||||||
if (i == 0 || i == 2) && funct == "fcntl" {
|
|
||||||
// These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if p.Type == "int32" {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
} else if p.Type == "int64" {
|
|
||||||
cIn = append(cIn, "long long")
|
|
||||||
} else if p.Type == "uint32" {
|
|
||||||
cIn = append(cIn, "unsigned int")
|
|
||||||
} else if p.Type == "uint64" {
|
|
||||||
cIn = append(cIn, "unsigned long long")
|
|
||||||
} else {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !onlyCommon {
|
|
||||||
// GCCGO Prototype Generation
|
|
||||||
// Imports of system calls from libc
|
|
||||||
if sysname == "select" {
|
|
||||||
// select is a keyword of Go. Its name is
|
|
||||||
// changed to c_select.
|
|
||||||
cExtern += "#define c_select select\n"
|
|
||||||
}
|
|
||||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
|
||||||
cIn := strings.Join(cIn, ", ")
|
|
||||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
|
||||||
}
|
|
||||||
// GC Library name
|
|
||||||
if modname == "" {
|
|
||||||
modname = "libc.a/shr_64.o"
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
sysvarname := fmt.Sprintf("libc_%s", sysname)
|
|
||||||
|
|
||||||
if !onlyCommon {
|
|
||||||
// GC Runtime import of function to allow cross-platform builds.
|
|
||||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
|
|
||||||
// GC Link symbol to proc address variable.
|
|
||||||
linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
|
|
||||||
// GC Library proc address variable.
|
|
||||||
vars = append(vars, sysvarname)
|
|
||||||
}
|
|
||||||
|
|
||||||
strconvfunc := "BytePtrFromString"
|
|
||||||
strconvtype := "*byte"
|
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
if outps != "" {
|
|
||||||
outps = fmt.Sprintf(" (%s)", outps)
|
|
||||||
}
|
|
||||||
if textcommon != "" {
|
|
||||||
textcommon += "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
|
||||||
|
|
||||||
// Prepare arguments tocall.
|
|
||||||
var argscommon []string // Arguments in the common part
|
|
||||||
var argscall []string // Arguments for call prototype
|
|
||||||
var argsgc []string // Arguments for gc call (with syscall6)
|
|
||||||
var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall)
|
|
||||||
n := 0
|
|
||||||
argN := 0
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
|
||||||
argsgc = append(argsgc, p.Name)
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else if p.Type == "string" && errvar != "" {
|
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
|
||||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
|
||||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
|
||||||
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
|
||||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
|
||||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
|
||||||
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
|
||||||
textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "int64" && endianness != "" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
|
|
||||||
} else if p.Type == "bool" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
|
||||||
argsgc = append(argsgc, p.Name)
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else if p.Type == "int" {
|
|
||||||
if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
|
|
||||||
// These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
|
||||||
argsgc = append(argsgc, p.Name)
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
|
|
||||||
} else {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "int32" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
} else if p.Type == "int64" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
|
|
||||||
} else if p.Type == "uint32" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
|
|
||||||
} else if p.Type == "uint64" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
|
||||||
} else if p.Type == "uintptr" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
|
||||||
argsgc = append(argsgc, p.Name)
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
}
|
|
||||||
argN++
|
|
||||||
}
|
|
||||||
nargs := len(argsgc)
|
|
||||||
|
|
||||||
// COMMON function generation
|
|
||||||
argscommonlist := strings.Join(argscommon, ", ")
|
|
||||||
callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
|
|
||||||
ret := []string{"_", "_"}
|
|
||||||
body := ""
|
|
||||||
doErrno := false
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
p := parseParam(out[i])
|
|
||||||
reg := ""
|
|
||||||
if p.Name == "err" {
|
|
||||||
reg = "e1"
|
|
||||||
ret[1] = reg
|
|
||||||
doErrno = true
|
|
||||||
} else {
|
|
||||||
reg = "r0"
|
|
||||||
ret[0] = reg
|
|
||||||
}
|
|
||||||
if p.Type == "bool" {
|
|
||||||
reg = fmt.Sprintf("%s != 0", reg)
|
|
||||||
}
|
|
||||||
if reg != "e1" {
|
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ret[0] == "_" && ret[1] == "_" {
|
|
||||||
textcommon += fmt.Sprintf("\t%s\n", callcommon)
|
|
||||||
} else {
|
|
||||||
textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
|
|
||||||
}
|
|
||||||
textcommon += body
|
|
||||||
|
|
||||||
if doErrno {
|
|
||||||
textcommon += "\tif e1 != 0 {\n"
|
|
||||||
textcommon += "\t\terr = errnoErr(e1)\n"
|
|
||||||
textcommon += "\t}\n"
|
|
||||||
}
|
|
||||||
textcommon += "\treturn\n"
|
|
||||||
textcommon += "}\n"
|
|
||||||
|
|
||||||
if onlyCommon {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// CALL Prototype
|
|
||||||
callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
|
|
||||||
|
|
||||||
// GC function generation
|
|
||||||
asm := "syscall6"
|
|
||||||
if nonblock != nil {
|
|
||||||
asm = "rawSyscall6"
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(argsgc) <= 6 {
|
|
||||||
for len(argsgc) < 6 {
|
|
||||||
argsgc = append(argsgc, "0")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
argsgclist := strings.Join(argsgc, ", ")
|
|
||||||
callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
|
|
||||||
|
|
||||||
textgc += callProto
|
|
||||||
textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
|
|
||||||
textgc += "\treturn\n}\n"
|
|
||||||
|
|
||||||
// GCCGO function generation
|
|
||||||
argsgccgolist := strings.Join(argsgccgo, ", ")
|
|
||||||
var callgccgo string
|
|
||||||
if sysname == "select" {
|
|
||||||
// select is a keyword of Go. Its name is
|
|
||||||
// changed to c_select.
|
|
||||||
callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist)
|
|
||||||
} else {
|
|
||||||
callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
|
|
||||||
}
|
|
||||||
textgccgo += callProto
|
|
||||||
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
|
|
||||||
textgccgo += "\te1 = syscall.GetErrno()\n"
|
|
||||||
textgccgo += "\treturn\n}\n"
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
imp := ""
|
|
||||||
if pack != "unix" {
|
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64.go
|
|
||||||
err := ioutil.WriteFile("zsyscall_aix_ppc64.go",
|
|
||||||
[]byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)),
|
|
||||||
0644)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64_gc.go
|
|
||||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
|
||||||
vardecls += " syscallFunc"
|
|
||||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go",
|
|
||||||
[]byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
|
|
||||||
0644)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64_gccgo.go
|
|
||||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go",
|
|
||||||
[]byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)),
|
|
||||||
0644)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate1 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
||||||
const srcTemplate2 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
// +build !gccgo
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
type syscallFunc uintptr
|
|
||||||
|
|
||||||
var (
|
|
||||||
%s
|
|
||||||
)
|
|
||||||
|
|
||||||
// Implemented in runtime/syscall_aix.go.
|
|
||||||
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
|
||||||
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
||||||
const srcTemplate3 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
// +build gccgo
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
%s
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
@ -1,335 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
This program reads a file containing function prototypes
|
|
||||||
(like syscall_solaris.go) and generates system call bodies.
|
|
||||||
The prototypes are marked by lines beginning with "//sys"
|
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument.
|
|
||||||
This includes return parameters.
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
* If the return parameter is an error number, it must be named err.
|
|
||||||
* If go func name needs to be different than its libc name,
|
|
||||||
* or the function is not in libc, name could be specified
|
|
||||||
* at the end, after "=" sign, like
|
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
|
||||||
tags = flag.String("tags", "", "build tags")
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return *tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string {
|
|
||||||
list = strings.TrimSpace(list)
|
|
||||||
if list == "" {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param {
|
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
|
||||||
if ps == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return Param{ps[1], ps[2]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness := ""
|
|
||||||
if *b32 {
|
|
||||||
endianness = "big-endian"
|
|
||||||
} else if *l32 {
|
|
||||||
endianness = "little-endian"
|
|
||||||
}
|
|
||||||
|
|
||||||
pack := ""
|
|
||||||
text := ""
|
|
||||||
dynimports := ""
|
|
||||||
linknames := ""
|
|
||||||
var vars []string
|
|
||||||
for _, path := range flag.Args() {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := s.Text()
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
|
||||||
pack = p[1]
|
|
||||||
}
|
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
|
||||||
if f == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps)
|
|
||||||
out := parseParamList(outps)
|
|
||||||
|
|
||||||
inps = strings.Join(in, ", ")
|
|
||||||
outps = strings.Join(out, ", ")
|
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
|
|
||||||
// So file name.
|
|
||||||
if modname == "" {
|
|
||||||
modname = "libc"
|
|
||||||
}
|
|
||||||
|
|
||||||
// System call name.
|
|
||||||
if sysname == "" {
|
|
||||||
sysname = funct
|
|
||||||
}
|
|
||||||
|
|
||||||
// System call pointer variable name.
|
|
||||||
sysvarname := fmt.Sprintf("proc%s", sysname)
|
|
||||||
|
|
||||||
strconvfunc := "BytePtrFromString"
|
|
||||||
strconvtype := "*byte"
|
|
||||||
|
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
// Runtime import of function to allow cross-platform builds.
|
|
||||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname)
|
|
||||||
// Link symbol to proc address variable.
|
|
||||||
linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname)
|
|
||||||
// Library proc address variable.
|
|
||||||
vars = append(vars, sysvarname)
|
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
outlist := strings.Join(out, ", ")
|
|
||||||
if outlist != "" {
|
|
||||||
outlist = fmt.Sprintf(" (%s)", outlist)
|
|
||||||
}
|
|
||||||
if text != "" {
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist)
|
|
||||||
|
|
||||||
// Check if err return available
|
|
||||||
errvar := ""
|
|
||||||
for _, param := range out {
|
|
||||||
p := parseParam(param)
|
|
||||||
if p.Type == "error" {
|
|
||||||
errvar = p.Name
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string
|
|
||||||
n := 0
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
|
||||||
} else if p.Type == "string" && errvar != "" {
|
|
||||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
|
||||||
text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
|
||||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
|
||||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
|
||||||
text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
n++
|
|
||||||
} else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil {
|
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1])
|
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "int64" && endianness != "" {
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "bool" {
|
|
||||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
|
||||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nargs := len(args)
|
|
||||||
|
|
||||||
// Determine which form to use; pad args with zeros.
|
|
||||||
asm := "sysvicall6"
|
|
||||||
if nonblock != nil {
|
|
||||||
asm = "rawSysvicall6"
|
|
||||||
}
|
|
||||||
if len(args) <= 6 {
|
|
||||||
for len(args) < 6 {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ")
|
|
||||||
call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist)
|
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := ""
|
|
||||||
ret := []string{"_", "_", "_"}
|
|
||||||
doErrno := false
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
p := parseParam(out[i])
|
|
||||||
reg := ""
|
|
||||||
if p.Name == "err" {
|
|
||||||
reg = "e1"
|
|
||||||
ret[2] = reg
|
|
||||||
doErrno = true
|
|
||||||
} else {
|
|
||||||
reg = fmt.Sprintf("r%d", i)
|
|
||||||
ret[i] = reg
|
|
||||||
}
|
|
||||||
if p.Type == "bool" {
|
|
||||||
reg = fmt.Sprintf("%d != 0", reg)
|
|
||||||
}
|
|
||||||
if p.Type == "int64" && endianness != "" {
|
|
||||||
// 64-bit number in r1:r0 or r0:r1.
|
|
||||||
if i+2 > len(out) {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
|
||||||
} else {
|
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
|
||||||
}
|
|
||||||
ret[i] = fmt.Sprintf("r%d", i)
|
|
||||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
|
||||||
}
|
|
||||||
if reg != "e1" {
|
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
|
||||||
text += fmt.Sprintf("\t%s\n", call)
|
|
||||||
} else {
|
|
||||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
|
||||||
}
|
|
||||||
text += body
|
|
||||||
|
|
||||||
if doErrno {
|
|
||||||
text += "\tif e1 != 0 {\n"
|
|
||||||
text += "\t\terr = e1\n"
|
|
||||||
text += "\t}\n"
|
|
||||||
}
|
|
||||||
text += "\treturn\n"
|
|
||||||
text += "}\n"
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
imp := ""
|
|
||||||
if pack != "unix" {
|
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
|
||||||
|
|
||||||
}
|
|
||||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
|
||||||
vardecls += " syscallFunc"
|
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
var (
|
|
||||||
%s
|
|
||||||
)
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
355
vendor/golang.org/x/sys/unix/mksysctl_openbsd.go
generated
vendored
355
vendor/golang.org/x/sys/unix/mksysctl_openbsd.go
generated
vendored
@ -1,355 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
|
|
||||||
//
|
|
||||||
// Build a MIB with each entry being an array containing the level, type and
|
|
||||||
// a hash that will contain additional entries if the current entry is a node.
|
|
||||||
// We then walk this MIB and create a flattened sysctl name to OID hash.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
goos, goarch string
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments.
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags.
|
|
||||||
func buildTags() string {
|
|
||||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// reMatch performs regular expression match and stores the substring slice to value pointed by m.
|
|
||||||
func reMatch(re *regexp.Regexp, str string, m *[]string) bool {
|
|
||||||
*m = re.FindStringSubmatch(str)
|
|
||||||
if *m != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type nodeElement struct {
|
|
||||||
n int
|
|
||||||
t string
|
|
||||||
pE *map[string]nodeElement
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
debugEnabled bool
|
|
||||||
mib map[string]nodeElement
|
|
||||||
node *map[string]nodeElement
|
|
||||||
nodeMap map[string]string
|
|
||||||
sysCtl []string
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`)
|
|
||||||
ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`)
|
|
||||||
ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`)
|
|
||||||
netInetRE = regexp.MustCompile(`^netinet/`)
|
|
||||||
netInet6RE = regexp.MustCompile(`^netinet6/`)
|
|
||||||
netRE = regexp.MustCompile(`^net/`)
|
|
||||||
bracesRE = regexp.MustCompile(`{.*}`)
|
|
||||||
ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`)
|
|
||||||
fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`)
|
|
||||||
)
|
|
||||||
|
|
||||||
func debug(s string) {
|
|
||||||
if debugEnabled {
|
|
||||||
fmt.Fprintln(os.Stderr, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Walk the MIB and build a sysctl name to OID mapping.
|
|
||||||
func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) {
|
|
||||||
lNode := pNode // local copy of pointer to node
|
|
||||||
var keys []string
|
|
||||||
for k := range *lNode {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
for _, key := range keys {
|
|
||||||
nodename := name
|
|
||||||
if name != "" {
|
|
||||||
nodename += "."
|
|
||||||
}
|
|
||||||
nodename += key
|
|
||||||
|
|
||||||
nodeoid := append(oid, (*pNode)[key].n)
|
|
||||||
|
|
||||||
if (*pNode)[key].t == `CTLTYPE_NODE` {
|
|
||||||
if _, ok := nodeMap[nodename]; ok {
|
|
||||||
lNode = &mib
|
|
||||||
ctlName := nodeMap[nodename]
|
|
||||||
for _, part := range strings.Split(ctlName, ".") {
|
|
||||||
lNode = ((*lNode)[part]).pE
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lNode = (*pNode)[key].pE
|
|
||||||
}
|
|
||||||
buildSysctl(lNode, nodename, nodeoid)
|
|
||||||
} else if (*pNode)[key].t != "" {
|
|
||||||
oidStr := []string{}
|
|
||||||
for j := range nodeoid {
|
|
||||||
oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j]))
|
|
||||||
}
|
|
||||||
text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n"
|
|
||||||
sysCtl = append(sysCtl, text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Get the OS (using GOOS_TARGET if it exist)
|
|
||||||
goos = os.Getenv("GOOS_TARGET")
|
|
||||||
if goos == "" {
|
|
||||||
goos = os.Getenv("GOOS")
|
|
||||||
}
|
|
||||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goarch = os.Getenv("GOARCH_TARGET")
|
|
||||||
if goarch == "" {
|
|
||||||
goarch = os.Getenv("GOARCH")
|
|
||||||
}
|
|
||||||
// Check if GOOS and GOARCH environment variables are defined
|
|
||||||
if goarch == "" || goos == "" {
|
|
||||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
mib = make(map[string]nodeElement)
|
|
||||||
headers := [...]string{
|
|
||||||
`sys/sysctl.h`,
|
|
||||||
`sys/socket.h`,
|
|
||||||
`sys/tty.h`,
|
|
||||||
`sys/malloc.h`,
|
|
||||||
`sys/mount.h`,
|
|
||||||
`sys/namei.h`,
|
|
||||||
`sys/sem.h`,
|
|
||||||
`sys/shm.h`,
|
|
||||||
`sys/vmmeter.h`,
|
|
||||||
`uvm/uvmexp.h`,
|
|
||||||
`uvm/uvm_param.h`,
|
|
||||||
`uvm/uvm_swap_encrypt.h`,
|
|
||||||
`ddb/db_var.h`,
|
|
||||||
`net/if.h`,
|
|
||||||
`net/if_pfsync.h`,
|
|
||||||
`net/pipex.h`,
|
|
||||||
`netinet/in.h`,
|
|
||||||
`netinet/icmp_var.h`,
|
|
||||||
`netinet/igmp_var.h`,
|
|
||||||
`netinet/ip_ah.h`,
|
|
||||||
`netinet/ip_carp.h`,
|
|
||||||
`netinet/ip_divert.h`,
|
|
||||||
`netinet/ip_esp.h`,
|
|
||||||
`netinet/ip_ether.h`,
|
|
||||||
`netinet/ip_gre.h`,
|
|
||||||
`netinet/ip_ipcomp.h`,
|
|
||||||
`netinet/ip_ipip.h`,
|
|
||||||
`netinet/pim_var.h`,
|
|
||||||
`netinet/tcp_var.h`,
|
|
||||||
`netinet/udp_var.h`,
|
|
||||||
`netinet6/in6.h`,
|
|
||||||
`netinet6/ip6_divert.h`,
|
|
||||||
`netinet6/pim6_var.h`,
|
|
||||||
`netinet/icmp6.h`,
|
|
||||||
`netmpls/mpls.h`,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctls := [...]string{
|
|
||||||
`kern`,
|
|
||||||
`vm`,
|
|
||||||
`fs`,
|
|
||||||
`net`,
|
|
||||||
//debug /* Special handling required */
|
|
||||||
`hw`,
|
|
||||||
//machdep /* Arch specific */
|
|
||||||
`user`,
|
|
||||||
`ddb`,
|
|
||||||
//vfs /* Special handling required */
|
|
||||||
`fs.posix`,
|
|
||||||
`kern.forkstat`,
|
|
||||||
`kern.intrcnt`,
|
|
||||||
`kern.malloc`,
|
|
||||||
`kern.nchstats`,
|
|
||||||
`kern.seminfo`,
|
|
||||||
`kern.shminfo`,
|
|
||||||
`kern.timecounter`,
|
|
||||||
`kern.tty`,
|
|
||||||
`kern.watchdog`,
|
|
||||||
`net.bpf`,
|
|
||||||
`net.ifq`,
|
|
||||||
`net.inet`,
|
|
||||||
`net.inet.ah`,
|
|
||||||
`net.inet.carp`,
|
|
||||||
`net.inet.divert`,
|
|
||||||
`net.inet.esp`,
|
|
||||||
`net.inet.etherip`,
|
|
||||||
`net.inet.gre`,
|
|
||||||
`net.inet.icmp`,
|
|
||||||
`net.inet.igmp`,
|
|
||||||
`net.inet.ip`,
|
|
||||||
`net.inet.ip.ifq`,
|
|
||||||
`net.inet.ipcomp`,
|
|
||||||
`net.inet.ipip`,
|
|
||||||
`net.inet.mobileip`,
|
|
||||||
`net.inet.pfsync`,
|
|
||||||
`net.inet.pim`,
|
|
||||||
`net.inet.tcp`,
|
|
||||||
`net.inet.udp`,
|
|
||||||
`net.inet6`,
|
|
||||||
`net.inet6.divert`,
|
|
||||||
`net.inet6.ip6`,
|
|
||||||
`net.inet6.icmp6`,
|
|
||||||
`net.inet6.pim6`,
|
|
||||||
`net.inet6.tcp6`,
|
|
||||||
`net.inet6.udp6`,
|
|
||||||
`net.mpls`,
|
|
||||||
`net.mpls.ifq`,
|
|
||||||
`net.key`,
|
|
||||||
`net.pflow`,
|
|
||||||
`net.pfsync`,
|
|
||||||
`net.pipex`,
|
|
||||||
`net.rt`,
|
|
||||||
`vm.swapencrypt`,
|
|
||||||
//vfsgenctl /* Special handling required */
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node name "fixups"
|
|
||||||
ctlMap := map[string]string{
|
|
||||||
"ipproto": "net.inet",
|
|
||||||
"net.inet.ipproto": "net.inet",
|
|
||||||
"net.inet6.ipv6proto": "net.inet6",
|
|
||||||
"net.inet6.ipv6": "net.inet6.ip6",
|
|
||||||
"net.inet.icmpv6": "net.inet6.icmp6",
|
|
||||||
"net.inet6.divert6": "net.inet6.divert",
|
|
||||||
"net.inet6.tcp6": "net.inet.tcp",
|
|
||||||
"net.inet6.udp6": "net.inet.udp",
|
|
||||||
"mpls": "net.mpls",
|
|
||||||
"swpenc": "vm.swapencrypt",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node mappings
|
|
||||||
nodeMap = map[string]string{
|
|
||||||
"net.inet.ip.ifq": "net.ifq",
|
|
||||||
"net.inet.pfsync": "net.pfsync",
|
|
||||||
"net.mpls.ifq": "net.ifq",
|
|
||||||
}
|
|
||||||
|
|
||||||
mCtls := make(map[string]bool)
|
|
||||||
for _, ctl := range ctls {
|
|
||||||
mCtls[ctl] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, header := range headers {
|
|
||||||
debug("Processing " + header)
|
|
||||||
file, err := os.Open(filepath.Join("/usr/include", header))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
var sub []string
|
|
||||||
if reMatch(ctlNames1RE, s.Text(), &sub) ||
|
|
||||||
reMatch(ctlNames2RE, s.Text(), &sub) ||
|
|
||||||
reMatch(ctlNames3RE, s.Text(), &sub) {
|
|
||||||
if sub[1] == `CTL_NAMES` {
|
|
||||||
// Top level.
|
|
||||||
node = &mib
|
|
||||||
} else {
|
|
||||||
// Node.
|
|
||||||
nodename := strings.ToLower(sub[2])
|
|
||||||
ctlName := ""
|
|
||||||
if reMatch(netInetRE, header, &sub) {
|
|
||||||
ctlName = "net.inet." + nodename
|
|
||||||
} else if reMatch(netInet6RE, header, &sub) {
|
|
||||||
ctlName = "net.inet6." + nodename
|
|
||||||
} else if reMatch(netRE, header, &sub) {
|
|
||||||
ctlName = "net." + nodename
|
|
||||||
} else {
|
|
||||||
ctlName = nodename
|
|
||||||
ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if val, ok := ctlMap[ctlName]; ok {
|
|
||||||
ctlName = val
|
|
||||||
}
|
|
||||||
if _, ok := mCtls[ctlName]; !ok {
|
|
||||||
debug("Ignoring " + ctlName + "...")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Walk down from the top of the MIB.
|
|
||||||
node = &mib
|
|
||||||
for _, part := range strings.Split(ctlName, ".") {
|
|
||||||
if _, ok := (*node)[part]; !ok {
|
|
||||||
debug("Missing node " + part)
|
|
||||||
(*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}}
|
|
||||||
}
|
|
||||||
node = (*node)[part].pE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate current node with entries.
|
|
||||||
i := -1
|
|
||||||
for !strings.HasPrefix(s.Text(), "}") {
|
|
||||||
s.Scan()
|
|
||||||
if reMatch(bracesRE, s.Text(), &sub) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if !reMatch(ctlTypeRE, s.Text(), &sub) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
(*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = s.Err()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
buildSysctl(&mib, "", []int{})
|
|
||||||
|
|
||||||
sort.Strings(sysCtl)
|
|
||||||
text := strings.Join(sysCtl, "")
|
|
||||||
|
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
type mibentry struct {
|
|
||||||
ctlname string
|
|
||||||
ctloid []_C_int
|
|
||||||
}
|
|
||||||
|
|
||||||
var sysctlMib = []mibentry {
|
|
||||||
%s
|
|
||||||
}
|
|
||||||
`
|
|
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
@ -1,190 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// Generate system call table for DragonFly, NetBSD,
|
|
||||||
// FreeBSD, OpenBSD or Darwin from master list
|
|
||||||
// (for example, /usr/src/sys/kern/syscalls.master or
|
|
||||||
// sys/syscall.h).
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
goos, goarch string
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksysnum.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkErr(err error) {
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// source string and substring slice for regexp
|
|
||||||
type re struct {
|
|
||||||
str string // source string
|
|
||||||
sub []string // matched sub-string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match performs regular expression match
|
|
||||||
func (r *re) Match(exp string) bool {
|
|
||||||
r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
|
|
||||||
if r.sub != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetchFile fetches a text file from URL
|
|
||||||
func fetchFile(URL string) io.Reader {
|
|
||||||
resp, err := http.Get(URL)
|
|
||||||
checkErr(err)
|
|
||||||
defer resp.Body.Close()
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
checkErr(err)
|
|
||||||
return strings.NewReader(string(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
// readFile reads a text file from path
|
|
||||||
func readFile(path string) io.Reader {
|
|
||||||
file, err := os.Open(os.Args[1])
|
|
||||||
checkErr(err)
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
func format(name, num, proto string) string {
|
|
||||||
name = strings.ToUpper(name)
|
|
||||||
// There are multiple entries for enosys and nosys, so comment them out.
|
|
||||||
nm := re{str: name}
|
|
||||||
if nm.Match(`^SYS_E?NOSYS$`) {
|
|
||||||
name = fmt.Sprintf("// %s", name)
|
|
||||||
}
|
|
||||||
if name == `SYS_SYS_EXIT` {
|
|
||||||
name = `SYS_EXIT`
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Get the OS (using GOOS_TARGET if it exist)
|
|
||||||
goos = os.Getenv("GOOS_TARGET")
|
|
||||||
if goos == "" {
|
|
||||||
goos = os.Getenv("GOOS")
|
|
||||||
}
|
|
||||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goarch = os.Getenv("GOARCH_TARGET")
|
|
||||||
if goarch == "" {
|
|
||||||
goarch = os.Getenv("GOARCH")
|
|
||||||
}
|
|
||||||
// Check if GOOS and GOARCH environment variables are defined
|
|
||||||
if goarch == "" || goos == "" {
|
|
||||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
file := strings.TrimSpace(os.Args[1])
|
|
||||||
var syscalls io.Reader
|
|
||||||
if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") {
|
|
||||||
// Download syscalls.master file
|
|
||||||
syscalls = fetchFile(file)
|
|
||||||
} else {
|
|
||||||
syscalls = readFile(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
var text, line string
|
|
||||||
s := bufio.NewScanner(syscalls)
|
|
||||||
for s.Scan() {
|
|
||||||
t := re{str: line}
|
|
||||||
if t.Match(`^(.*)\\$`) {
|
|
||||||
// Handle continuation
|
|
||||||
line = t.sub[1]
|
|
||||||
line += strings.TrimLeft(s.Text(), " \t")
|
|
||||||
} else {
|
|
||||||
// New line
|
|
||||||
line = s.Text()
|
|
||||||
}
|
|
||||||
t = re{str: line}
|
|
||||||
if t.Match(`\\$`) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t = re{str: line}
|
|
||||||
|
|
||||||
switch goos {
|
|
||||||
case "dragonfly":
|
|
||||||
if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) {
|
|
||||||
num, proto := t.sub[1], t.sub[2]
|
|
||||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
|
||||||
text += format(name, num, proto)
|
|
||||||
}
|
|
||||||
case "freebsd":
|
|
||||||
if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) {
|
|
||||||
num, proto := t.sub[1], t.sub[2]
|
|
||||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
|
||||||
text += format(name, num, proto)
|
|
||||||
}
|
|
||||||
case "openbsd":
|
|
||||||
if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) {
|
|
||||||
num, proto, name := t.sub[1], t.sub[3], t.sub[4]
|
|
||||||
text += format(name, num, proto)
|
|
||||||
}
|
|
||||||
case "netbsd":
|
|
||||||
if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) {
|
|
||||||
num, proto, compat := t.sub[1], t.sub[6], t.sub[8]
|
|
||||||
name := t.sub[7] + "_" + t.sub[9]
|
|
||||||
if t.sub[11] != "" {
|
|
||||||
name = t.sub[7] + "_" + t.sub[11]
|
|
||||||
}
|
|
||||||
name = strings.ToUpper(name)
|
|
||||||
if compat == "" || compat == "13" || compat == "30" || compat == "50" {
|
|
||||||
text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "darwin":
|
|
||||||
if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) {
|
|
||||||
name, num := t.sub[1], t.sub[2]
|
|
||||||
name = strings.ToUpper(name)
|
|
||||||
text += fmt.Sprintf(" SYS_%s = %s;\n", name, num)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos)
|
|
||||||
os.Exit(1)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err := s.Err()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
fmt.Printf(template, cmdLine(), buildTags(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const template = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
const(
|
|
||||||
%s)`
|
|
237
vendor/golang.org/x/sys/unix/types_aix.go
generated
vendored
237
vendor/golang.org/x/sys/unix/types_aix.go
generated
vendored
@ -1,237 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
// +build aix
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input to cgo -godefs. See also mkerrors.sh and mkall.sh
|
|
||||||
*/
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/limits.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <utime.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/statfs.h>
|
|
||||||
#include <sys/termio.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
#include <termios.h>
|
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/if_dl.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
sizeofPtr = sizeof(void*),
|
|
||||||
};
|
|
||||||
|
|
||||||
union sockaddr_all {
|
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3;
|
|
||||||
struct sockaddr_un s4;
|
|
||||||
struct sockaddr_dl s5;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sockaddr_any {
|
|
||||||
struct sockaddr addr;
|
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
|
||||||
};
|
|
||||||
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const (
|
|
||||||
SizeofPtr = C.sizeofPtr
|
|
||||||
SizeofShort = C.sizeof_short
|
|
||||||
SizeofInt = C.sizeof_int
|
|
||||||
SizeofLong = C.sizeof_long
|
|
||||||
SizeofLongLong = C.sizeof_longlong
|
|
||||||
PathMax = C.PATH_MAX
|
|
||||||
)
|
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type (
|
|
||||||
_C_short C.short
|
|
||||||
_C_int C.int
|
|
||||||
_C_long C.long
|
|
||||||
_C_long_long C.longlong
|
|
||||||
)
|
|
||||||
|
|
||||||
type off64 C.off64_t
|
|
||||||
type off C.off_t
|
|
||||||
type Mode_t C.mode_t
|
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec
|
|
||||||
|
|
||||||
type Timeval C.struct_timeval
|
|
||||||
|
|
||||||
type Timeval32 C.struct_timeval32
|
|
||||||
|
|
||||||
type Timex C.struct_timex
|
|
||||||
|
|
||||||
type Time_t C.time_t
|
|
||||||
|
|
||||||
type Tms C.struct_tms
|
|
||||||
|
|
||||||
type Utimbuf C.struct_utimbuf
|
|
||||||
|
|
||||||
type Timezone C.struct_timezone
|
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage
|
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit64
|
|
||||||
|
|
||||||
type Pid_t C.pid_t
|
|
||||||
|
|
||||||
type _Gid_t C.gid_t
|
|
||||||
|
|
||||||
type dev_t C.dev_t
|
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
type Stat_t C.struct_stat
|
|
||||||
|
|
||||||
type StatxTimestamp C.struct_statx_timestamp
|
|
||||||
|
|
||||||
type Statx_t C.struct_statx
|
|
||||||
|
|
||||||
type Dirent C.struct_dirent
|
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un
|
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr
|
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any
|
|
||||||
|
|
||||||
type _Socklen C.socklen_t
|
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter
|
|
||||||
|
|
||||||
type Iovec C.struct_iovec
|
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type Linger C.struct_linger
|
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
const (
|
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
|
||||||
SizeofLinger = C.sizeof_struct_linger
|
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const (
|
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
|
||||||
)
|
|
||||||
|
|
||||||
type IfMsgHdr C.struct_if_msghdr
|
|
||||||
|
|
||||||
// Misc
|
|
||||||
|
|
||||||
type FdSet C.fd_set
|
|
||||||
|
|
||||||
type Utsname C.struct_utsname
|
|
||||||
|
|
||||||
type Ustat_t C.struct_ustat
|
|
||||||
|
|
||||||
type Sigset_t C.sigset_t
|
|
||||||
|
|
||||||
const (
|
|
||||||
AT_FDCWD = C.AT_FDCWD
|
|
||||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
|
||||||
)
|
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios
|
|
||||||
|
|
||||||
type Termio C.struct_termio
|
|
||||||
|
|
||||||
type Winsize C.struct_winsize
|
|
||||||
|
|
||||||
//poll
|
|
||||||
|
|
||||||
type PollFd struct {
|
|
||||||
Fd int32
|
|
||||||
Events uint16
|
|
||||||
Revents uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
POLLERR = C.POLLERR
|
|
||||||
POLLHUP = C.POLLHUP
|
|
||||||
POLLIN = C.POLLIN
|
|
||||||
POLLNVAL = C.POLLNVAL
|
|
||||||
POLLOUT = C.POLLOUT
|
|
||||||
POLLPRI = C.POLLPRI
|
|
||||||
POLLRDBAND = C.POLLRDBAND
|
|
||||||
POLLRDNORM = C.POLLRDNORM
|
|
||||||
POLLWRBAND = C.POLLWRBAND
|
|
||||||
POLLWRNORM = C.POLLWRNORM
|
|
||||||
)
|
|
||||||
|
|
||||||
//flock_t
|
|
||||||
|
|
||||||
type Flock_t C.struct_flock64
|
|
||||||
|
|
||||||
// Statfs
|
|
||||||
|
|
||||||
type Fsid_t C.struct_fsid_t
|
|
||||||
type Fsid64_t C.struct_fsid64_t
|
|
||||||
|
|
||||||
type Statfs_t C.struct_statfs
|
|
||||||
|
|
||||||
const RNDGETENTCNT = 0x80045200
|
|
283
vendor/golang.org/x/sys/unix/types_darwin.go
generated
vendored
283
vendor/golang.org/x/sys/unix/types_darwin.go
generated
vendored
@ -1,283 +0,0 @@
|
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input to cgo -godefs. See README.md
|
|
||||||
*/
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define __DARWIN_UNIX03 0
|
|
||||||
#define KERNEL
|
|
||||||
#define _DARWIN_USE_64_BIT_INODE
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <mach/mach.h>
|
|
||||||
#include <mach/message.h>
|
|
||||||
#include <sys/event.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/ptrace.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/signal.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <net/bpf.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/if_dl.h>
|
|
||||||
#include <net/if_var.h>
|
|
||||||
#include <net/route.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
sizeofPtr = sizeof(void*),
|
|
||||||
};
|
|
||||||
|
|
||||||
union sockaddr_all {
|
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3;
|
|
||||||
struct sockaddr_un s4;
|
|
||||||
struct sockaddr_dl s5;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sockaddr_any {
|
|
||||||
struct sockaddr addr;
|
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
|
||||||
};
|
|
||||||
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
// Machine characteristics
|
|
||||||
|
|
||||||
const (
|
|
||||||
SizeofPtr = C.sizeofPtr
|
|
||||||
SizeofShort = C.sizeof_short
|
|
||||||
SizeofInt = C.sizeof_int
|
|
||||||
SizeofLong = C.sizeof_long
|
|
||||||
SizeofLongLong = C.sizeof_longlong
|
|
||||||
)
|
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type (
|
|
||||||
_C_short C.short
|
|
||||||
_C_int C.int
|
|
||||||
_C_long C.long
|
|
||||||
_C_long_long C.longlong
|
|
||||||
)
|
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec
|
|
||||||
|
|
||||||
type Timeval C.struct_timeval
|
|
||||||
|
|
||||||
type Timeval32 C.struct_timeval32
|
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage
|
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit
|
|
||||||
|
|
||||||
type _Gid_t C.gid_t
|
|
||||||
|
|
||||||
// Files
|
|
||||||
|
|
||||||
type Stat_t C.struct_stat64
|
|
||||||
|
|
||||||
type Statfs_t C.struct_statfs64
|
|
||||||
|
|
||||||
type Flock_t C.struct_flock
|
|
||||||
|
|
||||||
type Fstore_t C.struct_fstore
|
|
||||||
|
|
||||||
type Radvisory_t C.struct_radvisory
|
|
||||||
|
|
||||||
type Fbootstraptransfer_t C.struct_fbootstraptransfer
|
|
||||||
|
|
||||||
type Log2phys_t C.struct_log2phys
|
|
||||||
|
|
||||||
type Fsid C.struct_fsid
|
|
||||||
|
|
||||||
type Dirent C.struct_dirent
|
|
||||||
|
|
||||||
// Sockets
|
|
||||||
|
|
||||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type RawSockaddrUnix C.struct_sockaddr_un
|
|
||||||
|
|
||||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
|
||||||
|
|
||||||
type RawSockaddr C.struct_sockaddr
|
|
||||||
|
|
||||||
type RawSockaddrAny C.struct_sockaddr_any
|
|
||||||
|
|
||||||
type _Socklen C.socklen_t
|
|
||||||
|
|
||||||
type Linger C.struct_linger
|
|
||||||
|
|
||||||
type Iovec C.struct_iovec
|
|
||||||
|
|
||||||
type IPMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type IPv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type Msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type Cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type Inet4Pktinfo C.struct_in_pktinfo
|
|
||||||
|
|
||||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ICMPv6Filter C.struct_icmp6_filter
|
|
||||||
|
|
||||||
const (
|
|
||||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
|
||||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
|
||||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
|
||||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
|
||||||
SizeofLinger = C.sizeof_struct_linger
|
|
||||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
|
|
||||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ptrace requests
|
|
||||||
|
|
||||||
const (
|
|
||||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
|
||||||
PTRACE_CONT = C.PT_CONTINUE
|
|
||||||
PTRACE_KILL = C.PT_KILL
|
|
||||||
)
|
|
||||||
|
|
||||||
// Events (kqueue, kevent)
|
|
||||||
|
|
||||||
type Kevent_t C.struct_kevent
|
|
||||||
|
|
||||||
// Select
|
|
||||||
|
|
||||||
type FdSet C.fd_set
|
|
||||||
|
|
||||||
// Routing and interface messages
|
|
||||||
|
|
||||||
const (
|
|
||||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
|
||||||
SizeofIfData = C.sizeof_struct_if_data
|
|
||||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
|
||||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
|
||||||
SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2
|
|
||||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
|
||||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
|
||||||
)
|
|
||||||
|
|
||||||
type IfMsghdr C.struct_if_msghdr
|
|
||||||
|
|
||||||
type IfData C.struct_if_data
|
|
||||||
|
|
||||||
type IfaMsghdr C.struct_ifa_msghdr
|
|
||||||
|
|
||||||
type IfmaMsghdr C.struct_ifma_msghdr
|
|
||||||
|
|
||||||
type IfmaMsghdr2 C.struct_ifma_msghdr2
|
|
||||||
|
|
||||||
type RtMsghdr C.struct_rt_msghdr
|
|
||||||
|
|
||||||
type RtMetrics C.struct_rt_metrics
|
|
||||||
|
|
||||||
// Berkeley packet filter
|
|
||||||
|
|
||||||
const (
|
|
||||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
|
||||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
|
||||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
|
||||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
|
||||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
|
||||||
)
|
|
||||||
|
|
||||||
type BpfVersion C.struct_bpf_version
|
|
||||||
|
|
||||||
type BpfStat C.struct_bpf_stat
|
|
||||||
|
|
||||||
type BpfProgram C.struct_bpf_program
|
|
||||||
|
|
||||||
type BpfInsn C.struct_bpf_insn
|
|
||||||
|
|
||||||
type BpfHdr C.struct_bpf_hdr
|
|
||||||
|
|
||||||
// Terminal handling
|
|
||||||
|
|
||||||
type Termios C.struct_termios
|
|
||||||
|
|
||||||
type Winsize C.struct_winsize
|
|
||||||
|
|
||||||
// fchmodat-like syscalls.
|
|
||||||
|
|
||||||
const (
|
|
||||||
AT_FDCWD = C.AT_FDCWD
|
|
||||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
|
||||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
|
||||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
|
||||||
)
|
|
||||||
|
|
||||||
// poll
|
|
||||||
|
|
||||||
type PollFd C.struct_pollfd
|
|
||||||
|
|
||||||
const (
|
|
||||||
POLLERR = C.POLLERR
|
|
||||||
POLLHUP = C.POLLHUP
|
|
||||||
POLLIN = C.POLLIN
|
|
||||||
POLLNVAL = C.POLLNVAL
|
|
||||||
POLLOUT = C.POLLOUT
|
|
||||||
POLLPRI = C.POLLPRI
|
|
||||||
POLLRDBAND = C.POLLRDBAND
|
|
||||||
POLLRDNORM = C.POLLRDNORM
|
|
||||||
POLLWRBAND = C.POLLWRBAND
|
|
||||||
POLLWRNORM = C.POLLWRNORM
|
|
||||||
)
|
|
||||||
|
|
||||||
// uname
|
|
||||||
|
|
||||||
type Utsname C.struct_utsname
|
|
||||||
|
|
||||||
// Clockinfo
|
|
||||||
|
|
||||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
|
||||||
|
|
||||||
type Clockinfo C.struct_clockinfo
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user