diff options
author | Jordan Borean <jborean93@gmail.com> | 2022-05-24 20:37:06 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-24 20:37:06 (GMT) |
commit | fbd11f3edd6d2034774d802e048261e613ffcbf5 (patch) | |
tree | 23a08f9441e5a173240ec392c92be14dda2b0251 /Modules/socketmodule.c | |
parent | 5115a1683154a1f2093aa7f2c6834e47d326cb7d (diff) | |
download | cpython-fbd11f3edd6d2034774d802e048261e613ffcbf5.zip cpython-fbd11f3edd6d2034774d802e048261e613ffcbf5.tar.gz cpython-fbd11f3edd6d2034774d802e048261e613ffcbf5.tar.bz2 |
gh-92658: Add Hyper-V socket support (GH-92755)
Diffstat (limited to 'Modules/socketmodule.c')
-rw-r--r-- | Modules/socketmodule.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index f376513..0bc9901 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -271,6 +271,9 @@ shutdown(how) -- shut down traffic in one or both directions\n\ # include <fcntl.h> # endif +/* Helpers needed for AF_HYPERV */ +# include <Rpc.h> + /* Macros based on the IPPROTO enum, see: https://bugs.python.org/issue29515 */ #ifdef MS_WINDOWS #define IPPROTO_ICMP IPPROTO_ICMP @@ -1579,6 +1582,35 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) } #endif /* HAVE_SOCKADDR_ALG */ +#ifdef AF_HYPERV + case AF_HYPERV: + { + SOCKADDR_HV *a = (SOCKADDR_HV *) addr; + + wchar_t *guidStr; + RPC_STATUS res = UuidToStringW(&a->VmId, &guidStr); + if (res != RPC_S_OK) { + PyErr_SetFromWindowsErr(res); + return 0; + } + PyObject *vmId = PyUnicode_FromWideChar(guidStr, -1); + res = RpcStringFreeW(&guidStr); + assert(res == RPC_S_OK); + + res = UuidToStringW(&a->ServiceId, &guidStr); + if (res != RPC_S_OK) { + Py_DECREF(vmId); + PyErr_SetFromWindowsErr(res); + return 0; + } + PyObject *serviceId = PyUnicode_FromWideChar(guidStr, -1); + res = RpcStringFreeW(&guidStr); + assert(res == RPC_S_OK); + + return Py_BuildValue("NN", vmId, serviceId); + } +#endif /* AF_HYPERV */ + /* More cases here... */ default: @@ -2375,6 +2407,76 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, return 1; } #endif /* HAVE_SOCKADDR_ALG */ +#ifdef AF_HYPERV + case AF_HYPERV: + { + switch (s->sock_proto) { + case HV_PROTOCOL_RAW: + { + PyObject *vm_id_obj = NULL; + PyObject *service_id_obj = NULL; + + SOCKADDR_HV *addr = &addrbuf->hv; + + memset(addr, 0, sizeof(*addr)); + addr->Family = AF_HYPERV; + + if (!PyTuple_Check(args)) { + PyErr_Format(PyExc_TypeError, + "%s(): AF_HYPERV address must be tuple, not %.500s", + caller, Py_TYPE(args)->tp_name); + return 0; + } + if (!PyArg_ParseTuple(args, + "UU;AF_HYPERV address must be a str tuple (vm_id, service_id)", + &vm_id_obj, &service_id_obj)) + { + return 0; + } + + wchar_t *guid_str = PyUnicode_AsWideCharString(vm_id_obj, NULL); + if (guid_str == NULL) { + PyErr_Format(PyExc_ValueError, + "%s(): AF_HYPERV address vm_id is not a valid UUID string", + caller); + return 0; + } + RPC_STATUS rc = UuidFromStringW(guid_str, &addr->VmId); + PyMem_Free(guid_str); + if (rc != RPC_S_OK) { + PyErr_Format(PyExc_ValueError, + "%s(): AF_HYPERV address vm_id is not a valid UUID string", + caller); + return 0; + } + + guid_str = PyUnicode_AsWideCharString(service_id_obj, NULL); + if (guid_str == NULL) { + PyErr_Format(PyExc_ValueError, + "%s(): AF_HYPERV address service_id is not a valid UUID string", + caller); + return 0; + } + rc = UuidFromStringW(guid_str, &addr->ServiceId); + PyMem_Free(guid_str); + if (rc != RPC_S_OK) { + PyErr_Format(PyExc_ValueError, + "%s(): AF_HYPERV address service_id is not a valid UUID string", + caller); + return 0; + } + + *len_ret = sizeof(*addr); + return 1; + } + default: + PyErr_Format(PyExc_OSError, + "%s(): unsupported AF_HYPERV protocol: %d", + caller, s->sock_proto); + return 0; + } + } +#endif /* AF_HYPERV */ /* More cases here... */ @@ -2524,6 +2626,13 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret) return 1; } #endif /* HAVE_SOCKADDR_ALG */ +#ifdef AF_HYPERV + case AF_HYPERV: + { + *len_ret = sizeof (SOCKADDR_HV); + return 1; + } +#endif /* AF_HYPERV */ /* More cases here... */ @@ -7351,6 +7460,28 @@ PyInit__socket(void) /* Linux LLC */ PyModule_AddIntMacro(m, AF_LLC); #endif +#ifdef AF_HYPERV + /* Hyper-V sockets */ + PyModule_AddIntMacro(m, AF_HYPERV); + + /* for proto */ + PyModule_AddIntMacro(m, HV_PROTOCOL_RAW); + + /* for setsockopt() */ + PyModule_AddIntMacro(m, HVSOCKET_CONNECT_TIMEOUT); + PyModule_AddIntMacro(m, HVSOCKET_CONNECT_TIMEOUT_MAX); + PyModule_AddIntMacro(m, HVSOCKET_CONTAINER_PASSTHRU); + PyModule_AddIntMacro(m, HVSOCKET_CONNECTED_SUSPEND); + PyModule_AddIntMacro(m, HVSOCKET_ADDRESS_FLAG_PASSTHRU); + + /* for bind() or connect() */ + PyModule_AddStringConstant(m, "HV_GUID_ZERO", "00000000-0000-0000-0000-000000000000"); + PyModule_AddStringConstant(m, "HV_GUID_WILDCARD", "00000000-0000-0000-0000-000000000000"); + PyModule_AddStringConstant(m, "HV_GUID_BROADCAST", "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"); + PyModule_AddStringConstant(m, "HV_GUID_CHILDREN", "90DB8B89-0D35-4F79-8CE9-49EA0AC8B7CD"); + PyModule_AddStringConstant(m, "HV_GUID_LOOPBACK", "E0E16197-DD56-4A10-9195-5EE7A155A838"); + PyModule_AddStringConstant(m, "HV_GUID_PARENT", "A42E7CDA-D03F-480C-9CC2-A4DE20ABB878"); +#endif /* AF_HYPERV */ #ifdef USE_BLUETOOTH PyModule_AddIntMacro(m, AF_BLUETOOTH); |