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.c775
1 files changed, 569 insertions, 206 deletions
diff --git a/src/lib/libc/net/gethostnamadr.c b/src/lib/libc/net/gethostnamadr.c
index 83e0225a65..9826b46805 100644
--- a/src/lib/libc/net/gethostnamadr.c
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -52,7 +52,7 @@
52 */ 52 */
53 53
54#if defined(LIBC_SCCS) && !defined(lint) 54#if defined(LIBC_SCCS) && !defined(lint)
55static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.13 1997/01/30 05:56:06 deraadt Exp $"; 55static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.14 1997/03/13 19:07:24 downsj Exp $";
56#endif /* LIBC_SCCS and not lint */ 56#endif /* LIBC_SCCS and not lint */
57 57
58#include <sys/param.h> 58#include <sys/param.h>
@@ -66,6 +66,7 @@ static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.13 1997/01/30 05:56:06 dera
66#include <ctype.h> 66#include <ctype.h>
67#include <errno.h> 67#include <errno.h>
68#include <string.h> 68#include <string.h>
69#include <syslog.h>
69#ifdef YP 70#ifdef YP
70#include <rpc/rpc.h> 71#include <rpc/rpc.h>
71#include <rpcsvc/yp.h> 72#include <rpcsvc/yp.h>
@@ -73,6 +74,8 @@ static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.13 1997/01/30 05:56:06 dera
73#include "ypinternal.h" 74#include "ypinternal.h"
74#endif 75#endif
75 76
77#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
78
76#define MAXALIASES 35 79#define MAXALIASES 35
77#define MAXADDRS 35 80#define MAXADDRS 35
78 81
@@ -85,10 +88,22 @@ static char *__ypdomain;
85static struct hostent host; 88static struct hostent host;
86static char *host_aliases[MAXALIASES]; 89static char *host_aliases[MAXALIASES];
87static char hostbuf[BUFSIZ+1]; 90static char hostbuf[BUFSIZ+1];
88static struct in_addr host_addr; 91static u_char host_addr[16]; /* IPv4 or IPv6 */
89static FILE *hostf = NULL; 92static FILE *hostf = NULL;
90static int stayopen = 0; 93static int stayopen = 0;
91 94
95static void map_v4v6_address __P((const char *src, char *dst));
96static void map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len));
97
98#ifdef RESOLVSORT
99static void addrsort __P((char **, int));
100#endif
101
102static int hokchar __P((const char *));
103
104static const char AskedForGot[] =
105 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
106
92#if PACKETSZ > 1024 107#if PACKETSZ > 1024
93#define MAXPACKET PACKETSZ 108#define MAXPACKET PACKETSZ
94#else 109#else
@@ -105,15 +120,14 @@ typedef union {
105 char ac; 120 char ac;
106} align; 121} align;
107 122
108static int qcomp __P((struct in_addr **, struct in_addr **)); 123static struct hostent *getanswer __P((const querybuf *, int, const char *,
109static struct hostent *getanswer __P((querybuf *, int, int)); 124 int));
110static int hbadchar __P((char *));
111 125
112extern int h_errno; 126extern int h_errno;
113 127
114static int 128static int
115hbadchar(p) 129hokchar(p)
116 char *p; 130 const char *p;
117{ 131{
118 char c; 132 char c;
119 133
@@ -121,7 +135,7 @@ hbadchar(p)
121 * Many people do not obey RFC 822 and 1035. The valid 135 * Many people do not obey RFC 822 and 1035. The valid
122 * characters are a-z, A-Z, 0-9, '-' and . But the others 136 * characters are a-z, A-Z, 0-9, '-' and . But the others
123 * tested for below can happen, and we must be more permissive 137 * tested for below can happen, and we must be more permissive
124 * until those idiots clean up their act. 138 * than the resolver until those idiots clean up their act.
125 */ 139 */
126 while ((c = *p++)) { 140 while ((c = *p++)) {
127 if (('a' >= c && c <= 'z') || 141 if (('a' >= c && c <= 'z') ||
@@ -130,28 +144,50 @@ hbadchar(p)
130 continue; 144 continue;
131 if (strchr("-_/.[]\\", c) || 145 if (strchr("-_/.[]\\", c) ||
132 (c == '.' && p[1] == '.')) 146 (c == '.' && p[1] == '.'))
133 return 1; 147 return 0;
134 } 148 }
135 return 0; 149 return 1;
136} 150}
137 151
138static struct hostent * 152static struct hostent *
139getanswer(answer, anslen, iquery) 153getanswer(answer, anslen, qname, qtype)
140 querybuf *answer; 154 const querybuf *answer;
141 int anslen; 155 int anslen;
142 int iquery; 156 const char *qname;
157 int qtype;
143{ 158{
144 register HEADER *hp; 159 register const HEADER *hp;
145 register u_char *cp; 160 register const u_char *cp;
146 register int n; 161 register int n;
147 u_char *eom; 162 const u_char *eom;
148 char *bp, **ap; 163 char *bp, **ap, **hap;
149 int type, class, buflen, ancount, qdcount; 164 int type, class, buflen, ancount, qdcount;
150 int haveanswer, getclass = C_ANY; 165 int haveanswer, had_error;
151 char **hap; 166 int toobig = 0;
152 int good = 1; 167 char tbuf[MAXDNAME];
168 const char *tname;
169 int (*name_ok) __P((const char *));
153 170
171 tname = qname;
172 host.h_name = NULL;
154 eom = answer->buf + anslen; 173 eom = answer->buf + anslen;
174 switch (qtype) {
175 case T_A:
176 case T_AAAA:
177#ifdef USE_RESOLV_NAME_OK
178 name_ok = res_hnok;
179 break;
180#endif
181 case T_PTR:
182#ifdef USE_RESOLV_NAME_OK
183 name_ok = res_dnok;
184#else
185 name_ok = hokchar;
186#endif
187 break;
188 default:
189 return (NULL); /* XXX should be abort(); */
190 }
155 /* 191 /*
156 * find first satisfactory answer 192 * find first satisfactory answer
157 */ 193 */
@@ -159,34 +195,29 @@ getanswer(answer, anslen, iquery)
159 ancount = ntohs(hp->ancount); 195 ancount = ntohs(hp->ancount);
160 qdcount = ntohs(hp->qdcount); 196 qdcount = ntohs(hp->qdcount);
161 bp = hostbuf; 197 bp = hostbuf;
162 buflen = sizeof(hostbuf); 198 buflen = sizeof hostbuf;
163 cp = answer->buf + sizeof(HEADER); 199 cp = answer->buf + HFIXEDSZ;
164 if (qdcount) { 200 if (qdcount != 1) {
165 if (iquery) { 201 h_errno = NO_RECOVERY;
166 if ((n = dn_expand((u_char *)answer->buf, 202 return (NULL);
167 (u_char *)eom, (u_char *)cp, bp, 203 }
168 buflen)) < 0) { 204 n = dn_expand(answer->buf, eom, cp, bp, buflen);
169 h_errno = NO_RECOVERY; 205 if ((n < 0) || !(*name_ok)(bp)) {
170 return ((struct hostent *) NULL); 206 h_errno = NO_RECOVERY;
171 } 207 return (NULL);
172 cp += n + QFIXEDSZ; 208 }
173 host.h_name = bp; 209 cp += n + QFIXEDSZ;
174 n = strlen(bp); 210 if (qtype == T_A || qtype == T_AAAA) {
175 if (n >= MAXHOSTNAMELEN) 211 /* res_send() has already verified that the query name is the
176 host.h_name[MAXHOSTNAMELEN-1] = '\0'; 212 * same as the one we sent; this just gets the expanded name
177 n++; 213 * (i.e., with the succeeding search-domain tacked on).
178 bp += n; 214 */
179 buflen -= n; 215 n = strlen(bp) + 1; /* for the \0 */
180 } else 216 host.h_name = bp;
181 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 217 bp += n;
182 while (--qdcount > 0) 218 buflen -= n;
183 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 219 /* The qname can be abbreviated, but h_name is now absolute. */
184 } else if (iquery) { 220 qname = host.h_name;
185 if (hp->aa)
186 h_errno = HOST_NOT_FOUND;
187 else
188 h_errno = TRY_AGAIN;
189 return ((struct hostent *) NULL);
190 } 221 }
191 ap = host_aliases; 222 ap = host_aliases;
192 *ap = NULL; 223 *ap = NULL;
@@ -195,124 +226,258 @@ getanswer(answer, anslen, iquery)
195 *hap = NULL; 226 *hap = NULL;
196 host.h_addr_list = h_addr_ptrs; 227 host.h_addr_list = h_addr_ptrs;
197 haveanswer = 0; 228 haveanswer = 0;
198 if (ancount > MAXADDRS) 229 had_error = 0;
199 ancount = MAXADDRS; 230 while (ancount-- > 0 && cp < eom && !had_error) {
200 while (--ancount >= 0 && cp < eom) { 231 n = dn_expand(answer->buf, eom, cp, bp, buflen);
201 if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, 232 if ((n < 0) || !(*name_ok)(bp)) {
202 (u_char *)cp, bp, buflen)) < 0) 233 had_error++;
203 break; 234 continue;
204 cp += n; 235 }
236 cp += n; /* name */
205 type = _getshort(cp); 237 type = _getshort(cp);
206 cp += sizeof(u_int16_t); 238 cp += INT16SZ; /* type */
207 class = _getshort(cp); 239 class = _getshort(cp);
208 cp += sizeof(u_int16_t) + sizeof(u_int32_t); 240 cp += INT16SZ + INT32SZ; /* class, TTL */
209 n = _getshort(cp); 241 n = _getshort(cp);
210 cp += sizeof(u_int16_t); 242 cp += INT16SZ; /* len */
211 if (type == T_CNAME) { 243 if (class != C_IN) {
244 /* XXX - debug? syslog? */
212 cp += n; 245 cp += n;
246 continue; /* XXX - had_error++ ? */
247 }
248 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
213 if (ap >= &host_aliases[MAXALIASES-1]) 249 if (ap >= &host_aliases[MAXALIASES-1])
214 continue; 250 continue;
251 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
252 if ((n < 0) || !(*name_ok)(tbuf)) {
253 had_error++;
254 continue;
255 }
256 cp += n;
257 /* Store alias. */
215 *ap++ = bp; 258 *ap++ = bp;
216 n = strlen(bp) + 1; 259 n = strlen(bp) + 1; /* for the \0 */
217 if (n > MAXHOSTNAMELEN) 260 bp += n;
218 bp[MAXHOSTNAMELEN-1] = '\0'; 261 buflen -= n;
262 /* Get canonical name. */
263 n = strlen(tbuf) + 1; /* for the \0 */
264 if (n > buflen) {
265 had_error++;
266 continue;
267 }
268 strcpy(bp, tbuf);
269 host.h_name = bp;
219 bp += n; 270 bp += n;
220 buflen -= n; 271 buflen -= n;
221 continue; 272 continue;
222 } 273 }
223 if (iquery && type == T_PTR) { 274 if (qtype == T_PTR && type == T_CNAME) {
224 if ((n = dn_expand((u_char *)answer->buf, 275 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
225 (u_char *)eom, (u_char *)cp, bp, 276 if ((n < 0) || !res_hnok(tbuf)) {
226 buflen)) < 0) 277 had_error++;
227 break; 278 continue;
279 }
228 cp += n; 280 cp += n;
229 host.h_name = bp; 281 /* Get canonical name. */
230 n = strlen(host.h_name); 282 n = strlen(tbuf) + 1; /* for the \0 */
231 if (n >= MAXHOSTNAMELEN) 283 if (n > buflen) {
232 host.h_name[MAXHOSTNAMELEN-1] = '\0'; 284 had_error++;
233 goto gotent; 285 continue;
286 }
287 strcpy(bp, tbuf);
288 tname = bp;
289 bp += n;
290 buflen -= n;
291 continue;
234 } 292 }
235 if (iquery || type != T_A) { 293 if (type != qtype) {
236#ifdef DEBUG 294 syslog(LOG_NOTICE|LOG_AUTH,
237 if (_res.options & RES_DEBUG) 295 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
238 printf("unexpected answer type %d, size %d\n", 296 qname, p_class(C_IN), p_type(qtype),
239 type, n); 297 p_type(type));
240#endif
241 cp += n; 298 cp += n;
242 continue; 299 continue; /* XXX - had_error++ ? */
243 } 300 }
244 301 switch (type) {
245 if (haveanswer) { 302 case T_PTR:
246 if (n != host.h_length) { 303 if (strcasecmp(tname, bp) != 0) {
304 syslog(LOG_NOTICE|LOG_AUTH,
305 AskedForGot, qname, bp);
247 cp += n; 306 cp += n;
248 continue; 307 continue; /* XXX - had_error++ ? */
249 } 308 }
250 if (class != getclass) { 309 n = dn_expand(answer->buf, eom, cp, bp, buflen);
310 if ((n < 0) || !res_hnok(bp)) {
311 had_error++;
312 break;
313 }
314#if MULTI_PTRS_ARE_ALIASES
315 cp += n;
316 if (!haveanswer)
317 host.h_name = bp;
318 else if (ap < &host_aliases[MAXALIASES-1])
319 *ap++ = bp;
320 else
321 n = -1;
322 if (n != -1) {
323 n = strlen(bp) + 1; /* for the \0 */
324 bp += n;
325 buflen -= n;
326 }
327 break;
328#else
329 host.h_name = bp;
330 if (_res.options & RES_USE_INET6) {
331 n = strlen(bp) + 1; /* for the \0 */
332 bp += n;
333 buflen -= n;
334 map_v4v6_hostent(&host, &bp, &buflen);
335 }
336 h_errno = NETDB_SUCCESS;
337 return (&host);
338#endif
339 case T_A:
340 case T_AAAA:
341 if (strcasecmp(host.h_name, bp) != 0) {
342 syslog(LOG_NOTICE|LOG_AUTH,
343 AskedForGot, host.h_name, bp);
344 cp += n;
345 continue; /* XXX - had_error++ ? */
346 }
347 if (n != host.h_length) {
251 cp += n; 348 cp += n;
252 continue; 349 continue;
253 } 350 }
254 } else { 351 if (!haveanswer) {
255 host.h_length = n; 352 register int nn;
256 getclass = class; 353
257 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
258 if (host.h_addrtype == AF_INET)
259 host.h_length = INADDRSZ;
260 if (!iquery) {
261 host.h_name = bp; 354 host.h_name = bp;
262 bp += strlen(bp) + 1; 355 nn = strlen(bp) + 1; /* for the \0 */
263 if (strlen(host.h_name) >= MAXHOSTNAMELEN) 356 bp += nn;
264 host.h_name[MAXHOSTNAMELEN-1] = '\0'; 357 buflen -= nn;
265 } 358 }
266 }
267 359
268 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 360 bp += sizeof(align) - ((u_long)bp % sizeof(align));
269 361
270 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 362 if (bp + n >= &hostbuf[sizeof hostbuf]) {
363#ifdef DEBUG
364 if (_res.options & RES_DEBUG)
365 printf("size (%d) too big\n", n);
366#endif
367 had_error++;
368 continue;
369 }
370 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
371 if (!toobig++)
271#ifdef DEBUG 372#ifdef DEBUG
272 if (_res.options & RES_DEBUG) 373 if (_res.options & RES_DEBUG)
273 printf("size (%d) too big\n", n); 374 printf("Too many addresses (%d)\n", MAXADDRS);
274#endif 375#endif
376 cp += n;
377 continue;
378 }
379 bcopy(cp, *hap++ = bp, n);
380 bp += n;
381 buflen -= n;
382 cp += n;
275 break; 383 break;
384 default:
385 abort();
276 } 386 }
277 bcopy(cp, *hap++ = bp, n); 387 if (!had_error)
278 bp +=n; 388 haveanswer++;
279 cp += n;
280 haveanswer++;
281 }
282 if (!haveanswer) {
283 h_errno = TRY_AGAIN;
284 return ((struct hostent *) NULL);
285 }
286 *ap = NULL;
287 *hap = NULL;
288 if (_res.nsort) {
289 qsort(host.h_addr_list, haveanswer,
290 sizeof(struct in_addr),
291 (int (*)__P((const void *, const void *)))qcomp);
292 } 389 }
293gotent: 390 if (haveanswer) {
294 if (hbadchar(host.h_name)) 391 *ap = NULL;
295 good = 0; 392 *hap = NULL;
296 for (ap = host_aliases; good && *ap; ap++) 393# if defined(RESOLVSORT)
297 if (hbadchar(*ap)) 394 /*
298 good = 0; 395 * Note: we sort even if host can take only one address
299 if (good) 396 * in its return structures - should give it the "best"
397 * address in that case, not some random one
398 */
399 if (_res.nsort && haveanswer > 1 && qtype == T_A)
400 addrsort(h_addr_ptrs, haveanswer);
401# endif /*RESOLVSORT*/
402 if (!host.h_name) {
403 n = strlen(qname) + 1; /* for the \0 */
404 if (n > buflen)
405 goto try_again;
406 strcpy(bp, qname);
407 host.h_name = bp;
408 bp += n;
409 buflen -= n;
410 }
411 if (_res.options & RES_USE_INET6)
412 map_v4v6_hostent(&host, &bp, &buflen);
413 h_errno = NETDB_SUCCESS;
300 return (&host); 414 return (&host);
301 h_errno = NO_RECOVERY; 415 }
302 return ((struct hostent *) NULL); 416 try_again:
417 h_errno = TRY_AGAIN;
418 return (NULL);
303} 419}
304 420
305struct hostent * 421struct hostent *
306gethostbyname(name) 422gethostbyname(name)
307 const char *name; 423 const char *name;
308{ 424{
425 struct hostent *hp;
426 extern struct hostent *_gethtbyname2();
427
428 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
429 return (_gethtbyname2(name, AF_INET));
430
431 if (_res.options & RES_USE_INET6) {
432 hp = gethostbyname2(name, AF_INET6);
433 if (hp)
434 return (hp);
435 }
436 return (gethostbyname2(name, AF_INET));
437}
438
439struct hostent *
440gethostbyname2(name, af)
441 const char *name;
442 int af;
443{
309 querybuf buf; 444 querybuf buf;
310 register const char *cp; 445 register const char *cp;
311 int n, i; 446 char *bp;
312 extern struct hostent *_gethtbyname(), *_yp_gethtbyname(); 447 int n, size, type, len, i;
448 extern struct hostent *_gethtbyname2(), *_yp_gethtbyname();
313 register struct hostent *hp; 449 register struct hostent *hp;
314 char lookups[MAXDNSLUS]; 450 char lookups[MAXDNSLUS];
315 451
452 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
453 return (_gethtbyname2(name, af));
454
455 switch (af) {
456 case AF_INET:
457 size = INADDRSZ;
458 type = T_A;
459 break;
460 case AF_INET6:
461 size = IN6ADDRSZ;
462 type = T_AAAA;
463 break;
464 default:
465 h_errno = NETDB_INTERNAL;
466 errno = EAFNOSUPPORT;
467 return (NULL);
468 }
469
470 host.h_addrtype = af;
471 host.h_length = size;
472
473 /*
474 * if there aren't any dots, it could be a user-level alias.
475 * this is also done in res_query() since we are not the only
476 * function that looks up host names.
477 */
478 if (!strchr(name, '.') && (cp = __hostalias(name)))
479 name = cp;
480
316 /* 481 /*
317 * disallow names consisting only of digits/dots, unless 482 * disallow names consisting only of digits/dots, unless
318 * they end in a dot. 483 * they end in a dot.
@@ -327,26 +492,58 @@ gethostbyname(name)
327 * Fake up a hostent as if we'd actually 492 * Fake up a hostent as if we'd actually
328 * done a lookup. 493 * done a lookup.
329 */ 494 */
330 if (!inet_aton(name, &host_addr)) { 495 if (inet_pton(af, name, host_addr) <= 0) {
331 h_errno = HOST_NOT_FOUND; 496 h_errno = HOST_NOT_FOUND;
332 return((struct hostent *) NULL); 497 return (NULL);
333 } 498 }
334 host.h_name = (char *)name; 499 strncpy(hostbuf, name, MAXDNAME);
500 hostbuf[MAXDNAME] = '\0';
501 bp = hostbuf + MAXDNAME;
502 len = sizeof hostbuf - MAXDNAME;
503 host.h_name = hostbuf;
335 host.h_aliases = host_aliases; 504 host.h_aliases = host_aliases;
336 host_aliases[0] = NULL; 505 host_aliases[0] = NULL;
337 host.h_addrtype = AF_INET; 506 h_addr_ptrs[0] = (char *)host_addr;
338 host.h_length = sizeof(u_int32_t);
339 h_addr_ptrs[0] = (char *)&host_addr;
340 h_addr_ptrs[1] = NULL; 507 h_addr_ptrs[1] = NULL;
341 host.h_addr_list = h_addr_ptrs; 508 host.h_addr_list = h_addr_ptrs;
509 if (_res.options & RES_USE_INET6)
510 map_v4v6_hostent(&host, &bp, &len);
511 h_errno = NETDB_SUCCESS;
342 return (&host); 512 return (&host);
343 } 513 }
344 if (!isdigit(*cp) && *cp != '.') 514 if (!isdigit(*cp) && *cp != '.')
345 break; 515 break;
346 } 516 }
347 517 if (isxdigit(name[0]) || name[0] == ':')
348 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 518 for (cp = name;; ++cp) {
349 return (_gethtbyname(name)); 519 if (!*cp) {
520 if (*--cp == '.')
521 break;
522 /*
523 * All-IPv6-legal, no dot at the end.
524 * Fake up a hostent as if we'd actually
525 * done a lookup.
526 */
527 if (inet_pton(af, name, host_addr) <= 0) {
528 h_errno = HOST_NOT_FOUND;
529 return (NULL);
530 }
531 strncpy(hostbuf, name, MAXDNAME);
532 hostbuf[MAXDNAME] = '\0';
533 bp = hostbuf + MAXDNAME;
534 len = sizeof hostbuf - MAXDNAME;
535 host.h_name = hostbuf;
536 host.h_aliases = host_aliases;
537 host_aliases[0] = NULL;
538 h_addr_ptrs[0] = (char *)host_addr;
539 h_addr_ptrs[1] = NULL;
540 host.h_addr_list = h_addr_ptrs;
541 h_errno = NETDB_SUCCESS;
542 return (&host);
543 }
544 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
545 break;
546 }
350 547
351 bcopy(_res.lookups, lookups, sizeof lookups); 548 bcopy(_res.lookups, lookups, sizeof lookups);
352 if (lookups[0] == '\0') 549 if (lookups[0] == '\0')
@@ -357,11 +554,13 @@ gethostbyname(name)
357 switch (lookups[i]) { 554 switch (lookups[i]) {
358#ifdef YP 555#ifdef YP
359 case 'y': 556 case 'y':
360 hp = _yp_gethtbyname(name); 557 /* YP only suports AF_INET. */
558 if (af == AF_INET)
559 hp = _yp_gethtbyname(name);
361 break; 560 break;
362#endif 561#endif
363 case 'b': 562 case 'b':
364 if ((n = res_search(name, C_IN, T_A, buf.buf, 563 if ((n = res_search(name, C_IN, type, buf.buf,
365 sizeof(buf))) < 0) { 564 sizeof(buf))) < 0) {
366#ifdef DEBUG 565#ifdef DEBUG
367 if (_res.options & RES_DEBUG) 566 if (_res.options & RES_DEBUG)
@@ -369,10 +568,10 @@ gethostbyname(name)
369#endif 568#endif
370 break; 569 break;
371 } 570 }
372 hp = getanswer(&buf, n, 0); 571 hp = getanswer(&buf, n, name, type);
373 break; 572 break;
374 case 'f': 573 case 'f':
375 hp = _gethtbyname(name); 574 hp = _gethtbyname2(name, af);
376 break; 575 break;
377 } 576 }
378 } 577 }
@@ -380,27 +579,69 @@ gethostbyname(name)
380} 579}
381 580
382struct hostent * 581struct hostent *
383gethostbyaddr(addr, len, type) 582gethostbyaddr(addr, len, af)
384 const char *addr; 583 const char *addr; /* XXX should have been def'd as u_char! */
385 int len, type; 584 int len, af;
386{ 585{
387 int n, i; 586 const u_char *uaddr = (const u_char *)addr;
587 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
588 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
589 int n, size, i;
388 querybuf buf; 590 querybuf buf;
389 register struct hostent *hp; 591 register struct hostent *hp;
390 char qbuf[MAXDNAME]; 592 char qbuf[MAXDNAME+1], *qp;
391 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr(); 593 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr();
392 char lookups[MAXDNSLUS]; 594 char lookups[MAXDNSLUS];
393 595
394 if (type != AF_INET)
395 return ((struct hostent *) NULL);
396 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
397 ((unsigned)addr[3] & 0xff),
398 ((unsigned)addr[2] & 0xff),
399 ((unsigned)addr[1] & 0xff),
400 ((unsigned)addr[0] & 0xff));
401
402 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 596 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
403 return (_gethtbyaddr(addr, len, type)); 597 return (_gethtbyaddr(addr, len, af));
598
599 if (af == AF_INET6 && len == IN6ADDRSZ &&
600 (!bcmp(uaddr, mapped, sizeof mapped) ||
601 !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
602 /* Unmap. */
603 addr += sizeof mapped;
604 uaddr += sizeof mapped;
605 af = AF_INET;
606 len = INADDRSZ;
607 }
608 switch (af) {
609 case AF_INET:
610 size = INADDRSZ;
611 break;
612 case AF_INET6:
613 size = IN6ADDRSZ;
614 break;
615 default:
616 errno = EAFNOSUPPORT;
617 h_errno = NETDB_INTERNAL;
618 return (NULL);
619 }
620 if (size != len) {
621 errno = EINVAL;
622 h_errno = NETDB_INTERNAL;
623 return (NULL);
624 }
625 switch (af) {
626 case AF_INET:
627 (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
628 (uaddr[3] & 0xff),
629 (uaddr[2] & 0xff),
630 (uaddr[1] & 0xff),
631 (uaddr[0] & 0xff));
632 break;
633 case AF_INET6:
634 qp = qbuf;
635 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
636 qp += sprintf(qp, "%x.%x.",
637 uaddr[n] & 0xf,
638 (uaddr[n] >> 4) & 0xf);
639 }
640 strcpy(qp, "ip6.int");
641 break;
642 default:
643 abort();
644 }
404 645
405 bcopy(_res.lookups, lookups, sizeof lookups); 646 bcopy(_res.lookups, lookups, sizeof lookups);
406 if (lookups[0] == '\0') 647 if (lookups[0] == '\0')
@@ -411,29 +652,38 @@ gethostbyaddr(addr, len, type)
411 switch (lookups[i]) { 652 switch (lookups[i]) {
412#ifdef YP 653#ifdef YP
413 case 'y': 654 case 'y':
414 hp = _yp_gethtbyaddr(addr); 655 /* YP only supports AF_INET. */
656 if (af == AF_INET)
657 hp = _yp_gethtbyaddr(addr);
415 break; 658 break;
416#endif 659#endif
417 case 'b': 660 case 'b':
418 n = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf)); 661 n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf,
662 sizeof buf.buf);
419 if (n < 0) { 663 if (n < 0) {
420#ifdef DEBUG 664#ifdef DEBUG
421 if (_res.options & RES_DEBUG) 665 if (_res.options & RES_DEBUG)
422 printf("res_query failed\n"); 666 printf("res_query failed\n");
423#endif 667#endif
424 break; 668 return (NULL);
425 } 669 }
426 hp = getanswer(&buf, n, 1); 670 if (!(hp = getanswer(&buf, n, qbuf, T_PTR)))
427 if (hp == NULL) 671 return (NULL); /* h_errno was set by getanswer() */
428 break; 672 hp->h_addrtype = af;
429 hp->h_addrtype = type;
430 hp->h_length = len; 673 hp->h_length = len;
431 h_addr_ptrs[0] = (char *)&host_addr; 674 bcopy(addr, host_addr, len);
432 h_addr_ptrs[1] = (char *)0; 675 h_addr_ptrs[0] = (char *)host_addr;
433 host_addr = *(struct in_addr *)addr; 676 h_addr_ptrs[1] = NULL;
677 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
678 map_v4v6_address((char*)host_addr,
679 (char*)host_addr);
680 hp->h_addrtype = AF_INET6;
681 hp->h_length = IN6ADDRSZ;
682 }
683 h_errno = NETDB_SUCCESS;
434 break; 684 break;
435 case 'f': 685 case 'f':
436 hp = _gethtbyaddr(addr, len, type); 686 hp = _gethtbyaddr(addr, len, af);
437 break; 687 break;
438 } 688 }
439 } 689 }
@@ -465,35 +715,51 @@ _gethtent()
465{ 715{
466 char *p; 716 char *p;
467 register char *cp, **q; 717 register char *cp, **q;
718 int af, len;
468 719
469 if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 720 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
721 h_errno = NETDB_INTERNAL;
470 return (NULL); 722 return (NULL);
471again: 723 }
472 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 724 again:
725 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
726 h_errno = HOST_NOT_FOUND;
473 return (NULL); 727 return (NULL);
728 }
474 if (*p == '#') 729 if (*p == '#')
475 goto again; 730 goto again;
476 cp = strpbrk(p, "#\n"); 731 if (!(cp = strpbrk(p, "#\n")))
477 if (cp == NULL)
478 goto again; 732 goto again;
479 *cp = '\0'; 733 *cp = '\0';
480 cp = strpbrk(p, " \t"); 734 if (!(cp = strpbrk(p, " \t")))
481 if (cp == NULL)
482 goto again; 735 goto again;
483 *cp++ = '\0'; 736 *cp++ = '\0';
484 /* THIS STUFF IS INTERNET SPECIFIC */ 737 if ((_res.options & RES_USE_INET6) &&
485 h_addr_ptrs[0] = (char *)&host_addr; 738 inet_pton(AF_INET6, p, host_addr) > 0) {
739 af = AF_INET6;
740 len = IN6ADDRSZ;
741 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
742 if (_res.options & RES_USE_INET6) {
743 map_v4v6_address((char*)host_addr, (char*)host_addr);
744 af = AF_INET6;
745 len = IN6ADDRSZ;
746 } else {
747 af = AF_INET;
748 len = INADDRSZ;
749 }
750 } else {
751 goto again;
752 }
753 h_addr_ptrs[0] = (char *)host_addr;
486 h_addr_ptrs[1] = NULL; 754 h_addr_ptrs[1] = NULL;
487 (void) inet_aton(p, &host_addr);
488 host.h_addr_list = h_addr_ptrs; 755 host.h_addr_list = h_addr_ptrs;
489 host.h_length = sizeof(u_int32_t); 756 host.h_length = len;
490 host.h_addrtype = AF_INET; 757 host.h_addrtype = af;
491 while (*cp == ' ' || *cp == '\t') 758 while (*cp == ' ' || *cp == '\t')
492 cp++; 759 cp++;
493 host.h_name = cp; 760 host.h_name = cp;
494 q = host.h_aliases = host_aliases; 761 q = host.h_aliases = host_aliases;
495 cp = strpbrk(cp, " \t"); 762 if (cp = strpbrk(cp, " \t"))
496 if (cp != NULL)
497 *cp++ = '\0'; 763 *cp++ = '\0';
498 while (cp && *cp) { 764 while (cp && *cp) {
499 if (*cp == ' ' || *cp == '\t') { 765 if (*cp == ' ' || *cp == '\t') {
@@ -502,11 +768,17 @@ again:
502 } 768 }
503 if (q < &host_aliases[MAXALIASES - 1]) 769 if (q < &host_aliases[MAXALIASES - 1])
504 *q++ = cp; 770 *q++ = cp;
505 cp = strpbrk(cp, " \t"); 771 if (cp = strpbrk(cp, " \t"))
506 if (cp != NULL)
507 *cp++ = '\0'; 772 *cp++ = '\0';
508 } 773 }
509 *q = NULL; 774 *q = NULL;
775 if (_res.options & RES_USE_INET6) {
776 char *bp = hostbuf;
777 int buflen = sizeof hostbuf;
778
779 map_v4v6_hostent(&host, &bp, &buflen);
780 }
781 h_errno = NETDB_SUCCESS;
510 return (&host); 782 return (&host);
511} 783}
512 784
@@ -514,58 +786,55 @@ struct hostent *
514_gethtbyname(name) 786_gethtbyname(name)
515 const char *name; 787 const char *name;
516{ 788{
789 extern struct hostent *_gethtbyname2();
790 struct hostent *hp;
791
792 if (_res.options & RES_USE_INET6) {
793 hp = _gethtbyname2(name, AF_INET6);
794 if (hp)
795 return (hp);
796 }
797 return (_gethtbyname2(name, AF_INET));
798}
799
800struct hostent *
801_gethtbyname2(name, af)
802 const char *name;
803 int af;
804{
517 register struct hostent *p; 805 register struct hostent *p;
518 register char **cp; 806 register char **cp;
519 807
520 _sethtent(0); 808 _sethtent(0);
521 while (p = _gethtent()) { 809 while (p = _gethtent()) {
810 if (p->h_addrtype != af)
811 continue;
522 if (strcasecmp(p->h_name, name) == 0) 812 if (strcasecmp(p->h_name, name) == 0)
523 break; 813 break;
524 for (cp = p->h_aliases; *cp != 0; cp++) 814 for (cp = p->h_aliases; *cp != 0; cp++)
525 if (strcasecmp(*cp, name) == 0) 815 if (strcasecmp(*cp, name) == 0)
526 goto found; 816 goto found;
527 } 817 }
528found: 818 found:
529 _endhtent(); 819 _endhtent();
530 if (p==NULL)
531 h_errno = HOST_NOT_FOUND;
532 return (p); 820 return (p);
533} 821}
534 822
535struct hostent * 823struct hostent *
536_gethtbyaddr(addr, len, type) 824_gethtbyaddr(addr, len, af)
537 const char *addr; 825 const char *addr;
538 int len, type; 826 int len, af;
539{ 827{
540 register struct hostent *p; 828 register struct hostent *p;
541 829
542 _sethtent(0); 830 _sethtent(0);
543 while (p = _gethtent()) 831 while (p = _gethtent())
544 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 832 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
545 break; 833 break;
546 _endhtent(); 834 _endhtent();
547 if (p==NULL)
548 h_errno = HOST_NOT_FOUND;
549 return (p); 835 return (p);
550} 836}
551 837
552static int
553qcomp(a1, a2)
554 struct in_addr **a1, **a2;
555{
556 int pos1, pos2;
557
558 for (pos1 = 0; pos1 < _res.nsort; pos1++)
559 if (_res.sort_list[pos1].addr.s_addr ==
560 ((*a1)->s_addr & _res.sort_list[pos1].mask))
561 break;
562 for (pos2 = 0; pos2 < _res.nsort; pos2++)
563 if (_res.sort_list[pos2].addr.s_addr ==
564 ((*a2)->s_addr & _res.sort_list[pos2].mask))
565 break;
566 return pos1 - pos2;
567}
568
569#ifdef YP 838#ifdef YP
570struct hostent * 839struct hostent *
571_yphostent(line) 840_yphostent(line)
@@ -687,10 +956,104 @@ _yp_gethtbyname(name)
687 __ypcurrent = NULL; 956 __ypcurrent = NULL;
688 r = yp_match(__ypdomain, "hosts.byname", name, 957 r = yp_match(__ypdomain, "hosts.byname", name,
689 strlen(name), &__ypcurrent, &__ypcurrentlen); 958 strlen(name), &__ypcurrent, &__ypcurrentlen);
690 if (r==0) 959 if (r == 0)
691 hp = _yphostent(__ypcurrent); 960 hp = _yphostent(__ypcurrent);
692 if (hp==NULL) 961 if (hp == NULL)
693 h_errno = HOST_NOT_FOUND; 962 h_errno = HOST_NOT_FOUND;
694 return (hp); 963 return (hp);
695} 964}
696#endif 965#endif
966
967static void
968map_v4v6_address(src, dst)
969 const char *src;
970 char *dst;
971{
972 u_char *p = (u_char *)dst;
973 char tmp[INADDRSZ];
974 int i;
975
976 /* Stash a temporary copy so our caller can update in place. */
977 bcopy(src, tmp, INADDRSZ);
978 /* Mark this ipv6 addr as a mapped ipv4. */
979 for (i = 0; i < 10; i++)
980 *p++ = 0x00;
981 *p++ = 0xff;
982 *p++ = 0xff;
983 /* Retrieve the saved copy and we're done. */
984 bcopy(tmp, (void*)p, INADDRSZ);
985}
986
987static void
988map_v4v6_hostent(hp, bpp, lenp)
989 struct hostent *hp;
990 char **bpp;
991 int *lenp;
992{
993 char **ap;
994
995 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
996 return;
997 hp->h_addrtype = AF_INET6;
998 hp->h_length = IN6ADDRSZ;
999 for (ap = hp->h_addr_list; *ap; ap++) {
1000 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1001
1002 if (*lenp < (i + IN6ADDRSZ)) {
1003 /* Out of memory. Truncate address list here. XXX */
1004 *ap = NULL;
1005 return;
1006 }
1007 *bpp += i;
1008 *lenp -= i;
1009 map_v4v6_address(*ap, *bpp);
1010 *ap = *bpp;
1011 *bpp += IN6ADDRSZ;
1012 *lenp -= IN6ADDRSZ;
1013 }
1014}
1015
1016#ifdef RESOLVSORT
1017static void
1018addrsort(ap, num)
1019 char **ap;
1020 int num;
1021{
1022 int i, j;
1023 char **p;
1024 short aval[MAXADDRS];
1025 int needsort = 0;
1026
1027 p = ap;
1028 for (i = 0; i < num; i++, p++) {
1029 for (j = 0 ; (unsigned)j < _res.nsort; j++)
1030 if (_res.sort_list[j].addr.s_addr ==
1031 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
1032 break;
1033 aval[i] = j;
1034 if (needsort == 0 && i > 0 && j < aval[i-1])
1035 needsort = i;
1036 }
1037 if (!needsort)
1038 return;
1039
1040 while (needsort < num) {
1041 for (j = needsort - 1; j >= 0; j--) {
1042 if (aval[j] > aval[j+1]) {
1043 char *hp;
1044
1045 i = aval[j];
1046 aval[j] = aval[j+1];
1047 aval[j+1] = i;
1048
1049 hp = ap[j];
1050 ap[j] = ap[j+1];
1051 ap[j+1] = hp;
1052
1053 } else
1054 break;
1055 }
1056 needsort++;
1057 }
1058}
1059#endif