source: trunk/athena/bin/hostinfo/gethostnamadr.c @ 5279

Revision 5279, 10.4 KB checked in by epeisach, 33 years ago (diff)
[tom] mx queries and fixes to allow multiple host lookups\
Line 
1/*
2 * Copyright (c) 1985, 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley.  The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18#if defined(LIBC_SCCS) && !defined(lint)
19static char sccsid[] = "@(#)gethostnamadr.c     6.36 (Berkeley) 10/7/88";
20#endif /* LIBC_SCCS and not lint */
21
22#ifdef _IBMR2
23#define BIT_ZERO_ON_LEFT
24#endif
25
26#ifdef _AUX_SOURCE    /* who's the shithead who think up these things? */
27#include <sys/types.h>
28#endif
29
30#include <sys/param.h>
31#include <sys/socket.h>
32#include <netinet/in.h>
33#include <ctype.h>
34#include <netdb.h>
35#include <stdio.h>
36#include <errno.h>
37#include <arpa/inet.h>
38#include <arpa/nameser.h>
39#include <resolv.h>
40
41#define MAXALIASES      35
42#define MAXADDRS        35
43
44static char *h_addr_ptrs[MAXADDRS + 1];
45
46static struct hostent host;
47static char *host_aliases[MAXALIASES];
48static char hostbuf[BUFSIZ+1];
49static struct in_addr host_addr;
50static char HOSTDB[] = "/etc/hosts";
51static FILE *hostf = NULL;
52static char hostaddr[MAXADDRS];
53static char *host_addrs[2];
54static int stayopen = 0;
55static char *any();
56
57#if PACKETSZ > 1024
58#define MAXPACKET       PACKETSZ
59#else
60#define MAXPACKET       1024
61#endif
62
63typedef union {
64    HEADER hdr;
65    u_char buf[MAXPACKET];
66} querybuf;
67
68typedef union {
69    long al;
70    char ac;
71} align;
72
73
74int h_errno;
75extern errno;
76
77static struct hostent *
78getanswer(answer, anslen, iquery, info)
79        querybuf *answer;
80        int anslen;
81        int iquery;
82        char **info;
83{
84        register HEADER *hp;
85        register u_char *cp;
86        register int n;
87        u_char *eom;
88        char *bp, **ap;
89        int type, class, buflen, ancount, qdcount;
90        int haveanswer, getclass = C_ANY;
91        char **hap;
92
93        eom = answer->buf + anslen;
94        /*
95         * find first satisfactory answer
96         */
97        hp = &answer->hdr;
98        ancount = ntohs(hp->ancount);
99        qdcount = ntohs(hp->qdcount);
100        bp = hostbuf;
101        buflen = sizeof(hostbuf);
102        cp = answer->buf + sizeof(HEADER);
103        if (qdcount) {
104                if (iquery) {
105                        if ((n = dn_expand((char *)answer->buf, eom,
106                             cp, bp, buflen)) < 0) {
107                                h_errno = NO_RECOVERY;
108                                return ((struct hostent *) NULL);
109                        }
110                        cp += n + QFIXEDSZ;
111                        host.h_name = bp;
112                        n = strlen(bp) + 1;
113                        bp += n;
114                        buflen -= n;
115                } else
116                        cp += dn_skipname(cp, eom) + QFIXEDSZ;
117                while (--qdcount > 0)
118                        cp += dn_skipname(cp, eom) + QFIXEDSZ;
119        } else if (iquery) {
120                if (hp->aa)
121                        h_errno = HOST_NOT_FOUND;
122                else
123                        h_errno = TRY_AGAIN;
124                return ((struct hostent *) NULL);
125        }
126        ap = host_aliases;
127        host.h_aliases = host_aliases;
128        hap = h_addr_ptrs;
129#if BSD >= 43 || defined(h_addr)        /* new-style hostent structure */
130        host.h_addr_list = h_addr_ptrs;
131#endif
132        haveanswer = 0;
133        while (--ancount >= 0 && cp < eom) {
134                if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0)
135                        break;
136                cp += n;
137                type = _getshort(cp);
138                cp += sizeof(u_short);
139                class = _getshort(cp);
140                cp += sizeof(u_short) + sizeof(u_long);
141                n = _getshort(cp);
142                cp += sizeof(u_short);
143                if (type == T_CNAME) {
144                        cp += n;
145                        if (ap >= &host_aliases[MAXALIASES-1])
146                                continue;
147                        *ap++ = bp;
148                        n = strlen(bp) + 1;
149                        bp += n;
150                        buflen -= n;
151                        continue;
152                }
153                if (iquery && type == T_PTR) {
154                        if ((n = dn_expand((char *)answer->buf, eom,
155                            cp, bp, buflen)) < 0) {
156                                cp += n;
157                                continue;
158                        }
159                        cp += n;
160                        host.h_name = bp;
161                        return(&host);
162                }
163                if (type == T_HINFO) {
164                        *info = (char *) cp;
165                        cp += n;
166                        *cp = '\0';
167                        buflen -= n;
168                        haveanswer++;
169                        continue;
170                }
171                if (type == T_MX) {
172                        if ((n = dn_expand((char *)answer->buf, eom,
173                                     cp+2, bp, buflen)) < 0)
174                          {
175                            cp += n;
176                            continue;
177                          }
178                        *info = (char *) bp;
179                        cp += n;
180                        buflen -= n;
181                        haveanswer++;
182                        continue;
183                }
184                if (iquery || type != T_A)  {
185#ifdef DEBUG
186                        if (_res.options & RES_DEBUG)
187                                printf("unexpected answer type %d, size %d\n",
188                                        type, n);
189#endif
190                        cp += n;
191                        continue;
192                }
193                if (haveanswer) {
194                        if (n != host.h_length) {
195                                cp += n;
196                                continue;
197                        }
198                        if (class != getclass) {
199                                cp += n;
200                                continue;
201                        }
202                } else {
203                        host.h_length = n;
204                        getclass = class;
205                        host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
206                        if (!iquery) {
207                                host.h_name = bp;
208                                bp += strlen(bp) + 1;
209                        }
210                }
211
212                bp += sizeof(align) - ((u_long)bp % sizeof(align));
213
214                if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
215#ifdef DEBUG
216                        if (_res.options & RES_DEBUG)
217                                printf("size (%d) too big\n", n);
218#endif
219                        break;
220                }
221                bcopy(cp, *hap++ = bp, n);
222                bp +=n;
223                cp += n;
224                haveanswer++;
225        }
226        if (haveanswer) {
227                *ap = NULL;
228#if BSD >= 43 || defined(h_addr)        /* new-style hostent structure */
229                *hap = NULL;
230#else
231                host.h_addr = h_addr_ptrs[0];
232#endif
233                return (&host);
234        } else {
235                h_errno = TRY_AGAIN;
236                return ((struct hostent *) NULL);
237        }
238}
239
240
241struct hostent *
242gethostbyname(name)
243        char *name;
244{
245        querybuf buf;
246        register char *cp;
247        int n;
248        extern struct hostent *_gethtbyname();
249        char *d;
250
251        /*
252         * disallow names consisting only of digits/dots, unless
253         * they end in a dot.
254         */
255        if (isdigit(name[0]))
256                for (cp = name;; ++cp) {
257                        if (!*cp) {
258                                if (*--cp == '.')
259                                        break;
260                                h_errno = HOST_NOT_FOUND;
261                                return ((struct hostent *) NULL);
262                        }
263                        if (!isdigit(*cp) && *cp != '.')
264                                break;
265                }
266
267        if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
268#ifdef DEBUG
269                if (_res.options & RES_DEBUG)
270                        printf("res_search failed\n");
271#endif
272                if (errno == ECONNREFUSED)
273                        return (_gethtbyname(name));
274                else
275                        return ((struct hostent *) NULL);
276        }
277        return (getanswer(&buf, n, 0, 0));
278}
279
280
281struct hostent *
282gethostbyaddr(addr, len, type)
283        char *addr;
284        int len, type;
285{
286        int n;
287        querybuf buf;
288        register struct hostent *hp;
289        char qbuf[MAXDNAME];
290        extern struct hostent *_gethtbyaddr();
291       
292        if (type != AF_INET)
293                return ((struct hostent *) NULL);
294        (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
295                ((unsigned)addr[3] & 0xff),
296                ((unsigned)addr[2] & 0xff),
297                ((unsigned)addr[1] & 0xff),
298                ((unsigned)addr[0] & 0xff));
299        n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
300        if (n < 0) {
301#ifdef DEBUG
302                if (_res.options & RES_DEBUG)
303                        printf("res_query failed\n");
304#endif
305                if (errno == ECONNREFUSED)
306                        return (_gethtbyaddr(addr, len, type));
307                return ((struct hostent *) NULL);
308        }
309        hp = getanswer(&buf, n, 1, 0);
310        if (hp == NULL)
311                return ((struct hostent *) NULL);
312        hp->h_addrtype = type;
313        hp->h_length = len;
314        h_addr_ptrs[0] = (char *)&host_addr;
315        h_addr_ptrs[1] = (char *)0;
316        host_addr = *(struct in_addr *)addr;
317        return(hp);
318}
319
320
321
322
323char *
324gethinfobyname(name)
325        char *name;
326{
327        querybuf buf;
328        register char *cp;
329        int n;
330        extern struct hostent *_gethtbyname();
331        char *info;
332
333        /*
334         * disallow names consisting only of digits/dots, unless
335         * they end in a dot.
336         */
337        if (isdigit(name[0]))
338                for (cp = name;; ++cp) {
339                        if (!*cp) {
340                                if (*--cp == '.')
341                                        break;
342                                h_errno = HOST_NOT_FOUND;
343                                return ((char  *) NULL);
344                        }
345                        if (!isdigit(*cp) && *cp != '.')
346                                break;
347                }
348
349        n = res_search(name, C_IN, T_HINFO, buf.buf, sizeof(buf));
350        if (n < 0) {
351#ifdef DEBUG
352                if (_res.options & RES_DEBUG)
353                        printf("res_query failed\n");
354#endif
355/*              if (errno == ECONNREFUSED)
356                        return (_gethtbyaddr(addr, len, type));*/
357                return ((char *) NULL);
358        }
359        if(getanswer(&buf, n, 0, &info))
360          return(info);
361        else
362          return(NULL);
363}
364
365
366char *
367getmxbyname(name)
368        char *name;
369{
370        querybuf buf;
371        register char *cp;
372        int n;
373        extern struct hostent *_gethtbyname();
374        char *info;
375
376        /*
377         * disallow names consisting only of digits/dots, unless
378         * they end in a dot.
379         */
380        if (isdigit(name[0]))
381                for (cp = name;; ++cp) {
382                        if (!*cp) {
383                                if (*--cp == '.')
384                                        break;
385                                h_errno = HOST_NOT_FOUND;
386                                return ((char  *) NULL);
387                        }
388                        if (!isdigit(*cp) && *cp != '.')
389                                break;
390                }
391
392        n = res_search(name, C_IN, T_MX, buf.buf, sizeof(buf));
393        if (n < 0) {
394#ifdef DEBUG
395                if (_res.options & RES_DEBUG)
396                        printf("res_query failed\n");
397#endif
398/*              if (errno == ECONNREFUSED)
399                        return (_gethtbyaddr(addr, len, type));*/
400                return ((char *) NULL);
401        }
402        if(getanswer(&buf, n, 0, &info))
403          return(info);
404        else
405          return(NULL);
406}
407
408
409_sethtent(f)
410        int f;
411{
412        if (hostf == NULL)
413                hostf = fopen(HOSTDB, "r" );
414        else
415                rewind(hostf);
416        stayopen |= f;
417}
418
419_endhtent()
420{
421        if (hostf && !stayopen) {
422                (void) fclose(hostf);
423                hostf = NULL;
424        }
425}
426
427struct hostent *
428_gethtent()
429{
430        char *p;
431        register char *cp, **q;
432
433        if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL)
434                return (NULL);
435again:
436        if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
437                return (NULL);
438        if (*p == '#')
439                goto again;
440        cp = any(p, "#\n");
441        if (cp == NULL)
442                goto again;
443        *cp = '\0';
444        cp = any(p, " \t");
445        if (cp == NULL)
446                goto again;
447        *cp++ = '\0';
448        /* THIS STUFF IS INTERNET SPECIFIC */
449#if BSD >= 43 || defined(h_addr)        /* new-style hostent structure */
450        host.h_addr_list = host_addrs;
451#endif
452        host.h_addr = hostaddr;
453        *((u_long *)host.h_addr) = inet_addr(p);
454        host.h_length = sizeof (u_long);
455        host.h_addrtype = AF_INET;
456        while (*cp == ' ' || *cp == '\t')
457                cp++;
458        host.h_name = cp;
459        q = host.h_aliases = host_aliases;
460        cp = any(cp, " \t");
461        if (cp != NULL)
462                *cp++ = '\0';
463        while (cp && *cp) {
464                if (*cp == ' ' || *cp == '\t') {
465                        cp++;
466                        continue;
467                }
468                if (q < &host_aliases[MAXALIASES - 1])
469                        *q++ = cp;
470                cp = any(cp, " \t");
471                if (cp != NULL)
472                        *cp++ = '\0';
473        }
474        *q = NULL;
475        return (&host);
476}
477
478static char *
479any(cp, match)
480        register char *cp;
481        char *match;
482{
483        register char *mp, c;
484
485        while (c = *cp) {
486                for (mp = match; *mp; mp++)
487                        if (*mp == c)
488                                return (cp);
489                cp++;
490        }
491        return ((char *)0);
492}
493
494struct hostent *
495_gethtbyname(name)
496        char *name;
497{
498        register struct hostent *p;
499        register char **cp;
500       
501        _sethtent(0);
502        while (p = _gethtent()) {
503                if (strcasecmp(p->h_name, name) == 0)
504                        break;
505                for (cp = p->h_aliases; *cp != 0; cp++)
506                        if (strcasecmp(*cp, name) == 0)
507                                goto found;
508        }
509found:
510        _endhtent();
511        return (p);
512}
513
514struct hostent *
515_gethtbyaddr(addr, len, type)
516        char *addr;
517        int len, type;
518{
519        register struct hostent *p;
520
521        _sethtent(0);
522        while (p = _gethtent())
523                if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
524                        break;
525        _endhtent();
526        return (p);
527}
Note: See TracBrowser for help on using the repository browser.