OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
 
Re: "reject_unknown_reverse_client_hostname" bouncing mail when name server is down

From: Jordan Russell (jr-list-2006quo.to)
Date: Thu Aug 24 2006 - 22:42:16 CDT


Wietse Venema wrote:
> Please cite the vendor-independent standards document that requires
> that gethostbyaddr() supports IPv6, on IPv6 capable platforms.
>
> If such a document does not exist, then the above code is non-portable,
> that is, its behavior is undefined. With undefined behavior, different
> systems may produce different results, if any result at all.

I didn't realize that AF_INET6 wasn't universally supported.

But if the bug only affects certain systems, then the workaround need
only be applied to those specific systems.

In the case of Linux/glibc, it appears that support for AF_INET6 in
gethostbyaddr() was added back in 1996 (a year before getnameinfo() was
introduced):

http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/resolv/gethnamaddr.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=glibc

And it's documented here:

http://www.gnu.org/software/libc/manual/html_node/Host-Names.html

So, how about adding a new "BROKEN_GETNAMEINFO" #define in
sys_defs.h that activates the workaround code on only the affected
systems? (Again, as a temporary measure to stop mail from bouncing until
all the vendors get around to patching the bug.)

I've attached a patch which does that. Currently I'm only defining
BROKEN_GETNAMEINFO for Linux, since I'm not sure exactly when *BSD's
gethostbyaddr() got support for AF_INET6 (if it hasn't always been
supported; FreeBSD 6.1 definitely has it).

The code has been tested with IPv4 and IPv6 addresses, and it returns
the expected results for both: 250 if RDNS record exists, 554 if not,
and 450 if DNS server is down.

(Note: BSD doesn't have EAI_NODATA, so I changed the "sanity check" to
return EAI_FAMILY if it fails.)

--
Jordan Russell

diff -ur postfix-2.3.2.ORIG/src/util/myaddrinfo.c postfix-2.3.2/src/util/myaddrinfo.c
--- postfix-2.3.2.ORIG/src/util/myaddrinfo.c 2005-07-14 14:56:24.000000000 -0500
+++ postfix-2.3.2/src/util/myaddrinfo.c 2006-08-24 15:19:17.000000000 -0500
-582,7 +582,7
                                      MAI_SERVNAME_STR *service,
                                      int socktype)
 {
-#ifdef EMULATE_IPV4_ADDRINFO
+#if defined(EMULATE_IPV4_ADDRINFO) || defined(BROKEN_GETNAMEINFO)
 
     /*
      * Emulated getnameinfo(3) version.
-595,16 +595,29
      * Sanity check.
      */
     if (sa->sa_family != AF_INET)
- return (EAI_NODATA);
+#ifdef HAS_IPV6
+ if (sa->sa_family != AF_INET6)
+#endif
+ return (EAI_FAMILY);
 
     /*
      * Look up the host name.
      */
     if (hostname != 0) {
+#ifdef HAS_IPV6
+ if (sa->sa_family == AF_INET6) {
+ if ((hp = gethostbyaddr((char *) &(SOCK_ADDR_IN6_ADDR(sa)),
+ sizeof(SOCK_ADDR_IN6_ADDR(sa)),
+ AF_INET6)) == 0)
+ return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NONAME);
+ } else
+#endif
+ {
         if ((hp = gethostbyaddr((char *) &(SOCK_ADDR_IN_ADDR(sa)),
                                 sizeof(SOCK_ADDR_IN_ADDR(sa)),
                                 AF_INET)) == 0)
             return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NONAME);
+ }
 
         /*
          * Save the result. The buffer length includes the space for the null
diff -ur postfix-2.3.2.ORIG/src/util/sys_defs.h postfix-2.3.2/src/util/sys_defs.h
--- postfix-2.3.2.ORIG/src/util/sys_defs.h 2006-07-03 07:37:32.000000000 -0500
+++ postfix-2.3.2/src/util/sys_defs.h 2006-08-24 18:18:47.000000000 -0500
-680,6 +680,7
 # define HAS_IPV6
 # define HAS_PROCNET_IFINET6
 # define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
+# define BROKEN_GETNAMEINFO
 #endif
 #include <linux/version.h>
 #if !defined(KERNEL_VERSION) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)) \