[exim-cvs] malware: use sendfile for ClamAV TCP

Startseite
Nachricht löschen
Nachricht beantworten
Autor: Exim Git Commits Mailing List
Datum:  
To: exim-cvs
Betreff: [exim-cvs] malware: use sendfile for ClamAV TCP
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 */


/* ================================================================= */