- if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
- (void)close(sock);
- log_write(0, LOG_MAIN|LOG_PANIC,
- "malware acl condition: clamd: connection to %s, port %u failed (%s)",
- inet_ntoa(in), port, strerror(errno));
- return DEFER;
+ /* See the discussion of response formats below to see why we really don't
+ like colons in filenames when passing filenames to ClamAV. */
+ if (use_scan_command && Ustrchr(eml_filename, ':')) {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "malware acl condition: clamd: local/SCAN mode incompatible with" \
+ " : in path to email filename [%s]", eml_filename);
+ return DEFER;
+ }
+
+ /* We have some network servers specified */
+ if (num_servers) {
+
+ /* Confirmed in ClamAV source (0.95.3) that the TCPAddr option of clamd
+ * only supports AF_INET, but we should probably be looking to the
+ * future and rewriting this to be protocol-independent anyway. */
+
+ while ( num_servers > 0 ) {
+ /* Randomly pick a server to start with */
+ current_server = random_number( num_servers );
+
+ debug_printf("trying server name %s, port %u\n",
+ clamd_address_vector[current_server]->tcp_addr,
+ clamd_address_vector[current_server]->tcp_port);
+
+ /* 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) {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "malware acl condition: clamd: 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) {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "malware acl condition: clamd: 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) {
+ /* Connection successfully established with a server */
+ hostname = clamd_address_vector[current_server]->tcp_addr;
+ break;
+ } else {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "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:
+ /* Remove the server from the list. XXX We should free the memory */
+ num_servers--;
+ int i;
+ for( i = current_server; i < num_servers; i++ )
+ clamd_address_vector[i] = clamd_address_vector[i+1];