--- /dev/null
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/acconfig.h cyrus-imapd-2.0.12/acconfig.h
+--- cyrus-imapd-2.0.12.orig/acconfig.h Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/acconfig.h Thu Apr 26 17:11:37 2001
+@@ -111,6 +111,12 @@
+ /* do we have rlim_t? */
+ #undef HAVE_RLIM_T
+
++/* is IPv6 enabled? */
++#undef INET6
++
++/* Define if you have ss_family in struct sockaddr_storage. */
++#undef HAVE_SS_FAMILY
++
+ @BOTTOM@
+
+ #ifndef __GNUC__
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/aclocal.m4 cyrus-imapd-2.0.12/aclocal.m4
+--- cyrus-imapd-2.0.12.orig/aclocal.m4 Mon Feb 19 20:57:39 2001
++++ cyrus-imapd-2.0.12/aclocal.m4 Thu Apr 26 17:11:37 2001
+@@ -264,3 +264,71 @@
+ AC_SUBST(LIB_UCDSNMP)
+ ])
+
++dnl See whether we can use IPv6 related functions
++AC_DEFUN(IPv6_CHECK_FUNC, [
++changequote(, )dnl
++ac_tr_lib=HAVE_`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
++ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
++changequote([, ])dnl
++AC_CHECK_FUNC($1, [dnl
++ AC_DEFINE_UNQUOTED($ac_tr_lib)
++ ac_cv_lib_socket_$1=no
++ ac_cv_lib_inet6_$1=no
++], [dnl
++ AC_CHECK_LIB(socket, $1, [dnl
++ AC_DEFINE_UNQUOTED($ac_tr_lib)
++ LIBS="$LIBS -lsocket"
++ ac_cv_lib_inet6_$1=no
++ ], [dnl
++ AC_MSG_CHECKING([whether your system has IPv6 directory])
++ AC_CACHE_VAL(ipv6_cv_dir, [dnl
++ for ipv6_cv_dir in /usr/local/v6 /usr/inet6 no; do
++ if test $ipv6_cv_dir = no -o -d $ipv6_cv_dir; then
++ break
++ fi
++ done])dnl
++ AC_MSG_RESULT($ipv6_cv_dir)
++ if test $ipv6_cv_dir = no; then
++ ac_cv_lib_inet6_$1=no
++ else
++ if test x$ipv6_libinet6 = x; then
++ ipv6_libinet6=no
++ SAVELDFLAGS="$LDFLAGS"
++ LDFLAGS="$LDFLAGS -L$ipv6_cv_dir/lib"
++ fi
++ AC_CHECK_LIB(inet6, $1, [dnl
++ AC_DEFINE_UNQUOTED($ac_tr_lib)
++ if test $ipv6_libinet6 = no; then
++ ipv6_libinet6=yes
++ LIBS="$LIBS -linet6"
++ fi],)dnl
++ if test $ipv6_libinet6 = no; then
++ LDFLAGS="$SAVELDFLAGS"
++ fi
++ fi])dnl
++])dnl
++if test $ac_cv_func_$1 = yes -o $ac_cv_lib_socket_$1 = yes \
++ -o $ac_cv_lib_inet6_$1 = yes
++then
++ ipv6_cv_$1=yes
++ ifelse([$2], , :, [$2])
++else
++ ipv6_cv_$1=no
++ ifelse([$3], , :, [$3])
++fi])
++
++dnl See whether we have ss_family in sockaddr_storage
++AC_DEFUN(IPv6_CHECK_SS_FAMILY, [
++AC_MSG_CHECKING([whether you have ss_family in struct sockaddr_storage])
++AC_CACHE_VAL(ipv6_cv_ss_family, [dnl
++AC_TRY_COMPILE([#include <sys/types.h>
++#include <sys/socket.h>],
++ [struct sockaddr_storage ss; int i = ss.ss_family;],
++ [ipv6_cv_ss_family=yes], [ipv6_cv_ss_family=no])])dnl
++if test $ipv6_cv_ss_family = yes; then
++ ifelse([$1], , AC_DEFINE(HAVE_SS_FAMILY), [$1])
++else
++ ifelse([$2], , :, [$2])
++fi
++AC_MSG_RESULT($ipv6_cv_ss_family)])
++
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/config.h.in cyrus-imapd-2.0.12/config.h.in
+--- cyrus-imapd-2.0.12.orig/config.h.in Mon Feb 19 20:57:39 2001
++++ cyrus-imapd-2.0.12/config.h.in Thu Apr 26 17:11:37 2001
+@@ -128,6 +128,12 @@
+ /* do we have rlim_t? */
+ #undef HAVE_RLIM_T
+
++/* is IPv6 enabled? */
++#undef INET6
++
++/* Define if you have ss_family in struct sockaddr_storage. */
++#undef HAVE_SS_FAMILY
++
+ /* Define if you have the ftruncate function. */
+ #undef HAVE_FTRUNCATE
+
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/configure.in cyrus-imapd-2.0.12/configure.in
+--- cyrus-imapd-2.0.12.orig/configure.in Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/configure.in Thu Apr 26 17:11:37 2001
+@@ -725,6 +725,15 @@
+
+ LIBS="$LIBS ${LIB_SOCKET}"
+
++AC_ARG_ENABLE(ipv6, [ --disable-ipv6 Don't compile in IPv6 support],
++ ipv6="$enableval", ipv6="yes")
++if test "$ipv6" != "yes"; then
++ AC_MSG_RESULT(IPv6 support is disabled)
++else
++ IPv6_CHECK_FUNC(getaddrinfo, AC_DEFINE(INET6))
++ IPv6_CHECK_SS_FAMILY()
++fi
++
+ # Figure out what directories we're linking against.
+ # Lots of fun for the whole family.
+ # This probably chokes on anything with spaces in it.
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/imap/fud.c cyrus-imapd-2.0.12/imap/fud.c
+--- cyrus-imapd-2.0.12.orig/imap/fud.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/imap/fud.c Thu Apr 26 17:11:37 2001
+@@ -83,12 +83,21 @@
+ extern char *optarg;
+
+ /* forward decls */
++#ifdef INET6
++int handle_request(const char *who, const char *name,
++ struct sockaddr_storage sfrom);
++
++void send_reply(struct sockaddr_storage sfrom, int status,
++ const char *user, const char *mbox,
++ int numrecent, time_t lastread, time_t lastarrived);
++#else
+ int handle_request(const char *who, const char *name,
+ struct sockaddr_in sfrom);
+
+ void send_reply(struct sockaddr_in sfrom, int status,
+ const char *user, const char *mbox,
+ int numrecent, time_t lastread, time_t lastarrived);
++#endif
+
+ int soc;
+
+@@ -104,7 +113,11 @@
+
+ int begin_handling(void)
+ {
++#ifdef INET6
++ struct sockaddr_storage sfrom;
++#else
+ struct sockaddr_in sfrom;
++#endif
+ socklen_t sfromsiz = sizeof(sfrom);
+ int r;
+ char buf[MAXLOGNAME + MAX_MAILBOX_NAME + 1];
+@@ -190,8 +203,13 @@
+ shut_down(0);
+ }
+
++#ifdef INET6
++int handle_request(const char *who, const char *name,
++ struct sockaddr_storage sfrom)
++#else
+ int handle_request(const char *who, const char *name,
+ struct sockaddr_in sfrom)
++#endif
+ {
+ int r;
+ struct mailbox mailbox;
+@@ -277,9 +295,15 @@
+ }
+
+ void
++#ifdef INET6
++send_reply(struct sockaddr_storage sfrom, int status,
++ const char *user, const char *mbox,
++ int numrecent, time_t lastread, time_t lastarrived)
++#else
+ send_reply(struct sockaddr_in sfrom, int status,
+ const char *user, const char *mbox,
+ int numrecent, time_t lastread, time_t lastarrived)
++#endif
+ {
+ char buf[MAX_MAILBOX_PATH + 16 + 9];
+ int siz;
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/imap/imapd.c cyrus-imapd-2.0.12/imap/imapd.c
+--- cyrus-imapd-2.0.12.orig/imap/imapd.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/imap/imapd.c Thu Apr 26 17:18:32 2001
+@@ -93,6 +93,15 @@
+ #include "tls.h"
+ #endif /* HAVE_SSL */
+
++#ifdef INET6
++#ifndef NI_WITHSCOPEID
++#define NI_WITHSCOPEID 0
++#endif
++#ifndef HAVE_SS_FAMILY
++#define ss_family __ss_family
++#endif
++#endif
++
+ extern int optind;
+ extern char *optarg;
+ extern int errno;
+@@ -102,7 +111,11 @@
+
+ /* per-user/session state */
+ struct protstream *imapd_out, *imapd_in;
++#ifdef INET6
++static char imapd_clienthost[NI_MAXHOST*2+1] = "[local]";
++#else
+ static char imapd_clienthost[250] = "[local]";
++#endif
+ static time_t imapd_logtime;
+ static int imapd_logfd = -1;
+ char *imapd_userid;
+@@ -457,7 +470,12 @@
+ int timeout;
+ sasl_security_properties_t *secprops = NULL;
+ sasl_external_properties_t extprops;
++#ifdef INET6
++ struct sockaddr_storage imapd_localaddr, imapd_remoteaddr;
++ char hbuf[NI_MAXHOST];
++#else
+ struct sockaddr_in imapd_localaddr, imapd_remoteaddr;
++#endif
+ int imapd_haveaddr = 0;
+
+ signals_poll();
+@@ -493,6 +511,28 @@
+
+ /* Find out name of client host */
+ salen = sizeof(imapd_remoteaddr);
++#ifdef INET6
++ if (getpeername(0, (struct sockaddr *)&imapd_remoteaddr, &salen) == 0 &&
++ (imapd_remoteaddr.ss_family == AF_INET ||
++ imapd_remoteaddr.ss_family == AF_INET6)) {
++ if (getnameinfo((struct sockaddr *)&imapd_remoteaddr, salen,
++ hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) == 0) {
++ strncpy(imapd_clienthost, hbuf, sizeof(hbuf));
++ }
++ else {
++ imapd_clienthost[0] = '\0';
++ }
++ getnameinfo((struct sockaddr *)&imapd_remoteaddr, salen, hbuf,
++ sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
++ strcat(imapd_clienthost, "[");
++ strcat(imapd_clienthost, hbuf);
++ strcat(imapd_clienthost, "]");
++ salen = sizeof(imapd_localaddr);
++ if (getsockname(0, (struct sockaddr *)&imapd_localaddr, &salen) == 0) {
++ imapd_haveaddr = 1;
++ }
++ }
++#else
+ if (getpeername(0, (struct sockaddr *)&imapd_remoteaddr, &salen) == 0 &&
+ imapd_remoteaddr.sin_family == AF_INET) {
+ hp = gethostbyaddr((char *)&imapd_remoteaddr.sin_addr,
+@@ -511,6 +551,7 @@
+ imapd_haveaddr = 1;
+ }
+ }
++#endif
+
+ /* create the SASL connection */
+ if (sasl_server_new("imap", config_servername,
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/imap/lmtpengine.c cyrus-imapd-2.0.12/imap/lmtpengine.c
+--- cyrus-imapd-2.0.12.orig/imap/lmtpengine.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/imap/lmtpengine.c Thu Apr 26 17:11:38 2001
+@@ -85,6 +85,15 @@
+
+ #define RCPT_GROW 30
+
++#ifdef INET6
++#ifndef NI_WITHSCOPEID
++#define NI_WITHSCOPEID 0
++#endif
++#ifndef HAVE_SS_FAMILY
++#define ss_family __ss_family
++#endif
++#endif
++
+ /* data per message */
+ struct Header {
+ char *name;
+@@ -965,7 +974,11 @@
+ int r;
+ char *err;
+
++#ifdef INET6
++ struct sockaddr_storage localaddr, remoteaddr;
++#else
+ struct sockaddr_in localaddr, remoteaddr;
++#endif
+ socklen_t salen;
+
+ sasl_conn_t *conn = NULL;
+@@ -977,6 +990,9 @@
+ 1: did AUTH */
+ char *authuser = NULL;
+ struct auth_state *authstate = NULL;
++#ifdef INET6
++ char hbuf[NI_MAXHOST];
++#endif
+
+ msg_new(&msg);
+ if (sasl_server_new("lmtp", NULL, NULL, NULL, 0, &conn) != SASL_OK) {
+@@ -994,7 +1010,13 @@
+ /* determine who we're talking to */
+ salen = sizeof(remoteaddr);
+ r = getpeername(fd, (struct sockaddr *)&remoteaddr, &salen);
+- if (!r && remoteaddr.sin_family == AF_INET) {
++ if (!r &&
++#ifdef INET6
++ (remoteaddr.ss_family == AF_INET || remoteaddr.ss_family == AF_INET6)
++#else
++ remoteaddr.sin_family == AF_INET
++#endif
++ ) {
+ /* connected to an internet socket */
+
+ salen = sizeof(localaddr);
+@@ -1006,9 +1028,16 @@
+ fatal("can't get local addr", EC_SOFTWARE);
+ }
+
++#ifdef INET6
++ getnameinfo((struct sockaddr *)&remoteaddr, salen, hbuf, sizeof(hbuf),
++ NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
++ syslog(LOG_DEBUG, "connection from [%s]%s", hbuf,
++ func->preauth ? " preauth'd as postman" : "");
++#else
+ syslog(LOG_DEBUG, "connection from [%s]%s",
+ inet_ntoa(remoteaddr.sin_addr),
+ func->preauth ? " preauth'd as postman" : "");
++#endif
+ } else {
+ /* we're not connected to a internet socket! */
+ func->preauth = 1;
+@@ -1139,20 +1168,37 @@
+
+ if (in) { free(in); in = NULL; }
+ if (out) { free(out); out = NULL; }
++#ifdef INET6
++ if (remoteaddr.ss_family == AF_INET ||
++ remoteaddr.ss_family == AF_INET6)
++ getnameinfo((struct sockaddr *)&remoteaddr, salen,
++ hbuf, sizeof(hbuf), NULL, 0,
++ NI_NUMERICHOST | NI_WITHSCOPEID);
++ else
++ strcpy(hbuf, "[unix socket]");
++#endif
+ if ((r != SASL_OK) && (r != SASL_CONTINUE)) {
+ if (errstr) {
+ syslog(LOG_ERR, "badlogin: %s %s %s [%s]",
++#ifdef INET6
++ hbuf,
++#else
+ remoteaddr.sin_family == AF_INET ?
+ inet_ntoa(remoteaddr.sin_addr) :
+ "[unix socket]",
++#endif
+ mech,
+ sasl_errstring(r, NULL, NULL),
+ errstr);
+ } else {
+ syslog(LOG_ERR, "badlogin: %s %s %s",
++#ifdef INET6
++ hbuf,
++#else
+ remoteaddr.sin_family == AF_INET ?
+ inet_ntoa(remoteaddr.sin_addr) :
+ "[unix socket]",
++#endif
+ mech,
+ sasl_errstring(r, NULL, NULL));
+ }
+@@ -1173,9 +1219,13 @@
+ VARIABLE_AUTH, hash_simple(mech),
+ VARIABLE_LISTEND);
+ syslog(LOG_NOTICE, "login: %s %s %s %s",
++#ifdef INET6
++ hbuf,
++#else
+ remoteaddr.sin_family == AF_INET ?
+ inet_ntoa(remoteaddr.sin_addr) :
+ "[unix socket]",
++#endif
+ user, mech, "User logged in");
+
+ authenticated += 2;
+@@ -1595,18 +1645,59 @@
+ free(host);
+ host = xstrdup(config_servername);
+ } else {
++#ifdef INET6
++ struct addrinfo hints, *res0 = NULL, *res;
++ int err;
++#else
+ struct hostent *hp;
+ struct sockaddr_in addr;
+ struct servent *service;
++#endif
+ char *p;
+
++#ifdef INET6
++ if (*host == '[' && (p = strchr(host + 1, ']')) != NULL &&
++ (*++p == '\0' || *p == ':')) {
++ host++;
++ *(p - 1) = '\0';
++ if (*p != ':')
++ p = NULL;
++ } else
++ p = strchr(host, ':');
++#else
+ p = strchr(host, ':');
++#endif
+ if (p) {
+ *p++ = '\0';
+ } else {
+ p = "lmtp";
+ }
+
++#ifdef INET6
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = PF_UNSPEC;
++ hints.ai_socktype = SOCK_STREAM;
++ err = getaddrinfo(host, p, &hints, &res0);
++ if (err) {
++ syslog(LOG_ERR, "getaddrinfo(%s, %s) failed: %s",
++ host, p, gai_strerror(err));
++ goto donesock;
++ }
++ for (res = res0; res; res = res->ai_next) {
++ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
++ if (sock < 0)
++ continue;
++ if (connect(sock, res->ai_addr, res->ai_addrlen) >= 0)
++ break;
++ close(sock);
++ sock = -1;
++ }
++ freeaddrinfo(res0);
++ if (sock < 0) {
++ syslog(LOG_ERR, "connect(%s:%s) failed: %m", host, p);
++ goto donesock;
++ }
++#else
+ if ((hp = gethostbyname(host)) == NULL) {
+ syslog(LOG_ERR, "gethostbyname(%s) failed", host);
+ goto donesock;
+@@ -1636,6 +1727,7 @@
+ syslog(LOG_ERR, "connect(%s:%s) failed: %m", host, p);
+ goto donesock;
+ }
++#endif
+ }
+
+ donesock:
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/imap/pop3d.c cyrus-imapd-2.0.12/imap/pop3d.c
+--- cyrus-imapd-2.0.12.orig/imap/pop3d.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/imap/pop3d.c Thu Apr 26 17:11:38 2001
+@@ -93,6 +93,15 @@
+ #endif /* HAVE_KRB */
+ static int kflag = 0;
+
++#ifdef INET6
++#ifndef NI_WITHSCOPEID
++#define NI_WITHSCOPEID 0
++#endif
++#ifndef HAVE_SS_FAMILY
++#define ss_family __ss_family
++#endif
++#endif
++
+ extern int optind;
+ extern char *optarg;
+ extern int opterr;
+@@ -109,9 +118,17 @@
+
+ char *popd_userid = 0;
+ struct mailbox *popd_mailbox = 0;
++#ifdef INET6
++struct sockaddr_storage popd_localaddr, popd_remoteaddr;
++#else
+ struct sockaddr_in popd_localaddr, popd_remoteaddr;
++#endif
+ int popd_haveaddr = 0;
++#ifdef INET6
++char popd_clienthost[NI_MAXHOST*2+1] = "[local]";
++#else
+ char popd_clienthost[250] = "[local]";
++#endif
+ struct protstream *popd_out, *popd_in;
+ unsigned popd_exists = 0;
+ unsigned popd_highest;
+@@ -209,6 +226,9 @@
+ struct hostent *hp;
+ int timeout;
+ sasl_security_properties_t *secprops=NULL;
++#ifdef INET6
++ char hbuf[NI_MAXHOST];
++#endif
+
+ signals_poll();
+
+@@ -239,6 +259,28 @@
+
+ /* Find out name of client host */
+ salen = sizeof(popd_remoteaddr);
++#ifdef INET6
++ if (getpeername(0, (struct sockaddr *)&popd_remoteaddr, &salen) == 0 &&
++ (popd_remoteaddr.ss_family == AF_INET ||
++ popd_remoteaddr.ss_family == AF_INET6)) {
++ if (getnameinfo((struct sockaddr *)&popd_remoteaddr, salen,
++ hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) == 0) {
++ strncpy(popd_clienthost, hbuf, sizeof(hbuf));
++ }
++ else {
++ popd_clienthost[0] = '\0';
++ }
++ getnameinfo((struct sockaddr *)&popd_remoteaddr, salen, hbuf,
++ sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
++ strcat(popd_clienthost, "[");
++ strcat(popd_clienthost, hbuf);
++ strcat(popd_clienthost, "]");
++ salen = sizeof(popd_localaddr);
++ if (getsockname(0, (struct sockaddr *)&popd_localaddr, &salen) == 0) {
++ popd_haveaddr = 1;
++ }
++ }
++#else
+ if (getpeername(0, (struct sockaddr *)&popd_remoteaddr, &salen) == 0 &&
+ popd_remoteaddr.sin_family == AF_INET) {
+ hp = gethostbyaddr((char *)&popd_remoteaddr.sin_addr,
+@@ -257,6 +299,7 @@
+ popd_haveaddr = 1;
+ }
+ }
++#endif
+
+ /* other params should be filled in */
+ if (sasl_server_new("pop", config_servername, NULL,
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/imap/pop3proxyd.c cyrus-imapd-2.0.12/imap/pop3proxyd.c
+--- cyrus-imapd-2.0.12.orig/imap/pop3proxyd.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/imap/pop3proxyd.c Thu Apr 26 17:11:38 2001
+@@ -91,6 +91,15 @@
+ #endif /* HAVE_KRB */
+ static int kflag = 0;
+
++#ifdef INET6
++#ifndef NI_WITHSCOPEID
++#define NI_WITHSCOPEID 0
++#endif
++#ifndef HAVE_SS_FAMILY
++#define ss_family __ss_family
++#endif
++#endif
++
+ extern int optind;
+ extern char *optarg;
+ extern int opterr;
+@@ -106,9 +115,17 @@
+ sasl_conn_t *popd_saslconn; /* the sasl connection context */
+
+ char *popd_userid = 0;
++#ifdef INET6
++struct sockaddr_storage popd_localaddr, popd_remoteaddr;
++#else
+ struct sockaddr_in popd_localaddr, popd_remoteaddr;
++#endif
+ int popd_haveaddr = 0;
++#ifdef INET6
++char popd_clienthost[NI_MAXHOST*2+1] = "[local]";
++#else
+ char popd_clienthost[250] = "[local]";
++#endif
+ struct protstream *popd_out, *popd_in;
+ int popd_starttls_done = 0;
+ int popd_auth_done = 0;
+@@ -193,6 +210,9 @@
+ struct hostent *hp;
+ int timeout;
+ sasl_security_properties_t *secprops=NULL;
++#ifdef INET6
++ char hbuf[NI_MAXHOST];
++#endif
+
+ signals_poll();
+
+@@ -221,6 +241,28 @@
+
+ /* Find out name of client host */
+ salen = sizeof(popd_remoteaddr);
++#ifdef INET6
++ if (getpeername(0, (struct sockaddr *)&popd_remoteaddr, &salen) == 0 &&
++ (popd_remoteaddr.ss_family == AF_INET ||
++ popd_remoteaddr.ss_family == AF_INET6)) {
++ if (getnameinfo((struct sockaddr *)&popd_remoteaddr, salen,
++ hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) == 0) {
++ strncpy(popd_clienthost, hbuf, sizeof(hbuf));
++ }
++ else {
++ popd_clienthost[0] = '\0';
++ }
++ getnameinfo((struct sockaddr *)&popd_remoteaddr, salen, hbuf,
++ sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
++ strcat(popd_clienthost, "[");
++ strcat(popd_clienthost, hbuf);
++ strcat(popd_clienthost, "]");
++ salen = sizeof(popd_localaddr);
++ if (getsockname(0, (struct sockaddr *)&popd_localaddr, &salen) == 0) {
++ popd_haveaddr = 1;
++ }
++ }
++#else
+ if (getpeername(0, (struct sockaddr *)&popd_remoteaddr, &salen) == 0 &&
+ popd_remoteaddr.sin_family == AF_INET) {
+ hp = gethostbyaddr((char *)&popd_remoteaddr.sin_addr,
+@@ -239,6 +281,7 @@
+ popd_haveaddr = 1;
+ }
+ }
++#endif
+
+ /* other params should be filled in */
+ if (sasl_server_new("pop", config_servername, NULL,
+@@ -1023,11 +1066,19 @@
+ {
+ int r;
+ sasl_security_properties_t *secprops = NULL;
++#ifdef INET6
++ struct sockaddr *saddr_l =
++ (struct sockaddr *) malloc(sizeof(struct sockaddr_storage));
++ struct sockaddr *saddr_r =
++ (struct sockaddr *) malloc(sizeof(struct sockaddr_storage));
++ socklen_t addrsize = sizeof(struct sockaddr_storage);
++#else
+ struct sockaddr_in *saddr_l =
+ (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
+ struct sockaddr_in *saddr_r =
+ (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
+ socklen_t addrsize = sizeof(struct sockaddr_in);
++#endif
+ sasl_callback_t *cb;
+ char buf[2048];
+ char optstr[128];
+@@ -1064,7 +1115,11 @@
+ r = sasl_setprop(backend_saslconn, SASL_IP_REMOTE, saddr_r);
+ if (r != SASL_OK) return r;
+
++#ifdef INET6
++ addrsize=sizeof(struct sockaddr_storage);
++#else
+ addrsize=sizeof(struct sockaddr_in);
++#endif
+ if (getsockname(backend_sock, (struct sockaddr *)saddr_l,&addrsize)!=0)
+ return SASL_FAIL;
+ r = sasl_setprop(backend_saslconn, SASL_IP_LOCAL, saddr_l);
+@@ -1136,8 +1191,12 @@
+
+ static void openproxy(void)
+ {
++#ifdef INET6
++ struct addrinfo hints, *res0 = NULL, *res;
++#else
+ struct hostent *hp;
+ struct sockaddr_in sin;
++#endif
+ char inboxname[MAX_MAILBOX_PATH];
+ int r;
+ char *server;
+@@ -1148,6 +1207,28 @@
+ r = mboxlist_lookup(inboxname, &server, NULL, NULL);
+ if (!r) fatal("couldn't find backend server", EC_CONFIG);
+
++#ifdef INET6
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = PF_UNSPEC;
++ hints.ai_socktype = SOCK_STREAM;
++ if (getaddrinfo(server, "110", &hints, &res0))
++ fatal("getaddrinfo failed", EC_CONFIG);
++ for (res = res0; res; res = res->ai_next) {
++ backend_sock = socket(res->ai_family, res->ai_socktype,
++ res->ai_protocol);
++ if (backend_sock < 0)
++ continue;
++ if (connect(backend_sock, res->ai_addr, res->ai_addrlen) >= 0)
++ break;
++ close(backend_sock);
++ backend_sock = -1;
++ }
++ freeaddrinfo(res0);
++ if (backend_sock < 0) {
++ syslog(LOG_ERR, "connect() failed: %m");
++ fatal("connect failed", 1);
++ }
++#else
+ hp = gethostbyname(server);
+ if (!hp) fatal("gethostbyname failed", EC_CONFIG);
+ sin.sin_family = AF_INET;
+@@ -1162,6 +1243,7 @@
+ syslog(LOG_ERR, "connect() failed: %m");
+ fatal("connect failed", 1);
+ }
++#endif
+
+ backend_in = prot_new(backend_sock, 0);
+ backend_out = prot_new(backend_sock, 1);
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/imap/proxyd.c cyrus-imapd-2.0.12/imap/proxyd.c
+--- cyrus-imapd-2.0.12.orig/imap/proxyd.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/imap/proxyd.c Thu Apr 26 17:11:38 2001
+@@ -93,6 +93,15 @@
+ #include "pushstats.h"
+ #include "telemetry.h"
+
++#ifdef INET6
++#ifndef NI_WITHSCOPEID
++#define NI_WITHSCOPEID 0
++#endif
++#ifndef HAVE_SS_FAMILY
++#define ss_family __ss_family
++#endif
++#endif
++
+ /* PROXY STUFF */
+ /* we want a list of our outgoing connections here and which one we're
+ currently piping */
+@@ -103,7 +112,11 @@
+
+ struct backend {
+ char *hostname;
++#ifdef INET6
++ struct sockaddr_storage addr;
++#else
+ struct sockaddr_in addr;
++#endif
+ int sock;
+ struct prot_waitevent *timeout;
+
+@@ -155,9 +168,17 @@
+ char *proxyd_userid;
+ struct auth_state *proxyd_authstate = 0;
+ int proxyd_userisadmin;
++#ifdef INET6
++struct sockaddr_storage proxyd_localaddr, proxyd_remoteaddr;
++#else
+ struct sockaddr_in proxyd_localaddr, proxyd_remoteaddr;
++#endif
+ int proxyd_haveaddr = 0;
++#ifdef INET6
++char proxyd_clienthost[NI_MAXHOST*2+1] = "[local]";
++#else
+ char proxyd_clienthost[250] = "[local]";
++#endif
+ struct protstream *proxyd_out, *proxyd_in;
+ time_t proxyd_logtime;
+ static char shutdownfilename[1024];
+@@ -552,11 +573,19 @@
+ {
+ int r;
+ sasl_security_properties_t *secprops = NULL;
++#ifdef INET6
++ struct sockaddr *saddr_l =
++ (struct sockaddr *) malloc(sizeof(struct sockaddr_storage));
++ struct sockaddr *saddr_r =
++ (struct sockaddr *) malloc(sizeof(struct sockaddr_storage));
++ socklen_t addrsize = sizeof(struct sockaddr_storage);
++#else
+ struct sockaddr_in *saddr_l =
+ (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
+ struct sockaddr_in *saddr_r =
+ (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
+ socklen_t addrsize = sizeof(struct sockaddr_in);
++#endif
+ sasl_callback_t *cb;
+ char mytag[128];
+ char buf[2048];
+@@ -594,7 +623,11 @@
+ r = sasl_setprop(s->saslconn, SASL_IP_REMOTE, saddr_r);
+
+ if (r == SASL_OK) {
++#ifdef INET6
++ addrsize=sizeof(struct sockaddr_storage);
++#else
+ addrsize=sizeof(struct sockaddr_in);
++#endif
+ if (getsockname(s->sock, (struct sockaddr *)saddr_l,&addrsize)!=0)
+ return SASL_FAIL;
+ r = sasl_setprop(s->saslconn, SASL_IP_LOCAL, saddr_l);
+@@ -754,11 +787,14 @@
+ }
+
+ if (!ret) {
++#ifndef INET6
+ struct hostent *hp;
++#endif
+
+ ret = xmalloc(sizeof(struct backend));
+ memset(ret, 0, sizeof(struct backend));
+ ret->hostname = xstrdup(server);
++#ifndef INET6
+ if ((hp = gethostbyname(server)) == NULL) {
+ syslog(LOG_ERR, "gethostbyname(%s) failed: %m", server);
+ free(ret);
+@@ -767,15 +803,45 @@
+ ret->addr.sin_family = AF_INET;
+ memcpy(&ret->addr.sin_addr, hp->h_addr, hp->h_length);
+ ret->addr.sin_port = htons(143);
++#endif
+
+ ret->timeout = NULL;
+ }
+
+ if (!ret->timeout) {
+ /* need to (re)establish connection to server or create one */
+- int sock;
++ int sock = -1;
+ int r;
+-
++#ifdef INET6
++ int err;
++ struct addrinfo hints, *res0 = NULL, *res;
++
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = PF_UNSPEC;
++ hints.ai_socktype = SOCK_STREAM;
++ err = getaddrinfo(server, "143", &hints, &res0);
++ if (err) {
++ syslog(LOG_ERR, "getaddrinfo(%s) failed: %s",
++ server, gai_strerror(err));
++ free(ret);
++ return NULL;
++ }
++ for (res = res0; res; res = res->ai_next) {
++ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
++ if (sock < 0)
++ continue;
++ if (connect(sock, res->ai_addr, res->ai_addrlen) >= 0)
++ break;
++ close(sock);
++ sock = -1;
++ }
++ freeaddrinfo(res0);
++ if (sock < 0) {
++ syslog(LOG_ERR, "connect(%s) failed: %m", server);
++ free(ret);
++ return NULL;
++ }
++#else
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ syslog(LOG_ERR, "socket() failed: %m");
+ free(ret);
+@@ -787,6 +853,7 @@
+ free(ret);
+ return NULL;
+ }
++#endif
+
+ ret->in = prot_new(sock, 0);
+ ret->out = prot_new(sock, 1);
+@@ -1043,6 +1110,9 @@
+ int timeout;
+ sasl_security_properties_t *secprops = NULL;
+ sasl_external_properties_t extprops;
++#ifdef INET6
++ char hbuf[NI_MAXHOST];
++#endif
+
+ signals_poll();
+
+@@ -1079,6 +1149,29 @@
+
+ /* Find out name of client host */
+ salen = sizeof(proxyd_remoteaddr);
++#ifdef INET6
++ if (getpeername(0, (struct sockaddr *)&proxyd_remoteaddr, &salen) == 0 &&
++ (proxyd_remoteaddr.ss_family == AF_INET ||
++ proxyd_remoteaddr.ss_family == AF_INET6)) {
++ if (getnameinfo((struct sockaddr *)&proxyd_remoteaddr, salen,
++ hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) == 0) {
++ strncpy(proxyd_clienthost, hbuf, sizeof(hbuf));
++ }
++ else {
++ proxyd_clienthost[0] = '\0';
++ }
++ getnameinfo((struct sockaddr *)&proxyd_remoteaddr, salen, hbuf,
++ sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
++ strcat(proxyd_clienthost, "[");
++ strcat(proxyd_clienthost, hbuf);
++ strcat(proxyd_clienthost, "]");
++ salen = sizeof(proxyd_localaddr);
++ if (getsockname(0, (struct sockaddr *)&proxyd_localaddr,
++ &salen) == 0) {
++ proxyd_haveaddr = 1;
++ }
++ }
++#else
+ if (getpeername(0, (struct sockaddr *)&proxyd_remoteaddr, &salen) == 0 &&
+ proxyd_remoteaddr.sin_family == AF_INET) {
+ hp = gethostbyaddr((char *)&proxyd_remoteaddr.sin_addr,
+@@ -1098,6 +1191,7 @@
+ proxyd_haveaddr = 1;
+ }
+ }
++#endif
+
+ /* create the SASL connection */
+ /* Make a SASL connection and setup some properties for it */
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/imtest/imtest.c cyrus-imapd-2.0.12/imtest/imtest.c
+--- cyrus-imapd-2.0.12.orig/imtest/imtest.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/imtest/imtest.c Thu Apr 26 17:11:38 2001
+@@ -571,13 +571,23 @@
+ * Initialize SASL and set necessary options
+ */
+
++#ifdef INET6
++static int init_sasl(char *serverFQDN, char *port, int minssf, int maxssf)
++#else
+ static int init_sasl(char *serverFQDN, int port, int minssf, int maxssf)
++#endif
+ {
+ int saslresult;
+ sasl_security_properties_t *secprops=NULL;
++#ifdef INET6
++ socklen_t addrsize=sizeof(struct sockaddr_storage);
++ struct sockaddr *saddr_l=malloc(sizeof(struct sockaddr_storage));
++ struct sockaddr *saddr_r=malloc(sizeof(struct sockaddr_storage));
++#else
+ socklen_t addrsize=sizeof(struct sockaddr_in);
+ struct sockaddr_in *saddr_l=malloc(sizeof(struct sockaddr_in));
+ struct sockaddr_in *saddr_r=malloc(sizeof(struct sockaddr_in));
++#endif
+
+ /* attempt to start sasl */
+ saslresult=sasl_client_init(callbacks);
+@@ -607,7 +617,11 @@
+ if (sasl_setprop(conn, SASL_IP_REMOTE, saddr_r)!=SASL_OK)
+ return IMTEST_FAIL;
+
++#ifdef INET6
++ addrsize=sizeof(struct sockaddr_storage);
++#else
+ addrsize=sizeof(struct sockaddr_in);
++#endif
+ if (getsockname(sock,(struct sockaddr *)saddr_l,&addrsize)!=0)
+ return IMTEST_FAIL;
+
+@@ -852,6 +866,37 @@
+ }
+
+ /* initialize the network */
++#ifdef INET6
++int init_net(char *serverFQDN, char *port)
++{
++ struct addrinfo hints, *res0 = NULL, *res;
++ int err;
++
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = PF_UNSPEC;
++ hints.ai_socktype = SOCK_STREAM;
++ hints.ai_flags = AI_CANONNAME;
++ if ((err = getaddrinfo(serverFQDN, port, &hints, &res0)) != 0) {
++ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
++ return IMTEST_FAIL;
++ }
++ if (res0->ai_canonname)
++ strncpy(serverFQDN, res0->ai_canonname, 1023);
++ for (res = res0; res; res = res->ai_next) {
++ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
++ if (sock < 0)
++ continue;
++ if (connect(sock, res->ai_addr, res->ai_addrlen) >= 0)
++ break;
++ close(sock);
++ sock = -1;
++ }
++ freeaddrinfo(res0);
++ if (sock < 0) {
++ perror("connect");
++ return IMTEST_FAIL;
++ }
++#else
+ int init_net(char *serverFQDN, int port)
+ {
+ struct sockaddr_in addr;
+@@ -876,6 +921,7 @@
+ perror("connect");
+ return IMTEST_FAIL;
+ }
++#endif
+
+ return IMTEST_OK;
+ }
+@@ -1179,7 +1225,9 @@
+ char *tls_keyfile="";
+ char *port = "imap";
+ struct servent *serv;
++#ifndef INET6
+ int servport;
++#endif
+ int run_stress_test=0;
+ int dotls=0;
+ int server_supports_tls;
+@@ -1243,6 +1291,15 @@
+ /* last arg is server name */
+ strncpy(servername, argv[optind], 1023);
+
++#ifdef INET6
++ if (init_net(servername, port) != IMTEST_OK) {
++ imtest_fatal("Network initialization");
++ }
++
++ if (init_sasl(servername, port, minssf, maxssf) != IMTEST_OK) {
++ imtest_fatal("SASL initialization");
++ }
++#else
+ /* map port -> num */
+ serv = getservbyname(port, "tcp");
+ if (serv == NULL) {
+@@ -1258,6 +1315,7 @@
+ if (init_sasl(servername, servport, minssf, maxssf) != IMTEST_OK) {
+ imtest_fatal("SASL initialization");
+ }
++#endif
+
+ /* set up the prot layer */
+ pin = prot_new(sock, 0);
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/lib/imclient.c cyrus-imapd-2.0.12/lib/imclient.c
+--- cyrus-imapd-2.0.12.orig/lib/imclient.c Sat Feb 17 21:19:40 2001
++++ cyrus-imapd-2.0.12/lib/imclient.c Thu Apr 26 17:11:38 2001
+@@ -213,13 +213,39 @@
+ const char *port,
+ sasl_callback_t *cbs)
+ {
+- int s;
++ int s = -1;
++#ifdef INET6
++ struct addrinfo hints, *res0 = NULL, *res;
++ int err;
++#else
+ struct hostent *hp;
+ struct servent *sp;
+ struct sockaddr_in addr;
++#endif
+ static struct imclient zeroimclient;
+ int saslresult;
+
++#ifdef INET6
++ if (!port)
++ port = "143";
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = PF_UNSPEC;
++ hints.ai_socktype = SOCK_STREAM;
++ hints.ai_flags = AI_CANONNAME;
++ if (getaddrinfo(host, port, &hints, &res0))
++ return -1;
++ for (res = res0; res; res = res->ai_next) {
++ s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
++ if (s < 0)
++ continue;
++ if (connect(s, res->ai_addr, res->ai_addrlen) >= 0)
++ break;
++ close(s);
++ s = -1;
++ }
++ if (s < 0)
++ return errno;
++#else
+ hp = gethostbyname(host);
+ if (!hp) return -1;
+
+@@ -242,13 +268,20 @@
+ if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ return errno;
+ }
++#endif
+ /* nonblock(s, 1); */
+ *imclient = (struct imclient *)xmalloc(sizeof(struct imclient));
+ **imclient = zeroimclient;
+ (*imclient)->fd = s;
+ (*imclient)->saslconn = NULL;
+ (*imclient)->saslcompleted = 0;
++#ifdef INET6
++ (*imclient)->servername = xstrdup(res0->ai_canonname ?
++ res0->ai_canonname : host);
++ freeaddrinfo(res0);
++#else
+ (*imclient)->servername = xstrdup(hp->h_name);
++#endif
+ (*imclient)->outptr = (*imclient)->outstart = (*imclient)->outbuf;
+ (*imclient)->outleft = (*imclient)->maxplain = sizeof((*imclient)->outbuf);
+ imclient_addcallback(*imclient,
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/master/master.c cyrus-imapd-2.0.12/master/master.c
+--- cyrus-imapd-2.0.12.orig/master/master.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/master/master.c Thu Apr 26 17:11:38 2001
+@@ -241,6 +241,22 @@
+ return port;
+ }
+
++char *parse_host(char *listen)
++{
++ char *cp;
++
++ /* do we have a hostname, or IP number? */
++ /* XXX are brackets necessary, like for IPv6 later? */
++ if (*listen == '[') {
++ listen++; /* skip first bracket */
++ if ((cp = strrchr(listen,']')) != NULL) {
++ *cp = '\0';
++ }
++ }
++ return listen;
++}
++
++#ifndef INET6
+ /* set sin_port accordingly. return of 0 indicates failure. */
+ int resolve_port(char *port, struct service *s, struct sockaddr_in *sin)
+ {
+@@ -265,21 +281,14 @@
+ int resolve_host(struct service *s, struct sockaddr_in *sin)
+ {
+ struct hostent *hp;
+- char *cp;
++ char *listen_addr;
+
+- /* do we have a hostname, or IP number? */
+- /* XXX are brackets necessary, like for IPv6 later? */
+- if (*s->listen == '[') {
+- s->listen++; /* skip first bracket */
+- if ((cp = strrchr(s->listen,']')) != NULL) {
+- *cp = '\0';
+- }
+- }
+- sin->sin_addr.s_addr = inet_addr(s->listen);
++ listen_addr = parse_host(s->listen);
++ sin->sin_addr.s_addr = inet_addr(listen_addr);
+ if ((sin->sin_addr.s_addr == INADDR_NONE) || (sin->sin_addr.s_addr == 0)) {
+ /* looks like it isn't an IP address, so look up the host */
+- if ((hp = gethostbyname(s->listen)) == 0) {
+- syslog(LOG_INFO, "host not found: %s", s->listen);
++ if ((hp = gethostbyname(listen_addr)) == 0) {
++ syslog(LOG_INFO, "host not found: %s", listen_addr);
+ s->exec = NULL;
+ return 0;
+ }
+@@ -297,17 +306,146 @@
+ }
+ return 1;
+ }
++#endif
+
+ void service_create(struct service *s)
+ {
++#ifdef INET6
++ struct service service0, service;
++ struct addrinfo hints, *res0, *res;
++ struct sockaddr_storage sin;
++ int error, nsocket = 0;
++ char *listen_addr;
++#else
+ struct sockaddr_in sin;
+- struct sockaddr_un sunsock;
+ struct sockaddr *sa;
++ int salen;
++#endif
++ struct sockaddr_un sunsock;
+ mode_t oldumask;
+- int on = 1, salen;
++ int on = 1;
+ int r;
+ char *port;
+
++#ifdef INET6
++ if (s->socket > 0)
++ return; /* service is already activated */
++
++ if (s->listen[0] == '/') { /* unix socket */
++ res0 = (struct addrinfo *)malloc(sizeof(struct addrinfo));
++ if (!res0)
++ fatal("out of memory", EX_UNAVAILABLE);
++ memset(res0, 0, sizeof(struct addrinfo));
++ res0->ai_flags = AI_PASSIVE;
++ res0->ai_family = PF_UNIX;
++ res0->ai_socktype = SOCK_STREAM;
++ res0->ai_addr = (struct sockaddr *)&sunsock;
++ res0->ai_addrlen = sizeof(sunsock.sun_family) + strlen(s->listen) + 1;
++#ifdef SIN6_LEN
++ res0->ai_addrlen += sizeof(sunsock.sun_len);
++ sunsock.sun_len = res0->ai_addrlen;
++#endif
++ sunsock.sun_family = AF_UNIX;
++ strcpy(sunsock.sun_path, s->listen);
++ unlink(s->listen);
++ } else { /* inet socket */
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_flags = AI_PASSIVE;
++ hints.ai_family = PF_UNSPEC;
++ if (!strcmp(s->proto, "tcp"))
++ hints.ai_socktype = SOCK_STREAM;
++ else if (!strcmp(s->proto, "udp"))
++ hints.ai_socktype = SOCK_DGRAM;
++ else {
++ syslog(LOG_INFO, "invalid proto '%s', disabling %s",
++ s->proto, s->name);
++ s->exec = NULL;
++ return;
++ }
++ if ((port = parse_listen(s->listen)) == NULL) {
++ /* s->listen IS the port */
++ port = s->listen;
++ listen_addr = NULL;
++ } else {
++ /* s->listen is now just the address */
++ listen_addr = parse_host(s->listen);
++ if (*listen_addr == '\0')
++ listen_addr = NULL;
++ }
++ error = getaddrinfo(listen_addr, port, &hints, &res0);
++ if (error) {
++ syslog(LOG_INFO, "%s, disabling %s", gai_strerror(error), s->name);
++ s->exec = NULL;
++ return;
++ }
++ }
++
++ memcpy(&service0, s, sizeof(struct service));
++
++ for (res = res0; res; res = res->ai_next) {
++ if (s->socket > 0) {
++ memcpy(&service, &service0, sizeof(struct service));
++ s = &service;
++ }
++
++ s->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
++ if (s->socket < 0)
++ continue;
++
++ /* allow reuse of address */
++ setsockopt(s->socket, SOL_SOCKET, SO_REUSEADDR,
++ (void *) &on, sizeof(on));
++
++#if defined(IPV6_BINDV6ONLY) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
++ if (res->ai_family == AF_INET6)
++ setsockopt(s->socket, IPPROTO_IPV6, IPV6_BINDV6ONLY,
++ (void *) &on, sizeof(on));
++#endif
++
++ oldumask = umask((mode_t) 0); /* for linux */
++ r = bind(s->socket, res->ai_addr, res->ai_addrlen);
++ umask(oldumask);
++ if (r < 0) {
++ close(s->socket);
++ s->socket = -1;
++ continue;
++ }
++
++ if (s->listen[0] == '/') { /* unix socket */
++ /* for DUX, where this isn't the default.
++ (harmlessly fails on some systems) */
++ chmod(s->listen, (mode_t) 0777);
++ }
++
++ if (listen(s->socket, listen_queue_backlog) < 0) {
++ syslog(LOG_ERR, "unable to listen to %s socket: %m", s->name);
++ close(s->socket);
++ s->socket = -1;
++ continue;
++ }
++
++ s->ready_workers = 0;
++
++ get_statsock(s->stat);
++
++ if (s == &service) {
++ if (nservices == allocservices) {
++ Services = realloc(Services,
++ (allocservices+=5) * sizeof(struct service));
++ if (!Services) fatal("out of memory", EX_UNAVAILABLE);
++ }
++ memcpy(&Services[nservices++], s, sizeof(struct service));
++ }
++ nsocket++;
++ }
++ if (res0)
++ freeaddrinfo(res0);
++ if (nsocket <= 0) {
++ syslog(LOG_ERR, "unable to create %s listener socket: %m", s->name);
++ s->exec = NULL;
++ return;
++ }
++#else
+ memset(&sin, 0, sizeof(sin));
+
+ if (s->listen[0] == '/') { /* unix socket */
+@@ -379,6 +517,7 @@
+ s->ready_workers = 0;
+
+ get_statsock(s->stat);
++#endif
+ }
+
+ void run_startup(char **cmd)
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/master/service.c cyrus-imapd-2.0.12/master/service.c
+--- cyrus-imapd-2.0.12.orig/master/service.c Thu Apr 26 17:10:59 2001
++++ cyrus-imapd-2.0.12/master/service.c Thu Apr 26 17:11:38 2001
+@@ -95,12 +95,16 @@
+ static int libwrap_ask(struct request_info *r, int fd)
+ {
+ int a;
++#ifdef INET6
++ struct sockaddr_storage sin;
++#else
+ struct sockaddr_in sin;
++#endif
+ socklen_t len = sizeof(sin);
+
+ /* is this a connection from the local host? */
+ if (getpeername(fd, (struct sockaddr *) &sin, &len) == 0) {
+- if (sin.sin_family == AF_UNIX) {
++ if (((struct sockaddr *)&sin)->sa_family == AF_UNIX) {
+ return 1;
+ }
+ }
+diff -ruN --exclude *.orig --exclude configure cyrus-imapd-2.0.12.orig/timsieved/timsieved.c cyrus-imapd-2.0.12/timsieved/timsieved.c
+--- cyrus-imapd-2.0.12.orig/timsieved/timsieved.c Mon Feb 19 19:05:22 2001
++++ cyrus-imapd-2.0.12/timsieved/timsieved.c Thu Apr 26 17:11:38 2001
+@@ -81,19 +81,36 @@
+
+ #include "auth.h"
+
++#ifdef INET6
++#ifndef NI_WITHSCOPEID
++#define NI_WITHSCOPEID 0
++#endif
++#ifndef HAVE_SS_FAMILY
++#define ss_family __ss_family
++#endif
++#endif
+
+ sasl_conn_t *sieved_saslconn; /* the sasl connection context */
+
+ struct auth_state *sieved_authstate = 0;
+
++#ifdef INET6
++struct sockaddr_storage sieved_localaddr;
++struct sockaddr_storage sieved_remoteaddr;
++#else
+ struct sockaddr_in sieved_localaddr;
+ struct sockaddr_in sieved_remoteaddr;
++#endif
+
+ struct protstream *sieved_out;
+ struct protstream *sieved_in;
+
+ int sieved_haveaddr = 0;
++#ifdef INET6
++char sieved_clienthost[NI_MAXHOST*2+1] = "[local]";
++#else
+ char sieved_clienthost[250] = "[local]";
++#endif
+
+ int sieved_userisadmin;
+
+@@ -231,6 +248,9 @@
+ int timeout;
+ int secflags = 0;
+ sasl_security_properties_t *secprops = NULL;
++#ifdef INET6
++ char hbuf[NI_MAXHOST];
++#endif
+
+ /* set up the prot streams */
+ sieved_in = prot_new(0, 0);
+@@ -248,6 +268,28 @@
+
+ /* Find out name of client host */
+ salen = sizeof(sieved_remoteaddr);
++#ifdef INET6
++ if (getpeername(0, (struct sockaddr *)&sieved_remoteaddr, &salen) == 0 &&
++ (sieved_remoteaddr.ss_family == AF_INET ||
++ sieved_remoteaddr.ss_family == AF_INET6)) {
++ if (getnameinfo((struct sockaddr *)&sieved_remoteaddr, salen,
++ hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) == 0) {
++ strncpy(sieved_clienthost, hbuf, sizeof(hbuf));
++ }
++ else {
++ sieved_clienthost[0] = '\0';
++ }
++ getnameinfo((struct sockaddr *)&sieved_remoteaddr, salen, hbuf,
++ sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
++ strcat(sieved_clienthost, "[");
++ strcat(sieved_clienthost, hbuf);
++ strcat(sieved_clienthost, "]");
++ salen = sizeof(sieved_localaddr);
++ if (getsockname(0, (struct sockaddr *)&sieved_localaddr, &salen) == 0) {
++ sieved_haveaddr = 1;
++ }
++ }
++#else
+ if (getpeername(0, (struct sockaddr *)&sieved_remoteaddr, &salen) == 0 &&
+ sieved_remoteaddr.sin_family == AF_INET) {
+ if ((hp = gethostbyaddr((char *)&sieved_remoteaddr.sin_addr,
+@@ -266,6 +308,7 @@
+ sieved_haveaddr = 1;
+ }
+ }
++#endif
+
+ /* set the SASL allocation functions */
+ sasl_set_alloc((sasl_malloc_t *) &xmalloc,