From fb895264989267dffc521b05eeb77bf71e6a6b50 Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 14:38:46 +0100 Subject: [PATCH 01/13] proxy: simply the Dockerfile by shuffling code under vendor/ Note there is a slight name clash between the final binary 'proxy' and the library formerly known as 'proxy'. Resolve this by calling the library 'libproxy'. Signed-off-by: David Scott --- alpine/packages/proxy/Dockerfile | 7 +------ alpine/packages/proxy/main.go | 4 ++-- alpine/packages/proxy/proxy.go | 4 ++-- .../{pkg/proxy => vendor/libproxy}/network_proxy_test.go | 2 +- .../packages/proxy/{pkg/proxy => vendor/libproxy}/proxy.go | 2 +- .../proxy/{pkg/proxy => vendor/libproxy}/stub_proxy.go | 2 +- .../proxy/{pkg/proxy => vendor/libproxy}/tcp_proxy.go | 2 +- .../proxy/{pkg/proxy => vendor/libproxy}/udp_proxy.go | 2 +- 8 files changed, 10 insertions(+), 15 deletions(-) rename alpine/packages/proxy/{pkg/proxy => vendor/libproxy}/network_proxy_test.go (99%) rename alpine/packages/proxy/{pkg/proxy => vendor/libproxy}/proxy.go (98%) rename alpine/packages/proxy/{pkg/proxy => vendor/libproxy}/stub_proxy.go (97%) rename alpine/packages/proxy/{pkg/proxy => vendor/libproxy}/tcp_proxy.go (99%) rename alpine/packages/proxy/{pkg/proxy => vendor/libproxy}/udp_proxy.go (99%) diff --git a/alpine/packages/proxy/Dockerfile b/alpine/packages/proxy/Dockerfile index 98054e0cf..d38c03bfe 100644 --- a/alpine/packages/proxy/Dockerfile +++ b/alpine/packages/proxy/Dockerfile @@ -3,12 +3,7 @@ FROM golang:alpine RUN mkdir -p /go/src/proxy WORKDIR /go/src/proxy -COPY * /go/src/proxy/ - -RUN mkdir -p /go/src/pkg/proxy -COPY pkg/* /go/src/pkg/proxy/ -RUN mkdir -p /go/src/vendor/github.com/Sirupsen/logrus -COPY vendor/github.com/Sirupsen/logrus/* /go/src/vendor/github.com/Sirupsen/logrus/ +COPY ./ /go/src/proxy/ ARG GOARCH ARG GOOS diff --git a/alpine/packages/proxy/main.go b/alpine/packages/proxy/main.go index 78fc7c13f..19bbd7b85 100644 --- a/alpine/packages/proxy/main.go +++ b/alpine/packages/proxy/main.go @@ -6,7 +6,7 @@ import ( "log" "net" "os" - "pkg/proxy" + "libproxy" "strings" ) @@ -17,7 +17,7 @@ func main() { if err != nil { sendError(err) } - p, err := proxy.NewProxy(host, container) + p, err := libproxy.NewProxy(host, container) if err != nil { unexposePort(host) sendError(err) diff --git a/alpine/packages/proxy/proxy.go b/alpine/packages/proxy/proxy.go index f730bc22e..0724f0c52 100644 --- a/alpine/packages/proxy/proxy.go +++ b/alpine/packages/proxy/proxy.go @@ -9,7 +9,7 @@ import ( "os/signal" "syscall" - "pkg/proxy" + "libproxy" ) // sendError signals the error to the parent and quits the process. @@ -59,7 +59,7 @@ func parseHostContainerAddrs() (host net.Addr, port int, container net.Addr) { return host, port, container } -func handleStopSignals(p proxy.Proxy) { +func handleStopSignals(p libproxy.Proxy) { s := make(chan os.Signal, 10) signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP) diff --git a/alpine/packages/proxy/pkg/proxy/network_proxy_test.go b/alpine/packages/proxy/vendor/libproxy/network_proxy_test.go similarity index 99% rename from alpine/packages/proxy/pkg/proxy/network_proxy_test.go rename to alpine/packages/proxy/vendor/libproxy/network_proxy_test.go index 9e382567c..f4458939f 100644 --- a/alpine/packages/proxy/pkg/proxy/network_proxy_test.go +++ b/alpine/packages/proxy/vendor/libproxy/network_proxy_test.go @@ -1,4 +1,4 @@ -package proxy +package libproxy import ( "bytes" diff --git a/alpine/packages/proxy/pkg/proxy/proxy.go b/alpine/packages/proxy/vendor/libproxy/proxy.go similarity index 98% rename from alpine/packages/proxy/pkg/proxy/proxy.go rename to alpine/packages/proxy/vendor/libproxy/proxy.go index 4e24e5f6a..b825b972a 100644 --- a/alpine/packages/proxy/pkg/proxy/proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/proxy.go @@ -1,6 +1,6 @@ // Package proxy provides a network Proxy interface and implementations for TCP // and UDP. -package proxy +package libproxy import ( "fmt" diff --git a/alpine/packages/proxy/pkg/proxy/stub_proxy.go b/alpine/packages/proxy/vendor/libproxy/stub_proxy.go similarity index 97% rename from alpine/packages/proxy/pkg/proxy/stub_proxy.go rename to alpine/packages/proxy/vendor/libproxy/stub_proxy.go index 571749e46..97a4d3f58 100644 --- a/alpine/packages/proxy/pkg/proxy/stub_proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/stub_proxy.go @@ -1,4 +1,4 @@ -package proxy +package libproxy import ( "net" diff --git a/alpine/packages/proxy/pkg/proxy/tcp_proxy.go b/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go similarity index 99% rename from alpine/packages/proxy/pkg/proxy/tcp_proxy.go rename to alpine/packages/proxy/vendor/libproxy/tcp_proxy.go index 3cd742af7..5a8bc1292 100644 --- a/alpine/packages/proxy/pkg/proxy/tcp_proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go @@ -1,4 +1,4 @@ -package proxy +package libproxy import ( "io" diff --git a/alpine/packages/proxy/pkg/proxy/udp_proxy.go b/alpine/packages/proxy/vendor/libproxy/udp_proxy.go similarity index 99% rename from alpine/packages/proxy/pkg/proxy/udp_proxy.go rename to alpine/packages/proxy/vendor/libproxy/udp_proxy.go index b8375c374..7b59466b0 100644 --- a/alpine/packages/proxy/pkg/proxy/udp_proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/udp_proxy.go @@ -1,4 +1,4 @@ -package proxy +package libproxy import ( "encoding/binary" From 90b1734a52cbdba1ab933c4c38e19452c5b6932f Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 14:40:24 +0100 Subject: [PATCH 02/13] proxy: add a vsock package based on vsudd This package supports a more normal Go interface, in particular it has: // Listen returns a net.Listener which can accept connections on the given // vhan port. func Listen(port uint) (net.Listener, error) Signed-off-by: David Scott --- alpine/packages/proxy/Dockerfile | 4 +- .../vsock/include/uapi/linux/vm_sockets.h | 161 ++++++++++++++++++ alpine/packages/proxy/vendor/vsock/vsock.go | 101 +++++++++++ 3 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 alpine/packages/proxy/vendor/vsock/include/uapi/linux/vm_sockets.h create mode 100644 alpine/packages/proxy/vendor/vsock/vsock.go diff --git a/alpine/packages/proxy/Dockerfile b/alpine/packages/proxy/Dockerfile index d38c03bfe..dc06b22ca 100644 --- a/alpine/packages/proxy/Dockerfile +++ b/alpine/packages/proxy/Dockerfile @@ -1,5 +1,7 @@ FROM golang:alpine +RUN apk update && apk add alpine-sdk + RUN mkdir -p /go/src/proxy WORKDIR /go/src/proxy @@ -8,6 +10,6 @@ COPY ./ /go/src/proxy/ ARG GOARCH ARG GOOS -RUN go install +RUN go install --ldflags '-extldflags "-fno-PIC"' RUN [ -f /go/bin/*/proxy ] && mv /go/bin/*/proxy /go/bin/ || true diff --git a/alpine/packages/proxy/vendor/vsock/include/uapi/linux/vm_sockets.h b/alpine/packages/proxy/vendor/vsock/include/uapi/linux/vm_sockets.h new file mode 100644 index 000000000..41934a185 --- /dev/null +++ b/alpine/packages/proxy/vendor/vsock/include/uapi/linux/vm_sockets.h @@ -0,0 +1,161 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2007-2013 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _UAPI_VM_SOCKETS_H +#define _UAPI_VM_SOCKETS_H + +#ifdef __KERNEL__ +#include +#else +#define __kernel_sa_family_t sa_family_t +#include +#endif + +/* Option name for STREAM socket buffer size. Use as the option name in + * setsockopt(3) or getsockopt(3) to set or get an unsigned long long that + * specifies the size of the buffer underlying a vSockets STREAM socket. + * Value is clamped to the MIN and MAX. + */ + +#define SO_VM_SOCKETS_BUFFER_SIZE 0 + +/* Option name for STREAM socket minimum buffer size. Use as the option name + * in setsockopt(3) or getsockopt(3) to set or get an unsigned long long that + * specifies the minimum size allowed for the buffer underlying a vSockets + * STREAM socket. + */ + +#define SO_VM_SOCKETS_BUFFER_MIN_SIZE 1 + +/* Option name for STREAM socket maximum buffer size. Use as the option name + * in setsockopt(3) or getsockopt(3) to set or get an unsigned long long + * that specifies the maximum size allowed for the buffer underlying a + * vSockets STREAM socket. + */ + +#define SO_VM_SOCKETS_BUFFER_MAX_SIZE 2 + +/* Option name for socket peer's host-specific VM ID. Use as the option name + * in getsockopt(3) to get a host-specific identifier for the peer endpoint's + * VM. The identifier is a signed integer. + * Only available for hypervisor endpoints. + */ + +#define SO_VM_SOCKETS_PEER_HOST_VM_ID 3 + +/* Option name for determining if a socket is trusted. Use as the option name + * in getsockopt(3) to determine if a socket is trusted. The value is a + * signed integer. + */ + +#define SO_VM_SOCKETS_TRUSTED 5 + +/* Option name for STREAM socket connection timeout. Use as the option name + * in setsockopt(3) or getsockopt(3) to set or get the connection + * timeout for a STREAM socket. + */ + +#define SO_VM_SOCKETS_CONNECT_TIMEOUT 6 + +/* Option name for using non-blocking send/receive. Use as the option name + * for setsockopt(3) or getsockopt(3) to set or get the non-blocking + * transmit/receive flag for a STREAM socket. This flag determines whether + * send() and recv() can be called in non-blocking contexts for the given + * socket. The value is a signed integer. + * + * This option is only relevant to kernel endpoints, where descheduling the + * thread of execution is not allowed, for example, while holding a spinlock. + * It is not to be confused with conventional non-blocking socket operations. + * + * Only available for hypervisor endpoints. + */ + +#define SO_VM_SOCKETS_NONBLOCK_TXRX 7 + +/* The vSocket equivalent of INADDR_ANY. This works for the svm_cid field of + * sockaddr_vm and indicates the context ID of the current endpoint. + */ + +#define VMADDR_CID_ANY -1U + +/* Bind to any available port. Works for the svm_port field of + * sockaddr_vm. + */ + +#define VMADDR_PORT_ANY -1U + +/* Use this as the destination CID in an address when referring to the + * hypervisor. VMCI relies on it being 0, but this would be useful for other + * transports too. + */ + +#define VMADDR_CID_HYPERVISOR 0 + +/* This CID is specific to VMCI and can be considered reserved (even VMCI + * doesn't use it anymore, it's a legacy value from an older release). + */ + +#define VMADDR_CID_RESERVED 1 + +/* Use this as the destination CID in an address when referring to the host + * (any process other than the hypervisor). VMCI relies on it being 2, but + * this would be useful for other transports too. + */ + +#define VMADDR_CID_HOST 2 + +/* Invalid vSockets version. */ + +#define VM_SOCKETS_INVALID_VERSION -1U + +/* The epoch (first) component of the vSockets version. A single byte + * representing the epoch component of the vSockets version. + */ + +#define VM_SOCKETS_VERSION_EPOCH(_v) (((_v) & 0xFF000000) >> 24) + +/* The major (second) component of the vSockets version. A single byte + * representing the major component of the vSockets version. Typically + * changes for every major release of a product. + */ + +#define VM_SOCKETS_VERSION_MAJOR(_v) (((_v) & 0x00FF0000) >> 16) + +/* The minor (third) component of the vSockets version. Two bytes representing + * the minor component of the vSockets version. + */ + +#define VM_SOCKETS_VERSION_MINOR(_v) (((_v) & 0x0000FFFF)) + +/* Address structure for vSockets. The address family should be set to + * AF_VSOCK. The structure members should all align on their natural + * boundaries without resorting to compiler packing directives. The total size + * of this structure should be exactly the same as that of struct sockaddr. + */ + +struct sockaddr_vm { + __kernel_sa_family_t svm_family; + unsigned short svm_reserved1; + unsigned int svm_port; + unsigned int svm_cid; + unsigned char svm_zero[sizeof(struct sockaddr) - + sizeof(sa_family_t) - + sizeof(unsigned short) - + sizeof(unsigned int) - sizeof(unsigned int)]; +}; + +#define IOCTL_VM_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9) + +#endif /* _UAPI_VM_SOCKETS_H */ diff --git a/alpine/packages/proxy/vendor/vsock/vsock.go b/alpine/packages/proxy/vendor/vsock/vsock.go new file mode 100644 index 000000000..b17199125 --- /dev/null +++ b/alpine/packages/proxy/vendor/vsock/vsock.go @@ -0,0 +1,101 @@ +package vsock + +import ( + "errors" + "fmt" + "net" + "os" + "syscall" +) + +/* No way to teach net or syscall about vsock sockaddr, so go right to C */ + +/* +#include +#include "include/uapi/linux/vm_sockets.h" +int bind_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) { + return bind(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm)); +} +int connect_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) { + return connect(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm)); +} +int accept_vm(int fd, struct sockaddr_vm *sa_vm, socklen_t *sa_vm_len) { + return accept4(fd, (struct sockaddr *)sa_vm, sa_vm_len, 0); +} +*/ +import "C" + +const ( + AF_VSOCK = 40 + VSOCK_CID_ANY = 4294967295 /* 2^32-1 */ +) + +// Listen returns a net.Listener which can accept connections on the given +// vhan port. +func Listen(port uint) (net.Listener, error) { + accept_fd, err := syscall.Socket(AF_VSOCK, syscall.SOCK_STREAM, 0) + if err != nil { + return nil, err + } + + sa := C.struct_sockaddr_vm{} + sa.svm_family = AF_VSOCK + sa.svm_port = C.uint(port) + sa.svm_cid = VSOCK_CID_ANY + + if ret := C.bind_sockaddr_vm(C.int(accept_fd), &sa); ret != 0 { + return nil, errors.New(fmt.Sprintf("failed bind vsock connection to %08x.%08x, returned %d", sa.svm_cid, sa.svm_port, ret)) + } + + err = syscall.Listen(accept_fd, syscall.SOMAXCONN) + if err != nil { + return nil, err + } + return &vsockListener{accept_fd, port}, nil +} + +type vsockListener struct { + accept_fd int + port uint +} + +func (v *vsockListener) Accept() (net.Conn, error) { + var accept_sa C.struct_sockaddr_vm + var accept_sa_len C.socklen_t + + accept_sa_len = C.sizeof_struct_sockaddr_vm + fd, err := C.accept_vm(C.int(v.accept_fd), &accept_sa, &accept_sa_len) + if err != nil { + return nil, err + } + vsock := os.NewFile(uintptr(fd), fmt.Sprintf("vsock:%d", fd)) + conn, err := net.FileConn(vsock) + if err != nil { + return nil, err + } + return conn, nil +} + +func (v *vsockListener) Close() error { + return syscall.Close(v.accept_fd) +} + +type vsockAddr struct { + network string + addr string +} + +func (a *vsockAddr) Network() string { + return a.network +} + +func (a *vsockAddr) String() string { + return a.addr +} + +func (v *vsockListener) Addr() net.Addr { + return &vsockAddr{ + network: "vsock", + addr: fmt.Sprintf("%08x", v.port), + } +} From 2cf92956026549828b52e6ab34d31f5b422ed9ae Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 15:12:07 +0100 Subject: [PATCH 03/13] proxy: TCPProxy connects to TCP but can read from other things The TCPProxy can proxy from anything which satisfies this interface: type Conn interface { io.Reader io.Writer io.Closer CloseRead() error CloseWrite() error } Signed-off-by: David Scott --- alpine/packages/proxy/vendor/libproxy/tcp_proxy.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go b/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go index 5a8bc1292..6e36075de 100644 --- a/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go @@ -8,6 +8,14 @@ import ( "github.com/Sirupsen/logrus" ) +type Conn interface { + io.Reader + io.Writer + io.Closer + CloseRead() error + CloseWrite() error +} + // TCPProxy is a proxy for TCP connections. It implements the Proxy interface to // handle TCP traffic forwarding between the frontend and backend addresses. type TCPProxy struct { @@ -31,7 +39,7 @@ func NewTCPProxy(frontendAddr, backendAddr *net.TCPAddr) (*TCPProxy, error) { }, nil } -func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) { +func (proxy *TCPProxy) clientLoop(client Conn, quit chan bool) { backend, err := net.DialTCP("tcp", nil, proxy.backendAddr) if err != nil { logrus.Printf("Can't forward traffic to backend tcp/%v: %s\n", proxy.backendAddr, err) @@ -40,7 +48,7 @@ func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) { } event := make(chan int64) - var broker = func(to, from *net.TCPConn) { + var broker = func(to, from Conn) { written, err := io.Copy(to, from) if err != nil { // If the socket we are writing to is shutdown with @@ -85,7 +93,7 @@ func (proxy *TCPProxy) Run() { logrus.Printf("Stopping proxy on tcp/%v for tcp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err) return } - go proxy.clientLoop(client.(*net.TCPConn), quit) + go proxy.clientLoop(client.(Conn), quit) } } From 3c68728e9fa87d540f54dcdf4710ac0e3cd18bd1 Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 16:02:02 +0100 Subject: [PATCH 04/13] proxy: remove assumption that frontend is a TCPListener We require the frontend to be a `net.Listener` and the `net.Conn` connection which are established must be type-switched to `Conn` to support the `CloseRead` and `CloseWrite` methods. Signed-off-by: David Scott --- alpine/packages/proxy/vendor/libproxy/proxy.go | 8 +++++++- alpine/packages/proxy/vendor/libproxy/tcp_proxy.go | 12 ++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/alpine/packages/proxy/vendor/libproxy/proxy.go b/alpine/packages/proxy/vendor/libproxy/proxy.go index b825b972a..79bd6dbe7 100644 --- a/alpine/packages/proxy/vendor/libproxy/proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/proxy.go @@ -24,13 +24,19 @@ type Proxy interface { BackendAddr() net.Addr } + + // NewProxy creates a Proxy according to the specified frontendAddr and backendAddr. func NewProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) { switch frontendAddr.(type) { case *net.UDPAddr: return NewUDPProxy(frontendAddr.(*net.UDPAddr), backendAddr.(*net.UDPAddr)) case *net.TCPAddr: - return NewTCPProxy(frontendAddr.(*net.TCPAddr), backendAddr.(*net.TCPAddr)) + listener, err := net.Listen("tcp", frontendAddr.String()) + if err != nil { + return nil, err + } + return NewTCPProxy(listener, backendAddr.(*net.TCPAddr)) default: panic(fmt.Errorf("Unsupported protocol")) } diff --git a/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go b/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go index 6e36075de..659473fe3 100644 --- a/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go @@ -19,22 +19,18 @@ type Conn interface { // TCPProxy is a proxy for TCP connections. It implements the Proxy interface to // handle TCP traffic forwarding between the frontend and backend addresses. type TCPProxy struct { - listener *net.TCPListener - frontendAddr *net.TCPAddr + listener net.Listener + frontendAddr net.Addr backendAddr *net.TCPAddr } // NewTCPProxy creates a new TCPProxy. -func NewTCPProxy(frontendAddr, backendAddr *net.TCPAddr) (*TCPProxy, error) { - listener, err := net.ListenTCP("tcp", frontendAddr) - if err != nil { - return nil, err - } +func NewTCPProxy(listener net.Listener, backendAddr *net.TCPAddr) (*TCPProxy, error) { // If the port in frontendAddr was 0 then ListenTCP will have a picked // a port to listen on, hence the call to Addr to get that actual port: return &TCPProxy{ listener: listener, - frontendAddr: listener.Addr().(*net.TCPAddr), + frontendAddr: listener.Addr(), backendAddr: backendAddr, }, nil } From 2f80e98e7f51540cc8de6cfde4268d0d5bfb2a3c Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 16:14:05 +0100 Subject: [PATCH 05/13] proxy: vsock connections support CloseRead and CloseWrite This patch adds a wrapper around the `net.Conn` to include the `CloseRead` and `CloseWrite` implementations. This patch also exposes the `VsockAddr` type, which is similar to `TCPAddr` and `UDPAddr`. Signed-off-by: David Scott --- alpine/packages/proxy/vendor/vsock/vsock.go | 75 +++++++++++++++------ 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/alpine/packages/proxy/vendor/vsock/vsock.go b/alpine/packages/proxy/vendor/vsock/vsock.go index b17199125..cf719d9d1 100644 --- a/alpine/packages/proxy/vendor/vsock/vsock.go +++ b/alpine/packages/proxy/vendor/vsock/vsock.go @@ -26,8 +26,8 @@ int accept_vm(int fd, struct sockaddr_vm *sa_vm, socklen_t *sa_vm_len) { import "C" const ( - AF_VSOCK = 40 - VSOCK_CID_ANY = 4294967295 /* 2^32-1 */ + AF_VSOCK = 40 + VSOCK_CID_ANY = 4294967295 /* 2^32-1 */ ) // Listen returns a net.Listener which can accept connections on the given @@ -54,6 +54,13 @@ func Listen(port uint) (net.Listener, error) { return &vsockListener{accept_fd, port}, nil } +// Conn is a vsock connection which support half-close. +type Conn interface { + net.Conn + CloseRead() error + CloseWrite() error +} + type vsockListener struct { accept_fd int port uint @@ -68,34 +75,64 @@ func (v *vsockListener) Accept() (net.Conn, error) { if err != nil { return nil, err } - vsock := os.NewFile(uintptr(fd), fmt.Sprintf("vsock:%d", fd)) - conn, err := net.FileConn(vsock) - if err != nil { - return nil, err - } - return conn, nil + return newVsockConn(uintptr(fd), v.port) } func (v *vsockListener) Close() error { return syscall.Close(v.accept_fd) } -type vsockAddr struct { - network string - addr string +type VsockAddr struct { + Port uint } -func (a *vsockAddr) Network() string { - return a.network +func (a VsockAddr) Network() string { + return "vsock" } -func (a *vsockAddr) String() string { - return a.addr +func (a VsockAddr) String() string { + return fmt.Sprintf("%08x", a.Port) } func (v *vsockListener) Addr() net.Addr { - return &vsockAddr{ - network: "vsock", - addr: fmt.Sprintf("%08x", v.port), - } + return VsockAddr{Port: v.port} +} + +// a wrapper around FileConn which supports CloseRead and CloseWrite +type vsockConn struct { + net.Conn + fd uintptr + local VsockAddr + remote VsockAddr +} + +type VsockConn struct { + vsockConn +} + +func newVsockConn(fd uintptr, localPort uint) (*VsockConn, error) { + vsock := os.NewFile(fd, fmt.Sprintf("vsock:%d", fd)) + conn, err := net.FileConn(vsock) + if err != nil { + return nil, err + } + local := VsockAddr{Port: localPort} + remote := VsockAddr{Port: uint(0)} // FIXME + return &VsockConn{vsockConn{Conn: conn, fd: fd, local: local, remote: remote}}, nil +} + +func (v *VsockConn) LocalAddr() net.Addr { + return v.local +} + +func (v *VsockConn) RemoteAddr() net.Addr { + return v.remote +} + +func (v *VsockConn) CloseRead() error { + return syscall.Shutdown(int(v.fd), syscall.SHUT_RD) +} + +func (v *VsockConn) CloseWrite() error { + return syscall.Shutdown(int(v.fd), syscall.SHUT_WR) } From 403ce4e696b9b1ac7bcf026608f101ae260f7c4f Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 16:15:31 +0100 Subject: [PATCH 06/13] proxy: libproxy: add a case for `VsockAddr` types The `NewProxy` function already knows how to deal with `net.UDPAddr` and `net.TCPAddr`, this patch adds similar support for `vsock.VsockAddr`. Signed-off-by: David Scott --- alpine/packages/proxy/vendor/libproxy/proxy.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/alpine/packages/proxy/vendor/libproxy/proxy.go b/alpine/packages/proxy/vendor/libproxy/proxy.go index 79bd6dbe7..d0098502d 100644 --- a/alpine/packages/proxy/vendor/libproxy/proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/proxy.go @@ -5,6 +5,7 @@ package libproxy import ( "fmt" "net" + "vsock" ) // Proxy defines the behavior of a proxy. It forwards traffic back and forth @@ -37,6 +38,12 @@ func NewProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) { return nil, err } return NewTCPProxy(listener, backendAddr.(*net.TCPAddr)) + case *vsock.VsockAddr: + listener, err := vsock.Listen(frontendAddr.(vsock.VsockAddr).Port) + if err != nil { + return nil, err + } + return NewTCPProxy(listener, backendAddr.(*net.TCPAddr)) default: panic(fmt.Errorf("Unsupported protocol")) } From e4f405be26b5b1b2b0f276a0d9c741b03acc7cdc Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 16:27:59 +0100 Subject: [PATCH 07/13] proxy: request a vsock connection rather than a TCP/IP one Note this means we don't need to figure out our local IP address. Signed-off-by: David Scott --- alpine/packages/proxy/main.go | 33 ++------------------- alpine/packages/proxy/proxy.go | 7 ++++- alpine/packages/proxy/vendor/vsock/vsock.go | 5 ++-- 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/alpine/packages/proxy/main.go b/alpine/packages/proxy/main.go index 19bbd7b85..f70560924 100644 --- a/alpine/packages/proxy/main.go +++ b/alpine/packages/proxy/main.go @@ -8,6 +8,7 @@ import ( "os" "libproxy" "strings" + "vsock" ) func main() { @@ -42,12 +43,7 @@ func exposePort(host net.Addr, port int) error { log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err) return err } - me, err := getMyAddress() - if err != nil { - log.Printf("Failed to determine my local address: %#v\n", err) - return err - } - _, err = ctl.WriteString(fmt.Sprintf("%s:%s:%d", name, me, port)) + _, err = ctl.WriteString(fmt.Sprintf("%s:%d:%d", name, vsock.VSOCK_CID_SELF, vSockPortOffset + port)) if err != nil { log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err) return err @@ -84,28 +80,3 @@ func unexposePort(host net.Addr) { log.Printf("Failed to remove /port/%s: %#v\n", name, err) } } - -var myAddress string - -// getMyAddress returns a string representing my address from the host's -// point of view. For now this is an IP address but it soon should be a vsock -// port. -func getMyAddress() (string, error) { - if myAddress != "" { - return myAddress, nil - } - d, err := os.Open("/port/docker") - if err != nil { - return "", err - } - defer d.Close() - bytes := make([]byte, 100) - count, err := d.Read(bytes) - if err != nil { - return "", err - } - s := string(bytes)[0:count] - bits := strings.Split(s, ":") - myAddress = bits[2] - return myAddress, nil -} diff --git a/alpine/packages/proxy/proxy.go b/alpine/packages/proxy/proxy.go index 0724f0c52..d59d173d5 100644 --- a/alpine/packages/proxy/proxy.go +++ b/alpine/packages/proxy/proxy.go @@ -10,6 +10,7 @@ import ( "syscall" "libproxy" + "vsock" ) // sendError signals the error to the parent and quits the process. @@ -28,6 +29,9 @@ func sendOK() { f.Close() } +// Map dynamic ports onto vsock ports over this offset +var vSockPortOffset = 0x10000 + // From docker/libnetwork/portmapper/proxy.go: // parseHostContainerAddrs parses the flags passed on reexec to create the TCP or UDP @@ -45,7 +49,8 @@ func parseHostContainerAddrs() (host net.Addr, port int, container net.Addr) { switch *proto { case "tcp": - host = &net.TCPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort} + port = vSockPortOffset + *hostPort + host = &vsock.VsockAddr{Port: uint(port)} port = *hostPort container = &net.TCPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort} case "udp": diff --git a/alpine/packages/proxy/vendor/vsock/vsock.go b/alpine/packages/proxy/vendor/vsock/vsock.go index cf719d9d1..91dca0cb3 100644 --- a/alpine/packages/proxy/vendor/vsock/vsock.go +++ b/alpine/packages/proxy/vendor/vsock/vsock.go @@ -26,8 +26,9 @@ int accept_vm(int fd, struct sockaddr_vm *sa_vm, socklen_t *sa_vm_len) { import "C" const ( - AF_VSOCK = 40 - VSOCK_CID_ANY = 4294967295 /* 2^32-1 */ + AF_VSOCK = 40 + VSOCK_CID_ANY = 4294967295 /* 2^32-1 */ + VSOCK_CID_SELF = 3 ) // Listen returns a net.Listener which can accept connections on the given From b0c4fdae37501153a5434f55ac9a138eb459a9d6 Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 17:43:22 +0100 Subject: [PATCH 08/13] proxy: we don't need to explicitly unexposePort any more The port will be automatically removed when the fd/fid is closed by a process exit/crash, or by a hypervisor crash. Signed-off-by: David Scott --- alpine/packages/proxy/main.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/alpine/packages/proxy/main.go b/alpine/packages/proxy/main.go index f70560924..ebd026c24 100644 --- a/alpine/packages/proxy/main.go +++ b/alpine/packages/proxy/main.go @@ -20,13 +20,11 @@ func main() { } p, err := libproxy.NewProxy(host, container) if err != nil { - unexposePort(host) sendError(err) } go handleStopSignals(p) sendOK() p.Run() - unexposePort(host) os.Exit(0) } @@ -71,12 +69,3 @@ func exposePort(host net.Addr, port int) error { return nil } - -func unexposePort(host net.Addr) { - name := host.String() - log.Printf("unexposePort %s\n", name) - err := os.Remove("/port/" + name) - if err != nil { - log.Printf("Failed to remove /port/%s: %#v\n", name, err) - } -} From 1d3b8b566e1c12362275a02c43a71d0068b835d2 Mon Sep 17 00:00:00 2001 From: David Scott Date: Thu, 14 Apr 2016 22:13:38 +0100 Subject: [PATCH 09/13] proxy: tell the /port server the real external IP address Before this we accidentally told it the vsock address, which obviously isn't much good. Signed-off-by: David Scott --- alpine/packages/proxy/main.go | 3 +-- alpine/packages/proxy/proxy.go | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/alpine/packages/proxy/main.go b/alpine/packages/proxy/main.go index ebd026c24..022274fbb 100644 --- a/alpine/packages/proxy/main.go +++ b/alpine/packages/proxy/main.go @@ -8,7 +8,6 @@ import ( "os" "libproxy" "strings" - "vsock" ) func main() { @@ -41,7 +40,7 @@ func exposePort(host net.Addr, port int) error { log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err) return err } - _, err = ctl.WriteString(fmt.Sprintf("%s:%d:%d", name, vsock.VSOCK_CID_SELF, vSockPortOffset + port)) + _, err = ctl.WriteString(fmt.Sprintf("%s:%08x", name, port)) if err != nil { log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err) return err diff --git a/alpine/packages/proxy/proxy.go b/alpine/packages/proxy/proxy.go index d59d173d5..aea703761 100644 --- a/alpine/packages/proxy/proxy.go +++ b/alpine/packages/proxy/proxy.go @@ -10,7 +10,6 @@ import ( "syscall" "libproxy" - "vsock" ) // sendError signals the error to the parent and quits the process. @@ -49,13 +48,12 @@ func parseHostContainerAddrs() (host net.Addr, port int, container net.Addr) { switch *proto { case "tcp": + host = &net.TCPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort} port = vSockPortOffset + *hostPort - host = &vsock.VsockAddr{Port: uint(port)} - port = *hostPort container = &net.TCPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort} case "udp": host = &net.UDPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort} - port = *hostPort + port = vSockPortOffset + *hostPort container = &net.UDPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort} default: log.Fatalf("unsupported protocol %s", *proto) From 586d9c0598ae88bc48df722f0ec6c0122e97ebcf Mon Sep 17 00:00:00 2001 From: David Scott Date: Fri, 15 Apr 2016 11:03:47 +0100 Subject: [PATCH 10/13] proxy: fix up the vsock interface - don't try to create a `FileConn` because the Go library sees through the scam and rejects it - explicitly keep a reference to the `ctl` file just in case the GC decides its dead and should be closed. Signed-off-by: David Scott --- alpine/packages/proxy/main.go | 26 ++++++++------- .../packages/proxy/vendor/libproxy/proxy.go | 2 +- alpine/packages/proxy/vendor/vsock/vsock.go | 33 +++++++++++++++---- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/alpine/packages/proxy/main.go b/alpine/packages/proxy/main.go index 022274fbb..d9787a8f0 100644 --- a/alpine/packages/proxy/main.go +++ b/alpine/packages/proxy/main.go @@ -8,53 +8,57 @@ import ( "os" "libproxy" "strings" + "vsock" ) func main() { host, port, container := parseHostContainerAddrs() - err := exposePort(host, port) + ctl, err := exposePort(host, port) if err != nil { sendError(err) } - p, err := libproxy.NewProxy(host, container) + + p, err := libproxy.NewProxy(&vsock.VsockAddr{Port: uint(port)}, container) if err != nil { sendError(err) } + go handleStopSignals(p) sendOK() p.Run() + ctl.Close() // ensure ctl remains alive and un-GCed until here os.Exit(0) } -func exposePort(host net.Addr, port int) error { +func exposePort(host net.Addr, port int) (*os.File, error) { name := host.String() log.Printf("exposePort %s\n", name) err := os.Mkdir("/port/"+name, 0) if err != nil { log.Printf("Failed to mkdir /port/%s: %#v\n", name, err) - return err + return nil, err } ctl, err := os.OpenFile("/port/"+name+"/ctl", os.O_RDWR, 0) if err != nil { log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err) - return err + return nil, err } _, err = ctl.WriteString(fmt.Sprintf("%s:%08x", name, port)) if err != nil { log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err) - return err + return nil, err } _, err = ctl.Seek(0, 0) if err != nil { log.Printf("Failed to seek on /port/%s/ctl: %#v\n", name, err) - return err + return nil, err } results := make([]byte, 100) count, err := ctl.Read(results) if err != nil { log.Printf("Failed to read from /port/%s/ctl: %#v\n", name, err) - return err + return nil, err } // We deliberately keep the control file open since 9P clunk // will trigger a shutdown on the host side. @@ -63,8 +67,8 @@ func exposePort(host net.Addr, port int) error { if strings.HasPrefix(response, "ERROR ") { os.Remove("/port/" + name + "/ctl") response = strings.Trim(response[6:], " \t\r\n") - return errors.New(response) + return nil, errors.New(response) } - - return nil + // Hold on to a reference to prevent premature GC and close + return ctl, nil } diff --git a/alpine/packages/proxy/vendor/libproxy/proxy.go b/alpine/packages/proxy/vendor/libproxy/proxy.go index d0098502d..7e72057fb 100644 --- a/alpine/packages/proxy/vendor/libproxy/proxy.go +++ b/alpine/packages/proxy/vendor/libproxy/proxy.go @@ -39,7 +39,7 @@ func NewProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) { } return NewTCPProxy(listener, backendAddr.(*net.TCPAddr)) case *vsock.VsockAddr: - listener, err := vsock.Listen(frontendAddr.(vsock.VsockAddr).Port) + listener, err := vsock.Listen(frontendAddr.(*vsock.VsockAddr).Port) if err != nil { return nil, err } diff --git a/alpine/packages/proxy/vendor/vsock/vsock.go b/alpine/packages/proxy/vendor/vsock/vsock.go index 91dca0cb3..b0f734b99 100644 --- a/alpine/packages/proxy/vendor/vsock/vsock.go +++ b/alpine/packages/proxy/vendor/vsock/vsock.go @@ -6,6 +6,7 @@ import ( "net" "os" "syscall" + "time" ) /* No way to teach net or syscall about vsock sockaddr, so go right to C */ @@ -101,7 +102,7 @@ func (v *vsockListener) Addr() net.Addr { // a wrapper around FileConn which supports CloseRead and CloseWrite type vsockConn struct { - net.Conn + vsock *os.File fd uintptr local VsockAddr remote VsockAddr @@ -113,13 +114,9 @@ type VsockConn struct { func newVsockConn(fd uintptr, localPort uint) (*VsockConn, error) { vsock := os.NewFile(fd, fmt.Sprintf("vsock:%d", fd)) - conn, err := net.FileConn(vsock) - if err != nil { - return nil, err - } local := VsockAddr{Port: localPort} remote := VsockAddr{Port: uint(0)} // FIXME - return &VsockConn{vsockConn{Conn: conn, fd: fd, local: local, remote: remote}}, nil + return &VsockConn{vsockConn{vsock: vsock, fd: fd, local: local, remote: remote}}, nil } func (v *VsockConn) LocalAddr() net.Addr { @@ -137,3 +134,27 @@ func (v *VsockConn) CloseRead() error { func (v *VsockConn) CloseWrite() error { return syscall.Shutdown(int(v.fd), syscall.SHUT_WR) } + +func (v *VsockConn) Close() error { + return v.vsock.Close() +} + +func (v *VsockConn) Read(buf []byte) (int, error) { + return v.vsock.Read(buf) +} + +func (v *VsockConn) Write(buf []byte) (int, error) { + return v.vsock.Write(buf) +} + +func (v *VsockConn) SetDeadline(t time.Time) error { + return nil // FIXME +} + +func (v *VsockConn) SetReadDeadline(t time.Time) error { + return nil // FIXME +} + +func (v *VsockConn) SetWriteDeadline(t time.Time) error { + return nil // FIXME +} From a48307b5e74271d8f4a955e49df987ca67af8442 Mon Sep 17 00:00:00 2001 From: David Scott Date: Fri, 15 Apr 2016 13:02:10 +0100 Subject: [PATCH 11/13] proxy: calling Close() on the Accept()ing fd won't cause it to return This seems to be a difference between the AF_VSOCK and AF_INET implementations. We work around it by exiting the proxy process immediately, which will clean up resources anyway. Signed-off-by: David Scott --- alpine/packages/proxy/proxy.go | 4 +++- alpine/packages/proxy/vendor/vsock/vsock.go | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/alpine/packages/proxy/proxy.go b/alpine/packages/proxy/proxy.go index aea703761..3c38b5ceb 100644 --- a/alpine/packages/proxy/proxy.go +++ b/alpine/packages/proxy/proxy.go @@ -67,6 +67,8 @@ func handleStopSignals(p libproxy.Proxy) { signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP) for range s { - p.Close() + os.Exit(0) + // The vsock proxy cannot be shutdown the same way as the TCP one: + //p.Close() } } diff --git a/alpine/packages/proxy/vendor/vsock/vsock.go b/alpine/packages/proxy/vendor/vsock/vsock.go index b0f734b99..dc7217874 100644 --- a/alpine/packages/proxy/vendor/vsock/vsock.go +++ b/alpine/packages/proxy/vendor/vsock/vsock.go @@ -81,6 +81,7 @@ func (v *vsockListener) Accept() (net.Conn, error) { } func (v *vsockListener) Close() error { + // Note this won't cause the Accept to unblock. return syscall.Close(v.accept_fd) } From 910062520481d98a1160ac329a1572fa5ec15b4f Mon Sep 17 00:00:00 2001 From: David Scott Date: Fri, 15 Apr 2016 17:26:35 +0100 Subject: [PATCH 12/13] proxy: move vendor/libproxy to ./libproxy vendor should be used for things with fully-qualified names, Signed-off-by: David Scott --- .../packages/proxy/{vendor => }/libproxy/network_proxy_test.go | 0 alpine/packages/proxy/{vendor => }/libproxy/proxy.go | 0 alpine/packages/proxy/{vendor => }/libproxy/stub_proxy.go | 0 alpine/packages/proxy/{vendor => }/libproxy/tcp_proxy.go | 0 alpine/packages/proxy/{vendor => }/libproxy/udp_proxy.go | 0 alpine/packages/proxy/main.go | 2 +- alpine/packages/proxy/proxy.go | 2 +- 7 files changed, 2 insertions(+), 2 deletions(-) rename alpine/packages/proxy/{vendor => }/libproxy/network_proxy_test.go (100%) rename alpine/packages/proxy/{vendor => }/libproxy/proxy.go (100%) rename alpine/packages/proxy/{vendor => }/libproxy/stub_proxy.go (100%) rename alpine/packages/proxy/{vendor => }/libproxy/tcp_proxy.go (100%) rename alpine/packages/proxy/{vendor => }/libproxy/udp_proxy.go (100%) diff --git a/alpine/packages/proxy/vendor/libproxy/network_proxy_test.go b/alpine/packages/proxy/libproxy/network_proxy_test.go similarity index 100% rename from alpine/packages/proxy/vendor/libproxy/network_proxy_test.go rename to alpine/packages/proxy/libproxy/network_proxy_test.go diff --git a/alpine/packages/proxy/vendor/libproxy/proxy.go b/alpine/packages/proxy/libproxy/proxy.go similarity index 100% rename from alpine/packages/proxy/vendor/libproxy/proxy.go rename to alpine/packages/proxy/libproxy/proxy.go diff --git a/alpine/packages/proxy/vendor/libproxy/stub_proxy.go b/alpine/packages/proxy/libproxy/stub_proxy.go similarity index 100% rename from alpine/packages/proxy/vendor/libproxy/stub_proxy.go rename to alpine/packages/proxy/libproxy/stub_proxy.go diff --git a/alpine/packages/proxy/vendor/libproxy/tcp_proxy.go b/alpine/packages/proxy/libproxy/tcp_proxy.go similarity index 100% rename from alpine/packages/proxy/vendor/libproxy/tcp_proxy.go rename to alpine/packages/proxy/libproxy/tcp_proxy.go diff --git a/alpine/packages/proxy/vendor/libproxy/udp_proxy.go b/alpine/packages/proxy/libproxy/udp_proxy.go similarity index 100% rename from alpine/packages/proxy/vendor/libproxy/udp_proxy.go rename to alpine/packages/proxy/libproxy/udp_proxy.go diff --git a/alpine/packages/proxy/main.go b/alpine/packages/proxy/main.go index d9787a8f0..5e3c1e742 100644 --- a/alpine/packages/proxy/main.go +++ b/alpine/packages/proxy/main.go @@ -6,7 +6,7 @@ import ( "log" "net" "os" - "libproxy" + "proxy/libproxy" "strings" "vsock" ) diff --git a/alpine/packages/proxy/proxy.go b/alpine/packages/proxy/proxy.go index 3c38b5ceb..ee52bf6b5 100644 --- a/alpine/packages/proxy/proxy.go +++ b/alpine/packages/proxy/proxy.go @@ -9,7 +9,7 @@ import ( "os/signal" "syscall" - "libproxy" + "proxy/libproxy" ) // sendError signals the error to the parent and quits the process. From b3f82f045abd7ed67cd2dc42f908c79789bd49c9 Mon Sep 17 00:00:00 2001 From: David Scott Date: Fri, 15 Apr 2016 17:30:43 +0100 Subject: [PATCH 13/13] proxy: vendor github.com/djs55/vsock Signed-off-by: David Scott --- alpine/packages/proxy/libproxy/proxy.go | 2 +- alpine/packages/proxy/main.go | 2 +- .../{ => github.com/djs55}/vsock/vsock.go | 12 +- alpine/packages/proxy/vendor/manifest | 13 ++ .../vsock/include/uapi/linux/vm_sockets.h | 161 ------------------ 5 files changed, 26 insertions(+), 164 deletions(-) rename alpine/packages/proxy/vendor/{ => github.com/djs55}/vsock/vsock.go (92%) create mode 100644 alpine/packages/proxy/vendor/manifest delete mode 100644 alpine/packages/proxy/vendor/vsock/include/uapi/linux/vm_sockets.h diff --git a/alpine/packages/proxy/libproxy/proxy.go b/alpine/packages/proxy/libproxy/proxy.go index 7e72057fb..2e6bb569b 100644 --- a/alpine/packages/proxy/libproxy/proxy.go +++ b/alpine/packages/proxy/libproxy/proxy.go @@ -5,7 +5,7 @@ package libproxy import ( "fmt" "net" - "vsock" + "github.com/djs55/vsock" ) // Proxy defines the behavior of a proxy. It forwards traffic back and forth diff --git a/alpine/packages/proxy/main.go b/alpine/packages/proxy/main.go index 5e3c1e742..a7c125a2a 100644 --- a/alpine/packages/proxy/main.go +++ b/alpine/packages/proxy/main.go @@ -8,7 +8,7 @@ import ( "os" "proxy/libproxy" "strings" - "vsock" + "github.com/djs55/vsock" ) func main() { diff --git a/alpine/packages/proxy/vendor/vsock/vsock.go b/alpine/packages/proxy/vendor/github.com/djs55/vsock/vsock.go similarity index 92% rename from alpine/packages/proxy/vendor/vsock/vsock.go rename to alpine/packages/proxy/vendor/github.com/djs55/vsock/vsock.go index dc7217874..f8c38e00a 100644 --- a/alpine/packages/proxy/vendor/vsock/vsock.go +++ b/alpine/packages/proxy/vendor/github.com/djs55/vsock/vsock.go @@ -13,7 +13,17 @@ import ( /* #include -#include "include/uapi/linux/vm_sockets.h" + +struct sockaddr_vm { + sa_family_t svm_family; + unsigned short svm_reserved1; + unsigned int svm_port; + unsigned int svm_cid; + unsigned char svm_zero[sizeof(struct sockaddr) - + sizeof(sa_family_t) - sizeof(unsigned short) - + sizeof(unsigned int) - sizeof(unsigned int)]; +}; + int bind_sockaddr_vm(int fd, const struct sockaddr_vm *sa_vm) { return bind(fd, (const struct sockaddr*)sa_vm, sizeof(*sa_vm)); } diff --git a/alpine/packages/proxy/vendor/manifest b/alpine/packages/proxy/vendor/manifest new file mode 100644 index 000000000..27f87a766 --- /dev/null +++ b/alpine/packages/proxy/vendor/manifest @@ -0,0 +1,13 @@ +{ + "version": 0, + "dependencies": [ + { + "importpath": "github.com/djs55/vsock", + "repository": "ssh://github.com/djs55/vsock", + "vcs": "git", + "revision": "7ea787de194e9a251ea746cf37f464c1e6cb822a", + "branch": "master", + "notests": true + } + ] +} \ No newline at end of file diff --git a/alpine/packages/proxy/vendor/vsock/include/uapi/linux/vm_sockets.h b/alpine/packages/proxy/vendor/vsock/include/uapi/linux/vm_sockets.h deleted file mode 100644 index 41934a185..000000000 --- a/alpine/packages/proxy/vendor/vsock/include/uapi/linux/vm_sockets.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * VMware vSockets Driver - * - * Copyright (C) 2007-2013 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation version 2 and no later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#ifndef _UAPI_VM_SOCKETS_H -#define _UAPI_VM_SOCKETS_H - -#ifdef __KERNEL__ -#include -#else -#define __kernel_sa_family_t sa_family_t -#include -#endif - -/* Option name for STREAM socket buffer size. Use as the option name in - * setsockopt(3) or getsockopt(3) to set or get an unsigned long long that - * specifies the size of the buffer underlying a vSockets STREAM socket. - * Value is clamped to the MIN and MAX. - */ - -#define SO_VM_SOCKETS_BUFFER_SIZE 0 - -/* Option name for STREAM socket minimum buffer size. Use as the option name - * in setsockopt(3) or getsockopt(3) to set or get an unsigned long long that - * specifies the minimum size allowed for the buffer underlying a vSockets - * STREAM socket. - */ - -#define SO_VM_SOCKETS_BUFFER_MIN_SIZE 1 - -/* Option name for STREAM socket maximum buffer size. Use as the option name - * in setsockopt(3) or getsockopt(3) to set or get an unsigned long long - * that specifies the maximum size allowed for the buffer underlying a - * vSockets STREAM socket. - */ - -#define SO_VM_SOCKETS_BUFFER_MAX_SIZE 2 - -/* Option name for socket peer's host-specific VM ID. Use as the option name - * in getsockopt(3) to get a host-specific identifier for the peer endpoint's - * VM. The identifier is a signed integer. - * Only available for hypervisor endpoints. - */ - -#define SO_VM_SOCKETS_PEER_HOST_VM_ID 3 - -/* Option name for determining if a socket is trusted. Use as the option name - * in getsockopt(3) to determine if a socket is trusted. The value is a - * signed integer. - */ - -#define SO_VM_SOCKETS_TRUSTED 5 - -/* Option name for STREAM socket connection timeout. Use as the option name - * in setsockopt(3) or getsockopt(3) to set or get the connection - * timeout for a STREAM socket. - */ - -#define SO_VM_SOCKETS_CONNECT_TIMEOUT 6 - -/* Option name for using non-blocking send/receive. Use as the option name - * for setsockopt(3) or getsockopt(3) to set or get the non-blocking - * transmit/receive flag for a STREAM socket. This flag determines whether - * send() and recv() can be called in non-blocking contexts for the given - * socket. The value is a signed integer. - * - * This option is only relevant to kernel endpoints, where descheduling the - * thread of execution is not allowed, for example, while holding a spinlock. - * It is not to be confused with conventional non-blocking socket operations. - * - * Only available for hypervisor endpoints. - */ - -#define SO_VM_SOCKETS_NONBLOCK_TXRX 7 - -/* The vSocket equivalent of INADDR_ANY. This works for the svm_cid field of - * sockaddr_vm and indicates the context ID of the current endpoint. - */ - -#define VMADDR_CID_ANY -1U - -/* Bind to any available port. Works for the svm_port field of - * sockaddr_vm. - */ - -#define VMADDR_PORT_ANY -1U - -/* Use this as the destination CID in an address when referring to the - * hypervisor. VMCI relies on it being 0, but this would be useful for other - * transports too. - */ - -#define VMADDR_CID_HYPERVISOR 0 - -/* This CID is specific to VMCI and can be considered reserved (even VMCI - * doesn't use it anymore, it's a legacy value from an older release). - */ - -#define VMADDR_CID_RESERVED 1 - -/* Use this as the destination CID in an address when referring to the host - * (any process other than the hypervisor). VMCI relies on it being 2, but - * this would be useful for other transports too. - */ - -#define VMADDR_CID_HOST 2 - -/* Invalid vSockets version. */ - -#define VM_SOCKETS_INVALID_VERSION -1U - -/* The epoch (first) component of the vSockets version. A single byte - * representing the epoch component of the vSockets version. - */ - -#define VM_SOCKETS_VERSION_EPOCH(_v) (((_v) & 0xFF000000) >> 24) - -/* The major (second) component of the vSockets version. A single byte - * representing the major component of the vSockets version. Typically - * changes for every major release of a product. - */ - -#define VM_SOCKETS_VERSION_MAJOR(_v) (((_v) & 0x00FF0000) >> 16) - -/* The minor (third) component of the vSockets version. Two bytes representing - * the minor component of the vSockets version. - */ - -#define VM_SOCKETS_VERSION_MINOR(_v) (((_v) & 0x0000FFFF)) - -/* Address structure for vSockets. The address family should be set to - * AF_VSOCK. The structure members should all align on their natural - * boundaries without resorting to compiler packing directives. The total size - * of this structure should be exactly the same as that of struct sockaddr. - */ - -struct sockaddr_vm { - __kernel_sa_family_t svm_family; - unsigned short svm_reserved1; - unsigned int svm_port; - unsigned int svm_cid; - unsigned char svm_zero[sizeof(struct sockaddr) - - sizeof(sa_family_t) - - sizeof(unsigned short) - - sizeof(unsigned int) - sizeof(unsigned int)]; -}; - -#define IOCTL_VM_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9) - -#endif /* _UAPI_VM_SOCKETS_H */