diff --git a/alpine/packages/diagnostics/vendor/github.com/djs55/vsock/vsock.go b/alpine/packages/diagnostics/vendor/github.com/djs55/vsock/vsock.go new file mode 100644 index 000000000..f8c38e00a --- /dev/null +++ b/alpine/packages/diagnostics/vendor/github.com/djs55/vsock/vsock.go @@ -0,0 +1,171 @@ +package vsock + +import ( + "errors" + "fmt" + "net" + "os" + "syscall" + "time" +) + +/* No way to teach net or syscall about vsock sockaddr, so go right to C */ + +/* +#include + +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)); +} +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 */ + VSOCK_CID_SELF = 3 +) + +// 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 +} + +// 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 +} + +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 + } + return newVsockConn(uintptr(fd), v.port) +} + +func (v *vsockListener) Close() error { + // Note this won't cause the Accept to unblock. + return syscall.Close(v.accept_fd) +} + +type VsockAddr struct { + Port uint +} + +func (a VsockAddr) Network() string { + return "vsock" +} + +func (a VsockAddr) String() string { + return fmt.Sprintf("%08x", a.Port) +} + +func (v *vsockListener) Addr() net.Addr { + return VsockAddr{Port: v.port} +} + +// a wrapper around FileConn which supports CloseRead and CloseWrite +type vsockConn struct { + vsock *os.File + 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)) + local := VsockAddr{Port: localPort} + remote := VsockAddr{Port: uint(0)} // FIXME + return &VsockConn{vsockConn{vsock: vsock, 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) +} + +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 +} diff --git a/alpine/packages/diagnostics/vendor/manifest b/alpine/packages/diagnostics/vendor/manifest new file mode 100644 index 000000000..27f87a766 --- /dev/null +++ b/alpine/packages/diagnostics/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