gethost.c revision 96402570
17a0395d0Smrg/* 296402570Smrg * 37a0395d0SmrgCopyright 1989, 1998 The Open Group 47a0395d0Smrg 57a0395d0SmrgPermission to use, copy, modify, distribute, and sell this software and its 67a0395d0Smrgdocumentation for any purpose is hereby granted without fee, provided that 77a0395d0Smrgthe above copyright notice appear in all copies and that both that 87a0395d0Smrgcopyright notice and this permission notice appear in supporting 97a0395d0Smrgdocumentation. 107a0395d0Smrg 117a0395d0SmrgThe above copyright notice and this permission notice shall be included in 127a0395d0Smrgall copies or substantial portions of the Software. 137a0395d0Smrg 147a0395d0SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157a0395d0SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167a0395d0SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 177a0395d0SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 187a0395d0SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 197a0395d0SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 207a0395d0Smrg 217a0395d0SmrgExcept as contained in this notice, the name of The Open Group shall not be 227a0395d0Smrgused in advertising or otherwise to promote the sale, use or other dealings 237a0395d0Smrgin this Software without prior written authorization from The Open Group. 247a0395d0Smrg * * 257a0395d0Smrg * Author: Jim Fulton, MIT X Consortium 267a0395d0Smrg */ 277a0395d0Smrg 287a0395d0Smrg#ifdef HAVE_CONFIG_H 297a0395d0Smrg#include "config.h" 307a0395d0Smrg#endif 317a0395d0Smrg 327a0395d0Smrg/* sorry, streams support does not really work yet */ 337a0395d0Smrg#if defined(STREAMSCONN) && defined(SVR4) 347a0395d0Smrg#undef STREAMSCONN 357a0395d0Smrg#define TCPCONN 367a0395d0Smrg#endif 377a0395d0Smrg 387a0395d0Smrg#ifdef WIN32 397a0395d0Smrg#include <X11/Xwinsock.h> 407a0395d0Smrg#define EPROTOTYPE WSAEPROTOTYPE 417a0395d0Smrg#endif 427a0395d0Smrg#include <X11/X.h> 437a0395d0Smrg#include <signal.h> 447a0395d0Smrg#include <setjmp.h> 457a0395d0Smrg#include <ctype.h> 467a0395d0Smrg#ifndef __TYPES__ 477a0395d0Smrg#include <sys/types.h> 487a0395d0Smrg#define __TYPES__ 497a0395d0Smrg#endif 507a0395d0Smrg#ifndef WIN32 517a0395d0Smrg#ifndef STREAMSCONN 527a0395d0Smrg#ifndef Lynx 537a0395d0Smrg#include <sys/socket.h> 547a0395d0Smrg#else 557a0395d0Smrg#include <socket.h> 567a0395d0Smrg#endif 577a0395d0Smrg#include <netdb.h> 587a0395d0Smrg#include <netinet/in.h> 597a0395d0Smrg#include <arpa/inet.h> 607a0395d0Smrg#ifdef HAVE_NET_ERRNO_H 617a0395d0Smrg#include <net/errno.h> 627a0395d0Smrg#endif /* HAVE_NET_ERRNO_H */ 637a0395d0Smrg#endif /* !STREAMSCONN */ 647a0395d0Smrg#endif /* !WIN32 */ 657a0395d0Smrg#include <errno.h> 667a0395d0Smrg#include "xauth.h" 677a0395d0Smrg 687a0395d0Smrg#ifdef DNETCONN 697a0395d0Smrg#include <netdnet/dn.h> 707a0395d0Smrg#include <netdnet/dnetdb.h> 717a0395d0Smrg#endif 727a0395d0Smrg 737a0395d0Smrg#ifndef WIN32 747a0395d0Smrg#include <arpa/inet.h> 757a0395d0Smrg#endif 767a0395d0Smrg 7796402570Smrgconst char * 787a0395d0Smrgget_hostname (Xauth *auth) 797a0395d0Smrg{ 807a0395d0Smrg static struct hostent *hp; 817a0395d0Smrg int af; 827a0395d0Smrg#ifdef DNETCONN 837a0395d0Smrg struct nodeent *np; 847a0395d0Smrg static char nodeaddr[4 + 2 * DN_MAXADDL]; 857a0395d0Smrg#endif /* DNETCONN */ 867a0395d0Smrg 877a0395d0Smrg hp = NULL; 887a0395d0Smrg if (auth->address_length == 0) 897a0395d0Smrg return "Illegal Address"; 907a0395d0Smrg#ifdef TCPCONN 917a0395d0Smrg if (auth->family == FamilyInternet 927a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 937a0395d0Smrg || auth->family == FamilyInternet6 9496402570Smrg#endif 957a0395d0Smrg ) 967a0395d0Smrg { 977a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 987a0395d0Smrg if (auth->family == FamilyInternet6) 997a0395d0Smrg af = AF_INET6; 1007a0395d0Smrg else 1017a0395d0Smrg#endif 1027a0395d0Smrg af = AF_INET; 1037a0395d0Smrg if (no_name_lookups == False) { 1047a0395d0Smrg hp = gethostbyaddr (auth->address, auth->address_length, af); 1057a0395d0Smrg } 1067a0395d0Smrg if (hp) 1077a0395d0Smrg return (hp->h_name); 1087a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 1097a0395d0Smrg else if (af == AF_INET6) { 1107a0395d0Smrg static char addr[INET6_ADDRSTRLEN+2]; 1117a0395d0Smrg /* Add [] for clarity to distinguish between address & display, 1127a0395d0Smrg like RFC 2732 for URL's. Not required, since X display syntax 1137a0395d0Smrg always ends in :<display>, but makes it easier for people to read 1147a0395d0Smrg and less confusing to those who expect the RFC 2732 style. */ 1157a0395d0Smrg addr[0] = '['; 1167a0395d0Smrg if (inet_ntop(af, auth->address, addr + 1, INET6_ADDRSTRLEN) == NULL) 1177a0395d0Smrg return NULL; 1187a0395d0Smrg strcat(addr, "]"); 1197a0395d0Smrg return addr; 1207a0395d0Smrg } 1217a0395d0Smrg#endif 1227a0395d0Smrg else { 1237a0395d0Smrg return (inet_ntoa(*((struct in_addr *)(auth->address)))); 1247a0395d0Smrg } 1257a0395d0Smrg } 1267a0395d0Smrg#endif 1277a0395d0Smrg#ifdef DNETCONN 1287a0395d0Smrg if (auth->family == FamilyDECnet) { 1297a0395d0Smrg struct dn_naddr *addr_ptr = (struct dn_naddr *) auth->address; 1307a0395d0Smrg 1317a0395d0Smrg if ((no_name_lookups == False) && 1327a0395d0Smrg (np = getnodebyaddr(addr_ptr->a_addr, addr_ptr->a_len, AF_DECnet))) { 1337a0395d0Smrg sprintf(nodeaddr, "%s:", np->n_name); 1347a0395d0Smrg } else { 1357a0395d0Smrg sprintf(nodeaddr, "%s:", dnet_htoa(auth->address)); 1367a0395d0Smrg } 1377a0395d0Smrg return(nodeaddr); 1387a0395d0Smrg } 1397a0395d0Smrg#endif 1407a0395d0Smrg 1417a0395d0Smrg return (NULL); 1427a0395d0Smrg} 1437a0395d0Smrg 1447a0395d0Smrg#if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6)) 1457a0395d0Smrg/* 1467a0395d0Smrg * cribbed from lib/X/XConnDis.c 1477a0395d0Smrg */ 14896402570Smrgstatic Bool 1497a0395d0Smrgget_inet_address(char *name, unsigned int *resultp) 1507a0395d0Smrg{ 1517a0395d0Smrg unsigned int hostinetaddr = inet_addr (name); 1527a0395d0Smrg struct hostent *host_ptr; 1537a0395d0Smrg struct sockaddr_in inaddr; /* dummy variable for size calcs */ 1547a0395d0Smrg 1557a0395d0Smrg#ifndef INADDR_NONE 1567a0395d0Smrg#define INADDR_NONE -1 1577a0395d0Smrg#endif 1587a0395d0Smrg 1597a0395d0Smrg if (hostinetaddr == INADDR_NONE) { 1607a0395d0Smrg if ((host_ptr = gethostbyname (name)) == NULL) { 1617a0395d0Smrg /* No such host! */ 1627a0395d0Smrg errno = EINVAL; 1637a0395d0Smrg return False; 1647a0395d0Smrg } 1657a0395d0Smrg /* Check the address type for an internet host. */ 1667a0395d0Smrg if (host_ptr->h_addrtype != AF_INET) { 1677a0395d0Smrg /* Not an Internet host! */ 1687a0395d0Smrg errno = EPROTOTYPE; 1697a0395d0Smrg return False; 1707a0395d0Smrg } 17196402570Smrg 17296402570Smrg memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr, 1737a0395d0Smrg sizeof(inaddr.sin_addr)); 1747a0395d0Smrg } 1757a0395d0Smrg *resultp = hostinetaddr; 1767a0395d0Smrg return True; 1777a0395d0Smrg} 1787a0395d0Smrg#endif 1797a0395d0Smrg 1807a0395d0Smrg#ifdef DNETCONN 1817a0395d0Smrgstatic Bool get_dnet_address (name, resultp) 1827a0395d0Smrg char *name; 1837a0395d0Smrg struct dn_naddr *resultp; 1847a0395d0Smrg{ 1857a0395d0Smrg struct dn_naddr *dnaddrp, dnaddr; 1867a0395d0Smrg struct nodeent *np; 1877a0395d0Smrg 1887a0395d0Smrg if (dnaddrp = dnet_addr (name)) { /* stolen from xhost */ 1897a0395d0Smrg dnaddr = *dnaddrp; 1907a0395d0Smrg } else { 1917a0395d0Smrg if ((np = getnodebyname (name)) == NULL) return False; 1927a0395d0Smrg dnaddr.a_len = np->n_length; 1937a0395d0Smrg memmove( dnaddr.a_addr, np->n_addr, np->n_length); 1947a0395d0Smrg } 1957a0395d0Smrg *resultp = dnaddr; 1967a0395d0Smrg return True; 1977a0395d0Smrg} 1987a0395d0Smrg#endif 1997a0395d0Smrg 2007a0395d0Smrgstruct addrlist *get_address_info ( 2017a0395d0Smrg int family, 20296402570Smrg const char *fulldpyname, 2037a0395d0Smrg int prefix, 2047a0395d0Smrg char *host) 2057a0395d0Smrg{ 2067a0395d0Smrg struct addrlist *retval = NULL; 2077a0395d0Smrg int len = 0; 20896402570Smrg const void *src = NULL; 2097a0395d0Smrg#ifdef TCPCONN 2107a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 2117a0395d0Smrg struct addrlist *lastrv = NULL; 2127a0395d0Smrg struct addrinfo *firstai = NULL; 2137a0395d0Smrg struct addrinfo *ai = NULL; 2147a0395d0Smrg struct addrinfo hints; 2157a0395d0Smrg#else 2167a0395d0Smrg unsigned int hostinetaddr; 2177a0395d0Smrg#endif 2187a0395d0Smrg#endif 2197a0395d0Smrg#ifdef DNETCONN 2207a0395d0Smrg struct dn_naddr dnaddr; 2217a0395d0Smrg#endif 2227a0395d0Smrg char buf[255]; 2237a0395d0Smrg 2247a0395d0Smrg /* 2257a0395d0Smrg * based on the family, set the pointer src to the start of the address 2267a0395d0Smrg * information to be copied and set len to the number of bytes. 2277a0395d0Smrg */ 2287a0395d0Smrg switch (family) { 2297a0395d0Smrg case FamilyLocal: /* hostname/unix:0 */ 2307a0395d0Smrg /* handle unix:0 and :0 specially */ 2317a0395d0Smrg if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 || 2327a0395d0Smrg fulldpyname[0] == ':')) { 2337a0395d0Smrg 2347a0395d0Smrg if (!get_local_hostname (buf, sizeof buf)) { 2357a0395d0Smrg len = 0; 2367a0395d0Smrg } else { 2377a0395d0Smrg src = buf; 2387a0395d0Smrg len = strlen (buf); 2397a0395d0Smrg } 2402adc0320Smrg } else if(prefix == 0 && (strncmp (fulldpyname, "/tmp/launch", 11) == 0)) { 2412adc0320Smrg /* Use the bundle id (part preceding : in the basename) as our src id */ 2422adc0320Smrg char *c; 2432adc0320Smrg#ifdef HAVE_STRLCPY 2442adc0320Smrg strlcpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf)); 2452adc0320Smrg#else 2462adc0320Smrg strncpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf)); 2472adc0320Smrg buf[sizeof(buf) - 1] = '\0'; 2482adc0320Smrg#endif 2492adc0320Smrg 2502adc0320Smrg c = strchr(buf, ':'); 25196402570Smrg 2522adc0320Smrg /* In the legacy case with no bundle id, use the full path */ 2532adc0320Smrg if(c == buf) { 2542adc0320Smrg src = fulldpyname; 2552adc0320Smrg } else { 2562adc0320Smrg *c = '\0'; 2572adc0320Smrg src = buf; 2582adc0320Smrg } 2592adc0320Smrg 2602adc0320Smrg len = strlen(src); 2612adc0320Smrg } else { 2627a0395d0Smrg src = fulldpyname; 2637a0395d0Smrg len = prefix; 2647a0395d0Smrg } 2657a0395d0Smrg break; 2667a0395d0Smrg case FamilyInternet: /* host:0 */ 2677a0395d0Smrg#ifdef TCPCONN 2687a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 2697a0395d0Smrg case FamilyInternet6: 2707a0395d0Smrg memset(&hints, 0, sizeof(hints)); 2717a0395d0Smrg hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 */ 2727a0395d0Smrg hints.ai_socktype = SOCK_STREAM; /* only interested in TCP */ 27396402570Smrg hints.ai_protocol = 0; 2747a0395d0Smrg if (getaddrinfo(host,NULL,&hints,&firstai) !=0) return NULL; 2757a0395d0Smrg for (ai = firstai; ai != NULL; ai = ai->ai_next) { 2767366012aSmrg struct addrlist *duplicate; 2777366012aSmrg 2787a0395d0Smrg if (ai->ai_family == AF_INET) { 2797a0395d0Smrg struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; 2807a0395d0Smrg src = &(sin->sin_addr); 2817a0395d0Smrg len = sizeof(sin->sin_addr); 2827a0395d0Smrg family = FamilyInternet; 2837a0395d0Smrg } else if (ai->ai_family == AF_INET6) { 2847a0395d0Smrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; 2857a0395d0Smrg src = &(sin6->sin6_addr); 2867a0395d0Smrg len = sizeof(sin6->sin6_addr); 2877a0395d0Smrg family = FamilyInternet6; 2887a0395d0Smrg } 2897a0395d0Smrg 2907a0395d0Smrg for(duplicate = retval; duplicate != NULL; duplicate = duplicate->next) { 2917a0395d0Smrg if(duplicate->family == family && duplicate->len == len && 2927a0395d0Smrg memcmp(duplicate->address, src, len) == 0) { 2937a0395d0Smrg break; 2947a0395d0Smrg } 2957a0395d0Smrg } 2967a0395d0Smrg 2977a0395d0Smrg if (len > 0 && src != NULL && duplicate == NULL) { 2987a0395d0Smrg struct addrlist *newrv = malloc (sizeof(struct addrlist)); 2997a0395d0Smrg if (newrv) { 3007a0395d0Smrg newrv->address = malloc (len); 3017a0395d0Smrg if (newrv->address) { 3027a0395d0Smrg memcpy(newrv->address, src, len); 3037a0395d0Smrg newrv->next = NULL; 3047a0395d0Smrg newrv->family = family; 3057a0395d0Smrg newrv->len = len; 3067a0395d0Smrg if (retval == NULL) { 3077a0395d0Smrg lastrv = retval = newrv; 3087a0395d0Smrg } else { 3097a0395d0Smrg lastrv->next = newrv; 3107a0395d0Smrg lastrv = newrv; 3117a0395d0Smrg } 3127a0395d0Smrg } else { 3137a0395d0Smrg free(newrv); 3147a0395d0Smrg } 3157a0395d0Smrg } 3167a0395d0Smrg } 3177a0395d0Smrg /* reset to avoid copying into list twice */ 3187a0395d0Smrg len = 0; 3197a0395d0Smrg src = NULL; 3207a0395d0Smrg } 3217a0395d0Smrg freeaddrinfo(firstai); 3227a0395d0Smrg break; 3237a0395d0Smrg#else 3247a0395d0Smrg if (!get_inet_address (host, &hostinetaddr)) return NULL; 3257a0395d0Smrg src = (char *) &hostinetaddr; 3267a0395d0Smrg len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */ 3277a0395d0Smrg break; 3287a0395d0Smrg#endif /* IPv6 */ 3297a0395d0Smrg#else 3307a0395d0Smrg return NULL; 3317a0395d0Smrg#endif 3327a0395d0Smrg case FamilyDECnet: /* host::0 */ 3337a0395d0Smrg#ifdef DNETCONN 3347a0395d0Smrg if (!get_dnet_address (host, &dnaddr)) return NULL; 3357a0395d0Smrg src = (char *) &dnaddr; 3367a0395d0Smrg len = (sizeof dnaddr); 3377a0395d0Smrg break; 3387a0395d0Smrg#else 3397a0395d0Smrg /* fall through since we don't have code for it */ 3407a0395d0Smrg#endif 3417a0395d0Smrg default: 3427a0395d0Smrg src = NULL; 3437a0395d0Smrg len = 0; 3447a0395d0Smrg } 3457a0395d0Smrg 3467a0395d0Smrg /* 3477a0395d0Smrg * if source was provided, allocate space and copy it 3487a0395d0Smrg */ 3497a0395d0Smrg if (len > 0 && src != NULL) { 3507a0395d0Smrg retval = malloc (sizeof(struct addrlist)); 3517a0395d0Smrg if (retval) { 3527a0395d0Smrg retval->address = malloc (len); 3537a0395d0Smrg if (retval->address) { 3547a0395d0Smrg memcpy(retval->address, src, len); 3557a0395d0Smrg retval->next = NULL; 3567a0395d0Smrg retval->family = family; 3577a0395d0Smrg retval->len = len; 3587a0395d0Smrg } else { 3597a0395d0Smrg free(retval); 3607a0395d0Smrg retval = NULL; 3617a0395d0Smrg } 3627a0395d0Smrg } 3637a0395d0Smrg } 3647a0395d0Smrg return retval; 3657a0395d0Smrg} 366