2 * $Xorg: gethost.c,v 1.5 2001/02/09 02:05:38 xorgcvs Exp $
5 Copyright 1989, 1998 The Open Group
7 Permission to use, copy, modify, distribute, and sell this software and its
8 documentation for any purpose is hereby granted without fee, provided that
9 the above copyright notice appear in all copies and that both that
10 copyright notice and this permission notice appear in supporting
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of The Open Group shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from The Open Group.
27 * Author: Jim Fulton, MIT X Consortium
30 /* $XFree86: xc/programs/xauth/gethost.c,v 3.20 2003/07/27 12:34:25 herrb Exp $ */
36 /* sorry, streams support does not really work yet */
37 #if defined(STREAMSCONN) && defined(SVR4)
43 #include <X11/Xwinsock.h>
44 #define EPROTOTYPE WSAEPROTOTYPE
51 #include <sys/types.h>
57 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
64 #ifdef HAVE_NET_ERRNO_H
65 #include <net/errno.h>
66 #endif /* HAVE_NET_ERRNO_H */
67 #endif /* !STREAMSCONN */
73 #include <netdnet/dn.h>
74 #include <netdnet/dnetdb.h>
78 #include <arpa/inet.h>
82 static volatile Bool nameserver_timedout = False;
86 * get_hostname - Given an internet address, return a name (CHARON.MIT.EDU)
87 * or a string representing the address (18.58.0.13) if the name cannot
88 * be found. Stolen from xhost.
93 nameserver_lost(int sig)
95 nameserver_timedout = True;
98 #ifdef SIGNALRETURNSINT
99 return -1; /* for picky compilers */
105 get_hostname (Xauth *auth)
107 static struct hostent *hp;
111 static char nodeaddr[4 + 2 * DN_MAXADDL];
112 #endif /* DNETCONN */
115 if (auth->address_length == 0)
116 return "Illegal Address";
118 if (auth->family == FamilyInternet
119 #if defined(IPv6) && defined(AF_INET6)
120 || auth->family == FamilyInternet6
124 #if defined(IPv6) && defined(AF_INET6)
125 if (auth->family == FamilyInternet6)
130 if (no_name_lookups == False) {
132 /* gethostbyaddr can take a LONG time if the host does not exist.
133 Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
134 that something is wrong and do not make the user wait.
135 gethostbyaddr will continue after a signal, so we have to
138 nameserver_timedout = False;
139 signal (SIGALRM, nameserver_lost);
141 if (setjmp(env) == 0) {
143 hp = gethostbyaddr (auth->address, auth->address_length, af);
151 #if defined(IPv6) && defined(AF_INET6)
152 else if (af == AF_INET6) {
153 static char addr[INET6_ADDRSTRLEN+2];
154 /* Add [] for clarity to distinguish between address & display,
155 like RFC 2732 for URL's. Not required, since X display syntax
156 always ends in :<display>, but makes it easier for people to read
157 and less confusing to those who expect the RFC 2732 style. */
159 if (inet_ntop(af, auth->address, addr + 1, INET6_ADDRSTRLEN) == NULL)
166 return (inet_ntoa(*((struct in_addr *)(auth->address))));
171 if (auth->family == FamilyDECnet) {
172 struct dn_naddr *addr_ptr = (struct dn_naddr *) auth->address;
174 if ((no_name_lookups == False) &&
175 (np = getnodebyaddr(addr_ptr->a_addr, addr_ptr->a_len, AF_DECnet))) {
176 sprintf(nodeaddr, "%s:", np->n_name);
178 sprintf(nodeaddr, "%s:", dnet_htoa(auth->address));
187 #if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6))
189 * cribbed from lib/X/XConnDis.c
192 get_inet_address(char *name, unsigned int *resultp)
194 unsigned int hostinetaddr = inet_addr (name);
195 struct hostent *host_ptr;
196 struct sockaddr_in inaddr; /* dummy variable for size calcs */
199 #define INADDR_NONE -1
202 if (hostinetaddr == INADDR_NONE) {
203 if ((host_ptr = gethostbyname (name)) == NULL) {
208 /* Check the address type for an internet host. */
209 if (host_ptr->h_addrtype != AF_INET) {
210 /* Not an Internet host! */
215 memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr,
216 sizeof(inaddr.sin_addr));
218 *resultp = hostinetaddr;
224 static Bool get_dnet_address (name, resultp)
226 struct dn_naddr *resultp;
228 struct dn_naddr *dnaddrp, dnaddr;
231 if (dnaddrp = dnet_addr (name)) { /* stolen from xhost */
234 if ((np = getnodebyname (name)) == NULL) return False;
235 dnaddr.a_len = np->n_length;
236 memmove( dnaddr.a_addr, np->n_addr, np->n_length);
243 struct addrlist *get_address_info (
249 struct addrlist *retval = NULL;
253 #if defined(IPv6) && defined(AF_INET6)
254 struct addrlist *lastrv = NULL;
255 struct addrinfo *firstai = NULL;
256 struct addrinfo *ai = NULL;
257 struct addrinfo hints;
259 unsigned int hostinetaddr;
263 struct dn_naddr dnaddr;
268 * based on the family, set the pointer src to the start of the address
269 * information to be copied and set len to the number of bytes.
272 case FamilyLocal: /* hostname/unix:0 */
273 /* handle unix:0 and :0 specially */
274 if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 ||
275 fulldpyname[0] == ':')) {
277 if (!get_local_hostname (buf, sizeof buf)) {
283 } else if(prefix == 0 && (strncmp (fulldpyname, "/tmp/launch", 11) == 0)) {
284 /* Use the bundle id (part preceding : in the basename) as our src id */
287 strlcpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf));
289 strncpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf));
290 buf[sizeof(buf) - 1] = '\0';
293 c = strchr(buf, ':');
295 /* In the legacy case with no bundle id, use the full path */
309 case FamilyInternet: /* host:0 */
311 #if defined(IPv6) && defined(AF_INET6)
312 case FamilyInternet6:
313 memset(&hints, 0, sizeof(hints));
314 hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 */
315 hints.ai_socktype = SOCK_STREAM; /* only interested in TCP */
316 hints.ai_protocol = 0;
317 if (getaddrinfo(host,NULL,&hints,&firstai) !=0) return NULL;
318 for (ai = firstai; ai != NULL; ai = ai->ai_next) {
319 struct addrlist *duplicate;
321 if (ai->ai_family == AF_INET) {
322 struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
323 src = &(sin->sin_addr);
324 len = sizeof(sin->sin_addr);
325 family = FamilyInternet;
326 } else if (ai->ai_family == AF_INET6) {
327 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
328 src = &(sin6->sin6_addr);
329 len = sizeof(sin6->sin6_addr);
330 family = FamilyInternet6;
333 for(duplicate = retval; duplicate != NULL; duplicate = duplicate->next) {
334 if(duplicate->family == family && duplicate->len == len &&
335 memcmp(duplicate->address, src, len) == 0) {
340 if (len > 0 && src != NULL && duplicate == NULL) {
341 struct addrlist *newrv = malloc (sizeof(struct addrlist));
343 newrv->address = malloc (len);
344 if (newrv->address) {
345 memcpy(newrv->address, src, len);
347 newrv->family = family;
349 if (retval == NULL) {
350 lastrv = retval = newrv;
352 lastrv->next = newrv;
360 /* reset to avoid copying into list twice */
364 freeaddrinfo(firstai);
367 if (!get_inet_address (host, &hostinetaddr)) return NULL;
368 src = (char *) &hostinetaddr;
369 len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */
375 case FamilyDECnet: /* host::0 */
377 if (!get_dnet_address (host, &dnaddr)) return NULL;
378 src = (char *) &dnaddr;
379 len = (sizeof dnaddr);
382 /* fall through since we don't have code for it */
390 * if source was provided, allocate space and copy it
392 if (len > 0 && src != NULL) {
393 retval = malloc (sizeof(struct addrlist));
395 retval->address = malloc (len);
396 if (retval->address) {
397 memcpy(retval->address, src, len);
399 retval->family = family;