mirror of https://github.com/containers/podman.git
116 lines
3.6 KiB
Go
116 lines
3.6 KiB
Go
// Package hvsock provides a Go interface to Hyper-V sockets both on
|
|
// Windows and on Linux. The Linux bindings require patches for the
|
|
// 4.9.x kernel. If you are using a Linux kernel 4.14.x or newer you
|
|
// should use the vsock package instead as the Hyper-V socket support
|
|
// in these kernels have been merged with the virtio sockets
|
|
// implementation.
|
|
package hvsock
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"net"
|
|
"reflect"
|
|
)
|
|
|
|
var (
|
|
// GUIDZero used by listeners to accept connections from all partitions
|
|
GUIDZero, _ = GUIDFromString("00000000-0000-0000-0000-000000000000")
|
|
// GUIDWildcard used by listeners to accept connections from all partitions
|
|
GUIDWildcard, _ = GUIDFromString("00000000-0000-0000-0000-000000000000")
|
|
// GUIDBroadcast undocumented
|
|
GUIDBroadcast, _ = GUIDFromString("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")
|
|
// GUIDChildren used by listeners to accept connections from children
|
|
GUIDChildren, _ = GUIDFromString("90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd")
|
|
// GUIDLoopback use to connect in loopback mode
|
|
GUIDLoopback, _ = GUIDFromString("e0e16197-dd56-4a10-9195-5ee7a155a838")
|
|
// GUIDParent use to connect to the parent partition
|
|
GUIDParent, _ = GUIDFromString("a42e7cda-d03f-480c-9cc2-a4de20abb878")
|
|
|
|
// GUIDs for LinuxVMs with the new Hyper-V socket implementation need to match this template
|
|
guidTemplate, _ = GUIDFromString("00000000-facb-11e6-bd58-64006a7986d3")
|
|
)
|
|
|
|
const (
|
|
// The Hyper-V socket implementation used in the 4.9.x kernels
|
|
// seems to fail silently if messages are above 8k. The newer
|
|
// implementation in the 4.14.x (and newer) kernels seems to
|
|
// work fine with larger messages. This is constant is used as
|
|
// a temporary workaround to limit the amount of data sent and
|
|
// should be removed once support for 4.9.x kernels is
|
|
// deprecated.
|
|
maxMsgSize = 8 * 1024
|
|
)
|
|
|
|
// GUID is used by Hypper-V sockets for "addresses" and "ports"
|
|
type GUID [16]byte
|
|
|
|
// Convert a GUID into a string
|
|
func (g *GUID) String() string {
|
|
/* XXX This assume little endian */
|
|
return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
g[3], g[2], g[1], g[0],
|
|
g[5], g[4],
|
|
g[7], g[6],
|
|
g[8], g[9],
|
|
g[10], g[11], g[12], g[13], g[14], g[15])
|
|
}
|
|
|
|
// Port converts a Service GUID to a "port" usable by the vsock package.
|
|
// It can be used to convert hvsock code to vsock code. On 4.14.x
|
|
// kernels Service GUIDs for talking to Linux should have the form of
|
|
// xxxxxxxx-facb-11e6-bd58-64006a7986d3, where xxxxxxxx is the vsock port.
|
|
func (g *GUID) Port() (uint32, error) {
|
|
// Check that the GUID is as expected
|
|
if !reflect.DeepEqual(g[4:], guidTemplate[4:]) {
|
|
return 0, fmt.Errorf("%s does not conform with the template", g)
|
|
}
|
|
return binary.LittleEndian.Uint32(g[0:4]), nil
|
|
}
|
|
|
|
// GUIDFromString parses a string and returns a GUID
|
|
func GUIDFromString(s string) (GUID, error) {
|
|
var g GUID
|
|
var err error
|
|
_, err = fmt.Sscanf(s, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
&g[3], &g[2], &g[1], &g[0],
|
|
&g[5], &g[4],
|
|
&g[7], &g[6],
|
|
&g[8], &g[9],
|
|
&g[10], &g[11], &g[12], &g[13], &g[14], &g[15])
|
|
return g, err
|
|
}
|
|
|
|
// Addr represents a Hyper-V socket address
|
|
type Addr struct {
|
|
VMID GUID
|
|
ServiceID GUID
|
|
}
|
|
|
|
// Network returns the type of network for Hyper-V sockets
|
|
func (a Addr) Network() string {
|
|
return "hvsock"
|
|
}
|
|
|
|
func (a Addr) String() string {
|
|
vmid := a.VMID.String()
|
|
svc := a.ServiceID.String()
|
|
|
|
return vmid + ":" + svc
|
|
}
|
|
|
|
// Conn is a hvsock connection which supports half-close.
|
|
type Conn interface {
|
|
net.Conn
|
|
CloseRead() error
|
|
CloseWrite() error
|
|
}
|
|
|
|
// Since there doesn't seem to be a standard min function
|
|
func min(x, y int) int {
|
|
if x < y {
|
|
return x
|
|
}
|
|
return y
|
|
}
|