Issue #27744: Add AF_ALG (Linux Kernel crypto) to socket module.
This commit is contained in:
parent
92a6c170e6
commit
dffa3949c7
|
@ -131,6 +131,22 @@ created. Socket addresses are represented as follows:
|
||||||
string format. (ex. ``b'12:23:34:45:56:67'``) This protocol is not
|
string format. (ex. ``b'12:23:34:45:56:67'``) This protocol is not
|
||||||
supported under FreeBSD.
|
supported under FreeBSD.
|
||||||
|
|
||||||
|
- :const:`AF_ALG` is a Linux-only socket based interface to Kernel
|
||||||
|
cryptography. An algorithm socket is configured with a tuple of two to four
|
||||||
|
elements ``(type, name [, feat [, mask]])``, where:
|
||||||
|
|
||||||
|
- *type* is the algorithm type as string, e.g. ``aead``, ``hash``,
|
||||||
|
``skcipher`` or ``rng``.
|
||||||
|
|
||||||
|
- *name* is the algorithm name and operation mode as string, e.g.
|
||||||
|
``sha256``, ``hmac(sha256)``, ``cbc(aes)`` or ``drbg_nopr_ctr_aes256``.
|
||||||
|
|
||||||
|
- *feat* and *mask* are unsigned 32bit integers.
|
||||||
|
|
||||||
|
Availability Linux 2.6.38, some algorithm types require more recent Kernels.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
- Certain other address families (:const:`AF_PACKET`, :const:`AF_CAN`)
|
- Certain other address families (:const:`AF_PACKET`, :const:`AF_CAN`)
|
||||||
support specific representations.
|
support specific representations.
|
||||||
|
|
||||||
|
@ -350,6 +366,16 @@ Constants
|
||||||
TIPC related constants, matching the ones exported by the C socket API. See
|
TIPC related constants, matching the ones exported by the C socket API. See
|
||||||
the TIPC documentation for more information.
|
the TIPC documentation for more information.
|
||||||
|
|
||||||
|
.. data:: AF_ALG
|
||||||
|
SOL_ALG
|
||||||
|
ALG_*
|
||||||
|
|
||||||
|
Constants for Linux Kernel cryptography.
|
||||||
|
|
||||||
|
Availability: Linux >= 2.6.38.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
.. data:: AF_LINK
|
.. data:: AF_LINK
|
||||||
|
|
||||||
Availability: BSD, OSX.
|
Availability: BSD, OSX.
|
||||||
|
@ -1294,6 +1320,15 @@ to sockets.
|
||||||
an exception, the method now retries the system call instead of raising
|
an exception, the method now retries the system call instead of raising
|
||||||
an :exc:`InterruptedError` exception (see :pep:`475` for the rationale).
|
an :exc:`InterruptedError` exception (see :pep:`475` for the rationale).
|
||||||
|
|
||||||
|
.. method:: socket.sendmsg_afalg([msg], *, op[, iv[, assoclen[, flags]]])
|
||||||
|
|
||||||
|
Specialized version of :meth:`~socket.sendmsg` for :const:`AF_ALG` socket.
|
||||||
|
Set mode, IV, AEAD associated data length and flags for :const:`AF_ALG` socket.
|
||||||
|
|
||||||
|
Availability: Linux >= 2.6.38
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
.. method:: socket.sendfile(file, offset=0, count=None)
|
.. method:: socket.sendfile(file, offset=0, count=None)
|
||||||
|
|
||||||
Send a file until EOF is reached by using high-performance
|
Send a file until EOF is reached by using high-performance
|
||||||
|
@ -1342,21 +1377,29 @@ to sockets.
|
||||||
For further information, please consult the :ref:`notes on socket timeouts <socket-timeouts>`.
|
For further information, please consult the :ref:`notes on socket timeouts <socket-timeouts>`.
|
||||||
|
|
||||||
|
|
||||||
.. method:: socket.setsockopt(level, optname, value)
|
.. method:: socket.setsockopt(level, optname, value: int)
|
||||||
|
.. method:: socket.setsockopt(level, optname, value: buffer)
|
||||||
|
.. method:: socket.setsockopt(level, optname, None, optlen: int)
|
||||||
|
|
||||||
.. index:: module: struct
|
.. index:: module: struct
|
||||||
|
|
||||||
Set the value of the given socket option (see the Unix manual page
|
Set the value of the given socket option (see the Unix manual page
|
||||||
:manpage:`setsockopt(2)`). The needed symbolic constants are defined in the
|
:manpage:`setsockopt(2)`). The needed symbolic constants are defined in the
|
||||||
:mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer or
|
:mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer,
|
||||||
a :term:`bytes-like object` representing a buffer. In the latter case it is
|
None or a :term:`bytes-like object` representing a buffer. In the later
|
||||||
up to the caller to
|
case it is up to the caller to ensure that the bytestring contains the
|
||||||
ensure that the bytestring contains the proper bits (see the optional built-in
|
proper bits (see the optional built-in module :mod:`struct` for a way to
|
||||||
module :mod:`struct` for a way to encode C structures as bytestrings).
|
encode C structures as bytestrings). When value is set to None,
|
||||||
|
optlen argument is required. It's equivalent to call setsockopt C
|
||||||
|
function with optval=NULL and optlen=optlen.
|
||||||
|
|
||||||
|
|
||||||
.. versionchanged:: 3.5
|
.. versionchanged:: 3.5
|
||||||
Writable :term:`bytes-like object` is now accepted.
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
setsockopt(level, optname, None, optlen: int) form added.
|
||||||
|
|
||||||
|
|
||||||
.. method:: socket.shutdown(how)
|
.. method:: socket.shutdown(how)
|
||||||
|
|
||||||
|
|
|
@ -5325,6 +5325,170 @@ class SendfileUsingSendfileTest(SendfileUsingSendTest):
|
||||||
def meth_from_sock(self, sock):
|
def meth_from_sock(self, sock):
|
||||||
return getattr(sock, "_sendfile_use_sendfile")
|
return getattr(sock, "_sendfile_use_sendfile")
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(socket, "AF_ALG"), 'AF_ALG required')
|
||||||
|
class LinuxKernelCryptoAPI(unittest.TestCase):
|
||||||
|
# tests for AF_ALG
|
||||||
|
def create_alg(self, typ, name):
|
||||||
|
sock = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
|
||||||
|
sock.bind((typ, name))
|
||||||
|
return sock
|
||||||
|
|
||||||
|
def test_sha256(self):
|
||||||
|
expected = bytes.fromhex("ba7816bf8f01cfea414140de5dae2223b00361a396"
|
||||||
|
"177a9cb410ff61f20015ad")
|
||||||
|
with self.create_alg('hash', 'sha256') as algo:
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
op.sendall(b"abc")
|
||||||
|
self.assertEqual(op.recv(512), expected)
|
||||||
|
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
op.send(b'a', socket.MSG_MORE)
|
||||||
|
op.send(b'b', socket.MSG_MORE)
|
||||||
|
op.send(b'c', socket.MSG_MORE)
|
||||||
|
op.send(b'')
|
||||||
|
self.assertEqual(op.recv(512), expected)
|
||||||
|
|
||||||
|
def test_hmac_sha1(self):
|
||||||
|
expected = bytes.fromhex("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79")
|
||||||
|
with self.create_alg('hash', 'hmac(sha1)') as algo:
|
||||||
|
algo.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, b"Jefe")
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
op.sendall(b"what do ya want for nothing?")
|
||||||
|
self.assertEqual(op.recv(512), expected)
|
||||||
|
|
||||||
|
def test_aes_cbc(self):
|
||||||
|
key = bytes.fromhex('06a9214036b8a15b512e03d534120006')
|
||||||
|
iv = bytes.fromhex('3dafba429d9eb430b422da802c9fac41')
|
||||||
|
msg = b"Single block msg"
|
||||||
|
ciphertext = bytes.fromhex('e353779c1079aeb82708942dbe77181a')
|
||||||
|
msglen = len(msg)
|
||||||
|
with self.create_alg('skcipher', 'cbc(aes)') as algo:
|
||||||
|
algo.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, key)
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
op.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, iv=iv,
|
||||||
|
flags=socket.MSG_MORE)
|
||||||
|
op.sendall(msg)
|
||||||
|
self.assertEqual(op.recv(msglen), ciphertext)
|
||||||
|
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
op.sendmsg_afalg([ciphertext],
|
||||||
|
op=socket.ALG_OP_DECRYPT, iv=iv)
|
||||||
|
self.assertEqual(op.recv(msglen), msg)
|
||||||
|
|
||||||
|
# long message
|
||||||
|
multiplier = 1024
|
||||||
|
longmsg = [msg] * multiplier
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
op.sendmsg_afalg(longmsg,
|
||||||
|
op=socket.ALG_OP_ENCRYPT, iv=iv)
|
||||||
|
enc = op.recv(msglen * multiplier)
|
||||||
|
self.assertEqual(len(enc), msglen * multiplier)
|
||||||
|
self.assertTrue(enc[:msglen], ciphertext)
|
||||||
|
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
op.sendmsg_afalg([enc],
|
||||||
|
op=socket.ALG_OP_DECRYPT, iv=iv)
|
||||||
|
dec = op.recv(msglen * multiplier)
|
||||||
|
self.assertEqual(len(dec), msglen * multiplier)
|
||||||
|
self.assertEqual(dec, msg * multiplier)
|
||||||
|
|
||||||
|
@support.requires_linux_version(3, 19)
|
||||||
|
def test_aead_aes_gcm(self):
|
||||||
|
key = bytes.fromhex('c939cc13397c1d37de6ae0e1cb7c423c')
|
||||||
|
iv = bytes.fromhex('b3d8cc017cbb89b39e0f67e2')
|
||||||
|
plain = bytes.fromhex('c3b3c41f113a31b73d9a5cd432103069')
|
||||||
|
assoc = bytes.fromhex('24825602bd12a984e0092d3e448eda5f')
|
||||||
|
expected_ct = bytes.fromhex('93fe7d9e9bfd10348a5606e5cafa7354')
|
||||||
|
expected_tag = bytes.fromhex('0032a1dc85f1c9786925a2e71d8272dd')
|
||||||
|
|
||||||
|
taglen = len(expected_tag)
|
||||||
|
assoclen = len(assoc)
|
||||||
|
|
||||||
|
with self.create_alg('aead', 'gcm(aes)') as algo:
|
||||||
|
algo.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, key)
|
||||||
|
algo.setsockopt(socket.SOL_ALG, socket.ALG_SET_AEAD_AUTHSIZE,
|
||||||
|
None, taglen)
|
||||||
|
|
||||||
|
# send assoc, plain and tag buffer in separate steps
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
op.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, iv=iv,
|
||||||
|
assoclen=assoclen, flags=socket.MSG_MORE)
|
||||||
|
op.sendall(assoc, socket.MSG_MORE)
|
||||||
|
op.sendall(plain, socket.MSG_MORE)
|
||||||
|
op.sendall(b'\x00' * taglen)
|
||||||
|
res = op.recv(assoclen + len(plain) + taglen)
|
||||||
|
self.assertEqual(expected_ct, res[assoclen:-taglen])
|
||||||
|
self.assertEqual(expected_tag, res[-taglen:])
|
||||||
|
|
||||||
|
# now with msg
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
msg = assoc + plain + b'\x00' * taglen
|
||||||
|
op.sendmsg_afalg([msg], op=socket.ALG_OP_ENCRYPT, iv=iv,
|
||||||
|
assoclen=assoclen)
|
||||||
|
res = op.recv(assoclen + len(plain) + taglen)
|
||||||
|
self.assertEqual(expected_ct, res[assoclen:-taglen])
|
||||||
|
self.assertEqual(expected_tag, res[-taglen:])
|
||||||
|
|
||||||
|
# create anc data manually
|
||||||
|
pack_uint32 = struct.Struct('I').pack
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
msg = assoc + plain + b'\x00' * taglen
|
||||||
|
op.sendmsg(
|
||||||
|
[msg],
|
||||||
|
([socket.SOL_ALG, socket.ALG_SET_OP, pack_uint32(socket.ALG_OP_ENCRYPT)],
|
||||||
|
[socket.SOL_ALG, socket.ALG_SET_IV, pack_uint32(len(iv)) + iv],
|
||||||
|
[socket.SOL_ALG, socket.ALG_SET_AEAD_ASSOCLEN, pack_uint32(assoclen)],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
res = op.recv(len(msg))
|
||||||
|
self.assertEqual(expected_ct, res[assoclen:-taglen])
|
||||||
|
self.assertEqual(expected_tag, res[-taglen:])
|
||||||
|
|
||||||
|
# decrypt and verify
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
msg = assoc + expected_ct + expected_tag
|
||||||
|
op.sendmsg_afalg([msg], op=socket.ALG_OP_DECRYPT, iv=iv,
|
||||||
|
assoclen=assoclen)
|
||||||
|
res = op.recv(len(msg))
|
||||||
|
self.assertEqual(plain, res[assoclen:-taglen])
|
||||||
|
|
||||||
|
def test_drbg_pr_sha256(self):
|
||||||
|
# deterministic random bit generator, prediction resistance, sha256
|
||||||
|
with self.create_alg('rng', 'drbg_pr_sha256') as algo:
|
||||||
|
extra_seed = os.urandom(32)
|
||||||
|
algo.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, extra_seed)
|
||||||
|
op, _ = algo.accept()
|
||||||
|
with op:
|
||||||
|
rn = op.recv(32)
|
||||||
|
self.assertEqual(len(rn), 32)
|
||||||
|
|
||||||
|
def test_sendmsg_afalg_args(self):
|
||||||
|
sock = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
sock.sendmsg_afalg()
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
sock.sendmsg_afalg(op=None)
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
sock.sendmsg_afalg(1)
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
sock.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, assoclen=None)
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
sock.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, assoclen=-1)
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest,
|
tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest,
|
||||||
|
@ -5352,6 +5516,7 @@ def test_main():
|
||||||
tests.extend([TIPCTest, TIPCThreadableTest])
|
tests.extend([TIPCTest, TIPCThreadableTest])
|
||||||
tests.extend([BasicCANTest, CANTest])
|
tests.extend([BasicCANTest, CANTest])
|
||||||
tests.extend([BasicRDSTest, RDSTest])
|
tests.extend([BasicRDSTest, RDSTest])
|
||||||
|
tests.append(LinuxKernelCryptoAPI)
|
||||||
tests.extend([
|
tests.extend([
|
||||||
CmsgMacroTests,
|
CmsgMacroTests,
|
||||||
SendmsgUDPTest,
|
SendmsgUDPTest,
|
||||||
|
|
|
@ -77,6 +77,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #27744: Add AF_ALG (Linux Kernel crypto) to socket module.
|
||||||
|
|
||||||
- Issue #26470: Port ssl and hashlib module to OpenSSL 1.1.0.
|
- Issue #26470: Port ssl and hashlib module to OpenSSL 1.1.0.
|
||||||
|
|
||||||
- Issue #11620: Fix support for SND_MEMORY in winsound.PlaySound. Based on a
|
- Issue #11620: Fix support for SND_MEMORY in winsound.PlaySound. Based on a
|
||||||
|
|
|
@ -136,7 +136,7 @@ sendall(data[, flags]) -- send all data\n\
|
||||||
send(data[, flags]) -- send data, may not send all of it\n\
|
send(data[, flags]) -- send data, may not send all of it\n\
|
||||||
sendto(data[, flags], addr) -- send data to a given address\n\
|
sendto(data[, flags], addr) -- send data to a given address\n\
|
||||||
setblocking(0 | 1) -- set or clear the blocking I/O flag\n\
|
setblocking(0 | 1) -- set or clear the blocking I/O flag\n\
|
||||||
setsockopt(level, optname, value) -- set socket options\n\
|
setsockopt(level, optname, value[, optlen]) -- set socket options\n\
|
||||||
settimeout(None | float) -- set or clear the timeout\n\
|
settimeout(None | float) -- set or clear the timeout\n\
|
||||||
shutdown(how) -- shut down traffic in one or both directions\n\
|
shutdown(how) -- shut down traffic in one or both directions\n\
|
||||||
if_nameindex() -- return all network interface indices and names\n\
|
if_nameindex() -- return all network interface indices and names\n\
|
||||||
|
@ -286,6 +286,36 @@ http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getaddrinfo.c.diff?r1=1.82&
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SOCKADDR_ALG
|
||||||
|
#include <linux/if_alg.h>
|
||||||
|
#ifndef AF_ALG
|
||||||
|
#define AF_ALG 38
|
||||||
|
#endif
|
||||||
|
#ifndef SOL_ALG
|
||||||
|
#define SOL_ALG 279
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Linux 3.19 */
|
||||||
|
#ifndef ALG_SET_AEAD_ASSOCLEN
|
||||||
|
#define ALG_SET_AEAD_ASSOCLEN 4
|
||||||
|
#endif
|
||||||
|
#ifndef ALG_SET_AEAD_AUTHSIZE
|
||||||
|
#define ALG_SET_AEAD_AUTHSIZE 5
|
||||||
|
#endif
|
||||||
|
/* Linux 4.8 */
|
||||||
|
#ifndef ALG_SET_PUBKEY
|
||||||
|
#define ALG_SET_PUBKEY 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ALG_OP_SIGN
|
||||||
|
#define ALG_OP_SIGN 2
|
||||||
|
#endif
|
||||||
|
#ifndef ALG_OP_VERIFY
|
||||||
|
#define ALG_OP_VERIFY 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAVE_SOCKADDR_ALG */
|
||||||
|
|
||||||
/* Generic socket object definitions and includes */
|
/* Generic socket object definitions and includes */
|
||||||
#define PySocket_BUILDING_SOCKET
|
#define PySocket_BUILDING_SOCKET
|
||||||
#include "socketmodule.h"
|
#include "socketmodule.h"
|
||||||
|
@ -1375,6 +1405,22 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
/* More cases here... */
|
/* More cases here... */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1940,6 +1986,36 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SOCKADDR_ALG
|
||||||
|
case AF_ALG:
|
||||||
|
{
|
||||||
|
struct sockaddr_alg *sa;
|
||||||
|
char *type;
|
||||||
|
char *name;
|
||||||
|
sa = (struct sockaddr_alg *)addr_ret;
|
||||||
|
|
||||||
|
memset(sa, 0, sizeof(*sa));
|
||||||
|
sa->salg_family = AF_ALG;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "ss|HH:getsockaddrarg",
|
||||||
|
&type, &name, &sa->salg_feat, &sa->salg_mask))
|
||||||
|
return 0;
|
||||||
|
/* sockaddr_alg has fixed-sized char arrays for type and name */
|
||||||
|
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
|
||||||
|
|
||||||
/* More cases here... */
|
/* More cases here... */
|
||||||
|
|
||||||
|
@ -2061,6 +2137,13 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SOCKADDR_ALG
|
||||||
|
case AF_ALG:
|
||||||
|
{
|
||||||
|
*len_ret = sizeof (struct sockaddr_alg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* More cases here... */
|
/* More cases here... */
|
||||||
|
|
||||||
|
@ -2220,10 +2303,21 @@ static int
|
||||||
sock_accept_impl(PySocketSockObject *s, void *data)
|
sock_accept_impl(PySocketSockObject *s, void *data)
|
||||||
{
|
{
|
||||||
struct sock_accept *ctx = 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 defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
|
||||||
if (accept4_works != 0) {
|
if (accept4_works != 0) {
|
||||||
ctx->result = accept4(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen,
|
ctx->result = accept4(s->sock_fd, addr, paddrlen,
|
||||||
SOCK_CLOEXEC);
|
SOCK_CLOEXEC);
|
||||||
if (ctx->result == INVALID_SOCKET && accept4_works == -1) {
|
if (ctx->result == INVALID_SOCKET && accept4_works == -1) {
|
||||||
/* On Linux older than 2.6.28, accept4() fails with ENOSYS */
|
/* On Linux older than 2.6.28, accept4() fails with ENOSYS */
|
||||||
|
@ -2231,9 +2325,9 @@ sock_accept_impl(PySocketSockObject *s, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (accept4_works == 0)
|
if (accept4_works == 0)
|
||||||
ctx->result = accept(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen);
|
ctx->result = accept(s->sock_fd, addr, paddrlen);
|
||||||
#else
|
#else
|
||||||
ctx->result = accept(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen);
|
ctx->result = accept(s->sock_fd, addr, paddrlen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
@ -2435,9 +2529,12 @@ operations. A timeout of None indicates that timeouts on socket \n\
|
||||||
operations are disabled.");
|
operations are disabled.");
|
||||||
|
|
||||||
/* s.setsockopt() method.
|
/* s.setsockopt() method.
|
||||||
With an integer third argument, sets an integer option.
|
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;
|
With a string third argument, sets an option from a buffer;
|
||||||
use optional built-in module 'struct' to encode the string. */
|
use optional built-in module 'struct' to encode the string.
|
||||||
|
*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sock_setsockopt(PySocketSockObject *s, PyObject *args)
|
sock_setsockopt(PySocketSockObject *s, PyObject *args)
|
||||||
|
@ -2447,17 +2544,33 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
|
||||||
int res;
|
int res;
|
||||||
Py_buffer optval;
|
Py_buffer optval;
|
||||||
int flag;
|
int flag;
|
||||||
|
unsigned int optlen;
|
||||||
|
PyObject *none;
|
||||||
|
|
||||||
|
/* setsockopt(level, opt, flag) */
|
||||||
if (PyArg_ParseTuple(args, "iii:setsockopt",
|
if (PyArg_ParseTuple(args, "iii:setsockopt",
|
||||||
&level, &optname, &flag)) {
|
&level, &optname, &flag)) {
|
||||||
res = setsockopt(s->sock_fd, level, optname,
|
res = setsockopt(s->sock_fd, level, optname,
|
||||||
(char*)&flag, sizeof flag);
|
(char*)&flag, sizeof flag);
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
/* setsockopt(level, opt, (None, flag)) */
|
||||||
|
if (PyArg_ParseTuple(args, "iiO!I:setsockopt",
|
||||||
|
&level, &optname, Py_TYPE(Py_None), &none, &optlen)) {
|
||||||
|
assert(sizeof(socklen_t) >= sizeof(unsigned int));
|
||||||
|
res = setsockopt(s->sock_fd, level, optname,
|
||||||
|
NULL, (socklen_t)optlen);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErr_Clear();
|
||||||
|
/* setsockopt(level, opt, buffer) */
|
||||||
if (!PyArg_ParseTuple(args, "iiy*:setsockopt",
|
if (!PyArg_ParseTuple(args, "iiy*:setsockopt",
|
||||||
&level, &optname, &optval))
|
&level, &optname, &optval))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
if (optval.len > INT_MAX) {
|
if (optval.len > INT_MAX) {
|
||||||
PyBuffer_Release(&optval);
|
PyBuffer_Release(&optval);
|
||||||
|
@ -2472,7 +2585,8 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
|
||||||
res = setsockopt(s->sock_fd, level, optname, optval.buf, optval.len);
|
res = setsockopt(s->sock_fd, level, optname, optval.buf, optval.len);
|
||||||
#endif
|
#endif
|
||||||
PyBuffer_Release(&optval);
|
PyBuffer_Release(&optval);
|
||||||
}
|
|
||||||
|
done:
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
return s->errorhandler();
|
return s->errorhandler();
|
||||||
}
|
}
|
||||||
|
@ -2481,10 +2595,13 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(setsockopt_doc,
|
PyDoc_STRVAR(setsockopt_doc,
|
||||||
"setsockopt(level, option, value)\n\
|
"setsockopt(level, option, value: int)\n\
|
||||||
|
setsockopt(level, option, value: buffer)\n\
|
||||||
|
setsockopt(level, option, None, optlen: int)\n\
|
||||||
\n\
|
\n\
|
||||||
Set a socket option. See the Unix manual for level and option.\n\
|
Set a socket option. See the Unix manual for level and option.\n\
|
||||||
The value argument can either be an integer or a string.");
|
The value argument can either be an integer, a string buffer, or \n\
|
||||||
|
None, optlen.");
|
||||||
|
|
||||||
|
|
||||||
/* s.getsockopt() method.
|
/* s.getsockopt() method.
|
||||||
|
@ -3773,6 +3890,51 @@ struct sock_sendmsg {
|
||||||
ssize_t result;
|
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. */
|
||||||
|
if ((data_fast = PySequence_Fast(data_arg,
|
||||||
|
"sendmsg() argument 1 must be an "
|
||||||
|
"iterable")) == NULL)
|
||||||
|
goto finally;
|
||||||
|
ndataparts = PySequence_Fast_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 &&
|
||||||
|
((msg->msg_iov = iovs = PyMem_New(struct iovec, ndataparts)) == NULL ||
|
||||||
|
(databufs = PyMem_New(Py_buffer, ndataparts)) == NULL)) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
for (; ndatabufs < ndataparts; ndatabufs++) {
|
||||||
|
if (!PyArg_Parse(PySequence_Fast_GET_ITEM(data_fast, ndatabufs),
|
||||||
|
"y*;sendmsg() argument 1 must be an iterable of "
|
||||||
|
"bytes-like objects",
|
||||||
|
&databufs[ndatabufs]))
|
||||||
|
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
|
static int
|
||||||
sock_sendmsg_impl(PySocketSockObject *s, void *data)
|
sock_sendmsg_impl(PySocketSockObject *s, void *data)
|
||||||
{
|
{
|
||||||
|
@ -3787,9 +3949,8 @@ sock_sendmsg_impl(PySocketSockObject *s, void *data)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sock_sendmsg(PySocketSockObject *s, PyObject *args)
|
sock_sendmsg(PySocketSockObject *s, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t i, ndataparts, ndatabufs = 0, ncmsgs, ncmsgbufs = 0;
|
Py_ssize_t i, ndatabufs = 0, ncmsgs, ncmsgbufs = 0;
|
||||||
Py_buffer *databufs = NULL;
|
Py_buffer *databufs = NULL;
|
||||||
struct iovec *iovs = NULL;
|
|
||||||
sock_addr_t addrbuf;
|
sock_addr_t addrbuf;
|
||||||
struct msghdr msg = {0};
|
struct msghdr msg = {0};
|
||||||
struct cmsginfo {
|
struct cmsginfo {
|
||||||
|
@ -3800,7 +3961,7 @@ sock_sendmsg(PySocketSockObject *s, PyObject *args)
|
||||||
void *controlbuf = NULL;
|
void *controlbuf = NULL;
|
||||||
size_t controllen, controllen_last;
|
size_t controllen, controllen_last;
|
||||||
int addrlen, flags = 0;
|
int addrlen, flags = 0;
|
||||||
PyObject *data_arg, *cmsg_arg = NULL, *addr_arg = NULL, *data_fast = NULL,
|
PyObject *data_arg, *cmsg_arg = NULL, *addr_arg = NULL,
|
||||||
*cmsg_fast = NULL, *retval = NULL;
|
*cmsg_fast = NULL, *retval = NULL;
|
||||||
struct sock_sendmsg ctx;
|
struct sock_sendmsg ctx;
|
||||||
|
|
||||||
|
@ -3818,30 +3979,8 @@ sock_sendmsg(PySocketSockObject *s, PyObject *args)
|
||||||
|
|
||||||
/* Fill in an iovec for each message part, and save the Py_buffer
|
/* Fill in an iovec for each message part, and save the Py_buffer
|
||||||
structs to release afterwards. */
|
structs to release afterwards. */
|
||||||
if ((data_fast = PySequence_Fast(data_arg,
|
if (sock_sendmsg_iovec(s, data_arg, &msg, &databufs, &ndatabufs) == -1) {
|
||||||
"sendmsg() argument 1 must be an "
|
|
||||||
"iterable")) == NULL)
|
|
||||||
goto finally;
|
goto finally;
|
||||||
ndataparts = PySequence_Fast_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 &&
|
|
||||||
((msg.msg_iov = iovs = PyMem_New(struct iovec, ndataparts)) == NULL ||
|
|
||||||
(databufs = PyMem_New(Py_buffer, ndataparts)) == NULL)) {
|
|
||||||
PyErr_NoMemory();
|
|
||||||
goto finally;
|
|
||||||
}
|
|
||||||
for (; ndatabufs < ndataparts; ndatabufs++) {
|
|
||||||
if (!PyArg_Parse(PySequence_Fast_GET_ITEM(data_fast, ndatabufs),
|
|
||||||
"y*;sendmsg() argument 1 must be an iterable of "
|
|
||||||
"bytes-like objects",
|
|
||||||
&databufs[ndatabufs]))
|
|
||||||
goto finally;
|
|
||||||
iovs[ndatabufs].iov_base = databufs[ndatabufs].buf;
|
|
||||||
iovs[ndatabufs].iov_len = databufs[ndatabufs].len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmsg_arg == NULL)
|
if (cmsg_arg == NULL)
|
||||||
|
@ -3972,8 +4111,6 @@ finally:
|
||||||
for (i = 0; i < ndatabufs; i++)
|
for (i = 0; i < ndatabufs; i++)
|
||||||
PyBuffer_Release(&databufs[i]);
|
PyBuffer_Release(&databufs[i]);
|
||||||
PyMem_Free(databufs);
|
PyMem_Free(databufs);
|
||||||
PyMem_Free(iovs);
|
|
||||||
Py_XDECREF(data_fast);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3995,6 +4132,165 @@ the message. The return value is the number of bytes of non-ancillary\n\
|
||||||
data sent.");
|
data sent.");
|
||||||
#endif /* CMSG_LEN */
|
#endif /* CMSG_LEN */
|
||||||
|
|
||||||
|
#ifdef HAVE_SOCKADDR_ALG
|
||||||
|
static PyObject*
|
||||||
|
sock_sendmsg_afalg(PySocketSockObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
PyObject *retval = NULL;
|
||||||
|
|
||||||
|
Py_ssize_t i, ndatabufs = 0;
|
||||||
|
Py_buffer *databufs = NULL;
|
||||||
|
PyObject *data_arg = NULL;
|
||||||
|
|
||||||
|
Py_buffer iv = {NULL, NULL};
|
||||||
|
|
||||||
|
PyObject *opobj = NULL;
|
||||||
|
int op = -1;
|
||||||
|
|
||||||
|
PyObject *assoclenobj = NULL;
|
||||||
|
int assoclen = -1;
|
||||||
|
|
||||||
|
unsigned int *uiptr;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
static char *keywords[] = {"msg", "op", "iv", "assoclen", "flags", 0};
|
||||||
|
|
||||||
|
if (self->sock_family != AF_ALG) {
|
||||||
|
PyErr_SetString(PyExc_OSError,
|
||||||
|
"algset is only supported for AF_ALG");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
||||||
|
"|O$O!y*O!i:sendmsg_afalg", keywords,
|
||||||
|
&data_arg,
|
||||||
|
&PyLong_Type, &opobj, &iv,
|
||||||
|
&PyLong_Type, &assoclenobj, &flags))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
return PyErr_NoMemory();
|
||||||
|
}
|
||||||
|
memset(controlbuf, 0, controllen);
|
||||||
|
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
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);
|
||||||
|
if (iv.buf != NULL) {
|
||||||
|
PyBuffer_Release(&iv);
|
||||||
|
}
|
||||||
|
for (i = 0; i < ndatabufs; i++)
|
||||||
|
PyBuffer_Release(&databufs[i]);
|
||||||
|
PyMem_Free(databufs);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(sendmsg_afalg_doc,
|
||||||
|
"sendmsg_afalg([msg], *, op[, iv[, assoclen[, flags=MSG_MORE]]])\n\
|
||||||
|
\n\
|
||||||
|
Set operation mode, IV and length of associated data for an AF_ALG\n\
|
||||||
|
operation socket.");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* s.shutdown(how) method */
|
/* s.shutdown(how) method */
|
||||||
|
|
||||||
|
@ -4173,6 +4469,10 @@ static PyMethodDef sock_methods[] = {
|
||||||
recvmsg_into_doc,},
|
recvmsg_into_doc,},
|
||||||
{"sendmsg", (PyCFunction)sock_sendmsg, METH_VARARGS,
|
{"sendmsg", (PyCFunction)sock_sendmsg, METH_VARARGS,
|
||||||
sendmsg_doc},
|
sendmsg_doc},
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SOCKADDR_ALG
|
||||||
|
{"sendmsg_afalg", (PyCFunction)sock_sendmsg_afalg, METH_VARARGS | METH_KEYWORDS,
|
||||||
|
sendmsg_afalg_doc},
|
||||||
#endif
|
#endif
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
@ -6277,6 +6577,9 @@ PyInit__socket(void)
|
||||||
/* Reserved for Werner's ATM */
|
/* Reserved for Werner's ATM */
|
||||||
PyModule_AddIntMacro(m, AF_AAL5);
|
PyModule_AddIntMacro(m, AF_AAL5);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SOCKADDR_ALG
|
||||||
|
PyModule_AddIntMacro(m, AF_ALG); /* Linux crypto */
|
||||||
|
#endif
|
||||||
#ifdef AF_X25
|
#ifdef AF_X25
|
||||||
/* Reserved for X.25 project */
|
/* Reserved for X.25 project */
|
||||||
PyModule_AddIntMacro(m, AF_X25);
|
PyModule_AddIntMacro(m, AF_X25);
|
||||||
|
@ -6338,6 +6641,9 @@ PyInit__socket(void)
|
||||||
#ifdef NETLINK_TAPBASE
|
#ifdef NETLINK_TAPBASE
|
||||||
PyModule_AddIntMacro(m, NETLINK_TAPBASE);
|
PyModule_AddIntMacro(m, NETLINK_TAPBASE);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef NETLINK_CRYPTO
|
||||||
|
PyModule_AddIntMacro(m, NETLINK_CRYPTO);
|
||||||
|
#endif
|
||||||
#endif /* AF_NETLINK */
|
#endif /* AF_NETLINK */
|
||||||
#ifdef AF_ROUTE
|
#ifdef AF_ROUTE
|
||||||
/* Alias to emulate 4.4BSD */
|
/* Alias to emulate 4.4BSD */
|
||||||
|
@ -6491,6 +6797,22 @@ PyInit__socket(void)
|
||||||
PyModule_AddIntMacro(m, TIPC_TOP_SRV);
|
PyModule_AddIntMacro(m, TIPC_TOP_SRV);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SOCKADDR_ALG
|
||||||
|
/* Socket options */
|
||||||
|
PyModule_AddIntMacro(m, ALG_SET_KEY);
|
||||||
|
PyModule_AddIntMacro(m, ALG_SET_IV);
|
||||||
|
PyModule_AddIntMacro(m, ALG_SET_OP);
|
||||||
|
PyModule_AddIntMacro(m, ALG_SET_AEAD_ASSOCLEN);
|
||||||
|
PyModule_AddIntMacro(m, ALG_SET_AEAD_AUTHSIZE);
|
||||||
|
PyModule_AddIntMacro(m, ALG_SET_PUBKEY);
|
||||||
|
|
||||||
|
/* Operations */
|
||||||
|
PyModule_AddIntMacro(m, ALG_OP_DECRYPT);
|
||||||
|
PyModule_AddIntMacro(m, ALG_OP_ENCRYPT);
|
||||||
|
PyModule_AddIntMacro(m, ALG_OP_SIGN);
|
||||||
|
PyModule_AddIntMacro(m, ALG_OP_VERIFY);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Socket types */
|
/* Socket types */
|
||||||
PyModule_AddIntMacro(m, SOCK_STREAM);
|
PyModule_AddIntMacro(m, SOCK_STREAM);
|
||||||
PyModule_AddIntMacro(m, SOCK_DGRAM);
|
PyModule_AddIntMacro(m, SOCK_DGRAM);
|
||||||
|
@ -6761,6 +7083,9 @@ PyInit__socket(void)
|
||||||
#ifdef SOL_RDS
|
#ifdef SOL_RDS
|
||||||
PyModule_AddIntMacro(m, SOL_RDS);
|
PyModule_AddIntMacro(m, SOL_RDS);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SOCKADDR_ALG
|
||||||
|
PyModule_AddIntMacro(m, SOL_ALG);
|
||||||
|
#endif
|
||||||
#ifdef RDS_CANCEL_SENT_TO
|
#ifdef RDS_CANCEL_SENT_TO
|
||||||
PyModule_AddIntMacro(m, RDS_CANCEL_SENT_TO);
|
PyModule_AddIntMacro(m, RDS_CANCEL_SENT_TO);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -775,7 +775,6 @@ infodir
|
||||||
docdir
|
docdir
|
||||||
oldincludedir
|
oldincludedir
|
||||||
includedir
|
includedir
|
||||||
runstatedir
|
|
||||||
localstatedir
|
localstatedir
|
||||||
sharedstatedir
|
sharedstatedir
|
||||||
sysconfdir
|
sysconfdir
|
||||||
|
@ -886,7 +885,6 @@ datadir='${datarootdir}'
|
||||||
sysconfdir='${prefix}/etc'
|
sysconfdir='${prefix}/etc'
|
||||||
sharedstatedir='${prefix}/com'
|
sharedstatedir='${prefix}/com'
|
||||||
localstatedir='${prefix}/var'
|
localstatedir='${prefix}/var'
|
||||||
runstatedir='${localstatedir}/run'
|
|
||||||
includedir='${prefix}/include'
|
includedir='${prefix}/include'
|
||||||
oldincludedir='/usr/include'
|
oldincludedir='/usr/include'
|
||||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||||
|
@ -1139,15 +1137,6 @@ do
|
||||||
| -silent | --silent | --silen | --sile | --sil)
|
| -silent | --silent | --silen | --sile | --sil)
|
||||||
silent=yes ;;
|
silent=yes ;;
|
||||||
|
|
||||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
|
||||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
|
||||||
| --run | --ru | --r)
|
|
||||||
ac_prev=runstatedir ;;
|
|
||||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
|
||||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
|
||||||
| --run=* | --ru=* | --r=*)
|
|
||||||
runstatedir=$ac_optarg ;;
|
|
||||||
|
|
||||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||||
ac_prev=sbindir ;;
|
ac_prev=sbindir ;;
|
||||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||||
|
@ -1285,7 +1274,7 @@ fi
|
||||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||||
libdir localedir mandir runstatedir
|
libdir localedir mandir
|
||||||
do
|
do
|
||||||
eval ac_val=\$$ac_var
|
eval ac_val=\$$ac_var
|
||||||
# Remove trailing slashes.
|
# Remove trailing slashes.
|
||||||
|
@ -1438,7 +1427,6 @@ Fine tuning of the installation directories:
|
||||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
|
||||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||||
--includedir=DIR C header files [PREFIX/include]
|
--includedir=DIR C header files [PREFIX/include]
|
||||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||||
|
@ -13062,6 +13050,41 @@ $as_echo "#define HAVE_SOCKADDR_STORAGE 1" >>confdefs.h
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sockaddr_alg" >&5
|
||||||
|
$as_echo_n "checking for sockaddr_alg... " >&6; }
|
||||||
|
if ${ac_cv_struct_sockaddr_alg+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <linux/if_alg.h>
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
struct sockaddr_alg s
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_compile "$LINENO"; then :
|
||||||
|
ac_cv_struct_sockaddr_alg=yes
|
||||||
|
else
|
||||||
|
ac_cv_struct_sockaddr_alg=no
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_sockaddr_alg" >&5
|
||||||
|
$as_echo "$ac_cv_struct_sockaddr_alg" >&6; }
|
||||||
|
if test $ac_cv_struct_sockaddr_alg = yes; then
|
||||||
|
|
||||||
|
$as_echo "#define HAVE_SOCKADDR_ALG 1" >>confdefs.h
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
# checks for compiler characteristics
|
# checks for compiler characteristics
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5
|
||||||
|
|
13
configure.ac
13
configure.ac
|
@ -3862,6 +3862,19 @@ if test $ac_cv_struct_sockaddr_storage = yes; then
|
||||||
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1, [struct sockaddr_storage (sys/socket.h)])
|
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1, [struct sockaddr_storage (sys/socket.h)])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for sockaddr_alg)
|
||||||
|
AC_CACHE_VAL(ac_cv_struct_sockaddr_alg,
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <linux/if_alg.h>]], [[struct sockaddr_alg s]])],
|
||||||
|
[ac_cv_struct_sockaddr_alg=yes],
|
||||||
|
[ac_cv_struct_sockaddr_alg=no]))
|
||||||
|
AC_MSG_RESULT($ac_cv_struct_sockaddr_alg)
|
||||||
|
if test $ac_cv_struct_sockaddr_alg = yes; then
|
||||||
|
AC_DEFINE(HAVE_SOCKADDR_ALG, 1, [struct sockaddr_alg (linux/if_alg.h)])
|
||||||
|
fi
|
||||||
|
|
||||||
# checks for compiler characteristics
|
# checks for compiler characteristics
|
||||||
|
|
||||||
AC_C_CHAR_UNSIGNED
|
AC_C_CHAR_UNSIGNED
|
||||||
|
|
|
@ -892,6 +892,9 @@
|
||||||
/* Define to 1 if you have the `snprintf' function. */
|
/* Define to 1 if you have the `snprintf' function. */
|
||||||
#undef HAVE_SNPRINTF
|
#undef HAVE_SNPRINTF
|
||||||
|
|
||||||
|
/* struct sockaddr_alg (linux/if_alg.h) */
|
||||||
|
#undef HAVE_SOCKADDR_ALG
|
||||||
|
|
||||||
/* Define if sockaddr has sa_len member */
|
/* Define if sockaddr has sa_len member */
|
||||||
#undef HAVE_SOCKADDR_SA_LEN
|
#undef HAVE_SOCKADDR_SA_LEN
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue