gethost.c revision 2adc0320
17a0395d0Smrg/* 27a0395d0Smrg * $Xorg: gethost.c,v 1.5 2001/02/09 02:05:38 xorgcvs Exp $ 37a0395d0Smrg * $XdotOrg: $ 47a0395d0Smrg * 57a0395d0SmrgCopyright 1989, 1998 The Open Group 67a0395d0Smrg 77a0395d0SmrgPermission to use, copy, modify, distribute, and sell this software and its 87a0395d0Smrgdocumentation for any purpose is hereby granted without fee, provided that 97a0395d0Smrgthe above copyright notice appear in all copies and that both that 107a0395d0Smrgcopyright notice and this permission notice appear in supporting 117a0395d0Smrgdocumentation. 127a0395d0Smrg 137a0395d0SmrgThe above copyright notice and this permission notice shall be included in 147a0395d0Smrgall copies or substantial portions of the Software. 157a0395d0Smrg 167a0395d0SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 177a0395d0SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187a0395d0SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 197a0395d0SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 207a0395d0SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 217a0395d0SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 227a0395d0Smrg 237a0395d0SmrgExcept as contained in this notice, the name of The Open Group shall not be 247a0395d0Smrgused in advertising or otherwise to promote the sale, use or other dealings 257a0395d0Smrgin this Software without prior written authorization from The Open Group. 267a0395d0Smrg * * 277a0395d0Smrg * Author: Jim Fulton, MIT X Consortium 287a0395d0Smrg */ 297a0395d0Smrg 307a0395d0Smrg/* $XFree86: xc/programs/xauth/gethost.c,v 3.20 2003/07/27 12:34:25 herrb Exp $ */ 317a0395d0Smrg 327a0395d0Smrg#ifdef HAVE_CONFIG_H 337a0395d0Smrg#include "config.h" 347a0395d0Smrg#endif 357a0395d0Smrg 367a0395d0Smrg/* sorry, streams support does not really work yet */ 377a0395d0Smrg#if defined(STREAMSCONN) && defined(SVR4) 387a0395d0Smrg#undef STREAMSCONN 397a0395d0Smrg#define TCPCONN 407a0395d0Smrg#endif 417a0395d0Smrg 427a0395d0Smrg#ifdef WIN32 437a0395d0Smrg#include <X11/Xwinsock.h> 447a0395d0Smrg#define EPROTOTYPE WSAEPROTOTYPE 457a0395d0Smrg#endif 467a0395d0Smrg#include <X11/X.h> 477a0395d0Smrg#include <signal.h> 487a0395d0Smrg#include <setjmp.h> 497a0395d0Smrg#include <ctype.h> 507a0395d0Smrg#ifndef __TYPES__ 517a0395d0Smrg#include <sys/types.h> 527a0395d0Smrg#define __TYPES__ 537a0395d0Smrg#endif 547a0395d0Smrg#ifndef WIN32 557a0395d0Smrg#ifndef STREAMSCONN 567a0395d0Smrg#ifndef Lynx 577a0395d0Smrg#include <sys/socket.h> 587a0395d0Smrg#else 597a0395d0Smrg#include <socket.h> 607a0395d0Smrg#endif 617a0395d0Smrg#include <netdb.h> 627a0395d0Smrg#include <netinet/in.h> 637a0395d0Smrg#include <arpa/inet.h> 647a0395d0Smrg#ifdef HAVE_NET_ERRNO_H 657a0395d0Smrg#include <net/errno.h> 667a0395d0Smrg#endif /* HAVE_NET_ERRNO_H */ 677a0395d0Smrg#endif /* !STREAMSCONN */ 687a0395d0Smrg#endif /* !WIN32 */ 697a0395d0Smrg#include <errno.h> 707a0395d0Smrg#include "xauth.h" 717a0395d0Smrg 727a0395d0Smrg#ifdef DNETCONN 737a0395d0Smrg#include <netdnet/dn.h> 747a0395d0Smrg#include <netdnet/dnetdb.h> 757a0395d0Smrg#endif 767a0395d0Smrg 777a0395d0Smrg#ifndef WIN32 787a0395d0Smrg#include <arpa/inet.h> 797a0395d0Smrg#endif 807a0395d0Smrg 817a0395d0Smrg#ifdef SIGALRM 827a0395d0Smrgstatic volatile Bool nameserver_timedout = False; 837a0395d0Smrg 847a0395d0Smrg 857a0395d0Smrg/* 867a0395d0Smrg * get_hostname - Given an internet address, return a name (CHARON.MIT.EDU) 877a0395d0Smrg * or a string representing the address (18.58.0.13) if the name cannot 887a0395d0Smrg * be found. Stolen from xhost. 897a0395d0Smrg */ 907a0395d0Smrg 917a0395d0Smrgstatic jmp_buf env; 927a0395d0Smrgstatic RETSIGTYPE 937a0395d0Smrgnameserver_lost(int sig) 947a0395d0Smrg{ 957a0395d0Smrg nameserver_timedout = True; 967a0395d0Smrg longjmp (env, -1); 977a0395d0Smrg /* NOTREACHED */ 987a0395d0Smrg#ifdef SIGNALRETURNSINT 997a0395d0Smrg return -1; /* for picky compilers */ 1007a0395d0Smrg#endif 1017a0395d0Smrg} 1027a0395d0Smrg#endif 1037a0395d0Smrg 1047a0395d0Smrgchar * 1057a0395d0Smrgget_hostname (Xauth *auth) 1067a0395d0Smrg{ 1077a0395d0Smrg static struct hostent *hp; 1087a0395d0Smrg int af; 1097a0395d0Smrg#ifdef DNETCONN 1107a0395d0Smrg struct nodeent *np; 1117a0395d0Smrg static char nodeaddr[4 + 2 * DN_MAXADDL]; 1127a0395d0Smrg#endif /* DNETCONN */ 1137a0395d0Smrg 1147a0395d0Smrg hp = NULL; 1157a0395d0Smrg if (auth->address_length == 0) 1167a0395d0Smrg return "Illegal Address"; 1177a0395d0Smrg#ifdef TCPCONN 1187a0395d0Smrg if (auth->family == FamilyInternet 1197a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 1207a0395d0Smrg || auth->family == FamilyInternet6 1217a0395d0Smrg#endif 1227a0395d0Smrg ) 1237a0395d0Smrg { 1247a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 1257a0395d0Smrg if (auth->family == FamilyInternet6) 1267a0395d0Smrg af = AF_INET6; 1277a0395d0Smrg else 1287a0395d0Smrg#endif 1297a0395d0Smrg af = AF_INET; 1307a0395d0Smrg if (no_name_lookups == False) { 1317a0395d0Smrg#ifdef SIGALRM 1327a0395d0Smrg /* gethostbyaddr can take a LONG time if the host does not exist. 1337a0395d0Smrg Assume that if it does not respond in NAMESERVER_TIMEOUT seconds 1347a0395d0Smrg that something is wrong and do not make the user wait. 1357a0395d0Smrg gethostbyaddr will continue after a signal, so we have to 1367a0395d0Smrg jump out of it. 1377a0395d0Smrg */ 1387a0395d0Smrg nameserver_timedout = False; 1397a0395d0Smrg signal (SIGALRM, nameserver_lost); 1407a0395d0Smrg alarm (4); 1417a0395d0Smrg if (setjmp(env) == 0) { 1427a0395d0Smrg#endif 1437a0395d0Smrg hp = gethostbyaddr (auth->address, auth->address_length, af); 1447a0395d0Smrg#ifdef SIGALRM 1457a0395d0Smrg } 1467a0395d0Smrg alarm (0); 1477a0395d0Smrg#endif 1487a0395d0Smrg } 1497a0395d0Smrg if (hp) 1507a0395d0Smrg return (hp->h_name); 1517a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 1527a0395d0Smrg else if (af == AF_INET6) { 1537a0395d0Smrg static char addr[INET6_ADDRSTRLEN+2]; 1547a0395d0Smrg /* Add [] for clarity to distinguish between address & display, 1557a0395d0Smrg like RFC 2732 for URL's. Not required, since X display syntax 1567a0395d0Smrg always ends in :<display>, but makes it easier for people to read 1577a0395d0Smrg and less confusing to those who expect the RFC 2732 style. */ 1587a0395d0Smrg addr[0] = '['; 1597a0395d0Smrg if (inet_ntop(af, auth->address, addr + 1, INET6_ADDRSTRLEN) == NULL) 1607a0395d0Smrg return NULL; 1617a0395d0Smrg strcat(addr, "]"); 1627a0395d0Smrg return addr; 1637a0395d0Smrg } 1647a0395d0Smrg#endif 1657a0395d0Smrg else { 1667a0395d0Smrg return (inet_ntoa(*((struct in_addr *)(auth->address)))); 1677a0395d0Smrg } 1687a0395d0Smrg } 1697a0395d0Smrg#endif 1707a0395d0Smrg#ifdef DNETCONN 1717a0395d0Smrg if (auth->family == FamilyDECnet) { 1727a0395d0Smrg struct dn_naddr *addr_ptr = (struct dn_naddr *) auth->address; 1737a0395d0Smrg 1747a0395d0Smrg if ((no_name_lookups == False) && 1757a0395d0Smrg (np = getnodebyaddr(addr_ptr->a_addr, addr_ptr->a_len, AF_DECnet))) { 1767a0395d0Smrg sprintf(nodeaddr, "%s:", np->n_name); 1777a0395d0Smrg } else { 1787a0395d0Smrg sprintf(nodeaddr, "%s:", dnet_htoa(auth->address)); 1797a0395d0Smrg } 1807a0395d0Smrg return(nodeaddr); 1817a0395d0Smrg } 1827a0395d0Smrg#endif 1837a0395d0Smrg 1847a0395d0Smrg return (NULL); 1857a0395d0Smrg} 1867a0395d0Smrg 1877a0395d0Smrg#if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6)) 1887a0395d0Smrg/* 1897a0395d0Smrg * cribbed from lib/X/XConnDis.c 1907a0395d0Smrg */ 1917a0395d0Smrgstatic Bool 1927a0395d0Smrgget_inet_address(char *name, unsigned int *resultp) 1937a0395d0Smrg{ 1947a0395d0Smrg unsigned int hostinetaddr = inet_addr (name); 1957a0395d0Smrg struct hostent *host_ptr; 1967a0395d0Smrg struct sockaddr_in inaddr; /* dummy variable for size calcs */ 1977a0395d0Smrg 1987a0395d0Smrg#ifndef INADDR_NONE 1997a0395d0Smrg#define INADDR_NONE -1 2007a0395d0Smrg#endif 2017a0395d0Smrg 2027a0395d0Smrg if (hostinetaddr == INADDR_NONE) { 2037a0395d0Smrg if ((host_ptr = gethostbyname (name)) == NULL) { 2047a0395d0Smrg /* No such host! */ 2057a0395d0Smrg errno = EINVAL; 2067a0395d0Smrg return False; 2077a0395d0Smrg } 2087a0395d0Smrg /* Check the address type for an internet host. */ 2097a0395d0Smrg if (host_ptr->h_addrtype != AF_INET) { 2107a0395d0Smrg /* Not an Internet host! */ 2117a0395d0Smrg errno = EPROTOTYPE; 2127a0395d0Smrg return False; 2137a0395d0Smrg } 2147a0395d0Smrg 2157a0395d0Smrg memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr, 2167a0395d0Smrg sizeof(inaddr.sin_addr)); 2177a0395d0Smrg } 2187a0395d0Smrg *resultp = hostinetaddr; 2197a0395d0Smrg return True; 2207a0395d0Smrg} 2217a0395d0Smrg#endif 2227a0395d0Smrg 2237a0395d0Smrg#ifdef DNETCONN 2247a0395d0Smrgstatic Bool get_dnet_address (name, resultp) 2257a0395d0Smrg char *name; 2267a0395d0Smrg struct dn_naddr *resultp; 2277a0395d0Smrg{ 2287a0395d0Smrg struct dn_naddr *dnaddrp, dnaddr; 2297a0395d0Smrg struct nodeent *np; 2307a0395d0Smrg 2317a0395d0Smrg if (dnaddrp = dnet_addr (name)) { /* stolen from xhost */ 2327a0395d0Smrg dnaddr = *dnaddrp; 2337a0395d0Smrg } else { 2347a0395d0Smrg if ((np = getnodebyname (name)) == NULL) return False; 2357a0395d0Smrg dnaddr.a_len = np->n_length; 2367a0395d0Smrg memmove( dnaddr.a_addr, np->n_addr, np->n_length); 2377a0395d0Smrg } 2387a0395d0Smrg *resultp = dnaddr; 2397a0395d0Smrg return True; 2407a0395d0Smrg} 2417a0395d0Smrg#endif 2427a0395d0Smrg 2437a0395d0Smrgstruct addrlist *get_address_info ( 2447a0395d0Smrg int family, 2457a0395d0Smrg char *fulldpyname, 2467a0395d0Smrg int prefix, 2477a0395d0Smrg char *host) 2487a0395d0Smrg{ 2497a0395d0Smrg struct addrlist *retval = NULL; 2507a0395d0Smrg int len = 0; 2517a0395d0Smrg void *src = NULL; 2527a0395d0Smrg#ifdef TCPCONN 2537a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 2547a0395d0Smrg struct addrlist *lastrv = NULL; 2557a0395d0Smrg struct addrinfo *firstai = NULL; 2567a0395d0Smrg struct addrinfo *ai = NULL; 2577a0395d0Smrg struct addrinfo hints; 2587a0395d0Smrg#else 2597a0395d0Smrg unsigned int hostinetaddr; 2607a0395d0Smrg#endif 2617a0395d0Smrg#endif 2627a0395d0Smrg#ifdef DNETCONN 2637a0395d0Smrg struct dn_naddr dnaddr; 2647a0395d0Smrg#endif 2657a0395d0Smrg char buf[255]; 2667a0395d0Smrg 2677a0395d0Smrg /* 2687a0395d0Smrg * based on the family, set the pointer src to the start of the address 2697a0395d0Smrg * information to be copied and set len to the number of bytes. 2707a0395d0Smrg */ 2717a0395d0Smrg switch (family) { 2727a0395d0Smrg case FamilyLocal: /* hostname/unix:0 */ 2737a0395d0Smrg /* handle unix:0 and :0 specially */ 2747a0395d0Smrg if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 || 2757a0395d0Smrg fulldpyname[0] == ':')) { 2767a0395d0Smrg 2777a0395d0Smrg if (!get_local_hostname (buf, sizeof buf)) { 2787a0395d0Smrg len = 0; 2797a0395d0Smrg } else { 2807a0395d0Smrg src = buf; 2817a0395d0Smrg len = strlen (buf); 2827a0395d0Smrg } 2832adc0320Smrg } else if(prefix == 0 && (strncmp (fulldpyname, "/tmp/launch", 11) == 0)) { 2842adc0320Smrg /* Use the bundle id (part preceding : in the basename) as our src id */ 2852adc0320Smrg char *c; 2862adc0320Smrg#ifdef HAVE_STRLCPY 2872adc0320Smrg strlcpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf)); 2882adc0320Smrg#else 2892adc0320Smrg strncpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf)); 2902adc0320Smrg buf[sizeof(buf) - 1] = '\0'; 2912adc0320Smrg#endif 2922adc0320Smrg 2932adc0320Smrg c = strchr(buf, ':'); 2942adc0320Smrg 2952adc0320Smrg /* In the legacy case with no bundle id, use the full path */ 2962adc0320Smrg if(c == buf) { 2972adc0320Smrg src = fulldpyname; 2982adc0320Smrg } else { 2992adc0320Smrg *c = '\0'; 3002adc0320Smrg src = buf; 3012adc0320Smrg } 3022adc0320Smrg 3032adc0320Smrg len = strlen(src); 3042adc0320Smrg } else { 3057a0395d0Smrg src = fulldpyname; 3067a0395d0Smrg len = prefix; 3077a0395d0Smrg } 3087a0395d0Smrg break; 3097a0395d0Smrg case FamilyInternet: /* host:0 */ 3107a0395d0Smrg#ifdef TCPCONN 3117a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 3127a0395d0Smrg case FamilyInternet6: 3137a0395d0Smrg memset(&hints, 0, sizeof(hints)); 3147a0395d0Smrg hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 */ 3157a0395d0Smrg hints.ai_socktype = SOCK_STREAM; /* only interested in TCP */ 3167a0395d0Smrg hints.ai_protocol = 0; 3177a0395d0Smrg if (getaddrinfo(host,NULL,&hints,&firstai) !=0) return NULL; 3187a0395d0Smrg for (ai = firstai; ai != NULL; ai = ai->ai_next) { 3197366012aSmrg struct addrlist *duplicate; 3207366012aSmrg 3217a0395d0Smrg if (ai->ai_family == AF_INET) { 3227a0395d0Smrg struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; 3237a0395d0Smrg src = &(sin->sin_addr); 3247a0395d0Smrg len = sizeof(sin->sin_addr); 3257a0395d0Smrg family = FamilyInternet; 3267a0395d0Smrg } else if (ai->ai_family == AF_INET6) { 3277a0395d0Smrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; 3287a0395d0Smrg src = &(sin6->sin6_addr); 3297a0395d0Smrg len = sizeof(sin6->sin6_addr); 3307a0395d0Smrg family = FamilyInternet6; 3317a0395d0Smrg } 3327a0395d0Smrg 3337a0395d0Smrg for(duplicate = retval; duplicate != NULL; duplicate = duplicate->next) { 3347a0395d0Smrg if(duplicate->family == family && duplicate->len == len && 3357a0395d0Smrg memcmp(duplicate->address, src, len) == 0) { 3367a0395d0Smrg break; 3377a0395d0Smrg } 3387a0395d0Smrg } 3397a0395d0Smrg 3407a0395d0Smrg if (len > 0 && src != NULL && duplicate == NULL) { 3417a0395d0Smrg struct addrlist *newrv = malloc (sizeof(struct addrlist)); 3427a0395d0Smrg if (newrv) { 3437a0395d0Smrg newrv->address = malloc (len); 3447a0395d0Smrg if (newrv->address) { 3457a0395d0Smrg memcpy(newrv->address, src, len); 3467a0395d0Smrg newrv->next = NULL; 3477a0395d0Smrg newrv->family = family; 3487a0395d0Smrg newrv->len = len; 3497a0395d0Smrg if (retval == NULL) { 3507a0395d0Smrg lastrv = retval = newrv; 3517a0395d0Smrg } else { 3527a0395d0Smrg lastrv->next = newrv; 3537a0395d0Smrg lastrv = newrv; 3547a0395d0Smrg } 3557a0395d0Smrg } else { 3567a0395d0Smrg free(newrv); 3577a0395d0Smrg } 3587a0395d0Smrg } 3597a0395d0Smrg } 3607a0395d0Smrg /* reset to avoid copying into list twice */ 3617a0395d0Smrg len = 0; 3627a0395d0Smrg src = NULL; 3637a0395d0Smrg } 3647a0395d0Smrg freeaddrinfo(firstai); 3657a0395d0Smrg break; 3667a0395d0Smrg#else 3677a0395d0Smrg if (!get_inet_address (host, &hostinetaddr)) return NULL; 3687a0395d0Smrg src = (char *) &hostinetaddr; 3697a0395d0Smrg len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */ 3707a0395d0Smrg break; 3717a0395d0Smrg#endif /* IPv6 */ 3727a0395d0Smrg#else 3737a0395d0Smrg return NULL; 3747a0395d0Smrg#endif 3757a0395d0Smrg case FamilyDECnet: /* host::0 */ 3767a0395d0Smrg#ifdef DNETCONN 3777a0395d0Smrg if (!get_dnet_address (host, &dnaddr)) return NULL; 3787a0395d0Smrg src = (char *) &dnaddr; 3797a0395d0Smrg len = (sizeof dnaddr); 3807a0395d0Smrg break; 3817a0395d0Smrg#else 3827a0395d0Smrg /* fall through since we don't have code for it */ 3837a0395d0Smrg#endif 3847a0395d0Smrg default: 3857a0395d0Smrg src = NULL; 3867a0395d0Smrg len = 0; 3877a0395d0Smrg } 3887a0395d0Smrg 3897a0395d0Smrg /* 3907a0395d0Smrg * if source was provided, allocate space and copy it 3917a0395d0Smrg */ 3927a0395d0Smrg if (len > 0 && src != NULL) { 3937a0395d0Smrg retval = malloc (sizeof(struct addrlist)); 3947a0395d0Smrg if (retval) { 3957a0395d0Smrg retval->address = malloc (len); 3967a0395d0Smrg if (retval->address) { 3977a0395d0Smrg memcpy(retval->address, src, len); 3987a0395d0Smrg retval->next = NULL; 3997a0395d0Smrg retval->family = family; 4007a0395d0Smrg retval->len = len; 4017a0395d0Smrg } else { 4027a0395d0Smrg free(retval); 4037a0395d0Smrg retval = NULL; 4047a0395d0Smrg } 4057a0395d0Smrg } 4067a0395d0Smrg } 4077a0395d0Smrg return retval; 4087a0395d0Smrg} 409