From: Jeremy Harris Date: Wed, 28 Jan 2015 00:16:56 +0000 (+0000) Subject: Support hostnames and IPv6 addresses for spamd_address. Bug 1259 X-Git-Tag: exim-4_86_RC1~124 X-Git-Url: https://git.exim.org/users/heiko/exim.git/commitdiff_plain/2aad5761b59a709d98a7d278d83e978ac4e83c2b?ds=inline Support hostnames and IPv6 addresses for spamd_address. Bug 1259 --- diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index e34ed8054..cb3d78d5d 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -30778,6 +30778,12 @@ condition defers. Unix and TCP socket specifications may be mixed in any order. Each element of the list is a list itself, space-separated by default and changeable in the usual way. + +For TCP socket specifications a host name or IP (v4 or v6, but +subject to list-separator quoting rules) address can be used, +and the port can be one or a dash-separated pair. +In the latter case, the range is tried in strict order. + Elements after the first for Unix sockets, or second for TCP socket, are options. The supported option are: diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index e06ac6065..fbfe7507e 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -58,7 +58,8 @@ JH/15 Bug 670: The spamd_address main option (for the spam= ACL condition) modifiers per server. Patch originally by . JH/16 The spamd_address main option now supports a mixed list of local - and remote servers. + and remote servers. Remote servers can be IPv6 addresses, and + specify a port-range. diff --git a/src/src/spam.c b/src/src/spam.c index 89be98a4e..76db2b667 100644 --- a/src/src/spam.c +++ b/src/src/spam.c @@ -263,8 +263,7 @@ start = time(NULL); uschar *address; uschar *spamd_address_list_ptr = spamd_address_work; spamd_address_container * spamd_address_vector[32]; - spamd_address_container * this_spamd; - + spamd_address_container * sd; /* Check how many spamd servers we have and register their addresses */ @@ -277,10 +276,9 @@ start = time(NULL); uschar * s; HDEBUG(D_acl) debug_printf("spamd: addr entry '%s'\n", address); - this_spamd = - (spamd_address_container *)store_get(sizeof(spamd_address_container)); + sd = (spamd_address_container *)store_get(sizeof(spamd_address_container)); - for (sublist = address, args = 0, spamd_param_init(this_spamd); + for (sublist = address, args = 0, spamd_param_init(sd); s = string_nextinlist(&sublist, &sublist_sep, NULL, 0); args++ ) @@ -288,11 +286,13 @@ start = time(NULL); HDEBUG(D_acl) debug_printf("spamd: addr parm '%s'\n", s); switch (args) { - case 0: this_spamd->hostname = s; + case 0: sd->hostspec = s; if (*s == '/') args++; /* local; no port */ break; - case 1: this_spamd->tcp_port = atoi(s); break; - default: spamd_param(s, this_spamd); break; + case 1: sd->hostspec = string_sprintf("%s %s", sd->hostspec, s); + break; + default: spamd_param(s, sd); + break; } } if (args < 2) @@ -302,7 +302,7 @@ start = time(NULL); continue; } - spamd_address_vector[num_servers] = this_spamd; + spamd_address_vector[num_servers] = sd; if (++num_servers > 31) break; } @@ -318,82 +318,29 @@ start = time(NULL); while (1) { - struct hostent *he; - int i; - BOOL is_local; + uschar * errstr; current_server = spamd_get_server(spamd_address_vector, num_servers); - this_spamd = spamd_address_vector[current_server]; - - is_local = *this_spamd->hostname == '/'; + sd = spamd_address_vector[current_server]; - debug_printf(is_local - ? "trying server %s\n" : "trying server %s, port %u\n", - this_spamd->hostname, this_spamd->tcp_port); + debug_printf("trying server %s\n", sd->hostspec); /* contact a spamd */ - if (is_local) - { - if ((spamd_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - { - log_write(0, LOG_MAIN|LOG_PANIC, - "%s spamd: unable to acquire socket (%s)", - loglabel, - strerror(errno)); - goto defer; - } - - server.sun_family = AF_UNIX; - Ustrcpy(server.sun_path, this_spamd->hostname); + if ((spamd_sock = ip_streamsocket(sd->hostspec, &errstr, 5)) >= 0) + break; - if (connect(spamd_sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) >= 0) - break; /* connection OK */ + log_write(0, LOG_MAIN, "%s spamd: %s", loglabel, errstr); + sd->is_failed = TRUE; - log_write(0, LOG_MAIN, - "%s spamd: unable to connect to UNIX socket %s (%s)", - loglabel, server.sun_path, strerror(errno) ); - } - else + current_server = spamd_get_server(spamd_address_vector, num_servers); + if (current_server < 0) { - if ((spamd_sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) - { - log_write(0, LOG_MAIN|LOG_PANIC, - "%s error creating IP socket for spamd", loglabel); - goto defer; - } - - /*XXX should we use getaddrinfo? */ - if (!(he = gethostbyname(CS this_spamd->hostname))) - log_write(0, LOG_MAIN|LOG_PANIC, - "%s failed to lookup host '%s'", loglabel, this_spamd->hostname); - - else - { - struct in_addr in = *(struct in_addr *) he->h_addr_list[0]; - - if (ip_connect(spamd_sock, AF_INET, US inet_ntoa(in), - this_spamd->tcp_port, 5) > -1) - break; /* connection OK */ - - log_write(0, LOG_MAIN, - "%s warning - spamd connection to '%s', port %u failed: %s", - loglabel, - this_spamd->hostname, this_spamd->tcp_port, strerror(errno)); - } - - (void)close(spamd_sock); - - this_spamd->is_failed = TRUE; - current_server = spamd_get_server(spamd_address_vector, num_servers); - if (current_server < 0) - { - log_write(0, LOG_MAIN|LOG_PANIC, "%s all spamd servers failed", - loglabel); - goto defer; - } + log_write(0, LOG_MAIN|LOG_PANIC, "%s all spamd servers failed", + loglabel); + goto defer; } } - is_rspamd = this_spamd->is_rspamd; + is_rspamd = sd->is_rspamd; } if (spamd_sock == -1) @@ -672,3 +619,5 @@ defer: } #endif +/* vi: aw ai sw=2 +*/ diff --git a/src/src/spam.h b/src/src/spam.h index 50aed9145..7ab6d2a58 100644 --- a/src/src/spam.h +++ b/src/src/spam.h @@ -25,8 +25,7 @@ typedef struct spamd_address_container { - uschar * hostname; - unsigned short tcp_port; + uschar * hostspec; int is_rspamd:1; int is_failed:1; int is_backup:1;