| /* Socket module */ | |
| /* | |
| This module provides an interface to Berkeley socket IPC. | |
| Limitations: | |
| - Only AF_INET, AF_INET6 and AF_UNIX address families are supported in a | |
| portable manner, though AF_PACKET, AF_NETLINK, AF_QIPCRTR and AF_TIPC are | |
| supported under Linux. | |
| - No read/write operations (use sendall/recv or makefile instead). | |
| - Additional restrictions apply on some non-Unix platforms (compensated | |
| for by socket.py). | |
| Module interface: | |
| - socket.error: exception raised for socket specific errors, alias for OSError | |
| - socket.gaierror: exception raised for getaddrinfo/getnameinfo errors, | |
| a subclass of socket.error | |
| - socket.herror: exception raised for gethostby* errors, | |
| a subclass of socket.error | |
| - socket.gethostbyname(hostname) --> host IP address (string: 'dd.dd.dd.dd') | |
| - socket.gethostbyaddr(IP address) --> (hostname, [alias, ...], [IP addr, ...]) | |
| - socket.gethostname() --> host name (string: 'spam' or 'spam.domain.com') | |
| - socket.getprotobyname(protocolname) --> protocol number | |
| - socket.getservbyname(servicename[, protocolname]) --> port number | |
| - socket.getservbyport(portnumber[, protocolname]) --> service name | |
| - socket.socket([family[, type [, proto, fileno]]]) --> new socket object | |
| (fileno specifies a pre-existing socket file descriptor) | |
| - socket.socketpair([family[, type [, proto]]]) --> (socket, socket) | |
| - socket.ntohs(16 bit value) --> new int object | |
| - socket.ntohl(32 bit value) --> new int object | |
| - socket.htons(16 bit value) --> new int object | |
| - socket.htonl(32 bit value) --> new int object | |
| - socket.getaddrinfo(host, port [, family, type, proto, flags]) | |
| --> List of (family, type, proto, canonname, sockaddr) | |
| - socket.getnameinfo(sockaddr, flags) --> (host, port) | |
| - socket.AF_INET, socket.SOCK_STREAM, etc.: constants from <socket.h> | |
| - socket.has_ipv6: boolean value indicating if IPv6 is supported | |
| - socket.inet_aton(IP address) -> 32-bit packed IP representation | |
| - socket.inet_ntoa(packed IP) -> IP address string | |
| - socket.getdefaulttimeout() -> None | float | |
| - socket.setdefaulttimeout(None | float) | |
| - socket.if_nameindex() -> list of tuples (if_index, if_name) | |
| - socket.if_nametoindex(name) -> corresponding interface index | |
| - socket.if_indextoname(index) -> corresponding interface name | |
| - an internet socket address is a pair (hostname, port) | |
| where hostname can be anything recognized by gethostbyname() | |
| (including the dd.dd.dd.dd notation) and port is in host byte order | |
| - where a hostname is returned, the dd.dd.dd.dd notation is used | |
| - a UNIX domain socket address is a string specifying the pathname | |
| - an AF_PACKET socket address is a tuple containing a string | |
| specifying the ethernet interface and an integer specifying | |
| the Ethernet protocol number to be received. For example: | |
| ("eth0",0x1234). Optional 3rd,4th,5th elements in the tuple | |
| specify packet-type and ha-type/addr. | |
| - an AF_QIPCRTR socket address is a (node, port) tuple where the | |
| node and port are non-negative integers. | |
| - an AF_TIPC socket address is expressed as | |
| (addr_type, v1, v2, v3 [, scope]); where addr_type can be one of: | |
| TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, and TIPC_ADDR_ID; | |
| and scope can be one of: | |
| TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, and TIPC_NODE_SCOPE. | |
| The meaning of v1, v2 and v3 depends on the value of addr_type: | |
| if addr_type is TIPC_ADDR_NAME: | |
| v1 is the server type | |
| v2 is the port identifier | |
| v3 is ignored | |
| if addr_type is TIPC_ADDR_NAMESEQ: | |
| v1 is the server type | |
| v2 is the lower port number | |
| v3 is the upper port number | |
| if addr_type is TIPC_ADDR_ID: | |
| v1 is the node | |
| v2 is the ref | |
| v3 is ignored | |
| Local naming conventions: | |
| - names starting with sock_ are socket object methods | |
| - names starting with socket_ are module-level functions | |
| - names starting with PySocket are exported through socketmodule.h | |
| */ | |
| #ifndef Py_BUILD_CORE_BUILTIN | |
| # define Py_BUILD_CORE_MODULE 1 | |
| #endif | |
| #ifdef __APPLE__ | |
| // Issue #35569: Expose RFC 3542 socket options. | |
| #define __APPLE_USE_RFC_3542 1 | |
| #include <AvailabilityMacros.h> | |
| /* for getaddrinfo thread safety test on old versions of OS X */ | |
| #ifndef MAC_OS_X_VERSION_10_5 | |
| #define MAC_OS_X_VERSION_10_5 1050 | |
| #endif | |
| /* | |
| * inet_aton is not available on OSX 10.3, yet we want to use a binary | |
| * that was build on 10.4 or later to work on that release, weak linking | |
| * comes to the rescue. | |
| */ | |
| # pragma weak inet_aton | |
| #endif | |
| #include "Python.h" | |
| #include "pycore_capsule.h" // _PyCapsule_SetTraverse() | |
| #include "pycore_fileutils.h" // _Py_set_inheritable() | |
| #include "pycore_moduleobject.h" // _PyModule_GetState | |
| #include "pycore_object.h" // _PyObject_VisitType() | |
| #include "pycore_time.h" // _PyTime_AsMilliseconds() | |
| #include "pycore_tuple.h" // _PyTuple_FromPairSteal | |
| #include "pycore_pystate.h" // _Py_AssertHoldsTstate() | |
| #ifdef _Py_MEMORY_SANITIZER | |
| # include <sanitizer/msan_interface.h> | |
| #endif | |
| /* Socket object documentation */ | |
| PyDoc_STRVAR(sock_doc, | |
| "socket(family=AF_INET, type=SOCK_STREAM, proto=0) -> socket object\n\ | |
| socket(family=-1, type=-1, proto=-1, fileno=None) -> socket object\n\ | |
| \n\ | |
| Open a socket of the given type. The family argument specifies the\n\ | |
| address family; it defaults to AF_INET. The type argument specifies\n\ | |
| whether this is a stream (SOCK_STREAM, this is the default)\n\ | |
| or datagram (SOCK_DGRAM) socket. The protocol argument defaults to 0,\n\ | |
| specifying the default protocol. Keyword arguments are accepted.\n\ | |
| The socket is created as non-inheritable.\n\ | |
| \n\ | |
| When a fileno is passed in, family, type and proto are auto-detected,\n\ | |
| unless they are explicitly set.\n\ | |
| \n\ | |
| A socket object represents one endpoint of a network connection.\n\ | |
| \n\ | |
| Methods of socket objects (keyword arguments not allowed):\n\ | |
| \n\ | |
| _accept() -- accept connection, returning new socket fd and client address\n\ | |
| bind(addr) -- bind the socket to a local address\n\ | |
| close() -- close the socket\n\ | |
| connect(addr) -- connect the socket to a remote address\n\ | |
| connect_ex(addr) -- connect, return an error code instead of an exception\n\ | |
| dup() -- return a new socket fd duplicated from fileno()\n\ | |
| fileno() -- return underlying file descriptor\n\ | |
| getpeername() -- return remote address [*]\n\ | |
| getsockname() -- return local address\n\ | |
| getsockopt(level, optname[, buflen]) -- get socket options\n\ | |
| gettimeout() -- return timeout or None\n\ | |
| listen([n]) -- start listening for incoming connections\n\ | |
| recv(buflen[, flags]) -- receive data\n\ | |
| recv_into(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\ | |
| recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\ | |
| recvfrom_into(buffer[, nbytes, [, flags]])\n\ | |
| -- receive data and sender\'s address (into a buffer)\n\ | |
| sendall(data[, flags]) -- send all data\n\ | |
| send(data[, flags]) -- send data, may not send all of it\n\ | |
| sendto(data[, flags], addr) -- send data to a given address\n\ | |
| setblocking(bool) -- set or clear the blocking I/O flag\n\ | |
| getblocking() -- return True if socket is blocking, False if non-blocking\n\ | |
| setsockopt(level, optname, value[, optlen]) -- set socket options\n\ | |
| settimeout(None | float) -- set or clear the timeout\n\ | |
| shutdown(how) -- shut down traffic in one or both directions\n\ | |
| \n\ | |
| [*] not available on all platforms!"); | |
| /* XXX This is a terrible mess of platform-dependent preprocessor hacks. | |
| I hope some day someone can clean this up please... */ | |
| /* Hacks for gethostbyname_r(). On some non-Linux platforms, the configure | |
| script doesn't get this right, so we hardcode some platform checks below. | |
| On the other hand, not all Linux versions agree, so there the settings | |
| computed by the configure script are needed! */ | |
| #ifndef __linux__ | |
| # undef HAVE_GETHOSTBYNAME_R_3_ARG | |
| # undef HAVE_GETHOSTBYNAME_R_5_ARG | |
| # undef HAVE_GETHOSTBYNAME_R_6_ARG | |
| #endif | |
| #if defined(__OpenBSD__) | |
| # include <sys/uio.h> | |
| #endif | |
| #if defined(__ANDROID__) && __ANDROID_API__ < 23 | |
| # undef HAVE_GETHOSTBYNAME_R | |
| #endif | |
| #ifdef HAVE_GETHOSTBYNAME_R | |
| # if defined(_AIX) && !defined(_LINUX_SOURCE_COMPAT) | |
| # define HAVE_GETHOSTBYNAME_R_3_ARG | |
| # elif defined(__sun) || defined(__sgi) | |
| # define HAVE_GETHOSTBYNAME_R_5_ARG | |
| # elif defined(__linux__) | |
| /* Rely on the configure script */ | |
| # elif defined(_LINUX_SOURCE_COMPAT) /* Linux compatibility on AIX */ | |
| # define HAVE_GETHOSTBYNAME_R_6_ARG | |
| # else | |
| # undef HAVE_GETHOSTBYNAME_R | |
| # endif | |
| #endif | |
| #if !defined(HAVE_GETHOSTBYNAME_R) && !defined(MS_WINDOWS) | |
| # define USE_GETHOSTBYNAME_LOCK | |
| #endif | |
| #if defined(__APPLE__) || defined(__CYGWIN__) || defined(__NetBSD__) | |
| # include <sys/ioctl.h> | |
| #endif | |
| #if defined(HAVE_BLUETOOTH_H) && !defined(__FreeBSD__) | |
| # include <netbt/l2cap.h> | |
| # include <netbt/rfcomm.h> | |
| # include <netbt/hci.h> | |
| # include <netbt/sco.h> | |
| #endif | |
| #if defined(__sgi) && _COMPILER_VERSION>700 && !_SGIAPI | |
| /* make sure that the reentrant (gethostbyaddr_r etc) | |
| functions are declared correctly if compiling with | |
| MIPSPro 7.x in ANSI C mode (default) */ | |
| /* XXX Using _SGIAPI is the wrong thing, | |
| but I don't know what the right thing is. */ | |
| #undef _SGIAPI /* to avoid warning */ | |
| #define _SGIAPI 1 | |
| #undef _XOPEN_SOURCE | |
| #include <sys/socket.h> | |
| #include <sys/types.h> | |
| #include <netinet/in.h> | |
| #ifdef _SS_ALIGNSIZE | |
| #define HAVE_GETADDRINFO 1 | |
| #define HAVE_GETNAMEINFO 1 | |
| #endif | |
| #define HAVE_INET_PTON | |
| #include <netdb.h> | |
| #endif // __sgi | |
| /* Solaris fails to define this variable at all. */ | |
| #if (defined(__sun) && defined(__SVR4)) && !defined(INET_ADDRSTRLEN) | |
| #define INET_ADDRSTRLEN 16 | |
| #endif | |
| /* Generic includes */ | |
| #ifdef HAVE_SYS_TYPES_H | |
| #include <sys/types.h> | |
| #endif | |
| #ifdef HAVE_SYS_SOCKET_H | |
| #include <sys/socket.h> | |
| #endif | |
| #ifdef HAVE_NET_IF_H | |
| #include <net/if.h> | |
| #endif | |
| #ifdef HAVE_NET_ETHERNET_H | |
| #include <net/ethernet.h> | |
| #endif | |
| /* Generic socket object definitions and includes */ | |
| #define PySocket_BUILDING_SOCKET | |
| #include "socketmodule.h" | |
| /* Addressing includes */ | |
| #ifndef MS_WINDOWS | |
| /* Non-MS WINDOWS includes */ | |
| #ifdef HAVE_NETDB_H | |
| # include <netdb.h> | |
| #endif | |
| #include <unistd.h> // close() | |
| /* Headers needed for inet_ntoa() and inet_addr() */ | |
| # include <arpa/inet.h> | |
| # include <fcntl.h> | |
| #else /* MS_WINDOWS */ | |
| /* MS_WINDOWS includes */ | |
| # ifdef HAVE_FCNTL_H | |
| # include <fcntl.h> | |
| # endif | |
| /* Helpers needed for AF_HYPERV */ | |
| # include <Rpc.h> | |
| #ifndef RPC_S_OK | |
| #define RPC_S_OK 0L | |
| #endif | |
| /* Macros based on the IPPROTO enum, see: https://bugs.python.org/issue29515 */ | |
| #define IPPROTO_ICMP IPPROTO_ICMP | |
| #define IPPROTO_IGMP IPPROTO_IGMP | |
| #define IPPROTO_GGP IPPROTO_GGP | |
| #define IPPROTO_TCP IPPROTO_TCP | |
| #define IPPROTO_PUP IPPROTO_PUP | |
| #define IPPROTO_UDP IPPROTO_UDP | |
| #define IPPROTO_IDP IPPROTO_IDP | |
| #define IPPROTO_ND IPPROTO_ND | |
| #define IPPROTO_RAW IPPROTO_RAW | |
| #define IPPROTO_MAX IPPROTO_MAX | |
| #define IPPROTO_HOPOPTS IPPROTO_HOPOPTS | |
| #define IPPROTO_IPV4 IPPROTO_IPV4 | |
| #define IPPROTO_IPV6 IPPROTO_IPV6 | |
| #define IPPROTO_ROUTING IPPROTO_ROUTING | |
| #define IPPROTO_FRAGMENT IPPROTO_FRAGMENT | |
| #define IPPROTO_ESP IPPROTO_ESP | |
| #define IPPROTO_AH IPPROTO_AH | |
| #define IPPROTO_ICMPV6 IPPROTO_ICMPV6 | |
| #define IPPROTO_NONE IPPROTO_NONE | |
| #define IPPROTO_DSTOPTS IPPROTO_DSTOPTS | |
| #define IPPROTO_EGP IPPROTO_EGP | |
| #define IPPROTO_PIM IPPROTO_PIM | |
| #define IPPROTO_ICLFXBM IPPROTO_ICLFXBM // WinSock2 only | |
| #define IPPROTO_ST IPPROTO_ST // WinSock2 only | |
| #define IPPROTO_CBT IPPROTO_CBT // WinSock2 only | |
| #define IPPROTO_IGP IPPROTO_IGP // WinSock2 only | |
| #define IPPROTO_RDP IPPROTO_RDP // WinSock2 only | |
| #define IPPROTO_PGM IPPROTO_PGM // WinSock2 only | |
| #define IPPROTO_L2TP IPPROTO_L2TP // WinSock2 only | |
| #define IPPROTO_SCTP IPPROTO_SCTP // WinSock2 only | |
| /* Provides the IsWindows7SP1OrGreater() function */ | |
| #include <versionhelpers.h> | |
| // For if_nametoindex() and if_indextoname() | |
| #include <iphlpapi.h> | |
| /* remove some flags on older version Windows during run-time. | |
| https://msdn.microsoft.com/en-us/library/windows/desktop/ms738596.aspx */ | |
| typedef struct { | |
| DWORD build_number; /* available starting with this Win10 BuildNumber */ | |
| const char flag_name[20]; | |
| } FlagRuntimeInfo; | |
| /* IMPORTANT: make sure the list ordered by descending build_number */ | |
| static FlagRuntimeInfo win_runtime_flags[] = { | |
| /* available starting with Windows 10 1709 */ | |
| {16299, "TCP_KEEPIDLE"}, | |
| {16299, "TCP_KEEPINTVL"}, | |
| /* available starting with Windows 10 1703 */ | |
| {15063, "TCP_KEEPCNT"}, | |
| /* available starting with Windows 10 1607 */ | |
| {14393, "TCP_FASTOPEN"} | |
| }; | |
| static int | |
| remove_unusable_flags(PyObject *m) | |
| { | |
| PyObject *dict; | |
| OSVERSIONINFOEX info; | |
| dict = PyModule_GetDict(m); | |
| if (dict == NULL) { | |
| return -1; | |
| } | |
| #ifndef MS_WINDOWS_DESKTOP | |
| info.dwOSVersionInfoSize = sizeof(info); | |
| if (!GetVersionEx((OSVERSIONINFO*) &info)) { | |
| PyErr_SetFromWindowsErr(0); | |
| return -1; | |
| } | |
| #else | |
| /* set to Windows 10, except BuildNumber. */ | |
| memset(&info, 0, sizeof(info)); | |
| info.dwOSVersionInfoSize = sizeof(info); | |
| info.dwMajorVersion = 10; | |
| info.dwMinorVersion = 0; | |
| /* set Condition Mask */ | |
| DWORDLONG dwlConditionMask = 0; | |
| VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); | |
| VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); | |
| VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL); | |
| #endif | |
| for (int i=0; i<sizeof(win_runtime_flags)/sizeof(FlagRuntimeInfo); i++) { | |
| #ifdef MS_WINDOWS_DESKTOP | |
| info.dwBuildNumber = win_runtime_flags[i].build_number; | |
| /* greater than or equal to the specified version? | |
| Compatibility Mode will not cheat VerifyVersionInfo(...) */ | |
| BOOL isSupported = VerifyVersionInfo( | |
| &info, | |
| VER_MAJORVERSION|VER_MINORVERSION|VER_BUILDNUMBER, | |
| dwlConditionMask); | |
| #else | |
| /* note in this case 'info' is the actual OS version, whereas above | |
| it is the version to compare against. */ | |
| BOOL isSupported = info.dwMajorVersion > 10 || | |
| (info.dwMajorVersion == 10 && info.dwMinorVersion > 0) || | |
| (info.dwMajorVersion == 10 && info.dwMinorVersion == 0 && | |
| info.dwBuildNumber >= win_runtime_flags[i].build_number); | |
| #endif | |
| if (isSupported) { | |
| break; | |
| } | |
| else { | |
| if (PyDict_PopString(dict, win_runtime_flags[i].flag_name, | |
| NULL) < 0) { | |
| return -1; | |
| } | |
| } | |
| } | |
| return 0; | |
| } | |
| #endif | |
| #include <stddef.h> | |
| #ifndef O_NONBLOCK | |
| # define O_NONBLOCK O_NDELAY | |
| #endif | |
| /* include Python's addrinfo.h unless it causes trouble */ | |
| #if defined(__sgi) && _COMPILER_VERSION>700 && defined(_SS_ALIGNSIZE) | |
| /* Do not include addinfo.h on some newer IRIX versions. | |
| * _SS_ALIGNSIZE is defined in sys/socket.h by 6.5.21, | |
| * for example, but not by 6.5.10. | |
| */ | |
| #elif defined(_MSC_VER) && _MSC_VER>1201 | |
| /* Do not include addrinfo.h for MSVC7 or greater. 'addrinfo' and | |
| * EAI_* constants are defined in (the already included) ws2tcpip.h. | |
| */ | |
| #else | |
| # include "addrinfo.h" | |
| #endif | |
| #ifdef __APPLE__ | |
| #ifdef HAVE_INET_ATON | |
| #define USE_INET_ATON_WEAKLINK | |
| #endif | |
| #endif | |
| /* I know this is a bad practice, but it is the easiest... */ | |
| #if !defined(HAVE_GETADDRINFO) | |
| /* avoid clashes with the C library definition of the symbol. */ | |
| #define getaddrinfo fake_getaddrinfo | |
| #define gai_strerror fake_gai_strerror | |
| #define freeaddrinfo fake_freeaddrinfo | |
| #include "getaddrinfo.c" | |
| #endif | |
| #if !defined(HAVE_GETNAMEINFO) | |
| #define getnameinfo fake_getnameinfo | |
| #include "getnameinfo.c" | |
| #endif // HAVE_GETNAMEINFO | |
| #ifdef MS_WINDOWS | |
| #define SOCKETCLOSE closesocket | |
| #endif | |
| #ifdef MS_WIN32 | |
| # undef EAFNOSUPPORT | |
| # define EAFNOSUPPORT WSAEAFNOSUPPORT | |
| #endif | |
| #ifndef SOCKETCLOSE | |
| # define SOCKETCLOSE close | |
| #endif | |
| #if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H) | |
| # define USE_BLUETOOTH 1 | |
| # if defined(HAVE_BLUETOOTH_BLUETOOTH_H) // Linux | |
| # define _BT_L2_MEMB(sa, memb) ((sa)->l2_##memb) | |
| # define _BT_RC_MEMB(sa, memb) ((sa)->rc_##memb) | |
| # define _BT_HCI_MEMB(sa, memb) ((sa)->hci_##memb) | |
| # define _BT_SCO_MEMB(sa, memb) ((sa)->sco_##memb) | |
| # elif defined(__FreeBSD__) | |
| # define BTPROTO_L2CAP BLUETOOTH_PROTO_L2CAP | |
| # define BTPROTO_RFCOMM BLUETOOTH_PROTO_RFCOMM | |
| # define BTPROTO_HCI BLUETOOTH_PROTO_HCI | |
| # define BTPROTO_SCO BLUETOOTH_PROTO_SCO | |
| # define SOL_HCI SOL_HCI_RAW | |
| # define HCI_FILTER SO_HCI_RAW_FILTER | |
| # define HCI_DATA_DIR SO_HCI_RAW_DIRECTION | |
| # define sockaddr_l2 sockaddr_l2cap | |
| # define sockaddr_rc sockaddr_rfcomm | |
| # define hci_dev hci_node | |
| # define _BT_L2_MEMB(sa, memb) ((sa)->l2cap_##memb) | |
| # define _BT_RC_MEMB(sa, memb) ((sa)->rfcomm_##memb) | |
| # define _BT_HCI_MEMB(sa, memb) ((sa)->hci_##memb) | |
| # define _BT_SCO_MEMB(sa, memb) ((sa)->sco_##memb) | |
| # else // NetBSD, DragonFly BSD | |
| # define sockaddr_l2 sockaddr_bt | |
| # define sockaddr_rc sockaddr_bt | |
| # define sockaddr_hci sockaddr_bt | |
| # define sockaddr_sco sockaddr_bt | |
| # define bt_l2 bt | |
| # define bt_rc bt | |
| # define bt_sco bt | |
| # define bt_hci bt | |
| # define bt_cid bt_channel | |
| # define SOL_L2CAP BTPROTO_L2CAP | |
| # define SOL_RFCOMM BTPROTO_RFCOMM | |
| # define SOL_HCI BTPROTO_HCI | |
| # define SOL_SCO BTPROTO_SCO | |
| # define HCI_DATA_DIR SO_HCI_DIRECTION | |
| # define _BT_L2_MEMB(sa, memb) ((sa)->bt_##memb) | |
| # define _BT_RC_MEMB(sa, memb) ((sa)->bt_##memb) | |
| # define _BT_HCI_MEMB(sa, memb) ((sa)->bt_##memb) | |
| # define _BT_SCO_MEMB(sa, memb) ((sa)->bt_##memb) | |
| # endif | |
| #endif | |
| #ifdef MS_WINDOWS_DESKTOP | |
| #define sockaddr_rc SOCKADDR_BTH_REDEF | |
| #define USE_BLUETOOTH 1 | |
| #define AF_BLUETOOTH AF_BTH | |
| #define BTPROTO_RFCOMM BTHPROTO_RFCOMM | |
| #define _BT_RC_MEMB(sa, memb) ((sa)->memb) | |
| #endif /* MS_WINDOWS_DESKTOP */ | |
| /* Convert "sock_addr_t *" to "struct sockaddr *". */ | |
| #define SAS2SA(x) (&((x)->sa)) | |
| /* | |
| * Constants for getnameinfo() | |
| */ | |
| #if !defined(NI_MAXHOST) | |
| #define NI_MAXHOST 1025 | |
| #endif | |
| #if !defined(NI_MAXSERV) | |
| #define NI_MAXSERV 32 | |
| #endif | |
| #ifndef INVALID_SOCKET /* MS defines this */ | |
| #define INVALID_SOCKET (-1) | |
| #endif | |
| #ifndef INADDR_NONE | |
| #define INADDR_NONE (-1) | |
| #endif | |
| typedef struct _socket_state { | |
| /* The sock_type variable contains pointers to various functions, | |
| some of which call new_sockobject(), which uses sock_type, so | |
| there has to be a circular reference. */ | |
| PyTypeObject *sock_type; | |
| /* Global variable holding the exception type for errors detected | |
| by this module (but not argument type or memory errors, etc.). */ | |
| PyObject *socket_herror; | |
| PyObject *socket_gaierror; | |
| /* Default timeout for new sockets */ | |
| PyTime_t defaulttimeout; | |
| } socket_state; | |
| #if defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4) | |
| #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) | |
| /* accept4() is available on Linux 2.6.28+ and glibc 2.10 */ | |
| static int accept4_works = -1; | |
| #endif | |
| #endif | |
| #ifdef SOCK_CLOEXEC | |
| /* socket() and socketpair() fail with EINVAL on Linux kernel older | |
| * than 2.6.27 if SOCK_CLOEXEC flag is set in the socket type. */ | |
| static int sock_cloexec_works = -1; | |
| #endif | |
| static inline void | |
| set_sock_fd(PySocketSockObject *s, SOCKET_T fd) | |
| { | |
| #if SIZEOF_SOCKET_T == SIZEOF_INT | |
| _Py_atomic_store_int_relaxed((int *)&s->sock_fd, (int)fd); | |
| #elif SIZEOF_SOCKET_T == SIZEOF_LONG | |
| _Py_atomic_store_long_relaxed((long *)&s->sock_fd, (long)fd); | |
| #elif SIZEOF_SOCKET_T == SIZEOF_LONG_LONG | |
| _Py_atomic_store_llong_relaxed((long long *)&s->sock_fd, (long long)fd); | |
| #else | |
| #error "Unsupported SIZEOF_SOCKET_T" | |
| #endif | |
| } | |
| static inline SOCKET_T | |
| get_sock_fd(PySocketSockObject *s) | |
| { | |
| #if SIZEOF_SOCKET_T == SIZEOF_INT | |
| return (SOCKET_T)_Py_atomic_load_int_relaxed((int *)&s->sock_fd); | |
| #elif SIZEOF_SOCKET_T == SIZEOF_LONG | |
| return (SOCKET_T)_Py_atomic_load_long_relaxed((long *)&s->sock_fd); | |
| #elif SIZEOF_SOCKET_T == SIZEOF_LONG_LONG | |
| return (SOCKET_T)_Py_atomic_load_llong_relaxed((long long *)&s->sock_fd); | |
| #else | |
| #error "Unsupported SIZEOF_SOCKET_T" | |
| #endif | |
| } | |
| #define _PySocketSockObject_CAST(op) ((PySocketSockObject *)(op)) | |
| static inline socket_state * | |
| get_module_state(PyObject *mod) | |
| { | |
| void *state = _PyModule_GetState(mod); | |
| assert(state != NULL); | |
| return (socket_state *)state; | |
| } | |
| static struct PyModuleDef socketmodule; | |
| static inline socket_state * | |
| find_module_state_by_def(PyTypeObject *type) | |
| { | |
| PyObject *mod = PyType_GetModuleByDef(type, &socketmodule); | |
| assert(mod != NULL); | |
| return get_module_state(mod); | |
| } | |
| #define UNSIGNED_INT_CONVERTER(NAME, TYPE) \ | |
| static int \ | |
| _PyLong_##NAME##_Converter(PyObject *obj, void *ptr) \ | |
| { \ | |
| Py_ssize_t bytes = PyLong_AsNativeBytes(obj, ptr, sizeof(TYPE), \ | |
| Py_ASNATIVEBYTES_NATIVE_ENDIAN | \ | |
| Py_ASNATIVEBYTES_ALLOW_INDEX | \ | |
| Py_ASNATIVEBYTES_REJECT_NEGATIVE | \ | |
| Py_ASNATIVEBYTES_UNSIGNED_BUFFER); \ | |
| if (bytes < 0) { \ | |
| return 0; \ | |
| } \ | |
| if ((size_t)bytes > sizeof(TYPE)) { \ | |
| PyErr_SetString(PyExc_OverflowError, \ | |
| "Python int too large for C " #TYPE); \ | |
| return 0; \ | |
| } \ | |
| return 1; \ | |
| } | |
| #if defined(HAVE_IF_INDEXTONAME) || defined(MS_WINDOWS_DESKTOP) | |
| # ifdef MS_WINDOWS | |
| UNSIGNED_INT_CONVERTER(NetIfindex, NET_IFINDEX) | |
| # else | |
| # define _PyLong_NetIfindex_Converter _PyLong_UnsignedInt_Converter | |
| # define NET_IFINDEX unsigned int | |
| # endif | |
| #endif // defined(HAVE_IF_INDEXTONAME) || defined(MS_WINDOWS_DESKTOP) | |
| /*[python input] | |
| class NET_IFINDEX_converter(CConverter): | |
| type = "NET_IFINDEX" | |
| converter = '_PyLong_NetIfindex_Converter' | |
| [python start generated code]*/ | |
| /*[python end generated code: output=da39a3ee5e6b4b0d input=1cf809c40a407c34]*/ | |
| /*[clinic input] | |
| module _socket | |
| class _socket.socket "PySocketSockObject *" "clinic_state()->sock_type" | |
| [clinic start generated code]*/ | |
| /*[clinic end generated code: output=da39a3ee5e6b4b0d input=2db2489bd2219fd8]*/ | |
| /* XXX There's a problem here: *static* functions are not supposed to have | |
| a Py prefix (or use CapitalizedWords). Later... */ | |
| #if defined(HAVE_POLL_H) | |
| #include <poll.h> | |
| #elif defined(HAVE_SYS_POLL_H) | |
| #include <sys/poll.h> | |
| #endif | |
| /* Largest value to try to store in a socklen_t (used when handling | |
| ancillary data). POSIX requires socklen_t to hold at least | |
| (2**31)-1 and recommends against storing larger values, but | |
| socklen_t was originally int in the BSD interface, so to be on the | |
| safe side we use the smaller of (2**31)-1 and INT_MAX. */ | |
| #if INT_MAX > 0x7fffffff | |
| #define SOCKLEN_T_LIMIT 0x7fffffff | |
| #else | |
| #define SOCKLEN_T_LIMIT INT_MAX | |
| #endif | |
| #ifdef HAVE_POLL | |
| /* Instead of select(), we'll use poll() since poll() works on any fd. */ | |
| #define IS_SELECTABLE(s) 1 | |
| /* Can we call select() with this socket without a buffer overrun? */ | |
| #else | |
| /* If there's no timeout left, we don't have to call select, so it's a safe, | |
| * little white lie. */ | |
| #define IS_SELECTABLE(s) (_PyIsSelectable_fd((s)->sock_fd) || (s)->sock_timeout <= 0) | |
| #endif | |
| // SCM_RIGHTS, sendmsg(), recvmsg() and sethostname() don't work properly on | |
| // Cygwin: disable these features. | |
| #ifdef __CYGWIN__ | |
| # undef CMSG_LEN | |
| # undef SCM_RIGHTS | |
| # undef HAVE_SETHOSTNAME | |
| #endif | |
| /* The default family of socketpair() is AF_UNIX if defined on the | |
| platform; otherwise, the default is AF_INET. */ | |
| #if defined(AF_UNIX) | |
| # define SOCKETPAIR_DEFAULT_FAMILY AF_UNIX | |
| #else | |
| # define SOCKETPAIR_DEFAULT_FAMILY AF_INET | |
| #endif | |
| #define clinic_state() (find_module_state_by_def(type)) | |
| #include "clinic/socketmodule.c.h" | |
| #undef clinic_state | |
| static PyObject* | |
| select_error(void) | |
| { | |
| PyErr_SetString(PyExc_OSError, "unable to select on socket"); | |
| return NULL; | |
| } | |
| #ifdef MS_WINDOWS | |
| #ifndef WSAEAGAIN | |
| #define WSAEAGAIN WSAEWOULDBLOCK | |
| #endif | |
| #define CHECK_ERRNO(expected) \ | |
| (WSAGetLastError() == WSA ## expected) | |
| #else | |
| #define CHECK_ERRNO(expected) \ | |
| (errno == expected) | |
| #endif | |
| #ifdef MS_WINDOWS | |
| # define GET_SOCK_ERROR WSAGetLastError() | |
| # define SET_SOCK_ERROR(err) WSASetLastError(err) | |
| # define SOCK_TIMEOUT_ERR WSAEWOULDBLOCK | |
| # define SOCK_INPROGRESS_ERR WSAEWOULDBLOCK | |
| #else | |
| # define GET_SOCK_ERROR errno | |
| # define SET_SOCK_ERROR(err) do { errno = err; } while (0) | |
| # define SOCK_TIMEOUT_ERR EWOULDBLOCK | |
| # define SOCK_INPROGRESS_ERR EINPROGRESS | |
| #endif | |
| /* Convenience function to raise an error according to errno | |
| and return a NULL pointer from a function. */ | |
| static PyObject * | |
| set_error(void) | |
| { | |
| #ifdef MS_WINDOWS | |
| int err_no = WSAGetLastError(); | |
| /* PyErr_SetExcFromWindowsErr() invokes FormatMessage() which | |
| recognizes the error codes used by both GetLastError() and | |
| WSAGetLastError */ | |
| if (err_no) | |
| return PyErr_SetExcFromWindowsErr(PyExc_OSError, err_no); | |
| #endif | |
| return PyErr_SetFromErrno(PyExc_OSError); | |
| } | |
| #if defined(HAVE_HSTRERROR) || defined(HAVE_GAI_STRERROR) | |
| /* Decode a locale-encoded error message from the C library. | |
| It can be localized and use a non-UTF-8 encoding. */ | |
| static PyObject * | |
| decode_error_message(const char *str) | |
| { | |
| return PyUnicode_DecodeLocale(str, "surrogateescape"); | |
| } | |
| #endif | |
| #if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME) || defined (HAVE_GETHOSTBYADDR) | |
| static PyObject * | |
| set_herror(socket_state *state, int h_error) | |
| { | |
| PyObject *v; | |
| #ifdef HAVE_HSTRERROR | |
| const char *errmsg = hstrerror(h_error); | |
| _Py_MSAN_UNPOISON_STRING(errmsg); | |
| v = Py_BuildValue("(iN)", h_error, decode_error_message(errmsg)); | |
| #else | |
| v = Py_BuildValue("(is)", h_error, "host not found"); | |
| #endif | |
| if (v != NULL) { | |
| PyErr_SetObject(state->socket_herror, v); | |
| Py_DECREF(v); | |
| } | |
| return NULL; | |
| } | |
| #endif | |
| #ifdef HAVE_GETADDRINFO | |
| static PyObject * | |
| set_gaierror(socket_state *state, int error) | |
| { | |
| PyObject *v; | |
| #ifdef EAI_SYSTEM | |
| /* EAI_SYSTEM is not available on Windows XP. */ | |
| if (error == EAI_SYSTEM) | |
| return set_error(); | |
| #endif | |
| #ifdef HAVE_GAI_STRERROR | |
| const char *errmsg = gai_strerror(error); | |
| _Py_MSAN_UNPOISON_STRING(errmsg); | |
| v = Py_BuildValue("(iN)", error, decode_error_message(errmsg)); | |
| #else | |
| v = Py_BuildValue("(is)", error, "getaddrinfo failed"); | |
| #endif | |
| if (v != NULL) { | |
| PyErr_SetObject(state->socket_gaierror, v); | |
| Py_DECREF(v); | |
| } | |
| return NULL; | |
| } | |
| #endif | |
| /* Function to perform the setting of socket blocking mode | |
| internally. block = (1 | 0). */ | |
| static int | |
| internal_setblocking(PySocketSockObject *s, int block) | |
| { | |
| int result = -1; | |
| #ifdef MS_WINDOWS | |
| u_long arg; | |
| #endif | |
| #if !defined(MS_WINDOWS) \ | |
| && !((defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO))) | |
| int delay_flag, new_delay_flag; | |
| #endif | |
| Py_BEGIN_ALLOW_THREADS | |
| #ifndef MS_WINDOWS | |
| #if (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO)) | |
| block = !block; | |
| if (ioctl(get_sock_fd(s), FIONBIO, (unsigned int *)&block) == -1) | |
| goto done; | |
| #else | |
| delay_flag = fcntl(get_sock_fd(s), F_GETFL, 0); | |
| if (delay_flag == -1) | |
| goto done; | |
| if (block) | |
| new_delay_flag = delay_flag & (~O_NONBLOCK); | |
| else | |
| new_delay_flag = delay_flag | O_NONBLOCK; | |
| if (new_delay_flag != delay_flag) | |
| if (fcntl(get_sock_fd(s), F_SETFL, new_delay_flag) == -1) | |
| goto done; | |
| #endif | |
| #else /* MS_WINDOWS */ | |
| arg = !block; | |
| if (ioctlsocket(get_sock_fd(s), FIONBIO, &arg) != 0) | |
| goto done; | |
| #endif /* MS_WINDOWS */ | |
| result = 0; | |
| done: | |
| Py_END_ALLOW_THREADS | |
| if (result) { | |
| #ifndef MS_WINDOWS | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| #else | |
| PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); | |
| #endif | |
| } | |
| return result; | |
| } | |
| static int | |
| internal_select(PySocketSockObject *s, int writing, PyTime_t interval, | |
| int connect) | |
| { | |
| int n; | |
| #ifdef HAVE_POLL | |
| struct pollfd pollfd; | |
| PyTime_t ms; | |
| #else | |
| fd_set fds, efds; | |
| struct timeval tv, *tvp; | |
| #endif | |
| /* must be called with a thread state */ | |
| _Py_AssertHoldsTstate(); | |
| /* Error condition is for output only */ | |
| assert(!(connect && !writing)); | |
| /* Guard against closed socket */ | |
| if (get_sock_fd(s) == INVALID_SOCKET) | |
| return 0; | |
| /* Prefer poll, if available, since you can poll() any fd | |
| * which can't be done with select(). */ | |
| #ifdef HAVE_POLL | |
| pollfd.fd = get_sock_fd(s); | |
| pollfd.events = writing ? POLLOUT : POLLIN; | |
| if (connect) { | |
| /* On Windows, the socket becomes writable on connection success, | |
| but a connection failure is notified as an error. On POSIX, the | |
| socket becomes writable on connection success or on connection | |
| failure. */ | |
| pollfd.events |= POLLERR; | |
| } | |
| /* s->sock_timeout is in seconds, timeout in ms */ | |
| ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); | |
| if (ms > INT_MAX) { | |
| ms = INT_MAX; | |
| } | |
| /* On some OSes, typically BSD-based ones, the timeout parameter of the | |
| poll() syscall, when negative, must be exactly INFTIM, where defined, | |
| or -1. See issue 37811. */ | |
| if (ms < 0) { | |
| #ifdef INFTIM | |
| ms = INFTIM; | |
| #else | |
| ms = -1; | |
| #endif | |
| } | |
| assert(INT_MIN <= ms && ms <= INT_MAX); | |
| Py_BEGIN_ALLOW_THREADS; | |
| n = poll(&pollfd, 1, (int)ms); | |
| Py_END_ALLOW_THREADS; | |
| #else | |
| if (interval >= 0) { | |
| _PyTime_AsTimeval_clamp(interval, &tv, _PyTime_ROUND_CEILING); | |
| tvp = &tv; | |
| } | |
| else | |
| tvp = NULL; | |
| FD_ZERO(&fds); | |
| FD_SET(get_sock_fd(s), &fds); | |
| FD_ZERO(&efds); | |
| if (connect) { | |
| /* On Windows, the socket becomes writable on connection success, | |
| but a connection failure is notified as an error. On POSIX, the | |
| socket becomes writable on connection success or on connection | |
| failure. */ | |
| FD_SET(get_sock_fd(s), &efds); | |
| } | |
| /* See if the socket is ready */ | |
| Py_BEGIN_ALLOW_THREADS; | |
| if (writing) | |
| n = select(Py_SAFE_DOWNCAST(get_sock_fd(s)+1, SOCKET_T, int), | |
| NULL, &fds, &efds, tvp); | |
| else | |
| n = select(Py_SAFE_DOWNCAST(get_sock_fd(s)+1, SOCKET_T, int), | |
| &fds, NULL, &efds, tvp); | |
| Py_END_ALLOW_THREADS; | |
| #endif | |
| if (n < 0) | |
| return -1; | |
| if (n == 0) | |
| return 1; | |
| return 0; | |
| } | |
| /* Call a socket function. | |
| On error, raise an exception and return -1 if err is set, or fill err and | |
| return -1 otherwise. If a signal was received and the signal handler raised | |
| an exception, return -1, and set err to -1 if err is set. | |
| On success, return 0, and set err to 0 if err is set. | |
| If the socket has a timeout, wait until the socket is ready before calling | |
| the function: wait until the socket is writable if writing is nonzero, wait | |
| until the socket received data otherwise. | |
| If the socket function is interrupted by a signal (failed with EINTR): retry | |
| the function, except if the signal handler raised an exception (PEP 475). | |
| When the function is retried, recompute the timeout using a monotonic clock. | |
| sock_call_ex() must be called with the GIL held. The socket function is | |
| called with the GIL released. */ | |
| static int | |
| sock_call_ex(PySocketSockObject *s, | |
| int writing, | |
| int (*sock_func) (PySocketSockObject *s, void *data), | |
| void *data, | |
| int connect, | |
| int *err, | |
| PyTime_t timeout) | |
| { | |
| int has_timeout = (timeout > 0); | |
| PyTime_t deadline = 0; | |
| int deadline_initialized = 0; | |
| int res; | |
| /* sock_call() must be called with a thread state. */ | |
| _Py_AssertHoldsTstate(); | |
| /* outer loop to retry select() when select() is interrupted by a signal | |
| or to retry select()+sock_func() on false positive (see above) */ | |
| while (1) { | |
| /* For connect(), poll even for blocking socket. The connection | |
| runs asynchronously. */ | |
| if (has_timeout || connect) { | |
| if (has_timeout) { | |
| PyTime_t interval; | |
| if (deadline_initialized) { | |
| /* recompute the timeout */ | |
| interval = _PyDeadline_Get(deadline); | |
| } | |
| else { | |
| deadline_initialized = 1; | |
| deadline = _PyDeadline_Init(timeout); | |
| interval = timeout; | |
| } | |
| if (interval >= 0) { | |
| res = internal_select(s, writing, interval, connect); | |
| } | |
| else { | |
| res = 1; | |
| } | |
| } | |
| else { | |
| res = internal_select(s, writing, timeout, connect); | |
| } | |
| if (res == -1) { | |
| if (err) | |
| *err = GET_SOCK_ERROR; | |
| if (CHECK_ERRNO(EINTR)) { | |
| /* select() was interrupted by a signal */ | |
| if (PyErr_CheckSignals()) { | |
| if (err) | |
| *err = -1; | |
| return -1; | |
| } | |
| /* retry select() */ | |
| continue; | |
| } | |
| /* select() failed */ | |
| s->errorhandler(); | |
| return -1; | |
| } | |
| if (res == 1) { | |
| if (err) | |
| *err = SOCK_TIMEOUT_ERR; | |
| else | |
| PyErr_SetString(PyExc_TimeoutError, "timed out"); | |
| return -1; | |
| } | |
| /* the socket is ready */ | |
| } | |
| /* inner loop to retry sock_func() when sock_func() is interrupted | |
| by a signal */ | |
| while (1) { | |
| Py_BEGIN_ALLOW_THREADS | |
| res = sock_func(s, data); | |
| Py_END_ALLOW_THREADS | |
| if (res) { | |
| /* sock_func() succeeded */ | |
| if (err) | |
| *err = 0; | |
| return 0; | |
| } | |
| if (err) | |
| *err = GET_SOCK_ERROR; | |
| if (!CHECK_ERRNO(EINTR)) | |
| break; | |
| /* sock_func() was interrupted by a signal */ | |
| if (PyErr_CheckSignals()) { | |
| if (err) | |
| *err = -1; | |
| return -1; | |
| } | |
| /* retry sock_func() */ | |
| } | |
| if (s->sock_timeout > 0 | |
| && (CHECK_ERRNO(EWOULDBLOCK) || CHECK_ERRNO(EAGAIN))) { | |
| /* False positive: sock_func() failed with EWOULDBLOCK or EAGAIN. | |
| For example, select() could indicate a socket is ready for | |
| reading, but the data then discarded by the OS because of a | |
| wrong checksum. | |
| Loop on select() to recheck for socket readiness. */ | |
| continue; | |
| } | |
| /* sock_func() failed */ | |
| if (!err) | |
| s->errorhandler(); | |
| /* else: err was already set before */ | |
| return -1; | |
| } | |
| } | |
| static int | |
| sock_call(PySocketSockObject *s, | |
| int writing, | |
| int (*func) (PySocketSockObject *s, void *data), | |
| void *data) | |
| { | |
| return sock_call_ex(s, writing, func, data, 0, NULL, s->sock_timeout); | |
| } | |
| /* Initialize a new socket object. */ | |
| static int | |
| init_sockobject(socket_state *state, PySocketSockObject *s, | |
| SOCKET_T fd, int family, int type, int proto) | |
| { | |
| set_sock_fd(s, fd); | |
| s->sock_family = family; | |
| s->sock_type = type; | |
| /* It's possible to pass SOCK_NONBLOCK and SOCK_CLOEXEC bit flags | |
| on some OSes as part of socket.type. We want to reset them here, | |
| to make socket.type be set to the same value on all platforms. | |
| Otherwise, simple code like 'if sock.type == SOCK_STREAM' is | |
| not portable. | |
| */ | |
| #ifdef SOCK_NONBLOCK | |
| s->sock_type = s->sock_type & ~SOCK_NONBLOCK; | |
| #endif | |
| #ifdef SOCK_CLOEXEC | |
| s->sock_type = s->sock_type & ~SOCK_CLOEXEC; | |
| #endif | |
| s->sock_proto = proto; | |
| s->errorhandler = &set_error; | |
| #ifdef SOCK_NONBLOCK | |
| if (type & SOCK_NONBLOCK) | |
| s->sock_timeout = 0; | |
| else | |
| #endif | |
| { | |
| s->sock_timeout = _Py_atomic_load_int64_relaxed(&state->defaulttimeout); | |
| if (s->sock_timeout >= 0) { | |
| if (internal_setblocking(s, 0) == -1) { | |
| return -1; | |
| } | |
| } | |
| } | |
| s->state = state; | |
| return 0; | |
| } | |
| #ifdef HAVE_SOCKETPAIR | |
| /* Create a new socket object. | |
| This just creates the object and initializes it. | |
| If the creation fails, return NULL and set an exception (implicit | |
| in NEWOBJ()). */ | |
| static PySocketSockObject * | |
| new_sockobject(socket_state *state, SOCKET_T fd, int family, int type, | |
| int proto) | |
| { | |
| PyTypeObject *tp = state->sock_type; | |
| PySocketSockObject *s = (PySocketSockObject *)tp->tp_alloc(tp, 0); | |
| if (s == NULL) { | |
| return NULL; | |
| } | |
| if (init_sockobject(state, s, fd, family, type, proto) == -1) { | |
| Py_DECREF(s); | |
| return NULL; | |
| } | |
| return s; | |
| } | |
| #endif | |
| /* Lock to allow python interpreter to continue, but only allow one | |
| thread to be in gethostbyname or getaddrinfo */ | |
| #if defined(USE_GETHOSTBYNAME_LOCK) | |
| static PyMutex netdb_lock = {0}; | |
| #endif | |
| #ifdef HAVE_GETADDRINFO | |
| /* Convert a string specifying a host name or one of a few symbolic | |
| names to a numeric IP address. This usually calls gethostbyname() | |
| to do the work; the names "" and "<broadcast>" are special. | |
| Return the length (IPv4 should be 4 bytes), or negative if | |
| an error occurred; then an exception is raised. */ | |
| static int | |
| setipaddr(socket_state *state, const char *name, struct sockaddr *addr_ret, | |
| size_t addr_ret_size, int af) | |
| { | |
| struct addrinfo hints, *res; | |
| int error; | |
| memset((void *) addr_ret, '\0', sizeof(*addr_ret)); | |
| if (name[0] == '\0') { | |
| int siz; | |
| memset(&hints, 0, sizeof(hints)); | |
| hints.ai_family = af; | |
| hints.ai_socktype = SOCK_DGRAM; /*dummy*/ | |
| hints.ai_flags = AI_PASSIVE; | |
| Py_BEGIN_ALLOW_THREADS | |
| error = getaddrinfo(NULL, "0", &hints, &res); | |
| Py_END_ALLOW_THREADS | |
| /* We assume that those thread-unsafe getaddrinfo() versions | |
| *are* safe regarding their return value, ie. that a | |
| subsequent call to getaddrinfo() does not destroy the | |
| outcome of the first call. */ | |
| if (error) { | |
| res = NULL; // no-op, remind us that it is invalid; gh-100795 | |
| set_gaierror(state, error); | |
| return -1; | |
| } | |
| switch (res->ai_family) { | |
| case AF_INET: | |
| siz = 4; | |
| break; | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| siz = 16; | |
| break; | |
| #endif | |
| default: | |
| freeaddrinfo(res); | |
| PyErr_SetString(PyExc_OSError, | |
| "unsupported address family"); | |
| return -1; | |
| } | |
| if (res->ai_next) { | |
| freeaddrinfo(res); | |
| PyErr_SetString(PyExc_OSError, | |
| "wildcard resolved to multiple address"); | |
| return -1; | |
| } | |
| if (res->ai_addrlen < addr_ret_size) | |
| addr_ret_size = res->ai_addrlen; | |
| memcpy(addr_ret, res->ai_addr, addr_ret_size); | |
| freeaddrinfo(res); | |
| return siz; | |
| } | |
| /* special-case broadcast - inet_addr() below can return INADDR_NONE for | |
| * this */ | |
| if (strcmp(name, "255.255.255.255") == 0 || | |
| strcmp(name, "<broadcast>") == 0) { | |
| struct sockaddr_in *sin; | |
| if (af != AF_INET && af != AF_UNSPEC) { | |
| PyErr_SetString(PyExc_OSError, | |
| "address family mismatched"); | |
| return -1; | |
| } | |
| sin = (struct sockaddr_in *)addr_ret; | |
| memset((void *) sin, '\0', sizeof(*sin)); | |
| sin->sin_family = AF_INET; | |
| #ifdef HAVE_SOCKADDR_SA_LEN | |
| sin->sin_len = sizeof(*sin); | |
| #endif | |
| sin->sin_addr.s_addr = INADDR_BROADCAST; | |
| return sizeof(sin->sin_addr); | |
| } | |
| /* avoid a name resolution in case of numeric address */ | |
| #ifdef HAVE_INET_PTON | |
| /* check for an IPv4 address */ | |
| if (af == AF_UNSPEC || af == AF_INET) { | |
| struct sockaddr_in *sin = (struct sockaddr_in *)addr_ret; | |
| memset(sin, 0, sizeof(*sin)); | |
| if (inet_pton(AF_INET, name, &sin->sin_addr) > 0) { | |
| sin->sin_family = AF_INET; | |
| #ifdef HAVE_SOCKADDR_SA_LEN | |
| sin->sin_len = sizeof(*sin); | |
| #endif | |
| return 4; | |
| } | |
| } | |
| #ifdef ENABLE_IPV6 | |
| /* check for an IPv6 address - if the address contains a scope ID, we | |
| * fallback to getaddrinfo(), which can handle translation from interface | |
| * name to interface index */ | |
| if ((af == AF_UNSPEC || af == AF_INET6) && !strchr(name, '%')) { | |
| struct sockaddr_in6 *sin = (struct sockaddr_in6 *)addr_ret; | |
| memset(sin, 0, sizeof(*sin)); | |
| if (inet_pton(AF_INET6, name, &sin->sin6_addr) > 0) { | |
| sin->sin6_family = AF_INET6; | |
| #ifdef HAVE_SOCKADDR_SA_LEN | |
| sin->sin6_len = sizeof(*sin); | |
| #endif | |
| return 16; | |
| } | |
| } | |
| #endif /* ENABLE_IPV6 */ | |
| #else /* HAVE_INET_PTON */ | |
| /* check for an IPv4 address */ | |
| if (af == AF_INET || af == AF_UNSPEC) { | |
| struct sockaddr_in *sin = (struct sockaddr_in *)addr_ret; | |
| memset(sin, 0, sizeof(*sin)); | |
| if ((sin->sin_addr.s_addr = inet_addr(name)) != INADDR_NONE) { | |
| sin->sin_family = AF_INET; | |
| #ifdef HAVE_SOCKADDR_SA_LEN | |
| sin->sin_len = sizeof(*sin); | |
| #endif | |
| return 4; | |
| } | |
| } | |
| #endif /* HAVE_INET_PTON */ | |
| /* perform a name resolution */ | |
| memset(&hints, 0, sizeof(hints)); | |
| hints.ai_family = af; | |
| Py_BEGIN_ALLOW_THREADS | |
| error = getaddrinfo(name, NULL, &hints, &res); | |
| #if defined(__digital__) && defined(__unix__) | |
| if (error == EAI_NONAME && af == AF_UNSPEC) { | |
| /* On Tru64 V5.1, numeric-to-addr conversion fails | |
| if no address family is given. Assume IPv4 for now.*/ | |
| hints.ai_family = AF_INET; | |
| error = getaddrinfo(name, NULL, &hints, &res); | |
| } | |
| #endif | |
| Py_END_ALLOW_THREADS | |
| if (error) { | |
| res = NULL; // no-op, remind us that it is invalid; gh-100795 | |
| set_gaierror(state, error); | |
| return -1; | |
| } | |
| if (res->ai_addrlen < addr_ret_size) | |
| addr_ret_size = res->ai_addrlen; | |
| memcpy((char *) addr_ret, res->ai_addr, addr_ret_size); | |
| freeaddrinfo(res); | |
| switch (addr_ret->sa_family) { | |
| case AF_INET: | |
| return 4; | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| return 16; | |
| #endif | |
| default: | |
| PyErr_SetString(PyExc_OSError, "unknown address family"); | |
| return -1; | |
| } | |
| } | |
| #endif // HAVE_GETADDRINFO | |
| /* Convert IPv4 sockaddr to a Python str. */ | |
| static PyObject * | |
| make_ipv4_addr(const struct sockaddr_in *addr) | |
| { | |
| char buf[INET_ADDRSTRLEN]; | |
| if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) { | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| return NULL; | |
| } | |
| return PyUnicode_FromString(buf); | |
| } | |
| #ifdef ENABLE_IPV6 | |
| /* Convert IPv6 sockaddr to a Python str. */ | |
| static PyObject * | |
| make_ipv6_addr(const struct sockaddr_in6 *addr) | |
| { | |
| char buf[INET6_ADDRSTRLEN]; | |
| if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) { | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| return NULL; | |
| } | |
| return PyUnicode_FromString(buf); | |
| } | |
| #endif | |
| #ifdef USE_BLUETOOTH | |
| /* Convert a string representation of a Bluetooth address into a numeric | |
| address. Returns the length (6), or raises an exception and returns -1 if | |
| an error occurred. */ | |
| static int | |
| setbdaddr(const char *name, bdaddr_t *bdaddr) | |
| { | |
| unsigned int b0, b1, b2, b3, b4, b5; | |
| char ch; | |
| int n; | |
| n = sscanf(name, "%X:%X:%X:%X:%X:%X%c", | |
| &b5, &b4, &b3, &b2, &b1, &b0, &ch); | |
| if (n == 6 && (b0 | b1 | b2 | b3 | b4 | b5) < 256) { | |
| #ifdef MS_WINDOWS | |
| *bdaddr = (ULONGLONG)(b0 & 0xFF); | |
| *bdaddr |= ((ULONGLONG)(b1 & 0xFF) << 8); | |
| *bdaddr |= ((ULONGLONG)(b2 & 0xFF) << 16); | |
| *bdaddr |= ((ULONGLONG)(b3 & 0xFF) << 24); | |
| *bdaddr |= ((ULONGLONG)(b4 & 0xFF) << 32); | |
| *bdaddr |= ((ULONGLONG)(b5 & 0xFF) << 40); | |
| #else | |
| bdaddr->b[0] = b0; | |
| bdaddr->b[1] = b1; | |
| bdaddr->b[2] = b2; | |
| bdaddr->b[3] = b3; | |
| bdaddr->b[4] = b4; | |
| bdaddr->b[5] = b5; | |
| #endif | |
| return 6; | |
| } else { | |
| PyErr_SetString(PyExc_OSError, "bad bluetooth address"); | |
| return -1; | |
| } | |
| } | |
| /* Create a string representation of the Bluetooth address. This is always a | |
| string of the form 'XX:XX:XX:XX:XX:XX' where XX is a two digit hexadecimal | |
| value (zero padded if necessary). */ | |
| static PyObject * | |
| makebdaddr(bdaddr_t *bdaddr) | |
| { | |
| #ifdef MS_WINDOWS | |
| int i; | |
| unsigned int octets[6]; | |
| for (i = 0; i < 6; ++i) { | |
| octets[i] = ((*bdaddr) >> (8 * i)) & 0xFF; | |
| } | |
| return PyUnicode_FromFormat("%02X:%02X:%02X:%02X:%02X:%02X", | |
| octets[5], octets[4], octets[3], | |
| octets[2], octets[1], octets[0]); | |
| #else | |
| return PyUnicode_FromFormat("%02X:%02X:%02X:%02X:%02X:%02X", | |
| bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], | |
| bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); | |
| #endif | |
| } | |
| #endif | |
| PyObject* | |
| unicode_fsdecode(void *arg) | |
| { | |
| return PyUnicode_DecodeFSDefault((const char*)arg); | |
| } | |
| /* Create an object representing the given socket address, | |
| suitable for passing it back to bind(), connect() etc. | |
| The family field of the sockaddr structure is inspected | |
| to determine what kind of address it really is. */ | |
| /*ARGSUSED*/ | |
| static PyObject * | |
| makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) | |
| { | |
| if (addrlen == 0) { | |
| /* No address -- may be recvfrom() from known socket */ | |
| Py_RETURN_NONE; | |
| } | |
| switch (addr->sa_family) { | |
| case AF_INET: | |
| { | |
| const struct sockaddr_in *a = (const struct sockaddr_in *)addr; | |
| PyObject *addrobj = make_ipv4_addr(a); | |
| PyObject *ret = NULL; | |
| if (addrobj) { | |
| ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port)); | |
| Py_DECREF(addrobj); | |
| } | |
| return ret; | |
| } | |
| #if defined(AF_UNIX) | |
| case AF_UNIX: | |
| { | |
| struct sockaddr_un *a = (struct sockaddr_un *) addr; | |
| #ifdef __linux__ | |
| size_t linuxaddrlen = addrlen - offsetof(struct sockaddr_un, sun_path); | |
| if (linuxaddrlen > 0 && a->sun_path[0] == 0) { /* Linux abstract namespace */ | |
| return PyBytes_FromStringAndSize(a->sun_path, linuxaddrlen); | |
| } | |
| else | |
| #endif /* linux */ | |
| { | |
| /* regular NULL-terminated string */ | |
| return PyUnicode_DecodeFSDefault(a->sun_path); | |
| } | |
| } | |
| #endif /* AF_UNIX */ | |
| #if defined(AF_NETLINK) | |
| case AF_NETLINK: | |
| { | |
| struct sockaddr_nl *a = (struct sockaddr_nl *) addr; | |
| return Py_BuildValue("II", a->nl_pid, a->nl_groups); | |
| } | |
| #endif /* AF_NETLINK */ | |
| #if defined(AF_QIPCRTR) | |
| case AF_QIPCRTR: | |
| { | |
| struct sockaddr_qrtr *a = (struct sockaddr_qrtr *) addr; | |
| return Py_BuildValue("II", a->sq_node, a->sq_port); | |
| } | |
| #endif /* AF_QIPCRTR */ | |
| #if defined(AF_VSOCK) | |
| case AF_VSOCK: | |
| { | |
| struct sockaddr_vm *a = (struct sockaddr_vm *) addr; | |
| return Py_BuildValue("II", a->svm_cid, a->svm_port); | |
| } | |
| #endif /* AF_VSOCK */ | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| { | |
| const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)addr; | |
| PyObject *addrobj = make_ipv6_addr(a); | |
| PyObject *ret = NULL; | |
| if (addrobj) { | |
| ret = Py_BuildValue("OiII", | |
| addrobj, | |
| ntohs(a->sin6_port), | |
| ntohl(a->sin6_flowinfo), | |
| a->sin6_scope_id); | |
| Py_DECREF(addrobj); | |
| } | |
| return ret; | |
| } | |
| #endif /* ENABLE_IPV6 */ | |
| #ifdef USE_BLUETOOTH | |
| case AF_BLUETOOTH: | |
| switch (proto) { | |
| #ifdef BTPROTO_L2CAP | |
| case BTPROTO_L2CAP: | |
| { | |
| struct sockaddr_l2 *a = (struct sockaddr_l2 *) addr; | |
| PyObject *addrobj = makebdaddr(&_BT_L2_MEMB(a, bdaddr)); | |
| PyObject *ret = NULL; | |
| if (addrobj) { | |
| #if defined(BDADDR_BREDR) // Linux, FreeBSD | |
| if (_BT_L2_MEMB(a, bdaddr_type) != BDADDR_BREDR) { | |
| ret = Py_BuildValue("OiiB", | |
| addrobj, | |
| _BT_L2_MEMB(a, psm), | |
| _BT_L2_MEMB(a, cid), | |
| _BT_L2_MEMB(a, bdaddr_type)); | |
| } | |
| else | |
| #endif | |
| if (_BT_L2_MEMB(a, cid) != 0) { | |
| ret = Py_BuildValue("Oii", | |
| addrobj, | |
| _BT_L2_MEMB(a, psm), | |
| _BT_L2_MEMB(a, cid)); | |
| } | |
| else { | |
| /* Retain old format for non-LE address. */ | |
| ret = Py_BuildValue("Oi", | |
| addrobj, | |
| _BT_L2_MEMB(a, psm)); | |
| } | |
| Py_DECREF(addrobj); | |
| } | |
| return ret; | |
| } | |
| #endif /* BTPROTO_L2CAP */ | |
| case BTPROTO_RFCOMM: | |
| { | |
| struct sockaddr_rc *a = (struct sockaddr_rc *) addr; | |
| PyObject *addrobj = makebdaddr(&_BT_RC_MEMB(a, bdaddr)); | |
| PyObject *ret = NULL; | |
| if (addrobj) { | |
| ret = Py_BuildValue("Oi", | |
| addrobj, | |
| _BT_RC_MEMB(a, channel)); | |
| Py_DECREF(addrobj); | |
| } | |
| return ret; | |
| } | |
| #ifdef BTPROTO_HCI | |
| case BTPROTO_HCI: | |
| { | |
| struct sockaddr_hci *a = (struct sockaddr_hci *) addr; | |
| #if defined(HAVE_BLUETOOTH_BLUETOOTH_H) | |
| PyObject *ret = NULL; | |
| if (_BT_HCI_MEMB(a, channel) == HCI_CHANNEL_RAW) { | |
| return Py_BuildValue("i", _BT_HCI_MEMB(a, dev)); | |
| } | |
| else { | |
| return Py_BuildValue("ii", | |
| _BT_HCI_MEMB(a, dev), | |
| _BT_HCI_MEMB(a, channel)); | |
| } | |
| return ret; | |
| #elif defined(__FreeBSD__) | |
| const char *node = _BT_HCI_MEMB(a, node); | |
| size_t len = strnlen(node, sizeof(_BT_HCI_MEMB(a, node))); | |
| return PyUnicode_FromStringAndSize(node, (Py_ssize_t)len); | |
| #else | |
| return makebdaddr(&_BT_HCI_MEMB(a, bdaddr)); | |
| #endif | |
| } | |
| #endif /* BTPROTO_HCI */ | |
| #ifdef BTPROTO_SCO | |
| case BTPROTO_SCO: | |
| { | |
| struct sockaddr_sco *a = (struct sockaddr_sco *) addr; | |
| return makebdaddr(&_BT_SCO_MEMB(a, bdaddr)); | |
| } | |
| #endif /* BTPROTO_SCO */ | |
| default: | |
| PyErr_SetString(PyExc_ValueError, | |
| "Unknown Bluetooth protocol"); | |
| return NULL; | |
| } | |
| #endif /* USE_BLUETOOTH */ | |
| #if defined(HAVE_NETPACKET_PACKET_H) && defined(SIOCGIFNAME) | |
| case AF_PACKET: | |
| { | |
| struct sockaddr_ll *a = (struct sockaddr_ll *)addr; | |
| const char *ifname = ""; | |
| struct ifreq ifr; | |
| /* need to look up interface name give index */ | |
| if (a->sll_ifindex) { | |
| ifr.ifr_ifindex = a->sll_ifindex; | |
| if (ioctl(sockfd, SIOCGIFNAME, &ifr) == 0) | |
| ifname = ifr.ifr_name; | |
| } | |
| return Py_BuildValue("shbhy#", | |
| ifname, | |
| ntohs(a->sll_protocol), | |
| a->sll_pkttype, | |
| a->sll_hatype, | |
| a->sll_addr, | |
| (Py_ssize_t)a->sll_halen); | |
| } | |
| #endif /* HAVE_NETPACKET_PACKET_H && SIOCGIFNAME */ | |
| #ifdef HAVE_LINUX_TIPC_H | |
| case AF_TIPC: | |
| { | |
| struct sockaddr_tipc *a = (struct sockaddr_tipc *) addr; | |
| if (a->addrtype == TIPC_ADDR_NAMESEQ) { | |
| return Py_BuildValue("IIIII", | |
| a->addrtype, | |
| a->addr.nameseq.type, | |
| a->addr.nameseq.lower, | |
| a->addr.nameseq.upper, | |
| a->scope); | |
| } else if (a->addrtype == TIPC_ADDR_NAME) { | |
| return Py_BuildValue("IIIII", | |
| a->addrtype, | |
| a->addr.name.name.type, | |
| a->addr.name.name.instance, | |
| a->addr.name.name.instance, | |
| a->scope); | |
| } else if (a->addrtype == TIPC_ADDR_ID) { | |
| return Py_BuildValue("IIIII", | |
| a->addrtype, | |
| a->addr.id.node, | |
| a->addr.id.ref, | |
| 0, | |
| a->scope); | |
| } else { | |
| PyErr_SetString(PyExc_ValueError, | |
| "Invalid address type"); | |
| return NULL; | |
| } | |
| } | |
| #endif /* HAVE_LINUX_TIPC_H */ | |
| #if defined(AF_CAN) && defined(SIOCGIFNAME) | |
| case AF_CAN: | |
| { | |
| struct sockaddr_can *a = (struct sockaddr_can *)addr; | |
| const char *ifname = ""; | |
| struct ifreq ifr; | |
| /* need to look up interface name given index */ | |
| if (a->can_ifindex) { | |
| ifr.ifr_ifindex = a->can_ifindex; | |
| if (ioctl(sockfd, SIOCGIFNAME, &ifr) == 0) | |
| ifname = ifr.ifr_name; | |
| } | |
| switch (proto) { | |
| #ifdef CAN_ISOTP | |
| case CAN_ISOTP: | |
| { | |
| return Py_BuildValue("O&kk", unicode_fsdecode, | |
| ifname, | |
| a->can_addr.tp.rx_id, | |
| a->can_addr.tp.tx_id); | |
| } | |
| #endif /* CAN_ISOTP */ | |
| #ifdef CAN_J1939 | |
| case CAN_J1939: | |
| { | |
| return Py_BuildValue("O&KIB", unicode_fsdecode, | |
| ifname, | |
| (unsigned long long)a->can_addr.j1939.name, | |
| (unsigned int)a->can_addr.j1939.pgn, | |
| a->can_addr.j1939.addr); | |
| } | |
| #endif /* CAN_J1939 */ | |
| default: | |
| { | |
| return Py_BuildValue("(O&)", unicode_fsdecode, ifname); | |
| } | |
| } | |
| } | |
| #endif /* AF_CAN && SIOCGIFNAME */ | |
| #ifdef PF_SYSTEM | |
| case PF_SYSTEM: | |
| switch(proto) { | |
| #ifdef SYSPROTO_CONTROL | |
| case SYSPROTO_CONTROL: | |
| { | |
| struct sockaddr_ctl *a = (struct sockaddr_ctl *)addr; | |
| return Py_BuildValue("(II)", a->sc_id, a->sc_unit); | |
| } | |
| #endif /* SYSPROTO_CONTROL */ | |
| default: | |
| PyErr_SetString(PyExc_ValueError, | |
| "Invalid address type"); | |
| return 0; | |
| } | |
| #endif /* PF_SYSTEM */ | |
| #ifdef HAVE_SOCKADDR_ALG | |
| case AF_ALG: | |
| { | |
| struct sockaddr_alg *a = (struct sockaddr_alg *)addr; | |
| return Py_BuildValue("s#s#HH", | |
| a->salg_type, | |
| strnlen((const char*)a->salg_type, | |
| sizeof(a->salg_type)), | |
| a->salg_name, | |
| strnlen((const char*)a->salg_name, | |
| sizeof(a->salg_name)), | |
| a->salg_feat, | |
| a->salg_mask); | |
| } | |
| #endif /* HAVE_SOCKADDR_ALG */ | |
| #ifdef HAVE_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: | |
| /* If we don't know the address family, don't raise an | |
| exception -- return it as an (int, bytes) tuple. */ | |
| return Py_BuildValue("iy#", | |
| addr->sa_family, | |
| addr->sa_data, | |
| sizeof(addr->sa_data)); | |
| } | |
| } | |
| #if defined(HAVE_BIND) || defined(HAVE_CONNECTTO) || defined(CMSG_LEN) | |
| /* Helper for getsockaddrarg: bypass IDNA for ASCII-only host names | |
| (in particular, numeric IP addresses). */ | |
| struct maybe_idna { | |
| PyObject *obj; | |
| const char *buf; | |
| }; | |
| static void | |
| idna_cleanup(struct maybe_idna *data) | |
| { | |
| Py_CLEAR(data->obj); | |
| } | |
| static int | |
| idna_converter(PyObject *obj, void *arg) | |
| { | |
| struct maybe_idna *data = (struct maybe_idna*)arg; | |
| size_t len; | |
| PyObject *obj2; | |
| if (obj == NULL) { | |
| idna_cleanup(data); | |
| return 1; | |
| } | |
| data->obj = NULL; | |
| len = -1; | |
| if (PyBytes_Check(obj)) { | |
| data->buf = PyBytes_AsString(obj); | |
| len = PyBytes_Size(obj); | |
| } | |
| else if (PyByteArray_Check(obj)) { | |
| data->buf = PyByteArray_AsString(obj); | |
| len = PyByteArray_Size(obj); | |
| } | |
| else if (PyUnicode_Check(obj)) { | |
| if (PyUnicode_IS_COMPACT_ASCII(obj)) { | |
| data->buf = PyUnicode_DATA(obj); | |
| len = PyUnicode_GET_LENGTH(obj); | |
| } | |
| else { | |
| obj2 = PyUnicode_AsEncodedString(obj, "idna", NULL); | |
| if (!obj2) { | |
| PyErr_SetString(PyExc_TypeError, "encoding of hostname failed"); | |
| return 0; | |
| } | |
| assert(PyBytes_Check(obj2)); | |
| data->obj = obj2; | |
| data->buf = PyBytes_AS_STRING(obj2); | |
| len = PyBytes_GET_SIZE(obj2); | |
| } | |
| } | |
| else { | |
| PyErr_Format(PyExc_TypeError, "str, bytes or bytearray expected, not %s", | |
| Py_TYPE(obj)->tp_name); | |
| return 0; | |
| } | |
| if (strlen(data->buf) != len) { | |
| Py_CLEAR(data->obj); | |
| PyErr_SetString(PyExc_TypeError, "host name must not contain null character"); | |
| return 0; | |
| } | |
| return Py_CLEANUP_SUPPORTED; | |
| } | |
| /* Parse a socket address argument according to the socket object's | |
| address family. Return 1 if the address was in the proper format, | |
| 0 of not. The address is returned through addr_ret, its length | |
| through len_ret. */ | |
| static int | |
| getsockaddrarg(PySocketSockObject *s, PyObject *args, | |
| sock_addr_t *addrbuf, int *len_ret, const char *caller) | |
| { | |
| switch (s->sock_family) { | |
| #if defined(AF_UNIX) | |
| case AF_UNIX: | |
| { | |
| Py_buffer path; | |
| int retval = 0; | |
| /* PEP 383. Not using PyUnicode_FSConverter since we need to | |
| allow embedded nulls on Linux. */ | |
| if (PyUnicode_Check(args)) { | |
| if ((args = PyUnicode_EncodeFSDefault(args)) == NULL) | |
| return 0; | |
| } | |
| else | |
| Py_INCREF(args); | |
| if (!PyArg_Parse(args, "y*", &path)) { | |
| Py_DECREF(args); | |
| return retval; | |
| } | |
| assert(path.len >= 0); | |
| struct sockaddr_un* addr = &addrbuf->un; | |
| memset(addr, 0, sizeof(struct sockaddr_un)); | |
| #ifdef __linux__ | |
| if (path.len == 0 || *(const char *)path.buf == 0) { | |
| /* Linux abstract namespace extension: | |
| - Empty address auto-binding to an abstract address | |
| - Address that starts with null byte */ | |
| if ((size_t)path.len > sizeof addr->sun_path) { | |
| PyErr_SetString(PyExc_OSError, | |
| "AF_UNIX path too long"); | |
| goto unix_out; | |
| } | |
| *len_ret = path.len + offsetof(struct sockaddr_un, sun_path); | |
| } | |
| else | |
| #endif /* linux */ | |
| { | |
| /* regular NULL-terminated string */ | |
| if ((size_t)path.len >= sizeof addr->sun_path) { | |
| PyErr_SetString(PyExc_OSError, | |
| "AF_UNIX path too long"); | |
| goto unix_out; | |
| } | |
| addr->sun_path[path.len] = 0; | |
| /* including the tailing NUL */ | |
| *len_ret = path.len + offsetof(struct sockaddr_un, sun_path) + 1; | |
| } | |
| addr->sun_family = s->sock_family; | |
| memcpy(addr->sun_path, path.buf, path.len); | |
| retval = 1; | |
| unix_out: | |
| PyBuffer_Release(&path); | |
| Py_DECREF(args); | |
| return retval; | |
| } | |
| #endif /* AF_UNIX */ | |
| #if defined(AF_NETLINK) | |
| case AF_NETLINK: | |
| { | |
| int pid, groups; | |
| struct sockaddr_nl* addr = &addrbuf->nl; | |
| memset(addr, 0, sizeof(struct sockaddr_nl)); | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format( | |
| PyExc_TypeError, | |
| "%s(): AF_NETLINK address must be tuple, not %.500s", | |
| caller, Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| if (!PyArg_ParseTuple(args, | |
| "II;AF_NETLINK address must be a pair " | |
| "(pid, groups)", | |
| &pid, &groups)) | |
| { | |
| return 0; | |
| } | |
| addr->nl_family = AF_NETLINK; | |
| addr->nl_pid = pid; | |
| addr->nl_groups = groups; | |
| *len_ret = sizeof(*addr); | |
| return 1; | |
| } | |
| #endif /* AF_NETLINK */ | |
| #if defined(AF_QIPCRTR) | |
| case AF_QIPCRTR: | |
| { | |
| unsigned int node, port; | |
| struct sockaddr_qrtr* addr = &addrbuf->sq; | |
| memset(addr, 0, sizeof(struct sockaddr_qrtr)); | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format( | |
| PyExc_TypeError, | |
| "getsockaddrarg: " | |
| "AF_QIPCRTR address must be tuple, not %.500s", | |
| Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| if (!PyArg_ParseTuple(args, "II:getsockaddrarg", &node, &port)) | |
| return 0; | |
| addr->sq_family = AF_QIPCRTR; | |
| addr->sq_node = node; | |
| addr->sq_port = port; | |
| *len_ret = sizeof(*addr); | |
| return 1; | |
| } | |
| #endif /* AF_QIPCRTR */ | |
| #if defined(AF_VSOCK) | |
| case AF_VSOCK: | |
| { | |
| struct sockaddr_vm* addr = &addrbuf->vm; | |
| int port, cid; | |
| memset(addr, 0, sizeof(struct sockaddr_vm)); | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format( | |
| PyExc_TypeError, | |
| "getsockaddrarg: " | |
| "AF_VSOCK address must be tuple, not %.500s", | |
| Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| if (!PyArg_ParseTuple(args, "II:getsockaddrarg", &cid, &port)) | |
| return 0; | |
| addr->svm_family = s->sock_family; | |
| addr->svm_port = port; | |
| addr->svm_cid = cid; | |
| *len_ret = sizeof(*addr); | |
| return 1; | |
| } | |
| #endif /* AF_VSOCK */ | |
| #ifdef AF_RDS | |
| case AF_RDS: | |
| /* RDS sockets use sockaddr_in */ | |
| _Py_FALLTHROUGH; | |
| #endif /* AF_RDS */ | |
| #ifdef AF_DIVERT | |
| case AF_DIVERT: | |
| /* FreeBSD divert(4) sockets use sockaddr_in */ | |
| _Py_FALLTHROUGH; | |
| #endif /* AF_DIVERT */ | |
| case AF_INET: | |
| { | |
| struct maybe_idna host = {NULL, NULL}; | |
| int port, result; | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format( | |
| PyExc_TypeError, | |
| "%s(): AF_INET address must be tuple, not %.500s", | |
| caller, Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| if (!PyArg_ParseTuple(args, | |
| "O&i;AF_INET address must be a pair " | |
| "(host, port)", | |
| idna_converter, &host, &port)) | |
| { | |
| assert(PyErr_Occurred()); | |
| if (PyErr_ExceptionMatches(PyExc_OverflowError)) { | |
| PyErr_Format(PyExc_OverflowError, | |
| "%s(): port must be 0-65535.", caller); | |
| } | |
| return 0; | |
| } | |
| struct sockaddr_in* addr = &addrbuf->in; | |
| memset(addr, 0, sizeof(struct sockaddr_in)); | |
| result = setipaddr(s->state, host.buf, (struct sockaddr *)addr, | |
| sizeof(*addr), AF_INET); | |
| idna_cleanup(&host); | |
| if (result < 0) | |
| return 0; | |
| if (port < 0 || port > 0xffff) { | |
| PyErr_Format( | |
| PyExc_OverflowError, | |
| "%s(): port must be 0-65535.", caller); | |
| return 0; | |
| } | |
| addr->sin_family = AF_INET; | |
| addr->sin_port = htons((short)port); | |
| *len_ret = sizeof *addr; | |
| return 1; | |
| } | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| { | |
| struct maybe_idna host = {NULL, NULL}; | |
| int port, result; | |
| unsigned int flowinfo, scope_id; | |
| flowinfo = scope_id = 0; | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format( | |
| PyExc_TypeError, | |
| "%s(): AF_INET6 address must be tuple, not %.500s", | |
| caller, Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| if (!PyArg_ParseTuple(args, | |
| "O&i|II;AF_INET6 address must be a tuple " | |
| "(host, port[, flowinfo[, scopeid]])", | |
| idna_converter, &host, &port, &flowinfo, | |
| &scope_id)) | |
| { | |
| assert(PyErr_Occurred()); | |
| if (PyErr_ExceptionMatches(PyExc_OverflowError)) { | |
| PyErr_Format(PyExc_OverflowError, | |
| "%s(): port must be 0-65535.", caller); | |
| } | |
| return 0; | |
| } | |
| struct sockaddr_in6* addr = &addrbuf->in6; | |
| memset(addr, 0, sizeof(struct sockaddr_in6)); | |
| result = setipaddr(s->state, host.buf, (struct sockaddr *)addr, | |
| sizeof(*addr), AF_INET6); | |
| idna_cleanup(&host); | |
| if (result < 0) | |
| return 0; | |
| if (port < 0 || port > 0xffff) { | |
| PyErr_Format( | |
| PyExc_OverflowError, | |
| "%s(): port must be 0-65535.", caller); | |
| return 0; | |
| } | |
| if (flowinfo > 0xfffff) { | |
| PyErr_Format( | |
| PyExc_OverflowError, | |
| "%s(): flowinfo must be 0-1048575.", caller); | |
| return 0; | |
| } | |
| addr->sin6_family = s->sock_family; | |
| addr->sin6_port = htons((short)port); | |
| addr->sin6_flowinfo = htonl(flowinfo); | |
| addr->sin6_scope_id = scope_id; | |
| *len_ret = sizeof *addr; | |
| return 1; | |
| } | |
| #endif /* ENABLE_IPV6 */ | |
| #ifdef USE_BLUETOOTH | |
| case AF_BLUETOOTH: | |
| { | |
| switch (s->sock_proto) { | |
| #ifdef BTPROTO_L2CAP | |
| case BTPROTO_L2CAP: | |
| { | |
| const char *straddr; | |
| struct sockaddr_l2 *addr = &addrbuf->bt_l2; | |
| memset(addr, 0, sizeof(struct sockaddr_l2)); | |
| _BT_L2_MEMB(addr, family) = AF_BLUETOOTH; | |
| unsigned short psm; | |
| #if defined(BDADDR_BREDR) // Linux, FreeBSD | |
| unsigned short cid = 0; | |
| unsigned char bdaddr_type = BDADDR_BREDR; | |
| if (!PyArg_ParseTuple(args, "sH|HB", &straddr, | |
| &psm, | |
| &cid, | |
| &bdaddr_type)) { | |
| PyErr_Format(PyExc_OSError, | |
| "%s(): wrong format", caller); | |
| return 0; | |
| } | |
| _BT_L2_MEMB(addr, bdaddr_type) = bdaddr_type; | |
| #else | |
| unsigned char cid = 0; | |
| if (!PyArg_ParseTuple(args, "sH|B", &straddr, | |
| &psm, &cid)) { | |
| PyErr_Format(PyExc_OSError, | |
| "%s(): wrong format", caller); | |
| return 0; | |
| } | |
| #endif | |
| _BT_L2_MEMB(addr, psm) = psm; | |
| _BT_L2_MEMB(addr, cid) = cid; | |
| if (setbdaddr(straddr, &_BT_L2_MEMB(addr, bdaddr)) < 0) | |
| return 0; | |
| *len_ret = sizeof *addr; | |
| return 1; | |
| } | |
| #endif /* BTPROTO_L2CAP */ | |
| case BTPROTO_RFCOMM: | |
| { | |
| const char *straddr; | |
| struct sockaddr_rc *addr = &addrbuf->bt_rc; | |
| memset(addr, 0, sizeof(struct sockaddr_rc)); | |
| _BT_RC_MEMB(addr, family) = AF_BLUETOOTH; | |
| #ifdef MS_WINDOWS | |
| unsigned long channel; | |
| # define FORMAT_CHANNEL "k" | |
| #else | |
| unsigned char channel; | |
| # define FORMAT_CHANNEL "B" | |
| #endif | |
| if (!PyArg_ParseTuple(args, "s" FORMAT_CHANNEL, | |
| &straddr, &channel)) { | |
| PyErr_Format(PyExc_OSError, "%s(): wrong format", caller); | |
| return 0; | |
| } | |
| #undef FORMAT_CHANNEL | |
| _BT_RC_MEMB(addr, channel) = channel; | |
| if (setbdaddr(straddr, &_BT_RC_MEMB(addr, bdaddr)) < 0) | |
| return 0; | |
| *len_ret = sizeof *addr; | |
| return 1; | |
| } | |
| #ifdef BTPROTO_HCI | |
| case BTPROTO_HCI: | |
| { | |
| struct sockaddr_hci *addr = &addrbuf->bt_hci; | |
| memset(addr, 0, sizeof(struct sockaddr_hci)); | |
| _BT_HCI_MEMB(addr, family) = AF_BLUETOOTH; | |
| #if defined(HAVE_BLUETOOTH_BLUETOOTH_H) | |
| unsigned short dev; | |
| unsigned short channel = HCI_CHANNEL_RAW; | |
| if (PyIndex_Check(args)) { | |
| if (!PyArg_Parse(args, "H", &dev)) { | |
| return 0; | |
| } | |
| } | |
| else if (!PyArg_ParseTuple(args, "H|H", &dev, &channel)) { | |
| PyErr_Format(PyExc_OSError, | |
| "%s(): wrong format", caller); | |
| return 0; | |
| } | |
| _BT_HCI_MEMB(addr, dev) = dev; | |
| _BT_HCI_MEMB(addr, channel) = channel; | |
| #else | |
| const char *straddr; | |
| if (!PyArg_Parse(args, "s", &straddr)) { | |
| PyErr_Format(PyExc_OSError, "%s: " | |
| "wrong format", caller); | |
| return 0; | |
| } | |
| # if defined(__FreeBSD__) | |
| if (strlen(straddr) > sizeof(_BT_HCI_MEMB(addr, node))) { | |
| PyErr_Format(PyExc_ValueError, "%s: " | |
| "node too long", caller); | |
| return 0; | |
| } | |
| strncpy(_BT_HCI_MEMB(addr, node), straddr, | |
| sizeof(_BT_HCI_MEMB(addr, node))); | |
| # else | |
| if (setbdaddr(straddr, &_BT_HCI_MEMB(addr, bdaddr)) < 0) | |
| return 0; | |
| # endif | |
| #endif | |
| *len_ret = sizeof *addr; | |
| return 1; | |
| } | |
| #endif /* BTPROTO_HCI */ | |
| #ifdef BTPROTO_SCO | |
| case BTPROTO_SCO: | |
| { | |
| const char *straddr; | |
| struct sockaddr_sco *addr = &addrbuf->bt_sco; | |
| memset(addr, 0, sizeof(struct sockaddr_sco)); | |
| _BT_SCO_MEMB(addr, family) = AF_BLUETOOTH; | |
| if (PyBytes_Check(args)) { | |
| if (!PyArg_Parse(args, "y", &straddr)) { | |
| return 0; | |
| } | |
| } | |
| else if (PyUnicode_Check(args)) { | |
| if (!PyArg_Parse(args, "s", &straddr)) { | |
| return 0; | |
| } | |
| } | |
| else { | |
| PyErr_Format(PyExc_OSError, | |
| "%s(): wrong format", caller); | |
| return 0; | |
| } | |
| if (setbdaddr(straddr, &_BT_SCO_MEMB(addr, bdaddr)) < 0) | |
| return 0; | |
| *len_ret = sizeof *addr; | |
| return 1; | |
| } | |
| #endif /* BTPROTO_SCO */ | |
| default: | |
| PyErr_Format(PyExc_OSError, | |
| "%s(): unknown Bluetooth protocol", caller); | |
| return 0; | |
| } | |
| } | |
| #endif /* USE_BLUETOOTH */ | |
| #if defined(HAVE_NETPACKET_PACKET_H) && defined(SIOCGIFINDEX) | |
| case AF_PACKET: | |
| { | |
| struct ifreq ifr; | |
| const char *interfaceName; | |
| int protoNumber; | |
| int hatype = 0; | |
| int pkttype = PACKET_HOST; | |
| Py_buffer haddr = {NULL, NULL}; | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format( | |
| PyExc_TypeError, | |
| "%s(): AF_PACKET address must be tuple, not %.500s", | |
| caller, Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| /* XXX: improve the default error message according to the | |
| documentation of AF_PACKET, which would be added as part | |
| of bpo-25041. */ | |
| if (!PyArg_ParseTuple(args, | |
| "si|iiy*;AF_PACKET address must be a tuple of " | |
| "two to five elements", | |
| &interfaceName, &protoNumber, &pkttype, &hatype, | |
| &haddr)) | |
| { | |
| assert(PyErr_Occurred()); | |
| if (PyErr_ExceptionMatches(PyExc_OverflowError)) { | |
| PyErr_Format(PyExc_OverflowError, | |
| "%s(): address argument out of range", caller); | |
| } | |
| return 0; | |
| } | |
| strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name)); | |
| ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0'; | |
| if (ioctl(get_sock_fd(s), SIOCGIFINDEX, &ifr) < 0) { | |
| s->errorhandler(); | |
| PyBuffer_Release(&haddr); | |
| return 0; | |
| } | |
| if (haddr.buf && haddr.len > 8) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "Hardware address must be 8 bytes or less"); | |
| PyBuffer_Release(&haddr); | |
| return 0; | |
| } | |
| if (protoNumber < 0 || protoNumber > 0xffff) { | |
| PyErr_Format( | |
| PyExc_OverflowError, | |
| "%s(): proto must be 0-65535.", caller); | |
| PyBuffer_Release(&haddr); | |
| return 0; | |
| } | |
| struct sockaddr_ll* addr = &addrbuf->ll; | |
| memset(addr, 0, sizeof(struct sockaddr_ll)); | |
| addr->sll_family = AF_PACKET; | |
| addr->sll_protocol = htons((short)protoNumber); | |
| addr->sll_ifindex = ifr.ifr_ifindex; | |
| addr->sll_pkttype = pkttype; | |
| addr->sll_hatype = hatype; | |
| if (haddr.buf) { | |
| memcpy(&addr->sll_addr, haddr.buf, haddr.len); | |
| addr->sll_halen = haddr.len; | |
| } | |
| else | |
| addr->sll_halen = 0; | |
| *len_ret = sizeof *addr; | |
| PyBuffer_Release(&haddr); | |
| return 1; | |
| } | |
| #endif /* HAVE_NETPACKET_PACKET_H && SIOCGIFINDEX */ | |
| #ifdef HAVE_LINUX_TIPC_H | |
| case AF_TIPC: | |
| { | |
| unsigned int atype, v1, v2, v3; | |
| unsigned int scope = TIPC_CLUSTER_SCOPE; | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format( | |
| PyExc_TypeError, | |
| "%s(): AF_TIPC address must be tuple, not %.500s", | |
| caller, Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| if (!PyArg_ParseTuple(args, | |
| "IIII|I;AF_TIPC address must be a tuple " | |
| "(addr_type, v1, v2, v3[, scope])", | |
| &atype, &v1, &v2, &v3, &scope)) | |
| { | |
| return 0; | |
| } | |
| struct sockaddr_tipc *addr = &addrbuf->tipc; | |
| memset(addr, 0, sizeof(struct sockaddr_tipc)); | |
| addr->family = AF_TIPC; | |
| addr->scope = scope; | |
| addr->addrtype = atype; | |
| if (atype == TIPC_ADDR_NAMESEQ) { | |
| addr->addr.nameseq.type = v1; | |
| addr->addr.nameseq.lower = v2; | |
| addr->addr.nameseq.upper = v3; | |
| } else if (atype == TIPC_ADDR_NAME) { | |
| addr->addr.name.name.type = v1; | |
| addr->addr.name.name.instance = v2; | |
| } else if (atype == TIPC_ADDR_ID) { | |
| addr->addr.id.node = v1; | |
| addr->addr.id.ref = v2; | |
| } else { | |
| /* Shouldn't happen */ | |
| PyErr_SetString(PyExc_TypeError, "Invalid address type"); | |
| return 0; | |
| } | |
| *len_ret = sizeof(*addr); | |
| return 1; | |
| } | |
| #endif /* HAVE_LINUX_TIPC_H */ | |
| #if defined(AF_CAN) && defined(SIOCGIFINDEX) | |
| case AF_CAN: | |
| switch (s->sock_proto) { | |
| #ifdef CAN_RAW | |
| case CAN_RAW: | |
| #ifdef CAN_BCM | |
| _Py_FALLTHROUGH; | |
| #endif | |
| #endif | |
| #ifdef CAN_BCM | |
| case CAN_BCM: | |
| #endif | |
| #if defined(CAN_RAW) || defined(CAN_BCM) | |
| { | |
| PyObject *interfaceName; | |
| struct ifreq ifr; | |
| Py_ssize_t len; | |
| struct sockaddr_can *addr = &addrbuf->can; | |
| memset(addr, 0, sizeof(struct sockaddr_can)); | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format(PyExc_TypeError, | |
| "%s(): AF_CAN address must be tuple, not %.500s", | |
| caller, Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| if (!PyArg_ParseTuple(args, | |
| "O&;AF_CAN address must be a tuple " | |
| "(interface, )", | |
| PyUnicode_FSConverter, &interfaceName)) | |
| { | |
| return 0; | |
| } | |
| len = PyBytes_GET_SIZE(interfaceName); | |
| if (len == 0) { | |
| ifr.ifr_ifindex = 0; | |
| } else if ((size_t)len < sizeof(ifr.ifr_name)) { | |
| strncpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName), sizeof(ifr.ifr_name)); | |
| ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0'; | |
| if (ioctl(get_sock_fd(s), SIOCGIFINDEX, &ifr) < 0) { | |
| s->errorhandler(); | |
| Py_DECREF(interfaceName); | |
| return 0; | |
| } | |
| } else { | |
| PyErr_SetString(PyExc_OSError, | |
| "AF_CAN interface name too long"); | |
| Py_DECREF(interfaceName); | |
| return 0; | |
| } | |
| addr->can_family = AF_CAN; | |
| addr->can_ifindex = ifr.ifr_ifindex; | |
| *len_ret = sizeof(*addr); | |
| Py_DECREF(interfaceName); | |
| return 1; | |
| } | |
| #endif /* CAN_RAW || CAN_BCM */ | |
| #ifdef CAN_ISOTP | |
| case CAN_ISOTP: | |
| { | |
| PyObject *interfaceName; | |
| struct ifreq ifr; | |
| Py_ssize_t len; | |
| unsigned long int rx_id, tx_id; | |
| struct sockaddr_can *addr = &addrbuf->can; | |
| memset(addr, 0, sizeof(struct sockaddr_can)); | |
| if (!PyArg_ParseTuple(args, "O&kk", PyUnicode_FSConverter, | |
| &interfaceName, | |
| &rx_id, | |
| &tx_id)) | |
| return 0; | |
| len = PyBytes_GET_SIZE(interfaceName); | |
| if (len == 0) { | |
| ifr.ifr_ifindex = 0; | |
| } else if ((size_t)len < sizeof(ifr.ifr_name)) { | |
| strncpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName), sizeof(ifr.ifr_name)); | |
| ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0'; | |
| if (ioctl(get_sock_fd(s), SIOCGIFINDEX, &ifr) < 0) { | |
| s->errorhandler(); | |
| Py_DECREF(interfaceName); | |
| return 0; | |
| } | |
| } else { | |
| PyErr_SetString(PyExc_OSError, | |
| "AF_CAN interface name too long"); | |
| Py_DECREF(interfaceName); | |
| return 0; | |
| } | |
| addr->can_family = AF_CAN; | |
| addr->can_ifindex = ifr.ifr_ifindex; | |
| addr->can_addr.tp.rx_id = rx_id; | |
| addr->can_addr.tp.tx_id = tx_id; | |
| *len_ret = sizeof(*addr); | |
| Py_DECREF(interfaceName); | |
| return 1; | |
| } | |
| #endif /* CAN_ISOTP */ | |
| #ifdef CAN_J1939 | |
| case CAN_J1939: | |
| { | |
| PyObject *interfaceName; | |
| struct ifreq ifr; | |
| Py_ssize_t len; | |
| unsigned long long j1939_name; /* at least 64 bits */ | |
| unsigned int j1939_pgn; /* at least 32 bits */ | |
| uint8_t j1939_addr; | |
| struct sockaddr_can *addr = &addrbuf->can; | |
| memset(addr, 0, sizeof(struct sockaddr_can)); | |
| if (!PyArg_ParseTuple(args, "O&KIB", PyUnicode_FSConverter, | |
| &interfaceName, | |
| &j1939_name, | |
| &j1939_pgn, | |
| &j1939_addr)) | |
| return 0; | |
| len = PyBytes_GET_SIZE(interfaceName); | |
| if (len == 0) { | |
| ifr.ifr_ifindex = 0; | |
| } else if ((size_t)len < sizeof(ifr.ifr_name)) { | |
| strncpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName), sizeof(ifr.ifr_name)); | |
| ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0'; | |
| if (ioctl(get_sock_fd(s), SIOCGIFINDEX, &ifr) < 0) { | |
| s->errorhandler(); | |
| Py_DECREF(interfaceName); | |
| return 0; | |
| } | |
| } else { | |
| PyErr_SetString(PyExc_OSError, | |
| "AF_CAN interface name too long"); | |
| Py_DECREF(interfaceName); | |
| return 0; | |
| } | |
| addr->can_family = AF_CAN; | |
| addr->can_ifindex = ifr.ifr_ifindex; | |
| addr->can_addr.j1939.name = (uint64_t)j1939_name; | |
| addr->can_addr.j1939.pgn = (uint32_t)j1939_pgn; | |
| addr->can_addr.j1939.addr = j1939_addr; | |
| *len_ret = sizeof(*addr); | |
| Py_DECREF(interfaceName); | |
| return 1; | |
| } | |
| #endif /* CAN_J1939 */ | |
| default: | |
| PyErr_Format(PyExc_OSError, | |
| "%s(): unsupported CAN protocol", caller); | |
| return 0; | |
| } | |
| #endif /* AF_CAN && SIOCGIFINDEX */ | |
| #ifdef PF_SYSTEM | |
| case PF_SYSTEM: | |
| switch (s->sock_proto) { | |
| #ifdef SYSPROTO_CONTROL | |
| case SYSPROTO_CONTROL: | |
| { | |
| struct sockaddr_ctl *addr = &addrbuf->ctl; | |
| memset(addr, 0, sizeof(struct sockaddr_ctl)); | |
| addr->sc_family = AF_SYSTEM; | |
| addr->ss_sysaddr = AF_SYS_CONTROL; | |
| if (PyUnicode_Check(args)) { | |
| struct ctl_info info; | |
| PyObject *ctl_name; | |
| if (!PyArg_Parse(args, "O&", | |
| PyUnicode_FSConverter, &ctl_name)) { | |
| return 0; | |
| } | |
| if (PyBytes_GET_SIZE(ctl_name) > (Py_ssize_t)sizeof(info.ctl_name)) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "provided string is too long"); | |
| Py_DECREF(ctl_name); | |
| return 0; | |
| } | |
| strncpy(info.ctl_name, PyBytes_AS_STRING(ctl_name), | |
| sizeof(info.ctl_name)); | |
| Py_DECREF(ctl_name); | |
| if (ioctl(get_sock_fd(s), CTLIOCGINFO, &info)) { | |
| PyErr_SetString(PyExc_OSError, | |
| "cannot find kernel control with provided name"); | |
| return 0; | |
| } | |
| addr->sc_id = info.ctl_id; | |
| addr->sc_unit = 0; | |
| } else if (!PyArg_ParseTuple(args, "II", | |
| &(addr->sc_id), &(addr->sc_unit))) { | |
| PyErr_Format(PyExc_TypeError, | |
| "%s(): PF_SYSTEM address must be a str or " | |
| "a pair (id, unit)", caller); | |
| return 0; | |
| } | |
| *len_ret = sizeof(*addr); | |
| return 1; | |
| } | |
| #endif /* SYSPROTO_CONTROL */ | |
| default: | |
| PyErr_Format(PyExc_OSError, | |
| "%s(): unsupported PF_SYSTEM protocol", caller); | |
| return 0; | |
| } | |
| #endif /* PF_SYSTEM */ | |
| #ifdef HAVE_SOCKADDR_ALG | |
| case AF_ALG: | |
| { | |
| const char *type; | |
| const char *name; | |
| struct sockaddr_alg *sa = &addrbuf->alg; | |
| memset(sa, 0, sizeof(*sa)); | |
| sa->salg_family = AF_ALG; | |
| if (!PyTuple_Check(args)) { | |
| PyErr_Format(PyExc_TypeError, | |
| "%s(): AF_ALG address must be tuple, not %.500s", | |
| caller, Py_TYPE(args)->tp_name); | |
| return 0; | |
| } | |
| if (!PyArg_ParseTuple(args, | |
| "ss|HH;AF_ALG address must be a tuple " | |
| "(type, name[, feat[, mask]])", | |
| &type, &name, &sa->salg_feat, &sa->salg_mask)) | |
| { | |
| return 0; | |
| } | |
| /* sockaddr_alg has fixed-sized char arrays for type, and name | |
| * both must be NULL terminated. | |
| */ | |
| if (strlen(type) >= sizeof(sa->salg_type)) { | |
| PyErr_SetString(PyExc_ValueError, "AF_ALG type too long."); | |
| return 0; | |
| } | |
| strncpy((char *)sa->salg_type, type, sizeof(sa->salg_type)); | |
| if (strlen(name) >= sizeof(sa->salg_name)) { | |
| PyErr_SetString(PyExc_ValueError, "AF_ALG name too long."); | |
| return 0; | |
| } | |
| strncpy((char *)sa->salg_name, name, sizeof(sa->salg_name)); | |
| *len_ret = sizeof(*sa); | |
| return 1; | |
| } | |
| #endif /* HAVE_SOCKADDR_ALG */ | |
| #ifdef HAVE_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 /* HAVE_AF_HYPERV */ | |
| /* More cases here... */ | |
| default: | |
| PyErr_Format(PyExc_OSError, "%s(): bad family", caller); | |
| return 0; | |
| } | |
| } | |
| #endif // defined(HAVE_BIND) || defined(HAVE_CONNECTTO) || defined(CMSG_LEN) | |
| /* Get the address length according to the socket object's address family. | |
| Return 1 if the family is known, 0 otherwise. The length is returned | |
| through len_ret. */ | |
| static int | |
| getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret) | |
| { | |
| switch (s->sock_family) { | |
| #if defined(AF_UNIX) | |
| case AF_UNIX: | |
| { | |
| *len_ret = sizeof (struct sockaddr_un); | |
| return 1; | |
| } | |
| #endif /* AF_UNIX */ | |
| #if defined(AF_NETLINK) | |
| case AF_NETLINK: | |
| { | |
| *len_ret = sizeof (struct sockaddr_nl); | |
| return 1; | |
| } | |
| #endif /* AF_NETLINK */ | |
| #if defined(AF_QIPCRTR) | |
| case AF_QIPCRTR: | |
| { | |
| *len_ret = sizeof (struct sockaddr_qrtr); | |
| return 1; | |
| } | |
| #endif /* AF_QIPCRTR */ | |
| #if defined(AF_VSOCK) | |
| case AF_VSOCK: | |
| { | |
| *len_ret = sizeof (struct sockaddr_vm); | |
| return 1; | |
| } | |
| #endif /* AF_VSOCK */ | |
| #ifdef AF_RDS | |
| case AF_RDS: | |
| /* RDS sockets use sockaddr_in */ | |
| _Py_FALLTHROUGH; | |
| #endif /* AF_RDS */ | |
| #ifdef AF_DIVERT | |
| case AF_DIVERT: | |
| /* FreeBSD divert(4) sockets use sockaddr_in: fall-through */ | |
| _Py_FALLTHROUGH; | |
| #endif /* AF_DIVERT */ | |
| case AF_INET: | |
| { | |
| *len_ret = sizeof (struct sockaddr_in); | |
| return 1; | |
| } | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| { | |
| *len_ret = sizeof (struct sockaddr_in6); | |
| return 1; | |
| } | |
| #endif /* ENABLE_IPV6 */ | |
| #ifdef USE_BLUETOOTH | |
| case AF_BLUETOOTH: | |
| { | |
| switch(s->sock_proto) | |
| { | |
| #ifdef BTPROTO_L2CAP | |
| case BTPROTO_L2CAP: | |
| *len_ret = sizeof (struct sockaddr_l2); | |
| return 1; | |
| #endif /* BTPROTO_L2CAP */ | |
| case BTPROTO_RFCOMM: | |
| *len_ret = sizeof (struct sockaddr_rc); | |
| return 1; | |
| #ifdef BTPROTO_HCI | |
| case BTPROTO_HCI: | |
| *len_ret = sizeof (struct sockaddr_hci); | |
| return 1; | |
| #endif /* BTPROTO_HCI */ | |
| #ifdef BTPROTO_SCO | |
| case BTPROTO_SCO: | |
| *len_ret = sizeof (struct sockaddr_sco); | |
| return 1; | |
| #endif /* BTPROTO_SCO */ | |
| default: | |
| PyErr_SetString(PyExc_OSError, "getsockaddrlen: " | |
| "unknown BT protocol"); | |
| return 0; | |
| } | |
| } | |
| #endif /* USE_BLUETOOTH */ | |
| #ifdef HAVE_NETPACKET_PACKET_H | |
| case AF_PACKET: | |
| { | |
| *len_ret = sizeof (struct sockaddr_ll); | |
| return 1; | |
| } | |
| #endif /* HAVE_NETPACKET_PACKET_H */ | |
| #ifdef HAVE_LINUX_TIPC_H | |
| case AF_TIPC: | |
| { | |
| *len_ret = sizeof (struct sockaddr_tipc); | |
| return 1; | |
| } | |
| #endif /* HAVE_LINUX_TIPC_H */ | |
| #ifdef AF_CAN | |
| case AF_CAN: | |
| { | |
| *len_ret = sizeof (struct sockaddr_can); | |
| return 1; | |
| } | |
| #endif /* AF_CAN */ | |
| #ifdef PF_SYSTEM | |
| case PF_SYSTEM: | |
| switch(s->sock_proto) { | |
| #ifdef SYSPROTO_CONTROL | |
| case SYSPROTO_CONTROL: | |
| *len_ret = sizeof (struct sockaddr_ctl); | |
| return 1; | |
| #endif /* SYSPROTO_CONTROL */ | |
| default: | |
| PyErr_SetString(PyExc_OSError, "getsockaddrlen: " | |
| "unknown PF_SYSTEM protocol"); | |
| return 0; | |
| } | |
| #endif /* PF_SYSTEM */ | |
| #ifdef HAVE_SOCKADDR_ALG | |
| case AF_ALG: | |
| { | |
| *len_ret = sizeof (struct sockaddr_alg); | |
| return 1; | |
| } | |
| #endif /* HAVE_SOCKADDR_ALG */ | |
| #ifdef HAVE_AF_HYPERV | |
| case AF_HYPERV: | |
| { | |
| *len_ret = sizeof (SOCKADDR_HV); | |
| return 1; | |
| } | |
| #endif /* HAVE_AF_HYPERV */ | |
| /* More cases here... */ | |
| default: | |
| PyErr_SetString(PyExc_OSError, "getsockaddrlen: bad family"); | |
| return 0; | |
| } | |
| } | |
| /* Support functions for the sendmsg() and recvmsg[_into]() methods. | |
| Currently, these methods are only compiled if the RFC 2292/3542 | |
| CMSG_LEN() macro is available. Older systems seem to have used | |
| sizeof(struct cmsghdr) + (length) where CMSG_LEN() is used now, so | |
| it may be possible to define CMSG_LEN() that way if it's not | |
| provided. Some architectures might need extra padding after the | |
| cmsghdr, however, and CMSG_LEN() would have to take account of | |
| this. */ | |
| #ifdef CMSG_LEN | |
| /* If length is in range, set *result to CMSG_LEN(length) and return | |
| true; otherwise, return false. */ | |
| static int | |
| get_CMSG_LEN(size_t length, size_t *result) | |
| { | |
| size_t tmp; | |
| if (length > (SOCKLEN_T_LIMIT - CMSG_LEN(0))) | |
| return 0; | |
| tmp = CMSG_LEN(length); | |
| if (tmp > SOCKLEN_T_LIMIT || tmp < length) | |
| return 0; | |
| *result = tmp; | |
| return 1; | |
| } | |
| #ifdef CMSG_SPACE | |
| /* If length is in range, set *result to CMSG_SPACE(length) and return | |
| true; otherwise, return false. */ | |
| static int | |
| get_CMSG_SPACE(size_t length, size_t *result) | |
| { | |
| size_t tmp; | |
| /* Use CMSG_SPACE(1) here in order to take account of the padding | |
| necessary before *and* after the data. */ | |
| if (length > (SOCKLEN_T_LIMIT - CMSG_SPACE(1))) | |
| return 0; | |
| tmp = CMSG_SPACE(length); | |
| if (tmp > SOCKLEN_T_LIMIT || tmp < length) | |
| return 0; | |
| *result = tmp; | |
| return 1; | |
| } | |
| #endif | |
| /* Return true iff msg->msg_controllen is valid, cmsgh is a valid | |
| pointer in msg->msg_control with at least "space" bytes after it, | |
| and its cmsg_len member inside the buffer. */ | |
| static int | |
| cmsg_min_space(struct msghdr *msg, struct cmsghdr *cmsgh, size_t space) | |
| { | |
| size_t cmsg_offset; | |
| static const size_t cmsg_len_end = (offsetof(struct cmsghdr, cmsg_len) + | |
| sizeof(cmsgh->cmsg_len)); | |
| /* Note that POSIX allows msg_controllen to be of signed type. */ | |
| if (cmsgh == NULL || msg->msg_control == NULL) | |
| return 0; | |
| /* Note that POSIX allows msg_controllen to be of a signed type. This is | |
| annoying under OS X as it's unsigned there and so it triggers a | |
| tautological comparison warning under Clang when compared against 0. | |
| Since the check is valid on other platforms, silence the warning under | |
| Clang. */ | |
| #ifdef __clang__ | |
| #pragma clang diagnostic push | |
| #pragma clang diagnostic ignored "-Wtautological-compare" | |
| #endif | |
| #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))) | |
| #pragma GCC diagnostic push | |
| #pragma GCC diagnostic ignored "-Wtype-limits" | |
| #endif | |
| if (msg->msg_controllen < 0) | |
| return 0; | |
| #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))) | |
| #pragma GCC diagnostic pop | |
| #endif | |
| #ifdef __clang__ | |
| #pragma clang diagnostic pop | |
| #endif | |
| if (space < cmsg_len_end) | |
| space = cmsg_len_end; | |
| cmsg_offset = (char *)cmsgh - (char *)msg->msg_control; | |
| return (cmsg_offset <= (size_t)-1 - space && | |
| cmsg_offset + space <= msg->msg_controllen); | |
| } | |
| /* If pointer CMSG_DATA(cmsgh) is in buffer msg->msg_control, set | |
| *space to number of bytes following it in the buffer and return | |
| true; otherwise, return false. Assumes cmsgh, msg->msg_control and | |
| msg->msg_controllen are valid. */ | |
| static int | |
| get_cmsg_data_space(struct msghdr *msg, struct cmsghdr *cmsgh, size_t *space) | |
| { | |
| size_t data_offset; | |
| char *data_ptr; | |
| if ((data_ptr = (char *)CMSG_DATA(cmsgh)) == NULL) | |
| return 0; | |
| data_offset = data_ptr - (char *)msg->msg_control; | |
| if (data_offset > msg->msg_controllen) | |
| return 0; | |
| *space = msg->msg_controllen - data_offset; | |
| return 1; | |
| } | |
| /* If cmsgh is invalid or not contained in the buffer pointed to by | |
| msg->msg_control, return -1. If cmsgh is valid and its associated | |
| data is entirely contained in the buffer, set *data_len to the | |
| length of the associated data and return 0. If only part of the | |
| associated data is contained in the buffer but cmsgh is otherwise | |
| valid, set *data_len to the length contained in the buffer and | |
| return 1. */ | |
| static int | |
| get_cmsg_data_len(struct msghdr *msg, struct cmsghdr *cmsgh, size_t *data_len) | |
| { | |
| size_t space, cmsg_data_len; | |
| if (!cmsg_min_space(msg, cmsgh, CMSG_LEN(0)) || | |
| cmsgh->cmsg_len < CMSG_LEN(0)) | |
| return -1; | |
| cmsg_data_len = cmsgh->cmsg_len - CMSG_LEN(0); | |
| if (!get_cmsg_data_space(msg, cmsgh, &space)) | |
| return -1; | |
| if (space >= cmsg_data_len) { | |
| *data_len = cmsg_data_len; | |
| return 0; | |
| } | |
| *data_len = space; | |
| return 1; | |
| } | |
| #endif /* CMSG_LEN */ | |
| struct sock_accept { | |
| socklen_t *addrlen; | |
| sock_addr_t *addrbuf; | |
| SOCKET_T result; | |
| }; | |
| #if defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4) | |
| static int | |
| sock_accept_impl(PySocketSockObject *s, void *data) | |
| { | |
| struct sock_accept *ctx = data; | |
| struct sockaddr *addr = SAS2SA(ctx->addrbuf); | |
| socklen_t *paddrlen = ctx->addrlen; | |
| #ifdef HAVE_SOCKADDR_ALG | |
| /* AF_ALG does not support accept() with addr and raises | |
| * ECONNABORTED instead. */ | |
| if (s->sock_family == AF_ALG) { | |
| addr = NULL; | |
| paddrlen = NULL; | |
| *ctx->addrlen = 0; | |
| } | |
| #endif | |
| #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) | |
| if (_Py_atomic_load_int_relaxed(&accept4_works) != 0) { | |
| ctx->result = accept4(get_sock_fd(s), addr, paddrlen, | |
| SOCK_CLOEXEC); | |
| if (ctx->result == INVALID_SOCKET && _Py_atomic_load_int_relaxed(&accept4_works) == -1) { | |
| /* On Linux older than 2.6.28, accept4() fails with ENOSYS */ | |
| _Py_atomic_store_int_relaxed(&accept4_works, errno != ENOSYS); | |
| } | |
| } | |
| if (_Py_atomic_load_int_relaxed(&accept4_works) == 0) | |
| ctx->result = accept(get_sock_fd(s), addr, paddrlen); | |
| #else | |
| ctx->result = accept(get_sock_fd(s), addr, paddrlen); | |
| #endif | |
| #ifdef MS_WINDOWS | |
| return (ctx->result != INVALID_SOCKET); | |
| #else | |
| return (ctx->result >= 0); | |
| #endif | |
| } | |
| /* s._accept() -> (fd, address) */ | |
| /*[clinic input] | |
| _socket.socket._accept | |
| self as s: self(type="PySocketSockObject *") | |
| Wait for an incoming connection. | |
| Return a new socket file descriptor representing the connection, and | |
| the address of the client. For IP sockets, the address info is a | |
| pair (hostaddr, port). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket__accept_impl(PySocketSockObject *s) | |
| /*[clinic end generated code: output=d24eca9a1d4c988e input=07959cdbb2f2a387]*/ | |
| { | |
| sock_addr_t addrbuf; | |
| SOCKET_T newfd; | |
| socklen_t addrlen; | |
| PyObject *sock = NULL; | |
| PyObject *addr = NULL; | |
| struct sock_accept ctx; | |
| if (!getsockaddrlen(s, &addrlen)) | |
| return NULL; | |
| memset(&addrbuf, 0, addrlen); | |
| if (!IS_SELECTABLE(s)) | |
| return select_error(); | |
| ctx.addrlen = &addrlen; | |
| ctx.addrbuf = &addrbuf; | |
| ctx.result = INVALID_SOCKET; | |
| if (sock_call(s, 0, sock_accept_impl, &ctx) < 0) | |
| return NULL; | |
| newfd = ctx.result; | |
| #ifdef MS_WINDOWS | |
| #if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) | |
| #ifndef HANDLE_FLAG_INHERIT | |
| #define HANDLE_FLAG_INHERIT 0x00000001 | |
| #endif | |
| if (!SetHandleInformation((HANDLE)newfd, HANDLE_FLAG_INHERIT, 0)) { | |
| PyErr_SetFromWindowsErr(0); | |
| SOCKETCLOSE(newfd); | |
| goto error; | |
| } | |
| #endif | |
| #else | |
| #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) | |
| if (!_Py_atomic_load_int_relaxed(&accept4_works)) | |
| #endif | |
| { | |
| if (_Py_set_inheritable(newfd, 0, NULL) < 0) { | |
| SOCKETCLOSE(newfd); | |
| goto error; | |
| } | |
| } | |
| #endif | |
| sock = PyLong_FromSocket_t(newfd); | |
| if (sock == NULL) { | |
| SOCKETCLOSE(newfd); | |
| goto error; | |
| } | |
| addr = makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), | |
| addrlen, s->sock_proto); | |
| if (addr == NULL) | |
| goto error; | |
| return _PyTuple_FromPairSteal(sock, addr); | |
| error: | |
| Py_XDECREF(sock); | |
| Py_XDECREF(addr); | |
| return NULL; | |
| } | |
| #endif // defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4) | |
| /* s.setblocking(flag) method. Argument: | |
| False -- non-blocking mode; same as settimeout(0) | |
| True -- blocking mode; same as settimeout(None) | |
| */ | |
| /*[clinic input] | |
| _socket.socket.setblocking | |
| self as s: self(type="PySocketSockObject *") | |
| flag: bool | |
| / | |
| Set the socket to blocking (flag is true) or non-blocking (false). | |
| setblocking(True) is equivalent to settimeout(None); | |
| setblocking(False) is equivalent to settimeout(0.0). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_setblocking_impl(PySocketSockObject *s, int flag) | |
| /*[clinic end generated code: output=0d27b1c391538401 input=bfc2c8564d8b67f6]*/ | |
| { | |
| s->sock_timeout = _PyTime_FromSeconds(flag ? -1 : 0); | |
| if (internal_setblocking(s, flag) == -1) { | |
| return NULL; | |
| } | |
| Py_RETURN_NONE; | |
| } | |
| /* s.getblocking() method. | |
| Returns True if socket is in blocking mode, | |
| False if it is in non-blocking mode. | |
| */ | |
| /*[clinic input] | |
| _socket.socket.getblocking | |
| self as s: self(type="PySocketSockObject *") | |
| Return True if socket is in blocking mode, False if in non-blocking. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_getblocking_impl(PySocketSockObject *s) | |
| /*[clinic end generated code: output=e760d93dae8b6ef7 input=13dfb70bc40c3cf8]*/ | |
| { | |
| if (s->sock_timeout) { | |
| Py_RETURN_TRUE; | |
| } | |
| else { | |
| Py_RETURN_FALSE; | |
| } | |
| } | |
| static int | |
| socket_parse_timeout(PyTime_t *timeout, PyObject *timeout_obj) | |
| { | |
| #ifdef MS_WINDOWS | |
| struct timeval tv; | |
| #endif | |
| #ifndef HAVE_POLL | |
| PyTime_t ms; | |
| #endif | |
| int overflow = 0; | |
| if (timeout_obj == Py_None) { | |
| *timeout = _PyTime_FromSeconds(-1); | |
| return 0; | |
| } | |
| if (_PyTime_FromSecondsObject(timeout, | |
| timeout_obj, _PyTime_ROUND_TIMEOUT) < 0) | |
| return -1; | |
| if (*timeout < 0) { | |
| PyErr_SetString(PyExc_ValueError, "Timeout value out of range"); | |
| return -1; | |
| } | |
| #ifdef MS_WINDOWS | |
| overflow |= (_PyTime_AsTimeval(*timeout, &tv, _PyTime_ROUND_TIMEOUT) < 0); | |
| #endif | |
| #ifndef HAVE_POLL | |
| ms = _PyTime_AsMilliseconds(*timeout, _PyTime_ROUND_TIMEOUT); | |
| overflow |= (ms > INT_MAX); | |
| #endif | |
| if (overflow) { | |
| PyErr_SetString(PyExc_OverflowError, | |
| "timeout doesn't fit into C timeval"); | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| /* s.settimeout(timeout) method. Argument: | |
| None -- no timeout, blocking mode; same as setblocking(True) | |
| 0.0 -- non-blocking mode; same as setblocking(False) | |
| > 0 -- timeout mode; operations time out after timeout seconds | |
| < 0 -- illegal; raises an exception | |
| */ | |
| /*[clinic input] | |
| _socket.socket.settimeout | |
| self as s: self(type="PySocketSockObject *") | |
| timeout as arg: object | |
| / | |
| Set a timeout on socket operations. | |
| 'timeout' can be a float, giving in seconds, or None. Setting a | |
| timeout of None disables the timeout feature and is equivalent to | |
| setblocking(1). Setting a timeout of zero is the same as | |
| setblocking(0). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_settimeout_impl(PySocketSockObject *s, PyObject *arg) | |
| /*[clinic end generated code: output=5e57e2e1cba1c234 input=08bc8324b9fdb3f9]*/ | |
| { | |
| PyTime_t timeout; | |
| if (socket_parse_timeout(&timeout, arg) < 0) | |
| return NULL; | |
| s->sock_timeout = timeout; | |
| int block = timeout < 0; | |
| /* Blocking mode for a Python socket object means that operations | |
| like :meth:`recv` or :meth:`sendall` will block the execution of | |
| the current thread until they are complete or aborted with a | |
| `TimeoutError` or `socket.error` errors. When timeout is `None`, | |
| the underlying FD is in a blocking mode. When timeout is a positive | |
| number, the FD is in a non-blocking mode, and socket ops are | |
| implemented with a `select()` call. | |
| When timeout is 0.0, the FD is in a non-blocking mode. | |
| This table summarizes all states in which the socket object and | |
| its underlying FD can be: | |
| ==================== ===================== ============== | |
| `gettimeout()` `getblocking()` FD | |
| ==================== ===================== ============== | |
| ``None`` ``True`` blocking | |
| ``0.0`` ``False`` non-blocking | |
| ``> 0`` ``True`` non-blocking | |
| */ | |
| if (internal_setblocking(s, block) == -1) { | |
| return NULL; | |
| } | |
| Py_RETURN_NONE; | |
| } | |
| /* s.gettimeout() method. | |
| Returns the timeout associated with a socket. */ | |
| static PyObject * | |
| sock_gettimeout_impl(PyObject *self, void *Py_UNUSED(ignored)) | |
| { | |
| PySocketSockObject *s = _PySocketSockObject_CAST(self); | |
| if (s->sock_timeout < 0) { | |
| Py_RETURN_NONE; | |
| } | |
| else { | |
| double seconds = PyTime_AsSecondsDouble(s->sock_timeout); | |
| return PyFloat_FromDouble(seconds); | |
| } | |
| } | |
| /*[clinic input] | |
| _socket.socket.gettimeout | |
| Return the timeout in seconds (float) of socket operations. | |
| A timeout of None indicates that timeouts on socket operations are | |
| disabled. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_gettimeout_impl(PySocketSockObject *self) | |
| /*[clinic end generated code: output=cd49b7758a504532 input=47e7c5bf80e26eaa]*/ | |
| { | |
| return sock_gettimeout_impl((PyObject *)self, NULL); | |
| } | |
| static inline PyObject * | |
| sock_gettimeout_getter(PyObject *self, void *Py_UNUSED(closure)) | |
| { | |
| return sock_gettimeout_impl(self, NULL); | |
| } | |
| #ifdef HAVE_SETSOCKOPT | |
| /* s.setsockopt() method. | |
| With an integer third argument, sets an integer optval with optlen=4. | |
| With None as third argument and an integer fourth argument, set | |
| optval=NULL with unsigned int as optlen. | |
| With a string third argument, sets an option from a buffer; | |
| use optional built-in module 'struct' to encode the string. | |
| */ | |
| static PyObject * | |
| sock_setsockopt(PyObject *self, PyObject *args) | |
| { | |
| PySocketSockObject *s = _PySocketSockObject_CAST(self); | |
| Py_ssize_t arglen; | |
| int level; | |
| int optname; | |
| int res; | |
| Py_buffer buffer; | |
| int flag; | |
| unsigned int optlen; | |
| PyObject *optval; | |
| if (!PyArg_ParseTuple(args, "iiO|I:setsockopt", | |
| &level, &optname, &optval, &optlen)) | |
| { | |
| return NULL; | |
| } | |
| arglen = PyTuple_Size(args); | |
| if (arglen == 3 && optval == Py_None) { | |
| PyErr_Format(PyExc_TypeError, | |
| "setsockopt() requires 4 arguments when the third argument is None"); | |
| return NULL; | |
| } | |
| if (arglen == 4 && optval != Py_None) { | |
| PyErr_Format(PyExc_TypeError, | |
| "setsockopt() only takes 4 arguments when the third argument is None (got %T)", | |
| optval); | |
| return NULL; | |
| } | |
| #ifdef AF_VSOCK | |
| if (s->sock_family == AF_VSOCK) { | |
| uint64_t vflag; // Must be set width of 64 bits | |
| /* setsockopt(level, opt, flag) */ | |
| if (!PyArg_Parse(optval, "K", &vflag)) { | |
| return NULL; | |
| } | |
| // level should always be set to AF_VSOCK | |
| res = setsockopt(get_sock_fd(s), level, optname, | |
| (void*)&vflag, sizeof vflag); | |
| goto done; | |
| } | |
| #endif | |
| /* setsockopt(level, opt, flag) */ | |
| if (PyIndex_Check(optval)) { | |
| if (!PyArg_Parse(optval, "i", &flag)) { | |
| return NULL; | |
| } | |
| #ifdef MS_WINDOWS | |
| if (optname == SIO_TCP_SET_ACK_FREQUENCY) { | |
| DWORD dummy; | |
| res = WSAIoctl(get_sock_fd(s), SIO_TCP_SET_ACK_FREQUENCY, &flag, | |
| sizeof(flag), NULL, 0, &dummy, NULL, NULL); | |
| if (res >= 0) { | |
| s->quickack = flag; | |
| } | |
| goto done; | |
| } | |
| #endif | |
| res = setsockopt(get_sock_fd(s), level, optname, | |
| (char*)&flag, sizeof flag); | |
| goto done; | |
| } | |
| /* setsockopt(level, opt, None, optlen) */ | |
| if (optval == Py_None) { | |
| assert(sizeof(socklen_t) >= sizeof(unsigned int)); | |
| res = setsockopt(get_sock_fd(s), level, optname, | |
| NULL, (socklen_t)optlen); | |
| goto done; | |
| } | |
| /* setsockopt(level, opt, buffer) */ | |
| if (PyObject_CheckBuffer(optval)) { | |
| if (!PyArg_Parse(optval, "y*", &buffer)) { | |
| return NULL; | |
| } | |
| #ifdef MS_WINDOWS | |
| if (buffer.len > INT_MAX) { | |
| PyBuffer_Release(&buffer); | |
| PyErr_Format(PyExc_OverflowError, | |
| "socket option is larger than %i bytes", | |
| INT_MAX); | |
| return NULL; | |
| } | |
| res = setsockopt(get_sock_fd(s), level, optname, | |
| buffer.buf, (int)buffer.len); | |
| #else | |
| res = setsockopt(get_sock_fd(s), level, optname, buffer.buf, buffer.len); | |
| #endif | |
| PyBuffer_Release(&buffer); | |
| goto done; | |
| } | |
| PyErr_Format(PyExc_TypeError, | |
| "socket option should be int, bytes-like object or None (got %T)", | |
| optval); | |
| return NULL; | |
| done: | |
| if (res < 0) { | |
| return s->errorhandler(); | |
| } | |
| Py_RETURN_NONE; | |
| } | |
| PyDoc_STRVAR(setsockopt_doc, | |
| "setsockopt(level, option, value: int)\n\ | |
| setsockopt(level, option, value: buffer)\n\ | |
| setsockopt(level, option, None, optlen: int)\n\ | |
| \n\ | |
| Set a socket option. See the Unix manual for level and option.\n\ | |
| The value argument can either be an integer, a string buffer, or\n\ | |
| None, optlen."); | |
| #endif | |
| /* s.getsockopt() method. | |
| With two arguments, retrieves an integer option. | |
| With a third integer argument, retrieves a string buffer of that size; | |
| use optional built-in module 'struct' to decode the string. */ | |
| /*[clinic input] | |
| _socket.socket.getsockopt | |
| self as s: self(type="PySocketSockObject *") | |
| level: int | |
| option as optname: int | |
| buffersize as buflen: int = 0 | |
| / | |
| Get a socket option. | |
| See the Unix manual for level and option. If a nonzero buffersize | |
| argument is given, the return value is a bytes object of that | |
| length; otherwise it is an integer. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_getsockopt_impl(PySocketSockObject *s, int level, int optname, | |
| int buflen) | |
| /*[clinic end generated code: output=0b397d1e2237a512 input=1a586fad20b3c3fa]*/ | |
| { | |
| int res; | |
| int flag = 0; | |
| socklen_t flagsize; | |
| if (buflen == 0) { | |
| #ifdef AF_VSOCK | |
| if (s->sock_family == AF_VSOCK) { | |
| uint64_t vflag = 0; // Must be set width of 64 bits | |
| flagsize = sizeof vflag; | |
| res = getsockopt(get_sock_fd(s), level, optname, | |
| (void *)&vflag, &flagsize); | |
| if (res < 0) | |
| return s->errorhandler(); | |
| return PyLong_FromUnsignedLong(vflag); | |
| } | |
| #endif | |
| #ifdef MS_WINDOWS | |
| if (optname == SIO_TCP_SET_ACK_FREQUENCY) { | |
| return PyLong_FromLong(s->quickack); | |
| } | |
| #endif | |
| flagsize = sizeof flag; | |
| res = getsockopt(get_sock_fd(s), level, optname, | |
| (void *)&flag, &flagsize); | |
| if (res < 0) | |
| return s->errorhandler(); | |
| return PyLong_FromLong(flag); | |
| } | |
| #ifdef AF_VSOCK | |
| if (s->sock_family == AF_VSOCK) { | |
| PyErr_SetString(PyExc_OSError, | |
| "getsockopt string buffer not allowed"); | |
| return NULL; | |
| } | |
| #endif | |
| if (buflen <= 0 || buflen > 1024) { | |
| PyErr_SetString(PyExc_OSError, | |
| "getsockopt buflen out of range"); | |
| return NULL; | |
| } | |
| PyBytesWriter *writer = PyBytesWriter_Create(buflen); | |
| if (writer == NULL) { | |
| return NULL; | |
| } | |
| socklen_t optlen = buflen; | |
| res = getsockopt(get_sock_fd(s), level, optname, | |
| PyBytesWriter_GetData(writer), &optlen); | |
| if (res < 0) { | |
| PyBytesWriter_Discard(writer); | |
| return s->errorhandler(); | |
| } | |
| return PyBytesWriter_FinishWithSize(writer, optlen); | |
| } | |
| #ifdef HAVE_BIND | |
| /* s.bind(sockaddr) method */ | |
| /*[clinic input] | |
| _socket.socket.bind | |
| self as s: self(type="PySocketSockObject *") | |
| address as addro: object | |
| / | |
| Bind the socket to a local address. | |
| For IP sockets, the address is a pair (host, port); the host must | |
| refer to the local host. For raw packet sockets the address is a | |
| tuple (ifname, proto [,pkttype [,hatype [,addr]]]). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_bind_impl(PySocketSockObject *s, PyObject *addro) | |
| /*[clinic end generated code: output=b8d74d0184a9f187 input=ee3f536adbaaa1cb]*/ | |
| { | |
| sock_addr_t addrbuf; | |
| int addrlen; | |
| int res; | |
| if (!getsockaddrarg(s, addro, &addrbuf, &addrlen, "bind")) { | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.bind", "OO", s, addro) < 0) { | |
| return NULL; | |
| } | |
| Py_BEGIN_ALLOW_THREADS | |
| res = bind(get_sock_fd(s), SAS2SA(&addrbuf), addrlen); | |
| Py_END_ALLOW_THREADS | |
| if (res < 0) | |
| return s->errorhandler(); | |
| Py_RETURN_NONE; | |
| } | |
| #endif | |
| /* s.close() method. | |
| Set the file descriptor to -1 so operations tried subsequently | |
| will surely fail. */ | |
| /*[clinic input] | |
| _socket.socket.close | |
| self as s: self(type="PySocketSockObject *") | |
| close() | |
| Close the socket. It cannot be used after this call. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_close_impl(PySocketSockObject *s) | |
| /*[clinic end generated code: output=038b2418e07f6f6c input=dc487e470e55a83c]*/ | |
| { | |
| SOCKET_T fd; | |
| int res; | |
| fd = get_sock_fd(s); | |
| if (fd != INVALID_SOCKET) { | |
| set_sock_fd(s, INVALID_SOCKET); | |
| /* We do not want to retry upon EINTR: see | |
| http://lwn.net/Articles/576478/ and | |
| http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html | |
| for more details. */ | |
| Py_BEGIN_ALLOW_THREADS | |
| res = SOCKETCLOSE(fd); | |
| Py_END_ALLOW_THREADS | |
| /* bpo-30319: The peer can already have closed the connection. | |
| Python ignores ECONNRESET on close(). */ | |
| if (res < 0 && errno != ECONNRESET) { | |
| return s->errorhandler(); | |
| } | |
| } | |
| Py_RETURN_NONE; | |
| } | |
| /*[clinic input] | |
| _socket.socket.detach | |
| self as s: self(type="PySocketSockObject *") | |
| Close the socket object without closing the file descriptor. | |
| The object cannot be used after this call, but the file descriptor | |
| can be reused for other purposes. The file descriptor is returned. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_detach_impl(PySocketSockObject *s) | |
| /*[clinic end generated code: output=769cc72d7fdddebd input=ee1305f0594b88cc]*/ | |
| { | |
| SOCKET_T fd = get_sock_fd(s); | |
| set_sock_fd(s, INVALID_SOCKET); | |
| return PyLong_FromSocket_t(fd); | |
| } | |
| #ifdef HAVE_CONNECT | |
| static int | |
| sock_connect_impl(PySocketSockObject *s, void* Py_UNUSED(data)) | |
| { | |
| int err; | |
| socklen_t size = sizeof err; | |
| if (getsockopt(get_sock_fd(s), SOL_SOCKET, SO_ERROR, (void *)&err, &size)) { | |
| /* getsockopt() failed */ | |
| return 0; | |
| } | |
| if (err == EISCONN) | |
| return 1; | |
| if (err != 0) { | |
| /* sock_call_ex() uses GET_SOCK_ERROR() to get the error code */ | |
| SET_SOCK_ERROR(err); | |
| return 0; | |
| } | |
| return 1; | |
| } | |
| /* Common functionality for socket.connect and socket.connect_ex. | |
| * | |
| * If *raise* is set: | |
| * - On success, return 0. | |
| * - On any failure, return -1 with an exception set. | |
| * If *raise* is zero: | |
| * - On success, return 0. | |
| * - On connect() failure, return errno (without an exception set) | |
| * - On other error, return -1 with an exception set. | |
| * | |
| * Note that -1 is a valid errno value on some systems. | |
| */ | |
| static int | |
| internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, | |
| int raise) | |
| { | |
| int res, err, wait_connect; | |
| Py_BEGIN_ALLOW_THREADS | |
| res = connect(get_sock_fd(s), addr, addrlen); | |
| Py_END_ALLOW_THREADS | |
| if (!res) { | |
| /* connect() succeeded, the socket is connected */ | |
| return 0; | |
| } | |
| /* connect() failed */ | |
| /* save error, PyErr_CheckSignals() can replace it */ | |
| err = GET_SOCK_ERROR; | |
| if (CHECK_ERRNO(EINTR)) { | |
| if (PyErr_CheckSignals()) | |
| return -1; | |
| /* Issue #23618: when connect() fails with EINTR, the connection is | |
| running asynchronously. | |
| If the socket is blocking or has a timeout, wait until the | |
| connection completes, fails or timed out using select(), and then | |
| get the connection status using getsockopt(SO_ERROR). | |
| If the socket is non-blocking, raise InterruptedError. The caller is | |
| responsible to wait until the connection completes, fails or timed | |
| out (it's the case in asyncio for example). */ | |
| wait_connect = (s->sock_timeout != 0 && IS_SELECTABLE(s)); | |
| } | |
| else { | |
| wait_connect = (s->sock_timeout > 0 && err == SOCK_INPROGRESS_ERR | |
| && IS_SELECTABLE(s)); | |
| } | |
| if (!wait_connect) { | |
| if (raise) { | |
| /* restore error, maybe replaced by PyErr_CheckSignals() */ | |
| SET_SOCK_ERROR(err); | |
| s->errorhandler(); | |
| return -1; | |
| } | |
| else | |
| return err; | |
| } | |
| if (raise) { | |
| /* socket.connect() raises an exception on error */ | |
| if (sock_call_ex(s, 1, sock_connect_impl, NULL, | |
| 1, NULL, s->sock_timeout) < 0) | |
| return -1; | |
| } | |
| else { | |
| /* socket.connect_ex() returns the error code on error */ | |
| if (sock_call_ex(s, 1, sock_connect_impl, NULL, | |
| 1, &err, s->sock_timeout) < 0) | |
| return err; | |
| } | |
| return 0; | |
| } | |
| /* s.connect(sockaddr) method */ | |
| /*[clinic input] | |
| _socket.socket.connect | |
| self as s: self(type="PySocketSockObject *") | |
| address as addro: object | |
| / | |
| Connect the socket to a remote address. | |
| For IP sockets, the address is a pair (host, port). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_connect_impl(PySocketSockObject *s, PyObject *addro) | |
| /*[clinic end generated code: output=d4f73817eb43ed12 input=1b7c601416490538]*/ | |
| { | |
| sock_addr_t addrbuf; | |
| int addrlen; | |
| int res; | |
| if (!getsockaddrarg(s, addro, &addrbuf, &addrlen, "connect")) { | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.connect", "OO", s, addro) < 0) { | |
| return NULL; | |
| } | |
| res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 1); | |
| if (res < 0) { | |
| assert(PyErr_Occurred()); | |
| return NULL; | |
| } | |
| Py_RETURN_NONE; | |
| } | |
| /* s.connect_ex(sockaddr) method */ | |
| /*[clinic input] | |
| _socket.socket.connect_ex | |
| self as s: self(type="PySocketSockObject *") | |
| address as addro: object | |
| / | |
| Connect the socket to a remote address. | |
| This is like connect(address), but returns an error code (the errno | |
| value) instead of raising an exception when an error occurs. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_connect_ex_impl(PySocketSockObject *s, PyObject *addro) | |
| /*[clinic end generated code: output=bc8b7cdf80e419af input=716f3a78a296d7ca]*/ | |
| { | |
| sock_addr_t addrbuf; | |
| int addrlen; | |
| int res; | |
| if (!getsockaddrarg(s, addro, &addrbuf, &addrlen, "connect_ex")) { | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.connect", "OO", s, addro) < 0) { | |
| return NULL; | |
| } | |
| res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 0); | |
| if (res == -1 && PyErr_Occurred()) { | |
| return NULL; | |
| } | |
| return PyLong_FromLong((long) res); | |
| } | |
| #endif // HAVE_CONNECT | |
| /* s.fileno() method */ | |
| /*[clinic input] | |
| _socket.socket.fileno | |
| self as s: self(type="PySocketSockObject *") | |
| Return the integer file descriptor of the socket. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_fileno_impl(PySocketSockObject *s) | |
| /*[clinic end generated code: output=6d422560f508d2c6 input=7f817a2413c3c37c]*/ | |
| { | |
| return PyLong_FromSocket_t(get_sock_fd(s)); | |
| } | |
| #ifdef HAVE_GETSOCKNAME | |
| /* s.getsockname() method */ | |
| /*[clinic input] | |
| _socket.socket.getsockname | |
| self as s: self(type="PySocketSockObject *") | |
| Return the address of the local endpoint. | |
| The format depends on the address family. For IPv4 sockets, the | |
| address info is a pair (hostaddr, port). For IPv6 sockets, the | |
| address info is a 4-tuple (hostaddr, port, flowinfo, scope_id). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_getsockname_impl(PySocketSockObject *s) | |
| /*[clinic end generated code: output=b4c94874b6bf20ed input=b6628802847b2eef]*/ | |
| { | |
| sock_addr_t addrbuf; | |
| int res; | |
| socklen_t addrlen; | |
| if (!getsockaddrlen(s, &addrlen)) | |
| return NULL; | |
| memset(&addrbuf, 0, addrlen); | |
| Py_BEGIN_ALLOW_THREADS | |
| res = getsockname(get_sock_fd(s), SAS2SA(&addrbuf), &addrlen); | |
| Py_END_ALLOW_THREADS | |
| if (res < 0) | |
| return s->errorhandler(); | |
| return makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen, | |
| s->sock_proto); | |
| } | |
| #endif | |
| #ifdef HAVE_GETPEERNAME /* Cray APP doesn't have this :-( */ | |
| /* s.getpeername() method */ | |
| /*[clinic input] | |
| _socket.socket.getpeername | |
| self as s: self(type="PySocketSockObject *") | |
| Return the address of the remote endpoint. | |
| For IP sockets, the address info is a pair (hostaddr, port). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_getpeername_impl(PySocketSockObject *s) | |
| /*[clinic end generated code: output=3e20211d74c8f60b input=aa6b96e92c7996be]*/ | |
| { | |
| sock_addr_t addrbuf; | |
| int res; | |
| socklen_t addrlen; | |
| if (!getsockaddrlen(s, &addrlen)) | |
| return NULL; | |
| memset(&addrbuf, 0, addrlen); | |
| Py_BEGIN_ALLOW_THREADS | |
| res = getpeername(get_sock_fd(s), SAS2SA(&addrbuf), &addrlen); | |
| Py_END_ALLOW_THREADS | |
| if (res < 0) | |
| return s->errorhandler(); | |
| return makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen, | |
| s->sock_proto); | |
| } | |
| #endif /* HAVE_GETPEERNAME */ | |
| #ifdef HAVE_LISTEN | |
| /* s.listen(n) method */ | |
| /*[clinic input] | |
| _socket.socket.listen | |
| self as s: self(type="PySocketSockObject *") | |
| backlog: int(c_default="Py_MIN(SOMAXCONN, 128)") = min(SOMAXCONN, 128) | |
| / | |
| Enable a server to accept connections. | |
| If backlog is specified, it must be at least 0 (if it is lower, it | |
| is set to 0); it specifies the number of unaccepted connections that | |
| the system will allow before refusing new connections. If not | |
| specified, a default reasonable value is chosen. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_listen_impl(PySocketSockObject *s, int backlog) | |
| /*[clinic end generated code: output=245718576af7f07b input=8eb794d108797ad9]*/ | |
| { | |
| int res; | |
| Py_BEGIN_ALLOW_THREADS | |
| /* To avoid problems on systems that don't allow a negative backlog | |
| * (which doesn't make sense anyway) we force a minimum value of 0. */ | |
| if (backlog < 0) | |
| backlog = 0; | |
| res = listen(get_sock_fd(s), backlog); | |
| Py_END_ALLOW_THREADS | |
| if (res < 0) | |
| return s->errorhandler(); | |
| Py_RETURN_NONE; | |
| } | |
| #endif | |
| struct sock_recv { | |
| char *cbuf; | |
| Py_ssize_t len; | |
| int flags; | |
| Py_ssize_t result; | |
| }; | |
| static int | |
| sock_recv_impl(PySocketSockObject *s, void *data) | |
| { | |
| struct sock_recv *ctx = data; | |
| #ifdef MS_WINDOWS | |
| if (ctx->len > INT_MAX) | |
| ctx->len = INT_MAX; | |
| ctx->result = recv(get_sock_fd(s), ctx->cbuf, (int)ctx->len, ctx->flags); | |
| #else | |
| ctx->result = recv(get_sock_fd(s), ctx->cbuf, ctx->len, ctx->flags); | |
| #endif | |
| return (ctx->result >= 0); | |
| } | |
| /* | |
| * This is the guts of the recv() and recv_into() methods, which reads into a | |
| * char buffer. If you have any inc/dec ref to do to the objects that contain | |
| * the buffer, do it in the caller. This function returns the number of bytes | |
| * successfully read. If there was an error, it returns -1. Note that it is | |
| * also possible that we return a number of bytes smaller than the request | |
| * bytes. | |
| */ | |
| static Py_ssize_t | |
| sock_recv_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags) | |
| { | |
| struct sock_recv ctx; | |
| if (!IS_SELECTABLE(s)) { | |
| select_error(); | |
| return -1; | |
| } | |
| if (len == 0) { | |
| /* If 0 bytes were requested, do nothing. */ | |
| return 0; | |
| } | |
| ctx.cbuf = cbuf; | |
| ctx.len = len; | |
| ctx.flags = flags; | |
| if (sock_call(s, 0, sock_recv_impl, &ctx) < 0) | |
| return -1; | |
| return ctx.result; | |
| } | |
| /* s.recv(nbytes [,flags]) method */ | |
| /*[clinic input] | |
| _socket.socket.recv | |
| self as s: self(type="PySocketSockObject *") | |
| buffersize as recvlen: Py_ssize_t | |
| flags: int = 0 | |
| / | |
| Receive up to buffersize bytes from the socket. | |
| For the optional flags argument, see the Unix manual. When no data | |
| is available, block until at least one byte is available or until | |
| the remote end is closed. When the remote end is closed and all data | |
| is read, return the empty string. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_recv_impl(PySocketSockObject *s, Py_ssize_t recvlen, | |
| int flags) | |
| /*[clinic end generated code: output=412b46af1a68ee75 input=6c8382200e8f85fc]*/ | |
| { | |
| Py_ssize_t outlen; | |
| if (recvlen < 0) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "negative buffersize in recv"); | |
| return NULL; | |
| } | |
| /* Allocate a new string. */ | |
| PyBytesWriter *writer = PyBytesWriter_Create(recvlen); | |
| if (writer == NULL) { | |
| return NULL; | |
| } | |
| /* Call the guts */ | |
| outlen = sock_recv_guts(s, PyBytesWriter_GetData(writer), recvlen, flags); | |
| if (outlen < 0) { | |
| /* An error occurred, release the string and return an | |
| error. */ | |
| PyBytesWriter_Discard(writer); | |
| return NULL; | |
| } | |
| return PyBytesWriter_FinishWithSize(writer, outlen); | |
| } | |
| /* s.recv_into(buffer, [nbytes [,flags]]) method */ | |
| /*[clinic input] | |
| _socket.socket.recv_into | |
| self as s: self(type="PySocketSockObject *") | |
| buffer as pbuf: Py_buffer(accept={rwbuffer}) | |
| nbytes as recvlen: Py_ssize_t = 0 | |
| flags: int = 0 | |
| Receive up to nbytes bytes from the socket, storing into a buffer. | |
| A version of recv() that stores its data into a buffer rather than | |
| creating a new bytes object. If nbytes is not specified (or 0), | |
| receive up to the size available in the given buffer. | |
| See recv() for documentation about the flags. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_recv_into_impl(PySocketSockObject *s, Py_buffer *pbuf, | |
| Py_ssize_t recvlen, int flags) | |
| /*[clinic end generated code: output=58a1cbe9fadb88d7 input=410e6aff36c416a0]*/ | |
| { | |
| char *buf = pbuf->buf; | |
| Py_ssize_t buflen = pbuf->len, readlen; | |
| if (recvlen < 0) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "negative buffersize in recv_into"); | |
| return NULL; | |
| } | |
| if (recvlen == 0) { | |
| /* If nbytes was not specified, use the buffer's length */ | |
| recvlen = buflen; | |
| } | |
| /* Check if the buffer is large enough */ | |
| if (buflen < recvlen) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "buffer too small for requested bytes"); | |
| return NULL; | |
| } | |
| /* Call the guts */ | |
| readlen = sock_recv_guts(s, buf, recvlen, flags); | |
| if (readlen < 0) { | |
| /* Return an error. */ | |
| return NULL; | |
| } | |
| /* Return the number of bytes read. Note that we do not do anything | |
| special here in the case that readlen < recvlen. */ | |
| return PyLong_FromSsize_t(readlen); | |
| } | |
| struct sock_recvfrom { | |
| char* cbuf; | |
| Py_ssize_t len; | |
| int flags; | |
| socklen_t *addrlen; | |
| sock_addr_t *addrbuf; | |
| Py_ssize_t result; | |
| }; | |
| #ifdef HAVE_RECVFROM | |
| static int | |
| sock_recvfrom_impl(PySocketSockObject *s, void *data) | |
| { | |
| struct sock_recvfrom *ctx = data; | |
| memset(ctx->addrbuf, 0, *ctx->addrlen); | |
| #ifdef MS_WINDOWS | |
| if (ctx->len > INT_MAX) | |
| ctx->len = INT_MAX; | |
| ctx->result = recvfrom(get_sock_fd(s), ctx->cbuf, (int)ctx->len, ctx->flags, | |
| SAS2SA(ctx->addrbuf), ctx->addrlen); | |
| #else | |
| ctx->result = recvfrom(get_sock_fd(s), ctx->cbuf, ctx->len, ctx->flags, | |
| SAS2SA(ctx->addrbuf), ctx->addrlen); | |
| #endif | |
| return (ctx->result >= 0); | |
| } | |
| /* | |
| * This is the guts of the recvfrom() and recvfrom_into() methods, which reads | |
| * into a char buffer. If you have any inc/def ref to do to the objects that | |
| * contain the buffer, do it in the caller. This function returns the number | |
| * of bytes successfully read. If there was an error, it returns -1. Note | |
| * that it is also possible that we return a number of bytes smaller than the | |
| * request bytes. | |
| * | |
| * 'addr' is a return value for the address object. Note that you must decref | |
| * it yourself. | |
| */ | |
| static Py_ssize_t | |
| sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags, | |
| PyObject** addr) | |
| { | |
| sock_addr_t addrbuf; | |
| socklen_t addrlen; | |
| struct sock_recvfrom ctx; | |
| *addr = NULL; | |
| if (!getsockaddrlen(s, &addrlen)) | |
| return -1; | |
| if (!IS_SELECTABLE(s)) { | |
| select_error(); | |
| return -1; | |
| } | |
| ctx.cbuf = cbuf; | |
| ctx.len = len; | |
| ctx.flags = flags; | |
| ctx.addrbuf = &addrbuf; | |
| ctx.addrlen = &addrlen; | |
| if (sock_call(s, 0, sock_recvfrom_impl, &ctx) < 0) | |
| return -1; | |
| *addr = makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen, | |
| s->sock_proto); | |
| if (*addr == NULL) | |
| return -1; | |
| return ctx.result; | |
| } | |
| /* s.recvfrom(nbytes [,flags]) method */ | |
| /*[clinic input] | |
| _socket.socket.recvfrom | |
| self as s: self(type="PySocketSockObject *") | |
| buffersize as recvlen: Py_ssize_t | |
| flags: int = 0 | |
| / | |
| Receive up to buffersize bytes and the sender's address info. | |
| Like recv(buffersize, flags), but return a (data, address info) | |
| pair. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_recvfrom_impl(PySocketSockObject *s, Py_ssize_t recvlen, | |
| int flags) | |
| /*[clinic end generated code: output=52b2ece9ea4251b1 input=d8c8c5dc56c02e86]*/ | |
| { | |
| PyObject *addr = NULL; | |
| Py_ssize_t outlen; | |
| if (recvlen < 0) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "negative buffersize in recvfrom"); | |
| return NULL; | |
| } | |
| PyBytesWriter *writer = PyBytesWriter_Create(recvlen); | |
| if (writer == NULL) { | |
| return NULL; | |
| } | |
| outlen = sock_recvfrom_guts(s, PyBytesWriter_GetData(writer), | |
| recvlen, flags, &addr); | |
| if (outlen < 0) { | |
| PyBytesWriter_Discard(writer); | |
| goto error; | |
| } | |
| PyObject *buf = PyBytesWriter_FinishWithSize(writer, outlen); | |
| if (buf == NULL) { | |
| goto error; | |
| } | |
| return _PyTuple_FromPairSteal(buf, addr); | |
| error: | |
| Py_XDECREF(addr); | |
| return NULL; | |
| } | |
| /* s.recvfrom_into(buffer[, nbytes [,flags]]) method */ | |
| /*[clinic input] | |
| _socket.socket.recvfrom_into | |
| self as s: self(type="PySocketSockObject *") | |
| buffer as pbuf: Py_buffer(accept={rwbuffer}) | |
| nbytes as recvlen: Py_ssize_t = 0 | |
| flags: int = 0 | |
| Receive up to nbytes bytes and the sender's address info. | |
| Like recv_into(buffer, nbytes, flags), but return a (nbytes, address | |
| info) pair. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_recvfrom_into_impl(PySocketSockObject *s, Py_buffer *pbuf, | |
| Py_ssize_t recvlen, int flags) | |
| /*[clinic end generated code: output=e60b491a1c9d5bec input=2a15bf437b8b98ba]*/ | |
| { | |
| char *buf = pbuf->buf; | |
| Py_ssize_t readlen, buflen = pbuf->len; | |
| PyObject *addr = NULL; | |
| if (recvlen < 0) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "negative buffersize in recvfrom_into"); | |
| return NULL; | |
| } | |
| if (recvlen == 0) { | |
| /* If nbytes was not specified, use the buffer's length */ | |
| recvlen = buflen; | |
| } else if (recvlen > buflen) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "nbytes is greater than the length of the buffer"); | |
| return NULL; | |
| } | |
| readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr); | |
| if (readlen < 0) { | |
| /* Return an error */ | |
| Py_XDECREF(addr); | |
| return NULL; | |
| } | |
| /* Return the number of bytes read and the address. Note that we do | |
| not do anything special here in the case that readlen < recvlen. */ | |
| return Py_BuildValue("nN", readlen, addr); | |
| } | |
| #endif | |
| /* The sendmsg() and recvmsg[_into]() methods require a working | |
| CMSG_LEN(). See the comment near get_CMSG_LEN(). */ | |
| #ifdef CMSG_LEN | |
| struct sock_recvmsg { | |
| struct msghdr *msg; | |
| int flags; | |
| ssize_t result; | |
| }; | |
| static int | |
| sock_recvmsg_impl(PySocketSockObject *s, void *data) | |
| { | |
| struct sock_recvmsg *ctx = data; | |
| ctx->result = recvmsg(get_sock_fd(s), ctx->msg, ctx->flags); | |
| return (ctx->result >= 0); | |
| } | |
| /* | |
| * Call recvmsg() with the supplied iovec structures, flags, and | |
| * ancillary data buffer size (controllen). Returns the tuple return | |
| * value for recvmsg() or recvmsg_into(), with the first item provided | |
| * by the supplied makeval() function. makeval() will be called with | |
| * the length read and makeval_data as arguments, and must return a | |
| * new reference (which will be decrefed if there is a subsequent | |
| * error). On error, closes any file descriptors received via | |
| * SCM_RIGHTS. | |
| */ | |
| static PyObject * | |
| sock_recvmsg_guts(PySocketSockObject *s, struct iovec *iov, int iovlen, | |
| int flags, Py_ssize_t controllen, | |
| PyObject *(*makeval)(ssize_t, void *), void *makeval_data) | |
| { | |
| sock_addr_t addrbuf; | |
| socklen_t addrbuflen; | |
| struct msghdr msg = {0}; | |
| PyObject *cmsg_list = NULL, *retval = NULL; | |
| void *controlbuf = NULL; | |
| struct cmsghdr *cmsgh; | |
| size_t cmsgdatalen = 0; | |
| int cmsg_status; | |
| struct sock_recvmsg ctx; | |
| /* XXX: POSIX says that msg_name and msg_namelen "shall be | |
| ignored" when the socket is connected (Linux fills them in | |
| anyway for AF_UNIX sockets at least). Normally msg_namelen | |
| seems to be set to 0 if there's no address, but try to | |
| initialize msg_name to something that won't be mistaken for a | |
| real address if that doesn't happen. */ | |
| if (!getsockaddrlen(s, &addrbuflen)) | |
| return NULL; | |
| memset(&addrbuf, 0, addrbuflen); | |
| SAS2SA(&addrbuf)->sa_family = AF_UNSPEC; | |
| if (controllen < 0 || controllen > SOCKLEN_T_LIMIT) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "invalid ancillary data buffer length"); | |
| return NULL; | |
| } | |
| if (controllen > 0 && (controlbuf = PyMem_Malloc(controllen)) == NULL) | |
| return PyErr_NoMemory(); | |
| /* Make the system call. */ | |
| if (!IS_SELECTABLE(s)) { | |
| select_error(); | |
| goto finally; | |
| } | |
| msg.msg_name = SAS2SA(&addrbuf); | |
| msg.msg_namelen = addrbuflen; | |
| msg.msg_iov = iov; | |
| msg.msg_iovlen = iovlen; | |
| msg.msg_control = controlbuf; | |
| msg.msg_controllen = controllen; | |
| ctx.msg = &msg; | |
| ctx.flags = flags; | |
| if (sock_call(s, 0, sock_recvmsg_impl, &ctx) < 0) | |
| goto finally; | |
| /* Make list of (level, type, data) tuples from control messages. */ | |
| if ((cmsg_list = PyList_New(0)) == NULL) | |
| goto err_closefds; | |
| /* Check for empty ancillary data as old CMSG_FIRSTHDR() | |
| implementations didn't do so. */ | |
| for (cmsgh = ((msg.msg_controllen > 0) ? CMSG_FIRSTHDR(&msg) : NULL); | |
| cmsgh != NULL; cmsgh = CMSG_NXTHDR(&msg, cmsgh)) { | |
| PyObject *bytes, *tuple; | |
| int tmp; | |
| cmsg_status = get_cmsg_data_len(&msg, cmsgh, &cmsgdatalen); | |
| if (cmsg_status != 0) { | |
| if (PyErr_WarnEx(PyExc_RuntimeWarning, | |
| "received malformed or improperly-truncated " | |
| "ancillary data", 1) == -1) | |
| goto err_closefds; | |
| } | |
| if (cmsg_status < 0) | |
| break; | |
| if (cmsgdatalen > PY_SSIZE_T_MAX) { | |
| PyErr_SetString(PyExc_OSError, "control message too long"); | |
| goto err_closefds; | |
| } | |
| bytes = PyBytes_FromStringAndSize((char *)CMSG_DATA(cmsgh), | |
| cmsgdatalen); | |
| tuple = Py_BuildValue("iiN", (int)cmsgh->cmsg_level, | |
| (int)cmsgh->cmsg_type, bytes); | |
| if (tuple == NULL) | |
| goto err_closefds; | |
| tmp = PyList_Append(cmsg_list, tuple); | |
| Py_DECREF(tuple); | |
| if (tmp != 0) | |
| goto err_closefds; | |
| if (cmsg_status != 0) | |
| break; | |
| } | |
| retval = Py_BuildValue("NOiN", | |
| (*makeval)(ctx.result, makeval_data), | |
| cmsg_list, | |
| (int)msg.msg_flags, | |
| makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), | |
| ((msg.msg_namelen > addrbuflen) ? | |
| addrbuflen : msg.msg_namelen), | |
| s->sock_proto)); | |
| if (retval == NULL) | |
| goto err_closefds; | |
| finally: | |
| Py_XDECREF(cmsg_list); | |
| PyMem_Free(controlbuf); | |
| return retval; | |
| err_closefds: | |
| #ifdef SCM_RIGHTS | |
| /* Close all descriptors coming from SCM_RIGHTS, so they don't leak. */ | |
| for (cmsgh = ((msg.msg_controllen > 0) ? CMSG_FIRSTHDR(&msg) : NULL); | |
| cmsgh != NULL; cmsgh = CMSG_NXTHDR(&msg, cmsgh)) { | |
| cmsg_status = get_cmsg_data_len(&msg, cmsgh, &cmsgdatalen); | |
| if (cmsg_status < 0) | |
| break; | |
| if (cmsgh->cmsg_level == SOL_SOCKET && | |
| cmsgh->cmsg_type == SCM_RIGHTS) { | |
| size_t numfds; | |
| int *fdp; | |
| numfds = cmsgdatalen / sizeof(int); | |
| fdp = (int *)CMSG_DATA(cmsgh); | |
| while (numfds-- > 0) | |
| close(*fdp++); | |
| } | |
| if (cmsg_status != 0) | |
| break; | |
| } | |
| #endif /* SCM_RIGHTS */ | |
| goto finally; | |
| } | |
| static PyObject * | |
| makeval_recvmsg(ssize_t received, void *data) | |
| { | |
| PyBytesWriter **writer = data; | |
| PyObject *buf = PyBytesWriter_FinishWithSize(*writer, received); | |
| *writer = NULL; | |
| return buf; | |
| } | |
| /* s.recvmsg(bufsize[, ancbufsize[, flags]]) method */ | |
| /*[clinic input] | |
| _socket.socket.recvmsg | |
| self as s: self(type="PySocketSockObject *") | |
| bufsize: Py_ssize_t | |
| ancbufsize: Py_ssize_t = 0 | |
| flags: int = 0 | |
| / | |
| Receive normal data and ancillary data from the socket. | |
| Receive up to bufsize bytes of normal data. The ancbufsize argument | |
| sets the size in bytes of the internal buffer used to receive the | |
| ancillary data; it defaults to 0, meaning that no ancillary data | |
| will be received. Appropriate buffer sizes for ancillary data can | |
| be calculated using CMSG_SPACE() or CMSG_LEN(), and items which do | |
| not fit into the buffer might be truncated or discarded. The flags | |
| argument defaults to 0 and has the same meaning as for recv(). | |
| The return value is a 4-tuple: (data, ancdata, msg_flags, address). | |
| The data item is a bytes object holding the non-ancillary data | |
| received. The ancdata item is a list of zero or more tuples | |
| (cmsg_level, cmsg_type, cmsg_data) representing the ancillary data | |
| (control messages) received: cmsg_level and cmsg_type are integers | |
| specifying the protocol level and protocol-specific type | |
| respectively, and cmsg_data is a bytes object holding the associated | |
| data. The msg_flags item is the bitwise OR of various flags | |
| indicating conditions on the received message; see your system | |
| documentation for details. If the receiving socket is unconnected, | |
| address is the address of the sending socket, if available; | |
| otherwise, its value is unspecified. | |
| If recvmsg() raises an exception after the system call returns, it | |
| will first attempt to close any file descriptors received via the | |
| SCM_RIGHTS mechanism. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_recvmsg_impl(PySocketSockObject *s, Py_ssize_t bufsize, | |
| Py_ssize_t ancbufsize, int flags) | |
| /*[clinic end generated code: output=1a26c130cf1a898f input=ae53e29436e6c0a3]*/ | |
| { | |
| if (bufsize < 0) { | |
| PyErr_SetString(PyExc_ValueError, "negative buffer size in recvmsg()"); | |
| return NULL; | |
| } | |
| PyBytesWriter *writer = PyBytesWriter_Create(bufsize); | |
| if (writer == NULL) { | |
| return NULL; | |
| } | |
| struct iovec iov; | |
| iov.iov_base = PyBytesWriter_GetData(writer); | |
| iov.iov_len = bufsize; | |
| /* Note that we're passing a pointer to *our pointer* to the bytes | |
| writer (&writer); makeval_recvmsg() finish it and set our pointer to | |
| NULL. */ | |
| PyObject *retval; | |
| retval = sock_recvmsg_guts(s, &iov, 1, flags, ancbufsize, | |
| &makeval_recvmsg, &writer); | |
| PyBytesWriter_Discard(writer); | |
| return retval; | |
| } | |
| static PyObject * | |
| makeval_recvmsg_into(ssize_t received, void *data) | |
| { | |
| return PyLong_FromSsize_t(received); | |
| } | |
| /* s.recvmsg_into(buffers[, ancbufsize[, flags]]) method */ | |
| /*[clinic input] | |
| _socket.socket.recvmsg_into | |
| self as s: self(type="PySocketSockObject *") | |
| buffers as buffers_arg: object | |
| ancbufsize: Py_ssize_t = 0 | |
| flags: int = 0 | |
| / | |
| Receive normal and ancillary data, scattering the normal data. | |
| The buffers argument must be an iterable of objects that export | |
| writable buffers (e.g. bytearray objects); these will be filled | |
| with successive chunks of the non-ancillary data until it has all | |
| been written or there are no more buffers. The ancbufsize argument | |
| sets the size in bytes of the internal buffer used to receive the | |
| ancillary data; it defaults to 0, meaning that no ancillary data | |
| will be received. Appropriate buffer sizes for ancillary data can | |
| be calculated using CMSG_SPACE() or CMSG_LEN(), and items which do | |
| not fit into the buffer might be truncated or discarded. The flags | |
| argument defaults to 0 and has the same meaning as for recv(). | |
| The return value is a 4-tuple: (nbytes, ancdata, msg_flags, | |
| address). The nbytes item is the total number of bytes of | |
| non-ancillary data written into the buffers. The ancdata item is a | |
| list of zero or more tuples (cmsg_level, cmsg_type, cmsg_data) | |
| representing the ancillary data (control messages) received: | |
| cmsg_level and cmsg_type are integers specifying the protocol level | |
| and protocol-specific type respectively, and cmsg_data is a bytes | |
| object holding the associated data. The msg_flags item is the | |
| bitwise OR of various flags indicating conditions on the received | |
| message; see your system documentation for details. If the | |
| receiving socket is unconnected, address is the address of the | |
| sending socket, if available; otherwise, its value is unspecified. | |
| If recvmsg_into() raises an exception after the system call returns, | |
| it will first attempt to close any file descriptors received via the | |
| SCM_RIGHTS mechanism. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_recvmsg_into_impl(PySocketSockObject *s, | |
| PyObject *buffers_arg, | |
| Py_ssize_t ancbufsize, int flags) | |
| /*[clinic end generated code: output=282fd7dd1bdb15f8 input=427536a5043122d2]*/ | |
| { | |
| struct iovec *iovs = NULL; | |
| Py_ssize_t i, nitems, nbufs = 0; | |
| Py_buffer *bufs = NULL; | |
| PyObject *buffers_tuple, *retval = NULL; | |
| buffers_tuple = PySequence_Tuple(buffers_arg); | |
| if (buffers_tuple == NULL) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "recvmsg_into() argument 1 must be an iterable"); | |
| return NULL; | |
| } | |
| nitems = PyTuple_GET_SIZE(buffers_tuple); | |
| if (nitems > INT_MAX) { | |
| PyErr_SetString(PyExc_OSError, "recvmsg_into() argument 1 is too long"); | |
| goto finally; | |
| } | |
| /* Fill in an iovec for each item, and save the Py_buffer | |
| structs to release afterwards. */ | |
| if (nitems > 0 && ((iovs = PyMem_New(struct iovec, nitems)) == NULL || | |
| (bufs = PyMem_New(Py_buffer, nitems)) == NULL)) { | |
| PyErr_NoMemory(); | |
| goto finally; | |
| } | |
| for (; nbufs < nitems; nbufs++) { | |
| if (!PyArg_Parse(PyTuple_GET_ITEM(buffers_tuple, nbufs), | |
| "w*;recvmsg_into() argument 1 must be an iterable " | |
| "of single-segment read-write buffers", | |
| &bufs[nbufs])) | |
| goto finally; | |
| iovs[nbufs].iov_base = bufs[nbufs].buf; | |
| iovs[nbufs].iov_len = bufs[nbufs].len; | |
| } | |
| retval = sock_recvmsg_guts(s, iovs, nitems, flags, ancbufsize, | |
| &makeval_recvmsg_into, NULL); | |
| finally: | |
| for (i = 0; i < nbufs; i++) | |
| PyBuffer_Release(&bufs[i]); | |
| PyMem_Free(bufs); | |
| PyMem_Free(iovs); | |
| Py_DECREF(buffers_tuple); | |
| return retval; | |
| } | |
| #endif /* CMSG_LEN */ | |
| struct sock_send { | |
| char *buf; | |
| Py_ssize_t len; | |
| int flags; | |
| Py_ssize_t result; | |
| }; | |
| static int | |
| sock_send_impl(PySocketSockObject *s, void *data) | |
| { | |
| struct sock_send *ctx = data; | |
| #ifdef MS_WINDOWS | |
| if (ctx->len > INT_MAX) | |
| ctx->len = INT_MAX; | |
| ctx->result = send(get_sock_fd(s), ctx->buf, (int)ctx->len, ctx->flags); | |
| #else | |
| ctx->result = send(get_sock_fd(s), ctx->buf, ctx->len, ctx->flags); | |
| #endif | |
| return (ctx->result >= 0); | |
| } | |
| /*[clinic input] | |
| _socket.socket.send | |
| self as s: self(type="PySocketSockObject *") | |
| data as pbuf: Py_buffer | |
| flags: int = 0 | |
| / | |
| Send a data string to the socket. | |
| For the optional flags argument, see the Unix manual. | |
| Return the number of bytes sent; this may be less than len(data) if | |
| the network is busy. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_send_impl(PySocketSockObject *s, Py_buffer *pbuf, int flags) | |
| /*[clinic end generated code: output=3ddf83f17d0c875b input=d2b8af9bf99cfafb]*/ | |
| { | |
| struct sock_send ctx; | |
| if (!IS_SELECTABLE(s)) { | |
| return select_error(); | |
| } | |
| ctx.buf = pbuf->buf; | |
| ctx.len = pbuf->len; | |
| ctx.flags = flags; | |
| if (sock_call(s, 1, sock_send_impl, &ctx) < 0) { | |
| return NULL; | |
| } | |
| return PyLong_FromSsize_t(ctx.result); | |
| } | |
| /*[clinic input] | |
| _socket.socket.sendall | |
| self as s: self(type="PySocketSockObject *") | |
| data as pbuf: Py_buffer | |
| flags: int = 0 | |
| / | |
| Send a data string to the socket. | |
| For the optional flags argument, see the Unix manual. | |
| This calls send() repeatedly until all data is sent. | |
| If an error occurs, it's impossible to tell how much data has been | |
| sent. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_sendall_impl(PySocketSockObject *s, Py_buffer *pbuf, | |
| int flags) | |
| /*[clinic end generated code: output=ec92861424d3faa8 input=2600de13b4614893]*/ | |
| { | |
| char *buf; | |
| Py_ssize_t len, n; | |
| struct sock_send ctx; | |
| int has_timeout = (s->sock_timeout > 0); | |
| PyTime_t timeout = s->sock_timeout; | |
| PyTime_t deadline = 0; | |
| int deadline_initialized = 0; | |
| PyObject *res = NULL; | |
| buf = pbuf->buf; | |
| len = pbuf->len; | |
| if (!IS_SELECTABLE(s)) { | |
| return select_error(); | |
| } | |
| do { | |
| if (has_timeout) { | |
| if (deadline_initialized) { | |
| /* recompute the timeout */ | |
| timeout = _PyDeadline_Get(deadline); | |
| } | |
| else { | |
| deadline_initialized = 1; | |
| deadline = _PyDeadline_Init(timeout); | |
| } | |
| if (timeout <= 0) { | |
| PyErr_SetString(PyExc_TimeoutError, "timed out"); | |
| goto done; | |
| } | |
| } | |
| ctx.buf = buf; | |
| ctx.len = len; | |
| ctx.flags = flags; | |
| if (sock_call_ex(s, 1, sock_send_impl, &ctx, 0, NULL, timeout) < 0) | |
| goto done; | |
| n = ctx.result; | |
| assert(n >= 0); | |
| buf += n; | |
| len -= n; | |
| /* We must run our signal handlers before looping again. | |
| send() can return a successful partial write when it is | |
| interrupted, so we can't restrict ourselves to EINTR. */ | |
| if (PyErr_CheckSignals()) | |
| goto done; | |
| } while (len > 0); | |
| res = Py_NewRef(Py_None); | |
| done: | |
| return res; | |
| } | |
| #ifdef HAVE_SENDTO | |
| struct sock_sendto { | |
| char *buf; | |
| Py_ssize_t len; | |
| int flags; | |
| int addrlen; | |
| sock_addr_t *addrbuf; | |
| Py_ssize_t result; | |
| }; | |
| static int | |
| sock_sendto_impl(PySocketSockObject *s, void *data) | |
| { | |
| struct sock_sendto *ctx = data; | |
| #ifdef MS_WINDOWS | |
| if (ctx->len > INT_MAX) | |
| ctx->len = INT_MAX; | |
| ctx->result = sendto(get_sock_fd(s), ctx->buf, (int)ctx->len, ctx->flags, | |
| SAS2SA(ctx->addrbuf), ctx->addrlen); | |
| #else | |
| ctx->result = sendto(get_sock_fd(s), ctx->buf, ctx->len, ctx->flags, | |
| SAS2SA(ctx->addrbuf), ctx->addrlen); | |
| #endif | |
| return (ctx->result >= 0); | |
| } | |
| /* s.sendto(data, [flags,] sockaddr) method */ | |
| static PyObject * | |
| sock_sendto(PyObject *self, PyObject *args) | |
| { | |
| PySocketSockObject *s = _PySocketSockObject_CAST(self); | |
| Py_buffer pbuf; | |
| PyObject *addro; | |
| Py_ssize_t arglen; | |
| sock_addr_t addrbuf; | |
| int addrlen, flags; | |
| struct sock_sendto ctx; | |
| flags = 0; | |
| arglen = PyTuple_Size(args); | |
| switch (arglen) { | |
| case 2: | |
| if (!PyArg_ParseTuple(args, "y*O:sendto", &pbuf, &addro)) { | |
| return NULL; | |
| } | |
| break; | |
| case 3: | |
| if (!PyArg_ParseTuple(args, "y*iO:sendto", | |
| &pbuf, &flags, &addro)) { | |
| return NULL; | |
| } | |
| break; | |
| default: | |
| PyErr_Format(PyExc_TypeError, | |
| "sendto() takes 2 or 3 arguments (%zd given)", | |
| arglen); | |
| return NULL; | |
| } | |
| if (!IS_SELECTABLE(s)) { | |
| PyBuffer_Release(&pbuf); | |
| return select_error(); | |
| } | |
| if (!getsockaddrarg(s, addro, &addrbuf, &addrlen, "sendto")) { | |
| PyBuffer_Release(&pbuf); | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.sendto", "OO", s, addro) < 0) { | |
| PyBuffer_Release(&pbuf); | |
| return NULL; | |
| } | |
| ctx.buf = pbuf.buf; | |
| ctx.len = pbuf.len; | |
| ctx.flags = flags; | |
| ctx.addrlen = addrlen; | |
| ctx.addrbuf = &addrbuf; | |
| if (sock_call(s, 1, sock_sendto_impl, &ctx) < 0) { | |
| PyBuffer_Release(&pbuf); | |
| return NULL; | |
| } | |
| PyBuffer_Release(&pbuf); | |
| return PyLong_FromSsize_t(ctx.result); | |
| } | |
| PyDoc_STRVAR(sendto_doc, | |
| "sendto(data[, flags], address) -> count\n\ | |
| \n\ | |
| Like send(data, flags) but allows specifying the destination address.\n\ | |
| For IP sockets, the address is a pair (hostaddr, port)."); | |
| #endif | |
| /* The sendmsg() and recvmsg[_into]() methods require a working | |
| CMSG_LEN(). See the comment near get_CMSG_LEN(). */ | |
| #ifdef CMSG_LEN | |
| struct sock_sendmsg { | |
| struct msghdr *msg; | |
| int flags; | |
| ssize_t result; | |
| }; | |
| static int | |
| sock_sendmsg_iovec(PySocketSockObject *s, PyObject *data_arg, | |
| struct msghdr *msg, | |
| Py_buffer **databufsout, Py_ssize_t *ndatabufsout) { | |
| Py_ssize_t ndataparts, ndatabufs = 0; | |
| int result = -1; | |
| struct iovec *iovs = NULL; | |
| PyObject *data_fast = NULL; | |
| Py_buffer *databufs = NULL; | |
| /* Fill in an iovec for each message part, and save the Py_buffer | |
| structs to release afterwards. */ | |
| data_fast = PySequence_Tuple(data_arg); | |
| if (data_fast == NULL) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "sendmsg() argument 1 must be an iterable"); | |
| goto finally; | |
| } | |
| ndataparts = PyTuple_GET_SIZE(data_fast); | |
| if (ndataparts > INT_MAX) { | |
| PyErr_SetString(PyExc_OSError, "sendmsg() argument 1 is too long"); | |
| goto finally; | |
| } | |
| msg->msg_iovlen = ndataparts; | |
| if (ndataparts > 0) { | |
| iovs = PyMem_New(struct iovec, ndataparts); | |
| if (iovs == NULL) { | |
| PyErr_NoMemory(); | |
| goto finally; | |
| } | |
| msg->msg_iov = iovs; | |
| databufs = PyMem_New(Py_buffer, ndataparts); | |
| if (databufs == NULL) { | |
| PyErr_NoMemory(); | |
| goto finally; | |
| } | |
| } | |
| for (; ndatabufs < ndataparts; ndatabufs++) { | |
| if (PyObject_GetBuffer(PyTuple_GET_ITEM(data_fast, ndatabufs), | |
| &databufs[ndatabufs], PyBUF_SIMPLE) < 0) | |
| goto finally; | |
| iovs[ndatabufs].iov_base = databufs[ndatabufs].buf; | |
| iovs[ndatabufs].iov_len = databufs[ndatabufs].len; | |
| } | |
| result = 0; | |
| finally: | |
| *databufsout = databufs; | |
| *ndatabufsout = ndatabufs; | |
| Py_XDECREF(data_fast); | |
| return result; | |
| } | |
| static int | |
| sock_sendmsg_impl(PySocketSockObject *s, void *data) | |
| { | |
| struct sock_sendmsg *ctx = data; | |
| ctx->result = sendmsg(get_sock_fd(s), ctx->msg, ctx->flags); | |
| return (ctx->result >= 0); | |
| } | |
| /*[clinic input] | |
| _socket.socket.sendmsg | |
| self as s: self(type="PySocketSockObject *") | |
| buffers as data_arg: object | |
| ancdata as cmsg_arg: object(c_default="NULL") = () | |
| flags: int = 0 | |
| address as addr_arg: object(c_default="NULL") = None | |
| / | |
| Send normal and ancillary data to the socket. | |
| It gathering the non-ancillary data from a series of buffers | |
| and concatenating it into a single message. | |
| The buffers argument specifies the non-ancillary | |
| data as an iterable of bytes-like objects (e.g. bytes objects). | |
| The ancdata argument specifies the ancillary data (control messages) | |
| as an iterable of zero or more tuples (cmsg_level, cmsg_type, | |
| cmsg_data), where cmsg_level and cmsg_type are integers specifying | |
| the protocol level and protocol-specific type respectively, and | |
| cmsg_data is a bytes-like object holding the associated data. The | |
| flags argument defaults to 0 and has the same meaning as for send(). | |
| If address is supplied and not None, it sets a destination address | |
| for the message. The return value is the number of bytes of | |
| non-ancillary data sent. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_sendmsg_impl(PySocketSockObject *s, PyObject *data_arg, | |
| PyObject *cmsg_arg, int flags, | |
| PyObject *addr_arg) | |
| /*[clinic end generated code: output=3b4cb1110644ce39 input=5fdf9b49bed3848b]*/ | |
| { | |
| Py_ssize_t i, ndatabufs = 0, ncmsgs, ncmsgbufs = 0; | |
| Py_buffer *databufs = NULL; | |
| sock_addr_t addrbuf; | |
| struct msghdr msg; | |
| struct cmsginfo { | |
| int level; | |
| int type; | |
| Py_buffer data; | |
| } *cmsgs = NULL; | |
| void *controlbuf = NULL; | |
| size_t controllen, controllen_last; | |
| int addrlen; | |
| PyObject *cmsg_fast = NULL, *retval = NULL; | |
| struct sock_sendmsg ctx; | |
| memset(&msg, 0, sizeof(msg)); | |
| /* Parse destination address. */ | |
| if (addr_arg != NULL && addr_arg != Py_None) { | |
| if (!getsockaddrarg(s, addr_arg, &addrbuf, &addrlen, | |
| "sendmsg")) | |
| { | |
| goto finally; | |
| } | |
| if (PySys_Audit("socket.sendmsg", "OO", s, addr_arg) < 0) { | |
| return NULL; | |
| } | |
| msg.msg_name = &addrbuf; | |
| msg.msg_namelen = addrlen; | |
| } else { | |
| if (PySys_Audit("socket.sendmsg", "OO", s, Py_None) < 0) { | |
| return NULL; | |
| } | |
| } | |
| /* Fill in an iovec for each message part, and save the Py_buffer | |
| structs to release afterwards. */ | |
| if (sock_sendmsg_iovec(s, data_arg, &msg, &databufs, &ndatabufs) == -1) { | |
| goto finally; | |
| } | |
| if (cmsg_arg == NULL) | |
| ncmsgs = 0; | |
| else { | |
| cmsg_fast = PySequence_Tuple(cmsg_arg); | |
| if (cmsg_fast == NULL) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "sendmsg() argument 2 must be an iterable"); | |
| goto finally; | |
| } | |
| ncmsgs = PyTuple_GET_SIZE(cmsg_fast); | |
| } | |
| #ifndef CMSG_SPACE | |
| if (ncmsgs > 1) { | |
| PyErr_SetString(PyExc_OSError, | |
| "sending multiple control messages is not supported " | |
| "on this system"); | |
| goto finally; | |
| } | |
| #endif | |
| /* Save level, type and Py_buffer for each control message, | |
| and calculate total size. */ | |
| if (ncmsgs > 0 && (cmsgs = PyMem_New(struct cmsginfo, ncmsgs)) == NULL) { | |
| PyErr_NoMemory(); | |
| goto finally; | |
| } | |
| controllen = controllen_last = 0; | |
| while (ncmsgbufs < ncmsgs) { | |
| size_t bufsize, space; | |
| PyObject *item = PyTuple_GET_ITEM(cmsg_fast, ncmsgbufs); | |
| if (!PyArg_Parse(item, | |
| "(iiy*):[sendmsg() ancillary data items]", | |
| &cmsgs[ncmsgbufs].level, | |
| &cmsgs[ncmsgbufs].type, | |
| &cmsgs[ncmsgbufs].data)) | |
| goto finally; | |
| bufsize = cmsgs[ncmsgbufs++].data.len; | |
| #ifdef CMSG_SPACE | |
| if (!get_CMSG_SPACE(bufsize, &space)) { | |
| #else | |
| if (!get_CMSG_LEN(bufsize, &space)) { | |
| #endif | |
| PyErr_SetString(PyExc_OSError, "ancillary data item too large"); | |
| goto finally; | |
| } | |
| controllen += space; | |
| if (controllen > SOCKLEN_T_LIMIT || controllen < controllen_last) { | |
| PyErr_SetString(PyExc_OSError, "too much ancillary data"); | |
| goto finally; | |
| } | |
| controllen_last = controllen; | |
| } | |
| /* Construct ancillary data block from control message info. */ | |
| if (ncmsgbufs > 0) { | |
| struct cmsghdr *cmsgh = NULL; | |
| controlbuf = PyMem_Malloc(controllen); | |
| if (controlbuf == NULL) { | |
| PyErr_NoMemory(); | |
| goto finally; | |
| } | |
| msg.msg_control = controlbuf; | |
| msg.msg_controllen = controllen; | |
| /* Need to zero out the buffer as a workaround for glibc's | |
| CMSG_NXTHDR() implementation. After getting the pointer to | |
| the next header, it checks its (uninitialized) cmsg_len | |
| member to see if the "message" fits in the buffer, and | |
| returns NULL if it doesn't. Zero-filling the buffer | |
| ensures that this doesn't happen. */ | |
| memset(controlbuf, 0, controllen); | |
| for (i = 0; i < ncmsgbufs; i++) { | |
| size_t msg_len, data_len = cmsgs[i].data.len; | |
| int enough_space = 0; | |
| cmsgh = (i == 0) ? CMSG_FIRSTHDR(&msg) : CMSG_NXTHDR(&msg, cmsgh); | |
| if (cmsgh == NULL) { | |
| PyErr_Format(PyExc_RuntimeError, | |
| "unexpected NULL result from %s()", | |
| (i == 0) ? "CMSG_FIRSTHDR" : "CMSG_NXTHDR"); | |
| goto finally; | |
| } | |
| if (!get_CMSG_LEN(data_len, &msg_len)) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "item size out of range for CMSG_LEN()"); | |
| goto finally; | |
| } | |
| if (cmsg_min_space(&msg, cmsgh, msg_len)) { | |
| size_t space; | |
| cmsgh->cmsg_len = msg_len; | |
| if (get_cmsg_data_space(&msg, cmsgh, &space)) | |
| enough_space = (space >= data_len); | |
| } | |
| if (!enough_space) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "ancillary data does not fit in calculated " | |
| "space"); | |
| goto finally; | |
| } | |
| cmsgh->cmsg_level = cmsgs[i].level; | |
| cmsgh->cmsg_type = cmsgs[i].type; | |
| memcpy(CMSG_DATA(cmsgh), cmsgs[i].data.buf, data_len); | |
| } | |
| } | |
| /* Make the system call. */ | |
| if (!IS_SELECTABLE(s)) { | |
| select_error(); | |
| goto finally; | |
| } | |
| ctx.msg = &msg; | |
| ctx.flags = flags; | |
| if (sock_call(s, 1, sock_sendmsg_impl, &ctx) < 0) | |
| goto finally; | |
| retval = PyLong_FromSsize_t(ctx.result); | |
| finally: | |
| PyMem_Free(controlbuf); | |
| for (i = 0; i < ncmsgbufs; i++) | |
| PyBuffer_Release(&cmsgs[i].data); | |
| PyMem_Free(cmsgs); | |
| Py_XDECREF(cmsg_fast); | |
| PyMem_Free(msg.msg_iov); | |
| for (i = 0; i < ndatabufs; i++) { | |
| PyBuffer_Release(&databufs[i]); | |
| } | |
| PyMem_Free(databufs); | |
| return retval; | |
| } | |
| #endif /* CMSG_LEN */ | |
| #ifdef HAVE_SOCKADDR_ALG | |
| /*[clinic input] | |
| _socket.socket.sendmsg_afalg | |
| self: self(type="PySocketSockObject *") | |
| msg as data_arg: object = NULL | |
| * | |
| op as opobj: object(subclass_of='&PyLong_Type') = NULL | |
| iv: Py_buffer = NULL | |
| assoclen as assoclenobj: object(subclass_of='&PyLong_Type') = NULL | |
| flags: int = 0 | |
| Set operation mode, IV and associated data length. | |
| For an AF_ALG operation socket. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_sendmsg_afalg_impl(PySocketSockObject *self, | |
| PyObject *data_arg, PyObject *opobj, | |
| Py_buffer *iv, PyObject *assoclenobj, | |
| int flags) | |
| /*[clinic end generated code: output=3fd9856d4d9f7c97 input=3ed371da034a1bb3]*/ | |
| { | |
| PyObject *retval = NULL; | |
| Py_ssize_t i, ndatabufs = 0; | |
| Py_buffer *databufs = NULL; | |
| int op = -1; | |
| int assoclen = -1; | |
| unsigned int *uiptr; | |
| struct msghdr msg; | |
| struct cmsghdr *header = NULL; | |
| struct af_alg_iv *alg_iv = NULL; | |
| struct sock_sendmsg ctx; | |
| Py_ssize_t controllen; | |
| void *controlbuf = NULL; | |
| if (self->sock_family != AF_ALG) { | |
| PyErr_SetString(PyExc_OSError, | |
| "algset is only supported for AF_ALG"); | |
| return NULL; | |
| } | |
| memset(&msg, 0, sizeof(msg)); | |
| /* op is a required, keyword-only argument >= 0 */ | |
| if (opobj != NULL) { | |
| op = PyLong_AsInt(opobj); | |
| } | |
| if (op < 0) { | |
| /* override exception from PyLong_AsInt() */ | |
| PyErr_SetString(PyExc_TypeError, | |
| "Invalid or missing argument 'op'"); | |
| goto finally; | |
| } | |
| /* assoclen is optional but must be >= 0 */ | |
| if (assoclenobj != NULL) { | |
| assoclen = PyLong_AsInt(assoclenobj); | |
| if (assoclen == -1 && PyErr_Occurred()) { | |
| goto finally; | |
| } | |
| if (assoclen < 0) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "assoclen must be positive"); | |
| goto finally; | |
| } | |
| } | |
| controllen = CMSG_SPACE(4); | |
| if (iv->buf != NULL) { | |
| controllen += CMSG_SPACE(sizeof(*alg_iv) + iv->len); | |
| } | |
| if (assoclen >= 0) { | |
| controllen += CMSG_SPACE(4); | |
| } | |
| controlbuf = PyMem_Malloc(controllen); | |
| if (controlbuf == NULL) { | |
| PyErr_NoMemory(); | |
| goto finally; | |
| } | |
| memset(controlbuf, 0, controllen); | |
| msg.msg_controllen = controllen; | |
| msg.msg_control = controlbuf; | |
| /* Fill in an iovec for each message part, and save the Py_buffer | |
| structs to release afterwards. */ | |
| if (data_arg != NULL) { | |
| if (sock_sendmsg_iovec(self, data_arg, &msg, &databufs, &ndatabufs) == -1) { | |
| goto finally; | |
| } | |
| } | |
| /* set operation to encrypt or decrypt */ | |
| header = CMSG_FIRSTHDR(&msg); | |
| if (header == NULL) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "unexpected NULL result from CMSG_FIRSTHDR"); | |
| goto finally; | |
| } | |
| header->cmsg_level = SOL_ALG; | |
| header->cmsg_type = ALG_SET_OP; | |
| header->cmsg_len = CMSG_LEN(4); | |
| uiptr = (void*)CMSG_DATA(header); | |
| *uiptr = (unsigned int)op; | |
| /* set initialization vector */ | |
| if (iv->buf != NULL) { | |
| header = CMSG_NXTHDR(&msg, header); | |
| if (header == NULL) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "unexpected NULL result from CMSG_NXTHDR(iv)"); | |
| goto finally; | |
| } | |
| header->cmsg_level = SOL_ALG; | |
| header->cmsg_type = ALG_SET_IV; | |
| header->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv->len); | |
| alg_iv = (void*)CMSG_DATA(header); | |
| alg_iv->ivlen = iv->len; | |
| memcpy(alg_iv->iv, iv->buf, iv->len); | |
| } | |
| /* set length of associated data for AEAD */ | |
| if (assoclen >= 0) { | |
| header = CMSG_NXTHDR(&msg, header); | |
| if (header == NULL) { | |
| PyErr_SetString(PyExc_RuntimeError, | |
| "unexpected NULL result from CMSG_NXTHDR(assoc)"); | |
| goto finally; | |
| } | |
| header->cmsg_level = SOL_ALG; | |
| header->cmsg_type = ALG_SET_AEAD_ASSOCLEN; | |
| header->cmsg_len = CMSG_LEN(4); | |
| uiptr = (void*)CMSG_DATA(header); | |
| *uiptr = (unsigned int)assoclen; | |
| } | |
| ctx.msg = &msg; | |
| ctx.flags = flags; | |
| if (sock_call(self, 1, sock_sendmsg_impl, &ctx) < 0) { | |
| goto finally; | |
| } | |
| retval = PyLong_FromSsize_t(ctx.result); | |
| finally: | |
| PyMem_Free(controlbuf); | |
| PyMem_Free(msg.msg_iov); | |
| for (i = 0; i < ndatabufs; i++) { | |
| PyBuffer_Release(&databufs[i]); | |
| } | |
| PyMem_Free(databufs); | |
| return retval; | |
| } | |
| #endif | |
| #ifdef HAVE_SHUTDOWN | |
| /* s.shutdown(how) method */ | |
| /*[clinic input] | |
| _socket.socket.shutdown | |
| self as s: self(type="PySocketSockObject *") | |
| flag as arg: object | |
| / | |
| Shut down one or both halves of the connection. | |
| Shut down the reading side of the socket (flag == SHUT_RD), the | |
| writing side of the socket (flag == SHUT_WR), or both ends (flag == | |
| SHUT_RDWR). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_shutdown_impl(PySocketSockObject *s, PyObject *arg) | |
| /*[clinic end generated code: output=84264513a6049ca7 input=a90afb227247ce03]*/ | |
| { | |
| int how; | |
| int res; | |
| how = PyLong_AsInt(arg); | |
| if (how == -1 && PyErr_Occurred()) | |
| return NULL; | |
| Py_BEGIN_ALLOW_THREADS | |
| res = shutdown(get_sock_fd(s), how); | |
| Py_END_ALLOW_THREADS | |
| if (res < 0) | |
| return s->errorhandler(); | |
| Py_RETURN_NONE; | |
| } | |
| #endif | |
| #if defined(MS_WINDOWS) && defined(SIO_RCVALL) | |
| static PyObject* | |
| sock_ioctl(PyObject *self, PyObject *arg) | |
| { | |
| PySocketSockObject *s = _PySocketSockObject_CAST(self); | |
| unsigned long cmd = SIO_RCVALL; | |
| PyObject *argO; | |
| DWORD recv; | |
| if (!PyArg_ParseTuple(arg, "kO:ioctl", &cmd, &argO)) | |
| return NULL; | |
| switch (cmd) { | |
| case SIO_RCVALL: { | |
| unsigned int option = RCVALL_ON; | |
| if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option)) | |
| return NULL; | |
| if (WSAIoctl(get_sock_fd(s), cmd, &option, sizeof(option), | |
| NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) { | |
| return set_error(); | |
| } | |
| return PyLong_FromUnsignedLong(recv); } | |
| case SIO_KEEPALIVE_VALS: { | |
| struct tcp_keepalive ka; | |
| if (!PyArg_ParseTuple(arg, "k(kkk):ioctl", &cmd, | |
| &ka.onoff, &ka.keepalivetime, &ka.keepaliveinterval)) | |
| return NULL; | |
| if (WSAIoctl(get_sock_fd(s), cmd, &ka, sizeof(ka), | |
| NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) { | |
| return set_error(); | |
| } | |
| return PyLong_FromUnsignedLong(recv); } | |
| #if defined(SIO_LOOPBACK_FAST_PATH) | |
| case SIO_LOOPBACK_FAST_PATH: { | |
| unsigned int option; | |
| if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option)) | |
| return NULL; | |
| if (WSAIoctl(get_sock_fd(s), cmd, &option, sizeof(option), | |
| NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) { | |
| return set_error(); | |
| } | |
| return PyLong_FromUnsignedLong(recv); } | |
| #endif | |
| default: | |
| PyErr_Format(PyExc_ValueError, "invalid ioctl command %lu", cmd); | |
| return NULL; | |
| } | |
| } | |
| PyDoc_STRVAR(sock_ioctl_doc, | |
| "ioctl(cmd, option) -> long\n\ | |
| \n\ | |
| Control the socket with WSAIoctl syscall. Currently supported 'cmd' values are\n\ | |
| SIO_RCVALL: 'option' must be one of the socket.RCVALL_* constants.\n\ | |
| SIO_KEEPALIVE_VALS: 'option' is a tuple of (onoff, timeout, interval).\n\ | |
| SIO_LOOPBACK_FAST_PATH: 'option' is a boolean value, and is disabled by default"); | |
| #endif | |
| #if defined(MS_WINDOWS) | |
| /*[clinic input] | |
| _socket.socket.share | |
| self as s: self(type="PySocketSockObject *") | |
| process_id as processId: unsigned_int(bitwise=True) | |
| / | |
| Share the socket with another process. | |
| The target process id must be provided and the resulting bytes | |
| object passed to the target process. There the shared socket can be | |
| instantiated by calling socket.fromshare(). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socket_share_impl(PySocketSockObject *s, unsigned int processId) | |
| /*[clinic end generated code: output=446bfcc5fe3273c6 input=0a9d7536371bfe2d]*/ | |
| { | |
| WSAPROTOCOL_INFOW info; | |
| int result; | |
| Py_BEGIN_ALLOW_THREADS | |
| result = WSADuplicateSocketW(get_sock_fd(s), processId, &info); | |
| Py_END_ALLOW_THREADS | |
| if (result == SOCKET_ERROR) | |
| return set_error(); | |
| return PyBytes_FromStringAndSize((const char*)&info, sizeof(info)); | |
| } | |
| #endif | |
| /* List of methods for socket objects */ | |
| static PyMethodDef sock_methods[] = { | |
| _SOCKET_SOCKET__ACCEPT_METHODDEF | |
| _SOCKET_SOCKET_BIND_METHODDEF | |
| _SOCKET_SOCKET_CLOSE_METHODDEF | |
| _SOCKET_SOCKET_CONNECT_METHODDEF | |
| _SOCKET_SOCKET_CONNECT_EX_METHODDEF | |
| _SOCKET_SOCKET_DETACH_METHODDEF | |
| _SOCKET_SOCKET_FILENO_METHODDEF | |
| _SOCKET_SOCKET_GETPEERNAME_METHODDEF | |
| _SOCKET_SOCKET_GETSOCKNAME_METHODDEF | |
| _SOCKET_SOCKET_GETSOCKOPT_METHODDEF | |
| #if defined(MS_WINDOWS) && defined(SIO_RCVALL) | |
| {"ioctl", sock_ioctl, METH_VARARGS, sock_ioctl_doc}, | |
| #endif | |
| _SOCKET_SOCKET_SHARE_METHODDEF | |
| _SOCKET_SOCKET_LISTEN_METHODDEF | |
| _SOCKET_SOCKET_RECV_METHODDEF | |
| _SOCKET_SOCKET_RECV_INTO_METHODDEF | |
| _SOCKET_SOCKET_RECVFROM_METHODDEF | |
| _SOCKET_SOCKET_RECVFROM_INTO_METHODDEF | |
| _SOCKET_SOCKET_SEND_METHODDEF | |
| _SOCKET_SOCKET_SENDALL_METHODDEF | |
| #ifdef HAVE_SENDTO | |
| {"sendto", sock_sendto, METH_VARARGS, sendto_doc}, | |
| #endif | |
| _SOCKET_SOCKET_SETBLOCKING_METHODDEF | |
| _SOCKET_SOCKET_GETBLOCKING_METHODDEF | |
| _SOCKET_SOCKET_SETTIMEOUT_METHODDEF | |
| _SOCKET_SOCKET_GETTIMEOUT_METHODDEF | |
| #ifdef HAVE_SETSOCKOPT | |
| {"setsockopt", sock_setsockopt, METH_VARARGS, setsockopt_doc}, | |
| #endif | |
| _SOCKET_SOCKET_SHUTDOWN_METHODDEF | |
| _SOCKET_SOCKET_RECVMSG_METHODDEF | |
| _SOCKET_SOCKET_RECVMSG_INTO_METHODDEF | |
| _SOCKET_SOCKET_SENDMSG_METHODDEF | |
| _SOCKET_SOCKET_SENDMSG_AFALG_METHODDEF | |
| {NULL, NULL, 0, NULL} /* sentinel */ | |
| }; | |
| /* SockObject members */ | |
| static PyMemberDef sock_memberlist[] = { | |
| {"family", Py_T_INT, offsetof(PySocketSockObject, sock_family), Py_READONLY, "the socket family"}, | |
| {"type", Py_T_INT, offsetof(PySocketSockObject, sock_type), Py_READONLY, "the socket type"}, | |
| {"proto", Py_T_INT, offsetof(PySocketSockObject, sock_proto), Py_READONLY, "the socket protocol"}, | |
| {0}, | |
| }; | |
| static PyGetSetDef sock_getsetlist[] = { | |
| {"timeout", sock_gettimeout_getter, NULL, PyDoc_STR("the socket timeout")}, | |
| {NULL} /* sentinel */ | |
| }; | |
| /* Deallocate a socket object in response to the last Py_DECREF(). | |
| First close the file description. */ | |
| static void | |
| sock_finalize(PyObject *self) | |
| { | |
| PySocketSockObject *s = _PySocketSockObject_CAST(self); | |
| SOCKET_T fd; | |
| /* Save the current exception, if any. */ | |
| PyObject *exc = PyErr_GetRaisedException(); | |
| if (get_sock_fd(s) != INVALID_SOCKET) { | |
| if (PyErr_ResourceWarning((PyObject *)s, 1, "unclosed %R", s)) { | |
| /* Spurious errors can appear at shutdown */ | |
| if (PyErr_ExceptionMatches(PyExc_Warning)) { | |
| PyErr_FormatUnraisable("Exception ignored while " | |
| "finalizing socket %R", s); | |
| } | |
| } | |
| /* Only close the socket *after* logging the ResourceWarning warning | |
| to allow the logger to call socket methods like | |
| socket.getsockname(). If the socket is closed before, socket | |
| methods fails with the EBADF error. */ | |
| fd = get_sock_fd(s); | |
| set_sock_fd(s, INVALID_SOCKET); | |
| /* We do not want to retry upon EINTR: see sock_close() */ | |
| Py_BEGIN_ALLOW_THREADS | |
| (void) SOCKETCLOSE(fd); | |
| Py_END_ALLOW_THREADS | |
| } | |
| /* Restore the saved exception. */ | |
| PyErr_SetRaisedException(exc); | |
| } | |
| static void | |
| sock_dealloc(PyObject *s) | |
| { | |
| if (PyObject_CallFinalizerFromDealloc(s) < 0) { | |
| return; | |
| } | |
| PyTypeObject *tp = Py_TYPE(s); | |
| PyObject_GC_UnTrack(s); | |
| tp->tp_free(s); | |
| Py_DECREF(tp); | |
| } | |
| static PyObject * | |
| sock_repr(PyObject *self) | |
| { | |
| PySocketSockObject *s = _PySocketSockObject_CAST(self); | |
| long sock_fd; | |
| /* On Windows, this test is needed because SOCKET_T is unsigned */ | |
| if (get_sock_fd(s) == INVALID_SOCKET) { | |
| sock_fd = -1; | |
| } | |
| #if SIZEOF_SOCKET_T > SIZEOF_LONG | |
| else if (get_sock_fd(s) > LONG_MAX) { | |
| /* this can occur on Win64, and actually there is a special | |
| ugly printf formatter for decimal pointer length integer | |
| printing, only bother if necessary*/ | |
| PyErr_SetString(PyExc_OverflowError, | |
| "no printf formatter to display " | |
| "the socket descriptor in decimal"); | |
| return NULL; | |
| } | |
| #endif | |
| else | |
| sock_fd = (long)get_sock_fd(s); | |
| return PyUnicode_FromFormat( | |
| "<socket object, fd=%ld, family=%d, type=%d, proto=%d>", | |
| sock_fd, s->sock_family, | |
| s->sock_type, | |
| s->sock_proto); | |
| } | |
| /* Create a new, uninitialized socket object. */ | |
| static PyObject * | |
| sock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| { | |
| PyObject *new; | |
| new = type->tp_alloc(type, 0); | |
| if (new != NULL) { | |
| ((PySocketSockObject *)new)->sock_fd = INVALID_SOCKET; | |
| ((PySocketSockObject *)new)->sock_timeout = _PyTime_FromSeconds(-1); | |
| ((PySocketSockObject *)new)->errorhandler = &set_error; | |
| #ifdef MS_WINDOWS | |
| ((PySocketSockObject *)new)->quickack = 0; | |
| #endif | |
| } | |
| return new; | |
| } | |
| /* Initialize a new socket object. */ | |
| /*ARGSUSED*/ | |
| #ifndef HAVE_SOCKET | |
| #define socket stub_socket | |
| static int | |
| socket(int domain, int type, int protocol) | |
| { | |
| errno = ENOTSUP; | |
| return INVALID_SOCKET; | |
| } | |
| #endif | |
| /*[clinic input] | |
| _socket.socket.__init__ as sock_initobj | |
| family: int = -1 | |
| type: int = -1 | |
| proto: int = -1 | |
| fileno as fdobj: object = NULL | |
| [clinic start generated code]*/ | |
| static int | |
| sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto, | |
| PyObject *fdobj) | |
| /*[clinic end generated code: output=d114d026b9a9a810 input=04cfc32953f5cc25]*/ | |
| { | |
| SOCKET_T fd = INVALID_SOCKET; | |
| socket_state *state = find_module_state_by_def(Py_TYPE(self)); | |
| #ifndef MS_WINDOWS | |
| #ifdef SOCK_CLOEXEC | |
| int *atomic_flag_works = &sock_cloexec_works; | |
| #else | |
| int *atomic_flag_works = NULL; | |
| #endif | |
| #endif | |
| #ifdef MS_WINDOWS | |
| /* In this case, we don't use the family, type and proto args */ | |
| if (fdobj == NULL || fdobj == Py_None) | |
| #endif | |
| { | |
| if (PySys_Audit("socket.__new__", "Oiii", | |
| self, family, type, proto) < 0) { | |
| return -1; | |
| } | |
| } | |
| if (fdobj != NULL && fdobj != Py_None) { | |
| #ifdef MS_WINDOWS | |
| /* recreate a socket that was duplicated */ | |
| if (PyBytes_Check(fdobj)) { | |
| WSAPROTOCOL_INFOW info; | |
| if (PyBytes_GET_SIZE(fdobj) != sizeof(info)) { | |
| PyErr_Format(PyExc_ValueError, | |
| "socket descriptor string has wrong size, " | |
| "should be %zu bytes.", sizeof(info)); | |
| return -1; | |
| } | |
| memcpy(&info, PyBytes_AS_STRING(fdobj), sizeof(info)); | |
| if (PySys_Audit("socket.__new__", "Oiii", self, | |
| info.iAddressFamily, info.iSocketType, | |
| info.iProtocol) < 0) { | |
| return -1; | |
| } | |
| Py_BEGIN_ALLOW_THREADS | |
| fd = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, | |
| FROM_PROTOCOL_INFO, &info, 0, WSA_FLAG_OVERLAPPED); | |
| Py_END_ALLOW_THREADS | |
| if (fd == INVALID_SOCKET) { | |
| set_error(); | |
| return -1; | |
| } | |
| if (!SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0)) { | |
| PyErr_SetFromWindowsErr(0); | |
| closesocket(fd); | |
| return -1; | |
| } | |
| family = info.iAddressFamily; | |
| type = info.iSocketType; | |
| proto = info.iProtocol; | |
| } | |
| else | |
| #endif | |
| { | |
| fd = PyLong_AsSocket_t(fdobj); | |
| if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) | |
| return -1; | |
| #ifdef MS_WINDOWS | |
| if (fd == INVALID_SOCKET) { | |
| #else | |
| if (fd < 0) { | |
| #endif | |
| PyErr_SetString(PyExc_ValueError, "negative file descriptor"); | |
| return -1; | |
| } | |
| /* validate that passed file descriptor is valid and a socket. */ | |
| sock_addr_t addrbuf; | |
| socklen_t addrlen = sizeof(sock_addr_t); | |
| memset(&addrbuf, 0, addrlen); | |
| #ifdef HAVE_GETSOCKNAME | |
| if (getsockname(fd, SAS2SA(&addrbuf), &addrlen) == 0) { | |
| if (family == -1) { | |
| family = SAS2SA(&addrbuf)->sa_family; | |
| } | |
| } else { | |
| #ifdef MS_WINDOWS | |
| /* getsockname() on an unbound socket is an error on Windows. | |
| Invalid descriptor and not a socket is same error code. | |
| Error out if family must be resolved, or bad descriptor. */ | |
| if (family == -1 || CHECK_ERRNO(ENOTSOCK)) { | |
| #else | |
| /* getsockname() is not supported for SOL_ALG on Linux. */ | |
| if (family == -1 || CHECK_ERRNO(EBADF) || CHECK_ERRNO(ENOTSOCK)) { | |
| #endif | |
| set_error(); | |
| return -1; | |
| } | |
| } | |
| #endif // HAVE_GETSOCKNAME | |
| #ifdef SO_TYPE | |
| if (type == -1) { | |
| int tmp; | |
| socklen_t slen = sizeof(tmp); | |
| if (getsockopt(fd, SOL_SOCKET, SO_TYPE, | |
| (void *)&tmp, &slen) == 0) | |
| { | |
| type = tmp; | |
| } else { | |
| set_error(); | |
| return -1; | |
| } | |
| } | |
| #else | |
| type = SOCK_STREAM; | |
| #endif | |
| #ifdef SO_PROTOCOL | |
| if (proto == -1) { | |
| int tmp; | |
| socklen_t slen = sizeof(tmp); | |
| if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, | |
| (void *)&tmp, &slen) == 0) | |
| { | |
| proto = tmp; | |
| } else { | |
| set_error(); | |
| return -1; | |
| } | |
| } | |
| #else | |
| proto = 0; | |
| #endif | |
| } | |
| } | |
| else { | |
| /* No fd, default to AF_INET and SOCK_STREAM */ | |
| if (family == -1) { | |
| family = AF_INET; | |
| } | |
| if (type == -1) { | |
| type = SOCK_STREAM; | |
| } | |
| if (proto == -1) { | |
| proto = 0; | |
| } | |
| #ifdef MS_WINDOWS | |
| Py_BEGIN_ALLOW_THREADS | |
| fd = WSASocketW(family, type, proto, | |
| NULL, 0, | |
| WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); | |
| Py_END_ALLOW_THREADS | |
| if (fd == INVALID_SOCKET) { | |
| set_error(); | |
| return -1; | |
| } | |
| #else | |
| /* UNIX */ | |
| Py_BEGIN_ALLOW_THREADS | |
| #ifdef SOCK_CLOEXEC | |
| if (_Py_atomic_load_int_relaxed(&sock_cloexec_works) != 0) { | |
| fd = socket(family, type | SOCK_CLOEXEC, proto); | |
| if (_Py_atomic_load_int_relaxed(&sock_cloexec_works) == -1) { | |
| if (fd >= 0) { | |
| _Py_atomic_store_int_relaxed(&sock_cloexec_works, 1); | |
| } | |
| else if (errno == EINVAL) { | |
| /* Linux older than 2.6.27 does not support SOCK_CLOEXEC */ | |
| _Py_atomic_store_int_relaxed(&sock_cloexec_works, 0); | |
| fd = socket(family, type, proto); | |
| } | |
| } | |
| } | |
| else | |
| #endif | |
| { | |
| fd = socket(family, type, proto); | |
| } | |
| Py_END_ALLOW_THREADS | |
| if (fd == INVALID_SOCKET) { | |
| set_error(); | |
| return -1; | |
| } | |
| if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { | |
| SOCKETCLOSE(fd); | |
| return -1; | |
| } | |
| #endif | |
| } | |
| if (init_sockobject(state, self, fd, family, type, proto) == -1) { | |
| SOCKETCLOSE(fd); | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| /* Type object for socket objects. */ | |
| static PyType_Slot sock_slots[] = { | |
| {Py_tp_dealloc, sock_dealloc}, | |
| {Py_tp_traverse, _PyObject_VisitType}, | |
| {Py_tp_repr, sock_repr}, | |
| {Py_tp_doc, (void *)sock_doc}, | |
| {Py_tp_methods, sock_methods}, | |
| {Py_tp_members, sock_memberlist}, | |
| {Py_tp_getset, sock_getsetlist}, | |
| {Py_tp_init, sock_initobj}, | |
| {Py_tp_new, sock_new}, | |
| {Py_tp_finalize, sock_finalize}, | |
| {0, NULL}, | |
| }; | |
| static PyType_Spec sock_spec = { | |
| .name = "_socket.socket", | |
| .basicsize = sizeof(PySocketSockObject), | |
| .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | | |
| Py_TPFLAGS_IMMUTABLETYPE), | |
| .slots = sock_slots, | |
| }; | |
| #ifdef HAVE_GETHOSTNAME | |
| /* Python interface to gethostname(). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.gethostname | |
| Return the current host name. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_gethostname_impl(PyObject *module) | |
| /*[clinic end generated code: output=1d9b789d69464c01 input=994028f092f41baf]*/ | |
| { | |
| if (PySys_Audit("socket.gethostname", NULL) < 0) { | |
| return NULL; | |
| } | |
| #ifdef MS_WINDOWS | |
| /* Don't use winsock's gethostname, as this returns the ANSI | |
| version of the hostname, whereas we need a Unicode string. | |
| Otherwise, gethostname apparently also returns the DNS name. */ | |
| wchar_t buf[MAX_COMPUTERNAME_LENGTH + 1]; | |
| DWORD size = Py_ARRAY_LENGTH(buf); | |
| #ifdef MS_WINDOWS_DESKTOP | |
| if (GetComputerNameExW(ComputerNamePhysicalDnsHostname, buf, &size)) | |
| #else | |
| if (GetComputerNameW(buf, &size)) | |
| #endif | |
| return PyUnicode_FromWideChar(buf, size); | |
| if (GetLastError() != ERROR_MORE_DATA) | |
| return PyErr_SetFromWindowsErr(0); | |
| if (size == 0) | |
| return Py_GetConstant(Py_CONSTANT_EMPTY_STR); | |
| #ifndef MS_WINDOWS_DESKTOP | |
| return NULL; | |
| #else | |
| /* MSDN says ERROR_MORE_DATA may occur because DNS allows longer | |
| names */ | |
| wchar_t* name = PyMem_New(wchar_t, size); | |
| if (!name) { | |
| PyErr_NoMemory(); | |
| return NULL; | |
| } | |
| if (!GetComputerNameExW(ComputerNamePhysicalDnsHostname, | |
| name, | |
| &size)) | |
| { | |
| PyErr_SetFromWindowsErr(0); | |
| PyMem_Free(name); | |
| return NULL; | |
| } | |
| PyObject* result = PyUnicode_FromWideChar(name, size); | |
| PyMem_Free(name); | |
| return result; | |
| #endif | |
| #else | |
| char buf[1024]; | |
| int res; | |
| Py_BEGIN_ALLOW_THREADS | |
| res = gethostname(buf, (int) sizeof buf - 1); | |
| Py_END_ALLOW_THREADS | |
| if (res < 0) | |
| return set_error(); | |
| buf[sizeof buf - 1] = '\0'; | |
| return PyUnicode_DecodeFSDefault(buf); | |
| #endif | |
| } | |
| #endif | |
| #ifdef HAVE_SETHOSTNAME | |
| /*[clinic input] | |
| _socket.sethostname | |
| name as hnobj: object | |
| / | |
| Set the hostname to name. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_sethostname(PyObject *module, PyObject *hnobj) | |
| /*[clinic end generated code: output=0b789350cbbc4553 input=89c1a7022cb1082a]*/ | |
| { | |
| Py_buffer buf; | |
| int res, flag = 0; | |
| #ifdef __ANDROID__ | |
| // On Android, calling this function as a non-root user leads to a process crash | |
| // rather than returning a permission error. | |
| if (getuid() != 0) { | |
| errno = EPERM; | |
| return set_error(); | |
| } | |
| #endif | |
| #if defined(_AIX) || (defined(__sun) && defined(__SVR4) && Py_SUNOS_VERSION <= 510) | |
| /* issue #18259, sethostname is not declared in any useful header file on AIX | |
| * the same is true for Solaris 10 */ | |
| extern int sethostname(const char *, size_t); | |
| #endif | |
| if (!PyBytes_Check(hnobj)) { | |
| if (!PyUnicode_FSConverter(hnobj, &hnobj)) { | |
| return NULL; | |
| } | |
| flag = 1; | |
| } | |
| if (PySys_Audit("socket.sethostname", "(O)", hnobj) < 0) { | |
| if (flag) | |
| Py_DECREF(hnobj); | |
| return NULL; | |
| } | |
| res = PyObject_GetBuffer(hnobj, &buf, PyBUF_SIMPLE); | |
| if (!res) { | |
| res = sethostname(buf.buf, buf.len); | |
| PyBuffer_Release(&buf); | |
| } | |
| if (flag) | |
| Py_DECREF(hnobj); | |
| if (res) | |
| return set_error(); | |
| Py_RETURN_NONE; | |
| } | |
| #endif | |
| #ifdef HAVE_GETADDRINFO | |
| /* Python interface to gethostbyname(name). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.gethostbyname | |
| host as hobj: object | |
| / | |
| Return the IP address for a host. | |
| The address is a string of the form '255.255.255.255'. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_gethostbyname(PyObject *module, PyObject *hobj) | |
| /*[clinic end generated code: output=19f571343780c48b input=3c0d3b92e44a1795]*/ | |
| { | |
| struct sockaddr_in addrbuf; | |
| char *name; | |
| PyObject *ret = NULL; | |
| if (!PyArg_Parse(hobj, "et:gethostbyname", "idna", &name)) { | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.gethostbyname", "(O)", hobj) < 0) { | |
| goto finally; | |
| } | |
| socket_state *state = get_module_state(module); | |
| int rc = setipaddr(state, name, (struct sockaddr *)&addrbuf, | |
| sizeof(addrbuf), AF_INET); | |
| if (rc < 0) { | |
| goto finally; | |
| } | |
| ret = make_ipv4_addr(&addrbuf); | |
| finally: | |
| PyMem_Free(name); | |
| return ret; | |
| } | |
| #endif | |
| #if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME) || defined (HAVE_GETHOSTBYADDR) | |
| static PyObject* | |
| sock_decode_hostname(const char *name) | |
| { | |
| #ifdef MS_WINDOWS | |
| /* Issue #26227: gethostbyaddr() returns a string encoded | |
| * to the ANSI code page */ | |
| return PyUnicode_DecodeMBCS(name, strlen(name), "surrogatepass"); | |
| #else | |
| /* Decode from UTF-8 */ | |
| return PyUnicode_FromString(name); | |
| #endif | |
| } | |
| /* Convenience function common to gethostbyname_ex and gethostbyaddr */ | |
| static PyObject * | |
| gethost_common(socket_state *state, struct hostent *h, struct sockaddr *addr, | |
| size_t alen, int af, int h_error) | |
| { | |
| char **pch; | |
| PyObject *rtn_tuple = (PyObject *)NULL; | |
| PyObject *name_list = (PyObject *)NULL; | |
| PyObject *addr_list = (PyObject *)NULL; | |
| PyObject *tmp; | |
| PyObject *name; | |
| if (h == NULL) { | |
| /* Let's get real error message to return */ | |
| set_herror(state, h_error); | |
| return NULL; | |
| } | |
| if (h->h_addrtype != af) { | |
| /* Let's get real error message to return */ | |
| errno = EAFNOSUPPORT; | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| return NULL; | |
| } | |
| switch (af) { | |
| case AF_INET: | |
| if (alen < sizeof(struct sockaddr_in)) | |
| return NULL; | |
| break; | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| if (alen < sizeof(struct sockaddr_in6)) | |
| return NULL; | |
| break; | |
| #endif | |
| } | |
| if ((name_list = PyList_New(0)) == NULL) | |
| goto err; | |
| if ((addr_list = PyList_New(0)) == NULL) | |
| goto err; | |
| /* SF #1511317: h_aliases can be NULL */ | |
| if (h->h_aliases) { | |
| for (pch = h->h_aliases; ; pch++) { | |
| int status; | |
| char *host_alias; | |
| // pch can be misaligned | |
| memcpy(&host_alias, pch, sizeof(host_alias)); | |
| if (host_alias == NULL) { | |
| break; | |
| } | |
| tmp = PyUnicode_FromString(host_alias); | |
| if (tmp == NULL) | |
| goto err; | |
| status = PyList_Append(name_list, tmp); | |
| Py_DECREF(tmp); | |
| if (status) | |
| goto err; | |
| } | |
| } | |
| for (pch = h->h_addr_list; ; pch++) { | |
| int status; | |
| char *host_address; | |
| // pch can be misaligned | |
| memcpy(&host_address, pch, sizeof(host_address)); | |
| if (host_address == NULL) { | |
| break; | |
| } | |
| switch (af) { | |
| case AF_INET: | |
| { | |
| struct sockaddr_in sin; | |
| memset(&sin, 0, sizeof(sin)); | |
| sin.sin_family = af; | |
| #ifdef HAVE_SOCKADDR_SA_LEN | |
| sin.sin_len = sizeof(sin); | |
| #endif | |
| memcpy(&sin.sin_addr, host_address, sizeof(sin.sin_addr)); | |
| tmp = make_ipv4_addr(&sin); | |
| if (pch == h->h_addr_list && alen >= sizeof(sin)) | |
| memcpy((char *) addr, &sin, sizeof(sin)); | |
| break; | |
| } | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| { | |
| struct sockaddr_in6 sin6; | |
| memset(&sin6, 0, sizeof(sin6)); | |
| sin6.sin6_family = af; | |
| #ifdef HAVE_SOCKADDR_SA_LEN | |
| sin6.sin6_len = sizeof(sin6); | |
| #endif | |
| memcpy(&sin6.sin6_addr, host_address, sizeof(sin6.sin6_addr)); | |
| tmp = make_ipv6_addr(&sin6); | |
| if (pch == h->h_addr_list && alen >= sizeof(sin6)) | |
| memcpy((char *) addr, &sin6, sizeof(sin6)); | |
| break; | |
| } | |
| #endif | |
| default: /* can't happen */ | |
| PyErr_SetString(PyExc_OSError, | |
| "unsupported address family"); | |
| return NULL; | |
| } | |
| if (tmp == NULL) | |
| goto err; | |
| status = PyList_Append(addr_list, tmp); | |
| Py_DECREF(tmp); | |
| if (status) | |
| goto err; | |
| } | |
| name = sock_decode_hostname(h->h_name); | |
| if (name == NULL) | |
| goto err; | |
| rtn_tuple = Py_BuildValue("NOO", name, name_list, addr_list); | |
| err: | |
| Py_XDECREF(name_list); | |
| Py_XDECREF(addr_list); | |
| return rtn_tuple; | |
| } | |
| #endif | |
| #if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME) | |
| /* Python interface to gethostbyname_ex(name). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.gethostbyname_ex | |
| host as hobj: object | |
| / | |
| Map a host name to its IP number. | |
| Return the true host name, a list of aliases, and a list of IP | |
| addresses, which are strings of the form '255.255.255.255'. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_gethostbyname_ex(PyObject *module, PyObject *hobj) | |
| /*[clinic end generated code: output=a1ea4607d257756e input=1ee9eb485339c58b]*/ | |
| { | |
| char *name; | |
| int h_error; | |
| struct hostent *h; | |
| sock_addr_t addr; | |
| struct sockaddr *sa; | |
| PyObject *ret = NULL; | |
| #ifdef HAVE_GETHOSTBYNAME_R | |
| struct hostent hp_allocated; | |
| #ifdef HAVE_GETHOSTBYNAME_R_3_ARG | |
| struct hostent_data data; | |
| #else | |
| char buf[16384]; | |
| int buf_len = (sizeof buf) - 1; | |
| #endif | |
| #ifdef HAVE_GETHOSTBYNAME_R_3_ARG | |
| int result; | |
| #endif | |
| #endif /* HAVE_GETHOSTBYNAME_R */ | |
| if (!PyArg_Parse(hobj, "et:gethostbyname_ex", "idna", &name)) { | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.gethostbyname", "(O)", hobj) < 0) { | |
| goto finally; | |
| } | |
| socket_state *state = get_module_state(module); | |
| if (setipaddr(state, name, SAS2SA(&addr), sizeof(addr), AF_INET) < 0) { | |
| goto finally; | |
| } | |
| Py_BEGIN_ALLOW_THREADS | |
| #ifdef HAVE_GETHOSTBYNAME_R | |
| #if defined(HAVE_GETHOSTBYNAME_R_6_ARG) | |
| gethostbyname_r(name, &hp_allocated, buf, buf_len, &h, &h_error); | |
| #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG) | |
| h = gethostbyname_r(name, &hp_allocated, buf, buf_len, &h_error); | |
| #else /* HAVE_GETHOSTBYNAME_R_3_ARG */ | |
| memset((void *) &data, '\0', sizeof(data)); | |
| result = gethostbyname_r(name, &hp_allocated, &data); | |
| h = (result != 0) ? NULL : &hp_allocated; | |
| h_error = h_errno; | |
| #endif | |
| #else /* not HAVE_GETHOSTBYNAME_R */ | |
| #ifdef USE_GETHOSTBYNAME_LOCK | |
| PyMutex_Lock(&netdb_lock); | |
| #endif | |
| _Py_COMP_DIAG_PUSH | |
| _Py_COMP_DIAG_IGNORE_DEPR_DECLS | |
| h = gethostbyname(name); | |
| _Py_COMP_DIAG_POP | |
| h_error = h_errno; | |
| #endif /* HAVE_GETHOSTBYNAME_R */ | |
| Py_END_ALLOW_THREADS | |
| /* Some C libraries would require addr.__ss_family instead of | |
| addr.ss_family. | |
| Therefore, we cast the sockaddr_storage into sockaddr to | |
| access sa_family. */ | |
| sa = SAS2SA(&addr); | |
| ret = gethost_common(state, h, SAS2SA(&addr), sizeof(addr), | |
| sa->sa_family, h_error); | |
| #ifdef USE_GETHOSTBYNAME_LOCK | |
| PyMutex_Unlock(&netdb_lock); | |
| #endif | |
| finally: | |
| PyMem_Free(name); | |
| return ret; | |
| } | |
| #endif | |
| #if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR) | |
| /* Python interface to gethostbyaddr(IP). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.gethostbyaddr | |
| host as hobj: object | |
| / | |
| Map an IP number or host name to the true host name and addresses. | |
| Return the true host name, a list of aliases, and a list of IP | |
| addresses. The host argument is a string giving a host name or IP | |
| number. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_gethostbyaddr(PyObject *module, PyObject *hobj) | |
| /*[clinic end generated code: output=4ba6c4d7a3085ab5 input=c602ba97bf0d395b]*/ | |
| { | |
| char *ip_num; | |
| sock_addr_t addr; | |
| struct sockaddr *sa = SAS2SA(&addr); | |
| struct hostent *h; | |
| PyObject *ret = NULL; | |
| #ifdef HAVE_GETHOSTBYNAME_R | |
| struct hostent hp_allocated; | |
| #ifdef HAVE_GETHOSTBYNAME_R_3_ARG | |
| struct hostent_data data; | |
| #else | |
| /* glibcs up to 2.10 assume that the buf argument to | |
| gethostbyaddr_r is 8-byte aligned, which at least llvm-gcc | |
| does not ensure. The attribute below instructs the compiler | |
| to maintain this alignment. */ | |
| _Py_ALIGNED_DEF(8, char) buf[16384]; | |
| int buf_len = (sizeof buf) - 1; | |
| #endif | |
| #ifdef HAVE_GETHOSTBYNAME_R_3_ARG | |
| int result; | |
| #endif | |
| #endif /* HAVE_GETHOSTBYNAME_R */ | |
| const char *ap; | |
| int al; | |
| int af; | |
| int h_error; | |
| if (!PyArg_Parse(hobj, "et:gethostbyaddr", "idna", &ip_num)) { | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.gethostbyaddr", "(O)", hobj) < 0) { | |
| goto finally; | |
| } | |
| af = AF_UNSPEC; | |
| socket_state *state = get_module_state(module); | |
| if (setipaddr(state, ip_num, sa, sizeof(addr), af) < 0) { | |
| goto finally; | |
| } | |
| af = sa->sa_family; | |
| ap = NULL; | |
| /* al = 0; */ | |
| switch (af) { | |
| case AF_INET: | |
| ap = (char *)&((struct sockaddr_in *)sa)->sin_addr; | |
| al = sizeof(((struct sockaddr_in *)sa)->sin_addr); | |
| break; | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| ap = (char *)&((struct sockaddr_in6 *)sa)->sin6_addr; | |
| al = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); | |
| break; | |
| #endif | |
| default: | |
| PyErr_SetString(PyExc_OSError, "unsupported address family"); | |
| goto finally; | |
| } | |
| Py_BEGIN_ALLOW_THREADS | |
| #ifdef HAVE_GETHOSTBYNAME_R | |
| #if defined(HAVE_GETHOSTBYNAME_R_6_ARG) | |
| gethostbyaddr_r(ap, al, af, &hp_allocated, buf, buf_len, &h, &h_error); | |
| #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG) | |
| h = gethostbyaddr_r(ap, al, af, &hp_allocated, buf, buf_len, &h_error); | |
| #else /* HAVE_GETHOSTBYNAME_R_3_ARG */ | |
| memset((void *) &data, '\0', sizeof(data)); | |
| result = gethostbyaddr_r(ap, al, af, &hp_allocated, &data); | |
| h = (result != 0) ? NULL : &hp_allocated; | |
| h_error = h_errno; | |
| #endif | |
| #else /* not HAVE_GETHOSTBYNAME_R */ | |
| #ifdef USE_GETHOSTBYNAME_LOCK | |
| PyMutex_Lock(&netdb_lock); | |
| #endif | |
| _Py_COMP_DIAG_PUSH | |
| _Py_COMP_DIAG_IGNORE_DEPR_DECLS | |
| h = gethostbyaddr(ap, al, af); | |
| _Py_COMP_DIAG_POP | |
| h_error = h_errno; | |
| #endif /* HAVE_GETHOSTBYNAME_R */ | |
| Py_END_ALLOW_THREADS | |
| ret = gethost_common(state, h, SAS2SA(&addr), sizeof(addr), af, h_error); | |
| #ifdef USE_GETHOSTBYNAME_LOCK | |
| PyMutex_Unlock(&netdb_lock); | |
| #endif | |
| finally: | |
| PyMem_Free(ip_num); | |
| return ret; | |
| } | |
| #endif | |
| #ifdef HAVE_GETSERVBYNAME | |
| /* Python interface to getservbyname(name). | |
| This only returns the port number, since the other info is already | |
| known or not useful (like the list of aliases). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.getservbyname | |
| servicename as name: str | |
| protocolname as proto: str = NULL | |
| / | |
| Return a port number from a service name and protocol name. | |
| The optional protocol name, if given, should be 'tcp' or 'udp', | |
| otherwise any protocol will match. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_getservbyname_impl(PyObject *module, const char *name, | |
| const char *proto) | |
| /*[clinic end generated code: output=b0c47287f8ec2b00 input=a8e3ad7ced8c8798]*/ | |
| { | |
| struct servent *sp; | |
| if (PySys_Audit("socket.getservbyname", "ss", name, proto) < 0) { | |
| return NULL; | |
| } | |
| Py_BEGIN_ALLOW_THREADS | |
| sp = getservbyname(name, proto); | |
| Py_END_ALLOW_THREADS | |
| if (sp == NULL) { | |
| PyErr_SetString(PyExc_OSError, "service/proto not found"); | |
| return NULL; | |
| } | |
| return PyLong_FromLong((long) ntohs(sp->s_port)); | |
| } | |
| #endif | |
| #ifdef HAVE_GETSERVBYPORT | |
| /* Python interface to getservbyport(port). | |
| This only returns the service name, since the other info is already | |
| known or not useful (like the list of aliases). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.getservbyport | |
| port: int | |
| protocolname as proto: str = NULL | |
| / | |
| Return the service name from a port number and protocol name. | |
| The optional protocol name, if given, should be 'tcp' or 'udp', | |
| otherwise any protocol will match. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_getservbyport_impl(PyObject *module, int port, const char *proto) | |
| /*[clinic end generated code: output=42351ab1857aa9e4 input=9a2a3091ea6ff146]*/ | |
| { | |
| struct servent *sp; | |
| if (port < 0 || port > 0xffff) { | |
| PyErr_SetString( | |
| PyExc_OverflowError, | |
| "getservbyport: port must be 0-65535."); | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.getservbyport", "is", port, proto) < 0) { | |
| return NULL; | |
| } | |
| Py_BEGIN_ALLOW_THREADS | |
| sp = getservbyport(htons((short)port), proto); | |
| Py_END_ALLOW_THREADS | |
| if (sp == NULL) { | |
| PyErr_SetString(PyExc_OSError, "port/proto not found"); | |
| return NULL; | |
| } | |
| _Py_MSAN_UNPOISON_STRING(sp->s_name); | |
| return PyUnicode_FromString(sp->s_name); | |
| } | |
| #endif | |
| #ifdef HAVE_GETPROTOBYNAME | |
| /* Python interface to getprotobyname(name). | |
| This only returns the protocol number, since the other info is | |
| already known or not useful (like the list of aliases). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.getprotobyname | |
| name: str | |
| / | |
| Return the protocol number for the named protocol. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_getprotobyname_impl(PyObject *module, const char *name) | |
| /*[clinic end generated code: output=30fb71f0c6ffbaea input=d197d3726c828e38]*/ | |
| { | |
| struct protoent *sp; | |
| Py_BEGIN_ALLOW_THREADS | |
| sp = getprotobyname(name); | |
| Py_END_ALLOW_THREADS | |
| if (sp == NULL) { | |
| PyErr_SetString(PyExc_OSError, "protocol not found"); | |
| return NULL; | |
| } | |
| return PyLong_FromLong((long) sp->p_proto); | |
| } | |
| #endif | |
| /*[clinic input] | |
| _socket.close | |
| fd as fdobj: object | |
| / | |
| Close a socket fd. | |
| This is like os.close(), but for sockets; on some platforms os.close() | |
| won't work for socket file descriptors. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_close(PyObject *module, PyObject *fdobj) | |
| /*[clinic end generated code: output=1d62092e6fc365dc input=b9fc18380117ee4b]*/ | |
| { | |
| SOCKET_T fd; | |
| int res; | |
| fd = PyLong_AsSocket_t(fdobj); | |
| if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) | |
| return NULL; | |
| Py_BEGIN_ALLOW_THREADS | |
| res = SOCKETCLOSE(fd); | |
| Py_END_ALLOW_THREADS | |
| /* bpo-30319: The peer can already have closed the connection. | |
| Python ignores ECONNRESET on close(). */ | |
| if (res < 0 && !CHECK_ERRNO(ECONNRESET)) { | |
| return set_error(); | |
| } | |
| Py_RETURN_NONE; | |
| } | |
| #ifndef NO_DUP | |
| /* dup() function for socket fds */ | |
| /*[clinic input] | |
| _socket.dup | |
| fd as fdobj: object | |
| / | |
| Duplicate a socket descriptor. | |
| The new descriptor is non-inheritable. This is like os.dup(), but for | |
| sockets; on some platforms os.dup() won't work for socket file | |
| descriptors. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_dup(PyObject *module, PyObject *fdobj) | |
| /*[clinic end generated code: output=7e9c4485cf5a76c0 input=d1d74c320feb3d04]*/ | |
| { | |
| SOCKET_T fd, newfd; | |
| PyObject *newfdobj; | |
| #ifdef MS_WINDOWS | |
| WSAPROTOCOL_INFOW info; | |
| #endif | |
| fd = PyLong_AsSocket_t(fdobj); | |
| if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) { | |
| return NULL; | |
| } | |
| #ifdef MS_WINDOWS | |
| if (WSADuplicateSocketW(fd, GetCurrentProcessId(), &info)) | |
| return set_error(); | |
| newfd = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, | |
| FROM_PROTOCOL_INFO, | |
| &info, 0, WSA_FLAG_OVERLAPPED); | |
| if (newfd == INVALID_SOCKET) { | |
| return set_error(); | |
| } | |
| if (!SetHandleInformation((HANDLE)newfd, HANDLE_FLAG_INHERIT, 0)) { | |
| PyErr_SetFromWindowsErr(0); | |
| closesocket(newfd); | |
| return NULL; | |
| } | |
| #else | |
| /* On UNIX, dup can be used to duplicate the file descriptor of a socket */ | |
| newfd = _Py_dup(fd); | |
| if (newfd == INVALID_SOCKET) { | |
| return NULL; | |
| } | |
| #endif | |
| newfdobj = PyLong_FromSocket_t(newfd); | |
| if (newfdobj == NULL) { | |
| SOCKETCLOSE(newfd); | |
| } | |
| return newfdobj; | |
| } | |
| #endif | |
| #ifdef HAVE_SOCKETPAIR | |
| /* Create a pair of sockets using the socketpair() function. | |
| Arguments as for socket() except the default family is AF_UNIX if | |
| defined on the platform; otherwise, the default is AF_INET. */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.socketpair | |
| family: int(c_default="SOCKETPAIR_DEFAULT_FAMILY") = AF_UNIX | |
| type: int(c_default="SOCK_STREAM") = SOCK_STREAM | |
| proto: int = 0 | |
| / | |
| Create a pair of connected socket objects. | |
| The sockets are returned by the platform socketpair() function. The | |
| arguments are the same as for socket(), except that the default | |
| family is AF_UNIX if defined on the platform; otherwise, the default | |
| is AF_INET. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_socketpair_impl(PyObject *module, int family, int type, int proto) | |
| /*[clinic end generated code: output=c012ae1f558bb0ca input=59695511a31a2d52]*/ | |
| { | |
| PySocketSockObject *s0 = NULL, *s1 = NULL; | |
| SOCKET_T sv[2]; | |
| socket_state *state = get_module_state(module); | |
| #ifdef SOCK_CLOEXEC | |
| int *atomic_flag_works = &sock_cloexec_works; | |
| #else | |
| int *atomic_flag_works = NULL; | |
| #endif | |
| int ret; | |
| /* Create a pair of socket fds */ | |
| Py_BEGIN_ALLOW_THREADS | |
| #ifdef SOCK_CLOEXEC | |
| if (_Py_atomic_load_int_relaxed(&sock_cloexec_works) != 0) { | |
| ret = socketpair(family, type | SOCK_CLOEXEC, proto, sv); | |
| if (_Py_atomic_load_int_relaxed(&sock_cloexec_works) == -1) { | |
| if (ret >= 0) { | |
| _Py_atomic_store_int_relaxed(&sock_cloexec_works, 1); | |
| } | |
| else if (errno == EINVAL) { | |
| /* Linux older than 2.6.27 does not support SOCK_CLOEXEC */ | |
| _Py_atomic_store_int_relaxed(&sock_cloexec_works, 0); | |
| ret = socketpair(family, type, proto, sv); | |
| } | |
| } | |
| } | |
| else | |
| #endif | |
| { | |
| ret = socketpair(family, type, proto, sv); | |
| } | |
| Py_END_ALLOW_THREADS | |
| if (ret < 0) | |
| return set_error(); | |
| if (_Py_set_inheritable(sv[0], 0, atomic_flag_works) < 0) | |
| goto error; | |
| if (_Py_set_inheritable(sv[1], 0, atomic_flag_works) < 0) | |
| goto error; | |
| s0 = new_sockobject(state, sv[0], family, type, proto); | |
| if (s0 == NULL) | |
| goto error; | |
| s1 = new_sockobject(state, sv[1], family, type, proto); | |
| if (s1 == NULL) | |
| goto error; | |
| return _PyTuple_FromPairSteal((PyObject *)s0, (PyObject *)s1); | |
| error: | |
| if (s0 == NULL) | |
| SOCKETCLOSE(sv[0]); | |
| if (s1 == NULL) | |
| SOCKETCLOSE(sv[1]); | |
| Py_XDECREF(s0); | |
| Py_XDECREF(s1); | |
| return NULL; | |
| } | |
| #endif /* HAVE_SOCKETPAIR */ | |
| /*[clinic input] | |
| _socket.ntohs | |
| integer as x: uint16 | |
| / | |
| Convert a 16-bit unsigned integer from network to host byte order. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_ntohs_impl(PyObject *module, uint16_t x) | |
| /*[clinic end generated code: output=8e991859ddcedcc9 input=a702372437396511]*/ | |
| { | |
| return PyLong_FromUnsignedLong(ntohs(x)); | |
| } | |
| /*[clinic input] | |
| _socket.ntohl | |
| integer as x: uint32 | |
| / | |
| Convert a 32-bit unsigned integer from network to host byte order. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_ntohl_impl(PyObject *module, uint32_t x) | |
| /*[clinic end generated code: output=158bcc5ba449f795 input=a0406faf2236bd1f]*/ | |
| { | |
| return PyLong_FromUnsignedLong(ntohl(x)); | |
| } | |
| /*[clinic input] | |
| _socket.htons | |
| integer as x: uint16 | |
| / | |
| Convert a 16-bit unsigned integer from host to network byte order. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_htons_impl(PyObject *module, uint16_t x) | |
| /*[clinic end generated code: output=35aa2bcc370fd80b input=78047a26d51866d1]*/ | |
| { | |
| return PyLong_FromUnsignedLong(htons(x)); | |
| } | |
| /*[clinic input] | |
| _socket.htonl | |
| integer as x: uint32 | |
| / | |
| Convert a 32-bit unsigned integer from host to network byte order. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_htonl_impl(PyObject *module, uint32_t x) | |
| /*[clinic end generated code: output=283eb6857d5f7e0d input=89a9077647082806]*/ | |
| { | |
| return PyLong_FromUnsignedLong(htonl(x)); | |
| } | |
| /* socket.inet_aton() and socket.inet_ntoa() functions. */ | |
| /*[clinic input] | |
| @permit_long_summary | |
| _socket.inet_aton | |
| ip_addr: str | |
| / | |
| Convert an IP address in string format (123.45.67.89) to the 32-bit packed binary format used in low-level network functions. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_inet_aton_impl(PyObject *module, const char *ip_addr) | |
| /*[clinic end generated code: output=f2c2f772eb721b6e input=0bd9e5ee400fafd6]*/ | |
| { | |
| #ifdef HAVE_INET_ATON | |
| struct in_addr buf; | |
| #endif | |
| #if !defined(HAVE_INET_ATON) || defined(USE_INET_ATON_WEAKLINK) | |
| #if (SIZEOF_INT != 4) | |
| #error "Not sure if in_addr_t exists and int is not 32-bits." | |
| #endif | |
| /* Have to use inet_addr() instead */ | |
| unsigned int packed_addr; | |
| #endif | |
| #ifdef HAVE_INET_ATON | |
| #ifdef USE_INET_ATON_WEAKLINK | |
| if (inet_aton != NULL) { | |
| #endif | |
| if (inet_aton(ip_addr, &buf)) | |
| return PyBytes_FromStringAndSize((char *)(&buf), | |
| sizeof(buf)); | |
| PyErr_SetString(PyExc_OSError, | |
| "illegal IP address string passed to inet_aton"); | |
| return NULL; | |
| #ifdef USE_INET_ATON_WEAKLINK | |
| } else { | |
| #endif | |
| #endif | |
| #if !defined(HAVE_INET_ATON) || defined(USE_INET_ATON_WEAKLINK) | |
| /* special-case this address as inet_addr might return INADDR_NONE | |
| * for this */ | |
| if (strcmp(ip_addr, "255.255.255.255") == 0) { | |
| packed_addr = INADDR_BROADCAST; | |
| } else { | |
| _Py_COMP_DIAG_PUSH | |
| _Py_COMP_DIAG_IGNORE_DEPR_DECLS | |
| packed_addr = inet_addr(ip_addr); | |
| _Py_COMP_DIAG_POP | |
| if (packed_addr == INADDR_NONE) { /* invalid address */ | |
| PyErr_SetString(PyExc_OSError, | |
| "illegal IP address string passed to inet_aton"); | |
| return NULL; | |
| } | |
| } | |
| return PyBytes_FromStringAndSize((char *) &packed_addr, | |
| sizeof(packed_addr)); | |
| #ifdef USE_INET_ATON_WEAKLINK | |
| } | |
| #endif | |
| #endif | |
| } | |
| #ifdef HAVE_INET_NTOA | |
| /*[clinic input] | |
| _socket.inet_ntoa | |
| packed_ip: Py_buffer | |
| / | |
| Convert an IP address from 32-bit packed binary format to string format. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_inet_ntoa_impl(PyObject *module, Py_buffer *packed_ip) | |
| /*[clinic end generated code: output=3077324c50af0935 input=2850d4f57e4db345]*/ | |
| { | |
| struct in_addr packed_addr; | |
| if (packed_ip->len != sizeof(packed_addr)) { | |
| PyErr_SetString(PyExc_OSError, | |
| "packed IP wrong length for inet_ntoa"); | |
| PyBuffer_Release(packed_ip); | |
| return NULL; | |
| } | |
| memcpy(&packed_addr, packed_ip->buf, packed_ip->len); | |
| PyBuffer_Release(packed_ip); | |
| _Py_COMP_DIAG_PUSH | |
| _Py_COMP_DIAG_IGNORE_DEPR_DECLS | |
| return PyUnicode_FromString(inet_ntoa(packed_addr)); | |
| _Py_COMP_DIAG_POP | |
| } | |
| #endif // HAVE_INET_NTOA | |
| #ifdef HAVE_INET_PTON | |
| /*[clinic input] | |
| _socket.inet_pton | |
| af: int | |
| ip: str | |
| / | |
| Convert an IP address from string format to a packed string. | |
| The string is suitable for use with low-level network functions. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_inet_pton_impl(PyObject *module, int af, const char *ip) | |
| /*[clinic end generated code: output=a1488ddddc478dc2 input=044acc246469c125]*/ | |
| { | |
| int retval; | |
| #ifdef ENABLE_IPV6 | |
| char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; | |
| #else | |
| char packed[sizeof(struct in_addr)]; | |
| #endif | |
| #if !defined(ENABLE_IPV6) && defined(AF_INET6) | |
| if(af == AF_INET6) { | |
| PyErr_SetString(PyExc_OSError, | |
| "can't use AF_INET6, IPv6 is disabled"); | |
| return NULL; | |
| } | |
| #endif | |
| retval = inet_pton(af, ip, packed); | |
| if (retval < 0) { | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| return NULL; | |
| } else if (retval == 0) { | |
| PyErr_SetString(PyExc_OSError, | |
| "illegal IP address string passed to inet_pton"); | |
| return NULL; | |
| } else if (af == AF_INET) { | |
| return PyBytes_FromStringAndSize(packed, | |
| sizeof(struct in_addr)); | |
| #ifdef ENABLE_IPV6 | |
| } else if (af == AF_INET6) { | |
| return PyBytes_FromStringAndSize(packed, | |
| sizeof(struct in6_addr)); | |
| #endif | |
| } else { | |
| PyErr_SetString(PyExc_OSError, "unknown address family"); | |
| return NULL; | |
| } | |
| } | |
| /*[clinic input] | |
| _socket.inet_ntop | |
| af: int | |
| packed_ip: Py_buffer | |
| / | |
| Convert a packed IP address of the given family to string format. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_inet_ntop_impl(PyObject *module, int af, Py_buffer *packed_ip) | |
| /*[clinic end generated code: output=eabff3e56456ede0 input=7027f0a0abdf71d1]*/ | |
| { | |
| const char* retval; | |
| #ifdef ENABLE_IPV6 | |
| char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; | |
| #else | |
| char ip[INET_ADDRSTRLEN]; | |
| #endif | |
| if (af == AF_INET) { | |
| if (packed_ip->len != sizeof(struct in_addr)) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "invalid length of packed IP address string"); | |
| return NULL; | |
| } | |
| #ifdef ENABLE_IPV6 | |
| } else if (af == AF_INET6) { | |
| if (packed_ip->len != sizeof(struct in6_addr)) { | |
| PyErr_SetString(PyExc_ValueError, | |
| "invalid length of packed IP address string"); | |
| return NULL; | |
| } | |
| #endif | |
| } else { | |
| PyErr_Format(PyExc_ValueError, | |
| "unknown address family %d", af); | |
| return NULL; | |
| } | |
| /* inet_ntop guarantee NUL-termination of resulting string. */ | |
| retval = inet_ntop(af, packed_ip->buf, ip, sizeof(ip)); | |
| if (!retval) { | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| return NULL; | |
| } | |
| return PyUnicode_FromString(retval); | |
| } | |
| #endif /* HAVE_INET_PTON */ | |
| #ifdef HAVE_GETADDRINFO | |
| /* Python interface to getaddrinfo(host, port). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.getaddrinfo | |
| host as hobj: object | |
| port as pobj: object | |
| family: int(c_default="AF_UNSPEC") = AF_UNSPEC | |
| type as socktype: int = 0 | |
| proto as protocol: int = 0 | |
| flags: int = 0 | |
| Resolve host and port into a list of 5-tuples. | |
| Each tuple is (family, type, proto, canonname, sockaddr). | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_getaddrinfo_impl(PyObject *module, PyObject *hobj, PyObject *pobj, | |
| int family, int socktype, int protocol, int flags) | |
| /*[clinic end generated code: output=a54f59f33f3da184 input=1fd64ac89aee1d18]*/ | |
| { | |
| struct addrinfo hints, *res; | |
| struct addrinfo *res0 = NULL; | |
| PyObject *pstr = NULL; | |
| const char *hptr, *pptr; | |
| int error; | |
| PyObject *all = (PyObject *)NULL; | |
| PyObject *idna = NULL; | |
| if (hobj == Py_None) { | |
| hptr = NULL; | |
| } else if (PyUnicode_Check(hobj)) { | |
| idna = PyUnicode_AsEncodedString(hobj, "idna", NULL); | |
| if (!idna) | |
| return NULL; | |
| assert(PyBytes_Check(idna)); | |
| hptr = PyBytes_AS_STRING(idna); | |
| } else if (PyBytes_Check(hobj)) { | |
| hptr = PyBytes_AsString(hobj); | |
| } else { | |
| PyErr_SetString(PyExc_TypeError, | |
| "getaddrinfo() argument 1 must be string or None"); | |
| return NULL; | |
| } | |
| if (PyIndex_Check(pobj)) { | |
| pstr = PyNumber_Index(pobj); | |
| if (pstr == NULL) | |
| goto err; | |
| assert(PyLong_CheckExact(pstr)); | |
| Py_SETREF(pstr, PyObject_Str(pstr)); | |
| if (pstr == NULL) | |
| goto err; | |
| assert(PyUnicode_Check(pstr)); | |
| pptr = PyUnicode_AsUTF8(pstr); | |
| if (pptr == NULL) | |
| goto err; | |
| } else if (PyUnicode_Check(pobj)) { | |
| pptr = PyUnicode_AsUTF8(pobj); | |
| if (pptr == NULL) | |
| goto err; | |
| } else if (PyBytes_Check(pobj)) { | |
| pptr = PyBytes_AS_STRING(pobj); | |
| } else if (pobj == Py_None) { | |
| pptr = (char *)NULL; | |
| } else { | |
| PyErr_SetString(PyExc_OSError, "Int or String expected"); | |
| goto err; | |
| } | |
| #if defined(__APPLE__) && defined(AI_NUMERICSERV) | |
| if ((flags & AI_NUMERICSERV) && (pptr == NULL || (pptr[0] == '0' && pptr[1] == 0))) { | |
| /* On OSX up to at least OSX 10.8 getaddrinfo crashes | |
| * if AI_NUMERICSERV is set and the servname is NULL or "0". | |
| * This workaround avoids a segfault in libsystem. | |
| */ | |
| pptr = "00"; | |
| } | |
| #endif | |
| if (PySys_Audit("socket.getaddrinfo", "OOiii", | |
| hobj, pobj, family, socktype, protocol) < 0) { | |
| goto err; | |
| } | |
| memset(&hints, 0, sizeof(hints)); | |
| hints.ai_family = family; | |
| hints.ai_socktype = socktype; | |
| hints.ai_protocol = protocol; | |
| hints.ai_flags = flags; | |
| Py_BEGIN_ALLOW_THREADS | |
| error = getaddrinfo(hptr, pptr, &hints, &res0); | |
| Py_END_ALLOW_THREADS | |
| if (error) { | |
| res0 = NULL; // gh-100795 | |
| socket_state *state = get_module_state(module); | |
| set_gaierror(state, error); | |
| goto err; | |
| } | |
| all = PyList_New(0); | |
| if (all == NULL) | |
| goto err; | |
| for (res = res0; res; res = res->ai_next) { | |
| PyObject *single; | |
| PyObject *addr = | |
| makesockaddr(-1, res->ai_addr, res->ai_addrlen, protocol); | |
| if (addr == NULL) | |
| goto err; | |
| single = Py_BuildValue("iiisO", res->ai_family, | |
| res->ai_socktype, res->ai_protocol, | |
| res->ai_canonname ? res->ai_canonname : "", | |
| addr); | |
| Py_DECREF(addr); | |
| if (single == NULL) | |
| goto err; | |
| if (PyList_Append(all, single)) { | |
| Py_DECREF(single); | |
| goto err; | |
| } | |
| Py_DECREF(single); | |
| } | |
| Py_XDECREF(idna); | |
| Py_XDECREF(pstr); | |
| if (res0) | |
| freeaddrinfo(res0); | |
| return all; | |
| err: | |
| Py_XDECREF(all); | |
| Py_XDECREF(idna); | |
| Py_XDECREF(pstr); | |
| if (res0) | |
| freeaddrinfo(res0); | |
| return (PyObject *)NULL; | |
| } | |
| #endif // HAVE_GETADDRINFO | |
| #ifdef HAVE_GETNAMEINFO | |
| /* Python interface to getnameinfo(sa, flags). */ | |
| /*ARGSUSED*/ | |
| /*[clinic input] | |
| _socket.getnameinfo | |
| sockaddr as sa: object | |
| flags: int | |
| / | |
| Get host and port for a sockaddr. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_getnameinfo_impl(PyObject *module, PyObject *sa, int flags) | |
| /*[clinic end generated code: output=2e1d7ef2bd94f698 input=dd0444ac9adae4d3]*/ | |
| { | |
| const char *hostp; | |
| int port; | |
| unsigned int flowinfo, scope_id; | |
| char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; | |
| struct addrinfo hints, *res = NULL; | |
| int error; | |
| PyObject *ret = (PyObject *)NULL; | |
| PyObject *name; | |
| flowinfo = scope_id = 0; | |
| if (!PyTuple_Check(sa)) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "getnameinfo() argument 1 must be a tuple"); | |
| return NULL; | |
| } | |
| if (!PyArg_ParseTuple(sa, "si|II;getnameinfo(): illegal sockaddr argument", | |
| &hostp, &port, &flowinfo, &scope_id)) | |
| { | |
| return NULL; | |
| } | |
| if (flowinfo > 0xfffff) { | |
| PyErr_SetString(PyExc_OverflowError, | |
| "getnameinfo(): flowinfo must be 0-1048575."); | |
| return NULL; | |
| } | |
| if (PySys_Audit("socket.getnameinfo", "(O)", sa) < 0) { | |
| return NULL; | |
| } | |
| PyOS_snprintf(pbuf, sizeof(pbuf), "%d", port); | |
| memset(&hints, 0, sizeof(hints)); | |
| hints.ai_family = AF_UNSPEC; | |
| hints.ai_socktype = SOCK_DGRAM; /* make numeric port happy */ | |
| hints.ai_flags = AI_NUMERICHOST; /* don't do any name resolution */ | |
| Py_BEGIN_ALLOW_THREADS | |
| error = getaddrinfo(hostp, pbuf, &hints, &res); | |
| Py_END_ALLOW_THREADS | |
| if (error) { | |
| res = NULL; // gh-100795 | |
| socket_state *state = get_module_state(module); | |
| set_gaierror(state, error); | |
| goto fail; | |
| } | |
| if (res->ai_next) { | |
| PyErr_SetString(PyExc_OSError, | |
| "sockaddr resolved to multiple addresses"); | |
| goto fail; | |
| } | |
| switch (res->ai_family) { | |
| case AF_INET: | |
| { | |
| if (PyTuple_GET_SIZE(sa) != 2) { | |
| PyErr_SetString(PyExc_OSError, | |
| "IPv4 sockaddr must be 2 tuple"); | |
| goto fail; | |
| } | |
| break; | |
| } | |
| #ifdef ENABLE_IPV6 | |
| case AF_INET6: | |
| { | |
| struct sockaddr_in6 *sin6; | |
| sin6 = (struct sockaddr_in6 *)res->ai_addr; | |
| sin6->sin6_flowinfo = htonl(flowinfo); | |
| sin6->sin6_scope_id = scope_id; | |
| break; | |
| } | |
| #endif | |
| } | |
| Py_BEGIN_ALLOW_THREADS | |
| error = getnameinfo(res->ai_addr, (socklen_t) res->ai_addrlen, | |
| hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), flags); | |
| Py_END_ALLOW_THREADS | |
| if (error) { | |
| socket_state *state = get_module_state(module); | |
| set_gaierror(state, error); | |
| goto fail; | |
| } | |
| name = sock_decode_hostname(hbuf); | |
| if (name == NULL) | |
| goto fail; | |
| ret = Py_BuildValue("Ns", name, pbuf); | |
| fail: | |
| if (res) | |
| freeaddrinfo(res); | |
| return ret; | |
| } | |
| #endif // HAVE_GETNAMEINFO | |
| /* Python API to getting and setting the default timeout value. */ | |
| /*[clinic input] | |
| _socket.getdefaulttimeout | |
| Return the default timeout in seconds for new socket objects. | |
| A value of None indicates that new socket objects have no timeout. | |
| When the socket module is first imported, the default is None. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_getdefaulttimeout_impl(PyObject *module) | |
| /*[clinic end generated code: output=7b3e1be56948c44c input=c9fb729acf998a58]*/ | |
| { | |
| socket_state *state = get_module_state(module); | |
| PyTime_t timeout = _Py_atomic_load_int64_relaxed(&state->defaulttimeout); | |
| if (timeout < 0) { | |
| Py_RETURN_NONE; | |
| } | |
| else { | |
| double seconds = PyTime_AsSecondsDouble(timeout); | |
| return PyFloat_FromDouble(seconds); | |
| } | |
| } | |
| /*[clinic input] | |
| _socket.setdefaulttimeout | |
| timeout as arg: object | |
| / | |
| Set the default timeout in seconds for new socket objects. | |
| A value of None indicates that new socket objects have no timeout. | |
| When the socket module is first imported, the default is None. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_setdefaulttimeout(PyObject *module, PyObject *arg) | |
| /*[clinic end generated code: output=b5d59296163d66bf input=929785d885173684]*/ | |
| { | |
| PyTime_t timeout; | |
| if (socket_parse_timeout(&timeout, arg) < 0) | |
| return NULL; | |
| socket_state *state = get_module_state(module); | |
| _Py_atomic_store_int64_relaxed(&state->defaulttimeout, timeout); | |
| Py_RETURN_NONE; | |
| } | |
| #if defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS_DESKTOP) | |
| /* Python API for getting interface indices and names */ | |
| /*[clinic input] | |
| _socket.if_nameindex | |
| Return a list of network interface information (index, name) tuples. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_if_nameindex_impl(PyObject *module) | |
| /*[clinic end generated code: output=93c863a6262059c4 input=d6438bb556de2100]*/ | |
| { | |
| PyObject *list = PyList_New(0); | |
| if (list == NULL) { | |
| return NULL; | |
| } | |
| #ifdef MS_WINDOWS | |
| PMIB_IF_TABLE2 tbl; | |
| int ret; | |
| if ((ret = GetIfTable2Ex(MibIfTableRaw, &tbl)) != NO_ERROR) { | |
| Py_DECREF(list); | |
| // ret is used instead of GetLastError() | |
| return PyErr_SetFromWindowsErr(ret); | |
| } | |
| for (ULONG i = 0; i < tbl->NumEntries; ++i) { | |
| MIB_IF_ROW2 r = tbl->Table[i]; | |
| WCHAR buf[NDIS_IF_MAX_STRING_SIZE + 1]; | |
| if ((ret = ConvertInterfaceLuidToNameW(&r.InterfaceLuid, buf, | |
| Py_ARRAY_LENGTH(buf)))) { | |
| Py_DECREF(list); | |
| FreeMibTable(tbl); | |
| // ret is used instead of GetLastError() | |
| return PyErr_SetFromWindowsErr(ret); | |
| } | |
| PyObject *tuple = Py_BuildValue("Iu", r.InterfaceIndex, buf); | |
| if (tuple == NULL || PyList_Append(list, tuple) == -1) { | |
| Py_XDECREF(tuple); | |
| Py_DECREF(list); | |
| FreeMibTable(tbl); | |
| return NULL; | |
| } | |
| Py_DECREF(tuple); | |
| } | |
| FreeMibTable(tbl); | |
| return list; | |
| #else | |
| int i; | |
| struct if_nameindex *ni; | |
| ni = if_nameindex(); | |
| if (ni == NULL) { | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| Py_DECREF(list); | |
| return NULL; | |
| } | |
| #ifdef _Py_MEMORY_SANITIZER | |
| __msan_unpoison(ni, sizeof(ni)); | |
| __msan_unpoison(&ni[0], sizeof(ni[0])); | |
| #endif | |
| for (i = 0; ni[i].if_index != 0 && i < INT_MAX; i++) { | |
| #ifdef _Py_MEMORY_SANITIZER | |
| /* This one isn't the end sentinel, the next one must exist. */ | |
| __msan_unpoison(&ni[i+1], sizeof(ni[0])); | |
| /* Otherwise Py_BuildValue internals are flagged by MSan when | |
| they access the not-msan-tracked if_name string data. */ | |
| { | |
| char *to_sanitize = ni[i].if_name; | |
| do { | |
| __msan_unpoison(to_sanitize, 1); | |
| } while (*to_sanitize++ != '\0'); | |
| } | |
| #endif | |
| PyObject *ni_tuple = Py_BuildValue("IO&", | |
| ni[i].if_index, unicode_fsdecode, ni[i].if_name); | |
| if (ni_tuple == NULL || PyList_Append(list, ni_tuple) == -1) { | |
| Py_XDECREF(ni_tuple); | |
| Py_DECREF(list); | |
| if_freenameindex(ni); | |
| return NULL; | |
| } | |
| Py_DECREF(ni_tuple); | |
| } | |
| if_freenameindex(ni); | |
| return list; | |
| #endif | |
| } | |
| #endif // defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS_DESKTOP) | |
| #if defined(HAVE_IF_NAMETOINDEX) || defined(MS_WINDOWS_DESKTOP) | |
| /*[clinic input] | |
| _socket.if_nametoindex | |
| oname: unicode_fs_encoded | |
| / | |
| Returns the interface index corresponding to the interface name if_name. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_if_nametoindex_impl(PyObject *module, PyObject *oname) | |
| /*[clinic end generated code: output=289a411614f30244 input=6125dc20683560cf]*/ | |
| { | |
| #ifdef MS_WINDOWS | |
| NET_IFINDEX index; | |
| #else | |
| unsigned long index; | |
| #endif | |
| errno = ENODEV; // in case 'if_nametoindex' does not set errno | |
| index = if_nametoindex(PyBytes_AS_STRING(oname)); | |
| if (index == 0) { | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| return NULL; | |
| } | |
| return PyLong_FromUnsignedLong(index); | |
| } | |
| #endif // defined(HAVE_IF_NAMETOINDEX) || defined(MS_WINDOWS_DESKTOP) | |
| #if defined(HAVE_IF_INDEXTONAME) || defined(MS_WINDOWS_DESKTOP) | |
| /*[clinic input] | |
| @permit_long_summary | |
| _socket.if_indextoname | |
| if_index as index: NET_IFINDEX | |
| / | |
| Returns the interface name corresponding to the interface index if_index. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_if_indextoname_impl(PyObject *module, NET_IFINDEX index) | |
| /*[clinic end generated code: output=e48bc324993052e0 input=2a0026b271cd43ae]*/ | |
| { | |
| errno = ENXIO; // in case 'if_indextoname' does not set errno | |
| char name[IF_NAMESIZE + 1]; | |
| if (if_indextoname(index, name) == NULL) { | |
| PyErr_SetFromErrno(PyExc_OSError); | |
| return NULL; | |
| } | |
| return PyUnicode_DecodeFSDefault(name); | |
| } | |
| #endif // defined(HAVE_IF_INDEXTONAME) || defined(MS_WINDOWS_DESKTOP) | |
| #ifdef CMSG_LEN | |
| /* Python interface to CMSG_LEN(length). */ | |
| /*[clinic input] | |
| _socket.CMSG_LEN | |
| length: Py_ssize_t | |
| / | |
| Return the total length of an ancillary data item with associated data. | |
| The associated data has the given length. This value can often be | |
| used as the buffer size for recvmsg() to receive a single item of | |
| ancillary data, but RFC 3542 requires portable applications to use | |
| CMSG_SPACE() and thus include space for padding, even when the item | |
| will be the last in the buffer. Raises OverflowError if length is | |
| outside the permissible range of values. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_CMSG_LEN_impl(PyObject *module, Py_ssize_t length) | |
| /*[clinic end generated code: output=e1dd6bb3a3f4a7ff input=b0787fd8c8d9c7be]*/ | |
| { | |
| size_t result; | |
| if (length < 0 || !get_CMSG_LEN(length, &result)) { | |
| PyErr_Format(PyExc_OverflowError, "CMSG_LEN() argument out of range"); | |
| return NULL; | |
| } | |
| return PyLong_FromSize_t(result); | |
| } | |
| #ifdef CMSG_SPACE | |
| /* Python interface to CMSG_SPACE(length). */ | |
| /*[clinic input] | |
| _socket.CMSG_SPACE | |
| length: Py_ssize_t | |
| / | |
| Return the buffer size needed to receive an ancillary data item. | |
| The item has associated data of the given length, and the size | |
| includes any trailing padding. The buffer space needed to receive | |
| multiple items is the sum of the CMSG_SPACE() values for their | |
| associated data lengths. Raises OverflowError if length is outside | |
| the permissible range of values. | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _socket_CMSG_SPACE_impl(PyObject *module, Py_ssize_t length) | |
| /*[clinic end generated code: output=857b925dc29c68c3 input=dedf123dcda72642]*/ | |
| { | |
| size_t result; | |
| if (length < 0 || !get_CMSG_SPACE(length, &result)) { | |
| PyErr_SetString(PyExc_OverflowError, | |
| "CMSG_SPACE() argument out of range"); | |
| return NULL; | |
| } | |
| return PyLong_FromSize_t(result); | |
| } | |
| #endif /* CMSG_SPACE */ | |
| #endif /* CMSG_LEN */ | |
| /* List of functions exported by this module. */ | |
| static PyMethodDef socket_methods[] = { | |
| _SOCKET_GETHOSTBYNAME_METHODDEF | |
| _SOCKET_GETHOSTBYNAME_EX_METHODDEF | |
| _SOCKET_GETHOSTBYADDR_METHODDEF | |
| _SOCKET_GETHOSTNAME_METHODDEF | |
| _SOCKET_SETHOSTNAME_METHODDEF | |
| _SOCKET_GETSERVBYNAME_METHODDEF | |
| _SOCKET_GETSERVBYPORT_METHODDEF | |
| _SOCKET_GETPROTOBYNAME_METHODDEF | |
| _SOCKET_CLOSE_METHODDEF | |
| _SOCKET_DUP_METHODDEF | |
| _SOCKET_SOCKETPAIR_METHODDEF | |
| _SOCKET_NTOHS_METHODDEF | |
| _SOCKET_NTOHL_METHODDEF | |
| _SOCKET_HTONS_METHODDEF | |
| _SOCKET_HTONL_METHODDEF | |
| _SOCKET_INET_ATON_METHODDEF | |
| _SOCKET_INET_NTOA_METHODDEF | |
| _SOCKET_INET_PTON_METHODDEF | |
| _SOCKET_INET_NTOP_METHODDEF | |
| _SOCKET_GETADDRINFO_METHODDEF | |
| _SOCKET_GETNAMEINFO_METHODDEF | |
| _SOCKET_GETDEFAULTTIMEOUT_METHODDEF | |
| _SOCKET_SETDEFAULTTIMEOUT_METHODDEF | |
| _SOCKET_IF_NAMEINDEX_METHODDEF | |
| _SOCKET_IF_NAMETOINDEX_METHODDEF | |
| _SOCKET_IF_INDEXTONAME_METHODDEF | |
| _SOCKET_CMSG_LEN_METHODDEF | |
| _SOCKET_CMSG_SPACE_METHODDEF | |
| {NULL, NULL} /* Sentinel */ | |
| }; | |
| #ifdef MS_WINDOWS | |
| #define OS_INIT_DEFINED | |
| /* Additional initialization and cleanup for Windows */ | |
| static void | |
| os_cleanup(void) | |
| { | |
| WSACleanup(); | |
| } | |
| static int | |
| os_init(void) | |
| { | |
| WSADATA WSAData; | |
| int ret; | |
| ret = WSAStartup(0x0101, &WSAData); | |
| switch (ret) { | |
| case 0: /* No error */ | |
| Py_AtExit(os_cleanup); | |
| return 1; /* Success */ | |
| case WSASYSNOTREADY: | |
| PyErr_SetString(PyExc_ImportError, | |
| "WSAStartup failed: network not ready"); | |
| break; | |
| case WSAVERNOTSUPPORTED: | |
| case WSAEINVAL: | |
| PyErr_SetString( | |
| PyExc_ImportError, | |
| "WSAStartup failed: requested version not supported"); | |
| break; | |
| default: | |
| PyErr_Format(PyExc_ImportError, "WSAStartup failed: error code %d", ret); | |
| break; | |
| } | |
| return 0; /* Failure */ | |
| } | |
| #endif /* MS_WINDOWS */ | |
| #ifndef OS_INIT_DEFINED | |
| static int | |
| os_init(void) | |
| { | |
| return 1; /* Success */ | |
| } | |
| #endif | |
| static int | |
| sock_capi_traverse(PyObject *capsule, visitproc visit, void *arg) | |
| { | |
| PySocketModule_APIObject *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME); | |
| assert(capi != NULL); | |
| Py_VISIT(capi->Sock_Type); | |
| return 0; | |
| } | |
| static int | |
| sock_capi_clear(PyObject *capsule) | |
| { | |
| PySocketModule_APIObject *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME); | |
| assert(capi != NULL); | |
| Py_CLEAR(capi->Sock_Type); | |
| return 0; | |
| } | |
| static void | |
| sock_capi_free(PySocketModule_APIObject *capi) | |
| { | |
| Py_XDECREF(capi->Sock_Type); // sock_capi_free() can clear it | |
| Py_DECREF(capi->error); | |
| Py_DECREF(capi->timeout_error); | |
| PyMem_Free(capi); | |
| } | |
| static void | |
| sock_capi_destroy(PyObject *capsule) | |
| { | |
| void *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME); | |
| assert(capi != NULL); | |
| sock_capi_free(capi); | |
| } | |
| static PySocketModule_APIObject * | |
| sock_get_api(socket_state *state) | |
| { | |
| PySocketModule_APIObject *capi = PyMem_Malloc(sizeof(PySocketModule_APIObject)); | |
| if (capi == NULL) { | |
| PyErr_NoMemory(); | |
| return NULL; | |
| } | |
| capi->Sock_Type = (PyTypeObject *)Py_NewRef(state->sock_type); | |
| capi->error = Py_NewRef(PyExc_OSError); | |
| capi->timeout_error = Py_NewRef(PyExc_TimeoutError); | |
| return capi; | |
| } | |
| /* Initialize the _socket module. | |
| This module is actually called "_socket", and there's a wrapper | |
| "socket.py" which implements some additional functionality. | |
| The import of "_socket" may fail with an ImportError exception if | |
| os-specific initialization fails. On Windows, this does WINSOCK | |
| initialization. When WINSOCK is initialized successfully, a call to | |
| WSACleanup() is scheduled to be made at exit time. | |
| */ | |
| PyDoc_STRVAR(socket_doc, | |
| "Implementation module for socket operations.\n\ | |
| \n\ | |
| See the socket module for documentation."); | |
| static int | |
| socket_exec(PyObject *m) | |
| { | |
| if (!os_init()) { | |
| goto error; | |
| } | |
| socket_state *state = get_module_state(m); | |
| _Py_atomic_store_int64_relaxed(&state->defaulttimeout, _PYTIME_FROMSECONDS(-1)); | |
| #define ADD_EXC(MOD, NAME, VAR, BASE) do { \ | |
| VAR = PyErr_NewException("socket." NAME, BASE, NULL); \ | |
| if (VAR == NULL) { \ | |
| goto error; \ | |
| } \ | |
| if (PyModule_AddObjectRef(MOD, NAME, VAR) < 0) { \ | |
| goto error; \ | |
| } \ | |
| } while (0) | |
| ADD_EXC(m, "herror", state->socket_herror, PyExc_OSError); | |
| ADD_EXC(m, "gaierror", state->socket_gaierror, PyExc_OSError); | |
| #undef ADD_EXC | |
| if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) { | |
| goto error; | |
| } | |
| if (PyModule_AddObjectRef(m, "timeout", PyExc_TimeoutError) < 0) { | |
| goto error; | |
| } | |
| PyObject *sock_type = PyType_FromMetaclass(NULL, m, &sock_spec, NULL); | |
| if (sock_type == NULL) { | |
| goto error; | |
| } | |
| state->sock_type = (PyTypeObject *)sock_type; | |
| if (PyModule_AddObjectRef(m, "SocketType", sock_type) < 0) { | |
| goto error; | |
| } | |
| if (PyModule_AddType(m, state->sock_type) < 0) { | |
| goto error; | |
| } | |
| PyObject *has_ipv6; | |
| #ifdef ENABLE_IPV6 | |
| has_ipv6 = Py_True; | |
| #else | |
| has_ipv6 = Py_False; | |
| #endif | |
| if (PyModule_AddObjectRef(m, "has_ipv6", has_ipv6) < 0) { | |
| goto error; | |
| } | |
| /* Export C API */ | |
| PySocketModule_APIObject *capi = sock_get_api(state); | |
| if (capi == NULL) { | |
| goto error; | |
| } | |
| PyObject *capsule = PyCapsule_New(capi, | |
| PySocket_CAPSULE_NAME, | |
| sock_capi_destroy); | |
| if (capsule == NULL) { | |
| sock_capi_free(capi); | |
| goto error; | |
| } | |
| if (_PyCapsule_SetTraverse(capsule, | |
| sock_capi_traverse, sock_capi_clear) < 0) { | |
| sock_capi_free(capi); | |
| goto error; | |
| } | |
| if (PyModule_Add(m, PySocket_CAPI_NAME, capsule) < 0) { | |
| goto error; | |
| } | |
| #define ADD_INT_MACRO(MOD, INT) do { \ | |
| if (PyModule_AddIntConstant(MOD, #INT, INT) < 0) { \ | |
| goto error; \ | |
| } \ | |
| } while (0) | |
| #define ADD_INT_CONST(MOD, NAME, INT) do { \ | |
| if (PyModule_AddIntConstant(MOD, NAME, INT) < 0) { \ | |
| goto error; \ | |
| } \ | |
| } while (0) | |
| #define ADD_STR_CONST(MOD, NAME, STR) do { \ | |
| if (PyModule_AddStringConstant(MOD, NAME, STR) < 0) { \ | |
| goto error; \ | |
| } \ | |
| } while (0) | |
| /* Address families (we only support AF_INET and AF_UNIX) */ | |
| #ifdef AF_UNSPEC | |
| ADD_INT_MACRO(m, AF_UNSPEC); | |
| #endif | |
| ADD_INT_MACRO(m, AF_INET); | |
| #if defined(AF_UNIX) | |
| ADD_INT_MACRO(m, AF_UNIX); | |
| #endif /* AF_UNIX */ | |
| #ifdef AF_AX25 | |
| /* Amateur Radio AX.25 */ | |
| ADD_INT_MACRO(m, AF_AX25); | |
| #endif | |
| #ifdef AF_IPX | |
| ADD_INT_MACRO(m, AF_IPX); /* Novell IPX */ | |
| #endif | |
| #ifdef AF_APPLETALK | |
| /* Appletalk DDP */ | |
| ADD_INT_MACRO(m, AF_APPLETALK); | |
| #endif | |
| #ifdef AF_NETROM | |
| /* Amateur radio NetROM */ | |
| ADD_INT_MACRO(m, AF_NETROM); | |
| #endif | |
| #ifdef AF_BRIDGE | |
| /* Multiprotocol bridge */ | |
| ADD_INT_MACRO(m, AF_BRIDGE); | |
| #endif | |
| #ifdef AF_ATMPVC | |
| /* ATM PVCs */ | |
| ADD_INT_MACRO(m, AF_ATMPVC); | |
| #endif | |
| #ifdef AF_AAL5 | |
| /* Reserved for Werner's ATM */ | |
| ADD_INT_MACRO(m, AF_AAL5); | |
| #endif | |
| #ifdef HAVE_SOCKADDR_ALG | |
| ADD_INT_MACRO(m, AF_ALG); /* Linux crypto */ | |
| #endif | |
| #ifdef AF_X25 | |
| /* Reserved for X.25 project */ | |
| ADD_INT_MACRO(m, AF_X25); | |
| #endif | |
| #ifdef AF_INET6 | |
| ADD_INT_MACRO(m, AF_INET6); /* IP version 6 */ | |
| #endif | |
| #ifdef AF_ROSE | |
| /* Amateur Radio X.25 PLP */ | |
| ADD_INT_MACRO(m, AF_ROSE); | |
| #endif | |
| #ifdef AF_DECnet | |
| /* Reserved for DECnet project */ | |
| ADD_INT_MACRO(m, AF_DECnet); | |
| #endif | |
| #ifdef AF_NETBEUI | |
| /* Reserved for 802.2LLC project */ | |
| ADD_INT_MACRO(m, AF_NETBEUI); | |
| #endif | |
| #ifdef AF_SECURITY | |
| /* Security callback pseudo AF */ | |
| ADD_INT_MACRO(m, AF_SECURITY); | |
| #endif | |
| #ifdef AF_KEY | |
| /* PF_KEY key management API */ | |
| ADD_INT_MACRO(m, AF_KEY); | |
| #endif | |
| #ifdef AF_NETLINK | |
| /* */ | |
| ADD_INT_MACRO(m, AF_NETLINK); | |
| ADD_INT_MACRO(m, NETLINK_ROUTE); | |
| ADD_INT_MACRO(m, NETLINK_USERSOCK); | |
| ADD_INT_MACRO(m, NETLINK_FIREWALL); | |
| #ifdef NETLINK_NFLOG | |
| ADD_INT_MACRO(m, NETLINK_NFLOG); | |
| #endif | |
| #ifdef NETLINK_XFRM | |
| ADD_INT_MACRO(m, NETLINK_XFRM); | |
| #endif | |
| #ifdef NETLINK_IP6_FW | |
| ADD_INT_MACRO(m, NETLINK_IP6_FW); | |
| #endif | |
| #ifdef NETLINK_DNRTMSG | |
| ADD_INT_MACRO(m, NETLINK_DNRTMSG); | |
| #endif | |
| #ifdef NETLINK_CRYPTO | |
| ADD_INT_MACRO(m, NETLINK_CRYPTO); | |
| #endif | |
| #endif /* AF_NETLINK */ | |
| #ifdef AF_QIPCRTR | |
| /* Qualcomm IPCROUTER */ | |
| ADD_INT_MACRO(m, AF_QIPCRTR); | |
| #endif | |
| #ifdef AF_VSOCK | |
| ADD_INT_CONST(m, "AF_VSOCK", AF_VSOCK); | |
| ADD_INT_CONST(m, "SO_VM_SOCKETS_BUFFER_SIZE", 0); | |
| ADD_INT_CONST(m, "SO_VM_SOCKETS_BUFFER_MIN_SIZE", 1); | |
| ADD_INT_CONST(m, "SO_VM_SOCKETS_BUFFER_MAX_SIZE", 2); | |
| ADD_INT_CONST(m, "VMADDR_CID_ANY", 0xffffffff); | |
| ADD_INT_CONST(m, "VMADDR_PORT_ANY", 0xffffffff); | |
| ADD_INT_CONST(m, "VMADDR_CID_LOCAL", 1); | |
| ADD_INT_CONST(m, "VMADDR_CID_HOST", 2); | |
| ADD_INT_CONST(m, "VM_SOCKETS_INVALID_VERSION", 0xffffffff); | |
| ADD_INT_CONST(m, "IOCTL_VM_SOCKETS_GET_LOCAL_CID", _IO(7, 0xb9)); | |
| #endif | |
| #ifdef AF_ROUTE | |
| /* Alias to emulate 4.4BSD */ | |
| ADD_INT_MACRO(m, AF_ROUTE); | |
| #endif | |
| #ifdef AF_LINK | |
| ADD_INT_MACRO(m, AF_LINK); | |
| #endif | |
| #ifdef AF_ASH | |
| /* Ash */ | |
| ADD_INT_MACRO(m, AF_ASH); | |
| #endif | |
| #ifdef AF_ECONET | |
| /* Acorn Econet */ | |
| ADD_INT_MACRO(m, AF_ECONET); | |
| #endif | |
| #ifdef AF_ATMSVC | |
| /* ATM SVCs */ | |
| ADD_INT_MACRO(m, AF_ATMSVC); | |
| #endif | |
| #ifdef AF_SNA | |
| /* Linux SNA Project (nutters!) */ | |
| ADD_INT_MACRO(m, AF_SNA); | |
| #endif | |
| #ifdef AF_IRDA | |
| /* IRDA sockets */ | |
| ADD_INT_MACRO(m, AF_IRDA); | |
| #endif | |
| #ifdef AF_PPPOX | |
| /* PPPoX sockets */ | |
| ADD_INT_MACRO(m, AF_PPPOX); | |
| #endif | |
| #ifdef AF_WANPIPE | |
| /* Wanpipe API Sockets */ | |
| ADD_INT_MACRO(m, AF_WANPIPE); | |
| #endif | |
| #ifdef AF_LLC | |
| /* Linux LLC */ | |
| ADD_INT_MACRO(m, AF_LLC); | |
| #endif | |
| #ifdef HAVE_AF_HYPERV | |
| /* Hyper-V sockets */ | |
| ADD_INT_MACRO(m, AF_HYPERV); | |
| /* for proto */ | |
| ADD_INT_MACRO(m, HV_PROTOCOL_RAW); | |
| /* for setsockopt() */ | |
| ADD_INT_MACRO(m, HVSOCKET_CONNECT_TIMEOUT); | |
| ADD_INT_MACRO(m, HVSOCKET_CONNECT_TIMEOUT_MAX); | |
| ADD_INT_MACRO(m, HVSOCKET_CONNECTED_SUSPEND); | |
| ADD_INT_MACRO(m, HVSOCKET_ADDRESS_FLAG_PASSTHRU); | |
| /* for bind() or connect() */ | |
| ADD_STR_CONST(m, "HV_GUID_ZERO", "00000000-0000-0000-0000-000000000000"); | |
| ADD_STR_CONST(m, "HV_GUID_WILDCARD", "00000000-0000-0000-0000-000000000000"); | |
| ADD_STR_CONST(m, "HV_GUID_BROADCAST", "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"); | |
| ADD_STR_CONST(m, "HV_GUID_CHILDREN", "90DB8B89-0D35-4F79-8CE9-49EA0AC8B7CD"); | |
| ADD_STR_CONST(m, "HV_GUID_LOOPBACK", "E0E16197-DD56-4A10-9195-5EE7A155A838"); | |
| ADD_STR_CONST(m, "HV_GUID_PARENT", "A42E7CDA-D03F-480C-9CC2-A4DE20ABB878"); | |
| #endif /* HAVE_AF_HYPERV */ | |
| #ifdef USE_BLUETOOTH | |
| ADD_INT_MACRO(m, AF_BLUETOOTH); | |
| #ifdef BTPROTO_L2CAP | |
| ADD_INT_MACRO(m, BTPROTO_L2CAP); | |
| ADD_INT_MACRO(m, SOL_L2CAP); | |
| #if defined(BDADDR_BREDR) | |
| ADD_INT_MACRO(m, BDADDR_BREDR); | |
| ADD_INT_MACRO(m, BDADDR_LE_PUBLIC); | |
| ADD_INT_MACRO(m, BDADDR_LE_RANDOM); | |
| #endif | |
| #ifdef SO_L2CAP_IMTU | |
| ADD_INT_MACRO(m, SO_L2CAP_IMTU); | |
| ADD_INT_MACRO(m, SO_L2CAP_OMTU); | |
| ADD_INT_MACRO(m, SO_L2CAP_FLUSH); | |
| #endif | |
| #ifdef SO_L2CAP_IQOS | |
| ADD_INT_MACRO(m, SO_L2CAP_IQOS); | |
| ADD_INT_MACRO(m, SO_L2CAP_OQOS); | |
| #endif | |
| #ifdef SO_L2CAP_ENCRYPTED | |
| ADD_INT_MACRO(m, SO_L2CAP_ENCRYPTED); | |
| #endif | |
| #ifdef L2CAP_LM | |
| ADD_INT_MACRO(m, L2CAP_LM); | |
| ADD_INT_MACRO(m, L2CAP_LM_MASTER); | |
| ADD_INT_MACRO(m, L2CAP_LM_AUTH); | |
| ADD_INT_MACRO(m, L2CAP_LM_ENCRYPT); | |
| ADD_INT_MACRO(m, L2CAP_LM_TRUSTED); | |
| ADD_INT_MACRO(m, L2CAP_LM_RELIABLE); | |
| ADD_INT_MACRO(m, L2CAP_LM_SECURE); | |
| #endif | |
| #ifdef SO_L2CAP_LM | |
| ADD_INT_MACRO(m, SO_L2CAP_LM); | |
| ADD_INT_MACRO(m, L2CAP_LM_AUTH); | |
| ADD_INT_MACRO(m, L2CAP_LM_ENCRYPT); | |
| ADD_INT_MACRO(m, L2CAP_LM_SECURE); | |
| #endif | |
| #endif /* BTPROTO_L2CAP */ | |
| #ifdef BTPROTO_HCI | |
| ADD_INT_MACRO(m, BTPROTO_HCI); | |
| ADD_INT_MACRO(m, SOL_HCI); | |
| #ifdef HAVE_BLUETOOTH_BLUETOOTH_H | |
| ADD_INT_MACRO(m, HCI_DEV_NONE); | |
| ADD_INT_MACRO(m, HCI_CHANNEL_RAW); | |
| ADD_INT_MACRO(m, HCI_CHANNEL_USER); | |
| ADD_INT_MACRO(m, HCI_CHANNEL_MONITOR); | |
| ADD_INT_MACRO(m, HCI_CHANNEL_CONTROL); | |
| ADD_INT_MACRO(m, HCI_CHANNEL_LOGGING); | |
| #endif | |
| #ifdef HCI_FILTER | |
| ADD_INT_MACRO(m, HCI_FILTER); | |
| #endif | |
| #ifdef HCI_DATA_DIR | |
| ADD_INT_MACRO(m, HCI_DATA_DIR); | |
| #endif | |
| #ifdef HCI_TIME_STAMP | |
| ADD_INT_MACRO(m, HCI_TIME_STAMP); | |
| #endif | |
| #ifdef SO_HCI_EVT_FILTER | |
| ADD_INT_MACRO(m, SO_HCI_EVT_FILTER); | |
| ADD_INT_MACRO(m, SO_HCI_PKT_FILTER); | |
| #endif | |
| #endif /* BTPROTO_HCI */ | |
| #ifdef BTPROTO_RFCOMM | |
| ADD_INT_MACRO(m, BTPROTO_RFCOMM); | |
| ADD_INT_MACRO(m, SOL_RFCOMM); | |
| #ifdef SO_RFCOMM_MTU | |
| ADD_INT_MACRO(m, SO_RFCOMM_MTU); | |
| ADD_INT_MACRO(m, SO_RFCOMM_FC_INFO); | |
| #endif | |
| #ifdef SO_RFCOMM_LM | |
| ADD_INT_MACRO(m, SO_RFCOMM_LM); | |
| ADD_INT_MACRO(m, RFCOMM_LM_AUTH); | |
| ADD_INT_MACRO(m, RFCOMM_LM_ENCRYPT); | |
| ADD_INT_MACRO(m, RFCOMM_LM_SECURE); | |
| #endif | |
| #ifdef MS_WINDOWS_DESKTOP | |
| ADD_INT_MACRO(m, SO_BTH_ENCRYPT); | |
| ADD_INT_MACRO(m, SO_BTH_MTU); | |
| ADD_INT_MACRO(m, SO_BTH_MTU_MAX); | |
| ADD_INT_MACRO(m, SO_BTH_MTU_MIN); | |
| #endif | |
| #endif /* BTPROTO_RFCOMM */ | |
| ADD_STR_CONST(m, "BDADDR_ANY", "00:00:00:00:00:00"); | |
| ADD_STR_CONST(m, "BDADDR_LOCAL", "00:00:00:FF:FF:FF"); | |
| #ifdef BTPROTO_SCO | |
| ADD_INT_MACRO(m, BTPROTO_SCO); | |
| ADD_INT_MACRO(m, SOL_SCO); | |
| #ifdef SO_SCO_MTU | |
| ADD_INT_MACRO(m, SO_SCO_MTU); | |
| #endif | |
| #ifdef SO_SCO_CONNINFO | |
| ADD_INT_MACRO(m, SO_SCO_CONNINFO); | |
| #endif | |
| #ifdef SO_SCO_HANDLE | |
| ADD_INT_MACRO(m, SO_SCO_HANDLE); | |
| #endif | |
| #endif /* BTPROTO_SCO */ | |
| #ifdef HAVE_BLUETOOTH_BLUETOOTH_H | |
| ADD_INT_MACRO(m, SOL_BLUETOOTH); | |
| ADD_INT_MACRO(m, BT_SECURITY); | |
| ADD_INT_MACRO(m, BT_SECURITY_SDP); | |
| ADD_INT_MACRO(m, BT_SECURITY_LOW); | |
| ADD_INT_MACRO(m, BT_SECURITY_MEDIUM); | |
| ADD_INT_MACRO(m, BT_SECURITY_HIGH); | |
| #ifdef BT_SECURITY_FIPS | |
| ADD_INT_MACRO(m, BT_SECURITY_FIPS); | |
| #endif | |
| #ifdef BT_DEFER_SETUP | |
| ADD_INT_MACRO(m, BT_DEFER_SETUP); | |
| #endif | |
| ADD_INT_MACRO(m, BT_FLUSHABLE); | |
| ADD_INT_MACRO(m, BT_FLUSHABLE_OFF); | |
| ADD_INT_MACRO(m, BT_FLUSHABLE_ON); | |
| ADD_INT_MACRO(m, BT_POWER); | |
| ADD_INT_MACRO(m, BT_POWER_FORCE_ACTIVE_OFF); | |
| ADD_INT_MACRO(m, BT_POWER_FORCE_ACTIVE_ON); | |
| ADD_INT_MACRO(m, BT_CHANNEL_POLICY); | |
| ADD_INT_MACRO(m, BT_CHANNEL_POLICY_BREDR_ONLY); | |
| ADD_INT_MACRO(m, BT_CHANNEL_POLICY_BREDR_PREFERRED); | |
| ADD_INT_MACRO(m, BT_CHANNEL_POLICY_BREDR_PREFERRED); | |
| ADD_INT_MACRO(m, BT_VOICE); | |
| ADD_INT_MACRO(m, BT_VOICE_TRANSPARENT); | |
| ADD_INT_MACRO(m, BT_VOICE_CVSD_16BIT); | |
| #ifdef BT_VOICE_TRANSPARENT_16BIT | |
| ADD_INT_MACRO(m, BT_VOICE_TRANSPARENT_16BIT); | |
| #endif | |
| ADD_INT_MACRO(m, BT_SNDMTU); | |
| ADD_INT_MACRO(m, BT_RCVMTU); | |
| #ifdef BT_PHY | |
| ADD_INT_MACRO(m, BT_PHY); | |
| ADD_INT_MACRO(m, BT_PHY_BR_1M_1SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_BR_1M_3SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_BR_1M_5SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_EDR_2M_1SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_EDR_2M_3SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_EDR_2M_5SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_EDR_3M_1SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_EDR_3M_3SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_EDR_3M_5SLOT); | |
| ADD_INT_MACRO(m, BT_PHY_LE_1M_TX); | |
| ADD_INT_MACRO(m, BT_PHY_LE_1M_RX); | |
| ADD_INT_MACRO(m, BT_PHY_LE_2M_TX); | |
| ADD_INT_MACRO(m, BT_PHY_LE_2M_RX); | |
| ADD_INT_MACRO(m, BT_PHY_LE_CODED_TX); | |
| ADD_INT_MACRO(m, BT_PHY_LE_CODED_RX); | |
| #endif | |
| #ifdef BT_MODE | |
| ADD_INT_MACRO(m, BT_MODE); | |
| ADD_INT_MACRO(m, BT_MODE_BASIC); | |
| ADD_INT_MACRO(m, BT_MODE_ERTM); | |
| ADD_INT_MACRO(m, BT_MODE_STREAMING); | |
| ADD_INT_MACRO(m, BT_MODE_LE_FLOWCTL); | |
| ADD_INT_MACRO(m, BT_MODE_EXT_FLOWCTL); | |
| #endif | |
| #ifdef BT_PKT_STATUS | |
| ADD_INT_MACRO(m, BT_PKT_STATUS); | |
| #endif | |
| #ifdef BT_ISO_QOS | |
| ADD_INT_MACRO(m, BT_ISO_QOS); | |
| #endif | |
| #ifdef BT_CODEC | |
| ADD_INT_MACRO(m, BT_CODEC); | |
| #endif | |
| #endif /* HAVE_BLUETOOTH_BLUETOOTH_H */ | |
| #endif /* USE_BLUETOOTH */ | |
| #ifdef AF_CAN | |
| /* Controller Area Network */ | |
| ADD_INT_MACRO(m, AF_CAN); | |
| #endif | |
| #ifdef PF_CAN | |
| /* Controller Area Network */ | |
| ADD_INT_MACRO(m, PF_CAN); | |
| #endif | |
| /* Reliable Datagram Sockets */ | |
| #ifdef AF_RDS | |
| ADD_INT_MACRO(m, AF_RDS); | |
| #endif | |
| #ifdef PF_RDS | |
| ADD_INT_MACRO(m, PF_RDS); | |
| #endif | |
| /* Kernel event messages */ | |
| #ifdef PF_SYSTEM | |
| ADD_INT_MACRO(m, PF_SYSTEM); | |
| #endif | |
| #ifdef AF_SYSTEM | |
| ADD_INT_MACRO(m, AF_SYSTEM); | |
| #endif | |
| /* FreeBSD divert(4) */ | |
| #ifdef PF_DIVERT | |
| ADD_INT_MACRO(m, PF_DIVERT); | |
| #endif | |
| #ifdef AF_DIVERT | |
| ADD_INT_MACRO(m, AF_DIVERT); | |
| #endif | |
| #ifdef AF_PACKET | |
| ADD_INT_MACRO(m, AF_PACKET); | |
| #endif | |
| #ifdef PF_PACKET | |
| ADD_INT_MACRO(m, PF_PACKET); | |
| #endif | |
| #ifdef PACKET_HOST | |
| ADD_INT_MACRO(m, PACKET_HOST); | |
| #endif | |
| #ifdef PACKET_BROADCAST | |
| ADD_INT_MACRO(m, PACKET_BROADCAST); | |
| #endif | |
| #ifdef PACKET_MULTICAST | |
| ADD_INT_MACRO(m, PACKET_MULTICAST); | |
| #endif | |
| #ifdef PACKET_OTHERHOST | |
| ADD_INT_MACRO(m, PACKET_OTHERHOST); | |
| #endif | |
| #ifdef PACKET_OUTGOING | |
| ADD_INT_MACRO(m, PACKET_OUTGOING); | |
| #endif | |
| #ifdef PACKET_LOOPBACK | |
| ADD_INT_MACRO(m, PACKET_LOOPBACK); | |
| #endif | |
| #ifdef PACKET_FASTROUTE | |
| ADD_INT_MACRO(m, PACKET_FASTROUTE); | |
| #endif | |
| #ifdef HAVE_LINUX_TIPC_H | |
| ADD_INT_MACRO(m, AF_TIPC); | |
| /* for addresses */ | |
| ADD_INT_MACRO(m, TIPC_ADDR_NAMESEQ); | |
| ADD_INT_MACRO(m, TIPC_ADDR_NAME); | |
| ADD_INT_MACRO(m, TIPC_ADDR_ID); | |
| ADD_INT_MACRO(m, TIPC_ZONE_SCOPE); | |
| ADD_INT_MACRO(m, TIPC_CLUSTER_SCOPE); | |
| ADD_INT_MACRO(m, TIPC_NODE_SCOPE); | |
| /* for setsockopt() */ | |
| ADD_INT_MACRO(m, SOL_TIPC); | |
| ADD_INT_MACRO(m, TIPC_IMPORTANCE); | |
| ADD_INT_MACRO(m, TIPC_SRC_DROPPABLE); | |
| ADD_INT_MACRO(m, TIPC_DEST_DROPPABLE); | |
| ADD_INT_MACRO(m, TIPC_CONN_TIMEOUT); | |
| ADD_INT_MACRO(m, TIPC_LOW_IMPORTANCE); | |
| ADD_INT_MACRO(m, TIPC_MEDIUM_IMPORTANCE); | |
| ADD_INT_MACRO(m, TIPC_HIGH_IMPORTANCE); | |
| ADD_INT_MACRO(m, TIPC_CRITICAL_IMPORTANCE); | |
| /* for subscriptions */ | |
| ADD_INT_MACRO(m, TIPC_SUB_PORTS); | |
| ADD_INT_MACRO(m, TIPC_SUB_SERVICE); | |
| #ifdef TIPC_SUB_CANCEL | |
| /* doesn't seem to be available everywhere */ | |
| ADD_INT_MACRO(m, TIPC_SUB_CANCEL); | |
| #endif | |
| ADD_INT_MACRO(m, TIPC_WAIT_FOREVER); | |
| ADD_INT_MACRO(m, TIPC_PUBLISHED); | |
| ADD_INT_MACRO(m, TIPC_WITHDRAWN); | |
| ADD_INT_MACRO(m, TIPC_SUBSCR_TIMEOUT); | |
| ADD_INT_MACRO(m, TIPC_CFG_SRV); | |
| ADD_INT_MACRO(m, TIPC_TOP_SRV); | |
| #endif | |
| #ifdef HAVE_SOCKADDR_ALG | |
| /* Socket options */ | |
| ADD_INT_MACRO(m, ALG_SET_KEY); | |
| ADD_INT_MACRO(m, ALG_SET_IV); | |
| ADD_INT_MACRO(m, ALG_SET_OP); | |
| ADD_INT_MACRO(m, ALG_SET_AEAD_ASSOCLEN); | |
| ADD_INT_MACRO(m, ALG_SET_AEAD_AUTHSIZE); | |
| ADD_INT_MACRO(m, ALG_SET_PUBKEY); | |
| /* Operations */ | |
| ADD_INT_MACRO(m, ALG_OP_DECRYPT); | |
| ADD_INT_MACRO(m, ALG_OP_ENCRYPT); | |
| ADD_INT_MACRO(m, ALG_OP_SIGN); | |
| ADD_INT_MACRO(m, ALG_OP_VERIFY); | |
| #endif | |
| /* IEEE 802.3 protocol numbers required for a standard TCP/IP network stack */ | |
| #ifdef ETHERTYPE_ARP | |
| ADD_INT_MACRO(m, ETHERTYPE_ARP); | |
| #endif | |
| #ifdef ETHERTYPE_IP | |
| ADD_INT_MACRO(m, ETHERTYPE_IP); | |
| #endif | |
| #ifdef ETHERTYPE_IPV6 | |
| ADD_INT_MACRO(m, ETHERTYPE_IPV6); | |
| #endif | |
| #ifdef ETHERTYPE_VLAN | |
| ADD_INT_MACRO(m, ETHERTYPE_VLAN); | |
| #endif | |
| /* Linux pseudo-protocol for sniffing every packet */ | |
| #ifdef ETH_P_ALL | |
| ADD_INT_MACRO(m, ETH_P_ALL); | |
| #endif | |
| /* Socket types */ | |
| ADD_INT_MACRO(m, SOCK_STREAM); | |
| ADD_INT_MACRO(m, SOCK_DGRAM); | |
| /* We have incomplete socket support. */ | |
| #ifdef SOCK_RAW | |
| /* SOCK_RAW is marked as optional in the POSIX specification */ | |
| ADD_INT_MACRO(m, SOCK_RAW); | |
| #endif | |
| #ifdef SOCK_SEQPACKET | |
| ADD_INT_MACRO(m, SOCK_SEQPACKET); | |
| #endif | |
| #if defined(SOCK_RDM) | |
| ADD_INT_MACRO(m, SOCK_RDM); | |
| #endif | |
| #ifdef SOCK_CLOEXEC | |
| ADD_INT_MACRO(m, SOCK_CLOEXEC); | |
| #endif | |
| #ifdef SOCK_NONBLOCK | |
| ADD_INT_MACRO(m, SOCK_NONBLOCK); | |
| #endif | |
| #ifdef SO_DEBUG | |
| ADD_INT_MACRO(m, SO_DEBUG); | |
| #endif | |
| #ifdef SO_ACCEPTCONN | |
| ADD_INT_MACRO(m, SO_ACCEPTCONN); | |
| #endif | |
| #ifdef SO_REUSEADDR | |
| ADD_INT_MACRO(m, SO_REUSEADDR); | |
| #endif | |
| #ifdef SO_EXCLUSIVEADDRUSE | |
| ADD_INT_MACRO(m, SO_EXCLUSIVEADDRUSE); | |
| #endif | |
| #ifdef SO_INCOMING_CPU | |
| ADD_INT_MACRO(m, SO_INCOMING_CPU); | |
| #endif | |
| #ifdef SO_KEEPALIVE | |
| ADD_INT_MACRO(m, SO_KEEPALIVE); | |
| #endif | |
| #ifdef SO_DONTROUTE | |
| ADD_INT_MACRO(m, SO_DONTROUTE); | |
| #endif | |
| #ifdef SO_BROADCAST | |
| ADD_INT_MACRO(m, SO_BROADCAST); | |
| #endif | |
| #ifdef SO_USELOOPBACK | |
| ADD_INT_MACRO(m, SO_USELOOPBACK); | |
| #endif | |
| #ifdef SO_LINGER | |
| ADD_INT_MACRO(m, SO_LINGER); | |
| #endif | |
| #ifdef SO_OOBINLINE | |
| ADD_INT_MACRO(m, SO_OOBINLINE); | |
| #endif | |
| #ifdef SO_ORIGINAL_DST | |
| ADD_INT_MACRO(m, SO_ORIGINAL_DST); | |
| #endif | |
| #ifndef __GNU__ | |
| #ifdef SO_REUSEPORT | |
| ADD_INT_MACRO(m, SO_REUSEPORT); | |
| #endif | |
| #endif | |
| #ifdef SO_REUSEPORT_LB | |
| ADD_INT_MACRO(m, SO_REUSEPORT_LB); | |
| #endif | |
| #ifdef SO_SNDBUF | |
| ADD_INT_MACRO(m, SO_SNDBUF); | |
| #endif | |
| #ifdef SO_RCVBUF | |
| ADD_INT_MACRO(m, SO_RCVBUF); | |
| #endif | |
| #ifdef SO_SNDLOWAT | |
| ADD_INT_MACRO(m, SO_SNDLOWAT); | |
| #endif | |
| #ifdef SO_RCVLOWAT | |
| ADD_INT_MACRO(m, SO_RCVLOWAT); | |
| #endif | |
| #ifdef SO_SNDTIMEO | |
| ADD_INT_MACRO(m, SO_SNDTIMEO); | |
| #endif | |
| #ifdef SO_RCVTIMEO | |
| ADD_INT_MACRO(m, SO_RCVTIMEO); | |
| #endif | |
| #ifdef SO_ERROR | |
| ADD_INT_MACRO(m, SO_ERROR); | |
| #endif | |
| #ifdef SO_TYPE | |
| ADD_INT_MACRO(m, SO_TYPE); | |
| #endif | |
| #ifdef SO_SETFIB | |
| ADD_INT_MACRO(m, SO_SETFIB); | |
| #endif | |
| #ifdef SO_PASSCRED | |
| ADD_INT_MACRO(m, SO_PASSCRED); | |
| #endif | |
| #ifdef SO_PEERCRED | |
| ADD_INT_MACRO(m, SO_PEERCRED); | |
| #endif | |
| #ifdef LOCAL_PEERCRED | |
| ADD_INT_MACRO(m, LOCAL_PEERCRED); | |
| #endif | |
| #ifdef SO_PASSSEC | |
| ADD_INT_MACRO(m, SO_PASSSEC); | |
| #endif | |
| #ifdef SO_PEERSEC | |
| ADD_INT_MACRO(m, SO_PEERSEC); | |
| #endif | |
| #ifdef SO_BINDTODEVICE | |
| ADD_INT_MACRO(m, SO_BINDTODEVICE); | |
| #endif | |
| #ifdef SO_PASSRIGHTS | |
| ADD_INT_MACRO(m, SO_PASSRIGHTS); | |
| #endif | |
| #ifdef SO_BINDTOIFINDEX | |
| ADD_INT_MACRO(m, SO_BINDTOIFINDEX); | |
| #endif | |
| #ifdef SO_PRIORITY | |
| ADD_INT_MACRO(m, SO_PRIORITY); | |
| #endif | |
| #ifdef SO_MARK | |
| ADD_INT_MACRO(m, SO_MARK); | |
| #endif | |
| #ifdef SO_USER_COOKIE | |
| ADD_INT_MACRO(m, SO_USER_COOKIE); | |
| #endif | |
| #ifdef SO_RTABLE | |
| ADD_INT_MACRO(m, SO_RTABLE); | |
| #endif | |
| #ifdef SO_DOMAIN | |
| ADD_INT_MACRO(m, SO_DOMAIN); | |
| #endif | |
| #ifdef SO_PROTOCOL | |
| ADD_INT_MACRO(m, SO_PROTOCOL); | |
| #endif | |
| #ifdef LOCAL_CREDS | |
| ADD_INT_MACRO(m, LOCAL_CREDS); | |
| #endif | |
| #ifdef LOCAL_CREDS_PERSISTENT | |
| ADD_INT_MACRO(m, LOCAL_CREDS_PERSISTENT); | |
| #endif | |
| /* Maximum number of connections for "listen" */ | |
| #ifdef SOMAXCONN | |
| ADD_INT_MACRO(m, SOMAXCONN); | |
| #else | |
| ADD_INT_CONST(m, "SOMAXCONN", 5); /* Common value */ | |
| #endif | |
| /* Ancillary message types */ | |
| #ifdef SCM_RIGHTS | |
| ADD_INT_MACRO(m, SCM_RIGHTS); | |
| #endif | |
| #ifdef SCM_CREDENTIALS | |
| ADD_INT_MACRO(m, SCM_CREDENTIALS); | |
| #endif | |
| #ifdef SCM_CREDS | |
| ADD_INT_MACRO(m, SCM_CREDS); | |
| #endif | |
| #ifdef SCM_CREDS2 | |
| ADD_INT_MACRO(m, SCM_CREDS2); | |
| #endif | |
| /* Flags for send, recv */ | |
| #ifdef MSG_OOB | |
| ADD_INT_MACRO(m, MSG_OOB); | |
| #endif | |
| #ifdef MSG_PEEK | |
| ADD_INT_MACRO(m, MSG_PEEK); | |
| #endif | |
| #ifdef MSG_DONTROUTE | |
| ADD_INT_MACRO(m, MSG_DONTROUTE); | |
| #endif | |
| #ifdef MSG_DONTWAIT | |
| ADD_INT_MACRO(m, MSG_DONTWAIT); | |
| #endif | |
| #ifdef MSG_EOR | |
| ADD_INT_MACRO(m, MSG_EOR); | |
| #endif | |
| #ifdef MSG_TRUNC | |
| // workaround for https://github.com/WebAssembly/wasi-libc/issues/305 | |
| #if defined(__wasi__) && !defined(__WASI_RIFLAGS_RECV_DATA_TRUNCATED) | |
| # define __WASI_RIFLAGS_RECV_DATA_TRUNCATED 2 | |
| #endif | |
| ADD_INT_MACRO(m, MSG_TRUNC); | |
| #endif | |
| #ifdef MSG_CTRUNC | |
| ADD_INT_MACRO(m, MSG_CTRUNC); | |
| #endif | |
| #ifdef MSG_WAITALL | |
| ADD_INT_MACRO(m, MSG_WAITALL); | |
| #endif | |
| #ifdef MSG_BTAG | |
| ADD_INT_MACRO(m, MSG_BTAG); | |
| #endif | |
| #ifdef MSG_ETAG | |
| ADD_INT_MACRO(m, MSG_ETAG); | |
| #endif | |
| #ifdef MSG_NOSIGNAL | |
| ADD_INT_MACRO(m, MSG_NOSIGNAL); | |
| #endif | |
| #ifdef MSG_NOTIFICATION | |
| ADD_INT_MACRO(m, MSG_NOTIFICATION); | |
| #endif | |
| #ifdef MSG_CMSG_CLOEXEC | |
| ADD_INT_MACRO(m, MSG_CMSG_CLOEXEC); | |
| #endif | |
| #ifdef MSG_ERRQUEUE | |
| ADD_INT_MACRO(m, MSG_ERRQUEUE); | |
| #endif | |
| #ifdef MSG_CONFIRM | |
| ADD_INT_MACRO(m, MSG_CONFIRM); | |
| #endif | |
| #ifdef MSG_MORE | |
| ADD_INT_MACRO(m, MSG_MORE); | |
| #endif | |
| #ifdef MSG_EOF | |
| ADD_INT_MACRO(m, MSG_EOF); | |
| #endif | |
| #ifdef MSG_BCAST | |
| ADD_INT_MACRO(m, MSG_BCAST); | |
| #endif | |
| #ifdef MSG_MCAST | |
| ADD_INT_MACRO(m, MSG_MCAST); | |
| #endif | |
| #ifdef MSG_FASTOPEN | |
| ADD_INT_MACRO(m, MSG_FASTOPEN); | |
| #endif | |
| /* Protocol level and numbers, usable for [gs]etsockopt */ | |
| #ifdef SOL_SOCKET | |
| ADD_INT_MACRO(m, SOL_SOCKET); | |
| #endif | |
| #ifdef SOL_IP | |
| ADD_INT_MACRO(m, SOL_IP); | |
| #else | |
| ADD_INT_CONST(m, "SOL_IP", 0); | |
| #endif | |
| #ifdef SOL_IPX | |
| ADD_INT_MACRO(m, SOL_IPX); | |
| #endif | |
| #ifdef SOL_AX25 | |
| ADD_INT_MACRO(m, SOL_AX25); | |
| #endif | |
| #ifdef SOL_ATALK | |
| ADD_INT_MACRO(m, SOL_ATALK); | |
| #endif | |
| #ifdef SOL_NETROM | |
| ADD_INT_MACRO(m, SOL_NETROM); | |
| #endif | |
| #ifdef SOL_ROSE | |
| ADD_INT_MACRO(m, SOL_ROSE); | |
| #endif | |
| #ifdef SOL_TCP | |
| ADD_INT_MACRO(m, SOL_TCP); | |
| #else | |
| ADD_INT_CONST(m, "SOL_TCP", 6); | |
| #endif | |
| #ifdef SOL_UDP | |
| ADD_INT_MACRO(m, SOL_UDP); | |
| #else | |
| ADD_INT_CONST(m, "SOL_UDP", 17); | |
| #endif | |
| #ifdef SOL_CAN_BASE | |
| ADD_INT_MACRO(m, SOL_CAN_BASE); | |
| #endif | |
| #ifdef SOL_CAN_RAW | |
| ADD_INT_MACRO(m, SOL_CAN_RAW); | |
| ADD_INT_MACRO(m, CAN_RAW); | |
| #endif | |
| #if defined(HAVE_LINUX_CAN_H) || defined(HAVE_NETCAN_CAN_H) | |
| ADD_INT_MACRO(m, CAN_EFF_FLAG); | |
| ADD_INT_MACRO(m, CAN_RTR_FLAG); | |
| ADD_INT_MACRO(m, CAN_ERR_FLAG); | |
| ADD_INT_MACRO(m, CAN_SFF_MASK); | |
| ADD_INT_MACRO(m, CAN_EFF_MASK); | |
| ADD_INT_MACRO(m, CAN_ERR_MASK); | |
| #ifdef CAN_ISOTP | |
| ADD_INT_MACRO(m, CAN_ISOTP); | |
| #endif | |
| #ifdef CAN_J1939 | |
| ADD_INT_MACRO(m, CAN_J1939); | |
| #endif | |
| #endif | |
| #if defined(HAVE_LINUX_CAN_RAW_H) || defined(HAVE_NETCAN_CAN_H) | |
| ADD_INT_MACRO(m, CAN_RAW_FILTER); | |
| #ifdef HAVE_LINUX_CAN_RAW_H | |
| ADD_INT_MACRO(m, CAN_RAW_ERR_FILTER); | |
| #endif | |
| ADD_INT_MACRO(m, CAN_RAW_LOOPBACK); | |
| ADD_INT_MACRO(m, CAN_RAW_RECV_OWN_MSGS); | |
| #endif | |
| #ifdef HAVE_LINUX_CAN_RAW_FD_FRAMES | |
| ADD_INT_MACRO(m, CAN_RAW_FD_FRAMES); | |
| #endif | |
| #ifdef HAVE_LINUX_CAN_RAW_JOIN_FILTERS | |
| ADD_INT_MACRO(m, CAN_RAW_JOIN_FILTERS); | |
| #endif | |
| #ifdef HAVE_LINUX_CAN_BCM_H | |
| ADD_INT_MACRO(m, CAN_BCM); | |
| /* BCM opcodes */ | |
| ADD_INT_CONST(m, "CAN_BCM_TX_SETUP", TX_SETUP); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_DELETE", TX_DELETE); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_READ", TX_READ); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_SEND", TX_SEND); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_SETUP", RX_SETUP); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_DELETE", RX_DELETE); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_READ", RX_READ); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_STATUS", TX_STATUS); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_EXPIRED", TX_EXPIRED); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_STATUS", RX_STATUS); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_TIMEOUT", RX_TIMEOUT); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_CHANGED", RX_CHANGED); | |
| /* BCM flags */ | |
| ADD_INT_CONST(m, "CAN_BCM_SETTIMER", SETTIMER); | |
| ADD_INT_CONST(m, "CAN_BCM_STARTTIMER", STARTTIMER); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_COUNTEVT", TX_COUNTEVT); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_ANNOUNCE", TX_ANNOUNCE); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_CP_CAN_ID", TX_CP_CAN_ID); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_FILTER_ID", RX_FILTER_ID); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_CHECK_DLC", RX_CHECK_DLC); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_NO_AUTOTIMER", RX_NO_AUTOTIMER); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_ANNOUNCE_RESUME", RX_ANNOUNCE_RESUME); | |
| ADD_INT_CONST(m, "CAN_BCM_TX_RESET_MULTI_IDX", TX_RESET_MULTI_IDX); | |
| ADD_INT_CONST(m, "CAN_BCM_RX_RTR_FRAME", RX_RTR_FRAME); | |
| #ifdef CAN_FD_FRAME | |
| /* CAN_FD_FRAME was only introduced in the 4.8.x kernel series */ | |
| ADD_INT_CONST(m, "CAN_BCM_CAN_FD_FRAME", CAN_FD_FRAME); | |
| #endif | |
| #endif | |
| #ifdef HAVE_LINUX_CAN_J1939_H | |
| ADD_INT_MACRO(m, J1939_MAX_UNICAST_ADDR); | |
| ADD_INT_MACRO(m, J1939_IDLE_ADDR); | |
| ADD_INT_MACRO(m, J1939_NO_ADDR); | |
| ADD_INT_MACRO(m, J1939_NO_NAME); | |
| ADD_INT_MACRO(m, J1939_PGN_REQUEST); | |
| ADD_INT_MACRO(m, J1939_PGN_ADDRESS_CLAIMED); | |
| ADD_INT_MACRO(m, J1939_PGN_ADDRESS_COMMANDED); | |
| ADD_INT_MACRO(m, J1939_PGN_PDU1_MAX); | |
| ADD_INT_MACRO(m, J1939_PGN_MAX); | |
| ADD_INT_MACRO(m, J1939_NO_PGN); | |
| /* J1939 socket options */ | |
| ADD_INT_MACRO(m, SO_J1939_FILTER); | |
| ADD_INT_MACRO(m, SO_J1939_PROMISC); | |
| ADD_INT_MACRO(m, SO_J1939_SEND_PRIO); | |
| ADD_INT_MACRO(m, SO_J1939_ERRQUEUE); | |
| ADD_INT_MACRO(m, SCM_J1939_DEST_ADDR); | |
| ADD_INT_MACRO(m, SCM_J1939_DEST_NAME); | |
| ADD_INT_MACRO(m, SCM_J1939_PRIO); | |
| ADD_INT_MACRO(m, SCM_J1939_ERRQUEUE); | |
| ADD_INT_MACRO(m, J1939_NLA_PAD); | |
| ADD_INT_MACRO(m, J1939_NLA_BYTES_ACKED); | |
| ADD_INT_MACRO(m, J1939_EE_INFO_NONE); | |
| ADD_INT_MACRO(m, J1939_EE_INFO_TX_ABORT); | |
| ADD_INT_MACRO(m, J1939_FILTER_MAX); | |
| #endif | |
| #ifdef HAVE_LINUX_CAN_ISOTP_H | |
| ADD_INT_MACRO(m, SOL_CAN_ISOTP); | |
| ADD_INT_MACRO(m, CAN_ISOTP_OPTS); | |
| ADD_INT_MACRO(m, CAN_ISOTP_RECV_FC); | |
| ADD_INT_MACRO(m, CAN_ISOTP_TX_STMIN); | |
| ADD_INT_MACRO(m, CAN_ISOTP_RX_STMIN); | |
| ADD_INT_MACRO(m, CAN_ISOTP_LL_OPTS); | |
| ADD_INT_MACRO(m, CAN_ISOTP_LISTEN_MODE); | |
| ADD_INT_MACRO(m, CAN_ISOTP_EXTEND_ADDR); | |
| ADD_INT_MACRO(m, CAN_ISOTP_TX_PADDING); | |
| ADD_INT_MACRO(m, CAN_ISOTP_RX_PADDING); | |
| ADD_INT_MACRO(m, CAN_ISOTP_CHK_PAD_LEN); | |
| ADD_INT_MACRO(m, CAN_ISOTP_CHK_PAD_DATA); | |
| ADD_INT_MACRO(m, CAN_ISOTP_HALF_DUPLEX); | |
| ADD_INT_MACRO(m, CAN_ISOTP_FORCE_TXSTMIN); | |
| ADD_INT_MACRO(m, CAN_ISOTP_FORCE_RXSTMIN); | |
| ADD_INT_MACRO(m, CAN_ISOTP_RX_EXT_ADDR); | |
| ADD_INT_MACRO(m, CAN_ISOTP_WAIT_TX_DONE); | |
| #ifdef CAN_ISOTP_SF_BROADCAST | |
| ADD_INT_MACRO(m, CAN_ISOTP_SF_BROADCAST); | |
| #endif | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_FLAGS); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_EXT_ADDRESS); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_PAD_CONTENT); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_FRAME_TXTIME); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_RECV_BS); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_RECV_STMIN); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_RECV_WFTMAX); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_LL_MTU); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_LL_TX_DL); | |
| ADD_INT_MACRO(m, CAN_ISOTP_DEFAULT_LL_TX_FLAGS); | |
| #endif | |
| #ifdef SOL_RDS | |
| ADD_INT_MACRO(m, SOL_RDS); | |
| #endif | |
| #ifdef HAVE_SOCKADDR_ALG | |
| ADD_INT_MACRO(m, SOL_ALG); | |
| #endif | |
| #ifdef RDS_CANCEL_SENT_TO | |
| ADD_INT_MACRO(m, RDS_CANCEL_SENT_TO); | |
| #endif | |
| #ifdef RDS_GET_MR | |
| ADD_INT_MACRO(m, RDS_GET_MR); | |
| #endif | |
| #ifdef RDS_FREE_MR | |
| ADD_INT_MACRO(m, RDS_FREE_MR); | |
| #endif | |
| #ifdef RDS_RECVERR | |
| ADD_INT_MACRO(m, RDS_RECVERR); | |
| #endif | |
| #ifdef RDS_CONG_MONITOR | |
| ADD_INT_MACRO(m, RDS_CONG_MONITOR); | |
| #endif | |
| #ifdef RDS_GET_MR_FOR_DEST | |
| ADD_INT_MACRO(m, RDS_GET_MR_FOR_DEST); | |
| #endif | |
| #ifdef IPPROTO_IP | |
| ADD_INT_MACRO(m, IPPROTO_IP); | |
| #else | |
| ADD_INT_CONST(m, "IPPROTO_IP", 0); | |
| #endif | |
| #ifdef IPPROTO_HOPOPTS | |
| ADD_INT_MACRO(m, IPPROTO_HOPOPTS); | |
| #endif | |
| #ifdef IPPROTO_ICMP | |
| ADD_INT_MACRO(m, IPPROTO_ICMP); | |
| #else | |
| ADD_INT_CONST(m, "IPPROTO_ICMP", 1); | |
| #endif | |
| #ifdef IPPROTO_IGMP | |
| ADD_INT_MACRO(m, IPPROTO_IGMP); | |
| #endif | |
| #ifdef IPPROTO_GGP | |
| ADD_INT_MACRO(m, IPPROTO_GGP); | |
| #endif | |
| #ifdef IPPROTO_IPV4 | |
| ADD_INT_MACRO(m, IPPROTO_IPV4); | |
| #endif | |
| #ifdef IPPROTO_IPV6 | |
| ADD_INT_MACRO(m, IPPROTO_IPV6); | |
| #endif | |
| #ifdef IPPROTO_IPIP | |
| ADD_INT_MACRO(m, IPPROTO_IPIP); | |
| #endif | |
| #ifdef IPPROTO_TCP | |
| ADD_INT_MACRO(m, IPPROTO_TCP); | |
| #else | |
| ADD_INT_CONST(m, "IPPROTO_TCP", 6); | |
| #endif | |
| #ifdef IPPROTO_EGP | |
| ADD_INT_MACRO(m, IPPROTO_EGP); | |
| #endif | |
| #ifdef IPPROTO_PUP | |
| ADD_INT_MACRO(m, IPPROTO_PUP); | |
| #endif | |
| #ifdef IPPROTO_UDP | |
| ADD_INT_MACRO(m, IPPROTO_UDP); | |
| #else | |
| ADD_INT_CONST(m, "IPPROTO_UDP", 17); | |
| #endif | |
| #ifdef IPPROTO_UDPLITE | |
| ADD_INT_MACRO(m, IPPROTO_UDPLITE); | |
| #ifndef UDPLITE_SEND_CSCOV | |
| #define UDPLITE_SEND_CSCOV 10 | |
| #endif | |
| ADD_INT_MACRO(m, UDPLITE_SEND_CSCOV); | |
| #ifndef UDPLITE_RECV_CSCOV | |
| #define UDPLITE_RECV_CSCOV 11 | |
| #endif | |
| ADD_INT_MACRO(m, UDPLITE_RECV_CSCOV); | |
| #endif | |
| #ifdef IPPROTO_IDP | |
| ADD_INT_MACRO(m, IPPROTO_IDP); | |
| #endif | |
| #ifdef IPPROTO_HELLO | |
| ADD_INT_MACRO(m, IPPROTO_HELLO); | |
| #endif | |
| #ifdef IPPROTO_ND | |
| ADD_INT_MACRO(m, IPPROTO_ND); | |
| #endif | |
| #ifdef IPPROTO_TP | |
| ADD_INT_MACRO(m, IPPROTO_TP); | |
| #endif | |
| #ifdef IPPROTO_ROUTING | |
| ADD_INT_MACRO(m, IPPROTO_ROUTING); | |
| #endif | |
| #ifdef IPPROTO_FRAGMENT | |
| ADD_INT_MACRO(m, IPPROTO_FRAGMENT); | |
| #endif | |
| #ifdef IPPROTO_RSVP | |
| ADD_INT_MACRO(m, IPPROTO_RSVP); | |
| #endif | |
| #ifdef IPPROTO_GRE | |
| ADD_INT_MACRO(m, IPPROTO_GRE); | |
| #endif | |
| #ifdef IPPROTO_ESP | |
| ADD_INT_MACRO(m, IPPROTO_ESP); | |
| #endif | |
| #ifdef IPPROTO_AH | |
| ADD_INT_MACRO(m, IPPROTO_AH); | |
| #endif | |
| #ifdef IPPROTO_MOBILE | |
| ADD_INT_MACRO(m, IPPROTO_MOBILE); | |
| #endif | |
| #ifdef IPPROTO_ICMPV6 | |
| ADD_INT_MACRO(m, IPPROTO_ICMPV6); | |
| #endif | |
| #ifdef IPPROTO_NONE | |
| ADD_INT_MACRO(m, IPPROTO_NONE); | |
| #endif | |
| #ifdef IPPROTO_DSTOPTS | |
| ADD_INT_MACRO(m, IPPROTO_DSTOPTS); | |
| #endif | |
| #ifdef IPPROTO_XTP | |
| ADD_INT_MACRO(m, IPPROTO_XTP); | |
| #endif | |
| #ifdef IPPROTO_EON | |
| ADD_INT_MACRO(m, IPPROTO_EON); | |
| #endif | |
| #ifdef IPPROTO_PIM | |
| ADD_INT_MACRO(m, IPPROTO_PIM); | |
| #endif | |
| #ifdef IPPROTO_IPCOMP | |
| ADD_INT_MACRO(m, IPPROTO_IPCOMP); | |
| #endif | |
| #ifdef IPPROTO_VRRP | |
| ADD_INT_MACRO(m, IPPROTO_VRRP); | |
| #endif | |
| #ifdef IPPROTO_SCTP | |
| ADD_INT_MACRO(m, IPPROTO_SCTP); | |
| #endif | |
| #ifdef IPPROTO_BIP | |
| ADD_INT_MACRO(m, IPPROTO_BIP); | |
| #endif | |
| #ifdef IPPROTO_MPTCP | |
| ADD_INT_MACRO(m, IPPROTO_MPTCP); | |
| #endif | |
| /**/ | |
| #ifdef IPPROTO_RAW | |
| ADD_INT_MACRO(m, IPPROTO_RAW); | |
| #else | |
| ADD_INT_CONST(m, "IPPROTO_RAW", 255); | |
| #endif | |
| #ifdef IPPROTO_MAX | |
| ADD_INT_MACRO(m, IPPROTO_MAX); | |
| #endif | |
| #ifdef MS_WINDOWS | |
| ADD_INT_MACRO(m, IPPROTO_ICLFXBM); | |
| ADD_INT_MACRO(m, IPPROTO_ST); | |
| ADD_INT_MACRO(m, IPPROTO_CBT); | |
| ADD_INT_MACRO(m, IPPROTO_IGP); | |
| ADD_INT_MACRO(m, IPPROTO_RDP); | |
| ADD_INT_MACRO(m, IPPROTO_PGM); | |
| ADD_INT_MACRO(m, IPPROTO_L2TP); | |
| ADD_INT_MACRO(m, IPPROTO_SCTP); | |
| #endif | |
| #ifdef SYSPROTO_CONTROL | |
| ADD_INT_MACRO(m, SYSPROTO_CONTROL); | |
| #endif | |
| /* Some port configuration */ | |
| #ifdef IPPORT_RESERVED | |
| ADD_INT_MACRO(m, IPPORT_RESERVED); | |
| #else | |
| ADD_INT_CONST(m, "IPPORT_RESERVED", 1024); | |
| #endif | |
| #ifdef IPPORT_USERRESERVED | |
| ADD_INT_MACRO(m, IPPORT_USERRESERVED); | |
| #else | |
| ADD_INT_CONST(m, "IPPORT_USERRESERVED", 5000); | |
| #endif | |
| /* Some reserved IP v.4 addresses */ | |
| #ifdef INADDR_ANY | |
| ADD_INT_MACRO(m, INADDR_ANY); | |
| #else | |
| ADD_INT_CONST(m, "INADDR_ANY", 0x00000000); | |
| #endif | |
| #ifdef INADDR_BROADCAST | |
| ADD_INT_MACRO(m, INADDR_BROADCAST); | |
| #else | |
| ADD_INT_CONST(m, "INADDR_BROADCAST", 0xffffffff); | |
| #endif | |
| #ifdef INADDR_LOOPBACK | |
| ADD_INT_MACRO(m, INADDR_LOOPBACK); | |
| #else | |
| ADD_INT_CONST(m, "INADDR_LOOPBACK", 0x7F000001); | |
| #endif | |
| #ifdef INADDR_UNSPEC_GROUP | |
| ADD_INT_MACRO(m, INADDR_UNSPEC_GROUP); | |
| #else | |
| ADD_INT_CONST(m, "INADDR_UNSPEC_GROUP", 0xe0000000); | |
| #endif | |
| #ifdef INADDR_ALLHOSTS_GROUP | |
| ADD_INT_CONST(m, "INADDR_ALLHOSTS_GROUP", | |
| INADDR_ALLHOSTS_GROUP); | |
| #else | |
| ADD_INT_CONST(m, "INADDR_ALLHOSTS_GROUP", 0xe0000001); | |
| #endif | |
| #ifdef INADDR_MAX_LOCAL_GROUP | |
| ADD_INT_MACRO(m, INADDR_MAX_LOCAL_GROUP); | |
| #else | |
| ADD_INT_CONST(m, "INADDR_MAX_LOCAL_GROUP", 0xe00000ff); | |
| #endif | |
| #ifdef INADDR_NONE | |
| ADD_INT_MACRO(m, INADDR_NONE); | |
| #else | |
| ADD_INT_CONST(m, "INADDR_NONE", 0xffffffff); | |
| #endif | |
| /* IPv4 [gs]etsockopt options */ | |
| #ifdef IP_OPTIONS | |
| ADD_INT_MACRO(m, IP_OPTIONS); | |
| #endif | |
| #ifdef IP_HDRINCL | |
| ADD_INT_MACRO(m, IP_HDRINCL); | |
| #endif | |
| #ifdef IP_TOS | |
| ADD_INT_MACRO(m, IP_TOS); | |
| #endif | |
| #ifdef IP_TTL | |
| ADD_INT_MACRO(m, IP_TTL); | |
| #endif | |
| #ifdef IP_RECVERR | |
| ADD_INT_MACRO(m, IP_RECVERR); | |
| #endif | |
| #ifdef IP_RECVOPTS | |
| ADD_INT_MACRO(m, IP_RECVOPTS); | |
| #endif | |
| #ifdef IP_RECVORIGDSTADDR | |
| ADD_INT_MACRO(m, IP_RECVORIGDSTADDR); | |
| #endif | |
| #ifdef IP_RECVRETOPTS | |
| ADD_INT_MACRO(m, IP_RECVRETOPTS); | |
| #endif | |
| #ifdef IP_RECVTOS | |
| ADD_INT_MACRO(m, IP_RECVTOS); | |
| #endif | |
| #ifdef IP_RECVTTL | |
| ADD_INT_MACRO(m, IP_RECVTTL); | |
| #endif | |
| #ifdef IP_RECVDSTADDR | |
| ADD_INT_MACRO(m, IP_RECVDSTADDR); | |
| #endif | |
| #ifdef IP_RETOPTS | |
| ADD_INT_MACRO(m, IP_RETOPTS); | |
| #endif | |
| #ifdef IP_MULTICAST_IF | |
| ADD_INT_MACRO(m, IP_MULTICAST_IF); | |
| #endif | |
| #ifdef IP_MULTICAST_TTL | |
| ADD_INT_MACRO(m, IP_MULTICAST_TTL); | |
| #endif | |
| #ifdef IP_MULTICAST_LOOP | |
| ADD_INT_MACRO(m, IP_MULTICAST_LOOP); | |
| #endif | |
| #ifdef IP_ADD_MEMBERSHIP | |
| ADD_INT_MACRO(m, IP_ADD_MEMBERSHIP); | |
| #endif | |
| #ifdef IP_DROP_MEMBERSHIP | |
| ADD_INT_MACRO(m, IP_DROP_MEMBERSHIP); | |
| #endif | |
| #ifdef IP_DEFAULT_MULTICAST_TTL | |
| ADD_INT_MACRO(m, IP_DEFAULT_MULTICAST_TTL); | |
| #endif | |
| #ifdef IP_DEFAULT_MULTICAST_LOOP | |
| ADD_INT_MACRO(m, IP_DEFAULT_MULTICAST_LOOP); | |
| #endif | |
| #ifdef IP_MAX_MEMBERSHIPS | |
| ADD_INT_MACRO(m, IP_MAX_MEMBERSHIPS); | |
| #endif | |
| #ifdef IP_FREEBIND | |
| ADD_INT_MACRO(m, IP_FREEBIND); | |
| #endif | |
| #ifdef IP_TRANSPARENT | |
| ADD_INT_MACRO(m, IP_TRANSPARENT); | |
| #endif | |
| #ifdef IP_PKTINFO | |
| ADD_INT_MACRO(m, IP_PKTINFO); | |
| #endif | |
| #ifdef IP_BIND_ADDRESS_NO_PORT | |
| ADD_INT_MACRO(m, IP_BIND_ADDRESS_NO_PORT); | |
| #endif | |
| #ifdef IP_UNBLOCK_SOURCE | |
| ADD_INT_MACRO(m, IP_UNBLOCK_SOURCE); | |
| #endif | |
| #ifdef IP_BLOCK_SOURCE | |
| ADD_INT_MACRO(m, IP_BLOCK_SOURCE); | |
| #endif | |
| #ifdef IP_ADD_SOURCE_MEMBERSHIP | |
| ADD_INT_MACRO(m, IP_ADD_SOURCE_MEMBERSHIP); | |
| #endif | |
| #ifdef IP_DROP_SOURCE_MEMBERSHIP | |
| ADD_INT_MACRO(m, IP_DROP_SOURCE_MEMBERSHIP); | |
| #endif | |
| /* IPv6 [gs]etsockopt options, defined in RFC2553 */ | |
| #ifdef IPV6_JOIN_GROUP | |
| ADD_INT_MACRO(m, IPV6_JOIN_GROUP); | |
| #endif | |
| #ifdef IPV6_LEAVE_GROUP | |
| ADD_INT_MACRO(m, IPV6_LEAVE_GROUP); | |
| #endif | |
| #ifdef IPV6_MULTICAST_HOPS | |
| ADD_INT_MACRO(m, IPV6_MULTICAST_HOPS); | |
| #endif | |
| #ifdef IPV6_MULTICAST_IF | |
| ADD_INT_MACRO(m, IPV6_MULTICAST_IF); | |
| #endif | |
| #ifdef IPV6_MULTICAST_LOOP | |
| ADD_INT_MACRO(m, IPV6_MULTICAST_LOOP); | |
| #endif | |
| #ifdef IPV6_UNICAST_HOPS | |
| ADD_INT_MACRO(m, IPV6_UNICAST_HOPS); | |
| #endif | |
| /* Additional IPV6 socket options, defined in RFC 3493 */ | |
| #ifdef IPV6_V6ONLY | |
| ADD_INT_MACRO(m, IPV6_V6ONLY); | |
| #endif | |
| /* Advanced IPV6 socket options, from RFC 3542 */ | |
| #ifdef IPV6_CHECKSUM | |
| ADD_INT_MACRO(m, IPV6_CHECKSUM); | |
| #endif | |
| #ifdef IPV6_DONTFRAG | |
| ADD_INT_MACRO(m, IPV6_DONTFRAG); | |
| #endif | |
| #ifdef IPV6_DSTOPTS | |
| ADD_INT_MACRO(m, IPV6_DSTOPTS); | |
| #endif | |
| #ifdef IPV6_HOPLIMIT | |
| ADD_INT_MACRO(m, IPV6_HOPLIMIT); | |
| #endif | |
| #ifdef IPV6_HDRINCL | |
| ADD_INT_MACRO(m, IPV6_HDRINCL); | |
| #endif | |
| #ifdef IPV6_HOPOPTS | |
| ADD_INT_MACRO(m, IPV6_HOPOPTS); | |
| #endif | |
| #ifdef IPV6_NEXTHOP | |
| ADD_INT_MACRO(m, IPV6_NEXTHOP); | |
| #endif | |
| #ifdef IPV6_PATHMTU | |
| ADD_INT_MACRO(m, IPV6_PATHMTU); | |
| #endif | |
| #ifdef IPV6_PKTINFO | |
| ADD_INT_MACRO(m, IPV6_PKTINFO); | |
| #endif | |
| #ifdef IPV6_RECVDSTOPTS | |
| ADD_INT_MACRO(m, IPV6_RECVDSTOPTS); | |
| #endif | |
| #ifdef IPV6_RECVERR | |
| ADD_INT_MACRO(m, IPV6_RECVERR); | |
| #endif | |
| #ifdef IPV6_RECVHOPLIMIT | |
| ADD_INT_MACRO(m, IPV6_RECVHOPLIMIT); | |
| #endif | |
| #ifdef IPV6_RECVHOPOPTS | |
| ADD_INT_MACRO(m, IPV6_RECVHOPOPTS); | |
| #endif | |
| #ifdef IPV6_RECVPKTINFO | |
| ADD_INT_MACRO(m, IPV6_RECVPKTINFO); | |
| #endif | |
| #ifdef IPV6_RECVRTHDR | |
| ADD_INT_MACRO(m, IPV6_RECVRTHDR); | |
| #endif | |
| #ifdef IPV6_RECVTCLASS | |
| ADD_INT_MACRO(m, IPV6_RECVTCLASS); | |
| #endif | |
| #ifdef IPV6_RTHDR | |
| ADD_INT_MACRO(m, IPV6_RTHDR); | |
| #endif | |
| #ifdef IPV6_RTHDRDSTOPTS | |
| ADD_INT_MACRO(m, IPV6_RTHDRDSTOPTS); | |
| #endif | |
| #ifdef IPV6_RTHDR_TYPE_0 | |
| ADD_INT_MACRO(m, IPV6_RTHDR_TYPE_0); | |
| #endif | |
| #ifdef IPV6_RECVPATHMTU | |
| ADD_INT_MACRO(m, IPV6_RECVPATHMTU); | |
| #endif | |
| #ifdef IPV6_TCLASS | |
| ADD_INT_MACRO(m, IPV6_TCLASS); | |
| #endif | |
| #ifdef IPV6_USE_MIN_MTU | |
| ADD_INT_MACRO(m, IPV6_USE_MIN_MTU); | |
| #endif | |
| /* TCP options */ | |
| #ifdef TCP_NODELAY | |
| ADD_INT_MACRO(m, TCP_NODELAY); | |
| #endif | |
| #ifdef TCP_MAXSEG | |
| ADD_INT_MACRO(m, TCP_MAXSEG); | |
| #endif | |
| #ifdef TCP_CORK | |
| ADD_INT_MACRO(m, TCP_CORK); | |
| #endif | |
| #ifdef TCP_KEEPIDLE | |
| ADD_INT_MACRO(m, TCP_KEEPIDLE); | |
| #endif | |
| /* TCP_KEEPALIVE is OSX's TCP_KEEPIDLE equivalent */ | |
| #if defined(__APPLE__) && defined(TCP_KEEPALIVE) | |
| ADD_INT_MACRO(m, TCP_KEEPALIVE); | |
| #endif | |
| #ifdef TCP_KEEPINTVL | |
| ADD_INT_MACRO(m, TCP_KEEPINTVL); | |
| #endif | |
| #ifdef TCP_KEEPCNT | |
| ADD_INT_MACRO(m, TCP_KEEPCNT); | |
| #endif | |
| #ifdef TCP_SYNCNT | |
| ADD_INT_MACRO(m, TCP_SYNCNT); | |
| #endif | |
| #ifdef TCP_LINGER2 | |
| ADD_INT_MACRO(m, TCP_LINGER2); | |
| #endif | |
| #ifdef TCP_DEFER_ACCEPT | |
| ADD_INT_MACRO(m, TCP_DEFER_ACCEPT); | |
| #endif | |
| #ifdef TCP_WINDOW_CLAMP | |
| ADD_INT_MACRO(m, TCP_WINDOW_CLAMP); | |
| #endif | |
| #ifdef TCP_INFO | |
| ADD_INT_MACRO(m, TCP_INFO); | |
| #endif | |
| #ifdef TCP_CONNECTION_INFO | |
| ADD_INT_MACRO(m, TCP_CONNECTION_INFO); | |
| #endif | |
| #ifdef SIO_TCP_SET_ACK_FREQUENCY | |
| #define TCP_QUICKACK SIO_TCP_SET_ACK_FREQUENCY | |
| #endif | |
| #ifdef TCP_QUICKACK | |
| ADD_INT_MACRO(m, TCP_QUICKACK); | |
| #endif | |
| #ifdef TCP_CONGESTION | |
| ADD_INT_MACRO(m, TCP_CONGESTION); | |
| #endif | |
| #ifdef TCP_MD5SIG | |
| ADD_INT_MACRO(m, TCP_MD5SIG); | |
| #endif | |
| #ifdef TCP_THIN_LINEAR_TIMEOUTS | |
| ADD_INT_MACRO(m, TCP_THIN_LINEAR_TIMEOUTS); | |
| #endif | |
| #ifdef TCP_THIN_DUPACK | |
| ADD_INT_MACRO(m, TCP_THIN_DUPACK); | |
| #endif | |
| #ifdef TCP_USER_TIMEOUT | |
| ADD_INT_MACRO(m, TCP_USER_TIMEOUT); | |
| #endif | |
| #ifdef TCP_REPAIR | |
| ADD_INT_MACRO(m, TCP_REPAIR); | |
| #endif | |
| #ifdef TCP_REPAIR_QUEUE | |
| ADD_INT_MACRO(m, TCP_REPAIR_QUEUE); | |
| #endif | |
| #ifdef TCP_QUEUE_SEQ | |
| ADD_INT_MACRO(m, TCP_QUEUE_SEQ); | |
| #endif | |
| #ifdef TCP_REPAIR_OPTIONS | |
| ADD_INT_MACRO(m, TCP_REPAIR_OPTIONS); | |
| #endif | |
| #ifdef TCP_FASTOPEN | |
| ADD_INT_MACRO(m, TCP_FASTOPEN); | |
| #endif | |
| #ifdef TCP_TIMESTAMP | |
| ADD_INT_MACRO(m, TCP_TIMESTAMP); | |
| #endif | |
| #ifdef TCP_NOTSENT_LOWAT | |
| ADD_INT_MACRO(m, TCP_NOTSENT_LOWAT); | |
| #endif | |
| #ifdef TCP_CC_INFO | |
| ADD_INT_MACRO(m, TCP_CC_INFO); | |
| #endif | |
| #ifdef TCP_SAVE_SYN | |
| ADD_INT_MACRO(m, TCP_SAVE_SYN); | |
| #endif | |
| #ifdef TCP_SAVED_SYN | |
| ADD_INT_MACRO(m, TCP_SAVED_SYN); | |
| #endif | |
| #ifdef TCP_REPAIR_WINDOW | |
| ADD_INT_MACRO(m, TCP_REPAIR_WINDOW); | |
| #endif | |
| #ifdef TCP_FASTOPEN_CONNECT | |
| ADD_INT_MACRO(m, TCP_FASTOPEN_CONNECT); | |
| #endif | |
| #ifdef TCP_ULP | |
| ADD_INT_MACRO(m, TCP_ULP); | |
| #endif | |
| #ifdef TCP_MD5SIG_EXT | |
| ADD_INT_MACRO(m, TCP_MD5SIG_EXT); | |
| #endif | |
| #ifdef TCP_FASTOPEN_KEY | |
| ADD_INT_MACRO(m, TCP_FASTOPEN_KEY); | |
| #endif | |
| #ifdef TCP_FASTOPEN_NO_COOKIE | |
| ADD_INT_MACRO(m, TCP_FASTOPEN_NO_COOKIE); | |
| #endif | |
| #ifdef TCP_ZEROCOPY_RECEIVE | |
| ADD_INT_MACRO(m, TCP_ZEROCOPY_RECEIVE); | |
| #endif | |
| #ifdef TCP_INQ | |
| ADD_INT_MACRO(m, TCP_INQ); | |
| #endif | |
| #ifdef TCP_TX_DELAY | |
| ADD_INT_MACRO(m, TCP_TX_DELAY); | |
| #endif | |
| /* IPX options */ | |
| #ifdef IPX_TYPE | |
| ADD_INT_MACRO(m, IPX_TYPE); | |
| #endif | |
| /* Reliable Datagram Sockets */ | |
| #ifdef RDS_CMSG_RDMA_ARGS | |
| ADD_INT_MACRO(m, RDS_CMSG_RDMA_ARGS); | |
| #endif | |
| #ifdef RDS_CMSG_RDMA_DEST | |
| ADD_INT_MACRO(m, RDS_CMSG_RDMA_DEST); | |
| #endif | |
| #ifdef RDS_CMSG_RDMA_MAP | |
| ADD_INT_MACRO(m, RDS_CMSG_RDMA_MAP); | |
| #endif | |
| #ifdef RDS_CMSG_RDMA_STATUS | |
| ADD_INT_MACRO(m, RDS_CMSG_RDMA_STATUS); | |
| #endif | |
| #ifdef RDS_CMSG_RDMA_UPDATE | |
| ADD_INT_MACRO(m, RDS_CMSG_RDMA_UPDATE); | |
| #endif | |
| #ifdef RDS_RDMA_READWRITE | |
| ADD_INT_MACRO(m, RDS_RDMA_READWRITE); | |
| #endif | |
| #ifdef RDS_RDMA_FENCE | |
| ADD_INT_MACRO(m, RDS_RDMA_FENCE); | |
| #endif | |
| #ifdef RDS_RDMA_INVALIDATE | |
| ADD_INT_MACRO(m, RDS_RDMA_INVALIDATE); | |
| #endif | |
| #ifdef RDS_RDMA_USE_ONCE | |
| ADD_INT_MACRO(m, RDS_RDMA_USE_ONCE); | |
| #endif | |
| #ifdef RDS_RDMA_DONTWAIT | |
| ADD_INT_MACRO(m, RDS_RDMA_DONTWAIT); | |
| #endif | |
| #ifdef RDS_RDMA_NOTIFY_ME | |
| ADD_INT_MACRO(m, RDS_RDMA_NOTIFY_ME); | |
| #endif | |
| #ifdef RDS_RDMA_SILENT | |
| ADD_INT_MACRO(m, RDS_RDMA_SILENT); | |
| #endif | |
| /* get{addr,name}info parameters */ | |
| #ifdef EAI_ADDRFAMILY | |
| ADD_INT_MACRO(m, EAI_ADDRFAMILY); | |
| #endif | |
| #ifdef EAI_AGAIN | |
| ADD_INT_MACRO(m, EAI_AGAIN); | |
| #endif | |
| #ifdef EAI_BADFLAGS | |
| ADD_INT_MACRO(m, EAI_BADFLAGS); | |
| #endif | |
| #ifdef EAI_FAIL | |
| ADD_INT_MACRO(m, EAI_FAIL); | |
| #endif | |
| #ifdef EAI_FAMILY | |
| ADD_INT_MACRO(m, EAI_FAMILY); | |
| #endif | |
| #ifdef EAI_MEMORY | |
| ADD_INT_MACRO(m, EAI_MEMORY); | |
| #endif | |
| #ifdef EAI_NODATA | |
| ADD_INT_MACRO(m, EAI_NODATA); | |
| #endif | |
| #ifdef EAI_NONAME | |
| ADD_INT_MACRO(m, EAI_NONAME); | |
| #endif | |
| #ifdef EAI_OVERFLOW | |
| ADD_INT_MACRO(m, EAI_OVERFLOW); | |
| #endif | |
| #ifdef EAI_SERVICE | |
| ADD_INT_MACRO(m, EAI_SERVICE); | |
| #endif | |
| #ifdef EAI_SOCKTYPE | |
| ADD_INT_MACRO(m, EAI_SOCKTYPE); | |
| #endif | |
| #ifdef EAI_SYSTEM | |
| ADD_INT_MACRO(m, EAI_SYSTEM); | |
| #endif | |
| #ifdef EAI_BADHINTS | |
| ADD_INT_MACRO(m, EAI_BADHINTS); | |
| #endif | |
| #ifdef EAI_PROTOCOL | |
| ADD_INT_MACRO(m, EAI_PROTOCOL); | |
| #endif | |
| #ifdef EAI_MAX | |
| ADD_INT_MACRO(m, EAI_MAX); | |
| #endif | |
| #ifdef AI_PASSIVE | |
| ADD_INT_MACRO(m, AI_PASSIVE); | |
| #endif | |
| #ifdef AI_CANONNAME | |
| ADD_INT_MACRO(m, AI_CANONNAME); | |
| #endif | |
| #ifdef AI_NUMERICHOST | |
| ADD_INT_MACRO(m, AI_NUMERICHOST); | |
| #endif | |
| #ifdef AI_NUMERICSERV | |
| ADD_INT_MACRO(m, AI_NUMERICSERV); | |
| #endif | |
| #ifdef AI_MASK | |
| ADD_INT_MACRO(m, AI_MASK); | |
| #endif | |
| #ifdef AI_ALL | |
| ADD_INT_MACRO(m, AI_ALL); | |
| #endif | |
| #ifdef AI_V4MAPPED_CFG | |
| ADD_INT_MACRO(m, AI_V4MAPPED_CFG); | |
| #endif | |
| #ifdef AI_ADDRCONFIG | |
| ADD_INT_MACRO(m, AI_ADDRCONFIG); | |
| #endif | |
| #ifdef AI_V4MAPPED | |
| ADD_INT_MACRO(m, AI_V4MAPPED); | |
| #endif | |
| #ifdef AI_DEFAULT | |
| ADD_INT_MACRO(m, AI_DEFAULT); | |
| #endif | |
| #ifdef NI_MAXHOST | |
| ADD_INT_MACRO(m, NI_MAXHOST); | |
| #endif | |
| #ifdef NI_MAXSERV | |
| ADD_INT_MACRO(m, NI_MAXSERV); | |
| #endif | |
| #ifdef NI_NOFQDN | |
| ADD_INT_MACRO(m, NI_NOFQDN); | |
| #endif | |
| #ifdef NI_NUMERICHOST | |
| ADD_INT_MACRO(m, NI_NUMERICHOST); | |
| #endif | |
| #ifdef NI_NAMEREQD | |
| ADD_INT_MACRO(m, NI_NAMEREQD); | |
| #endif | |
| #ifdef NI_NUMERICSERV | |
| ADD_INT_MACRO(m, NI_NUMERICSERV); | |
| #endif | |
| #ifdef NI_DGRAM | |
| ADD_INT_MACRO(m, NI_DGRAM); | |
| #endif | |
| #ifdef NI_IDN | |
| ADD_INT_MACRO(m, NI_IDN); | |
| #endif | |
| /* shutdown() parameters */ | |
| #ifdef SHUT_RD | |
| ADD_INT_MACRO(m, SHUT_RD); | |
| #elif defined(SD_RECEIVE) | |
| ADD_INT_CONST(m, "SHUT_RD", SD_RECEIVE); | |
| #else | |
| ADD_INT_CONST(m, "SHUT_RD", 0); | |
| #endif | |
| #ifdef SHUT_WR | |
| ADD_INT_MACRO(m, SHUT_WR); | |
| #elif defined(SD_SEND) | |
| ADD_INT_CONST(m, "SHUT_WR", SD_SEND); | |
| #else | |
| ADD_INT_CONST(m, "SHUT_WR", 1); | |
| #endif | |
| #ifdef SHUT_RDWR | |
| ADD_INT_MACRO(m, SHUT_RDWR); | |
| #elif defined(SD_BOTH) | |
| ADD_INT_CONST(m, "SHUT_RDWR", SD_BOTH); | |
| #else | |
| ADD_INT_CONST(m, "SHUT_RDWR", 2); | |
| #endif | |
| #ifdef SIO_RCVALL | |
| { | |
| DWORD codes[] = {SIO_RCVALL, SIO_KEEPALIVE_VALS, | |
| #if defined(SIO_LOOPBACK_FAST_PATH) | |
| SIO_LOOPBACK_FAST_PATH | |
| #endif | |
| }; | |
| const char *names[] = {"SIO_RCVALL", "SIO_KEEPALIVE_VALS", | |
| #if defined(SIO_LOOPBACK_FAST_PATH) | |
| "SIO_LOOPBACK_FAST_PATH" | |
| #endif | |
| }; | |
| int i; | |
| for (i = 0; i < Py_ARRAY_LENGTH(codes); ++i) { | |
| if (PyModule_Add(m, names[i], PyLong_FromUnsignedLong(codes[i])) < 0) { | |
| goto error; | |
| } | |
| } | |
| } | |
| ADD_INT_MACRO(m, RCVALL_OFF); | |
| ADD_INT_MACRO(m, RCVALL_ON); | |
| ADD_INT_MACRO(m, RCVALL_SOCKETLEVELONLY); | |
| #ifdef RCVALL_IPLEVEL | |
| ADD_INT_MACRO(m, RCVALL_IPLEVEL); | |
| #endif | |
| #ifdef RCVALL_MAX | |
| ADD_INT_MACRO(m, RCVALL_MAX); | |
| #endif | |
| #endif /* _MSTCPIP_ */ | |
| #ifdef MS_WINDOWS_DESKTOP | |
| /* remove some flags on older version Windows during run-time */ | |
| if (remove_unusable_flags(m) < 0) { | |
| goto error; | |
| } | |
| #endif | |
| #undef ADD_INT_MACRO | |
| #undef ADD_INT_CONST | |
| #undef ADD_STR_CONST | |
| return 0; | |
| error: | |
| return -1; | |
| } | |
| static struct PyModuleDef_Slot socket_slots[] = { | |
| _Py_ABI_SLOT, | |
| {Py_mod_exec, socket_exec}, | |
| {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | |
| {Py_mod_gil, Py_MOD_GIL_NOT_USED}, | |
| {0, NULL}, | |
| }; | |
| static int | |
| socket_traverse(PyObject *mod, visitproc visit, void *arg) | |
| { | |
| socket_state *state = get_module_state(mod); | |
| Py_VISIT(state->sock_type); | |
| Py_VISIT(state->socket_herror); | |
| Py_VISIT(state->socket_gaierror); | |
| return 0; | |
| } | |
| static int | |
| socket_clear(PyObject *mod) | |
| { | |
| socket_state *state = get_module_state(mod); | |
| Py_CLEAR(state->sock_type); | |
| Py_CLEAR(state->socket_herror); | |
| Py_CLEAR(state->socket_gaierror); | |
| return 0; | |
| } | |
| static void | |
| socket_free(void *mod) | |
| { | |
| (void)socket_clear((PyObject *)mod); | |
| } | |
| static struct PyModuleDef socketmodule = { | |
| .m_base = PyModuleDef_HEAD_INIT, | |
| .m_name = PySocket_MODULE_NAME, | |
| .m_doc = socket_doc, | |
| .m_size = sizeof(socket_state), | |
| .m_methods = socket_methods, | |
| .m_slots = socket_slots, | |
| .m_traverse = socket_traverse, | |
| .m_clear = socket_clear, | |
| .m_free = socket_free, | |
| }; | |
| PyMODINIT_FUNC | |
| PyInit__socket(void) | |
| { | |
| return PyModuleDef_Init(&socketmodule); | |
| } |