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;
     }
 

Reply via email to