From owner-freebsd-ports Fri Jul 16 1: 0:36 1999 Delivered-To: freebsd-ports@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id 76E8114FB6 for ; Fri, 16 Jul 1999 01:00:32 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id BAA10349; Fri, 16 Jul 1999 01:00:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from david.siemens.de (david.siemens.de [192.35.17.14]) by hub.freebsd.org (Postfix) with ESMTP id 64BBF15660 for ; Fri, 16 Jul 1999 00:55:05 -0700 (PDT) (envelope-from andre.albsmeier@mchp.siemens.de) Received: from mail1.siemens.de (mail1.siemens.de [139.23.33.14]) by david.siemens.de (8.9.3/8.9.3) with ESMTP id JAA17349 for ; Fri, 16 Jul 1999 09:54:53 +0200 (MET DST) Received: from curry.mchp.siemens.de (curry.mchp.siemens.de [139.25.42.7]) by mail1.siemens.de (8.9.3/8.9.3) with ESMTP id JAA22519 for ; Fri, 16 Jul 1999 09:54:53 +0200 (MET DST) Received: (from daemon@localhost) by curry.mchp.siemens.de (8.9.3/8.9.3) id JAA36012 for ; Fri, 16 Jul 1999 09:54:53 +0200 (CEST) Message-Id: <199907160754.JAA16398@internal> Date: Fri, 16 Jul 1999 09:54:50 +0200 (CEST) From: Andre Albsmeier To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: ports/12660: Fix for gethostbyname2() problem when using socks5 Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 12660 >Category: ports >Synopsis: Fix for gethostbyname2() problem when using socks5 >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-ports >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Jul 16 01:00:01 PDT 1999 >Closed-Date: >Last-Modified: >Originator: Andre Albsmeier >Release: FreeBSD 3.2-STABLE i386 >Organization: >Environment: FreeBSD (any version), socks5 from the ports and a program that uses gethostbyname2() (fetch, whois,...) >Description: When trying to socksify (with runsocks) a program that uses gethostbyname2(), sometimes the program fails. This is due to the following reason: 1. the program calls gethostbyname2() which is not socksified 2. gethostbyname2() starts his work and calls other functions that are socksified (e.g. sendto) 3. sendto (from the sockslib) now starts its work and, as part of that, itself does a gethostbyname(). 4. gethostbyname() from libc does nothing more than calling gethostbyname2(). 5. Now we have entered gethostbyname2() again and that fails... >How-To-Repeat: As I said above, the program not always fails. I can make it fail here when I have only one nameserver in /etc/resolv.conf. With three nameservers (even if they are the same), it works. I could make it fail by running "runsocks whois blahblah" with only one nameserver in /etc/resolv.conf. >Fix: I have tried to implement the gethostbyname2() call the same way as gethostbyname() is done in the sockslib. In case socks5 is configured to fake DNS calls, we call the daemon if the af argument is AF_INET. If we don't fake DNS calls, we call the original gethostbyname2() function. *** ./lib/rld.c.ORI Thu Jul 15 21:48:13 1999 --- ./lib/rld.c Thu Jul 15 21:34:27 1999 *************** *** 183,188 **** --- 183,203 ---- return hp; } + struct hostent *REAL(gethostbyname2)(const char *name, int af) { + struct hostent *hp; + static void *func = NULL; + + S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "RLD: gethostbyname2: %s %d", name, af); + GetOriginalFunc(&func, "_gethostbyname2", TRY_LIBC | TRY_LIBNSL | TRY_LIBRESOLV); + if (!func || func == (void *)-1) return NULL; + + lsInRLDFunctions = 1; + hp = ((struct hostent *(*)P((const char *, int)))func)(name, af); + lsInRLDFunctions = 0; + S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "RLD: gethostbyname2 results: %s %s", name, hp?hp->h_name:"???"); + return hp; + } + int REAL(getpeername) (S5IOHandle sd, ss *sa, int *slen) { GETFUNC("_getpeername", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, ss *, int *))), (sd, sa, slen), int); } *** ./lib/hostname.c.ORI Thu Jul 15 21:48:52 1999 --- ./lib/hostname.c Thu Jul 15 21:43:28 1999 *************** *** 312,317 **** --- 312,409 ---- return &h; } + /* wrapper around the gethostbyname2 call. */ + /* similar to gethostbyname2() except for: */ + /* *** if gethostbyname2() fails, then it returns a pointer to a hostent */ + /* structure filled with a special value, so that SOCKSxxxxxx() will */ + /* realize that this host was unresolved and fill in the protocol */ + /* accordingly... */ + /* */ + /* returns a pointer to a gethostent structure on success; NULL on failure */ + struct hostent *LIBPREFIX(gethostbyname2)(const char *name, int af) { + static struct in_addr special_addr, *my_addr_list[S5_HOSTLIST_SIZE+1]; + static char my_name[MAXNAMELEN], *my_aliases[S5_HOSTALIASES_SIZE+1]; + static struct hostent h; + struct hostent *hp; + char *local, *fake; + int hlen, i; + + #ifdef FOR_SHARED_LIBRARY + if (lsInRLDFunctions || lsInWrapFunction || lsInWrapHostname) return REAL(gethostbyname2)(name,af); + #endif + + lsInWrapFunction = 1; + lsInWrapHostname = 1; + LIBPREFIX2(init)("libsocks5"); + S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS gethostbyname2: looking up %s", name); + + fake = getenv("SOCKS5_FAKEALLHOSTS"); + local = getenv("SOCKS5_LOCALDNSONLY"); + + if (!fake && (hp = REAL(gethostbyname2)(name,af)) != NULL) { + S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS gethostbyname2: REAL: %s", inet_ntoa(*(struct in_addr *)hp->h_addr)); + + hlen = MIN(strlen(hp->h_name)+1, sizeof(my_name)); + strncpy(my_name, hp->h_name, hlen); + if (hlen == sizeof(my_name)) my_name[hlen-1] = '\0'; + + HostentCopy(my_addr_list, my_aliases, hp); + + h.h_name = my_name; + h.h_aliases = my_aliases; + h.h_addrtype = hp->h_addrtype; + h.h_length = hp->h_length; + h.h_addr_list = (char **)my_addr_list; + + lsInWrapFunction = 0; + lsInWrapHostname = 0; + return &h; + } + + /* 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 gethostbyname2: REAL: Fake not configured"); + lsInWrapFunction = 0; + lsInWrapHostname = 0; + return NULL; + } + + /* The daemon can only do AF_INET */ + if (af != AF_INET) { + h_errno = NO_RECOVERY; + return NULL; + } + + /* Fill in some UNRESOLVED values and let the daemon resolve it */ + if ((i = GetFakeHost(name)) <= 0) { + S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "SOCKS gethostbyname2: Get fake host failed"); + lsInWrapFunction = 0; + lsInWrapHostname = 0; + return NULL; + } + + hlen = MIN(strlen(name)+1, sizeof(my_name)); + strncpy(my_name, name, hlen); + if (hlen == sizeof(my_name)) my_name[hlen-1] = '\0'; + my_aliases[0] = NULL; + + special_addr.s_addr = htonl(i); + my_addr_list[0] = &special_addr; + my_addr_list[1] = NULL; + + h.h_name = my_name; + h.h_aliases = my_aliases; + h.h_addrtype = AF_INET; + h.h_length = sizeof(struct in_addr); + h.h_addr_list = (char **)my_addr_list; + + S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS gethostbyname2: FAKE: %s", inet_ntoa(*(struct in_addr *)h.h_addr_list[0])); + lsInWrapFunction = 0; + lsInWrapHostname = 0; + return &h; + } + int lsGetCachedAddress(const char *name, S5NetAddr *na) { int i; char hostname[256]; *** ./include/hide.h.ORI Thu Jul 15 21:47:22 1999 --- ./include/hide.h Thu Jul 15 06:18:39 1999 *************** *** 16,21 **** --- 16,22 ---- /* Try to hide these functions so we don't get compiler pukage. */ #define HIDE(x) _hidden_ ## x #define gethostbyname HIDE(gethostbyname) + #define gethostbyname2 HIDE(gethostbyname2) #define getpeername HIDE(getpeername) #define getsockname HIDE(getsockname) #define accept HIDE(accept) *************** *** 48,53 **** --- 49,55 ---- /* Unhide these functions so we can deal with them now that includes are */ /* done...Hopefully... */ #undef gethostbyname + #undef gethostbyname2 #undef getpeername #undef getsockname #undef accept *** ./include/socks.h.ORI Thu Jul 15 21:47:39 1999 --- ./include/socks.h Thu Jul 15 06:19:27 1999 *************** *** 50,55 **** --- 50,56 ---- extern int LIBPREFIX(select) P((int, fd_set *, fd_set *, fd_set *, struct timeval *)); extern struct hostent *LIBPREFIX(gethostbyname) P((char *)); + extern struct hostent *LIBPREFIX(gethostbyname2) P((char *, int)); #endif /* include prototypes */ #ifndef LIBPREFIX *************** *** 89,94 **** --- 90,96 ---- #endif #define gethostbyname LIBPREFIX(gethostbyname) + #define gethostbyname2 LIBPREFIX(gethostbyname2) #define rresvport LIBPREFIX(rresvport) #define connect LIBPREFIX(connect) #define listen LIBPREFIX(listen) *** ./include/system.h.ORI Thu Jul 15 21:47:57 1999 --- ./include/system.h Thu Jul 15 06:19:48 1999 *************** *** 22,27 **** --- 22,28 ---- #define LIBPREFIX(x) x struct hostent * REAL(gethostbyname) P((const char *)); + struct hostent * REAL(gethostbyname2) P((const char *, int)); struct hostent * REAL(gethostbyaddr) P((const void *, int, int)); struct servent * REAL(getservbyname) P((const char *, const char *)); >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message