aboutsummaryrefslogtreecommitdiff
path: root/apps/xauth/gethost.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/xauth/gethost.c')
-rw-r--r--apps/xauth/gethost.c404
1 files changed, 404 insertions, 0 deletions
diff --git a/apps/xauth/gethost.c b/apps/xauth/gethost.c
new file mode 100644
index 000000000..acac86478
--- /dev/null
+++ b/apps/xauth/gethost.c
@@ -0,0 +1,404 @@
+/*
+ *
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ * *
+ * Author: Jim Fulton, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* sorry, streams support does not really work yet */
+#if defined(STREAMSCONN) && defined(SVR4)
+#undef STREAMSCONN
+#define TCPCONN
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#define EPROTOTYPE WSAEPROTOTYPE
+#endif
+#include <X11/X.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <ctype.h>
+#ifndef __TYPES__
+#include <sys/types.h>
+#define __TYPES__
+#endif
+#ifndef WIN32
+#ifndef STREAMSCONN
+#ifndef Lynx
+#include <sys/socket.h>
+#else
+#include <socket.h>
+#endif
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef HAVE_NET_ERRNO_H
+#include <net/errno.h>
+#endif /* HAVE_NET_ERRNO_H */
+#endif /* !STREAMSCONN */
+#endif /* !WIN32 */
+#include <errno.h>
+#include "xauth.h"
+
+#ifdef DNETCONN
+#include <netdnet/dn.h>
+#include <netdnet/dnetdb.h>
+#endif
+
+#ifndef WIN32
+#include <arpa/inet.h>
+#endif
+
+#ifdef SIGALRM
+static volatile Bool nameserver_timedout = False;
+
+
+/*
+ * get_hostname - Given an internet address, return a name (CHARON.MIT.EDU)
+ * or a string representing the address (18.58.0.13) if the name cannot
+ * be found. Stolen from xhost.
+ */
+
+static jmp_buf env;
+static RETSIGTYPE
+nameserver_lost(int sig)
+{
+ nameserver_timedout = True;
+ longjmp (env, -1);
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+#endif
+
+char *
+get_hostname (Xauth *auth)
+{
+ static struct hostent *hp;
+ int af;
+#ifdef DNETCONN
+ struct nodeent *np;
+ static char nodeaddr[4 + 2 * DN_MAXADDL];
+#endif /* DNETCONN */
+
+ hp = NULL;
+ if (auth->address_length == 0)
+ return "Illegal Address";
+#ifdef TCPCONN
+ if (auth->family == FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ || auth->family == FamilyInternet6
+#endif
+ )
+ {
+#if defined(IPv6) && defined(AF_INET6)
+ if (auth->family == FamilyInternet6)
+ af = AF_INET6;
+ else
+#endif
+ af = AF_INET;
+ if (no_name_lookups == False) {
+#ifdef SIGALRM
+ /* gethostbyaddr can take a LONG time if the host does not exist.
+ Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
+ that something is wrong and do not make the user wait.
+ gethostbyaddr will continue after a signal, so we have to
+ jump out of it.
+ */
+ nameserver_timedout = False;
+ signal (SIGALRM, nameserver_lost);
+ alarm (4);
+ if (setjmp(env) == 0) {
+#endif
+ hp = gethostbyaddr (auth->address, auth->address_length, af);
+#ifdef SIGALRM
+ }
+ alarm (0);
+#endif
+ }
+ if (hp)
+ return (hp->h_name);
+#if defined(IPv6) && defined(AF_INET6)
+ else if (af == AF_INET6) {
+ static char addr[INET6_ADDRSTRLEN+2];
+ /* Add [] for clarity to distinguish between address & display,
+ like RFC 2732 for URL's. Not required, since X display syntax
+ always ends in :<display>, but makes it easier for people to read
+ and less confusing to those who expect the RFC 2732 style. */
+ addr[0] = '[';
+ if (inet_ntop(af, auth->address, addr + 1, INET6_ADDRSTRLEN) == NULL)
+ return NULL;
+ strcat(addr, "]");
+ return addr;
+ }
+#endif
+ else {
+ return (inet_ntoa(*((struct in_addr *)(auth->address))));
+ }
+ }
+#endif
+#ifdef DNETCONN
+ if (auth->family == FamilyDECnet) {
+ struct dn_naddr *addr_ptr = (struct dn_naddr *) auth->address;
+
+ if ((no_name_lookups == False) &&
+ (np = getnodebyaddr(addr_ptr->a_addr, addr_ptr->a_len, AF_DECnet))) {
+ sprintf(nodeaddr, "%s:", np->n_name);
+ } else {
+ sprintf(nodeaddr, "%s:", dnet_htoa(auth->address));
+ }
+ return(nodeaddr);
+ }
+#endif
+
+ return (NULL);
+}
+
+#if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6))
+/*
+ * cribbed from lib/X/XConnDis.c
+ */
+static Bool
+get_inet_address(char *name, unsigned int *resultp)
+{
+ unsigned int hostinetaddr = inet_addr (name);
+ struct hostent *host_ptr;
+ struct sockaddr_in inaddr; /* dummy variable for size calcs */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
+
+ if (hostinetaddr == INADDR_NONE) {
+ if ((host_ptr = gethostbyname (name)) == NULL) {
+ /* No such host! */
+ errno = EINVAL;
+ return False;
+ }
+ /* Check the address type for an internet host. */
+ if (host_ptr->h_addrtype != AF_INET) {
+ /* Not an Internet host! */
+ errno = EPROTOTYPE;
+ return False;
+ }
+
+ memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr,
+ sizeof(inaddr.sin_addr));
+ }
+ *resultp = hostinetaddr;
+ return True;
+}
+#endif
+
+#ifdef DNETCONN
+static Bool get_dnet_address (name, resultp)
+ char *name;
+ struct dn_naddr *resultp;
+{
+ struct dn_naddr *dnaddrp, dnaddr;
+ struct nodeent *np;
+
+ if (dnaddrp = dnet_addr (name)) { /* stolen from xhost */
+ dnaddr = *dnaddrp;
+ } else {
+ if ((np = getnodebyname (name)) == NULL) return False;
+ dnaddr.a_len = np->n_length;
+ memmove( dnaddr.a_addr, np->n_addr, np->n_length);
+ }
+ *resultp = dnaddr;
+ return True;
+}
+#endif
+
+struct addrlist *get_address_info (
+ int family,
+ char *fulldpyname,
+ int prefix,
+ char *host)
+{
+ struct addrlist *retval = NULL;
+ int len = 0;
+ void *src = NULL;
+#ifdef TCPCONN
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrlist *lastrv = NULL;
+ struct addrinfo *firstai = NULL;
+ struct addrinfo *ai = NULL;
+ struct addrinfo hints;
+#else
+ unsigned int hostinetaddr;
+#endif
+#endif
+#ifdef DNETCONN
+ struct dn_naddr dnaddr;
+#endif
+ char buf[255];
+
+ /*
+ * based on the family, set the pointer src to the start of the address
+ * information to be copied and set len to the number of bytes.
+ */
+ switch (family) {
+ case FamilyLocal: /* hostname/unix:0 */
+ /* handle unix:0 and :0 specially */
+ if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 ||
+ fulldpyname[0] == ':')) {
+
+ if (!get_local_hostname (buf, sizeof buf)) {
+ len = 0;
+ } else {
+ src = buf;
+ len = strlen (buf);
+ }
+ } else if(prefix == 0 && (strncmp (fulldpyname, "/tmp/launch", 11) == 0)) {
+ /* Use the bundle id (part preceding : in the basename) as our src id */
+ char *c;
+#ifdef HAVE_STRLCPY
+ strlcpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf));
+#else
+ strncpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+#endif
+
+ c = strchr(buf, ':');
+
+ /* In the legacy case with no bundle id, use the full path */
+ if(c == buf) {
+ src = fulldpyname;
+ } else {
+ *c = '\0';
+ src = buf;
+ }
+
+ len = strlen(src);
+ } else {
+ src = fulldpyname;
+ len = prefix;
+ }
+ break;
+ case FamilyInternet: /* host:0 */
+#ifdef TCPCONN
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_STREAM; /* only interested in TCP */
+ hints.ai_protocol = 0;
+ if (getaddrinfo(host,NULL,&hints,&firstai) !=0) return NULL;
+ for (ai = firstai; ai != NULL; ai = ai->ai_next) {
+ struct addrlist *duplicate;
+
+ if (ai->ai_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
+ src = &(sin->sin_addr);
+ len = sizeof(sin->sin_addr);
+ family = FamilyInternet;
+ } else if (ai->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
+ src = &(sin6->sin6_addr);
+ len = sizeof(sin6->sin6_addr);
+ family = FamilyInternet6;
+ }
+
+ for(duplicate = retval; duplicate != NULL; duplicate = duplicate->next) {
+ if(duplicate->family == family && duplicate->len == len &&
+ memcmp(duplicate->address, src, len) == 0) {
+ break;
+ }
+ }
+
+ if (len > 0 && src != NULL && duplicate == NULL) {
+ struct addrlist *newrv = malloc (sizeof(struct addrlist));
+ if (newrv) {
+ newrv->address = malloc (len);
+ if (newrv->address) {
+ memcpy(newrv->address, src, len);
+ newrv->next = NULL;
+ newrv->family = family;
+ newrv->len = len;
+ if (retval == NULL) {
+ lastrv = retval = newrv;
+ } else {
+ lastrv->next = newrv;
+ lastrv = newrv;
+ }
+ } else {
+ free(newrv);
+ }
+ }
+ }
+ /* reset to avoid copying into list twice */
+ len = 0;
+ src = NULL;
+ }
+ freeaddrinfo(firstai);
+ break;
+#else
+ if (!get_inet_address (host, &hostinetaddr)) return NULL;
+ src = (char *) &hostinetaddr;
+ len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */
+ break;
+#endif /* IPv6 */
+#else
+ return NULL;
+#endif
+ case FamilyDECnet: /* host::0 */
+#ifdef DNETCONN
+ if (!get_dnet_address (host, &dnaddr)) return NULL;
+ src = (char *) &dnaddr;
+ len = (sizeof dnaddr);
+ break;
+#else
+ /* fall through since we don't have code for it */
+#endif
+ default:
+ src = NULL;
+ len = 0;
+ }
+
+ /*
+ * if source was provided, allocate space and copy it
+ */
+ if (len > 0 && src != NULL) {
+ retval = malloc (sizeof(struct addrlist));
+ if (retval) {
+ retval->address = malloc (len);
+ if (retval->address) {
+ memcpy(retval->address, src, len);
+ retval->next = NULL;
+ retval->family = family;
+ retval->len = len;
+ } else {
+ free(retval);
+ retval = NULL;
+ }
+ }
+ }
+ return retval;
+}