From: Jeremy Harris Date: Sun, 16 Feb 2014 16:33:01 +0000 (+0000) Subject: Refactor clamd socket connection X-Git-Url: https://git.exim.org/users/jgh/exim.git/commitdiff_plain/2b058a997c64555ea1fcb748d5658e56a534f7bb Refactor clamd socket connection --- diff --git a/src/src/acl.c b/src/src/acl.c index 89932bbf1..f25debd93 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -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); diff --git a/src/src/expand.c b/src/src/expand.c index a47cc0d64..30735db61 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -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; } diff --git a/src/src/functions.h b/src/src/functions.h index 574675f48..f646d25cf 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -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); diff --git a/src/src/ip.c b/src/src/ip.c index 4a1877dfd..6706b4479 100644 --- a/src/src/ip.c +++ b/src/src/ip.c @@ -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; } } diff --git a/src/src/malware.c b/src/src/malware.c index 9a822fdc2..298031aa3 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -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) diff --git a/src/src/string.c b/src/src/string.c index 0e73e2c79..94d61b1a3 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -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))) {