$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 <popper.h>
 
+#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
 	/* 
