gethost.c revision 8abc0ccf
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#ifdef WIN32 337a0395d0Smrg#include <X11/Xwinsock.h> 347a0395d0Smrg#define EPROTOTYPE WSAEPROTOTYPE 357a0395d0Smrg#endif 367a0395d0Smrg#include <X11/X.h> 377a0395d0Smrg#include <signal.h> 387a0395d0Smrg#include <setjmp.h> 397a0395d0Smrg#include <ctype.h> 407a0395d0Smrg#ifndef __TYPES__ 417a0395d0Smrg#include <sys/types.h> 427a0395d0Smrg#define __TYPES__ 437a0395d0Smrg#endif 447a0395d0Smrg#ifndef WIN32 457a0395d0Smrg#ifndef Lynx 467a0395d0Smrg#include <sys/socket.h> 477a0395d0Smrg#else 487a0395d0Smrg#include <socket.h> 497a0395d0Smrg#endif 507a0395d0Smrg#include <netdb.h> 517a0395d0Smrg#include <netinet/in.h> 527a0395d0Smrg#include <arpa/inet.h> 537a0395d0Smrg#ifdef HAVE_NET_ERRNO_H 547a0395d0Smrg#include <net/errno.h> 557a0395d0Smrg#endif /* HAVE_NET_ERRNO_H */ 567a0395d0Smrg#endif /* !WIN32 */ 577a0395d0Smrg#include <errno.h> 587a0395d0Smrg#include "xauth.h" 597a0395d0Smrg 607a0395d0Smrg 617a0395d0Smrg#ifndef WIN32 627a0395d0Smrg#include <arpa/inet.h> 637a0395d0Smrg#endif 647a0395d0Smrg 6596402570Smrgconst char * 667a0395d0Smrgget_hostname (Xauth *auth) 677a0395d0Smrg{ 688abc0ccfSmrg#ifdef TCPCONN 697a0395d0Smrg static struct hostent *hp; 707a0395d0Smrg int af; 717a0395d0Smrg 727a0395d0Smrg hp = NULL; 738abc0ccfSmrg#endif 748abc0ccfSmrg 757a0395d0Smrg if (auth->address_length == 0) 767a0395d0Smrg return "Illegal Address"; 777a0395d0Smrg#ifdef TCPCONN 787a0395d0Smrg if (auth->family == FamilyInternet 797a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 807a0395d0Smrg || auth->family == FamilyInternet6 8196402570Smrg#endif 827a0395d0Smrg ) 837a0395d0Smrg { 847a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 857a0395d0Smrg if (auth->family == FamilyInternet6) 867a0395d0Smrg af = AF_INET6; 877a0395d0Smrg else 887a0395d0Smrg#endif 897a0395d0Smrg af = AF_INET; 907a0395d0Smrg if (no_name_lookups == False) { 917a0395d0Smrg hp = gethostbyaddr (auth->address, auth->address_length, af); 927a0395d0Smrg } 937a0395d0Smrg if (hp) 947a0395d0Smrg return (hp->h_name); 957a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 967a0395d0Smrg else if (af == AF_INET6) { 977a0395d0Smrg static char addr[INET6_ADDRSTRLEN+2]; 987a0395d0Smrg /* Add [] for clarity to distinguish between address & display, 997a0395d0Smrg like RFC 2732 for URL's. Not required, since X display syntax 1007a0395d0Smrg always ends in :<display>, but makes it easier for people to read 1017a0395d0Smrg and less confusing to those who expect the RFC 2732 style. */ 1027a0395d0Smrg addr[0] = '['; 1037a0395d0Smrg if (inet_ntop(af, auth->address, addr + 1, INET6_ADDRSTRLEN) == NULL) 1047a0395d0Smrg return NULL; 1057a0395d0Smrg strcat(addr, "]"); 1067a0395d0Smrg return addr; 1077a0395d0Smrg } 1087a0395d0Smrg#endif 1097a0395d0Smrg else { 1107a0395d0Smrg return (inet_ntoa(*((struct in_addr *)(auth->address)))); 1117a0395d0Smrg } 1127a0395d0Smrg } 1137a0395d0Smrg#endif 1147a0395d0Smrg 1157a0395d0Smrg return (NULL); 1167a0395d0Smrg} 1177a0395d0Smrg 1187a0395d0Smrg#if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6)) 1197a0395d0Smrg/* 1207a0395d0Smrg * cribbed from lib/X/XConnDis.c 1217a0395d0Smrg */ 12296402570Smrgstatic Bool 1237a0395d0Smrgget_inet_address(char *name, unsigned int *resultp) 1247a0395d0Smrg{ 1257a0395d0Smrg unsigned int hostinetaddr = inet_addr (name); 1267a0395d0Smrg struct hostent *host_ptr; 1277a0395d0Smrg struct sockaddr_in inaddr; /* dummy variable for size calcs */ 1287a0395d0Smrg 1297a0395d0Smrg#ifndef INADDR_NONE 1307a0395d0Smrg#define INADDR_NONE -1 1317a0395d0Smrg#endif 1327a0395d0Smrg 1337a0395d0Smrg if (hostinetaddr == INADDR_NONE) { 1347a0395d0Smrg if ((host_ptr = gethostbyname (name)) == NULL) { 1357a0395d0Smrg /* No such host! */ 1367a0395d0Smrg errno = EINVAL; 1377a0395d0Smrg return False; 1387a0395d0Smrg } 1397a0395d0Smrg /* Check the address type for an internet host. */ 1407a0395d0Smrg if (host_ptr->h_addrtype != AF_INET) { 1417a0395d0Smrg /* Not an Internet host! */ 1427a0395d0Smrg errno = EPROTOTYPE; 1437a0395d0Smrg return False; 1447a0395d0Smrg } 14596402570Smrg 14696402570Smrg memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr, 1477a0395d0Smrg sizeof(inaddr.sin_addr)); 1487a0395d0Smrg } 1497a0395d0Smrg *resultp = hostinetaddr; 1507a0395d0Smrg return True; 1517a0395d0Smrg} 1527a0395d0Smrg#endif 1537a0395d0Smrg 1547a0395d0Smrg 1557a0395d0Smrgstruct addrlist *get_address_info ( 1567a0395d0Smrg int family, 15796402570Smrg const char *fulldpyname, 1587a0395d0Smrg int prefix, 1597a0395d0Smrg char *host) 1607a0395d0Smrg{ 1617a0395d0Smrg struct addrlist *retval = NULL; 1627a0395d0Smrg int len = 0; 16396402570Smrg const void *src = NULL; 1647a0395d0Smrg#ifdef TCPCONN 1657a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 1667a0395d0Smrg struct addrlist *lastrv = NULL; 1677a0395d0Smrg struct addrinfo *firstai = NULL; 1687a0395d0Smrg struct addrinfo *ai = NULL; 1697a0395d0Smrg struct addrinfo hints; 1707a0395d0Smrg#else 1717a0395d0Smrg unsigned int hostinetaddr; 1727a0395d0Smrg#endif 1737a0395d0Smrg#endif 1747a0395d0Smrg char buf[255]; 1757a0395d0Smrg 1767a0395d0Smrg /* 1777a0395d0Smrg * based on the family, set the pointer src to the start of the address 1787a0395d0Smrg * information to be copied and set len to the number of bytes. 1797a0395d0Smrg */ 1807a0395d0Smrg switch (family) { 1817a0395d0Smrg case FamilyLocal: /* hostname/unix:0 */ 1827a0395d0Smrg /* handle unix:0 and :0 specially */ 1837a0395d0Smrg if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 || 1847a0395d0Smrg fulldpyname[0] == ':')) { 1857a0395d0Smrg 1867a0395d0Smrg if (!get_local_hostname (buf, sizeof buf)) { 1877a0395d0Smrg len = 0; 1887a0395d0Smrg } else { 1897a0395d0Smrg src = buf; 1907a0395d0Smrg len = strlen (buf); 1917a0395d0Smrg } 1922adc0320Smrg } else if(prefix == 0 && (strncmp (fulldpyname, "/tmp/launch", 11) == 0)) { 1932adc0320Smrg /* Use the bundle id (part preceding : in the basename) as our src id */ 1942adc0320Smrg char *c; 1952adc0320Smrg#ifdef HAVE_STRLCPY 1962adc0320Smrg strlcpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf)); 1972adc0320Smrg#else 1982adc0320Smrg strncpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf)); 1992adc0320Smrg buf[sizeof(buf) - 1] = '\0'; 2002adc0320Smrg#endif 2012adc0320Smrg 2022adc0320Smrg c = strchr(buf, ':'); 20396402570Smrg 2042adc0320Smrg /* In the legacy case with no bundle id, use the full path */ 2052adc0320Smrg if(c == buf) { 2062adc0320Smrg src = fulldpyname; 2072adc0320Smrg } else { 2082adc0320Smrg *c = '\0'; 2092adc0320Smrg src = buf; 2102adc0320Smrg } 2112adc0320Smrg 2122adc0320Smrg len = strlen(src); 2132adc0320Smrg } else { 2147a0395d0Smrg src = fulldpyname; 2157a0395d0Smrg len = prefix; 2167a0395d0Smrg } 2177a0395d0Smrg break; 2187a0395d0Smrg case FamilyInternet: /* host:0 */ 2197a0395d0Smrg#ifdef TCPCONN 2207a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 2217a0395d0Smrg case FamilyInternet6: 2227a0395d0Smrg memset(&hints, 0, sizeof(hints)); 2237a0395d0Smrg hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 */ 2247a0395d0Smrg hints.ai_socktype = SOCK_STREAM; /* only interested in TCP */ 22596402570Smrg hints.ai_protocol = 0; 2267a0395d0Smrg if (getaddrinfo(host,NULL,&hints,&firstai) !=0) return NULL; 2277a0395d0Smrg for (ai = firstai; ai != NULL; ai = ai->ai_next) { 2287366012aSmrg struct addrlist *duplicate; 2297366012aSmrg 2308abc0ccfSmrg len = 0; 2317a0395d0Smrg if (ai->ai_family == AF_INET) { 2327a0395d0Smrg struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; 2337a0395d0Smrg src = &(sin->sin_addr); 2348abc0ccfSmrg if (*(const in_addr_t *) src == htonl(INADDR_LOOPBACK)) { 2358abc0ccfSmrg family = FamilyLocal; 2368abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 2378abc0ccfSmrg src = buf; 2388abc0ccfSmrg len = strlen (buf); 2398abc0ccfSmrg } else 2408abc0ccfSmrg src = NULL; 2418abc0ccfSmrg } else { 2428abc0ccfSmrg len = sizeof(sin->sin_addr); 2438abc0ccfSmrg family = FamilyInternet; 2448abc0ccfSmrg } 2457a0395d0Smrg } else if (ai->ai_family == AF_INET6) { 2467a0395d0Smrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; 2477a0395d0Smrg src = &(sin6->sin6_addr); 2488abc0ccfSmrg if (!IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) { 2498abc0ccfSmrg if (IN6_IS_ADDR_LOOPBACK((const struct in6_addr *)src)) { 2508abc0ccfSmrg family = FamilyLocal; 2518abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 2528abc0ccfSmrg src = buf; 2538abc0ccfSmrg len = strlen (buf); 2548abc0ccfSmrg } else 2558abc0ccfSmrg src = NULL; 2568abc0ccfSmrg } else { 2578abc0ccfSmrg len = sizeof(sin6->sin6_addr); 2588abc0ccfSmrg family = FamilyInternet6; 2598abc0ccfSmrg } 2608abc0ccfSmrg } else { 2618abc0ccfSmrg src = &(sin6->sin6_addr.s6_addr[12]); 2628abc0ccfSmrg len = sizeof(((struct sockaddr_in *) 2638abc0ccfSmrg ai->ai_addr)->sin_addr); 2648abc0ccfSmrg family = FamilyInternet; 2658abc0ccfSmrg } 2667a0395d0Smrg } 2677a0395d0Smrg 2687a0395d0Smrg for(duplicate = retval; duplicate != NULL; duplicate = duplicate->next) { 2697a0395d0Smrg if(duplicate->family == family && duplicate->len == len && 2707a0395d0Smrg memcmp(duplicate->address, src, len) == 0) { 2717a0395d0Smrg break; 2727a0395d0Smrg } 2737a0395d0Smrg } 2747a0395d0Smrg 2757a0395d0Smrg if (len > 0 && src != NULL && duplicate == NULL) { 2767a0395d0Smrg struct addrlist *newrv = malloc (sizeof(struct addrlist)); 2777a0395d0Smrg if (newrv) { 2787a0395d0Smrg newrv->address = malloc (len); 2797a0395d0Smrg if (newrv->address) { 2807a0395d0Smrg memcpy(newrv->address, src, len); 2817a0395d0Smrg newrv->next = NULL; 2827a0395d0Smrg newrv->family = family; 2837a0395d0Smrg newrv->len = len; 2847a0395d0Smrg if (retval == NULL) { 2857a0395d0Smrg lastrv = retval = newrv; 2867a0395d0Smrg } else { 2877a0395d0Smrg lastrv->next = newrv; 2887a0395d0Smrg lastrv = newrv; 2897a0395d0Smrg } 2907a0395d0Smrg } else { 2917a0395d0Smrg free(newrv); 2927a0395d0Smrg } 2937a0395d0Smrg } 2947a0395d0Smrg } 2957a0395d0Smrg /* reset to avoid copying into list twice */ 2967a0395d0Smrg len = 0; 2977a0395d0Smrg src = NULL; 2987a0395d0Smrg } 2997a0395d0Smrg freeaddrinfo(firstai); 3007a0395d0Smrg break; 3017a0395d0Smrg#else 3027a0395d0Smrg if (!get_inet_address (host, &hostinetaddr)) return NULL; 3037a0395d0Smrg src = (char *) &hostinetaddr; 3048abc0ccfSmrg if (*(const in_addr_t *) src == htonl(INADDR_LOOPBACK)) { 3058abc0ccfSmrg family = FamilyLocal; 3068abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 3078abc0ccfSmrg src = buf; 3088abc0ccfSmrg len = strlen (buf); 3098abc0ccfSmrg } else { 3108abc0ccfSmrg len = 0; 3118abc0ccfSmrg src = NULL; 3128abc0ccfSmrg } 3138abc0ccfSmrg } else 3148abc0ccfSmrg len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */ 3157a0395d0Smrg break; 3167a0395d0Smrg#endif /* IPv6 */ 3177a0395d0Smrg#else 3187a0395d0Smrg return NULL; 3197a0395d0Smrg#endif 3207a0395d0Smrg case FamilyDECnet: /* host::0 */ 3217a0395d0Smrg /* fall through since we don't have code for it */ 3227a0395d0Smrg default: 3237a0395d0Smrg src = NULL; 3247a0395d0Smrg len = 0; 3257a0395d0Smrg } 3267a0395d0Smrg 3277a0395d0Smrg /* 3287a0395d0Smrg * if source was provided, allocate space and copy it 3297a0395d0Smrg */ 3307a0395d0Smrg if (len > 0 && src != NULL) { 3317a0395d0Smrg retval = malloc (sizeof(struct addrlist)); 3327a0395d0Smrg if (retval) { 3337a0395d0Smrg retval->address = malloc (len); 3347a0395d0Smrg if (retval->address) { 3357a0395d0Smrg memcpy(retval->address, src, len); 3367a0395d0Smrg retval->next = NULL; 3377a0395d0Smrg retval->family = family; 3387a0395d0Smrg retval->len = len; 3397a0395d0Smrg } else { 3407a0395d0Smrg free(retval); 3417a0395d0Smrg retval = NULL; 3427a0395d0Smrg } 3437a0395d0Smrg } 3447a0395d0Smrg } 3457a0395d0Smrg return retval; 3467a0395d0Smrg} 347