Refactor clamd socket connection
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 16 Feb 2014 16:33:01 +0000 (16:33 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 16 Feb 2014 16:33:01 +0000 (16:33 +0000)
src/src/acl.c
src/src/expand.c
src/src/functions.h
src/src/ip.c
src/src/malware.c
src/src/string.c

index 89932bbf1e5a5481b4892d2e467ff7ea17434f3f..f25debd93d1c2ac2ed78c677e1fe31723b7d8ba8 100644 (file)
@@ -2895,7 +2895,7 @@ if (r == HOST_FIND_FAILED || r == HOST_FIND_AGAIN)
 HDEBUG(D_acl)
   debug_printf("udpsend [%s]:%d %s\n", h->address, portnum, arg);
 
-r = s = ip_connectedsocket(SOCK_DGRAM, h_address, portnum, 1, &errstr);
+r = s = ip_connectedsocket(SOCK_DGRAM, h->address, portnum, 1, NULL, &errstr);
 if (r < 0) goto defer;
 len = Ustrlen(arg);
 r = send(s, arg, len, 0);
index a47cc0d64ca2db7516bd2a5fc69c8038d9fb9039..30735db614c0445fed41d0a8dc83f2c2199df086 100644 (file)
@@ -4538,7 +4538,7 @@ while (*s != 0)
             }
 
          if ((fd = ip_connectedsocket(SOCK_STREAM, server_name, port, port,
-                 timeout, &expand_string_message)) < 0)
+                 timeout, NULL, &expand_string_message)) < 0)
               goto SOCK_FAIL;
           }
 
index 574675f480ae5454af74bfd37b7dc9be249e37f7..f646d25cf60f5e8cae78580caa11b54b6652f5d5 100644 (file)
@@ -360,7 +360,7 @@ extern uschar *string_dequote(uschar **);
 extern BOOL    string_format(uschar *, int, const char *, ...) ALMOST_PRINTF(3,4);
 extern uschar *string_format_size(int, uschar *);
 extern int     string_interpret_escape(uschar **);
-extern int     string_is_ip_address(uschar *, int *);
+extern int     string_is_ip_address(const uschar *, int *);
 extern uschar *string_log_address(address_item *, BOOL, BOOL);
 extern uschar *string_nextinlist(uschar **, int *, uschar *, int);
 extern uschar *string_open_failed(int, const char *, ...) PRINTF_FUNCTION(2,3);
index 4a1877dfd52761df424596956355a603f629ca62..6706b447986852b3550e10881e5fccf86adfd6d4 100644 (file)
@@ -248,13 +248,15 @@ return -1;
 }
 
 
-/*
+/* Create a socket and connect to host (name or number, ipv6 ok)
+   at one of port-range.
 Arguments:
   type          SOCK_DGRAM or SOCK_STREAM
   af            AF_INET6 or AF_INET for the socket type
   address       the remote address, in text form
   portlo,porthi the remote port range
   timeout       a timeout
+  connhost     if not NULL, host_item filled in with connection details
   errstr        pointer for allocated string on error
 
 Return:
@@ -262,16 +264,16 @@ Return:
 */
 int
 ip_connectedsocket(int type, const uschar * hostname, int portlo, int porthi,
-       int timeout, uschar ** errstr)
+       int timeout, host_item * connhost, uschar ** errstr)
 {
 int namelen, port;
 host_item shost;
 host_item *h;
-int fd, fd4 = -1, fd6 = -1;
+int af, fd, fd4 = -1, fd6 = -1;
 
 shost.next = NULL;
 shost.address = NULL;
-shost.port = port;
+shost.port = portlo;
 shost.mx = -1;
 
 namelen = Ustrlen(hostname);
@@ -295,13 +297,13 @@ if (hostname[0] == '[' &&
 /* Otherwise check for an unadorned IP address */
 
 else if (string_is_ip_address(hostname, NULL) != 0)
-  shost.name = shost.address = hostname;
+  shost.name = shost.address = string_copy(hostname);
 
 /* Otherwise lookup IP address(es) from the name */
 
 else
   {
-  shost.name = hostname;
+  shost.name = string_copy(hostname);
   if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE, NULL,
       FALSE) != HOST_FOUND)
     {
@@ -315,8 +317,8 @@ else
 for (h = &shost; h != NULL; h = h->next)
   {
   fd = (Ustrchr(h->address, ':') != 0)
-    ? (fd6 < 0) ? (fd6 = ip_socket(SOCK_STREAM, AF_INET6)) : fd6
-    : (fd4 < 0) ? (fd4 = ip_socket(SOCK_STREAM, AF_INET )) : fd4;
+    ? (fd6 < 0) ? (fd6 = ip_socket(SOCK_STREAM, af = AF_INET6)) : fd6
+    : (fd4 < 0) ? (fd4 = ip_socket(SOCK_STREAM, af = AF_INET )) : fd4;
 
   if (fd < 0)
     {
@@ -324,11 +326,16 @@ for (h = &shost; h != NULL; h = h->next)
     goto bad;
     }
 
-  for(port = portlo, port <= porthi; port++)
+  for(port = portlo; port <= porthi; port++)
     if (ip_connect(fd, af, h->address, port, timeout) == 0)
       {
       if (fd != fd6) close(fd6);
       if (fd != fd4) close(fd4);
+      if (connhost) {
+       h->port = port;
+       *connhost = *h;
+       connhost->next = NULL;
+       }
       return fd;
       }
   }
index 9a822fdc21e554066d152c4da212f915e585f4ec..298031aa39a2777905cbcdec9fdca5c5696499c6 100644 (file)
@@ -226,44 +226,14 @@ clmd_errlog(const uschar * str)
 
 /*************************************************/
 
-static int
-m_streamsocket(const uschar * hostname, struct in_addr * inp, uschar ** errstr)
-{
-  struct hostent * he;
-  int sock;
-
-  /* Lookup the host */
-  if(!(he = gethostbyname(CS hostname))) {
-    *errstr = string_sprintf("failed to lookup host '%s'", hostname);
-    return -1;
-  }
-/*XXX will fail for ipv6 */
-  *inp = *(struct in_addr *) he->h_addr_list[0];
-
-  /* Create the TCP socket */
-  if ((sock = ip_socket(SOCK_STREAM, AF_INET)) >= 0)
-    return sock;
-
-  *errstr = string_sprintf("unable to acquire socket (%s)", strerror(errno));
-  return -1;
-}
-
-static int
+/* Only used by the Clamav code, which is working from a list of servers and
+uses the returned in_addr to get a second connection to the same system.
+*/
+static inline int
 m_tcpsocket(const uschar * hostname, unsigned int port,
-       struct in_addr * inp, uschar ** errstr)
+       host_item * host, uschar ** errstr)
 {
-  int sock;
-
-  if ((sock = m_streamsocket(hostname, inp, errstr)) < 0)
-    return -1;
-
-  if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(*inp), port, 5) >= 0)
-    return sock;
-
-  *errstr = string_sprintf("connection to %s, port %u failed (%s)",
-                     inet_ntoa(*inp), port, strerror(errno));
-  (void)close(sock);
-  return -1;
+  return ip_connectedsocket(SOCK_STREAM, hostname, port, port, 5, host, errstr);
 }
 
 static int
@@ -284,7 +254,7 @@ m_tcpsocket_fromdef(const uschar * hostport, uschar ** errstr)
   }
 
   return ip_connectedsocket(SOCK_STREAM, hostname, portlow, porthigh,
-                           5, errstr);
+                           5, NULL, errstr);
 }
 
 static int
@@ -1171,7 +1141,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
        uschar * file_name;
        uschar av_buffer[1024];
        uschar *hostname = "";
-       struct in_addr in;
+       host_item connhost;
        uschar *clamav_fbuf;
        int clam_fd, result;
        unsigned int fsize;
@@ -1261,7 +1231,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
             * on both connections (as one host could resolve to multiple ips) */
            sock= m_tcpsocket(CS clamd_address_vector[current_server]->tcp_addr,
                                clamd_address_vector[current_server]->tcp_port,
-                               &in, &errstr);
+                               &connhost, &errstr);
            if (sock >= 0) {
              /* Connection successfully established with a server */
              hostname = clamd_address_vector[current_server]->tcp_addr;
@@ -1333,19 +1303,10 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
                av_buffer2));
          }
 
-         if ( (sockData = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
-           int err = errno;
+         sockData = m_tcpsocket(connhost.address, port, NULL, &errstr);
+         if (sockData < 0) {
            (void)close(sock);
-           return clmd_errlog_defer(
-             string_sprintf("unable to acquire socket (%s)", strerror(err)));
-         }
-
-         if (ip_connect(sockData, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
-           int err = errno;
-           (void)close(sockData); (void)close(sock);
-           return clmd_errlog_defer(
-             string_sprintf("connection to %s, port %u failed (%s)",
-                   inet_ntoa(in), port, strerror(err)));
+           return clmd_errlog_defer(errstr);
          }
 
   #define CLOSE_SOCKDATA (void)close(sockData)
index 0e73e2c79c73ef2e65783b46b47e06fbfbb16bbe..94d61b1a35e320b3ee9e09f0d9fd9a09a16e1bf0 100644 (file)
@@ -34,7 +34,7 @@ Returns:    0 if the string is not a textual representation of an IP address
 */
 
 int
-string_is_ip_address(uschar *s, int *maskptr)
+string_is_ip_address(const uschar *s, int *maskptr)
 {
 int i;
 int yield = 4;
@@ -44,7 +44,7 @@ offset. */
 
 if (maskptr != NULL)
   {
-  uschar *ss = s + Ustrlen(s);
+  const uschar *ss = s + Ustrlen(s);
   *maskptr = 0;
   if (s != ss && isdigit(*(--ss)))
     {