summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Andersson <bjorn@kryo.se>2018-09-26 13:47:52 (GMT)
committerTal Einat <taleinat+github@gmail.com>2018-09-26 13:47:52 (GMT)
commitbb8165172ac2ef8c7092e8e82928cc7f5f310ab3 (patch)
tree7674fc11d7cbb19a938d05e4a95d8e56446fb274
parent2aaf98c16ae3070378de523a173e29644037d8bd (diff)
downloadcpython-bb8165172ac2ef8c7092e8e82928cc7f5f310ab3.zip
cpython-bb8165172ac2ef8c7092e8e82928cc7f5f310ab3.tar.gz
cpython-bb8165172ac2ef8c7092e8e82928cc7f5f310ab3.tar.bz2
bpo-31425: Expose AF_QIPCRTR in socket module (GH-3706)
The AF_QIPCRTR address family was introduced in Linux v4.7. Co-authored-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r--Doc/library/socket.rst14
-rw-r--r--Lib/test/test_socket.py41
-rw-r--r--Misc/NEWS.d/next/Library/2017-10-24-10-18-35.bpo-31425.1lgw47.rst3
-rw-r--r--Modules/socketmodule.c51
-rw-r--r--Modules/socketmodule.h12
-rwxr-xr-xconfigure22
-rw-r--r--configure.ac10
-rw-r--r--pyconfig.h.in3
8 files changed, 154 insertions, 2 deletions
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
index 32e7c5e..44370fe 100644
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -193,6 +193,13 @@ created. Socket addresses are represented as follows:
- *addr* - Optional bytes-like object specifying the hardware physical
address, whose interpretation depends on the device.
+- :const:`AF_QIPCRTR` is a Linux-only socket based interface for communicating
+ with services running on co-processors in Qualcomm platforms. The address
+ family is represented as a ``(node, port)`` tuple where the *node* and *port*
+ are non-negative integers.
+
+ .. versionadded:: 3.7
+
If you use a hostname in the *host* portion of IPv4/v6 socket address, the
program may show a nondeterministic behavior, as Python uses the first address
returned from the DNS resolution. The socket address will be resolved
@@ -481,6 +488,13 @@ Constants
:const:`HCI_DATA_DIR` are not available for FreeBSD, NetBSD, or
DragonFlyBSD.
+.. data:: AF_QIPCRTR
+
+ Constant for Qualcomm's IPC router protocol, used to communicate with
+ service providing remote processors.
+
+ Availability: Linux >= 4.7.
+
Functions
^^^^^^^^^
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index bd4fad1..bbbf27b 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -94,6 +94,16 @@ def _have_socket_alg():
s.close()
return True
+def _have_socket_qipcrtr():
+ """Check whether AF_QIPCRTR sockets are supported on this host."""
+ try:
+ s = socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM, 0)
+ except (AttributeError, OSError):
+ return False
+ else:
+ s.close()
+ return True
+
def _have_socket_vsock():
"""Check whether AF_VSOCK sockets are supported on this host."""
ret = get_cid() is not None
@@ -113,6 +123,8 @@ HAVE_SOCKET_RDS = _have_socket_rds()
HAVE_SOCKET_ALG = _have_socket_alg()
+HAVE_SOCKET_QIPCRTR = _have_socket_qipcrtr()
+
HAVE_SOCKET_VSOCK = _have_socket_vsock()
# Size in bytes of the int type
@@ -2054,6 +2066,34 @@ class RDSTest(ThreadedRDSSocketTest):
self.data = b'select'
self.cli.sendto(self.data, 0, (HOST, self.port))
+@unittest.skipUnless(HAVE_SOCKET_QIPCRTR,
+ 'QIPCRTR sockets required for this test.')
+class BasicQIPCRTRTest(unittest.TestCase):
+
+ def testCrucialConstants(self):
+ socket.AF_QIPCRTR
+
+ def testCreateSocket(self):
+ with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
+ pass
+
+ def testUnbound(self):
+ with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
+ self.assertEqual(s.getsockname()[1], 0)
+
+ def testBindSock(self):
+ with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
+ support.bind_port(s, host=s.getsockname()[0])
+ self.assertNotEqual(s.getsockname()[1], 0)
+
+ def testInvalidBindSock(self):
+ with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
+ self.assertRaises(OSError, support.bind_port, s, host=-2)
+
+ def testAutoBindSock(self):
+ with socket.socket(socket.AF_QIPCRTR, socket.SOCK_DGRAM) as s:
+ s.connect((123, 123))
+ self.assertNotEqual(s.getsockname()[1], 0)
@unittest.skipIf(fcntl is None, "need fcntl")
@unittest.skipUnless(HAVE_SOCKET_VSOCK,
@@ -5978,6 +6018,7 @@ def test_main():
tests.extend([BasicCANTest, CANTest])
tests.extend([BasicRDSTest, RDSTest])
tests.append(LinuxKernelCryptoAPI)
+ tests.append(BasicQIPCRTRTest)
tests.extend([
BasicVSOCKTest,
ThreadedVSOCKSocketStreamTest,
diff --git a/Misc/NEWS.d/next/Library/2017-10-24-10-18-35.bpo-31425.1lgw47.rst b/Misc/NEWS.d/next/Library/2017-10-24-10-18-35.bpo-31425.1lgw47.rst
new file mode 100644
index 0000000..c5d6467
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-10-24-10-18-35.bpo-31425.1lgw47.rst
@@ -0,0 +1,3 @@
+Add support for sockets of the AF_QIPCRTR address family, supported by the
+Linux kernel. This is used to communicate with services, such as GPS or
+radio, running on Qualcomm devices.
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index adaefad..9149641 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -7,8 +7,8 @@ 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 and AF_TIPC are supported
- under Linux.
+ 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).
@@ -55,6 +55,8 @@ Module interface:
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;
@@ -1293,6 +1295,14 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
}
#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:
{
@@ -1668,6 +1678,30 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
}
#endif /* AF_NETLINK */
+#if defined(AF_QIPCRTR)
+ case AF_QIPCRTR:
+ {
+ struct sockaddr_qrtr* addr;
+ unsigned int node, port;
+ addr = (struct sockaddr_qrtr *)addr_ret;
+ 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:
{
@@ -2263,6 +2297,14 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
}
#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:
{
@@ -6983,6 +7025,11 @@ PyInit__socket(void)
#endif
#endif /* AF_NETLINK */
+#ifdef AF_QIPCRTR
+ /* Qualcomm IPCROUTER */
+ PyModule_AddIntMacro(m, AF_QIPCRTR);
+#endif
+
#ifdef AF_VSOCK
PyModule_AddIntConstant(m, "AF_VSOCK", AF_VSOCK);
PyModule_AddIntConstant(m, "SO_VM_SOCKETS_BUFFER_SIZE", 0);
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index 0b2edc1..dff1f8f 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -54,6 +54,15 @@ typedef int socklen_t;
# undef AF_NETLINK
#endif
+#ifdef HAVE_LINUX_QRTR_H
+# ifdef HAVE_ASM_TYPES_H
+# include <asm/types.h>
+# endif
+# include <linux/qrtr.h>
+#else
+# undef AF_QIPCRTR
+#endif
+
#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
@@ -203,6 +212,9 @@ typedef union sock_addr {
#ifdef HAVE_SOCKADDR_ALG
struct sockaddr_alg alg;
#endif
+#ifdef AF_QIPCRTR
+ struct sockaddr_qrtr sq;
+#endif
#ifdef AF_VSOCK
struct sockaddr_vm vm;
#endif
diff --git a/configure b/configure
index 38546d6..9d2c4e4 100755
--- a/configure
+++ b/configure
@@ -8023,6 +8023,28 @@ fi
done
+# On Linux, qrtr.h requires asm/types.h
+for ac_header in linux/qrtr.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "linux/qrtr.h" "ac_cv_header_linux_qrtr_h" "
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+"
+if test "x$ac_cv_header_linux_qrtr_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_QRTR_H 1
+_ACEOF
+
+fi
+
+done
+
+
for ac_header in linux/vm_sockets.h
do :
ac_fn_c_check_header_compile "$LINENO" "linux/vm_sockets.h" "ac_cv_header_linux_vm_sockets_h" "
diff --git a/configure.ac b/configure.ac
index 96331ec..2235a13 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2112,6 +2112,16 @@ AC_CHECK_HEADERS(linux/netlink.h,,,[
#endif
])
+# On Linux, qrtr.h requires asm/types.h
+AC_CHECK_HEADERS(linux/qrtr.h,,,[
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+])
+
AC_CHECK_HEADERS(linux/vm_sockets.h,,,[
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 41e0479..254a2dc 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -615,6 +615,9 @@
/* Define to 1 if you have the <linux/netlink.h> header file. */
#undef HAVE_LINUX_NETLINK_H
+/* Define to 1 if you have the <linux/qrtr.h> header file. */
+#undef HAVE_LINUX_QRTR_H
+
/* Define to 1 if you have the <linux/random.h> header file. */
#undef HAVE_LINUX_RANDOM_H