Updated from BIND 4.9.3-BETA14.
[kopensolaris-gnu/glibc.git] / resolv / gethnamaddr.c
1 /*
2  * ++Copyright++ 1985, 1988, 1993
3  * -
4  * Copyright (c) 1985, 1988, 1993
5  *    The Regents of the University of California.  All rights reserved.
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the University of
18  *      California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  * 
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  * -
35  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
36  * 
37  * Permission to use, copy, modify, and distribute this software for any
38  * purpose with or without fee is hereby granted, provided that the above
39  * copyright notice and this permission notice appear in all copies, and that
40  * the name of Digital Equipment Corporation not be used in advertising or
41  * publicity pertaining to distribution of the document or software without
42  * specific, written prior permission.
43  * 
44  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
47  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51  * SOFTWARE.
52  * -
53  * --Copyright--
54  */
55
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid[] = "@(#)gethostnamadr.c     8.1 (Berkeley) 6/4/93";
58 static char rcsid[] = "$Id$";
59 #endif /* LIBC_SCCS and not lint */
60
61 #include <sys/param.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <arpa/nameser.h>
66
67 #include <stdio.h>
68 #include <netdb.h>
69 #include <resolv.h>
70 #include <ctype.h>
71 #include <errno.h>
72 #include <syslog.h>
73
74 #ifndef LOG_AUTH
75 # define LOG_AUTH 0
76 #endif
77
78 #define MULTI_PTRS_ARE_ALIASES 1        /* XXX - experimental */
79
80 #if defined(BSD) && (BSD >= 199103)
81 # include <string.h>
82 #else
83 # include "../conf/portability.h"
84 #endif
85 #if defined(USE_OPTIONS_H)
86 # include <../conf/options.h>
87 #endif
88
89 #define MAXALIASES      35
90 #define MAXADDRS        35
91
92 static const char AskedForGot[] =
93                           "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
94
95 static char *h_addr_ptrs[MAXADDRS + 1];
96
97 static struct hostent host;
98 static char *host_aliases[MAXALIASES];
99 static char hostbuf[8*1024];
100 static struct in_addr host_addr;
101 static FILE *hostf = NULL;
102 static int stayopen = 0;
103
104 #ifdef RESOLVSORT
105 static void addrsort __P((char **, int));
106 #endif
107
108 #if PACKETSZ > 1024
109 #define MAXPACKET       PACKETSZ
110 #else
111 #define MAXPACKET       1024
112 #endif
113
114 typedef union {
115     HEADER hdr;
116     u_char buf[MAXPACKET];
117 } querybuf;
118
119 typedef union {
120     int32_t al;
121     char ac;
122 } align;
123
124 extern int h_errno;
125
126 #ifdef DEBUG
127 static void
128 dprintf(msg, num)
129         char *msg;
130         int num;
131 {
132         if (_res.options & RES_DEBUG) {
133                 int save = errno;
134
135                 printf(msg, num);
136                 errno = save;
137         }
138 }
139 #else
140 # define dprintf(msg, num) /*nada*/
141 #endif
142
143 static struct hostent *
144 getanswer(answer, anslen, qname, qclass, qtype)
145         const querybuf *answer;
146         int anslen;
147         const char *qname;
148         int qclass, qtype;
149 {
150         register const HEADER *hp;
151         register const u_char *cp;
152         register int n;
153         const u_char *eom;
154         char *bp, **ap, **hap;
155         int type, class, buflen, ancount, qdcount;
156         int haveanswer, had_error;
157         int toobig = 0;
158         char tbuf[MAXDNAME+1];
159
160         host.h_name = NULL;
161         eom = answer->buf + anslen;
162         /*
163          * find first satisfactory answer
164          */
165         hp = &answer->hdr;
166         ancount = ntohs(hp->ancount);
167         qdcount = ntohs(hp->qdcount);
168         bp = hostbuf;
169         buflen = sizeof hostbuf;
170         cp = answer->buf + HFIXEDSZ;
171         if (qdcount != 1) {
172                 h_errno = NO_RECOVERY;
173                 return (NULL);
174         }
175         if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
176                 h_errno = NO_RECOVERY;
177                 return (NULL);
178         }
179         cp += n + QFIXEDSZ;
180         if (qtype == T_A) {
181                 /* res_send() has already verified that the query name is the
182                  * same as the one we sent; this just gets the expanded name
183                  * (i.e., with the succeeding search-domain tacked on).
184                  */
185                 n = strlen(bp) + 1;             /* for the \0 */
186                 host.h_name = bp;
187                 bp += n;
188                 buflen -= n;
189                 /* The qname can be abbreviated, but h_name is now absolute. */
190                 qname = host.h_name;
191         }
192         ap = host_aliases;
193         *ap = NULL;
194         host.h_aliases = host_aliases;
195         hap = h_addr_ptrs;
196         *hap = NULL;
197 #if BSD >= 43 || defined(h_addr)        /* new-style hostent structure */
198         host.h_addr_list = h_addr_ptrs;
199 #endif
200         haveanswer = 0;
201         had_error = 0;
202         while (ancount-- > 0 && cp < eom && !had_error) {
203                 n = dn_expand(answer->buf, eom, cp, bp, buflen);
204                 if (n < 0) {
205                         had_error++;
206                         continue;
207                 }
208                 cp += n;                        /* name */
209                 type = _getshort(cp);
210                 cp += INT16SZ;                  /* type */
211                 class = _getshort(cp);
212                 cp += INT16SZ + INT32SZ;        /* class, TTL */
213                 n = _getshort(cp);
214                 cp += INT16SZ;                  /* len */
215                 if (class != qclass) {
216                         /* XXX - debug? syslog? */
217                         cp += n;
218                         continue;               /* XXX - had_error++ ? */
219                 }
220                 if (qtype == T_A && type == T_CNAME) {
221                         if (ap >= &host_aliases[MAXALIASES-1])
222                                 continue;
223                         n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
224                         if (n < 0) {
225                                 had_error++;
226                                 continue;
227                         }
228                         cp += n;
229                         if (host.h_name && strcasecmp(host.h_name, bp) != 0) {
230                                 syslog(LOG_NOTICE|LOG_AUTH,
231                 "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"",
232                                        host.h_name, bp);
233                                 continue;       /* XXX - had_error++ ? */
234                         }
235                         /* Store alias. */
236                         *ap++ = bp;
237                         n = strlen(bp) + 1;     /* for the \0 */
238                         bp += n;
239                         buflen -= n;
240                         /* Get canonical name. */
241                         n = strlen(tbuf) + 1;   /* for the \0 */
242                         if (n > buflen) {
243                                 had_error++;
244                                 continue;
245                         }
246                         strcpy(bp, tbuf);
247                         host.h_name = bp;
248                         bp += n;
249                         buflen -= n;
250                         continue;
251                 }
252                 if (type != qtype) {
253                         syslog(LOG_NOTICE|LOG_AUTH,
254                "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
255                                qname, p_class(qclass), p_type(qtype),
256                                p_type(type));
257                         cp += n;
258                         continue;               /* XXX - had_error++ ? */
259                 }
260                 switch (type) {
261                 case T_PTR:
262                         if (strcasecmp(qname, bp) != 0) {
263                                 syslog(LOG_NOTICE|LOG_AUTH,
264                                        AskedForGot, qname, bp);
265                                 cp += n;
266                                 continue;       /* XXX - had_error++ ? */
267                         }
268                         n = dn_expand(answer->buf, eom, cp, bp, buflen);
269                         if (n < 0) {
270                                 had_error++;
271                                 break;
272                         }
273 #if MULTI_PTRS_ARE_ALIASES
274                         cp += n;
275                         if (!haveanswer)
276                                 host.h_name = bp;
277                         else if (ap < &host_aliases[MAXALIASES-1])
278                                 *ap++ = bp;
279                         else
280                                 n = -1;
281                         if (n != -1) {
282                                 n = strlen(bp) + 1;     /* for the \0 */
283                                 bp += n;
284                                 buflen -= n;
285                         }
286                         break;
287 #else
288                         host.h_name = bp;
289                         h_errno = NETDB_SUCCESS;
290                         return (&host);
291 #endif
292                 case T_A:
293                         if (strcasecmp(host.h_name, bp) != 0) {
294                                 syslog(LOG_NOTICE|LOG_AUTH,
295                                        AskedForGot, host.h_name, bp);
296                                 cp += n;
297                                 continue;       /* XXX - had_error++ ? */
298                         }
299                         if (haveanswer) {
300                                 if (n != host.h_length) {
301                                         cp += n;
302                                         continue;
303                                 }
304                         } else {
305                                 register int nn;
306
307                                 host.h_length = n;
308                                 host.h_addrtype = (class == C_IN)
309                                                   ? AF_INET
310                                                   : AF_UNSPEC;
311                                 host.h_name = bp;
312                                 nn = strlen(bp) + 1;    /* for the \0 */
313                                 bp += nn;
314                                 buflen -= nn;
315                         }
316
317                         bp += sizeof(align) - ((u_long)bp % sizeof(align));
318
319                         if (bp + n >= &hostbuf[sizeof hostbuf]) {
320                                 dprintf("size (%d) too big\n", n);
321                                 had_error++;
322                                 continue;
323                         }
324                         if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
325                                 if (!toobig++)
326                                         dprintf("Too many addresses (%d)\n",
327                                                 MAXADDRS);
328                                 cp += n;
329                                 continue;
330                         }
331                         bcopy(cp, *hap++ = bp, n);
332                         bp += n;
333                         cp += n;
334                         break;
335                 default:
336                         dprintf("Impossible condition (type=%d)\n", type);
337                         h_errno = NO_RECOVERY;
338                         return (NULL);
339                 } /*switch*/
340                 if (!had_error)
341                         haveanswer++;
342         } /*while*/
343         if (haveanswer) {
344                 *ap = NULL;
345                 *hap = NULL;
346 # if defined(RESOLVSORT)
347                 /*
348                  * Note: we sort even if host can take only one address
349                  * in its return structures - should give it the "best"
350                  * address in that case, not some random one
351                  */
352                 if (_res.nsort && haveanswer > 1 &&
353                     qclass == C_IN && qtype == T_A)
354                         addrsort(h_addr_ptrs, haveanswer);
355 # endif /*RESOLVSORT*/
356 #if BSD >= 43 || defined(h_addr)        /* new-style hostent structure */
357                 /* nothing */
358 #else
359                 host.h_addr = h_addr_ptrs[0];
360 #endif /*BSD*/
361                 if (!host.h_name) {
362                         n = strlen(qname) + 1;  /* for the \0 */
363                         strcpy(bp, qname);
364                         host.h_name = bp;
365                 }
366                 h_errno = NETDB_SUCCESS;
367                 return (&host);
368         } else {
369                 h_errno = TRY_AGAIN;
370                 return (NULL);
371         }
372 }
373
374 struct hostent *
375 gethostbyname(name)
376         const char *name;
377 {
378         querybuf buf;
379         register const char *cp;
380         int n;
381         extern struct hostent *_gethtbyname();
382
383         /*
384          * if there aren't any dots, it could be a user-level alias.
385          * this is also done in res_query() since we are not the only
386          * function that looks up host names.
387          */
388         if (!strchr(name, '.') && (cp = __hostalias(name)))
389                 name = cp;
390
391         /*
392          * disallow names consisting only of digits/dots, unless
393          * they end in a dot.
394          */
395         if (isdigit(name[0]))
396                 for (cp = name;; ++cp) {
397                         if (!*cp) {
398                                 if (*--cp == '.')
399                                         break;
400                                 /*
401                                  * All-numeric, no dot at the end.
402                                  * Fake up a hostent as if we'd actually
403                                  * done a lookup.
404                                  */
405                                 if (!inet_aton(name, &host_addr)) {
406                                         h_errno = HOST_NOT_FOUND;
407                                         return (NULL);
408                                 }
409                                 host.h_name = (char *)name;
410                                 host.h_aliases = host_aliases;
411                                 host_aliases[0] = NULL;
412                                 host.h_addrtype = AF_INET;
413                                 host.h_length = INT32SZ;
414                                 h_addr_ptrs[0] = (char *)&host_addr;
415                                 h_addr_ptrs[1] = NULL;
416 #if BSD >= 43 || defined(h_addr)        /* new-style hostent structure */
417                                 host.h_addr_list = h_addr_ptrs;
418 #else
419                                 host.h_addr = h_addr_ptrs[0];
420 #endif
421                                 h_errno = NETDB_SUCCESS;
422                                 return (&host);
423                         }
424                         if (!isdigit(*cp) && *cp != '.') 
425                                 break;
426                 }
427
428         if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
429                 dprintf("res_search failed (%d)\n", n);
430                 if (errno == ECONNREFUSED)
431                         return (_gethtbyname(name));
432                 return (NULL);
433         }
434         return (getanswer(&buf, n, name, C_IN, T_A));
435 }
436
437 struct hostent *
438 gethostbyaddr(addr, len, type)
439         const char *addr;
440         int len, type;
441 {
442         int n;
443         querybuf buf;
444         register struct hostent *hp;
445         char qbuf[MAXDNAME+1];
446 #ifdef SUNSECURITY
447         register struct hostent *rhp;
448         char **haddr;
449         u_long old_options;
450         char hname2[MAXDNAME+1];
451 #endif /*SUNSECURITY*/
452         extern struct hostent *_gethtbyaddr();
453         
454         if (type != AF_INET) {
455                 errno = EAFNOSUPPORT;
456                 h_errno = NETDB_INTERNAL;
457                 return (NULL);
458         }
459         (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
460                 ((unsigned)addr[3] & 0xff),
461                 ((unsigned)addr[2] & 0xff),
462                 ((unsigned)addr[1] & 0xff),
463                 ((unsigned)addr[0] & 0xff));
464         n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
465         if (n < 0) {
466                 dprintf("res_query failed (%d)\n", n);
467                 if (errno == ECONNREFUSED)
468                         return (_gethtbyaddr(addr, len, type));
469                 return (NULL);
470         }
471         if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR)))
472                 return (NULL);  /* h_errno was set by getanswer() */
473 #ifdef SUNSECURITY
474         /*
475          * turn off search as the name should be absolute,
476          * 'localhost' should be matched by defnames
477          */
478         strncpy(hname2, hp->h_name, MAXDNAME);
479         hname2[MAXDNAME] = '\0';
480         old_options = _res.options;
481         _res.options &= ~RES_DNSRCH;
482         _res.options |= RES_DEFNAMES;
483         if (!(rhp = gethostbyname(hp->h_name))) {
484                 syslog(LOG_NOTICE|LOG_AUTH,
485                        "gethostbyaddr: No A record for %s (verifying [%s])",
486                        hname2, inet_ntoa(*((struct in_addr *)addr)));
487                 _res.options = old_options;
488                 h_errno = HOST_NOT_FOUND;
489                 return (NULL);
490         }
491         _res.options = old_options;
492         for (haddr = rhp->h_addr_list; *haddr; haddr++)
493                 if (!memcmp(*haddr, addr, INADDRSZ))
494                         break;
495         if (!*haddr) {
496                 syslog(LOG_NOTICE|LOG_AUTH,
497                        "gethostbyaddr: A record of %s != PTR record [%s]",
498                        hname2, inet_ntoa(*((struct in_addr *)addr)));
499                 h_errno = HOST_NOT_FOUND;
500                 return (NULL);
501         }
502 #endif /*SUNSECURITY*/
503         hp->h_addrtype = type;
504         hp->h_length = len;
505         h_addr_ptrs[0] = (char *)&host_addr;
506         h_addr_ptrs[1] = NULL;
507         host_addr = *(struct in_addr *)addr;
508         h_errno = NETDB_SUCCESS;
509         return (hp);
510 }
511
512 void
513 _sethtent(f)
514         int f;
515 {
516         if (!hostf)
517                 hostf = fopen(_PATH_HOSTS, "r" );
518         else
519                 rewind(hostf);
520         stayopen = f;
521 }
522
523 void
524 _endhtent()
525 {
526         if (hostf && !stayopen) {
527                 (void) fclose(hostf);
528                 hostf = NULL;
529         }
530 }
531
532 struct hostent *
533 _gethtent()
534 {
535         char *p;
536         register char *cp, **q;
537
538         if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
539                 h_errno = NETDB_INTERNAL;
540                 return (NULL);
541         }
542 again:
543         if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
544                 h_errno = HOST_NOT_FOUND;
545                 return (NULL);
546         }
547         if (*p == '#')
548                 goto again;
549         if (!(cp = strpbrk(p, "#\n")))
550                 goto again;
551         *cp = '\0';
552         if (!(cp = strpbrk(p, " \t")))
553                 goto again;
554         *cp++ = '\0';
555         /* THIS STUFF IS INTERNET SPECIFIC */
556         if (!inet_aton(p, &host_addr))
557                 goto again;
558         h_addr_ptrs[0] = (char *)&host_addr;
559         h_addr_ptrs[1] = NULL;
560 #if BSD >= 43 || defined(h_addr)        /* new-style hostent structure */
561         host.h_addr_list = h_addr_ptrs;
562 #else
563         host.h_addr = h_addr_ptrs[0];
564 #endif
565         host.h_length = INT32SZ;
566         host.h_addrtype = AF_INET;
567         while (*cp == ' ' || *cp == '\t')
568                 cp++;
569         host.h_name = cp;
570         q = host.h_aliases = host_aliases;
571         if (cp = strpbrk(cp, " \t"))
572                 *cp++ = '\0';
573         while (cp && *cp) {
574                 if (*cp == ' ' || *cp == '\t') {
575                         cp++;
576                         continue;
577                 }
578                 if (q < &host_aliases[MAXALIASES - 1])
579                         *q++ = cp;
580                 if (cp = strpbrk(cp, " \t"))
581                         *cp++ = '\0';
582         }
583         *q = NULL;
584         h_errno = NETDB_SUCCESS;
585         return (&host);
586 }
587
588 struct hostent *
589 _gethtbyname(name)
590         char *name;
591 {
592         register struct hostent *p;
593         register char **cp;
594         
595         _sethtent(0);
596         while (p = _gethtent()) {
597                 if (strcasecmp(p->h_name, name) == 0)
598                         break;
599                 for (cp = p->h_aliases; *cp != 0; cp++)
600                         if (strcasecmp(*cp, name) == 0)
601                                 goto found;
602         }
603 found:
604         _endhtent();
605         return (p);
606 }
607
608 struct hostent *
609 _gethtbyaddr(addr, len, type)
610         const char *addr;
611         int len, type;
612 {
613         register struct hostent *p;
614
615         _sethtent(0);
616         while (p = _gethtent())
617                 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
618                         break;
619         _endhtent();
620         return (p);
621 }
622
623 #ifdef RESOLVSORT
624 static void
625 addrsort(ap, num)
626         char **ap;
627         int num;
628 {
629         int i, j;
630         char **p;
631         short aval[MAXADDRS];
632         int needsort = 0;
633
634         p = ap;
635         for (i = 0; i < num; i++, p++) {
636             for (j = 0 ; (unsigned)j < _res.nsort; j++)
637                 if (_res.sort_list[j].addr.s_addr == 
638                     (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
639                         break;
640             aval[i] = j;
641             if (needsort == 0 && i > 0 && j < aval[i-1])
642                 needsort = i;
643         }
644         if (!needsort)
645             return;
646
647         while (needsort < num) {
648             for (j = needsort - 1; j >= 0; j--) {
649                 if (aval[j] > aval[j+1]) {
650                     char *hp;
651
652                     i = aval[j];
653                     aval[j] = aval[j+1];
654                     aval[j+1] = i;
655
656                     hp = ap[j];
657                     ap[j] = ap[j+1];
658                     ap[j+1] = hp;
659
660                 } else
661                     break;
662             }
663             needsort++;
664         }
665 }
666 #endif
667
668 #if defined(BSD43_BSD43_NFS) || defined(sun)
669 /* some libc's out there are bound internally to these names (UMIPS) */
670 void
671 ht_sethostent(stayopen)
672         int stayopen;
673 {
674         _sethtent(stayopen);
675 }
676
677 void
678 ht_endhostent()
679 {
680         _endhtent();
681 }
682
683 struct hostent *
684 ht_gethostbyname(name)
685         char *name;
686 {
687         return (_gethtbyname(name));
688 }
689
690 struct hostent *
691 ht_gethostbyaddr(addr, len, type)
692         const char *addr;
693         int len, type;
694 {
695         return (_gethtbyaddr(addr, len, type));
696 }
697
698 struct hostent *
699 gethostent()
700 {
701         return (_gethtent());
702 }
703
704 void
705 dns_service()
706 {
707         return;
708 }
709
710 #undef dn_skipname
711 dn_skipname(comp_dn, eom)
712         const u_char *comp_dn, *eom;
713 {
714         return (__dn_skipname(comp_dn, eom));
715 }
716 #endif /*old-style libc with yp junk in it*/
717
718 #ifdef ultrix
719 /* more icky libc packaging in ultrix */
720 int
721 local_hostname_length(hostname)
722         const char *hostname;
723 {
724         int len_host, len_domain;
725
726         if (!*_res.defdname)
727                 res_init();
728         len_host = strlen(hostname);
729         len_domain = strlen(_res.defdname);
730         if (len_host > len_domain &&
731             !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
732             hostname[len_host - len_domain - 1] == '.')
733                 return (len_host - len_domain - 1);
734         return (0);
735 }
736 #endif