--- lib/hostname.c.orig	Wed Aug 16 09:38:40 2000
+++ lib/hostname.c	Wed Aug 30 13:27:33 2000
@@ -17,6 +17,11 @@
 #define S5_HOSTLIST_SIZE    256
 #define S5_HOSTALIASES_SIZE 16
  
+/* wrapper for KAME-special getnameinfo() */
+#ifndef NI_WITHSCOPEID
+#define	NI_WITHSCOPEID	0
+#endif
+
 struct hostEntry {
     char name[S5_HOSTNAME_SIZE];
 };
@@ -398,6 +403,129 @@
     lsInWrapFunction = 0;
     lsInWrapHostname = 0;
     return &h;
+}
+#endif
+
+#if defined(HAVE_GETADDRINFO) && defined(HAVE_GETNAMEINFO)
+/* wrapper around the getaddrinfo call.                                      */
+/* similar to getaddrinfo() except for:                                      */
+/* *** if getaddrinfo() fails, then it returns a pointer to a addrinfo       */
+/*     structure filled with a special value, so that SOCKSxxxxxx() will     */
+/*     realize that this host was unresolved and fill in the protocol        */
+/*     accordingly...                                                        */
+/*                                                                           */
+/* returns an error number on failure; 0 on success   */
+int LIBPREFIX(getaddrinfo)(const char *hostname, const char *servname,
+			    const struct addrinfo *hints,
+			    struct addrinfo **aip) {
+    static char numaddrbuf[MAXHOSTNAMELEN];
+    static struct addrinfo *ai;
+    char *local, *fake;
+    int error = 0, i;
+    int addrlen, namelen, family;
+
+#ifdef FOR_SHARED_LIBRARY
+    if (lsInRLDFunctions || lsInWrapFunction || lsInWrapHostname) return REAL(getaddrinfo)(hostname, servname, hints, aip);
+#endif
+
+    lsInWrapFunction = 1;
+    lsInWrapHostname = 1;
+    LIBPREFIX2(init)("libsocks5");
+    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS getaddrinfo: looking up %s", hostname);
+
+    fake  = getenv("SOCKS5_FAKEALLHOSTS");
+    local = getenv("SOCKS5_LOCALDNSONLY");
+
+    if (!fake &&
+	(error = REAL(getaddrinfo)(hostname, servname, hints, aip)) == NULL) {
+        getnameinfo((*aip)->ai_addr, (*aip)->ai_addrlen, numaddrbuf,
+		    sizeof(numaddrbuf) - 1, NULL, 0,
+		    NI_NUMERICHOST|NI_WITHSCOPEID);
+	S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS getaddrinfo: REAL: %s", numaddrbuf);
+
+        lsInWrapFunction = 0;
+        lsInWrapHostname = 0;
+	return error;
+    }
+
+    /* If your DNS is the same as the socks server, don't fake a correct     */
+    /* lookup when you know it won't work...                                 */
+    if (local) {
+	S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS getaddrinfo: REAL: Fake not configured");
+        lsInWrapFunction = 0;
+        lsInWrapHostname = 0;
+	return (error != 0) ? error : EAI_FAIL;
+    }
+
+    /* Fill in some UNRESOLVED values and let the daemon resolve it          */
+    if ((i = GetFakeHost(hostname)) <= 0) {
+        S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "SOCKS getaddrinfo: Get fake host failed");
+        lsInWrapFunction = 0;
+        lsInWrapHostname = 0;
+	return (error != 0) ? error : EAI_FAIL;
+    }
+
+    /* create fake for AF_INET. AF_INET6 support is not yet */
+    if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) {
+        addrlen = sizeof(struct sockaddr_in);
+	family = AF_INET;
+        ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + addrlen);
+	if (ai == NULL)
+	    return EAI_MEMORY;
+	memcpy(ai, hints, sizeof(struct addrinfo));
+	ai->ai_family = family;
+	ai->ai_addr = (struct sockaddr *)(ai + 1);
+	memset(ai->ai_addr, 0, addrlen);
+	ai->ai_addr->sa_len = addrlen;
+	ai->ai_addrlen = addrlen;
+	ai->ai_addr->sa_family = family;
+	if (servname != NULL) {
+	    struct servent *sp;
+	    const char *p;
+	    int is_number, port;
+
+	    p = servname;
+	    is_number = 1;
+	    while (*p) {
+	        if (!isdigit(*p))
+		    is_number = 0;
+		p++;
+	    }
+	    if (is_number) {
+	        port = htons(atoi(servname));
+		if (port < 0 || port > 65535) {
+		    free(ai);
+		    return EAI_SERVICE;
+		}
+	    } else {
+	        sp = getservbyname(servname, NULL);
+		if (sp == NULL) {
+		    free(ai);
+		    return EAI_SERVICE;
+		}
+	        port = sp->s_port;		
+	    }
+	    ((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
+	}
+	((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr = htonl(i);
+	if ((hints->ai_flags & AI_CANONNAME) != 0) {
+	    ai->ai_canonname = (char *)malloc(strlen(hostname) + 1);
+	    if (ai->ai_canonname == NULL) {
+	        free(ai);
+		return EAI_MEMORY;
+	    }
+	    strncpy(ai->ai_canonname, hostname, strlen(hostname) + 1);
+	}
+    } else
+        return EAI_FAMILY;
+    *aip = ai;
+
+    getnameinfo((*aip)->ai_addr, (*aip)->ai_addrlen, numaddrbuf,
+		sizeof(numaddrbuf) - 1, NULL, 0, NI_NUMERICHOST);
+    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS getaddrinfo: FAKE: %s",  numaddrbuf);
+    lsInWrapFunction = 0;
+    lsInWrapHostname = 0;
+    return 0;
 }
 #endif
 
