host-timesync-daemon: Use Go Modules

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
This commit is contained in:
Dave Tucker
2021-04-30 10:42:00 +01:00
parent 599aedc9c5
commit 65da053ac3
321 changed files with 169878 additions and 9 deletions

View File

@@ -0,0 +1,11 @@
# This file lists all individuals having contributed content to the repository.
# For how it is generated, see `scripts/generate-authors.sh`.
Ben Weedon <beweedon@microsoft.com>
Ian Campbell <ian.campbell@docker.com>
John Starks <jostarks@microsoft.com>
Justin Cormack <justin.cormack@docker.com>
Magnus Skjegstad <magnus.skjegstad@docker.com>
Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Rolf Neugebauer <rolf.neugebauer@docker.com>
Simon Ferquel <simon.ferquel@docker.com>

View File

@@ -0,0 +1,16 @@
Unless explicitly stated at the top of the file, this code is covered
by the following license:
Copyright 2016-2017 The authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,24 @@
// +build !linux,!darwin
package vsock
import (
"fmt"
"log"
"net"
)
// SocketMode is the unimplemented fallback for unsupported OSes
func SocketMode(socketMode string) {
log.Fatalln("Unimplemented")
}
// Dial is the unimplemented fallback for unsupported OSes
func Dial(cid, port uint32) (Conn, error) {
return nil, fmt.Errorf("Unimplemented")
}
// Listen is the unimplemented fallback for unsupported OSes
func Listen(cid, port uint32) (net.Listener, error) {
return nil, fmt.Errorf("Unimplemented")
}

View File

@@ -0,0 +1,66 @@
// Package vsock provides bindings to the hyperkit based
// implementation on macOS hosts. virtio Sockets are exposed as named
// pipes on macOS. Two modes are supported (to be set with
// SockerMode()):
// - Hyperkit mode: The package needs to be initialised with the path
// to where the named pipe was created.
// - Docker for Mac mode: This is a shortcut which hard codes the
// location of the named pipe.
package vsock
import (
"fmt"
"log"
"net"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
)
var (
socketPath string
connectPath string
socketFmt string
)
// SocketMode initialises the bindings to either raw hyperkit mode
// ("hyperkit:/path") or Docker for Mac mode ("docker"). This function
// must be called before using the vsock bindings.
func SocketMode(socketMode string) {
socketFmt = "%08x.%08x"
if strings.HasPrefix(socketMode, "hyperkit:") {
socketPath = socketMode[len("hyperkit:"):]
} else if socketMode == "docker" {
socketPath = filepath.Join(os.Getenv("HOME"), "/Library/Containers/com.docker.docker/Data/vms/0")
} else {
log.Fatalln("Unknown socket mode: ", socketMode)
}
connectPath = filepath.Join(socketPath, "connect")
}
// Dial creates a connection to the VM with the given client ID and port
func Dial(cid, port uint32) (Conn, error) {
c, err := net.DialUnix("unix", nil, &net.UnixAddr{connectPath, "unix"})
if err != nil {
return c, errors.Wrapf(err, "failed to dial on %s", connectPath)
}
if _, err := fmt.Fprintf(c, "%08x.%08x\n", cid, port); err != nil {
return c, errors.Wrapf(err, "Failed to write dest (%08x.%08x) to %s", cid, port, connectPath)
}
return c, nil
}
// Listen creates a listener for a specifc vsock.
func Listen(cid, port uint32) (net.Listener, error) {
sock := filepath.Join(socketPath, fmt.Sprintf(socketFmt, cid, port))
if err := os.Remove(sock); err != nil && !os.IsNotExist(err) {
log.Fatalln("Listen(): Remove:", err)
return nil, err
}
return net.ListenUnix("unix", &net.UnixAddr{sock, "unix"})
}

View File

@@ -0,0 +1,51 @@
// Package vsock provides the Linux guest bindings to VM sockets. VM
// sockets are a generic mechanism for guest<->host communication. It
// was originally developed for VMware but now also supports virtio
// sockets and (soon) Hyper-V sockets.
//
// The main purpose is to provide bindings to the Linux implementation
// of VM sockets, based on the low level support in
// golang.org/x/sys/unix.
//
// The package also provides bindings to the host interface to virtio
// sockets for HyperKit on macOS.
package vsock
import (
"fmt"
"net"
"os"
)
const (
// CIDAny is a wildcard CID
CIDAny = 4294967295 // 2^32-1
// CIDHypervisor is the reserved CID for the Hypervisor
CIDHypervisor = 0
// CIDHost is the reserved CID for the host system
CIDHost = 2
)
// Addr represents the address of a vsock end point.
type Addr struct {
CID uint32
Port uint32
}
// Network returns the network type for a Addr
func (a Addr) Network() string {
return "vsock"
}
// String returns a string representation of a Addr
func (a Addr) String() string {
return fmt.Sprintf("%08x.%08x", a.CID, a.Port)
}
// Conn is a vsock connection which supports half-close.
type Conn interface {
net.Conn
CloseRead() error
CloseWrite() error
File() (*os.File, error)
}

View File

@@ -0,0 +1,164 @@
// Bindings to the Linux hues interface to VM sockets.
package vsock
import (
"fmt"
"net"
"os"
"syscall"
"time"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
)
// SocketMode is a NOOP on Linux
func SocketMode(m string) {
}
// Convert a generic unix.Sockaddr to a Addr
func sockaddrToVsock(sa unix.Sockaddr) *Addr {
switch sa := sa.(type) {
case *unix.SockaddrVM:
return &Addr{CID: sa.CID, Port: sa.Port}
}
return nil
}
// Dial connects to the CID.Port via virtio sockets
func Dial(cid, port uint32) (Conn, error) {
fd, err := syscall.Socket(unix.AF_VSOCK, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return nil, errors.Wrap(err, "Failed to create AF_VSOCK socket")
}
sa := &unix.SockaddrVM{CID: cid, Port: port}
// Retry connect in a loop if EINTR is encountered.
for {
if err := unix.Connect(fd, sa); err != nil {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
continue
}
return nil, errors.Wrapf(err, "failed connect() to %08x.%08x", cid, port)
}
break
}
return newVsockConn(uintptr(fd), nil, &Addr{cid, port}), nil
}
// Listen returns a net.Listener which can accept connections on the given port
func Listen(cid, port uint32) (net.Listener, error) {
fd, err := syscall.Socket(unix.AF_VSOCK, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
if err != nil {
return nil, err
}
sa := &unix.SockaddrVM{CID: cid, Port: port}
if err = unix.Bind(fd, sa); err != nil {
return nil, errors.Wrapf(err, "bind() to %08x.%08x failed", cid, port)
}
err = syscall.Listen(fd, syscall.SOMAXCONN)
if err != nil {
return nil, errors.Wrapf(err, "listen() on %08x.%08x failed", cid, port)
}
return &vsockListener{fd, Addr{cid, port}}, nil
}
type vsockListener struct {
fd int
local Addr
}
// Accept accepts an incoming call and returns the new connection.
func (v *vsockListener) Accept() (net.Conn, error) {
fd, sa, err := unix.Accept(v.fd)
if err != nil {
return nil, err
}
return newVsockConn(uintptr(fd), &v.local, sockaddrToVsock(sa)), nil
}
// Close closes the listening connection
func (v *vsockListener) Close() error {
// Note this won't cause the Accept to unblock.
return unix.Close(v.fd)
}
// Addr returns the address the Listener is listening on
func (v *vsockListener) Addr() net.Addr {
return v.local
}
// a wrapper around FileConn which supports CloseRead and CloseWrite
type vsockConn struct {
vsock *os.File
fd uintptr
local *Addr
remote *Addr
}
func newVsockConn(fd uintptr, local, remote *Addr) *vsockConn {
vsock := os.NewFile(fd, fmt.Sprintf("vsock:%d", fd))
return &vsockConn{vsock: vsock, fd: fd, local: local, remote: remote}
}
// LocalAddr returns the local address of a connection
func (v *vsockConn) LocalAddr() net.Addr {
return v.local
}
// RemoteAddr returns the remote address of a connection
func (v *vsockConn) RemoteAddr() net.Addr {
return v.remote
}
// Close closes the connection
func (v *vsockConn) Close() error {
return v.vsock.Close()
}
// CloseRead shuts down the reading side of a vsock connection
func (v *vsockConn) CloseRead() error {
return syscall.Shutdown(int(v.fd), syscall.SHUT_RD)
}
// CloseWrite shuts down the writing side of a vsock connection
func (v *vsockConn) CloseWrite() error {
return syscall.Shutdown(int(v.fd), syscall.SHUT_WR)
}
// Read reads data from the connection
func (v *vsockConn) Read(buf []byte) (int, error) {
return v.vsock.Read(buf)
}
// Write writes data over the connection
func (v *vsockConn) Write(buf []byte) (int, error) {
return v.vsock.Write(buf)
}
// SetDeadline sets the read and write deadlines associated with the connection
func (v *vsockConn) SetDeadline(t time.Time) error {
return nil // FIXME
}
// SetReadDeadline sets the deadline for future Read calls.
func (v *vsockConn) SetReadDeadline(t time.Time) error {
return nil // FIXME
}
// SetWriteDeadline sets the deadline for future Write calls
func (v *vsockConn) SetWriteDeadline(t time.Time) error {
return nil // FIXME
}
// File duplicates the underlying socket descriptor and returns it.
func (v *vsockConn) File() (*os.File, error) {
// This is equivalent to dup(2) but creates the new fd with CLOEXEC already set.
r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(v.vsock.Fd()), syscall.F_DUPFD_CLOEXEC, 0)
if e1 != 0 {
return nil, os.NewSyscallError("fcntl", e1)
}
return os.NewFile(r0, v.vsock.Name()), nil
}