diff options
-rw-r--r-- | libc/dns/gethnamaddr.c | 1329 | ||||
-rw-r--r-- | libc/dns/include/hostent.h | 93 | ||||
-rw-r--r-- | libc/dns/net/sethostent.c | 266 | ||||
-rw-r--r-- | libc/include/netdb.h | 2 | ||||
-rw-r--r-- | tests/netdb_test.cpp | 126 |
5 files changed, 1260 insertions, 556 deletions
diff --git a/libc/dns/gethnamaddr.c b/libc/dns/gethnamaddr.c index 736858ff..63a6a60d 100644 --- a/libc/dns/gethnamaddr.c +++ b/libc/dns/gethnamaddr.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $NetBSD: gethnamaddr.c,v 1.70 2006/03/22 00:03:51 christos Exp $ */ | 1 | /* $NetBSD: gethnamaddr.c,v 1.91 2014/06/19 15:08:18 christos Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * ++Copyright++ 1985, 1988, 1993 | 4 | * ++Copyright++ 1985, 1988, 1993 |
@@ -88,6 +88,31 @@ | |||
88 | #include <stdlib.h> | 88 | #include <stdlib.h> |
89 | #include <string.h> | 89 | #include <string.h> |
90 | 90 | ||
91 | #include "hostent.h" | ||
92 | |||
93 | #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \ | ||
94 | (ok)(nm) != 0) | ||
95 | #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) | ||
96 | #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) | ||
97 | |||
98 | #define addalias(d, s, arr, siz) do { \ | ||
99 | if (d >= &arr[siz]) { \ | ||
100 | char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \ | ||
101 | if (xptr == NULL) \ | ||
102 | goto nospc; \ | ||
103 | d = xptr + (d - arr); \ | ||
104 | arr = xptr; \ | ||
105 | siz += 10; \ | ||
106 | } \ | ||
107 | *d++ = s; \ | ||
108 | } while (/*CONSTCOND*/0) | ||
109 | |||
110 | #define setup(arr, siz) do { \ | ||
111 | arr = malloc((siz = 10) * sizeof(*arr)); \ | ||
112 | if (arr == NULL) \ | ||
113 | goto nospc; \ | ||
114 | } while (/*CONSTCOND*/0) | ||
115 | |||
91 | // This should be synchronized to ResponseCode.h | 116 | // This should be synchronized to ResponseCode.h |
92 | static const int DnsProxyQueryResult = 222; | 117 | static const int DnsProxyQueryResult = 222; |
93 | 118 | ||
@@ -107,18 +132,15 @@ typedef union { | |||
107 | } align; | 132 | } align; |
108 | 133 | ||
109 | #ifdef DEBUG | 134 | #ifdef DEBUG |
110 | static void dprintf(const char *, res_state, ...) | 135 | static void debugprintf(const char *, res_state, ...) |
111 | __attribute__((__format__(__printf__, 1, 3))); | 136 | __attribute__((__format__(__printf__, 1, 3))); |
112 | #endif | 137 | #endif |
113 | static struct hostent *getanswer(const querybuf *, int, const char *, int, | 138 | static struct hostent *getanswer(const querybuf *, int, const char *, int, |
114 | res_state); | 139 | res_state, struct hostent *, char *, size_t, int *); |
115 | static void map_v4v6_address(const char *, char *); | 140 | static void map_v4v6_address(const char *, char *); |
116 | static void map_v4v6_hostent(struct hostent *, char **, char *); | 141 | static void map_v4v6_hostent(struct hostent *, char **, char *); |
117 | static void addrsort(char **, int, res_state); | 142 | static void addrsort(char **, int, res_state); |
118 | 143 | ||
119 | static void _sethtent(int); | ||
120 | static void _endhtent(void); | ||
121 | static struct hostent *_gethtent(void); | ||
122 | void ht_sethostent(int); | 144 | void ht_sethostent(int); |
123 | void ht_endhostent(void); | 145 | void ht_endhostent(void); |
124 | struct hostent *ht_gethostbyname(char *); | 146 | struct hostent *ht_gethostbyname(char *); |
@@ -126,13 +148,13 @@ struct hostent *ht_gethostbyaddr(const char *, int, int); | |||
126 | void dns_service(void); | 148 | void dns_service(void); |
127 | #undef dn_skipname | 149 | #undef dn_skipname |
128 | int dn_skipname(const u_char *, const u_char *); | 150 | int dn_skipname(const u_char *, const u_char *); |
129 | static int _gethtbyaddr(void *, void *, va_list); | ||
130 | static int _gethtbyname(void *, void *, va_list); | ||
131 | static struct hostent *_gethtbyname2(const char *, int); | ||
132 | static int _dns_gethtbyaddr(void *, void *, va_list); | 151 | static int _dns_gethtbyaddr(void *, void *, va_list); |
133 | static int _dns_gethtbyname(void *, void *, va_list); | 152 | static int _dns_gethtbyname(void *, void *, va_list); |
134 | 153 | ||
135 | static struct hostent *gethostbyname_internal(const char *, int, res_state, unsigned, unsigned); | 154 | static struct hostent *gethostbyname_internal(const char *, int, res_state, |
155 | struct hostent *, char *, size_t, int *, unsigned, unsigned); | ||
156 | static struct hostent* android_gethostbyaddrfornet_proxy_internal(const void*, socklen_t, | ||
157 | int, struct hostent *, char *, size_t, int *, unsigned, unsigned); | ||
136 | 158 | ||
137 | static const ns_src default_dns_files[] = { | 159 | static const ns_src default_dns_files[] = { |
138 | { NSSRC_FILES, NS_SUCCESS }, | 160 | { NSSRC_FILES, NS_SUCCESS }, |
@@ -143,9 +165,9 @@ static const ns_src default_dns_files[] = { | |||
143 | 165 | ||
144 | #ifdef DEBUG | 166 | #ifdef DEBUG |
145 | static void | 167 | static void |
146 | dprintf(const char *msg, res_state res, ...) | 168 | debugprintf(const char *msg, res_state res, ...) |
147 | { | 169 | { |
148 | assert(msg != NULL); | 170 | _DIAGASSERT(msg != NULL); |
149 | 171 | ||
150 | if (res->options & RES_DEBUG) { | 172 | if (res->options & RES_DEBUG) { |
151 | int save = errno; | 173 | int save = errno; |
@@ -159,48 +181,47 @@ dprintf(const char *msg, res_state res, ...) | |||
159 | } | 181 | } |
160 | } | 182 | } |
161 | #else | 183 | #else |
162 | # define dprintf(msg, res, num) ((void)0) /*nada*/ | 184 | # define debugprintf(msg, res, num) /*nada*/ |
163 | #endif | 185 | #endif |
164 | 186 | ||
165 | #define BOUNDED_INCR(x) \ | 187 | #define BOUNDED_INCR(x) \ |
166 | do { \ | 188 | do { \ |
167 | cp += (x); \ | 189 | cp += (x); \ |
168 | if (cp > eom) { \ | 190 | if (cp > eom) \ |
169 | h_errno = NO_RECOVERY; \ | 191 | goto no_recovery; \ |
170 | return NULL; \ | ||
171 | } \ | ||
172 | } while (/*CONSTCOND*/0) | 192 | } while (/*CONSTCOND*/0) |
173 | 193 | ||
174 | #define BOUNDS_CHECK(ptr, count) \ | 194 | #define BOUNDS_CHECK(ptr, count) \ |
175 | do { \ | 195 | do { \ |
176 | if ((ptr) + (count) > eom) { \ | 196 | if ((ptr) + (count) > eom) \ |
177 | h_errno = NO_RECOVERY; \ | 197 | goto no_recovery; \ |
178 | return NULL; \ | ||
179 | } \ | ||
180 | } while (/*CONSTCOND*/0) | 198 | } while (/*CONSTCOND*/0) |
181 | 199 | ||
182 | static struct hostent * | 200 | static struct hostent * |
183 | getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | 201 | getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, |
184 | res_state res) | 202 | res_state res, struct hostent *hent, char *buf, size_t buflen, int *he) |
185 | { | 203 | { |
186 | const HEADER *hp; | 204 | const HEADER *hp; |
187 | const u_char *cp; | 205 | const u_char *cp; |
188 | int n; | 206 | int n; |
207 | size_t qlen; | ||
189 | const u_char *eom, *erdata; | 208 | const u_char *eom, *erdata; |
190 | char *bp, **ap, **hap, *ep; | 209 | char *bp, **ap, **hap, *ep; |
191 | int type, class, ancount, qdcount; | 210 | int type, class, ancount, qdcount; |
192 | int haveanswer, had_error; | 211 | int haveanswer, had_error; |
193 | int toobig = 0; | 212 | int toobig = 0; |
194 | char tbuf[MAXDNAME]; | 213 | char tbuf[MAXDNAME]; |
214 | char **aliases; | ||
215 | size_t maxaliases; | ||
216 | char *addr_ptrs[MAXADDRS]; | ||
195 | const char *tname; | 217 | const char *tname; |
196 | int (*name_ok)(const char *); | 218 | int (*name_ok)(const char *); |
197 | res_static rs = __res_get_static(); | ||
198 | 219 | ||
199 | assert(answer != NULL); | 220 | _DIAGASSERT(answer != NULL); |
200 | assert(qname != NULL); | 221 | _DIAGASSERT(qname != NULL); |
201 | 222 | ||
202 | tname = qname; | 223 | tname = qname; |
203 | rs->host.h_name = NULL; | 224 | hent->h_name = NULL; |
204 | eom = answer->buf + anslen; | 225 | eom = answer->buf + anslen; |
205 | switch (qtype) { | 226 | switch (qtype) { |
206 | case T_A: | 227 | case T_A: |
@@ -211,54 +232,51 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | |||
211 | name_ok = res_dnok; | 232 | name_ok = res_dnok; |
212 | break; | 233 | break; |
213 | default: | 234 | default: |
235 | *he = NO_RECOVERY; | ||
214 | return NULL; /* XXX should be abort(); */ | 236 | return NULL; /* XXX should be abort(); */ |
215 | } | 237 | } |
238 | |||
239 | setup(aliases, maxaliases); | ||
216 | /* | 240 | /* |
217 | * find first satisfactory answer | 241 | * find first satisfactory answer |
218 | */ | 242 | */ |
219 | hp = &answer->hdr; | 243 | hp = &answer->hdr; |
220 | ancount = ntohs(hp->ancount); | 244 | ancount = ntohs(hp->ancount); |
221 | qdcount = ntohs(hp->qdcount); | 245 | qdcount = ntohs(hp->qdcount); |
222 | bp = rs->hostbuf; | 246 | bp = buf; |
223 | ep = rs->hostbuf + sizeof rs->hostbuf; | 247 | ep = buf + buflen; |
224 | cp = answer->buf; | 248 | cp = answer->buf; |
225 | BOUNDED_INCR(HFIXEDSZ); | 249 | BOUNDED_INCR(HFIXEDSZ); |
226 | if (qdcount != 1) { | 250 | if (qdcount != 1) |
227 | h_errno = NO_RECOVERY; | 251 | goto no_recovery; |
228 | return NULL; | 252 | |
229 | } | 253 | n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); |
230 | n = dn_expand(answer->buf, eom, cp, bp, ep - bp); | 254 | if ((n < 0) || !maybe_ok(res, bp, name_ok)) |
231 | if ((n < 0) || !(*name_ok)(bp)) { | 255 | goto no_recovery; |
232 | h_errno = NO_RECOVERY; | 256 | |
233 | return NULL; | ||
234 | } | ||
235 | BOUNDED_INCR(n + QFIXEDSZ); | 257 | BOUNDED_INCR(n + QFIXEDSZ); |
236 | if (qtype == T_A || qtype == T_AAAA) { | 258 | if (qtype == T_A || qtype == T_AAAA) { |
237 | /* res_send() has already verified that the query name is the | 259 | /* res_send() has already verified that the query name is the |
238 | * same as the one we sent; this just gets the expanded name | 260 | * same as the one we sent; this just gets the expanded name |
239 | * (i.e., with the succeeding search-domain tacked on). | 261 | * (i.e., with the succeeding search-domain tacked on). |
240 | */ | 262 | */ |
241 | n = strlen(bp) + 1; /* for the \0 */ | 263 | n = (int)strlen(bp) + 1; /* for the \0 */ |
242 | if (n >= MAXHOSTNAMELEN) { | 264 | if (n >= MAXHOSTNAMELEN) |
243 | h_errno = NO_RECOVERY; | 265 | goto no_recovery; |
244 | return NULL; | 266 | hent->h_name = bp; |
245 | } | ||
246 | rs->host.h_name = bp; | ||
247 | bp += n; | 267 | bp += n; |
248 | /* The qname can be abbreviated, but h_name is now absolute. */ | 268 | /* The qname can be abbreviated, but h_name is now absolute. */ |
249 | qname = rs->host.h_name; | 269 | qname = hent->h_name; |
250 | } | 270 | } |
251 | ap = rs->host_aliases; | 271 | hent->h_aliases = ap = aliases; |
272 | hent->h_addr_list = hap = addr_ptrs; | ||
252 | *ap = NULL; | 273 | *ap = NULL; |
253 | rs->host.h_aliases = rs->host_aliases; | ||
254 | hap = rs->h_addr_ptrs; | ||
255 | *hap = NULL; | 274 | *hap = NULL; |
256 | rs->host.h_addr_list = rs->h_addr_ptrs; | ||
257 | haveanswer = 0; | 275 | haveanswer = 0; |
258 | had_error = 0; | 276 | had_error = 0; |
259 | while (ancount-- > 0 && cp < eom && !had_error) { | 277 | while (ancount-- > 0 && cp < eom && !had_error) { |
260 | n = dn_expand(answer->buf, eom, cp, bp, ep - bp); | 278 | n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); |
261 | if ((n < 0) || !(*name_ok)(bp)) { | 279 | if ((n < 0) || !maybe_ok(res, bp, name_ok)) { |
262 | had_error++; | 280 | had_error++; |
263 | continue; | 281 | continue; |
264 | } | 282 | } |
@@ -278,50 +296,46 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | |||
278 | continue; /* XXX - had_error++ ? */ | 296 | continue; /* XXX - had_error++ ? */ |
279 | } | 297 | } |
280 | if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { | 298 | if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { |
281 | if (ap >= &rs->host_aliases[MAXALIASES-1]) | 299 | n = dn_expand(answer->buf, eom, cp, tbuf, |
282 | continue; | 300 | (int)sizeof tbuf); |
283 | n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); | 301 | if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) { |
284 | if ((n < 0) || !(*name_ok)(tbuf)) { | ||
285 | had_error++; | 302 | had_error++; |
286 | continue; | 303 | continue; |
287 | } | 304 | } |
288 | cp += n; | 305 | cp += n; |
289 | if (cp != erdata) { | 306 | if (cp != erdata) |
290 | h_errno = NO_RECOVERY; | 307 | goto no_recovery; |
291 | return NULL; | ||
292 | } | ||
293 | /* Store alias. */ | 308 | /* Store alias. */ |
294 | *ap++ = bp; | 309 | addalias(ap, bp, aliases, maxaliases); |
295 | n = strlen(bp) + 1; /* for the \0 */ | 310 | n = (int)strlen(bp) + 1; /* for the \0 */ |
296 | if (n >= MAXHOSTNAMELEN) { | 311 | if (n >= MAXHOSTNAMELEN) { |
297 | had_error++; | 312 | had_error++; |
298 | continue; | 313 | continue; |
299 | } | 314 | } |
300 | bp += n; | 315 | bp += n; |
301 | /* Get canonical name. */ | 316 | /* Get canonical name. */ |
302 | n = strlen(tbuf) + 1; /* for the \0 */ | 317 | n = (int)strlen(tbuf) + 1; /* for the \0 */ |
303 | if (n > ep - bp || n >= MAXHOSTNAMELEN) { | 318 | if (n > ep - bp || n >= MAXHOSTNAMELEN) { |
304 | had_error++; | 319 | had_error++; |
305 | continue; | 320 | continue; |
306 | } | 321 | } |
307 | strlcpy(bp, tbuf, (size_t)(ep - bp)); | 322 | strlcpy(bp, tbuf, (size_t)(ep - bp)); |
308 | rs->host.h_name = bp; | 323 | hent->h_name = bp; |
309 | bp += n; | 324 | bp += n; |
310 | continue; | 325 | continue; |
311 | } | 326 | } |
312 | if (qtype == T_PTR && type == T_CNAME) { | 327 | if (qtype == T_PTR && type == T_CNAME) { |
313 | n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); | 328 | n = dn_expand(answer->buf, eom, cp, tbuf, |
314 | if (n < 0 || !res_dnok(tbuf)) { | 329 | (int)sizeof tbuf); |
330 | if (n < 0 || !maybe_dnok(res, tbuf)) { | ||
315 | had_error++; | 331 | had_error++; |
316 | continue; | 332 | continue; |
317 | } | 333 | } |
318 | cp += n; | 334 | cp += n; |
319 | if (cp != erdata) { | 335 | if (cp != erdata) |
320 | h_errno = NO_RECOVERY; | 336 | goto no_recovery; |
321 | return NULL; | ||
322 | } | ||
323 | /* Get canonical name. */ | 337 | /* Get canonical name. */ |
324 | n = strlen(tbuf) + 1; /* for the \0 */ | 338 | n = (int)strlen(tbuf) + 1; /* for the \0 */ |
325 | if (n > ep - bp || n >= MAXHOSTNAMELEN) { | 339 | if (n > ep - bp || n >= MAXHOSTNAMELEN) { |
326 | had_error++; | 340 | had_error++; |
327 | continue; | 341 | continue; |
@@ -348,25 +362,21 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | |||
348 | cp += n; | 362 | cp += n; |
349 | continue; /* XXX - had_error++ ? */ | 363 | continue; /* XXX - had_error++ ? */ |
350 | } | 364 | } |
351 | n = dn_expand(answer->buf, eom, cp, bp, ep - bp); | 365 | n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); |
352 | if ((n < 0) || !res_hnok(bp)) { | 366 | if ((n < 0) || !maybe_hnok(res, bp)) { |
353 | had_error++; | 367 | had_error++; |
354 | break; | 368 | break; |
355 | } | 369 | } |
356 | #if MULTI_PTRS_ARE_ALIASES | 370 | #if MULTI_PTRS_ARE_ALIASES |
357 | cp += n; | 371 | cp += n; |
358 | if (cp != erdata) { | 372 | if (cp != erdata) |
359 | h_errno = NO_RECOVERY; | 373 | goto no_recovery; |
360 | return NULL; | ||
361 | } | ||
362 | if (!haveanswer) | 374 | if (!haveanswer) |
363 | rs->host.h_name = bp; | 375 | hent->h_name = bp; |
364 | else if (ap < &rs->host_aliases[MAXALIASES-1]) | ||
365 | *ap++ = bp; | ||
366 | else | 376 | else |
367 | n = -1; | 377 | addalias(ap, bp, aliases, maxaliases); |
368 | if (n != -1) { | 378 | if (n != -1) { |
369 | n = strlen(bp) + 1; /* for the \0 */ | 379 | n = (int)strlen(bp) + 1; /* for the \0 */ |
370 | if (n >= MAXHOSTNAMELEN) { | 380 | if (n >= MAXHOSTNAMELEN) { |
371 | had_error++; | 381 | had_error++; |
372 | break; | 382 | break; |
@@ -375,7 +385,7 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | |||
375 | } | 385 | } |
376 | break; | 386 | break; |
377 | #else | 387 | #else |
378 | rs->host.h_name = bp; | 388 | hent->h_name = bp; |
379 | if (res->options & RES_USE_INET6) { | 389 | if (res->options & RES_USE_INET6) { |
380 | n = strlen(bp) + 1; /* for the \0 */ | 390 | n = strlen(bp) + 1; /* for the \0 */ |
381 | if (n >= MAXHOSTNAMELEN) { | 391 | if (n >= MAXHOSTNAMELEN) { |
@@ -383,26 +393,25 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | |||
383 | break; | 393 | break; |
384 | } | 394 | } |
385 | bp += n; | 395 | bp += n; |
386 | map_v4v6_hostent(&rs->host, &bp, ep); | 396 | map_v4v6_hostent(hent, &bp, ep); |
387 | } | 397 | } |
388 | h_errno = NETDB_SUCCESS; | 398 | goto success; |
389 | return &rs->host; | ||
390 | #endif | 399 | #endif |
391 | case T_A: | 400 | case T_A: |
392 | case T_AAAA: | 401 | case T_AAAA: |
393 | if (strcasecmp(rs->host.h_name, bp) != 0) { | 402 | if (strcasecmp(hent->h_name, bp) != 0) { |
394 | syslog(LOG_NOTICE|LOG_AUTH, | 403 | syslog(LOG_NOTICE|LOG_AUTH, |
395 | AskedForGot, rs->host.h_name, bp); | 404 | AskedForGot, hent->h_name, bp); |
396 | cp += n; | 405 | cp += n; |
397 | continue; /* XXX - had_error++ ? */ | 406 | continue; /* XXX - had_error++ ? */ |
398 | } | 407 | } |
399 | if (n != rs->host.h_length) { | 408 | if (n != hent->h_length) { |
400 | cp += n; | 409 | cp += n; |
401 | continue; | 410 | continue; |
402 | } | 411 | } |
403 | if (type == T_AAAA) { | 412 | if (type == T_AAAA) { |
404 | struct in6_addr in6; | 413 | struct in6_addr in6; |
405 | memcpy(&in6, cp, IN6ADDRSZ); | 414 | memcpy(&in6, cp, NS_IN6ADDRSZ); |
406 | if (IN6_IS_ADDR_V4MAPPED(&in6)) { | 415 | if (IN6_IS_ADDR_V4MAPPED(&in6)) { |
407 | cp += n; | 416 | cp += n; |
408 | continue; | 417 | continue; |
@@ -411,33 +420,32 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | |||
411 | if (!haveanswer) { | 420 | if (!haveanswer) { |
412 | int nn; | 421 | int nn; |
413 | 422 | ||
414 | rs->host.h_name = bp; | 423 | hent->h_name = bp; |
415 | nn = strlen(bp) + 1; /* for the \0 */ | 424 | nn = (int)strlen(bp) + 1; /* for the \0 */ |
416 | bp += nn; | 425 | bp += nn; |
417 | } | 426 | } |
418 | 427 | ||
419 | bp += sizeof(align) - | 428 | bp += sizeof(align) - |
420 | (size_t)((u_long)bp % sizeof(align)); | 429 | (size_t)((u_long)bp % sizeof(align)); |
421 | 430 | ||
422 | if (bp + n >= &rs->hostbuf[sizeof rs->hostbuf]) { | 431 | if (bp + n >= ep) { |
423 | dprintf("size (%d) too big\n", res, n); | 432 | debugprintf("size (%d) too big\n", res, n); |
424 | had_error++; | 433 | had_error++; |
425 | continue; | 434 | continue; |
426 | } | 435 | } |
427 | if (hap >= &rs->h_addr_ptrs[MAXADDRS-1]) { | 436 | if (hap >= &addr_ptrs[MAXADDRS - 1]) { |
428 | if (!toobig++) | 437 | if (!toobig++) { |
429 | dprintf("Too many addresses (%d)\n", | 438 | debugprintf("Too many addresses (%d)\n", |
430 | res, MAXADDRS); | 439 | res, MAXADDRS); |
440 | } | ||
431 | cp += n; | 441 | cp += n; |
432 | continue; | 442 | continue; |
433 | } | 443 | } |
434 | (void)memcpy(*hap++ = bp, cp, (size_t)n); | 444 | (void)memcpy(*hap++ = bp, cp, (size_t)n); |
435 | bp += n; | 445 | bp += n; |
436 | cp += n; | 446 | cp += n; |
437 | if (cp != erdata) { | 447 | if (cp != erdata) |
438 | h_errno = NO_RECOVERY; | 448 | goto no_recovery; |
439 | return NULL; | ||
440 | } | ||
441 | break; | 449 | break; |
442 | default: | 450 | default: |
443 | abort(); | 451 | abort(); |
@@ -454,83 +462,103 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | |||
454 | * address in that case, not some random one | 462 | * address in that case, not some random one |
455 | */ | 463 | */ |
456 | if (res->nsort && haveanswer > 1 && qtype == T_A) | 464 | if (res->nsort && haveanswer > 1 && qtype == T_A) |
457 | addrsort(rs->h_addr_ptrs, haveanswer, res); | 465 | addrsort(addr_ptrs, haveanswer, res); |
458 | if (!rs->host.h_name) { | 466 | if (!hent->h_name) { |
459 | n = strlen(qname) + 1; /* for the \0 */ | 467 | n = (int)strlen(qname) + 1; /* for the \0 */ |
460 | if (n > ep - bp || n >= MAXHOSTNAMELEN) | 468 | if (n > ep - bp || n >= MAXHOSTNAMELEN) |
461 | goto no_recovery; | 469 | goto no_recovery; |
462 | strlcpy(bp, qname, (size_t)(ep - bp)); | 470 | strlcpy(bp, qname, (size_t)(ep - bp)); |
463 | rs->host.h_name = bp; | 471 | hent->h_name = bp; |
464 | bp += n; | 472 | bp += n; |
465 | } | 473 | } |
466 | if (res->options & RES_USE_INET6) | 474 | if (res->options & RES_USE_INET6) |
467 | map_v4v6_hostent(&rs->host, &bp, ep); | 475 | map_v4v6_hostent(hent, &bp, ep); |
468 | h_errno = NETDB_SUCCESS; | 476 | goto success; |
469 | return &rs->host; | ||
470 | } | 477 | } |
471 | no_recovery: | 478 | no_recovery: |
472 | h_errno = NO_RECOVERY; | 479 | free(aliases); |
480 | *he = NO_RECOVERY; | ||
481 | return NULL; | ||
482 | success: | ||
483 | bp = (char *)ALIGN(bp); | ||
484 | n = (int)(ap - aliases); | ||
485 | qlen = (n + 1) * sizeof(*hent->h_aliases); | ||
486 | if ((size_t)(ep - bp) < qlen) | ||
487 | goto nospc; | ||
488 | hent->h_aliases = (void *)bp; | ||
489 | memcpy(bp, aliases, qlen); | ||
490 | free(aliases); | ||
491 | aliases = NULL; | ||
492 | |||
493 | bp += qlen; | ||
494 | n = (int)(hap - addr_ptrs); | ||
495 | qlen = (n + 1) * sizeof(*hent->h_addr_list); | ||
496 | if ((size_t)(ep - bp) < qlen) | ||
497 | goto nospc; | ||
498 | hent->h_addr_list = (void *)bp; | ||
499 | memcpy(bp, addr_ptrs, qlen); | ||
500 | *he = NETDB_SUCCESS; | ||
501 | return hent; | ||
502 | nospc: | ||
503 | free(aliases); | ||
504 | errno = ENOSPC; | ||
505 | *he = NETDB_INTERNAL; | ||
473 | return NULL; | 506 | return NULL; |
474 | } | 507 | } |
475 | 508 | ||
509 | /* The prototype of gethostbyname_r is from glibc, not that in netbsd. */ | ||
476 | int | 510 | int |
477 | gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen, | 511 | gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen, |
478 | struct hostent**result, int *errorp) | 512 | struct hostent **result, int *errorp) |
479 | { | ||
480 | struct hostent *res; | ||
481 | |||
482 | res = gethostbyname(name); | ||
483 | *errorp = h_errno; | ||
484 | if (res == NULL) { | ||
485 | *result = NULL; | ||
486 | return -1; | ||
487 | } | ||
488 | memcpy(hp, res, sizeof *hp); | ||
489 | *result = hp; | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | struct hostent * | ||
494 | gethostbyname(const char *name) | ||
495 | { | 513 | { |
496 | struct hostent *hp; | ||
497 | res_state res = __res_get_state(); | 514 | res_state res = __res_get_state(); |
498 | 515 | ||
499 | if (res == NULL) | 516 | if (res == NULL) { |
500 | return NULL; | 517 | *result = NULL; |
518 | *errorp = NETDB_INTERNAL; | ||
519 | return -1; | ||
520 | } | ||
501 | 521 | ||
502 | assert(name != NULL); | 522 | _DIAGASSERT(name != NULL); |
503 | 523 | ||
504 | /* try IPv6 first - if that fails do IPv4 */ | ||
505 | if (res->options & RES_USE_INET6) { | 524 | if (res->options & RES_USE_INET6) { |
506 | hp = gethostbyname_internal(name, AF_INET6, res, NETID_UNSET, MARK_UNSET); | 525 | *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp, NETID_UNSET, |
507 | if (hp) { | 526 | MARK_UNSET); |
527 | if (*result) { | ||
508 | __res_put_state(res); | 528 | __res_put_state(res); |
509 | return hp; | 529 | return 0; |
510 | } | 530 | } |
511 | } | 531 | } |
512 | hp = gethostbyname_internal(name, AF_INET, res, NETID_UNSET, MARK_UNSET); | 532 | *result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp, NETID_UNSET, |
533 | MARK_UNSET); | ||
513 | __res_put_state(res); | 534 | __res_put_state(res); |
514 | return hp; | 535 | if (!*result && errno == ENOSPC) { |
515 | } | 536 | errno = ERANGE; |
516 | 537 | return ERANGE; /* Return error as in linux manual page. */ | |
517 | struct hostent * | 538 | } |
518 | gethostbyname2(const char *name, int af) | 539 | return (*result) ? 0 : -1; |
519 | { | ||
520 | return android_gethostbynamefornet(name, af, NETID_UNSET, MARK_UNSET); | ||
521 | } | 540 | } |
522 | 541 | ||
523 | struct hostent * | 542 | /* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */ |
524 | android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark) | 543 | int |
544 | gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf, | ||
545 | size_t buflen, struct hostent **result, int *errorp) | ||
525 | { | 546 | { |
526 | struct hostent *hp; | ||
527 | res_state res = __res_get_state(); | 547 | res_state res = __res_get_state(); |
528 | 548 | ||
529 | if (res == NULL) | 549 | if (res == NULL) { |
530 | return NULL; | 550 | *result = NULL; |
531 | hp = gethostbyname_internal(name, af, res, netid, mark); | 551 | *errorp = NETDB_INTERNAL; |
552 | return -1; | ||
553 | } | ||
554 | *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp, NETID_UNSET, | ||
555 | MARK_UNSET); | ||
532 | __res_put_state(res); | 556 | __res_put_state(res); |
533 | return hp; | 557 | if (!*result && errno == ENOSPC) { |
558 | errno = ERANGE; | ||
559 | return ERANGE; | ||
560 | } | ||
561 | return (*result) ? 0 : -1; | ||
534 | } | 562 | } |
535 | 563 | ||
536 | __LIBC_HIDDEN__ FILE* android_open_proxy() { | 564 | __LIBC_HIDDEN__ FILE* android_open_proxy() { |
@@ -562,7 +590,7 @@ __LIBC_HIDDEN__ FILE* android_open_proxy() { | |||
562 | } | 590 | } |
563 | 591 | ||
564 | static struct hostent * | 592 | static struct hostent * |
565 | android_read_hostent(FILE* proxy) | 593 | android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he) |
566 | { | 594 | { |
567 | uint32_t size; | 595 | uint32_t size; |
568 | char buf[4]; | 596 | char buf[4]; |
@@ -573,21 +601,27 @@ android_read_hostent(FILE* proxy) | |||
573 | int result_code = strtol(buf, NULL, 10); | 601 | int result_code = strtol(buf, NULL, 10); |
574 | if (result_code != DnsProxyQueryResult) { | 602 | if (result_code != DnsProxyQueryResult) { |
575 | fread(&size, 1, sizeof(size), proxy); | 603 | fread(&size, 1, sizeof(size), proxy); |
604 | *he = HOST_NOT_FOUND; | ||
576 | return NULL; | 605 | return NULL; |
577 | } | 606 | } |
578 | 607 | ||
579 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; | 608 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; |
580 | size = ntohl(size); | 609 | size = ntohl(size); |
581 | res_static rs = __res_get_static(); | ||
582 | memset(&rs->host, 0, sizeof(rs->host)); | ||
583 | char *ptr = rs->hostbuf; | ||
584 | 610 | ||
611 | memset(hp, 0, sizeof(*hp)); | ||
612 | char *ptr = hbuf; | ||
613 | char *hbuf_end = hbuf + hbuflen; | ||
614 | |||
615 | if (ptr + size > hbuf_end) { | ||
616 | goto nospc; | ||
617 | } | ||
585 | if (fread(ptr, 1, size, proxy) != size) return NULL; | 618 | if (fread(ptr, 1, size, proxy) != size) return NULL; |
619 | hp->h_name = ptr; | ||
586 | ptr += size; | 620 | ptr += size; |
587 | rs->host.h_name = rs->hostbuf; | ||
588 | 621 | ||
589 | char **aliases = rs->host_aliases; | 622 | char *aliases_ptrs[MAXALIASES]; |
590 | rs->host.h_aliases = rs->host_aliases; | 623 | char **aliases = &aliases_ptrs[0]; |
624 | |||
591 | while (1) { | 625 | while (1) { |
592 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; | 626 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; |
593 | size = ntohl(size); | 627 | size = ntohl(size); |
@@ -596,74 +630,107 @@ android_read_hostent(FILE* proxy) | |||
596 | *aliases = NULL; | 630 | *aliases = NULL; |
597 | break; | 631 | break; |
598 | } | 632 | } |
633 | if (ptr + size > hbuf_end) { | ||
634 | goto nospc; | ||
635 | } | ||
599 | if (fread(ptr, 1, size, proxy) != size) return NULL; | 636 | if (fread(ptr, 1, size, proxy) != size) return NULL; |
600 | *aliases++ = ptr; | 637 | if (aliases < &aliases_ptrs[MAXALIASES - 1]) { |
638 | *aliases++ = ptr; | ||
639 | } | ||
601 | ptr += size; | 640 | ptr += size; |
602 | } | 641 | } |
603 | 642 | ||
643 | int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases); | ||
644 | if (ptr + aliases_len > hbuf_end) { | ||
645 | goto nospc; | ||
646 | } | ||
647 | hp->h_aliases = (void*)ptr; | ||
648 | memcpy(ptr, aliases_ptrs, aliases_len); | ||
649 | ptr += aliases_len; | ||
650 | |||
604 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; | 651 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; |
605 | rs->host.h_addrtype = ntohl(size); | 652 | hp->h_addrtype = ntohl(size); |
606 | 653 | ||
607 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; | 654 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; |
608 | rs->host.h_length = ntohl(size); | 655 | hp->h_length = ntohl(size); |
656 | |||
657 | char *addr_ptrs[MAXADDRS]; | ||
658 | char **addr_p = &addr_ptrs[0]; | ||
609 | 659 | ||
610 | char **addrs = rs->h_addr_ptrs; | ||
611 | rs->host.h_addr_list = rs->h_addr_ptrs; | ||
612 | while (1) { | 660 | while (1) { |
613 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; | 661 | if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; |
614 | size = ntohl(size); | 662 | size = ntohl(size); |
615 | if (size == 0) { | 663 | if (size == 0) { |
616 | *addrs = NULL; | 664 | *addr_p = NULL; |
617 | break; | 665 | break; |
618 | } | 666 | } |
667 | if (ptr + size > hbuf_end) { | ||
668 | goto nospc; | ||
669 | } | ||
619 | if (fread(ptr, 1, size, proxy) != size) return NULL; | 670 | if (fread(ptr, 1, size, proxy) != size) return NULL; |
620 | *addrs++ = ptr; | 671 | if (addr_p < &addr_ptrs[MAXADDRS - 1]) { |
672 | *addr_p++ = ptr; | ||
673 | } | ||
621 | ptr += size; | 674 | ptr += size; |
622 | } | 675 | } |
623 | 676 | ||
624 | return &rs->host; | 677 | int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list); |
625 | } | 678 | if (ptr + addrs_len > hbuf_end) { |
679 | goto nospc; | ||
680 | } | ||
681 | hp->h_addr_list = (void*)ptr; | ||
682 | memcpy(ptr, addr_ptrs, addrs_len); | ||
683 | *he = NETDB_SUCCESS; | ||
684 | return hp; | ||
626 | 685 | ||
686 | nospc: | ||
687 | *he = NETDB_INTERNAL; | ||
688 | errno = ENOSPC; | ||
689 | return NULL; | ||
690 | } | ||
627 | 691 | ||
628 | static struct hostent * | 692 | static struct hostent * |
629 | gethostbyname_internal_real(const char *name, int af, res_state res) | 693 | gethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf, |
694 | size_t buflen, int *he) | ||
630 | { | 695 | { |
631 | const char *cp; | 696 | const char *cp; |
632 | char *bp, *ep; | 697 | struct getnamaddr info; |
633 | int size; | 698 | char hbuf[MAXHOSTNAMELEN]; |
634 | struct hostent *hp; | 699 | size_t size; |
635 | res_static rs = __res_get_static(); | ||
636 | |||
637 | static const ns_dtab dtab[] = { | 700 | static const ns_dtab dtab[] = { |
638 | NS_FILES_CB(_gethtbyname, NULL) | 701 | NS_FILES_CB(_hf_gethtbyname, NULL) |
639 | { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */ | 702 | { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */ |
640 | { 0, 0, 0 } | 703 | NS_NIS_CB(_yp_gethtbyname, NULL) |
704 | NS_NULL_CB | ||
641 | }; | 705 | }; |
642 | 706 | ||
643 | assert(name != NULL); | 707 | _DIAGASSERT(name != NULL); |
644 | 708 | ||
645 | switch (af) { | 709 | switch (af) { |
646 | case AF_INET: | 710 | case AF_INET: |
647 | size = INADDRSZ; | 711 | size = NS_INADDRSZ; |
648 | break; | 712 | break; |
649 | case AF_INET6: | 713 | case AF_INET6: |
650 | size = IN6ADDRSZ; | 714 | size = NS_IN6ADDRSZ; |
651 | break; | 715 | break; |
652 | default: | 716 | default: |
653 | h_errno = NETDB_INTERNAL; | 717 | *he = NETDB_INTERNAL; |
654 | errno = EAFNOSUPPORT; | 718 | errno = EAFNOSUPPORT; |
655 | return NULL; | 719 | return NULL; |
656 | } | 720 | } |
721 | if (buflen < size) | ||
722 | goto nospc; | ||
657 | 723 | ||
658 | rs->host.h_addrtype = af; | 724 | hp->h_addrtype = af; |
659 | rs->host.h_length = size; | 725 | hp->h_length = (int)size; |
660 | 726 | ||
661 | /* | 727 | /* |
662 | * if there aren't any dots, it could be a user-level alias. | 728 | * if there aren't any dots, it could be a user-level alias. |
663 | * this is also done in res_nquery() since we are not the only | 729 | * this is also done in res_nquery() since we are not the only |
664 | * function that looks up host names. | 730 | * function that looks up host names. |
665 | */ | 731 | */ |
666 | if (!strchr(name, '.') && (cp = __hostalias(name))) | 732 | if (!strchr(name, '.') && (cp = res_hostalias(res, name, |
733 | hbuf, sizeof(hbuf)))) | ||
667 | name = cp; | 734 | name = cp; |
668 | 735 | ||
669 | /* | 736 | /* |
@@ -680,25 +747,7 @@ gethostbyname_internal_real(const char *name, int af, res_state res) | |||
680 | * Fake up a hostent as if we'd actually | 747 | * Fake up a hostent as if we'd actually |
681 | * done a lookup. | 748 | * done a lookup. |
682 | */ | 749 | */ |
683 | if (inet_pton(af, name, | 750 | goto fake; |
684 | (char *)(void *)rs->host_addr) <= 0) { | ||
685 | h_errno = HOST_NOT_FOUND; | ||
686 | return NULL; | ||
687 | } | ||
688 | strncpy(rs->hostbuf, name, MAXDNAME); | ||
689 | rs->hostbuf[MAXDNAME] = '\0'; | ||
690 | bp = rs->hostbuf + MAXDNAME; | ||
691 | ep = rs->hostbuf + sizeof rs->hostbuf; | ||
692 | rs->host.h_name = rs->hostbuf; | ||
693 | rs->host.h_aliases = rs->host_aliases; | ||
694 | rs->host_aliases[0] = NULL; | ||
695 | rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr; | ||
696 | rs->h_addr_ptrs[1] = NULL; | ||
697 | rs->host.h_addr_list = rs->h_addr_ptrs; | ||
698 | if (res->options & RES_USE_INET6) | ||
699 | map_v4v6_hostent(&rs->host, &bp, ep); | ||
700 | h_errno = NETDB_SUCCESS; | ||
701 | return &rs->host; | ||
702 | } | 751 | } |
703 | if (!isdigit((u_char) *cp) && *cp != '.') | 752 | if (!isdigit((u_char) *cp) && *cp != '.') |
704 | break; | 753 | break; |
@@ -714,49 +763,60 @@ gethostbyname_internal_real(const char *name, int af, res_state res) | |||
714 | * Fake up a hostent as if we'd actually | 763 | * Fake up a hostent as if we'd actually |
715 | * done a lookup. | 764 | * done a lookup. |
716 | */ | 765 | */ |
717 | if (inet_pton(af, name, | 766 | goto fake; |
718 | (char *)(void *)rs->host_addr) <= 0) { | ||
719 | h_errno = HOST_NOT_FOUND; | ||
720 | return NULL; | ||
721 | } | ||
722 | strncpy(rs->hostbuf, name, MAXDNAME); | ||
723 | rs->hostbuf[MAXDNAME] = '\0'; | ||
724 | bp = rs->hostbuf + MAXDNAME; | ||
725 | ep = rs->hostbuf + sizeof rs->hostbuf; | ||
726 | rs->host.h_name = rs->hostbuf; | ||
727 | rs->host.h_aliases = rs->host_aliases; | ||
728 | rs->host_aliases[0] = NULL; | ||
729 | rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr; | ||
730 | rs->h_addr_ptrs[1] = NULL; | ||
731 | rs->host.h_addr_list = rs->h_addr_ptrs; | ||
732 | h_errno = NETDB_SUCCESS; | ||
733 | return &rs->host; | ||
734 | } | 767 | } |
735 | if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') | 768 | if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') |
736 | break; | 769 | break; |
737 | } | 770 | } |
738 | 771 | ||
739 | hp = NULL; | 772 | *he = NETDB_INTERNAL; |
740 | h_errno = NETDB_INTERNAL; | 773 | info.hp = hp; |
741 | if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname", | 774 | info.buf = buf; |
742 | default_dns_files, name, strlen(name), af) != NS_SUCCESS) { | 775 | info.buflen = buflen; |
776 | info.he = he; | ||
777 | if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname", | ||
778 | default_dns_files, name, strlen(name), af) != NS_SUCCESS) | ||
779 | return NULL; | ||
780 | *he = NETDB_SUCCESS; | ||
781 | return hp; | ||
782 | nospc: | ||
783 | *he = NETDB_INTERNAL; | ||
784 | errno = ENOSPC; | ||
785 | return NULL; | ||
786 | fake: | ||
787 | HENT_ARRAY(hp->h_addr_list, 1, buf, buflen); | ||
788 | HENT_ARRAY(hp->h_aliases, 0, buf, buflen); | ||
789 | |||
790 | hp->h_aliases[0] = NULL; | ||
791 | if (size > buflen) | ||
792 | goto nospc; | ||
793 | |||
794 | if (inet_pton(af, name, buf) <= 0) { | ||
795 | *he = HOST_NOT_FOUND; | ||
743 | return NULL; | 796 | return NULL; |
744 | } | 797 | } |
745 | h_errno = NETDB_SUCCESS; | 798 | hp->h_addr_list[0] = buf; |
799 | hp->h_addr_list[1] = NULL; | ||
800 | buf += size; | ||
801 | buflen -= size; | ||
802 | HENT_SCOPY(hp->h_name, name, buf, buflen); | ||
803 | if (res->options & RES_USE_INET6) | ||
804 | map_v4v6_hostent(hp, &buf, buf + buflen); | ||
805 | *he = NETDB_SUCCESS; | ||
746 | return hp; | 806 | return hp; |
747 | } | 807 | } |
748 | 808 | ||
749 | |||
750 | // very similar in proxy-ness to android_getaddrinfo_proxy | 809 | // very similar in proxy-ness to android_getaddrinfo_proxy |
751 | static struct hostent * | 810 | static struct hostent * |
752 | gethostbyname_internal(const char *name, int af, res_state res, unsigned netid, unsigned mark) | 811 | gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf, |
812 | size_t hbuflen, int *errorp, unsigned netid, unsigned mark) | ||
753 | { | 813 | { |
754 | FILE* proxy = android_open_proxy(); | 814 | FILE* proxy = android_open_proxy(); |
755 | if (proxy == NULL) { | 815 | if (proxy == NULL) { |
756 | // Either we're not supposed to be using the proxy or the proxy is unavailable. | 816 | // Either we're not supposed to be using the proxy or the proxy is unavailable. |
757 | res_setnetid(res, netid); | 817 | res_setnetid(res, netid); |
758 | res_setmark(res, mark); | 818 | res_setmark(res, mark); |
759 | return gethostbyname_internal_real(name, af, res); | 819 | return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp); |
760 | } | 820 | } |
761 | 821 | ||
762 | netid = __netdClientDispatch.netIdForResolv(netid); | 822 | netid = __netdClientDispatch.netIdForResolv(netid); |
@@ -776,29 +836,44 @@ gethostbyname_internal(const char *name, int af, res_state res, unsigned netid, | |||
776 | return NULL; | 836 | return NULL; |
777 | } | 837 | } |
778 | 838 | ||
779 | struct hostent* result = android_read_hostent(proxy); | 839 | struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp); |
780 | fclose(proxy); | 840 | fclose(proxy); |
781 | return result; | 841 | return result; |
782 | } | 842 | } |
783 | 843 | ||
844 | /* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */ | ||
845 | int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf, | ||
846 | size_t buflen, struct hostent **result, int *h_errnop) | ||
847 | { | ||
848 | *result = android_gethostbyaddrfornet_proxy_internal(addr, len, af, hp, buf, buflen, h_errnop, | ||
849 | NETID_UNSET, MARK_UNSET); | ||
850 | if (!*result && errno == ENOSPC) { | ||
851 | errno = ERANGE; | ||
852 | return ERANGE; | ||
853 | } | ||
854 | return (*result) ? 0 : -1; | ||
855 | } | ||
784 | 856 | ||
785 | static struct hostent * | 857 | static struct hostent * |
786 | android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) { | 858 | android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, struct hostent *hp, |
859 | char *buf, size_t buflen, int *he, unsigned netid, unsigned mark) | ||
860 | { | ||
787 | const u_char *uaddr = (const u_char *)addr; | 861 | const u_char *uaddr = (const u_char *)addr; |
788 | socklen_t size; | 862 | socklen_t size; |
789 | struct hostent *hp; | 863 | struct getnamaddr info; |
790 | static const ns_dtab dtab[] = { | 864 | static const ns_dtab dtab[] = { |
791 | NS_FILES_CB(_gethtbyaddr, NULL) | 865 | NS_FILES_CB(_hf_gethtbyaddr, NULL) |
792 | { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */ | 866 | { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */ |
793 | { 0, 0, 0 } | 867 | NS_NIS_CB(_yp_gethtbyaddr, NULL) |
868 | NS_NULL_CB | ||
794 | }; | 869 | }; |
795 | 870 | ||
796 | assert(addr != NULL); | 871 | _DIAGASSERT(addr != NULL); |
797 | 872 | ||
798 | if (af == AF_INET6 && len == NS_IN6ADDRSZ && | 873 | if (af == AF_INET6 && len == NS_IN6ADDRSZ && |
799 | (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) || | 874 | (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) || |
800 | IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) { | 875 | IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) { |
801 | h_errno = HOST_NOT_FOUND; | 876 | *he = HOST_NOT_FOUND; |
802 | return NULL; | 877 | return NULL; |
803 | } | 878 | } |
804 | if (af == AF_INET6 && len == NS_IN6ADDRSZ && | 879 | if (af == AF_INET6 && len == NS_IN6ADDRSZ && |
@@ -819,29 +894,35 @@ android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, unsign | |||
819 | break; | 894 | break; |
820 | default: | 895 | default: |
821 | errno = EAFNOSUPPORT; | 896 | errno = EAFNOSUPPORT; |
822 | h_errno = NETDB_INTERNAL; | 897 | *he = NETDB_INTERNAL; |
823 | return NULL; | 898 | return NULL; |
824 | } | 899 | } |
825 | if (size != len) { | 900 | if (size != len) { |
826 | errno = EINVAL; | 901 | errno = EINVAL; |
827 | h_errno = NETDB_INTERNAL; | 902 | *he = NETDB_INTERNAL; |
828 | return NULL; | 903 | return NULL; |
829 | } | 904 | } |
830 | hp = NULL; | 905 | info.hp = hp; |
831 | h_errno = NETDB_INTERNAL; | 906 | info.buf = buf; |
832 | if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr", | 907 | info.buflen = buflen; |
833 | default_dns_files, uaddr, len, af, netid, mark) != NS_SUCCESS) | 908 | info.he = he; |
909 | *he = NETDB_INTERNAL; | ||
910 | if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr", | ||
911 | default_dns_files, uaddr, len, af, netid, mark) != NS_SUCCESS) | ||
834 | return NULL; | 912 | return NULL; |
835 | h_errno = NETDB_SUCCESS; | 913 | *he = NETDB_SUCCESS; |
836 | return hp; | 914 | return hp; |
837 | } | 915 | } |
838 | 916 | ||
839 | __LIBC_HIDDEN__ struct hostent* | 917 | static struct hostent* |
840 | android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af, unsigned netid, unsigned mark) { | 918 | android_gethostbyaddrfornet_proxy_internal(const void* addr, socklen_t len, int af, |
919 | struct hostent *hp, char *hbuf, size_t hbuflen, int *he, | ||
920 | unsigned netid, unsigned mark) | ||
921 | { | ||
841 | FILE* proxy = android_open_proxy(); | 922 | FILE* proxy = android_open_proxy(); |
842 | if (proxy == NULL) { | 923 | if (proxy == NULL) { |
843 | // Either we're not supposed to be using the proxy or the proxy is unavailable. | 924 | // Either we're not supposed to be using the proxy or the proxy is unavailable. |
844 | return android_gethostbyaddrfornet_real(addr,len, af, netid, mark); | 925 | return android_gethostbyaddrfornet_real(addr,len, af, hp, hbuf, hbuflen, he, netid, mark); |
845 | } | 926 | } |
846 | 927 | ||
847 | char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6 | 928 | char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6 |
@@ -864,302 +945,144 @@ android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af, unsig | |||
864 | return NULL; | 945 | return NULL; |
865 | } | 946 | } |
866 | 947 | ||
867 | struct hostent *result = android_read_hostent(proxy); | 948 | struct hostent *result = android_read_hostent(proxy, hp, hbuf, hbuflen, he); |
868 | fclose(proxy); | 949 | fclose(proxy); |
869 | return result; | 950 | return result; |
870 | } | 951 | } |
871 | 952 | ||
872 | struct hostent * | 953 | struct hostent* |
873 | android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) | 954 | netbsd_gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he) |
874 | { | 955 | { |
875 | return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark); | 956 | char *p, *name; |
876 | } | ||
877 | |||
878 | struct hostent * | ||
879 | gethostbyaddr(const void *addr, socklen_t len, int af) | ||
880 | { | ||
881 | return android_gethostbyaddrfornet(addr, len, af, NETID_UNSET, MARK_UNSET); | ||
882 | } | ||
883 | |||
884 | |||
885 | static void | ||
886 | _sethtent(int f) | ||
887 | { | ||
888 | res_static rs = __res_get_static(); | ||
889 | if (rs == NULL) return; | ||
890 | if (!rs->hostf) | ||
891 | rs->hostf = fopen(_PATH_HOSTS, "re" ); | ||
892 | else | ||
893 | rewind(rs->hostf); | ||
894 | rs->stayopen = f; | ||
895 | } | ||
896 | |||
897 | static void | ||
898 | _endhtent(void) | ||
899 | { | ||
900 | res_static rs = __res_get_static(); | ||
901 | if (rs == NULL) return; | ||
902 | |||
903 | if (rs->hostf && !rs->stayopen) { | ||
904 | (void) fclose(rs->hostf); | ||
905 | rs->hostf = NULL; | ||
906 | } | ||
907 | } | ||
908 | |||
909 | static struct hostent * | ||
910 | _gethtent(void) | ||
911 | { | ||
912 | char *p; | ||
913 | char *cp, **q; | 957 | char *cp, **q; |
914 | int af, len; | 958 | int af, len; |
915 | res_static rs = __res_get_static(); | 959 | size_t anum; |
960 | char **aliases; | ||
961 | size_t maxaliases; | ||
962 | struct in6_addr host_addr; | ||
916 | 963 | ||
917 | if (!rs->hostf && !(rs->hostf = fopen(_PATH_HOSTS, "re" ))) { | 964 | if (hf == NULL) { |
918 | h_errno = NETDB_INTERNAL; | 965 | *he = NETDB_INTERNAL; |
966 | errno = EINVAL; | ||
919 | return NULL; | 967 | return NULL; |
920 | } | 968 | } |
921 | again: | 969 | p = NULL; |
922 | if (!(p = fgets(rs->hostbuf, sizeof rs->hostbuf, rs->hostf))) { | 970 | setup(aliases, maxaliases); |
923 | h_errno = HOST_NOT_FOUND; | 971 | |
924 | return NULL; | 972 | /* Allocate a new space to read file lines like upstream does. |
973 | * To keep reentrancy we cannot use __res_get_static()->hostbuf here, | ||
974 | * as the buffer may be used to store content for a previous hostent | ||
975 | * returned by non-reentrant functions like gethostbyname(). | ||
976 | */ | ||
977 | const size_t line_buf_size = sizeof(__res_get_static()->hostbuf); | ||
978 | if ((p = malloc(line_buf_size)) == NULL) { | ||
979 | goto nospc; | ||
925 | } | 980 | } |
926 | if (*p == '#') | 981 | for (;;) { |
927 | goto again; | 982 | if (!fgets(p, line_buf_size, hf)) { |
928 | if (!(cp = strpbrk(p, "#\n"))) | 983 | free(p); |
929 | goto again; | 984 | free(aliases); |
930 | *cp = '\0'; | 985 | *he = HOST_NOT_FOUND; |
931 | if (!(cp = strpbrk(p, " \t"))) | ||
932 | goto again; | ||
933 | *cp++ = '\0'; | ||
934 | if (inet_pton(AF_INET6, p, (char *)(void *)rs->host_addr) > 0) { | ||
935 | af = AF_INET6; | ||
936 | len = IN6ADDRSZ; | ||
937 | } else if (inet_pton(AF_INET, p, (char *)(void *)rs->host_addr) > 0) { | ||
938 | res_state res = __res_get_state(); | ||
939 | if (res == NULL) | ||
940 | return NULL; | 986 | return NULL; |
941 | if (res->options & RES_USE_INET6) { | 987 | } |
942 | map_v4v6_address((char *)(void *)rs->host_addr, | 988 | if (*p == '#') { |
943 | (char *)(void *)rs->host_addr); | ||
944 | af = AF_INET6; | ||
945 | len = IN6ADDRSZ; | ||
946 | } else { | ||
947 | af = AF_INET; | ||
948 | len = INADDRSZ; | ||
949 | } | ||
950 | __res_put_state(res); | ||
951 | } else { | ||
952 | goto again; | ||
953 | } | ||
954 | /* if this is not something we're looking for, skip it. */ | ||
955 | if (rs->host.h_addrtype != 0 && rs->host.h_addrtype != af) | ||
956 | goto again; | ||
957 | if (rs->host.h_length != 0 && rs->host.h_length != len) | ||
958 | goto again; | ||
959 | rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr; | ||
960 | rs->h_addr_ptrs[1] = NULL; | ||
961 | rs->host.h_addr_list = rs->h_addr_ptrs; | ||
962 | rs->host.h_length = len; | ||
963 | rs->host.h_addrtype = af; | ||
964 | while (*cp == ' ' || *cp == '\t') | ||
965 | cp++; | ||
966 | rs->host.h_name = cp; | ||
967 | q = rs->host.h_aliases = rs->host_aliases; | ||
968 | if ((cp = strpbrk(cp, " \t")) != NULL) | ||
969 | *cp++ = '\0'; | ||
970 | while (cp && *cp) { | ||
971 | if (*cp == ' ' || *cp == '\t') { | ||
972 | cp++; | ||
973 | continue; | 989 | continue; |
974 | } | 990 | } |
975 | if (q < &rs->host_aliases[MAXALIASES - 1]) | 991 | if (!(cp = strpbrk(p, "#\n"))) { |
976 | *q++ = cp; | ||
977 | if ((cp = strpbrk(cp, " \t")) != NULL) | ||
978 | *cp++ = '\0'; | ||
979 | } | ||
980 | *q = NULL; | ||
981 | h_errno = NETDB_SUCCESS; | ||
982 | return &rs->host; | ||
983 | } | ||
984 | |||
985 | /*ARGSUSED*/ | ||
986 | int | ||
987 | _gethtbyname(void *rv, void *cb_data, va_list ap) | ||
988 | { | ||
989 | struct hostent *hp; | ||
990 | const char *name; | ||
991 | int af; | ||
992 | |||
993 | assert(rv != NULL); | ||
994 | |||
995 | name = va_arg(ap, char *); | ||
996 | /* NOSTRICT skip len */(void)va_arg(ap, int); | ||
997 | af = va_arg(ap, int); | ||
998 | |||
999 | hp = NULL; | ||
1000 | #if 0 | ||
1001 | { | ||
1002 | res_state res = __res_get_state(); | ||
1003 | if (res == NULL) | ||
1004 | return NS_NOTFOUND; | ||
1005 | if (res->options & RES_USE_INET6) | ||
1006 | hp = _gethtbyname2(name, AF_INET6); | ||
1007 | if (hp==NULL) | ||
1008 | hp = _gethtbyname2(name, AF_INET); | ||
1009 | __res_put_state(res); | ||
1010 | } | ||
1011 | #else | ||
1012 | hp = _gethtbyname2(name, af); | ||
1013 | #endif | ||
1014 | *((struct hostent **)rv) = hp; | ||
1015 | if (hp == NULL) { | ||
1016 | h_errno = HOST_NOT_FOUND; | ||
1017 | return NS_NOTFOUND; | ||
1018 | } | ||
1019 | return NS_SUCCESS; | ||
1020 | } | ||
1021 | |||
1022 | static struct hostent * | ||
1023 | _gethtbyname2(const char *name, int af) | ||
1024 | { | ||
1025 | struct hostent *p; | ||
1026 | char *tmpbuf, *ptr, **cp; | ||
1027 | int num; | ||
1028 | size_t len; | ||
1029 | res_static rs = __res_get_static(); | ||
1030 | |||
1031 | assert(name != NULL); | ||
1032 | |||
1033 | _sethtent(rs->stayopen); | ||
1034 | ptr = tmpbuf = NULL; | ||
1035 | num = 0; | ||
1036 | while ((p = _gethtent()) != NULL && num < MAXADDRS) { | ||
1037 | if (p->h_addrtype != af) | ||
1038 | continue; | 992 | continue; |
1039 | if (strcasecmp(p->h_name, name) != 0) { | ||
1040 | for (cp = p->h_aliases; *cp != NULL; cp++) | ||
1041 | if (strcasecmp(*cp, name) == 0) | ||
1042 | break; | ||
1043 | if (*cp == NULL) continue; | ||
1044 | } | 993 | } |
994 | *cp = '\0'; | ||
995 | if (!(cp = strpbrk(p, " \t"))) | ||
996 | continue; | ||
997 | *cp++ = '\0'; | ||
998 | if (inet_pton(AF_INET6, p, &host_addr) > 0) { | ||
999 | af = AF_INET6; | ||
1000 | len = NS_IN6ADDRSZ; | ||
1001 | } else { | ||
1002 | if (inet_pton(AF_INET, p, &host_addr) <= 0) | ||
1003 | continue; | ||
1045 | 1004 | ||
1046 | if (num == 0) { | 1005 | res_state res = __res_get_state(); |
1047 | size_t bufsize; | 1006 | if (res == NULL) |
1048 | char *src; | 1007 | goto nospc; |
1049 | 1008 | if (res->options & RES_USE_INET6) { | |
1050 | bufsize = strlen(p->h_name) + 2 + | 1009 | map_v4v6_address(buf, buf); |
1051 | MAXADDRS * p->h_length + | 1010 | af = AF_INET6; |
1052 | ALIGNBYTES; | 1011 | len = NS_IN6ADDRSZ; |
1053 | for (cp = p->h_aliases; *cp != NULL; cp++) | 1012 | } else { |
1054 | bufsize += strlen(*cp) + 1; | 1013 | af = AF_INET; |
1055 | 1014 | len = NS_INADDRSZ; | |
1056 | if ((tmpbuf = malloc(bufsize)) == NULL) { | ||
1057 | h_errno = NETDB_INTERNAL; | ||
1058 | return NULL; | ||
1059 | } | ||
1060 | |||
1061 | ptr = tmpbuf; | ||
1062 | src = p->h_name; | ||
1063 | while ((*ptr++ = *src++) != '\0'); | ||
1064 | for (cp = p->h_aliases; *cp != NULL; cp++) { | ||
1065 | src = *cp; | ||
1066 | while ((*ptr++ = *src++) != '\0'); | ||
1067 | } | 1015 | } |
1068 | *ptr++ = '\0'; | 1016 | __res_put_state(res); |
1069 | |||
1070 | ptr = (char *)(void *)ALIGN(ptr); | ||
1071 | } | 1017 | } |
1072 | 1018 | ||
1073 | (void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length); | 1019 | /* if this is not something we're looking for, skip it. */ |
1074 | ptr += p->h_length; | 1020 | if (hent->h_addrtype != 0 && hent->h_addrtype != af) |
1075 | num++; | 1021 | continue; |
1076 | } | 1022 | if (hent->h_length != 0 && hent->h_length != len) |
1077 | _endhtent(); | 1023 | continue; |
1078 | if (num == 0) return NULL; | ||
1079 | |||
1080 | len = ptr - tmpbuf; | ||
1081 | if (len > (sizeof(rs->hostbuf) - ALIGNBYTES)) { | ||
1082 | free(tmpbuf); | ||
1083 | errno = ENOSPC; | ||
1084 | h_errno = NETDB_INTERNAL; | ||
1085 | return NULL; | ||
1086 | } | ||
1087 | ptr = memcpy((void *)ALIGN(rs->hostbuf), tmpbuf, len); | ||
1088 | free(tmpbuf); | ||
1089 | |||
1090 | rs->host.h_name = ptr; | ||
1091 | while (*ptr++); | ||
1092 | |||
1093 | cp = rs->host_aliases; | ||
1094 | while (*ptr) { | ||
1095 | *cp++ = ptr; | ||
1096 | while (*ptr++); | ||
1097 | } | ||
1098 | ptr++; | ||
1099 | *cp = NULL; | ||
1100 | |||
1101 | ptr = (char *)(void *)ALIGN(ptr); | ||
1102 | cp = rs->h_addr_ptrs; | ||
1103 | while (num--) { | ||
1104 | *cp++ = ptr; | ||
1105 | ptr += rs->host.h_length; | ||
1106 | } | ||
1107 | *cp = NULL; | ||
1108 | |||
1109 | return &rs->host; | ||
1110 | } | ||
1111 | |||
1112 | /*ARGSUSED*/ | ||
1113 | static int | ||
1114 | _gethtbyaddr(void *rv, void *cb_data, va_list ap) | ||
1115 | { | ||
1116 | struct hostent *p; | ||
1117 | const unsigned char *addr; | ||
1118 | int len, af; | ||
1119 | res_static rs = __res_get_static(); | ||
1120 | |||
1121 | assert(rv != NULL); | ||
1122 | |||
1123 | addr = va_arg(ap, unsigned char *); | ||
1124 | len = va_arg(ap, int); | ||
1125 | af = va_arg(ap, int); | ||
1126 | |||
1127 | rs->host.h_length = len; | ||
1128 | rs->host.h_addrtype = af; | ||
1129 | 1024 | ||
1130 | _sethtent(rs->stayopen); | 1025 | while (*cp == ' ' || *cp == '\t') |
1131 | while ((p = _gethtent()) != NULL) | 1026 | cp++; |
1132 | if (p->h_addrtype == af && !memcmp(p->h_addr, addr, | 1027 | if ((cp = strpbrk(name = cp, " \t")) != NULL) |
1133 | (size_t)len)) | 1028 | *cp++ = '\0'; |
1134 | break; | 1029 | q = aliases; |
1135 | _endhtent(); | 1030 | while (cp && *cp) { |
1136 | *((struct hostent **)rv) = p; | 1031 | if (*cp == ' ' || *cp == '\t') { |
1137 | if (p==NULL) { | 1032 | cp++; |
1138 | h_errno = HOST_NOT_FOUND; | 1033 | continue; |
1139 | return NS_NOTFOUND; | 1034 | } |
1035 | addalias(q, cp, aliases, maxaliases); | ||
1036 | if ((cp = strpbrk(cp, " \t")) != NULL) | ||
1037 | *cp++ = '\0'; | ||
1038 | } | ||
1039 | break; | ||
1140 | } | 1040 | } |
1141 | return NS_SUCCESS; | 1041 | hent->h_length = len; |
1042 | hent->h_addrtype = af; | ||
1043 | HENT_ARRAY(hent->h_addr_list, 1, buf, buflen); | ||
1044 | anum = (size_t)(q - aliases); | ||
1045 | HENT_ARRAY(hent->h_aliases, anum, buf, buflen); | ||
1046 | HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, | ||
1047 | buflen); | ||
1048 | hent->h_addr_list[1] = NULL; | ||
1049 | |||
1050 | HENT_SCOPY(hent->h_name, name, buf, buflen); | ||
1051 | for (size_t i = 0; i < anum; i++) | ||
1052 | HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen); | ||
1053 | hent->h_aliases[anum] = NULL; | ||
1054 | |||
1055 | *he = NETDB_SUCCESS; | ||
1056 | free(p); | ||
1057 | free(aliases); | ||
1058 | return hent; | ||
1059 | nospc: | ||
1060 | free(p); | ||
1061 | free(aliases); | ||
1062 | errno = ENOSPC; | ||
1063 | *he = NETDB_INTERNAL; | ||
1064 | return NULL; | ||
1142 | } | 1065 | } |
1143 | 1066 | ||
1144 | static void | 1067 | static void |
1145 | map_v4v6_address(const char *src, char *dst) | 1068 | map_v4v6_address(const char *src, char *dst) |
1146 | { | 1069 | { |
1147 | u_char *p = (u_char *)dst; | 1070 | u_char *p = (u_char *)dst; |
1148 | char tmp[INADDRSZ]; | 1071 | char tmp[NS_INADDRSZ]; |
1149 | int i; | 1072 | int i; |
1150 | 1073 | ||
1151 | assert(src != NULL); | 1074 | _DIAGASSERT(src != NULL); |
1152 | assert(dst != NULL); | 1075 | _DIAGASSERT(dst != NULL); |
1153 | 1076 | ||
1154 | /* Stash a temporary copy so our caller can update in place. */ | 1077 | /* Stash a temporary copy so our caller can update in place. */ |
1155 | (void)memcpy(tmp, src, INADDRSZ); | 1078 | (void)memcpy(tmp, src, NS_INADDRSZ); |
1156 | /* Mark this ipv6 addr as a mapped ipv4. */ | 1079 | /* Mark this ipv6 addr as a mapped ipv4. */ |
1157 | for (i = 0; i < 10; i++) | 1080 | for (i = 0; i < 10; i++) |
1158 | *p++ = 0x00; | 1081 | *p++ = 0x00; |
1159 | *p++ = 0xff; | 1082 | *p++ = 0xff; |
1160 | *p++ = 0xff; | 1083 | *p++ = 0xff; |
1161 | /* Retrieve the saved copy and we're done. */ | 1084 | /* Retrieve the saved copy and we're done. */ |
1162 | (void)memcpy((void *)p, tmp, INADDRSZ); | 1085 | (void)memcpy(p, tmp, NS_INADDRSZ); |
1163 | } | 1086 | } |
1164 | 1087 | ||
1165 | static void | 1088 | static void |
@@ -1167,18 +1090,19 @@ map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) | |||
1167 | { | 1090 | { |
1168 | char **ap; | 1091 | char **ap; |
1169 | 1092 | ||
1170 | assert(hp != NULL); | 1093 | _DIAGASSERT(hp != NULL); |
1171 | assert(bpp != NULL); | 1094 | _DIAGASSERT(bpp != NULL); |
1172 | assert(ep != NULL); | 1095 | _DIAGASSERT(ep != NULL); |
1173 | 1096 | ||
1174 | if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) | 1097 | if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) |
1175 | return; | 1098 | return; |
1176 | hp->h_addrtype = AF_INET6; | 1099 | hp->h_addrtype = AF_INET6; |
1177 | hp->h_length = IN6ADDRSZ; | 1100 | hp->h_length = NS_IN6ADDRSZ; |
1178 | for (ap = hp->h_addr_list; *ap; ap++) { | 1101 | for (ap = hp->h_addr_list; *ap; ap++) { |
1179 | int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align)); | 1102 | int i = (int)(sizeof(align) - |
1103 | (size_t)((u_long)*bpp % sizeof(align))); | ||
1180 | 1104 | ||
1181 | if (ep - *bpp < (i + IN6ADDRSZ)) { | 1105 | if (ep - *bpp < (i + NS_IN6ADDRSZ)) { |
1182 | /* Out of memory. Truncate address list here. XXX */ | 1106 | /* Out of memory. Truncate address list here. XXX */ |
1183 | *ap = NULL; | 1107 | *ap = NULL; |
1184 | return; | 1108 | return; |
@@ -1186,7 +1110,7 @@ map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) | |||
1186 | *bpp += i; | 1110 | *bpp += i; |
1187 | map_v4v6_address(*ap, *bpp); | 1111 | map_v4v6_address(*ap, *bpp); |
1188 | *ap = *bpp; | 1112 | *ap = *bpp; |
1189 | *bpp += IN6ADDRSZ; | 1113 | *bpp += NS_IN6ADDRSZ; |
1190 | } | 1114 | } |
1191 | } | 1115 | } |
1192 | 1116 | ||
@@ -1198,7 +1122,7 @@ addrsort(char **ap, int num, res_state res) | |||
1198 | short aval[MAXADDRS]; | 1122 | short aval[MAXADDRS]; |
1199 | int needsort = 0; | 1123 | int needsort = 0; |
1200 | 1124 | ||
1201 | assert(ap != NULL); | 1125 | _DIAGASSERT(ap != NULL); |
1202 | 1126 | ||
1203 | p = ap; | 1127 | p = ap; |
1204 | for (i = 0; i < num; i++, p++) { | 1128 | for (i = 0; i < num; i++, p++) { |
@@ -1233,15 +1157,6 @@ addrsort(char **ap, int num, res_state res) | |||
1233 | } | 1157 | } |
1234 | } | 1158 | } |
1235 | 1159 | ||
1236 | struct hostent * | ||
1237 | gethostent(void) | ||
1238 | { | ||
1239 | res_static rs = __res_get_static(); | ||
1240 | rs->host.h_addrtype = 0; | ||
1241 | rs->host.h_length = 0; | ||
1242 | return _gethtent(); | ||
1243 | } | ||
1244 | |||
1245 | /*ARGSUSED*/ | 1160 | /*ARGSUSED*/ |
1246 | static int | 1161 | static int |
1247 | _dns_gethtbyname(void *rv, void *cb_data, va_list ap) | 1162 | _dns_gethtbyname(void *rv, void *cb_data, va_list ap) |
@@ -1250,20 +1165,22 @@ _dns_gethtbyname(void *rv, void *cb_data, va_list ap) | |||
1250 | int n, type; | 1165 | int n, type; |
1251 | struct hostent *hp; | 1166 | struct hostent *hp; |
1252 | const char *name; | 1167 | const char *name; |
1253 | int af; | ||
1254 | res_state res; | 1168 | res_state res; |
1169 | struct getnamaddr *info = rv; | ||
1255 | 1170 | ||
1256 | assert(rv != NULL); | 1171 | _DIAGASSERT(rv != NULL); |
1257 | 1172 | ||
1258 | name = va_arg(ap, char *); | 1173 | name = va_arg(ap, char *); |
1259 | /* NOSTRICT skip len */(void)va_arg(ap, int); | 1174 | /* NOSTRICT skip string len */(void)va_arg(ap, int); |
1260 | af = va_arg(ap, int); | 1175 | info->hp->h_addrtype = va_arg(ap, int); |
1261 | 1176 | ||
1262 | switch (af) { | 1177 | switch (info->hp->h_addrtype) { |
1263 | case AF_INET: | 1178 | case AF_INET: |
1179 | info->hp->h_length = NS_INADDRSZ; | ||
1264 | type = T_A; | 1180 | type = T_A; |
1265 | break; | 1181 | break; |
1266 | case AF_INET6: | 1182 | case AF_INET6: |
1183 | info->hp->h_length = NS_IN6ADDRSZ; | ||
1267 | type = T_AAAA; | 1184 | type = T_AAAA; |
1268 | break; | 1185 | break; |
1269 | default: | 1186 | default: |
@@ -1271,7 +1188,7 @@ _dns_gethtbyname(void *rv, void *cb_data, va_list ap) | |||
1271 | } | 1188 | } |
1272 | buf = malloc(sizeof(*buf)); | 1189 | buf = malloc(sizeof(*buf)); |
1273 | if (buf == NULL) { | 1190 | if (buf == NULL) { |
1274 | h_errno = NETDB_INTERNAL; | 1191 | *info->he = NETDB_INTERNAL; |
1275 | return NS_NOTFOUND; | 1192 | return NS_NOTFOUND; |
1276 | } | 1193 | } |
1277 | res = __res_get_state(); | 1194 | res = __res_get_state(); |
@@ -1279,14 +1196,15 @@ _dns_gethtbyname(void *rv, void *cb_data, va_list ap) | |||
1279 | free(buf); | 1196 | free(buf); |
1280 | return NS_NOTFOUND; | 1197 | return NS_NOTFOUND; |
1281 | } | 1198 | } |
1282 | n = res_nsearch(res, name, C_IN, type, buf->buf, sizeof(buf->buf)); | 1199 | n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf)); |
1283 | if (n < 0) { | 1200 | if (n < 0) { |
1284 | free(buf); | 1201 | free(buf); |
1285 | dprintf("res_nsearch failed (%d)\n", res, n); | 1202 | debugprintf("res_nsearch failed (%d)\n", res, n); |
1286 | __res_put_state(res); | 1203 | __res_put_state(res); |
1287 | return NS_NOTFOUND; | 1204 | return NS_NOTFOUND; |
1288 | } | 1205 | } |
1289 | hp = getanswer(buf, n, name, type, res); | 1206 | hp = getanswer(buf, n, name, type, res, info->hp, info->buf, |
1207 | info->buflen, info->he); | ||
1290 | free(buf); | 1208 | free(buf); |
1291 | __res_put_state(res); | 1209 | __res_put_state(res); |
1292 | if (hp == NULL) | 1210 | if (hp == NULL) |
@@ -1298,7 +1216,6 @@ _dns_gethtbyname(void *rv, void *cb_data, va_list ap) | |||
1298 | default: | 1216 | default: |
1299 | return NS_UNAVAIL; | 1217 | return NS_UNAVAIL; |
1300 | } | 1218 | } |
1301 | *((struct hostent **)rv) = hp; | ||
1302 | return NS_SUCCESS; | 1219 | return NS_SUCCESS; |
1303 | } | 1220 | } |
1304 | 1221 | ||
@@ -1311,20 +1228,22 @@ _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap) | |||
1311 | querybuf *buf; | 1228 | querybuf *buf; |
1312 | struct hostent *hp; | 1229 | struct hostent *hp; |
1313 | const unsigned char *uaddr; | 1230 | const unsigned char *uaddr; |
1314 | int len, af, advance; | 1231 | int advance; |
1315 | res_state res; | 1232 | res_state res; |
1233 | char *bf; | ||
1234 | size_t blen; | ||
1235 | struct getnamaddr *info = rv; | ||
1316 | unsigned netid, mark; | 1236 | unsigned netid, mark; |
1317 | res_static rs = __res_get_static(); | ||
1318 | 1237 | ||
1319 | assert(rv != NULL); | 1238 | _DIAGASSERT(rv != NULL); |
1320 | 1239 | ||
1321 | uaddr = va_arg(ap, unsigned char *); | 1240 | uaddr = va_arg(ap, unsigned char *); |
1322 | len = va_arg(ap, int); | 1241 | info->hp->h_length = va_arg(ap, int); |
1323 | af = va_arg(ap, int); | 1242 | info->hp->h_addrtype = va_arg(ap, int); |
1324 | netid = va_arg(ap, unsigned); | 1243 | netid = va_arg(ap, unsigned); |
1325 | mark = va_arg(ap, unsigned); | 1244 | mark = va_arg(ap, unsigned); |
1326 | 1245 | ||
1327 | switch (af) { | 1246 | switch (info->hp->h_addrtype) { |
1328 | case AF_INET: | 1247 | case AF_INET: |
1329 | (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", | 1248 | (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", |
1330 | (uaddr[3] & 0xff), (uaddr[2] & 0xff), | 1249 | (uaddr[3] & 0xff), (uaddr[2] & 0xff), |
@@ -1334,29 +1253,29 @@ _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap) | |||
1334 | case AF_INET6: | 1253 | case AF_INET6: |
1335 | qp = qbuf; | 1254 | qp = qbuf; |
1336 | ep = qbuf + sizeof(qbuf) - 1; | 1255 | ep = qbuf + sizeof(qbuf) - 1; |
1337 | for (n = IN6ADDRSZ - 1; n >= 0; n--) { | 1256 | for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) { |
1338 | advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", | 1257 | advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", |
1339 | uaddr[n] & 0xf, | 1258 | uaddr[n] & 0xf, |
1340 | ((unsigned int)uaddr[n] >> 4) & 0xf); | 1259 | ((unsigned int)uaddr[n] >> 4) & 0xf); |
1341 | if (advance > 0 && qp + advance < ep) | 1260 | if (advance > 0 && qp + advance < ep) |
1342 | qp += advance; | 1261 | qp += advance; |
1343 | else { | 1262 | else { |
1344 | h_errno = NETDB_INTERNAL; | 1263 | *info->he = NETDB_INTERNAL; |
1345 | return NS_NOTFOUND; | 1264 | return NS_NOTFOUND; |
1346 | } | 1265 | } |
1347 | } | 1266 | } |
1348 | if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) { | 1267 | if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) { |
1349 | h_errno = NETDB_INTERNAL; | 1268 | *info->he = NETDB_INTERNAL; |
1350 | return NS_NOTFOUND; | 1269 | return NS_NOTFOUND; |
1351 | } | 1270 | } |
1352 | break; | 1271 | break; |
1353 | default: | 1272 | default: |
1354 | abort(); | 1273 | return NS_UNAVAIL; |
1355 | } | 1274 | } |
1356 | 1275 | ||
1357 | buf = malloc(sizeof(*buf)); | 1276 | buf = malloc(sizeof(*buf)); |
1358 | if (buf == NULL) { | 1277 | if (buf == NULL) { |
1359 | h_errno = NETDB_INTERNAL; | 1278 | *info->he = NETDB_INTERNAL; |
1360 | return NS_NOTFOUND; | 1279 | return NS_NOTFOUND; |
1361 | } | 1280 | } |
1362 | res = __res_get_state(); | 1281 | res = __res_get_state(); |
@@ -1366,18 +1285,19 @@ _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap) | |||
1366 | } | 1285 | } |
1367 | res_setnetid(res, netid); | 1286 | res_setnetid(res, netid); |
1368 | res_setmark(res, mark); | 1287 | res_setmark(res, mark); |
1369 | n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf)); | 1288 | n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf)); |
1370 | if (n < 0) { | 1289 | if (n < 0) { |
1371 | free(buf); | 1290 | free(buf); |
1372 | dprintf("res_nquery failed (%d)\n", res, n); | 1291 | debugprintf("res_nquery failed (%d)\n", res, n); |
1373 | __res_put_state(res); | 1292 | __res_put_state(res); |
1374 | return NS_NOTFOUND; | 1293 | return NS_NOTFOUND; |
1375 | } | 1294 | } |
1376 | hp = getanswer(buf, n, qbuf, T_PTR, res); | 1295 | hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, |
1296 | info->buflen, info->he); | ||
1377 | free(buf); | 1297 | free(buf); |
1378 | if (hp == NULL) { | 1298 | if (hp == NULL) { |
1379 | __res_put_state(res); | 1299 | __res_put_state(res); |
1380 | switch (h_errno) { | 1300 | switch (*info->he) { |
1381 | case HOST_NOT_FOUND: | 1301 | case HOST_NOT_FOUND: |
1382 | return NS_NOTFOUND; | 1302 | return NS_NOTFOUND; |
1383 | case TRY_AGAIN: | 1303 | case TRY_AGAIN: |
@@ -1386,20 +1306,325 @@ _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap) | |||
1386 | return NS_UNAVAIL; | 1306 | return NS_UNAVAIL; |
1387 | } | 1307 | } |
1388 | } | 1308 | } |
1389 | hp->h_addrtype = af; | 1309 | |
1390 | hp->h_length = len; | 1310 | bf = (void *)(hp->h_addr_list + 2); |
1391 | (void)memcpy(rs->host_addr, uaddr, (size_t)len); | 1311 | blen = (size_t)(bf - info->buf); |
1392 | rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr; | 1312 | if (blen + info->hp->h_length > info->buflen) |
1393 | rs->h_addr_ptrs[1] = NULL; | 1313 | goto nospc; |
1394 | if (af == AF_INET && (res->options & RES_USE_INET6)) { | 1314 | hp->h_addr_list[0] = bf; |
1395 | map_v4v6_address((char *)(void *)rs->host_addr, | 1315 | hp->h_addr_list[1] = NULL; |
1396 | (char *)(void *)rs->host_addr); | 1316 | (void)memcpy(bf, uaddr, (size_t)info->hp->h_length); |
1317 | if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) { | ||
1318 | if (blen + NS_IN6ADDRSZ > info->buflen) | ||
1319 | goto nospc; | ||
1320 | map_v4v6_address(bf, bf); | ||
1397 | hp->h_addrtype = AF_INET6; | 1321 | hp->h_addrtype = AF_INET6; |
1398 | hp->h_length = IN6ADDRSZ; | 1322 | hp->h_length = NS_IN6ADDRSZ; |
1399 | } | 1323 | } |
1400 | 1324 | ||
1401 | __res_put_state(res); | 1325 | __res_put_state(res); |
1402 | *((struct hostent **)rv) = hp; | 1326 | *info->he = NETDB_SUCCESS; |
1403 | h_errno = NETDB_SUCCESS; | 1327 | return NS_SUCCESS; |
1328 | nospc: | ||
1329 | *info->he = NETDB_INTERNAL; | ||
1330 | return NS_UNAVAIL; | ||
1331 | } | ||
1332 | |||
1333 | #ifdef YP | ||
1334 | /*ARGSUSED*/ | ||
1335 | static struct hostent * | ||
1336 | _yp_hostent(char *line, int af, struct getnamaddr *info) | ||
1337 | { | ||
1338 | struct in6_addr host_addrs[MAXADDRS]; | ||
1339 | char **aliases; | ||
1340 | size_t maxaliases; | ||
1341 | char *p = line; | ||
1342 | char *cp, **q, *ptr; | ||
1343 | size_t len, anum, i; | ||
1344 | int addrok; | ||
1345 | int more; | ||
1346 | size_t naddrs; | ||
1347 | struct hostent *hp = info->hp; | ||
1348 | |||
1349 | _DIAGASSERT(line != NULL); | ||
1350 | |||
1351 | hp->h_name = NULL; | ||
1352 | hp->h_addrtype = af; | ||
1353 | switch (af) { | ||
1354 | case AF_INET: | ||
1355 | hp->h_length = NS_INADDRSZ; | ||
1356 | break; | ||
1357 | case AF_INET6: | ||
1358 | hp->h_length = NS_IN6ADDRSZ; | ||
1359 | break; | ||
1360 | default: | ||
1361 | return NULL; | ||
1362 | } | ||
1363 | setup(aliases, maxaliases); | ||
1364 | naddrs = 0; | ||
1365 | q = aliases; | ||
1366 | |||
1367 | nextline: | ||
1368 | /* check for host_addrs overflow */ | ||
1369 | if (naddrs >= __arraycount(host_addrs)) | ||
1370 | goto done; | ||
1371 | |||
1372 | more = 0; | ||
1373 | cp = strpbrk(p, " \t"); | ||
1374 | if (cp == NULL) | ||
1375 | goto done; | ||
1376 | *cp++ = '\0'; | ||
1377 | |||
1378 | /* p has should have an address */ | ||
1379 | addrok = inet_pton(af, p, &host_addrs[naddrs]); | ||
1380 | if (addrok != 1) { | ||
1381 | /* skip to the next line */ | ||
1382 | while (cp && *cp) { | ||
1383 | if (*cp == '\n') { | ||
1384 | cp++; | ||
1385 | goto nextline; | ||
1386 | } | ||
1387 | cp++; | ||
1388 | } | ||
1389 | goto done; | ||
1390 | } | ||
1391 | naddrs++; | ||
1392 | |||
1393 | while (*cp == ' ' || *cp == '\t') | ||
1394 | cp++; | ||
1395 | p = cp; | ||
1396 | cp = strpbrk(p, " \t\n"); | ||
1397 | if (cp != NULL) { | ||
1398 | if (*cp == '\n') | ||
1399 | more = 1; | ||
1400 | *cp++ = '\0'; | ||
1401 | } | ||
1402 | if (!hp->h_name) | ||
1403 | hp->h_name = p; | ||
1404 | else if (strcmp(hp->h_name, p) == 0) | ||
1405 | ; | ||
1406 | else | ||
1407 | addalias(q, p, aliases, maxaliases); | ||
1408 | p = cp; | ||
1409 | if (more) | ||
1410 | goto nextline; | ||
1411 | |||
1412 | while (cp && *cp) { | ||
1413 | if (*cp == ' ' || *cp == '\t') { | ||
1414 | cp++; | ||
1415 | continue; | ||
1416 | } | ||
1417 | if (*cp == '\n') { | ||
1418 | cp++; | ||
1419 | goto nextline; | ||
1420 | } | ||
1421 | addalias(q, cp, aliases, maxaliases); | ||
1422 | cp = strpbrk(cp, " \t"); | ||
1423 | if (cp != NULL) | ||
1424 | *cp++ = '\0'; | ||
1425 | } | ||
1426 | |||
1427 | done: | ||
1428 | if (hp->h_name == NULL) { | ||
1429 | free(aliases); | ||
1430 | return NULL; | ||
1431 | } | ||
1432 | |||
1433 | ptr = info->buf; | ||
1434 | len = info->buflen; | ||
1435 | |||
1436 | anum = (size_t)(q - aliases); | ||
1437 | HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len); | ||
1438 | HENT_ARRAY(hp->h_aliases, anum, ptr, len); | ||
1439 | |||
1440 | for (i = 0; i < naddrs; i++) | ||
1441 | HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length, | ||
1442 | ptr, len); | ||
1443 | hp->h_addr_list[naddrs] = NULL; | ||
1444 | |||
1445 | HENT_SCOPY(hp->h_name, hp->h_name, ptr, len); | ||
1446 | |||
1447 | for (i = 0; i < anum; i++) | ||
1448 | HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); | ||
1449 | hp->h_aliases[anum] = NULL; | ||
1450 | free(aliases); | ||
1451 | |||
1452 | return hp; | ||
1453 | nospc: | ||
1454 | free(aliases); | ||
1455 | *info->he = NETDB_INTERNAL; | ||
1456 | errno = ENOSPC; | ||
1457 | return NULL; | ||
1458 | } | ||
1459 | |||
1460 | /*ARGSUSED*/ | ||
1461 | int | ||
1462 | _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap) | ||
1463 | { | ||
1464 | struct hostent *hp = NULL; | ||
1465 | char *ypcurrent; | ||
1466 | int ypcurrentlen, r; | ||
1467 | char name[INET6_ADDRSTRLEN]; /* XXX enough? */ | ||
1468 | const unsigned char *uaddr; | ||
1469 | int af; | ||
1470 | const char *map; | ||
1471 | struct getnamaddr *info = rv; | ||
1472 | |||
1473 | _DIAGASSERT(rv != NULL); | ||
1474 | |||
1475 | uaddr = va_arg(ap, unsigned char *); | ||
1476 | /* NOSTRICT skip len */(void)va_arg(ap, int); | ||
1477 | af = va_arg(ap, int); | ||
1478 | |||
1479 | if (!__ypdomain) { | ||
1480 | if (_yp_check(&__ypdomain) == 0) | ||
1481 | return NS_UNAVAIL; | ||
1482 | } | ||
1483 | /* | ||
1484 | * XXX unfortunately, we cannot support IPv6 extended scoped address | ||
1485 | * notation here. gethostbyaddr() is not scope-aware. too bad. | ||
1486 | */ | ||
1487 | if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL) | ||
1488 | return NS_UNAVAIL; | ||
1489 | switch (af) { | ||
1490 | case AF_INET: | ||
1491 | map = "hosts.byaddr"; | ||
1492 | break; | ||
1493 | default: | ||
1494 | map = "ipnodes.byaddr"; | ||
1495 | break; | ||
1496 | } | ||
1497 | ypcurrent = NULL; | ||
1498 | r = yp_match(__ypdomain, map, name, | ||
1499 | (int)strlen(name), &ypcurrent, &ypcurrentlen); | ||
1500 | if (r == 0) | ||
1501 | hp = _yp_hostent(ypcurrent, af, info); | ||
1502 | else | ||
1503 | hp = NULL; | ||
1504 | free(ypcurrent); | ||
1505 | if (hp == NULL) { | ||
1506 | *info->he = HOST_NOT_FOUND; | ||
1507 | return NS_NOTFOUND; | ||
1508 | } | ||
1509 | return NS_SUCCESS; | ||
1510 | } | ||
1511 | |||
1512 | /*ARGSUSED*/ | ||
1513 | int | ||
1514 | _yp_gethtbyname(void *rv, void *cb_data, va_list ap) | ||
1515 | { | ||
1516 | struct hostent *hp; | ||
1517 | char *ypcurrent; | ||
1518 | int ypcurrentlen, r; | ||
1519 | const char *name; | ||
1520 | int af; | ||
1521 | const char *map; | ||
1522 | struct getnamaddr *info = rv; | ||
1523 | |||
1524 | _DIAGASSERT(rv != NULL); | ||
1525 | |||
1526 | name = va_arg(ap, char *); | ||
1527 | /* NOSTRICT skip string len */(void)va_arg(ap, int); | ||
1528 | af = va_arg(ap, int); | ||
1529 | |||
1530 | if (!__ypdomain) { | ||
1531 | if (_yp_check(&__ypdomain) == 0) | ||
1532 | return NS_UNAVAIL; | ||
1533 | } | ||
1534 | switch (af) { | ||
1535 | case AF_INET: | ||
1536 | map = "hosts.byname"; | ||
1537 | break; | ||
1538 | default: | ||
1539 | map = "ipnodes.byname"; | ||
1540 | break; | ||
1541 | } | ||
1542 | ypcurrent = NULL; | ||
1543 | r = yp_match(__ypdomain, map, name, | ||
1544 | (int)strlen(name), &ypcurrent, &ypcurrentlen); | ||
1545 | if (r == 0) | ||
1546 | hp = _yp_hostent(ypcurrent, af, info); | ||
1547 | else | ||
1548 | hp = NULL; | ||
1549 | free(ypcurrent); | ||
1550 | if (hp == NULL) { | ||
1551 | *info->he = HOST_NOT_FOUND; | ||
1552 | return NS_NOTFOUND; | ||
1553 | } | ||
1404 | return NS_SUCCESS; | 1554 | return NS_SUCCESS; |
1405 | } | 1555 | } |
1556 | #endif | ||
1557 | |||
1558 | /* | ||
1559 | * Non-reentrant versions. | ||
1560 | */ | ||
1561 | |||
1562 | struct hostent * | ||
1563 | gethostbyname(const char *name) | ||
1564 | { | ||
1565 | struct hostent *result = NULL; | ||
1566 | res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ | ||
1567 | |||
1568 | gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno); | ||
1569 | return result; | ||
1570 | } | ||
1571 | |||
1572 | struct hostent * | ||
1573 | gethostbyname2(const char *name, int af) | ||
1574 | { | ||
1575 | struct hostent *result = NULL; | ||
1576 | res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ | ||
1577 | |||
1578 | gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno); | ||
1579 | return result; | ||
1580 | } | ||
1581 | |||
1582 | struct hostent * | ||
1583 | android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark) | ||
1584 | { | ||
1585 | struct hostent *hp; | ||
1586 | res_state res = __res_get_state(); | ||
1587 | if (res == NULL) | ||
1588 | return NULL; | ||
1589 | res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ | ||
1590 | hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), | ||
1591 | &h_errno, netid, mark); | ||
1592 | __res_put_state(res); | ||
1593 | return hp; | ||
1594 | } | ||
1595 | |||
1596 | struct hostent * | ||
1597 | gethostbyaddr(const void *addr, socklen_t len, int af) | ||
1598 | { | ||
1599 | return android_gethostbyaddrfornet_proxy(addr, len, af, NETID_UNSET, MARK_UNSET); | ||
1600 | } | ||
1601 | |||
1602 | struct hostent * | ||
1603 | android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) | ||
1604 | { | ||
1605 | return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark); | ||
1606 | } | ||
1607 | |||
1608 | __LIBC_HIDDEN__ struct hostent* | ||
1609 | android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af, | ||
1610 | unsigned netid, unsigned mark) | ||
1611 | { | ||
1612 | res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ | ||
1613 | return android_gethostbyaddrfornet_proxy_internal(addr, len, af, &rs->host, rs->hostbuf, | ||
1614 | sizeof(rs->hostbuf), &h_errno, netid, mark); | ||
1615 | } | ||
1616 | |||
1617 | struct hostent * | ||
1618 | gethostent(void) | ||
1619 | { | ||
1620 | res_static rs = __res_get_static(); | ||
1621 | if (!rs->hostf) { | ||
1622 | sethostent_r(&rs->hostf); | ||
1623 | if (!rs->hostf) { | ||
1624 | h_errno = NETDB_INTERNAL; | ||
1625 | return NULL; | ||
1626 | } | ||
1627 | } | ||
1628 | memset(&rs->host, 0, sizeof(rs->host)); | ||
1629 | return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno); | ||
1630 | } | ||
diff --git a/libc/dns/include/hostent.h b/libc/dns/include/hostent.h new file mode 100644 index 00000000..8b9a637c --- /dev/null +++ b/libc/dns/include/hostent.h | |||
@@ -0,0 +1,93 @@ | |||
1 | /* $NetBSD: hostent.h,v 1.2 2013/08/27 09:56:12 christos Exp $ */ | ||
2 | |||
3 | /*- | ||
4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * This code is derived from software contributed to The NetBSD Foundation | ||
8 | * by Christos Zoulas. | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * 1. Redistributions of source code must retain the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer. | ||
15 | * 2. Redistributions in binary form must reproduce the above copyright | ||
16 | * notice, this list of conditions and the following disclaimer in the | ||
17 | * documentation and/or other materials provided with the distribution. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | ||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | ||
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
29 | * POSSIBILITY OF SUCH DAMAGE. | ||
30 | */ | ||
31 | #ifndef _DNS_NET_HOSTENT_H | ||
32 | #define _DNS_NET_HOSTENT_H | ||
33 | |||
34 | #include <stdio.h> | ||
35 | #include <netdb.h> | ||
36 | #include <stdarg.h> | ||
37 | |||
38 | /* | ||
39 | * These are not being advertised because the interfaces are non-standard. | ||
40 | * There are versions by linux, aix, qnx, sun, etc. Our versions are used | ||
41 | * internally to provide thread safety; they mostly resemble qnx. | ||
42 | */ | ||
43 | void sethostent_r(FILE **); | ||
44 | struct hostent *netbsd_gethostent_r(FILE *, struct hostent *, char *, size_t, int *); | ||
45 | void endhostent_r(FILE **); | ||
46 | |||
47 | /* | ||
48 | * The following are internal API's and are used only for testing. | ||
49 | */ | ||
50 | struct getnamaddr { | ||
51 | struct hostent *hp; | ||
52 | char *buf; | ||
53 | size_t buflen; | ||
54 | int *he; | ||
55 | }; | ||
56 | |||
57 | /* /etc/hosts lookup */ | ||
58 | int _hf_gethtbyaddr(void *, void *, va_list); | ||
59 | int _hf_gethtbyname(void *, void *, va_list); | ||
60 | |||
61 | #ifdef YP | ||
62 | /* NIS lookup */ | ||
63 | int _yp_gethtbyaddr(void *, void *, va_list); | ||
64 | int _yp_gethtbyname(void *, void *, va_list); | ||
65 | #endif | ||
66 | |||
67 | #define HENT_ARRAY(dst, anum, ptr, len) \ | ||
68 | do { \ | ||
69 | size_t _len = (anum + 1) * sizeof(*dst); \ | ||
70 | if (_len > len) \ | ||
71 | goto nospc; \ | ||
72 | dst = (void *)ptr; \ | ||
73 | ptr += _len; \ | ||
74 | len -= _len; \ | ||
75 | } while (/*CONSTCOND*/0) | ||
76 | |||
77 | #define HENT_COPY(dst, src, slen, ptr, len) \ | ||
78 | do { \ | ||
79 | if ((size_t)slen > len) \ | ||
80 | goto nospc; \ | ||
81 | memcpy(ptr, src, (size_t)slen); \ | ||
82 | dst = ptr; \ | ||
83 | ptr += slen; \ | ||
84 | len -= slen; \ | ||
85 | } while (/* CONSTCOND */0) | ||
86 | |||
87 | #define HENT_SCOPY(dst, src, ptr, len) \ | ||
88 | do { \ | ||
89 | size_t _len = strlen(src) + 1; \ | ||
90 | HENT_COPY(dst, src, _len, ptr, len); \ | ||
91 | } while (/* CONSTCOND */0) | ||
92 | |||
93 | #endif /* _DNS_NET_HOSTENT_H */ | ||
diff --git a/libc/dns/net/sethostent.c b/libc/dns/net/sethostent.c new file mode 100644 index 00000000..f501c8b5 --- /dev/null +++ b/libc/dns/net/sethostent.c | |||
@@ -0,0 +1,266 @@ | |||
1 | /* $NetBSD: sethostent.c,v 1.20 2014/03/17 13:24:23 christos Exp $ */ | ||
2 | |||
3 | /* | ||
4 | * Copyright (c) 1985, 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. Neither the name of the University nor the names of its contributors | ||
16 | * may be used to endorse or promote products derived from this software | ||
17 | * without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | #include <sys/cdefs.h> | ||
33 | #if defined(LIBC_SCCS) && !defined(lint) | ||
34 | #if 0 | ||
35 | static char sccsid[] = "@(#)sethostent.c 8.1 (Berkeley) 6/4/93"; | ||
36 | static char rcsid[] = "Id: sethostent.c,v 8.5 1996/09/28 06:51:07 vixie Exp "; | ||
37 | #else | ||
38 | __RCSID("$NetBSD: sethostent.c,v 1.20 2014/03/17 13:24:23 christos Exp $"); | ||
39 | #endif | ||
40 | #endif /* LIBC_SCCS and not lint */ | ||
41 | |||
42 | #include "namespace.h" | ||
43 | #include <sys/param.h> | ||
44 | #include <netinet/in.h> | ||
45 | #include <arpa/nameser.h> | ||
46 | #include <arpa/inet.h> | ||
47 | #include <assert.h> | ||
48 | #include <string.h> | ||
49 | #include <nsswitch.h> | ||
50 | #include <netdb.h> | ||
51 | #include <resolv.h> | ||
52 | #include <errno.h> | ||
53 | #include <stdlib.h> | ||
54 | |||
55 | #include "hostent.h" | ||
56 | #include "resolv_private.h" | ||
57 | |||
58 | #define ALIGNBYTES (sizeof(uintptr_t) - 1) | ||
59 | #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES) | ||
60 | |||
61 | #ifndef _REENTRANT | ||
62 | void res_close(void); | ||
63 | #endif | ||
64 | |||
65 | static struct hostent *_hf_gethtbyname2(const char *, int, struct getnamaddr *); | ||
66 | |||
67 | static const char *_h_hosts = _PATH_HOSTS; | ||
68 | |||
69 | void | ||
70 | sethostent_r(FILE **hf) | ||
71 | { | ||
72 | if (!*hf) | ||
73 | *hf = fopen(_h_hosts, "re"); | ||
74 | else | ||
75 | rewind(*hf); | ||
76 | } | ||
77 | |||
78 | void | ||
79 | endhostent_r(FILE **hf) | ||
80 | { | ||
81 | if (*hf) { | ||
82 | (void)fclose(*hf); | ||
83 | *hf = NULL; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | /*ARGSUSED*/ | ||
88 | int | ||
89 | _hf_gethtbyname(void *rv, void *cb_data, va_list ap) | ||
90 | { | ||
91 | struct hostent *hp; | ||
92 | const char *name; | ||
93 | int af; | ||
94 | struct getnamaddr *info = rv; | ||
95 | |||
96 | _DIAGASSERT(rv != NULL); | ||
97 | |||
98 | name = va_arg(ap, char *); | ||
99 | /* NOSTRICT skip string len */(void)va_arg(ap, int); | ||
100 | af = va_arg(ap, int); | ||
101 | |||
102 | #if 0 | ||
103 | { | ||
104 | res_state res = __res_get_state(); | ||
105 | if (res == NULL) | ||
106 | return NS_NOTFOUND; | ||
107 | if (res->options & RES_USE_INET6) | ||
108 | hp = _hf_gethtbyname2(name, AF_INET6, info); | ||
109 | else | ||
110 | hp = NULL; | ||
111 | if (hp == NULL) | ||
112 | hp = _hf_gethtbyname2(name, AF_INET, info); | ||
113 | __res_put_state(res); | ||
114 | } | ||
115 | #else | ||
116 | hp = _hf_gethtbyname2(name, af, info); | ||
117 | #endif | ||
118 | if (hp == NULL) { | ||
119 | *info->he = HOST_NOT_FOUND; | ||
120 | return NS_NOTFOUND; | ||
121 | } | ||
122 | return NS_SUCCESS; | ||
123 | } | ||
124 | |||
125 | static struct hostent * | ||
126 | _hf_gethtbyname2(const char *name, int af, struct getnamaddr *info) | ||
127 | { | ||
128 | struct hostent *hp, hent; | ||
129 | char *buf, *ptr; | ||
130 | size_t len, anum, num, i; | ||
131 | FILE *hf; | ||
132 | char *aliases[MAXALIASES]; | ||
133 | char *addr_ptrs[MAXADDRS]; | ||
134 | |||
135 | _DIAGASSERT(name != NULL); | ||
136 | |||
137 | hf = NULL; | ||
138 | sethostent_r(&hf); | ||
139 | if (hf == NULL) { | ||
140 | errno = EINVAL; | ||
141 | *info->he = NETDB_INTERNAL; | ||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | if ((ptr = buf = malloc(len = info->buflen)) == NULL) { | ||
146 | endhostent_r(&hf); | ||
147 | *info->he = NETDB_INTERNAL; | ||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | anum = 0; /* XXX: gcc */ | ||
152 | hent.h_name = NULL; /* XXX: gcc */ | ||
153 | hent.h_addrtype = 0; /* XXX: gcc */ | ||
154 | hent.h_length = 0; /* XXX: gcc */ | ||
155 | |||
156 | for (num = 0; num < MAXADDRS;) { | ||
157 | info->hp->h_addrtype = af; | ||
158 | info->hp->h_length = 0; | ||
159 | |||
160 | hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, | ||
161 | info->he); | ||
162 | if (hp == NULL) | ||
163 | break; | ||
164 | |||
165 | if (strcasecmp(hp->h_name, name) != 0) { | ||
166 | char **cp; | ||
167 | for (cp = hp->h_aliases; *cp != NULL; cp++) | ||
168 | if (strcasecmp(*cp, name) == 0) | ||
169 | break; | ||
170 | if (*cp == NULL) continue; | ||
171 | } | ||
172 | |||
173 | if (num == 0) { | ||
174 | hent.h_addrtype = af = hp->h_addrtype; | ||
175 | hent.h_length = hp->h_length; | ||
176 | |||
177 | HENT_SCOPY(hent.h_name, hp->h_name, ptr, len); | ||
178 | for (anum = 0; hp->h_aliases[anum]; anum++) { | ||
179 | if (anum >= MAXALIASES) | ||
180 | goto nospc; | ||
181 | HENT_SCOPY(aliases[anum], hp->h_aliases[anum], | ||
182 | ptr, len); | ||
183 | } | ||
184 | ptr = (void *)ALIGN(ptr); | ||
185 | if ((size_t)(ptr - buf) >= info->buflen) | ||
186 | goto nospc; | ||
187 | } | ||
188 | |||
189 | if (num >= MAXADDRS) | ||
190 | goto nospc; | ||
191 | HENT_COPY(addr_ptrs[num], hp->h_addr_list[0], hp->h_length, ptr, | ||
192 | len); | ||
193 | num++; | ||
194 | } | ||
195 | endhostent_r(&hf); | ||
196 | |||
197 | if (num == 0) { | ||
198 | *info->he = HOST_NOT_FOUND; | ||
199 | free(buf); | ||
200 | return NULL; | ||
201 | } | ||
202 | |||
203 | hp = info->hp; | ||
204 | ptr = info->buf; | ||
205 | len = info->buflen; | ||
206 | |||
207 | hp->h_addrtype = hent.h_addrtype; | ||
208 | hp->h_length = hent.h_length; | ||
209 | |||
210 | HENT_ARRAY(hp->h_aliases, anum, ptr, len); | ||
211 | HENT_ARRAY(hp->h_addr_list, num, ptr, len); | ||
212 | |||
213 | for (i = 0; i < num; i++) | ||
214 | HENT_COPY(hp->h_addr_list[i], addr_ptrs[i], hp->h_length, ptr, | ||
215 | len); | ||
216 | hp->h_addr_list[num] = NULL; | ||
217 | |||
218 | HENT_SCOPY(hp->h_name, hent.h_name, ptr, len); | ||
219 | |||
220 | for (i = 0; i < anum; i++) | ||
221 | HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); | ||
222 | hp->h_aliases[anum] = NULL; | ||
223 | |||
224 | free(buf); | ||
225 | return hp; | ||
226 | nospc: | ||
227 | endhostent_r(&hf); | ||
228 | *info->he = NETDB_INTERNAL; | ||
229 | free(buf); | ||
230 | errno = ENOSPC; | ||
231 | return NULL; | ||
232 | } | ||
233 | |||
234 | /*ARGSUSED*/ | ||
235 | int | ||
236 | _hf_gethtbyaddr(void *rv, void *cb_data, va_list ap) | ||
237 | { | ||
238 | struct hostent *hp; | ||
239 | const unsigned char *addr; | ||
240 | struct getnamaddr *info = rv; | ||
241 | FILE *hf; | ||
242 | |||
243 | _DIAGASSERT(rv != NULL); | ||
244 | |||
245 | addr = va_arg(ap, unsigned char *); | ||
246 | info->hp->h_length = va_arg(ap, int); | ||
247 | info->hp->h_addrtype = va_arg(ap, int); | ||
248 | |||
249 | hf = NULL; | ||
250 | sethostent_r(&hf); | ||
251 | if (hf == NULL) { | ||
252 | *info->he = NETDB_INTERNAL; | ||
253 | return NS_UNAVAIL; | ||
254 | } | ||
255 | while ((hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, | ||
256 | info->he)) != NULL) | ||
257 | if (!memcmp(hp->h_addr_list[0], addr, (size_t)hp->h_length)) | ||
258 | break; | ||
259 | endhostent_r(&hf); | ||
260 | |||
261 | if (hp == NULL) { | ||
262 | *info->he = HOST_NOT_FOUND; | ||
263 | return NS_NOTFOUND; | ||
264 | } | ||
265 | return NS_SUCCESS; | ||
266 | } | ||
diff --git a/libc/include/netdb.h b/libc/include/netdb.h index 527d5c19..e1653762 100644 --- a/libc/include/netdb.h +++ b/libc/include/netdb.h | |||
@@ -209,7 +209,7 @@ void endprotoent(void); | |||
209 | void endservent(void); | 209 | void endservent(void); |
210 | void freehostent(struct hostent *); | 210 | void freehostent(struct hostent *); |
211 | struct hostent *gethostbyaddr(const void *, socklen_t, int); | 211 | struct hostent *gethostbyaddr(const void *, socklen_t, int); |
212 | int gethostbyaddr_r(const void *, int, int, struct hostent *, char *, size_t, struct hostent **, int *); | 212 | int gethostbyaddr_r(const void *, socklen_t, int, struct hostent *, char *, size_t, struct hostent **, int *); |
213 | struct hostent *gethostbyname(const char *); | 213 | struct hostent *gethostbyname(const char *); |
214 | int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *); | 214 | int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *); |
215 | struct hostent *gethostbyname2(const char *, int); | 215 | struct hostent *gethostbyname2(const char *, int); |
diff --git a/tests/netdb_test.cpp b/tests/netdb_test.cpp index 0cebe4e8..ab5b4875 100644 --- a/tests/netdb_test.cpp +++ b/tests/netdb_test.cpp | |||
@@ -14,11 +14,13 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <netdb.h> | ||
18 | |||
17 | #include <gtest/gtest.h> | 19 | #include <gtest/gtest.h> |
18 | 20 | ||
21 | #include <arpa/inet.h> | ||
19 | #include <sys/types.h> | 22 | #include <sys/types.h> |
20 | #include <sys/socket.h> | 23 | #include <sys/socket.h> |
21 | #include <netdb.h> | ||
22 | #include <netinet/in.h> | 24 | #include <netinet/in.h> |
23 | 25 | ||
24 | TEST(netdb, getaddrinfo_NULL_host) { | 26 | TEST(netdb, getaddrinfo_NULL_host) { |
@@ -114,8 +116,7 @@ TEST(netdb, getnameinfo_salen) { | |||
114 | ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST)); | 116 | ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST)); |
115 | } | 117 | } |
116 | 118 | ||
117 | TEST(netdb, gethostbyname) { | 119 | void VerifyLocalhost(hostent *hent) { |
118 | hostent* hent = gethostbyname("localhost"); | ||
119 | ASSERT_TRUE(hent != NULL); | 120 | ASSERT_TRUE(hent != NULL); |
120 | ASSERT_EQ(hent->h_addrtype, AF_INET); | 121 | ASSERT_EQ(hent->h_addrtype, AF_INET); |
121 | ASSERT_EQ(hent->h_addr[0], 127); | 122 | ASSERT_EQ(hent->h_addr[0], 127); |
@@ -124,6 +125,125 @@ TEST(netdb, gethostbyname) { | |||
124 | ASSERT_EQ(hent->h_addr[3], 1); | 125 | ASSERT_EQ(hent->h_addr[3], 1); |
125 | } | 126 | } |
126 | 127 | ||
128 | TEST(netdb, gethostbyname) { | ||
129 | hostent* hp = gethostbyname("localhost"); | ||
130 | VerifyLocalhost(hp); | ||
131 | } | ||
132 | |||
133 | TEST(netdb, gethostbyname2) { | ||
134 | hostent* hp = gethostbyname2("localhost", AF_INET); | ||
135 | VerifyLocalhost(hp); | ||
136 | } | ||
137 | |||
138 | TEST(netdb, gethostbyname_r) { | ||
139 | hostent hent; | ||
140 | hostent *hp; | ||
141 | char buf[512]; | ||
142 | int err; | ||
143 | int result = gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &err); | ||
144 | ASSERT_EQ(0, result); | ||
145 | VerifyLocalhost(hp); | ||
146 | |||
147 | // Change hp->h_addr to test reentrancy. | ||
148 | hp->h_addr[0] = 0; | ||
149 | |||
150 | hostent hent2; | ||
151 | hostent *hp2; | ||
152 | char buf2[512]; | ||
153 | result = gethostbyname_r("localhost", &hent2, buf2, sizeof(buf2), &hp2, &err); | ||
154 | ASSERT_EQ(0, result); | ||
155 | VerifyLocalhost(hp2); | ||
156 | |||
157 | ASSERT_EQ(0, hp->h_addr[0]); | ||
158 | } | ||
159 | |||
160 | TEST(netdb, gethostbyname2_r) { | ||
161 | hostent hent; | ||
162 | hostent *hp; | ||
163 | char buf[512]; | ||
164 | int err; | ||
165 | int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err); | ||
166 | ASSERT_EQ(0, result); | ||
167 | VerifyLocalhost(hp); | ||
168 | |||
169 | // Change hp->h_addr to test reentrancy. | ||
170 | hp->h_addr[0] = 0; | ||
171 | |||
172 | hostent hent2; | ||
173 | hostent *hp2; | ||
174 | char buf2[512]; | ||
175 | result = gethostbyname2_r("localhost", AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err); | ||
176 | ASSERT_EQ(0, result); | ||
177 | VerifyLocalhost(hp2); | ||
178 | |||
179 | ASSERT_EQ(0, hp->h_addr[0]); | ||
180 | } | ||
181 | |||
182 | TEST(netdb, gethostbyaddr) { | ||
183 | char addr[4]; | ||
184 | ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr)); | ||
185 | hostent *hp = gethostbyaddr(addr, sizeof(addr), AF_INET); | ||
186 | VerifyLocalhost(hp); | ||
187 | } | ||
188 | |||
189 | TEST(netdb, gethostbyaddr_r) { | ||
190 | char addr[4]; | ||
191 | ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr)); | ||
192 | |||
193 | hostent hent; | ||
194 | hostent *hp; | ||
195 | char buf[512]; | ||
196 | int err; | ||
197 | int result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err); | ||
198 | ASSERT_EQ(0, result); | ||
199 | VerifyLocalhost(hp); | ||
200 | |||
201 | // Change hp->h_addr to test reentrancy. | ||
202 | hp->h_addr[0] = 0; | ||
203 | |||
204 | hostent hent2; | ||
205 | hostent *hp2; | ||
206 | char buf2[512]; | ||
207 | result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err); | ||
208 | ASSERT_EQ(0, result); | ||
209 | VerifyLocalhost(hp2); | ||
210 | |||
211 | ASSERT_EQ(0, hp->h_addr[0]); | ||
212 | } | ||
213 | |||
214 | TEST(netdb, gethostbyname_r_ERANGE) { | ||
215 | hostent hent; | ||
216 | hostent *hp; | ||
217 | char buf[4]; // Use too small buffer. | ||
218 | int err; | ||
219 | int result = gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &err); | ||
220 | ASSERT_EQ(ERANGE, result); | ||
221 | ASSERT_EQ(NULL, hp); | ||
222 | } | ||
223 | |||
224 | TEST(netdb, gethostbyname2_r_ERANGE) { | ||
225 | hostent hent; | ||
226 | hostent *hp; | ||
227 | char buf[4]; // Use too small buffer. | ||
228 | int err; | ||
229 | int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err); | ||
230 | ASSERT_EQ(ERANGE, result); | ||
231 | ASSERT_EQ(NULL, hp); | ||
232 | } | ||
233 | |||
234 | TEST(netdb, gethostbyaddr_r_ERANGE) { | ||
235 | char addr[4]; | ||
236 | ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr)); | ||
237 | |||
238 | hostent hent; | ||
239 | hostent *hp; | ||
240 | char buf[4]; // Use too small buffer. | ||
241 | int err; | ||
242 | int result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err); | ||
243 | ASSERT_EQ(ERANGE, result); | ||
244 | ASSERT_EQ(NULL, hp); | ||
245 | } | ||
246 | |||
127 | TEST(netdb, getservbyname) { | 247 | TEST(netdb, getservbyname) { |
128 | // smtp is TCP-only, so we know we'll get 25/tcp back. | 248 | // smtp is TCP-only, so we know we'll get 25/tcp back. |
129 | servent* s = getservbyname("smtp", NULL); | 249 | servent* s = getservbyname("smtp", NULL); |