I want to write simple application that communicates between the Hyper-V host and its virtual machine using Hyper-V sockets (netcat over vsock). In the Internet there are a few documents describing how to do it: Make your own integration services, Practical Hyper-V socket communication. However, any of them helps me to achieve my goal.
First of all, I've made sure that the connection using Hyper-V sockets is possible. On the guest Linux I loaded hv_sock module and run nc-vsock application which is able to listen on vsocks:
$ sudo modprobe hv_sock
$ nc-vsock -l 1234
On Windows in PowerShell I ran hvc, which utilises Hyper-V sockets and is able to emulate netcat:
hvc nc -t vsock little-helper 1234
and it works. I can see data sent from server to client and vice versa.
Then I wrote a simple application basing on 1 and 2 with slight changes.
I registered my application with the Hyper-V Host's registry as said in 1 and I ran my application. The connection was not established and the connect function returned error 10049.
I've tried to run my application as a administrator and manipulate GUIDs in the source code and on the Hyper-V Host's registry as well. However, nothing helps and application always reports error 10049.
In my opinion in the document are some ambiguity. E.g. it's said that the service id shall be a random GUID. But later on there is a note that the first four octets translate to port in AF_VSOCK address family, and the specific GUID is presented for this purpose.
Question is rather simple: what I did wrong or misunderstood. Is it possible to write netcat utilising vsock between Windows and Linux?
Full code:
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <hvsocket.h>
#include <combaseapi.h>
int main()
{
struct __declspec(uuid("00000000-185c-4e04-985a-4c2eee3e03cc")) VSockTemplate {};
struct __declspec(uuid("2a9fa68e-4add-45cb-85c8-de97fc66d388")) ServerVsockTemplate {};
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup function failed with error: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_HYPERV, SOCK_STREAM, HV_PROTOCOL_RAW);
if (ConnectSocket == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
SOCKADDR_HV clientService;
clientService.Family = AF_HYPERV;
clientService.VmId = __uuidof(ServerVsockTemplate);
clientService.ServiceId = __uuidof(VSockTemplate);
clientService.ServiceId.Data1 = 1234;
//----------------------
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService));
if (iResult == SOCKET_ERROR) {
wprintf(L"connect function failed with error: %ld\n", WSAGetLastError());
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR)
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
wprintf(L"Connected to server.\n");
iResult = closesocket(ConnectSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
WSACleanup();
return 0;
}