Использование сокетов Hyper-V между Windows host и Linux guest - PullRequest
0 голосов
/ 15 марта 2020

Я хочу написать простое приложение, которое обменивается данными между хостом Hyper-V и его виртуальной машиной с помощью сокетов Hyper-V (netcat over vsock). В Inte rnet есть несколько документов, описывающих, как это сделать: Создайте свои собственные службы интеграции , Практическая связь через сокет Hyper-V . Однако любой из них помогает мне достичь своей цели.

Прежде всего, я убедился, что соединение с использованием сокетов Hyper-V возможно. На гостевом Linux я загрузил hv_sock модуль и запустил n c -vsock приложение, которое может прослушивать vsocks:

$ sudo modprobe hv_sock
$ nc-vsock -l 1234

Вкл Windows в PowerShell Я запустил hv c, который использует сокеты Hyper-V и способен эмулировать netcat:

hvc nc -t vsock little-helper 1234

, и это работает. Я могу видеть данные, отправленные с сервера клиенту и наоборот.

Затем я написал простое приложение, основанное на 1 и 2 с небольшими изменениями. Я зарегистрировал свое приложение в реестре хоста Hyper-V, как указано в 1 , и запустил свое приложение. Соединение не было установлено, и функция connect вернула ошибку 10049.

Я пытался запустить свое приложение от имени администратора и манипулировать GUID в исходном коде, а также в реестре хоста Hyper-V. Однако ничего не помогает и приложение всегда сообщает об ошибке 10049.

На мой взгляд в документе есть некоторая двусмысленность. Например, сказано, что идентификатор сервиса должен быть случайным GUID. Но позже есть примечание, что первые четыре октета преобразуются в порт в семействе адресов AF_VSOCK, и для этой цели предоставляется специфицированный c GUID.

Вопрос довольно прост: что я сделал неправильно или неправильно понял , Можно ли написать netcat, используя vsock между Windows и Linux?

Полный код:

#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;
}
...