mirror of
https://github.com/containers/podman.git
synced 2025-05-21 09:05:56 +08:00
rootless: use RootlessKit port forwarder
RootlessKit port forwarder has a lot of advantages over the slirp4netns port forwarder: * Very high throughput. Benchmark result on Travis: socat: 5.2 Gbps, slirp4netns: 8.3 Gbps, RootlessKit: 27.3 Gbps (https://travis-ci.org/rootless-containers/rootlesskit/builds/597056377) * Connections from the host are treated as 127.0.0.1 rather than 10.0.2.2 in the namespace. No UDP issue (#4586) * No tcp_rmem issue (#4537) * Probably works with IPv6. Even if not, it is trivial to support IPv6. (#4311) * Easily extensible for future support of SCTP * Easily extensible for future support of `lxc-user-nic` SUID network RootlessKit port forwarder has been already adopted as the default port forwarder by Rootless Docker/Moby, and no issue has been reported AFAIK. As the port forwarder is imported as a Go package, no `rootlesskit` binary is required for Podman. Fix #4586 May-fix #4559 Fix #4537 May-fix #4311 See https://github.com/rootless-containers/rootlesskit/blob/v0.7.0/pkg/port/builtin/builtin.go Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
4
go.mod
4
go.mod
@ -11,7 +11,6 @@ require (
|
||||
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784
|
||||
github.com/containernetworking/plugins v0.8.2
|
||||
github.com/containers/buildah v1.12.0
|
||||
github.com/containers/conmon v2.0.2+incompatible // indirect
|
||||
github.com/containers/image/v5 v5.1.0
|
||||
github.com/containers/psgo v1.4.0
|
||||
github.com/containers/storage v1.15.4
|
||||
@ -37,7 +36,6 @@ require (
|
||||
github.com/hashicorp/go-multierror v1.0.0
|
||||
github.com/hpcloud/tail v1.0.0
|
||||
github.com/json-iterator/go v1.1.8
|
||||
github.com/mattn/go-isatty v0.0.8 // indirect
|
||||
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
|
||||
github.com/onsi/ginkgo v1.10.3
|
||||
github.com/onsi/gomega v1.7.1
|
||||
@ -51,13 +49,13 @@ require (
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pkg/profile v1.4.0
|
||||
github.com/pmezard/go-difflib v1.0.0
|
||||
github.com/rootless-containers/rootlesskit v0.7.1
|
||||
github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/spf13/cobra v0.0.5
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
||||
github.com/uber-go/atomic v1.4.0 // indirect
|
||||
github.com/uber/jaeger-client-go v2.20.1+incompatible
|
||||
github.com/uber/jaeger-lib v0.0.0-20190122222657-d036253de8f5 // indirect
|
||||
github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b
|
||||
|
66
go.sum
66
go.sum
@ -13,8 +13,6 @@ github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
|
||||
github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
|
||||
@ -58,8 +56,6 @@ github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.
|
||||
github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY=
|
||||
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20180216233310-d8fb8589b0e8/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
@ -73,20 +69,10 @@ github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784 h1:rqUVL
|
||||
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784/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/containers/buildah v1.11.4-0.20191028173731-21b4778b359e h1:iDavHEx5Yr7o+0l6495Ya6N0YEPplIUZuWC2e14baDM=
|
||||
github.com/containers/buildah v1.11.4-0.20191028173731-21b4778b359e/go.mod h1:Igrk75FAxLnzDaHUbtpWB8pwL+Bv+cnakWMvqAXW2v8=
|
||||
github.com/containers/buildah v1.11.5-0.20191031204705-20e92ffe0982 h1:5WUe09k2sJSbmxwLHZLHc41TrIPrP0GlbhX+WDJBqvs=
|
||||
github.com/containers/buildah v1.11.5-0.20191031204705-20e92ffe0982/go.mod h1:eGWB4tLoo0hIBuytQpvgUC0hk2mvl2ofaYBeDsU/qoc=
|
||||
github.com/containers/buildah v1.11.5 h1:bVpkaVlvA7G+1mBDAcX6yf7jNZJ/ZrrAHDt4WCx2i8E=
|
||||
github.com/containers/buildah v1.11.5/go.mod h1:bfNPqLO8GnI0qMPmI6MHSpQNK+a3TH9syYsRg+iqhRw=
|
||||
github.com/containers/buildah v1.11.6 h1:PhlF++LAezRtOKHfKhBlo8DLvpMQIvU/K2VfAhknadE=
|
||||
github.com/containers/buildah v1.11.6/go.mod h1:02+o3ZTICaPyP0QcQFoQd07obLMdAecSnFN2kDhcqNo=
|
||||
github.com/containers/buildah v1.12.0 h1:bi/8ACl8qobazwfYgNze5y+aRuBIG+R7lMStFbnDOxE=
|
||||
github.com/containers/buildah v1.12.0/go.mod h1:yzPuQ/mJTPsfSLCyBPbeaoXgBLanjnf36M2cDzyckMg=
|
||||
github.com/containers/common v0.0.3 h1:C2Zshb0w720FqPa42MCRuiGfbW0kwbURRwvK1EWIC5I=
|
||||
github.com/containers/common v0.0.3/go.mod h1:CaOgMRiwi2JJHISMZ6VPPZhQYFUDRv3YYVss2RqUCMg=
|
||||
github.com/containers/conmon v2.0.2+incompatible h1:h2HCdd/EBpwFn7RT82Y2GyXnVUHWxk1Jm4cESSZG4P8=
|
||||
github.com/containers/conmon v2.0.2+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
||||
github.com/containers/image/v5 v5.0.0 h1:arnXgbt1ucsC/ndtSpiQY87rA0UjhF+/xQnPzqdBDn4=
|
||||
github.com/containers/image/v5 v5.0.0/go.mod h1:MgiLzCfIeo8lrHi+4Lb8HP+rh513sm0Mlk6RrhjFOLY=
|
||||
github.com/containers/image/v5 v5.1.0 h1:5FjAvPJniamuNNIQHkh4PnsL+n+xzs6Aonzaz5dqTEo=
|
||||
@ -95,21 +81,11 @@ github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDpl
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
||||
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741 h1:8tQkOcednLJtUcZgK7sPglscXtxvMOnFOa6wd09VWLM=
|
||||
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
|
||||
github.com/containers/psgo v1.3.2 h1:jYfppPih3S/j2Yi5O14AXjd8GfCx1ph9L3YsoK3adko=
|
||||
github.com/containers/psgo v1.3.2/go.mod h1:ENXXLQ5E1At4K0EUsGogXBJi/C28gwqkONWeLPI9fJ8=
|
||||
github.com/containers/psgo v1.4.0 h1:D8B4fZCCZhYgc8hDyMPCiShOinmOB1TP1qe46sSC19k=
|
||||
github.com/containers/psgo v1.4.0/go.mod h1:ENXXLQ5E1At4K0EUsGogXBJi/C28gwqkONWeLPI9fJ8=
|
||||
github.com/containers/storage v1.13.2/go.mod h1:6D8nK2sU9V7nEmAraINRs88ZEscM5C5DK+8Npp27GeA=
|
||||
github.com/containers/storage v1.13.4 h1:j0bBaJDKbUHtAW1MXPFnwXJtqcH+foWeuXK1YaBV5GA=
|
||||
github.com/containers/storage v1.13.4/go.mod h1:6D8nK2sU9V7nEmAraINRs88ZEscM5C5DK+8Npp27GeA=
|
||||
github.com/containers/storage v1.13.5 h1:/SUzGeOP2HDijpF7Yur21Ch6WTZC1BNeZF917CWcp5c=
|
||||
github.com/containers/storage v1.13.5/go.mod h1:HELz8Sn+UVbPaUZMI8RvIG9doD4y4z6Gtg4k7xdd2ZY=
|
||||
github.com/containers/storage v1.14.0 h1:LbX6WZaDmkXt4DT4xWIg3YXAWd6oA4K9Fi6/KG1xt84=
|
||||
github.com/containers/storage v1.14.0/go.mod h1:qGPsti/qC1xxX+xcpHfiTMT+8ThVE2Jf83wFHHqkDAY=
|
||||
github.com/containers/storage v1.15.0 h1:QNW7jJ94ccGcAbFIOSMHUAsUxvHceb71ecLye9EDrkk=
|
||||
github.com/containers/storage v1.15.0/go.mod h1:qGPsti/qC1xxX+xcpHfiTMT+8ThVE2Jf83wFHHqkDAY=
|
||||
github.com/containers/storage v1.15.2 h1:hLgafU4tuyQk/smMkXZfHTS8FtAQsqQvfWCp4bsgjuw=
|
||||
github.com/containers/storage v1.15.2/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8=
|
||||
github.com/containers/storage v1.15.3 h1:+lFSQZnnKUFyUEtguIgdoQLJfWSuYz+j/wg5GxLtsN4=
|
||||
github.com/containers/storage v1.15.3/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8=
|
||||
github.com/containers/storage v1.15.4 h1:eiUtV9MOTnPHibO18nDRI+aDhKudY7WmAiJdyVMsqSM=
|
||||
@ -128,8 +104,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbp
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cri-o/ocicni v0.1.1-0.20190702175919-7762645d18ca h1:CJstDqYy9ClWuPcDHMTCAiUS+ckekluYetGR2iYYWuo=
|
||||
github.com/cri-o/ocicni v0.1.1-0.20190702175919-7762645d18ca/go.mod h1:BO0al9TKber3XUTucLzKgoG5sq8qiOB41H7zSdfw6r8=
|
||||
github.com/cri-o/ocicni v0.1.1-0.20190920040751-deac903fd99b h1:SgS+WV10y2Bubuy2HquSBori6DXj9sqRN77Hgs5H7Qc=
|
||||
github.com/cri-o/ocicni v0.1.1-0.20190920040751-deac903fd99b/go.mod h1:ZOuIEOp/3MB1eCBWANnNxM3zUA3NWh76wSRCsnKAg2c=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
|
||||
@ -149,8 +123,6 @@ github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BU
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v0.0.0-20171019062838-86f080cff091/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v0.0.0-20180522102801-da99009bbb11/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v1.4.2-0.20190927142053-ada3c14355ce h1:H3csZuxZESJeeEiOxq4YXPNmLFbjl7u2qVBrAAGX/sA=
|
||||
github.com/docker/docker v1.4.2-0.20190927142053-ada3c14355ce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23 h1:oqgGT9O61YAYvI41EBsLePOr+LE6roB0xY4gpkZuFSE=
|
||||
github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f h1:Sm8iD2lifO31DwXfkGzq8VgA7rwxPjRsYmeo0K/dF9Y=
|
||||
@ -188,8 +160,6 @@ github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8
|
||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsouza/go-dockerclient v1.5.0 h1:7OtayOe5HnoG+KWMHgyyPymwaodnB2IDYuVfseKyxbA=
|
||||
github.com/fsouza/go-dockerclient v1.5.0/go.mod h1:AqZZK/zFO3phxYxlTsAaeAMSdQ9mgHuhy+bjN034Qds=
|
||||
github.com/fsouza/go-dockerclient v1.6.0 h1:f7j+AX94143JL1H3TiqSMkM4EcLDI0De1qD4GGn3Hig=
|
||||
github.com/fsouza/go-dockerclient v1.6.0/go.mod h1:YWwtNPuL4XTX1SKJQk86cWPmmqwx+4np9qfPbb+znGc=
|
||||
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
|
||||
@ -207,10 +177,9 @@ github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nA
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus v0.0.0-20181101234600-2ff6f7ffd60f h1:zlOR3rOlPAVvtfuxGKoghCmop5B0TRyu/ZieziZuGiM=
|
||||
github.com/godbus/dbus v0.0.0-20181101234600-2ff6f7ffd60f/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gogo/protobuf v0.0.0-20170815085658-fcdc5011193f/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@ -225,7 +194,6 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
@ -270,15 +238,15 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
|
||||
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20190712084813-dc1a53400564/go.mod h1:CfMdguCK66I5DAUJgGKyNz8aB6vO5dZzkm9Xep6WGvw=
|
||||
github.com/ishidawataru/sctp v0.0.0-20180918013207-6e2cb1366111 h1:NAAiV9ass6VReWFjuxqrMIq12WKlSULI6Gs3PxQghLA=
|
||||
github.com/ishidawataru/sctp v0.0.0-20180918013207-6e2cb1366111/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8=
|
||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||
github.com/jamescun/tuntap v0.0.0-20190712092105-cb1fb277045c/go.mod h1:zzwpsgcYhzzIP5WyF8g9ivCv38cY9uAV9Gu0m3lThhE=
|
||||
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
|
||||
@ -298,8 +266,6 @@ github.com/klauspost/compress v1.7.2 h1:liMOoeIvFpr9kEvalrZ7VVBA4wGf7zfOgwBjzz/5
|
||||
github.com/klauspost/compress v1.7.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.8.1 h1:oygt2ychZFHOB6M9gUgajzgKrwRgHbGC77NwA4COVgI=
|
||||
github.com/klauspost/compress v1.8.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.9.2 h1:LfVyl+ZlLlLDeQ/d2AqfGIIH4qEDu0Ed2S5GyhCWIWY=
|
||||
github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.9.4 h1:xhvAeUPQ2drNUhKtrGdTGNvV9nNafHMUkRyLkzxJoB4=
|
||||
github.com/klauspost/compress v1.9.4/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
|
||||
@ -319,8 +285,6 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
github.com/mattn/go-shellwords v1.0.5 h1:JhhFTIOslh5ZsPrpa3Wdg8bF0WI3b44EMblmU9wIsXc=
|
||||
github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
@ -332,6 +296,7 @@ github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJd
|
||||
github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/vpnkit v0.3.1-0.20190720080441-7dd3dcce7d3d/go.mod h1:KyjUrL9cb6ZSNNAUwZfqRjhwwgJ3BJN+kXh0t43WTUQ=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -354,8 +319,6 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
|
||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@ -364,7 +327,6 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
|
||||
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
@ -380,7 +342,6 @@ github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5X
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc8 h1:dDCFes8Hj1r/i5qnypONo5jdOme/8HWZC/aNDyhECt0=
|
||||
github.com/opencontainers/runc v1.0.0-rc8/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190827142921-dd075602f158 h1:/A6bAdnSZoTQmKml3MdHAnSEPnBAQeigNBl4sxnfaaQ=
|
||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190827142921-dd075602f158/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc=
|
||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
@ -408,8 +369,6 @@ github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.3.0 h1:OQIvuDgm00gWVWGTf4m4mCt6W1/0YqU7Ntg0mySWgaI=
|
||||
github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/profile v1.4.0 h1:uCmaf4vVbWAOZz36k1hrQD7ijGRzLwaME8Am/7a4jZI=
|
||||
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@ -438,6 +397,8 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
|
||||
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
|
||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||
github.com/rootless-containers/rootlesskit v0.7.1 h1:enhwHIAXDjfpV83bL4xF60WZ+1ATjMB7spDDvpWAfPk=
|
||||
github.com/rootless-containers/rootlesskit v0.7.1/go.mod h1:r9YL5mKRIdnwcYk4G8E5CSc9MDeFtgYmhfE4CSvDGYA=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U=
|
||||
@ -481,12 +442,8 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs=
|
||||
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||
github.com/uber-go/atomic v1.4.0 h1:yOuPqEq4ovnhEjpHmfFwsqBXDYbQeT6Nb0bwD6XnD5o=
|
||||
github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
|
||||
github.com/uber/jaeger-client-go v2.19.0+incompatible h1:pbwbYfHUoaase0oPQOdZ1GcaUjImYGimUXSQ/+8+Z8Q=
|
||||
github.com/uber/jaeger-client-go v2.19.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/uber/jaeger-client-go v2.20.0+incompatible h1:ttG9wKdl2ikV/BGOtu+eb+VPp+R7jMeuM177Ihs5Fdc=
|
||||
github.com/uber/jaeger-client-go v2.20.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/theckman/go-flock v0.7.1/go.mod h1:kjuth3y9VJ2aNlkNEO99G/8lp9fMIKaGyBmh84IBheM=
|
||||
github.com/u-root/u-root v5.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
|
||||
github.com/uber/jaeger-client-go v2.20.1+incompatible h1:HgqpYBng0n7tLJIlyT4kPCIv5XgCsF+kai1NnnrJzEU=
|
||||
github.com/uber/jaeger-client-go v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/uber/jaeger-lib v0.0.0-20190122222657-d036253de8f5 h1:CwmGyzHTzCqCdZJkWR0A7ucZXgrCY7spRcpvm7ci//s=
|
||||
@ -495,6 +452,7 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT
|
||||
github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=
|
||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b h1:hdDRrn9OP/roL8a/e/5Zu85ldrcdndu9IeBj2OEvQm0=
|
||||
github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b/go.mod h1:YHaw8N660ESgMgLOZfLQqT1htFItynAUxMesFBho52s=
|
||||
@ -577,19 +535,18 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190425145619-16072639606e h1:4ktJgTV34+N3qOZUc5fAaG3Pb11qzMm3PkAoTAgUZ2I=
|
||||
golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4=
|
||||
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -623,7 +580,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 h1:9VBRTdmgQxbs6HE0sUnMrSWNePppAJU07NYvX5dIB04=
|
||||
google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
@ -655,8 +611,6 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v0.0.0-20190624233834-05ebafbffc79/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
|
||||
|
@ -135,6 +135,9 @@ type Container struct {
|
||||
rootlessSlirpSyncR *os.File
|
||||
rootlessSlirpSyncW *os.File
|
||||
|
||||
rootlessPortSyncR *os.File
|
||||
rootlessPortSyncW *os.File
|
||||
|
||||
// A restored container should have the same IP address as before
|
||||
// being checkpointed. If requestedIP is set it will be used instead
|
||||
// of config.StaticIP.
|
||||
|
@ -3,8 +3,10 @@
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
@ -20,6 +22,7 @@ import (
|
||||
"github.com/containers/libpod/pkg/errorhandling"
|
||||
"github.com/containers/libpod/pkg/netns"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/containers/libpod/pkg/rootlessport"
|
||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -151,19 +154,6 @@ func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q []*cnitypes.Result,
|
||||
return ctrNS, networkStatus, err
|
||||
}
|
||||
|
||||
type slirp4netnsCmdArg struct {
|
||||
Proto string `json:"proto,omitempty"`
|
||||
HostAddr string `json:"host_addr"`
|
||||
HostPort int32 `json:"host_port"`
|
||||
GuestAddr string `json:"guest_addr"`
|
||||
GuestPort int32 `json:"guest_port"`
|
||||
}
|
||||
|
||||
type slirp4netnsCmd struct {
|
||||
Execute string `json:"execute"`
|
||||
Args slirp4netnsCmdArg `json:"arguments"`
|
||||
}
|
||||
|
||||
func checkSlirpFlags(path string) (bool, bool, bool, error) {
|
||||
cmd := exec.Command(path, "--help")
|
||||
out, err := cmd.CombinedOutput()
|
||||
@ -194,13 +184,9 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
|
||||
defer errorhandling.CloseQuiet(syncW)
|
||||
|
||||
havePortMapping := len(ctr.Config().PortMappings) > 0
|
||||
apiSocket := filepath.Join(ctr.runtime.config.TmpDir, fmt.Sprintf("%s.net", ctr.config.ID))
|
||||
logPath := filepath.Join(ctr.runtime.config.TmpDir, fmt.Sprintf("slirp4netns-%s.log", ctr.config.ID))
|
||||
|
||||
cmdArgs := []string{}
|
||||
if havePortMapping {
|
||||
cmdArgs = append(cmdArgs, "--api-socket", apiSocket)
|
||||
}
|
||||
dhp, mtu, sandbox, err := checkSlirpFlags(path)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error checking slirp4netns binary %s: %q", path, err)
|
||||
@ -221,15 +207,19 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
|
||||
// -e, --exit-fd=FD specify the FD for terminating slirp4netns
|
||||
// -r, --ready-fd=FD specify the FD to write to when the initialization steps are finished
|
||||
cmdArgs = append(cmdArgs, "-c", "-e", "3", "-r", "4")
|
||||
netnsPath := ""
|
||||
if !ctr.config.PostConfigureNetNS {
|
||||
ctr.rootlessSlirpSyncR, ctr.rootlessSlirpSyncW, err = os.Pipe()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to create rootless network sync pipe")
|
||||
}
|
||||
cmdArgs = append(cmdArgs, "--netns-type=path", ctr.state.NetNS.Path(), "tap0")
|
||||
netnsPath = ctr.state.NetNS.Path()
|
||||
cmdArgs = append(cmdArgs, "--netns-type=path", netnsPath, "tap0")
|
||||
} else {
|
||||
defer errorhandling.CloseQuiet(ctr.rootlessSlirpSyncR)
|
||||
defer errorhandling.CloseQuiet(ctr.rootlessSlirpSyncW)
|
||||
netnsPath = fmt.Sprintf("/proc/%d/ns/net", ctr.state.PID)
|
||||
// we don't use --netns-path here (unavailable for slirp4netns < v0.4)
|
||||
cmdArgs = append(cmdArgs, fmt.Sprintf("%d", ctr.state.PID), "tap0")
|
||||
}
|
||||
|
||||
@ -269,11 +259,27 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
|
||||
}
|
||||
}()
|
||||
|
||||
if err := waitForSync(syncR, cmd, logFile, 1*time.Second); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if havePortMapping {
|
||||
return r.setupRootlessPortMapping(ctr, netnsPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout time.Duration) error {
|
||||
prog := filepath.Base(cmd.Path)
|
||||
if len(cmd.Args) > 0 {
|
||||
prog = cmd.Args[0]
|
||||
}
|
||||
b := make([]byte, 16)
|
||||
for {
|
||||
if err := syncR.SetDeadline(time.Now().Add(1 * time.Second)); err != nil {
|
||||
return errors.Wrapf(err, "error setting slirp4netns pipe timeout")
|
||||
if err := syncR.SetDeadline(time.Now().Add(timeout)); err != nil {
|
||||
return errors.Wrapf(err, "error setting %s pipe timeout", prog)
|
||||
}
|
||||
// FIXME: return err as soon as proc exits, without waiting for timeout
|
||||
if _, err := syncR.Read(b); err == nil {
|
||||
break
|
||||
} else {
|
||||
@ -282,7 +288,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
|
||||
var status syscall.WaitStatus
|
||||
pid, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read slirp4netns process status")
|
||||
return errors.Wrapf(err, "failed to read %s process status", prog)
|
||||
}
|
||||
if pid != cmd.Process.Pid {
|
||||
continue
|
||||
@ -294,100 +300,86 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) {
|
||||
}
|
||||
logContent, err := ioutil.ReadAll(logFile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "slirp4netns failed")
|
||||
return errors.Wrapf(err, "%s failed", prog)
|
||||
}
|
||||
return errors.Errorf("slirp4netns failed: %q", logContent)
|
||||
return errors.Errorf("%s failed: %q", prog, logContent)
|
||||
}
|
||||
if status.Signaled() {
|
||||
return errors.New("slirp4netns killed by signal")
|
||||
return errors.Errorf("%s killed by signal", prog)
|
||||
}
|
||||
continue
|
||||
}
|
||||
return errors.Wrapf(err, "failed to read from slirp4netns sync pipe")
|
||||
return errors.Wrapf(err, "failed to read from %s sync pipe", prog)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if havePortMapping {
|
||||
const pidWaitTimeout = 60 * time.Second
|
||||
chWait := make(chan error)
|
||||
go func() {
|
||||
interval := 25 * time.Millisecond
|
||||
for i := time.Duration(0); i < pidWaitTimeout; i += interval {
|
||||
// Check if the process is still running.
|
||||
var status syscall.WaitStatus
|
||||
pid, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if pid != cmd.Process.Pid {
|
||||
continue
|
||||
}
|
||||
if status.Exited() || status.Signaled() {
|
||||
chWait <- fmt.Errorf("slirp4netns exited with status %d", status.ExitStatus())
|
||||
}
|
||||
time.Sleep(interval)
|
||||
}
|
||||
}()
|
||||
defer close(chWait)
|
||||
|
||||
// wait that API socket file appears before trying to use it.
|
||||
if _, err := WaitForFile(apiSocket, chWait, pidWaitTimeout); err != nil {
|
||||
return errors.Wrapf(err, "waiting for slirp4nets to create the api socket file %s", apiSocket)
|
||||
}
|
||||
|
||||
// for each port we want to add we need to open a connection to the slirp4netns control socket
|
||||
// and send the add_hostfwd command.
|
||||
for _, i := range ctr.config.PortMappings {
|
||||
conn, err := net.Dial("unix", apiSocket)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cannot open connection to %s", apiSocket)
|
||||
}
|
||||
defer func() {
|
||||
if err := conn.Close(); err != nil {
|
||||
logrus.Errorf("unable to close connection: %q", err)
|
||||
}
|
||||
}()
|
||||
hostIP := i.HostIP
|
||||
if hostIP == "" {
|
||||
hostIP = "0.0.0.0"
|
||||
}
|
||||
cmd := slirp4netnsCmd{
|
||||
Execute: "add_hostfwd",
|
||||
Args: slirp4netnsCmdArg{
|
||||
Proto: i.Protocol,
|
||||
HostAddr: hostIP,
|
||||
HostPort: i.HostPort,
|
||||
GuestPort: i.ContainerPort,
|
||||
},
|
||||
}
|
||||
// create the JSON payload and send it. Mark the end of request shutting down writes
|
||||
// to the socket, as requested by slirp4netns.
|
||||
data, err := json.Marshal(&cmd)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cannot marshal JSON for slirp4netns")
|
||||
}
|
||||
if _, err := conn.Write([]byte(fmt.Sprintf("%s\n", data))); err != nil {
|
||||
return errors.Wrapf(err, "cannot write to control socket %s", apiSocket)
|
||||
}
|
||||
if err := conn.(*net.UnixConn).CloseWrite(); err != nil {
|
||||
return errors.Wrapf(err, "cannot shutdown the socket %s", apiSocket)
|
||||
}
|
||||
buf := make([]byte, 2048)
|
||||
readLength, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cannot read from control socket %s", apiSocket)
|
||||
}
|
||||
// if there is no 'error' key in the received JSON data, then the operation was
|
||||
// successful.
|
||||
var y map[string]interface{}
|
||||
if err := json.Unmarshal(buf[0:readLength], &y); err != nil {
|
||||
return errors.Wrapf(err, "error parsing error status from slirp4netns")
|
||||
}
|
||||
if e, found := y["error"]; found {
|
||||
return errors.Errorf("error from slirp4netns while setting up port redirection: %v", e)
|
||||
}
|
||||
}
|
||||
func (r *Runtime) setupRootlessPortMapping(ctr *Container, netnsPath string) (err error) {
|
||||
syncR, syncW, err := os.Pipe()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to open pipe")
|
||||
}
|
||||
defer errorhandling.CloseQuiet(syncR)
|
||||
defer errorhandling.CloseQuiet(syncW)
|
||||
|
||||
logPath := filepath.Join(ctr.runtime.config.TmpDir, fmt.Sprintf("rootlessport-%s.log", ctr.config.ID))
|
||||
logFile, err := os.Create(logPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to open rootlessport log file %s", logPath)
|
||||
}
|
||||
defer logFile.Close()
|
||||
// Unlink immediately the file so we won't need to worry about cleaning it up later.
|
||||
// It is still accessible through the open fd logFile.
|
||||
if err := os.Remove(logPath); err != nil {
|
||||
return errors.Wrapf(err, "delete file %s", logPath)
|
||||
}
|
||||
|
||||
ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to create rootless port sync pipe")
|
||||
}
|
||||
cfg := rootlessport.Config{
|
||||
Mappings: ctr.config.PortMappings,
|
||||
NetNSPath: netnsPath,
|
||||
ExitFD: 3,
|
||||
ReadyFD: 4,
|
||||
}
|
||||
cfgJSON, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgR := bytes.NewReader(cfgJSON)
|
||||
var stdout bytes.Buffer
|
||||
cmd := exec.Command(fmt.Sprintf("/proc/%d/exe", os.Getpid()))
|
||||
cmd.Args = []string{rootlessport.ReexecKey}
|
||||
// Leak one end of the pipe in rootlessport process, the other will be sent to conmon
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessPortSyncR, syncW)
|
||||
cmd.Stdin = cfgR
|
||||
// stdout is for human-readable error, stderr is for debug log
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = io.MultiWriter(logFile, &logrusDebugWriter{"rootlessport: "})
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
return errors.Wrapf(err, "failed to start rootlessport process")
|
||||
}
|
||||
defer func() {
|
||||
if err := cmd.Process.Release(); err != nil {
|
||||
logrus.Errorf("unable to release rootlessport process: %q", err)
|
||||
}
|
||||
}()
|
||||
if err := waitForSync(syncR, cmd, logFile, 3*time.Second); err != nil {
|
||||
stdoutStr := stdout.String()
|
||||
if stdoutStr != "" {
|
||||
// err contains full debug log and too verbose, so return stdoutStr
|
||||
logrus.Debug(err)
|
||||
return errors.Errorf("failed to expose ports via rootlessport: %q", stdoutStr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
logrus.Debug("rootlessport is ready")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -587,3 +579,12 @@ func (c *Container) getContainerNetworkInfo(data *InspectContainerData) *Inspect
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
type logrusDebugWriter struct {
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (w *logrusDebugWriter) Write(p []byte) (int, error) {
|
||||
logrus.Debugf("%s%s", w.prefix, string(p))
|
||||
return len(p), nil
|
||||
}
|
||||
|
@ -1000,6 +1000,15 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
|
||||
}
|
||||
// Leak one end in conmon, the other one will be leaked into slirp4netns
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessSlirpSyncW)
|
||||
|
||||
if ctr.rootlessPortSyncR != nil {
|
||||
defer errorhandling.CloseQuiet(ctr.rootlessPortSyncR)
|
||||
}
|
||||
if ctr.rootlessPortSyncW != nil {
|
||||
defer errorhandling.CloseQuiet(ctr.rootlessPortSyncW)
|
||||
// Leak one end in conmon, the other one will be leaked into rootlessport
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessPortSyncW)
|
||||
}
|
||||
}
|
||||
|
||||
err = startCommandGivenSelinux(cmd)
|
||||
|
262
pkg/rootlessport/rootlessport_linux.go
Normal file
262
pkg/rootlessport/rootlessport_linux.go
Normal file
@ -0,0 +1,262 @@
|
||||
// +build linux
|
||||
|
||||
// Package rootlessport provides reexec for RootlessKit-based port forwarder.
|
||||
//
|
||||
// init() contains reexec.Register() for ReexecKey .
|
||||
//
|
||||
// The reexec requires Config to be provided via stdin.
|
||||
//
|
||||
// The reexec writes human-readable error message on stdout on error.
|
||||
//
|
||||
// Debug log is printed on stderr.
|
||||
package rootlessport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containers/storage/pkg/reexec"
|
||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||
"github.com/pkg/errors"
|
||||
rkport "github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
rkbuiltin "github.com/rootless-containers/rootlesskit/pkg/port/builtin"
|
||||
rkportutil "github.com/rootless-containers/rootlesskit/pkg/port/portutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
// ReexecKey is the reexec key for the parent process.
|
||||
ReexecKey = "containers-rootlessport"
|
||||
// reexecChildKey is used internally for the second reexec
|
||||
reexecChildKey = "containers-rootlessport-child"
|
||||
reexecChildEnvOpaque = "_CONTAINERS_ROOTLESSPORT_CHILD_OPAQUE"
|
||||
)
|
||||
|
||||
// Config needs to be provided to the process via stdin as a JSON string.
|
||||
// stdin needs to be closed after the message has been written.
|
||||
type Config struct {
|
||||
Mappings []ocicni.PortMapping
|
||||
NetNSPath string
|
||||
ExitFD int
|
||||
ReadyFD int
|
||||
}
|
||||
|
||||
func init() {
|
||||
reexec.Register(ReexecKey, func() {
|
||||
if err := parent(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
})
|
||||
reexec.Register(reexecChildKey, func() {
|
||||
if err := child(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func loadConfig(r io.Reader) (*Config, io.ReadCloser, io.WriteCloser, error) {
|
||||
stdin, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
var cfg Config
|
||||
if err := json.Unmarshal(stdin, &cfg); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if cfg.NetNSPath == "" {
|
||||
return nil, nil, nil, errors.New("missing NetNSPath")
|
||||
}
|
||||
if cfg.ExitFD <= 0 {
|
||||
return nil, nil, nil, errors.New("missing ExitFD")
|
||||
}
|
||||
exitFile := os.NewFile(uintptr(cfg.ExitFD), "exitfile")
|
||||
if exitFile == nil {
|
||||
return nil, nil, nil, errors.New("invalid ExitFD")
|
||||
}
|
||||
if cfg.ReadyFD <= 0 {
|
||||
return nil, nil, nil, errors.New("missing ReadyFD")
|
||||
}
|
||||
readyFile := os.NewFile(uintptr(cfg.ReadyFD), "readyfile")
|
||||
if readyFile == nil {
|
||||
return nil, nil, nil, errors.New("invalid ReadyFD")
|
||||
}
|
||||
return &cfg, exitFile, readyFile, nil
|
||||
}
|
||||
|
||||
func parent() error {
|
||||
// load config from stdin
|
||||
cfg, exitR, readyW, err := loadConfig(os.Stdin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create the parent driver
|
||||
stateDir, err := ioutil.TempDir("", "rootlessport")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
driver, err := rkbuiltin.NewParentDriver(&logrusWriter{prefix: "parent: "}, stateDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
initComplete := make(chan struct{})
|
||||
quit := make(chan struct{})
|
||||
errCh := make(chan error)
|
||||
// start the parent driver. initComplete will be closed when the child connected to the parent.
|
||||
logrus.Infof("starting parent driver")
|
||||
go func() {
|
||||
driverErr := driver.RunParentDriver(initComplete, quit, nil)
|
||||
if driverErr != nil {
|
||||
logrus.WithError(driverErr).Warn("parent driver exited")
|
||||
}
|
||||
errCh <- driverErr
|
||||
}()
|
||||
opaque := driver.OpaqueForChild()
|
||||
logrus.Infof("opaque=%+v", opaque)
|
||||
opaqueJSON, err := json.Marshal(opaque)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
childQuitR, childQuitW, err := os.Pipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
// stop the child
|
||||
logrus.Info("stopping child driver")
|
||||
if err := childQuitW.Close(); err != nil {
|
||||
logrus.WithError(err).Warn("unable to close childQuitW")
|
||||
}
|
||||
}()
|
||||
|
||||
// reexec the child process in the child netns
|
||||
cmd := exec.Command(fmt.Sprintf("/proc/%d/exe", os.Getpid()))
|
||||
cmd.Args = []string{reexecChildKey}
|
||||
cmd.Stdin = childQuitR
|
||||
cmd.Stdout = &logrusWriter{prefix: "child"}
|
||||
cmd.Stderr = cmd.Stdout
|
||||
cmd.Env = append(os.Environ(), reexecChildEnvOpaque+"="+string(opaqueJSON))
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Pdeathsig: syscall.SIGTERM,
|
||||
}
|
||||
childNS, err := ns.GetNS(cfg.NetNSPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := childNS.Do(func(_ ns.NetNS) error {
|
||||
logrus.Infof("starting child driver in child netns (%q %v)", cmd.Path, cmd.Args)
|
||||
return cmd.Start()
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Info("waiting for initComplete")
|
||||
// wait for the child to connect to the parent
|
||||
select {
|
||||
case <-initComplete:
|
||||
logrus.Infof("initComplete is closed; parent and child established the communication channel")
|
||||
case err := <-errCh:
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
logrus.Info("stopping parent driver")
|
||||
quit <- struct{}{}
|
||||
if err := <-errCh; err != nil {
|
||||
logrus.WithError(err).Warn("parent driver returned error on exit")
|
||||
}
|
||||
}()
|
||||
|
||||
// let parent expose ports
|
||||
logrus.Infof("exposing ports %v", cfg.Mappings)
|
||||
if err := exposePorts(driver, cfg.Mappings); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// write and close ReadyFD (convention is same as slirp4netns --ready-fd)
|
||||
logrus.Info("ready")
|
||||
if _, err := readyW.Write([]byte("1")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := readyW.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait for ExitFD to be closed
|
||||
logrus.Info("waiting for exitfd to be closed")
|
||||
if _, err := ioutil.ReadAll(exitR); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func exposePorts(pm rkport.Manager, portMappings []ocicni.PortMapping) error {
|
||||
ctx := context.TODO()
|
||||
for _, i := range portMappings {
|
||||
hostIP := i.HostIP
|
||||
if hostIP == "" {
|
||||
hostIP = "0.0.0.0"
|
||||
}
|
||||
spec := rkport.Spec{
|
||||
Proto: i.Protocol,
|
||||
ParentIP: hostIP,
|
||||
ParentPort: int(i.HostPort),
|
||||
ChildPort: int(i.ContainerPort),
|
||||
}
|
||||
if err := rkportutil.ValidatePortSpec(spec, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := pm.AddPort(ctx, spec); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func child() error {
|
||||
// load the config from the parent
|
||||
var opaque map[string]string
|
||||
if err := json.Unmarshal([]byte(os.Getenv(reexecChildEnvOpaque)), &opaque); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// start the child driver
|
||||
quit := make(chan struct{})
|
||||
errCh := make(chan error)
|
||||
go func() {
|
||||
d := rkbuiltin.NewChildDriver(os.Stderr)
|
||||
dErr := d.RunChildDriver(opaque, quit)
|
||||
errCh <- dErr
|
||||
}()
|
||||
defer func() {
|
||||
logrus.Info("stopping child driver")
|
||||
quit <- struct{}{}
|
||||
if err := <-errCh; err != nil {
|
||||
logrus.WithError(err).Warn("child driver returned error on exit")
|
||||
}
|
||||
}()
|
||||
|
||||
// wait for stdin to be closed
|
||||
if _, err := ioutil.ReadAll(os.Stdin); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type logrusWriter struct {
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (w *logrusWriter) Write(p []byte) (int, error) {
|
||||
logrus.Infof("%s%s", w.prefix, string(p))
|
||||
return len(p), nil
|
||||
}
|
202
vendor/github.com/rootless-containers/rootlesskit/LICENSE
generated
vendored
Normal file
202
vendor/github.com/rootless-containers/rootlesskit/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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.
|
66
vendor/github.com/rootless-containers/rootlesskit/pkg/msgutil/msgutil.go
generated
vendored
Normal file
66
vendor/github.com/rootless-containers/rootlesskit/pkg/msgutil/msgutil.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
// Package msgutil provides utility for JSON message with uint32le header
|
||||
package msgutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
maxLength = 1 << 16
|
||||
)
|
||||
|
||||
func MarshalToWriter(w io.Writer, x interface{}) (int, error) {
|
||||
b, err := json.Marshal(x)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(b) > maxLength {
|
||||
return 0, errors.Errorf("bad message length: %d (max: %d)", len(b), maxLength)
|
||||
}
|
||||
h := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(h, uint32(len(b)))
|
||||
return w.Write(append(h, b...))
|
||||
}
|
||||
|
||||
func UnmarshalFromReader(r io.Reader, x interface{}) (int, error) {
|
||||
hdr := make([]byte, 4)
|
||||
n, err := r.Read(hdr)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if n != 4 {
|
||||
return n, errors.Errorf("read %d bytes, expected 4 bytes", n)
|
||||
}
|
||||
bLen := binary.LittleEndian.Uint32(hdr)
|
||||
if bLen > maxLength || bLen < 1 {
|
||||
return n, errors.Errorf("bad message length: %d (max: %d)", bLen, maxLength)
|
||||
}
|
||||
b := make([]byte, bLen)
|
||||
n, err = r.Read(b)
|
||||
if err != nil {
|
||||
return 4 + n, err
|
||||
}
|
||||
if n != int(bLen) {
|
||||
return 4 + n, errors.Errorf("read %d bytes, expected %d bytes", n, bLen)
|
||||
}
|
||||
return 4 + n, json.Unmarshal(b, x)
|
||||
}
|
||||
|
||||
func Marshal(x interface{}) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
_, err := MarshalToWriter(&b, x)
|
||||
return b.Bytes(), err
|
||||
}
|
||||
|
||||
func Unmarshal(b []byte, x interface{}) error {
|
||||
n, err := UnmarshalFromReader(bytes.NewReader(b), x)
|
||||
if n != len(b) {
|
||||
return errors.Errorf("read %d bytes, expected %d bytes", n, len(b))
|
||||
}
|
||||
return err
|
||||
}
|
14
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/builtin.go
generated
vendored
Normal file
14
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/builtin.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package builtin
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/child"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent"
|
||||
)
|
||||
|
||||
var (
|
||||
NewParentDriver func(logWriter io.Writer, stateDir string) (port.ParentDriver, error) = parent.NewDriver
|
||||
NewChildDriver func(logWriter io.Writer) port.ChildDriver = child.NewDriver
|
||||
)
|
134
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/child/child.go
generated
vendored
Normal file
134
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/child/child.go
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
package child
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/rootless-containers/rootlesskit/pkg/msgutil"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
|
||||
opaquepkg "github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque"
|
||||
)
|
||||
|
||||
func NewDriver(logWriter io.Writer) port.ChildDriver {
|
||||
return &childDriver{
|
||||
logWriter: logWriter,
|
||||
}
|
||||
}
|
||||
|
||||
type childDriver struct {
|
||||
logWriter io.Writer
|
||||
}
|
||||
|
||||
func (d *childDriver) RunChildDriver(opaque map[string]string, quit <-chan struct{}) error {
|
||||
socketPath := opaque[opaquepkg.SocketPath]
|
||||
if socketPath == "" {
|
||||
return errors.New("socket path not set")
|
||||
}
|
||||
childReadyPipePath := opaque[opaquepkg.ChildReadyPipePath]
|
||||
if childReadyPipePath == "" {
|
||||
return errors.New("child ready pipe path not set")
|
||||
}
|
||||
childReadyPipeW, err := os.OpenFile(childReadyPipePath, os.O_WRONLY, os.ModeNamedPipe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ln, err := net.ListenUnix("unix", &net.UnixAddr{
|
||||
Name: socketPath,
|
||||
Net: "unix",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// write nothing, just close
|
||||
if err = childReadyPipeW.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
stopAccept := make(chan struct{}, 1)
|
||||
go func() {
|
||||
<-quit
|
||||
stopAccept <- struct{}{}
|
||||
ln.Close()
|
||||
}()
|
||||
for {
|
||||
c, err := ln.AcceptUnix()
|
||||
if err != nil {
|
||||
select {
|
||||
case <-stopAccept:
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
if rerr := d.routine(c); rerr != nil {
|
||||
rep := msg.Reply{
|
||||
Error: rerr.Error(),
|
||||
}
|
||||
msgutil.MarshalToWriter(c, &rep)
|
||||
}
|
||||
c.Close()
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *childDriver) routine(c *net.UnixConn) error {
|
||||
var req msg.Request
|
||||
if _, err := msgutil.UnmarshalFromReader(c, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
switch req.Type {
|
||||
case msg.RequestTypeInit:
|
||||
return d.handleConnectInit(c, &req)
|
||||
case msg.RequestTypeConnect:
|
||||
return d.handleConnectRequest(c, &req)
|
||||
default:
|
||||
return errors.Errorf("unknown request type %q", req.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *childDriver) handleConnectInit(c *net.UnixConn, req *msg.Request) error {
|
||||
_, err := msgutil.MarshalToWriter(c, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *childDriver) handleConnectRequest(c *net.UnixConn, req *msg.Request) error {
|
||||
switch req.Proto {
|
||||
case "tcp":
|
||||
case "udp":
|
||||
default:
|
||||
return errors.Errorf("unknown proto: %q", req.Proto)
|
||||
}
|
||||
var dialer net.Dialer
|
||||
targetConn, err := dialer.Dial(req.Proto, fmt.Sprintf("127.0.0.1:%d", req.Port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer targetConn.Close() // no effect on duplicated FD
|
||||
targetConnFiler, ok := targetConn.(filer)
|
||||
if !ok {
|
||||
return errors.Errorf("unknown target connection: %+v", targetConn)
|
||||
}
|
||||
targetConnFile, err := targetConnFiler.File()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oob := unix.UnixRights(int(targetConnFile.Fd()))
|
||||
f, err := c.File()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = unix.Sendmsg(int(f.Fd()), []byte("dummy"), oob, nil, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// filer is implemented by *net.TCPConn and *net.UDPConn
|
||||
type filer interface {
|
||||
File() (f *os.File, err error)
|
||||
}
|
129
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg/msg.go
generated
vendored
Normal file
129
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg/msg.go
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
package msg
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/rootless-containers/rootlesskit/pkg/msgutil"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
)
|
||||
|
||||
const (
|
||||
RequestTypeInit = "init"
|
||||
RequestTypeConnect = "connect"
|
||||
)
|
||||
|
||||
// Request and Response are encoded as JSON with uint32le length header.
|
||||
type Request struct {
|
||||
Type string // "init" or "connect"
|
||||
Proto string // "tcp" or "udp"
|
||||
Port int
|
||||
}
|
||||
|
||||
// Reply may contain FD as OOB
|
||||
type Reply struct {
|
||||
Error string
|
||||
}
|
||||
|
||||
// Initiate sends "init" request to the child UNIX socket.
|
||||
func Initiate(c *net.UnixConn) error {
|
||||
req := Request{
|
||||
Type: RequestTypeInit,
|
||||
}
|
||||
if _, err := msgutil.MarshalToWriter(c, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.CloseWrite(); err != nil {
|
||||
return err
|
||||
}
|
||||
var rep Reply
|
||||
if _, err := msgutil.UnmarshalFromReader(c, &rep); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.CloseRead()
|
||||
}
|
||||
|
||||
// ConnectToChild connects to the child UNIX socket, and obtains TCP or UDP socket FD
|
||||
// that corresponds to the port spec.
|
||||
func ConnectToChild(c *net.UnixConn, spec port.Spec) (int, error) {
|
||||
req := Request{
|
||||
Type: RequestTypeConnect,
|
||||
Proto: spec.Proto,
|
||||
Port: spec.ChildPort,
|
||||
}
|
||||
if _, err := msgutil.MarshalToWriter(c, &req); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := c.CloseWrite(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
oobSpace := unix.CmsgSpace(4)
|
||||
oob := make([]byte, oobSpace)
|
||||
_, oobN, _, _, err := c.ReadMsgUnix(nil, oob)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if oobN != oobSpace {
|
||||
return 0, errors.Errorf("expected OOB space %d, got %d", oobSpace, oobN)
|
||||
}
|
||||
oob = oob[:oobN]
|
||||
fd, err := parseFDFromOOB(oob)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := c.CloseRead(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return fd, nil
|
||||
}
|
||||
|
||||
// ConnectToChildWithSocketPath wraps ConnectToChild
|
||||
func ConnectToChildWithSocketPath(socketPath string, spec port.Spec) (int, error) {
|
||||
var dialer net.Dialer
|
||||
conn, err := dialer.Dial("unix", socketPath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer conn.Close()
|
||||
c := conn.(*net.UnixConn)
|
||||
return ConnectToChild(c, spec)
|
||||
}
|
||||
|
||||
// ConnectToChildWithRetry retries ConnectToChild every (i*5) milliseconds.
|
||||
func ConnectToChildWithRetry(socketPath string, spec port.Spec, retries int) (int, error) {
|
||||
for i := 0; i < retries; i++ {
|
||||
fd, err := ConnectToChildWithSocketPath(socketPath, spec)
|
||||
if i == retries-1 && err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err == nil {
|
||||
return fd, err
|
||||
}
|
||||
// TODO: backoff
|
||||
time.Sleep(time.Duration(i*5) * time.Millisecond)
|
||||
}
|
||||
// NOT REACHED
|
||||
return 0, errors.New("reached max retry")
|
||||
}
|
||||
|
||||
func parseFDFromOOB(oob []byte) (int, error) {
|
||||
scms, err := unix.ParseSocketControlMessage(oob)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(scms) != 1 {
|
||||
return 0, errors.Errorf("unexpected scms: %v", scms)
|
||||
}
|
||||
scm := scms[0]
|
||||
fds, err := unix.ParseUnixRights(&scm)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(fds) != 1 {
|
||||
return 0, errors.Errorf("unexpected fds: %v", fds)
|
||||
}
|
||||
return fds[0], nil
|
||||
}
|
6
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque/opaque.go
generated
vendored
Normal file
6
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque/opaque.go
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
package opaque
|
||||
|
||||
const (
|
||||
SocketPath = "builtin.socketpath"
|
||||
ChildReadyPipePath = "builtin.readypipepath"
|
||||
)
|
145
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go
generated
vendored
Normal file
145
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
package parent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/portutil"
|
||||
)
|
||||
|
||||
// NewDriver for builtin driver.
|
||||
func NewDriver(logWriter io.Writer, stateDir string) (port.ParentDriver, error) {
|
||||
// TODO: consider using socketpair FD instead of socket file
|
||||
socketPath := filepath.Join(stateDir, ".bp.sock")
|
||||
childReadyPipePath := filepath.Join(stateDir, ".bp-ready.pipe")
|
||||
// remove the path just in case the previous rootlesskit instance crashed
|
||||
if err := os.RemoveAll(childReadyPipePath); err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot remove %s", childReadyPipePath)
|
||||
}
|
||||
if err := syscall.Mkfifo(childReadyPipePath, 0600); err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot mkfifo %s", childReadyPipePath)
|
||||
}
|
||||
d := driver{
|
||||
logWriter: logWriter,
|
||||
socketPath: socketPath,
|
||||
childReadyPipePath: childReadyPipePath,
|
||||
ports: make(map[int]*port.Status, 0),
|
||||
stoppers: make(map[int]func() error, 0),
|
||||
nextID: 1,
|
||||
}
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
type driver struct {
|
||||
logWriter io.Writer
|
||||
socketPath string
|
||||
childReadyPipePath string
|
||||
mu sync.Mutex
|
||||
ports map[int]*port.Status
|
||||
stoppers map[int]func() error
|
||||
nextID int
|
||||
}
|
||||
|
||||
func (d *driver) OpaqueForChild() map[string]string {
|
||||
return map[string]string{
|
||||
opaque.SocketPath: d.socketPath,
|
||||
opaque.ChildReadyPipePath: d.childReadyPipePath,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) RunParentDriver(initComplete chan struct{}, quit <-chan struct{}, _ *port.ChildContext) error {
|
||||
childReadyPipeR, err := os.OpenFile(d.childReadyPipePath, os.O_RDONLY, os.ModeNamedPipe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = ioutil.ReadAll(childReadyPipeR); err != nil {
|
||||
return err
|
||||
}
|
||||
childReadyPipeR.Close()
|
||||
var dialer net.Dialer
|
||||
conn, err := dialer.Dial("unix", d.socketPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = msg.Initiate(conn.(*net.UnixConn))
|
||||
conn.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
initComplete <- struct{}{}
|
||||
<-quit
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) AddPort(ctx context.Context, spec port.Spec) (*port.Status, error) {
|
||||
d.mu.Lock()
|
||||
err := portutil.ValidatePortSpec(spec, d.ports)
|
||||
d.mu.Unlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
routineStopCh := make(chan struct{})
|
||||
routineStop := func() error {
|
||||
close(routineStopCh)
|
||||
return nil // FIXME
|
||||
}
|
||||
switch spec.Proto {
|
||||
case "tcp":
|
||||
err = tcp.Run(d.socketPath, spec, routineStopCh, d.logWriter)
|
||||
case "udp":
|
||||
err = udp.Run(d.socketPath, spec, routineStopCh, d.logWriter)
|
||||
default:
|
||||
// NOTREACHED
|
||||
return nil, errors.New("spec was not validated?")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.mu.Lock()
|
||||
id := d.nextID
|
||||
st := port.Status{
|
||||
ID: id,
|
||||
Spec: spec,
|
||||
}
|
||||
d.ports[id] = &st
|
||||
d.stoppers[id] = routineStop
|
||||
d.nextID++
|
||||
d.mu.Unlock()
|
||||
return &st, nil
|
||||
}
|
||||
|
||||
func (d *driver) ListPorts(ctx context.Context) ([]port.Status, error) {
|
||||
var ports []port.Status
|
||||
d.mu.Lock()
|
||||
for _, p := range d.ports {
|
||||
ports = append(ports, *p)
|
||||
}
|
||||
d.mu.Unlock()
|
||||
return ports, nil
|
||||
}
|
||||
|
||||
func (d *driver) RemovePort(ctx context.Context, id int) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
stop, ok := d.stoppers[id]
|
||||
if !ok {
|
||||
return errors.Errorf("unknown id: %d", id)
|
||||
}
|
||||
err := stop()
|
||||
delete(d.stoppers, id)
|
||||
delete(d.ports, id)
|
||||
return err
|
||||
}
|
104
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go
generated
vendored
Normal file
104
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
|
||||
)
|
||||
|
||||
func Run(socketPath string, spec port.Spec, stopCh <-chan struct{}, logWriter io.Writer) error {
|
||||
ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", spec.ParentIP, spec.ParentPort))
|
||||
if err != nil {
|
||||
fmt.Fprintf(logWriter, "listen: %v\n", err)
|
||||
return err
|
||||
}
|
||||
newConns := make(chan net.Conn)
|
||||
go func() {
|
||||
for {
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
fmt.Fprintf(logWriter, "accept: %v\n", err)
|
||||
close(newConns)
|
||||
return
|
||||
}
|
||||
newConns <- c
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer ln.Close()
|
||||
for {
|
||||
select {
|
||||
case c, ok := <-newConns:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
if err := copyConnToChild(c, socketPath, spec, stopCh); err != nil {
|
||||
fmt.Fprintf(logWriter, "copyConnToChild: %v\n", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
case <-stopCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
// no wait
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyConnToChild(c net.Conn, socketPath string, spec port.Spec, stopCh <-chan struct{}) error {
|
||||
defer c.Close()
|
||||
// get fd from the child as an SCM_RIGHTS cmsg
|
||||
fd, err := msg.ConnectToChildWithRetry(socketPath, spec, 10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f := os.NewFile(uintptr(fd), "")
|
||||
defer f.Close()
|
||||
fc, err := net.FileConn(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fc.Close()
|
||||
bicopy(c, fc, stopCh)
|
||||
return nil
|
||||
}
|
||||
|
||||
// bicopy is based on libnetwork/cmd/proxy/tcp_proxy.go .
|
||||
// NOTE: sendfile(2) cannot be used for sockets
|
||||
func bicopy(x, y net.Conn, quit <-chan struct{}) {
|
||||
var wg sync.WaitGroup
|
||||
var broker = func(to, from net.Conn) {
|
||||
io.Copy(to, from)
|
||||
if fromTCP, ok := from.(*net.TCPConn); ok {
|
||||
fromTCP.CloseRead()
|
||||
}
|
||||
if toTCP, ok := to.(*net.TCPConn); ok {
|
||||
toTCP.CloseWrite()
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
wg.Add(2)
|
||||
go broker(x, y)
|
||||
go broker(y, x)
|
||||
finish := make(chan struct{})
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(finish)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-quit:
|
||||
case <-finish:
|
||||
}
|
||||
x.Close()
|
||||
y.Close()
|
||||
<-finish
|
||||
}
|
60
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go
generated
vendored
Normal file
60
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
package udp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udpproxy"
|
||||
)
|
||||
|
||||
func Run(socketPath string, spec port.Spec, stopCh <-chan struct{}, logWriter io.Writer) error {
|
||||
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", spec.ParentIP, spec.ParentPort))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c, err := net.ListenUDP("udp", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
udpp := &udpproxy.UDPProxy{
|
||||
LogWriter: logWriter,
|
||||
Listener: c,
|
||||
BackendDial: func() (*net.UDPConn, error) {
|
||||
// get fd from the child as an SCM_RIGHTS cmsg
|
||||
fd, err := msg.ConnectToChildWithRetry(socketPath, spec, 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f := os.NewFile(uintptr(fd), "")
|
||||
defer f.Close()
|
||||
fc, err := net.FileConn(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uc, ok := fc.(*net.UDPConn)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("file conn doesn't implement *net.UDPConn: %+v", fc)
|
||||
}
|
||||
return uc, nil
|
||||
},
|
||||
}
|
||||
go udpp.Run()
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-stopCh:
|
||||
// udpp.Close closes ln as well
|
||||
udpp.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
// no wait
|
||||
return nil
|
||||
}
|
150
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udpproxy/udp_proxy.go
generated
vendored
Normal file
150
vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udpproxy/udp_proxy.go
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
// Package udpproxy is from https://raw.githubusercontent.com/docker/libnetwork/fec6476dfa21380bf8ee4d74048515d968c1ee63/cmd/proxy/udp_proxy.go
|
||||
package udpproxy
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// UDPConnTrackTimeout is the timeout used for UDP connection tracking
|
||||
UDPConnTrackTimeout = 90 * time.Second
|
||||
// UDPBufSize is the buffer size for the UDP proxy
|
||||
UDPBufSize = 65507
|
||||
)
|
||||
|
||||
// A net.Addr where the IP is split into two fields so you can use it as a key
|
||||
// in a map:
|
||||
type connTrackKey struct {
|
||||
IPHigh uint64
|
||||
IPLow uint64
|
||||
Port int
|
||||
}
|
||||
|
||||
func newConnTrackKey(addr *net.UDPAddr) *connTrackKey {
|
||||
if len(addr.IP) == net.IPv4len {
|
||||
return &connTrackKey{
|
||||
IPHigh: 0,
|
||||
IPLow: uint64(binary.BigEndian.Uint32(addr.IP)),
|
||||
Port: addr.Port,
|
||||
}
|
||||
}
|
||||
return &connTrackKey{
|
||||
IPHigh: binary.BigEndian.Uint64(addr.IP[:8]),
|
||||
IPLow: binary.BigEndian.Uint64(addr.IP[8:]),
|
||||
Port: addr.Port,
|
||||
}
|
||||
}
|
||||
|
||||
type connTrackMap map[connTrackKey]*net.UDPConn
|
||||
|
||||
// UDPProxy is proxy for which handles UDP datagrams.
|
||||
// From libnetwork udp_proxy.go .
|
||||
type UDPProxy struct {
|
||||
LogWriter io.Writer
|
||||
Listener *net.UDPConn
|
||||
BackendDial func() (*net.UDPConn, error)
|
||||
connTrackTable connTrackMap
|
||||
connTrackLock sync.Mutex
|
||||
}
|
||||
|
||||
func (proxy *UDPProxy) replyLoop(proxyConn *net.UDPConn, clientAddr *net.UDPAddr, clientKey *connTrackKey) {
|
||||
defer func() {
|
||||
proxy.connTrackLock.Lock()
|
||||
delete(proxy.connTrackTable, *clientKey)
|
||||
proxy.connTrackLock.Unlock()
|
||||
proxyConn.Close()
|
||||
}()
|
||||
|
||||
readBuf := make([]byte, UDPBufSize)
|
||||
for {
|
||||
proxyConn.SetReadDeadline(time.Now().Add(UDPConnTrackTimeout))
|
||||
again:
|
||||
read, err := proxyConn.Read(readBuf)
|
||||
if err != nil {
|
||||
if err, ok := err.(*net.OpError); ok && err.Err == syscall.ECONNREFUSED {
|
||||
// This will happen if the last write failed
|
||||
// (e.g: nothing is actually listening on the
|
||||
// proxied port on the container), ignore it
|
||||
// and continue until UDPConnTrackTimeout
|
||||
// expires:
|
||||
goto again
|
||||
}
|
||||
return
|
||||
}
|
||||
for i := 0; i != read; {
|
||||
written, err := proxy.Listener.WriteToUDP(readBuf[i:read], clientAddr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
i += written
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run starts forwarding the traffic using UDP.
|
||||
func (proxy *UDPProxy) Run() {
|
||||
proxy.connTrackTable = make(connTrackMap)
|
||||
readBuf := make([]byte, UDPBufSize)
|
||||
for {
|
||||
read, from, err := proxy.Listener.ReadFromUDP(readBuf)
|
||||
if err != nil {
|
||||
// NOTE: Apparently ReadFrom doesn't return
|
||||
// ECONNREFUSED like Read do (see comment in
|
||||
// UDPProxy.replyLoop)
|
||||
if !isClosedError(err) {
|
||||
fmt.Fprintf(proxy.LogWriter, "Stopping proxy on udp: %v\n", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
fromKey := newConnTrackKey(from)
|
||||
proxy.connTrackLock.Lock()
|
||||
proxyConn, hit := proxy.connTrackTable[*fromKey]
|
||||
if !hit {
|
||||
proxyConn, err = proxy.BackendDial()
|
||||
if err != nil {
|
||||
fmt.Fprintf(proxy.LogWriter, "Can't proxy a datagram to udp: %v\n", err)
|
||||
proxy.connTrackLock.Unlock()
|
||||
continue
|
||||
}
|
||||
proxy.connTrackTable[*fromKey] = proxyConn
|
||||
go proxy.replyLoop(proxyConn, from, fromKey)
|
||||
}
|
||||
proxy.connTrackLock.Unlock()
|
||||
for i := 0; i != read; {
|
||||
written, err := proxyConn.Write(readBuf[i:read])
|
||||
if err != nil {
|
||||
fmt.Fprintf(proxy.LogWriter, "Can't proxy a datagram to udp: %v\n", err)
|
||||
break
|
||||
}
|
||||
i += written
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close stops forwarding the traffic.
|
||||
func (proxy *UDPProxy) Close() {
|
||||
proxy.Listener.Close()
|
||||
proxy.connTrackLock.Lock()
|
||||
defer proxy.connTrackLock.Unlock()
|
||||
for _, conn := range proxy.connTrackTable {
|
||||
conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func isClosedError(err error) bool {
|
||||
/* This comparison is ugly, but unfortunately, net.go doesn't export errClosing.
|
||||
* See:
|
||||
* http://golang.org/src/pkg/net/net.go
|
||||
* https://code.google.com/p/go/issues/detail?id=4337
|
||||
* https://groups.google.com/forum/#!msg/golang-nuts/0_aaCvBmOcM/SptmDyX1XJMJ
|
||||
*/
|
||||
return strings.HasSuffix(err.Error(), "use of closed network connection")
|
||||
}
|
51
vendor/github.com/rootless-containers/rootlesskit/pkg/port/port.go
generated
vendored
Normal file
51
vendor/github.com/rootless-containers/rootlesskit/pkg/port/port.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
package port
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Spec struct {
|
||||
Proto string `json:"proto,omitempty"` // either "tcp" or "udp". in future "sctp" will be supported as well.
|
||||
ParentIP string `json:"parentIP,omitempty"` // IPv4 address. can be empty (0.0.0.0).
|
||||
ParentPort int `json:"parentPort,omitempty"`
|
||||
ChildPort int `json:"childPort,omitempty"`
|
||||
}
|
||||
|
||||
type Status struct {
|
||||
ID int `json:"id"`
|
||||
Spec Spec `json:"spec"`
|
||||
}
|
||||
|
||||
// Manager MUST be thread-safe.
|
||||
type Manager interface {
|
||||
AddPort(ctx context.Context, spec Spec) (*Status, error)
|
||||
ListPorts(ctx context.Context) ([]Status, error)
|
||||
RemovePort(ctx context.Context, id int) error
|
||||
}
|
||||
|
||||
// ChildContext is used for RunParentDriver
|
||||
type ChildContext struct {
|
||||
// PID of the child, can be used for ns-entering to the child namespaces.
|
||||
PID int
|
||||
// IP of the tap device
|
||||
IP net.IP
|
||||
}
|
||||
|
||||
// ParentDriver is a driver for the parent process.
|
||||
type ParentDriver interface {
|
||||
Manager
|
||||
// OpaqueForChild typically consists of socket path
|
||||
// for controlling child from parent
|
||||
OpaqueForChild() map[string]string
|
||||
// RunParentDriver signals initComplete when ParentDriver is ready to
|
||||
// serve as Manager.
|
||||
// RunParentDriver blocks until quit is signaled.
|
||||
//
|
||||
// ChildContext is optional.
|
||||
RunParentDriver(initComplete chan struct{}, quit <-chan struct{}, cctx *ChildContext) error
|
||||
}
|
||||
|
||||
type ChildDriver interface {
|
||||
RunChildDriver(opaque map[string]string, quit <-chan struct{}) error
|
||||
}
|
67
vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go
generated
vendored
Normal file
67
vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
package portutil
|
||||
|
||||
import (
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
)
|
||||
|
||||
// ParsePortSpec parses a Docker-like representation of PortSpec.
|
||||
// e.g. "127.0.0.1:8080:80/tcp"
|
||||
func ParsePortSpec(s string) (*port.Spec, error) {
|
||||
r := regexp.MustCompile("^([0-9a-f\\.]+):([0-9]+):([0-9]+)/([a-z]+)$")
|
||||
g := r.FindStringSubmatch(s)
|
||||
if len(g) != 5 {
|
||||
return nil, errors.Errorf("unexpected PortSpec string: %q", s)
|
||||
}
|
||||
parentIP := g[1]
|
||||
parentPort, err := strconv.Atoi(g[2])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unexpected ParentPort in PortSpec string: %q", s)
|
||||
}
|
||||
childPort, err := strconv.Atoi(g[3])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unexpected ChildPort in PortSpec string: %q", s)
|
||||
}
|
||||
proto := g[4]
|
||||
// validation is up to the caller (as json.Unmarshal doesn't validate values)
|
||||
return &port.Spec{
|
||||
Proto: proto,
|
||||
ParentIP: parentIP,
|
||||
ParentPort: parentPort,
|
||||
ChildPort: childPort,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ValidatePortSpec validates *port.Spec.
|
||||
// existingPorts can be optionally passed for detecting conflicts.
|
||||
func ValidatePortSpec(spec port.Spec, existingPorts map[int]*port.Status) error {
|
||||
if spec.Proto != "tcp" && spec.Proto != "udp" {
|
||||
return errors.Errorf("unknown proto: %q", spec.Proto)
|
||||
}
|
||||
if spec.ParentIP != "" {
|
||||
if net.ParseIP(spec.ParentIP) == nil {
|
||||
return errors.Errorf("invalid ParentIP: %q", spec.ParentIP)
|
||||
}
|
||||
}
|
||||
if spec.ParentPort <= 0 || spec.ParentPort > 65535 {
|
||||
return errors.Errorf("invalid ParentPort: %q", spec.ParentPort)
|
||||
}
|
||||
if spec.ChildPort <= 0 || spec.ChildPort > 65535 {
|
||||
return errors.Errorf("invalid ChildPort: %q", spec.ChildPort)
|
||||
}
|
||||
for id, p := range existingPorts {
|
||||
sp := p.Spec
|
||||
sameProto := sp.Proto == spec.Proto
|
||||
sameParent := sp.ParentIP == spec.ParentIP && sp.ParentPort == spec.ParentPort
|
||||
sameChild := sp.ChildPort == spec.ChildPort
|
||||
if sameProto && (sameParent || sameChild) {
|
||||
return errors.Errorf("conflict with ID %d", id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
12
vendor/modules.txt
vendored
12
vendor/modules.txt
vendored
@ -442,6 +442,18 @@ github.com/prometheus/common/model
|
||||
github.com/prometheus/procfs
|
||||
github.com/prometheus/procfs/internal/fs
|
||||
github.com/prometheus/procfs/internal/util
|
||||
# github.com/rootless-containers/rootlesskit v0.7.1
|
||||
github.com/rootless-containers/rootlesskit/pkg/msgutil
|
||||
github.com/rootless-containers/rootlesskit/pkg/port
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/builtin
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/builtin/child
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/builtin/msg
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/builtin/opaque
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udpproxy
|
||||
github.com/rootless-containers/rootlesskit/pkg/port/portutil
|
||||
# github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8
|
||||
github.com/safchain/ethtool
|
||||
# github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f
|
||||
|
Reference in New Issue
Block a user