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 +#include ], + [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,