uschar *portend;
host_item *h;
int portnum;
-int host_af;
int len;
int r, s;
+uschar * errstr;
hostname = string_nextinlist(&arg, &sep, NULL, 0);
portstr = string_nextinlist(&arg, &sep, NULL, 0);
HDEBUG(D_acl)
debug_printf("udpsend [%s]:%d %s\n", h->address, portnum, arg);
-host_af = (Ustrchr(h->address, ':') == NULL)? AF_INET:AF_INET6;
-r = s = ip_socket(SOCK_DGRAM, host_af);
-if (r < 0) goto defer;
-r = ip_connect(s, host_af, h->address, portnum, 1);
+r = s = ip_connectedsocket(SOCK_DGRAM, h_address, portnum, 1, &errstr);
if (r < 0) goto defer;
len = Ustrlen(arg);
r = send(s, arg, len, 0);
-if (r < 0) goto defer;
+if (r < 0)
+ {
+ errstr = strerror(errno);
+ close(s);
+ goto defer;
+ }
+close(s);
if (r < len)
{
*log_msgptr =
return OK;
defer:
-*log_msgptr = string_sprintf("\"udpsend\" failed: %s", strerror(errno));
+*log_msgptr = string_sprintf("\"udpsend\" failed: %s", errstr);
return DEFER;
}
port = ntohs(service_info->s_port);
}
- /* Sort out the server. */
-
- shost.next = NULL;
- shost.address = NULL;
- shost.port = port;
- shost.mx = -1;
-
- namelen = Ustrlen(server_name);
-
- /* Anything enclosed in [] must be an IP address. */
-
- if (server_name[0] == '[' &&
- server_name[namelen - 1] == ']')
- {
- server_name[namelen - 1] = 0;
- server_name++;
- if (string_is_ip_address(server_name, NULL) == 0)
- {
- expand_string_message =
- string_sprintf("malformed IP address \"%s\"", server_name);
- goto EXPAND_FAILED;
- }
- shost.name = shost.address = server_name;
- }
-
- /* Otherwise check for an unadorned IP address */
-
- else if (string_is_ip_address(server_name, NULL) != 0)
- shost.name = shost.address = server_name;
-
- /* Otherwise lookup IP address(es) from the name */
-
- else
- {
- shost.name = server_name;
- if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE, NULL,
- FALSE) != HOST_FOUND)
- {
- expand_string_message =
- string_sprintf("no IP address found for host %s", shost.name);
- goto EXPAND_FAILED;
- }
- }
-
- /* Try to connect to the server - test each IP till one works */
-
- for (h = &shost; h != NULL; h = h->next)
- {
- int af = (Ustrchr(h->address, ':') != 0)? AF_INET6 : AF_INET;
- if ((fd = ip_socket(SOCK_STREAM, af)) == -1)
- {
- expand_string_message = string_sprintf("failed to create socket: "
- "%s", strerror(errno));
+ if ((fd = ip_connectedsocket(SOCK_STREAM, server_name, port, port,
+ timeout, &expand_string_message)) < 0)
goto SOCK_FAIL;
- }
-
- if (ip_connect(fd, af, h->address, port, timeout) == 0)
- {
- connected = TRUE;
- break;
- }
- }
-
- if (!connected)
- {
- expand_string_message = string_sprintf("failed to connect to "
- "socket %s: couldn't connect to any host", sub_arg[0],
- strerror(errno));
- goto SOCK_FAIL;
- }
}
/* Handle a Unix domain socket */
extern void invert_address(uschar *, uschar *);
extern int ip_bind(int, int, uschar *, int);
extern int ip_connect(int, int, uschar *, int, int);
+extern int ip_connected_socket(int, const uschar *, int, int, int,
+ uschar **);
extern int ip_get_address_family(int);
extern void ip_keepalive(int, uschar *, BOOL);
extern int ip_recv(int, uschar *, int, int);
af AF_INET6 or AF_INET for the socket type
address the remote address, in text form
port the remote port
- timeout a timeout
+ timeout a timeout (zero for indefinite timeout)
Returns: 0 on success; -1 on failure, with errno set
*/
}
+/*
+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
+ errstr pointer for allocated string on error
+
+Return:
+ socket fd, or -1 on failure (having allocated an error string)
+*/
+int
+ip_connectedsocket(int type, const uschar * hostname, int portlo, int porthi,
+ int timeout, uschar ** errstr)
+{
+int namelen, port;
+host_item shost;
+host_item *h;
+int fd, fd4 = -1, fd6 = -1;
+
+shost.next = NULL;
+shost.address = NULL;
+shost.port = port;
+shost.mx = -1;
+
+namelen = Ustrlen(hostname);
+
+/* Anything enclosed in [] must be an IP address. */
+
+if (hostname[0] == '[' &&
+ hostname[namelen - 1] == ']')
+ {
+ uschar * host = string_copy(hostname);
+ host[namelen - 1] = 0;
+ host++;
+ if (string_is_ip_address(host, NULL) == 0)
+ {
+ *errstr = string_sprintf("malformed IP address \"%s\"", hostname);
+ return -1;
+ }
+ shost.name = shost.address = host;
+ }
+
+/* Otherwise check for an unadorned IP address */
+
+else if (string_is_ip_address(hostname, NULL) != 0)
+ shost.name = shost.address = hostname;
+
+/* Otherwise lookup IP address(es) from the name */
+
+else
+ {
+ shost.name = hostname;
+ if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE, NULL,
+ FALSE) != HOST_FOUND)
+ {
+ *errstr = string_sprintf("no IP address found for host %s", shost.name);
+ return -1;
+ }
+ }
+
+/* Try to connect to the server - test each IP till one works */
+
+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;
+
+ if (fd < 0)
+ {
+ *errstr = string_sprintf("failed to create socket: %s", strerror(errno));
+ goto bad;
+ }
+
+ 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);
+ return fd;
+ }
+ }
+
+*errstr = string_sprintf("failed to connect to "
+ "%s: couldn't connect to any host", hostname, strerror(errno));
+
+bad:
+ close(fd4); close(fd6); return -1;
+}
+
/*************************************************
* Set keepalive on a socket *
*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 */
{
int scan;
uschar hostname[256];
- unsigned int port, portlow, porthigh;
- struct hostent * he;
- struct in_addr in;
- int sock;
+ unsigned int portlow, porthigh;
/* extract host and port part */
scan = sscanf(CS hostport, "%255s %u-%u", hostname, &portlow, &porthigh);
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;
+ return ip_connectedsocket(SOCK_STREAM, hostname, portlow, porthigh,
+ 5, errstr);
}
static int