Upload Tizen:Main source
[pkgs/xorg/util/xorg-x11-xauth.git] / gethost.c
1 /*
2  * $Xorg: gethost.c,v 1.5 2001/02/09 02:05:38 xorgcvs Exp $
3  * $XdotOrg: $
4  * 
5 Copyright 1989, 1998  The Open Group
6
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
11 documentation.
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
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.
22
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.
26  * *
27  * Author:  Jim Fulton, MIT X Consortium
28  */
29
30 /* $XFree86: xc/programs/xauth/gethost.c,v 3.20 2003/07/27 12:34:25 herrb Exp $ */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 /* sorry, streams support does not really work yet */
37 #if defined(STREAMSCONN) && defined(SVR4)
38 #undef STREAMSCONN
39 #define TCPCONN
40 #endif
41
42 #ifdef WIN32
43 #include <X11/Xwinsock.h>
44 #define EPROTOTYPE WSAEPROTOTYPE
45 #endif
46 #include <X11/X.h>
47 #include <signal.h>
48 #include <setjmp.h>
49 #include <ctype.h>
50 #ifndef __TYPES__
51 #include <sys/types.h>
52 #define __TYPES__
53 #endif
54 #ifndef WIN32
55 #ifndef STREAMSCONN
56 #ifndef Lynx
57 #include <sys/socket.h>
58 #else
59 #include <socket.h>
60 #endif
61 #include <netdb.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 */
68 #endif /* !WIN32 */
69 #include <errno.h>
70 #include "xauth.h"
71
72 #ifdef DNETCONN
73 #include <netdnet/dn.h>
74 #include <netdnet/dnetdb.h>
75 #endif
76
77 #ifndef WIN32
78 #include <arpa/inet.h>
79 #endif
80
81 #ifdef SIGALRM
82 static volatile Bool nameserver_timedout = False;
83
84
85 /*
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.
89  */
90
91 static jmp_buf env;
92 static RETSIGTYPE
93 nameserver_lost(int sig)
94 {
95   nameserver_timedout = True;
96   longjmp (env, -1);
97   /* NOTREACHED */
98 #ifdef SIGNALRETURNSINT
99   return -1;                            /* for picky compilers */
100 #endif
101 }
102 #endif
103
104 char *
105 get_hostname (Xauth *auth)
106 {
107     static struct hostent *hp;
108     int af;
109 #ifdef DNETCONN
110     struct nodeent *np;
111     static char nodeaddr[4 + 2 * DN_MAXADDL];
112 #endif /* DNETCONN */
113
114     hp = NULL;
115     if (auth->address_length == 0)
116         return "Illegal Address";
117 #ifdef TCPCONN
118     if (auth->family == FamilyInternet
119 #if defined(IPv6) && defined(AF_INET6)
120       || auth->family == FamilyInternet6
121 #endif 
122         )
123     {
124 #if defined(IPv6) && defined(AF_INET6)
125         if (auth->family == FamilyInternet6)
126             af = AF_INET6;
127         else
128 #endif
129             af = AF_INET;
130         if (no_name_lookups == False) {
131 #ifdef SIGALRM
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
136            jump out of it. 
137            */
138         nameserver_timedout = False;
139         signal (SIGALRM, nameserver_lost);
140         alarm (4);
141         if (setjmp(env) == 0) {
142 #endif
143             hp = gethostbyaddr (auth->address, auth->address_length, af);
144 #ifdef SIGALRM
145         }
146         alarm (0);
147 #endif
148         }
149         if (hp)
150           return (hp->h_name);
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. */
158           addr[0] = '[';
159           if (inet_ntop(af, auth->address, addr + 1, INET6_ADDRSTRLEN) == NULL)
160             return NULL;
161           strcat(addr, "]");
162           return addr;
163         }
164 #endif
165         else {
166           return (inet_ntoa(*((struct in_addr *)(auth->address))));
167         }
168     }
169 #endif
170 #ifdef DNETCONN
171     if (auth->family == FamilyDECnet) {
172         struct dn_naddr *addr_ptr = (struct dn_naddr *) auth->address;
173
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);
177         } else {
178             sprintf(nodeaddr, "%s:", dnet_htoa(auth->address));
179         }
180         return(nodeaddr);
181     }
182 #endif
183
184     return (NULL);
185 }
186
187 #if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6))
188 /*
189  * cribbed from lib/X/XConnDis.c
190  */
191 static Bool 
192 get_inet_address(char *name, unsigned int *resultp)
193 {
194     unsigned int hostinetaddr = inet_addr (name);
195     struct hostent *host_ptr;
196     struct sockaddr_in inaddr;          /* dummy variable for size calcs */
197
198 #ifndef INADDR_NONE
199 #define INADDR_NONE -1
200 #endif
201
202     if (hostinetaddr == INADDR_NONE) {
203         if ((host_ptr = gethostbyname (name)) == NULL) {
204             /* No such host! */
205             errno = EINVAL;
206             return False;
207         }
208         /* Check the address type for an internet host. */
209         if (host_ptr->h_addrtype != AF_INET) {
210             /* Not an Internet host! */
211             errno = EPROTOTYPE;
212             return False;
213         }
214  
215         memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr, 
216               sizeof(inaddr.sin_addr));
217     }
218     *resultp = hostinetaddr;
219     return True;
220 }
221 #endif
222
223 #ifdef DNETCONN
224 static Bool get_dnet_address (name, resultp)
225     char *name;
226     struct dn_naddr *resultp;
227 {
228     struct dn_naddr *dnaddrp, dnaddr;
229     struct nodeent *np;
230
231     if (dnaddrp = dnet_addr (name)) {   /* stolen from xhost */
232         dnaddr = *dnaddrp;
233     } else {
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);
237     }
238     *resultp = dnaddr;
239     return True;
240 }
241 #endif
242
243 struct addrlist *get_address_info (
244     int family,
245     char *fulldpyname,
246     int prefix,
247     char *host)
248 {
249     struct addrlist *retval = NULL;
250     int len = 0;
251     void *src = NULL;
252 #ifdef TCPCONN
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;
258 #else
259     unsigned int hostinetaddr;
260 #endif
261 #endif
262 #ifdef DNETCONN
263     struct dn_naddr dnaddr;
264 #endif
265     char buf[255];
266
267     /*
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.
270      */
271     switch (family) {
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] == ':')) {
276
277             if (!get_local_hostname (buf, sizeof buf)) {
278                 len = 0;
279             } else {
280                 src = buf;
281                 len = strlen (buf);
282             }
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 */
285         char *c;
286 #ifdef HAVE_STRLCPY
287         strlcpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf));
288 #else
289         strncpy(buf, strrchr(fulldpyname, '/') + 1, sizeof(buf));
290         buf[sizeof(buf) - 1] = '\0';
291 #endif
292
293         c = strchr(buf, ':');
294         
295         /* In the legacy case with no bundle id, use the full path */
296         if(c == buf) {
297             src = fulldpyname;
298         } else {
299             *c = '\0';
300             src = buf;
301         }
302
303         len = strlen(src);
304     } else {
305             src = fulldpyname;
306             len = prefix;
307         }
308         break;
309       case FamilyInternet:              /* host:0 */
310 #ifdef TCPCONN
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;
320
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;
331             }
332
333             for(duplicate = retval; duplicate != NULL; duplicate = duplicate->next) {
334                 if(duplicate->family == family && duplicate->len == len &&
335                    memcmp(duplicate->address, src, len) == 0) {
336                     break;
337                 }
338             }
339
340             if (len > 0 && src != NULL && duplicate == NULL) {
341                 struct addrlist *newrv = malloc (sizeof(struct addrlist));
342                 if (newrv) {
343                     newrv->address = malloc (len);
344                     if (newrv->address) {
345                         memcpy(newrv->address, src, len);
346                         newrv->next = NULL;
347                         newrv->family = family;
348                         newrv->len = len;
349                         if (retval == NULL) {
350                             lastrv = retval = newrv;
351                         } else {
352                             lastrv->next = newrv;
353                             lastrv = newrv;
354                         }
355                     } else {
356                         free(newrv);
357                     }
358                 }
359             }
360             /* reset to avoid copying into list twice */
361             len = 0;
362             src = NULL;
363         }
364         freeaddrinfo(firstai);
365         break;
366 #else
367         if (!get_inet_address (host, &hostinetaddr)) return NULL;
368         src = (char *) &hostinetaddr;
369         len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */
370         break;
371 #endif /* IPv6 */
372 #else
373         return NULL;
374 #endif
375       case FamilyDECnet:                /* host::0 */
376 #ifdef DNETCONN
377         if (!get_dnet_address (host, &dnaddr)) return NULL;
378         src = (char *) &dnaddr;
379         len = (sizeof dnaddr);
380         break;
381 #else
382         /* fall through since we don't have code for it */
383 #endif
384       default:
385         src = NULL;
386         len = 0;
387     }
388
389     /*
390      * if source was provided, allocate space and copy it
391      */
392     if (len > 0 && src != NULL) {
393         retval = malloc (sizeof(struct addrlist));
394         if (retval) {
395             retval->address = malloc (len);
396             if (retval->address) {
397                 memcpy(retval->address, src, len);
398                 retval->next = NULL;
399                 retval->family = family;
400                 retval->len = len;
401             } else {
402                 free(retval);
403                 retval = NULL;
404             }
405         }
406     }
407     return retval;
408 }