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