aboutsummaryrefslogtreecommitdiffstats
path: root/mail/exim
diff options
context:
space:
mode:
authorsheldonh <sheldonh@FreeBSD.org>2001-07-16 17:12:55 +0800
committersheldonh <sheldonh@FreeBSD.org>2001-07-16 17:12:55 +0800
commitc5b9899e5b4710a15c0e2e39987415c5e969f9fa (patch)
tree18d62c2196fa8be86aa3a1aa81bae4f8c36aec1b /mail/exim
parent66008c09be63113e7da7902286185bc637daeeb6 (diff)
downloadfreebsd-ports-graphics-c5b9899e5b4710a15c0e2e39987415c5e969f9fa.tar.gz
freebsd-ports-graphics-c5b9899e5b4710a15c0e2e39987415c5e969f9fa.tar.zst
freebsd-ports-graphics-c5b9899e5b4710a15c0e2e39987415c5e969f9fa.zip
Apply the author's fix for socket binding in the case where
net.inet6.ip6.v6only is set. This sysctl disables AF_INET6 wildcard listeners from accepting IPv4 traffic.
Diffstat (limited to 'mail/exim')
-rw-r--r--mail/exim/files/patch-src::daemon.c182
1 files changed, 177 insertions, 5 deletions
diff --git a/mail/exim/files/patch-src::daemon.c b/mail/exim/files/patch-src::daemon.c
index b792bbf3529..72ee5952dd6 100644
--- a/mail/exim/files/patch-src::daemon.c
+++ b/mail/exim/files/patch-src::daemon.c
@@ -1,17 +1,189 @@
--- src/daemon.c.orig Tue Jul 10 11:52:32 2001
+++ src/daemon.c Tue Jul 10 11:53:33 2001
-@@ -841,7 +841,13 @@
+@@ -661,7 +661,7 @@
+ union sockaddr_46 sin;
+
+ #if HAVE_IPV6
+- struct in6_addr anyaddr6 = IN6ADDR_ANY_INIT;
++ struct in6_addr anyaddr6 = in6addr_any;
+ #endif
+
+ /* Find the standard SMTP port if no port number given; otherwise
+@@ -690,7 +690,11 @@
+ }
+
+ /* Otherwise set up one address item with a null address, implying listening
+- on all interfaces. */
++ on all interfaces. In an IPv6 world, we set up a second address for listening
++ on all IPv6 interfaces. Some IPv6 stacks will pick up incoming IPv4 calls on
++ an IPv6 wildcard socket, but some won't (there are security issues). Using
++ two sockets should work in all cases. We identify an IPv6 wildcard address by
++ the string ":". */
+
+ else
+ {
+@@ -698,6 +702,13 @@
+ addresses->next = NULL;
+ addresses->address[0] = 0;
+ listen_socket_count = 1;
++ #if HAVE_IPV6
++ addresses->next = store_get(sizeof(ip_address_item));
++ addresses->next->next = NULL;
++ addresses->next->address[0] = ':';
++ addresses->next->address[1] = 0;
++ listen_socket_count++;
++ #endif /* HAVE_IPV6 */
+ }
+
+ /* Get a vector to remember all the sockets in */
+@@ -714,41 +725,20 @@
+ #endif
+
+ /* For each IP address, create a socket and bind it to the appropriate
+- port. Note that if local_interfaces is not set, we bind a single socket to
+- all interfaces. */
++ port. Some IPv6 stacks can handle IPv4 addresses on IPv6 sockets using
++ the mapping facilities. However, some don't do this because of security
++ concerns. Therefore, we use IPv4 sockets for IPv4 addresses even in an
++ IPv6 world. */
+
+ for (ipa = addresses, sk = 0; sk < listen_socket_count; ipa = ipa->next, sk++)
+ {
+ int i;
++ int af = (strchr(ipa->address, ':') != NULL)? AF_INET6 : AF_INET;
+
+- #if HAVE_IPV6
+- BOOL ipv6_socket = TRUE;
+- BOOL ipv6_address = strchr(ipa->address, ':') != NULL;
+-
+- /* A system which has all the IPv6 libraries etc. may nevertheless not
+- support IPv6 in the kernel, so if the socket creation fails, fall back
+- on creating an IPv4 socket, except when we have an explicit IPv6 address,
+- for which we really do need an IPv6 socket. */
+-
+- listen_sockets[sk] = socket(AF_INET6, SOCK_STREAM, 0);
+- if (listen_sockets[sk] < 0)
+- {
+- if (!ipv6_address)
+- {
+- listen_sockets[sk] = socket(AF_INET, SOCK_STREAM, 0);
+- ipv6_socket = FALSE;
+- }
+- }
+-
+- /* The IPv4 case */
+-
+- #else /* HAVE_IPV6 */
+- listen_sockets[sk] = socket(AF_INET, SOCK_STREAM, 0);
+- #endif /* HAVE_IPV6 */
+-
++ listen_sockets[sk] = socket(af, SOCK_STREAM, 0);
+ if (listen_sockets[sk] < 0)
+- log_write(0, LOG_PANIC_DIE, "socket creation failed: %s",
+- strerror(errno));
++ log_write(0, LOG_PANIC_DIE, "IPv%c socket creation failed: %s",
++ (af == AF_INET6)? '6' : '4', strerror(errno));
+
+ /* Set SO_REUSEADDR so that the daemon can be restarted while a connection
+ is being handled. Without this, a connection will prevent reuse of the
+@@ -765,44 +755,29 @@
+
+ memset(&sin, 0, sizeof(sin));
+
+- /* This code has to be entirely different for IPv6 and IPv4 because
+- of the different struct layouts. Sigh. Under IPv6, however, we may have
+- ended up with an IPv4 socket because the kernel may not support IPv6 even
+- if the libraries etc. are available. In this case, revert to IPv4 style
+- code (this will happen only when the the address is not an IPv6 one).
+- Although the code is identical, I've chosen to replicate it for ease of
+- reading the two cases. */
++ /* Setup code when using an IPv6 socket. The wildcard address is ":", to
++ ensure an IPv6 socket is used. */
+
+ #if HAVE_IPV6
+- if (ipv6_socket)
++ if (af == AF_INET6)
+ {
+ sin.v6.sin6_family = AF_INET6;
+ sin.v6.sin6_port = net_port;
+-
+- if (ipa->address[0] == 0)
++ if (ipa->address[0] == ':' && ipa->address[1] == 0)
+ {
+ sin.v6.sin6_addr = anyaddr6;
+ DEBUG(9) debug_printf("listening on all interfaces (IPv6)\n");
+ }
+ else
+ {
+- int rc;
+- if (ipv6_address)
+- rc = inet_pton(AF_INET6, ipa->address, &sin.v6.sin6_addr);
+- else
+- /* We have an IPv6 socket, and an IPv4 address. We have to turn the
+- address into an IPv6 mapped form. */
+- {
+- memmove(ipa->address+7, ipa->address, (int)strlen(ipa->address) + 1);
+- memcpy(ipa->address, "::ffff:", 7);
+- rc = inet_pton(AF_INET6, ipa->address, &sin.v6.sin6_addr);
+- }
+- if (rc != 1)
++ if (inet_pton(AF_INET6, ipa->address, &sin.v6.sin6_addr) != 1)
+ log_write(0, LOG_PANIC_DIE, "unable to parse \"%s\"", ipa->address);
+ DEBUG(9) debug_printf("listening on %s\n", ipa->address);
+ }
+ }
+- else /* Revert to IPv4 code */
++ else
++ #endif /* HAVE_IPV6 */
++ /* Setup code when using IPv4 socket. The wildcard address is "". */
+ {
+ sin.v4.sin_family = AF_INET;
+ sin.v4.sin_port = net_port;
+@@ -817,34 +792,25 @@
+ DEBUG(9) debug_printf("listening on %s\n", ipa->address);
+ }
+ }
+- #else /* HAVE_IPV6 */
+
+-
+- /* The IPv4 case is simple. */
+-
+- sin.v4.sin_family = AF_INET;
+- sin.v4.sin_port = net_port;
+- if (ipa->address[0] == 0)
+- {
+- sin.v4.sin_addr.s_addr = (S_ADDR_TYPE)INADDR_ANY;
+- DEBUG(9) debug_printf("listening on all interfaces\n");
+- }
+- else
+- {
+- sin.v4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(ipa->address);
+- DEBUG(9) debug_printf("listening on %s\n", ipa->address);
+- }
+- #endif /* HAVE_IPV6 */
+-
+-
+- /* Retry loop */
++ /* Retry loop. Need to get the length of sin right for IPv4/IPv6
++ for some operating systems that check it. Although AF_INET6 is always
++ available (even on old IPv4 systems), the sin.v6 field isn't. */
for (i = 9; i >= 0; i--)
{
- if (bind(listen_sockets[sk], (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ if (bind(listen_sockets[sk], (struct sockaddr *)&sin,
-+ #ifdef HAVE_IPV6
-+ ipv6_socket? sizeof(sin.v6) : sizeof(sin.v4)
++ #if HAVE_IPV6
++ (af == AF_INET6)? sizeof(sin.v6) : sizeof(sin.v4)
+ #else
+ sizeof(sin)
-+ #endif
++ #endif /* HAVE_IPV6 */
+ ) < 0)
{
char *msg = strerror(errno);
- char *addr = (ipa->address[0] == 0)? "(any)" : ipa->address;
+- char *addr = (ipa->address[0] == 0)? "(any)" : ipa->address;
++ char *addr = (ipa->address[0] == 0)? "(any IPv4)" :
++ (ipa->address[0] == ':' && ipa->address[1] == 0)? "(any IPv6)" :
++ ipa->address;
+ if (i == 0)
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE,
+ "socket bind() to port %d for address %s failed: %s: "