$NetBSD: patch-ad,v 1.3 1999/09/15 21:30:59 tron Exp $ --- pop_init.c.orig Fri Jul 10 01:44:07 1998 +++ pop_init.c Wed Sep 15 23:28:18 1999 @@ -44,6 +44,8 @@ #include +#include "sockunion.h" + /* CNS Kerberos IV */ #ifdef KERBEROS AUTH_DAT kdata; @@ -75,9 +77,37 @@ } #endif +char * +sock_ntop(p) + struct sockaddr *p; +{ +#ifdef INET6 + static char ntop_buf[INET6_ADDRSTRLEN]; +#else + static char ntop_buf[INET_ADDRSTRLEN]; +#endif + union sockunion *su; + + su = (union sockunion *)p; + switch (su->su_family) { + case AF_INET: + inet_ntop(su->su_family, &su->su_sin.sin_addr, ntop_buf, + sizeof(ntop_buf)); + return ntop_buf; +#ifdef INET6 + case AF_INET6: + inet_ntop(su->su_family, &su->su_sin6.sin6_addr, ntop_buf, + sizeof(ntop_buf)); + return ntop_buf; +#endif + default: + return "(unsupported AF)"; + } +} + authenticate(p, addr) POP *p; - struct sockaddr_in *addr; + union sockunion *addr; { #ifdef KERBEROS @@ -87,10 +117,10 @@ char version[9]; int auth; - if (p->kerberos) { + if (p->kerberos && addr->su_family == AF_INET) { /*XXX*/ strcpy(instance, "*"); auth = krb_recvauth(0L, 0, &ticket, KERBEROS_SERVICE, instance, - addr, (struct sockaddr_in *) NULL, + (struct sockaddr_in *)addr, (struct sockaddr_in *) NULL, &kdata, "", schedule, version); if (auth != KSUCCESS) { @@ -105,7 +135,7 @@ # ifdef DEBUG if (p->debug) pop_log(p, POP_DEBUG, "%s.%s@%s (%s): ok", kdata.pname, - kdata.pinst, kdata.prealm, inet_ntoa(addr->sin_addr)); + kdata.pinst, kdata.prealm, sock_ntop(addr)); # endif /* DEBUG */ strncpy(p->user, kdata.pname, sizeof(p->user)); @@ -126,7 +156,7 @@ char ** argmessage; { - struct sockaddr_in cs; /* Communication parameters */ + union sockunion cs; /* Communication parameters */ struct hostent * ch; /* Client host information */ int errflag = 0; int c; @@ -272,13 +302,25 @@ /* Save the dotted decimal form of the client's IP address in the POP parameter block */ - p->ipaddr = (char *)strdup(inet_ntoa(cs.sin_addr)); + p->ipaddr = (char *)strdup(sock_ntop(&cs)); /* Save the client's port */ - p->ipport = ntohs(cs.sin_port); + p->ipport = ntohs(cs.su_port); /* Get the canonical name of the host to whom I am speaking */ - ch = gethostbyaddr((char *) &cs.sin_addr, sizeof(cs.sin_addr), AF_INET); + switch (cs.su_family) { + case AF_INET: + ch = gethostbyaddr((char *) &cs.su_sin.sin_addr, sizeof(cs.su_sin.sin_addr), AF_INET); + break; +#ifdef INET6 + case AF_INET6: + ch = gethostbyaddr((char *) &cs.su_sin6.sin6_addr, sizeof(cs.su_sin6.sin6_addr), AF_INET6); + break; +#endif + default: + ch = NULL; + break; + } if (ch == NULL){ pop_log(p,POP_PRIORITY, "(v%s) Unable to get canonical name of client, err = %d", @@ -320,6 +362,7 @@ strncpy(h_name, ch->h_name, sizeof(h_name)); +#ifndef INET6 /* See if the name obtained for the client's IP address returns an address */ if ((ch_again = gethostbyname(h_name)) == NULL) { @@ -336,7 +379,7 @@ /* Look for the client's IP address in the list returned for its name */ for (addrp=ch_again->h_addr_list; *addrp; ++addrp) - if (bcmp(*addrp,&(cs.sin_addr),sizeof(cs.sin_addr)) == 0) break; + if (bcmp(*addrp,&(cs.su_sin.sin_addr),sizeof(cs.su_sin.sin_addr)) == 0) break; if (!*addrp) { pop_log (p,POP_PRIORITY, @@ -345,6 +388,54 @@ p->client = p->ipaddr; } } +#else + { + struct addrinfo hints, *res; + int error; + + p->client = (char *)strdup(ch->h_name); + + /* + * See if the name obtained for the client's IP + * address returns an address + */ + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + error = getaddrinfo(h_name, NULL, &hints, &res); + if (error) { + pop_log(p,POP_PRIORITY, + "Client at \"%s\" resolves to an unknown host name \"%s\"", + p->ipaddr, h_name); + p->client = p->ipaddr; + } else { + for ( ; res; res = res->ai_next) { + if (res->ai_addr->sa_family == AF_INET) { + if (!memcmp(&((struct sockaddr_in *)res->ai_addr)->sin_addr, + &(cs.su_sin.sin_addr), sizeof(cs.su_sin.sin_addr))) { + break; + } + } else if (res->ai_addr->sa_family == AF_INET6) { + if (!memcmp(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, + &(cs.su_sin6.sin6_addr), sizeof(cs.su_sin6.sin6_addr))) { + break; + } + } else { + break; + } + } + + if (!res) { + pop_log (p,POP_PRIORITY, + "Client address \"%s\" not listed for its host name \"%s\"", + p->ipaddr,h_name); + p->client = p->ipaddr; + } + } + } +#endif #ifdef RES_DEFNAMES /*