mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
Separate CNI plugin dependencies
Because: - Current CNI plugins produces an error on Raspbian: `failed to create bridge \"cni0\": could not add \"cni0\": operation not supported"` - Dependencies for CNI plugins may interfere with containerd dependencies. This change will compile and download CNI plugins separately, and will downgrade CNI plugins to v0.7.6 for compatability with armv7.
This commit is contained in:
parent
1b9698bb71
commit
262a4950bf
@ -1,23 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
hostlocal "github.com/containernetworking/plugins/plugins/ipam/host-local"
|
|
||||||
"github.com/containernetworking/plugins/plugins/main/bridge"
|
|
||||||
"github.com/containernetworking/plugins/plugins/main/loopback"
|
|
||||||
"github.com/containernetworking/plugins/plugins/meta/flannel"
|
|
||||||
"github.com/containernetworking/plugins/plugins/meta/portmap"
|
|
||||||
"github.com/docker/docker/pkg/reexec"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
os.Args[0] = filepath.Base(os.Args[0])
|
|
||||||
reexec.Register("host-local", hostlocal.Main)
|
|
||||||
reexec.Register("bridge", bridge.Main)
|
|
||||||
reexec.Register("flannel", flannel.Main)
|
|
||||||
reexec.Register("loopback", loopback.Main)
|
|
||||||
reexec.Register("portmap", portmap.Main)
|
|
||||||
reexec.Init()
|
|
||||||
}
|
|
4
go.mod
4
go.mod
@ -12,7 +12,6 @@ replace (
|
|||||||
github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c
|
github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c
|
||||||
github.com/containerd/go-runc => github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda
|
github.com/containerd/go-runc => github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda
|
||||||
github.com/containerd/typeurl => github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd
|
github.com/containerd/typeurl => github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd
|
||||||
github.com/containernetworking/plugins => github.com/rancher/plugins v0.8.2-k3s.2
|
|
||||||
github.com/coreos/flannel => github.com/rancher/flannel v0.11.0-k3s.1
|
github.com/coreos/flannel => github.com/rancher/flannel v0.11.0-k3s.1
|
||||||
github.com/coreos/go-systemd => github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7
|
github.com/coreos/go-systemd => github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7
|
||||||
github.com/docker/distribution => github.com/docker/distribution v0.0.0-20190205005809-0d3efadf0154
|
github.com/docker/distribution => github.com/docker/distribution v0.0.0-20190205005809-0d3efadf0154
|
||||||
@ -73,7 +72,7 @@ require (
|
|||||||
github.com/containerd/go-cni v0.0.0-20190904155053-d20b7eebc7ee // indirect
|
github.com/containerd/go-cni v0.0.0-20190904155053-d20b7eebc7ee // indirect
|
||||||
github.com/containerd/go-runc v0.0.0-20190923131748-a2952bc25f51 // indirect
|
github.com/containerd/go-runc v0.0.0-20190923131748-a2952bc25f51 // indirect
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8 // indirect
|
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8 // indirect
|
||||||
github.com/containernetworking/plugins v0.8.2
|
github.com/containernetworking/plugins v0.8.2 // indirect
|
||||||
github.com/coreos/flannel v0.11.0
|
github.com/coreos/flannel v0.11.0
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
||||||
github.com/docker/docker v0.7.3-0.20190731001754-589f1dad8dad
|
github.com/docker/docker v0.7.3-0.20190731001754-589f1dad8dad
|
||||||
@ -86,7 +85,6 @@ require (
|
|||||||
github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2
|
github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2
|
||||||
github.com/gorilla/mux v1.7.3
|
github.com/gorilla/mux v1.7.3
|
||||||
github.com/gorilla/websocket v1.4.0
|
github.com/gorilla/websocket v1.4.0
|
||||||
github.com/j-keck/arping v1.0.0 // indirect
|
|
||||||
github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d // indirect
|
github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d // indirect
|
||||||
github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2 // indirect
|
github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2 // indirect
|
||||||
github.com/kubernetes-sigs/cri-tools v0.0.0-00010101000000-000000000000
|
github.com/kubernetes-sigs/cri-tools v0.0.0-00010101000000-000000000000
|
||||||
|
12
go.sum
12
go.sum
@ -53,7 +53,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
|
|||||||
github.com/Rican7/retry v0.1.0 h1:FqK94z34ly8Baa6K+G8Mmza9rYWTKOJk+yckIBB5qVk=
|
github.com/Rican7/retry v0.1.0 h1:FqK94z34ly8Baa6K+G8Mmza9rYWTKOJk+yckIBB5qVk=
|
||||||
github.com/Rican7/retry v0.1.0/go.mod h1:FgOROf8P5bebcC1DS0PdOQiqGUridaZvikzUmkFW6gg=
|
github.com/Rican7/retry v0.1.0/go.mod h1:FgOROf8P5bebcC1DS0PdOQiqGUridaZvikzUmkFW6gg=
|
||||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae h1:AMzIhMUqU3jMrZiTuW0zkYeKlKDAFD+DG20IoO421/Y=
|
|
||||||
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/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
@ -117,6 +116,8 @@ github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kw
|
|||||||
github.com/containernetworking/cni v0.7.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
github.com/containernetworking/cni v0.7.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||||
github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE=
|
github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE=
|
||||||
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||||
|
github.com/containernetworking/plugins v0.8.2 h1:5lnwfsAYO+V7yXhysJKy3E1A2Gy9oVut031zfdOzI9w=
|
||||||
|
github.com/containernetworking/plugins v0.8.2/go.mod h1:TxALKWZpWL79BC3GOYKJzzXr7U8R23PdhwaLp6F3adc=
|
||||||
github.com/coredns/corefile-migration v1.0.2/go.mod h1:OFwBp/Wc9dJt5cAZzHWMNhK1r5L0p0jDwIBc6j8NC8E=
|
github.com/coredns/corefile-migration v1.0.2/go.mod h1:OFwBp/Wc9dJt5cAZzHWMNhK1r5L0p0jDwIBc6j8NC8E=
|
||||||
github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A=
|
github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A=
|
||||||
github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
@ -179,8 +180,6 @@ github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkg
|
|||||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
|
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
|
||||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
github.com/erikwilson/rancher-dynamiclistener v0.0.0-20190717164634-c08b499d1719 h1:oBIokhBifMqHqzn1e6973Uyh+tmEG1gjTJxYN8BVWxE=
|
|
||||||
github.com/erikwilson/rancher-dynamiclistener v0.0.0-20190717164634-c08b499d1719/go.mod h1:vNqDnGTkrX8tiBUevkvjZoQoiZOjaahVbMaYRIl25l0=
|
|
||||||
github.com/euank/go-kmsg-parser v2.0.0+incompatible h1:cHD53+PLQuuQyLZeriD1V/esuG4MuU0Pjs5y6iknohY=
|
github.com/euank/go-kmsg-parser v2.0.0+incompatible h1:cHD53+PLQuuQyLZeriD1V/esuG4MuU0Pjs5y6iknohY=
|
||||||
github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw=
|
github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw=
|
||||||
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
|
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
|
||||||
@ -386,8 +385,6 @@ github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
|||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
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/j-keck/arping v1.0.0 h1:DN6Wy73IeadEEo5xVCgEp+ZGn2xmAypggxj8mtxXBD0=
|
|
||||||
github.com/j-keck/arping v1.0.0/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
|
||||||
github.com/jetstack/cert-manager v0.7.2/go.mod h1:nbddmhjWxYGt04bxvwVGUSeLhZ2PCyNvd7MpXdq+yWY=
|
github.com/jetstack/cert-manager v0.7.2/go.mod h1:nbddmhjWxYGt04bxvwVGUSeLhZ2PCyNvd7MpXdq+yWY=
|
||||||
github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8=
|
github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||||
@ -617,8 +614,6 @@ github.com/rancher/kubernetes/staging/src/k8s.io/metrics v1.16.0-k3s.1/go.mod h1
|
|||||||
github.com/rancher/kubernetes/staging/src/k8s.io/sample-apiserver v1.16.0-k3s.1/go.mod h1:E3i4wscD52Qj6PEcgUjvCd81Tl6Mghk1GHtEzoaaqwU=
|
github.com/rancher/kubernetes/staging/src/k8s.io/sample-apiserver v1.16.0-k3s.1/go.mod h1:E3i4wscD52Qj6PEcgUjvCd81Tl6Mghk1GHtEzoaaqwU=
|
||||||
github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 h1:Xsxh7fX3+2wAUJtPy8g2lZh0cYuyifqhBL0vxCIYojs=
|
github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 h1:Xsxh7fX3+2wAUJtPy8g2lZh0cYuyifqhBL0vxCIYojs=
|
||||||
github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009/go.mod h1:wpITyDPTi/Na5h73XkbuEf2AP9fbgrIGqqxVzFhYD6U=
|
github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009/go.mod h1:wpITyDPTi/Na5h73XkbuEf2AP9fbgrIGqqxVzFhYD6U=
|
||||||
github.com/rancher/plugins v0.8.2-k3s.2 h1:5GiHA4adchBV238NuPQvKDRPO0UR4ttAxfBehH2Vx/M=
|
|
||||||
github.com/rancher/plugins v0.8.2-k3s.2/go.mod h1:TxALKWZpWL79BC3GOYKJzzXr7U8R23PdhwaLp6F3adc=
|
|
||||||
github.com/rancher/remotedialer v0.2.0 h1:xD7t3K6JYwTdAsxmGtTHQMkEkFgKouQ1foLxVW424Dc=
|
github.com/rancher/remotedialer v0.2.0 h1:xD7t3K6JYwTdAsxmGtTHQMkEkFgKouQ1foLxVW424Dc=
|
||||||
github.com/rancher/remotedialer v0.2.0/go.mod h1:tkU8ZvrR5lRgaKWaX71nAy6daeqvPFx/lJEnbW7tXSI=
|
github.com/rancher/remotedialer v0.2.0/go.mod h1:tkU8ZvrR5lRgaKWaX71nAy6daeqvPFx/lJEnbW7tXSI=
|
||||||
github.com/rancher/wrangler v0.0.0-20190512193419-40fa298578b9/go.mod h1:HM0BuhAugqM5cGtQn2hrMwpbExuLQe7NCUTD+crAxV0=
|
github.com/rancher/wrangler v0.0.0-20190512193419-40fa298578b9/go.mod h1:HM0BuhAugqM5cGtQn2hrMwpbExuLQe7NCUTD+crAxV0=
|
||||||
@ -641,7 +636,6 @@ github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/
|
|||||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U=
|
|
||||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
@ -688,7 +682,6 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci
|
|||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/syndtr/gocapability v0.0.0-20160928074757-e7cb7fa329f4 h1:w58e6FAOMd+rUgOfhaBb+ZVOQIOfUkpv5AAQVmf6hsI=
|
|
||||||
github.com/syndtr/gocapability v0.0.0-20160928074757-e7cb7fa329f4/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20160928074757-e7cb7fa329f4/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8 h1:zLV6q4e8Jv9EHjNg/iHfzwDkCve6Ua5jCygptrtXHvI=
|
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8 h1:zLV6q4e8Jv9EHjNg/iHfzwDkCve6Ua5jCygptrtXHvI=
|
||||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
@ -729,7 +722,6 @@ github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSf
|
|||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
|
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
@ -48,6 +48,16 @@ rm -f \
|
|||||||
bin/crictl \
|
bin/crictl \
|
||||||
bin/ctr
|
bin/ctr
|
||||||
|
|
||||||
|
INSTALLBIN=$(pwd)/bin
|
||||||
|
(
|
||||||
|
echo Building cni
|
||||||
|
WORKDIR=$(go env GOPATH)/src/github.com/containernetworking/plugins
|
||||||
|
[ -d $WORKDIR ] || git clone https://github.com/rancher/plugins.git $WORKDIR
|
||||||
|
cd $WORKDIR
|
||||||
|
git fetch -f
|
||||||
|
git checkout $VERSION_CNIPLUGINS
|
||||||
|
CGO_ENABLED=0 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC" -o $INSTALLBIN/cni
|
||||||
|
)
|
||||||
# echo Building agent
|
# echo Building agent
|
||||||
# CGO_ENABLED=1 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC" -o bin/k3s-agent ./cmd/agent/main.go
|
# CGO_ENABLED=1 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC" -o bin/k3s-agent ./cmd/agent/main.go
|
||||||
echo Building server
|
echo Building server
|
||||||
@ -63,8 +73,6 @@ CGO_ENABLED=1 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC_SQLITE" -o bin/h
|
|||||||
#CGO_ENABLED=1 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC_SQLITE" -o bin/ctr ./cmd/ctr/main.go
|
#CGO_ENABLED=1 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC_SQLITE" -o bin/ctr ./cmd/ctr/main.go
|
||||||
# echo Building containerd
|
# echo Building containerd
|
||||||
# CGO_ENABLED=0 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC" -o bin/containerd ./cmd/containerd/
|
# CGO_ENABLED=0 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC" -o bin/containerd ./cmd/containerd/
|
||||||
echo Building cni
|
|
||||||
CGO_ENABLED=0 go build -tags "$TAGS" -ldflags "$LDFLAGS $STATIC" -o bin/cni ./cmd/cni/main.go
|
|
||||||
echo Building runc
|
echo Building runc
|
||||||
make EXTRA_LDFLAGS="-w -s" BUILDTAGS="apparmor seccomp" -C ./vendor/github.com/opencontainers/runc static
|
make EXTRA_LDFLAGS="-w -s" BUILDTAGS="apparmor seccomp" -C ./vendor/github.com/opencontainers/runc static
|
||||||
cp -f ./vendor/github.com/opencontainers/runc/runc ./bin/runc
|
cp -f ./vendor/github.com/opencontainers/runc/runc ./bin/runc
|
||||||
|
@ -26,3 +26,5 @@ fi
|
|||||||
if [ -z "$VERSION_CRICTL" ]; then
|
if [ -z "$VERSION_CRICTL" ]; then
|
||||||
VERSION_CRICTL="v0.0.0"
|
VERSION_CRICTL="v0.0.0"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
VERSION_CNIPLUGINS="v0.7.6-k3s1"
|
||||||
|
913
vendor/github.com/Microsoft/go-winio/pkg/etw/mksyscall_windows.go
generated
vendored
913
vendor/github.com/Microsoft/go-winio/pkg/etw/mksyscall_windows.go
generated
vendored
@ -1,913 +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 its 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")
|
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
|
||||||
}`
|
|
||||||
if r.Name == "" && !r.ReturnsError {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if r.Name == "" {
|
|
||||||
return r.useLongHandleErrorCode("r1")
|
|
||||||
}
|
|
||||||
if r.Type == "error" {
|
|
||||||
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
|
|
||||||
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 + "\"")
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 (f *Fn) IsUTF16() bool {
|
|
||||||
s := f.DLLFuncName()
|
|
||||||
return s[len(s)-1] == 'W'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) FuncImports() []*Fn {
|
|
||||||
uniq := make(map[string]bool)
|
|
||||||
r := make([]*Fn, 0)
|
|
||||||
for _, f := range src.Funcs {
|
|
||||||
name := f.DLLFuncName()
|
|
||||||
if _, found := uniq[name]; !found {
|
|
||||||
uniq[name] = true
|
|
||||||
r = append(r, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
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 reports whether 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 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 + ")"
|
|
||||||
}
|
|
||||||
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 by 'go generate'; 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 .FuncImports}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}")
|
|
||||||
{{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 "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 "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n")
|
|
||||||
{{end}}{{end}}
|
|
||||||
|
|
||||||
`
|
|
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}}
|
|
||||||
|
|
||||||
`
|
|
21
vendor/github.com/alexflint/go-filemutex/LICENSE
generated
vendored
21
vendor/github.com/alexflint/go-filemutex/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
The MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2010-2017 Alex Flint.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
31
vendor/github.com/alexflint/go-filemutex/README.md
generated
vendored
31
vendor/github.com/alexflint/go-filemutex/README.md
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
# FileMutex
|
|
||||||
|
|
||||||
FileMutex is similar to `sync.RWMutex`, but also synchronizes across processes.
|
|
||||||
On Linux, OSX, and other POSIX systems it uses the flock system call. On windows
|
|
||||||
it uses the LockFileEx and UnlockFileEx system calls.
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"github.com/alexflint/go-filemutex"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m, err := filemutex.New("/tmp/foo.lock")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Directory did not exist or file could not created")
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Lock() // Will block until lock can be acquired
|
|
||||||
|
|
||||||
// Code here is protected by the mutex
|
|
||||||
|
|
||||||
m.Unlock()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
go get github.com/alexflint/go-filemutex
|
|
||||||
|
|
||||||
Forked from https://github.com/golang/build/tree/master/cmd/builder/filemutex_*.go
|
|
67
vendor/github.com/alexflint/go-filemutex/filemutex_flock.go
generated
vendored
67
vendor/github.com/alexflint/go-filemutex/filemutex_flock.go
generated
vendored
@ -1,67 +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 darwin dragonfly freebsd linux netbsd openbsd
|
|
||||||
|
|
||||||
package filemutex
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
mkdirPerm = 0750
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileMutex is similar to sync.RWMutex, but also synchronizes across processes.
|
|
||||||
// This implementation is based on flock syscall.
|
|
||||||
type FileMutex struct {
|
|
||||||
fd int
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(filename string) (*FileMutex, error) {
|
|
||||||
fd, err := syscall.Open(filename, syscall.O_CREAT|syscall.O_RDONLY, mkdirPerm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &FileMutex{fd: fd}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FileMutex) Lock() error {
|
|
||||||
if err := syscall.Flock(m.fd, syscall.LOCK_EX); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FileMutex) Unlock() error {
|
|
||||||
if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FileMutex) RLock() error {
|
|
||||||
if err := syscall.Flock(m.fd, syscall.LOCK_SH); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FileMutex) RUnlock() error {
|
|
||||||
if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close does an Unlock() combined with closing and unlinking the associated
|
|
||||||
// lock file. You should create a New() FileMutex for every Lock() attempt if
|
|
||||||
// using Close().
|
|
||||||
func (m *FileMutex) Close() error {
|
|
||||||
if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return syscall.Close(m.fd)
|
|
||||||
}
|
|
102
vendor/github.com/alexflint/go-filemutex/filemutex_windows.go
generated
vendored
102
vendor/github.com/alexflint/go-filemutex/filemutex_windows.go
generated
vendored
@ -1,102 +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.
|
|
||||||
|
|
||||||
package filemutex
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
||||||
procLockFileEx = modkernel32.NewProc("LockFileEx")
|
|
||||||
procUnlockFileEx = modkernel32.NewProc("UnlockFileEx")
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
lockfileExclusiveLock = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
|
|
||||||
r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)))
|
|
||||||
if r1 == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = error(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
|
|
||||||
r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0)
|
|
||||||
if r1 == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = error(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileMutex is similar to sync.RWMutex, but also synchronizes across processes.
|
|
||||||
// This implementation is based on flock syscall.
|
|
||||||
type FileMutex struct {
|
|
||||||
fd syscall.Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(filename string) (*FileMutex, error) {
|
|
||||||
fd, err := syscall.CreateFile(&(syscall.StringToUTF16(filename)[0]), syscall.GENERIC_READ|syscall.GENERIC_WRITE,
|
|
||||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, nil, syscall.OPEN_ALWAYS, syscall.FILE_ATTRIBUTE_NORMAL, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &FileMutex{fd: fd}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FileMutex) Lock() error {
|
|
||||||
var ol syscall.Overlapped
|
|
||||||
if err := lockFileEx(m.fd, lockfileExclusiveLock, 0, 1, 0, &ol); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FileMutex) Unlock() error {
|
|
||||||
var ol syscall.Overlapped
|
|
||||||
if err := unlockFileEx(m.fd, 0, 1, 0, &ol); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FileMutex) RLock() error {
|
|
||||||
var ol syscall.Overlapped
|
|
||||||
if err := lockFileEx(m.fd, 0, 0, 1, 0, &ol); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FileMutex) RUnlock() error {
|
|
||||||
var ol syscall.Overlapped
|
|
||||||
if err := unlockFileEx(m.fd, 0, 1, 0, &ol); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close does an Unlock() combined with closing and unlinking the associated
|
|
||||||
// lock file. You should create a New() FileMutex for every Lock() attempt if
|
|
||||||
// using Close().
|
|
||||||
func (m *FileMutex) Close() error {
|
|
||||||
var ol syscall.Overlapped
|
|
||||||
if err := unlockFileEx(m.fd, 0, 1, 0, &ol); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return syscall.Close(m.fd)
|
|
||||||
}
|
|
22
vendor/github.com/chai2010/gettext-go/gettext/hello.go
generated
vendored
22
vendor/github.com/chai2010/gettext-go/gettext/hello.go
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
// Copyright 2013 <chaishushan{AT}gmail.com>. 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
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/chai2010/gettext-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
gettext.SetLocale("zh_CN")
|
|
||||||
gettext.BindTextdomain("hello", "../examples/local", nil)
|
|
||||||
gettext.Textdomain("hello")
|
|
||||||
|
|
||||||
fmt.Println(gettext.Gettext("Hello, world!"))
|
|
||||||
// Output: 你好, 世界!
|
|
||||||
}
|
|
39
vendor/github.com/containerd/continuity/manifest_test_darwin.go
generated
vendored
39
vendor/github.com/containerd/continuity/manifest_test_darwin.go
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 continuity
|
|
||||||
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
var (
|
|
||||||
devNullResource = resource{
|
|
||||||
kind: chardev,
|
|
||||||
path: "/dev/null",
|
|
||||||
major: 3,
|
|
||||||
minor: 2,
|
|
||||||
mode: 0666 | os.ModeDevice | os.ModeCharDevice,
|
|
||||||
}
|
|
||||||
|
|
||||||
devZeroResource = resource{
|
|
||||||
kind: chardev,
|
|
||||||
path: "/dev/zero",
|
|
||||||
major: 3,
|
|
||||||
minor: 3,
|
|
||||||
mode: 0666 | os.ModeDevice | os.ModeCharDevice,
|
|
||||||
}
|
|
||||||
)
|
|
307
vendor/github.com/containernetworking/cni/pkg/skel/skel.go
generated
vendored
307
vendor/github.com/containernetworking/cni/pkg/skel/skel.go
generated
vendored
@ -1,307 +0,0 @@
|
|||||||
// Copyright 2014-2016 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 skel provides skeleton code for a CNI plugin.
|
|
||||||
// In particular, it implements argument parsing and validation.
|
|
||||||
package skel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CmdArgs captures all the arguments passed in to the plugin
|
|
||||||
// via both env vars and stdin
|
|
||||||
type CmdArgs struct {
|
|
||||||
ContainerID string
|
|
||||||
Netns string
|
|
||||||
IfName string
|
|
||||||
Args string
|
|
||||||
Path string
|
|
||||||
StdinData []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type dispatcher struct {
|
|
||||||
Getenv func(string) string
|
|
||||||
Stdin io.Reader
|
|
||||||
Stdout io.Writer
|
|
||||||
Stderr io.Writer
|
|
||||||
|
|
||||||
ConfVersionDecoder version.ConfigDecoder
|
|
||||||
VersionReconciler version.Reconciler
|
|
||||||
}
|
|
||||||
|
|
||||||
type reqForCmdEntry map[string]bool
|
|
||||||
|
|
||||||
// internal only error to indicate lack of required environment variables
|
|
||||||
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
|
|
||||||
|
|
||||||
vars := []struct {
|
|
||||||
name string
|
|
||||||
val *string
|
|
||||||
reqForCmd reqForCmdEntry
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"CNI_COMMAND",
|
|
||||||
&cmd,
|
|
||||||
reqForCmdEntry{
|
|
||||||
"ADD": true,
|
|
||||||
"CHECK": true,
|
|
||||||
"DEL": true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"CNI_CONTAINERID",
|
|
||||||
&contID,
|
|
||||||
reqForCmdEntry{
|
|
||||||
"ADD": true,
|
|
||||||
"CHECK": true,
|
|
||||||
"DEL": true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"CNI_NETNS",
|
|
||||||
&netns,
|
|
||||||
reqForCmdEntry{
|
|
||||||
"ADD": true,
|
|
||||||
"CHECK": true,
|
|
||||||
"DEL": false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"CNI_IFNAME",
|
|
||||||
&ifName,
|
|
||||||
reqForCmdEntry{
|
|
||||||
"ADD": true,
|
|
||||||
"CHECK": true,
|
|
||||||
"DEL": true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"CNI_ARGS",
|
|
||||||
&args,
|
|
||||||
reqForCmdEntry{
|
|
||||||
"ADD": false,
|
|
||||||
"CHECK": false,
|
|
||||||
"DEL": false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"CNI_PATH",
|
|
||||||
&path,
|
|
||||||
reqForCmdEntry{
|
|
||||||
"ADD": true,
|
|
||||||
"CHECK": true,
|
|
||||||
"DEL": true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
argsMissing := make([]string, 0)
|
|
||||||
for _, v := range vars {
|
|
||||||
*v.val = t.Getenv(v.name)
|
|
||||||
if *v.val == "" {
|
|
||||||
if v.reqForCmd[cmd] || v.name == "CNI_COMMAND" {
|
|
||||||
argsMissing = append(argsMissing, v.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(argsMissing) > 0 {
|
|
||||||
joined := strings.Join(argsMissing, ",")
|
|
||||||
return "", nil, missingEnvError{fmt.Sprintf("required env variables [%s] missing", joined)}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cmd == "VERSION" {
|
|
||||||
t.Stdin = bytes.NewReader(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
stdinData, err := ioutil.ReadAll(t.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, fmt.Errorf("error reading from stdin: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdArgs := &CmdArgs{
|
|
||||||
ContainerID: contID,
|
|
||||||
Netns: netns,
|
|
||||||
IfName: ifName,
|
|
||||||
Args: args,
|
|
||||||
Path: path,
|
|
||||||
StdinData: stdinData,
|
|
||||||
}
|
|
||||||
return cmd, cmdArgs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTypedError(f string, args ...interface{}) *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)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
verErr := t.VersionReconciler.Check(configVersion, pluginVersionInfo)
|
|
||||||
if verErr != nil {
|
|
||||||
return &types.Error{
|
|
||||||
Code: types.ErrIncompatibleCNIVersion,
|
|
||||||
Msg: "incompatible CNI versions",
|
|
||||||
Details: verErr.Details(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return toCall(cmdArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateConfig(jsonBytes []byte) error {
|
|
||||||
var conf struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(jsonBytes, &conf); err != nil {
|
|
||||||
return fmt.Errorf("error reading network config: %s", err)
|
|
||||||
}
|
|
||||||
if conf.Name == "" {
|
|
||||||
return fmt.Errorf("missing network name")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo, about string) *types.Error {
|
|
||||||
cmd, cmdArgs, err := t.getCmdArgsFromEnv()
|
|
||||||
if err != nil {
|
|
||||||
// Print the about string to stderr when no command is set
|
|
||||||
if _, ok := err.(missingEnvError); ok && t.Getenv("CNI_COMMAND") == "" && about != "" {
|
|
||||||
fmt.Fprintln(t.Stderr, about)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return createTypedError(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if cmd != "VERSION" {
|
|
||||||
err = validateConfig(cmdArgs.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return createTypedError(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch cmd {
|
|
||||||
case "ADD":
|
|
||||||
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdAdd)
|
|
||||||
case "CHECK":
|
|
||||||
configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return createTypedError(err.Error())
|
|
||||||
}
|
|
||||||
if gtet, err := version.GreaterThanOrEqualTo(configVersion, "0.4.0"); err != nil {
|
|
||||||
return createTypedError(err.Error())
|
|
||||||
} else if !gtet {
|
|
||||||
return &types.Error{
|
|
||||||
Code: types.ErrIncompatibleCNIVersion,
|
|
||||||
Msg: "config version does not allow CHECK",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, pluginVersion := range versionInfo.SupportedVersions() {
|
|
||||||
gtet, err := version.GreaterThanOrEqualTo(pluginVersion, configVersion)
|
|
||||||
if err != nil {
|
|
||||||
return createTypedError(err.Error())
|
|
||||||
} else if gtet {
|
|
||||||
if err := t.checkVersionAndCall(cmdArgs, versionInfo, cmdCheck); err != nil {
|
|
||||||
return createTypedError(err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &types.Error{
|
|
||||||
Code: types.ErrIncompatibleCNIVersion,
|
|
||||||
Msg: "plugin version does not allow CHECK",
|
|
||||||
}
|
|
||||||
case "DEL":
|
|
||||||
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdDel)
|
|
||||||
case "VERSION":
|
|
||||||
err = versionInfo.Encode(t.Stdout)
|
|
||||||
default:
|
|
||||||
return createTypedError("unknown CNI_COMMAND: %v", cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if e, ok := err.(*types.Error); ok {
|
|
||||||
// don't wrap Error in Error
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
return createTypedError(err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginMainWithError is the core "main" for a plugin. It accepts
|
|
||||||
// callback functions for add, check, and del CNI commands and returns an error.
|
|
||||||
//
|
|
||||||
// The caller must also specify what CNI spec versions the plugin supports.
|
|
||||||
//
|
|
||||||
// It is the responsibility of the caller to check for non-nil error return.
|
|
||||||
//
|
|
||||||
// For a plugin to comply with the CNI spec, it must print any error to stdout
|
|
||||||
// as JSON and then exit with nonzero status code.
|
|
||||||
//
|
|
||||||
// To let this package automatically handle errors and call os.Exit(1) for you,
|
|
||||||
// use PluginMain() instead.
|
|
||||||
func PluginMainWithError(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo, about string) *types.Error {
|
|
||||||
return (&dispatcher{
|
|
||||||
Getenv: os.Getenv,
|
|
||||||
Stdin: os.Stdin,
|
|
||||||
Stdout: os.Stdout,
|
|
||||||
Stderr: os.Stderr,
|
|
||||||
}).pluginMain(cmdAdd, cmdCheck, cmdDel, versionInfo, about)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginMain is the core "main" for a plugin which includes automatic error handling.
|
|
||||||
//
|
|
||||||
// The caller must also specify what CNI spec versions the plugin supports.
|
|
||||||
//
|
|
||||||
// The caller can specify an "about" string, which is printed on stderr
|
|
||||||
// when no CNI_COMMAND is specified. The recommended output is "CNI plugin <foo> v<version>"
|
|
||||||
//
|
|
||||||
// When an error occurs in either cmdAdd, cmdCheck, or cmdDel, PluginMain will print the error
|
|
||||||
// as JSON to stdout and call os.Exit(1).
|
|
||||||
//
|
|
||||||
// To have more control over error handling, use PluginMainWithError() instead.
|
|
||||||
func PluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo, about string) {
|
|
||||||
if e := PluginMainWithError(cmdAdd, cmdCheck, cmdDel, versionInfo, about); e != nil {
|
|
||||||
if err := e.Print(); err != nil {
|
|
||||||
log.Print("Error writing error JSON to stdout: ", err)
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
371
vendor/github.com/containernetworking/plugins/pkg/hns/endpoint_windows.go
generated
vendored
371
vendor/github.com/containernetworking/plugins/pkg/hns/endpoint_windows.go
generated
vendored
@ -1,371 +0,0 @@
|
|||||||
// 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 hns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim"
|
|
||||||
"github.com/Microsoft/hcsshim/hcn"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
"github.com/juju/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
pauseContainerNetNS = "none"
|
|
||||||
)
|
|
||||||
|
|
||||||
type EndpointInfo struct {
|
|
||||||
EndpointName string
|
|
||||||
DNS types.DNS
|
|
||||||
NetworkName string
|
|
||||||
NetworkId string
|
|
||||||
Gateway net.IP
|
|
||||||
IpAddress net.IP
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSandboxContainerID returns the sandbox ID of this pod
|
|
||||||
func GetSandboxContainerID(containerID string, netNs string) string {
|
|
||||||
if len(netNs) != 0 && netNs != pauseContainerNetNS {
|
|
||||||
splits := strings.SplitN(netNs, ":", 2)
|
|
||||||
if len(splits) == 2 {
|
|
||||||
containerID = splits[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return containerID
|
|
||||||
}
|
|
||||||
|
|
||||||
// short function so we know when to return "" for a string
|
|
||||||
func GetIpString(ip *net.IP) string {
|
|
||||||
if len(*ip) == 0 {
|
|
||||||
return ""
|
|
||||||
} else {
|
|
||||||
return ip.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GenerateHnsEndpoint(epInfo *EndpointInfo, n *NetConf) (*hcsshim.HNSEndpoint, error) {
|
|
||||||
// run the IPAM plugin and get back the config to apply
|
|
||||||
hnsEndpoint, err := hcsshim.GetHNSEndpointByName(epInfo.EndpointName)
|
|
||||||
if err != nil && !hcsshim.IsNotExist(err) {
|
|
||||||
return nil, errors.Annotatef(err, "Attempt to get endpoint \"%v\" failed", epInfo.EndpointName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hnsEndpoint != nil {
|
|
||||||
if hnsEndpoint.VirtualNetwork != epInfo.NetworkId {
|
|
||||||
_, err = hnsEndpoint.Delete()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "Failed to delete endpoint %v", epInfo.EndpointName)
|
|
||||||
}
|
|
||||||
hnsEndpoint = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.LoopbackDSR {
|
|
||||||
n.ApplyLoopbackDSR(&epInfo.IpAddress)
|
|
||||||
}
|
|
||||||
if hnsEndpoint == nil {
|
|
||||||
hnsEndpoint = &hcsshim.HNSEndpoint{
|
|
||||||
Name: epInfo.EndpointName,
|
|
||||||
VirtualNetwork: epInfo.NetworkId,
|
|
||||||
DNSServerList: strings.Join(epInfo.DNS.Nameservers, ","),
|
|
||||||
DNSSuffix: strings.Join(epInfo.DNS.Search, ","),
|
|
||||||
GatewayAddress: GetIpString(&epInfo.Gateway),
|
|
||||||
IPAddress: epInfo.IpAddress,
|
|
||||||
Policies: n.MarshalPolicies(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hnsEndpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GenerateHcnEndpoint(epInfo *EndpointInfo, n *NetConf) (*hcn.HostComputeEndpoint, error) {
|
|
||||||
// run the IPAM plugin and get back the config to apply
|
|
||||||
hcnEndpoint, err := hcn.GetEndpointByName(epInfo.EndpointName)
|
|
||||||
if err != nil && !hcn.IsNotFoundError(err) {
|
|
||||||
return nil, errors.Annotatef(err, "Attempt to get endpoint \"%v\" failed", epInfo.EndpointName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hcnEndpoint != nil {
|
|
||||||
// If the endpont already exists, then we should return error unless
|
|
||||||
// the endpoint is based on a different network then delete
|
|
||||||
// should that fail return error
|
|
||||||
if !strings.EqualFold(hcnEndpoint.HostComputeNetwork, epInfo.NetworkId) {
|
|
||||||
err = hcnEndpoint.Delete()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "Failed to delete endpoint %v", epInfo.EndpointName)
|
|
||||||
hcnEndpoint = nil
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("Endpoint \"%v\" already exits", epInfo.EndpointName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if hcnEndpoint == nil {
|
|
||||||
routes := []hcn.Route{
|
|
||||||
{
|
|
||||||
NextHop: GetIpString(&epInfo.Gateway),
|
|
||||||
DestinationPrefix: GetDefaultDestinationPrefix(&epInfo.Gateway),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
hcnDns := hcn.Dns{
|
|
||||||
Search: epInfo.DNS.Search,
|
|
||||||
ServerList: epInfo.DNS.Nameservers,
|
|
||||||
}
|
|
||||||
|
|
||||||
hcnIpConfig := hcn.IpConfig{
|
|
||||||
IpAddress: GetIpString(&epInfo.IpAddress),
|
|
||||||
}
|
|
||||||
ipConfigs := []hcn.IpConfig{hcnIpConfig}
|
|
||||||
|
|
||||||
if n.LoopbackDSR {
|
|
||||||
n.ApplyLoopbackDSR(&epInfo.IpAddress)
|
|
||||||
}
|
|
||||||
hcnEndpoint = &hcn.HostComputeEndpoint{
|
|
||||||
SchemaVersion: hcn.Version{Major: 2},
|
|
||||||
Name: epInfo.EndpointName,
|
|
||||||
HostComputeNetwork: epInfo.NetworkId,
|
|
||||||
Dns: hcnDns,
|
|
||||||
Routes: routes,
|
|
||||||
IpConfigurations: ipConfigs,
|
|
||||||
Policies: func() []hcn.EndpointPolicy {
|
|
||||||
if n.HcnPolicyArgs == nil {
|
|
||||||
n.HcnPolicyArgs = []hcn.EndpointPolicy{}
|
|
||||||
}
|
|
||||||
return n.HcnPolicyArgs
|
|
||||||
}(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hcnEndpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConstructEndpointName constructs enpointId which is used to identify an endpoint from HNS
|
|
||||||
// There is a special consideration for netNs name here, which is required for Windows Server 1709
|
|
||||||
// containerID is the Id of the container on which the endpoint is worked on
|
|
||||||
func ConstructEndpointName(containerID string, netNs string, networkName string) string {
|
|
||||||
return GetSandboxContainerID(containerID, netNs) + "_" + networkName
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeprovisionEndpoint removes an endpoint from the container by sending a Detach request to HNS
|
|
||||||
// For shared endpoint, ContainerDetach is used
|
|
||||||
// for removing the endpoint completely, HotDetachEndpoint is used
|
|
||||||
func DeprovisionEndpoint(epName string, netns string, containerID string) error {
|
|
||||||
if len(netns) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
hnsEndpoint, err := hcsshim.GetHNSEndpointByName(epName)
|
|
||||||
|
|
||||||
if hcsshim.IsNotExist(err) {
|
|
||||||
return nil
|
|
||||||
} else if err != nil {
|
|
||||||
return errors.Annotatef(err, "failed to find HNSEndpoint %s", epName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if netns != pauseContainerNetNS {
|
|
||||||
// Shared endpoint removal. Do not remove the endpoint.
|
|
||||||
hnsEndpoint.ContainerDetach(containerID)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not consider this as failure, else this would leak endpoints
|
|
||||||
hcsshim.HotDetachEndpoint(containerID, hnsEndpoint.Id)
|
|
||||||
|
|
||||||
// Do not return error
|
|
||||||
hnsEndpoint.Delete()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type EndpointMakerFunc func() (*hcsshim.HNSEndpoint, error)
|
|
||||||
|
|
||||||
// ProvisionEndpoint provisions an endpoint to a container specified by containerID.
|
|
||||||
// If an endpoint already exists, the endpoint is reused.
|
|
||||||
// This call is idempotent
|
|
||||||
func ProvisionEndpoint(epName string, expectedNetworkId string, containerID string, netns string, makeEndpoint EndpointMakerFunc) (*hcsshim.HNSEndpoint, error) {
|
|
||||||
// On the second add call we expect that the endpoint already exists. If it
|
|
||||||
// does not then we should return an error.
|
|
||||||
if netns != pauseContainerNetNS {
|
|
||||||
_, err := hcsshim.GetHNSEndpointByName(epName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "failed to find HNSEndpoint %s", epName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if endpoint already exists
|
|
||||||
createEndpoint := true
|
|
||||||
hnsEndpoint, err := hcsshim.GetHNSEndpointByName(epName)
|
|
||||||
if hnsEndpoint != nil && strings.EqualFold(hnsEndpoint.VirtualNetwork, expectedNetworkId) {
|
|
||||||
createEndpoint = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if createEndpoint {
|
|
||||||
if hnsEndpoint != nil {
|
|
||||||
if _, err = hnsEndpoint.Delete(); err != nil {
|
|
||||||
return nil, errors.Annotate(err, "failed to delete the stale HNSEndpoint")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if hnsEndpoint, err = makeEndpoint(); err != nil {
|
|
||||||
return nil, errors.Annotate(err, "failed to make a new HNSEndpoint")
|
|
||||||
}
|
|
||||||
|
|
||||||
if hnsEndpoint, err = hnsEndpoint.Create(); err != nil {
|
|
||||||
return nil, errors.Annotate(err, "failed to create the new HNSEndpoint")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// hot attach
|
|
||||||
if err := hcsshim.HotAttachEndpoint(containerID, hnsEndpoint.Id); err != nil {
|
|
||||||
if createEndpoint {
|
|
||||||
err := DeprovisionEndpoint(epName, netns, containerID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "failed to Deprovsion after HotAttach failure")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if hcsshim.ErrComputeSystemDoesNotExist == err {
|
|
||||||
return hnsEndpoint, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return hnsEndpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type HcnEndpointMakerFunc func() (*hcn.HostComputeEndpoint, error)
|
|
||||||
|
|
||||||
func AddHcnEndpoint(epName string, expectedNetworkId string, namespace string,
|
|
||||||
makeEndpoint HcnEndpointMakerFunc) (*hcn.HostComputeEndpoint, error) {
|
|
||||||
|
|
||||||
hcnEndpoint, err := makeEndpoint()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Annotate(err, "failed to make a new HNSEndpoint")
|
|
||||||
}
|
|
||||||
|
|
||||||
if hcnEndpoint, err = hcnEndpoint.Create(); err != nil {
|
|
||||||
return nil, errors.Annotate(err, "failed to create the new HNSEndpoint")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = hcn.AddNamespaceEndpoint(namespace, hcnEndpoint.Id)
|
|
||||||
if err != nil {
|
|
||||||
err := RemoveHcnEndpoint(epName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "failed to Remove Endpoint after AddNamespaceEndpoint failure")
|
|
||||||
}
|
|
||||||
return nil, errors.Annotatef(err, "Failed to Add endpoint to namespace")
|
|
||||||
}
|
|
||||||
return hcnEndpoint, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConstructResult constructs the CNI result for the endpoint
|
|
||||||
func ConstructResult(hnsNetwork *hcsshim.HNSNetwork, hnsEndpoint *hcsshim.HNSEndpoint) (*current.Result, error) {
|
|
||||||
resultInterface := ¤t.Interface{
|
|
||||||
Name: hnsEndpoint.Name,
|
|
||||||
Mac: hnsEndpoint.MacAddress,
|
|
||||||
}
|
|
||||||
_, ipSubnet, err := net.ParseCIDR(hnsNetwork.Subnets[0].AddressPrefix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Annotatef(err, "failed to parse CIDR from %s", hnsNetwork.Subnets[0].AddressPrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipVersion string
|
|
||||||
if ipv4 := hnsEndpoint.IPAddress.To4(); ipv4 != nil {
|
|
||||||
ipVersion = "4"
|
|
||||||
} else if ipv6 := hnsEndpoint.IPAddress.To16(); ipv6 != nil {
|
|
||||||
ipVersion = "6"
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("IPAddress of HNSEndpoint %s isn't a valid ipv4 or ipv6 Address", hnsEndpoint.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
resultIPConfig := ¤t.IPConfig{
|
|
||||||
Version: ipVersion,
|
|
||||||
Address: net.IPNet{
|
|
||||||
IP: hnsEndpoint.IPAddress,
|
|
||||||
Mask: ipSubnet.Mask},
|
|
||||||
Gateway: net.ParseIP(hnsEndpoint.GatewayAddress),
|
|
||||||
}
|
|
||||||
result := ¤t.Result{}
|
|
||||||
result.Interfaces = []*current.Interface{resultInterface}
|
|
||||||
result.IPs = []*current.IPConfig{resultIPConfig}
|
|
||||||
result.DNS = types.DNS{
|
|
||||||
Search: strings.Split(hnsEndpoint.DNSSuffix, ","),
|
|
||||||
Nameservers: strings.Split(hnsEndpoint.DNSServerList, ","),
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// This version follows the v2 workflow of removing the endpoint from the namespace and deleting it
|
|
||||||
func RemoveHcnEndpoint(epName string) error {
|
|
||||||
hcnEndpoint, err := hcn.GetEndpointByName(epName)
|
|
||||||
if hcn.IsNotFoundError(err) {
|
|
||||||
return nil
|
|
||||||
} else if err != nil {
|
|
||||||
_ = fmt.Errorf("[win-cni] Failed to find endpoint %v, err:%v", epName, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if hcnEndpoint != nil {
|
|
||||||
err = hcnEndpoint.Delete()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("[win-cni] Failed to delete endpoint %v, err:%v", epName, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConstructHcnResult(hcnNetwork *hcn.HostComputeNetwork, hcnEndpoint *hcn.HostComputeEndpoint) (*current.Result, error) {
|
|
||||||
resultInterface := ¤t.Interface{
|
|
||||||
Name: hcnEndpoint.Name,
|
|
||||||
Mac: hcnEndpoint.MacAddress,
|
|
||||||
}
|
|
||||||
_, ipSubnet, err := net.ParseCIDR(hcnNetwork.Ipams[0].Subnets[0].IpAddressPrefix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipVersion string
|
|
||||||
ipAddress := net.ParseIP(hcnEndpoint.IpConfigurations[0].IpAddress)
|
|
||||||
if ipv4 := ipAddress.To4(); ipv4 != nil {
|
|
||||||
ipVersion = "4"
|
|
||||||
} else if ipv6 := ipAddress.To16(); ipv6 != nil {
|
|
||||||
ipVersion = "6"
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("[win-cni] The IPAddress of hnsEndpoint isn't a valid ipv4 or ipv6 Address.")
|
|
||||||
}
|
|
||||||
|
|
||||||
resultIPConfig := ¤t.IPConfig{
|
|
||||||
Version: ipVersion,
|
|
||||||
Address: net.IPNet{
|
|
||||||
IP: ipAddress,
|
|
||||||
Mask: ipSubnet.Mask},
|
|
||||||
Gateway: net.ParseIP(hcnEndpoint.Routes[0].NextHop),
|
|
||||||
}
|
|
||||||
result := ¤t.Result{}
|
|
||||||
result.Interfaces = []*current.Interface{resultInterface}
|
|
||||||
result.IPs = []*current.IPConfig{resultIPConfig}
|
|
||||||
result.DNS = types.DNS{
|
|
||||||
Search: hcnEndpoint.Dns.Search,
|
|
||||||
Nameservers: hcnEndpoint.Dns.ServerList,
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
209
vendor/github.com/containernetworking/plugins/pkg/hns/netconf_windows.go
generated
vendored
209
vendor/github.com/containernetworking/plugins/pkg/hns/netconf_windows.go
generated
vendored
@ -1,209 +0,0 @@
|
|||||||
// 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 hns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim/hcn"
|
|
||||||
"github.com/buger/jsonparser"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NetConf is the CNI spec
|
|
||||||
type NetConf struct {
|
|
||||||
types.NetConf
|
|
||||||
// ApiVersion is either 1 or 2, which specifies which hns APIs to call
|
|
||||||
ApiVersion int `json:"ApiVersion"`
|
|
||||||
// V2 Api Policies
|
|
||||||
HcnPolicyArgs []hcn.EndpointPolicy `json:"HcnPolicyArgs,omitempty"`
|
|
||||||
// V1 Api Policies
|
|
||||||
Policies []policy `json:"policies,omitempty"`
|
|
||||||
// Options to be passed in by the runtime
|
|
||||||
RuntimeConfig RuntimeConfig `json:"runtimeConfig"`
|
|
||||||
// If true, adds a policy to endpoints to support loopback direct server return
|
|
||||||
LoopbackDSR bool `json:"loopbackDSR"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RuntimeDNS struct {
|
|
||||||
Nameservers []string `json:"servers,omitempty"`
|
|
||||||
Search []string `json:"searches,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RuntimeConfig struct {
|
|
||||||
DNS RuntimeDNS `json:"dns"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type policy struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Value json.RawMessage `json:"value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDefaultDestinationPrefix(ip *net.IP) string {
|
|
||||||
destinationPrefix := "0.0.0.0/0"
|
|
||||||
if ipv6 := ip.To4(); ipv6 == nil {
|
|
||||||
destinationPrefix = "::/0"
|
|
||||||
}
|
|
||||||
return destinationPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NetConf) ApplyLoopbackDSR(ip *net.IP) {
|
|
||||||
value := fmt.Sprintf(`"Destinations" : ["%s"]`, ip.String())
|
|
||||||
if n.ApiVersion == 2 {
|
|
||||||
hcnLoopbackRoute := hcn.EndpointPolicy{
|
|
||||||
Type: "OutBoundNAT",
|
|
||||||
Settings: []byte(fmt.Sprintf("{%s}", value)),
|
|
||||||
}
|
|
||||||
n.HcnPolicyArgs = append(n.HcnPolicyArgs, hcnLoopbackRoute)
|
|
||||||
} else {
|
|
||||||
hnsLoopbackRoute := policy{
|
|
||||||
Name: "EndpointPolicy",
|
|
||||||
Value: []byte(fmt.Sprintf(`{"Type": "OutBoundNAT", %s}`, value)),
|
|
||||||
}
|
|
||||||
n.Policies = append(n.Policies, hnsLoopbackRoute)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If runtime dns values are there use that else use cni conf supplied dns
|
|
||||||
func (n *NetConf) GetDNS() types.DNS {
|
|
||||||
dnsResult := n.DNS
|
|
||||||
if len(n.RuntimeConfig.DNS.Nameservers) > 0 {
|
|
||||||
dnsResult.Nameservers = n.RuntimeConfig.DNS.Nameservers
|
|
||||||
}
|
|
||||||
if len(n.RuntimeConfig.DNS.Search) > 0 {
|
|
||||||
dnsResult.Search = n.RuntimeConfig.DNS.Search
|
|
||||||
}
|
|
||||||
return dnsResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalPolicies converts the Endpoint policies in Policies
|
|
||||||
// to HNS specific policies as Json raw bytes
|
|
||||||
func (n *NetConf) MarshalPolicies() []json.RawMessage {
|
|
||||||
if n.Policies == nil {
|
|
||||||
n.Policies = make([]policy, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make([]json.RawMessage, 0, len(n.Policies))
|
|
||||||
for _, p := range n.Policies {
|
|
||||||
if !strings.EqualFold(p.Name, "EndpointPolicy") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, p.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApplyOutboundNatPolicy applies NAT Policy in VFP using HNS
|
|
||||||
// Simultaneously an exception is added for the network that has to be Nat'd
|
|
||||||
func (n *NetConf) ApplyOutboundNatPolicy(nwToNat string) {
|
|
||||||
if n.Policies == nil {
|
|
||||||
n.Policies = make([]policy, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
nwToNatBytes := []byte(nwToNat)
|
|
||||||
|
|
||||||
for i, p := range n.Policies {
|
|
||||||
if !strings.EqualFold(p.Name, "EndpointPolicy") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
typeValue, err := jsonparser.GetUnsafeString(p.Value, "Type")
|
|
||||||
if err != nil || len(typeValue) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.EqualFold(typeValue, "OutBoundNAT") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
exceptionListValue, dt, _, _ := jsonparser.Get(p.Value, "ExceptionList")
|
|
||||||
// OutBoundNAT must with ExceptionList, so don't need to judge jsonparser.NotExist
|
|
||||||
if dt == jsonparser.Array {
|
|
||||||
buf := bytes.Buffer{}
|
|
||||||
buf.WriteString(`{"Type": "OutBoundNAT", "ExceptionList": [`)
|
|
||||||
|
|
||||||
jsonparser.ArrayEach(exceptionListValue, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
|
|
||||||
if dataType == jsonparser.String && len(value) != 0 {
|
|
||||||
if bytes.Compare(value, nwToNatBytes) != 0 {
|
|
||||||
buf.WriteByte('"')
|
|
||||||
buf.Write(value)
|
|
||||||
buf.WriteByte('"')
|
|
||||||
buf.WriteByte(',')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
buf.WriteString(`"` + nwToNat + `"]}`)
|
|
||||||
|
|
||||||
n.Policies[i] = policy{
|
|
||||||
Name: "EndpointPolicy",
|
|
||||||
Value: buf.Bytes(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
n.Policies[i] = policy{
|
|
||||||
Name: "EndpointPolicy",
|
|
||||||
Value: []byte(`{"Type": "OutBoundNAT", "ExceptionList": ["` + nwToNat + `"]}`),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// didn't find the policyArg, add it
|
|
||||||
n.Policies = append(n.Policies, policy{
|
|
||||||
Name: "EndpointPolicy",
|
|
||||||
Value: []byte(`{"Type": "OutBoundNAT", "ExceptionList": ["` + nwToNat + `"]}`),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApplyDefaultPAPolicy is used to configure a endpoint PA policy in HNS
|
|
||||||
func (n *NetConf) ApplyDefaultPAPolicy(paAddress string) {
|
|
||||||
if n.Policies == nil {
|
|
||||||
n.Policies = make([]policy, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if its already present, leave untouched
|
|
||||||
for i, p := range n.Policies {
|
|
||||||
if !strings.EqualFold(p.Name, "EndpointPolicy") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
paValue, dt, _, _ := jsonparser.Get(p.Value, "PA")
|
|
||||||
if dt == jsonparser.NotExist {
|
|
||||||
continue
|
|
||||||
} else if dt == jsonparser.String && len(paValue) != 0 {
|
|
||||||
// found it, don't override
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n.Policies[i] = policy{
|
|
||||||
Name: "EndpointPolicy",
|
|
||||||
Value: []byte(`{"Type": "PA", "PA": "` + paAddress + `"}`),
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// didn't find the policyArg, add it
|
|
||||||
n.Policies = append(n.Policies, policy{
|
|
||||||
Name: "EndpointPolicy",
|
|
||||||
Value: []byte(`{"Type": "PA", "PA": "` + paAddress + `"}`),
|
|
||||||
})
|
|
||||||
}
|
|
68
vendor/github.com/containernetworking/plugins/pkg/ip/addr_linux.go
generated
vendored
68
vendor/github.com/containernetworking/plugins/pkg/ip/addr_linux.go
generated
vendored
@ -1,68 +0,0 @@
|
|||||||
// 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 ip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
const SETTLE_INTERVAL = 50 * time.Millisecond
|
|
||||||
|
|
||||||
// SettleAddresses waits for all addresses on a link to leave tentative state.
|
|
||||||
// This is particularly useful for ipv6, where all addresses need to do DAD.
|
|
||||||
// There is no easy way to wait for this as an event, so just loop until the
|
|
||||||
// addresses are no longer tentative.
|
|
||||||
// If any addresses are still tentative after timeout seconds, then error.
|
|
||||||
func SettleAddresses(ifName string, timeout int) error {
|
|
||||||
link, err := netlink.LinkByName(ifName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to retrieve link: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
|
|
||||||
for {
|
|
||||||
addrs, err := netlink.AddrList(link, netlink.FAMILY_ALL)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not list addresses: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(addrs) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ok := true
|
|
||||||
for _, addr := range addrs {
|
|
||||||
if addr.Flags&(syscall.IFA_F_TENTATIVE|syscall.IFA_F_DADFAILED) > 0 {
|
|
||||||
ok = false
|
|
||||||
break // Break out of the `range addrs`, not the `for`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if time.Now().After(deadline) {
|
|
||||||
return fmt.Errorf("link %s still has tentative addresses after %d seconds",
|
|
||||||
ifName,
|
|
||||||
timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(SETTLE_INTERVAL)
|
|
||||||
}
|
|
||||||
}
|
|
61
vendor/github.com/containernetworking/plugins/pkg/ip/cidr.go
generated
vendored
61
vendor/github.com/containernetworking/plugins/pkg/ip/cidr.go
generated
vendored
@ -1,61 +0,0 @@
|
|||||||
// Copyright 2015 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 ip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NextIP returns IP incremented by 1
|
|
||||||
func NextIP(ip net.IP) net.IP {
|
|
||||||
i := ipToInt(ip)
|
|
||||||
return intToIP(i.Add(i, big.NewInt(1)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrevIP returns IP decremented by 1
|
|
||||||
func PrevIP(ip net.IP) net.IP {
|
|
||||||
i := ipToInt(ip)
|
|
||||||
return intToIP(i.Sub(i, big.NewInt(1)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cmp compares two IPs, returning the usual ordering:
|
|
||||||
// a < b : -1
|
|
||||||
// a == b : 0
|
|
||||||
// a > b : 1
|
|
||||||
func Cmp(a, b net.IP) int {
|
|
||||||
aa := ipToInt(a)
|
|
||||||
bb := ipToInt(b)
|
|
||||||
return aa.Cmp(bb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ipToInt(ip net.IP) *big.Int {
|
|
||||||
if v := ip.To4(); v != nil {
|
|
||||||
return big.NewInt(0).SetBytes(v)
|
|
||||||
}
|
|
||||||
return big.NewInt(0).SetBytes(ip.To16())
|
|
||||||
}
|
|
||||||
|
|
||||||
func intToIP(i *big.Int) net.IP {
|
|
||||||
return net.IP(i.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Network masks off the host portion of the IP
|
|
||||||
func Network(ipn *net.IPNet) *net.IPNet {
|
|
||||||
return &net.IPNet{
|
|
||||||
IP: ipn.IP.Mask(ipn.Mask),
|
|
||||||
Mask: ipn.Mask,
|
|
||||||
}
|
|
||||||
}
|
|
61
vendor/github.com/containernetworking/plugins/pkg/ip/ipforward_linux.go
generated
vendored
61
vendor/github.com/containernetworking/plugins/pkg/ip/ipforward_linux.go
generated
vendored
@ -1,61 +0,0 @@
|
|||||||
// Copyright 2015 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 ip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
)
|
|
||||||
|
|
||||||
func EnableIP4Forward() error {
|
|
||||||
return echo1("/proc/sys/net/ipv4/ip_forward")
|
|
||||||
}
|
|
||||||
|
|
||||||
func EnableIP6Forward() error {
|
|
||||||
return echo1("/proc/sys/net/ipv6/conf/all/forwarding")
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableForward will enable forwarding for all configured
|
|
||||||
// address families
|
|
||||||
func EnableForward(ips []*current.IPConfig) error {
|
|
||||||
v4 := false
|
|
||||||
v6 := false
|
|
||||||
|
|
||||||
for _, ip := range ips {
|
|
||||||
if ip.Version == "4" && !v4 {
|
|
||||||
if err := EnableIP4Forward(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v4 = true
|
|
||||||
} else if ip.Version == "6" && !v6 {
|
|
||||||
if err := EnableIP6Forward(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
v6 = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func echo1(f string) error {
|
|
||||||
if content, err := ioutil.ReadFile(f); err == nil {
|
|
||||||
if bytes.Equal(bytes.TrimSpace(content), []byte("1")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ioutil.WriteFile(f, []byte("1"), 0644)
|
|
||||||
}
|
|
126
vendor/github.com/containernetworking/plugins/pkg/ip/ipmasq_linux.go
generated
vendored
126
vendor/github.com/containernetworking/plugins/pkg/ip/ipmasq_linux.go
generated
vendored
@ -1,126 +0,0 @@
|
|||||||
// Copyright 2015 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 ip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/coreos/go-iptables/iptables"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SetupIPMasq installs iptables rules to masquerade traffic
|
|
||||||
// coming from ip of ipn and going outside of ipn
|
|
||||||
func SetupIPMasq(ipn *net.IPNet, chain string, comment string) error {
|
|
||||||
isV6 := ipn.IP.To4() == nil
|
|
||||||
|
|
||||||
var ipt *iptables.IPTables
|
|
||||||
var err error
|
|
||||||
var multicastNet string
|
|
||||||
|
|
||||||
if isV6 {
|
|
||||||
ipt, err = iptables.NewWithProtocol(iptables.ProtocolIPv6)
|
|
||||||
multicastNet = "ff00::/8"
|
|
||||||
} else {
|
|
||||||
ipt, err = iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
|
||||||
multicastNet = "224.0.0.0/4"
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to locate iptables: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create chain if doesn't exist
|
|
||||||
exists := false
|
|
||||||
chains, err := ipt.ListChains("nat")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to list chains: %v", err)
|
|
||||||
}
|
|
||||||
for _, ch := range chains {
|
|
||||||
if ch == chain {
|
|
||||||
exists = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
if err = ipt.NewChain("nat", chain); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Packets to this network should not be touched
|
|
||||||
if err := ipt.AppendUnique("nat", chain, "-d", ipn.String(), "-j", "ACCEPT", "-m", "comment", "--comment", comment); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't masquerade multicast - pods should be able to talk to other pods
|
|
||||||
// on the local network via multicast.
|
|
||||||
if err := ipt.AppendUnique("nat", chain, "!", "-d", multicastNet, "-j", "MASQUERADE", "-m", "comment", "--comment", comment); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Packets from the specific IP of this network will hit the chain
|
|
||||||
return ipt.AppendUnique("nat", "POSTROUTING", "-s", ipn.IP.String(), "-j", chain, "-m", "comment", "--comment", comment)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TeardownIPMasq undoes the effects of SetupIPMasq
|
|
||||||
func TeardownIPMasq(ipn *net.IPNet, chain string, comment string) error {
|
|
||||||
isV6 := ipn.IP.To4() == nil
|
|
||||||
|
|
||||||
var ipt *iptables.IPTables
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if isV6 {
|
|
||||||
ipt, err = iptables.NewWithProtocol(iptables.ProtocolIPv6)
|
|
||||||
} else {
|
|
||||||
ipt, err = iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to locate iptables: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ipt.Delete("nat", "POSTROUTING", "-s", ipn.IP.String(), "-j", chain, "-m", "comment", "--comment", comment)
|
|
||||||
if err != nil && !isNotExist(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// for downward compatibility
|
|
||||||
err = ipt.Delete("nat", "POSTROUTING", "-s", ipn.String(), "-j", chain, "-m", "comment", "--comment", comment)
|
|
||||||
if err != nil && !isNotExist(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ipt.ClearChain("nat", chain)
|
|
||||||
if err != nil && !isNotExist(err) {
|
|
||||||
return err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ipt.DeleteChain("nat", chain)
|
|
||||||
if err != nil && !isNotExist(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// isNotExist returnst true if the error is from iptables indicating
|
|
||||||
// that the target does not exist.
|
|
||||||
func isNotExist(err error) bool {
|
|
||||||
e, ok := err.(*iptables.Error)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return e.IsNotExist()
|
|
||||||
}
|
|
288
vendor/github.com/containernetworking/plugins/pkg/ip/link_linux.go
generated
vendored
288
vendor/github.com/containernetworking/plugins/pkg/ip/link_linux.go
generated
vendored
@ -1,288 +0,0 @@
|
|||||||
// Copyright 2015 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 ip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
|
||||||
"github.com/containernetworking/plugins/pkg/utils/hwaddr"
|
|
||||||
"github.com/safchain/ethtool"
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrLinkNotFound = errors.New("link not found")
|
|
||||||
)
|
|
||||||
|
|
||||||
func makeVethPair(name, peer string, mtu int) (netlink.Link, error) {
|
|
||||||
veth := &netlink.Veth{
|
|
||||||
LinkAttrs: netlink.LinkAttrs{
|
|
||||||
Name: name,
|
|
||||||
Flags: net.FlagUp,
|
|
||||||
MTU: mtu,
|
|
||||||
},
|
|
||||||
PeerName: peer,
|
|
||||||
}
|
|
||||||
if err := netlink.LinkAdd(veth); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Re-fetch the link to get its creation-time parameters, e.g. index and mac
|
|
||||||
veth2, err := netlink.LinkByName(name)
|
|
||||||
if err != nil {
|
|
||||||
netlink.LinkDel(veth) // try and clean up the link if possible.
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return veth2, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func peerExists(name string) bool {
|
|
||||||
if _, err := netlink.LinkByName(name); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeVeth(name, vethPeerName string, mtu int) (peerName string, veth netlink.Link, err error) {
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
if vethPeerName != "" {
|
|
||||||
peerName = vethPeerName
|
|
||||||
} else {
|
|
||||||
peerName, err = RandomVethName()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
veth, err = makeVethPair(name, peerName, mtu)
|
|
||||||
switch {
|
|
||||||
case err == nil:
|
|
||||||
return
|
|
||||||
|
|
||||||
case os.IsExist(err):
|
|
||||||
if peerExists(peerName) && vethPeerName == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err = fmt.Errorf("container veth name provided (%v) already exists", name)
|
|
||||||
return
|
|
||||||
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("failed to make veth pair: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// should really never be hit
|
|
||||||
err = fmt.Errorf("failed to find a unique veth name")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomVethName returns string "veth" with random prefix (hashed from entropy)
|
|
||||||
func RandomVethName() (string, error) {
|
|
||||||
entropy := make([]byte, 4)
|
|
||||||
_, err := rand.Reader.Read(entropy)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to generate random veth name: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkManager (recent versions) will ignore veth devices that start with "veth"
|
|
||||||
return fmt.Sprintf("veth%x", entropy), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenameLink(curName, newName string) error {
|
|
||||||
link, err := netlink.LinkByName(curName)
|
|
||||||
if err == nil {
|
|
||||||
err = netlink.LinkSetName(link, newName)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func ifaceFromNetlinkLink(l netlink.Link) net.Interface {
|
|
||||||
a := l.Attrs()
|
|
||||||
return net.Interface{
|
|
||||||
Index: a.Index,
|
|
||||||
MTU: a.MTU,
|
|
||||||
Name: a.Name,
|
|
||||||
HardwareAddr: a.HardwareAddr,
|
|
||||||
Flags: a.Flags,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetupVethWithName sets up a pair of virtual ethernet devices.
|
|
||||||
// Call SetupVethWithName from inside the container netns. It will create both veth
|
|
||||||
// devices and move the host-side veth into the provided hostNS namespace.
|
|
||||||
// hostVethName: If hostVethName is not specified, the host-side veth name will use a random string.
|
|
||||||
// On success, SetupVethWithName returns (hostVeth, containerVeth, nil)
|
|
||||||
func SetupVethWithName(contVethName, hostVethName string, mtu int, hostNS ns.NetNS) (net.Interface, net.Interface, error) {
|
|
||||||
hostVethName, contVeth, err := makeVeth(contVethName, hostVethName, mtu)
|
|
||||||
if err != nil {
|
|
||||||
return net.Interface{}, net.Interface{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = netlink.LinkSetUp(contVeth); err != nil {
|
|
||||||
return net.Interface{}, net.Interface{}, fmt.Errorf("failed to set %q up: %v", contVethName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hostVeth, err := netlink.LinkByName(hostVethName)
|
|
||||||
if err != nil {
|
|
||||||
return net.Interface{}, net.Interface{}, fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
|
|
||||||
return net.Interface{}, net.Interface{}, fmt.Errorf("failed to move veth to host netns: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = hostNS.Do(func(_ ns.NetNS) error {
|
|
||||||
hostVeth, err = netlink.LinkByName(hostVethName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to lookup %q in %q: %v", hostVethName, hostNS.Path(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = netlink.LinkSetUp(hostVeth); err != nil {
|
|
||||||
return fmt.Errorf("failed to set %q up: %v", hostVethName, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return net.Interface{}, net.Interface{}, err
|
|
||||||
}
|
|
||||||
return ifaceFromNetlinkLink(hostVeth), ifaceFromNetlinkLink(contVeth), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetupVeth sets up a pair of virtual ethernet devices.
|
|
||||||
// Call SetupVeth from inside the container netns. It will create both veth
|
|
||||||
// devices and move the host-side veth into the provided hostNS namespace.
|
|
||||||
// On success, SetupVeth returns (hostVeth, containerVeth, nil)
|
|
||||||
func SetupVeth(contVethName string, mtu int, hostNS ns.NetNS) (net.Interface, net.Interface, error) {
|
|
||||||
return SetupVethWithName(contVethName, "", mtu, hostNS)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DelLinkByName removes an interface link.
|
|
||||||
func DelLinkByName(ifName string) error {
|
|
||||||
iface, err := netlink.LinkByName(ifName)
|
|
||||||
if err != nil {
|
|
||||||
if err.Error() == "Link not found" {
|
|
||||||
return ErrLinkNotFound
|
|
||||||
}
|
|
||||||
return fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = netlink.LinkDel(iface); err != nil {
|
|
||||||
return fmt.Errorf("failed to delete %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DelLinkByNameAddr remove an interface and returns its addresses
|
|
||||||
func DelLinkByNameAddr(ifName string) ([]*net.IPNet, error) {
|
|
||||||
iface, err := netlink.LinkByName(ifName)
|
|
||||||
if err != nil {
|
|
||||||
if err != nil && err.Error() == "Link not found" {
|
|
||||||
return nil, ErrLinkNotFound
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
addrs, err := netlink.AddrList(iface, netlink.FAMILY_ALL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get IP addresses for %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = netlink.LinkDel(iface); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to delete %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
out := []*net.IPNet{}
|
|
||||||
for _, addr := range addrs {
|
|
||||||
if addr.IP.IsGlobalUnicast() {
|
|
||||||
out = append(out, addr.IPNet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetHWAddrByIP(ifName string, ip4 net.IP, ip6 net.IP) error {
|
|
||||||
iface, err := netlink.LinkByName(ifName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case ip4 == nil && ip6 == nil:
|
|
||||||
return fmt.Errorf("neither ip4 or ip6 specified")
|
|
||||||
|
|
||||||
case ip4 != nil:
|
|
||||||
{
|
|
||||||
hwAddr, err := hwaddr.GenerateHardwareAddr4(ip4, hwaddr.PrivateMACPrefix)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to generate hardware addr: %v", err)
|
|
||||||
}
|
|
||||||
if err = netlink.LinkSetHardwareAddr(iface, hwAddr); err != nil {
|
|
||||||
return fmt.Errorf("failed to add hardware addr to %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case ip6 != nil:
|
|
||||||
// TODO: IPv6
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVethPeerIfindex returns the veth link object, the peer ifindex of the
|
|
||||||
// veth, or an error. This peer ifindex will only be valid in the peer's
|
|
||||||
// network namespace.
|
|
||||||
func GetVethPeerIfindex(ifName string) (netlink.Link, int, error) {
|
|
||||||
link, err := netlink.LinkByName(ifName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, -1, fmt.Errorf("could not look up %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
if _, ok := link.(*netlink.Veth); !ok {
|
|
||||||
return nil, -1, fmt.Errorf("interface %q was not a veth interface", ifName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// veth supports IFLA_LINK (what vishvananda/netlink calls ParentIndex)
|
|
||||||
// on 4.1 and higher kernels
|
|
||||||
peerIndex := link.Attrs().ParentIndex
|
|
||||||
if peerIndex <= 0 {
|
|
||||||
// Fall back to ethtool for 4.0 and earlier kernels
|
|
||||||
e, err := ethtool.NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return nil, -1, fmt.Errorf("failed to initialize ethtool: %v", err)
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
|
|
||||||
stats, err := e.Stats(link.Attrs().Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, -1, fmt.Errorf("failed to request ethtool stats: %v", err)
|
|
||||||
}
|
|
||||||
n, ok := stats["peer_ifindex"]
|
|
||||||
if !ok {
|
|
||||||
return nil, -1, fmt.Errorf("failed to find 'peer_ifindex' in ethtool stats")
|
|
||||||
}
|
|
||||||
if n > 32767 || n == 0 {
|
|
||||||
return nil, -1, fmt.Errorf("invalid 'peer_ifindex' %d", n)
|
|
||||||
}
|
|
||||||
peerIndex = int(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
return link, peerIndex, nil
|
|
||||||
}
|
|
47
vendor/github.com/containernetworking/plugins/pkg/ip/route_linux.go
generated
vendored
47
vendor/github.com/containernetworking/plugins/pkg/ip/route_linux.go
generated
vendored
@ -1,47 +0,0 @@
|
|||||||
// Copyright 2015-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 ip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddRoute adds a universally-scoped route to a device.
|
|
||||||
func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error {
|
|
||||||
return netlink.RouteAdd(&netlink.Route{
|
|
||||||
LinkIndex: dev.Attrs().Index,
|
|
||||||
Scope: netlink.SCOPE_UNIVERSE,
|
|
||||||
Dst: ipn,
|
|
||||||
Gw: gw,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddHostRoute adds a host-scoped route to a device.
|
|
||||||
func AddHostRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error {
|
|
||||||
return netlink.RouteAdd(&netlink.Route{
|
|
||||||
LinkIndex: dev.Attrs().Index,
|
|
||||||
Scope: netlink.SCOPE_HOST,
|
|
||||||
Dst: ipn,
|
|
||||||
Gw: gw,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDefaultRoute sets the default route on the given gateway.
|
|
||||||
func AddDefaultRoute(gw net.IP, dev netlink.Link) error {
|
|
||||||
_, defNet, _ := net.ParseCIDR("0.0.0.0/0")
|
|
||||||
return AddRoute(defNet, gw, dev)
|
|
||||||
}
|
|
120
vendor/github.com/containernetworking/plugins/pkg/ip/utils_linux.go
generated
vendored
120
vendor/github.com/containernetworking/plugins/pkg/ip/utils_linux.go
generated
vendored
@ -1,120 +0,0 @@
|
|||||||
// +build linux
|
|
||||||
|
|
||||||
// Copyright 2016 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 ip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig) error {
|
|
||||||
|
|
||||||
// Ensure ips
|
|
||||||
for _, ips := range resultIPs {
|
|
||||||
ourAddr := netlink.Addr{IPNet: &ips.Address}
|
|
||||||
match := false
|
|
||||||
|
|
||||||
link, err := netlink.LinkByName(ifName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Cannot find container link %v", ifName)
|
|
||||||
}
|
|
||||||
|
|
||||||
addrList, err := netlink.AddrList(link, netlink.FAMILY_ALL)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Cannot obtain List of IP Addresses")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, addr := range addrList {
|
|
||||||
if addr.Equal(ourAddr) {
|
|
||||||
match = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if match == false {
|
|
||||||
return fmt.Errorf("Failed to match addr %v on interface %v", ourAddr, ifName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the host/prefixlen to just prefix for route lookup.
|
|
||||||
_, ourPrefix, err := net.ParseCIDR(ourAddr.String())
|
|
||||||
|
|
||||||
findGwy := &netlink.Route{Dst: ourPrefix}
|
|
||||||
routeFilter := netlink.RT_FILTER_DST
|
|
||||||
var family int
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case ips.Version == "4":
|
|
||||||
family = netlink.FAMILY_V4
|
|
||||||
case ips.Version == "6":
|
|
||||||
family = netlink.FAMILY_V6
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Invalid IP Version %v for interface %v", ips.Version, ifName)
|
|
||||||
}
|
|
||||||
|
|
||||||
gwy, err := netlink.RouteListFiltered(family, findGwy, routeFilter)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error %v trying to find Gateway %v for interface %v", err, ips.Gateway, ifName)
|
|
||||||
}
|
|
||||||
if gwy == nil {
|
|
||||||
return fmt.Errorf("Failed to find Gateway %v for interface %v", ips.Gateway, ifName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateExpectedRoute(resultRoutes []*types.Route) error {
|
|
||||||
|
|
||||||
// Ensure that each static route in prevResults is found in the routing table
|
|
||||||
for _, route := range resultRoutes {
|
|
||||||
find := &netlink.Route{Dst: &route.Dst, Gw: route.GW}
|
|
||||||
routeFilter := netlink.RT_FILTER_DST | netlink.RT_FILTER_GW
|
|
||||||
var family int
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case route.Dst.IP.To4() != nil:
|
|
||||||
family = netlink.FAMILY_V4
|
|
||||||
// Default route needs Dst set to nil
|
|
||||||
if route.Dst.String() == "0.0.0.0/0" {
|
|
||||||
find = &netlink.Route{Dst: nil, Gw: route.GW}
|
|
||||||
routeFilter = netlink.RT_FILTER_DST
|
|
||||||
}
|
|
||||||
case len(route.Dst.IP) == net.IPv6len:
|
|
||||||
family = netlink.FAMILY_V6
|
|
||||||
// Default route needs Dst set to nil
|
|
||||||
if route.Dst.String() == "::/0" {
|
|
||||||
find = &netlink.Route{Dst: nil, Gw: route.GW}
|
|
||||||
routeFilter = netlink.RT_FILTER_DST
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Invalid static route found %v", route)
|
|
||||||
}
|
|
||||||
|
|
||||||
wasFound, err := netlink.RouteListFiltered(family, find, routeFilter)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Expected Route %v not route table lookup error %v", route, err)
|
|
||||||
}
|
|
||||||
if wasFound == nil {
|
|
||||||
return fmt.Errorf("Expected Route %v not found in routing table", route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
33
vendor/github.com/containernetworking/plugins/pkg/ipam/ipam.go
generated
vendored
33
vendor/github.com/containernetworking/plugins/pkg/ipam/ipam.go
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
// Copyright 2015 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 ipam
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/containernetworking/cni/pkg/invoke"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExecAdd(plugin string, netconf []byte) (types.Result, error) {
|
|
||||||
return invoke.DelegateAdd(context.TODO(), plugin, netconf, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExecCheck(plugin string, netconf []byte) error {
|
|
||||||
return invoke.DelegateCheck(context.TODO(), plugin, netconf, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExecDel(plugin string, netconf []byte) error {
|
|
||||||
return invoke.DelegateDel(context.TODO(), plugin, netconf, nil)
|
|
||||||
}
|
|
121
vendor/github.com/containernetworking/plugins/pkg/ipam/ipam_linux.go
generated
vendored
121
vendor/github.com/containernetworking/plugins/pkg/ipam/ipam_linux.go
generated
vendored
@ -1,121 +0,0 @@
|
|||||||
// Copyright 2015 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 ipam
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
"github.com/containernetworking/plugins/pkg/ip"
|
|
||||||
"github.com/containernetworking/plugins/pkg/utils/sysctl"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
DisableIPv6SysctlTemplate = "net.ipv6.conf.%s.disable_ipv6"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ConfigureIface takes the result of IPAM plugin and
|
|
||||||
// applies to the ifName interface
|
|
||||||
func ConfigureIface(ifName string, res *current.Result) error {
|
|
||||||
if len(res.Interfaces) == 0 {
|
|
||||||
return fmt.Errorf("no interfaces to configure")
|
|
||||||
}
|
|
||||||
|
|
||||||
link, err := netlink.LinkByName(ifName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := netlink.LinkSetUp(link); err != nil {
|
|
||||||
return fmt.Errorf("failed to set %q UP: %v", ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var v4gw, v6gw net.IP
|
|
||||||
var has_enabled_ipv6 bool = false
|
|
||||||
for _, ipc := range res.IPs {
|
|
||||||
if ipc.Interface == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
intIdx := *ipc.Interface
|
|
||||||
if intIdx < 0 || intIdx >= len(res.Interfaces) || res.Interfaces[intIdx].Name != ifName {
|
|
||||||
// IP address is for a different interface
|
|
||||||
return fmt.Errorf("failed to add IP addr %v to %q: invalid interface index", ipc, ifName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure sysctl "disable_ipv6" is 0 if we are about to add
|
|
||||||
// an IPv6 address to the interface
|
|
||||||
if !has_enabled_ipv6 && ipc.Version == "6" {
|
|
||||||
// Enabled IPv6 for loopback "lo" and the interface
|
|
||||||
// being configured
|
|
||||||
for _, iface := range [2]string{"lo", ifName} {
|
|
||||||
ipv6SysctlValueName := fmt.Sprintf(DisableIPv6SysctlTemplate, iface)
|
|
||||||
|
|
||||||
// Read current sysctl value
|
|
||||||
value, err := sysctl.Sysctl(ipv6SysctlValueName)
|
|
||||||
if err != nil || value == "0" {
|
|
||||||
// FIXME: log warning if unable to read sysctl value
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write sysctl to enable IPv6
|
|
||||||
_, err = sysctl.Sysctl(ipv6SysctlValueName, "0")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to enable IPv6 for interface %q (%s=%s): %v", iface, ipv6SysctlValueName, value, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
has_enabled_ipv6 = true
|
|
||||||
}
|
|
||||||
|
|
||||||
addr := &netlink.Addr{IPNet: &ipc.Address, Label: ""}
|
|
||||||
if err = netlink.AddrAdd(link, addr); err != nil {
|
|
||||||
return fmt.Errorf("failed to add IP addr %v to %q: %v", ipc, ifName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gwIsV4 := ipc.Gateway.To4() != nil
|
|
||||||
if gwIsV4 && v4gw == nil {
|
|
||||||
v4gw = ipc.Gateway
|
|
||||||
} else if !gwIsV4 && v6gw == nil {
|
|
||||||
v6gw = ipc.Gateway
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v6gw != nil {
|
|
||||||
ip.SettleAddresses(ifName, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range res.Routes {
|
|
||||||
routeIsV4 := r.Dst.IP.To4() != nil
|
|
||||||
gw := r.GW
|
|
||||||
if gw == nil {
|
|
||||||
if routeIsV4 && v4gw != nil {
|
|
||||||
gw = v4gw
|
|
||||||
} else if !routeIsV4 && v6gw != nil {
|
|
||||||
gw = v6gw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err = ip.AddRoute(&r.Dst, gw, link); err != nil {
|
|
||||||
// we skip over duplicate routes as we assume the first one wins
|
|
||||||
if !os.IsExist(err) {
|
|
||||||
return fmt.Errorf("failed to add route '%v via %v dev %v': %v", r.Dst, gw, ifName, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
26
vendor/github.com/containernetworking/plugins/pkg/utils/buildversion/buildversion.go
generated
vendored
26
vendor/github.com/containernetworking/plugins/pkg/utils/buildversion/buildversion.go
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Buildversion is a destination for the linker trickery so we can auto
|
|
||||||
// set the build-version
|
|
||||||
package buildversion
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// This is overridden in the linker script
|
|
||||||
var BuildVersion = "version unknown"
|
|
||||||
|
|
||||||
func BuildString(pluginName string) string {
|
|
||||||
return fmt.Sprintf("CNI %s plugin %s", pluginName, BuildVersion)
|
|
||||||
}
|
|
63
vendor/github.com/containernetworking/plugins/pkg/utils/hwaddr/hwaddr.go
generated
vendored
63
vendor/github.com/containernetworking/plugins/pkg/utils/hwaddr/hwaddr.go
generated
vendored
@ -1,63 +0,0 @@
|
|||||||
// Copyright 2016 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 hwaddr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ipRelevantByteLen = 4
|
|
||||||
PrivateMACPrefixString = "0a:58"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// private mac prefix safe to use
|
|
||||||
PrivateMACPrefix = []byte{0x0a, 0x58}
|
|
||||||
)
|
|
||||||
|
|
||||||
type SupportIp4OnlyErr struct{ msg string }
|
|
||||||
|
|
||||||
func (e SupportIp4OnlyErr) Error() string { return e.msg }
|
|
||||||
|
|
||||||
type MacParseErr struct{ msg string }
|
|
||||||
|
|
||||||
func (e MacParseErr) Error() string { return e.msg }
|
|
||||||
|
|
||||||
type InvalidPrefixLengthErr struct{ msg string }
|
|
||||||
|
|
||||||
func (e InvalidPrefixLengthErr) Error() string { return e.msg }
|
|
||||||
|
|
||||||
// GenerateHardwareAddr4 generates 48 bit virtual mac addresses based on the IP4 input.
|
|
||||||
func GenerateHardwareAddr4(ip net.IP, prefix []byte) (net.HardwareAddr, error) {
|
|
||||||
switch {
|
|
||||||
|
|
||||||
case ip.To4() == nil:
|
|
||||||
return nil, SupportIp4OnlyErr{msg: "GenerateHardwareAddr4 only supports valid IPv4 address as input"}
|
|
||||||
|
|
||||||
case len(prefix) != len(PrivateMACPrefix):
|
|
||||||
return nil, InvalidPrefixLengthErr{msg: fmt.Sprintf(
|
|
||||||
"Prefix has length %d instead of %d", len(prefix), len(PrivateMACPrefix)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ipByteLen := len(ip)
|
|
||||||
return (net.HardwareAddr)(
|
|
||||||
append(
|
|
||||||
prefix,
|
|
||||||
ip[ipByteLen-ipRelevantByteLen:ipByteLen]...),
|
|
||||||
), nil
|
|
||||||
}
|
|
56
vendor/github.com/containernetworking/plugins/pkg/utils/sysctl/sysctl_linux.go
generated
vendored
56
vendor/github.com/containernetworking/plugins/pkg/utils/sysctl/sysctl_linux.go
generated
vendored
@ -1,56 +0,0 @@
|
|||||||
// Copyright 2016 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
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sysctl provides a method to set/get values from /proc/sys - in linux systems
|
|
||||||
// new interface to set/get values of variables formerly handled by sysctl syscall
|
|
||||||
// If optional `params` have only one string value - this function will
|
|
||||||
// set this value into corresponding sysctl variable
|
|
||||||
func Sysctl(name string, params ...string) (string, error) {
|
|
||||||
if len(params) > 1 {
|
|
||||||
return "", fmt.Errorf("unexcepted additional parameters")
|
|
||||||
} else if len(params) == 1 {
|
|
||||||
return setSysctl(name, params[0])
|
|
||||||
}
|
|
||||||
return getSysctl(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSysctl(name string) (string, error) {
|
|
||||||
fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1))
|
|
||||||
fullName = filepath.Clean(fullName)
|
|
||||||
data, err := ioutil.ReadFile(fullName)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(data[:len(data)-1]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setSysctl(name, value string) (string, error) {
|
|
||||||
fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1))
|
|
||||||
fullName = filepath.Clean(fullName)
|
|
||||||
if err := ioutil.WriteFile(fullName, []byte(value), 0644); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return getSysctl(name)
|
|
||||||
}
|
|
60
vendor/github.com/containernetworking/plugins/pkg/utils/utils.go
generated
vendored
60
vendor/github.com/containernetworking/plugins/pkg/utils/utils.go
generated
vendored
@ -1,60 +0,0 @@
|
|||||||
// Copyright 2016 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 (
|
|
||||||
"crypto/sha512"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
maxChainLength = 28
|
|
||||||
chainPrefix = "CNI-"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FormatChainName generates a chain name to be used
|
|
||||||
// with iptables. Ensures that the generated chain
|
|
||||||
// name is exactly maxChainLength chars in length.
|
|
||||||
func FormatChainName(name string, id string) string {
|
|
||||||
return MustFormatChainNameWithPrefix(name, id, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustFormatChainNameWithPrefix generates a chain name similar
|
|
||||||
// to FormatChainName, but adds a custom prefix between
|
|
||||||
// chainPrefix and unique identifier. Ensures that the
|
|
||||||
// generated chain name is exactly maxChainLength chars in length.
|
|
||||||
// Panics if the given prefix is too long.
|
|
||||||
func MustFormatChainNameWithPrefix(name string, id string, prefix string) string {
|
|
||||||
return MustFormatHashWithPrefix(maxChainLength, chainPrefix+prefix, name+id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatComment returns a comment used for easier
|
|
||||||
// rule identification within iptables.
|
|
||||||
func FormatComment(name string, id string) string {
|
|
||||||
return fmt.Sprintf("name: %q id: %q", name, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
const MaxHashLen = sha512.Size * 2
|
|
||||||
|
|
||||||
// MustFormatHashWithPrefix returns a string of given length that begins with the
|
|
||||||
// given prefix. It is filled with entropy based on the given string toHash.
|
|
||||||
func MustFormatHashWithPrefix(length int, prefix string, toHash string) string {
|
|
||||||
if len(prefix) >= length || length > MaxHashLen {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
|
|
||||||
output := sha512.Sum512([]byte(toHash))
|
|
||||||
return fmt.Sprintf("%s%x", prefix, output)[:length]
|
|
||||||
}
|
|
142
vendor/github.com/containernetworking/plugins/plugins/ipam/host-local/README.md
generated
vendored
142
vendor/github.com/containernetworking/plugins/plugins/ipam/host-local/README.md
generated
vendored
@ -1,142 +0,0 @@
|
|||||||
# host-local IP address management plugin
|
|
||||||
|
|
||||||
host-local IPAM allocates IPv4 and IPv6 addresses out of a specified address range. Optionally,
|
|
||||||
it can include a DNS configuration from a `resolv.conf` file on the host.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
host-local IPAM plugin allocates ip addresses out of a set of address ranges.
|
|
||||||
It stores the state locally on the host filesystem, therefore ensuring uniqueness of IP addresses on a single host.
|
|
||||||
|
|
||||||
The allocator can allocate multiple ranges, and supports sets of multiple (disjoint)
|
|
||||||
subnets. The allocation strategy is loosely round-robin within each range set.
|
|
||||||
|
|
||||||
## Example configurations
|
|
||||||
|
|
||||||
Note that the key `ranges` is a list of range sets. That is to say, the length
|
|
||||||
of the top-level array is the number of addresses returned. The second-level
|
|
||||||
array is a set of subnets to use as a pool of possible addresses.
|
|
||||||
|
|
||||||
This example configuration returns 2 IP addresses.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"ipam": {
|
|
||||||
"type": "host-local",
|
|
||||||
"ranges": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"subnet": "10.10.0.0/16",
|
|
||||||
"rangeStart": "10.10.1.20",
|
|
||||||
"rangeEnd": "10.10.3.50",
|
|
||||||
"gateway": "10.10.0.254"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"subnet": "172.16.5.0/24"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"subnet": "3ffe:ffff:0:01ff::/64",
|
|
||||||
"rangeStart": "3ffe:ffff:0:01ff::0010",
|
|
||||||
"rangeEnd": "3ffe:ffff:0:01ff::0020"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"routes": [
|
|
||||||
{ "dst": "0.0.0.0/0" },
|
|
||||||
{ "dst": "192.168.0.0/16", "gw": "10.10.5.1" },
|
|
||||||
{ "dst": "3ffe:ffff:0:01ff::1/64" }
|
|
||||||
],
|
|
||||||
"dataDir": "/run/my-orchestrator/container-ipam-state"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Previous versions of the `host-local` allocator did not support the `ranges`
|
|
||||||
property, and instead expected a single range on the top level. This is
|
|
||||||
deprecated but still supported.
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"ipam": {
|
|
||||||
"type": "host-local",
|
|
||||||
"subnet": "3ffe:ffff:0:01ff::/64",
|
|
||||||
"rangeStart": "3ffe:ffff:0:01ff::0010",
|
|
||||||
"rangeEnd": "3ffe:ffff:0:01ff::0020",
|
|
||||||
"routes": [
|
|
||||||
{ "dst": "3ffe:ffff:0:01ff::1/64" }
|
|
||||||
],
|
|
||||||
"resolvConf": "/etc/resolv.conf"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
We can test it out on the command-line:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ echo '{ "cniVersion": "0.3.1", "name": "examplenet", "ipam": { "type": "host-local", "ranges": [ [{"subnet": "203.0.113.0/24"}], [{"subnet": "2001:db8:1::/64"}]], "dataDir": "/tmp/cni-example" } }' | CNI_COMMAND=ADD CNI_CONTAINERID=example CNI_NETNS=/dev/null CNI_IFNAME=dummy0 CNI_PATH=. ./host-local
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"ips": [
|
|
||||||
{
|
|
||||||
"version": "4",
|
|
||||||
"address": "203.0.113.2/24",
|
|
||||||
"gateway": "203.0.113.1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": "6",
|
|
||||||
"address": "2001:db8:1::2/64",
|
|
||||||
"gateway": "2001:db8:1::1"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dns": {}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Network configuration reference
|
|
||||||
|
|
||||||
* `type` (string, required): "host-local".
|
|
||||||
* `routes` (string, optional): list of routes to add to the container namespace. Each route is a dictionary with "dst" and optional "gw" fields. If "gw" is omitted, value of "gateway" will be used.
|
|
||||||
* `resolvConf` (string, optional): Path to a `resolv.conf` on the host to parse and return as the DNS configuration
|
|
||||||
* `dataDir` (string, optional): Path to a directory to use for maintaining state, e.g. which IPs have been allocated to which containers
|
|
||||||
* `ranges`, (array, required, nonempty) an array of arrays of range objects:
|
|
||||||
* `subnet` (string, required): CIDR block to allocate out of.
|
|
||||||
* `rangeStart` (string, optional): IP inside of "subnet" from which to start allocating addresses. Defaults to ".2" IP inside of the "subnet" block.
|
|
||||||
* `rangeEnd` (string, optional): IP inside of "subnet" with which to end allocating addresses. Defaults to ".254" IP inside of the "subnet" block for ipv4, ".255" for IPv6
|
|
||||||
* `gateway` (string, optional): IP inside of "subnet" to designate as the gateway. Defaults to ".1" IP inside of the "subnet" block.
|
|
||||||
|
|
||||||
Older versions of the `host-local` plugin did not support the `ranges` array. Instead,
|
|
||||||
all the properties in the `range` object were top-level. This is still supported but deprecated.
|
|
||||||
|
|
||||||
## Supported arguments
|
|
||||||
The following [CNI_ARGS](https://github.com/containernetworking/cni/blob/master/SPEC.md#parameters) are supported:
|
|
||||||
|
|
||||||
* `ip`: request a specific IP address from a subnet.
|
|
||||||
|
|
||||||
The following [args conventions](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md) are supported:
|
|
||||||
|
|
||||||
* `ips` (array of strings): A list of custom IPs to attempt to allocate
|
|
||||||
|
|
||||||
The following [Capability Args](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md) are supported:
|
|
||||||
|
|
||||||
* `ipRanges`: The exact same as the `ranges` array - a list of address pools
|
|
||||||
|
|
||||||
### Custom IP allocation
|
|
||||||
For every requested custom IP, the `host-local` allocator will request that IP
|
|
||||||
if it falls within one of the `range` objects. Thus it is possible to specify
|
|
||||||
multiple custom IPs and multiple ranges.
|
|
||||||
|
|
||||||
If any requested IPs cannot be reserved, either because they are already in use
|
|
||||||
or are not part of a specified range, the plugin will return an error.
|
|
||||||
|
|
||||||
|
|
||||||
## Files
|
|
||||||
|
|
||||||
Allocated IP addresses are stored as files in `/var/lib/cni/networks/$NETWORK_NAME`.
|
|
||||||
The path can be customized with the `dataDir` option listed above. Environments
|
|
||||||
where IPs are released automatically on reboot (e.g. running containers are not
|
|
||||||
restored) may wish to specify `/var/run/cni` or another tmpfs mounted directory
|
|
||||||
instead.
|
|
@ -1,228 +0,0 @@
|
|||||||
// Copyright 2015 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 allocator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
"github.com/containernetworking/plugins/pkg/ip"
|
|
||||||
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IPAllocator struct {
|
|
||||||
rangeset *RangeSet
|
|
||||||
store backend.Store
|
|
||||||
rangeID string // Used for tracking last reserved ip
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIPAllocator(s *RangeSet, store backend.Store, id int) *IPAllocator {
|
|
||||||
return &IPAllocator{
|
|
||||||
rangeset: s,
|
|
||||||
store: store,
|
|
||||||
rangeID: strconv.Itoa(id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get allocates an IP
|
|
||||||
func (a *IPAllocator) Get(id string, ifname string, requestedIP net.IP) (*current.IPConfig, error) {
|
|
||||||
a.store.Lock()
|
|
||||||
defer a.store.Unlock()
|
|
||||||
|
|
||||||
var reservedIP *net.IPNet
|
|
||||||
var gw net.IP
|
|
||||||
|
|
||||||
if requestedIP != nil {
|
|
||||||
if err := canonicalizeIP(&requestedIP); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := a.rangeset.RangeFor(requestedIP)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if requestedIP.Equal(r.Gateway) {
|
|
||||||
return nil, fmt.Errorf("requested ip %s is subnet's gateway", requestedIP.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
reserved, err := a.store.Reserve(id, ifname, requestedIP, a.rangeID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !reserved {
|
|
||||||
return nil, fmt.Errorf("requested IP address %s is not available in range set %s", requestedIP, a.rangeset.String())
|
|
||||||
}
|
|
||||||
reservedIP = &net.IPNet{IP: requestedIP, Mask: r.Subnet.Mask}
|
|
||||||
gw = r.Gateway
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// try to get allocated IPs for this given id, if exists, just return error
|
|
||||||
// because duplicate allocation is not allowed in SPEC
|
|
||||||
// https://github.com/containernetworking/cni/blob/master/SPEC.md
|
|
||||||
allocatedIPs := a.store.GetByID(id, ifname)
|
|
||||||
for _, allocatedIP := range allocatedIPs {
|
|
||||||
// check whether the existing IP belong to this range set
|
|
||||||
if _, err := a.rangeset.RangeFor(allocatedIP); err == nil {
|
|
||||||
return nil, fmt.Errorf("%s has been allocated to %s, duplicate allocation is not allowed", allocatedIP.String(), id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iter, err := a.GetIter()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
reservedIP, gw = iter.Next()
|
|
||||||
if reservedIP == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
reserved, err := a.store.Reserve(id, ifname, reservedIP.IP, a.rangeID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if reserved {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if reservedIP == nil {
|
|
||||||
return nil, fmt.Errorf("no IP addresses available in range set: %s", a.rangeset.String())
|
|
||||||
}
|
|
||||||
version := "4"
|
|
||||||
if reservedIP.IP.To4() == nil {
|
|
||||||
version = "6"
|
|
||||||
}
|
|
||||||
|
|
||||||
return ¤t.IPConfig{
|
|
||||||
Version: version,
|
|
||||||
Address: *reservedIP,
|
|
||||||
Gateway: gw,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release clears all IPs allocated for the container with given ID
|
|
||||||
func (a *IPAllocator) Release(id string, ifname string) error {
|
|
||||||
a.store.Lock()
|
|
||||||
defer a.store.Unlock()
|
|
||||||
|
|
||||||
return a.store.ReleaseByID(id, ifname)
|
|
||||||
}
|
|
||||||
|
|
||||||
type RangeIter struct {
|
|
||||||
rangeset *RangeSet
|
|
||||||
|
|
||||||
// The current range id
|
|
||||||
rangeIdx int
|
|
||||||
|
|
||||||
// Our current position
|
|
||||||
cur net.IP
|
|
||||||
|
|
||||||
// The IP and range index where we started iterating; if we hit this again, we're done.
|
|
||||||
startIP net.IP
|
|
||||||
startRange int
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIter encapsulates the strategy for this allocator.
|
|
||||||
// We use a round-robin strategy, attempting to evenly use the whole set.
|
|
||||||
// More specifically, a crash-looping container will not see the same IP until
|
|
||||||
// the entire range has been run through.
|
|
||||||
// We may wish to consider avoiding recently-released IPs in the future.
|
|
||||||
func (a *IPAllocator) GetIter() (*RangeIter, error) {
|
|
||||||
iter := RangeIter{
|
|
||||||
rangeset: a.rangeset,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round-robin by trying to allocate from the last reserved IP + 1
|
|
||||||
startFromLastReservedIP := false
|
|
||||||
|
|
||||||
// We might get a last reserved IP that is wrong if the range indexes changed.
|
|
||||||
// This is not critical, we just lose round-robin this one time.
|
|
||||||
lastReservedIP, err := a.store.LastReservedIP(a.rangeID)
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
log.Printf("Error retrieving last reserved ip: %v", err)
|
|
||||||
} else if lastReservedIP != nil {
|
|
||||||
startFromLastReservedIP = a.rangeset.Contains(lastReservedIP)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the range in the set with this IP
|
|
||||||
if startFromLastReservedIP {
|
|
||||||
for i, r := range *a.rangeset {
|
|
||||||
if r.Contains(lastReservedIP) {
|
|
||||||
iter.rangeIdx = i
|
|
||||||
iter.startRange = i
|
|
||||||
|
|
||||||
// We advance the cursor on every Next(), so the first call
|
|
||||||
// to next() will return lastReservedIP + 1
|
|
||||||
iter.cur = lastReservedIP
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
iter.rangeIdx = 0
|
|
||||||
iter.startRange = 0
|
|
||||||
iter.startIP = (*a.rangeset)[0].RangeStart
|
|
||||||
}
|
|
||||||
return &iter, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next returns the next IP, its mask, and its gateway. Returns nil
|
|
||||||
// if the iterator has been exhausted
|
|
||||||
func (i *RangeIter) Next() (*net.IPNet, net.IP) {
|
|
||||||
r := (*i.rangeset)[i.rangeIdx]
|
|
||||||
|
|
||||||
// If this is the first time iterating and we're not starting in the middle
|
|
||||||
// of the range, then start at rangeStart, which is inclusive
|
|
||||||
if i.cur == nil {
|
|
||||||
i.cur = r.RangeStart
|
|
||||||
i.startIP = i.cur
|
|
||||||
if i.cur.Equal(r.Gateway) {
|
|
||||||
return i.Next()
|
|
||||||
}
|
|
||||||
return &net.IPNet{IP: i.cur, Mask: r.Subnet.Mask}, r.Gateway
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we've reached the end of this range, we need to advance the range
|
|
||||||
// RangeEnd is inclusive as well
|
|
||||||
if i.cur.Equal(r.RangeEnd) {
|
|
||||||
i.rangeIdx += 1
|
|
||||||
i.rangeIdx %= len(*i.rangeset)
|
|
||||||
r = (*i.rangeset)[i.rangeIdx]
|
|
||||||
|
|
||||||
i.cur = r.RangeStart
|
|
||||||
} else {
|
|
||||||
i.cur = ip.NextIP(i.cur)
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.startIP == nil {
|
|
||||||
i.startIP = i.cur
|
|
||||||
} else if i.rangeIdx == i.startRange && i.cur.Equal(i.startIP) {
|
|
||||||
// IF we've looped back to where we started, give up
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.cur.Equal(r.Gateway) {
|
|
||||||
return i.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
return &net.IPNet{IP: i.cur, Mask: r.Subnet.Mask}, r.Gateway
|
|
||||||
}
|
|
@ -1,160 +0,0 @@
|
|||||||
// Copyright 2015 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 allocator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/types/020"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The top-level network config - IPAM plugins are passed the full configuration
|
|
||||||
// of the calling plugin, not just the IPAM section.
|
|
||||||
type Net struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
CNIVersion string `json:"cniVersion"`
|
|
||||||
IPAM *IPAMConfig `json:"ipam"`
|
|
||||||
RuntimeConfig struct { // The capability arg
|
|
||||||
IPRanges []RangeSet `json:"ipRanges,omitempty"`
|
|
||||||
} `json:"runtimeConfig,omitempty"`
|
|
||||||
Args *struct {
|
|
||||||
A *IPAMArgs `json:"cni"`
|
|
||||||
} `json:"args"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPAMConfig represents the IP related network configuration.
|
|
||||||
// This nests Range because we initially only supported a single
|
|
||||||
// range directly, and wish to preserve backwards compatability
|
|
||||||
type IPAMConfig struct {
|
|
||||||
*Range
|
|
||||||
Name string
|
|
||||||
Type string `json:"type"`
|
|
||||||
Routes []*types.Route `json:"routes"`
|
|
||||||
DataDir string `json:"dataDir"`
|
|
||||||
ResolvConf string `json:"resolvConf"`
|
|
||||||
Ranges []RangeSet `json:"ranges"`
|
|
||||||
IPArgs []net.IP `json:"-"` // Requested IPs from CNI_ARGS and args
|
|
||||||
}
|
|
||||||
|
|
||||||
type IPAMEnvArgs struct {
|
|
||||||
types.CommonArgs
|
|
||||||
IP net.IP `json:"ip,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type IPAMArgs struct {
|
|
||||||
IPs []net.IP `json:"ips"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RangeSet []Range
|
|
||||||
|
|
||||||
type Range struct {
|
|
||||||
RangeStart net.IP `json:"rangeStart,omitempty"` // The first ip, inclusive
|
|
||||||
RangeEnd net.IP `json:"rangeEnd,omitempty"` // The last ip, inclusive
|
|
||||||
Subnet types.IPNet `json:"subnet"`
|
|
||||||
Gateway net.IP `json:"gateway,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewIPAMConfig creates a NetworkConfig from the given network name.
|
|
||||||
func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
|
||||||
n := Net{}
|
|
||||||
if err := json.Unmarshal(bytes, &n); err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.IPAM == nil {
|
|
||||||
return nil, "", fmt.Errorf("IPAM config missing 'ipam' key")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse custom IP from both env args *and* the top-level args config
|
|
||||||
if envArgs != "" {
|
|
||||||
e := IPAMEnvArgs{}
|
|
||||||
err := types.LoadArgs(envArgs, &e)
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.IP != nil {
|
|
||||||
n.IPAM.IPArgs = []net.IP{e.IP}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Args != nil && n.Args.A != nil && len(n.Args.A.IPs) != 0 {
|
|
||||||
n.IPAM.IPArgs = append(n.IPAM.IPArgs, n.Args.A.IPs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx := range n.IPAM.IPArgs {
|
|
||||||
if err := canonicalizeIP(&n.IPAM.IPArgs[idx]); err != nil {
|
|
||||||
return nil, "", fmt.Errorf("cannot understand ip: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a single range (old-style config) is specified, prepend it to
|
|
||||||
// the Ranges array
|
|
||||||
if n.IPAM.Range != nil && n.IPAM.Range.Subnet.IP != nil {
|
|
||||||
n.IPAM.Ranges = append([]RangeSet{{*n.IPAM.Range}}, n.IPAM.Ranges...)
|
|
||||||
}
|
|
||||||
n.IPAM.Range = nil
|
|
||||||
|
|
||||||
// If a range is supplied as a runtime config, prepend it to the Ranges
|
|
||||||
if len(n.RuntimeConfig.IPRanges) > 0 {
|
|
||||||
n.IPAM.Ranges = append(n.RuntimeConfig.IPRanges, n.IPAM.Ranges...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(n.IPAM.Ranges) == 0 {
|
|
||||||
return nil, "", fmt.Errorf("no IP ranges specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate all ranges
|
|
||||||
numV4 := 0
|
|
||||||
numV6 := 0
|
|
||||||
for i := range n.IPAM.Ranges {
|
|
||||||
if err := n.IPAM.Ranges[i].Canonicalize(); err != nil {
|
|
||||||
return nil, "", fmt.Errorf("invalid range set %d: %s", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.IPAM.Ranges[i][0].RangeStart.To4() != nil {
|
|
||||||
numV4++
|
|
||||||
} else {
|
|
||||||
numV6++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CNI spec 0.2.0 and below supported only one v4 and v6 address
|
|
||||||
if numV4 > 1 || numV6 > 1 {
|
|
||||||
for _, v := range types020.SupportedVersions {
|
|
||||||
if n.CNIVersion == v {
|
|
||||||
return nil, "", fmt.Errorf("CNI version %v does not support more than 1 address per family", n.CNIVersion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for overlaps
|
|
||||||
l := len(n.IPAM.Ranges)
|
|
||||||
for i, p1 := range n.IPAM.Ranges[:l-1] {
|
|
||||||
for j, p2 := range n.IPAM.Ranges[i+1:] {
|
|
||||||
if p1.Overlaps(&p2) {
|
|
||||||
return nil, "", fmt.Errorf("range set %d overlaps with %d", i, (i + j + 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy net name into IPAM so not to drag Net struct around
|
|
||||||
n.IPAM.Name = n.Name
|
|
||||||
|
|
||||||
return n.IPAM, n.CNIVersion, nil
|
|
||||||
}
|
|
@ -1,166 +0,0 @@
|
|||||||
// 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 allocator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/plugins/pkg/ip"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Canonicalize takes a given range and ensures that all information is consistent,
|
|
||||||
// filling out Start, End, and Gateway with sane values if missing
|
|
||||||
func (r *Range) Canonicalize() error {
|
|
||||||
if err := canonicalizeIP(&r.Subnet.IP); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't create an allocator for a network with no addresses, eg
|
|
||||||
// a /32 or /31
|
|
||||||
ones, masklen := r.Subnet.Mask.Size()
|
|
||||||
if ones > masklen-2 {
|
|
||||||
return fmt.Errorf("Network %s too small to allocate from", (*net.IPNet)(&r.Subnet).String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(r.Subnet.IP) != len(r.Subnet.Mask) {
|
|
||||||
return fmt.Errorf("IPNet IP and Mask version mismatch")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure Subnet IP is the network address, not some other address
|
|
||||||
networkIP := r.Subnet.IP.Mask(r.Subnet.Mask)
|
|
||||||
if !r.Subnet.IP.Equal(networkIP) {
|
|
||||||
return fmt.Errorf("Network has host bits set. For a subnet mask of length %d the network address is %s", ones, networkIP.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the gateway is nil, claim .1
|
|
||||||
if r.Gateway == nil {
|
|
||||||
r.Gateway = ip.NextIP(r.Subnet.IP)
|
|
||||||
} else {
|
|
||||||
if err := canonicalizeIP(&r.Gateway); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RangeStart: If specified, make sure it's sane (inside the subnet),
|
|
||||||
// otherwise use the first free IP (i.e. .1) - this will conflict with the
|
|
||||||
// gateway but we skip it in the iterator
|
|
||||||
if r.RangeStart != nil {
|
|
||||||
if err := canonicalizeIP(&r.RangeStart); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !r.Contains(r.RangeStart) {
|
|
||||||
return fmt.Errorf("RangeStart %s not in network %s", r.RangeStart.String(), (*net.IPNet)(&r.Subnet).String())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r.RangeStart = ip.NextIP(r.Subnet.IP)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RangeEnd: If specified, verify sanity. Otherwise, add a sensible default
|
|
||||||
// (e.g. for a /24: .254 if IPv4, ::255 if IPv6)
|
|
||||||
if r.RangeEnd != nil {
|
|
||||||
if err := canonicalizeIP(&r.RangeEnd); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !r.Contains(r.RangeEnd) {
|
|
||||||
return fmt.Errorf("RangeEnd %s not in network %s", r.RangeEnd.String(), (*net.IPNet)(&r.Subnet).String())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r.RangeEnd = lastIP(r.Subnet)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValidIP checks if a given ip is a valid, allocatable address in a given Range
|
|
||||||
func (r *Range) Contains(addr net.IP) bool {
|
|
||||||
if err := canonicalizeIP(&addr); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
subnet := (net.IPNet)(r.Subnet)
|
|
||||||
|
|
||||||
// Not the same address family
|
|
||||||
if len(addr) != len(r.Subnet.IP) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not in network
|
|
||||||
if !subnet.Contains(addr) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// We ignore nils here so we can use this function as we initialize the range.
|
|
||||||
if r.RangeStart != nil {
|
|
||||||
// Before the range start
|
|
||||||
if ip.Cmp(addr, r.RangeStart) < 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.RangeEnd != nil {
|
|
||||||
if ip.Cmp(addr, r.RangeEnd) > 0 {
|
|
||||||
// After the range end
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overlaps returns true if there is any overlap between ranges
|
|
||||||
func (r *Range) Overlaps(r1 *Range) bool {
|
|
||||||
// different familes
|
|
||||||
if len(r.RangeStart) != len(r1.RangeStart) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.Contains(r1.RangeStart) ||
|
|
||||||
r.Contains(r1.RangeEnd) ||
|
|
||||||
r1.Contains(r.RangeStart) ||
|
|
||||||
r1.Contains(r.RangeEnd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Range) String() string {
|
|
||||||
return fmt.Sprintf("%s-%s", r.RangeStart.String(), r.RangeEnd.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// canonicalizeIP makes sure a provided ip is in standard form
|
|
||||||
func canonicalizeIP(ip *net.IP) error {
|
|
||||||
if ip.To4() != nil {
|
|
||||||
*ip = ip.To4()
|
|
||||||
return nil
|
|
||||||
} else if ip.To16() != nil {
|
|
||||||
*ip = ip.To16()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("IP %s not v4 nor v6", *ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the last IP of a subnet, excluding the broadcast if IPv4
|
|
||||||
func lastIP(subnet types.IPNet) net.IP {
|
|
||||||
var end net.IP
|
|
||||||
for i := 0; i < len(subnet.IP); i++ {
|
|
||||||
end = append(end, subnet.IP[i]|^subnet.Mask[i])
|
|
||||||
}
|
|
||||||
if subnet.IP.To4() != nil {
|
|
||||||
end[3]--
|
|
||||||
}
|
|
||||||
|
|
||||||
return end
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
// 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 allocator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Contains returns true if any range in this set contains an IP
|
|
||||||
func (s *RangeSet) Contains(addr net.IP) bool {
|
|
||||||
r, _ := s.RangeFor(addr)
|
|
||||||
return r != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RangeFor finds the range that contains an IP, or nil if not found
|
|
||||||
func (s *RangeSet) RangeFor(addr net.IP) (*Range, error) {
|
|
||||||
if err := canonicalizeIP(&addr); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range *s {
|
|
||||||
if r.Contains(addr) {
|
|
||||||
return &r, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("%s not in range set %s", addr.String(), s.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overlaps returns true if any ranges in any set overlap with this one
|
|
||||||
func (s *RangeSet) Overlaps(p1 *RangeSet) bool {
|
|
||||||
for _, r := range *s {
|
|
||||||
for _, r1 := range *p1 {
|
|
||||||
if r.Overlaps(&r1) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canonicalize ensures the RangeSet is in a standard form, and detects any
|
|
||||||
// invalid input. Call Range.Canonicalize() on every Range in the set
|
|
||||||
func (s *RangeSet) Canonicalize() error {
|
|
||||||
if len(*s) == 0 {
|
|
||||||
return fmt.Errorf("empty range set")
|
|
||||||
}
|
|
||||||
|
|
||||||
fam := 0
|
|
||||||
for i := range *s {
|
|
||||||
if err := (*s)[i].Canonicalize(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if i == 0 {
|
|
||||||
fam = len((*s)[i].RangeStart)
|
|
||||||
} else {
|
|
||||||
if fam != len((*s)[i].RangeStart) {
|
|
||||||
return fmt.Errorf("mixed address families")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure none of the ranges in the set overlap
|
|
||||||
l := len(*s)
|
|
||||||
for i, r1 := range (*s)[:l-1] {
|
|
||||||
for _, r2 := range (*s)[i+1:] {
|
|
||||||
if r1.Overlaps(&r2) {
|
|
||||||
return fmt.Errorf("subnets %s and %s overlap", r1.String(), r2.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *RangeSet) String() string {
|
|
||||||
out := []string{}
|
|
||||||
for _, r := range *s {
|
|
||||||
out = append(out, r.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join(out, ",")
|
|
||||||
}
|
|
@ -1,209 +0,0 @@
|
|||||||
// Copyright 2015 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 disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend"
|
|
||||||
)
|
|
||||||
|
|
||||||
const lastIPFilePrefix = "last_reserved_ip."
|
|
||||||
const LineBreak = "\r\n"
|
|
||||||
|
|
||||||
var defaultDataDir = "/var/lib/cni/networks"
|
|
||||||
|
|
||||||
// Store is a simple disk-backed store that creates one file per IP
|
|
||||||
// address in a given directory. The contents of the file are the container ID.
|
|
||||||
type Store struct {
|
|
||||||
*FileLock
|
|
||||||
dataDir string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store implements the Store interface
|
|
||||||
var _ backend.Store = &Store{}
|
|
||||||
|
|
||||||
func New(network, dataDir string) (*Store, error) {
|
|
||||||
if dataDir == "" {
|
|
||||||
dataDir = defaultDataDir
|
|
||||||
}
|
|
||||||
dir := filepath.Join(dataDir, network)
|
|
||||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lk, err := NewFileLock(dir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Store{lk, dir}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) Reserve(id string, ifname string, ip net.IP, rangeID string) (bool, error) {
|
|
||||||
fname := GetEscapedPath(s.dataDir, ip.String())
|
|
||||||
|
|
||||||
f, err := os.OpenFile(fname, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0644)
|
|
||||||
if os.IsExist(err) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if _, err := f.WriteString(strings.TrimSpace(id) + LineBreak + ifname); err != nil {
|
|
||||||
f.Close()
|
|
||||||
os.Remove(f.Name())
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if err := f.Close(); err != nil {
|
|
||||||
os.Remove(f.Name())
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
// store the reserved ip in lastIPFile
|
|
||||||
ipfile := GetEscapedPath(s.dataDir, lastIPFilePrefix+rangeID)
|
|
||||||
err = ioutil.WriteFile(ipfile, []byte(ip.String()), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LastReservedIP returns the last reserved IP if exists
|
|
||||||
func (s *Store) LastReservedIP(rangeID string) (net.IP, error) {
|
|
||||||
ipfile := GetEscapedPath(s.dataDir, lastIPFilePrefix+rangeID)
|
|
||||||
data, err := ioutil.ReadFile(ipfile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return net.ParseIP(string(data)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) Release(ip net.IP) error {
|
|
||||||
return os.Remove(GetEscapedPath(s.dataDir, ip.String()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) FindByKey(id string, ifname string, match string) (bool, error) {
|
|
||||||
found := false
|
|
||||||
|
|
||||||
err := filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil || info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(string(data)) == match {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return found, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) FindByID(id string, ifname string) bool {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
found := false
|
|
||||||
match := strings.TrimSpace(id) + LineBreak + ifname
|
|
||||||
found, err := s.FindByKey(id, ifname, match)
|
|
||||||
|
|
||||||
// Match anything created by this id
|
|
||||||
if !found && err == nil {
|
|
||||||
match := strings.TrimSpace(id)
|
|
||||||
found, err = s.FindByKey(id, ifname, match)
|
|
||||||
}
|
|
||||||
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) ReleaseByKey(id string, ifname string, match string) (bool, error) {
|
|
||||||
found := false
|
|
||||||
err := filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil || info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(string(data)) == match {
|
|
||||||
if err := os.Remove(path); err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return found, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// N.B. This function eats errors to be tolerant and
|
|
||||||
// release as much as possible
|
|
||||||
func (s *Store) ReleaseByID(id string, ifname string) error {
|
|
||||||
found := false
|
|
||||||
match := strings.TrimSpace(id) + LineBreak + ifname
|
|
||||||
found, err := s.ReleaseByKey(id, ifname, match)
|
|
||||||
|
|
||||||
// For backwards compatibility, look for files written by a previous version
|
|
||||||
if !found && err == nil {
|
|
||||||
match := strings.TrimSpace(id)
|
|
||||||
found, err = s.ReleaseByKey(id, ifname, match)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetByID returns the IPs which have been allocated to the specific ID
|
|
||||||
func (s *Store) GetByID(id string, ifname string) []net.IP {
|
|
||||||
var ips []net.IP
|
|
||||||
|
|
||||||
match := strings.TrimSpace(id) + LineBreak + ifname
|
|
||||||
// matchOld for backwards compatibility
|
|
||||||
matchOld := strings.TrimSpace(id)
|
|
||||||
|
|
||||||
// walk through all ips in this network to get the ones which belong to a specific ID
|
|
||||||
_ = filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil || info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(string(data)) == match || strings.TrimSpace(string(data)) == matchOld {
|
|
||||||
_, ipString := filepath.Split(path)
|
|
||||||
if ip := net.ParseIP(ipString); ip != nil {
|
|
||||||
ips = append(ips, ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return ips
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetEscapedPath(dataDir string, fname string) string {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
fname = strings.Replace(fname, ":", "_", -1)
|
|
||||||
}
|
|
||||||
return filepath.Join(dataDir, fname)
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
// Copyright 2015 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 disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/alexflint/go-filemutex"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileLock wraps os.File to be used as a lock using flock
|
|
||||||
type FileLock struct {
|
|
||||||
f *filemutex.FileMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFileLock opens file/dir at path and returns unlocked FileLock object
|
|
||||||
func NewFileLock(lockPath string) (*FileLock, error) {
|
|
||||||
fi, err := os.Stat(lockPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi.IsDir() {
|
|
||||||
lockPath = path.Join(lockPath, "lock")
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := filemutex.New(lockPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &FileLock{f}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *FileLock) Close() error {
|
|
||||||
return l.f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock acquires an exclusive lock
|
|
||||||
func (l *FileLock) Lock() error {
|
|
||||||
return l.f.Lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock releases the lock
|
|
||||||
func (l *FileLock) Unlock() error {
|
|
||||||
return l.f.Unlock()
|
|
||||||
}
|
|
28
vendor/github.com/containernetworking/plugins/plugins/ipam/host-local/backend/store.go
generated
vendored
28
vendor/github.com/containernetworking/plugins/plugins/ipam/host-local/backend/store.go
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
// Copyright 2015 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 backend
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
type Store interface {
|
|
||||||
Lock() error
|
|
||||||
Unlock() error
|
|
||||||
Close() error
|
|
||||||
Reserve(id string, ifname string, ip net.IP, rangeID string) (bool, error)
|
|
||||||
LastReservedIP(rangeID string) (net.IP, error)
|
|
||||||
Release(ip net.IP) error
|
|
||||||
ReleaseByID(id string, ifname string) error
|
|
||||||
GetByID(id string, ifname string) []net.IP
|
|
||||||
}
|
|
64
vendor/github.com/containernetworking/plugins/plugins/ipam/host-local/dns.go
generated
vendored
64
vendor/github.com/containernetworking/plugins/plugins/ipam/host-local/dns.go
generated
vendored
@ -1,64 +0,0 @@
|
|||||||
// Copyright 2016 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 hostlocal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// parseResolvConf parses an existing resolv.conf in to a DNS struct
|
|
||||||
func parseResolvConf(filename string) (*types.DNS, error) {
|
|
||||||
fp, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dns := types.DNS{}
|
|
||||||
scanner := bufio.NewScanner(fp)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
|
|
||||||
// Skip comments, empty lines
|
|
||||||
if len(line) == 0 || line[0] == '#' || line[0] == ';' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fields := strings.Fields(line)
|
|
||||||
if len(fields) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch fields[0] {
|
|
||||||
case "nameserver":
|
|
||||||
dns.Nameservers = append(dns.Nameservers, fields[1])
|
|
||||||
case "domain":
|
|
||||||
dns.Domain = fields[1]
|
|
||||||
case "search":
|
|
||||||
dns.Search = append(dns.Search, fields[1:]...)
|
|
||||||
case "options":
|
|
||||||
dns.Options = append(dns.Options, fields[1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &dns, nil
|
|
||||||
}
|
|
173
vendor/github.com/containernetworking/plugins/plugins/ipam/host-local/main.go
generated
vendored
173
vendor/github.com/containernetworking/plugins/plugins/ipam/host-local/main.go
generated
vendored
@ -1,173 +0,0 @@
|
|||||||
// Copyright 2015 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 hostlocal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
|
||||||
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
|
|
||||||
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/disk"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Main() {
|
|
||||||
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, bv.BuildString("host-local"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadNetConf(bytes []byte) (*types.NetConf, string, error) {
|
|
||||||
n := &types.NetConf{}
|
|
||||||
if err := json.Unmarshal(bytes, n); err != nil {
|
|
||||||
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
|
|
||||||
}
|
|
||||||
return n, n.CNIVersion, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdCheck(args *skel.CmdArgs) error {
|
|
||||||
|
|
||||||
ipamConf, _, err := allocator.LoadIPAMConfig(args.StdinData, args.Args)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look to see if there is at least one IP address allocated to the container
|
|
||||||
// in the data dir, irrespective of what that address actually is
|
|
||||||
store, err := disk.New(ipamConf.Name, ipamConf.DataDir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer store.Close()
|
|
||||||
|
|
||||||
containerIpFound := store.FindByID(args.ContainerID, args.IfName)
|
|
||||||
if containerIpFound == false {
|
|
||||||
return fmt.Errorf("host-local: Failed to find address added by container %v", args.ContainerID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
|
||||||
ipamConf, confVersion, err := allocator.LoadIPAMConfig(args.StdinData, args.Args)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := ¤t.Result{}
|
|
||||||
|
|
||||||
if ipamConf.ResolvConf != "" {
|
|
||||||
dns, err := parseResolvConf(ipamConf.ResolvConf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
result.DNS = *dns
|
|
||||||
}
|
|
||||||
|
|
||||||
store, err := disk.New(ipamConf.Name, ipamConf.DataDir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer store.Close()
|
|
||||||
|
|
||||||
// Keep the allocators we used, so we can release all IPs if an error
|
|
||||||
// occurs after we start allocating
|
|
||||||
allocs := []*allocator.IPAllocator{}
|
|
||||||
|
|
||||||
// Store all requested IPs in a map, so we can easily remove ones we use
|
|
||||||
// and error if some remain
|
|
||||||
requestedIPs := map[string]net.IP{} //net.IP cannot be a key
|
|
||||||
|
|
||||||
for _, ip := range ipamConf.IPArgs {
|
|
||||||
requestedIPs[ip.String()] = ip
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx, rangeset := range ipamConf.Ranges {
|
|
||||||
allocator := allocator.NewIPAllocator(&rangeset, store, idx)
|
|
||||||
|
|
||||||
// Check to see if there are any custom IPs requested in this range.
|
|
||||||
var requestedIP net.IP
|
|
||||||
for k, ip := range requestedIPs {
|
|
||||||
if rangeset.Contains(ip) {
|
|
||||||
requestedIP = ip
|
|
||||||
delete(requestedIPs, k)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ipConf, err := allocator.Get(args.ContainerID, args.IfName, requestedIP)
|
|
||||||
if err != nil {
|
|
||||||
// Deallocate all already allocated IPs
|
|
||||||
for _, alloc := range allocs {
|
|
||||||
_ = alloc.Release(args.ContainerID, args.IfName)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("failed to allocate for range %d: %v", idx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
allocs = append(allocs, allocator)
|
|
||||||
|
|
||||||
result.IPs = append(result.IPs, ipConf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If an IP was requested that wasn't fulfilled, fail
|
|
||||||
if len(requestedIPs) != 0 {
|
|
||||||
for _, alloc := range allocs {
|
|
||||||
_ = alloc.Release(args.ContainerID, args.IfName)
|
|
||||||
}
|
|
||||||
errstr := "failed to allocate all requested IPs:"
|
|
||||||
for _, ip := range requestedIPs {
|
|
||||||
errstr = errstr + " " + ip.String()
|
|
||||||
}
|
|
||||||
return fmt.Errorf(errstr)
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Routes = ipamConf.Routes
|
|
||||||
|
|
||||||
return types.PrintResult(result, confVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdDel(args *skel.CmdArgs) error {
|
|
||||||
ipamConf, _, err := allocator.LoadIPAMConfig(args.StdinData, args.Args)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
store, err := disk.New(ipamConf.Name, ipamConf.DataDir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer store.Close()
|
|
||||||
|
|
||||||
// Loop through all ranges, releasing all IPs, even if an error occurs
|
|
||||||
var errors []string
|
|
||||||
for idx, rangeset := range ipamConf.Ranges {
|
|
||||||
ipAllocator := allocator.NewIPAllocator(&rangeset, store, idx)
|
|
||||||
|
|
||||||
err := ipAllocator.Release(args.ContainerID, args.IfName)
|
|
||||||
if err != nil {
|
|
||||||
errors = append(errors, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors != nil {
|
|
||||||
return fmt.Errorf(strings.Join(errors, ";"))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
59
vendor/github.com/containernetworking/plugins/plugins/main/bridge/README.md
generated
vendored
59
vendor/github.com/containernetworking/plugins/plugins/main/bridge/README.md
generated
vendored
@ -1,59 +0,0 @@
|
|||||||
# bridge plugin
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
With bridge plugin, all containers (on the same host) are plugged into a bridge (virtual switch) that resides in the host network namespace.
|
|
||||||
The containers receive one end of the veth pair with the other end connected to the bridge.
|
|
||||||
An IP address is only assigned to one end of the veth pair -- one residing in the container.
|
|
||||||
The bridge itself can also be assigned an IP address, turning it into a gateway for the containers.
|
|
||||||
Alternatively, the bridge can function purely in L2 mode and would need to be bridged to the host network interface (if other than container-to-container communication on the same host is desired).
|
|
||||||
|
|
||||||
The network configuration specifies the name of the bridge to be used.
|
|
||||||
If the bridge is missing, the plugin will create one on first use and, if gateway mode is used, assign it an IP that was returned by IPAM plugin via the gateway field.
|
|
||||||
|
|
||||||
## Example configuration
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"name": "mynet",
|
|
||||||
"type": "bridge",
|
|
||||||
"bridge": "mynet0",
|
|
||||||
"isDefaultGateway": true,
|
|
||||||
"forceAddress": false,
|
|
||||||
"ipMasq": true,
|
|
||||||
"hairpinMode": true,
|
|
||||||
"ipam": {
|
|
||||||
"type": "host-local",
|
|
||||||
"subnet": "10.10.0.0/16"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example L2-only configuration
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"cniVersion": "0.3.1",
|
|
||||||
"name": "mynet",
|
|
||||||
"type": "bridge",
|
|
||||||
"bridge": "mynet0",
|
|
||||||
"ipam": {}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Network configuration reference
|
|
||||||
|
|
||||||
* `name` (string, required): the name of the network.
|
|
||||||
* `type` (string, required): "bridge".
|
|
||||||
* `bridge` (string, optional): name of the bridge to use/create. Defaults to "cni0".
|
|
||||||
* `isGateway` (boolean, optional): assign an IP address to the bridge. Defaults to false.
|
|
||||||
* `isDefaultGateway` (boolean, optional): Sets isGateway to true and makes the assigned IP the default route. Defaults to false.
|
|
||||||
* `forceAddress` (boolean, optional): Indicates if a new IP address should be set if the previous value has been changed. Defaults to false.
|
|
||||||
* `ipMasq` (boolean, optional): set up IP Masquerade on the host for traffic originating from this network and destined outside of it. Defaults to false.
|
|
||||||
* `mtu` (integer, optional): explicitly set MTU to the specified value. Defaults to the value chosen by the kernel.
|
|
||||||
* `hairpinMode` (boolean, optional): set hairpin mode for interfaces on the bridge. Defaults to false.
|
|
||||||
* `ipam` (dictionary, required): IPAM configuration to be used for this network. For L2-only network, create empty dictionary.
|
|
||||||
* `promiscMode` (boolean, optional): set promiscuous mode on the bridge. Defaults to false.
|
|
||||||
* `vlan` (int, optional): assign VLAN tag. Defaults to none.
|
|
||||||
|
|
||||||
*Note:* The VLAN parameter configures the VLAN tag on the host end of the veth and also enables the vlan_filtering feature on the bridge interface.
|
|
||||||
|
|
||||||
*Note:* To configure uplink for L2 network you need to allow the vlan on the uplink interface by using the following command ``` bridge vlan add vid VLAN_ID dev DEV```.
|
|
861
vendor/github.com/containernetworking/plugins/plugins/main/bridge/bridge.go
generated
vendored
861
vendor/github.com/containernetworking/plugins/plugins/main/bridge/bridge.go
generated
vendored
@ -1,861 +0,0 @@
|
|||||||
// Copyright 2014 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 bridge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/j-keck/arping"
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
|
||||||
"github.com/containernetworking/plugins/pkg/ip"
|
|
||||||
"github.com/containernetworking/plugins/pkg/ipam"
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
|
||||||
"github.com/containernetworking/plugins/pkg/utils"
|
|
||||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
|
||||||
)
|
|
||||||
|
|
||||||
// For testcases to force an error after IPAM has been performed
|
|
||||||
var debugPostIPAMError error
|
|
||||||
|
|
||||||
const defaultBrName = "cni0"
|
|
||||||
|
|
||||||
type NetConf struct {
|
|
||||||
types.NetConf
|
|
||||||
BrName string `json:"bridge"`
|
|
||||||
IsGW bool `json:"isGateway"`
|
|
||||||
IsDefaultGW bool `json:"isDefaultGateway"`
|
|
||||||
ForceAddress bool `json:"forceAddress"`
|
|
||||||
IPMasq bool `json:"ipMasq"`
|
|
||||||
MTU int `json:"mtu"`
|
|
||||||
HairpinMode bool `json:"hairpinMode"`
|
|
||||||
PromiscMode bool `json:"promiscMode"`
|
|
||||||
Vlan int `json:"vlan"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type gwInfo struct {
|
|
||||||
gws []net.IPNet
|
|
||||||
family int
|
|
||||||
defaultRouteFound bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// this ensures that main runs only on main thread (thread group leader).
|
|
||||||
// since namespace ops (unshare, setns) are done for a single thread, we
|
|
||||||
// must ensure that the goroutine does not jump from OS thread to thread
|
|
||||||
runtime.LockOSThread()
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadNetConf(bytes []byte) (*NetConf, string, error) {
|
|
||||||
n := &NetConf{
|
|
||||||
BrName: defaultBrName,
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(bytes, n); err != nil {
|
|
||||||
return nil, "", fmt.Errorf("failed to load netconf: %v", err)
|
|
||||||
}
|
|
||||||
return n, n.CNIVersion, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// calcGateways processes the results from the IPAM plugin and does the
|
|
||||||
// following for each IP family:
|
|
||||||
// - Calculates and compiles a list of gateway addresses
|
|
||||||
// - Adds a default route if needed
|
|
||||||
func calcGateways(result *current.Result, n *NetConf) (*gwInfo, *gwInfo, error) {
|
|
||||||
|
|
||||||
gwsV4 := &gwInfo{}
|
|
||||||
gwsV6 := &gwInfo{}
|
|
||||||
|
|
||||||
for _, ipc := range result.IPs {
|
|
||||||
|
|
||||||
// Determine if this config is IPv4 or IPv6
|
|
||||||
var gws *gwInfo
|
|
||||||
defaultNet := &net.IPNet{}
|
|
||||||
switch {
|
|
||||||
case ipc.Address.IP.To4() != nil:
|
|
||||||
gws = gwsV4
|
|
||||||
gws.family = netlink.FAMILY_V4
|
|
||||||
defaultNet.IP = net.IPv4zero
|
|
||||||
case len(ipc.Address.IP) == net.IPv6len:
|
|
||||||
gws = gwsV6
|
|
||||||
gws.family = netlink.FAMILY_V6
|
|
||||||
defaultNet.IP = net.IPv6zero
|
|
||||||
default:
|
|
||||||
return nil, nil, fmt.Errorf("Unknown IP object: %v", ipc)
|
|
||||||
}
|
|
||||||
defaultNet.Mask = net.IPMask(defaultNet.IP)
|
|
||||||
|
|
||||||
// All IPs currently refer to the container interface
|
|
||||||
ipc.Interface = current.Int(2)
|
|
||||||
|
|
||||||
// If not provided, calculate the gateway address corresponding
|
|
||||||
// to the selected IP address
|
|
||||||
if ipc.Gateway == nil && n.IsGW {
|
|
||||||
ipc.Gateway = calcGatewayIP(&ipc.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a default route for this family using the current
|
|
||||||
// gateway address if necessary.
|
|
||||||
if n.IsDefaultGW && !gws.defaultRouteFound {
|
|
||||||
for _, route := range result.Routes {
|
|
||||||
if route.GW != nil && defaultNet.String() == route.Dst.String() {
|
|
||||||
gws.defaultRouteFound = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !gws.defaultRouteFound {
|
|
||||||
result.Routes = append(
|
|
||||||
result.Routes,
|
|
||||||
&types.Route{Dst: *defaultNet, GW: ipc.Gateway},
|
|
||||||
)
|
|
||||||
gws.defaultRouteFound = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append this gateway address to the list of gateways
|
|
||||||
if n.IsGW {
|
|
||||||
gw := net.IPNet{
|
|
||||||
IP: ipc.Gateway,
|
|
||||||
Mask: ipc.Address.Mask,
|
|
||||||
}
|
|
||||||
gws.gws = append(gws.gws, gw)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return gwsV4, gwsV6, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureAddr(br netlink.Link, family int, ipn *net.IPNet, forceAddress bool) error {
|
|
||||||
addrs, err := netlink.AddrList(br, family)
|
|
||||||
if err != nil && err != syscall.ENOENT {
|
|
||||||
return fmt.Errorf("could not get list of IP addresses: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ipnStr := ipn.String()
|
|
||||||
for _, a := range addrs {
|
|
||||||
|
|
||||||
// string comp is actually easiest for doing IPNet comps
|
|
||||||
if a.IPNet.String() == ipnStr {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiple IPv6 addresses are allowed on the bridge if the
|
|
||||||
// corresponding subnets do not overlap. For IPv4 or for
|
|
||||||
// overlapping IPv6 subnets, reconfigure the IP address if
|
|
||||||
// forceAddress is true, otherwise throw an error.
|
|
||||||
if family == netlink.FAMILY_V4 || a.IPNet.Contains(ipn.IP) || ipn.Contains(a.IPNet.IP) {
|
|
||||||
if forceAddress {
|
|
||||||
if err = deleteAddr(br, a.IPNet); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("%q already has an IP address different from %v", br.Attrs().Name, ipnStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addr := &netlink.Addr{IPNet: ipn, Label: ""}
|
|
||||||
if err := netlink.AddrAdd(br, addr); err != nil && err != syscall.EEXIST {
|
|
||||||
return fmt.Errorf("could not add IP address to %q: %v", br.Attrs().Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the bridge's MAC to itself. Otherwise, the bridge will take the
|
|
||||||
// lowest-numbered mac on the bridge, and will change as ifs churn
|
|
||||||
if err := netlink.LinkSetHardwareAddr(br, br.Attrs().HardwareAddr); err != nil {
|
|
||||||
return fmt.Errorf("could not set bridge's mac: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteAddr(br netlink.Link, ipn *net.IPNet) error {
|
|
||||||
addr := &netlink.Addr{IPNet: ipn, Label: ""}
|
|
||||||
|
|
||||||
if err := netlink.AddrDel(br, addr); err != nil {
|
|
||||||
return fmt.Errorf("could not remove IP address from %q: %v", br.Attrs().Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bridgeByName(name string) (*netlink.Bridge, error) {
|
|
||||||
l, err := netlink.LinkByName(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not lookup %q: %v", name, err)
|
|
||||||
}
|
|
||||||
br, ok := l.(*netlink.Bridge)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("%q already exists but is not a bridge", name)
|
|
||||||
}
|
|
||||||
return br, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureBridge(brName string, mtu int, promiscMode, vlanFiltering bool) (*netlink.Bridge, error) {
|
|
||||||
br := &netlink.Bridge{
|
|
||||||
LinkAttrs: netlink.LinkAttrs{
|
|
||||||
Name: brName,
|
|
||||||
MTU: mtu,
|
|
||||||
// Let kernel use default txqueuelen; leaving it unset
|
|
||||||
// means 0, and a zero-length TX queue messes up FIFO
|
|
||||||
// traffic shapers which use TX queue length as the
|
|
||||||
// default packet limit
|
|
||||||
TxQLen: -1,
|
|
||||||
},
|
|
||||||
VlanFiltering: &vlanFiltering,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := netlink.LinkAdd(br)
|
|
||||||
if err != nil && err != syscall.EEXIST {
|
|
||||||
return nil, fmt.Errorf("could not add %q: %v", brName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if promiscMode {
|
|
||||||
if err := netlink.SetPromiscOn(br); err != nil {
|
|
||||||
return nil, fmt.Errorf("could not set promiscuous mode on %q: %v", brName, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-fetch link to read all attributes and if it already existed,
|
|
||||||
// ensure it's really a bridge with similar configuration
|
|
||||||
br, err = bridgeByName(brName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := netlink.LinkSetUp(br); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return br, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureVlanInterface(br *netlink.Bridge, vlanId int) (netlink.Link, error) {
|
|
||||||
name := fmt.Sprintf("%s.%d", br.Name, vlanId)
|
|
||||||
|
|
||||||
brGatewayVeth, err := netlink.LinkByName(name)
|
|
||||||
if err != nil {
|
|
||||||
if err.Error() != "Link not found" {
|
|
||||||
return nil, fmt.Errorf("failed to find interface %q: %v", name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hostNS, err := ns.GetCurrentNS()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("faild to find host namespace: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, brGatewayIface, err := setupVeth(hostNS, br, name, br.MTU, false, vlanId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("faild to create vlan gateway %q: %v", name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
brGatewayVeth, err = netlink.LinkByName(brGatewayIface.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to lookup %q: %v", brGatewayIface.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return brGatewayVeth, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupVeth(netns ns.NetNS, br *netlink.Bridge, ifName string, mtu int, hairpinMode bool, vlanID int) (*current.Interface, *current.Interface, error) {
|
|
||||||
contIface := ¤t.Interface{}
|
|
||||||
hostIface := ¤t.Interface{}
|
|
||||||
|
|
||||||
err := netns.Do(func(hostNS ns.NetNS) error {
|
|
||||||
// create the veth pair in the container and move host end into host netns
|
|
||||||
hostVeth, containerVeth, err := ip.SetupVeth(ifName, mtu, hostNS)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
contIface.Name = containerVeth.Name
|
|
||||||
contIface.Mac = containerVeth.HardwareAddr.String()
|
|
||||||
contIface.Sandbox = netns.Path()
|
|
||||||
hostIface.Name = hostVeth.Name
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to lookup hostVeth again as its index has changed during ns move
|
|
||||||
hostVeth, err := netlink.LinkByName(hostIface.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to lookup %q: %v", hostIface.Name, err)
|
|
||||||
}
|
|
||||||
hostIface.Mac = hostVeth.Attrs().HardwareAddr.String()
|
|
||||||
|
|
||||||
// connect host veth end to the bridge
|
|
||||||
if err := netlink.LinkSetMaster(hostVeth, br); err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to connect %q to bridge %v: %v", hostVeth.Attrs().Name, br.Attrs().Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// set hairpin mode
|
|
||||||
if err = netlink.LinkSetHairpin(hostVeth, hairpinMode); err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to setup hairpin mode for %v: %v", hostVeth.Attrs().Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if vlanID != 0 {
|
|
||||||
err = netlink.BridgeVlanAdd(hostVeth, uint16(vlanID), true, true, false, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to setup vlan tag on interface %q: %v", hostIface.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostIface, contIface, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func calcGatewayIP(ipn *net.IPNet) net.IP {
|
|
||||||
nid := ipn.IP.Mask(ipn.Mask)
|
|
||||||
return ip.NextIP(nid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupBridge(n *NetConf) (*netlink.Bridge, *current.Interface, error) {
|
|
||||||
vlanFiltering := false
|
|
||||||
if n.Vlan != 0 {
|
|
||||||
vlanFiltering = true
|
|
||||||
}
|
|
||||||
// create bridge if necessary
|
|
||||||
br, err := ensureBridge(n.BrName, n.MTU, n.PromiscMode, vlanFiltering)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to create bridge %q: %v", n.BrName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return br, ¤t.Interface{
|
|
||||||
Name: br.Attrs().Name,
|
|
||||||
Mac: br.Attrs().HardwareAddr.String(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// disableIPV6DAD disables IPv6 Duplicate Address Detection (DAD)
|
|
||||||
// for an interface, if the interface does not support enhanced_dad.
|
|
||||||
// We do this because interfaces with hairpin mode will see their own DAD packets
|
|
||||||
func disableIPV6DAD(ifName string) error {
|
|
||||||
// ehanced_dad sends a nonce with the DAD packets, so that we can safely
|
|
||||||
// ignore ourselves
|
|
||||||
enh, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/enhanced_dad", ifName))
|
|
||||||
if err == nil && string(enh) == "1\n" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
f := fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/accept_dad", ifName)
|
|
||||||
return ioutil.WriteFile(f, []byte("0"), 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
func enableIPForward(family int) error {
|
|
||||||
if family == netlink.FAMILY_V4 {
|
|
||||||
return ip.EnableIP4Forward()
|
|
||||||
}
|
|
||||||
return ip.EnableIP6Forward()
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
|
||||||
var success bool = false
|
|
||||||
|
|
||||||
n, cniVersion, err := loadNetConf(args.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
isLayer3 := n.IPAM.Type != ""
|
|
||||||
|
|
||||||
if n.IsDefaultGW {
|
|
||||||
n.IsGW = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.HairpinMode && n.PromiscMode {
|
|
||||||
return fmt.Errorf("cannot set hairpin mode and promiscous mode at the same time.")
|
|
||||||
}
|
|
||||||
|
|
||||||
br, brInterface, err := setupBridge(n)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
netns, err := ns.GetNS(args.Netns)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
|
|
||||||
}
|
|
||||||
defer netns.Close()
|
|
||||||
|
|
||||||
hostInterface, containerInterface, err := setupVeth(netns, br, args.IfName, n.MTU, n.HairpinMode, n.Vlan)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assume L2 interface only
|
|
||||||
result := ¤t.Result{CNIVersion: cniVersion, Interfaces: []*current.Interface{brInterface, hostInterface, containerInterface}}
|
|
||||||
|
|
||||||
if isLayer3 {
|
|
||||||
// run the IPAM plugin and get back the config to apply
|
|
||||||
r, err := ipam.ExecAdd(n.IPAM.Type, args.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// release IP in case of failure
|
|
||||||
defer func() {
|
|
||||||
if !success {
|
|
||||||
ipam.ExecDel(n.IPAM.Type, args.StdinData)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Convert whatever the IPAM result was into the current Result type
|
|
||||||
ipamResult, err := current.NewResultFromResult(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result.IPs = ipamResult.IPs
|
|
||||||
result.Routes = ipamResult.Routes
|
|
||||||
|
|
||||||
if len(result.IPs) == 0 {
|
|
||||||
return errors.New("IPAM plugin returned missing IP config")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gather gateway information for each IP family
|
|
||||||
gwsV4, gwsV6, err := calcGateways(result, n)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the container hardware address and IP address(es)
|
|
||||||
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
|
|
||||||
// bridge. Hairpin mode causes echos of neighbor solicitation
|
|
||||||
// packets, which causes DAD failures.
|
|
||||||
for _, ipc := range result.IPs {
|
|
||||||
if ipc.Version == "6" && (n.HairpinMode || n.PromiscMode) {
|
|
||||||
if err := disableIPV6DAD(args.IfName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the IP to the interface
|
|
||||||
if err := ipam.ConfigureIface(args.IfName, result); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a gratuitous arp
|
|
||||||
for _, ipc := range result.IPs {
|
|
||||||
if ipc.Version == "4" {
|
|
||||||
_ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.IsGW {
|
|
||||||
var firstV4Addr net.IP
|
|
||||||
var vlanInterface *current.Interface
|
|
||||||
// Set the IP address(es) on the bridge and enable forwarding
|
|
||||||
for _, gws := range []*gwInfo{gwsV4, gwsV6} {
|
|
||||||
for _, gw := range gws.gws {
|
|
||||||
if gw.IP.To4() != nil && firstV4Addr == nil {
|
|
||||||
firstV4Addr = gw.IP
|
|
||||||
}
|
|
||||||
if n.Vlan != 0 {
|
|
||||||
vlanIface, err := ensureVlanInterface(br, n.Vlan)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create vlan interface: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if vlanInterface == nil {
|
|
||||||
vlanInterface = ¤t.Interface{Name: vlanIface.Attrs().Name,
|
|
||||||
Mac: vlanIface.Attrs().HardwareAddr.String()}
|
|
||||||
result.Interfaces = append(result.Interfaces, vlanInterface)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ensureAddr(vlanIface, gws.family, &gw, n.ForceAddress)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to set vlan interface for bridge with addr: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = ensureAddr(br, gws.family, &gw, n.ForceAddress)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to set bridge addr: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if gws.gws != nil {
|
|
||||||
if err = enableIPForward(gws.family); err != nil {
|
|
||||||
return fmt.Errorf("failed to enable forwarding: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.IPMasq {
|
|
||||||
chain := utils.FormatChainName(n.Name, args.ContainerID)
|
|
||||||
comment := utils.FormatComment(n.Name, args.ContainerID)
|
|
||||||
for _, ipc := range result.IPs {
|
|
||||||
if err = ip.SetupIPMasq(&ipc.Address, chain, comment); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refetch the bridge since its MAC address may change when the first
|
|
||||||
// veth is added or after its IP address is set
|
|
||||||
br, err = bridgeByName(n.BrName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
brInterface.Mac = br.Attrs().HardwareAddr.String()
|
|
||||||
|
|
||||||
result.DNS = n.DNS
|
|
||||||
|
|
||||||
// Return an error requested by testcases, if any
|
|
||||||
if debugPostIPAMError != nil {
|
|
||||||
return debugPostIPAMError
|
|
||||||
}
|
|
||||||
|
|
||||||
success = true
|
|
||||||
|
|
||||||
return types.PrintResult(result, cniVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdDel(args *skel.CmdArgs) error {
|
|
||||||
n, _, err := loadNetConf(args.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
isLayer3 := n.IPAM.Type != ""
|
|
||||||
|
|
||||||
if isLayer3 {
|
|
||||||
if err := ipam.ExecDel(n.IPAM.Type, args.StdinData); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.Netns == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// There is a netns so try to clean up. Delete can be called multiple times
|
|
||||||
// so don't return an error if the device is already removed.
|
|
||||||
// If the device isn't there then don't try to clean up IP masq either.
|
|
||||||
var ipnets []*net.IPNet
|
|
||||||
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
|
||||||
var err error
|
|
||||||
ipnets, err = ip.DelLinkByNameAddr(args.IfName)
|
|
||||||
if err != nil && err == ip.ErrLinkNotFound {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if isLayer3 && n.IPMasq {
|
|
||||||
chain := utils.FormatChainName(n.Name, args.ContainerID)
|
|
||||||
comment := utils.FormatComment(n.Name, args.ContainerID)
|
|
||||||
for _, ipn := range ipnets {
|
|
||||||
if err := ip.TeardownIPMasq(ipn, chain, comment); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func Main() {
|
|
||||||
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, bv.BuildString("bridge"))
|
|
||||||
}
|
|
||||||
|
|
||||||
type cniBridgeIf struct {
|
|
||||||
Name string
|
|
||||||
ifIndex int
|
|
||||||
peerIndex int
|
|
||||||
masterIndex int
|
|
||||||
found bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateInterface(intf current.Interface, expectInSb bool) (cniBridgeIf, netlink.Link, error) {
|
|
||||||
|
|
||||||
ifFound := cniBridgeIf{found: false}
|
|
||||||
if intf.Name == "" {
|
|
||||||
return ifFound, nil, fmt.Errorf("Interface name missing ")
|
|
||||||
}
|
|
||||||
|
|
||||||
link, err := netlink.LinkByName(intf.Name)
|
|
||||||
if err != nil {
|
|
||||||
return ifFound, nil, fmt.Errorf("Interface name %s not found", intf.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if expectInSb {
|
|
||||||
if intf.Sandbox == "" {
|
|
||||||
return ifFound, nil, fmt.Errorf("Interface %s is expected to be in a sandbox", intf.Name)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if intf.Sandbox != "" {
|
|
||||||
return ifFound, nil, fmt.Errorf("Interface %s should not be in sandbox", intf.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ifFound, link, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateCniBrInterface(intf current.Interface, n *NetConf) (cniBridgeIf, error) {
|
|
||||||
|
|
||||||
brFound, link, err := validateInterface(intf, false)
|
|
||||||
if err != nil {
|
|
||||||
return brFound, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, isBridge := link.(*netlink.Bridge)
|
|
||||||
if !isBridge {
|
|
||||||
return brFound, fmt.Errorf("Interface %s does not have link type of bridge", intf.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if intf.Mac != "" {
|
|
||||||
if intf.Mac != link.Attrs().HardwareAddr.String() {
|
|
||||||
return brFound, fmt.Errorf("Bridge interface %s Mac doesn't match: %s", intf.Name, intf.Mac)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
linkPromisc := link.Attrs().Promisc != 0
|
|
||||||
if linkPromisc != n.PromiscMode {
|
|
||||||
return brFound, fmt.Errorf("Bridge interface %s configured Promisc Mode %v doesn't match current state: %v ",
|
|
||||||
intf.Name, n.PromiscMode, linkPromisc)
|
|
||||||
}
|
|
||||||
|
|
||||||
brFound.found = true
|
|
||||||
brFound.Name = link.Attrs().Name
|
|
||||||
brFound.ifIndex = link.Attrs().Index
|
|
||||||
brFound.masterIndex = link.Attrs().MasterIndex
|
|
||||||
|
|
||||||
return brFound, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateCniVethInterface(intf *current.Interface, brIf cniBridgeIf, contIf cniBridgeIf) (cniBridgeIf, error) {
|
|
||||||
|
|
||||||
vethFound, link, err := validateInterface(*intf, false)
|
|
||||||
if err != nil {
|
|
||||||
return vethFound, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, isVeth := link.(*netlink.Veth)
|
|
||||||
if !isVeth {
|
|
||||||
// just skip it, it's not what CNI created
|
|
||||||
return vethFound, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, vethFound.peerIndex, err = ip.GetVethPeerIfindex(link.Attrs().Name)
|
|
||||||
if err != nil {
|
|
||||||
return vethFound, fmt.Errorf("Unable to obtain veth peer index for veth %s", link.Attrs().Name)
|
|
||||||
}
|
|
||||||
vethFound.ifIndex = link.Attrs().Index
|
|
||||||
vethFound.masterIndex = link.Attrs().MasterIndex
|
|
||||||
|
|
||||||
if vethFound.ifIndex != contIf.peerIndex {
|
|
||||||
return vethFound, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if contIf.ifIndex != vethFound.peerIndex {
|
|
||||||
return vethFound, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if vethFound.masterIndex != brIf.ifIndex {
|
|
||||||
return vethFound, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if intf.Mac != "" {
|
|
||||||
if intf.Mac != link.Attrs().HardwareAddr.String() {
|
|
||||||
return vethFound, fmt.Errorf("Interface %s Mac doesn't match: %s not found", intf.Name, intf.Mac)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vethFound.found = true
|
|
||||||
vethFound.Name = link.Attrs().Name
|
|
||||||
|
|
||||||
return vethFound, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateCniContainerInterface(intf current.Interface) (cniBridgeIf, error) {
|
|
||||||
|
|
||||||
vethFound, link, err := validateInterface(intf, true)
|
|
||||||
if err != nil {
|
|
||||||
return vethFound, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, isVeth := link.(*netlink.Veth)
|
|
||||||
if !isVeth {
|
|
||||||
return vethFound, fmt.Errorf("Error: Container interface %s not of type veth", link.Attrs().Name)
|
|
||||||
}
|
|
||||||
_, vethFound.peerIndex, err = ip.GetVethPeerIfindex(link.Attrs().Name)
|
|
||||||
if err != nil {
|
|
||||||
return vethFound, fmt.Errorf("Unable to obtain veth peer index for veth %s", link.Attrs().Name)
|
|
||||||
}
|
|
||||||
vethFound.ifIndex = link.Attrs().Index
|
|
||||||
|
|
||||||
if intf.Mac != "" {
|
|
||||||
if intf.Mac != link.Attrs().HardwareAddr.String() {
|
|
||||||
return vethFound, fmt.Errorf("Interface %s Mac %s doesn't match container Mac: %s", intf.Name, intf.Mac, link.Attrs().HardwareAddr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vethFound.found = true
|
|
||||||
vethFound.Name = link.Attrs().Name
|
|
||||||
|
|
||||||
return vethFound, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdCheck(args *skel.CmdArgs) error {
|
|
||||||
|
|
||||||
n, _, err := loadNetConf(args.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
netns, err := ns.GetNS(args.Netns)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
|
|
||||||
}
|
|
||||||
defer netns.Close()
|
|
||||||
|
|
||||||
// run the IPAM plugin and get back the config to apply
|
|
||||||
err = ipam.ExecCheck(n.IPAM.Type, args.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse previous result.
|
|
||||||
if n.NetConf.RawPrevResult == nil {
|
|
||||||
return fmt.Errorf("Required prevResult missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := version.ParsePrevResult(&n.NetConf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := current.NewResultFromResult(n.PrevResult)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var errLink error
|
|
||||||
var contCNI, vethCNI cniBridgeIf
|
|
||||||
var brMap, contMap current.Interface
|
|
||||||
|
|
||||||
// Find interfaces for names whe know, CNI Bridge and container
|
|
||||||
for _, intf := range result.Interfaces {
|
|
||||||
if n.BrName == intf.Name {
|
|
||||||
brMap = *intf
|
|
||||||
continue
|
|
||||||
} else if args.IfName == intf.Name {
|
|
||||||
if args.Netns == intf.Sandbox {
|
|
||||||
contMap = *intf
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
brCNI, err := validateCniBrInterface(brMap, n)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// The namespace must be the same as what was configured
|
|
||||||
if args.Netns != contMap.Sandbox {
|
|
||||||
return fmt.Errorf("Sandbox in prevResult %s doesn't match configured netns: %s",
|
|
||||||
contMap.Sandbox, args.Netns)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check interface against values found in the container
|
|
||||||
if err := netns.Do(func(_ ns.NetNS) error {
|
|
||||||
contCNI, errLink = validateCniContainerInterface(contMap)
|
|
||||||
if errLink != nil {
|
|
||||||
return errLink
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now look for veth that is peer with container interface.
|
|
||||||
// Anything else wasn't created by CNI, skip it
|
|
||||||
for _, intf := range result.Interfaces {
|
|
||||||
// Skip this result if name is the same as cni bridge
|
|
||||||
// It's either the cni bridge we dealt with above, or something with the
|
|
||||||
// same name in a different namespace. We just skip since it's not ours
|
|
||||||
if brMap.Name == intf.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// same here for container name
|
|
||||||
if contMap.Name == intf.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
vethCNI, errLink = validateCniVethInterface(intf, brCNI, contCNI)
|
|
||||||
if errLink != nil {
|
|
||||||
return errLink
|
|
||||||
}
|
|
||||||
|
|
||||||
if vethCNI.found {
|
|
||||||
// veth with container interface as peer and bridge as master found
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !brCNI.found {
|
|
||||||
return fmt.Errorf("CNI created bridge %s in host namespace was not found", n.BrName)
|
|
||||||
}
|
|
||||||
if !contCNI.found {
|
|
||||||
return fmt.Errorf("CNI created interface in container %s not found", args.IfName)
|
|
||||||
}
|
|
||||||
if !vethCNI.found {
|
|
||||||
return fmt.Errorf("CNI veth created for bridge %s was not found", n.BrName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check prevResults for ips, routes and dns against values found in the container
|
|
||||||
if err := netns.Do(func(_ ns.NetNS) error {
|
|
||||||
err = ip.ValidateExpectedInterfaceIPs(args.IfName, result.IPs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ip.ValidateExpectedRoute(result.Routes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
83
vendor/github.com/containernetworking/plugins/plugins/main/loopback/loopback.go
generated
vendored
83
vendor/github.com/containernetworking/plugins/plugins/main/loopback/loopback.go
generated
vendored
@ -1,83 +0,0 @@
|
|||||||
// Copyright 2016 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 loopback
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
|
||||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
|
||||||
)
|
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
|
||||||
args.IfName = "lo" // ignore config, this only works for loopback
|
|
||||||
err := ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
|
||||||
link, err := netlink.LinkByName(args.IfName)
|
|
||||||
if err != nil {
|
|
||||||
return err // not tested
|
|
||||||
}
|
|
||||||
|
|
||||||
err = netlink.LinkSetUp(link)
|
|
||||||
if err != nil {
|
|
||||||
return err // not tested
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err // not tested
|
|
||||||
}
|
|
||||||
|
|
||||||
result := current.Result{}
|
|
||||||
return result.Print()
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdDel(args *skel.CmdArgs) error {
|
|
||||||
if args.Netns == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
args.IfName = "lo" // ignore config, this only works for loopback
|
|
||||||
err := ns.WithNetNSPath(args.Netns, func(ns.NetNS) error {
|
|
||||||
link, err := netlink.LinkByName(args.IfName)
|
|
||||||
if err != nil {
|
|
||||||
return err // not tested
|
|
||||||
}
|
|
||||||
|
|
||||||
err = netlink.LinkSetDown(link)
|
|
||||||
if err != nil {
|
|
||||||
return err // not tested
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err // not tested
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Main() {
|
|
||||||
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, bv.BuildString("loopback"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdCheck(args *skel.CmdArgs) error {
|
|
||||||
// TODO: implement
|
|
||||||
return nil
|
|
||||||
}
|
|
135
vendor/github.com/containernetworking/plugins/plugins/meta/flannel/README.md
generated
vendored
135
vendor/github.com/containernetworking/plugins/plugins/meta/flannel/README.md
generated
vendored
@ -1,135 +0,0 @@
|
|||||||
# flannel plugin
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
This plugin is designed to work in conjunction with [flannel](https://github.com/coreos/flannel), a network fabric for containers.
|
|
||||||
When flannel daemon is started, it outputs a `/run/flannel/subnet.env` file that looks like this:
|
|
||||||
```
|
|
||||||
FLANNEL_NETWORK=10.1.0.0/16
|
|
||||||
FLANNEL_SUBNET=10.1.17.1/24
|
|
||||||
FLANNEL_MTU=1472
|
|
||||||
FLANNEL_IPMASQ=true
|
|
||||||
```
|
|
||||||
|
|
||||||
This information reflects the attributes of flannel network on the host.
|
|
||||||
The flannel CNI plugin uses this information to configure another CNI plugin, such as bridge plugin.
|
|
||||||
|
|
||||||
## Operation
|
|
||||||
Given the following network configuration file and the contents of `/run/flannel/subnet.env` above,
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"name": "mynet",
|
|
||||||
"type": "flannel"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
the flannel plugin will generate another network configuration file:
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"name": "mynet",
|
|
||||||
"type": "bridge",
|
|
||||||
"mtu": 1472,
|
|
||||||
"ipMasq": false,
|
|
||||||
"isGateway": true,
|
|
||||||
"ipam": {
|
|
||||||
"type": "host-local",
|
|
||||||
"subnet": "10.1.17.0/24"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
It will then invoke the bridge plugin, passing it the generated configuration.
|
|
||||||
|
|
||||||
As can be seen from above, the flannel plugin, by default, will delegate to the bridge plugin.
|
|
||||||
If additional configuration values need to be passed to the bridge plugin, it can be done so via the `delegate` field:
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"name": "mynet",
|
|
||||||
"type": "flannel",
|
|
||||||
"delegate": {
|
|
||||||
"bridge": "mynet0",
|
|
||||||
"mtu": 1400
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This supplies a configuration parameter to the bridge plugin -- the created bridge will now be named `mynet0`.
|
|
||||||
Notice that `mtu` has also been specified and this value will not be overwritten by flannel plugin.
|
|
||||||
|
|
||||||
Additionally, the `delegate` field can be used to select a different kind of plugin altogether.
|
|
||||||
To use `ipvlan` instead of `bridge`, the following configuration can be specified:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"name": "mynet",
|
|
||||||
"type": "flannel",
|
|
||||||
"delegate": {
|
|
||||||
"type": "ipvlan",
|
|
||||||
"master": "eth0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Network configuration reference
|
|
||||||
|
|
||||||
* `name` (string, required): the name of the network
|
|
||||||
* `type` (string, required): "flannel"
|
|
||||||
* `subnetFile` (string, optional): full path to the subnet file written out by flanneld. Defaults to /run/flannel/subnet.env
|
|
||||||
* `dataDir` (string, optional): path to directory where plugin will store generated network configuration files. Defaults to `/var/lib/cni/flannel`
|
|
||||||
* `delegate` (dictionary, optional): specifies configuration options for the delegated plugin.
|
|
||||||
|
|
||||||
flannel plugin will always set the following fields in the delegated plugin configuration:
|
|
||||||
|
|
||||||
* `name`: value of its "name" field.
|
|
||||||
* `ipam`: "host-local" type will be used with "subnet" set to `$FLANNEL_SUBNET`.
|
|
||||||
|
|
||||||
flannel plugin will set the following fields in the delegated plugin configuration if they are not present:
|
|
||||||
* `ipMasq`: the inverse of `$FLANNEL_IPMASQ`
|
|
||||||
* `mtu`: `$FLANNEL_MTU`
|
|
||||||
|
|
||||||
Additionally, for the bridge plugin, `isGateway` will be set to `true`, if not present.
|
|
||||||
|
|
||||||
## 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).
|
|
||||||
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.
|
|
||||||
|
|
||||||
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)
|
|
||||||
* `type` (string, optional): set to `win-l2bridge` by default. Can be set to `win-overlay` or other custom windows CNI
|
|
||||||
* `ipMasq`: the inverse of `$FLANNEL_IPMASQ`
|
|
||||||
* `endpointMacPrefix` (string, optional): required for `win-overlay` mode, set to the MAC prefix configured for Flannel
|
|
||||||
* `clusterNetworkPrefix` (string, optional): required for `win-l2bridge` mode, setup NAT if `ipMasq` is set to true
|
|
||||||
|
|
||||||
For `win-l2bridge`, the Flannel CNI plugin will set:
|
|
||||||
* `ipam`: "host-local" type will be used with "subnet" set to `$FLANNEL_SUBNET` and gateway as the .2 address in `$FLANNEL_NETWORK`
|
|
||||||
|
|
||||||
For `win-overlay`, the Flannel CNI plugin will set:
|
|
||||||
* `ipam`: "host-local" type will be used with "subnet" set to `$FLANNEL_SUBNET` and gateway as the .1 address in `$FLANNEL_NETWORK`
|
|
||||||
|
|
||||||
If IPMASQ is true, the Flannel CNI plugin will setup an OutBoundNAT policy and add FLANNEL_SUBNET to any existing exclusions.
|
|
||||||
|
|
||||||
All other delegate config e.g. other HNS endpoint policies in AdditionalArgs will be passed to WINCNI as-is.
|
|
||||||
|
|
||||||
Example VXLAN Flannel CNI config
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"name": "mynet",
|
|
||||||
"type": "flannel",
|
|
||||||
"delegate": {
|
|
||||||
"type": "win-overlay",
|
|
||||||
"endpointMacPrefix": "0E-2A"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For this example, Flannel CNI would generate the following config to delegate to the windows CNI when FLANNEL_NETWORK=10.244.0.0/16, FLANNEL_SUBNET=10.244.1.0/24 and IPMASQ=true
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"name": "mynet",
|
|
||||||
"type": "win-overlay",
|
|
||||||
"endpointMacPrefix": "0E-2A",
|
|
||||||
"ipMasq": true,
|
|
||||||
"ipam": {
|
|
||||||
"subnet": "10.244.1.0/24",
|
|
||||||
"type": "host-local"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
241
vendor/github.com/containernetworking/plugins/plugins/meta/flannel/flannel.go
generated
vendored
241
vendor/github.com/containernetworking/plugins/plugins/meta/flannel/flannel.go
generated
vendored
@ -1,241 +0,0 @@
|
|||||||
// Copyright 2015 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.
|
|
||||||
|
|
||||||
// This is a "meta-plugin". It reads in its own netconf, combines it with
|
|
||||||
// the data from flannel generated subnet file and then invokes a plugin
|
|
||||||
// like bridge or ipvlan to do the real work.
|
|
||||||
|
|
||||||
package flannel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/invoke"
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
|
||||||
|
|
||||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultSubnetFile = "/run/flannel/subnet.env"
|
|
||||||
defaultDataDir = "/var/lib/cni/flannel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type NetConf struct {
|
|
||||||
types.NetConf
|
|
||||||
|
|
||||||
SubnetFile string `json:"subnetFile"`
|
|
||||||
DataDir string `json:"dataDir"`
|
|
||||||
Delegate map[string]interface{} `json:"delegate"`
|
|
||||||
RuntimeConfig map[string]interface{} `json:"runtimeConfig,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type subnetEnv struct {
|
|
||||||
nw *net.IPNet
|
|
||||||
sn *net.IPNet
|
|
||||||
mtu *uint
|
|
||||||
ipmasq *bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (se *subnetEnv) missing() string {
|
|
||||||
m := []string{}
|
|
||||||
|
|
||||||
if se.nw == nil {
|
|
||||||
m = append(m, "FLANNEL_NETWORK")
|
|
||||||
}
|
|
||||||
if se.sn == nil {
|
|
||||||
m = append(m, "FLANNEL_SUBNET")
|
|
||||||
}
|
|
||||||
if se.mtu == nil {
|
|
||||||
m = append(m, "FLANNEL_MTU")
|
|
||||||
}
|
|
||||||
if se.ipmasq == nil {
|
|
||||||
m = append(m, "FLANNEL_IPMASQ")
|
|
||||||
}
|
|
||||||
return strings.Join(m, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadFlannelNetConf(bytes []byte) (*NetConf, error) {
|
|
||||||
n := &NetConf{
|
|
||||||
SubnetFile: defaultSubnetFile,
|
|
||||||
DataDir: defaultDataDir,
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(bytes, n); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadFlannelSubnetEnv(fn string) (*subnetEnv, error) {
|
|
||||||
f, err := os.Open(fn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
se := &subnetEnv{}
|
|
||||||
|
|
||||||
s := bufio.NewScanner(f)
|
|
||||||
for s.Scan() {
|
|
||||||
parts := strings.SplitN(s.Text(), "=", 2)
|
|
||||||
switch parts[0] {
|
|
||||||
case "FLANNEL_NETWORK":
|
|
||||||
_, se.nw, err = net.ParseCIDR(parts[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
case "FLANNEL_SUBNET":
|
|
||||||
_, se.sn, err = net.ParseCIDR(parts[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
case "FLANNEL_MTU":
|
|
||||||
mtu, err := strconv.ParseUint(parts[1], 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
se.mtu = new(uint)
|
|
||||||
*se.mtu = uint(mtu)
|
|
||||||
|
|
||||||
case "FLANNEL_IPMASQ":
|
|
||||||
ipmasq := parts[1] == "true"
|
|
||||||
se.ipmasq = &ipmasq
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if m := se.missing(); m != "" {
|
|
||||||
return nil, fmt.Errorf("%v is missing %v", fn, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return se, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveScratchNetConf(containerID, dataDir string, netconf []byte) error {
|
|
||||||
if err := os.MkdirAll(dataDir, 0700); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
path := filepath.Join(dataDir, containerID)
|
|
||||||
return ioutil.WriteFile(path, netconf, 0600)
|
|
||||||
}
|
|
||||||
|
|
||||||
func consumeScratchNetConf(containerID, dataDir string) ([]byte, error) {
|
|
||||||
path := filepath.Join(dataDir, containerID)
|
|
||||||
// Ignore errors when removing - Per spec safe to continue during DEL
|
|
||||||
defer os.Remove(path)
|
|
||||||
|
|
||||||
return ioutil.ReadFile(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func delegateAdd(cid, dataDir string, netconf map[string]interface{}) error {
|
|
||||||
netconfBytes, err := json.Marshal(netconf)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error serializing delegate netconf: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the rendered netconf for cmdDel
|
|
||||||
if err = saveScratchNetConf(cid, dataDir, netconfBytes); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := invoke.DelegateAdd(context.TODO(), netconf["type"].(string), netconfBytes, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.Print()
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasKey(m map[string]interface{}, k string) bool {
|
|
||||||
_, ok := m[k]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func isString(i interface{}) bool {
|
|
||||||
_, ok := i.(string)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
|
||||||
n, err := loadFlannelNetConf(args.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fenv, err := loadFlannelSubnetEnv(n.SubnetFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Delegate == nil {
|
|
||||||
n.Delegate = make(map[string]interface{})
|
|
||||||
} else {
|
|
||||||
if hasKey(n.Delegate, "type") && !isString(n.Delegate["type"]) {
|
|
||||||
return fmt.Errorf("'delegate' dictionary, if present, must have (string) 'type' field")
|
|
||||||
}
|
|
||||||
if hasKey(n.Delegate, "name") {
|
|
||||||
return fmt.Errorf("'delegate' dictionary must not have 'name' field, it'll be set by flannel")
|
|
||||||
}
|
|
||||||
if hasKey(n.Delegate, "ipam") {
|
|
||||||
return fmt.Errorf("'delegate' dictionary must not have 'ipam' field, it'll be set by flannel")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.RuntimeConfig != nil {
|
|
||||||
n.Delegate["runtimeConfig"] = n.RuntimeConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
return doCmdAdd(args, n, fenv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdDel(args *skel.CmdArgs) error {
|
|
||||||
nc, err := loadFlannelNetConf(args.StdinData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nc.RuntimeConfig != nil {
|
|
||||||
if nc.Delegate == nil {
|
|
||||||
nc.Delegate = make(map[string]interface{})
|
|
||||||
}
|
|
||||||
nc.Delegate["runtimeConfig"] = nc.RuntimeConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
return doCmdDel(args, nc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Main() {
|
|
||||||
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, bv.BuildString("flannel"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdCheck(args *skel.CmdArgs) error {
|
|
||||||
// TODO: implement
|
|
||||||
return nil
|
|
||||||
}
|
|
87
vendor/github.com/containernetworking/plugins/plugins/meta/flannel/flannel_linux.go
generated
vendored
87
vendor/github.com/containernetworking/plugins/plugins/meta/flannel/flannel_linux.go
generated
vendored
@ -1,87 +0,0 @@
|
|||||||
// Copyright 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.
|
|
||||||
|
|
||||||
// This is a "meta-plugin". It reads in its own netconf, combines it with
|
|
||||||
// the data from flannel generated subnet file and then invokes a plugin
|
|
||||||
// like bridge or ipvlan to do the real work.
|
|
||||||
|
|
||||||
package flannel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/containernetworking/cni/pkg/invoke"
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error {
|
|
||||||
n.Delegate["name"] = n.Name
|
|
||||||
|
|
||||||
if !hasKey(n.Delegate, "type") {
|
|
||||||
n.Delegate["type"] = "bridge"
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasKey(n.Delegate, "ipMasq") {
|
|
||||||
// if flannel is not doing ipmasq, we should
|
|
||||||
ipmasq := !*fenv.ipmasq
|
|
||||||
n.Delegate["ipMasq"] = ipmasq
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasKey(n.Delegate, "mtu") {
|
|
||||||
mtu := fenv.mtu
|
|
||||||
n.Delegate["mtu"] = mtu
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Delegate["type"].(string) == "bridge" {
|
|
||||||
if !hasKey(n.Delegate, "isGateway") {
|
|
||||||
n.Delegate["isGateway"] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if n.CNIVersion != "" {
|
|
||||||
n.Delegate["cniVersion"] = n.CNIVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
n.Delegate["ipam"] = map[string]interface{}{
|
|
||||||
"type": "host-local",
|
|
||||||
"subnet": fenv.sn.String(),
|
|
||||||
"routes": []types.Route{
|
|
||||||
{
|
|
||||||
Dst: *fenv.nw,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return delegateAdd(args.ContainerID, n.DataDir, n.Delegate)
|
|
||||||
}
|
|
||||||
|
|
||||||
func doCmdDel(args *skel.CmdArgs, n *NetConf) error {
|
|
||||||
netconfBytes, err := consumeScratchNetConf(args.ContainerID, n.DataDir)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
// Per spec should ignore error if resources are missing / already removed
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
nc := &types.NetConf{}
|
|
||||||
if err = json.Unmarshal(netconfBytes, nc); err != nil {
|
|
||||||
return fmt.Errorf("failed to parse netconf: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return invoke.DelegateDel(context.TODO(), nc.Type, netconfBytes, nil)
|
|
||||||
}
|
|
74
vendor/github.com/containernetworking/plugins/plugins/meta/flannel/flannel_windows.go
generated
vendored
74
vendor/github.com/containernetworking/plugins/plugins/meta/flannel/flannel_windows.go
generated
vendored
@ -1,74 +0,0 @@
|
|||||||
// Copyright 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.
|
|
||||||
|
|
||||||
// This is a "meta-plugin". It reads in its own netconf, combines it with
|
|
||||||
// the data from flannel generated subnet file and then invokes a plugin
|
|
||||||
// like bridge or ipvlan to do the real work.
|
|
||||||
|
|
||||||
package flannel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/containernetworking/cni/pkg/invoke"
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/types/020"
|
|
||||||
"github.com/containernetworking/plugins/pkg/hns"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error {
|
|
||||||
n.Delegate["name"] = n.Name
|
|
||||||
|
|
||||||
if !hasKey(n.Delegate, "type") {
|
|
||||||
n.Delegate["type"] = "win-bridge"
|
|
||||||
}
|
|
||||||
|
|
||||||
// if flannel needs ipmasq - get the plugin to configure it
|
|
||||||
// (this is the opposite of how linux works - on linux the flannel daemon configure ipmasq)
|
|
||||||
n.Delegate["ipMasq"] = *fenv.ipmasq
|
|
||||||
n.Delegate["ipMasqNetwork"] = fenv.nw.String()
|
|
||||||
|
|
||||||
n.Delegate["cniVersion"] = types020.ImplementedSpecVersion
|
|
||||||
if len(n.CNIVersion) != 0 {
|
|
||||||
n.Delegate["cniVersion"] = n.CNIVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
n.Delegate["ipam"] = map[string]interface{}{
|
|
||||||
"type": "host-local",
|
|
||||||
"subnet": fenv.sn.String(),
|
|
||||||
}
|
|
||||||
|
|
||||||
return delegateAdd(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir, n.Delegate)
|
|
||||||
}
|
|
||||||
|
|
||||||
func doCmdDel(args *skel.CmdArgs, n *NetConf) error {
|
|
||||||
netconfBytes, err := consumeScratchNetConf(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
// Per spec should ignore error if resources are missing / already removed
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
nc := &types.NetConf{}
|
|
||||||
if err = json.Unmarshal(netconfBytes, nc); err != nil {
|
|
||||||
return fmt.Errorf("failed to parse netconf: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return invoke.DelegateDel(context.TODO(), nc.Type, netconfBytes, nil)
|
|
||||||
}
|
|
133
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/README.md
generated
vendored
133
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/README.md
generated
vendored
@ -1,133 +0,0 @@
|
|||||||
## Port-mapping plugin
|
|
||||||
|
|
||||||
This plugin will forward traffic from one or more ports on the host to the
|
|
||||||
container. It expects to be run as a chained plugin.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
You should use this plugin as part of a network configuration list. It accepts
|
|
||||||
the following configuration options:
|
|
||||||
|
|
||||||
* `snat` - boolean, default true. If true or omitted, set up the SNAT chains
|
|
||||||
* `markMasqBit` - int, (0-31), default 13. The mark bit to use for masquerading (see section SNAT). Cannot be set when `externalSetMarkChain` is used.
|
|
||||||
* `externalSetMarkChain` - string, default nil. If you already have a Masquerade mark chain (e.g. Kubernetes), specify it here. This will use that instead of creating a separate chain. When this is set, `markMasqBit` must be unspecified.
|
|
||||||
* `conditionsV4`, `conditionsV6` - array of strings. A list of arbitrary `iptables`
|
|
||||||
matches to add to the per-container rule. This may be useful if you wish to
|
|
||||||
exclude specific IPs from port-mapping
|
|
||||||
|
|
||||||
The plugin expects to receive the actual list of port mappings via the
|
|
||||||
`portMappings` [capability argument](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md)
|
|
||||||
|
|
||||||
A sample standalone config list for Kubernetes (with the file extension .conflist) might
|
|
||||||
look like:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"cniVersion": "0.3.1",
|
|
||||||
"name": "mynet",
|
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"type": "ptp",
|
|
||||||
"ipMasq": true,
|
|
||||||
"ipam": {
|
|
||||||
"type": "host-local",
|
|
||||||
"subnet": "172.16.30.0/24",
|
|
||||||
"routes": [
|
|
||||||
{
|
|
||||||
"dst": "0.0.0.0/0"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "portmap",
|
|
||||||
"capabilities": {"portMappings": true},
|
|
||||||
"externalSetMarkChain": "KUBE-MARK-MASQ"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
A configuration file with all options set:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "portmap",
|
|
||||||
"capabilities": {"portMappings": true},
|
|
||||||
"snat": true,
|
|
||||||
"markMasqBit": 13,
|
|
||||||
"externalSetMarkChain": "CNI-HOSTPORT-SETMARK",
|
|
||||||
"conditionsV4": ["!", "-d", "192.0.2.0/24"],
|
|
||||||
"conditionsV6": ["!", "-d", "fc00::/7"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Rule structure
|
|
||||||
The plugin sets up two sequences of chains and rules - one "primary" DNAT
|
|
||||||
sequence to rewrite the destination, and one additional SNAT sequence that
|
|
||||||
will masquerade traffic as needed.
|
|
||||||
|
|
||||||
|
|
||||||
### DNAT
|
|
||||||
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
|
|
||||||
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
|
|
||||||
8080 and 8043 on the host forwarded to ports 80 and 443 in the container, the
|
|
||||||
rules look like this:
|
|
||||||
|
|
||||||
`PREROUTING`, `OUTPUT` chains:
|
|
||||||
- `--dst-type LOCAL -j CNI-HOSTPORT-DNAT`
|
|
||||||
|
|
||||||
`CNI-HOSTPORT-DNAT` chain:
|
|
||||||
- `${ConditionsV4/6} -p tcp --destination-ports 8080,8043 -j CNI-DN-xxxxxx` (where xxxxxx is a function of the ContainerID and network name)
|
|
||||||
|
|
||||||
`CNI-HOSTPORT-SETMARK` chain:
|
|
||||||
- `-j MARK --set-xmark 0x2000/0x2000`
|
|
||||||
|
|
||||||
`CNI-DN-xxxxxx` chain:
|
|
||||||
- `-p tcp -s 172.16.30.2 --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 --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 127.0.0.1 --dport 8043 -j CNI-HOSTPORT-SETMARK`
|
|
||||||
- `-p tcp --dport 8043 -j DNAT --to-destination 172.16.30.2:443`
|
|
||||||
|
|
||||||
New connections to the host will have to traverse every rule, so large numbers
|
|
||||||
of port forwards may have a performance impact. This won't affect established
|
|
||||||
connections, just the first packet.
|
|
||||||
|
|
||||||
### SNAT (Masquerade)
|
|
||||||
Some packets also need to have the source address rewritten:
|
|
||||||
* connections from localhost
|
|
||||||
* Hairpin traffic back to the container.
|
|
||||||
|
|
||||||
In the DNAT chain, a bit is set on the mark for packets that need snat. This
|
|
||||||
chain performs that masquerading. By default, bit 13 is set, but this is
|
|
||||||
configurable. If you are using other tools that also use the iptables mark,
|
|
||||||
you should make sure this doesn't conflict.
|
|
||||||
|
|
||||||
Some container runtimes, most notably Kubernetes, already have a set of rules
|
|
||||||
for masquerading when a specific mark bit is set. If so enabled, the plugin
|
|
||||||
will use that chain instead.
|
|
||||||
|
|
||||||
`POSTROUTING`:
|
|
||||||
- `-j CNI-HOSTPORT-MASQ`
|
|
||||||
|
|
||||||
`CNI-HOSTPORT-MASQ`:
|
|
||||||
- `--mark 0x2000 -j MASQUERADE`
|
|
||||||
|
|
||||||
Because MASQUERADE happens in POSTROUTING, it means that packets with source ip
|
|
||||||
127.0.0.1 need to first pass a routing boundary before being masqueraded. By
|
|
||||||
default, that is not allowed in Linux. So, the plugin needs to enable the sysctl
|
|
||||||
`net.ipv4.conf.IFNAME.route_localnet`, where IFNAME is the name of the host-side
|
|
||||||
interface that routes traffic to the container.
|
|
||||||
|
|
||||||
There is no equivalent to `route_localnet` for ipv6, so connections to ::1
|
|
||||||
will not be portmapped for ipv6. If you need port forwarding from localhost,
|
|
||||||
your container must have an ipv4 address.
|
|
||||||
|
|
||||||
|
|
||||||
## Known issues
|
|
||||||
- ipsets could improve efficiency
|
|
||||||
- forwarding from localhost does not work with ipv6.
|
|
181
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/chain.go
generated
vendored
181
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/chain.go
generated
vendored
@ -1,181 +0,0 @@
|
|||||||
// 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 portmap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/coreos/go-iptables/iptables"
|
|
||||||
"github.com/mattn/go-shellwords"
|
|
||||||
)
|
|
||||||
|
|
||||||
type chain struct {
|
|
||||||
table string
|
|
||||||
name string
|
|
||||||
entryChains []string // the chains to add the entry rule
|
|
||||||
|
|
||||||
entryRules [][]string // the rules that "point" to this chain
|
|
||||||
rules [][]string // the rules this chain contains
|
|
||||||
|
|
||||||
prependEntry bool // whether or not the entry rules should be prepended
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup idempotently creates the chain. It will not error if the chain exists.
|
|
||||||
func (c *chain) setup(ipt *iptables.IPTables) error {
|
|
||||||
// create the chain
|
|
||||||
exists, err := chainExists(ipt, c.table, c.name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
if err := ipt.NewChain(c.table, c.name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the rules to the chain
|
|
||||||
for _, rule := range c.rules {
|
|
||||||
if err := insertUnique(ipt, c.table, c.name, false, rule); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the entry rules to the entry chains
|
|
||||||
for _, entryChain := range c.entryChains {
|
|
||||||
for _, rule := range c.entryRules {
|
|
||||||
r := []string{}
|
|
||||||
r = append(r, rule...)
|
|
||||||
r = append(r, "-j", c.name)
|
|
||||||
if err := insertUnique(ipt, c.table, entryChain, c.prependEntry, r); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// teardown idempotently deletes a chain. It will not error if the chain doesn't exist.
|
|
||||||
// It will first delete all references to this chain in the entryChains.
|
|
||||||
func (c *chain) teardown(ipt *iptables.IPTables) error {
|
|
||||||
// flush the chain
|
|
||||||
// This will succeed *and create the chain* if it does not exist.
|
|
||||||
// If the chain doesn't exist, the next checks will fail.
|
|
||||||
if err := ipt.ClearChain(c.table, c.name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entryChain := range c.entryChains {
|
|
||||||
entryChainRules, err := ipt.List(c.table, entryChain)
|
|
||||||
if err != nil || len(entryChainRules) < 1 {
|
|
||||||
// Swallow error here - probably the chain doesn't exist.
|
|
||||||
// If we miss something the deletion will fail
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entryChainRule := range entryChainRules[1:] {
|
|
||||||
if strings.HasSuffix(entryChainRule, "-j "+c.name) {
|
|
||||||
chainParts, err := shellwords.Parse(entryChainRule)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error parsing iptables rule: %s: %v", entryChainRule, err)
|
|
||||||
}
|
|
||||||
chainParts = chainParts[2:] // List results always include an -A CHAINNAME
|
|
||||||
|
|
||||||
if err := ipt.Delete(c.table, entryChain, chainParts...); err != nil {
|
|
||||||
return fmt.Errorf("Failed to delete referring rule %s %s: %v", c.table, entryChainRule, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ipt.DeleteChain(c.table, c.name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// insertUnique will add a rule to a chain if it does not already exist.
|
|
||||||
// By default the rule is appended, unless prepend is true.
|
|
||||||
func insertUnique(ipt *iptables.IPTables, table, chain string, prepend bool, rule []string) error {
|
|
||||||
exists, err := ipt.Exists(table, chain, rule...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if exists {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if prepend {
|
|
||||||
return ipt.Insert(table, chain, 1, rule...)
|
|
||||||
} else {
|
|
||||||
return ipt.Append(table, chain, rule...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
func (c *chain) check(ipt *iptables.IPTables) error {
|
|
||||||
|
|
||||||
exists, err := chainExists(ipt, c.table, c.name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
return fmt.Errorf("chain %s not found in iptables table %s", c.name, c.table)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := len(c.rules) - 1; i >= 0; i-- {
|
|
||||||
match := checkRule(ipt, c.table, c.name, c.rules[i])
|
|
||||||
if !match {
|
|
||||||
return fmt.Errorf("rule %s in chain %s not found in table %s", c.rules, c.name, c.table)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entryChain := range c.entryChains {
|
|
||||||
for i := len(c.entryRules) - 1; i >= 0; i-- {
|
|
||||||
r := []string{}
|
|
||||||
r = append(r, c.entryRules[i]...)
|
|
||||||
r = append(r, "-j", c.name)
|
|
||||||
matchEntryChain := checkRule(ipt, c.table, entryChain, r)
|
|
||||||
if !matchEntryChain {
|
|
||||||
return fmt.Errorf("rule %s in chain %s not found in table %s", c.entryRules, entryChain, c.table)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkRule(ipt *iptables.IPTables, table, chain string, rule []string) bool {
|
|
||||||
exists, err := ipt.Exists(table, chain, rule...)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return exists
|
|
||||||
}
|
|
234
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/main.go
generated
vendored
234
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/main.go
generated
vendored
@ -1,234 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// This is a post-setup plugin that establishes port forwarding - using iptables,
|
|
||||||
// from the host's network interface(s) to a pod's network interface.
|
|
||||||
//
|
|
||||||
// It is intended to be used as a chained CNI plugin, and determines the container
|
|
||||||
// IP from the previous result. If the result includes an IPv6 address, it will
|
|
||||||
// also be configured. (IPTables will not forward cross-family).
|
|
||||||
//
|
|
||||||
// This has one notable limitation: it does not perform any kind of reservation
|
|
||||||
// of the actual host port. If there is a service on the host, it will have all
|
|
||||||
// its traffic captured by the container. If another container also claims a given
|
|
||||||
// port, it will caputure the traffic - it is last-write-wins.
|
|
||||||
package portmap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
|
||||||
|
|
||||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PortMapEntry corresponds to a single entry in the port_mappings argument,
|
|
||||||
// see CONVENTIONS.md
|
|
||||||
type PortMapEntry struct {
|
|
||||||
HostPort int `json:"hostPort"`
|
|
||||||
ContainerPort int `json:"containerPort"`
|
|
||||||
Protocol string `json:"protocol"`
|
|
||||||
HostIP string `json:"hostIP,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PortMapConf struct {
|
|
||||||
types.NetConf
|
|
||||||
SNAT *bool `json:"snat,omitempty"`
|
|
||||||
ConditionsV4 *[]string `json:"conditionsV4"`
|
|
||||||
ConditionsV6 *[]string `json:"conditionsV6"`
|
|
||||||
MarkMasqBit *int `json:"markMasqBit"`
|
|
||||||
ExternalSetMarkChain *string `json:"externalSetMarkChain"`
|
|
||||||
RuntimeConfig struct {
|
|
||||||
PortMaps []PortMapEntry `json:"portMappings,omitempty"`
|
|
||||||
} `json:"runtimeConfig,omitempty"`
|
|
||||||
|
|
||||||
// These are fields parsed out of the config or the environment;
|
|
||||||
// included here for convenience
|
|
||||||
ContainerID string `json:"-"`
|
|
||||||
ContIPv4 net.IP `json:"-"`
|
|
||||||
ContIPv6 net.IP `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// The default mark bit to signal that masquerading is required
|
|
||||||
// Kubernetes uses 14 and 15, Calico uses 20-31.
|
|
||||||
const DefaultMarkBit = 13
|
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
|
||||||
netConf, _, err := parseConfig(args.StdinData, args.IfName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse config: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if netConf.PrevResult == nil {
|
|
||||||
return fmt.Errorf("must be called as chained plugin")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(netConf.RuntimeConfig.PortMaps) == 0 {
|
|
||||||
return types.PrintResult(netConf.PrevResult, netConf.CNIVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
netConf.ContainerID = args.ContainerID
|
|
||||||
|
|
||||||
if netConf.ContIPv4 != nil {
|
|
||||||
if err := forwardPorts(netConf, netConf.ContIPv4); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if netConf.ContIPv6 != nil {
|
|
||||||
if err := forwardPorts(netConf, netConf.ContIPv6); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass through the previous result
|
|
||||||
return types.PrintResult(netConf.PrevResult, netConf.CNIVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdDel(args *skel.CmdArgs) error {
|
|
||||||
netConf, _, err := parseConfig(args.StdinData, args.IfName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse config: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
netConf.ContainerID = args.ContainerID
|
|
||||||
|
|
||||||
// We don't need to parse out whether or not we're using v6 or snat,
|
|
||||||
// deletion is idempotent
|
|
||||||
if err := unforwardPorts(netConf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Main() {
|
|
||||||
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, bv.BuildString("portmap"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdCheck(args *skel.CmdArgs) error {
|
|
||||||
conf, result, err := parseConfig(args.StdinData, args.IfName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure we have previous result.
|
|
||||||
if result == nil {
|
|
||||||
return fmt.Errorf("Required prevResult missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(conf.RuntimeConfig.PortMaps) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
conf.ContainerID = args.ContainerID
|
|
||||||
|
|
||||||
if conf.ContIPv4 != nil {
|
|
||||||
if err := checkPorts(conf, conf.ContIPv4); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.ContIPv6 != nil {
|
|
||||||
if err := checkPorts(conf, conf.ContIPv6); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseConfig parses the supplied configuration (and prevResult) from stdin.
|
|
||||||
func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, error) {
|
|
||||||
conf := PortMapConf{}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(stdin, &conf); err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to parse network configuration: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse previous result.
|
|
||||||
var result *current.Result
|
|
||||||
if conf.RawPrevResult != nil {
|
|
||||||
var err error
|
|
||||||
if err = version.ParsePrevResult(&conf.NetConf); err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("could not parse prevResult: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = current.NewResultFromResult(conf.PrevResult)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("could not convert result to current version: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.SNAT == nil {
|
|
||||||
tvar := true
|
|
||||||
conf.SNAT = &tvar
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.MarkMasqBit != nil && conf.ExternalSetMarkChain != nil {
|
|
||||||
return nil, nil, fmt.Errorf("Cannot specify externalSetMarkChain and markMasqBit")
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.MarkMasqBit == nil {
|
|
||||||
bvar := DefaultMarkBit // go constants are "special"
|
|
||||||
conf.MarkMasqBit = &bvar
|
|
||||||
}
|
|
||||||
|
|
||||||
if *conf.MarkMasqBit < 0 || *conf.MarkMasqBit > 31 {
|
|
||||||
return nil, nil, fmt.Errorf("MasqMarkBit must be between 0 and 31")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reject invalid port numbers
|
|
||||||
for _, pm := range conf.RuntimeConfig.PortMaps {
|
|
||||||
if pm.ContainerPort <= 0 {
|
|
||||||
return nil, nil, fmt.Errorf("Invalid container port number: %d", pm.ContainerPort)
|
|
||||||
}
|
|
||||||
if pm.HostPort <= 0 {
|
|
||||||
return nil, nil, fmt.Errorf("Invalid host port number: %d", pm.HostPort)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.PrevResult != nil {
|
|
||||||
for _, ip := range result.IPs {
|
|
||||||
if ip.Version == "6" && conf.ContIPv6 != nil {
|
|
||||||
continue
|
|
||||||
} else if ip.Version == "4" && conf.ContIPv4 != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip known non-sandbox interfaces
|
|
||||||
if ip.Interface != nil {
|
|
||||||
intIdx := *ip.Interface
|
|
||||||
if intIdx >= 0 &&
|
|
||||||
intIdx < len(result.Interfaces) &&
|
|
||||||
(result.Interfaces[intIdx].Name != ifName ||
|
|
||||||
result.Interfaces[intIdx].Sandbox == "") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch ip.Version {
|
|
||||||
case "6":
|
|
||||||
conf.ContIPv6 = ip.Address.IP
|
|
||||||
case "4":
|
|
||||||
conf.ContIPv4 = ip.Address.IP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &conf, result, nil
|
|
||||||
}
|
|
391
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/portmap.go
generated
vendored
391
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/portmap.go
generated
vendored
@ -1,391 +0,0 @@
|
|||||||
// 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 portmap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/utils"
|
|
||||||
"github.com/containernetworking/plugins/pkg/utils/sysctl"
|
|
||||||
"github.com/coreos/go-iptables/iptables"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This creates the chains to be added to iptables. The basic structure is
|
|
||||||
// a bit complex for efficiency's sake. We create 2 chains: a summary chain
|
|
||||||
// that is shared between invocations, and an invocation (container)-specific
|
|
||||||
// chain. This minimizes the number of operations on the top level, but allows
|
|
||||||
// for easy cleanup.
|
|
||||||
//
|
|
||||||
// The basic setup (all operations are on the nat table) is:
|
|
||||||
//
|
|
||||||
// DNAT case (rewrite destination IP and port):
|
|
||||||
// PREROUTING, OUTPUT: --dst-type local -j CNI-HOSTPORT-DNAT
|
|
||||||
// CNI-HOSTPORT-DNAT: --destination-ports 8080,8081 -j CNI-DN-abcd123
|
|
||||||
// CNI-DN-abcd123: -p tcp --dport 8080 -j DNAT --to-destination 192.0.2.33:80
|
|
||||||
// CNI-DN-abcd123: -p tcp --dport 8081 -j DNAT ...
|
|
||||||
|
|
||||||
// The names of the top-level summary chains.
|
|
||||||
// These should never be changed, or else upgrading will require manual
|
|
||||||
// intervention.
|
|
||||||
const TopLevelDNATChainName = "CNI-HOSTPORT-DNAT"
|
|
||||||
const SetMarkChainName = "CNI-HOSTPORT-SETMARK"
|
|
||||||
const MarkMasqChainName = "CNI-HOSTPORT-MASQ"
|
|
||||||
const OldTopLevelSNATChainName = "CNI-HOSTPORT-SNAT"
|
|
||||||
|
|
||||||
// forwardPorts establishes port forwarding to a given container IP.
|
|
||||||
// containerIP can be either v4 or v6.
|
|
||||||
func forwardPorts(config *PortMapConf, containerIP net.IP) error {
|
|
||||||
isV6 := (containerIP.To4() == nil)
|
|
||||||
|
|
||||||
var ipt *iptables.IPTables
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if isV6 {
|
|
||||||
ipt, err = iptables.NewWithProtocol(iptables.ProtocolIPv6)
|
|
||||||
} else {
|
|
||||||
ipt, err = iptables.NewWithProtocol(iptables.ProtocolIPv4)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open iptables: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable masquerading for traffic as necessary.
|
|
||||||
// The DNAT chain sets a mark bit for traffic that needs masq:
|
|
||||||
// - connections from localhost
|
|
||||||
// - hairpin traffic back to the container
|
|
||||||
// Idempotently create the rule that masquerades traffic with this mark.
|
|
||||||
// Need to do this first; the DNAT rules reference these chains
|
|
||||||
if *config.SNAT {
|
|
||||||
if config.ExternalSetMarkChain == nil {
|
|
||||||
setMarkChain := genSetMarkChain(*config.MarkMasqBit)
|
|
||||||
if err := setMarkChain.setup(ipt); err != nil {
|
|
||||||
return fmt.Errorf("unable to create chain %s: %v", setMarkChain.name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
masqChain := genMarkMasqChain(*config.MarkMasqBit)
|
|
||||||
if err := masqChain.setup(ipt); err != nil {
|
|
||||||
return fmt.Errorf("unable to create chain %s: %v", setMarkChain.name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isV6 {
|
|
||||||
// Set the route_localnet bit on the host interface, so that
|
|
||||||
// 127/8 can cross a routing boundary.
|
|
||||||
hostIfName := getRoutableHostIF(containerIP)
|
|
||||||
if hostIfName != "" {
|
|
||||||
if err := enableLocalnetRouting(hostIfName); err != nil {
|
|
||||||
return fmt.Errorf("unable to enable route_localnet: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the DNAT (actual port forwarding) rules
|
|
||||||
toplevelDnatChain := genToplevelDnatChain()
|
|
||||||
if err := toplevelDnatChain.setup(ipt); err != nil {
|
|
||||||
return fmt.Errorf("failed to create top-level DNAT chain: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
|
||||||
// First, idempotently tear down this chain in case there was some
|
|
||||||
// sort of collision or bad state.
|
|
||||||
fillDnatRules(&dnatChain, config, containerIP)
|
|
||||||
if err := dnatChain.setup(ipt); err != nil {
|
|
||||||
return fmt.Errorf("unable to setup DNAT: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkPorts(config *PortMapConf, containerIP net.IP) error {
|
|
||||||
|
|
||||||
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
|
||||||
fillDnatRules(&dnatChain, config, containerIP)
|
|
||||||
|
|
||||||
ip4t := maybeGetIptables(false)
|
|
||||||
ip6t := maybeGetIptables(true)
|
|
||||||
if ip4t == nil && ip6t == nil {
|
|
||||||
return fmt.Errorf("neither iptables nor ip6tables usable")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip4t != nil {
|
|
||||||
exists, err := chainExists(ip4t, dnatChain.table, dnatChain.name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := dnatChain.check(ip4t); err != nil {
|
|
||||||
return fmt.Errorf("could not check ipv4 dnat: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip6t != nil {
|
|
||||||
exists, err := chainExists(ip6t, dnatChain.table, dnatChain.name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := dnatChain.check(ip6t); err != nil {
|
|
||||||
return fmt.Errorf("could not check ipv6 dnat: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// genToplevelDnatChain creates the top-level summary chain that we'll
|
|
||||||
// add our chain to. This is easy, because creating chains is idempotent.
|
|
||||||
// IMPORTANT: do not change this, or else upgrading plugins will require
|
|
||||||
// manual intervention.
|
|
||||||
func genToplevelDnatChain() chain {
|
|
||||||
return chain{
|
|
||||||
table: "nat",
|
|
||||||
name: TopLevelDNATChainName,
|
|
||||||
entryRules: [][]string{{
|
|
||||||
"-m", "addrtype",
|
|
||||||
"--dst-type", "LOCAL",
|
|
||||||
}},
|
|
||||||
entryChains: []string{"PREROUTING", "OUTPUT"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// genDnatChain creates the per-container chain.
|
|
||||||
// Conditions are any static entry conditions for the chain.
|
|
||||||
func genDnatChain(netName, containerID string) chain {
|
|
||||||
return chain{
|
|
||||||
table: "nat",
|
|
||||||
name: utils.MustFormatChainNameWithPrefix(netName, containerID, "DN-"),
|
|
||||||
entryChains: []string{TopLevelDNATChainName},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dnatRules generates the destination NAT rules, one per port, to direct
|
|
||||||
// traffic from hostip:hostport to podip:podport
|
|
||||||
func fillDnatRules(c *chain, config *PortMapConf, containerIP net.IP) {
|
|
||||||
isV6 := (containerIP.To4() == nil)
|
|
||||||
comment := trimComment(fmt.Sprintf(`dnat name: "%s" id: "%s"`, config.Name, config.ContainerID))
|
|
||||||
entries := config.RuntimeConfig.PortMaps
|
|
||||||
setMarkChainName := SetMarkChainName
|
|
||||||
if config.ExternalSetMarkChain != nil {
|
|
||||||
setMarkChainName = *config.ExternalSetMarkChain
|
|
||||||
}
|
|
||||||
|
|
||||||
//Generate the dnat entry rules. We'll use multiport, but it ony accepts
|
|
||||||
// up to 15 rules, so partition the list if needed.
|
|
||||||
// Do it in a stable order for testing
|
|
||||||
protoPorts := groupByProto(entries)
|
|
||||||
protos := []string{}
|
|
||||||
for proto := range protoPorts {
|
|
||||||
protos = append(protos, proto)
|
|
||||||
}
|
|
||||||
sort.Strings(protos)
|
|
||||||
for _, proto := range protos {
|
|
||||||
for _, portSpec := range splitPortList(protoPorts[proto]) {
|
|
||||||
r := []string{
|
|
||||||
"-m", "comment",
|
|
||||||
"--comment", comment,
|
|
||||||
"-m", "multiport",
|
|
||||||
"-p", proto,
|
|
||||||
"--destination-ports", portSpec,
|
|
||||||
}
|
|
||||||
|
|
||||||
if isV6 && config.ConditionsV6 != nil && len(*config.ConditionsV6) > 0 {
|
|
||||||
r = append(r, *config.ConditionsV6...)
|
|
||||||
} else if !isV6 && config.ConditionsV4 != nil && len(*config.ConditionsV4) > 0 {
|
|
||||||
r = append(r, *config.ConditionsV4...)
|
|
||||||
}
|
|
||||||
c.entryRules = append(c.entryRules, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For every entry, generate 3 rules:
|
|
||||||
// - mark hairpin for masq
|
|
||||||
// - mark localhost for masq (for v4)
|
|
||||||
// - do dnat
|
|
||||||
// the ordering is important here; the mark rules must be first.
|
|
||||||
c.rules = make([][]string, 0, 3*len(entries))
|
|
||||||
for _, entry := range entries {
|
|
||||||
ruleBase := []string{
|
|
||||||
"-p", entry.Protocol,
|
|
||||||
"--dport", strconv.Itoa(entry.HostPort)}
|
|
||||||
if entry.HostIP != "" {
|
|
||||||
ruleBase = append(ruleBase,
|
|
||||||
"-d", entry.HostIP)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add mark-to-masquerade rules for hairpin and localhost
|
|
||||||
if *config.SNAT {
|
|
||||||
// hairpin
|
|
||||||
hpRule := make([]string, len(ruleBase), len(ruleBase)+4)
|
|
||||||
copy(hpRule, ruleBase)
|
|
||||||
|
|
||||||
hpRule = append(hpRule,
|
|
||||||
"-s", containerIP.String(),
|
|
||||||
"-j", setMarkChainName,
|
|
||||||
)
|
|
||||||
c.rules = append(c.rules, hpRule)
|
|
||||||
|
|
||||||
if !isV6 {
|
|
||||||
// localhost
|
|
||||||
localRule := make([]string, len(ruleBase), len(ruleBase)+4)
|
|
||||||
copy(localRule, ruleBase)
|
|
||||||
|
|
||||||
localRule = append(localRule,
|
|
||||||
"-s", "127.0.0.1",
|
|
||||||
"-j", setMarkChainName,
|
|
||||||
)
|
|
||||||
c.rules = append(c.rules, localRule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The actual dnat rule
|
|
||||||
dnatRule := make([]string, len(ruleBase), len(ruleBase)+4)
|
|
||||||
copy(dnatRule, ruleBase)
|
|
||||||
dnatRule = append(dnatRule,
|
|
||||||
"-j", "DNAT",
|
|
||||||
"--to-destination", fmtIpPort(containerIP, entry.ContainerPort),
|
|
||||||
)
|
|
||||||
c.rules = append(c.rules, dnatRule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// genSetMarkChain creates the SETMARK chain - the chain that sets the
|
|
||||||
// "to-be-masqueraded" mark and returns.
|
|
||||||
// Chains are idempotent, so we'll always create this.
|
|
||||||
func genSetMarkChain(markBit int) chain {
|
|
||||||
markValue := 1 << uint(markBit)
|
|
||||||
markDef := fmt.Sprintf("%#x/%#x", markValue, markValue)
|
|
||||||
ch := chain{
|
|
||||||
table: "nat",
|
|
||||||
name: SetMarkChainName,
|
|
||||||
rules: [][]string{{
|
|
||||||
"-m", "comment",
|
|
||||||
"--comment", "CNI portfwd masquerade mark",
|
|
||||||
"-j", "MARK",
|
|
||||||
"--set-xmark", markDef,
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// genMarkMasqChain creates the chain that masquerades all packets marked
|
|
||||||
// in the SETMARK chain
|
|
||||||
func genMarkMasqChain(markBit int) chain {
|
|
||||||
markValue := 1 << uint(markBit)
|
|
||||||
markDef := fmt.Sprintf("%#x/%#x", markValue, markValue)
|
|
||||||
ch := chain{
|
|
||||||
table: "nat",
|
|
||||||
name: MarkMasqChainName,
|
|
||||||
entryChains: []string{"POSTROUTING"},
|
|
||||||
// Only this entry chain needs to be prepended, because otherwise it is
|
|
||||||
// stomped on by the masquerading rules created by the CNI ptp and bridge
|
|
||||||
// plugins.
|
|
||||||
prependEntry: true,
|
|
||||||
entryRules: [][]string{{
|
|
||||||
"-m", "comment",
|
|
||||||
"--comment", "CNI portfwd requiring masquerade",
|
|
||||||
}},
|
|
||||||
rules: [][]string{{
|
|
||||||
"-m", "mark",
|
|
||||||
"--mark", markDef,
|
|
||||||
"-j", "MASQUERADE",
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
// enableLocalnetRouting tells the kernel not to treat 127/8 as a martian,
|
|
||||||
// so that connections with a source ip of 127/8 can cross a routing boundary.
|
|
||||||
func enableLocalnetRouting(ifName string) error {
|
|
||||||
routeLocalnetPath := "net.ipv4.conf." + ifName + ".route_localnet"
|
|
||||||
_, err := sysctl.Sysctl(routeLocalnetPath, "1")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// genOldSnatChain is no longer used, but used to be created. We'll try and
|
|
||||||
// tear it down in case the plugin version changed between ADD and DEL
|
|
||||||
func genOldSnatChain(netName, containerID string) chain {
|
|
||||||
return chain{
|
|
||||||
table: "nat",
|
|
||||||
name: utils.MustFormatChainNameWithPrefix(netName, containerID, "SN-"),
|
|
||||||
entryChains: []string{OldTopLevelSNATChainName},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unforwardPorts deletes any iptables rules created by this plugin.
|
|
||||||
// It should be idempotent - it will not error if the chain does not exist.
|
|
||||||
//
|
|
||||||
// We also need to be a bit clever about how we handle errors with initializing
|
|
||||||
// iptables. We may be on a system with no ip(6)tables, or no kernel support
|
|
||||||
// for that protocol. The ADD would be successful, since it only adds forwarding
|
|
||||||
// based on the addresses assigned to the container. However, at DELETE time we
|
|
||||||
// don't know which protocols were used.
|
|
||||||
// So, we first check that iptables is "generally OK" by doing a check. If
|
|
||||||
// not, we ignore the error, unless neither v4 nor v6 are OK.
|
|
||||||
func unforwardPorts(config *PortMapConf) error {
|
|
||||||
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
|
||||||
|
|
||||||
// Might be lying around from old versions
|
|
||||||
oldSnatChain := genOldSnatChain(config.Name, config.ContainerID)
|
|
||||||
|
|
||||||
ip4t := maybeGetIptables(false)
|
|
||||||
ip6t := maybeGetIptables(true)
|
|
||||||
if ip4t == nil && ip6t == nil {
|
|
||||||
return fmt.Errorf("neither iptables nor ip6tables usable")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip4t != nil {
|
|
||||||
if err := dnatChain.teardown(ip4t); err != nil {
|
|
||||||
return fmt.Errorf("could not teardown ipv4 dnat: %v", err)
|
|
||||||
}
|
|
||||||
oldSnatChain.teardown(ip4t)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip6t != nil {
|
|
||||||
if err := dnatChain.teardown(ip6t); err != nil {
|
|
||||||
return fmt.Errorf("could not teardown ipv6 dnat: %v", err)
|
|
||||||
}
|
|
||||||
oldSnatChain.teardown(ip6t)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// maybeGetIptables implements the soft error swallowing. If iptables is
|
|
||||||
// usable for the given protocol, returns a handle, otherwise nil
|
|
||||||
func maybeGetIptables(isV6 bool) *iptables.IPTables {
|
|
||||||
proto := iptables.ProtocolIPv4
|
|
||||||
if isV6 {
|
|
||||||
proto = iptables.ProtocolIPv6
|
|
||||||
}
|
|
||||||
|
|
||||||
ipt, err := iptables.NewWithProtocol(proto)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ipt.List("nat", "OUTPUT")
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return ipt
|
|
||||||
}
|
|
108
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/utils.go
generated
vendored
108
vendor/github.com/containernetworking/plugins/plugins/meta/portmap/utils.go
generated
vendored
@ -1,108 +0,0 @@
|
|||||||
// 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 portmap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
// fmtIpPort correctly formats ip:port literals for iptables and ip6tables -
|
|
||||||
// need to wrap v6 literals in a []
|
|
||||||
func fmtIpPort(ip net.IP, port int) string {
|
|
||||||
if ip.To4() == nil {
|
|
||||||
return fmt.Sprintf("[%s]:%d", ip.String(), port)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s:%d", ip.String(), port)
|
|
||||||
}
|
|
||||||
|
|
||||||
func localhostIP(isV6 bool) string {
|
|
||||||
if isV6 {
|
|
||||||
return "::1"
|
|
||||||
}
|
|
||||||
return "127.0.0.1"
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRoutableHostIF will try and determine which interface routes the container's
|
|
||||||
// traffic. This is the one on which we disable martian filtering.
|
|
||||||
func getRoutableHostIF(containerIP net.IP) string {
|
|
||||||
routes, err := netlink.RouteGet(containerIP)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, route := range routes {
|
|
||||||
link, err := netlink.LinkByIndex(route.LinkIndex)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return link.Attrs().Name
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// groupByProto groups port numbers by protocol
|
|
||||||
func groupByProto(entries []PortMapEntry) map[string][]int {
|
|
||||||
if len(entries) == 0 {
|
|
||||||
return map[string][]int{}
|
|
||||||
}
|
|
||||||
out := map[string][]int{}
|
|
||||||
for _, e := range entries {
|
|
||||||
_, ok := out[e.Protocol]
|
|
||||||
if ok {
|
|
||||||
out[e.Protocol] = append(out[e.Protocol], e.HostPort)
|
|
||||||
} else {
|
|
||||||
out[e.Protocol] = []int{e.HostPort}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitPortList splits a list of integers in to one or more comma-separated
|
|
||||||
// string values, for use by multiport. Multiport only allows up to 15 ports
|
|
||||||
// per entry.
|
|
||||||
func splitPortList(l []int) []string {
|
|
||||||
out := []string{}
|
|
||||||
|
|
||||||
acc := []string{}
|
|
||||||
for _, i := range l {
|
|
||||||
acc = append(acc, strconv.Itoa(i))
|
|
||||||
if len(acc) == 15 {
|
|
||||||
out = append(out, strings.Join(acc, ","))
|
|
||||||
acc = []string{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(acc) > 0 {
|
|
||||||
out = append(out, strings.Join(acc, ","))
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// trimComment makes sure no comment is over the iptables limit of 255 chars
|
|
||||||
func trimComment(val string) string {
|
|
||||||
if len(val) <= 255 {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
return val[0:253] + "..."
|
|
||||||
}
|
|
294
vendor/github.com/globalsign/mgo/bson/bson_corpus_spec_test_generator.go
generated
vendored
294
vendor/github.com/globalsign/mgo/bson/bson_corpus_spec_test_generator.go
generated
vendored
@ -1,294 +0,0 @@
|
|||||||
// +build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"html/template"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/globalsign/mgo/internal/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.SetFlags(0)
|
|
||||||
log.SetPrefix(name + ": ")
|
|
||||||
|
|
||||||
var g Generator
|
|
||||||
|
|
||||||
fmt.Fprintf(&g, "// Code generated by \"%s.go\"; DO NOT EDIT\n\n", name)
|
|
||||||
|
|
||||||
src := g.generate()
|
|
||||||
|
|
||||||
err := ioutil.WriteFile(fmt.Sprintf("%s.go", strings.TrimSuffix(name, "_generator")), src, 0644)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("writing output: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generator holds the state of the analysis. Primarily used to buffer
|
|
||||||
// the output for format.Source.
|
|
||||||
type Generator struct {
|
|
||||||
bytes.Buffer // Accumulated output.
|
|
||||||
}
|
|
||||||
|
|
||||||
// format returns the gofmt-ed contents of the Generator's buffer.
|
|
||||||
func (g *Generator) format() []byte {
|
|
||||||
src, err := format.Source(g.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
// Should never happen, but can arise when developing this code.
|
|
||||||
// The user can compile the output to see the error.
|
|
||||||
log.Printf("warning: internal error: invalid Go generated: %s", err)
|
|
||||||
log.Printf("warning: compile the package to analyze the error")
|
|
||||||
return g.Bytes()
|
|
||||||
}
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
|
|
||||||
// EVERYTHING ABOVE IS CONSTANT BETWEEN THE GENERATORS
|
|
||||||
|
|
||||||
const name = "bson_corpus_spec_test_generator"
|
|
||||||
|
|
||||||
func (g *Generator) generate() []byte {
|
|
||||||
|
|
||||||
testFiles, err := filepath.Glob("./specdata/specifications/source/bson-corpus/tests/*.json")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error reading bson-corpus files: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tests, err := g.loadTests(testFiles)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error loading tests: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := g.getTemplate()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error loading template: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl.Execute(&g.Buffer, tests)
|
|
||||||
|
|
||||||
return g.format()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) loadTests(filenames []string) ([]*testDef, error) {
|
|
||||||
var tests []*testDef
|
|
||||||
for _, filename := range filenames {
|
|
||||||
test, err := g.loadTest(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tests = append(tests, test)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tests, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) loadTest(filename string) (*testDef, error) {
|
|
||||||
content, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var testDef testDef
|
|
||||||
err = json.Unmarshal(content, &testDef)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
names := make(map[string]struct{})
|
|
||||||
|
|
||||||
for i := len(testDef.Valid) - 1; i >= 0; i-- {
|
|
||||||
if testDef.BsonType == "0x05" && testDef.Valid[i].Description == "subtype 0x02" {
|
|
||||||
testDef.Valid = append(testDef.Valid[:i], testDef.Valid[i+1:]...)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
name := cleanupFuncName(testDef.Description + "_" + testDef.Valid[i].Description)
|
|
||||||
nameIdx := name
|
|
||||||
j := 1
|
|
||||||
for {
|
|
||||||
if _, ok := names[nameIdx]; !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
nameIdx = fmt.Sprintf("%s_%d", name, j)
|
|
||||||
}
|
|
||||||
|
|
||||||
names[nameIdx] = struct{}{}
|
|
||||||
|
|
||||||
testDef.Valid[i].TestDef = &testDef
|
|
||||||
testDef.Valid[i].Name = nameIdx
|
|
||||||
testDef.Valid[i].StructTest = testDef.TestKey != "" &&
|
|
||||||
(testDef.BsonType != "0x05" || strings.Contains(testDef.Valid[i].Description, "0x00")) &&
|
|
||||||
!testDef.Deprecated
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := len(testDef.DecodeErrors) - 1; i >= 0; i-- {
|
|
||||||
if strings.Contains(testDef.DecodeErrors[i].Description, "UTF-8") {
|
|
||||||
testDef.DecodeErrors = append(testDef.DecodeErrors[:i], testDef.DecodeErrors[i+1:]...)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
name := cleanupFuncName(testDef.Description + "_" + testDef.DecodeErrors[i].Description)
|
|
||||||
nameIdx := name
|
|
||||||
j := 1
|
|
||||||
for {
|
|
||||||
if _, ok := names[nameIdx]; !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
nameIdx = fmt.Sprintf("%s_%d", name, j)
|
|
||||||
}
|
|
||||||
names[nameIdx] = struct{}{}
|
|
||||||
|
|
||||||
testDef.DecodeErrors[i].Name = nameIdx
|
|
||||||
}
|
|
||||||
|
|
||||||
return &testDef, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) getTemplate() (*template.Template, error) {
|
|
||||||
content := `package bson_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
"github.com/globalsign/mgo/bson"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testValid(c *C, in []byte, expected []byte, result interface{}) {
|
|
||||||
err := bson.Unmarshal(in, result)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
out, err := bson.Marshal(result)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
c.Assert(string(expected), Equals, string(out), Commentf("roundtrip failed for %T, expected '%x' but got '%x'", result, expected, out))
|
|
||||||
}
|
|
||||||
|
|
||||||
func testDecodeSkip(c *C, in []byte) {
|
|
||||||
err := bson.Unmarshal(in, &struct{}{})
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testDecodeError(c *C, in []byte, result interface{}) {
|
|
||||||
err := bson.Unmarshal(in, result)
|
|
||||||
c.Assert(err, Not(IsNil))
|
|
||||||
}
|
|
||||||
|
|
||||||
{{range .}}
|
|
||||||
{{range .Valid}}
|
|
||||||
func (s *S) Test{{.Name}}(c *C) {
|
|
||||||
b, err := hex.DecodeString("{{.Bson}}")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
{{if .CanonicalBson}}
|
|
||||||
cb, err := hex.DecodeString("{{.CanonicalBson}}")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
{{else}}
|
|
||||||
cb := b
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
var resultD bson.D
|
|
||||||
testValid(c, b, cb, &resultD)
|
|
||||||
{{if .StructTest}}var resultS struct {
|
|
||||||
Element {{.TestDef.GoType}} ` + "`bson:\"{{.TestDef.TestKey}}\"`" + `
|
|
||||||
}
|
|
||||||
testValid(c, b, cb, &resultS){{end}}
|
|
||||||
|
|
||||||
testDecodeSkip(c, b)
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{range .DecodeErrors}}
|
|
||||||
func (s *S) Test{{.Name}}(c *C) {
|
|
||||||
b, err := hex.DecodeString("{{.Bson}}")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
var resultD bson.D
|
|
||||||
testDecodeError(c, b, &resultD)
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
`
|
|
||||||
tmpl, err := template.New("").Parse(content)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tmpl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanupFuncName(name string) string {
|
|
||||||
return strings.Map(func(r rune) rune {
|
|
||||||
if (r >= 48 && r <= 57) || (r >= 65 && r <= 90) || (r >= 97 && r <= 122) {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
return '_'
|
|
||||||
}, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
type testDef struct {
|
|
||||||
Description string `json:"description"`
|
|
||||||
BsonType string `json:"bson_type"`
|
|
||||||
TestKey string `json:"test_key"`
|
|
||||||
Valid []*valid `json:"valid"`
|
|
||||||
DecodeErrors []*decodeError `json:"decodeErrors"`
|
|
||||||
Deprecated bool `json:"deprecated"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testDef) GoType() string {
|
|
||||||
switch t.BsonType {
|
|
||||||
case "0x01":
|
|
||||||
return "float64"
|
|
||||||
case "0x02":
|
|
||||||
return "string"
|
|
||||||
case "0x03":
|
|
||||||
return "bson.D"
|
|
||||||
case "0x04":
|
|
||||||
return "[]interface{}"
|
|
||||||
case "0x05":
|
|
||||||
return "[]byte"
|
|
||||||
case "0x07":
|
|
||||||
return "bson.ObjectId"
|
|
||||||
case "0x08":
|
|
||||||
return "bool"
|
|
||||||
case "0x09":
|
|
||||||
return "time.Time"
|
|
||||||
case "0x0E":
|
|
||||||
return "string"
|
|
||||||
case "0x10":
|
|
||||||
return "int32"
|
|
||||||
case "0x12":
|
|
||||||
return "int64"
|
|
||||||
case "0x13":
|
|
||||||
return "bson.Decimal"
|
|
||||||
default:
|
|
||||||
return "interface{}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type valid struct {
|
|
||||||
Description string `json:"description"`
|
|
||||||
Bson string `json:"bson"`
|
|
||||||
CanonicalBson string `json:"canonical_bson"`
|
|
||||||
|
|
||||||
Name string
|
|
||||||
StructTest bool
|
|
||||||
TestDef *testDef
|
|
||||||
}
|
|
||||||
|
|
||||||
type decodeError struct {
|
|
||||||
Description string `json:"description"`
|
|
||||||
Bson string `json:"bson"`
|
|
||||||
|
|
||||||
Name string
|
|
||||||
}
|
|
76
vendor/github.com/google/btree/btree_mem.go
generated
vendored
76
vendor/github.com/google/btree/btree_mem.go
generated
vendored
@ -1,76 +0,0 @@
|
|||||||
// Copyright 2014 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// This binary compares memory usage between btree and gollrb.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/btree"
|
|
||||||
"github.com/petar/GoLLRB/llrb"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
size = flag.Int("size", 1000000, "size of the tree to build")
|
|
||||||
degree = flag.Int("degree", 8, "degree of btree")
|
|
||||||
gollrb = flag.Bool("llrb", false, "use llrb instead of btree")
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
vals := rand.Perm(*size)
|
|
||||||
var t, v interface{}
|
|
||||||
v = vals
|
|
||||||
var stats runtime.MemStats
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
runtime.GC()
|
|
||||||
}
|
|
||||||
fmt.Println("-------- BEFORE ----------")
|
|
||||||
runtime.ReadMemStats(&stats)
|
|
||||||
fmt.Printf("%+v\n", stats)
|
|
||||||
start := time.Now()
|
|
||||||
if *gollrb {
|
|
||||||
tr := llrb.New()
|
|
||||||
for _, v := range vals {
|
|
||||||
tr.ReplaceOrInsert(llrb.Int(v))
|
|
||||||
}
|
|
||||||
t = tr // keep it around
|
|
||||||
} else {
|
|
||||||
tr := btree.New(*degree)
|
|
||||||
for _, v := range vals {
|
|
||||||
tr.ReplaceOrInsert(btree.Int(v))
|
|
||||||
}
|
|
||||||
t = tr // keep it around
|
|
||||||
}
|
|
||||||
fmt.Printf("%v inserts in %v\n", *size, time.Since(start))
|
|
||||||
fmt.Println("-------- AFTER ----------")
|
|
||||||
runtime.ReadMemStats(&stats)
|
|
||||||
fmt.Printf("%+v\n", stats)
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
runtime.GC()
|
|
||||||
}
|
|
||||||
fmt.Println("-------- AFTER GC ----------")
|
|
||||||
runtime.ReadMemStats(&stats)
|
|
||||||
fmt.Printf("%+v\n", stats)
|
|
||||||
if t == v {
|
|
||||||
fmt.Println("to make sure vals and tree aren't GC'd")
|
|
||||||
}
|
|
||||||
}
|
|
187
vendor/github.com/google/certificate-transparency-go/x509/root_darwin_arm_gen.go
generated
vendored
187
vendor/github.com/google/certificate-transparency-go/x509/root_darwin_arm_gen.go
generated
vendored
@ -1,187 +0,0 @@
|
|||||||
// Copyright 2015 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
|
|
||||||
|
|
||||||
// Generates root_darwin_armx.go.
|
|
||||||
//
|
|
||||||
// As of iOS 8, there is no API for querying the system trusted X.509 root
|
|
||||||
// certificates. We could use SecTrustEvaluate to verify that a trust chain
|
|
||||||
// exists for a certificate, but the x509 API requires returning the entire
|
|
||||||
// chain.
|
|
||||||
//
|
|
||||||
// Apple publishes the list of trusted root certificates for iOS on
|
|
||||||
// support.apple.com. So we parse the list and extract the certificates from
|
|
||||||
// an OS X machine and embed them into the x509 package.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/pem"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/google/certificate-transparency-go/x509"
|
|
||||||
)
|
|
||||||
|
|
||||||
var output = flag.String("output", "root_darwin_armx.go", "file name to write")
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
certs, err := selectCerts()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
fmt.Fprintf(buf, "// Code generated by root_darwin_arm_gen --output %s; DO NOT EDIT.\n", *output)
|
|
||||||
fmt.Fprintf(buf, "%s", header)
|
|
||||||
|
|
||||||
fmt.Fprintf(buf, "const systemRootsPEM = `\n")
|
|
||||||
for _, cert := range certs {
|
|
||||||
b := &pem.Block{
|
|
||||||
Type: "CERTIFICATE",
|
|
||||||
Bytes: cert.Raw,
|
|
||||||
}
|
|
||||||
if err := pem.Encode(buf, b); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Fprintf(buf, "`")
|
|
||||||
|
|
||||||
source, err := format.Source(buf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("source format error:", err)
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile(*output, source, 0644); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func selectCerts() ([]*x509.Certificate, error) {
|
|
||||||
ids, err := fetchCertIDs()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
scerts, err := sysCerts()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var certs []*x509.Certificate
|
|
||||||
for _, id := range ids {
|
|
||||||
if c, ok := scerts[id.fingerprint]; ok {
|
|
||||||
certs = append(certs, c)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("WARNING: cannot find certificate: %s (fingerprint: %s)\n", id.name, id.fingerprint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return certs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sysCerts() (certs map[string]*x509.Certificate, err error) {
|
|
||||||
cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
|
|
||||||
data, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
certs = make(map[string]*x509.Certificate)
|
|
||||||
for len(data) > 0 {
|
|
||||||
var block *pem.Block
|
|
||||||
block, data = pem.Decode(data)
|
|
||||||
if block == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cert, err := x509.ParseCertificate(block.Bytes)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fingerprint := sha256.Sum256(cert.Raw)
|
|
||||||
certs[hex.EncodeToString(fingerprint[:])] = cert
|
|
||||||
}
|
|
||||||
return certs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type certID struct {
|
|
||||||
name string
|
|
||||||
fingerprint string
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetchCertIDs fetches IDs of iOS X509 certificates from apple.com.
|
|
||||||
func fetchCertIDs() ([]certID, error) {
|
|
||||||
// Download the iOS 11 support page. The index for all iOS versions is here:
|
|
||||||
// https://support.apple.com/en-us/HT204132
|
|
||||||
resp, err := http.Get("https://support.apple.com/en-us/HT208125")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
text := string(body)
|
|
||||||
text = text[strings.Index(text, "<div id=trusted"):]
|
|
||||||
text = text[:strings.Index(text, "</div>")]
|
|
||||||
|
|
||||||
var ids []certID
|
|
||||||
cols := make(map[string]int)
|
|
||||||
for i, rowmatch := range regexp.MustCompile("(?s)<tr>(.*?)</tr>").FindAllStringSubmatch(text, -1) {
|
|
||||||
row := rowmatch[1]
|
|
||||||
if i == 0 {
|
|
||||||
// Parse table header row to extract column names
|
|
||||||
for i, match := range regexp.MustCompile("(?s)<th>(.*?)</th>").FindAllStringSubmatch(row, -1) {
|
|
||||||
cols[match[1]] = i
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
values := regexp.MustCompile("(?s)<td>(.*?)</td>").FindAllStringSubmatch(row, -1)
|
|
||||||
name := values[cols["Certificate name"]][1]
|
|
||||||
fingerprint := values[cols["Fingerprint (SHA-256)"]][1]
|
|
||||||
fingerprint = strings.Replace(fingerprint, "<br>", "", -1)
|
|
||||||
fingerprint = strings.Replace(fingerprint, "\n", "", -1)
|
|
||||||
fingerprint = strings.Replace(fingerprint, " ", "", -1)
|
|
||||||
fingerprint = strings.ToLower(fingerprint)
|
|
||||||
|
|
||||||
ids = append(ids, certID{
|
|
||||||
name: name,
|
|
||||||
fingerprint: fingerprint,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return ids, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const header = `
|
|
||||||
// Copyright 2015 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 cgo
|
|
||||||
// +build darwin
|
|
||||||
// +build arm arm64 ios
|
|
||||||
|
|
||||||
package x509
|
|
||||||
|
|
||||||
func loadSystemRoots() (*CertPool, error) {
|
|
||||||
p := NewCertPool()
|
|
||||||
p.AppendCertsFromPEM([]byte(systemRootsPEM))
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
`
|
|
55
vendor/github.com/google/certificate-transparency-go/x509/x509_test_import.go
generated
vendored
55
vendor/github.com/google/certificate-transparency-go/x509/x509_test_import.go
generated
vendored
@ -1,55 +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
|
|
||||||
|
|
||||||
// This file is run by the x509 tests to ensure that a program with minimal
|
|
||||||
// imports can sign certificates without errors resulting from missing hash
|
|
||||||
// functions.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
// START CT CHANGES
|
|
||||||
"github.com/google/certificate-transparency-go/x509"
|
|
||||||
"github.com/google/certificate-transparency-go/x509/pkix"
|
|
||||||
// END CT CHANGES
|
|
||||||
"encoding/pem"
|
|
||||||
"math/big"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
block, _ := pem.Decode([]byte(pemPrivateKey))
|
|
||||||
rsaPriv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
|
||||||
if err != nil {
|
|
||||||
panic("Failed to parse private key: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
template := x509.Certificate{
|
|
||||||
SerialNumber: big.NewInt(1),
|
|
||||||
Subject: pkix.Name{
|
|
||||||
CommonName: "test",
|
|
||||||
Organization: []string{"Σ Acme Co"},
|
|
||||||
},
|
|
||||||
NotBefore: time.Unix(1000, 0),
|
|
||||||
NotAfter: time.Unix(100000, 0),
|
|
||||||
KeyUsage: x509.KeyUsageCertSign,
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = x509.CreateCertificate(rand.Reader, &template, &template, &rsaPriv.PublicKey, rsaPriv); err != nil {
|
|
||||||
panic("failed to create certificate with basic imports: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
|
|
||||||
fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
|
|
||||||
/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
|
|
||||||
RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
|
|
||||||
EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
|
|
||||||
IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
|
|
||||||
tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
`
|
|
1
vendor/github.com/j-keck/arping/.gitignore
generated
vendored
1
vendor/github.com/j-keck/arping/.gitignore
generated
vendored
@ -1 +0,0 @@
|
|||||||
arping
|
|
22
vendor/github.com/j-keck/arping/LICENSE
generated
vendored
22
vendor/github.com/j-keck/arping/LICENSE
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014-2016 j-keck [jhyphenkeck@gmail.com]
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
29
vendor/github.com/j-keck/arping/README.md
generated
vendored
29
vendor/github.com/j-keck/arping/README.md
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
# arping
|
|
||||||
|
|
||||||
arping is a native go library to ping a host per arp datagram, or query a host mac address
|
|
||||||
|
|
||||||
The currently supported platforms are: Linux and BSD.
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
### arping library
|
|
||||||
|
|
||||||
* import this library per `import "github.com/j-keck/arping"`
|
|
||||||
* export GOPATH if not already (`export GOPATH=$PWD`)
|
|
||||||
* download the library `go get`
|
|
||||||
* run it `sudo -E go run <YOUR PROGRAMM>`
|
|
||||||
* or build it `go build`
|
|
||||||
|
|
||||||
|
|
||||||
The library requires raw socket access. So it must run as root, or with appropriate capabilities under linux: `sudo setcap cap_net_raw+ep <BIN>`.
|
|
||||||
|
|
||||||
For api doc and examples see: [godoc](http://godoc.org/github.com/j-keck/arping) or check the standalone under 'cmd/arping/main.go'.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### arping executable
|
|
||||||
|
|
||||||
To get a runnable pinger use `go get -u github.com/j-keck/arping/cmd/arping`. This will build the binary in $GOPATH/bin.
|
|
||||||
|
|
||||||
arping requires raw socket access. So it must run as root, or with appropriate capabilities under Linux: `sudo setcap cap_net_raw+ep <ARPING_PATH>`.
|
|
||||||
|
|
97
vendor/github.com/j-keck/arping/arp_datagram.go
generated
vendored
97
vendor/github.com/j-keck/arping/arp_datagram.go
generated
vendored
@ -1,97 +0,0 @@
|
|||||||
package arping
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
requestOper = 1
|
|
||||||
responseOper = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
type arpDatagram struct {
|
|
||||||
htype uint16 // Hardware Type
|
|
||||||
ptype uint16 // Protocol Type
|
|
||||||
hlen uint8 // Hardware address Length
|
|
||||||
plen uint8 // Protocol address length
|
|
||||||
oper uint16 // Operation 1->request, 2->response
|
|
||||||
sha []byte // Sender hardware address, length from Hlen
|
|
||||||
spa []byte // Sender protocol address, length from Plen
|
|
||||||
tha []byte // Target hardware address, length from Hlen
|
|
||||||
tpa []byte // Target protocol address, length from Plen
|
|
||||||
}
|
|
||||||
|
|
||||||
func newArpRequest(
|
|
||||||
srcMac net.HardwareAddr,
|
|
||||||
srcIP net.IP,
|
|
||||||
dstMac net.HardwareAddr,
|
|
||||||
dstIP net.IP) arpDatagram {
|
|
||||||
return arpDatagram{
|
|
||||||
htype: uint16(1),
|
|
||||||
ptype: uint16(0x0800),
|
|
||||||
hlen: uint8(6),
|
|
||||||
plen: uint8(4),
|
|
||||||
oper: uint16(requestOper),
|
|
||||||
sha: srcMac,
|
|
||||||
spa: srcIP.To4(),
|
|
||||||
tha: dstMac,
|
|
||||||
tpa: dstIP.To4()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (datagram arpDatagram) Marshal() []byte {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
binary.Write(buf, binary.BigEndian, datagram.htype)
|
|
||||||
binary.Write(buf, binary.BigEndian, datagram.ptype)
|
|
||||||
binary.Write(buf, binary.BigEndian, datagram.hlen)
|
|
||||||
binary.Write(buf, binary.BigEndian, datagram.plen)
|
|
||||||
binary.Write(buf, binary.BigEndian, datagram.oper)
|
|
||||||
buf.Write(datagram.sha)
|
|
||||||
buf.Write(datagram.spa)
|
|
||||||
buf.Write(datagram.tha)
|
|
||||||
buf.Write(datagram.tpa)
|
|
||||||
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (datagram arpDatagram) MarshalWithEthernetHeader() []byte {
|
|
||||||
// ethernet frame header
|
|
||||||
var ethernetHeader []byte
|
|
||||||
ethernetHeader = append(ethernetHeader, datagram.tha...)
|
|
||||||
ethernetHeader = append(ethernetHeader, datagram.sha...)
|
|
||||||
ethernetHeader = append(ethernetHeader, []byte{0x08, 0x06}...) // arp
|
|
||||||
|
|
||||||
return append(ethernetHeader, datagram.Marshal()...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (datagram arpDatagram) SenderIP() net.IP {
|
|
||||||
return net.IP(datagram.spa)
|
|
||||||
}
|
|
||||||
func (datagram arpDatagram) SenderMac() net.HardwareAddr {
|
|
||||||
return net.HardwareAddr(datagram.sha)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (datagram arpDatagram) IsResponseOf(request arpDatagram) bool {
|
|
||||||
return datagram.oper == responseOper && bytes.Compare(request.spa, datagram.tpa) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseArpDatagram(buffer []byte) arpDatagram {
|
|
||||||
var datagram arpDatagram
|
|
||||||
|
|
||||||
b := bytes.NewBuffer(buffer)
|
|
||||||
binary.Read(b, binary.BigEndian, &datagram.htype)
|
|
||||||
binary.Read(b, binary.BigEndian, &datagram.ptype)
|
|
||||||
binary.Read(b, binary.BigEndian, &datagram.hlen)
|
|
||||||
binary.Read(b, binary.BigEndian, &datagram.plen)
|
|
||||||
binary.Read(b, binary.BigEndian, &datagram.oper)
|
|
||||||
|
|
||||||
haLen := int(datagram.hlen)
|
|
||||||
paLen := int(datagram.plen)
|
|
||||||
datagram.sha = b.Next(haLen)
|
|
||||||
datagram.spa = b.Next(paLen)
|
|
||||||
datagram.tha = b.Next(haLen)
|
|
||||||
datagram.tpa = b.Next(paLen)
|
|
||||||
|
|
||||||
return datagram
|
|
||||||
}
|
|
230
vendor/github.com/j-keck/arping/arping.go
generated
vendored
230
vendor/github.com/j-keck/arping/arping.go
generated
vendored
@ -1,230 +0,0 @@
|
|||||||
// Package arping is a native go library to ping a host per arp datagram, or query a host mac address
|
|
||||||
//
|
|
||||||
// The currently supported platforms are: Linux and BSD.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// The library requires raw socket access. So it must run as root, or with appropriate capabilities under linux:
|
|
||||||
// `sudo setcap cap_net_raw+ep <BIN>`.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
//
|
|
||||||
// ping a host:
|
|
||||||
// ------------
|
|
||||||
// package main
|
|
||||||
// import ("fmt"; "github.com/j-keck/arping"; "net")
|
|
||||||
//
|
|
||||||
// func main(){
|
|
||||||
// dstIP := net.ParseIP("192.168.1.1")
|
|
||||||
// if hwAddr, duration, err := arping.Ping(dstIP); err != nil {
|
|
||||||
// fmt.Println(err)
|
|
||||||
// } else {
|
|
||||||
// fmt.Printf("%s (%s) %d usec\n", dstIP, hwAddr, duration/1000)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// resolve mac address:
|
|
||||||
// --------------------
|
|
||||||
// package main
|
|
||||||
// import ("fmt"; "github.com/j-keck/arping"; "net")
|
|
||||||
//
|
|
||||||
// func main(){
|
|
||||||
// dstIP := net.ParseIP("192.168.1.1")
|
|
||||||
// if hwAddr, _, err := arping.Ping(dstIP); err != nil {
|
|
||||||
// fmt.Println(err)
|
|
||||||
// } else {
|
|
||||||
// fmt.Printf("%s is at %s\n", dstIP, hwAddr)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// check if host is online:
|
|
||||||
// ------------------------
|
|
||||||
// package main
|
|
||||||
// import ("fmt"; "github.com/j-keck/arping"; "net")
|
|
||||||
//
|
|
||||||
// func main(){
|
|
||||||
// dstIP := net.ParseIP("192.168.1.1")
|
|
||||||
// _, _, err := arping.Ping(dstIP)
|
|
||||||
// if err == arping.ErrTimeout {
|
|
||||||
// fmt.Println("offline")
|
|
||||||
// }else if err != nil {
|
|
||||||
// fmt.Println(err.Error())
|
|
||||||
// }else{
|
|
||||||
// fmt.Println("online")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
package arping
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrTimeout error
|
|
||||||
ErrTimeout = errors.New("timeout")
|
|
||||||
|
|
||||||
verboseLog = log.New(ioutil.Discard, "", 0)
|
|
||||||
timeout = time.Duration(500 * time.Millisecond)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ping sends an arp ping to 'dstIP'
|
|
||||||
func Ping(dstIP net.IP) (net.HardwareAddr, time.Duration, error) {
|
|
||||||
if err := validateIP(dstIP); err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
iface, err := findUsableInterfaceForNetwork(dstIP)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
return PingOverIface(dstIP, *iface)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PingOverIfaceByName sends an arp ping over interface name 'ifaceName' to 'dstIP'
|
|
||||||
func PingOverIfaceByName(dstIP net.IP, ifaceName string) (net.HardwareAddr, time.Duration, error) {
|
|
||||||
if err := validateIP(dstIP); err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
iface, err := net.InterfaceByName(ifaceName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
return PingOverIface(dstIP, *iface)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PingOverIface sends an arp ping over interface 'iface' to 'dstIP'
|
|
||||||
func PingOverIface(dstIP net.IP, iface net.Interface) (net.HardwareAddr, time.Duration, error) {
|
|
||||||
if err := validateIP(dstIP); err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
srcMac := iface.HardwareAddr
|
|
||||||
srcIP, err := findIPInNetworkFromIface(dstIP, iface)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
broadcastMac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
|
||||||
request := newArpRequest(srcMac, srcIP, broadcastMac, dstIP)
|
|
||||||
|
|
||||||
if err := initialize(iface); err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
defer deinitialize()
|
|
||||||
|
|
||||||
type PingResult struct {
|
|
||||||
mac net.HardwareAddr
|
|
||||||
duration time.Duration
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
pingResultChan := make(chan PingResult)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
// send arp request
|
|
||||||
verboseLog.Printf("arping '%s' over interface: '%s' with address: '%s'\n", dstIP, iface.Name, srcIP)
|
|
||||||
if sendTime, err := send(request); err != nil {
|
|
||||||
pingResultChan <- PingResult{nil, 0, err}
|
|
||||||
} else {
|
|
||||||
for {
|
|
||||||
// receive arp response
|
|
||||||
response, receiveTime, err := receive()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
pingResultChan <- PingResult{nil, 0, err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if response.IsResponseOf(request) {
|
|
||||||
duration := receiveTime.Sub(sendTime)
|
|
||||||
verboseLog.Printf("process received arp: srcIP: '%s', srcMac: '%s'\n",
|
|
||||||
response.SenderIP(), response.SenderMac())
|
|
||||||
pingResultChan <- PingResult{response.SenderMac(), duration, err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
verboseLog.Printf("ignore received arp: srcIP: '%s', srcMac: '%s'\n",
|
|
||||||
response.SenderIP(), response.SenderMac())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case pingResult := <-pingResultChan:
|
|
||||||
return pingResult.mac, pingResult.duration, pingResult.err
|
|
||||||
case <-time.After(timeout):
|
|
||||||
return nil, 0, ErrTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GratuitousArp sends an gratuitous arp from 'srcIP'
|
|
||||||
func GratuitousArp(srcIP net.IP) error {
|
|
||||||
if err := validateIP(srcIP); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
iface, err := findUsableInterfaceForNetwork(srcIP)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return GratuitousArpOverIface(srcIP, *iface)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GratuitousArpOverIfaceByName sends an gratuitous arp over interface name 'ifaceName' from 'srcIP'
|
|
||||||
func GratuitousArpOverIfaceByName(srcIP net.IP, ifaceName string) error {
|
|
||||||
if err := validateIP(srcIP); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
iface, err := net.InterfaceByName(ifaceName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return GratuitousArpOverIface(srcIP, *iface)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GratuitousArpOverIface sends an gratuitous arp over interface 'iface' from 'srcIP'
|
|
||||||
func GratuitousArpOverIface(srcIP net.IP, iface net.Interface) error {
|
|
||||||
if err := validateIP(srcIP); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
srcMac := iface.HardwareAddr
|
|
||||||
broadcastMac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
|
||||||
request := newArpRequest(srcMac, srcIP, broadcastMac, srcIP)
|
|
||||||
|
|
||||||
if err := initialize(iface); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer deinitialize()
|
|
||||||
verboseLog.Printf("gratuitous arp over interface: '%s' with address: '%s'\n", iface.Name, srcIP)
|
|
||||||
_, err := send(request)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableVerboseLog enables verbose logging on stdout
|
|
||||||
func EnableVerboseLog() {
|
|
||||||
verboseLog = log.New(os.Stdout, "", 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTimeout sets ping timeout
|
|
||||||
func SetTimeout(t time.Duration) {
|
|
||||||
timeout = t
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateIP(ip net.IP) error {
|
|
||||||
// ip must be a valid V4 address
|
|
||||||
if len(ip.To4()) != net.IPv4len {
|
|
||||||
return fmt.Errorf("not a valid v4 Address: %s", ip)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
101
vendor/github.com/j-keck/arping/arping_bsd.go
generated
vendored
101
vendor/github.com/j-keck/arping/arping_bsd.go
generated
vendored
@ -1,101 +0,0 @@
|
|||||||
// +build darwin freebsd openbsd
|
|
||||||
|
|
||||||
package arping
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var bpf *os.File
|
|
||||||
var bpfFd int
|
|
||||||
var buflen int
|
|
||||||
|
|
||||||
var bpfArpFilter = []syscall.BpfInsn{
|
|
||||||
// make sure this is an arp packet
|
|
||||||
*syscall.BpfStmt(syscall.BPF_LD+syscall.BPF_H+syscall.BPF_ABS, 12),
|
|
||||||
*syscall.BpfJump(syscall.BPF_JMP+syscall.BPF_JEQ+syscall.BPF_K, 0x0806, 0, 1),
|
|
||||||
// if we passed all the tests, ask for the whole packet.
|
|
||||||
*syscall.BpfStmt(syscall.BPF_RET+syscall.BPF_K, -1),
|
|
||||||
// otherwise, drop it.
|
|
||||||
*syscall.BpfStmt(syscall.BPF_RET+syscall.BPF_K, 0),
|
|
||||||
}
|
|
||||||
|
|
||||||
func initialize(iface net.Interface) (err error) {
|
|
||||||
verboseLog.Println("search available /dev/bpfX")
|
|
||||||
for i := 0; i <= 10; i++ {
|
|
||||||
bpfPath := fmt.Sprintf("/dev/bpf%d", i)
|
|
||||||
bpf, err = os.OpenFile(bpfPath, os.O_RDWR, 0666)
|
|
||||||
if err != nil {
|
|
||||||
verboseLog.Printf(" open failed: %s - %s\n", bpfPath, err.Error())
|
|
||||||
} else {
|
|
||||||
verboseLog.Printf(" open success: %s\n", bpfPath)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bpfFd = int(bpf.Fd())
|
|
||||||
if bpfFd == -1 {
|
|
||||||
return errors.New("unable to open /dev/bpfX")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := syscall.SetBpfInterface(bpfFd, iface.Name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := syscall.SetBpfImmediate(bpfFd, 1); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
buflen, err = syscall.BpfBuflen(bpfFd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := syscall.SetBpf(bpfFd, bpfArpFilter); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := syscall.FlushBpf(bpfFd); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func send(request arpDatagram) (time.Time, error) {
|
|
||||||
_, err := syscall.Write(bpfFd, request.MarshalWithEthernetHeader())
|
|
||||||
return time.Now(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func receive() (arpDatagram, time.Time, error) {
|
|
||||||
buffer := make([]byte, buflen)
|
|
||||||
n, err := syscall.Read(bpfFd, buffer)
|
|
||||||
if err != nil {
|
|
||||||
return arpDatagram{}, time.Now(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// FreeBSD uses a different bpf header (bh_tstamp differ in it's size)
|
|
||||||
// https://www.freebsd.org/cgi/man.cgi?bpf(4)#BPF_HEADER
|
|
||||||
//
|
|
||||||
var bpfHdrLength int
|
|
||||||
if runtime.GOOS == "freebsd" {
|
|
||||||
bpfHdrLength = 26
|
|
||||||
} else {
|
|
||||||
bpfHdrLength = 18
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip bpf header + 14 bytes ethernet header
|
|
||||||
var hdrLength = bpfHdrLength + 14
|
|
||||||
|
|
||||||
return parseArpDatagram(buffer[hdrLength:n]), time.Now(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deinitialize() error {
|
|
||||||
return bpf.Close()
|
|
||||||
}
|
|
38
vendor/github.com/j-keck/arping/arping_linux.go
generated
vendored
38
vendor/github.com/j-keck/arping/arping_linux.go
generated
vendored
@ -1,38 +0,0 @@
|
|||||||
package arping
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var sock int
|
|
||||||
var toSockaddr syscall.SockaddrLinklayer
|
|
||||||
|
|
||||||
func initialize(iface net.Interface) error {
|
|
||||||
toSockaddr = syscall.SockaddrLinklayer{Ifindex: iface.Index}
|
|
||||||
|
|
||||||
// 1544 = htons(ETH_P_ARP)
|
|
||||||
const proto = 1544
|
|
||||||
var err error
|
|
||||||
sock, err = syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, proto)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func send(request arpDatagram) (time.Time, error) {
|
|
||||||
return time.Now(), syscall.Sendto(sock, request.MarshalWithEthernetHeader(), 0, &toSockaddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func receive() (arpDatagram, time.Time, error) {
|
|
||||||
buffer := make([]byte, 128)
|
|
||||||
n, _, err := syscall.Recvfrom(sock, buffer, 0)
|
|
||||||
if err != nil {
|
|
||||||
return arpDatagram{}, time.Now(), err
|
|
||||||
}
|
|
||||||
// skip 14 bytes ethernet header
|
|
||||||
return parseArpDatagram(buffer[14:n]), time.Now(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deinitialize() error {
|
|
||||||
return syscall.Close(sock)
|
|
||||||
}
|
|
28
vendor/github.com/j-keck/arping/arping_windows.go
generated
vendored
28
vendor/github.com/j-keck/arping/arping_windows.go
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
// windows currently not supported.
|
|
||||||
// dummy implementation to prevent compilation errors under windows
|
|
||||||
|
|
||||||
package arping
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var errWindowsNotSupported = errors.New("arping under windows not supported")
|
|
||||||
|
|
||||||
func initialize(iface net.Interface) error {
|
|
||||||
return errWindowsNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func send(request arpDatagram) (time.Time, error) {
|
|
||||||
return time.Now(), errWindowsNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func receive() (arpDatagram, time.Time, error) {
|
|
||||||
return arpDatagram{}, time.Now(), errWindowsNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func deinitialize() error {
|
|
||||||
return errWindowsNotSupported
|
|
||||||
}
|
|
1
vendor/github.com/j-keck/arping/go.mod
generated
vendored
1
vendor/github.com/j-keck/arping/go.mod
generated
vendored
@ -1 +0,0 @@
|
|||||||
module github.com/j-keck/arping
|
|
64
vendor/github.com/j-keck/arping/netutils.go
generated
vendored
64
vendor/github.com/j-keck/arping/netutils.go
generated
vendored
@ -1,64 +0,0 @@
|
|||||||
package arping
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func findIPInNetworkFromIface(dstIP net.IP, iface net.Interface) (net.IP, error) {
|
|
||||||
addrs, err := iface.Addrs()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, a := range addrs {
|
|
||||||
if ipnet, ok := a.(*net.IPNet); ok {
|
|
||||||
if ipnet.Contains(dstIP) {
|
|
||||||
return ipnet.IP, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("iface: '%s' can't reach ip: '%s'", iface.Name, dstIP)
|
|
||||||
}
|
|
||||||
|
|
||||||
func findUsableInterfaceForNetwork(dstIP net.IP) (*net.Interface, error) {
|
|
||||||
ifaces, err := net.Interfaces()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
isDown := func(iface net.Interface) bool {
|
|
||||||
return iface.Flags&1 == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
hasAddressInNetwork := func(iface net.Interface) bool {
|
|
||||||
if _, err := findIPInNetworkFromIface(dstIP, iface); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
verboseLog.Println("search usable interface")
|
|
||||||
logIfaceResult := func(msg string, iface net.Interface) {
|
|
||||||
verboseLog.Printf("%10s: %6s %18s %s", msg, iface.Name, iface.HardwareAddr, iface.Flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, iface := range ifaces {
|
|
||||||
if isDown(iface) {
|
|
||||||
logIfaceResult("DOWN", iface)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasAddressInNetwork(iface) {
|
|
||||||
logIfaceResult("OTHER NET", iface)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
logIfaceResult("USABLE", iface)
|
|
||||||
return &iface, nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("no usable interface found")
|
|
||||||
}
|
|
93
vendor/github.com/lib/pq/oid/gen.go
generated
vendored
93
vendor/github.com/lib/pq/oid/gen.go
generated
vendored
@ -1,93 +0,0 @@
|
|||||||
// +build ignore
|
|
||||||
|
|
||||||
// Generate the table of OID values
|
|
||||||
// Run with 'go run gen.go'.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OID represent a postgres Object Identifier Type.
|
|
||||||
type OID struct {
|
|
||||||
ID int
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns an upper case version of the oid type.
|
|
||||||
func (o OID) Name() string {
|
|
||||||
return strings.ToUpper(o.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
datname := os.Getenv("PGDATABASE")
|
|
||||||
sslmode := os.Getenv("PGSSLMODE")
|
|
||||||
|
|
||||||
if datname == "" {
|
|
||||||
os.Setenv("PGDATABASE", "pqgotest")
|
|
||||||
}
|
|
||||||
|
|
||||||
if sslmode == "" {
|
|
||||||
os.Setenv("PGSSLMODE", "disable")
|
|
||||||
}
|
|
||||||
|
|
||||||
db, err := sql.Open("postgres", "")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
rows, err := db.Query(`
|
|
||||||
SELECT typname, oid
|
|
||||||
FROM pg_type WHERE oid < 10000
|
|
||||||
ORDER BY oid;
|
|
||||||
`)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
oids := make([]*OID, 0)
|
|
||||||
for rows.Next() {
|
|
||||||
var oid OID
|
|
||||||
if err = rows.Scan(&oid.Type, &oid.ID); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
oids = append(oids, &oid)
|
|
||||||
}
|
|
||||||
if err = rows.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
cmd := exec.Command("gofmt")
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
w, err := cmd.StdinPipe()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
f, err := os.Create("types.go")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
cmd.Stdout = f
|
|
||||||
err = cmd.Start()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.")
|
|
||||||
fmt.Fprintln(w, "\npackage oid")
|
|
||||||
fmt.Fprintln(w, "const (")
|
|
||||||
for _, oid := range oids {
|
|
||||||
fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, ")")
|
|
||||||
fmt.Fprintln(w, "var TypeName = map[Oid]string{")
|
|
||||||
for _, oid := range oids {
|
|
||||||
fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name())
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, "}")
|
|
||||||
w.Close()
|
|
||||||
cmd.Wait()
|
|
||||||
}
|
|
144
vendor/github.com/miekg/dns/duplicate_generate.go
generated
vendored
144
vendor/github.com/miekg/dns/duplicate_generate.go
generated
vendored
@ -1,144 +0,0 @@
|
|||||||
//+build ignore
|
|
||||||
|
|
||||||
// types_generate.go is meant to run with go generate. It will use
|
|
||||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
|
||||||
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
|
||||||
// methods (len, Header, copy) based on the struct tags. The generated source is
|
|
||||||
// written to ztypes.go, and is meant to be checked into git.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"go/importer"
|
|
||||||
"go/types"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var packageHdr = `
|
|
||||||
// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
`
|
|
||||||
|
|
||||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
|
||||||
st, ok := t.Underlying().(*types.Struct)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
|
||||||
return st, false
|
|
||||||
}
|
|
||||||
if st.Field(0).Anonymous() {
|
|
||||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
|
||||||
return st, true
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Import and type-check the package
|
|
||||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
|
||||||
fatalIfErr(err)
|
|
||||||
scope := pkg.Scope()
|
|
||||||
|
|
||||||
// Collect actual types (*X)
|
|
||||||
var namedTypes []string
|
|
||||||
for _, name := range scope.Names() {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
if o == nil || !o.Exported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "PrivateRR" || name == "OPT" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
namedTypes = append(namedTypes, o.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
b.WriteString(packageHdr)
|
|
||||||
|
|
||||||
// Generate the duplicate check for each type.
|
|
||||||
fmt.Fprint(b, "// isDuplicate() functions\n\n")
|
|
||||||
for _, name := range namedTypes {
|
|
||||||
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
|
||||||
if isEmbedded {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "func (r1 *%s) isDuplicate(_r2 RR) bool {\n", name)
|
|
||||||
fmt.Fprintf(b, "r2, ok := _r2.(*%s)\n", name)
|
|
||||||
fmt.Fprint(b, "if !ok { return false }\n")
|
|
||||||
fmt.Fprint(b, "_ = r2\n")
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
|
||||||
field := st.Field(i).Name()
|
|
||||||
o2 := func(s string) { fmt.Fprintf(b, s+"\n", field, field) }
|
|
||||||
o3 := func(s string) { fmt.Fprintf(b, s+"\n", field, field, field) }
|
|
||||||
|
|
||||||
// For some reason, a and aaaa don't pop up as *types.Slice here (mostly like because the are
|
|
||||||
// *indirectly* defined as a slice in the net package).
|
|
||||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
|
||||||
o2("if len(r1.%s) != len(r2.%s) {\nreturn false\n}")
|
|
||||||
|
|
||||||
if st.Tag(i) == `dns:"cdomain-name"` || st.Tag(i) == `dns:"domain-name"` {
|
|
||||||
o3(`for i := 0; i < len(r1.%s); i++ {
|
|
||||||
if !isDulicateName(r1.%s[i], r2.%s[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
o3(`for i := 0; i < len(r1.%s); i++ {
|
|
||||||
if r1.%s[i] != r2.%s[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch st.Tag(i) {
|
|
||||||
case `dns:"-"`:
|
|
||||||
// ignored
|
|
||||||
case `dns:"a"`, `dns:"aaaa"`:
|
|
||||||
o2("if !r1.%s.Equal(r2.%s) {\nreturn false\n}")
|
|
||||||
case `dns:"cdomain-name"`, `dns:"domain-name"`:
|
|
||||||
o2("if !isDulicateName(r1.%s, r2.%s) {\nreturn false\n}")
|
|
||||||
default:
|
|
||||||
o2("if r1.%s != r2.%s {\nreturn false\n}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "return true\n}\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// gofmt
|
|
||||||
res, err := format.Source(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
b.WriteTo(os.Stderr)
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// write result
|
|
||||||
f, err := os.Create("zduplicate.go")
|
|
||||||
fatalIfErr(err)
|
|
||||||
defer f.Close()
|
|
||||||
f.Write(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func fatalIfErr(err error) {
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
328
vendor/github.com/miekg/dns/msg_generate.go
generated
vendored
328
vendor/github.com/miekg/dns/msg_generate.go
generated
vendored
@ -1,328 +0,0 @@
|
|||||||
//+build ignore
|
|
||||||
|
|
||||||
// msg_generate.go is meant to run with go generate. It will use
|
|
||||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
|
||||||
// it will generate pack/unpack methods based on the struct tags. The generated source is
|
|
||||||
// written to zmsg.go, and is meant to be checked into git.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"go/importer"
|
|
||||||
"go/types"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var packageHdr = `
|
|
||||||
// Code generated by "go run msg_generate.go"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
`
|
|
||||||
|
|
||||||
// getTypeStruct will take a type and the package scope, and return the
|
|
||||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
|
||||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
|
||||||
// the RR interface). The bool return value indicates if embedded structs were
|
|
||||||
// resolved.
|
|
||||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
|
||||||
st, ok := t.Underlying().(*types.Struct)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
|
||||||
return st, false
|
|
||||||
}
|
|
||||||
if st.Field(0).Anonymous() {
|
|
||||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
|
||||||
return st, true
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Import and type-check the package
|
|
||||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
|
||||||
fatalIfErr(err)
|
|
||||||
scope := pkg.Scope()
|
|
||||||
|
|
||||||
// Collect actual types (*X)
|
|
||||||
var namedTypes []string
|
|
||||||
for _, name := range scope.Names() {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
if o == nil || !o.Exported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if name == "PrivateRR" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if corresponding TypeX exists
|
|
||||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
|
||||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
namedTypes = append(namedTypes, o.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
b.WriteString(packageHdr)
|
|
||||||
|
|
||||||
fmt.Fprint(b, "// pack*() functions\n\n")
|
|
||||||
for _, name := range namedTypes {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
|
||||||
|
|
||||||
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {\n", name)
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
|
||||||
o := func(s string) {
|
|
||||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
|
||||||
fmt.Fprint(b, `if err != nil {
|
|
||||||
return off, err
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
|
||||||
switch st.Tag(i) {
|
|
||||||
case `dns:"-"`: // ignored
|
|
||||||
case `dns:"txt"`:
|
|
||||||
o("off, err = packStringTxt(rr.%s, msg, off)\n")
|
|
||||||
case `dns:"opt"`:
|
|
||||||
o("off, err = packDataOpt(rr.%s, msg, off)\n")
|
|
||||||
case `dns:"nsec"`:
|
|
||||||
o("off, err = packDataNsec(rr.%s, msg, off)\n")
|
|
||||||
case `dns:"domain-name"`:
|
|
||||||
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, false)\n")
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case st.Tag(i) == `dns:"-"`: // ignored
|
|
||||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
|
||||||
o("off, err = packDomainName(rr.%s, msg, off, compression, compress)\n")
|
|
||||||
case st.Tag(i) == `dns:"domain-name"`:
|
|
||||||
o("off, err = packDomainName(rr.%s, msg, off, compression, false)\n")
|
|
||||||
case st.Tag(i) == `dns:"a"`:
|
|
||||||
o("off, err = packDataA(rr.%s, msg, off)\n")
|
|
||||||
case st.Tag(i) == `dns:"aaaa"`:
|
|
||||||
o("off, err = packDataAAAA(rr.%s, msg, off)\n")
|
|
||||||
case st.Tag(i) == `dns:"uint48"`:
|
|
||||||
o("off, err = packUint48(rr.%s, msg, off)\n")
|
|
||||||
case st.Tag(i) == `dns:"txt"`:
|
|
||||||
o("off, err = packString(rr.%s, msg, off)\n")
|
|
||||||
|
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base32`): // size-base32 can be packed just like base32
|
|
||||||
fallthrough
|
|
||||||
case st.Tag(i) == `dns:"base32"`:
|
|
||||||
o("off, err = packStringBase32(rr.%s, msg, off)\n")
|
|
||||||
|
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`): // size-base64 can be packed just like base64
|
|
||||||
fallthrough
|
|
||||||
case st.Tag(i) == `dns:"base64"`:
|
|
||||||
o("off, err = packStringBase64(rr.%s, msg, off)\n")
|
|
||||||
|
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:SaltLength`):
|
|
||||||
// directly write instead of using o() so we get the error check in the correct place
|
|
||||||
field := st.Field(i).Name()
|
|
||||||
fmt.Fprintf(b, `// Only pack salt if value is not "-", i.e. empty
|
|
||||||
if rr.%s != "-" {
|
|
||||||
off, err = packStringHex(rr.%s, msg, off)
|
|
||||||
if err != nil {
|
|
||||||
return off, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`, field, field)
|
|
||||||
continue
|
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): // size-hex can be packed just like hex
|
|
||||||
fallthrough
|
|
||||||
case st.Tag(i) == `dns:"hex"`:
|
|
||||||
o("off, err = packStringHex(rr.%s, msg, off)\n")
|
|
||||||
case st.Tag(i) == `dns:"any"`:
|
|
||||||
o("off, err = packStringAny(rr.%s, msg, off)\n")
|
|
||||||
case st.Tag(i) == `dns:"octet"`:
|
|
||||||
o("off, err = packStringOctet(rr.%s, msg, off)\n")
|
|
||||||
case st.Tag(i) == "":
|
|
||||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
|
||||||
case types.Uint8:
|
|
||||||
o("off, err = packUint8(rr.%s, msg, off)\n")
|
|
||||||
case types.Uint16:
|
|
||||||
o("off, err = packUint16(rr.%s, msg, off)\n")
|
|
||||||
case types.Uint32:
|
|
||||||
o("off, err = packUint32(rr.%s, msg, off)\n")
|
|
||||||
case types.Uint64:
|
|
||||||
o("off, err = packUint64(rr.%s, msg, off)\n")
|
|
||||||
case types.String:
|
|
||||||
o("off, err = packString(rr.%s, msg, off)\n")
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name())
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Fprintln(b, "return off, nil }\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprint(b, "// unpack*() functions\n\n")
|
|
||||||
for _, name := range namedTypes {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
|
||||||
|
|
||||||
fmt.Fprintf(b, "func (rr *%s) unpack(msg []byte, off int) (off1 int, err error) {\n", name)
|
|
||||||
fmt.Fprint(b, `rdStart := off
|
|
||||||
_ = rdStart
|
|
||||||
|
|
||||||
`)
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
|
||||||
o := func(s string) {
|
|
||||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
|
||||||
fmt.Fprint(b, `if err != nil {
|
|
||||||
return off, err
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// size-* are special, because they reference a struct member we should use for the length.
|
|
||||||
if strings.HasPrefix(st.Tag(i), `dns:"size-`) {
|
|
||||||
structMember := structMember(st.Tag(i))
|
|
||||||
structTag := structTag(st.Tag(i))
|
|
||||||
switch structTag {
|
|
||||||
case "hex":
|
|
||||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringHex(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
|
||||||
case "base32":
|
|
||||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase32(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
|
||||||
case "base64":
|
|
||||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase64(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
|
||||||
}
|
|
||||||
fmt.Fprint(b, `if err != nil {
|
|
||||||
return off, err
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
|
||||||
switch st.Tag(i) {
|
|
||||||
case `dns:"-"`: // ignored
|
|
||||||
case `dns:"txt"`:
|
|
||||||
o("rr.%s, off, err = unpackStringTxt(msg, off)\n")
|
|
||||||
case `dns:"opt"`:
|
|
||||||
o("rr.%s, off, err = unpackDataOpt(msg, off)\n")
|
|
||||||
case `dns:"nsec"`:
|
|
||||||
o("rr.%s, off, err = unpackDataNsec(msg, off)\n")
|
|
||||||
case `dns:"domain-name"`:
|
|
||||||
o("rr.%s, off, err = unpackDataDomainNames(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch st.Tag(i) {
|
|
||||||
case `dns:"-"`: // ignored
|
|
||||||
case `dns:"cdomain-name"`:
|
|
||||||
fallthrough
|
|
||||||
case `dns:"domain-name"`:
|
|
||||||
o("rr.%s, off, err = UnpackDomainName(msg, off)\n")
|
|
||||||
case `dns:"a"`:
|
|
||||||
o("rr.%s, off, err = unpackDataA(msg, off)\n")
|
|
||||||
case `dns:"aaaa"`:
|
|
||||||
o("rr.%s, off, err = unpackDataAAAA(msg, off)\n")
|
|
||||||
case `dns:"uint48"`:
|
|
||||||
o("rr.%s, off, err = unpackUint48(msg, off)\n")
|
|
||||||
case `dns:"txt"`:
|
|
||||||
o("rr.%s, off, err = unpackString(msg, off)\n")
|
|
||||||
case `dns:"base32"`:
|
|
||||||
o("rr.%s, off, err = unpackStringBase32(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
|
||||||
case `dns:"base64"`:
|
|
||||||
o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
|
||||||
case `dns:"hex"`:
|
|
||||||
o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
|
||||||
case `dns:"any"`:
|
|
||||||
o("rr.%s, off, err = unpackStringAny(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
|
||||||
case `dns:"octet"`:
|
|
||||||
o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
|
|
||||||
case "":
|
|
||||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
|
||||||
case types.Uint8:
|
|
||||||
o("rr.%s, off, err = unpackUint8(msg, off)\n")
|
|
||||||
case types.Uint16:
|
|
||||||
o("rr.%s, off, err = unpackUint16(msg, off)\n")
|
|
||||||
case types.Uint32:
|
|
||||||
o("rr.%s, off, err = unpackUint32(msg, off)\n")
|
|
||||||
case types.Uint64:
|
|
||||||
o("rr.%s, off, err = unpackUint64(msg, off)\n")
|
|
||||||
case types.String:
|
|
||||||
o("rr.%s, off, err = unpackString(msg, off)\n")
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name())
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
|
||||||
}
|
|
||||||
// If we've hit len(msg) we return without error.
|
|
||||||
if i < st.NumFields()-1 {
|
|
||||||
fmt.Fprintf(b, `if off == len(msg) {
|
|
||||||
return off, nil
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "return off, nil }\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// gofmt
|
|
||||||
res, err := format.Source(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
b.WriteTo(os.Stderr)
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// write result
|
|
||||||
f, err := os.Create("zmsg.go")
|
|
||||||
fatalIfErr(err)
|
|
||||||
defer f.Close()
|
|
||||||
f.Write(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
// structMember will take a tag like dns:"size-base32:SaltLength" and return the last part of this string.
|
|
||||||
func structMember(s string) string {
|
|
||||||
fields := strings.Split(s, ":")
|
|
||||||
if len(fields) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
f := fields[len(fields)-1]
|
|
||||||
// f should have a closing "
|
|
||||||
if len(f) > 1 {
|
|
||||||
return f[:len(f)-1]
|
|
||||||
}
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
// structTag will take a tag like dns:"size-base32:SaltLength" and return base32.
|
|
||||||
func structTag(s string) string {
|
|
||||||
fields := strings.Split(s, ":")
|
|
||||||
if len(fields) < 2 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fields[1][len("\"size-"):]
|
|
||||||
}
|
|
||||||
|
|
||||||
func fatalIfErr(err error) {
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
287
vendor/github.com/miekg/dns/types_generate.go
generated
vendored
287
vendor/github.com/miekg/dns/types_generate.go
generated
vendored
@ -1,287 +0,0 @@
|
|||||||
//+build ignore
|
|
||||||
|
|
||||||
// types_generate.go is meant to run with go generate. It will use
|
|
||||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
|
||||||
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
|
||||||
// methods (len, Header, copy) based on the struct tags. The generated source is
|
|
||||||
// written to ztypes.go, and is meant to be checked into git.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"go/importer"
|
|
||||||
"go/types"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
var skipLen = map[string]struct{}{
|
|
||||||
"NSEC": {},
|
|
||||||
"NSEC3": {},
|
|
||||||
"OPT": {},
|
|
||||||
"CSYNC": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
var packageHdr = `
|
|
||||||
// Code generated by "go run types_generate.go"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/base64"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
`
|
|
||||||
|
|
||||||
var TypeToRR = template.Must(template.New("TypeToRR").Parse(`
|
|
||||||
// TypeToRR is a map of constructors for each RR type.
|
|
||||||
var TypeToRR = map[uint16]func() RR{
|
|
||||||
{{range .}}{{if ne . "RFC3597"}} Type{{.}}: func() RR { return new({{.}}) },
|
|
||||||
{{end}}{{end}} }
|
|
||||||
|
|
||||||
`))
|
|
||||||
|
|
||||||
var typeToString = template.Must(template.New("typeToString").Parse(`
|
|
||||||
// TypeToString is a map of strings for each RR type.
|
|
||||||
var TypeToString = map[uint16]string{
|
|
||||||
{{range .}}{{if ne . "NSAPPTR"}} Type{{.}}: "{{.}}",
|
|
||||||
{{end}}{{end}} TypeNSAPPTR: "NSAP-PTR",
|
|
||||||
}
|
|
||||||
|
|
||||||
`))
|
|
||||||
|
|
||||||
var headerFunc = template.Must(template.New("headerFunc").Parse(`
|
|
||||||
{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
`))
|
|
||||||
|
|
||||||
// getTypeStruct will take a type and the package scope, and return the
|
|
||||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
|
||||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
|
||||||
// the RR interface). The bool return value indicates if embedded structs were
|
|
||||||
// resolved.
|
|
||||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
|
||||||
st, ok := t.Underlying().(*types.Struct)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
|
||||||
return st, false
|
|
||||||
}
|
|
||||||
if st.Field(0).Anonymous() {
|
|
||||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
|
||||||
return st, true
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Import and type-check the package
|
|
||||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
|
||||||
fatalIfErr(err)
|
|
||||||
scope := pkg.Scope()
|
|
||||||
|
|
||||||
// Collect constants like TypeX
|
|
||||||
var numberedTypes []string
|
|
||||||
for _, name := range scope.Names() {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
if o == nil || !o.Exported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b, ok := o.Type().(*types.Basic)
|
|
||||||
if !ok || b.Kind() != types.Uint16 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(o.Name(), "Type") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := strings.TrimPrefix(o.Name(), "Type")
|
|
||||||
if name == "PrivateRR" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
numberedTypes = append(numberedTypes, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect actual types (*X)
|
|
||||||
var namedTypes []string
|
|
||||||
for _, name := range scope.Names() {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
if o == nil || !o.Exported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if name == "PrivateRR" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if corresponding TypeX exists
|
|
||||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
|
||||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
namedTypes = append(namedTypes, o.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
b.WriteString(packageHdr)
|
|
||||||
|
|
||||||
// Generate TypeToRR
|
|
||||||
fatalIfErr(TypeToRR.Execute(b, namedTypes))
|
|
||||||
|
|
||||||
// Generate typeToString
|
|
||||||
fatalIfErr(typeToString.Execute(b, numberedTypes))
|
|
||||||
|
|
||||||
// Generate headerFunc
|
|
||||||
fatalIfErr(headerFunc.Execute(b, namedTypes))
|
|
||||||
|
|
||||||
// Generate len()
|
|
||||||
fmt.Fprint(b, "// len() functions\n")
|
|
||||||
for _, name := range namedTypes {
|
|
||||||
if _, ok := skipLen[name]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
|
||||||
if isEmbedded {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "func (rr *%s) len(off int, compression map[string]struct{}) int {\n", name)
|
|
||||||
fmt.Fprintf(b, "l := rr.Hdr.len(off, compression)\n")
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
|
||||||
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
|
|
||||||
|
|
||||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
|
||||||
switch st.Tag(i) {
|
|
||||||
case `dns:"-"`:
|
|
||||||
// ignored
|
|
||||||
case `dns:"cdomain-name"`:
|
|
||||||
o("for _, x := range rr.%s { l += domainNameLen(x, off+l, compression, true) }\n")
|
|
||||||
case `dns:"domain-name"`:
|
|
||||||
o("for _, x := range rr.%s { l += domainNameLen(x, off+l, compression, false) }\n")
|
|
||||||
case `dns:"txt"`:
|
|
||||||
o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case st.Tag(i) == `dns:"-"`:
|
|
||||||
// ignored
|
|
||||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
|
||||||
o("l += domainNameLen(rr.%s, off+l, compression, true)\n")
|
|
||||||
case st.Tag(i) == `dns:"domain-name"`:
|
|
||||||
o("l += domainNameLen(rr.%s, off+l, compression, false)\n")
|
|
||||||
case st.Tag(i) == `dns:"octet"`:
|
|
||||||
o("l += len(rr.%s)\n")
|
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
|
|
||||||
fallthrough
|
|
||||||
case st.Tag(i) == `dns:"base64"`:
|
|
||||||
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
|
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:`): // this has an extra field where the length is stored
|
|
||||||
o("l += len(rr.%s)/2\n")
|
|
||||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
|
|
||||||
fallthrough
|
|
||||||
case st.Tag(i) == `dns:"hex"`:
|
|
||||||
o("l += len(rr.%s)/2 + 1\n")
|
|
||||||
case st.Tag(i) == `dns:"any"`:
|
|
||||||
o("l += len(rr.%s)\n")
|
|
||||||
case st.Tag(i) == `dns:"a"`:
|
|
||||||
o("l += net.IPv4len // %s\n")
|
|
||||||
case st.Tag(i) == `dns:"aaaa"`:
|
|
||||||
o("l += net.IPv6len // %s\n")
|
|
||||||
case st.Tag(i) == `dns:"txt"`:
|
|
||||||
o("for _, t := range rr.%s { l += len(t) + 1 }\n")
|
|
||||||
case st.Tag(i) == `dns:"uint48"`:
|
|
||||||
o("l += 6 // %s\n")
|
|
||||||
case st.Tag(i) == "":
|
|
||||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
|
||||||
case types.Uint8:
|
|
||||||
o("l++ // %s\n")
|
|
||||||
case types.Uint16:
|
|
||||||
o("l += 2 // %s\n")
|
|
||||||
case types.Uint32:
|
|
||||||
o("l += 4 // %s\n")
|
|
||||||
case types.Uint64:
|
|
||||||
o("l += 8 // %s\n")
|
|
||||||
case types.String:
|
|
||||||
o("l += len(rr.%s) + 1\n")
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name())
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "return l }\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate copy()
|
|
||||||
fmt.Fprint(b, "// copy() functions\n")
|
|
||||||
for _, name := range namedTypes {
|
|
||||||
o := scope.Lookup(name)
|
|
||||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
|
||||||
if isEmbedded {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
|
|
||||||
fields := []string{"rr.Hdr"}
|
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
|
||||||
f := st.Field(i).Name()
|
|
||||||
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
|
||||||
t := sl.Underlying().String()
|
|
||||||
t = strings.TrimPrefix(t, "[]")
|
|
||||||
if strings.Contains(t, ".") {
|
|
||||||
splits := strings.Split(t, ".")
|
|
||||||
t = splits[len(splits)-1]
|
|
||||||
}
|
|
||||||
// For the EDNS0 interface (used in the OPT RR), we need to call the copy method on each element.
|
|
||||||
if t == "EDNS0" {
|
|
||||||
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s));\nfor i,e := range rr.%s {\n %s[i] = e.copy()\n}\n",
|
|
||||||
f, t, f, f, f)
|
|
||||||
fields = append(fields, f)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
|
|
||||||
f, t, f, f, f)
|
|
||||||
fields = append(fields, f)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if st.Field(i).Type().String() == "net.IP" {
|
|
||||||
fields = append(fields, "copyIP(rr."+f+")")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fields = append(fields, "rr."+f)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "return &%s{%s}\n", name, strings.Join(fields, ","))
|
|
||||||
fmt.Fprintf(b, "}\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// gofmt
|
|
||||||
res, err := format.Source(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
b.WriteTo(os.Stderr)
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// write result
|
|
||||||
f, err := os.Create("ztypes.go")
|
|
||||||
fatalIfErr(err)
|
|
||||||
defer f.Close()
|
|
||||||
f.Write(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func fatalIfErr(err error) {
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
27
vendor/github.com/safchain/ethtool/.gitignore
generated
vendored
27
vendor/github.com/safchain/ethtool/.gitignore
generated
vendored
@ -1,27 +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
|
|
||||||
*.prof
|
|
||||||
|
|
||||||
# Skip compiled example binary file
|
|
||||||
/example/example
|
|
1
vendor/github.com/safchain/ethtool/.travis.yml
generated
vendored
1
vendor/github.com/safchain/ethtool/.travis.yml
generated
vendored
@ -1 +0,0 @@
|
|||||||
language: go
|
|
202
vendor/github.com/safchain/ethtool/LICENSE
generated
vendored
202
vendor/github.com/safchain/ethtool/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
4
vendor/github.com/safchain/ethtool/Makefile
generated
vendored
4
vendor/github.com/safchain/ethtool/Makefile
generated
vendored
@ -1,4 +0,0 @@
|
|||||||
all: build
|
|
||||||
|
|
||||||
build:
|
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
|
|
60
vendor/github.com/safchain/ethtool/README.md
generated
vendored
60
vendor/github.com/safchain/ethtool/README.md
generated
vendored
@ -1,60 +0,0 @@
|
|||||||
# ethtool go package #
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/safchain/ethtool.png?branch=master)](https://travis-ci.org/safchain/ethtool)
|
|
||||||
[![GoDoc](https://godoc.org/github.com/safchain/ethtool?status.svg)](https://godoc.org/github.com/safchain/ethtool)
|
|
||||||
|
|
||||||
The ethtool package aims to provide a library giving a simple access to the Linux SIOCETHTOOL ioctl operations. It can be used to retrieve informations from a network device like statistics, driver related informations or even the peer of a VETH interface.
|
|
||||||
|
|
||||||
## Build and Test ##
|
|
||||||
|
|
||||||
go get command:
|
|
||||||
|
|
||||||
go get github.com/safchain/ethtool
|
|
||||||
|
|
||||||
Testing
|
|
||||||
|
|
||||||
In order to run te
|
|
||||||
|
|
||||||
go test github.com/safchain/ethtool
|
|
||||||
|
|
||||||
## Examples ##
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/safchain/ethtool"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
ethHandle, err := ethtool.NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
defer ethHandle.Close()
|
|
||||||
|
|
||||||
// Retrieve tx from eth0
|
|
||||||
stats, err := ethHandle.Stats("eth0")
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
fmt.Printf("TX: %d\n", stats["tx_bytes"])
|
|
||||||
|
|
||||||
// Retrieve peer index of a veth interface
|
|
||||||
stats, err = ethHandle.Stats("veth0")
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
fmt.Printf("Peer Index: %d\n", stats["peer_ifindex"])
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## LICENSE ##
|
|
||||||
|
|
||||||
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.
|
|
541
vendor/github.com/safchain/ethtool/ethtool.go
generated
vendored
541
vendor/github.com/safchain/ethtool/ethtool.go
generated
vendored
@ -1,541 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you 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 ethtool aims to provide a library giving a simple access to the
|
|
||||||
// Linux SIOCETHTOOL ioctl operations. It can be used to retrieve informations
|
|
||||||
// from a network device like statistics, driver related informations or
|
|
||||||
// even the peer of a VETH interface.
|
|
||||||
package ethtool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Maximum size of an interface name
|
|
||||||
const (
|
|
||||||
IFNAMSIZ = 16
|
|
||||||
)
|
|
||||||
|
|
||||||
// ioctl ethtool request
|
|
||||||
const (
|
|
||||||
SIOCETHTOOL = 0x8946
|
|
||||||
)
|
|
||||||
|
|
||||||
// ethtool stats related constants.
|
|
||||||
const (
|
|
||||||
ETH_GSTRING_LEN = 32
|
|
||||||
ETH_SS_STATS = 1
|
|
||||||
ETH_SS_FEATURES = 4
|
|
||||||
ETHTOOL_GDRVINFO = 0x00000003
|
|
||||||
ETHTOOL_GSTRINGS = 0x0000001b
|
|
||||||
ETHTOOL_GSTATS = 0x0000001d
|
|
||||||
// other CMDs from ethtool-copy.h of ethtool-3.5 package
|
|
||||||
ETHTOOL_GSET = 0x00000001 /* Get settings. */
|
|
||||||
ETHTOOL_SSET = 0x00000002 /* Set settings. */
|
|
||||||
ETHTOOL_GMSGLVL = 0x00000007 /* Get driver message level */
|
|
||||||
ETHTOOL_SMSGLVL = 0x00000008 /* Set driver msg level. */
|
|
||||||
/* Get link status for host, i.e. whether the interface *and* the
|
|
||||||
* physical port (if there is one) are up (ethtool_value). */
|
|
||||||
ETHTOOL_GLINK = 0x0000000a
|
|
||||||
ETHTOOL_GMODULEINFO = 0x00000042 /* Get plug-in module information */
|
|
||||||
ETHTOOL_GMODULEEEPROM = 0x00000043 /* Get plug-in module eeprom */
|
|
||||||
ETHTOOL_GPERMADDR = 0x00000020
|
|
||||||
ETHTOOL_GFEATURES = 0x0000003a /* Get device offload settings */
|
|
||||||
ETHTOOL_SFEATURES = 0x0000003b /* Change device offload settings */
|
|
||||||
ETHTOOL_GFLAGS = 0x00000025 /* Get flags bitmap(ethtool_value) */
|
|
||||||
ETHTOOL_GSSET_INFO = 0x00000037 /* Get string set info */
|
|
||||||
)
|
|
||||||
|
|
||||||
// MAX_GSTRINGS maximum number of stats entries that ethtool can
|
|
||||||
// retrieve currently.
|
|
||||||
const (
|
|
||||||
MAX_GSTRINGS = 1000
|
|
||||||
MAX_FEATURE_BLOCKS = (MAX_GSTRINGS + 32 - 1) / 32
|
|
||||||
EEPROM_LEN = 640
|
|
||||||
PERMADDR_LEN = 32
|
|
||||||
)
|
|
||||||
|
|
||||||
type ifreq struct {
|
|
||||||
ifr_name [IFNAMSIZ]byte
|
|
||||||
ifr_data uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
// following structures comes from uapi/linux/ethtool.h
|
|
||||||
type ethtoolSsetInfo struct {
|
|
||||||
cmd uint32
|
|
||||||
reserved uint32
|
|
||||||
sset_mask uint32
|
|
||||||
data uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolGetFeaturesBlock struct {
|
|
||||||
available uint32
|
|
||||||
requested uint32
|
|
||||||
active uint32
|
|
||||||
never_changed uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolGfeatures struct {
|
|
||||||
cmd uint32
|
|
||||||
size uint32
|
|
||||||
blocks [MAX_FEATURE_BLOCKS]ethtoolGetFeaturesBlock
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolSetFeaturesBlock struct {
|
|
||||||
valid uint32
|
|
||||||
requested uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolSfeatures struct {
|
|
||||||
cmd uint32
|
|
||||||
size uint32
|
|
||||||
blocks [MAX_FEATURE_BLOCKS]ethtoolSetFeaturesBlock
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolDrvInfo struct {
|
|
||||||
cmd uint32
|
|
||||||
driver [32]byte
|
|
||||||
version [32]byte
|
|
||||||
fw_version [32]byte
|
|
||||||
bus_info [32]byte
|
|
||||||
erom_version [32]byte
|
|
||||||
reserved2 [12]byte
|
|
||||||
n_priv_flags uint32
|
|
||||||
n_stats uint32
|
|
||||||
testinfo_len uint32
|
|
||||||
eedump_len uint32
|
|
||||||
regdump_len uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolGStrings struct {
|
|
||||||
cmd uint32
|
|
||||||
string_set uint32
|
|
||||||
len uint32
|
|
||||||
data [MAX_GSTRINGS * ETH_GSTRING_LEN]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolStats struct {
|
|
||||||
cmd uint32
|
|
||||||
n_stats uint32
|
|
||||||
data [MAX_GSTRINGS]uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolEeprom struct {
|
|
||||||
cmd uint32
|
|
||||||
magic uint32
|
|
||||||
offset uint32
|
|
||||||
len uint32
|
|
||||||
data [EEPROM_LEN]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolModInfo struct {
|
|
||||||
cmd uint32
|
|
||||||
tpe uint32
|
|
||||||
eeprom_len uint32
|
|
||||||
reserved [8]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolLink struct {
|
|
||||||
cmd uint32
|
|
||||||
data uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type ethtoolPermAddr struct {
|
|
||||||
cmd uint32
|
|
||||||
size uint32
|
|
||||||
data [PERMADDR_LEN]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Ethtool struct {
|
|
||||||
fd int
|
|
||||||
}
|
|
||||||
|
|
||||||
// DriverName returns the driver name of the given interface name.
|
|
||||||
func (e *Ethtool) DriverName(intf string) (string, error) {
|
|
||||||
info, err := e.getDriverInfo(intf)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(bytes.Trim(info.driver[:], "\x00")), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BusInfo returns the bus information of the given interface name.
|
|
||||||
func (e *Ethtool) BusInfo(intf string) (string, error) {
|
|
||||||
info, err := e.getDriverInfo(intf)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(bytes.Trim(info.bus_info[:], "\x00")), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModuleEeprom returns Eeprom information of the given interface name.
|
|
||||||
func (e *Ethtool) ModuleEeprom(intf string) ([]byte, error) {
|
|
||||||
eeprom, _, err := e.getModuleEeprom(intf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return eeprom.data[:eeprom.len], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModuleEeprom returns Eeprom information of the given interface name.
|
|
||||||
func (e *Ethtool) ModuleEepromHex(intf string) (string, error) {
|
|
||||||
eeprom, _, err := e.getModuleEeprom(intf)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return hex.EncodeToString(eeprom.data[:eeprom.len]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DriverInfo returns driver information of the given interface name.
|
|
||||||
func (e *Ethtool) DriverInfo(intf string) (ethtoolDrvInfo, error) {
|
|
||||||
drvInfo, err := e.getDriverInfo(intf)
|
|
||||||
if err != nil {
|
|
||||||
return ethtoolDrvInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return drvInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PermAddr returns permanent address of the given interface name.
|
|
||||||
func (e *Ethtool) PermAddr(intf string) (string, error) {
|
|
||||||
permAddr, err := e.getPermAddr(intf)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if permAddr.data[0] == 0 && permAddr.data[1] == 0 &&
|
|
||||||
permAddr.data[2] == 0 && permAddr.data[3] == 0 &&
|
|
||||||
permAddr.data[4] == 0 && permAddr.data[5] == 0 {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%x:%x:%x:%x:%x:%x",
|
|
||||||
permAddr.data[0:1],
|
|
||||||
permAddr.data[1:2],
|
|
||||||
permAddr.data[2:3],
|
|
||||||
permAddr.data[3:4],
|
|
||||||
permAddr.data[4:5],
|
|
||||||
permAddr.data[5:6],
|
|
||||||
), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Ethtool) ioctl(intf string, data uintptr) error {
|
|
||||||
var name [IFNAMSIZ]byte
|
|
||||||
copy(name[:], []byte(intf))
|
|
||||||
|
|
||||||
ifr := ifreq{
|
|
||||||
ifr_name: name,
|
|
||||||
ifr_data: data,
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd), SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
|
|
||||||
if ep != 0 {
|
|
||||||
return syscall.Errno(ep)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Ethtool) getDriverInfo(intf string) (ethtoolDrvInfo, error) {
|
|
||||||
drvinfo := ethtoolDrvInfo{
|
|
||||||
cmd: ETHTOOL_GDRVINFO,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&drvinfo))); err != nil {
|
|
||||||
return ethtoolDrvInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return drvinfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Ethtool) getPermAddr(intf string) (ethtoolPermAddr, error) {
|
|
||||||
permAddr := ethtoolPermAddr{
|
|
||||||
cmd: ETHTOOL_GPERMADDR,
|
|
||||||
size: PERMADDR_LEN,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&permAddr))); err != nil {
|
|
||||||
return ethtoolPermAddr{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return permAddr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Ethtool) getModuleEeprom(intf string) (ethtoolEeprom, ethtoolModInfo, error) {
|
|
||||||
modInfo := ethtoolModInfo{
|
|
||||||
cmd: ETHTOOL_GMODULEINFO,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&modInfo))); err != nil {
|
|
||||||
return ethtoolEeprom{}, ethtoolModInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
eeprom := ethtoolEeprom{
|
|
||||||
cmd: ETHTOOL_GMODULEEEPROM,
|
|
||||||
len: modInfo.eeprom_len,
|
|
||||||
offset: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
if modInfo.eeprom_len > EEPROM_LEN {
|
|
||||||
return ethtoolEeprom{}, ethtoolModInfo{}, fmt.Errorf("eeprom size: %d is larger than buffer size: %d", modInfo.eeprom_len, EEPROM_LEN)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&eeprom))); err != nil {
|
|
||||||
return ethtoolEeprom{}, ethtoolModInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return eeprom, modInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isFeatureBitSet(blocks [MAX_FEATURE_BLOCKS]ethtoolGetFeaturesBlock, index uint) bool {
|
|
||||||
return (blocks)[index/32].active&(1<<(index%32)) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func setFeatureBit(blocks *[MAX_FEATURE_BLOCKS]ethtoolSetFeaturesBlock, index uint, value bool) {
|
|
||||||
blockIndex, bitIndex := index/32, index%32
|
|
||||||
|
|
||||||
blocks[blockIndex].valid |= 1 << bitIndex
|
|
||||||
|
|
||||||
if value {
|
|
||||||
blocks[blockIndex].requested |= 1 << bitIndex
|
|
||||||
} else {
|
|
||||||
blocks[blockIndex].requested &= ^(1 << bitIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FeatureNames shows supported features by their name.
|
|
||||||
func (e *Ethtool) FeatureNames(intf string) (map[string]uint, error) {
|
|
||||||
ssetInfo := ethtoolSsetInfo{
|
|
||||||
cmd: ETHTOOL_GSSET_INFO,
|
|
||||||
sset_mask: 1 << ETH_SS_FEATURES,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&ssetInfo))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
length := uint32(ssetInfo.data)
|
|
||||||
if length == 0 {
|
|
||||||
return map[string]uint{}, nil
|
|
||||||
} else if length > MAX_GSTRINGS {
|
|
||||||
return nil, fmt.Errorf("ethtool currently doesn't support more than %d entries, received %d", MAX_GSTRINGS, length)
|
|
||||||
}
|
|
||||||
|
|
||||||
gstrings := ethtoolGStrings{
|
|
||||||
cmd: ETHTOOL_GSTRINGS,
|
|
||||||
string_set: ETH_SS_FEATURES,
|
|
||||||
len: length,
|
|
||||||
data: [MAX_GSTRINGS * ETH_GSTRING_LEN]byte{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&gstrings))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = make(map[string]uint)
|
|
||||||
for i := 0; i != int(length); i++ {
|
|
||||||
b := gstrings.data[i*ETH_GSTRING_LEN : i*ETH_GSTRING_LEN+ETH_GSTRING_LEN]
|
|
||||||
key := string(bytes.Trim(b, "\x00"))
|
|
||||||
if key != "" {
|
|
||||||
result[key] = uint(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Features retrieves features of the given interface name.
|
|
||||||
func (e *Ethtool) Features(intf string) (map[string]bool, error) {
|
|
||||||
names, err := e.FeatureNames(intf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
length := uint32(len(names))
|
|
||||||
if length == 0 {
|
|
||||||
return map[string]bool{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
features := ethtoolGfeatures{
|
|
||||||
cmd: ETHTOOL_GFEATURES,
|
|
||||||
size: (length + 32 - 1) / 32,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&features))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = make(map[string]bool, length)
|
|
||||||
for key, index := range names {
|
|
||||||
result[key] = isFeatureBitSet(features.blocks, index)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change requests a change in the given device's features.
|
|
||||||
func (e *Ethtool) Change(intf string, config map[string]bool) error {
|
|
||||||
names, err := e.FeatureNames(intf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
length := uint32(len(names))
|
|
||||||
|
|
||||||
features := ethtoolSfeatures{
|
|
||||||
cmd: ETHTOOL_SFEATURES,
|
|
||||||
size: (length + 32 - 1) / 32,
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, value := range config {
|
|
||||||
if index, ok := names[key]; ok {
|
|
||||||
setFeatureBit(&features.blocks, index, value)
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("unsupported feature %q", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.ioctl(intf, uintptr(unsafe.Pointer(&features)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get state of a link.
|
|
||||||
func (e *Ethtool) LinkState(intf string) (uint32, error) {
|
|
||||||
x := ethtoolLink{
|
|
||||||
cmd: ETHTOOL_GLINK,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&x))); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return x.data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stats retrieves stats of the given interface name.
|
|
||||||
func (e *Ethtool) Stats(intf string) (map[string]uint64, error) {
|
|
||||||
drvinfo := ethtoolDrvInfo{
|
|
||||||
cmd: ETHTOOL_GDRVINFO,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&drvinfo))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if drvinfo.n_stats*ETH_GSTRING_LEN > MAX_GSTRINGS*ETH_GSTRING_LEN {
|
|
||||||
return nil, fmt.Errorf("ethtool currently doesn't support more than %d entries, received %d", MAX_GSTRINGS, drvinfo.n_stats)
|
|
||||||
}
|
|
||||||
|
|
||||||
gstrings := ethtoolGStrings{
|
|
||||||
cmd: ETHTOOL_GSTRINGS,
|
|
||||||
string_set: ETH_SS_STATS,
|
|
||||||
len: drvinfo.n_stats,
|
|
||||||
data: [MAX_GSTRINGS * ETH_GSTRING_LEN]byte{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&gstrings))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
stats := ethtoolStats{
|
|
||||||
cmd: ETHTOOL_GSTATS,
|
|
||||||
n_stats: drvinfo.n_stats,
|
|
||||||
data: [MAX_GSTRINGS]uint64{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&stats))); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = make(map[string]uint64)
|
|
||||||
for i := 0; i != int(drvinfo.n_stats); i++ {
|
|
||||||
b := gstrings.data[i*ETH_GSTRING_LEN : i*ETH_GSTRING_LEN+ETH_GSTRING_LEN]
|
|
||||||
key := string(b[:strings.Index(string(b), "\x00")])
|
|
||||||
if len(key) != 0 {
|
|
||||||
result[key] = stats.data[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the ethool handler
|
|
||||||
func (e *Ethtool) Close() {
|
|
||||||
syscall.Close(e.fd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEthtool returns a new ethtool handler
|
|
||||||
func NewEthtool() (*Ethtool, error) {
|
|
||||||
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_IP)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Ethtool{
|
|
||||||
fd: int(fd),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BusInfo returns bus information of the given interface name.
|
|
||||||
func BusInfo(intf string) (string, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.BusInfo(intf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DriverName returns the driver name of the given interface name.
|
|
||||||
func DriverName(intf string) (string, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.DriverName(intf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stats retrieves stats of the given interface name.
|
|
||||||
func Stats(intf string) (map[string]uint64, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.Stats(intf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PermAddr returns permanent address of the given interface name.
|
|
||||||
func PermAddr(intf string) (string, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.PermAddr(intf)
|
|
||||||
}
|
|
207
vendor/github.com/safchain/ethtool/ethtool_cmd.go
generated
vendored
207
vendor/github.com/safchain/ethtool/ethtool_cmd.go
generated
vendored
@ -1,207 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you 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 ethtool aims to provide a library giving a simple access to the
|
|
||||||
// Linux SIOCETHTOOL ioctl operations. It can be used to retrieve informations
|
|
||||||
// from a network device like statistics, driver related informations or
|
|
||||||
// even the peer of a VETH interface.
|
|
||||||
package ethtool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
type EthtoolCmd struct { /* ethtool.c: struct ethtool_cmd */
|
|
||||||
Cmd uint32
|
|
||||||
Supported uint32
|
|
||||||
Advertising uint32
|
|
||||||
Speed uint16
|
|
||||||
Duplex uint8
|
|
||||||
Port uint8
|
|
||||||
Phy_address uint8
|
|
||||||
Transceiver uint8
|
|
||||||
Autoneg uint8
|
|
||||||
Mdio_support uint8
|
|
||||||
Maxtxpkt uint32
|
|
||||||
Maxrxpkt uint32
|
|
||||||
Speed_hi uint16
|
|
||||||
Eth_tp_mdix uint8
|
|
||||||
Reserved2 uint8
|
|
||||||
Lp_advertising uint32
|
|
||||||
Reserved [2]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmdGet returns the interface settings in the receiver struct
|
|
||||||
// and returns speed
|
|
||||||
func (ecmd *EthtoolCmd) CmdGet(intf string) (uint32, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.CmdGet(ecmd, intf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmdSet sets and returns the settings in the receiver struct
|
|
||||||
// and returns speed
|
|
||||||
func (ecmd *EthtoolCmd) CmdSet(intf string) (uint32, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.CmdSet(ecmd, intf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *EthtoolCmd) reflect(retv *map[string]uint64) {
|
|
||||||
val := reflect.ValueOf(f).Elem()
|
|
||||||
|
|
||||||
for i := 0; i < val.NumField(); i++ {
|
|
||||||
valueField := val.Field(i)
|
|
||||||
typeField := val.Type().Field(i)
|
|
||||||
|
|
||||||
t := valueField.Interface()
|
|
||||||
//tt := reflect.TypeOf(t)
|
|
||||||
//fmt.Printf(" t %T %v tt %T %v\n", t, t, tt, tt)
|
|
||||||
switch t.(type) {
|
|
||||||
case uint32:
|
|
||||||
//fmt.Printf(" t is uint32\n")
|
|
||||||
(*retv)[typeField.Name] = uint64(t.(uint32))
|
|
||||||
case uint16:
|
|
||||||
(*retv)[typeField.Name] = uint64(t.(uint16))
|
|
||||||
case uint8:
|
|
||||||
(*retv)[typeField.Name] = uint64(t.(uint8))
|
|
||||||
case int32:
|
|
||||||
(*retv)[typeField.Name] = uint64(t.(int32))
|
|
||||||
case int16:
|
|
||||||
(*retv)[typeField.Name] = uint64(t.(int16))
|
|
||||||
case int8:
|
|
||||||
(*retv)[typeField.Name] = uint64(t.(int8))
|
|
||||||
default:
|
|
||||||
(*retv)[typeField.Name+"_unknown_type"] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//tag := typeField.Tag
|
|
||||||
//fmt.Printf("Field Name: %s,\t Field Value: %v,\t Tag Value: %s\n",
|
|
||||||
// typeField.Name, valueField.Interface(), tag.Get("tag_name"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmdGet returns the interface settings in the receiver struct
|
|
||||||
// and returns speed
|
|
||||||
func (e *Ethtool) CmdGet(ecmd *EthtoolCmd, intf string) (uint32, error) {
|
|
||||||
ecmd.Cmd = ETHTOOL_GSET
|
|
||||||
|
|
||||||
var name [IFNAMSIZ]byte
|
|
||||||
copy(name[:], []byte(intf))
|
|
||||||
|
|
||||||
ifr := ifreq{
|
|
||||||
ifr_name: name,
|
|
||||||
ifr_data: uintptr(unsafe.Pointer(ecmd)),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd),
|
|
||||||
SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
|
|
||||||
if ep != 0 {
|
|
||||||
return 0, syscall.Errno(ep)
|
|
||||||
}
|
|
||||||
|
|
||||||
var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) |
|
|
||||||
(uint32(ecmd.Speed) & 0xffff)
|
|
||||||
if speedval == math.MaxUint16 {
|
|
||||||
speedval = math.MaxUint32
|
|
||||||
}
|
|
||||||
|
|
||||||
return speedval, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmdSet sets and returns the settings in the receiver struct
|
|
||||||
// and returns speed
|
|
||||||
func (e *Ethtool) CmdSet(ecmd *EthtoolCmd, intf string) (uint32, error) {
|
|
||||||
ecmd.Cmd = ETHTOOL_SSET
|
|
||||||
|
|
||||||
var name [IFNAMSIZ]byte
|
|
||||||
copy(name[:], []byte(intf))
|
|
||||||
|
|
||||||
ifr := ifreq{
|
|
||||||
ifr_name: name,
|
|
||||||
ifr_data: uintptr(unsafe.Pointer(ecmd)),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd),
|
|
||||||
SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
|
|
||||||
if ep != 0 {
|
|
||||||
return 0, syscall.Errno(ep)
|
|
||||||
}
|
|
||||||
|
|
||||||
var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) |
|
|
||||||
(uint32(ecmd.Speed) & 0xffff)
|
|
||||||
if speedval == math.MaxUint16 {
|
|
||||||
speedval = math.MaxUint32
|
|
||||||
}
|
|
||||||
|
|
||||||
return speedval, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmdGetMapped returns the interface settings in a map
|
|
||||||
func (e *Ethtool) CmdGetMapped(intf string) (map[string]uint64, error) {
|
|
||||||
ecmd := EthtoolCmd{
|
|
||||||
Cmd: ETHTOOL_GSET,
|
|
||||||
}
|
|
||||||
|
|
||||||
var name [IFNAMSIZ]byte
|
|
||||||
copy(name[:], []byte(intf))
|
|
||||||
|
|
||||||
ifr := ifreq{
|
|
||||||
ifr_name: name,
|
|
||||||
ifr_data: uintptr(unsafe.Pointer(&ecmd)),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd),
|
|
||||||
SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
|
|
||||||
if ep != 0 {
|
|
||||||
return nil, syscall.Errno(ep)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = make(map[string]uint64)
|
|
||||||
|
|
||||||
// ref https://gist.github.com/drewolson/4771479
|
|
||||||
// Golang Reflection Example
|
|
||||||
ecmd.reflect(&result)
|
|
||||||
|
|
||||||
var speedval uint32 = (uint32(ecmd.Speed_hi) << 16) |
|
|
||||||
(uint32(ecmd.Speed) & 0xffff)
|
|
||||||
result["speed"] = uint64(speedval)
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CmdGetMapped(intf string) (map[string]uint64, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.CmdGetMapped(intf)
|
|
||||||
}
|
|
113
vendor/github.com/safchain/ethtool/ethtool_msglvl.go
generated
vendored
113
vendor/github.com/safchain/ethtool/ethtool_msglvl.go
generated
vendored
@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you 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 ethtool aims to provide a library giving a simple access to the
|
|
||||||
// Linux SIOCETHTOOL ioctl operations. It can be used to retrieve informations
|
|
||||||
// from a network device like statistics, driver related informations or
|
|
||||||
// even the peer of a VETH interface.
|
|
||||||
package ethtool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ethtoolValue struct { /* ethtool.c: struct ethtool_value */
|
|
||||||
cmd uint32
|
|
||||||
data uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// MsglvlGet returns the msglvl of the given interface.
|
|
||||||
func (e *Ethtool) MsglvlGet(intf string) (uint32, error) {
|
|
||||||
edata := ethtoolValue{
|
|
||||||
cmd: ETHTOOL_GMSGLVL,
|
|
||||||
}
|
|
||||||
|
|
||||||
var name [IFNAMSIZ]byte
|
|
||||||
copy(name[:], []byte(intf))
|
|
||||||
|
|
||||||
ifr := ifreq{
|
|
||||||
ifr_name: name,
|
|
||||||
ifr_data: uintptr(unsafe.Pointer(&edata)),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd),
|
|
||||||
SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
|
|
||||||
if ep != 0 {
|
|
||||||
return 0, syscall.Errno(ep)
|
|
||||||
}
|
|
||||||
|
|
||||||
return edata.data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MsglvlSet returns the read-msglvl, post-set-msglvl of the given interface.
|
|
||||||
func (e *Ethtool) MsglvlSet(intf string, valset uint32) (uint32, uint32, error) {
|
|
||||||
edata := ethtoolValue{
|
|
||||||
cmd: ETHTOOL_GMSGLVL,
|
|
||||||
}
|
|
||||||
|
|
||||||
var name [IFNAMSIZ]byte
|
|
||||||
copy(name[:], []byte(intf))
|
|
||||||
|
|
||||||
ifr := ifreq{
|
|
||||||
ifr_name: name,
|
|
||||||
ifr_data: uintptr(unsafe.Pointer(&edata)),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, ep := syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd),
|
|
||||||
SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
|
|
||||||
if ep != 0 {
|
|
||||||
return 0, 0, syscall.Errno(ep)
|
|
||||||
}
|
|
||||||
|
|
||||||
readval := edata.data
|
|
||||||
|
|
||||||
edata.cmd = ETHTOOL_SMSGLVL
|
|
||||||
edata.data = valset
|
|
||||||
|
|
||||||
_, _, ep = syscall.Syscall(syscall.SYS_IOCTL, uintptr(e.fd),
|
|
||||||
SIOCETHTOOL, uintptr(unsafe.Pointer(&ifr)))
|
|
||||||
if ep != 0 {
|
|
||||||
return 0, 0, syscall.Errno(ep)
|
|
||||||
}
|
|
||||||
|
|
||||||
return readval, edata.data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MsglvlGet returns the msglvl of the given interface.
|
|
||||||
func MsglvlGet(intf string) (uint32, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.MsglvlGet(intf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MsglvlSet returns the read-msglvl, post-set-msglvl of the given interface.
|
|
||||||
func MsglvlSet(intf string, valset uint32) (uint32, uint32, error) {
|
|
||||||
e, err := NewEthtool()
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, err
|
|
||||||
}
|
|
||||||
defer e.Close()
|
|
||||||
return e.MsglvlSet(intf, valset)
|
|
||||||
}
|
|
712
vendor/golang.org/x/net/html/atom/gen.go
generated
vendored
712
vendor/golang.org/x/net/html/atom/gen.go
generated
vendored
@ -1,712 +0,0 @@
|
|||||||
// Copyright 2012 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
|
|
||||||
//go:generate go run gen.go -test
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io/ioutil"
|
|
||||||
"math/rand"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// identifier converts s to a Go exported identifier.
|
|
||||||
// It converts "div" to "Div" and "accept-charset" to "AcceptCharset".
|
|
||||||
func identifier(s string) string {
|
|
||||||
b := make([]byte, 0, len(s))
|
|
||||||
cap := true
|
|
||||||
for _, c := range s {
|
|
||||||
if c == '-' {
|
|
||||||
cap = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if cap && 'a' <= c && c <= 'z' {
|
|
||||||
c -= 'a' - 'A'
|
|
||||||
}
|
|
||||||
cap = false
|
|
||||||
b = append(b, byte(c))
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
var test = flag.Bool("test", false, "generate table_test.go")
|
|
||||||
|
|
||||||
func genFile(name string, buf *bytes.Buffer) {
|
|
||||||
b, err := format.Source(buf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile(name, b, 0644); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
var all []string
|
|
||||||
all = append(all, elements...)
|
|
||||||
all = append(all, attributes...)
|
|
||||||
all = append(all, eventHandlers...)
|
|
||||||
all = append(all, extra...)
|
|
||||||
sort.Strings(all)
|
|
||||||
|
|
||||||
// uniq - lists have dups
|
|
||||||
w := 0
|
|
||||||
for _, s := range all {
|
|
||||||
if w == 0 || all[w-1] != s {
|
|
||||||
all[w] = s
|
|
||||||
w++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
all = all[:w]
|
|
||||||
|
|
||||||
if *test {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
|
|
||||||
fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n")
|
|
||||||
fmt.Fprintln(&buf, "package atom\n")
|
|
||||||
fmt.Fprintln(&buf, "var testAtomList = []string{")
|
|
||||||
for _, s := range all {
|
|
||||||
fmt.Fprintf(&buf, "\t%q,\n", s)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(&buf, "}")
|
|
||||||
|
|
||||||
genFile("table_test.go", &buf)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find hash that minimizes table size.
|
|
||||||
var best *table
|
|
||||||
for i := 0; i < 1000000; i++ {
|
|
||||||
if best != nil && 1<<(best.k-1) < len(all) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
h := rand.Uint32()
|
|
||||||
for k := uint(0); k <= 16; k++ {
|
|
||||||
if best != nil && k >= best.k {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
var t table
|
|
||||||
if t.init(h, k, all) {
|
|
||||||
best = &t
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if best == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "failed to construct string table\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lay out strings, using overlaps when possible.
|
|
||||||
layout := append([]string{}, all...)
|
|
||||||
|
|
||||||
// Remove strings that are substrings of other strings
|
|
||||||
for changed := true; changed; {
|
|
||||||
changed = false
|
|
||||||
for i, s := range layout {
|
|
||||||
if s == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for j, t := range layout {
|
|
||||||
if i != j && t != "" && strings.Contains(s, t) {
|
|
||||||
changed = true
|
|
||||||
layout[j] = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join strings where one suffix matches another prefix.
|
|
||||||
for {
|
|
||||||
// Find best i, j, k such that layout[i][len-k:] == layout[j][:k],
|
|
||||||
// maximizing overlap length k.
|
|
||||||
besti := -1
|
|
||||||
bestj := -1
|
|
||||||
bestk := 0
|
|
||||||
for i, s := range layout {
|
|
||||||
if s == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for j, t := range layout {
|
|
||||||
if i == j {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for k := bestk + 1; k <= len(s) && k <= len(t); k++ {
|
|
||||||
if s[len(s)-k:] == t[:k] {
|
|
||||||
besti = i
|
|
||||||
bestj = j
|
|
||||||
bestk = k
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if bestk > 0 {
|
|
||||||
layout[besti] += layout[bestj][bestk:]
|
|
||||||
layout[bestj] = ""
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
text := strings.Join(layout, "")
|
|
||||||
|
|
||||||
atom := map[string]uint32{}
|
|
||||||
for _, s := range all {
|
|
||||||
off := strings.Index(text, s)
|
|
||||||
if off < 0 {
|
|
||||||
panic("lost string " + s)
|
|
||||||
}
|
|
||||||
atom[s] = uint32(off<<8 | len(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
// Generate the Go code.
|
|
||||||
fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
|
|
||||||
fmt.Fprintln(&buf, "//go:generate go run gen.go\n")
|
|
||||||
fmt.Fprintln(&buf, "package atom\n\nconst (")
|
|
||||||
|
|
||||||
// compute max len
|
|
||||||
maxLen := 0
|
|
||||||
for _, s := range all {
|
|
||||||
if maxLen < len(s) {
|
|
||||||
maxLen = len(s)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s])
|
|
||||||
}
|
|
||||||
fmt.Fprintln(&buf, ")\n")
|
|
||||||
|
|
||||||
fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0)
|
|
||||||
fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen)
|
|
||||||
|
|
||||||
fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k)
|
|
||||||
for i, s := range best.tab {
|
|
||||||
if s == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&buf, "}\n")
|
|
||||||
datasize := (1 << best.k) * 4
|
|
||||||
|
|
||||||
fmt.Fprintln(&buf, "const atomText =")
|
|
||||||
textsize := len(text)
|
|
||||||
for len(text) > 60 {
|
|
||||||
fmt.Fprintf(&buf, "\t%q +\n", text[:60])
|
|
||||||
text = text[60:]
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&buf, "\t%q\n\n", text)
|
|
||||||
|
|
||||||
genFile("table.go", &buf)
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
|
|
||||||
}
|
|
||||||
|
|
||||||
type byLen []string
|
|
||||||
|
|
||||||
func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
|
|
||||||
func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
|
||||||
func (x byLen) Len() int { return len(x) }
|
|
||||||
|
|
||||||
// fnv computes the FNV hash with an arbitrary starting value h.
|
|
||||||
func fnv(h uint32, s string) uint32 {
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
h ^= uint32(s[i])
|
|
||||||
h *= 16777619
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
// A table represents an attempt at constructing the lookup table.
|
|
||||||
// The lookup table uses cuckoo hashing, meaning that each string
|
|
||||||
// can be found in one of two positions.
|
|
||||||
type table struct {
|
|
||||||
h0 uint32
|
|
||||||
k uint
|
|
||||||
mask uint32
|
|
||||||
tab []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// hash returns the two hashes for s.
|
|
||||||
func (t *table) hash(s string) (h1, h2 uint32) {
|
|
||||||
h := fnv(t.h0, s)
|
|
||||||
h1 = h & t.mask
|
|
||||||
h2 = (h >> 16) & t.mask
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// init initializes the table with the given parameters.
|
|
||||||
// h0 is the initial hash value,
|
|
||||||
// k is the number of bits of hash value to use, and
|
|
||||||
// x is the list of strings to store in the table.
|
|
||||||
// init returns false if the table cannot be constructed.
|
|
||||||
func (t *table) init(h0 uint32, k uint, x []string) bool {
|
|
||||||
t.h0 = h0
|
|
||||||
t.k = k
|
|
||||||
t.tab = make([]string, 1<<k)
|
|
||||||
t.mask = 1<<k - 1
|
|
||||||
for _, s := range x {
|
|
||||||
if !t.insert(s) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert inserts s in the table.
|
|
||||||
func (t *table) insert(s string) bool {
|
|
||||||
h1, h2 := t.hash(s)
|
|
||||||
if t.tab[h1] == "" {
|
|
||||||
t.tab[h1] = s
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if t.tab[h2] == "" {
|
|
||||||
t.tab[h2] = s
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if t.push(h1, 0) {
|
|
||||||
t.tab[h1] = s
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if t.push(h2, 0) {
|
|
||||||
t.tab[h2] = s
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// push attempts to push aside the entry in slot i.
|
|
||||||
func (t *table) push(i uint32, depth int) bool {
|
|
||||||
if depth > len(t.tab) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
s := t.tab[i]
|
|
||||||
h1, h2 := t.hash(s)
|
|
||||||
j := h1 + h2 - i
|
|
||||||
if t.tab[j] != "" && !t.push(j, depth+1) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
t.tab[j] = s
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// The lists of element names and attribute keys were taken from
|
|
||||||
// https://html.spec.whatwg.org/multipage/indices.html#index
|
|
||||||
// as of the "HTML Living Standard - Last Updated 16 April 2018" version.
|
|
||||||
|
|
||||||
// "command", "keygen" and "menuitem" have been removed from the spec,
|
|
||||||
// but are kept here for backwards compatibility.
|
|
||||||
var elements = []string{
|
|
||||||
"a",
|
|
||||||
"abbr",
|
|
||||||
"address",
|
|
||||||
"area",
|
|
||||||
"article",
|
|
||||||
"aside",
|
|
||||||
"audio",
|
|
||||||
"b",
|
|
||||||
"base",
|
|
||||||
"bdi",
|
|
||||||
"bdo",
|
|
||||||
"blockquote",
|
|
||||||
"body",
|
|
||||||
"br",
|
|
||||||
"button",
|
|
||||||
"canvas",
|
|
||||||
"caption",
|
|
||||||
"cite",
|
|
||||||
"code",
|
|
||||||
"col",
|
|
||||||
"colgroup",
|
|
||||||
"command",
|
|
||||||
"data",
|
|
||||||
"datalist",
|
|
||||||
"dd",
|
|
||||||
"del",
|
|
||||||
"details",
|
|
||||||
"dfn",
|
|
||||||
"dialog",
|
|
||||||
"div",
|
|
||||||
"dl",
|
|
||||||
"dt",
|
|
||||||
"em",
|
|
||||||
"embed",
|
|
||||||
"fieldset",
|
|
||||||
"figcaption",
|
|
||||||
"figure",
|
|
||||||
"footer",
|
|
||||||
"form",
|
|
||||||
"h1",
|
|
||||||
"h2",
|
|
||||||
"h3",
|
|
||||||
"h4",
|
|
||||||
"h5",
|
|
||||||
"h6",
|
|
||||||
"head",
|
|
||||||
"header",
|
|
||||||
"hgroup",
|
|
||||||
"hr",
|
|
||||||
"html",
|
|
||||||
"i",
|
|
||||||
"iframe",
|
|
||||||
"img",
|
|
||||||
"input",
|
|
||||||
"ins",
|
|
||||||
"kbd",
|
|
||||||
"keygen",
|
|
||||||
"label",
|
|
||||||
"legend",
|
|
||||||
"li",
|
|
||||||
"link",
|
|
||||||
"main",
|
|
||||||
"map",
|
|
||||||
"mark",
|
|
||||||
"menu",
|
|
||||||
"menuitem",
|
|
||||||
"meta",
|
|
||||||
"meter",
|
|
||||||
"nav",
|
|
||||||
"noscript",
|
|
||||||
"object",
|
|
||||||
"ol",
|
|
||||||
"optgroup",
|
|
||||||
"option",
|
|
||||||
"output",
|
|
||||||
"p",
|
|
||||||
"param",
|
|
||||||
"picture",
|
|
||||||
"pre",
|
|
||||||
"progress",
|
|
||||||
"q",
|
|
||||||
"rp",
|
|
||||||
"rt",
|
|
||||||
"ruby",
|
|
||||||
"s",
|
|
||||||
"samp",
|
|
||||||
"script",
|
|
||||||
"section",
|
|
||||||
"select",
|
|
||||||
"slot",
|
|
||||||
"small",
|
|
||||||
"source",
|
|
||||||
"span",
|
|
||||||
"strong",
|
|
||||||
"style",
|
|
||||||
"sub",
|
|
||||||
"summary",
|
|
||||||
"sup",
|
|
||||||
"table",
|
|
||||||
"tbody",
|
|
||||||
"td",
|
|
||||||
"template",
|
|
||||||
"textarea",
|
|
||||||
"tfoot",
|
|
||||||
"th",
|
|
||||||
"thead",
|
|
||||||
"time",
|
|
||||||
"title",
|
|
||||||
"tr",
|
|
||||||
"track",
|
|
||||||
"u",
|
|
||||||
"ul",
|
|
||||||
"var",
|
|
||||||
"video",
|
|
||||||
"wbr",
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/indices.html#attributes-3
|
|
||||||
//
|
|
||||||
// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup",
|
|
||||||
// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec,
|
|
||||||
// but are kept here for backwards compatibility.
|
|
||||||
var attributes = []string{
|
|
||||||
"abbr",
|
|
||||||
"accept",
|
|
||||||
"accept-charset",
|
|
||||||
"accesskey",
|
|
||||||
"action",
|
|
||||||
"allowfullscreen",
|
|
||||||
"allowpaymentrequest",
|
|
||||||
"allowusermedia",
|
|
||||||
"alt",
|
|
||||||
"as",
|
|
||||||
"async",
|
|
||||||
"autocomplete",
|
|
||||||
"autofocus",
|
|
||||||
"autoplay",
|
|
||||||
"challenge",
|
|
||||||
"charset",
|
|
||||||
"checked",
|
|
||||||
"cite",
|
|
||||||
"class",
|
|
||||||
"color",
|
|
||||||
"cols",
|
|
||||||
"colspan",
|
|
||||||
"command",
|
|
||||||
"content",
|
|
||||||
"contenteditable",
|
|
||||||
"contextmenu",
|
|
||||||
"controls",
|
|
||||||
"coords",
|
|
||||||
"crossorigin",
|
|
||||||
"data",
|
|
||||||
"datetime",
|
|
||||||
"default",
|
|
||||||
"defer",
|
|
||||||
"dir",
|
|
||||||
"dirname",
|
|
||||||
"disabled",
|
|
||||||
"download",
|
|
||||||
"draggable",
|
|
||||||
"dropzone",
|
|
||||||
"enctype",
|
|
||||||
"for",
|
|
||||||
"form",
|
|
||||||
"formaction",
|
|
||||||
"formenctype",
|
|
||||||
"formmethod",
|
|
||||||
"formnovalidate",
|
|
||||||
"formtarget",
|
|
||||||
"headers",
|
|
||||||
"height",
|
|
||||||
"hidden",
|
|
||||||
"high",
|
|
||||||
"href",
|
|
||||||
"hreflang",
|
|
||||||
"http-equiv",
|
|
||||||
"icon",
|
|
||||||
"id",
|
|
||||||
"inputmode",
|
|
||||||
"integrity",
|
|
||||||
"is",
|
|
||||||
"ismap",
|
|
||||||
"itemid",
|
|
||||||
"itemprop",
|
|
||||||
"itemref",
|
|
||||||
"itemscope",
|
|
||||||
"itemtype",
|
|
||||||
"keytype",
|
|
||||||
"kind",
|
|
||||||
"label",
|
|
||||||
"lang",
|
|
||||||
"list",
|
|
||||||
"loop",
|
|
||||||
"low",
|
|
||||||
"manifest",
|
|
||||||
"max",
|
|
||||||
"maxlength",
|
|
||||||
"media",
|
|
||||||
"mediagroup",
|
|
||||||
"method",
|
|
||||||
"min",
|
|
||||||
"minlength",
|
|
||||||
"multiple",
|
|
||||||
"muted",
|
|
||||||
"name",
|
|
||||||
"nomodule",
|
|
||||||
"nonce",
|
|
||||||
"novalidate",
|
|
||||||
"open",
|
|
||||||
"optimum",
|
|
||||||
"pattern",
|
|
||||||
"ping",
|
|
||||||
"placeholder",
|
|
||||||
"playsinline",
|
|
||||||
"poster",
|
|
||||||
"preload",
|
|
||||||
"radiogroup",
|
|
||||||
"readonly",
|
|
||||||
"referrerpolicy",
|
|
||||||
"rel",
|
|
||||||
"required",
|
|
||||||
"reversed",
|
|
||||||
"rows",
|
|
||||||
"rowspan",
|
|
||||||
"sandbox",
|
|
||||||
"spellcheck",
|
|
||||||
"scope",
|
|
||||||
"scoped",
|
|
||||||
"seamless",
|
|
||||||
"selected",
|
|
||||||
"shape",
|
|
||||||
"size",
|
|
||||||
"sizes",
|
|
||||||
"sortable",
|
|
||||||
"sorted",
|
|
||||||
"slot",
|
|
||||||
"span",
|
|
||||||
"spellcheck",
|
|
||||||
"src",
|
|
||||||
"srcdoc",
|
|
||||||
"srclang",
|
|
||||||
"srcset",
|
|
||||||
"start",
|
|
||||||
"step",
|
|
||||||
"style",
|
|
||||||
"tabindex",
|
|
||||||
"target",
|
|
||||||
"title",
|
|
||||||
"translate",
|
|
||||||
"type",
|
|
||||||
"typemustmatch",
|
|
||||||
"updateviacache",
|
|
||||||
"usemap",
|
|
||||||
"value",
|
|
||||||
"width",
|
|
||||||
"workertype",
|
|
||||||
"wrap",
|
|
||||||
}
|
|
||||||
|
|
||||||
// "onautocomplete", "onautocompleteerror", "onmousewheel",
|
|
||||||
// "onshow" and "onsort" have been removed from the spec,
|
|
||||||
// but are kept here for backwards compatibility.
|
|
||||||
var eventHandlers = []string{
|
|
||||||
"onabort",
|
|
||||||
"onautocomplete",
|
|
||||||
"onautocompleteerror",
|
|
||||||
"onauxclick",
|
|
||||||
"onafterprint",
|
|
||||||
"onbeforeprint",
|
|
||||||
"onbeforeunload",
|
|
||||||
"onblur",
|
|
||||||
"oncancel",
|
|
||||||
"oncanplay",
|
|
||||||
"oncanplaythrough",
|
|
||||||
"onchange",
|
|
||||||
"onclick",
|
|
||||||
"onclose",
|
|
||||||
"oncontextmenu",
|
|
||||||
"oncopy",
|
|
||||||
"oncuechange",
|
|
||||||
"oncut",
|
|
||||||
"ondblclick",
|
|
||||||
"ondrag",
|
|
||||||
"ondragend",
|
|
||||||
"ondragenter",
|
|
||||||
"ondragexit",
|
|
||||||
"ondragleave",
|
|
||||||
"ondragover",
|
|
||||||
"ondragstart",
|
|
||||||
"ondrop",
|
|
||||||
"ondurationchange",
|
|
||||||
"onemptied",
|
|
||||||
"onended",
|
|
||||||
"onerror",
|
|
||||||
"onfocus",
|
|
||||||
"onhashchange",
|
|
||||||
"oninput",
|
|
||||||
"oninvalid",
|
|
||||||
"onkeydown",
|
|
||||||
"onkeypress",
|
|
||||||
"onkeyup",
|
|
||||||
"onlanguagechange",
|
|
||||||
"onload",
|
|
||||||
"onloadeddata",
|
|
||||||
"onloadedmetadata",
|
|
||||||
"onloadend",
|
|
||||||
"onloadstart",
|
|
||||||
"onmessage",
|
|
||||||
"onmessageerror",
|
|
||||||
"onmousedown",
|
|
||||||
"onmouseenter",
|
|
||||||
"onmouseleave",
|
|
||||||
"onmousemove",
|
|
||||||
"onmouseout",
|
|
||||||
"onmouseover",
|
|
||||||
"onmouseup",
|
|
||||||
"onmousewheel",
|
|
||||||
"onwheel",
|
|
||||||
"onoffline",
|
|
||||||
"ononline",
|
|
||||||
"onpagehide",
|
|
||||||
"onpageshow",
|
|
||||||
"onpaste",
|
|
||||||
"onpause",
|
|
||||||
"onplay",
|
|
||||||
"onplaying",
|
|
||||||
"onpopstate",
|
|
||||||
"onprogress",
|
|
||||||
"onratechange",
|
|
||||||
"onreset",
|
|
||||||
"onresize",
|
|
||||||
"onrejectionhandled",
|
|
||||||
"onscroll",
|
|
||||||
"onsecuritypolicyviolation",
|
|
||||||
"onseeked",
|
|
||||||
"onseeking",
|
|
||||||
"onselect",
|
|
||||||
"onshow",
|
|
||||||
"onsort",
|
|
||||||
"onstalled",
|
|
||||||
"onstorage",
|
|
||||||
"onsubmit",
|
|
||||||
"onsuspend",
|
|
||||||
"ontimeupdate",
|
|
||||||
"ontoggle",
|
|
||||||
"onunhandledrejection",
|
|
||||||
"onunload",
|
|
||||||
"onvolumechange",
|
|
||||||
"onwaiting",
|
|
||||||
}
|
|
||||||
|
|
||||||
// extra are ad-hoc values not covered by any of the lists above.
|
|
||||||
var extra = []string{
|
|
||||||
"acronym",
|
|
||||||
"align",
|
|
||||||
"annotation",
|
|
||||||
"annotation-xml",
|
|
||||||
"applet",
|
|
||||||
"basefont",
|
|
||||||
"bgsound",
|
|
||||||
"big",
|
|
||||||
"blink",
|
|
||||||
"center",
|
|
||||||
"color",
|
|
||||||
"desc",
|
|
||||||
"face",
|
|
||||||
"font",
|
|
||||||
"foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive.
|
|
||||||
"foreignobject",
|
|
||||||
"frame",
|
|
||||||
"frameset",
|
|
||||||
"image",
|
|
||||||
"isindex",
|
|
||||||
"listing",
|
|
||||||
"malignmark",
|
|
||||||
"marquee",
|
|
||||||
"math",
|
|
||||||
"mglyph",
|
|
||||||
"mi",
|
|
||||||
"mn",
|
|
||||||
"mo",
|
|
||||||
"ms",
|
|
||||||
"mtext",
|
|
||||||
"nobr",
|
|
||||||
"noembed",
|
|
||||||
"noframes",
|
|
||||||
"plaintext",
|
|
||||||
"prompt",
|
|
||||||
"public",
|
|
||||||
"rb",
|
|
||||||
"rtc",
|
|
||||||
"spacer",
|
|
||||||
"strike",
|
|
||||||
"svg",
|
|
||||||
"system",
|
|
||||||
"tt",
|
|
||||||
"xmp",
|
|
||||||
}
|
|
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
|
|
||||||
}
|
|
112
vendor/golang.org/x/net/ipv6/defs_darwin.go
generated
vendored
112
vendor/golang.org/x/net/ipv6/defs_darwin.go
generated
vendored
@ -1,112 +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_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define __APPLE_USE_RFC_3542
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
|
|
||||||
sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
|
|
||||||
sysIPV6_2292NEXTHOP = C.IPV6_2292NEXTHOP
|
|
||||||
sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
|
|
||||||
sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
|
|
||||||
sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
|
|
||||||
|
|
||||||
sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
|
||||||
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
|
||||||
|
|
||||||
sysIPV6_MSFILTER = C.IPV6_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
|
|
||||||
|
|
||||||
sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
84
vendor/golang.org/x/net/ipv6/defs_dragonfly.go
generated
vendored
84
vendor/golang.org/x/net/ipv6/defs_dragonfly.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_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
105
vendor/golang.org/x/net/ipv6/defs_freebsd.go
generated
vendored
105
vendor/golang.org/x/net/ipv6/defs_freebsd.go
generated
vendored
@ -1,105 +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_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
|
||||||
|
|
||||||
sysIPV6_BINDANY = C.IPV6_BINDANY
|
|
||||||
|
|
||||||
sysIPV6_MSFILTER = C.IPV6_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
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
147
vendor/golang.org/x/net/ipv6/defs_linux.go
generated
vendored
147
vendor/golang.org/x/net/ipv6/defs_linux.go
generated
vendored
@ -1,147 +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_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <linux/in.h>
|
|
||||||
#include <linux/in6.h>
|
|
||||||
#include <linux/ipv6.h>
|
|
||||||
#include <linux/icmpv6.h>
|
|
||||||
#include <linux/filter.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_ADDRFORM = C.IPV6_ADDRFORM
|
|
||||||
sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
|
|
||||||
sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
|
|
||||||
sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
|
|
||||||
sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
|
|
||||||
sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_FLOWINFO = C.IPV6_FLOWINFO
|
|
||||||
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_ADD_MEMBERSHIP = C.IPV6_ADD_MEMBERSHIP
|
|
||||||
sysIPV6_DROP_MEMBERSHIP = C.IPV6_DROP_MEMBERSHIP
|
|
||||||
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
|
|
||||||
sysIPV6_ROUTER_ALERT = C.IPV6_ROUTER_ALERT
|
|
||||||
sysIPV6_MTU_DISCOVER = C.IPV6_MTU_DISCOVER
|
|
||||||
sysIPV6_MTU = C.IPV6_MTU
|
|
||||||
sysIPV6_RECVERR = C.IPV6_RECVERR
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
sysIPV6_JOIN_ANYCAST = C.IPV6_JOIN_ANYCAST
|
|
||||||
sysIPV6_LEAVE_ANYCAST = C.IPV6_LEAVE_ANYCAST
|
|
||||||
|
|
||||||
//sysIPV6_PMTUDISC_DONT = C.IPV6_PMTUDISC_DONT
|
|
||||||
//sysIPV6_PMTUDISC_WANT = C.IPV6_PMTUDISC_WANT
|
|
||||||
//sysIPV6_PMTUDISC_DO = C.IPV6_PMTUDISC_DO
|
|
||||||
//sysIPV6_PMTUDISC_PROBE = C.IPV6_PMTUDISC_PROBE
|
|
||||||
//sysIPV6_PMTUDISC_INTERFACE = C.IPV6_PMTUDISC_INTERFACE
|
|
||||||
//sysIPV6_PMTUDISC_OMIT = C.IPV6_PMTUDISC_OMIT
|
|
||||||
|
|
||||||
sysIPV6_FLOWLABEL_MGR = C.IPV6_FLOWLABEL_MGR
|
|
||||||
sysIPV6_FLOWINFO_SEND = C.IPV6_FLOWINFO_SEND
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
sysIPV6_XFRM_POLICY = C.IPV6_XFRM_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
|
|
||||||
sysIPV6_ADDR_PREFERENCES = C.IPV6_ADDR_PREFERENCES
|
|
||||||
|
|
||||||
sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
|
|
||||||
sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
|
|
||||||
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = C.IPV6_PREFER_SRC_PUBTMP_DEFAULT
|
|
||||||
sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
|
|
||||||
sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
|
|
||||||
sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
|
|
||||||
sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
|
|
||||||
|
|
||||||
sysIPV6_MINHOPCOUNT = C.IPV6_MINHOPCOUNT
|
|
||||||
|
|
||||||
sysIPV6_ORIGDSTADDR = C.IPV6_ORIGDSTADDR
|
|
||||||
sysIPV6_RECVORIGDSTADDR = C.IPV6_RECVORIGDSTADDR
|
|
||||||
sysIPV6_TRANSPARENT = C.IPV6_TRANSPARENT
|
|
||||||
sysIPV6_UNICAST_IF = C.IPV6_UNICAST_IF
|
|
||||||
|
|
||||||
sysICMPV6_FILTER = C.ICMPV6_FILTER
|
|
||||||
|
|
||||||
sysICMPV6_FILTER_BLOCK = C.ICMPV6_FILTER_BLOCK
|
|
||||||
sysICMPV6_FILTER_PASS = C.ICMPV6_FILTER_PASS
|
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = C.ICMPV6_FILTER_BLOCKOTHERS
|
|
||||||
sysICMPV6_FILTER_PASSONLY = C.ICMPV6_FILTER_PASSONLY
|
|
||||||
|
|
||||||
sysSOL_SOCKET = C.SOL_SOCKET
|
|
||||||
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
|
|
||||||
|
|
||||||
sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
sizeofIPv6FlowlabelReq = C.sizeof_struct_in6_flowlabel_req
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
|
|
||||||
sizeofSockFprog = C.sizeof_struct_sock_fprog
|
|
||||||
)
|
|
||||||
|
|
||||||
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6FlowlabelReq C.struct_in6_flowlabel_req
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
||||||
|
|
||||||
type sockFProg C.struct_sock_fprog
|
|
||||||
|
|
||||||
type sockFilter C.struct_sock_filter
|
|
80
vendor/golang.org/x/net/ipv6/defs_netbsd.go
generated
vendored
80
vendor/golang.org/x/net/ipv6/defs_netbsd.go
generated
vendored
@ -1,80 +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_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
89
vendor/golang.org/x/net/ipv6/defs_openbsd.go
generated
vendored
89
vendor/golang.org/x/net/ipv6/defs_openbsd.go
generated
vendored
@ -1,89 +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_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_AUTH_LEVEL = C.IPV6_AUTH_LEVEL
|
|
||||||
sysIPV6_ESP_TRANS_LEVEL = C.IPV6_ESP_TRANS_LEVEL
|
|
||||||
sysIPV6_ESP_NETWORK_LEVEL = C.IPV6_ESP_NETWORK_LEVEL
|
|
||||||
sysIPSEC6_OUTSA = C.IPSEC6_OUTSA
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
|
||||||
sysIPV6_IPCOMP_LEVEL = C.IPV6_IPCOMP_LEVEL
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
sysIPV6_PIPEX = C.IPV6_PIPEX
|
|
||||||
|
|
||||||
sysIPV6_RTABLE = C.IPV6_RTABLE
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user