@@ -271,6 +271,9 @@ shutdown(how) -- shut down traffic in one or both directions\n\
271271# include <fcntl.h>
272272# endif
273273
274+ /* Helpers needed for AF_HYPERV */
275+ # include <Rpc.h>
276+
274277/* Macros based on the IPPROTO enum, see: https://bugs.python.org/issue29515 */
275278#ifdef MS_WINDOWS
276279#define IPPROTO_ICMP IPPROTO_ICMP
@@ -1579,6 +1582,35 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
15791582 }
15801583#endif /* HAVE_SOCKADDR_ALG */
15811584
1585+ #ifdef AF_HYPERV
1586+ case AF_HYPERV :
1587+ {
1588+ SOCKADDR_HV * a = (SOCKADDR_HV * ) addr ;
1589+
1590+ wchar_t * guidStr ;
1591+ RPC_STATUS res = UuidToStringW (& a -> VmId , & guidStr );
1592+ if (res != RPC_S_OK ) {
1593+ PyErr_SetFromWindowsErr (res );
1594+ return 0 ;
1595+ }
1596+ PyObject * vmId = PyUnicode_FromWideChar (guidStr , -1 );
1597+ res = RpcStringFreeW (& guidStr );
1598+ assert (res == RPC_S_OK );
1599+
1600+ res = UuidToStringW (& a -> ServiceId , & guidStr );
1601+ if (res != RPC_S_OK ) {
1602+ Py_DECREF (vmId );
1603+ PyErr_SetFromWindowsErr (res );
1604+ return 0 ;
1605+ }
1606+ PyObject * serviceId = PyUnicode_FromWideChar (guidStr , -1 );
1607+ res = RpcStringFreeW (& guidStr );
1608+ assert (res == RPC_S_OK );
1609+
1610+ return Py_BuildValue ("NN" , vmId , serviceId );
1611+ }
1612+ #endif /* AF_HYPERV */
1613+
15821614 /* More cases here... */
15831615
15841616 default :
@@ -2375,6 +2407,76 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
23752407 return 1 ;
23762408 }
23772409#endif /* HAVE_SOCKADDR_ALG */
2410+ #ifdef AF_HYPERV
2411+ case AF_HYPERV :
2412+ {
2413+ switch (s -> sock_proto ) {
2414+ case HV_PROTOCOL_RAW :
2415+ {
2416+ PyObject * vm_id_obj = NULL ;
2417+ PyObject * service_id_obj = NULL ;
2418+
2419+ SOCKADDR_HV * addr = & addrbuf -> hv ;
2420+
2421+ memset (addr , 0 , sizeof (* addr ));
2422+ addr -> Family = AF_HYPERV ;
2423+
2424+ if (!PyTuple_Check (args )) {
2425+ PyErr_Format (PyExc_TypeError ,
2426+ "%s(): AF_HYPERV address must be tuple, not %.500s" ,
2427+ caller , Py_TYPE (args )-> tp_name );
2428+ return 0 ;
2429+ }
2430+ if (!PyArg_ParseTuple (args ,
2431+ "UU;AF_HYPERV address must be a str tuple (vm_id, service_id)" ,
2432+ & vm_id_obj , & service_id_obj ))
2433+ {
2434+ return 0 ;
2435+ }
2436+
2437+ wchar_t * guid_str = PyUnicode_AsWideCharString (vm_id_obj , NULL );
2438+ if (guid_str == NULL ) {
2439+ PyErr_Format (PyExc_ValueError ,
2440+ "%s(): AF_HYPERV address vm_id is not a valid UUID string" ,
2441+ caller );
2442+ return 0 ;
2443+ }
2444+ RPC_STATUS rc = UuidFromStringW (guid_str , & addr -> VmId );
2445+ PyMem_Free (guid_str );
2446+ if (rc != RPC_S_OK ) {
2447+ PyErr_Format (PyExc_ValueError ,
2448+ "%s(): AF_HYPERV address vm_id is not a valid UUID string" ,
2449+ caller );
2450+ return 0 ;
2451+ }
2452+
2453+ guid_str = PyUnicode_AsWideCharString (service_id_obj , NULL );
2454+ if (guid_str == NULL ) {
2455+ PyErr_Format (PyExc_ValueError ,
2456+ "%s(): AF_HYPERV address service_id is not a valid UUID string" ,
2457+ caller );
2458+ return 0 ;
2459+ }
2460+ rc = UuidFromStringW (guid_str , & addr -> ServiceId );
2461+ PyMem_Free (guid_str );
2462+ if (rc != RPC_S_OK ) {
2463+ PyErr_Format (PyExc_ValueError ,
2464+ "%s(): AF_HYPERV address service_id is not a valid UUID string" ,
2465+ caller );
2466+ return 0 ;
2467+ }
2468+
2469+ * len_ret = sizeof (* addr );
2470+ return 1 ;
2471+ }
2472+ default :
2473+ PyErr_Format (PyExc_OSError ,
2474+ "%s(): unsupported AF_HYPERV protocol: %d" ,
2475+ caller , s -> sock_proto );
2476+ return 0 ;
2477+ }
2478+ }
2479+ #endif /* AF_HYPERV */
23782480
23792481 /* More cases here... */
23802482
@@ -2524,6 +2626,13 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
25242626 return 1 ;
25252627 }
25262628#endif /* HAVE_SOCKADDR_ALG */
2629+ #ifdef AF_HYPERV
2630+ case AF_HYPERV :
2631+ {
2632+ * len_ret = sizeof (SOCKADDR_HV );
2633+ return 1 ;
2634+ }
2635+ #endif /* AF_HYPERV */
25272636
25282637 /* More cases here... */
25292638
@@ -7351,6 +7460,28 @@ PyInit__socket(void)
73517460 /* Linux LLC */
73527461 PyModule_AddIntMacro (m , AF_LLC );
73537462#endif
7463+ #ifdef AF_HYPERV
7464+ /* Hyper-V sockets */
7465+ PyModule_AddIntMacro (m , AF_HYPERV );
7466+
7467+ /* for proto */
7468+ PyModule_AddIntMacro (m , HV_PROTOCOL_RAW );
7469+
7470+ /* for setsockopt() */
7471+ PyModule_AddIntMacro (m , HVSOCKET_CONNECT_TIMEOUT );
7472+ PyModule_AddIntMacro (m , HVSOCKET_CONNECT_TIMEOUT_MAX );
7473+ PyModule_AddIntMacro (m , HVSOCKET_CONTAINER_PASSTHRU );
7474+ PyModule_AddIntMacro (m , HVSOCKET_CONNECTED_SUSPEND );
7475+ PyModule_AddIntMacro (m , HVSOCKET_ADDRESS_FLAG_PASSTHRU );
7476+
7477+ /* for bind() or connect() */
7478+ PyModule_AddStringConstant (m , "HV_GUID_ZERO" , "00000000-0000-0000-0000-000000000000" );
7479+ PyModule_AddStringConstant (m , "HV_GUID_WILDCARD" , "00000000-0000-0000-0000-000000000000" );
7480+ PyModule_AddStringConstant (m , "HV_GUID_BROADCAST" , "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF" );
7481+ PyModule_AddStringConstant (m , "HV_GUID_CHILDREN" , "90DB8B89-0D35-4F79-8CE9-49EA0AC8B7CD" );
7482+ PyModule_AddStringConstant (m , "HV_GUID_LOOPBACK" , "E0E16197-DD56-4A10-9195-5EE7A155A838" );
7483+ PyModule_AddStringConstant (m , "HV_GUID_PARENT" , "A42E7CDA-D03F-480C-9CC2-A4DE20ABB878" );
7484+ #endif /* AF_HYPERV */
73547485
73557486#ifdef USE_BLUETOOTH
73567487 PyModule_AddIntMacro (m , AF_BLUETOOTH );
0 commit comments