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