summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/gethostnamadr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/gethostnamadr.c')
-rw-r--r--src/lib/libc/net/gethostnamadr.c958
1 files changed, 742 insertions, 216 deletions
diff --git a/src/lib/libc/net/gethostnamadr.c b/src/lib/libc/net/gethostnamadr.c
index ec3f14a900..7cf419fdb1 100644
--- a/src/lib/libc/net/gethostnamadr.c
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -1,5 +1,3 @@
1/* $NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycroft Exp $ */
2
3/*- 1/*-
4 * Copyright (c) 1985, 1988, 1993 2 * Copyright (c) 1985, 1988, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -54,12 +52,7 @@
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint) 54#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 55static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.55 2003/03/04 00:29:17 itojun Exp $";
58static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: gethnamaddr.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";
60#else
61static char rcsid[] = "$NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycroft Exp $";
62#endif
63#endif /* LIBC_SCCS and not lint */ 56#endif /* LIBC_SCCS and not lint */
64 57
65#include <sys/param.h> 58#include <sys/param.h>
@@ -73,11 +66,17 @@ static char rcsid[] = "$NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycro
73#include <ctype.h> 66#include <ctype.h>
74#include <errno.h> 67#include <errno.h>
75#include <string.h> 68#include <string.h>
69#include <syslog.h>
70#include <stdlib.h>
76#ifdef YP 71#ifdef YP
77#include <rpc/rpc.h> 72#include <rpc/rpc.h>
78#include <rpcsvc/yp_prot.h> 73#include <rpcsvc/yp.h>
79#include <rpcsvc/ypclnt.h> 74#include <rpcsvc/ypclnt.h>
75#include "ypinternal.h"
80#endif 76#endif
77#include "thread_private.h"
78
79#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
81 80
82#define MAXALIASES 35 81#define MAXALIASES 35
83#define MAXADDRS 35 82#define MAXADDRS 35
@@ -91,47 +90,109 @@ static char *__ypdomain;
91static struct hostent host; 90static struct hostent host;
92static char *host_aliases[MAXALIASES]; 91static char *host_aliases[MAXALIASES];
93static char hostbuf[BUFSIZ+1]; 92static char hostbuf[BUFSIZ+1];
94static struct in_addr host_addr; 93static union {
94 struct in_addr _host_in_addr;
95 u_char _host_addr[16]; /* IPv4 or IPv6 */
96} _host_addr_u;
97#define host_addr _host_addr_u._host_addr
95static FILE *hostf = NULL; 98static FILE *hostf = NULL;
96static int stayopen = 0; 99static int stayopen = 0;
97 100
98#if PACKETSZ > 1024 101static void map_v4v6_address(const char *src, char *dst);
99#define MAXPACKET PACKETSZ 102static void map_v4v6_hostent(struct hostent *hp, char **bp, char *);
100#else 103
101#define MAXPACKET 1024 104#ifdef RESOLVSORT
105static void addrsort(char **, int);
102#endif 106#endif
103 107
108int _hokchar(const char *);
109
110static const char AskedForGot[] =
111 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
112
113#define MAXPACKET (64*1024)
114
104typedef union { 115typedef union {
105 HEADER hdr; 116 HEADER hdr;
106 u_char buf[MAXPACKET]; 117 u_char buf[MAXPACKET];
107} querybuf; 118} querybuf;
108 119
109typedef union { 120typedef union {
110 int32_t al; 121 int32_t al;
111 char ac; 122 char ac;
112} align; 123} align;
113 124
114static int qcomp __P((struct in_addr **, struct in_addr **)); 125static struct hostent *getanswer(const querybuf *, int, const char *, int);
115static struct hostent *getanswer __P((querybuf *, int, int));
116 126
117extern int h_errno; 127extern int h_errno;
118 128
129int
130_hokchar(p)
131 const char *p;
132{
133 char c;
134
135 /*
136 * Many people do not obey RFC 822 and 1035. The valid
137 * characters are a-z, A-Z, 0-9, '-' and . But the others
138 * tested for below can happen, and we must be more permissive
139 * than the resolver until those idiots clean up their act.
140 * We let '/' through, but not '..'
141 */
142 while ((c = *p++)) {
143 if (('a' <= c && c <= 'z') ||
144 ('A' <= c && c <= 'Z') ||
145 ('0' <= c && c <= '9'))
146 continue;
147 if (strchr("-_/", c))
148 continue;
149 if (c == '.' && *p != '.')
150 continue;
151 return 0;
152 }
153 return 1;
154}
155
119static struct hostent * 156static struct hostent *
120getanswer(answer, anslen, iquery) 157getanswer(answer, anslen, qname, qtype)
121 querybuf *answer; 158 const querybuf *answer;
122 int anslen; 159 int anslen;
123 int iquery; 160 const char *qname;
161 int qtype;
124{ 162{
125 register HEADER *hp; 163 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
126 register u_char *cp; 164 register const HEADER *hp;
165 register const u_char *cp;
127 register int n; 166 register int n;
128 u_char *eom; 167 const u_char *eom;
129 char *bp, **ap; 168 char *bp, **ap, **hap, *ep;
130 int type, class, buflen, ancount, qdcount; 169 int type, class, ancount, qdcount;
131 int haveanswer, getclass = C_ANY; 170 int haveanswer, had_error;
132 char **hap; 171 int toobig = 0;
172 char tbuf[MAXDNAME];
173 const char *tname;
174 int (*name_ok)(const char *);
133 175
176 tname = qname;
177 host.h_name = NULL;
134 eom = answer->buf + anslen; 178 eom = answer->buf + anslen;
179 switch (qtype) {
180 case T_A:
181 case T_AAAA:
182#ifdef USE_RESOLV_NAME_OK
183 name_ok = res_hnok;
184 break;
185#endif
186 case T_PTR:
187#ifdef USE_RESOLV_NAME_OK
188 name_ok = res_dnok;
189#else
190 name_ok = _hokchar;
191#endif
192 break;
193 default:
194 return (NULL);
195 }
135 /* 196 /*
136 * find first satisfactory answer 197 * find first satisfactory answer
137 */ 198 */
@@ -139,31 +200,28 @@ getanswer(answer, anslen, iquery)
139 ancount = ntohs(hp->ancount); 200 ancount = ntohs(hp->ancount);
140 qdcount = ntohs(hp->qdcount); 201 qdcount = ntohs(hp->qdcount);
141 bp = hostbuf; 202 bp = hostbuf;
142 buflen = sizeof(hostbuf); 203 ep = hostbuf + sizeof hostbuf;
143 cp = answer->buf + sizeof(HEADER); 204 cp = answer->buf + HFIXEDSZ;
144 if (qdcount) { 205 if (qdcount != 1) {
145 if (iquery) { 206 h_errno = NO_RECOVERY;
146 if ((n = dn_expand((u_char *)answer->buf, 207 return (NULL);
147 (u_char *)eom, (u_char *)cp, (u_char *)bp, 208 }
148 buflen)) < 0) { 209 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
149 h_errno = NO_RECOVERY; 210 if ((n < 0) || !(*name_ok)(bp)) {
150 return ((struct hostent *) NULL); 211 h_errno = NO_RECOVERY;
151 } 212 return (NULL);
152 cp += n + QFIXEDSZ; 213 }
153 host.h_name = bp; 214 cp += n + QFIXEDSZ;
154 n = strlen(bp) + 1; 215 if (qtype == T_A || qtype == T_AAAA) {
155 bp += n; 216 /* res_send() has already verified that the query name is the
156 buflen -= n; 217 * same as the one we sent; this just gets the expanded name
157 } else 218 * (i.e., with the succeeding search-domain tacked on).
158 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 219 */
159 while (--qdcount > 0) 220 n = strlen(bp) + 1; /* for the \0 */
160 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 221 host.h_name = bp;
161 } else if (iquery) { 222 bp += n;
162 if (hp->aa) 223 /* The qname can be abbreviated, but h_name is now absolute. */
163 h_errno = HOST_NOT_FOUND; 224 qname = host.h_name;
164 else
165 h_errno = TRY_AGAIN;
166 return ((struct hostent *) NULL);
167 } 225 }
168 ap = host_aliases; 226 ap = host_aliases;
169 *ap = NULL; 227 *ap = NULL;
@@ -172,104 +230,325 @@ getanswer(answer, anslen, iquery)
172 *hap = NULL; 230 *hap = NULL;
173 host.h_addr_list = h_addr_ptrs; 231 host.h_addr_list = h_addr_ptrs;
174 haveanswer = 0; 232 haveanswer = 0;
175 while (--ancount >= 0 && cp < eom) { 233 had_error = 0;
176 if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, 234 while (ancount-- > 0 && cp < eom && !had_error) {
177 (u_char *)cp, (u_char *)bp, buflen)) < 0) 235 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
178 break; 236 if ((n < 0) || !(*name_ok)(bp)) {
179 cp += n; 237 had_error++;
238 continue;
239 }
240 cp += n; /* name */
180 type = _getshort(cp); 241 type = _getshort(cp);
181 cp += sizeof(u_int16_t); 242 cp += INT16SZ; /* type */
182 class = _getshort(cp); 243 class = _getshort(cp);
183 cp += sizeof(u_int16_t) + sizeof(u_int32_t); 244 cp += INT16SZ + INT32SZ; /* class, TTL */
184 n = _getshort(cp); 245 n = _getshort(cp);
185 cp += sizeof(u_int16_t); 246 cp += INT16SZ; /* len */
186 if (type == T_CNAME) { 247 if (type == T_SIG) {
248 /* XXX - ignore signatures as we don't use them yet */
187 cp += n; 249 cp += n;
250 continue;
251 }
252 if (class != C_IN) {
253 /* XXX - debug? syslog? */
254 cp += n;
255 continue; /* XXX - had_error++ ? */
256 }
257 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
188 if (ap >= &host_aliases[MAXALIASES-1]) 258 if (ap >= &host_aliases[MAXALIASES-1])
189 continue; 259 continue;
260 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
261 if ((n < 0) || !(*name_ok)(tbuf)) {
262 had_error++;
263 continue;
264 }
265 cp += n;
266 /* Store alias. */
190 *ap++ = bp; 267 *ap++ = bp;
191 n = strlen(bp) + 1; 268 n = strlen(bp) + 1; /* for the \0 */
192 bp += n; 269 bp += n;
193 buflen -= n; 270 /* Get canonical name. */
194 continue; 271 n = strlen(tbuf) + 1; /* for the \0 */
195 } 272 if (n > ep - bp) {
196 if (iquery && type == T_PTR) { 273 had_error++;
197 if ((n = dn_expand((u_char *)answer->buf, 274 continue;
198 (u_char *)eom, (u_char *)cp, (u_char *)bp, 275 }
199 buflen)) < 0) 276 strlcpy(bp, tbuf, ep - bp);
200 break;
201 cp += n;
202 host.h_name = bp; 277 host.h_name = bp;
203 return(&host); 278 bp += n;
279 continue;
204 } 280 }
205 if (iquery || type != T_A) { 281 if (qtype == T_PTR && type == T_CNAME) {
206#ifdef DEBUG 282 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
207 if (_res.options & RES_DEBUG) 283#ifdef USE_RESOLV_NAME_OK
208 printf("unexpected answer type %d, size %d\n", 284 if ((n < 0) || !res_hnok(tbuf)) {
209 type, n); 285#else
286 if ((n < 0) || !_hokchar(tbuf)) {
210#endif 287#endif
288 had_error++;
289 continue;
290 }
211 cp += n; 291 cp += n;
292 /* Get canonical name. */
293 n = strlen(tbuf) + 1; /* for the \0 */
294 if (n > ep - bp) {
295 had_error++;
296 continue;
297 }
298 strlcpy(bp, tbuf, ep - bp);
299 tname = bp;
300 bp += n;
212 continue; 301 continue;
213 } 302 }
214 if (haveanswer) { 303 if (type != qtype) {
215 if (n != host.h_length) { 304 syslog(LOG_NOTICE|LOG_AUTH,
305 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
306 qname, p_class(C_IN), p_type(qtype),
307 p_type(type));
308 cp += n;
309 continue; /* XXX - had_error++ ? */
310 }
311 switch (type) {
312 case T_PTR:
313 if (strcasecmp(tname, bp) != 0) {
314 syslog(LOG_NOTICE|LOG_AUTH,
315 AskedForGot, qname, bp);
216 cp += n; 316 cp += n;
217 continue; 317 continue; /* XXX - had_error++ ? */
318 }
319 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
320#ifdef USE_RESOLV_NAME_OK
321 if ((n < 0) || !res_hnok(bp)) {
322#else
323 if ((n < 0) || !_hokchar(bp)) {
324#endif
325 had_error++;
326 break;
327 }
328#if MULTI_PTRS_ARE_ALIASES
329 cp += n;
330 if (!haveanswer)
331 host.h_name = bp;
332 else if (ap < &host_aliases[MAXALIASES-1])
333 *ap++ = bp;
334 else
335 n = -1;
336 if (n != -1) {
337 n = strlen(bp) + 1; /* for the \0 */
338 bp += n;
339 }
340 break;
341#else
342 host.h_name = bp;
343 if (_resp->options & RES_USE_INET6) {
344 n = strlen(bp) + 1; /* for the \0 */
345 bp += n;
346 map_v4v6_hostent(&host, &bp, ep);
347 }
348 h_errno = NETDB_SUCCESS;
349 return (&host);
350#endif
351 case T_A:
352 case T_AAAA:
353 if (strcasecmp(host.h_name, bp) != 0) {
354 syslog(LOG_NOTICE|LOG_AUTH,
355 AskedForGot, host.h_name, bp);
356 cp += n;
357 continue; /* XXX - had_error++ ? */
218 } 358 }
219 if (class != getclass) { 359 if (n != host.h_length) {
220 cp += n; 360 cp += n;
221 continue; 361 continue;
222 } 362 }
223 } else { 363 if (type == T_AAAA) {
224 host.h_length = n; 364 struct in6_addr in6;
225 getclass = class; 365 memcpy(&in6, cp, IN6ADDRSZ);
226 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 366 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
227 if (!iquery) { 367 cp += n;
368 continue;
369 }
370 }
371 if (!haveanswer) {
372 register int nn;
373
228 host.h_name = bp; 374 host.h_name = bp;
229 bp += strlen(bp) + 1; 375 nn = strlen(bp) + 1; /* for the \0 */
376 bp += nn;
230 } 377 }
231 }
232 378
233 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 379 bp += sizeof(align) - ((u_long)bp % sizeof(align));
234 380
235 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 381 if (bp + n >= &hostbuf[sizeof hostbuf]) {
236#ifdef DEBUG 382#ifdef DEBUG
237 if (_res.options & RES_DEBUG) 383 if (_resp->options & RES_DEBUG)
238 printf("size (%d) too big\n", n); 384 printf("size (%d) too big\n", n);
239#endif 385#endif
386 had_error++;
387 continue;
388 }
389 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
390 if (!toobig++)
391#ifdef DEBUG
392 if (_resp->options & RES_DEBUG)
393 printf("Too many addresses (%d)\n", MAXADDRS);
394#endif
395 cp += n;
396 continue;
397 }
398 bcopy(cp, *hap++ = bp, n);
399 bp += n;
400 cp += n;
240 break; 401 break;
241 } 402 }
242 bcopy(cp, *hap++ = bp, n); 403 if (!had_error)
243 bp +=n; 404 haveanswer++;
244 cp += n;
245 haveanswer++;
246 } 405 }
247 if (haveanswer) { 406 if (haveanswer) {
248 *ap = NULL; 407 *ap = NULL;
249 *hap = NULL; 408 *hap = NULL;
250 if (_res.nsort) { 409# if defined(RESOLVSORT)
251 qsort(host.h_addr_list, haveanswer, 410 /*
252 sizeof(struct in_addr), 411 * Note: we sort even if host can take only one address
253 (int (*)__P((const void *, const void *)))qcomp); 412 * in its return structures - should give it the "best"
413 * address in that case, not some random one
414 */
415 if (_resp->nsort && haveanswer > 1 && qtype == T_A)
416 addrsort(h_addr_ptrs, haveanswer);
417# endif /*RESOLVSORT*/
418 if (!host.h_name) {
419 n = strlen(qname) + 1; /* for the \0 */
420 if (n > ep - bp)
421 goto try_again;
422 strlcpy(bp, qname, ep - bp);
423 host.h_name = bp;
424 bp += n;
254 } 425 }
426 if (_resp->options & RES_USE_INET6)
427 map_v4v6_hostent(&host, &bp, ep);
428 h_errno = NETDB_SUCCESS;
255 return (&host); 429 return (&host);
256 } else {
257 h_errno = TRY_AGAIN;
258 return ((struct hostent *) NULL);
259 } 430 }
431 try_again:
432 h_errno = TRY_AGAIN;
433 return (NULL);
434}
435
436#ifdef notyet
437/*
438 * XXX This is an extremely bogus implementation.
439 *
440 * FreeBSD has this interface:
441 * int gethostbyaddr_r(const char *addr, int len, int type,
442 * struct hostent *result, struct hostent_data *buffer)
443 */
444
445struct hostent *
446gethostbyname_r(name, hp, buf, buflen, errorp)
447 const char * name;
448 struct hostent * hp;
449 char * buf;
450 int buflen;
451 int * errorp;
452{
453 struct hostent *res;
454
455 res = gethostbyname(name);
456 *errorp = h_errno;
457 if (res == NULL)
458 return NULL;
459 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
460 return hp;
461}
462
463/*
464 * XXX This is an extremely bogus implementation.
465 */
466struct hostent *
467gethostbyaddr_r(addr, len, af, he, buf, buflen, errorp)
468 const char *addr; /* XXX should have been def'd as u_char! */
469 int len, af;
470 struct hostent * he;
471 char * buf;
472 int buflen;
473 int * errorp;
474{
475 struct hostent * res;
476
477 res = gethostbyaddr(addr, len, af);
478 *errorp = h_errno;
479 if (res == NULL)
480 return NULL;
481 memcpy(he, res, sizeof *he); /* XXX not sufficient */
482 return he;
260} 483}
261 484
485/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
486#endif
487
262struct hostent * 488struct hostent *
263gethostbyname(name) 489gethostbyname(name)
264 const char *name; 490 const char *name;
265{ 491{
266 querybuf buf; 492 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
493 struct hostent *hp;
494 extern struct hostent *_gethtbyname2();
495
496 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
497 hp = _gethtbyname2(name, AF_INET);
498
499 else if (_resp->options & RES_USE_INET6) {
500 hp = gethostbyname2(name, AF_INET6);
501 if (hp == NULL)
502 hp = gethostbyname2(name, AF_INET);
503 }
504 else
505 hp = gethostbyname2(name, AF_INET);
506 return hp;
507}
508
509struct hostent *
510gethostbyname2(name, af)
511 const char *name;
512 int af;
513{
514 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
515 querybuf *buf;
267 register const char *cp; 516 register const char *cp;
268 int n, i; 517 char *bp, *ep;
269 extern struct hostent *_gethtbyname(), *_yp_gethtbyname(); 518 int n, size, type, i;
519 extern struct hostent *_gethtbyname2(), *_yp_gethtbyname();
270 register struct hostent *hp; 520 register struct hostent *hp;
271 char lookups[MAXDNSLUS]; 521 char lookups[MAXDNSLUS];
272 522
523 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
524 return (_gethtbyname2(name, af));
525
526 switch (af) {
527 case AF_INET:
528 size = INADDRSZ;
529 type = T_A;
530 break;
531 case AF_INET6:
532 size = IN6ADDRSZ;
533 type = T_AAAA;
534 break;
535 default:
536 h_errno = NETDB_INTERNAL;
537 errno = EAFNOSUPPORT;
538 return (NULL);
539 }
540
541 host.h_addrtype = af;
542 host.h_length = size;
543
544 /*
545 * if there aren't any dots, it could be a user-level alias.
546 * this is also done in res_query() since we are not the only
547 * function that looks up host names.
548 */
549 if (!strchr(name, '.') && (cp = __hostalias(name)))
550 name = cp;
551
273 /* 552 /*
274 * disallow names consisting only of digits/dots, unless 553 * disallow names consisting only of digits/dots, unless
275 * they end in a dot. 554 * they end in a dot.
@@ -284,116 +563,230 @@ gethostbyname(name)
284 * Fake up a hostent as if we'd actually 563 * Fake up a hostent as if we'd actually
285 * done a lookup. 564 * done a lookup.
286 */ 565 */
287 if (!inet_aton(name, &host_addr)) { 566 if (inet_pton(af, name, host_addr) <= 0) {
288 h_errno = HOST_NOT_FOUND; 567 h_errno = HOST_NOT_FOUND;
289 return((struct hostent *) NULL); 568 return (NULL);
290 } 569 }
291 host.h_name = (char *)name; 570 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
571 bp = hostbuf + MAXHOSTNAMELEN;
572 ep = hostbuf + sizeof(hostbuf);
573 host.h_name = hostbuf;
292 host.h_aliases = host_aliases; 574 host.h_aliases = host_aliases;
293 host_aliases[0] = NULL; 575 host_aliases[0] = NULL;
294 host.h_addrtype = AF_INET; 576 h_addr_ptrs[0] = (char *)host_addr;
295 host.h_length = sizeof(u_int32_t);
296 h_addr_ptrs[0] = (char *)&host_addr;
297 h_addr_ptrs[1] = NULL; 577 h_addr_ptrs[1] = NULL;
298 host.h_addr_list = h_addr_ptrs; 578 host.h_addr_list = h_addr_ptrs;
579 if (_resp->options & RES_USE_INET6)
580 map_v4v6_hostent(&host, &bp, ep);
581 h_errno = NETDB_SUCCESS;
299 return (&host); 582 return (&host);
300 } 583 }
301 if (!isdigit(*cp) && *cp != '.') 584 if (!isdigit(*cp) && *cp != '.')
302 break; 585 break;
303 } 586 }
587 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
588 name[0] == ':')
589 for (cp = name;; ++cp) {
590 if (!*cp) {
591 if (*--cp == '.')
592 break;
593 /*
594 * All-IPv6-legal, no dot at the end.
595 * Fake up a hostent as if we'd actually
596 * done a lookup.
597 */
598 if (inet_pton(af, name, host_addr) <= 0) {
599 h_errno = HOST_NOT_FOUND;
600 return (NULL);
601 }
602 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
603 bp = hostbuf + MAXHOSTNAMELEN;
604 ep = hostbuf + sizeof(hostbuf);
605 host.h_name = hostbuf;
606 host.h_aliases = host_aliases;
607 host_aliases[0] = NULL;
608 h_addr_ptrs[0] = (char *)host_addr;
609 h_addr_ptrs[1] = NULL;
610 host.h_addr_list = h_addr_ptrs;
611 h_errno = NETDB_SUCCESS;
612 return (&host);
613 }
614 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
615 break;
616 }
304 617
305 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 618 bcopy(_resp->lookups, lookups, sizeof lookups);
306 return (_gethtbyname(name));
307
308 bcopy(_res.lookups, lookups, sizeof lookups);
309 if (lookups[0] == '\0') 619 if (lookups[0] == '\0')
310 strncpy(lookups, "bf", sizeof lookups); 620 strlcpy(lookups, "bf", sizeof lookups);
311 621
312 hp = (struct hostent *)NULL; 622 hp = (struct hostent *)NULL;
313 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 623 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
314 switch (lookups[i]) { 624 switch (lookups[i]) {
315#ifdef YP 625#ifdef YP
316 case 'y': 626 case 'y':
317 hp = _yp_gethtbyname(name); 627 /* YP only supports AF_INET. */
628 if (af == AF_INET)
629 hp = _yp_gethtbyname(name);
318 break; 630 break;
319#endif 631#endif
320 case 'b': 632 case 'b':
321 if ((n = res_search(name, C_IN, T_A, buf.buf, 633 buf = malloc(sizeof(*buf));
322 sizeof(buf))) < 0) { 634 if (buf == NULL)
635 break;
636 if ((n = res_search(name, C_IN, type, buf->buf,
637 sizeof(buf->buf))) < 0) {
638 free(buf);
323#ifdef DEBUG 639#ifdef DEBUG
324 if (_res.options & RES_DEBUG) 640 if (_resp->options & RES_DEBUG)
325 printf("res_search failed\n"); 641 printf("res_search failed\n");
326#endif 642#endif
327 break; 643 break;
328 } 644 }
329 hp = getanswer(&buf, n, 0); 645 hp = getanswer(buf, n, name, type);
646 free(buf);
330 break; 647 break;
331 case 'f': 648 case 'f':
332 hp = _gethtbyname(name); 649 hp = _gethtbyname2(name, af);
333 break; 650 break;
334 } 651 }
335 } 652 }
653 /* XXX h_errno not correct in all cases... */
336 return (hp); 654 return (hp);
337} 655}
338 656
339struct hostent * 657struct hostent *
340gethostbyaddr(addr, len, type) 658gethostbyaddr(addr, len, af)
341 const char *addr; 659 const char *addr; /* XXX should have been def'd as u_char! */
342 int len, type; 660 int len, af;
343{ 661{
344 int n, i; 662 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
345 querybuf buf; 663 const u_char *uaddr = (const u_char *)addr;
664 int n, size, i;
665 querybuf *buf;
346 register struct hostent *hp; 666 register struct hostent *hp;
347 char qbuf[MAXDNAME]; 667 char qbuf[MAXDNAME+1], *qp, *ep;
348 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr(); 668 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr();
349 char lookups[MAXDNSLUS]; 669 char lookups[MAXDNSLUS];
670 struct hostent *res;
350 671
351 if (type != AF_INET) 672 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
352 return ((struct hostent *) NULL); 673 res = _gethtbyaddr(addr, len, af);
353 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 674 return (res);
354 ((unsigned)addr[3] & 0xff), 675 }
355 ((unsigned)addr[2] & 0xff), 676
356 ((unsigned)addr[1] & 0xff), 677 if (af == AF_INET6 && len == IN6ADDRSZ &&
357 ((unsigned)addr[0] & 0xff)); 678 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
358 679 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
359 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 680 h_errno = HOST_NOT_FOUND;
360 return (_gethtbyaddr(addr, len, type)); 681 return (NULL);
361 682 }
362 bcopy(_res.lookups, lookups, sizeof lookups); 683 if (af == AF_INET6 && len == IN6ADDRSZ &&
684 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
685 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
686 /* Unmap. */
687 addr += IN6ADDRSZ - INADDRSZ;
688 uaddr += IN6ADDRSZ - INADDRSZ;
689 af = AF_INET;
690 len = INADDRSZ;
691 }
692 switch (af) {
693 case AF_INET:
694 size = INADDRSZ;
695 break;
696 case AF_INET6:
697 size = IN6ADDRSZ;
698 break;
699 default:
700 errno = EAFNOSUPPORT;
701 h_errno = NETDB_INTERNAL;
702 return (NULL);
703 }
704 if (size != len) {
705 errno = EINVAL;
706 h_errno = NETDB_INTERNAL;
707 return (NULL);
708 }
709 ep = qbuf + sizeof(qbuf);
710 switch (af) {
711 case AF_INET:
712 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
713 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
714 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
715 break;
716 case AF_INET6:
717 qp = qbuf;
718 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
719 i = snprintf(qp, ep - qp, "%x.%x.",
720 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
721 if (i <= 0) {
722 errno = EINVAL;
723 h_errno = NETDB_INTERNAL;
724 return (NULL);
725 }
726 qp += i;
727 }
728 break;
729 }
730
731 bcopy(_resp->lookups, lookups, sizeof lookups);
363 if (lookups[0] == '\0') 732 if (lookups[0] == '\0')
364 strncpy(lookups, "bf", sizeof lookups); 733 strlcpy(lookups, "bf", sizeof lookups);
365 734
366 hp = (struct hostent *)NULL; 735 hp = (struct hostent *)NULL;
367 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 736 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
368 switch (lookups[i]) { 737 switch (lookups[i]) {
369#ifdef YP 738#ifdef YP
370 case 'y': 739 case 'y':
371 hp = _yp_gethtbyaddr(addr, len, type); 740 /* YP only supports AF_INET. */
741 if (af == AF_INET)
742 hp = _yp_gethtbyaddr(addr);
372 break; 743 break;
373#endif 744#endif
374 case 'b': 745 case 'b':
375 n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 746 if (af == AF_INET6)
747 strlcpy(qp, "ip6.arpa", ep - qp);
748 buf = malloc(sizeof(*buf));
749 if (!buf)
750 break;
751 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
752 sizeof(buf->buf));
753 if (n < 0 && af == AF_INET6) {
754 strlcpy(qp, "ip6.int", ep - qp);
755 n = res_query(qbuf, C_IN, T_PTR,
756 buf->buf, sizeof(buf->buf));
757 }
376 if (n < 0) { 758 if (n < 0) {
759 free(buf);
377#ifdef DEBUG 760#ifdef DEBUG
378 if (_res.options & RES_DEBUG) 761 if (_resp->options & RES_DEBUG)
379 printf("res_query failed\n"); 762 printf("res_query failed\n");
380#endif 763#endif
381 break; 764 break;
382 } 765 }
383 hp = getanswer(&buf, n, 1); 766 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
384 if (hp == NULL) 767 free(buf);
385 break; 768 break;
386 hp->h_addrtype = type; 769 }
770 free(buf);
771 hp->h_addrtype = af;
387 hp->h_length = len; 772 hp->h_length = len;
388 h_addr_ptrs[0] = (char *)&host_addr; 773 bcopy(addr, host_addr, len);
389 h_addr_ptrs[1] = (char *)0; 774 h_addr_ptrs[0] = (char *)host_addr;
390 host_addr = *(struct in_addr *)addr; 775 h_addr_ptrs[1] = NULL;
776 if (af == AF_INET && (_resp->options & RES_USE_INET6)) {
777 map_v4v6_address((char*)host_addr,
778 (char*)host_addr);
779 hp->h_addrtype = AF_INET6;
780 hp->h_length = IN6ADDRSZ;
781 }
782 h_errno = NETDB_SUCCESS;
391 break; 783 break;
392 case 'f': 784 case 'f':
393 hp = _gethtbyaddr(addr, len, type); 785 hp = _gethtbyaddr(addr, len, af);
394 break; 786 break;
395 } 787 }
396 } 788 }
789 /* XXX h_errno not correct in all cases... */
397 return (hp); 790 return (hp);
398} 791}
399 792
@@ -420,37 +813,64 @@ _endhtent()
420struct hostent * 813struct hostent *
421_gethtent() 814_gethtent()
422{ 815{
816 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
423 char *p; 817 char *p;
424 register char *cp, **q; 818 register char *cp, **q;
819 int af;
820 size_t len;
425 821
426 if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 822 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
823 h_errno = NETDB_INTERNAL;
427 return (NULL); 824 return (NULL);
428again: 825 }
429 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 826 again:
827 if ((p = fgetln(hostf, &len)) == NULL) {
828 h_errno = HOST_NOT_FOUND;
430 return (NULL); 829 return (NULL);
830 }
831 if (p[len-1] == '\n')
832 len--;
833 if (len >= sizeof(hostbuf) || len == 0)
834 goto again;
835 p = memcpy(hostbuf, p, len);
836 hostbuf[len] = '\0';
431 if (*p == '#') 837 if (*p == '#')
432 goto again; 838 goto again;
433 cp = strpbrk(p, "#\n"); 839 if ((cp = strchr(p, '#')))
434 if (cp == NULL) 840 *cp = '\0';
435 goto again; 841 if (!(cp = strpbrk(p, " \t")))
436 *cp = '\0';
437 cp = strpbrk(p, " \t");
438 if (cp == NULL)
439 goto again; 842 goto again;
440 *cp++ = '\0'; 843 *cp++ = '\0';
441 /* THIS STUFF IS INTERNET SPECIFIC */ 844 if (inet_pton(AF_INET6, p, host_addr) > 0) {
442 h_addr_ptrs[0] = (char *)&host_addr; 845 af = AF_INET6;
846 len = IN6ADDRSZ;
847 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
848 if (_resp->options & RES_USE_INET6) {
849 map_v4v6_address((char*)host_addr, (char*)host_addr);
850 af = AF_INET6;
851 len = IN6ADDRSZ;
852 } else {
853 af = AF_INET;
854 len = INADDRSZ;
855 }
856 } else {
857 goto again;
858 }
859 /* if this is not something we're looking for, skip it. */
860 if (host.h_addrtype != af)
861 goto again;
862 if (host.h_length != len)
863 goto again;
864 h_addr_ptrs[0] = (char *)host_addr;
443 h_addr_ptrs[1] = NULL; 865 h_addr_ptrs[1] = NULL;
444 (void) inet_aton(p, &host_addr);
445 host.h_addr_list = h_addr_ptrs; 866 host.h_addr_list = h_addr_ptrs;
446 host.h_length = sizeof(u_int32_t); 867 host.h_length = len;
447 host.h_addrtype = AF_INET; 868 host.h_addrtype = af;
448 while (*cp == ' ' || *cp == '\t') 869 while (*cp == ' ' || *cp == '\t')
449 cp++; 870 cp++;
450 host.h_name = cp; 871 host.h_name = cp;
451 q = host.h_aliases = host_aliases; 872 q = host.h_aliases = host_aliases;
452 cp = strpbrk(cp, " \t"); 873 if ((cp = strpbrk(cp, " \t")))
453 if (cp != NULL)
454 *cp++ = '\0'; 874 *cp++ = '\0';
455 while (cp && *cp) { 875 while (cp && *cp) {
456 if (*cp == ' ' || *cp == '\t') { 876 if (*cp == ' ' || *cp == '\t') {
@@ -459,70 +879,77 @@ again:
459 } 879 }
460 if (q < &host_aliases[MAXALIASES - 1]) 880 if (q < &host_aliases[MAXALIASES - 1])
461 *q++ = cp; 881 *q++ = cp;
462 cp = strpbrk(cp, " \t"); 882 if ((cp = strpbrk(cp, " \t")))
463 if (cp != NULL)
464 *cp++ = '\0'; 883 *cp++ = '\0';
465 } 884 }
466 *q = NULL; 885 *q = NULL;
886 if (_resp->options & RES_USE_INET6) {
887 char *bp = hostbuf;
888 char *ep = hostbuf + sizeof hostbuf;
889
890 map_v4v6_hostent(&host, &bp, ep);
891 }
892 h_errno = NETDB_SUCCESS;
467 return (&host); 893 return (&host);
468} 894}
469 895
470struct hostent * 896struct hostent *
471_gethtbyname(name) 897_gethtbyname(name)
472 char *name; 898 const char *name;
899{
900 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
901 extern struct hostent *_gethtbyname2();
902 struct hostent *hp;
903
904 if (_resp->options & RES_USE_INET6) {
905 hp = _gethtbyname2(name, AF_INET6);
906 if (hp)
907 return (hp);
908 }
909 return (_gethtbyname2(name, AF_INET));
910}
911
912struct hostent *
913_gethtbyname2(name, af)
914 const char *name;
915 int af;
473{ 916{
474 register struct hostent *p; 917 register struct hostent *p;
475 register char **cp; 918 register char **cp;
476 919
477 _sethtent(0); 920 _sethtent(0);
478 while (p = _gethtent()) { 921 while ((p = _gethtent())) {
922 if (p->h_addrtype != af)
923 continue;
479 if (strcasecmp(p->h_name, name) == 0) 924 if (strcasecmp(p->h_name, name) == 0)
480 break; 925 break;
481 for (cp = p->h_aliases; *cp != 0; cp++) 926 for (cp = p->h_aliases; *cp != 0; cp++)
482 if (strcasecmp(*cp, name) == 0) 927 if (strcasecmp(*cp, name) == 0)
483 goto found; 928 goto found;
484 } 929 }
485found: 930 found:
486 _endhtent(); 931 _endhtent();
487 if (p==NULL)
488 h_errno = HOST_NOT_FOUND;
489 return (p); 932 return (p);
490} 933}
491 934
492struct hostent * 935struct hostent *
493_gethtbyaddr(addr, len, type) 936_gethtbyaddr(addr, len, af)
494 const char *addr; 937 const char *addr;
495 int len, type; 938 int len, af;
496{ 939{
497 register struct hostent *p; 940 register struct hostent *p;
498 941
942 host.h_length = len;
943 host.h_addrtype = af;
944
499 _sethtent(0); 945 _sethtent(0);
500 while (p = _gethtent()) 946 while ((p = _gethtent()))
501 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 947 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
502 break; 948 break;
503 _endhtent(); 949 _endhtent();
504 if (p==NULL)
505 h_errno = HOST_NOT_FOUND;
506 return (p); 950 return (p);
507} 951}
508 952
509static int
510qcomp(a1, a2)
511 struct in_addr **a1, **a2;
512{
513 int pos1, pos2;
514
515 for (pos1 = 0; pos1 < _res.nsort; pos1++)
516 if (_res.sort_list[pos1].addr.s_addr ==
517 ((*a1)->s_addr & _res.sort_list[pos1].mask))
518 break;
519 for (pos2 = 0; pos2 < _res.nsort; pos2++)
520 if (_res.sort_list[pos2].addr.s_addr ==
521 ((*a2)->s_addr & _res.sort_list[pos2].mask))
522 break;
523 return pos1 - pos2;
524}
525
526#ifdef YP 953#ifdef YP
527struct hostent * 954struct hostent *
528_yphostent(line) 955_yphostent(line)
@@ -537,21 +964,21 @@ _yphostent(line)
537 964
538 host.h_name = NULL; 965 host.h_name = NULL;
539 host.h_addr_list = h_addr_ptrs; 966 host.h_addr_list = h_addr_ptrs;
540 host.h_length = sizeof(u_int32_t); 967 host.h_length = INADDRSZ;
541 host.h_addrtype = AF_INET; 968 host.h_addrtype = AF_INET;
542 hap = h_addr_ptrs; 969 hap = h_addr_ptrs;
543 buf = host_addrs; 970 buf = host_addrs;
544 q = host.h_aliases = host_aliases; 971 q = host.h_aliases = host_aliases;
545 972
546nextline: 973nextline:
974 /* check for host_addrs overflow */
975 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
976 goto done;
977
547 more = 0; 978 more = 0;
548 cp = strpbrk(p, " \t"); 979 cp = strpbrk(p, " \t");
549 if (cp == NULL) { 980 if (cp == NULL)
550 if (host.h_name == NULL) 981 goto done;
551 return (NULL);
552 else
553 goto done;
554 }
555 *cp++ = '\0'; 982 *cp++ = '\0';
556 983
557 *hap++ = (char *)buf; 984 *hap++ = (char *)buf;
@@ -592,30 +1019,29 @@ nextline:
592 *cp++ = '\0'; 1019 *cp++ = '\0';
593 } 1020 }
594done: 1021done:
1022 if (host.h_name == NULL)
1023 return (NULL);
595 *q = NULL; 1024 *q = NULL;
596 *hap = NULL; 1025 *hap = NULL;
597 return (&host); 1026 return (&host);
598} 1027}
599 1028
600struct hostent * 1029struct hostent *
601_yp_gethtbyaddr(addr, len, type) 1030_yp_gethtbyaddr(addr)
602 const char *addr; 1031 const char *addr;
603 int len, type;
604{ 1032{
605 struct hostent *hp = (struct hostent *)NULL; 1033 struct hostent *hp = (struct hostent *)NULL;
606 static char *__ypcurrent; 1034 static char *__ypcurrent;
607 int __ypcurrentlen, r; 1035 int __ypcurrentlen, r;
608 char name[sizeof("xxx.xxx.xxx.xxx") + 1]; 1036 char name[sizeof("xxx.xxx.xxx.xxx")];
609 1037
610 if (!__ypdomain) { 1038 if (!__ypdomain) {
611 if (_yp_check(&__ypdomain) == 0) 1039 if (_yp_check(&__ypdomain) == 0)
612 return (hp); 1040 return (hp);
613 } 1041 }
614 sprintf(name, "%u.%u.%u.%u", 1042 snprintf(name, sizeof name, "%u.%u.%u.%u",
615 ((unsigned)addr[0] & 0xff), 1043 ((unsigned)addr[0] & 0xff), ((unsigned)addr[1] & 0xff),
616 ((unsigned)addr[1] & 0xff), 1044 ((unsigned)addr[2] & 0xff), ((unsigned)addr[3] & 0xff));
617 ((unsigned)addr[2] & 0xff),
618 ((unsigned)addr[3] & 0xff));
619 if (__ypcurrent) 1045 if (__ypcurrent)
620 free(__ypcurrent); 1046 free(__ypcurrent);
621 __ypcurrent = NULL; 1047 __ypcurrent = NULL;
@@ -636,6 +1062,8 @@ _yp_gethtbyname(name)
636 static char *__ypcurrent; 1062 static char *__ypcurrent;
637 int __ypcurrentlen, r; 1063 int __ypcurrentlen, r;
638 1064
1065 if (strlen(name) >= MAXHOSTNAMELEN)
1066 return (NULL);
639 if (!__ypdomain) { 1067 if (!__ypdomain) {
640 if (_yp_check(&__ypdomain) == 0) 1068 if (_yp_check(&__ypdomain) == 0)
641 return (hp); 1069 return (hp);
@@ -645,10 +1073,108 @@ _yp_gethtbyname(name)
645 __ypcurrent = NULL; 1073 __ypcurrent = NULL;
646 r = yp_match(__ypdomain, "hosts.byname", name, 1074 r = yp_match(__ypdomain, "hosts.byname", name,
647 strlen(name), &__ypcurrent, &__ypcurrentlen); 1075 strlen(name), &__ypcurrent, &__ypcurrentlen);
648 if (r==0) 1076 if (r == 0)
649 hp = _yphostent(__ypcurrent); 1077 hp = _yphostent(__ypcurrent);
650 if (hp==NULL) 1078 if (hp == NULL)
651 h_errno = HOST_NOT_FOUND; 1079 h_errno = HOST_NOT_FOUND;
652 return (hp); 1080 return (hp);
653} 1081}
654#endif 1082#endif
1083
1084static void
1085map_v4v6_address(src, dst)
1086 const char *src;
1087 char *dst;
1088{
1089 u_char *p = (u_char *)dst;
1090 char tmp[INADDRSZ];
1091 int i;
1092
1093 /* Stash a temporary copy so our caller can update in place. */
1094 bcopy(src, tmp, INADDRSZ);
1095 /* Mark this ipv6 addr as a mapped ipv4. */
1096 for (i = 0; i < 10; i++)
1097 *p++ = 0x00;
1098 *p++ = 0xff;
1099 *p++ = 0xff;
1100 /* Retrieve the saved copy and we're done. */
1101 bcopy(tmp, (void*)p, INADDRSZ);
1102}
1103
1104static void
1105map_v4v6_hostent(hp, bpp, ep)
1106 struct hostent *hp;
1107 char **bpp;
1108 char *ep;
1109{
1110 char **ap;
1111
1112 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1113 return;
1114 hp->h_addrtype = AF_INET6;
1115 hp->h_length = IN6ADDRSZ;
1116 for (ap = hp->h_addr_list; *ap; ap++) {
1117 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1118
1119 if (ep - *bpp < (i + IN6ADDRSZ)) {
1120 /* Out of memory. Truncate address list here. XXX */
1121 *ap = NULL;
1122 return;
1123 }
1124 *bpp += i;
1125 map_v4v6_address(*ap, *bpp);
1126 *ap = *bpp;
1127 *bpp += IN6ADDRSZ;
1128 }
1129}
1130
1131struct hostent *
1132gethostent()
1133{
1134 return (_gethtent());
1135}
1136
1137#ifdef RESOLVSORT
1138static void
1139addrsort(ap, num)
1140 char **ap;
1141 int num;
1142{
1143 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1144 int i, j;
1145 char **p;
1146 short aval[MAXADDRS];
1147 int needsort = 0;
1148
1149 p = ap;
1150 for (i = 0; i < num; i++, p++) {
1151 for (j = 0 ; (unsigned)j < _resp->nsort; j++)
1152 if (_resp->sort_list[j].addr.s_addr ==
1153 (((struct in_addr *)(*p))->s_addr & _resp->sort_list[j].mask))
1154 break;
1155 aval[i] = j;
1156 if (needsort == 0 && i > 0 && j < aval[i-1])
1157 needsort = i;
1158 }
1159 if (!needsort)
1160 return;
1161
1162 while (needsort < num) {
1163 for (j = needsort - 1; j >= 0; j--) {
1164 if (aval[j] > aval[j+1]) {
1165 char *hp;
1166
1167 i = aval[j];
1168 aval[j] = aval[j+1];
1169 aval[j+1] = i;
1170
1171 hp = ap[j];
1172 ap[j] = ap[j+1];
1173 ap[j+1] = hp;
1174 } else
1175 break;
1176 }
1177 needsort++;
1178 }
1179}
1180#endif