Commit bb816517 authored by Bjorn Andersson's avatar Bjorn Andersson Committed by Tal Einat

bpo-31425: Expose AF_QIPCRTR in socket module (GH-3706)

The AF_QIPCRTR address family was introduced in Linux v4.7.
Co-authored-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent 2aaf98c1
...@@ -193,6 +193,13 @@ created. Socket addresses are represented as follows: ...@@ -193,6 +193,13 @@ created. Socket addresses are represented as follows:
- *addr* - Optional bytes-like object specifying the hardware physical - *addr* - Optional bytes-like object specifying the hardware physical
address, whose interpretation depends on the device. 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 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 program may show a nondeterministic behavior, as Python uses the first address
returned from the DNS resolution. The socket address will be resolved returned from the DNS resolution. The socket address will be resolved
...@@ -481,6 +488,13 @@ Constants ...@@ -481,6 +488,13 @@ Constants
:const:`HCI_DATA_DIR` are not available for FreeBSD, NetBSD, or :const:`HCI_DATA_DIR` are not available for FreeBSD, NetBSD, or
DragonFlyBSD. DragonFlyBSD.
.. data:: AF_QIPCRTR
Constant for Qualcomm's IPC router protocol, used to communicate with
service providing remote processors.
Availability: Linux >= 4.7.
Functions Functions
^^^^^^^^^ ^^^^^^^^^
......
...@@ -94,6 +94,16 @@ def _have_socket_alg(): ...@@ -94,6 +94,16 @@ def _have_socket_alg():
s.close() s.close()
return True 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(): def _have_socket_vsock():
"""Check whether AF_VSOCK sockets are supported on this host.""" """Check whether AF_VSOCK sockets are supported on this host."""
ret = get_cid() is not None ret = get_cid() is not None
...@@ -113,6 +123,8 @@ HAVE_SOCKET_RDS = _have_socket_rds() ...@@ -113,6 +123,8 @@ HAVE_SOCKET_RDS = _have_socket_rds()
HAVE_SOCKET_ALG = _have_socket_alg() HAVE_SOCKET_ALG = _have_socket_alg()
HAVE_SOCKET_QIPCRTR = _have_socket_qipcrtr()
HAVE_SOCKET_VSOCK = _have_socket_vsock() HAVE_SOCKET_VSOCK = _have_socket_vsock()
# Size in bytes of the int type # Size in bytes of the int type
...@@ -2054,6 +2066,34 @@ class RDSTest(ThreadedRDSSocketTest): ...@@ -2054,6 +2066,34 @@ class RDSTest(ThreadedRDSSocketTest):
self.data = b'select' self.data = b'select'
self.cli.sendto(self.data, 0, (HOST, self.port)) 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.skipIf(fcntl is None, "need fcntl")
@unittest.skipUnless(HAVE_SOCKET_VSOCK, @unittest.skipUnless(HAVE_SOCKET_VSOCK,
...@@ -5978,6 +6018,7 @@ def test_main(): ...@@ -5978,6 +6018,7 @@ def test_main():
tests.extend([BasicCANTest, CANTest]) tests.extend([BasicCANTest, CANTest])
tests.extend([BasicRDSTest, RDSTest]) tests.extend([BasicRDSTest, RDSTest])
tests.append(LinuxKernelCryptoAPI) tests.append(LinuxKernelCryptoAPI)
tests.append(BasicQIPCRTRTest)
tests.extend([ tests.extend([
BasicVSOCKTest, BasicVSOCKTest,
ThreadedVSOCKSocketStreamTest, ThreadedVSOCKSocketStreamTest,
......
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.
...@@ -7,8 +7,8 @@ This module provides an interface to Berkeley socket IPC. ...@@ -7,8 +7,8 @@ This module provides an interface to Berkeley socket IPC.
Limitations: Limitations:
- Only AF_INET, AF_INET6 and AF_UNIX address families are supported in a - 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 portable manner, though AF_PACKET, AF_NETLINK, AF_QIPCRTR and AF_TIPC are
under Linux. supported under Linux.
- No read/write operations (use sendall/recv or makefile instead). - No read/write operations (use sendall/recv or makefile instead).
- Additional restrictions apply on some non-Unix platforms (compensated - Additional restrictions apply on some non-Unix platforms (compensated
for by socket.py). for by socket.py).
...@@ -55,6 +55,8 @@ Module interface: ...@@ -55,6 +55,8 @@ Module interface:
the Ethernet protocol number to be received. For example: the Ethernet protocol number to be received. For example:
("eth0",0x1234). Optional 3rd,4th,5th elements in the tuple ("eth0",0x1234). Optional 3rd,4th,5th elements in the tuple
specify packet-type and ha-type/addr. 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 - an AF_TIPC socket address is expressed as
(addr_type, v1, v2, v3 [, scope]); where addr_type can be one of: (addr_type, v1, v2, v3 [, scope]); where addr_type can be one of:
TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, and TIPC_ADDR_ID; 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) ...@@ -1293,6 +1295,14 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
} }
#endif /* AF_NETLINK */ #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) #if defined(AF_VSOCK)
case AF_VSOCK: case AF_VSOCK:
{ {
...@@ -1668,6 +1678,30 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, ...@@ -1668,6 +1678,30 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
} }
#endif /* AF_NETLINK */ #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) #if defined(AF_VSOCK)
case AF_VSOCK: case AF_VSOCK:
{ {
...@@ -2263,6 +2297,14 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret) ...@@ -2263,6 +2297,14 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
} }
#endif /* AF_NETLINK */ #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) #if defined(AF_VSOCK)
case AF_VSOCK: case AF_VSOCK:
{ {
...@@ -6983,6 +7025,11 @@ PyInit__socket(void) ...@@ -6983,6 +7025,11 @@ PyInit__socket(void)
#endif #endif
#endif /* AF_NETLINK */ #endif /* AF_NETLINK */
#ifdef AF_QIPCRTR
/* Qualcomm IPCROUTER */
PyModule_AddIntMacro(m, AF_QIPCRTR);
#endif
#ifdef AF_VSOCK #ifdef AF_VSOCK
PyModule_AddIntConstant(m, "AF_VSOCK", AF_VSOCK); PyModule_AddIntConstant(m, "AF_VSOCK", AF_VSOCK);
PyModule_AddIntConstant(m, "SO_VM_SOCKETS_BUFFER_SIZE", 0); PyModule_AddIntConstant(m, "SO_VM_SOCKETS_BUFFER_SIZE", 0);
......
...@@ -54,6 +54,15 @@ typedef int socklen_t; ...@@ -54,6 +54,15 @@ typedef int socklen_t;
# undef AF_NETLINK # undef AF_NETLINK
#endif #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 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
#include <bluetooth/bluetooth.h> #include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h> #include <bluetooth/rfcomm.h>
...@@ -203,6 +212,9 @@ typedef union sock_addr { ...@@ -203,6 +212,9 @@ typedef union sock_addr {
#ifdef HAVE_SOCKADDR_ALG #ifdef HAVE_SOCKADDR_ALG
struct sockaddr_alg alg; struct sockaddr_alg alg;
#endif #endif
#ifdef AF_QIPCRTR
struct sockaddr_qrtr sq;
#endif
#ifdef AF_VSOCK #ifdef AF_VSOCK
struct sockaddr_vm vm; struct sockaddr_vm vm;
#endif #endif
......
...@@ -8023,6 +8023,28 @@ fi ...@@ -8023,6 +8023,28 @@ fi
done 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 for ac_header in linux/vm_sockets.h
do : do :
ac_fn_c_check_header_compile "$LINENO" "linux/vm_sockets.h" "ac_cv_header_linux_vm_sockets_h" " ac_fn_c_check_header_compile "$LINENO" "linux/vm_sockets.h" "ac_cv_header_linux_vm_sockets_h" "
......
...@@ -2112,6 +2112,16 @@ AC_CHECK_HEADERS(linux/netlink.h,,,[ ...@@ -2112,6 +2112,16 @@ AC_CHECK_HEADERS(linux/netlink.h,,,[
#endif #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,,,[ AC_CHECK_HEADERS(linux/vm_sockets.h,,,[
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
......
...@@ -615,6 +615,9 @@ ...@@ -615,6 +615,9 @@
/* Define to 1 if you have the <linux/netlink.h> header file. */ /* Define to 1 if you have the <linux/netlink.h> header file. */
#undef HAVE_LINUX_NETLINK_H #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. */ /* Define to 1 if you have the <linux/random.h> header file. */
#undef HAVE_LINUX_RANDOM_H #undef HAVE_LINUX_RANDOM_H
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment