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);
}
if ((fd = ip_connectedsocket(SOCK_STREAM, server_name, port, port,
- timeout, &expand_string_message)) < 0)
+ timeout, NULL, &expand_string_message)) < 0)
goto SOCK_FAIL;
}
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);
}
-/*
+/* 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:
*/
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);
/* 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)
{
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)
{
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;
}
}
/*************************************************/
-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
}
return ip_connectedsocket(SOCK_STREAM, hostname, portlow, porthigh,
- 5, errstr);
+ 5, NULL, errstr);
}
static int
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;
* 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;
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)
*/
int
-string_is_ip_address(uschar *s, int *maskptr)
+string_is_ip_address(const uschar *s, int *maskptr)
{
int i;
int yield = 4;
if (maskptr != NULL)
{
- uschar *ss = s + Ustrlen(s);
+ const uschar *ss = s + Ustrlen(s);
*maskptr = 0;
if (s != ss && isdigit(*(--ss)))
{