gethost.c revision 273c00b8
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#include <sys/socket.h> 467a0395d0Smrg#include <netdb.h> 477a0395d0Smrg#include <netinet/in.h> 487a0395d0Smrg#include <arpa/inet.h> 497a0395d0Smrg#ifdef HAVE_NET_ERRNO_H 507a0395d0Smrg#include <net/errno.h> 517a0395d0Smrg#endif /* HAVE_NET_ERRNO_H */ 527a0395d0Smrg#endif /* !WIN32 */ 537a0395d0Smrg#include <errno.h> 547a0395d0Smrg#include "xauth.h" 557a0395d0Smrg 5640c5344fSmrg#include <sys/stat.h> 5740c5344fSmrg#include <limits.h> 587a0395d0Smrg 597a0395d0Smrg#ifndef WIN32 607a0395d0Smrg#include <arpa/inet.h> 617a0395d0Smrg#endif 627a0395d0Smrg 6396402570Smrgconst char * 647a0395d0Smrgget_hostname (Xauth *auth) 657a0395d0Smrg{ 667a0395d0Smrg if (auth->address_length == 0) 677a0395d0Smrg return "Illegal Address"; 687a0395d0Smrg#ifdef TCPCONN 697a0395d0Smrg if (auth->family == FamilyInternet 707a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 717a0395d0Smrg || auth->family == FamilyInternet6 7296402570Smrg#endif 737a0395d0Smrg ) 747a0395d0Smrg { 75273c00b8Smrg static struct hostent *hp = NULL; 76273c00b8Smrg int af; 77273c00b8Smrg 787a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 797a0395d0Smrg if (auth->family == FamilyInternet6) 807a0395d0Smrg af = AF_INET6; 817a0395d0Smrg else 827a0395d0Smrg#endif 837a0395d0Smrg af = AF_INET; 847a0395d0Smrg if (no_name_lookups == False) { 857a0395d0Smrg hp = gethostbyaddr (auth->address, auth->address_length, af); 867a0395d0Smrg } 877a0395d0Smrg if (hp) 887a0395d0Smrg return (hp->h_name); 897a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 907a0395d0Smrg else if (af == AF_INET6) { 917a0395d0Smrg static char addr[INET6_ADDRSTRLEN+2]; 927a0395d0Smrg /* Add [] for clarity to distinguish between address & display, 937a0395d0Smrg like RFC 2732 for URL's. Not required, since X display syntax 947a0395d0Smrg always ends in :<display>, but makes it easier for people to read 957a0395d0Smrg and less confusing to those who expect the RFC 2732 style. */ 967a0395d0Smrg addr[0] = '['; 977a0395d0Smrg if (inet_ntop(af, auth->address, addr + 1, INET6_ADDRSTRLEN) == NULL) 987a0395d0Smrg return NULL; 997a0395d0Smrg strcat(addr, "]"); 1007a0395d0Smrg return addr; 1017a0395d0Smrg } 1027a0395d0Smrg#endif 1037a0395d0Smrg else { 1047a0395d0Smrg return (inet_ntoa(*((struct in_addr *)(auth->address)))); 1057a0395d0Smrg } 1067a0395d0Smrg } 1077a0395d0Smrg#endif 1087a0395d0Smrg 1097a0395d0Smrg return (NULL); 1107a0395d0Smrg} 1117a0395d0Smrg 1127a0395d0Smrg#if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6)) 1137a0395d0Smrg/* 1147a0395d0Smrg * cribbed from lib/X/XConnDis.c 1157a0395d0Smrg */ 11696402570Smrgstatic Bool 1177a0395d0Smrgget_inet_address(char *name, unsigned int *resultp) 1187a0395d0Smrg{ 1197a0395d0Smrg unsigned int hostinetaddr = inet_addr (name); 1207a0395d0Smrg struct hostent *host_ptr; 1217a0395d0Smrg struct sockaddr_in inaddr; /* dummy variable for size calcs */ 1227a0395d0Smrg 1237a0395d0Smrg#ifndef INADDR_NONE 1247a0395d0Smrg#define INADDR_NONE -1 1257a0395d0Smrg#endif 1267a0395d0Smrg 1277a0395d0Smrg if (hostinetaddr == INADDR_NONE) { 1287a0395d0Smrg if ((host_ptr = gethostbyname (name)) == NULL) { 1297a0395d0Smrg /* No such host! */ 1307a0395d0Smrg errno = EINVAL; 1317a0395d0Smrg return False; 1327a0395d0Smrg } 1337a0395d0Smrg /* Check the address type for an internet host. */ 1347a0395d0Smrg if (host_ptr->h_addrtype != AF_INET) { 1357a0395d0Smrg /* Not an Internet host! */ 1367a0395d0Smrg errno = EPROTOTYPE; 1377a0395d0Smrg return False; 1387a0395d0Smrg } 13996402570Smrg 14096402570Smrg memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr, 1417a0395d0Smrg sizeof(inaddr.sin_addr)); 1427a0395d0Smrg } 1437a0395d0Smrg *resultp = hostinetaddr; 1447a0395d0Smrg return True; 1457a0395d0Smrg} 1467a0395d0Smrg#endif 1477a0395d0Smrg 1487a0395d0Smrg 1497a0395d0Smrgstruct addrlist *get_address_info ( 1507a0395d0Smrg int family, 15196402570Smrg const char *fulldpyname, 1527a0395d0Smrg int prefix, 1537a0395d0Smrg char *host) 1547a0395d0Smrg{ 1557a0395d0Smrg struct addrlist *retval = NULL; 1567a0395d0Smrg int len = 0; 15796402570Smrg const void *src = NULL; 1587a0395d0Smrg#ifdef TCPCONN 1597a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 1607a0395d0Smrg struct addrlist *lastrv = NULL; 1617a0395d0Smrg struct addrinfo *firstai = NULL; 1627a0395d0Smrg struct addrinfo hints; 1637a0395d0Smrg#else 1647a0395d0Smrg unsigned int hostinetaddr; 1657a0395d0Smrg#endif 1667a0395d0Smrg#endif 1677a0395d0Smrg char buf[255]; 1687a0395d0Smrg 1697a0395d0Smrg /* 1707a0395d0Smrg * based on the family, set the pointer src to the start of the address 1717a0395d0Smrg * information to be copied and set len to the number of bytes. 1727a0395d0Smrg */ 1737a0395d0Smrg switch (family) { 1747a0395d0Smrg case FamilyLocal: /* hostname/unix:0 */ 1757a0395d0Smrg /* handle unix:0 and :0 specially */ 1767a0395d0Smrg if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 || 1777a0395d0Smrg fulldpyname[0] == ':')) { 1787a0395d0Smrg 1797a0395d0Smrg if (!get_local_hostname (buf, sizeof buf)) { 1807a0395d0Smrg len = 0; 1817a0395d0Smrg } else { 1827a0395d0Smrg src = buf; 1837a0395d0Smrg len = strlen (buf); 1847a0395d0Smrg } 18540c5344fSmrg } else { 18640c5344fSmrg char path[PATH_MAX]; 18740c5344fSmrg struct stat sbuf; 18840c5344fSmrg int is_path_to_socket = 0; 18940c5344fSmrg 19040c5344fSmrg#ifdef HAVE_STRLCPY 19140c5344fSmrg strlcpy(path, fulldpyname, sizeof(path)); 19240c5344fSmrg#else 1930d22642bSmrg strncpy(path, fulldpyname, sizeof(path) - 1); 19440c5344fSmrg path[sizeof(path) - 1] = '\0'; 19540c5344fSmrg#endif 1960d22642bSmrg if (0 == stat(path, &sbuf) && S_ISSOCK(sbuf.st_mode) ) { 19740c5344fSmrg is_path_to_socket = 1; 19840c5344fSmrg } else { 19940c5344fSmrg char *dot = strrchr(path, '.'); 20040c5344fSmrg if (dot) { 20140c5344fSmrg *dot = '\0'; 20240c5344fSmrg /* screen = atoi(dot + 1); */ 2030d22642bSmrg if (0 == stat(path, &sbuf) && S_ISSOCK(sbuf.st_mode)) { 20440c5344fSmrg is_path_to_socket = 1; 20540c5344fSmrg } 20640c5344fSmrg } 20740c5344fSmrg } 20840c5344fSmrg 20940c5344fSmrg if (is_path_to_socket) { 21040c5344fSmrg /* Use the bundle id (part preceding : in the basename) as our src id */ 21140c5344fSmrg char *c; 2120d22642bSmrg c = strrchr(fulldpyname, '/'); 2132adc0320Smrg#ifdef HAVE_STRLCPY 2140d22642bSmrg strlcpy(buf, (NULL != c) ? c + 1 : fulldpyname, sizeof(buf)); 2152adc0320Smrg#else 2160d22642bSmrg strncpy(buf, (NULL != c) ? c + 1 : fulldpyname, sizeof(buf) - 1); 21740c5344fSmrg buf[sizeof(buf) - 1] = '\0'; 2182adc0320Smrg#endif 2192adc0320Smrg 22040c5344fSmrg c = strchr(buf, ':'); 22196402570Smrg 22240c5344fSmrg /* In the legacy case with no bundle id, use the full path */ 22340c5344fSmrg if(c == buf) { 22440c5344fSmrg src = fulldpyname; 22540c5344fSmrg } else { 22640c5344fSmrg *c = '\0'; 22740c5344fSmrg src = buf; 22840c5344fSmrg } 2292adc0320Smrg 23040c5344fSmrg len = strlen(src); 23140c5344fSmrg } else { 23240c5344fSmrg src = fulldpyname; 23340c5344fSmrg len = prefix; 23440c5344fSmrg } 2357a0395d0Smrg } 2367a0395d0Smrg break; 2377a0395d0Smrg case FamilyInternet: /* host:0 */ 2387a0395d0Smrg#ifdef TCPCONN 2397a0395d0Smrg#if defined(IPv6) && defined(AF_INET6) 2407a0395d0Smrg case FamilyInternet6: 2417a0395d0Smrg memset(&hints, 0, sizeof(hints)); 2427a0395d0Smrg hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 */ 2437a0395d0Smrg hints.ai_socktype = SOCK_STREAM; /* only interested in TCP */ 24496402570Smrg hints.ai_protocol = 0; 2457a0395d0Smrg if (getaddrinfo(host,NULL,&hints,&firstai) !=0) return NULL; 246273c00b8Smrg for (struct addrinfo *ai = firstai; ai != NULL; ai = ai->ai_next) { 2477366012aSmrg struct addrlist *duplicate; 2487366012aSmrg 2498abc0ccfSmrg len = 0; 2507a0395d0Smrg if (ai->ai_family == AF_INET) { 2517a0395d0Smrg struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; 2527a0395d0Smrg src = &(sin->sin_addr); 2538abc0ccfSmrg if (*(const in_addr_t *) src == htonl(INADDR_LOOPBACK)) { 2548abc0ccfSmrg family = FamilyLocal; 2558abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 2568abc0ccfSmrg src = buf; 2578abc0ccfSmrg len = strlen (buf); 2588abc0ccfSmrg } else 2598abc0ccfSmrg src = NULL; 2608abc0ccfSmrg } else { 2618abc0ccfSmrg len = sizeof(sin->sin_addr); 2628abc0ccfSmrg family = FamilyInternet; 2638abc0ccfSmrg } 2647a0395d0Smrg } else if (ai->ai_family == AF_INET6) { 2657a0395d0Smrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; 2667a0395d0Smrg src = &(sin6->sin6_addr); 2678abc0ccfSmrg if (!IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) { 2688abc0ccfSmrg if (IN6_IS_ADDR_LOOPBACK((const struct in6_addr *)src)) { 2698abc0ccfSmrg family = FamilyLocal; 2708abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 2718abc0ccfSmrg src = buf; 2728abc0ccfSmrg len = strlen (buf); 2738abc0ccfSmrg } else 2748abc0ccfSmrg src = NULL; 2758abc0ccfSmrg } else { 2768abc0ccfSmrg len = sizeof(sin6->sin6_addr); 2778abc0ccfSmrg family = FamilyInternet6; 2788abc0ccfSmrg } 2798abc0ccfSmrg } else { 2808abc0ccfSmrg src = &(sin6->sin6_addr.s6_addr[12]); 2818abc0ccfSmrg len = sizeof(((struct sockaddr_in *) 2828abc0ccfSmrg ai->ai_addr)->sin_addr); 2838abc0ccfSmrg family = FamilyInternet; 2848abc0ccfSmrg } 2857a0395d0Smrg } 2867a0395d0Smrg 2877a0395d0Smrg for(duplicate = retval; duplicate != NULL; duplicate = duplicate->next) { 2887a0395d0Smrg if(duplicate->family == family && duplicate->len == len && 2897a0395d0Smrg memcmp(duplicate->address, src, len) == 0) { 2907a0395d0Smrg break; 2917a0395d0Smrg } 2927a0395d0Smrg } 2937a0395d0Smrg 2947a0395d0Smrg if (len > 0 && src != NULL && duplicate == NULL) { 2957a0395d0Smrg struct addrlist *newrv = malloc (sizeof(struct addrlist)); 2967a0395d0Smrg if (newrv) { 2977a0395d0Smrg newrv->address = malloc (len); 2987a0395d0Smrg if (newrv->address) { 2997a0395d0Smrg memcpy(newrv->address, src, len); 3007a0395d0Smrg newrv->next = NULL; 3017a0395d0Smrg newrv->family = family; 3027a0395d0Smrg newrv->len = len; 3037a0395d0Smrg if (retval == NULL) { 3047a0395d0Smrg lastrv = retval = newrv; 3057a0395d0Smrg } else { 3067a0395d0Smrg lastrv->next = newrv; 3077a0395d0Smrg lastrv = newrv; 3087a0395d0Smrg } 3097a0395d0Smrg } else { 3107a0395d0Smrg free(newrv); 3117a0395d0Smrg } 3127a0395d0Smrg } 3137a0395d0Smrg } 3147a0395d0Smrg /* reset to avoid copying into list twice */ 3157a0395d0Smrg len = 0; 3167a0395d0Smrg src = NULL; 3177a0395d0Smrg } 3187a0395d0Smrg freeaddrinfo(firstai); 3197a0395d0Smrg break; 3207a0395d0Smrg#else 3217a0395d0Smrg if (!get_inet_address (host, &hostinetaddr)) return NULL; 3227a0395d0Smrg src = (char *) &hostinetaddr; 3238abc0ccfSmrg if (*(const in_addr_t *) src == htonl(INADDR_LOOPBACK)) { 3248abc0ccfSmrg family = FamilyLocal; 3258abc0ccfSmrg if (get_local_hostname (buf, sizeof buf)) { 3268abc0ccfSmrg src = buf; 3278abc0ccfSmrg len = strlen (buf); 3288abc0ccfSmrg } else { 3298abc0ccfSmrg len = 0; 3308abc0ccfSmrg src = NULL; 3318abc0ccfSmrg } 3328abc0ccfSmrg } else 3338abc0ccfSmrg len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */ 3347a0395d0Smrg break; 3357a0395d0Smrg#endif /* IPv6 */ 3367a0395d0Smrg#else 3377a0395d0Smrg return NULL; 3387a0395d0Smrg#endif 3397a0395d0Smrg case FamilyDECnet: /* host::0 */ 3407a0395d0Smrg /* fall through since we don't have code for it */ 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