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

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