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

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