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