Gitweb:
https://git.exim.org/exim.git/commitdiff/64cc4714abd0d616327bfacdfc1b0fb45bff096e
Commit: 64cc4714abd0d616327bfacdfc1b0fb45bff096e
Parent: 0cedb352e62898761b701af0c400df8ae1989383
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Sun Jan 17 20:42:10 2021 +0000
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Sun Jan 17 20:54:18 2021 +0000
malware: use sendfile for ClamAV TCP
---
src/src/malware.c | 47 +++++++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 18 deletions(-)
diff --git a/src/src/malware.c b/src/src/malware.c
index abe627d..7c134d7 100644
--- a/src/src/malware.c
+++ b/src/src/malware.c
@@ -1559,10 +1559,7 @@ badseek: err = errno;
if (!use_scan_command)
{ cmd_str.data = US"zINSTREAM"; cmd_str.len = 10; }
else
- {
- cmd_str.data = string_sprintf("SCAN %s\n", eml_filename);
- cmd_str.len = Ustrlen(cmd_str.data);
- }
+ cmd_str.data = string_sprintf("SCAN %s\n%n", eml_filename, &cmd_str.len);
/* We have some network servers specified */
if (num_servers)
@@ -1583,13 +1580,14 @@ badseek: err = errno;
on both connections (as one host could resolve to multiple ips) */
for (;;)
{
- /*XXX we trust that the cmd_str is ideempotent */
+ /*XXX we trust that the cmd_str is idempotent */
if ((malware_daemon_ctx.sock = m_tcpsocket(cd->hostspec, cd->tcp_port,
- &connhost, &errstr, &cmd_str)) >= 0)
+ &connhost, &errstr,
+ use_scan_command ? &cmd_str : NULL)) >= 0)
{
/* Connection successfully established with a server */
hostname = cd->hostspec;
- cmd_str.len = 0;
+ if (use_scan_command) cmd_str.len = 0;
break;
}
if (cd->retry <= 0) break;
@@ -1630,17 +1628,21 @@ badseek: err = errno;
if (!use_scan_command)
{
struct stat st;
-#ifdef EXIM_TCP_CORK
+#if defined(EXIM_TCP_CORK) && !defined(OS_SENDFILE)
BOOL corked = TRUE;
#endif
/* New protocol: "zINSTREAM\n" followed by a sequence of <length><data>
chunks, <n> a 4-byte number (network order), terminated by a zero-length
- chunk. */
+ chunk. We only send one chunk. */
DEBUG(D_acl) debug_printf_indent(
"Malware scan: issuing %s new-style remote scan (zINSTREAM)\n",
scanner_name);
+#if defined(EXIM_TCP_CORK)
+ (void) setsockopt(malware_daemon_ctx.sock, IPPROTO_TCP, EXIM_TCP_CORK,
+ US &on, sizeof(on));
+#endif
/* Pass the string to ClamAV (10 = "zINSTREAM\0"), if not already sent */
if (cmd_str.len)
if (send(malware_daemon_ctx.sock, cmd_str.data, cmd_str.len, 0) < 0)
@@ -1676,10 +1678,6 @@ badseek: err = errno;
}
/* send file size */
-#ifdef EXIM_TCP_CORK
- (void) setsockopt(malware_daemon_ctx.sock, IPPROTO_TCP, EXIM_TCP_CORK,
- US &on, sizeof(on));
-#endif
send_size = htonl(fsize_uint);
if (send(malware_daemon_ctx.sock, &send_size, sizeof(send_size), 0) < 0)
return m_panic_defer_3(scanent, NULL,
@@ -1687,10 +1685,17 @@ badseek: err = errno;
malware_daemon_ctx.sock);
/* send file body */
- /*XXX sendfile? */
while (fsize_uint)
{
- unsigned n = MIN(fsize_uint, big_buffer_size);
+#ifdef OS_SENDFILE
+ int n = os_sendfile(malware_daemon_ctx.sock, clam_fd, NULL, (size_t)fsize_uint);
+ if (n < 0)
+ return m_panic_defer_3(scanent, NULL,
+ string_sprintf("unable to send file body to socket (%s): %s", hostname, strerror(errno)),
+ malware_daemon_ctx.sock);
+ fsize_uint -= n;
+#else
+ int n = MIN(fsize_uint, big_buffer_size);
if ((n = read(clam_fd, big_buffer, n)) < 0)
return m_panic_defer_3(scanent, NULL,
string_sprintf("can't read spool file %s: %s",
@@ -1701,14 +1706,16 @@ badseek: err = errno;
string_sprintf("unable to send file body to socket (%s): %s", hostname, strerror(errno)),
malware_daemon_ctx.sock);
fsize_uint -= n;
-#ifdef EXIM_TCP_CORK
+# ifdef EXIM_TCP_CORK
if (corked)
{
corked = FALSE;
(void) setsockopt(malware_daemon_ctx.sock, IPPROTO_TCP, EXIM_TCP_CORK,
US &off, sizeof(off));
}
-#endif
+# endif
+#endif /*!OS_SENDFILE*/
+
}
send_final_zeroblock = 0;
@@ -1716,11 +1723,15 @@ badseek: err = errno;
return m_panic_defer_3(scanent, NULL,
string_sprintf("unable to send file terminator to socket (%s)", hostname),
malware_daemon_ctx.sock);
+#ifdef OS_SENDFILE
+ (void) setsockopt(malware_daemon_ctx.sock, IPPROTO_TCP, EXIM_TCP_CORK,
+ US &off, sizeof(off));
+#endif
}
else
{ /* use scan command */
/* Send a SCAN command pointing to a filename; then in the then in the
- * scan-method-neutral part, read the response back */
+ scan-method-neutral part, read the response back */
/* ================================================================= */