Refactor tcp socket opens
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 2 Feb 2014 20:09:10 +0000 (20:09 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 2 Feb 2014 20:09:10 +0000 (20:09 +0000)
src/src/malware.c

index 9d4d16abacca3d419e23ce83d71bdf5b7166451f..88e96911ff6cf4e7205526ccc5ec89b1fc8c2d90 100644 (file)
@@ -222,6 +222,79 @@ 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;
+  }
+  *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
+m_tcpsocket(const uschar * hostname, unsigned int port,
+       struct in_addr * inp, 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;
+}
+
+static int
+m_tcpsocket_fromdef(const uschar * hostport, uschar ** errstr)
+{
+  int scan;
+  uschar hostname[256];
+  unsigned int port, portlow, porthigh;
+  struct hostent * he;
+  struct in_addr in;
+  int sock;
+
+  /* extract host and port part */
+  scan = sscanf(CS hostport, "%255s %u-%u", hostname, &portlow, &porthigh);
+  if ( scan != 3 ) {
+    if ( scan != 2 ) {
+      *errstr = string_sprintf("invalid socket '%s'", hostport);
+      return -1;
+    }
+    porthigh = portlow;
+  }
+
+  if ((sock = m_streamsocket(hostname, &in, errstr)) < 0)
+    return -1;
+
+  /* Try to connect to all ports low-high until connection is established */
+  for (port = portlow; port <= porthigh; port++)
+    if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) >= 0)
+      return sock;
+
+  *errstr = string_sprintf("connection to %s, port %u-%u failed (%s)",
+                     inet_ntoa(in), portlow, porthigh, strerror(errno));
+  (void)close(sock);
+  return -1;
+}
+
 static int
 m_unixsocket(const uschar * path, uschar ** errstr)
 {
@@ -387,48 +460,13 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
     case M_FPROTD: /* "f-protd" scanner type -------------------------------- */
       {
        uschar *fp_scan_option;
-       uschar hostname[256];
-       unsigned int port, portlow, porthigh, connect_ok=0, detected=0, par_count=0;
-       struct hostent *he;
-       struct in_addr in;
+       unsigned int detected=0, par_count=0;
        int sock;
        uschar * scanrequest;
        uschar buf[32768], *strhelper, *strhelper2;
 
-       /* extract host and port part */
-       if ( sscanf(CS scanner_options, "%255s %u-%u", hostname, &portlow, &porthigh) != 3 ) {
-         if ( sscanf(CS scanner_options, "%s %u", hostname, &portlow) != 2 )
-           return fprotd_errlog_defer(
-             string_sprintf("invalid socket '%s'", scanner_options));
-         porthigh = portlow;
-       }
-
-       /* Lookup the host */
-       if((he = gethostbyname(CS hostname)) == 0)
-         return fprotd_errlog_defer(
-           string_sprintf("failed to lookup host '%s'", hostname));
-
-       in = *(struct in_addr *) he->h_addr_list[0];
-       port = portlow;
-
-
-       /* Open the f-protd TCP socket */
-       if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0)
-         return fprotd_errlog_defer(
-           string_sprintf("unable to acquire socket (%s)", strerror(errno)));
-
-       /* Try to connect to all portslow-high until connection is established */
-       for (port = portlow; !connect_ok && port < porthigh; port++)
-         if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) >= 0)
-           connect_ok = 1;
-
-       if ( !connect_ok ) {
-         int err = errno;
-         (void)close(sock);
-         return fprotd_errlog_defer(
-                   string_sprintf("connection to %s, port %u-%u failed (%s)",
-                           inet_ntoa(in), portlow, porthigh, strerror(err)));
-       }
+       if ((sock = m_tcpsocket_fromdef(scanner_options, &errstr)) < 0)
+         return fprotd_errlog_defer(errstr);
 
        DEBUG(D_acl) debug_printf("Malware scan: issuing %s GET\n", scanner_name);
        scanrequest = string_sprintf("GET %s", eml_filename);
@@ -470,42 +508,16 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
       {
        struct sockaddr_un server;
        int sock, result, ovector[10*3];
-       unsigned int port, fsize;
+       unsigned int fsize;
        uschar * tmpbuf, *drweb_fbuf;
        int drweb_rc, drweb_cmd, drweb_flags = 0x0000, drweb_fd,
            drweb_vnum, drweb_slen, drweb_fin = 0x0000;
        unsigned long bread;
-       uschar hostname[256];
-       struct hostent *he;
-       struct in_addr in;
        pcre *drweb_re;
 
        if (*scanner_options != '/') {
-
-         /* extract host and port part */
-         if( sscanf(CS scanner_options, "%255s %u", hostname, &port) != 2 )
-           return drweb_errlog_defer(
-             string_sprintf("invalid socket '%s'", scanner_options));
-
-         /* Lookup the host */
-         if((he = gethostbyname(CS hostname)) == 0)
-           return drweb_errlog_defer(
-             string_sprintf("failed to lookup host '%s'", hostname));
-
-         in = *(struct in_addr *) he->h_addr_list[0];
-
-         /* Open the drwebd TCP socket */
-         if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0)
-           return drweb_errlog_defer(
-             string_sprintf("unable to acquire socket (%s)", strerror(errno)));
-
-         if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
-           int err = errno;
-           (void)close(sock);
-           return drweb_errlog_defer(
-             string_sprintf("connection to %s, port %u failed (%s)",
-               inet_ntoa(in), port, strerror(err)));
-         }
+         if ((sock = m_tcpsocket_fromdef(scanner_options, &errstr)) < 0)
+           return drweb_errlog_defer(errstr);
 
          /* prepare variables */
          drweb_cmd = htonl(DRWEBD_SCAN_CMD);
@@ -532,8 +544,8 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
          drweb_slen = htonl(fsize);
          lseek(drweb_fd, 0, SEEK_SET);
 
-         DEBUG(D_acl) debug_printf("Malware scan: issuing %s remote scan [%s %u]\n",
-             scanner_name, hostname, port);
+         DEBUG(D_acl) debug_printf("Malware scan: issuing %s remote scan [%s]\n",
+             scanner_name, scanner_options);
 
          /* send scan request */
          if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
@@ -614,8 +626,7 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
        drweb_vnum = ntohl(drweb_vnum);
 
        /* "virus(es) found" if virus number is > 0 */
-       if (drweb_vnum)
-       {
+       if (drweb_vnum) {
          int i;
 
          /* setup default virus name */
@@ -1177,12 +1188,11 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
 
        uschar *p, *vname, *result_tag, *response_end;
        struct sockaddr_un server;
-       int sock,bread=0;
+       int sock, bread=0;
        unsigned int port;
        uschar * file_name;
        uschar av_buffer[1024];
        uschar *hostname = "";
-       struct hostent *he;
        struct in_addr in;
        uschar *clamav_fbuf;
        int clam_fd, result;
@@ -1271,41 +1281,17 @@ malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking)
 
            /* Lookup the host. This is to ensure that we connect to the same IP
             * on both connections (as one host could resolve to multiple ips) */
-           if((he = gethostbyname(CS clamd_address_vector[current_server]->tcp_addr))
-                           == 0) {
-             clmd_errlog(string_sprintf("failed to lookup host '%s'",
-                     clamd_address_vector[current_server]->tcp_addr));
-             goto try_next_server;
-           }
-
-           in = *(struct in_addr *) he->h_addr_list[0];
-
-           /* Open the ClamAV Socket */
-           if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
-             clmd_errlog(string_sprintf("unable to acquire socket (%s)",
-                       strerror(errno)));
-             goto try_next_server;
-           }
-
-           if (ip_connect( sock,
-                           AF_INET,
-                           (uschar*)inet_ntoa(in),
-                           clamd_address_vector[current_server]->tcp_port,
-                           5 ) > -1) {
+           sock= m_tcpsocket(CS clamd_address_vector[current_server]->tcp_addr,
+                               clamd_address_vector[current_server]->tcp_port,
+                               &in, &errstr);
+           if (sock >= 0) {
              /* Connection successfully established with a server */
              hostname = clamd_address_vector[current_server]->tcp_addr;
              break;
-           } else {
-             clmd_errlog(string_sprintf(
-                "malware acl condition: clamd: connection to %s, port %u failed (%s)",
-                clamd_address_vector[current_server]->tcp_addr,
-                clamd_address_vector[current_server]->tcp_port,
-                strerror(errno)));
-
-             (void)close(sock);
            }
 
-  try_next_server:
+           clmd_errlog(errstr);
+
            /* Remove the server from the list. XXX We should free the memory */
            num_servers--;
            int i;