Gurusamy Sarathy:
> Hi,
>
> I've run into an issue with the IPv6 support in postfix when it is
> set up to deliver to a literal IPv6 address in the transport table.
> It looks like 'smtpd' will only accept IPv6 address literals in RFC
> 2821 format while 'smtp' will only accept IPv6 address literals in
> the unadorned form (without the ipv6: prefix).
Aha. This has been broken since IPv6 support was added to Postfix.
Thanks for reporting this here. Unfortunately I don't have the time
to scrape every blog on the web for Postfix problem reports.
The patch below provides a workaround. I have followed your approach
to do minimal damage, and have added a simple sanity check so that
Postfix won't accept forms with [ipv6:hostname] or [ipv6:127.0.0.1].
If some site has omitted the ipv6: prefix in some transport map or
config file, then this patch won't break backwards compatibility.
In the final fix, Postfix should issue a warning that the form
[ipv6addr] is not supported, and that it will become a fatal error.
The final fix would require structural change, but that is allowed
only in the development release. Stable releases are sacred.
Wietse
--- /var/tmp/postfix-2.9-20110219/src/util/host_port.c 2005-01-18
20:22:18.000000000 -0500
+++ src/util/host_port.c 2011-02-25 10:05:53.000000000 -0500
@@ -95,22 +95,41 @@
#include <host_port.h>
+ /*
+ * Point-fix workaround. The libutil library should be email agnostic, but
+ * we can't rip up the library APIs in the stable releases.
+ */
+#include <string.h>
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+#define IPV6_COL "IPv6:" /* RFC 2821 */
+#define IPV6_COL_LEN (sizeof(IPV6_COL) - 1)
+#define HAS_IPV6_COL(str) (strncasecmp((str), IPV6_COL, IPV6_COL_LEN) == 0)
+
/* host_port - parse string into host and port, destroy string */
const char *host_port(char *buf, char **host, char *def_host,
char **port, char *def_service)
{
char *cp = buf;
+ int ipv6 = 0;
/*
* [host]:port, [host]:, [host].
+ * [ipv6:ipv6addr]:port, [ipv6:ipv6addr]:, [ipv6:ipv6addr].
*/
if (*cp == '[') {
- *host = ++cp;
+ ++cp;
+ if ((ipv6 = HAS_IPV6_COL(cp)) != 0)
+ cp += IPV6_COL_LEN;
+ *host = cp;
if ((cp = split_at(cp, ']')) == 0)
return ("missing \"]\"");
if (*cp && *cp++ != ':')
return ("garbage after \"]\"");
+ if (ipv6 && !valid_ipv6_hostaddr(host, DONT_GRIPE))
+ return ("malformed IPv6 address");
*port = *cp ? cp : def_service;
}